diff --git a/stuff/config/qss/gray_048/gray_048.less b/stuff/config/qss/gray_048/gray_048.less index ef27e52..9ed5281 100644 --- a/stuff/config/qss/gray_048/gray_048.less +++ b/stuff/config/qss/gray_048/gray_048.less @@ -748,7 +748,7 @@ DvDirTreeView { /*---------------------------------------------------------------------------*/ #CleanupSettingsFrame, #LoadLevelFrame, -#SolidLineFrame{ +#SolidLineFrame { border: 1px solid @m_baseTxtColor; } diff --git a/stuff/config/qss/gray_048/gray_048.qss b/stuff/config/qss/gray_048/gray_048.qss index 599b359..97438d3 100644 --- a/stuff/config/qss/gray_048/gray_048.qss +++ b/stuff/config/qss/gray_048/gray_048.qss @@ -764,7 +764,7 @@ DvDirTreeView { /*---------------------------------------------------------------------------*/ /* Cleanup Settings, LoadLevel, PsdSettingsPopup, FxSettingsPopup, RenameAsToonzPopup */ /*---------------------------------------------------------------------------*/ -#CleanupSettingsFrame, +#CleanupSettingsFrame, #LoadLevelFrame, #SolidLineFrame { border: 1px solid #e6e6e6; diff --git a/stuff/config/qss/gray_048/gray_048_mac.qss b/stuff/config/qss/gray_048/gray_048_mac.qss index e8cec36..f731688 100644 --- a/stuff/config/qss/gray_048/gray_048_mac.qss +++ b/stuff/config/qss/gray_048/gray_048_mac.qss @@ -764,7 +764,7 @@ DvDirTreeView { /*---------------------------------------------------------------------------*/ /* Cleanup Settings, LoadLevel, PsdSettingsPopup, FxSettingsPopup, RenameAsToonzPopup */ /*---------------------------------------------------------------------------*/ -#CleanupSettingsFrame, +#CleanupSettingsFrame, #LoadLevelFrame, #SolidLineFrame { border: 1px solid #e6e6e6; diff --git a/stuff/config/qss/gray_072/gray_072.less b/stuff/config/qss/gray_072/gray_072.less index aa97bd4..aedaa86 100644 --- a/stuff/config/qss/gray_072/gray_072.less +++ b/stuff/config/qss/gray_072/gray_072.less @@ -747,7 +747,7 @@ DvDirTreeView { /*---------------------------------------------------------------------------*/ #CleanupSettingsFrame, #LoadLevelFrame, -#SolidLineFrame{ +#SolidLineFrame { border: 1px solid @m_baseTxtColor; } diff --git a/stuff/config/qss/gray_072/gray_072.qss b/stuff/config/qss/gray_072/gray_072.qss index f8d0649..105fad9 100644 --- a/stuff/config/qss/gray_072/gray_072.qss +++ b/stuff/config/qss/gray_072/gray_072.qss @@ -764,7 +764,7 @@ DvDirTreeView { /*---------------------------------------------------------------------------*/ /* Cleanup Settings, LoadLevel, PsdSettingsPopup, FxSettingsPopup, RenameAsToonzPopup */ /*---------------------------------------------------------------------------*/ -#CleanupSettingsFrame, +#CleanupSettingsFrame, #LoadLevelFrame, #SolidLineFrame { border: 1px solid #e6e6e6; diff --git a/stuff/config/qss/gray_072/gray_072_mac.qss b/stuff/config/qss/gray_072/gray_072_mac.qss index 2aba2c9..e49f359 100644 --- a/stuff/config/qss/gray_072/gray_072_mac.qss +++ b/stuff/config/qss/gray_072/gray_072_mac.qss @@ -764,7 +764,7 @@ DvDirTreeView { /*---------------------------------------------------------------------------*/ /* Cleanup Settings, LoadLevel, PsdSettingsPopup, FxSettingsPopup, RenameAsToonzPopup */ /*---------------------------------------------------------------------------*/ -#CleanupSettingsFrame, +#CleanupSettingsFrame, #LoadLevelFrame, #SolidLineFrame { border: 1px solid #e6e6e6; diff --git a/stuff/config/qss/gray_128/gray_128.less b/stuff/config/qss/gray_128/gray_128.less index f52a3a8..0d23384 100644 --- a/stuff/config/qss/gray_128/gray_128.less +++ b/stuff/config/qss/gray_128/gray_128.less @@ -595,7 +595,7 @@ DvDirTreeView { /*---------------------------------------------------------------------------*/ #CleanupSettingsFrame, #LoadLevelFrame, -#SolidLineFrame{ +#SolidLineFrame { border: 1px solid rgb(20,20,20); } diff --git a/stuff/config/qss/gray_128/gray_128.qss b/stuff/config/qss/gray_128/gray_128.qss index 0763d1e..5e5eac7 100644 --- a/stuff/config/qss/gray_128/gray_128.qss +++ b/stuff/config/qss/gray_128/gray_128.qss @@ -526,7 +526,7 @@ DvDirTreeView { /*---------------------------------------------------------------------------*/ /* Cleanup Settings, LoadLevel, PsdSettingsPopup, FxSettingsPopup, RenameAsToonzPopup */ /*---------------------------------------------------------------------------*/ -#CleanupSettingsFrame, +#CleanupSettingsFrame, #LoadLevelFrame, #SolidLineFrame { border: 1px solid #141414; diff --git a/stuff/config/qss/gray_128/gray_128_mac.qss b/stuff/config/qss/gray_128/gray_128_mac.qss index 8d88797..4093fe5 100644 --- a/stuff/config/qss/gray_128/gray_128_mac.qss +++ b/stuff/config/qss/gray_128/gray_128_mac.qss @@ -526,7 +526,7 @@ DvDirTreeView { /*---------------------------------------------------------------------------*/ /* Cleanup Settings, LoadLevel, PsdSettingsPopup, FxSettingsPopup, RenameAsToonzPopup */ /*---------------------------------------------------------------------------*/ -#CleanupSettingsFrame, +#CleanupSettingsFrame, #LoadLevelFrame, #SolidLineFrame { border: 1px solid #141414; diff --git a/stuff/profiles/layouts/rooms/Default/menubar_template.xml b/stuff/profiles/layouts/rooms/Default/menubar_template.xml index c41c894..6c9f3b8 100644 --- a/stuff/profiles/layouts/rooms/Default/menubar_template.xml +++ b/stuff/profiles/layouts/rooms/Default/menubar_template.xml @@ -234,6 +234,7 @@ MI_ResetRoomLayout + MI_StartupPopup MI_About \ No newline at end of file diff --git a/toonz/sources/include/toonz/preferences.h b/toonz/sources/include/toonz/preferences.h index 3b32f86..37b9bd1 100644 --- a/toonz/sources/include/toonz/preferences.h +++ b/toonz/sources/include/toonz/preferences.h @@ -118,6 +118,9 @@ public: return m_replaceAfterSaveLevelAs; } + void enableStartupPopup(bool on); + bool isStartupPopupEnabled() { return m_startupPopupEnabled; } + void setProjectRoot(int index); int getProjectRoot() { return m_projectRoot; } @@ -474,7 +477,8 @@ private: bool m_rasterOptimizedMemory, m_saveUnpaintedInCleanup, m_askForOverrideRender, m_automaticSVNFolderRefreshEnabled, m_SVNEnabled, m_levelsBackupEnabled, m_minimizeSaveboxAfterEditing, - m_sceneNumberingEnabled, m_animationSheetEnabled, m_inksOnly; + m_sceneNumberingEnabled, m_animationSheetEnabled, m_inksOnly, + m_startupPopupEnabled; bool m_fillOnlySavebox, m_show0ThickLines, m_regionAntialias; bool m_onionSkinDuringPlayback; TPixel32 m_viewerBGColor, m_previewBGColor, m_chessboardColor1, diff --git a/toonz/sources/include/toonzqt/camerasettingswidget.h b/toonz/sources/include/toonzqt/camerasettingswidget.h index 18fc23b..1b2a995 100644 --- a/toonz/sources/include/toonzqt/camerasettingswidget.h +++ b/toonz/sources/include/toonzqt/camerasettingswidget.h @@ -71,6 +71,7 @@ protected: //--------------------------------------------------------------- class DVAPI CameraSettingsWidget final : public QFrame { + friend class StartupPopup; Q_OBJECT bool m_forCleanup; diff --git a/toonz/sources/toonz/CMakeLists.txt b/toonz/sources/toonz/CMakeLists.txt index 41ff9b3..484cfee 100644 --- a/toonz/sources/toonz/CMakeLists.txt +++ b/toonz/sources/toonz/CMakeLists.txt @@ -100,6 +100,7 @@ set(MOC_HEADERS selectionutils.h shifttracetool.h shortcutpopup.h + startuppopup.h subcameramanager.h subscenecommand.h svncleanupdialog.h @@ -232,6 +233,7 @@ set(SOURCES scriptconsolepanel.cpp shifttracetool.cpp shortcutpopup.cpp + startuppopup.cpp subcameramanager.cpp timestretchpopup.cpp trackerpopup.cpp diff --git a/toonz/sources/toonz/Resources/startup.png b/toonz/sources/toonz/Resources/startup.png new file mode 100644 index 0000000..10757e0 Binary files /dev/null and b/toonz/sources/toonz/Resources/startup.png differ diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 8609f34..afca011 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -12,6 +12,7 @@ #include "iocommand.h" #include "tapp.h" #include "comboviewerpane.h" +#include "startuppopup.h" // TnzTools includes #include "tools/toolcommandids.h" @@ -1275,6 +1276,12 @@ void MainWindow::onMenuCheckboxChanged() { void MainWindow::showEvent(QShowEvent *event) { getCurrentRoom()->layout()->setEnabled(true); // See main function in // main.cpp + if (Preferences::instance()->isStartupPopupEnabled() && + !m_startupPopupShown) { + StartupPopup *startupPopup = new StartupPopup(); + startupPopup->show(); + m_startupPopupShown = true; + } } extern const char *applicationName; extern const char *applicationVersion; @@ -1920,7 +1927,7 @@ void MainWindow::defineActions() { tr("Toggle Main Window's Full Screen Mode"), "Ctrl+`"); createMenuWindowsAction(MI_About, tr("&About OpenToonz..."), ""); - + createMenuWindowsAction(MI_StartupPopup, tr("&Startup Popup..."), "Alt+S"); createRightClickMenuAction(MI_BlendColors, tr("&Blend colors"), ""); createToggle(MI_OnionSkin, tr("Onion Skin Toggle"), "/", false, diff --git a/toonz/sources/toonz/mainwindow.h b/toonz/sources/toonz/mainwindow.h index 8efc118..4eb088a 100644 --- a/toonz/sources/toonz/mainwindow.h +++ b/toonz/sources/toonz/mainwindow.h @@ -67,6 +67,7 @@ class MainWindow final : public QMainWindow { Q_OBJECT bool m_saveSettingsOnQuit; + bool m_startupPopupShown = false; int m_oldRoomIndex; QString m_currentRoomsChoice; UpdateChecker *m_updateChecker; @@ -212,6 +213,7 @@ signals: }; class RecentFiles { + friend class StartupPopup; QList m_recentScenes; QList m_recentLevels; QList m_recentFlipbookImages; diff --git a/toonz/sources/toonz/menubar.cpp b/toonz/sources/toonz/menubar.cpp index 83ecf2c..c578245 100644 --- a/toonz/sources/toonz/menubar.cpp +++ b/toonz/sources/toonz/menubar.cpp @@ -1344,6 +1344,7 @@ QMenuBar *StackedMenuBar::createFullMenuBar() { //---Help Menu QMenu *helpMenu = addMenu(tr("Help"), fullMenuBar); + addMenuItem(helpMenu, MI_StartupPopup); addMenuItem(helpMenu, MI_About); return fullMenuBar; diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h index d0ec9f1..6c79b5e 100644 --- a/toonz/sources/toonz/menubarcommandids.h +++ b/toonz/sources/toonz/menubarcommandids.h @@ -311,5 +311,6 @@ #define MI_PreviewFx "MI_PreviewFx" #define MI_About "MI_About" +#define MI_StartupPopup "MI_StartupPopup" #define MI_PencilTest "MI_PencilTest" #endif diff --git a/toonz/sources/toonz/preferencespopup.cpp b/toonz/sources/toonz/preferencespopup.cpp index e310e51..d9cca43 100644 --- a/toonz/sources/toonz/preferencespopup.cpp +++ b/toonz/sources/toonz/preferencespopup.cpp @@ -583,6 +583,12 @@ void PreferencesPopup::onAutoSaveOtherFilesChanged(int index) { //----------------------------------------------------------------------------- +void PreferencesPopup::onStartupPopupChanged(int index) { + m_pref->enableStartupPopup(index == Qt::Checked); +} + +//----------------------------------------------------------------------------- + void PreferencesPopup::onKeyframeTypeChanged(int index) { m_pref->setKeyframeType(index + 2); } @@ -953,6 +959,8 @@ PreferencesPopup::PreferencesPopup() m_autoSaveSceneCB = new CheckBox(tr("Automatically Save the Scene File")); m_autoSaveOtherFilesCB = new CheckBox(tr("Automatically Save Non-Scene Files")); + CheckBox *startupPopupCB = + new CheckBox(tr("Show Startup Window when OpenToonz Starts")); m_minuteFld = new DVGui::IntLineEdit(this, 15, 1, 60); CheckBox *replaceAfterSaveLevelAsCB = new CheckBox(tr("Replace Toonz Level after SaveLevelAs command"), this); @@ -1167,6 +1175,7 @@ PreferencesPopup::PreferencesPopup() m_autoSaveSceneCB->setChecked(m_pref->isAutosaveSceneEnabled()); m_autoSaveOtherFilesCB->setChecked(m_pref->isAutosaveOtherFilesEnabled()); m_minuteFld->setValue(m_pref->getAutosavePeriod()); + startupPopupCB->setChecked(m_pref->isStartupPopupEnabled()); replaceAfterSaveLevelAsCB->setChecked( m_pref->isReplaceAfterSaveLevelAsEnabled()); @@ -1432,6 +1441,8 @@ PreferencesPopup::PreferencesPopup() } m_autoSaveGroup->setLayout(autoSaveOptionsLay); generalFrameLay->addWidget(m_autoSaveGroup); + generalFrameLay->addWidget(startupPopupCB, 0, + Qt::AlignLeft | Qt::AlignVCenter); // Unit, CameraUnit QGridLayout *unitLay = new QGridLayout(); unitLay->setMargin(0); @@ -1949,6 +1960,8 @@ PreferencesPopup::PreferencesPopup() SLOT(onAutoSaveOtherFilesChanged(int))); ret = ret && connect(m_minuteFld, SIGNAL(editingFinished()), SLOT(onMinuteChanged())); + ret = ret && connect(startupPopupCB, SIGNAL(stateChanged(int)), + SLOT(onStartupPopupChanged(int))); ret = ret && connect(m_cellsDragBehaviour, SIGNAL(currentIndexChanged(int)), SLOT(onDragCellsBehaviourChanged(int))); ret = ret && connect(m_undoMemorySize, SIGNAL(editingFinished()), diff --git a/toonz/sources/toonz/preferencespopup.h b/toonz/sources/toonz/preferencespopup.h index 134ce6e..8a49973 100644 --- a/toonz/sources/toonz/preferencespopup.h +++ b/toonz/sources/toonz/preferencespopup.h @@ -110,6 +110,7 @@ private slots: void onAutoSaveChanged(bool on); void onAutoSaveSceneChanged(int index); void onAutoSaveOtherFilesChanged(int index); + void onStartupPopupChanged(int index); void onDefaultViewerChanged(int index); void onBlankCountChanged(); void onBlankColorChanged(const TPixel32 &, bool isDragging); diff --git a/toonz/sources/toonz/startuppopup.cpp b/toonz/sources/toonz/startuppopup.cpp new file mode 100644 index 0000000..018198c --- /dev/null +++ b/toonz/sources/toonz/startuppopup.cpp @@ -0,0 +1,914 @@ + + +#include "startuppopup.h" + +// Tnz6 includes +#include "mainwindow.h" +#include "tapp.h" +#include "iocommand.h" +#include "toutputproperties.h" +#include "toonzqt/flipconsole.h" +#include "menubarcommandids.h" +#include "tenv.h" +#include "toonz/stage.h" + +// TnzQt includes +#include "toonzqt/menubarcommand.h" +#include "toonzqt/gutil.h" +#include "toonzqt/doublefield.h" + +// TnzLib includes +#include "toonz/toonzscene.h" +#include "toonz/txsheet.h" +#include "toonz/levelproperties.h" +#include "toonz/sceneproperties.h" +#include "toonz/tcamera.h" +#include "toonz/tscenehandle.h" +#include "toonz/txsheethandle.h" +#include "toonz/preferences.h" +#include "toonz/tproject.h" + +// TnzCore includes +#include "tsystem.h" +#include "filebrowsermodel.h" + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace DVGui; + +namespace { + +// the first value in the preset list +const QString custom = QObject::tr(""); + +QString removeZeros(QString srcStr) { + if (!srcStr.contains('.')) return srcStr; + + for (int i = srcStr.length() - 1; i >= 0; i--) { + if (srcStr.at(i) == '0') + srcStr.chop(1); + else if (srcStr.at(i) == '.') { + srcStr.chop(1); + break; + } else + break; + } + return srcStr; +} +} // namespace + +//============================================================================= +/*! \class StartupPopup + \brief The StartupPopup class provides a modal dialog to + bring up recent files or create a new scene. + + Inherits \b Dialog. +*/ +//----------------------------------------------------------------------------- + +StartupPopup::StartupPopup() + : Dialog(TApp::instance()->getMainWindow(), true, true, "StartupPopup") { + setWindowTitle(tr("OpenToonz Startup")); + + m_projectBox = new QGroupBox(tr("Choose Project"), this); + m_sceneBox = new QGroupBox(tr("Create a New Scene"), this); + m_recentBox = new QGroupBox(tr("Open Scene"), this); + m_projectBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_nameFld = new LineEdit(this); + m_pathFld = new FileField(this); + m_sceneNameLabel = new QLabel(tr("Scene Name:")); + m_widthLabel = new QLabel(tr("Width:"), this); + m_widthFld = new MeasuredDoubleLineEdit(this); + m_heightLabel = new QLabel(tr("Height:"), this); + m_heightFld = new MeasuredDoubleLineEdit(this); + m_dpiLabel = new QLabel(tr("DPI:"), this); + m_dpiFld = new DoubleLineEdit(this, 120); + m_resXLabel = new QLabel(tr("X"), this); + m_resXFld = new DoubleLineEdit(this); + m_resYFld = new DoubleLineEdit(this); + m_resTextLabel = new QLabel(tr("Resolution:"), this); + m_fpsLabel = new QLabel(tr("Frame Rate:"), this); + m_fpsFld = new DoubleLineEdit(this, 24.0); + m_cameraSettingsWidget = new CameraSettingsWidget(false); + m_presetCombo = new QComboBox(this); + m_unitsCB = new QComboBox(this); + m_addPresetBtn = new QPushButton(tr("Add"), this); + m_removePresetBtn = new QPushButton(tr("Remove"), this); + m_showAtStartCB = new QCheckBox(tr("Show this at startup"), this); + QPushButton *createButton = new QPushButton(tr("Create Scene"), this); + QPushButton *newProjectButton = new QPushButton(tr("New Project..."), this); + QPushButton *loadOtherSceneButton = + new QPushButton(tr("Open Another Scene..."), this); + m_projectsCB = new QComboBox(this); + QStringList type; + type << tr("pixel") << tr("cm") << tr("mm") << tr("inch") << tr("field"); + m_unitsCB->addItems(type); + + // Exclude all character which cannot fit in a filepath (Win). + // Dots are also prohibited since they are internally managed by Toonz. + QRegExp rx("[^\\\\/:?*.\"<>|]+"); + m_nameFld->setValidator(new QRegExpValidator(rx, this)); + + m_widthFld->setMeasure("camera.lx"); + m_heightFld->setMeasure("camera.ly"); + + m_widthFld->setRange(0.1, (std::numeric_limits::max)()); + m_heightFld->setRange(0.1, (std::numeric_limits::max)()); + m_fpsFld->setRange(1.0, (std::numeric_limits::max)()); + m_dpiFld->setRange(1.0, (std::numeric_limits::max)()); + m_resXFld->setRange(0.1, (std::numeric_limits::max)()); + m_resYFld->setRange(0.1, (std::numeric_limits::max)()); + m_showAtStartCB->setChecked(Preferences::instance()->isStartupPopupEnabled()); + m_showAtStartCB->setStyleSheet("QCheckBox{ background-color: none; }"); + m_addPresetBtn->setStyleSheet( + "QPushButton { padding-left: 4px; padding-right: 4px;}"); + m_removePresetBtn->setStyleSheet( + "QPushButton { padding-left: 4px; padding-right: 4px;}"); + QLabel *label = new QLabel(); + label->setPixmap(QPixmap(":Resources/startup.png")); + m_projectBox->setObjectName("SolidLineFrame"); + m_sceneBox->setObjectName("SolidLineFrame"); + m_recentBox->setObjectName("SolidLineFrame"); + m_projectBox->setContentsMargins(10, 10, 10, 10); + m_sceneBox->setContentsMargins(10, 10, 10, 10); + m_recentBox->setContentsMargins(10, 10, 10, 10); + m_recentBox->setFixedWidth(200); + m_sceneBox->setMinimumWidth(480); + m_projectBox->setMinimumWidth(480); + m_buttonFrame->setFixedHeight(30); + //--- layout + m_topLayout->setMargin(0); + m_topLayout->setSpacing(0); + { + QGridLayout *guiLay = new QGridLayout(); + QHBoxLayout *projectLay = new QHBoxLayout(); + QGridLayout *newSceneLay = new QGridLayout(); + m_recentSceneLay = new QVBoxLayout(); + guiLay->setMargin(10); + guiLay->setVerticalSpacing(10); + guiLay->setHorizontalSpacing(10); + + guiLay->addWidget(label, 0, 0, 1, 2, Qt::AlignLeft); + + projectLay->setSpacing(8); + projectLay->setMargin(8); + { + projectLay->addWidget(m_projectsCB, 1); + projectLay->addWidget(newProjectButton, 0); + } + m_projectBox->setLayout(projectLay); + guiLay->addWidget(m_projectBox, 1, 0, 1, 1, Qt::AlignCenter); + + newSceneLay->setMargin(8); + newSceneLay->setVerticalSpacing(8); + newSceneLay->setHorizontalSpacing(8); + { + // Scene Name + newSceneLay->addWidget(m_sceneNameLabel, 0, 0, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_nameFld, 0, 1, 1, 3); + + // Save In + newSceneLay->addWidget(new QLabel(tr("Save In:")), 1, 0, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_pathFld, 1, 1, 1, 3); + newSceneLay->addWidget(new QLabel(tr("Camera Size:")), 2, 0, + Qt::AlignRight | Qt::AlignVCenter); + QHBoxLayout *resListLay = new QHBoxLayout(); + resListLay->setSpacing(3); + resListLay->setMargin(1); + { + resListLay->addWidget(m_presetCombo, 1); + resListLay->addWidget(m_addPresetBtn, 0); + resListLay->addWidget(m_removePresetBtn, 0); + } + newSceneLay->addLayout(resListLay, 2, 1, 1, 3, Qt::AlignLeft); + + // Width - Height + newSceneLay->addWidget(m_widthLabel, 3, 0, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_widthFld, 3, 1); + newSceneLay->addWidget(m_heightLabel, 3, 2, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_heightFld, 3, 3); + + newSceneLay->addWidget(m_resTextLabel, 4, 0, 1, 1, Qt::AlignRight); + newSceneLay->addWidget(m_resXFld, 4, 1); + newSceneLay->addWidget(m_resXLabel, 4, 2, 1, 1, Qt::AlignCenter); + newSceneLay->addWidget(m_resYFld, 4, 3); + newSceneLay->addWidget(new QLabel(tr("Units:")), 5, 0, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_unitsCB, 5, 1, 1, 1); + newSceneLay->addWidget(m_dpiLabel, 5, 2, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_dpiFld, 5, 3, 1, 1); + newSceneLay->addWidget(m_fpsLabel, 6, 0, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_fpsFld, 6, 1, 1, 1); + newSceneLay->addWidget(createButton, 7, 1, 1, 3, Qt::AlignLeft); + } + m_sceneBox->setLayout(newSceneLay); + guiLay->addWidget(m_sceneBox, 2, 0, 4, 1, Qt::AlignLeft); + + m_recentSceneLay->setMargin(8); + m_recentSceneLay->setSpacing(8); + { + // Recent Scene List + m_recentBox->setLayout(m_recentSceneLay); + guiLay->addWidget(m_recentBox, 1, 1, 4, 1, Qt::AlignTop); + guiLay->addWidget(loadOtherSceneButton, 5, 1, 1, 1, Qt::AlignRight); + } + m_topLayout->addLayout(guiLay, 0); + } + + m_buttonLayout->setMargin(0); + m_buttonLayout->setSpacing(10); + { m_buttonLayout->addWidget(m_showAtStartCB, Qt::AlignLeft); } + + TApp *app = TApp::instance(); + TSceneHandle *sceneHandle = app->getCurrentScene(); + + //---- signal-slot connections + bool ret = true; + ret = ret && connect(sceneHandle, SIGNAL(sceneChanged()), this, + SLOT(onSceneChanged())); + ret = ret && connect(sceneHandle, SIGNAL(sceneSwitched()), this, + SLOT(onSceneChanged())); + ret = ret && connect(newProjectButton, SIGNAL(clicked()), this, + SLOT(onNewProjectButtonPressed())); + ret = ret && connect(loadOtherSceneButton, SIGNAL(clicked()), this, + SLOT(onLoadSceneButtonPressed())); + ret = ret && connect(m_projectsCB, SIGNAL(currentIndexChanged(int)), + SLOT(onProjectChanged(int))); + ret = ret && + connect(createButton, SIGNAL(clicked()), this, SLOT(onCreateButton())); + ret = ret && connect(m_showAtStartCB, SIGNAL(stateChanged(int)), this, + SLOT(onShowAtStartChanged(int))); + ret = ret && connect(m_widthFld, SIGNAL(valueChanged()), this, + SLOT(updateResolution())); + ret = ret && connect(m_heightFld, SIGNAL(valueChanged()), this, + SLOT(updateResolution())); + ret = ret && + connect(m_resXFld, SIGNAL(valueChanged()), this, SLOT(updateSize())); + ret = ret && + connect(m_resYFld, SIGNAL(valueChanged()), this, SLOT(updateSize())); + ret = ret && connect(m_dpiFld, SIGNAL(editingFinished()), this, + SLOT(onDpiChanged())); + ret = ret && connect(m_presetCombo, SIGNAL(activated(const QString &)), + SLOT(onPresetSelected(const QString &))); + ret = ret && connect(m_addPresetBtn, SIGNAL(clicked()), SLOT(addPreset())); + ret = ret && connect(m_unitsCB, SIGNAL(currentIndexChanged(int)), + SLOT(onCameraUnitChanged(int))); + ret = ret && + connect(m_removePresetBtn, SIGNAL(clicked()), SLOT(removePreset())); + ret = ret && connect(m_nameFld, SIGNAL(returnPressedNow()), createButton, + SLOT(animateClick())); + assert(ret); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::showEvent(QShowEvent *) { + loadPresetList(); + updateProjectCB(); + m_nameFld->setFocus(); + m_pathFld->setPath(TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProject() + ->getScenesPath() + .getQString()); + TDimensionD cameraSize = TApp::instance() + ->getCurrentScene() + ->getScene() + ->getCurrentCamera() + ->getSize(); + TDimension cameraRes = TApp::instance() + ->getCurrentScene() + ->getScene() + ->getCurrentCamera() + ->getRes(); + double fps = TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProperties() + ->getOutputProperties() + ->getFrameRate(); + m_widthFld->setValue(cameraSize.lx); + m_heightFld->setValue(cameraSize.ly); + if (Preferences::instance()->getCameraUnits() == "pixel") { + m_widthFld->setDecimals(0); + m_heightFld->setDecimals(0); + m_resTextLabel->hide(); + m_resXFld->hide(); + m_resYFld->hide(); + m_resXLabel->hide(); + m_dpiFld->hide(); + m_dpiLabel->hide(); + } else { + m_widthFld->setDecimals(4); + m_heightFld->setDecimals(4); + m_resXFld->show(); + m_resYFld->show(); + m_resXLabel->show(); + m_resTextLabel->show(); + m_dpiFld->show(); + m_dpiLabel->show(); + } + + m_fpsFld->setValue(fps); + m_unitsCB->setCurrentText(Preferences::instance()->getCameraUnits()); + m_dpi = cameraRes.lx / cameraSize.lx; + m_xRes = cameraRes.lx; + m_yRes = cameraRes.ly; + m_resXFld->setValue(m_xRes); + m_resYFld->setValue(m_yRes); + m_resXFld->setDecimals(0); + m_resYFld->setDecimals(0); + m_dpiFld->setValue(m_dpi); + + int boxWidth = m_sceneBox->width(); + int boxHeight = m_sceneBox->height(); + m_sceneBox->setFixedWidth(boxWidth); + m_projectBox->setFixedWidth(boxWidth); + m_recentBox->setMinimumHeight(boxHeight); + + // update recent scenes + // clear items if they exist first + + if (m_recentSceneLay->count() > 0) { + QLayoutItem *child; + while (m_recentSceneLay->count() != 0) { + child = m_recentSceneLay->takeAt(0); + delete child; + } + } + + m_sceneNames = RecentFiles::instance()->getFilesNameList(RecentFiles::Scene); + m_recentNamesLabels = QVector(m_sceneNames.count()); + + if (m_sceneNames.count() <= 0) { + m_recentSceneLay->addWidget(new QLabel(tr("No Recent Scenes"), this), 1, + Qt::AlignTop); + } else { + int i = 0; + for (QString name : m_sceneNames) { + if (i > 9) break; // box can hold 10 scenes + QString justName = QString::fromStdString(TFilePath(name).getName()); + m_recentNamesLabels[i] = new StartupLabel(justName, this, i); + m_recentSceneLay->addWidget(m_recentNamesLabels[i], i, Qt::AlignTop); + i++; + } + m_recentSceneLay->addStretch(100); + } + + bool ret = true; + for (int i = 0; i < m_recentNamesLabels.count() && i < 7; i++) { + ret = ret && connect(m_recentNamesLabels[i], SIGNAL(wasClicked(int)), this, + SLOT(onRecentSceneClicked(int))); + } + assert(ret); + // center window + this->move(QApplication::desktop()->screen()->rect().center() - + this->rect().center()); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onCreateButton() { + if (m_nameFld->text().trimmed() == "") { + DVGui::warning(tr("The name cannot be empty.")); + m_nameFld->setFocus(); + return; + } + if (!TSystem::doesExistFileOrLevel(TFilePath(m_pathFld->getPath()))) { + DVGui::warning(tr("The chosen file path is not valid.")); + m_pathFld->setFocus(); + return; + } + + if (m_widthFld->getValue() < 1) { + DVGui::warning(tr("The width must be 1 or more.")); + m_widthFld->setFocus(); + return; + } + if (m_heightFld->getValue() < 1) { + DVGui::warning(tr("The height must be 1 or more.")); + m_heightFld->setFocus(); + return; + } + if (m_fpsFld->getValue() < 1) { + DVGui::warning(tr("The frame rate must be 1 or more.")); + m_fpsFld->setFocus(); + return; + } + if (TSystem::doesExistFileOrLevel( + TFilePath(m_pathFld->getPath()) + + TFilePath(m_nameFld->text().trimmed().toStdWString() + L".tnz"))) { + QString question; + question = QObject::tr( + "The file name already exists." + "\nDo you want to overwrite it?"); + int ret = DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No"), 0); + if (ret == 0 || ret == 2) { + // no (or closed message box window) + return; + ; + } + } + CommandManager::instance()->execute(MI_NewScene); + TApp::instance()->getCurrentScene()->getScene()->setScenePath( + TFilePath(m_pathFld->getPath()) + + TFilePath(m_nameFld->text().trimmed().toStdWString())); + TDimensionD size = + TDimensionD(m_widthFld->getValue(), m_heightFld->getValue()); + TDimension res = TDimension(m_xRes, m_yRes); + double fps = m_fpsFld->getValue(); + TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProperties() + ->getOutputProperties() + ->setFrameRate(fps); + TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera()->setSize( + size); + TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera()->setRes( + res); + // this one is debatable - should the scene be saved right away? + // IoCmd::saveScene(); + // this makes sure the scene viewers update to the right fps + TApp::instance()->getCurrentScene()->notifySceneSwitched(); + + hide(); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::updateProjectCB() { + m_updating = true; + m_projectPaths.clear(); + m_projectsCB->clear(); + + TFilePath sandboxFp = TProjectManager::instance()->getSandboxProjectFolder() + + "sandbox_otprj.xml"; + m_projectPaths.push_back(sandboxFp); + m_projectsCB->addItem("sandbox"); + + std::vector prjRoots; + TProjectManager::instance()->getProjectRoots(prjRoots); + for (int i = 0; i < prjRoots.size(); i++) { + TFilePathSet fps; + TSystem::readDirectory_Dir_ReadExe(fps, prjRoots[i]); + + TFilePathSet::iterator it; + for (it = fps.begin(); it != fps.end(); ++it) { + TFilePath fp(*it); + if (TProjectManager::instance()->isProject(fp)) { + m_projectPaths.push_back( + TProjectManager::instance()->projectFolderToProjectPath(fp)); + m_projectsCB->addItem(QString::fromStdString(fp.getName())); + } + } + } + int i; + for (i = 0; i < m_projectPaths.size(); i++) { + if (TProjectManager::instance()->getCurrentProjectPath() == + m_projectPaths[i]) { + m_projectsCB->setCurrentIndex(i); + break; + } + } + m_pathFld->setPath(TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProject() + ->getScenesPath() + .getQString()); + m_updating = false; +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onProjectChanged(int index) { + if (m_updating) return; + TFilePath projectFp = m_projectPaths[index]; + + TProjectManager::instance()->setCurrentProjectPath(projectFp); + + IoCmd::newScene(); + m_pathFld->setPath(TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProject() + ->getScenesPath() + .getQString()); + m_fpsFld->setValue(TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProperties() + ->getOutputProperties() + ->getFrameRate()); + TDimension res = TApp::instance() + ->getCurrentScene() + ->getScene() + ->getCurrentCamera() + ->getRes(); + m_xRes = res.lx; + m_yRes = res.ly; + m_resXFld->setValue(m_xRes); + m_resYFld->setValue(m_yRes); + TDimensionD size = TApp::instance() + ->getCurrentScene() + ->getScene() + ->getCurrentCamera() + ->getSize(); + m_widthFld->setValue(size.lx); + m_heightFld->setValue(size.ly); + m_dpi = m_xRes / size.lx; + m_dpiFld->setValue(m_dpi); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::loadPresetList() { + m_presetCombo->clear(); + m_presetCombo->addItem("..."); + m_presetListFile = ToonzFolder::getReslistPath(false).getQString(); + QFile file(m_presetListFile); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&file); + while (!in.atEnd()) { + QString line = in.readLine().trimmed(); + if (line != "") m_presetCombo->addItem(line); + } + } + m_presetCombo->setCurrentIndex(0); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::savePresetList() { + QFile file(m_presetListFile); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; + QTextStream out(&file); + int n = m_presetCombo->count(); + for (int i = 1; i < n; i++) out << m_presetCombo->itemText(i) << "\n"; +} + +//----------------------------------------------------------------------------- + +void StartupPopup::addPreset() { + int xRes = (int)(m_widthFld->getValue() * m_dpi); + int yRes = (int)(m_heightFld->getValue() * m_dpi); + double lx = m_widthFld->getValue(); + double ly = m_heightFld->getValue(); + double ar = m_widthFld->getValue() / m_heightFld->getValue(); + + QString presetString; + presetString = QString::number(xRes) + "x" + QString::number(yRes) + ", " + + removeZeros(QString::number(lx)) + "x" + + removeZeros(QString::number(ly)) + ", " + + aspectRatioValueToString(ar); + + bool ok; + QString qs; + while (1) { + qs = DVGui::getText(tr("Preset name"), + tr("Enter the name for %1").arg(presetString), "", &ok); + + if (!ok) return; + + if (qs.indexOf(",") != -1) + QMessageBox::warning(this, tr("Error : Preset Name is Invalid"), + tr("The preset name must not use ','(comma).")); + else + break; + } + + int oldn = m_presetCombo->count(); + m_presetCombo->addItem(qs + "," + presetString); + int newn = m_presetCombo->count(); + m_presetCombo->blockSignals(true); + m_presetCombo->setCurrentIndex(m_presetCombo->count() - 1); + m_presetCombo->blockSignals(false); + + savePresetList(); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::removePreset() { + int index = m_presetCombo->currentIndex(); + if (index <= 0) return; + + // confirmation dialog + int ret = DVGui::MsgBox(QObject::tr("Deleting \"%1\".\nAre you sure?") + .arg(m_presetCombo->currentText()), + QObject::tr("Delete"), QObject::tr("Cancel")); + if (ret == 0 || ret == 2) return; + + m_presetCombo->removeItem(index); + m_presetCombo->setCurrentIndex(0); + savePresetList(); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onPresetSelected(const QString &str) { + if (str == custom || str.isEmpty()) return; + QString name, arStr; + int xres = 0, yres = 0; + double fx = -1.0, fy = -1.0; + QString xoffset = "", yoffset = ""; + double ar; + + if (parsePresetString(str, name, xres, yres, fx, fy, xoffset, yoffset, ar, + false)) { + m_xRes = xres; + m_yRes = yres; + // The current solution is to preserve the DPI so that scenes are less + // likely to become incompatible with pixels only mode in the future + // Commented below is the default behavior of the camera settings widget + // m_widthFld->setValue(m_heightFld->getValue() * ar); + // m_dpiFld->setValue(m_xRes / m_widthFld->getValue()); + + // here is the system that preserves dpi + m_widthFld->setValue((double)xres / (double)m_dpi); + m_heightFld->setValue((double)yres / (double)m_dpi); + if (Preferences::instance()->getPixelsOnly()) { + m_widthFld->setValue((double)xres / Stage::standardDpi); + m_heightFld->setValue((double)yres / Stage::standardDpi); + m_dpiFld->setValue(Stage::standardDpi); + } + m_resXFld->setValue(m_xRes); + m_resYFld->setValue(m_yRes); + } else { + QMessageBox::warning( + this, tr("Bad camera preset"), + tr("'%1' doesn't seem to be a well formed camera preset. \n" + "Possibly the preset file has been corrupted") + .arg(str)); + } +} + +//-------------------------------------------------------------------------- + +bool StartupPopup::parsePresetString(const QString &str, QString &name, + int &xres, int &yres, double &fx, + double &fy, QString &xoffset, + QString &yoffset, double &ar, + bool forCleanup) { + /* + parsing preset string with QString::split(). + !NOTE! fx/fy (camera size in inch) and xoffset/yoffset (camera offset used in + cleanup camera) are optional, + in order to keep compatibility with default (Harlequin's) reslist.txt + */ + + QStringList tokens = str.split(",", QString::SkipEmptyParts); + + if (!(tokens.count() == 3 || + (!forCleanup && tokens.count() == 4) || /*- with "fx x fy" token -*/ + (forCleanup && + tokens.count() == + 6))) /*- with "fx x fy", xoffset and yoffset tokens -*/ + return false; + /*- name -*/ + name = tokens[0]; + + /*- xres, yres (like: 1024x768) -*/ + QStringList values = tokens[1].split("x"); + if (values.count() != 2) return false; + bool ok; + xres = values[0].toInt(&ok); + if (!ok) return false; + yres = values[1].toInt(&ok); + if (!ok) return false; + + if (tokens.count() >= 4) { + /*- fx, fy -*/ + values = tokens[2].split("x"); + if (values.count() != 2) return false; + fx = values[0].toDouble(&ok); + if (!ok) return false; + fy = values[1].toDouble(&ok); + if (!ok) return false; + + /*- xoffset, yoffset -*/ + if (forCleanup) { + xoffset = tokens[3]; + yoffset = tokens[4]; + /*- remove single space -*/ + if (xoffset.startsWith(' ')) xoffset.remove(0, 1); + if (yoffset.startsWith(' ')) yoffset.remove(0, 1); + } + } + + /*- AR -*/ + ar = aspectRatioStringToValue(tokens.last()); + + return true; +} + +//----------------------------------------------------------------------------- + +double StartupPopup::aspectRatioStringToValue(const QString &s) { + if (s == "") { + return 1; + } + int i = s.indexOf("/"); + if (i <= 0 || i + 1 >= s.length()) return s.toDouble(); + int num = s.left(i).toInt(); + int den = s.mid(i + 1).toInt(); + if (den <= 0) den = 1; + return (double)num / (double)den; +} + +//----------------------------------------------------------------------------- + +// A/R : value => string (e.g. '4/3' or '1.23') +QString StartupPopup::aspectRatioValueToString(double value, int width, + int height) { + double v = value; + + if (width != 0 && height != 0) { + if (areAlmostEqual(value, (double)width / (double)height, 1e-3)) + return QString("%1/%2").arg(width).arg(height); + } + + double iv = tround(v); + if (fabs(iv - v) > 0.01) { + for (int d = 2; d < 20; d++) { + int n = tround(v * d); + if (fabs(n - v * d) <= 0.01) + return QString::number(n) + "/" + QString::number(d); + } + return QString::number(value, 'f', 5); + } else { + return QString::number((int)iv); + } +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onNewProjectButtonPressed() { + CommandManager::instance()->execute(MI_NewProject); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onSceneChanged() { + // close the box if a recent scene has been selected + if (!TApp::instance()->getCurrentScene()->getScene()->isUntitled()) { + hide(); + } else { + updateProjectCB(); + } +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onDpiChanged() { + if (Preferences::instance()->getPixelsOnly()) { + m_dpi = Stage::standardDpi; + m_dpiFld->setValue(Stage::standardDpi); + updateResolution(); + } else { + m_dpi = m_dpiFld->getValue(); + updateResolution(); + } +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onLoadSceneButtonPressed() { + CommandManager::instance()->execute(MI_LoadScene); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onRecentSceneClicked(int index) { + if (index < 0) return; + QString path = + RecentFiles::instance()->getFilePath(index, RecentFiles::Scene); + IoCmd::loadScene(TFilePath(path.toStdWString()), false); + RecentFiles::instance()->moveFilePath(index, 0, RecentFiles::Scene); + RecentFiles::instance()->refreshRecentFilesMenu(RecentFiles::Scene); + hide(); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onCameraUnitChanged(int index) { + Preferences *pref = Preferences::instance(); + QStringList type; + type << tr("pixel") << tr("cm") << tr("mm") << tr("inch") << tr("field"); + + double width = m_widthFld->getValue(); + double height = m_heightFld->getValue(); + if (index != 0) { + pref->setPixelsOnly(false); + pref->setCameraUnits(type[index].toStdString()); + m_widthFld->setDecimals(4); + m_heightFld->setDecimals(4); + m_resTextLabel->show(); + m_resXFld->show(); + m_resYFld->show(); + m_resXLabel->show(); + m_dpiFld->show(); + m_dpiLabel->show(); + m_widthFld->setMeasure("camera.lx"); + m_heightFld->setMeasure("camera.ly"); + m_widthFld->setValue(width); + m_heightFld->setValue(height); + } else { + pref->setPixelsOnly(true); + pref->setUnits("pixel"); + pref->setCameraUnits("pixel"); + m_widthFld->setDecimals(0); + m_heightFld->setDecimals(0); + m_resTextLabel->hide(); + m_resXFld->hide(); + m_resYFld->hide(); + m_resXLabel->hide(); + m_dpiFld->hide(); + m_dpiLabel->hide(); + m_dpiFld->setValue(Stage::standardDpi); + m_widthFld->setMeasure("camera.lx"); + m_heightFld->setMeasure("camera.ly"); + m_widthFld->setValue(m_xRes / Stage::standardDpi); + m_heightFld->setValue(m_yRes / Stage::standardDpi); + } +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onShowAtStartChanged(int index) { + Preferences::instance()->enableStartupPopup(index); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::updateResolution() { + if (Preferences::instance()->getPixelsOnly()) { + if (m_dpiFld->getValue() != Stage::standardDpi) { + m_dpiFld->setValue(Stage::standardDpi); + } + m_xRes = m_widthFld->getValue() * Stage::standardDpi; + m_yRes = m_heightFld->getValue() * Stage::standardDpi; + m_resXFld->setValue(m_xRes); + m_resYFld->setValue(m_yRes); + } else { + m_xRes = m_widthFld->getValue() * m_dpi; + m_yRes = m_heightFld->getValue() * m_dpi; + m_resXFld->setValue(m_xRes); + m_resYFld->setValue(m_yRes); + } + m_presetCombo->setCurrentIndex(0); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::updateSize() { + m_xRes = m_resXFld->getValue(); + m_yRes = m_resYFld->getValue(); + if (Preferences::instance()->getPixelsOnly()) { + if (m_dpiFld->getValue() != Stage::standardDpi) { + m_dpiFld->setValue(Stage::standardDpi); + } + m_widthFld->setValue((double)m_xRes / Stage::standardDpi); + m_heightFld->setValue((double)m_yRes / Stage::standardDpi); + } else { + m_widthFld->setValue((double)m_xRes / m_dpi); + m_heightFld->setValue((double)m_yRes / m_dpi); + } + m_presetCombo->setCurrentIndex(0); +} + +//----------------------------------------------------------------------------- + +StartupLabel::StartupLabel(const QString &text, QWidget *parent, int index) + : QLabel(parent), m_index(index) { + setText(text); +} + +StartupLabel::~StartupLabel() {} + +void StartupLabel::mousePressEvent(QMouseEvent *event) { + m_text = text(); + std::string strText = m_text.toStdString(); + emit wasClicked(m_index); +} + +OpenPopupCommandHandler openStartupPopup(MI_StartupPopup); diff --git a/toonz/sources/toonz/startuppopup.h b/toonz/sources/toonz/startuppopup.h new file mode 100644 index 0000000..cd1e33d --- /dev/null +++ b/toonz/sources/toonz/startuppopup.h @@ -0,0 +1,109 @@ +#pragma once + +#ifndef STARTUPPOPUP_H +#define STARTUPPOPUP_H + +#include "toonzqt/dvdialog.h" +#include "toonzqt/doublefield.h" +#include "toonzqt/intfield.h" +#include "toonzqt/filefield.h" +#include "toonzqt/camerasettingswidget.h" +#include +#include +#include +#include + +// forward declaration +class QLabel; +class QComboBox; +class StartupLabel; + +//============================================================================= +// LevelCreatePopup +//----------------------------------------------------------------------------- + +class StartupPopup final : public DVGui::Dialog { + Q_OBJECT + + DVGui::LineEdit *m_nameFld; + DVGui::FileField *m_pathFld; + QLabel *m_widthLabel; + QLabel *m_heightLabel; + QLabel *m_fpsLabel; + QLabel *m_resXLabel; + QLabel *m_resTextLabel; + QLabel *m_dpiLabel; + QLabel *m_sceneNameLabel; + DVGui::DoubleLineEdit *m_dpiFld; + DVGui::MeasuredDoubleLineEdit *m_widthFld; + DVGui::MeasuredDoubleLineEdit *m_heightFld; + DVGui::DoubleLineEdit *m_fpsFld; + DVGui::DoubleLineEdit *m_resXFld; + DVGui::DoubleLineEdit *m_resYFld; + QList m_sceneNames; + QList m_projectPaths; + QCheckBox *m_showAtStartCB; + QComboBox *m_projectsCB; + QComboBox *m_unitsCB; + QPushButton *m_loadOtherSceneButton; + QPushButton *m_newProjectButton; + QComboBox *m_presetCombo; + QPushButton *m_addPresetBtn, *m_removePresetBtn; + CameraSettingsWidget *m_cameraSettingsWidget; + double m_dpi; + int m_xRes, m_yRes; + bool m_updating = false; + QString m_presetListFile; + QGroupBox *m_projectBox; + QGroupBox *m_sceneBox; + QGroupBox *m_recentBox; + QVBoxLayout *m_recentSceneLay; + QVector m_recentNamesLabels; + +public: + StartupPopup(); + +protected: + void showEvent(QShowEvent *) override; + void loadPresetList(); + void savePresetList(); + QString aspectRatioValueToString(double value, int width = 0, int height = 0); + double aspectRatioStringToValue(const QString &s); + bool parsePresetString(const QString &str, QString &name, int &xres, + int &yres, double &fx, double &fy, QString &xoffset, + QString &yoffset, double &ar, bool forCleanup = false); + +public slots: + void onRecentSceneClicked(int index); + void onCreateButton(); + void onShowAtStartChanged(int index); + void updateProjectCB(); + void onProjectChanged(int index); + void onNewProjectButtonPressed(); + void onLoadSceneButtonPressed(); + void onSceneChanged(); + void updateResolution(); + void updateSize(); + void onDpiChanged(); + void addPreset(); + void removePreset(); + void onPresetSelected(const QString &str); + void onCameraUnitChanged(int index); +}; + +class StartupLabel : public QLabel { + Q_OBJECT +public: + explicit StartupLabel(const QString &text = "", QWidget *parent = 0, + int index = -1); + ~StartupLabel(); + QString m_text; + int m_index; +signals: + void wasClicked(int index); + +protected: + void mousePressEvent(QMouseEvent *event); +}; + +#endif // STARTUPPOPUP_H diff --git a/toonz/sources/toonz/toonz.qrc b/toonz/sources/toonz/toonz.qrc index 75aa7a1..cbc6f88 100644 --- a/toonz/sources/toonz/toonz.qrc +++ b/toonz/sources/toonz/toonz.qrc @@ -264,6 +264,7 @@ Resources/standard.png Resources/standard_on.png Resources/standard_over.png + Resources/startup.png Resources/start_off.png Resources/start_on.png Resources/stop_off.png diff --git a/toonz/sources/toonzlib/preferences.cpp b/toonz/sources/toonzlib/preferences.cpp index 2418bc8..07f7fcf 100644 --- a/toonz/sources/toonzlib/preferences.cpp +++ b/toonz/sources/toonzlib/preferences.cpp @@ -257,6 +257,7 @@ Preferences::Preferences() , m_autosaveEnabled(false) , m_autosaveSceneEnabled(true) , m_autosaveOtherFilesEnabled(true) + , m_startupPopupEnabled(true) , m_defaultViewerEnabled(false) , m_saveUnpaintedInCleanup(true) , m_askForOverrideRender(true) @@ -330,6 +331,7 @@ Preferences::Preferences() getValue(*m_settings, "autosaveSceneEnabled", m_autosaveSceneEnabled); getValue(*m_settings, "autosaveOtherFilesEnabled", m_autosaveOtherFilesEnabled); + getValue(*m_settings, "startupPopupEnabled", m_startupPopupEnabled); getValue(*m_settings, "defaultViewerEnabled", m_defaultViewerEnabled); getValue(*m_settings, "rasterOptimizedMemory", m_rasterOptimizedMemory); getValue(*m_settings, "saveUnpaintedInCleanup", m_saveUnpaintedInCleanup); @@ -667,6 +669,13 @@ void Preferences::enableAutosaveOtherFiles(bool on) { //----------------------------------------------------------------- +void Preferences::enableStartupPopup(bool on) { + m_startupPopupEnabled = on; + m_settings->setValue("startupPopupEnabled", on ? "1" : "0"); +} + +//----------------------------------------------------------------- + void Preferences::setAskForOverrideRender(bool on) { m_autosaveEnabled = on; m_settings->setValue("askForOverrideRender", on ? "1" : "0");