Pencil2D  ff90c0872e88be3bf81c548cd60f01983012ec49
Pencil2D is an animation software for both bitmap and vector graphics. It is free, multi-platform, and open source.
 All Classes Functions
mainwindow2.cpp
1 /*
2 
3 Pencil - Traditional Animation Software
4 Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5 Copyright (C) 2008-2009 Mj Mendoza IV
6 Copyright (C) 2011-2017 Matt Chiawen Chang
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; version 2 of the License.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 */
18 
19 #include "mainwindow2.h"
20 #include "ui_mainwindow2.h"
21 
22 // standard headers
23 #include <memory>
24 
25 // Qt headers
26 #include <QList>
27 #include <QMenu>
28 #include <QFile>
29 #include <QScopedPointer>
30 #include <QMessageBox>
31 #include <QProgressDialog>
32 #include <QDesktopWidget>
33 #include <QDesktopServices>
34 #include <QGraphicsDropShadowEffect>
35 #include <QStatusBar>
36 #include <QFileIconProvider>
37 
38 #include "pencildef.h"
39 #include "pencilsettings.h"
40 #include "object.h"
41 #include "filemanager.h"
42 #include "editor.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"
50 
51 #include "scribblearea.h"
52 #include "colorbox.h"
53 #include "colorpalettewidget.h"
54 #include "displayoptionwidget.h"
55 #include "tooloptionwidget.h"
56 #include "preferencesdialog.h"
57 #include "timeline.h"
58 #include "toolbox.h"
59 #include "preview.h"
60 #include "timeline2.h"
61 #include "errordialog.h"
62 #include "importimageseqdialog.h"
63 #include "aboutdialog.h"
64 
65 #include "colorbox.h"
66 #include "util.h"
67 
68 #include "fileformat.h" //contains constants used by Pencil File Format
69 #include "JlCompress.h" //compress and decompress New Pencil File Format
70 #include "recentfilemenu.h"
71 
72 #include "exportimagedialog.h"
73 #include "exportmoviedialog.h"
74 #include "shortcutfilter.h"
75 #include "filedialogex.h"
76 #include "movieexporter.h"
77 #include "app_util.h"
78 
79 MainWindow2::MainWindow2( QWidget *parent ) : QMainWindow( parent )
80 {
81  ui = new Ui::MainWindow2;
82  ui->setupUi( this );
83 
84  mBackground = new BackgroundWidget( this );
85 
86  mScribbleArea = new ScribbleArea( mBackground );
87  mScribbleArea->setFocusPolicy( Qt::StrongFocus );
88 
89  // Show the UI over the background
90  //
91  QVBoxLayout* layout = new QVBoxLayout();
92  layout->setSpacing(0);
93  layout->setMargin(0);
94  layout->setContentsMargins(0,0,0,0);
95  layout->addWidget(mScribbleArea);
96 
97  mBackground->setLayout(layout);
98 
99  // Central widget
100  setCentralWidget(mBackground);
101 
102 
103  Object* object = new Object();
104  object->init();
105 
106  mEditor = new Editor( this );
107  mEditor->setScribbleArea(mScribbleArea);
108  mEditor->init();
109  mEditor->setObject( object );
110 
111  mScribbleArea->setCore( mEditor );
112  mScribbleArea->init();
113 
114  mEditor->setScribbleArea( mScribbleArea );
115  makeConnections( mEditor, mScribbleArea );
116 
117  mCommands = new ActionCommands( this );
118  mCommands->setCore( mEditor );
119 
120  createDockWidgets();
121  createMenus();
122  setupKeyboardShortcuts();
123 
124  readSettings();
125 
126  connect( mEditor, &Editor::needSave, this, &MainWindow2::saveDocument );
127  connect( mToolBox, &ToolBoxWidget::clearButtonClicked, mEditor, &Editor::clearCurrentFrame );
128 
129  //connect( mScribbleArea, &ScribbleArea::refreshPreview, mPreview, &PreviewWidget::updateImage );
130 
131  mEditor->setCurrentLayer( mEditor->object()->getLayerCount() - 1 );
132  mEditor->tools()->setDefaultTool();
133 
134  mBackground->init(mEditor->preference());
135 
136  mEditor->updateObject();
137  mEditor->color()->setColorNumber(0);
138 
139  connect( mEditor->view(), &ViewManager::viewChanged, this, &MainWindow2::updateZoomLabel );
140 }
141 
142 MainWindow2::~MainWindow2()
143 {
144  delete ui;
145 }
146 
147 
148 void MainWindow2::createDockWidgets()
149 {
150  mTimeLine = new TimeLine( this );
151  mTimeLine->setObjectName( "TimeLine" );
152 
153  mColorWheel = new ColorBox( this );
154  mColorWheel->setToolTip( tr( "color palette:<br>use <b>(C)</b><br>toggle at cursor" ) );
155  mColorWheel->setObjectName( "ColorWheel" );
156  mColorWheel->setMaximumHeight(390);
157 
158  mColorPalette = new ColorPaletteWidget( this );
159  mColorPalette->setObjectName( "ColorPalette" );
160 
161  mDisplayOptionWidget = new DisplayOptionWidget( this );
162  mDisplayOptionWidget->setObjectName( "DisplayOption" );
163 
164  mToolOptions = new ToolOptionWidget( this );
165  mToolOptions->setObjectName( "ToolOption" );
166 
167  mToolBox = new ToolBoxWidget( this );
168  mToolBox->setObjectName( "ToolBox" );
169 
170  /*
171  mTimeline2 = new Timeline2;
172  mTimeline2->setObjectName( "Timeline2" );
173  mDockWidgets.append( mTimeline2 );
174  */
175 
176  mDockWidgets
177  << mTimeLine
178  << mColorWheel
179  << mColorPalette
180  << mDisplayOptionWidget
181  << mToolOptions
182  << mToolBox;
183 
184  mStartIcon = QIcon(":icons/controls/play.png");
185  mStopIcon = QIcon(":icons/controls/stop.png");
186 
187  for ( BaseDockWidget* pWidget : mDockWidgets )
188  {
189  pWidget->setAllowedAreas( Qt::AllDockWidgetAreas );
190  pWidget->setFeatures( QDockWidget::AllDockWidgetFeatures );
191  pWidget->setFocusPolicy( Qt::NoFocus );
192 
193  pWidget->setEditor( mEditor );
194  pWidget->initUI();
195  pWidget->show();
196  qDebug() << "Init Dock widget: " << pWidget->objectName();
197  }
198 
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 );
205  //addDockWidget( Qt::BottomDockWidgetArea, mTimeline2);
206 
207  /*
208  mPreview = new PreviewWidget( this );
209  mPreview->setImage( mScribbleArea->mBufferImg );
210  mPreview->setFeatures( QDockWidget::DockWidgetFloatable );
211  mPreview->setFocusPolicy( Qt::NoFocus );
212  addDockWidget( Qt::RightDockWidgetArea, mPreview );
213  */
214 
215  makeConnections( mEditor );
216  makeConnections( mEditor, mTimeLine );
217  makeConnections( mEditor, mColorWheel );
218  makeConnections( mEditor, mColorPalette );
219  makeConnections( mEditor, mDisplayOptionWidget );
220  makeConnections( mEditor, mToolOptions );
221 
222  for ( BaseDockWidget* w : mDockWidgets )
223  {
224  w->updateUI();
225  w->setFloating( false );
226  }
227 }
228 
229 
231 {
232  // ---------- File Menu -------------
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 );
238 
240  //connect( ui->actionExport_X_sheet, &QAction::triggered, mEditor, &Editor::exportX );
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 );
244 
245  connect( ui->actionExport_Palette, &QAction::triggered, this, &MainWindow2::exportPalette );
246 
248  //connect( ui->actionExport_Svg_Image, &QAction::triggered, editor, &Editor::saveSvg );
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 );
252 
253  connect( ui->actionImport_Sound, &QAction::triggered, mCommands, &ActionCommands::importSound );
254  connect( ui->actionImport_Palette, &QAction::triggered, this, &MainWindow2::importPalette );
255 
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 );
269 
270  ui->actionRedo->setEnabled( false );
271 
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 );
278 
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 );
288 
289  ui->actionPreview->setEnabled( false );
290  //# connect(previewAct, SIGNAL(triggered()), editor, SLOT(getCameraLayer()));//TODO: Preview view
291 
292  setMenuActionChecked( ui->actionGrid, mEditor->preference()->isOn( SETTING::GRID ) );
293  connect( ui->actionGrid, &QAction::triggered, mCommands, &ActionCommands::showGrid );
294 
295  bindActionWithSetting( ui->actionOnionPrev, SETTING::PREV_ONION );
296  bindActionWithSetting( ui->actionOnionNext, SETTING::NEXT_ONION );
297  bindActionWithSetting( ui->actionMultiLayerOnionSkin, SETTING::MULTILAYER_ONION );
298 
300  PlaybackManager* pPlaybackManager = mEditor->playback();
301  connect( ui->actionPlay, &QAction::triggered, mCommands, &ActionCommands::PlayStop );
302 
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 );
311 
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 );
321 
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 );
335 
337  QMenu* winMenu = ui->menuWindows;
338 
339  QAction* actions[] =
340  {
341  mToolBox->toggleViewAction(),
342  mToolOptions->toggleViewAction(),
343  mColorWheel->toggleViewAction(),
344  mColorPalette->toggleViewAction(),
345  mTimeLine->toggleViewAction(),
346  mDisplayOptionWidget->toggleViewAction()
347  };
348  winMenu->clear();
349  for ( QAction* action : actions )
350  {
351  action->setMenuRole( QAction::NoRole );
352  winMenu->addAction( action );
353  }
354 
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 );
361 
362 
363  // -------------- Help Menu ---------------
364  connect( ui->actionHelp, &QAction::triggered, this, &MainWindow2::helpBox);
365  connect( ui->actionAbout, &QAction::triggered, this, &MainWindow2::aboutPencil );
366 
367  // --------------- Menus ------------------
368  mRecentFileMenu = new RecentFileMenu( tr("Open Recent"), this );
369  mRecentFileMenu->loadFromDisk();
370  ui->menuFile->insertMenu( ui->actionSave, mRecentFileMenu );
371 
372  connect( mRecentFileMenu, &RecentFileMenu::loadRecentFile, this, &MainWindow2::openFile );
373 
374  connect( ui->menuEdit, SIGNAL( aboutToShow() ), this, SLOT( undoActSetText() ) );
375  connect( ui->menuEdit, SIGNAL( aboutToHide() ), this, SLOT( undoActSetEnabled() ) );
376 }
377 
378 void MainWindow2::setMenuActionChecked( QAction* action, bool bChecked )
379 {
380  SignalBlocker b( action );
381  action->setChecked( bChecked );
382 }
383 
384 void MainWindow2::setOpacity( int opacity )
385 {
386  mEditor->preference()->set(SETTING::WINDOW_OPACITY, 100 - opacity);
387  setWindowOpacity( opacity / 100.0 );
388 }
389 
390 void MainWindow2::updateSaveState()
391 {
392  setWindowModified( mEditor->currentBackup() != mBackupAtSave );
393 }
394 
395 void MainWindow2::clearRecentFilesList()
396 {
397  QStringList recentFilesList = mRecentFileMenu->getRecentFiles();
398  if (!recentFilesList.isEmpty()) {
399  mRecentFileMenu->clear();
400 
401  QMessageBox::information(this, 0,
402  tr("\n\n You have successfully cleared the list"),
403  QMessageBox::Ok);
404  }
405  getPrefDialog()->updateRecentListBtn(!recentFilesList.isEmpty());
406 }
407 
408 void MainWindow2::closeEvent( QCloseEvent* event )
409 {
410  if ( maybeSave() )
411  {
412  writeSettings();
413  event->accept();
414  }
415  else
416  {
417  event->ignore();
418  }
419 }
420 
421 void MainWindow2::tabletEvent( QTabletEvent* event )
422 {
423  event->ignore();
424 }
425 
426 void MainWindow2::newDocument()
427 {
428  if (maybeSave()) {
429  Object* object = new Object();
430  object->init();
431  mEditor->setObject( object );
432  mEditor->scrubTo( 0 );
433  mEditor->view()->resetView();
434 
435  // Refresh the palette
436  mColorPalette->refreshColorList();
437  mEditor->color()->setColorNumber(0);
438 
439  setWindowTitle( PENCIL_WINDOW_TITLE );
440  updateSaveState();
441  }
442 }
443 
444 void MainWindow2::openDocument()
445 {
446  if ( maybeSave() )
447  {
448  FileDialog fileDialog( this );
449  QString fileName = fileDialog.openFile( FileType::ANIMATION );
450  if ( fileName.isEmpty() )
451  {
452  return;
453  }
454  QFileInfo fileInfo( fileName );
455  if ( fileInfo.isDir() )
456  {
457  return;
458  }
459 
460  bool ok = openObject( fileName );
461  if ( !ok )
462  {
463  QMessageBox::warning( this, tr("Warning"), tr("Pencil cannot read this file. If you want to import images, use the command import.") );
464  newDocument();
465  }
466  }
467 }
468 
469 bool MainWindow2::saveAsNewDocument()
470 {
471  FileDialog fileDialog( this );
472  QString fileName = fileDialog.saveFile( FileType::ANIMATION );
473  if ( fileName.isEmpty() )
474  {
475  return false;
476  }
477 
478  if ( !fileName.endsWith( PFF_OLD_EXTENSION ) && !fileName.endsWith( PFF_EXTENSION ) )
479  {
480  fileName = fileName + PFF_EXTENSION;
481  }
482 
483  return saveObject( fileName );
484 
485 }
486 
487 void MainWindow2::openFile( QString filename )
488 {
489  bool ok = openObject( filename );
490  if ( !ok )
491  {
492  QMessageBox::warning( this, tr("Warning"), tr("Pencil cannot read this file. If you want to import images, use the command import.") );
493  newDocument();
494  }
495 }
496 
497 bool MainWindow2::openObject( QString strFilePath )
498 {
499  QProgressDialog progress( tr("Opening document..."), tr("Abort"), 0, 100, this );
500 
501  // Don't show progress bar if running without a GUI (aka. when rendering from command line)
502  if ( this->isVisible() )
503  {
504  hideQuestionMark( progress );
505  progress.setWindowModality( Qt::WindowModal );
506  progress.show();
507  }
508 
509  mEditor->setCurrentLayer( 0 );
510 
511  FileManager fm( this );
512  connect( &fm, &FileManager::progressUpdated, [&progress]( float f )
513  {
514  progress.setValue( (int)( f * 100.f ) );
515  QApplication::processEvents( QEventLoop::ExcludeUserInputEvents );
516 
517  } );
518 
519  Object* object = fm.load( strFilePath );
520 
521  if ( object == nullptr || !fm.error().ok() )
522  {
523  return false;
524  }
525 
526  mEditor->setObject( object );
527 
528  QSettings settings( PENCIL2D, PENCIL2D );
529  settings.setValue( LAST_PCLX_PATH, object->filePath() );
530 
531  mRecentFileMenu->addRecentFile( object->filePath() );
532  mRecentFileMenu->saveToDisk();
533 
534  setWindowTitle( object->filePath().prepend("[*]") );
535  setWindowModified( false );
536  setWindowIcon( QFileIconProvider().icon(strFilePath) );
537 
538  // Refresh the Palette
539  mColorPalette->refreshColorList();
540  mEditor->color()->setColorNumber(0);
541 
542  // Reset view
543  mEditor->scrubTo( 0 );
544  mEditor->view()->resetView();
545 
546  progress.setValue( 100 );
547  return true;
548 }
549 
550 bool MainWindow2::saveObject( QString strSavedFileName )
551 {
552  QProgressDialog progress( tr( "Saving document..." ), tr( "Abort" ), 0, 100, this );
553  progress.setWindowModality( Qt::WindowModal );
554  progress.show();
555 
556  mEditor->prepareSave();
557 
558  FileManager* fm = new FileManager( this );
559  Status st = fm->save( mEditor->object(), strSavedFileName );
560 
561  progress.setValue( 100 );
562 
563  if ( !st.ok() )
564  {
565  QDateTime dt = QDateTime::currentDateTime();
566  dt.setTimeSpec( Qt::UTC );
567 #if QT_VERSION >= 0x050400
568  QDir errorLogFolder( QStandardPaths::writableLocation( QStandardPaths::AppLocalDataLocation ) );
569 #else
570  QDir errorLogFolder( QStandardPaths::writableLocation( QStandardPaths::DataLocation ) );
571 #endif
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 ) )
576  {
577  QTextStream out( &eLog );
578  out << st.details().replace( "<br>", "\n", Qt::CaseInsensitive );
579  }
580 
581  ErrorDialog errorDialog( st.title(),
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() );
586  errorDialog.exec();
587  return false;
588  }
589 
590  QSettings settings( PENCIL2D, PENCIL2D );
591  settings.setValue( LAST_PCLX_PATH, strSavedFileName );
592 
593  mRecentFileMenu->addRecentFile( strSavedFileName );
594  mRecentFileMenu->saveToDisk();
595 
596  mTimeLine->updateContent();
597 
598  setWindowTitle( strSavedFileName.prepend("[*]") );
599  mBackupAtSave = mEditor->currentBackup();
600  updateSaveState();
601 
602  return true;
603 }
604 
605 void MainWindow2::saveDocument()
606 {
607  if ( !mEditor->object()->filePath().isEmpty() )
608  {
609  saveObject( mEditor->object()->filePath() );
610  }
611  else
612  {
613  saveAsNewDocument();
614  }
615 }
616 
617 bool MainWindow2::maybeSave()
618 {
619  if ( mEditor->currentBackup() != mBackupAtSave )
620  {
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,
624  QMessageBox::No,
625  QMessageBox::Cancel | QMessageBox::Escape );
626  if ( ret == QMessageBox::Yes )
627  {
628  saveDocument();
629  return true;
630  }
631  else if ( ret == QMessageBox::Cancel )
632  {
633  return false;
634  }
635  }
636  return true;
637 }
638 
639 void MainWindow2::importImage()
640 {
641  FileDialog fileDialog( this );
642  QString strFilePath = fileDialog.openFile( FileType::IMAGE );
643  if ( strFilePath.isEmpty() )
644  {
645  return;
646  }
647 
648  if ( !QFile::exists( strFilePath ) )
649  {
650  return;
651  }
652 
653  bool ok = mEditor->importImage( strFilePath );
654  if ( !ok )
655  {
656  QMessageBox::warning( this,
657  tr( "Warning" ),
658  tr( "Unable to import image.<br><b>TIP:</b> Use Bitmap layer to import bitmaps." ),
659  QMessageBox::Ok,
660  QMessageBox::Ok );
661  return;
662  }
663 
664  mScribbleArea->updateCurrentFrame();
665  mTimeLine->updateContent();
666 }
667 
668 void MainWindow2::importImageSequence()
669 {
670  auto imageSeqDialog = new ImportImageSeqDialog( this );
671  imageSeqDialog->exec();
672  if ( imageSeqDialog->result() == QDialog::Rejected )
673  {
674  return;
675  }
676 
677  QStringList files = imageSeqDialog->getFilePaths();
678  int number = imageSeqDialog->getSpace();
679  for ( QString strImgFile : files )
680  {
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" ) )
687  {
688  mEditor->importImage( strImgFile );
689  for ( int i = 1; i < number; i++ )
690  {
691  mEditor->scrubForward();
692  }
693  }
694  }
695 }
696 
697 void MainWindow2::importMovie()
698 {
699  FileDialog fileDialog( this );
700  QString filePath = fileDialog.openFile( FileType::MOVIE );
701  if ( filePath.isEmpty() )
702  {
703  return;
704  }
705  mEditor->importMovie( filePath, mEditor->playback()->fps() );
706 }
707 
708 void MainWindow2::lockWidgets(bool shouldLock)
709 {
710  QDockWidget::DockWidgetFeature feat = shouldLock ? QDockWidget::DockWidgetClosable : QDockWidget::AllDockWidgetFeatures;
711 
712  mColorWheel->setFeatures(feat);
713  mColorPalette->setFeatures(feat);
714  mDisplayOptionWidget->setFeatures(feat);
715  mToolOptions->setFeatures(feat);
716  mToolBox->setFeatures(feat);
717  mTimeLine->setFeatures(feat);
718 }
719 
720 void MainWindow2::exportImageSequence()
721 {
722  // Get the camera layer
723  int cameraLayerId = mEditor->layers()->getLastCameraLayer();
724 
725  LayerCamera *cameraLayer = dynamic_cast< LayerCamera* >(mEditor->object()->getLayer(cameraLayerId));
726 
727  // Options
728  auto dialog = new ExportImageDialog( this, true );
729  OnScopeExit( dialog->deleteLater() );
730 
731  if(cameraLayer != nullptr)
732  {
733  dialog->setExportSize( cameraLayer->getViewRect().size() );
734  }
735  else
736  {
737  dialog->setExportSize( QSize(640,480) );
738  }
739  dialog->exec();
740 
741  QString strFilePath = dialog->getFilePath();
742  QSize exportSize = dialog->getExportSize();
743  QString exportFormat = dialog->getExportFormat();
744  bool useTranparency = dialog->getTransparency();
745 
746  if ( dialog->result() == QDialog::Rejected )
747  {
748  return; // false;
749  }
750 
751 
752  // Export
753 // QTransform view = RectMapTransform( mScribbleArea->getViewRect(), QRectF( QPointF( 0, 0 ), exportSize ) );
754 // view = mScribbleArea->getView() * view;
755 
756 
757  int projectLength = mEditor->layers()->projectLength();
758 
759  // Show a progress dialog, as this can take a while if you have lots of frames.
760  QProgressDialog progress( tr( "Exporting image sequence..." ), tr( "Abort" ), 0, 100, this );
761  hideQuestionMark(progress);
762  progress.setWindowModality( Qt::WindowModal );
763  progress.show();
764 
765  mEditor->object()->exportFrames( 1,
766  projectLength,
767  cameraLayer,
768  exportSize,
769  strFilePath,
770  exportFormat.toStdString().c_str(),
771  -1,
772  useTranparency,
773  true,
774  &progress,
775  100 );
776 
777  progress.close();
778 
779  //return true;
780 }
781 
782 void MainWindow2::exportImage()
783 {
784  QSettings settings( PENCIL2D, PENCIL2D );
785 
786  // Get the camera layer
787  int cameraLayerId = mEditor->layers()->getLastCameraLayer();
788 
789  LayerCamera *cameraLayer = dynamic_cast< LayerCamera* >(mEditor->object()->getLayer(cameraLayerId));
790 
791 
792  // Options
793  auto dialog = new ExportImageDialog( this );
794  OnScopeExit( dialog->deleteLater() );
795 
796  if(cameraLayer != nullptr)
797  {
798  dialog->setExportSize(cameraLayer->getViewRect().size());
799  }
800  else
801  {
802  dialog->setExportSize(QSize(640, 480));
803  }
804  dialog->exec();
805 
806  QString filePath = dialog->getFilePath();
807  QSize exportSize = dialog->getExportSize();
808  QString exportFormat = dialog->getExportFormat();
809  bool useTranparency = dialog->getTransparency();
810 
811  if ( dialog->result() == QDialog::Rejected )
812  {
813  return; // false;
814  }
815 
816 
817  // Export
818  QTransform view = RectMapTransform( mScribbleArea->getViewRect(), QRectF( QPointF( 0, 0 ), exportSize ) );
819 // view = mScribbleArea->getView() * view;
820 
821  int projectLength = mEditor->layers()->projectLength();
822  if ( !mEditor->object()->exportIm( mEditor->currentFrame(),
823  projectLength,
824  view,
825  exportSize,
826  filePath,
827  exportFormat,
828  true,
829  useTranparency ) )
830  {
831  QMessageBox::warning( this,
832  tr( "Warning" ),
833  tr( "Unable to export image." ),
834  QMessageBox::Ok,
835  QMessageBox::Ok );
836  return;// false;
837  }
838  return; // true;
839 }
840 
841 void MainWindow2::preferences()
842 {
843  mPrefDialog = new PreferencesDialog( this );
844  mPrefDialog->setAttribute( Qt::WA_DeleteOnClose );
845  mPrefDialog->init( mEditor->preference() );
846 
847  connect( mPrefDialog, &PreferencesDialog::clearRecentList, this, &MainWindow2::clearRecentFilesList);
848  connect( mPrefDialog, &PreferencesDialog::windowOpacityChange, this, &MainWindow2::setOpacity );
849  connect( mPrefDialog, &PreferencesDialog::finished, [ &]
850  {
851  //qDebug() << "Preference dialog closed!";
852  clearKeyboardShortcuts();
853  setupKeyboardShortcuts();
854  mScribbleArea->updateCanvasCursor();
855  } );
856 
857  mPrefDialog->show();
858 }
859 
860 void MainWindow2::dockAllSubWidgets()
861 {
862  mToolBox->setFloating(false);
863  mToolOptions->setFloating(false);
864  mDisplayOptionWidget->setFloating(false);
865  mTimeLine->setFloating(false);
866  mColorPalette->setFloating(false);
867  mColorWheel->setFloating( false );
868 }
869 
870 void MainWindow2::readSettings()
871 {
872  QSettings settings( PENCIL2D, PENCIL2D );
873 
874  QVariant winGeometry = settings.value( SETTING_WINDOW_GEOMETRY );
875  restoreGeometry( winGeometry.toByteArray() );
876 
877  QVariant winState = settings.value( SETTING_WINDOW_STATE );
878  restoreState( winState.toByteArray() );
879 
880  QString myPath = settings.value( LAST_PCLX_PATH, QVariant( QDir::homePath() ) ).toString();
881  mRecentFileMenu->addRecentFile( myPath );
882 
883  int opacity = mEditor->preference()->getInt(SETTING::WINDOW_OPACITY);
884 
885  setOpacity( 100 - opacity );
886 }
887 
888 void MainWindow2::writeSettings()
889 {
890  qDebug( "Save current windows layout." );
891 
892  QSettings settings( PENCIL2D, PENCIL2D );
893  settings.setValue( SETTING_WINDOW_GEOMETRY, saveGeometry() );
894  settings.setValue( SETTING_WINDOW_STATE, saveState() );
895 }
896 
897 void MainWindow2::setupKeyboardShortcuts()
898 {
899  checkExistingShortcuts();
900 
901  auto cmdKeySeq = []( QString strCommandName ) -> QKeySequence
902  {
903  strCommandName = QString( "shortcuts/" ) + strCommandName;
904  QKeySequence keySequence( pencilSettings().value( strCommandName ).toString() );
905  return keySequence;
906  };
907 
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 ) );
913 
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 ) );
919 
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 ) );
926 
927  // edit menu
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 ) );
937 
938  // View menu
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 ) );
951 
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 ) );
963 
964  ShortcutFilter* shortcutfilter = new ShortcutFilter( mScribbleArea, this );
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 ) );
976 
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 );
989 
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));
995 
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 ) );
1002 
1003  ui->actionHelp->setShortcut( cmdKeySeq( CMD_HELP ) );
1004 }
1005 
1006 void MainWindow2::clearKeyboardShortcuts()
1007 {
1008  QList<QAction*> actionList = this->findChildren<QAction*>();
1009  for( QAction* action : actionList )
1010  {
1011  action->setShortcut( QKeySequence( 0 ) );
1012  }
1013 }
1014 
1015 void MainWindow2::undoActSetText( void )
1016 {
1017  if ( this->mEditor->mBackupIndex < 0 )
1018  {
1019  ui->actionUndo->setText( tr("Undo") );
1020  ui->actionUndo->setEnabled( false );
1021  }
1022  else
1023  {
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 );
1028  }
1029 
1030  if ( this->mEditor->mBackupIndex + 2 < this->mEditor->mBackupList.size() )
1031  {
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 );
1036  }
1037  else
1038  {
1039  ui->actionRedo->setText( tr("Redo") );
1040  ui->actionRedo->setEnabled( false );
1041  }
1042 }
1043 
1044 void MainWindow2::undoActSetEnabled( void )
1045 {
1046  ui->actionUndo->setEnabled( true );
1047  ui->actionRedo->setEnabled( true );
1048 }
1049 
1050 void MainWindow2::exportPalette()
1051 {
1052  FileDialog FileDialog( this );
1053  QString filePath = FileDialog.saveFile( FileType::PALETTE );
1054  if ( !filePath.isEmpty() )
1055  {
1056  mEditor->object()->exportPalette( filePath );
1057  }
1058 }
1059 
1060 void MainWindow2::importPalette()
1061 {
1062  FileDialog fileDialog( this );
1063  QString filePath = fileDialog.openFile( FileType::PALETTE );
1064  if ( !filePath.isEmpty() )
1065  {
1066  mEditor->object()->importPalette( filePath );
1067  mColorPalette->refreshColorList();
1068  mEditor->color()->setColorNumber(0);
1069  }
1070 }
1071 
1072 void MainWindow2::aboutPencil()
1073 {
1074  AboutDialog* about = new AboutDialog( this );
1075 
1076  about->init();
1077  about->exec();
1078 }
1079 
1080 void MainWindow2::helpBox()
1081 {
1082  //qDebug() << "Open help manual.";
1083 
1084  QString url = "http://www.pencil2d.org/documentation/";
1085  QDesktopServices::openUrl( QUrl(url) );
1086 }
1087 
1088 void MainWindow2::makeConnections( Editor* editor )
1089 {
1090  connect( editor, &Editor::updateBackup, this, &MainWindow2::updateSaveState );
1091 }
1092 
1093 void MainWindow2::makeConnections( Editor* editor, ColorBox* colorBox )
1094 {
1095  connect( colorBox, &ColorBox::colorChanged, editor->color(), &ColorManager::setColor );
1096  connect( editor->color(), &ColorManager::colorChanged, colorBox, &ColorBox::setColor );
1097 }
1098 
1099 void MainWindow2::makeConnections( Editor* editor, ScribbleArea* scribbleArea )
1100 {
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 );
1104 
1105  connect( editor, &Editor::currentFrameChanged, scribbleArea, &ScribbleArea::updateFrame );
1106  connect( editor, &Editor::selectAll, scribbleArea, &ScribbleArea::selectAll );
1107 
1108  connect( editor->view(), &ViewManager::viewChanged, scribbleArea, &ScribbleArea::updateAllFrames );
1109 // connect( editor->preference(), &PreferenceManager::preferenceChanged, scribbleArea, &ScribbleArea::onPreferencedChanged );
1110 }
1111 
1112 void MainWindow2::makeConnections( Editor* pEditor, TimeLine* pTimeline )
1113 {
1114  PlaybackManager* pPlaybackManager = pEditor->playback();
1115  connect( pTimeline, &TimeLine::duplicateKeyClick, pEditor, &Editor::duplicateKey );
1116 
1117  connect( pTimeline, &TimeLine::loopStartClick, pPlaybackManager, &PlaybackManager::setRangedStartFrame );
1118  connect( pTimeline, &TimeLine::loopEndClick, pPlaybackManager, &PlaybackManager::setRangedEndFrame );
1119 
1120  connect( pTimeline, &TimeLine::soundClick, pPlaybackManager, &PlaybackManager::enableSound );
1121  connect( pTimeline, &TimeLine::fpsClick, pPlaybackManager, &PlaybackManager::setFps );
1122 
1123  connect( pTimeline, &TimeLine::addKeyClick, mCommands, &ActionCommands::addNewKey );
1124  connect( pTimeline, &TimeLine::removeKeyClick, mCommands, &ActionCommands::removeKey );
1125 
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 );
1130 
1131  connect( pTimeline, &TimeLine::toogleAbsoluteOnionClick, pEditor, &Editor::toogleOnionSkinType );
1132 
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 );
1136 
1137  connect( pEditor, &Editor::objectLoaded, pTimeline, &TimeLine::onObjectLoaded );
1138  connect( pEditor, &Editor::updateTimeLine, pTimeline, &TimeLine::updateUI );
1139 
1140  connect( pEditor->layers(), &LayerManager::currentLayerChanged, mToolOptions, &ToolOptionWidget::updateUI);
1141 }
1142 
1143 void MainWindow2::makeConnections(Editor* editor, DisplayOptionWidget* display)
1144 {
1145  display->makeConnectionToEditor( editor );
1146 }
1147 
1148 void MainWindow2::makeConnections( Editor* editor, ToolOptionWidget* toolOptions )
1149 {
1150  toolOptions->makeConnectionToEditor( editor );
1151 }
1152 
1153 void MainWindow2::makeConnections( Editor* pEditor, ColorPaletteWidget* pColorPalette )
1154 {
1155  connect( pEditor, &Editor::objectLoaded, pColorPalette, &ColorPaletteWidget::updateUI );
1156 
1157  ColorManager* pColorManager = pEditor->color();
1158  ScribbleArea* pScribbleArea = pEditor->getScribbleArea();
1159 
1160  connect( pColorPalette, &ColorPaletteWidget::colorChanged, pColorManager, &ColorManager::setColor );
1161  connect( pColorPalette, &ColorPaletteWidget::colorNumberChanged, pColorManager, &ColorManager::setColorNumber );
1162 
1163  connect( pColorPalette, &ColorPaletteWidget::colorChanged, pScribbleArea, &ScribbleArea::paletteColorChanged );
1164 
1165  connect( pColorManager, &ColorManager::colorChanged, pColorPalette, &ColorPaletteWidget::setColor );
1166  connect( pColorManager, &ColorManager::colorNumberChanged, pColorPalette, &ColorPaletteWidget::selectColorNumber );
1167 }
1168 
1169 void MainWindow2::bindActionWithSetting( QAction* action, SETTING setting )
1170 {
1171  PreferenceManager* prefs = mEditor->preference();
1172 
1173  // set initial state
1174  action->setChecked( prefs->isOn( setting ) );
1175 
1176  // 2-way binding
1177  connect( action, &QAction::triggered, prefs, [ = ] ( bool b )
1178  {
1179  prefs->set( setting, b );
1180  } );
1181 
1182  connect( prefs, &PreferenceManager::optionChanged, action, [ = ]( SETTING s )
1183  {
1184  if ( s == setting )
1185  {
1186  action->setChecked( prefs->isOn( setting ) );
1187  }
1188  } );
1189 }
1190 
1191 void MainWindow2::updateZoomLabel()
1192 {
1193  float zoom = mEditor->view()->scaling() * 100.f;
1194  statusBar()->showMessage( QString( "Zoom: %0%1" ).arg( zoom, 0, 'f', 1 ).arg("%") );
1195 }
1196 
1197 void MainWindow2::changePlayState( bool isPlaying )
1198 {
1199  if( isPlaying )
1200  {
1201  ui->actionPlay->setText(tr("Stop"));
1202  ui->actionPlay->setIcon(mStopIcon);
1203  }
1204  else
1205  {
1206  ui->actionPlay->setText(tr("Play"));
1207  ui->actionPlay->setIcon(mStartIcon);
1208  }
1209  update();
1210 }
Definition: object.h:71
Definition: editor.h:45
void createMenus()