19 #include "mainwindow2.h"
20 #include "ui_mainwindow2.h"
27 #include <QMessageBox>
28 #include <QProgressDialog>
29 #include <QTabletEvent>
30 #include <QStandardPaths>
35 #include "pencildef.h"
36 #include "pencilsettings.h"
40 #include "filemanager.h"
41 #include "colormanager.h"
42 #include "layermanager.h"
43 #include "toolmanager.h"
44 #include "playbackmanager.h"
45 #include "selectionmanager.h"
46 #include "soundmanager.h"
47 #include "viewmanager.h"
49 #include "actioncommands.h"
50 #include "fileformat.h"
52 #include "backupelement.h"
56 #include "colorinspector.h"
57 #include "colorpalettewidget.h"
58 #include "displayoptionwidget.h"
59 #include "tooloptionwidget.h"
60 #include "preferencesdialog.h"
63 #include "onionskinwidget.h"
67 #include "errordialog.h"
68 #include "filedialog.h"
69 #include "importimageseqdialog.h"
70 #include "importlayersdialog.h"
71 #include "importpositiondialog.h"
72 #include "recentfilemenu.h"
73 #include "shortcutfilter.h"
75 #include "presetdialog.h"
76 #include "pegbaralignmentdialog.h"
80 #define BUILD_DATE S__GIT_TIMESTAMP
82 #define BUILD_DATE __DATE__
85 #if defined(PENCIL2D_RELEASE_BUILD)
86 #define PENCIL_WINDOW_TITLE QString("[*]Pencil2D v%1").arg(APP_VERSION)
87 #elif defined(PENCIL2D_NIGHTLY_BUILD)
88 #define PENCIL_WINDOW_TITLE QString("[*]Pencil2D Nightly Build %1").arg(BUILD_DATE)
90 #define PENCIL_WINDOW_TITLE QString("[*]Pencil2D Development Build %1").arg(BUILD_DATE)
95 MainWindow2::MainWindow2(
QWidget* parent) :
103 mEditor =
new Editor(
this);
104 mEditor->setScribbleArea(ui->scribbleArea);
109 ui->scribbleArea->setEditor(mEditor);
110 ui->scribbleArea->init();
112 mEditor->setScribbleArea(ui->scribbleArea);
113 makeConnections(mEditor, ui->scribbleArea);
116 mCommands->setCore(mEditor);
120 setupKeyboardShortcuts();
124 mZoomLabel =
new QLabel(
"");
125 ui->statusbar->addWidget(mZoomLabel);
130 connect(mEditor, &Editor::needSave,
this, &MainWindow2::autoSave);
131 connect(mToolBox, &ToolBoxWidget::clearButtonClicked, mEditor, &Editor::clearCurrentFrame);
132 connect(mEditor->view(), &ViewManager::viewChanged,
this, &MainWindow2::updateZoomLabel);
134 mEditor->tools()->setDefaultTool();
135 ui->background->init(mEditor->preference());
140 MainWindow2::~MainWindow2()
145 void MainWindow2::createDockWidgets()
148 mTimeLine->setObjectName(
"TimeLine");
151 mColorBox->setToolTip(
tr(
"color palette:<br>use <b>(C)</b><br>toggle at cursor"));
152 mColorBox->setObjectName(
"ColorWheel");
155 mColorInspector->setToolTip(
tr(
"Color inspector"));
156 mColorInspector->setObjectName(
"Color Inspector");
159 mColorPalette->setCore(mEditor);
160 mColorPalette->setObjectName(
"ColorPalette");
163 mDisplayOptionWidget->setObjectName(
"DisplayOption");
166 mOnionSkinWidget->setObjectName(
"Onion Skin");
169 mToolOptions->setObjectName(
"ToolOption");
172 mToolBox->setObjectName(
"ToolBox");
185 << mDisplayOptionWidget
190 mStartIcon =
QIcon(
":icons/controls/play.png");
191 mStopIcon =
QIcon(
":icons/controls/stop.png");
199 pWidget->setEditor(mEditor);
202 qDebug() <<
"Init Dock widget: " << pWidget->objectName();
213 setDockNestingEnabled(
true);
223 makeConnections(mEditor);
224 makeConnections(mEditor, mTimeLine);
225 makeConnections(mEditor, mColorBox);
226 makeConnections(mEditor, mColorInspector);
227 makeConnections(mEditor, mColorPalette);
228 makeConnections(mEditor, mToolOptions);
229 makeConnections(mEditor, mDisplayOptionWidget);
234 w->setFloating(
false);
238 void MainWindow2::createMenus()
278 connect(mEditor->select(), &SelectionManager::selectionChanged,
this, &MainWindow2::selectionChanged);
292 connect(ui->actionChangeLineColorCurrent_keyframe, &
QAction::triggered, mCommands, &ActionCommands::changeKeyframeLineColor);
293 connect(ui->actionChangeLineColorAll_keyframes_on_layer, &
QAction::triggered, mCommands, &ActionCommands::changeallKeyframeLineColor);
295 QList<QAction*> visibilityActions = ui->menuLayer_Visibility->actions();
297 visibilityGroup->setExclusive(
true);
298 for (
int i = 0; i < visibilityActions.
size(); i++) {
299 QAction* action = visibilityActions[i];
300 visibilityGroup->addAction(action);
303 visibilityActions[mEditor->preference()->getInt(SETTING::LAYER_VISIBILITY)]->setChecked(
true);
304 connect(mEditor->preference(), &PreferenceManager::optionChanged, [=](SETTING e) {
305 if (e == SETTING::LAYER_VISIBILITY) {
306 visibilityActions[mEditor->preference()->getInt(SETTING::LAYER_VISIBILITY)]->setChecked(
true);
327 connect(mEditor->view(), &ViewManager::viewFlipped,
this, &MainWindow2::viewFlipped);
330 bindPreferenceSetting(ui->actionGrid, prefs, SETTING::GRID);
331 bindPreferenceSetting(ui->actionOnionPrev, prefs, SETTING::PREV_ONION);
332 bindPreferenceSetting(ui->actionOnionNext, prefs, SETTING::NEXT_ONION);
341 connect(pPlaybackManager, &PlaybackManager::loopStateChanged, mTimeLine, &TimeLine::setLoop);
343 connect(pPlaybackManager, &PlaybackManager::rangedPlaybackStateChanged, mTimeLine, &TimeLine::setRangeState);
344 connect(pPlaybackManager, &PlaybackManager::playStateChanged, mTimeLine, &TimeLine::setPlaying);
345 connect(pPlaybackManager, &PlaybackManager::playStateChanged,
this, &MainWindow2::changePlayState);
346 connect(pPlaybackManager, &PlaybackManager::playStateChanged, mEditor, &Editor::updateCurrentFrame);
375 QMenu* winMenu = ui->menuWindows;
376 const std::vector<QAction*>
actions
378 mToolBox->toggleViewAction(),
379 mToolOptions->toggleViewAction(),
380 mColorBox->toggleViewAction(),
381 mColorPalette->toggleViewAction(),
382 mTimeLine->toggleViewAction(),
383 mDisplayOptionWidget->toggleViewAction(),
384 mColorInspector->toggleViewAction(),
385 mOnionSkinWidget->toggleViewAction()
391 winMenu->addAction(action);
395 bindPreferenceSetting(ui->actionLockWindows, prefs, SETTING::LAYOUT_LOCK);
410 mRecentFileMenu->loadFromDisk();
411 ui->menuFile->insertMenu(ui->actionSave, mRecentFileMenu);
413 connect(mRecentFileMenu, &RecentFileMenu::loadRecentFile,
this, &MainWindow2::openFile);
419 void MainWindow2::setOpacity(
int opacity)
421 mEditor->preference()->set(SETTING::WINDOW_OPACITY, 100 - opacity);
425 void MainWindow2::updateSaveState()
430 void MainWindow2::clearRecentFilesList()
432 QStringList recentFilesList = mRecentFileMenu->getRecentFiles();
433 if (!recentFilesList.
isEmpty())
435 mRecentFileMenu->
clear();
436 mRecentFileMenu->saveToDisk();
438 tr(
"\n\n You have successfully cleared the list"),
441 getPrefDialog()->updateRecentListBtn(!recentFilesList.
isEmpty());
444 void MainWindow2::openPegAlignDialog()
446 if (mPegAlign !=
nullptr)
449 tr(
"Dialog is already open!"),
456 mPegAlign->updatePegRegLayers();
457 mPegAlign->setRefLayer(mEditor->layers()->currentLayer()->name());
458 mPegAlign->setRefKey(mEditor->currentFrame());
462 flags &= (~Qt::WindowContextHelpButtonHint);
463 mPegAlign->setWindowFlags(flags);
471 void MainWindow2::currentLayerChanged()
473 bool isBitmap = (mEditor->layers()->currentLayer()->type() == Layer::BITMAP);
474 ui->menuChange_line_color->setEnabled(isBitmap);
477 void MainWindow2::selectionChanged()
479 bool somethingSelected = mEditor->select()->somethingSelected();
480 ui->menuSelection->setEnabled(somethingSelected);
483 void MainWindow2::viewFlipped()
485 ui->actionHorizontal_Flip->setChecked(mEditor->view()->isFlipHorizontal());
486 ui->actionVertical_Flip->setChecked(mEditor->view()->isFlipVertical());
505 m2ndCloseEvent =
true;
510 static bool firstShowEvent =
true;
515 firstShowEvent =
false;
516 if (tryRecoverUnsavedProject() || loadMostRecent() || tryLoadPreset()) {
return; }
525 void MainWindow2::newDocument()
527 if (maybeSave() && !tryLoadPreset())
533 void MainWindow2::openDocument()
542 openObject(fileName);
546 bool MainWindow2::saveAsNewDocument()
553 return saveObject(fileName);
556 void MainWindow2::openFile(
const QString& filename)
560 openObject(filename);
564 bool MainWindow2::openObject(
const QString& strFilePath)
568 if (fileInfo.isDir())
571 tr(
"The file you have selected is a directory, so we are unable to open it. "
572 "If you are are trying to open a project that uses the old structure, "
573 "please open the file ending with .pcl, not the data folder."),
574 QString(
"Raw file path: %1\nResolved file path: %2").arg(strFilePath, fileInfo.absoluteFilePath()));
578 if (!fileInfo.exists())
581 tr(
"The file you have selected does not exist, so we are unable to open it. "
582 "Please make sure that you've entered the correct path and that the file is accessible and try again."),
583 QString(
"Raw file path: %1\nResolved file path: %2").arg(strFilePath, fileInfo.absoluteFilePath()));
587 if (!fileInfo.isReadable())
590 tr(
"This program does not have permission to read the file you have selected. "
591 "Please check that you have read permissions for this file and try again."),
592 QString(
"Raw file path: %1\nResolved file path: %2\nPermissions: 0x%3") \
593 .arg(strFilePath, fileInfo.absoluteFilePath(),
QString::number(fileInfo.permissions(), 16)));
597 if (!fileInfo.isWritable())
600 tr(
"This program does not currently have permission to write to the file you have selected. "
601 "Please make sure you have write permission for this file before attempting to save it. "
602 "Alternatively, you can use the Save As... menu option to save to a writable location."),
611 hideQuestionMark(progress);
618 connect(&fm, &FileManager::progressChanged, [&progress](
int p)
620 progress.setValue(p);
623 connect(&fm, &FileManager::progressRangeChanged, [&progress](
int max)
625 progress.setRange(0, max + 3);
628 QString fullPath = fileInfo.absoluteFilePath();
630 Object*
object = fm.load(fullPath);
632 if (!fm.error().ok())
634 Status error = fm.error();
637 <<
QString(
"Resolved file path: ").
append(fileInfo.absoluteFilePath());
638 dd.collect(error.details());
639 ErrorDialog errorDialog(error.title(), error.description(), dd.str());
641 emptyDocumentWhenErrorOccurred();
645 if (
object ==
nullptr)
648 tr(
"An unknown error occurred while trying to load the file and we are not able to load your file."),
649 QString(
"Raw file path: %1\nResolved file path: %2").arg(strFilePath, fullPath));
651 emptyDocumentWhenErrorOccurred();
655 mEditor->setObject(
object);
658 settings.setValue(LAST_PCLX_PATH, object->filePath());
661 if (!object->filePath().
isEmpty())
663 mRecentFileMenu->addRecentFile(object->filePath());
664 mRecentFileMenu->saveToDisk();
670 progress.setValue(progress.value() + 1);
672 mEditor->layers()->notifyAnimationLengthChanged();
673 mEditor->setFps(mEditor->playback()->fps());
675 progress.setValue(progress.maximum());
681 bool MainWindow2::saveObject(
QString strSavedFileName)
684 hideQuestionMark(progress);
688 mEditor->prepareSave();
692 connect(&fm, &FileManager::progressChanged, [&progress](
int p)
694 progress.setValue(p);
697 connect(&fm, &FileManager::progressRangeChanged, [&progress](
int max)
699 progress.setRange(0, max + 3);
702 Status st = fm.save(mEditor->object(), strSavedFileName);
707 #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
712 errorLogFolder.mkpath(
"./logs");
713 errorLogFolder.cd(
"logs");
721 out << st.details().str();
726 st.description().append(
tr(
"<br><br>An error has occurred and your file may not have saved successfully."
727 "If you believe that this error is an issue with Pencil2D, please create a new issue at:"
728 "<br><a href='https://github.com/pencil2d/pencil/issues'>https://github.com/pencil2d/pencil/issues</a><br>"
729 "Please be sure to include the following details in your issue:")), st.details().html());
734 mEditor->object()->setFilePath(strSavedFileName);
735 mEditor->object()->setModified(
false);
737 mEditor->clearTemporary();
740 settings.setValue(LAST_PCLX_PATH, strSavedFileName);
742 mRecentFileMenu->addRecentFile(strSavedFileName);
743 mRecentFileMenu->saveToDisk();
745 mTimeLine->updateContent();
748 mBackupAtSave = mEditor->currentBackup();
751 progress.setValue(progress.maximum());
753 mEditor->resetAutoSaveCounter();
758 bool MainWindow2::saveDocument()
760 if (!mEditor->object()->filePath().
isEmpty())
761 return saveObject(mEditor->object()->filePath());
763 return saveAsNewDocument();
766 bool MainWindow2::maybeSave()
768 if (mEditor->currentBackup() == mBackupAtSave)
774 tr(
"This animation has been modified.\n Do you want to save your changes?"),
777 return saveDocument();
782 bool MainWindow2::autoSave()
784 if (!mEditor->object()->filePath().
isEmpty())
786 return saveDocument();
789 if (mEditor->autoSaveNeverAskAgain())
792 if(mSuppressAutoSaveDialog)
797 msgBox.setWindowTitle(
tr(
"AutoSave Reminder"));
798 msgBox.setText(
tr(
"The animation is not saved yet.\n Do you want to save now?"));
803 int ret = msgBox.exec();
806 return saveDocument();
810 mEditor->dontAskAutoSave(
true);
816 void MainWindow2::emptyDocumentWhenErrorOccurred()
824 void MainWindow2::importImage()
828 if (strFilePath.
isEmpty()) {
return; }
832 OnScopeExit(
delete positionDialog)
834 positionDialog->setCore(mEditor);
835 positionDialog->
exec();
842 bool ok = mEditor->importImage(strFilePath);
847 tr(
"Unable to import image.<br><b>TIP:</b> Use Bitmap layer to import bitmaps."),
853 ui->scribbleArea->updateCurrentFrame();
854 mTimeLine->updateContent();
857 void MainWindow2::importImageSequence()
859 mSuppressAutoSaveDialog =
true;
862 OnScopeExit(
delete imageSeqDialog)
863 imageSeqDialog->setCore(mEditor);
867 imageSeqDialog->
exec();
874 OnScopeExit(
delete positionDialog)
876 positionDialog->setCore(mEditor);
877 positionDialog->
exec();
883 imageSeqDialog->importArbitrarySequence();
885 mSuppressAutoSaveDialog =
false;
888 void MainWindow2::importPredefinedImageSet()
891 OnScopeExit(
delete imageSeqDialog)
892 imageSeqDialog->setCore(mEditor);
896 mSuppressAutoSaveDialog = true;
897 imageSeqDialog->
exec();
904 OnScopeExit(
delete positionDialog)
906 positionDialog->setCore(mEditor);
907 positionDialog->
exec();
913 imageSeqDialog->importPredefinedSet();
914 mSuppressAutoSaveDialog =
false;
917 void MainWindow2::importLayers()
920 importLayers->setCore(mEditor);
922 importLayers->
open();
925 void MainWindow2::importGIF()
935 mSuppressAutoSaveDialog =
true;
938 OnScopeExit(
delete positionDialog)
940 positionDialog->setCore(mEditor);
941 positionDialog->
exec();
947 int space = gifDialog->getSpace();
951 hideQuestionMark(progress);
955 QString strImgFileLower = gifDialog->getFilePath();
960 bool ok = mEditor->importGIF(strImgFileLower, space);
964 progress.setValue(50);
972 tr(
"was unable to import %1").arg(strImgFileLower),
977 progress.setValue(100);
980 mSuppressAutoSaveDialog =
false;
983 void MainWindow2::lockWidgets(
bool shouldLock)
989 d->setFeatures(feat);
994 QWidget* customTitleBarWidget = shouldLock ? (
new QWidget) :
nullptr;
995 d->setTitleBarWidget(customTitleBarWidget);
999 void MainWindow2::preferences()
1003 mPrefDialog->activateWindow();
1004 mPrefDialog->raise();
1010 mPrefDialog->init(mEditor->preference());
1012 connect(mPrefDialog, &PreferencesDialog::windowOpacityChange,
this, &MainWindow2::setOpacity);
1013 connect(mPrefDialog, &PreferencesDialog::soundScrubChanged, mEditor->playback(), &PlaybackManager::setSoundScrubActive);
1014 connect(mPrefDialog, &PreferencesDialog::soundScrubMsecChanged, mEditor->playback(), &PlaybackManager::setSoundScrubMsec);
1017 clearKeyboardShortcuts();
1018 setupKeyboardShortcuts();
1019 ui->scribbleArea->updateCanvasCursor();
1020 mPrefDialog =
nullptr;
1023 mPrefDialog->show();
1026 void MainWindow2::resetAndDockAllSubWidgets()
1029 settings.remove(SETTING_WINDOW_GEOMETRY);
1030 settings.remove(SETTING_WINDOW_STATE);
1034 dock->setFloating(
false);
1049 void MainWindow2::newObject()
const
1051 auto object =
new Object();
1053 object->createDefaultLayers();
1054 mEditor->setObject(
object);
1057 bool MainWindow2::newObjectFromPresets(
int presetIndex)
1059 QString presetFilePath = PresetDialog::getPresetPath(presetIndex);
1067 Object*
object = fm.load(presetFilePath);
1069 if (!fm.error().ok() ||
object ==
nullptr)
1074 mEditor->setObject(
object);
1075 object->setFilePath(
QString());
1083 bool MainWindow2::loadMostRecent()
1085 if(!mEditor->preference()->isOn(SETTING::LOAD_MOST_RECENT))
1091 QString myPath = settings.value(LAST_PCLX_PATH,
QVariant(
"")).toString();
1096 return openObject(myPath);
1099 bool MainWindow2::tryLoadPreset()
1101 if (!mEditor->preference()->isOn(SETTING::ASK_FOR_PRESET))
1103 int defaultPreset = mEditor->preference()->getInt(SETTING::DEFAULT_PRESET);
1104 return newObjectFromPresets(defaultPreset);
1116 int presetIndex = presetDialog->getPresetIndex();
1117 if (presetDialog->shouldAlwaysUse())
1119 mEditor->preference()->set(SETTING::ASK_FOR_PRESET,
false);
1120 mEditor->preference()->set(SETTING::DEFAULT_PRESET, presetIndex);
1122 if (!newObjectFromPresets(presetIndex))
1127 presetDialog->
open();
1131 void MainWindow2::readSettings()
1135 QVariant winGeometry = settings.
value(SETTING_WINDOW_GEOMETRY);
1139 restoreState(winState.toByteArray());
1141 int opacity = mEditor->preference()->getInt(SETTING::WINDOW_OPACITY);
1142 setOpacity(100 - opacity);
1144 bool isWindowsLocked = mEditor->preference()->isOn(SETTING::LAYOUT_LOCK);
1145 lockWidgets(isWindowsLocked);
1148 void MainWindow2::writeSettings()
1151 settings.setValue(SETTING_WINDOW_GEOMETRY,
saveGeometry());
1152 settings.setValue(SETTING_WINDOW_STATE, saveState());
1155 void MainWindow2::setupKeyboardShortcuts()
1157 checkExistingShortcuts();
1161 strCommandName =
QString(
"shortcuts/") + strCommandName;
1166 ui->actionNew->setShortcut(cmdKeySeq(CMD_NEW_FILE));
1167 ui->actionOpen->setShortcut(cmdKeySeq(CMD_OPEN_FILE));
1168 ui->actionSave->setShortcut(cmdKeySeq(CMD_SAVE_FILE));
1169 ui->actionSave_as->setShortcut(cmdKeySeq(CMD_SAVE_AS));
1171 ui->actionImport_Image->setShortcut(cmdKeySeq(CMD_IMPORT_IMAGE));
1172 ui->actionImport_ImageSeq->setShortcut(cmdKeySeq(CMD_IMPORT_IMAGE_SEQ));
1173 ui->actionImport_MovieVideo->setShortcut(cmdKeySeq(CMD_IMPORT_MOVIE_VIDEO));
1174 ui->actionImport_MovieAudio->setShortcut(cmdKeySeq(CMD_IMPORT_MOVIE_AUDIO));
1175 ui->actionImport_Append_Palette->setShortcut(cmdKeySeq(CMD_IMPORT_PALETTE));
1176 ui->actionImport_Sound->setShortcut(cmdKeySeq(CMD_IMPORT_SOUND));
1178 ui->actionExport_Image->setShortcut(cmdKeySeq(CMD_EXPORT_IMAGE));
1179 ui->actionExport_ImageSeq->setShortcut(cmdKeySeq(CMD_EXPORT_IMAGE_SEQ));
1180 ui->actionExport_Movie->setShortcut(cmdKeySeq(CMD_EXPORT_MOVIE));
1181 ui->actionExport_Palette->setShortcut(cmdKeySeq(CMD_EXPORT_PALETTE));
1184 ui->actionUndo->setShortcut(cmdKeySeq(CMD_UNDO));
1185 ui->actionRedo->setShortcut(cmdKeySeq(CMD_REDO));
1186 ui->actionCut->setShortcut(cmdKeySeq(CMD_CUT));
1187 ui->actionCopy->setShortcut(cmdKeySeq(CMD_COPY));
1188 ui->actionPaste->setShortcut(cmdKeySeq(CMD_PASTE));
1189 ui->actionClearFrame->setShortcut(cmdKeySeq(CMD_CLEAR_FRAME));
1190 ui->actionSelect_All->setShortcut(cmdKeySeq(CMD_SELECT_ALL));
1191 ui->actionDeselect_All->setShortcut(cmdKeySeq(CMD_DESELECT_ALL));
1192 ui->actionPreference->setShortcut(cmdKeySeq(CMD_PREFERENCE));
1195 ui->actionResetWindows->setShortcut(cmdKeySeq(CMD_RESET_WINDOWS));
1196 ui->actionReset_View->setShortcut(cmdKeySeq(CMD_RESET_ZOOM_ROTATE));
1197 ui->actionCenter_View->setShortcut(cmdKeySeq(CMD_CENTER_VIEW));
1198 ui->actionZoom_In->setShortcut(cmdKeySeq(CMD_ZOOM_IN));
1199 ui->actionZoom_Out->setShortcut(cmdKeySeq(CMD_ZOOM_OUT));
1200 ui->actionZoom400->setShortcut(cmdKeySeq(CMD_ZOOM_400));
1201 ui->actionZoom300->setShortcut(cmdKeySeq(CMD_ZOOM_300));
1202 ui->actionZoom200->setShortcut(cmdKeySeq(CMD_ZOOM_200));
1203 ui->actionZoom100->setShortcut(cmdKeySeq(CMD_ZOOM_100));
1204 ui->actionZoom50->setShortcut(cmdKeySeq(CMD_ZOOM_50));
1205 ui->actionZoom33->setShortcut(cmdKeySeq(CMD_ZOOM_33));
1206 ui->actionZoom25->setShortcut(cmdKeySeq(CMD_ZOOM_25));
1207 ui->actionRotate_Clockwise->setShortcut(cmdKeySeq(CMD_ROTATE_CLOCK));
1208 ui->actionRotate_Anticlockwise->setShortcut(cmdKeySeq(CMD_ROTATE_ANTI_CLOCK));
1209 ui->actionReset_Rotation->setShortcut(cmdKeySeq(CMD_RESET_ROTATION));
1210 ui->actionHorizontal_Flip->setShortcut(cmdKeySeq(CMD_FLIP_HORIZONTAL));
1211 ui->actionVertical_Flip->setShortcut(cmdKeySeq(CMD_FLIP_VERTICAL));
1212 ui->actionPreview->setShortcut(cmdKeySeq(CMD_PREVIEW));
1213 ui->actionGrid->setShortcut(cmdKeySeq(CMD_GRID));
1214 ui->actionOnionPrev->setShortcut(cmdKeySeq(CMD_ONIONSKIN_PREV));
1215 ui->actionOnionNext->setShortcut(cmdKeySeq(CMD_ONIONSKIN_NEXT));
1217 ui->actionPlay->setShortcut(cmdKeySeq(CMD_PLAY));
1218 ui->actionLoop->setShortcut(cmdKeySeq(CMD_LOOP));
1219 ui->actionPrevious_Frame->setShortcut(cmdKeySeq(CMD_GOTO_PREV_FRAME));
1220 ui->actionNext_Frame->setShortcut(cmdKeySeq(CMD_GOTO_NEXT_FRAME));
1221 ui->actionPrev_KeyFrame->setShortcut(cmdKeySeq(CMD_GOTO_PREV_KEY_FRAME));
1222 ui->actionNext_KeyFrame->setShortcut(cmdKeySeq(CMD_GOTO_NEXT_KEY_FRAME));
1223 ui->actionAdd_Frame->setShortcut(cmdKeySeq(CMD_ADD_FRAME));
1224 ui->actionDuplicate_Frame->setShortcut(cmdKeySeq(CMD_DUPLICATE_FRAME));
1225 ui->actionRemove_Frame->setShortcut(cmdKeySeq(CMD_REMOVE_FRAME));
1226 ui->actionMove_Frame_Backward->setShortcut(cmdKeySeq(CMD_MOVE_FRAME_BACKWARD));
1227 ui->actionMove_Frame_Forward->setShortcut(cmdKeySeq(CMD_MOVE_FRAME_FORWARD));
1228 ui->actionFlip_inbetween->setShortcut(cmdKeySeq(CMD_FLIP_INBETWEEN));
1229 ui->actionFlip_rolling->setShortcut(cmdKeySeq(CMD_FLIP_ROLLING));
1232 ui->actionMove->setShortcut(cmdKeySeq(CMD_TOOL_MOVE));
1233 ui->actionSelect->setShortcut(cmdKeySeq(CMD_TOOL_SELECT));
1234 ui->actionBrush->setShortcut(cmdKeySeq(CMD_TOOL_BRUSH));
1235 ui->actionPolyline->setShortcut(cmdKeySeq(CMD_TOOL_POLYLINE));
1236 ui->actionSmudge->setShortcut(cmdKeySeq(CMD_TOOL_SMUDGE));
1237 ui->actionPen->setShortcut(cmdKeySeq(CMD_TOOL_PEN));
1238 ui->actionHand->setShortcut(cmdKeySeq(CMD_TOOL_HAND));
1239 ui->actionPencil->setShortcut(cmdKeySeq(CMD_TOOL_PENCIL));
1240 ui->actionBucket->setShortcut(cmdKeySeq(CMD_TOOL_BUCKET));
1241 ui->actionEyedropper->setShortcut(cmdKeySeq(CMD_TOOL_EYEDROPPER));
1242 ui->actionEraser->setShortcut(cmdKeySeq(CMD_TOOL_ERASER));
1244 ui->actionMove->installEventFilter(shortcutFilter);
1245 ui->actionMove->installEventFilter(shortcutFilter);
1246 ui->actionSelect->installEventFilter(shortcutFilter);
1247 ui->actionBrush->installEventFilter(shortcutFilter);
1248 ui->actionPolyline->installEventFilter(shortcutFilter);
1249 ui->actionSmudge->installEventFilter(shortcutFilter);
1250 ui->actionPen->installEventFilter(shortcutFilter);
1251 ui->actionHand->installEventFilter(shortcutFilter);
1252 ui->actionPencil->installEventFilter(shortcutFilter);
1253 ui->actionBucket->installEventFilter(shortcutFilter);
1254 ui->actionEyedropper->installEventFilter(shortcutFilter);
1255 ui->actionEraser->installEventFilter(shortcutFilter);
1257 ui->actionNew_Bitmap_Layer->setShortcut(cmdKeySeq(CMD_NEW_BITMAP_LAYER));
1258 ui->actionNew_Vector_Layer->setShortcut(cmdKeySeq(CMD_NEW_VECTOR_LAYER));
1259 ui->actionNew_Camera_Layer->setShortcut(cmdKeySeq(CMD_NEW_CAMERA_LAYER));
1260 ui->actionNew_Sound_Layer->setShortcut(cmdKeySeq(CMD_NEW_SOUND_LAYER));
1261 ui->actionDelete_Current_Layer->setShortcut(cmdKeySeq(CMD_DELETE_CUR_LAYER));
1263 ui->actionVisibilityCurrentLayerOnly->setShortcut(cmdKeySeq(CMD_CURRENT_LAYER_VISIBILITY));
1264 ui->actionVisibilityRelative->setShortcut(cmdKeySeq(CMD_RELATIVE_LAYER_VISIBILITY));
1265 ui->actionVisibilityAll->setShortcut(cmdKeySeq(CMD_ALL_LAYER_VISIBILITY));
1267 mToolBox->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_TOOLBOX));
1268 mToolOptions->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_TOOL_OPTIONS));
1269 mColorBox->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_COLOR_WHEEL));
1270 mColorPalette->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_COLOR_LIBRARY));
1271 mTimeLine->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_TIMELINE));
1272 mDisplayOptionWidget->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_DISPLAY_OPTIONS));
1273 mColorInspector->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_COLOR_INSPECTOR));
1274 mOnionSkinWidget->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_ONION_SKIN));
1276 ui->actionHelp->setShortcut(cmdKeySeq(CMD_HELP));
1277 ui->actionExit->setShortcut(cmdKeySeq(CMD_EXIT));
1280 void MainWindow2::clearKeyboardShortcuts()
1283 for (
QAction* action : actionList)
1289 void MainWindow2::undoActSetText()
1291 if (mEditor->mBackupIndex < 0)
1293 ui->actionUndo->setText(
tr(
"Undo",
"Menu item text"));
1294 ui->actionUndo->setEnabled(
false);
1298 ui->actionUndo->setText(
QString(
"%1 %2 %3").arg(
tr(
"Undo",
"Menu item text"))
1300 .
arg(mEditor->mBackupList.
at(mEditor->mBackupIndex)->undoText));
1301 ui->actionUndo->setEnabled(
true);
1304 if (mEditor->mBackupIndex + 2 < mEditor->mBackupList.
size())
1306 ui->actionRedo->setText(
QString(
"%1 %2 %3").arg(
tr(
"Redo",
"Menu item text"))
1308 .
arg(mEditor->mBackupList.
at(mEditor->mBackupIndex + 1)->undoText));
1309 ui->actionRedo->setEnabled(
true);
1313 ui->actionRedo->setText(
tr(
"Redo",
"Menu item text"));
1314 ui->actionRedo->setEnabled(
false);
1318 void MainWindow2::undoActSetEnabled()
1320 ui->actionUndo->setEnabled(
true);
1321 ui->actionRedo->setEnabled(
true);
1324 void MainWindow2::exportPalette()
1329 mEditor->object()->exportPalette(filePath);
1333 void MainWindow2::importPalette()
1338 mEditor->object()->importPalette(filePath);
1339 mColorPalette->refreshColorList();
1340 mColorPalette->adjustSwatches();
1341 mEditor->color()->setColorNumber(0);
1345 void MainWindow2::openPalette()
1347 for (
int i = 0; i < mEditor->object()->getColorCount(); i++)
1349 if (!mEditor->object()->isColorInUse(i))
1355 msgBox.
setText(
tr(
"Opening a palette will replace the old palette.\n"
1356 "Color(s) in strokes will be altered by this action!"));
1372 mEditor->object()->openPalette(filePath);
1373 mColorPalette->refreshColorList();
1374 mEditor->color()->setColorNumber(0);
1377 void MainWindow2::makeConnections(
Editor* editor)
1379 connect(editor, &Editor::updateBackup,
this, &MainWindow2::updateSaveState);
1380 connect(editor, &Editor::needDisplayInfo,
this, &MainWindow2::displayMessageBox);
1381 connect(editor, &Editor::needDisplayInfoNoTitle,
this, &MainWindow2::displayMessageBoxNoTitle);
1382 connect(editor->layers(), &LayerManager::currentLayerChanged,
this, &MainWindow2::currentLayerChanged);
1385 void MainWindow2::makeConnections(
Editor* editor,
ColorBox* colorBox)
1387 connect(colorBox, &ColorBox::colorChanged, editor->color(), &ColorManager::setColor);
1388 connect(editor->color(), &ColorManager::colorChanged, colorBox, &ColorBox::setColor);
1393 connect(colorInspector, &ColorInspector::colorChanged, editor->color(), &ColorManager::setColor);
1394 connect(editor->color(), &ColorManager::colorChanged, colorInspector, &ColorInspector::setColor);
1399 connect(editor->tools(), &ToolManager::toolChanged, scribbleArea, &ScribbleArea::setCurrentTool);
1400 connect(editor->tools(), &ToolManager::toolPropertyChanged, scribbleArea, &ScribbleArea::updateToolCursor);
1402 connect(editor->layers(), &LayerManager::layerDeleted, scribbleArea, &ScribbleArea::updateAllFrames);
1404 connect(editor, &Editor::currentFrameChanged, scribbleArea, &ScribbleArea::updateCurrentFrame);
1406 connect(editor->view(), &ViewManager::viewChanged, scribbleArea, &ScribbleArea::updateAllFrames);
1409 void MainWindow2::makeConnections(
Editor* pEditor,
TimeLine* pTimeline)
1412 connect(pTimeline, &TimeLine::duplicateKeyClick, mCommands, &ActionCommands::duplicateKey);
1414 connect(pTimeline, &TimeLine::soundClick, pPlaybackManager, &PlaybackManager::enableSound);
1415 connect(pTimeline, &TimeLine::fpsChanged, pPlaybackManager, &PlaybackManager::setFps);
1416 connect(pTimeline, &TimeLine::fpsChanged, pEditor, &Editor::setFps);
1418 connect(pTimeline, &TimeLine::addKeyClick, mCommands, &ActionCommands::addNewKey);
1419 connect(pTimeline, &TimeLine::removeKeyClick, mCommands, &ActionCommands::removeKey);
1421 connect(pTimeline, &TimeLine::newBitmapLayer, mCommands, &ActionCommands::addNewBitmapLayer);
1422 connect(pTimeline, &TimeLine::newVectorLayer, mCommands, &ActionCommands::addNewVectorLayer);
1423 connect(pTimeline, &TimeLine::newSoundLayer, mCommands, &ActionCommands::addNewSoundLayer);
1424 connect(pTimeline, &TimeLine::newCameraLayer, mCommands, &ActionCommands::addNewCameraLayer);
1426 connect(mTimeLine, &TimeLine::playButtonTriggered, mCommands, &ActionCommands::PlayStop);
1428 connect(pEditor->layers(), &LayerManager::currentLayerChanged, pTimeline, &TimeLine::updateUI);
1429 connect(pEditor->layers(), &LayerManager::layerCountChanged, pTimeline, &TimeLine::updateUI);
1431 connect(pEditor->sound(), &SoundManager::soundClipDurationChanged, pTimeline, &TimeLine::updateUI);
1433 connect(pEditor, &Editor::objectLoaded, pTimeline, &TimeLine::onObjectLoaded);
1434 connect(pEditor, &Editor::updateTimeLine, pTimeline, &TimeLine::updateUI);
1436 connect(pEditor->layers(), &LayerManager::currentLayerChanged, mToolOptions, &ToolOptionWidget::updateUI);
1441 connect(editor->layers(), &LayerManager::currentLayerChanged, displayWidget, &DisplayOptionWidget::updateUI);
1450 toolOptions->makeConnectionToEditor(editor);
1455 connect(pEditor, &Editor::objectLoaded, pColorPalette, &ColorPaletteWidget::updateUI);
1458 ScribbleArea* pScribbleArea = pEditor->getScribbleArea();
1460 connect(pColorPalette, &ColorPaletteWidget::colorChanged, pColorManager, &ColorManager::setColor);
1461 connect(pColorPalette, &ColorPaletteWidget::colorNumberChanged, pColorManager, &ColorManager::setColorNumber);
1463 connect(pColorPalette, &ColorPaletteWidget::colorChanged, pScribbleArea, &ScribbleArea::paletteColorChanged);
1465 connect(pColorManager, &ColorManager::colorChanged, pColorPalette, &ColorPaletteWidget::setColor);
1466 connect(pColorManager, &ColorManager::colorNumberChanged, pColorPalette, &ColorPaletteWidget::selectColorNumber);
1469 void MainWindow2::updateZoomLabel()
1471 qreal zoom = mEditor->view()->scaling() * 100.f;
1472 mZoomLabel->setText(
tr(
"Zoom: %0%").arg(zoom, 0,
'f', 1));
1475 void MainWindow2::changePlayState(
bool isPlaying)
1479 ui->actionPlay->setText(
tr(
"Stop"));
1480 ui->actionPlay->setIcon(mStopIcon);
1484 ui->actionPlay->setText(
tr(
"Play"));
1485 ui->actionPlay->setIcon(mStartIcon);
1490 void MainWindow2::importMovieVideo()
1493 mSuppressAutoSaveDialog =
true;
1495 mCommands->importMovieVideo();
1497 mSuppressAutoSaveDialog =
false;
1500 void MainWindow2::displayMessageBox(
const QString& title,
const QString& body)
1505 void MainWindow2::displayMessageBoxNoTitle(
const QString& body)
1510 bool MainWindow2::tryRecoverUnsavedProject()
1513 QStringList recoverables = fm.searchForUnsavedProjects();
1515 if (recoverables.
empty())
1520 QString caption =
tr(
"Restore Project?");
1521 QString text =
tr(
"Pencil2D didn't close correctly. Would you like to restore the project?");
1523 QString recoverPath = recoverables[0];
1530 msgBox->
setText(
QString(
"<h4>%1</h4>%2").arg(caption).arg(text));
1534 hideQuestionMark(*msgBox);
1541 void MainWindow2::startProjectRecovery(
int result)
1556 Object* o = fm.recoverUnsavedProject(recoverPath);
1557 if (!fm.error().ok())
1559 Q_ASSERT(o ==
nullptr);
1560 const QString title =
tr(
"Recovery Failed.");
1561 const QString text =
tr(
"Sorry! Pencil2D is unable to restore your project");
1567 mEditor->setObject(o);
1570 const QString title =
tr(
"Recovery Succeeded!");
1571 const QString text =
tr(
"Please save your work immediately to prevent loss of data");
QString toString(Qt::DateFormat format) const const
QByteArray toByteArray() const const
void triggered(bool checked)
QString & append(QChar ch)
void setIconPixmap(const QPixmap &pixmap)
QString writableLocation(QStandardPaths::StandardLocation type)
QObject * sender() const const
QString & prepend(QChar ch)
const T & at(int i) const const
bool exists() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
void toggled(bool checked)
void finished(int result)
void setTimeSpec(Qt::TimeSpec spec)
QString number(int n, int base)
void processEvents(QEventLoop::ProcessEventsFlags flags)
void updateAllFramesIfNeeded()
Check if the cache should be invalidated for all frames since the last paint operation.
QVariant property(const char *name) const const
void setWindowTitle(const QString &title)
bool isEmpty() const const
bool isEmpty() const const
void setText(const QString &text)
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
void setInformativeText(const QString &text)
QString toLower() const const
virtual int exec() override
void setShortcut(const QKeySequence &shortcut)
static QString getOpenFileName(QWidget *parent, FileType fileType, const QString &caption=QString())
Shows a file dialog which allows the user to select a file to open.
QDateTime currentDateTime()
char * toString(const T &value)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
void extendLength(int frame)
Extends the timeline frame length if necessary.
void keySequence(QWindow *window, const QKeySequence &keySequence)
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
bool setProperty(const char *name, const QVariant &value)
void setWindowModality(Qt::WindowModality windowModality)
static QString getSaveFileName(QWidget *parent, FileType fileType, const QString &caption=QString())
Shows a file dialog which allows the user to select a file save path.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void open(QObject *receiver, const char *member)
QString toString() const const