19 #include "mainwindow2.h"
20 #include "ui_mainwindow2.h"
29 #include <QScopedPointer>
30 #include <QMessageBox>
31 #include <QProgressDialog>
32 #include <QDesktopWidget>
33 #include <QDesktopServices>
34 #include <QGraphicsDropShadowEffect>
36 #include <QFileIconProvider>
38 #include "pencildef.h"
39 #include "pencilsettings.h"
41 #include "filemanager.h"
43 #include "colormanager.h"
44 #include "layermanager.h"
45 #include "layercamera.h"
46 #include "toolmanager.h"
47 #include "playbackmanager.h"
48 #include "soundmanager.h"
49 #include "actioncommands.h"
51 #include "scribblearea.h"
53 #include "colorpalettewidget.h"
54 #include "displayoptionwidget.h"
55 #include "tooloptionwidget.h"
56 #include "preferencesdialog.h"
60 #include "timeline2.h"
61 #include "errordialog.h"
62 #include "importimageseqdialog.h"
63 #include "aboutdialog.h"
68 #include "fileformat.h"
69 #include "JlCompress.h"
70 #include "recentfilemenu.h"
72 #include "exportimagedialog.h"
73 #include "exportmoviedialog.h"
74 #include "shortcutfilter.h"
75 #include "filedialogex.h"
76 #include "movieexporter.h"
79 MainWindow2::MainWindow2( QWidget *parent ) : QMainWindow( parent )
81 ui =
new Ui::MainWindow2;
87 mScribbleArea->setFocusPolicy( Qt::StrongFocus );
91 QVBoxLayout* layout =
new QVBoxLayout();
92 layout->setSpacing(0);
94 layout->setContentsMargins(0,0,0,0);
95 layout->addWidget(mScribbleArea);
97 mBackground->setLayout(layout);
100 setCentralWidget(mBackground);
106 mEditor =
new Editor(
this );
107 mEditor->setScribbleArea(mScribbleArea);
109 mEditor->setObject(
object );
111 mScribbleArea->setCore( mEditor );
112 mScribbleArea->init();
114 mEditor->setScribbleArea( mScribbleArea );
115 makeConnections( mEditor, mScribbleArea );
118 mCommands->setCore( mEditor );
122 setupKeyboardShortcuts();
126 connect( mEditor, &Editor::needSave,
this, &MainWindow2::saveDocument );
127 connect( mToolBox, &ToolBoxWidget::clearButtonClicked, mEditor, &Editor::clearCurrentFrame );
131 mEditor->setCurrentLayer( mEditor->object()->getLayerCount() - 1 );
132 mEditor->tools()->setDefaultTool();
134 mBackground->init(mEditor->preference());
136 mEditor->updateObject();
137 mEditor->color()->setColorNumber(0);
139 connect( mEditor->view(), &ViewManager::viewChanged,
this, &MainWindow2::updateZoomLabel );
142 MainWindow2::~MainWindow2()
148 void MainWindow2::createDockWidgets()
151 mTimeLine->setObjectName(
"TimeLine" );
154 mColorWheel->setToolTip( tr(
"color palette:<br>use <b>(C)</b><br>toggle at cursor" ) );
155 mColorWheel->setObjectName(
"ColorWheel" );
156 mColorWheel->setMaximumHeight(390);
159 mColorPalette->setObjectName(
"ColorPalette" );
162 mDisplayOptionWidget->setObjectName(
"DisplayOption" );
165 mToolOptions->setObjectName(
"ToolOption" );
168 mToolBox->setObjectName(
"ToolBox" );
180 << mDisplayOptionWidget
184 mStartIcon = QIcon(
":icons/controls/play.png");
185 mStopIcon = QIcon(
":icons/controls/stop.png");
189 pWidget->setAllowedAreas( Qt::AllDockWidgetAreas );
190 pWidget->setFeatures( QDockWidget::AllDockWidgetFeatures );
191 pWidget->setFocusPolicy( Qt::NoFocus );
193 pWidget->setEditor( mEditor );
196 qDebug() <<
"Init Dock widget: " << pWidget->objectName();
199 addDockWidget( Qt::RightDockWidgetArea, mColorWheel );
200 addDockWidget( Qt::RightDockWidgetArea, mColorPalette );
201 addDockWidget( Qt::RightDockWidgetArea, mDisplayOptionWidget );
202 addDockWidget( Qt::LeftDockWidgetArea, mToolBox );
203 addDockWidget( Qt::LeftDockWidgetArea, mToolOptions );
204 addDockWidget( Qt::BottomDockWidgetArea, mTimeLine );
215 makeConnections( mEditor );
216 makeConnections( mEditor, mTimeLine );
217 makeConnections( mEditor, mColorWheel );
218 makeConnections( mEditor, mColorPalette );
219 makeConnections( mEditor, mDisplayOptionWidget );
220 makeConnections( mEditor, mToolOptions );
225 w->setFloating(
false );
233 connect( ui->actionNew, &QAction::triggered,
this, &MainWindow2::newDocument );
234 connect( ui->actionOpen, &QAction::triggered,
this, &MainWindow2::openDocument );
235 connect( ui->actionSave_as, &QAction::triggered,
this, &MainWindow2::saveAsNewDocument );
236 connect( ui->actionSave, &QAction::triggered,
this, &MainWindow2::saveDocument );
237 connect( ui->actionExit, &QAction::triggered,
this, &MainWindow2::close );
241 connect( ui->actionExport_Image, &QAction::triggered,
this, &MainWindow2::exportImage );
242 connect( ui->actionExport_ImageSeq, &QAction::triggered,
this, &MainWindow2::exportImageSequence );
243 connect( ui->actionExport_Movie, &QAction::triggered, mCommands, &ActionCommands::exportMovie );
245 connect( ui->actionExport_Palette, &QAction::triggered,
this, &MainWindow2::exportPalette );
249 connect( ui->actionImport_Image, &QAction::triggered,
this, &MainWindow2::importImage );
250 connect( ui->actionImport_ImageSeq, &QAction::triggered,
this, &MainWindow2::importImageSequence );
251 connect( ui->actionImport_Movie, &QAction::triggered,
this, &MainWindow2::importMovie );
253 connect( ui->actionImport_Sound, &QAction::triggered, mCommands, &ActionCommands::importSound );
254 connect( ui->actionImport_Palette, &QAction::triggered,
this, &MainWindow2::importPalette );
257 connect( ui->actionUndo, &QAction::triggered, mEditor, &Editor::undo );
258 connect( ui->actionRedo, &QAction::triggered, mEditor, &Editor::redo );
259 connect( ui->actionCut, &QAction::triggered, mEditor, &Editor::cut );
260 connect( ui->actionCopy, &QAction::triggered, mEditor, &Editor::copy );
261 connect( ui->actionPaste, &QAction::triggered, mEditor, &Editor::paste );
262 connect( ui->actionClearFrame, &QAction::triggered, mEditor, &Editor::clearCurrentFrame );
263 connect( ui->actionFlip_X, &QAction::triggered, mCommands, &ActionCommands::flipSelectionX );
264 connect( ui->actionFlip_Y, &QAction::triggered, mCommands, &ActionCommands::flipSelectionY );
265 connect( ui->actionSelect_All, &QAction::triggered, mEditor, &Editor::selectAll );
266 connect( ui->actionDeselect_All, &QAction::triggered, mEditor, &Editor::deselectAll );
267 connect( ui->actionPreference, &QAction::triggered, [=] { preferences(); } );
268 ui->actionPreference->setMenuRole( QAction::PreferencesRole );
270 ui->actionRedo->setEnabled(
false );
273 connect( ui->actionNew_Bitmap_Layer, &QAction::triggered, mCommands, &ActionCommands::addNewBitmapLayer );
274 connect( ui->actionNew_Vector_Layer, &QAction::triggered, mCommands, &ActionCommands::addNewVectorLayer );
275 connect( ui->actionNew_Sound_Layer, &QAction::triggered, mCommands, &ActionCommands::addNewSoundLayer );
276 connect( ui->actionNew_Camera_Layer, &QAction::triggered, mCommands, &ActionCommands::addNewCameraLayer );
277 connect( ui->actionDelete_Current_Layer, &QAction::triggered, mEditor->layers(), &LayerManager::deleteCurrentLayer );
280 connect( ui->actionZoom_In, &QAction::triggered, mCommands, &ActionCommands::ZoomIn );
281 connect( ui->actionZoom_Out, &QAction::triggered, mCommands, &ActionCommands::ZoomOut );
282 connect( ui->actionRotate_Clockwise, &QAction::triggered, mCommands, &ActionCommands::rotateClockwise );
283 connect( ui->actionRotate_Anticlosewise, &QAction::triggered, mCommands, &ActionCommands::rotateCounterClockwise );
284 connect( ui->actionReset_Windows, &QAction::triggered,
this, &MainWindow2::dockAllSubWidgets );
285 connect( ui->actionReset_View, &QAction::triggered, mEditor->view(), &ViewManager::resetView );
286 connect( ui->actionHorizontal_Flip, &QAction::triggered, mEditor, &Editor::toggleMirror );
287 connect( ui->actionVertical_Flip, &QAction::triggered, mEditor, &Editor::toggleMirrorV );
289 ui->actionPreview->setEnabled(
false );
292 setMenuActionChecked( ui->actionGrid, mEditor->preference()->isOn( SETTING::GRID ) );
293 connect( ui->actionGrid, &QAction::triggered, mCommands, &ActionCommands::showGrid );
295 bindActionWithSetting( ui->actionOnionPrev, SETTING::PREV_ONION );
296 bindActionWithSetting( ui->actionOnionNext, SETTING::NEXT_ONION );
297 bindActionWithSetting( ui->actionMultiLayerOnionSkin, SETTING::MULTILAYER_ONION );
301 connect( ui->actionPlay, &QAction::triggered, mCommands, &ActionCommands::PlayStop );
303 connect( ui->actionLoop, &QAction::triggered, pPlaybackManager, &PlaybackManager::setLooping );
304 connect( ui->actionLoopControl, &QAction::triggered, pPlaybackManager, &PlaybackManager::enableRangedPlayback );
305 connect( pPlaybackManager, &PlaybackManager::loopStateChanged, ui->actionLoop, &QAction::setChecked );
306 connect( pPlaybackManager, &PlaybackManager::loopStateChanged, mTimeLine, &TimeLine::setLoop );
307 connect( pPlaybackManager, &PlaybackManager::rangedPlaybackStateChanged, ui->actionLoopControl, &QAction::setChecked );
308 connect( pPlaybackManager, &PlaybackManager::rangedPlaybackStateChanged, mTimeLine, &TimeLine::setRangeState );
309 connect( pPlaybackManager, &PlaybackManager::playStateChanged, mTimeLine, &TimeLine::setPlaying );
310 connect( pPlaybackManager, &PlaybackManager::playStateChanged,
this, &MainWindow2::changePlayState );
312 connect(ui->actionAdd_Frame, &QAction::triggered, mEditor, &Editor::addNewKey );
313 connect(ui->actionRemove_Frame, &QAction::triggered, mEditor, &Editor::removeKey );
314 connect(ui->actionNext_Frame, &QAction::triggered, mCommands, &ActionCommands::GotoNextFrame );
315 connect(ui->actionPrevious_Frame, &QAction::triggered, mCommands, &ActionCommands::GotoPrevFrame );
316 connect(ui->actionNext_KeyFrame, &QAction::triggered, mCommands, &ActionCommands::GotoNextKeyFrame );
317 connect(ui->actionPrev_KeyFrame, &QAction::triggered, mCommands, &ActionCommands::GotoPrevKeyFrame );
318 connect(ui->actionDuplicate_Frame, &QAction::triggered, mEditor, &Editor::duplicateKey );
319 connect(ui->actionMove_Frame_Forward, &QAction::triggered, mEditor, &Editor::moveFrameForward );
320 connect(ui->actionMove_Frame_Backward, &QAction::triggered, mEditor, &Editor::moveFrameBackward );
323 connect(ui->actionMove, &QAction::triggered, mToolBox, &ToolBoxWidget::moveOn );
324 connect(ui->actionSelect, &QAction::triggered, mToolBox, &ToolBoxWidget::selectOn );
325 connect(ui->actionBrush, &QAction::triggered, mToolBox, &ToolBoxWidget::brushOn );
326 connect(ui->actionPolyline, &QAction::triggered, mToolBox, &ToolBoxWidget::polylineOn );
327 connect(ui->actionSmudge, &QAction::triggered, mToolBox, &ToolBoxWidget::smudgeOn );
328 connect(ui->actionPen, &QAction::triggered, mToolBox, &ToolBoxWidget::penOn );
329 connect(ui->actionHand, &QAction::triggered, mToolBox, &ToolBoxWidget::handOn );
330 connect(ui->actionPencil, &QAction::triggered, mToolBox, &ToolBoxWidget::pencilOn );
331 connect(ui->actionBucket, &QAction::triggered, mToolBox, &ToolBoxWidget::bucketOn );
332 connect(ui->actionEyedropper, &QAction::triggered, mToolBox, &ToolBoxWidget::eyedropperOn );
333 connect(ui->actionEraser, &QAction::triggered, mToolBox, &ToolBoxWidget::eraserOn );
334 connect(ui->actionResetToolsDefault, &QAction::triggered, mEditor->tools(), &ToolManager::resetAllTools );
337 QMenu* winMenu = ui->menuWindows;
341 mToolBox->toggleViewAction(),
342 mToolOptions->toggleViewAction(),
343 mColorWheel->toggleViewAction(),
344 mColorPalette->toggleViewAction(),
345 mTimeLine->toggleViewAction(),
346 mDisplayOptionWidget->toggleViewAction()
349 for ( QAction* action : actions )
351 action->setMenuRole( QAction::NoRole );
352 winMenu->addAction( action );
355 winMenu->addSeparator();
356 QAction *lockWidgets =
new QAction( tr(
"Lock Windows" ), winMenu );
357 lockWidgets->setCheckable(
true );
358 winMenu->addAction( lockWidgets );
359 connect( lockWidgets, &QAction::toggled,
this, &MainWindow2::lockWidgets );
360 bindActionWithSetting( lockWidgets, SETTING::LAYOUT_LOCK );
364 connect( ui->actionHelp, &QAction::triggered,
this, &MainWindow2::helpBox);
365 connect( ui->actionAbout, &QAction::triggered,
this, &MainWindow2::aboutPencil );
369 mRecentFileMenu->loadFromDisk();
370 ui->menuFile->insertMenu( ui->actionSave, mRecentFileMenu );
372 connect( mRecentFileMenu, &RecentFileMenu::loadRecentFile,
this, &MainWindow2::openFile );
374 connect( ui->menuEdit, SIGNAL( aboutToShow() ),
this, SLOT( undoActSetText() ) );
375 connect( ui->menuEdit, SIGNAL( aboutToHide() ),
this, SLOT( undoActSetEnabled() ) );
378 void MainWindow2::setMenuActionChecked( QAction* action,
bool bChecked )
381 action->setChecked( bChecked );
384 void MainWindow2::setOpacity(
int opacity )
386 mEditor->preference()->set(SETTING::WINDOW_OPACITY, 100 - opacity);
387 setWindowOpacity( opacity / 100.0 );
390 void MainWindow2::updateSaveState()
392 setWindowModified( mEditor->currentBackup() != mBackupAtSave );
395 void MainWindow2::clearRecentFilesList()
397 QStringList recentFilesList = mRecentFileMenu->getRecentFiles();
398 if (!recentFilesList.isEmpty()) {
399 mRecentFileMenu->clear();
401 QMessageBox::information(
this, 0,
402 tr(
"\n\n You have successfully cleared the list"),
405 getPrefDialog()->updateRecentListBtn(!recentFilesList.isEmpty());
408 void MainWindow2::closeEvent( QCloseEvent* event )
421 void MainWindow2::tabletEvent( QTabletEvent* event )
426 void MainWindow2::newDocument()
431 mEditor->setObject(
object );
432 mEditor->scrubTo( 0 );
433 mEditor->view()->resetView();
436 mColorPalette->refreshColorList();
437 mEditor->color()->setColorNumber(0);
439 setWindowTitle( PENCIL_WINDOW_TITLE );
444 void MainWindow2::openDocument()
449 QString fileName = fileDialog.openFile( FileType::ANIMATION );
450 if ( fileName.isEmpty() )
454 QFileInfo fileInfo( fileName );
455 if ( fileInfo.isDir() )
460 bool ok = openObject( fileName );
463 QMessageBox::warning(
this, tr(
"Warning"), tr(
"Pencil cannot read this file. If you want to import images, use the command import.") );
469 bool MainWindow2::saveAsNewDocument()
472 QString fileName = fileDialog.saveFile( FileType::ANIMATION );
473 if ( fileName.isEmpty() )
478 if ( !fileName.endsWith( PFF_OLD_EXTENSION ) && !fileName.endsWith( PFF_EXTENSION ) )
480 fileName = fileName + PFF_EXTENSION;
483 return saveObject( fileName );
487 void MainWindow2::openFile( QString filename )
489 bool ok = openObject( filename );
492 QMessageBox::warning(
this, tr(
"Warning"), tr(
"Pencil cannot read this file. If you want to import images, use the command import.") );
497 bool MainWindow2::openObject( QString strFilePath )
499 QProgressDialog progress( tr(
"Opening document..."), tr(
"Abort"), 0, 100,
this );
502 if ( this->isVisible() )
504 hideQuestionMark( progress );
505 progress.setWindowModality( Qt::WindowModal );
509 mEditor->setCurrentLayer( 0 );
512 connect( &fm, &FileManager::progressUpdated, [&progress](
float f )
514 progress.setValue( (
int)( f * 100.f ) );
515 QApplication::processEvents( QEventLoop::ExcludeUserInputEvents );
519 Object*
object = fm.load( strFilePath );
521 if (
object ==
nullptr || !fm.error().ok() )
526 mEditor->setObject(
object );
528 QSettings settings( PENCIL2D, PENCIL2D );
529 settings.setValue( LAST_PCLX_PATH, object->filePath() );
531 mRecentFileMenu->addRecentFile( object->filePath() );
532 mRecentFileMenu->saveToDisk();
534 setWindowTitle( object->filePath().prepend(
"[*]") );
535 setWindowModified(
false );
536 setWindowIcon( QFileIconProvider().icon(strFilePath) );
539 mColorPalette->refreshColorList();
540 mEditor->color()->setColorNumber(0);
543 mEditor->scrubTo( 0 );
544 mEditor->view()->resetView();
546 progress.setValue( 100 );
550 bool MainWindow2::saveObject( QString strSavedFileName )
552 QProgressDialog progress( tr(
"Saving document..." ), tr(
"Abort" ), 0, 100,
this );
553 progress.setWindowModality( Qt::WindowModal );
556 mEditor->prepareSave();
559 Status st = fm->save( mEditor->object(), strSavedFileName );
561 progress.setValue( 100 );
565 QDateTime dt = QDateTime::currentDateTime();
566 dt.setTimeSpec( Qt::UTC );
567 #if QT_VERSION >= 0x050400
568 QDir errorLogFolder( QStandardPaths::writableLocation( QStandardPaths::AppLocalDataLocation ) );
570 QDir errorLogFolder( QStandardPaths::writableLocation( QStandardPaths::DataLocation ) );
572 errorLogFolder.mkpath(
"./logs" );
573 errorLogFolder.cd(
"logs" );
574 QFile eLog( errorLogFolder.absoluteFilePath( QString(
"error-%1.txt" ).arg( dt.toString( Qt::ISODate ) ) ) );
575 if ( eLog.open( QIODevice::WriteOnly | QIODevice::Text ) )
577 QTextStream out( &eLog );
578 out << st.details().replace(
"<br>",
"\n", Qt::CaseInsensitive );
582 st.description().append( tr(
"<br><br>An error has occurred and your file may not have saved successfully."
583 "If you believe that this error is an issue with Pencil2D, please create a new issue at:"
584 "<br><a href='https://github.com/pencil2d/pencil/issues'>https://github.com/pencil2d/pencil/issues</a><br>"
585 "Please be sure to include the following details in your issue:") ), st.details() );
590 QSettings settings( PENCIL2D, PENCIL2D );
591 settings.setValue( LAST_PCLX_PATH, strSavedFileName );
593 mRecentFileMenu->addRecentFile( strSavedFileName );
594 mRecentFileMenu->saveToDisk();
596 mTimeLine->updateContent();
598 setWindowTitle( strSavedFileName.prepend(
"[*]") );
599 mBackupAtSave = mEditor->currentBackup();
605 void MainWindow2::saveDocument()
607 if ( !mEditor->object()->filePath().isEmpty() )
609 saveObject( mEditor->object()->filePath() );
617 bool MainWindow2::maybeSave()
619 if ( mEditor->currentBackup() != mBackupAtSave )
621 int ret = QMessageBox::warning(
this, tr(
"Warning" ),
622 tr(
"This animation has been modified.\n Do you want to save your changes?" ),
623 QMessageBox::Yes | QMessageBox::Default,
625 QMessageBox::Cancel | QMessageBox::Escape );
626 if ( ret == QMessageBox::Yes )
631 else if ( ret == QMessageBox::Cancel )
639 void MainWindow2::importImage()
642 QString strFilePath = fileDialog.openFile( FileType::IMAGE );
643 if ( strFilePath.isEmpty() )
648 if ( !QFile::exists( strFilePath ) )
653 bool ok = mEditor->importImage( strFilePath );
656 QMessageBox::warning(
this,
658 tr(
"Unable to import image.<br><b>TIP:</b> Use Bitmap layer to import bitmaps." ),
664 mScribbleArea->updateCurrentFrame();
665 mTimeLine->updateContent();
668 void MainWindow2::importImageSequence()
671 imageSeqDialog->exec();
672 if ( imageSeqDialog->result() == QDialog::Rejected )
677 QStringList files = imageSeqDialog->getFilePaths();
678 int number = imageSeqDialog->getSpace();
679 for ( QString strImgFile : files )
681 if ( strImgFile.endsWith(
".png" ) ||
682 strImgFile.endsWith(
".jpg" ) ||
683 strImgFile.endsWith(
".jpeg" ) ||
684 strImgFile.endsWith(
".tif" ) ||
685 strImgFile.endsWith(
".tiff" ) ||
686 strImgFile.endsWith(
".bmp" ) )
688 mEditor->importImage( strImgFile );
689 for (
int i = 1; i < number; i++ )
691 mEditor->scrubForward();
697 void MainWindow2::importMovie()
700 QString filePath = fileDialog.openFile( FileType::MOVIE );
701 if ( filePath.isEmpty() )
705 mEditor->importMovie( filePath, mEditor->playback()->fps() );
708 void MainWindow2::lockWidgets(
bool shouldLock)
710 QDockWidget::DockWidgetFeature feat = shouldLock ? QDockWidget::DockWidgetClosable : QDockWidget::AllDockWidgetFeatures;
712 mColorWheel->setFeatures(feat);
713 mColorPalette->setFeatures(feat);
714 mDisplayOptionWidget->setFeatures(feat);
715 mToolOptions->setFeatures(feat);
716 mToolBox->setFeatures(feat);
717 mTimeLine->setFeatures(feat);
720 void MainWindow2::exportImageSequence()
723 int cameraLayerId = mEditor->layers()->getLastCameraLayer();
729 OnScopeExit( dialog->deleteLater() );
731 if(cameraLayer !=
nullptr)
733 dialog->setExportSize( cameraLayer->getViewRect().size() );
737 dialog->setExportSize( QSize(640,480) );
741 QString strFilePath = dialog->getFilePath();
742 QSize exportSize = dialog->getExportSize();
743 QString exportFormat = dialog->getExportFormat();
744 bool useTranparency = dialog->getTransparency();
746 if ( dialog->result() == QDialog::Rejected )
757 int projectLength = mEditor->layers()->projectLength();
760 QProgressDialog progress( tr(
"Exporting image sequence..." ), tr(
"Abort" ), 0, 100,
this );
761 hideQuestionMark(progress);
762 progress.setWindowModality( Qt::WindowModal );
765 mEditor->object()->exportFrames( 1,
770 exportFormat.toStdString().c_str(),
782 void MainWindow2::exportImage()
784 QSettings settings( PENCIL2D, PENCIL2D );
787 int cameraLayerId = mEditor->layers()->getLastCameraLayer();
794 OnScopeExit( dialog->deleteLater() );
796 if(cameraLayer !=
nullptr)
798 dialog->setExportSize(cameraLayer->getViewRect().size());
802 dialog->setExportSize(QSize(640, 480));
806 QString filePath = dialog->getFilePath();
807 QSize exportSize = dialog->getExportSize();
808 QString exportFormat = dialog->getExportFormat();
809 bool useTranparency = dialog->getTransparency();
811 if ( dialog->result() == QDialog::Rejected )
818 QTransform view = RectMapTransform( mScribbleArea->getViewRect(), QRectF( QPointF( 0, 0 ), exportSize ) );
821 int projectLength = mEditor->layers()->projectLength();
822 if ( !mEditor->object()->exportIm( mEditor->currentFrame(),
831 QMessageBox::warning(
this,
833 tr(
"Unable to export image." ),
841 void MainWindow2::preferences()
844 mPrefDialog->setAttribute( Qt::WA_DeleteOnClose );
845 mPrefDialog->init( mEditor->preference() );
847 connect( mPrefDialog, &PreferencesDialog::clearRecentList,
this, &MainWindow2::clearRecentFilesList);
848 connect( mPrefDialog, &PreferencesDialog::windowOpacityChange,
this, &MainWindow2::setOpacity );
849 connect( mPrefDialog, &PreferencesDialog::finished, [ &]
852 clearKeyboardShortcuts();
853 setupKeyboardShortcuts();
854 mScribbleArea->updateCanvasCursor();
860 void MainWindow2::dockAllSubWidgets()
862 mToolBox->setFloating(
false);
863 mToolOptions->setFloating(
false);
864 mDisplayOptionWidget->setFloating(
false);
865 mTimeLine->setFloating(
false);
866 mColorPalette->setFloating(
false);
867 mColorWheel->setFloating(
false );
870 void MainWindow2::readSettings()
872 QSettings settings( PENCIL2D, PENCIL2D );
874 QVariant winGeometry = settings.value( SETTING_WINDOW_GEOMETRY );
875 restoreGeometry( winGeometry.toByteArray() );
877 QVariant winState = settings.value( SETTING_WINDOW_STATE );
878 restoreState( winState.toByteArray() );
880 QString myPath = settings.value( LAST_PCLX_PATH, QVariant( QDir::homePath() ) ).toString();
881 mRecentFileMenu->addRecentFile( myPath );
883 int opacity = mEditor->preference()->getInt(SETTING::WINDOW_OPACITY);
885 setOpacity( 100 - opacity );
888 void MainWindow2::writeSettings()
890 qDebug(
"Save current windows layout." );
892 QSettings settings( PENCIL2D, PENCIL2D );
893 settings.setValue( SETTING_WINDOW_GEOMETRY, saveGeometry() );
894 settings.setValue( SETTING_WINDOW_STATE, saveState() );
897 void MainWindow2::setupKeyboardShortcuts()
899 checkExistingShortcuts();
901 auto cmdKeySeq = []( QString strCommandName ) -> QKeySequence
903 strCommandName = QString(
"shortcuts/" ) + strCommandName;
904 QKeySequence keySequence( pencilSettings().value( strCommandName ).toString() );
908 ui->actionNew->setShortcut( cmdKeySeq( CMD_NEW_FILE ) );
909 ui->actionOpen->setShortcut( cmdKeySeq( CMD_OPEN_FILE ) );
910 ui->actionSave->setShortcut( cmdKeySeq( CMD_SAVE_FILE ) );
911 ui->actionSave_as->setShortcut( cmdKeySeq( CMD_SAVE_AS ) );
912 ui->actionPrint->setShortcut( cmdKeySeq( CMD_PRINT ) );
914 ui->actionImport_Image->setShortcut( cmdKeySeq( CMD_IMPORT_IMAGE ) );
915 ui->actionImport_ImageSeq->setShortcut( cmdKeySeq( CMD_IMPORT_IMAGE_SEQ ) );
916 ui->actionImport_Movie->setShortcut( cmdKeySeq( CMD_IMPORT_MOVIE ) );
917 ui->actionImport_Palette->setShortcut( cmdKeySeq( CMD_IMPORT_PALETTE ) );
918 ui->actionImport_Sound->setShortcut( cmdKeySeq( CMD_IMPORT_SOUND ) );
920 ui->actionExport_Image->setShortcut( cmdKeySeq( CMD_EXPORT_IMAGE ) );
921 ui->actionExport_ImageSeq->setShortcut( cmdKeySeq( CMD_EXPORT_IMAGE_SEQ ) );
922 ui->actionExport_Movie->setShortcut( cmdKeySeq( CMD_EXPORT_MOVIE ) );
923 ui->actionExport_Palette->setShortcut( cmdKeySeq( CMD_EXPORT_PALETTE ) );
924 ui->actionExport_Svg_Image->setShortcut( cmdKeySeq( CMD_EXPORT_SVG ) );
925 ui->actionExport_X_sheet->setShortcut( cmdKeySeq( CMD_EXPORT_XSHEET ) );
928 ui->actionUndo->setShortcut( cmdKeySeq( CMD_UNDO ) );
929 ui->actionRedo->setShortcut( cmdKeySeq( CMD_REDO ) );
930 ui->actionCut->setShortcut( cmdKeySeq( CMD_CUT ) );
931 ui->actionCopy->setShortcut( cmdKeySeq( CMD_COPY ) );
932 ui->actionPaste->setShortcut( cmdKeySeq( CMD_PASTE ) );
933 ui->actionClearFrame->setShortcut( cmdKeySeq( CMD_CLEAR_FRAME ) );
934 ui->actionSelect_All->setShortcut( cmdKeySeq( CMD_SELECT_ALL ) );
935 ui->actionDeselect_All->setShortcut( cmdKeySeq( CMD_DESELECT_ALL ) );
936 ui->actionPreference->setShortcut( cmdKeySeq( CMD_PREFERENCE ) );
939 ui->actionReset_Windows->setShortcut( cmdKeySeq( CMD_RESET_WINDOWS ) );
940 ui->actionReset_View->setShortcut( cmdKeySeq( CMD_RESET_ZOOM_ROTATE ) );
941 ui->actionZoom_In->setShortcut( cmdKeySeq( CMD_ZOOM_IN ) );
942 ui->actionZoom_Out->setShortcut( cmdKeySeq( CMD_ZOOM_OUT ) );
943 ui->actionRotate_Clockwise->setShortcut( cmdKeySeq( CMD_ROTATE_CLOCK ) );
944 ui->actionRotate_Anticlosewise->setShortcut( cmdKeySeq( CMD_ROTATE_ANTI_CLOCK ) );
945 ui->actionHorizontal_Flip->setShortcut( cmdKeySeq( CMD_FLIP_HORIZONTAL ) );
946 ui->actionVertical_Flip->setShortcut( cmdKeySeq( CMD_FLIP_VERTICAL ) );
947 ui->actionPreview->setShortcut( cmdKeySeq( CMD_PREVIEW ) );
948 ui->actionGrid->setShortcut( cmdKeySeq( CMD_GRID ) );
949 ui->actionOnionPrev->setShortcut( cmdKeySeq( CMD_ONIONSKIN_PREV ) );
950 ui->actionOnionNext->setShortcut( cmdKeySeq( CMD_ONIONSKIN_NEXT ) );
952 ui->actionPlay->setShortcut( cmdKeySeq( CMD_PLAY ) );
953 ui->actionLoop->setShortcut( cmdKeySeq( CMD_LOOP ) );
954 ui->actionPrevious_Frame->setShortcut( cmdKeySeq( CMD_GOTO_PREV_FRAME ) );
955 ui->actionNext_Frame->setShortcut( cmdKeySeq( CMD_GOTO_NEXT_FRAME ) );
956 ui->actionPrev_KeyFrame->setShortcut( cmdKeySeq( CMD_GOTO_PREV_KEY_FRAME ) );
957 ui->actionNext_KeyFrame->setShortcut( cmdKeySeq( CMD_GOTO_NEXT_KEY_FRAME ) );
958 ui->actionAdd_Frame->setShortcut( cmdKeySeq( CMD_ADD_FRAME ) );
959 ui->actionDuplicate_Frame->setShortcut( cmdKeySeq( CMD_DUPLICATE_FRAME ) );
960 ui->actionRemove_Frame->setShortcut( cmdKeySeq( CMD_REMOVE_FRAME ) );
961 ui->actionMove_Frame_Backward->setShortcut( cmdKeySeq( CMD_MOVE_FRAME_BACKWARD ) );
962 ui->actionMove_Frame_Forward->setShortcut( cmdKeySeq( CMD_MOVE_FRAME_FORWARD ) );
965 ui->actionMove->setShortcut( cmdKeySeq( CMD_TOOL_MOVE ) );
966 ui->actionSelect->setShortcut( cmdKeySeq( CMD_TOOL_SELECT ) );
967 ui->actionBrush->setShortcut( cmdKeySeq( CMD_TOOL_BRUSH ) );
968 ui->actionPolyline->setShortcut( cmdKeySeq( CMD_TOOL_POLYLINE ) );
969 ui->actionSmudge->setShortcut( cmdKeySeq( CMD_TOOL_SMUDGE ) );
970 ui->actionPen->setShortcut( cmdKeySeq( CMD_TOOL_PEN ) );
971 ui->actionHand->setShortcut( cmdKeySeq( CMD_TOOL_HAND ) );
972 ui->actionPencil->setShortcut( cmdKeySeq( CMD_TOOL_PENCIL ) );
973 ui->actionBucket->setShortcut( cmdKeySeq( CMD_TOOL_BUCKET ) );
974 ui->actionEyedropper->setShortcut( cmdKeySeq( CMD_TOOL_EYEDROPPER ) );
975 ui->actionEraser->setShortcut( cmdKeySeq( CMD_TOOL_ERASER ) );
977 ui->actionMove->installEventFilter( shortcutfilter );
978 ui->actionMove->installEventFilter( shortcutfilter );
979 ui->actionSelect->installEventFilter( shortcutfilter );
980 ui->actionBrush->installEventFilter( shortcutfilter );
981 ui->actionPolyline->installEventFilter( shortcutfilter );
982 ui->actionSmudge->installEventFilter( shortcutfilter );
983 ui->actionPen->installEventFilter( shortcutfilter );
984 ui->actionHand->installEventFilter( shortcutfilter );
985 ui->actionPencil->installEventFilter( shortcutfilter );
986 ui->actionBucket->installEventFilter( shortcutfilter );
987 ui->actionEyedropper->installEventFilter( shortcutfilter );
988 ui->actionEraser->installEventFilter( shortcutfilter );
990 ui->actionNew_Bitmap_Layer->setShortcut( cmdKeySeq( CMD_NEW_BITMAP_LAYER ) );
991 ui->actionNew_Vector_Layer->setShortcut( cmdKeySeq( CMD_NEW_VECTOR_LAYER ) );
992 ui->actionNew_Camera_Layer->setShortcut( cmdKeySeq( CMD_NEW_CAMERA_LAYER ) );
993 ui->actionNew_Sound_Layer->setShortcut( cmdKeySeq( CMD_NEW_SOUND_LAYER ) );
994 ui->actionDelete_Current_Layer->setShortcut(cmdKeySeq(CMD_DELETE_CUR_LAYER));
996 mToolBox->toggleViewAction()->setShortcut( cmdKeySeq( CMD_TOGGLE_TOOLBOX ) );
997 mToolOptions->toggleViewAction()->setShortcut( cmdKeySeq( CMD_TOGGLE_TOOL_OPTIONS ) );
998 mColorWheel->toggleViewAction()->setShortcut( cmdKeySeq( CMD_TOGGLE_COLOR_WHEEL ) );
999 mColorPalette->toggleViewAction()->setShortcut( cmdKeySeq( CMD_TOGGLE_COLOR_LIBRARY ) );
1000 mTimeLine->toggleViewAction()->setShortcut( cmdKeySeq( CMD_TOGGLE_TIMELINE ) );
1001 mDisplayOptionWidget->toggleViewAction()->setShortcut( cmdKeySeq( CMD_TOGGLE_DISPLAY_OPTIONS ) );
1003 ui->actionHelp->setShortcut( cmdKeySeq( CMD_HELP ) );
1006 void MainWindow2::clearKeyboardShortcuts()
1009 for( QAction* action : actionList )
1011 action->setShortcut( QKeySequence( 0 ) );
1015 void MainWindow2::undoActSetText(
void )
1017 if ( this->mEditor->mBackupIndex < 0 )
1019 ui->actionUndo->setText( tr(
"Undo") );
1020 ui->actionUndo->setEnabled(
false );
1024 ui->actionUndo->setText( tr(
"Undo %1 %2")
1025 .arg(QString::number( this->mEditor->mBackupIndex + 1 ))
1026 .arg(this->mEditor->mBackupList.at( this->mEditor->mBackupIndex )->undoText ));
1027 ui->actionUndo->setEnabled(
true );
1030 if ( this->mEditor->mBackupIndex + 2 < this->mEditor->mBackupList.size() )
1032 ui->actionRedo->setText( tr(
"Redo %1 %2")
1033 .arg(QString::number( this->mEditor->mBackupIndex + 2 ))
1034 .arg(this->mEditor->mBackupList.at( this->mEditor->mBackupIndex + 1 )->undoText ));
1035 ui->actionRedo->setEnabled(
true );
1039 ui->actionRedo->setText( tr(
"Redo") );
1040 ui->actionRedo->setEnabled(
false );
1044 void MainWindow2::undoActSetEnabled(
void )
1046 ui->actionUndo->setEnabled(
true );
1047 ui->actionRedo->setEnabled(
true );
1050 void MainWindow2::exportPalette()
1053 QString filePath =
FileDialog.saveFile( FileType::PALETTE );
1054 if ( !filePath.isEmpty() )
1056 mEditor->object()->exportPalette( filePath );
1060 void MainWindow2::importPalette()
1063 QString filePath = fileDialog.openFile( FileType::PALETTE );
1064 if ( !filePath.isEmpty() )
1066 mEditor->object()->importPalette( filePath );
1067 mColorPalette->refreshColorList();
1068 mEditor->color()->setColorNumber(0);
1072 void MainWindow2::aboutPencil()
1080 void MainWindow2::helpBox()
1084 QString url =
"http://www.pencil2d.org/documentation/";
1085 QDesktopServices::openUrl( QUrl(url) );
1088 void MainWindow2::makeConnections(
Editor* editor )
1090 connect( editor, &Editor::updateBackup,
this, &MainWindow2::updateSaveState );
1093 void MainWindow2::makeConnections(
Editor* editor,
ColorBox* colorBox )
1095 connect( colorBox, &ColorBox::colorChanged, editor->color(), &ColorManager::setColor );
1096 connect( editor->color(), &ColorManager::colorChanged, colorBox, &ColorBox::setColor );
1101 connect( editor->tools(), &ToolManager::toolChanged, scribbleArea, &ScribbleArea::setCurrentTool );
1102 connect( editor->tools(), &ToolManager::toolPropertyChanged, scribbleArea, &ScribbleArea::updateToolCursor );
1103 connect( editor->layers(), &LayerManager::currentLayerChanged, scribbleArea, &ScribbleArea::updateAllFrames );
1105 connect( editor, &Editor::currentFrameChanged, scribbleArea, &ScribbleArea::updateFrame );
1106 connect( editor, &Editor::selectAll, scribbleArea, &ScribbleArea::selectAll );
1108 connect( editor->view(), &ViewManager::viewChanged, scribbleArea, &ScribbleArea::updateAllFrames );
1112 void MainWindow2::makeConnections(
Editor* pEditor,
TimeLine* pTimeline )
1115 connect( pTimeline, &TimeLine::duplicateKeyClick, pEditor, &Editor::duplicateKey );
1117 connect( pTimeline, &TimeLine::loopStartClick, pPlaybackManager, &PlaybackManager::setRangedStartFrame );
1118 connect( pTimeline, &TimeLine::loopEndClick, pPlaybackManager, &PlaybackManager::setRangedEndFrame );
1120 connect( pTimeline, &TimeLine::soundClick, pPlaybackManager, &PlaybackManager::enableSound );
1121 connect( pTimeline, &TimeLine::fpsClick, pPlaybackManager, &PlaybackManager::setFps );
1123 connect( pTimeline, &TimeLine::addKeyClick, mCommands, &ActionCommands::addNewKey );
1124 connect( pTimeline, &TimeLine::removeKeyClick, mCommands, &ActionCommands::removeKey );
1126 connect( pTimeline, &TimeLine::newBitmapLayer, mCommands, &ActionCommands::addNewBitmapLayer );
1127 connect( pTimeline, &TimeLine::newVectorLayer, mCommands, &ActionCommands::addNewVectorLayer );
1128 connect( pTimeline, &TimeLine::newSoundLayer, mCommands, &ActionCommands::addNewSoundLayer );
1129 connect( pTimeline, &TimeLine::newCameraLayer, mCommands, &ActionCommands::addNewCameraLayer );
1131 connect( pTimeline, &TimeLine::toogleAbsoluteOnionClick, pEditor, &Editor::toogleOnionSkinType );
1133 connect( pEditor->layers(), &LayerManager::currentLayerChanged, pTimeline, &TimeLine::updateUI );
1134 connect( pEditor->layers(), &LayerManager::layerCountChanged, pTimeline, &TimeLine::updateUI );
1135 connect( pEditor->sound(), &SoundManager::soundClipDurationChanged, pTimeline, &TimeLine::updateUI );
1137 connect( pEditor, &Editor::objectLoaded, pTimeline, &TimeLine::onObjectLoaded );
1138 connect( pEditor, &Editor::updateTimeLine, pTimeline, &TimeLine::updateUI );
1140 connect( pEditor->layers(), &LayerManager::currentLayerChanged, mToolOptions, &ToolOptionWidget::updateUI);
1145 display->makeConnectionToEditor( editor );
1150 toolOptions->makeConnectionToEditor( editor );
1155 connect( pEditor, &Editor::objectLoaded, pColorPalette, &ColorPaletteWidget::updateUI );
1158 ScribbleArea* pScribbleArea = pEditor->getScribbleArea();
1160 connect( pColorPalette, &ColorPaletteWidget::colorChanged, pColorManager, &ColorManager::setColor );
1161 connect( pColorPalette, &ColorPaletteWidget::colorNumberChanged, pColorManager, &ColorManager::setColorNumber );
1163 connect( pColorPalette, &ColorPaletteWidget::colorChanged, pScribbleArea, &ScribbleArea::paletteColorChanged );
1165 connect( pColorManager, &ColorManager::colorChanged, pColorPalette, &ColorPaletteWidget::setColor );
1166 connect( pColorManager, &ColorManager::colorNumberChanged, pColorPalette, &ColorPaletteWidget::selectColorNumber );
1169 void MainWindow2::bindActionWithSetting( QAction* action, SETTING setting )
1174 action->setChecked( prefs->isOn( setting ) );
1177 connect( action, &QAction::triggered, prefs, [ = ] (
bool b )
1179 prefs->set( setting, b );
1182 connect( prefs, &PreferenceManager::optionChanged, action, [ = ]( SETTING s )
1186 action->setChecked( prefs->isOn( setting ) );
1191 void MainWindow2::updateZoomLabel()
1193 float zoom = mEditor->view()->scaling() * 100.f;
1194 statusBar()->showMessage( QString(
"Zoom: %0%1" ).arg( zoom, 0,
'f', 1 ).arg(
"%") );
1197 void MainWindow2::changePlayState(
bool isPlaying )
1201 ui->actionPlay->setText(tr(
"Stop"));
1202 ui->actionPlay->setIcon(mStopIcon);
1206 ui->actionPlay->setText(tr(
"Play"));
1207 ui->actionPlay->setIcon(mStartIcon);