1 
2 
3 #include "mainwindow.h"
4 
5 // Tnz6 includes
6 #include "menubar.h"
7 #include "menubarcommandids.h"
8 #include "xsheetviewer.h"
9 #include "viewerpane.h"
10 #include "flipbook.h"
11 #include "messagepanel.h"
12 #include "iocommand.h"
13 #include "tapp.h"
14 #include "comboviewerpane.h"
15 #include "startuppopup.h"
16 
17 // TnzTools includes
18 #include "tools/toolcommandids.h"
19 #include "tools/toolhandle.h"
20 
21 // TnzQt includes
22 #include "toonzqt/gutil.h"
23 #include "toonzqt/icongenerator.h"
24 #include "toonzqt/viewcommandids.h"
25 #include "toonzqt/updatechecker.h"
26 #include "toonzqt/paletteviewer.h"
27 
28 // TnzLib includes
29 #include "toonz/toonzfolders.h"
30 #include "toonz/stage2.h"
31 #include "toonz/stylemanager.h"
32 #include "toonz/tscenehandle.h"
33 #include "toonz/toonzscene.h"
34 #include "toonz/txshleveltypes.h"
35 #include "toonz/tproject.h"
36 
37 // TnzBase includes
38 #include "tenv.h"
39 
40 // TnzCore includes
41 #include "tsystem.h"
42 #include "timagecache.h"
43 #include "tthread.h"
44 
45 // Qt includes
46 #include <QStackedWidget>
47 #include <QSettings>
48 #include <QApplication>
49 #include <QGLPixelBuffer>
50 #include <QDebug>
51 #include <QDesktopServices>
52 #include <QButtonGroup>
53 #include <QPushButton>
54 #include <QLabel>
55 #include <QMessageBox>
56 #ifdef _WIN32
57 #include <QtPlatformHeaders/QWindowsWindowFunctions>
58 #endif
59 
60 TEnv::IntVar ViewCameraToggleAction("ViewCameraToggleAction", 1);
61 TEnv::IntVar ViewTableToggleAction("ViewTableToggleAction", 1);
62 TEnv::IntVar FieldGuideToggleAction("FieldGuideToggleAction", 0);
63 TEnv::IntVar ViewBBoxToggleAction("ViewBBoxToggleAction1", 1);
64 TEnv::IntVar EditInPlaceToggleAction("EditInPlaceToggleAction", 0);
65 TEnv::IntVar RasterizePliToggleAction("RasterizePliToggleAction", 0);
66 TEnv::IntVar SafeAreaToggleAction("SafeAreaToggleAction", 0);
67 TEnv::IntVar ViewColorcardToggleAction("ViewColorcardToggleAction", 1);
68 TEnv::IntVar ViewGuideToggleAction("ViewGuideToggleAction", 1);
69 TEnv::IntVar ViewRulerToggleAction("ViewRulerToggleAction", 1);
70 TEnv::IntVar TCheckToggleAction("TCheckToggleAction", 0);
71 TEnv::IntVar ICheckToggleAction("ICheckToggleAction", 0);
72 TEnv::IntVar Ink1CheckToggleAction("Ink1CheckToggleAction", 0);
73 TEnv::IntVar PCheckToggleAction("PCheckToggleAction", 0);
74 TEnv::IntVar IOnlyToggleAction("IOnlyToggleAction", 0);
75 TEnv::IntVar BCheckToggleAction("BCheckToggleAction", 0);
76 TEnv::IntVar GCheckToggleAction("GCheckToggleAction", 0);
77 TEnv::IntVar ACheckToggleAction("ACheckToggleAction", 0);
78 TEnv::IntVar LinkToggleAction("LinkToggleAction", 0);
79 TEnv::IntVar DockingCheckToggleAction("DockingCheckToggleAction", 0);
80 TEnv::IntVar ShiftTraceToggleAction("ShiftTraceToggleAction", 0);
81 TEnv::IntVar EditShiftToggleAction("EditShiftToggleAction", 0);
82 TEnv::IntVar NoShiftToggleAction("NoShiftToggleAction", 0);
83 TEnv::IntVar TouchGestureControl("TouchGestureControl", 0);
84 
85 //=============================================================================
86 namespace {
87 //=============================================================================
88 
89 // layout file name may be overwritten by the argument
90 std::string layoutsFileName           = "layouts.txt";
91 const std::string currentRoomFileName = "currentRoom.txt";
92 bool scrambledRooms                   = false;
93 
94 //=============================================================================
95 
readRoomList(std::vector<TFilePath> & roomPaths,const QString & argumentLayoutFileName)96 bool readRoomList(std::vector<TFilePath> &roomPaths,
97                   const QString &argumentLayoutFileName) {
98   bool argumentLayoutFileLoaded = false;
99 
100   TFilePath fp;
101   /*-レイアウトファイルが指定されている場合--*/
102   if (!argumentLayoutFileName.isEmpty()) {
103     fp = ToonzFolder::getRoomsFile(argumentLayoutFileName.toStdString());
104     if (!TFileStatus(fp).doesExist()) {
105       DVGui::warning("Room layout file " + argumentLayoutFileName +
106                      " not found!");
107       fp = ToonzFolder::getRoomsFile(layoutsFileName);
108       if (!TFileStatus(fp).doesExist()) return false;
109     } else {
110       argumentLayoutFileLoaded = true;
111       layoutsFileName          = argumentLayoutFileName.toStdString();
112     }
113   } else {
114     fp = ToonzFolder::getRoomsFile(layoutsFileName);
115     if (!TFileStatus(fp).doesExist()) return false;
116   }
117 
118   Tifstream is(fp);
119   for (;;) {
120     char buffer[1024];
121     is.getline(buffer, sizeof(buffer));
122     if (is.eof()) break;
123     char *s = buffer;
124     while (*s == ' ' || *s == '\t') s++;
125     char *t = s;
126     while (*t && *t != '\r' && *t != '\n') t++;
127     while (t > s && (t[-1] == ' ' || t[-1] == '\t')) t--;
128     t[0] = '\0';
129     if (s[0] == '\0') continue;
130     TFilePath roomPath = fp.getParentDir() + s;
131     roomPaths.push_back(roomPath);
132   }
133 
134   return argumentLayoutFileLoaded;
135 }
136 
137 //-----------------------------------------------------------------------------
138 
writeRoomList(std::vector<TFilePath> & roomPaths)139 void writeRoomList(std::vector<TFilePath> &roomPaths) {
140   TFilePath fp = ToonzFolder::getMyRoomsDir() + layoutsFileName;
141   TSystem::touchParentDir(fp);
142   Tofstream os(fp);
143   if (!os) return;
144   for (int i = 0; i < (int)roomPaths.size(); i++) {
145     TFilePath roomPath = roomPaths[i];
146     assert(roomPath.getParentDir() == fp.getParentDir());
147     os << roomPath.withoutParentDir() << "\n";
148   }
149 }
150 
151 //-----------------------------------------------------------------------------
152 
writeRoomList(std::vector<Room * > & rooms)153 void writeRoomList(std::vector<Room *> &rooms) {
154   std::vector<TFilePath> roomPaths;
155   for (int i = 0; i < (int)rooms.size(); i++)
156     roomPaths.push_back(rooms[i]->getPath());
157   writeRoomList(roomPaths);
158 }
159 
160 //-----------------------------------------------------------------------------
161 
makePrivate(Room * room)162 void makePrivate(Room *room) {
163   TFilePath layoutDir       = ToonzFolder::getMyRoomsDir();
164   TFilePath roomPath        = room->getPath();
165   std::string mbSrcFileName = roomPath.getName() + "_menubar.xml";
166   if (roomPath == TFilePath() || roomPath.getParentDir() != layoutDir) {
167     int count = 1;
168     for (;;) {
169       roomPath = layoutDir + ("room" + std::to_string(count++) + ".ini");
170       if (!TFileStatus(roomPath).doesExist()) break;
171     }
172     room->setPath(roomPath);
173     TSystem::touchParentDir(roomPath);
174     room->save();
175   }
176   /*- create private menubar settings if not exists -*/
177   std::string mbDstFileName = roomPath.getName() + "_menubar.xml";
178   TFilePath myMBPath        = layoutDir + mbDstFileName;
179   if (!TFileStatus(myMBPath).isReadable()) {
180     TFilePath templateRoomMBPath =
181         ToonzFolder::getTemplateRoomsDir() + mbSrcFileName;
182     if (TFileStatus(templateRoomMBPath).doesExist())
183       TSystem::copyFile(myMBPath, templateRoomMBPath);
184     else {
185       TFilePath templateFullMBPath =
186           ToonzFolder::getTemplateRoomsDir() + "menubar_template.xml";
187       if (TFileStatus(templateFullMBPath).doesExist())
188         TSystem::copyFile(myMBPath, templateFullMBPath);
189       else
190         DVGui::warning(
191             QObject::tr("Cannot open menubar settings template file. "
192                         "Re-installing Toonz will solve this problem."));
193     }
194   }
195 }
196 
197 //-----------------------------------------------------------------------------
198 
makePrivate(std::vector<Room * > & rooms)199 void makePrivate(std::vector<Room *> &rooms) {
200   for (int i = 0; i < (int)rooms.size(); i++) makePrivate(rooms[i]);
201 }
202 
203 // major version  :  7 bits
204 // minor version  :  8 bits
205 // revision number: 16 bits
get_version_code_from(std::string ver)206 int get_version_code_from(std::string ver) {
207   int version = 0;
208 
209   // major version: assume that the major version is less than 127.
210   std::string::size_type const a = ver.find('.');
211   std::string const major = (a == std::string::npos) ? ver : ver.substr(0, a);
212   version += std::stoi(major) << 24;
213   if ((a == std::string::npos) || (a + 1 == ver.length())) {
214     return version;
215   }
216 
217   // minor version: assume that the minor version is less than 255.
218   std::string::size_type const b = ver.find('.', a + 1);
219   std::string const minor        = (b == std::string::npos)
220                                 ? ver.substr(a + 1)
221                                 : ver.substr(a + 1, b - a - 1);
222   version += std::stoi(minor) << 16;
223   if ((b == std::string::npos) || (b + 1 == ver.length())) {
224     return version;
225   }
226 
227   // revision number: assume that the revision number is less than 32767.
228   version += std::stoi(ver.substr(b + 1));
229 
230   return version;
231 }
232 
233 }  // namespace
234 //=============================================================================
235 
236 //=============================================================================
237 // Room
238 //-----------------------------------------------------------------------------
239 
save()240 void Room::save() {
241   DockLayout *layout = dockLayout();
242 
243   // Now save layout state
244   DockLayout::State state        = layout->saveState();
245   std::vector<QRect> &geometries = state.first;
246 
247   QSettings settings(toQString(getPath()), QSettings::IniFormat);
248   settings.remove("");
249 
250   settings.beginGroup("room");
251 
252   int i;
253   for (i = 0; i < layout->count(); ++i) {
254     settings.beginGroup("pane_" + QString::number(i));
255     TPanel *pane = static_cast<TPanel *>(layout->itemAt(i)->widget());
256     settings.setValue("name", pane->objectName());
257     settings.setValue("geometry", geometries[i]);  // Use passed geometry
258     if (SaveLoadQSettings *persistent =
259             dynamic_cast<SaveLoadQSettings *>(pane->widget()))
260       persistent->save(settings);
261     if (pane->getViewType() != -1)
262       // If panel has different viewtypes, store current one
263       settings.setValue("viewtype", pane->getViewType());
264     if (pane->objectName() == "FlipBook") {
265       // Store flipbook's identification number
266       FlipBook *flip = static_cast<FlipBook *>(pane->widget());
267       settings.setValue("index", flip->getPoolIndex());
268     }
269     settings.endGroup();
270   }
271 
272   // Adding hierarchy string
273   settings.setValue("hierarchy", state.second);
274   settings.setValue("name", QVariant(QString(m_name)));
275 
276   settings.endGroup();
277 }
278 
279 //-----------------------------------------------------------------------------
280 
load(const TFilePath & fp)281 void Room::load(const TFilePath &fp) {
282   QSettings settings(toQString(fp), QSettings::IniFormat);
283 
284   setPath(fp);
285 
286   DockLayout *layout = dockLayout();
287 
288   settings.beginGroup("room");
289   QStringList itemsList = settings.childGroups();
290 
291   std::vector<QRect> geometries;
292   unsigned int i;
293   for (i = 0; i < itemsList.size(); i++) {
294     // Panel i
295     // NOTE: Panels have to be retrieved in the precise order they were saved.
296     // settings.beginGroup(itemsList[i]);  //NO! itemsList has lexicographical
297     // ordering!!
298     settings.beginGroup("pane_" + QString::number(i));
299 
300     TPanel *pane = 0;
301     QString paneObjectName;
302 
303     // Retrieve panel name
304     QVariant name = settings.value("name");
305     if (name.canConvert(QVariant::String)) {
306       // Allocate panel
307       paneObjectName          = name.toString();
308       std::string paneStrName = paneObjectName.toStdString();
309       pane = TPanelFactory::createPanel(this, paneObjectName);
310       if (SaveLoadQSettings *persistent =
311               dynamic_cast<SaveLoadQSettings *>(pane->widget()))
312         persistent->load(settings);
313     }
314 
315     if (!pane) {
316       // Allocate a message panel
317       MessagePanel *message = new MessagePanel(this);
318       message->setWindowTitle(name.toString());
319       message->setMessage(
320           "This panel is not supported by the currently set license!");
321 
322       pane = message;
323       pane->setPanelType(paneObjectName.toStdString());
324       pane->setObjectName(paneObjectName);
325     }
326 
327     pane->setObjectName(paneObjectName);
328 
329     // Add panel to room
330     addDockWidget(pane);
331 
332     // Store its geometry
333     geometries.push_back(settings.value("geometry").toRect());
334 
335     // Restore view type if present
336     if (settings.contains("viewtype"))
337       pane->setViewType(settings.value("viewtype").toInt());
338 
339     // Restore flipbook pool indices
340     if (paneObjectName == "FlipBook") {
341       int index = settings.value("index").toInt();
342       dynamic_cast<FlipBook *>(pane->widget())->setPoolIndex(index);
343     }
344 
345     settings.endGroup();
346   }
347 
348   // resolve resize events here to avoid unwanted minimize of floating viewer
349   qApp->processEvents();
350 
351   DockLayout::State state(geometries, settings.value("hierarchy").toString());
352 
353   layout->restoreState(state);
354 
355   setName(settings.value("name").toString());
356 }
357 
358 //=============================================================================
359 // MainWindow
360 //-----------------------------------------------------------------------------
361 
362 #if QT_VERSION >= 0x050500
MainWindow(const QString & argumentLayoutFileName,QWidget * parent,Qt::WindowFlags flags)363 MainWindow::MainWindow(const QString &argumentLayoutFileName, QWidget *parent,
364                        Qt::WindowFlags flags)
365 #else
366 MainWindow::MainWindow(const QString &argumentLayoutFileName, QWidget *parent,
367                        Qt::WFlags flags)
368 #endif
369     : QMainWindow(parent, flags)
370     , m_saveSettingsOnQuit(true)
371     , m_oldRoomIndex(0)
372     , m_layoutName("") {
373   // store a main window pointer in advance of making its contents
374   TApp::instance()->setMainWindow(this);
375 
376   m_toolsActionGroup = new QActionGroup(this);
377   m_toolsActionGroup->setExclusive(true);
378   m_currentRoomsChoice = Preferences::instance()->getCurrentRoomChoice();
379   defineActions();
380   // user defined shortcuts will be loaded here
381   CommandManager::instance()->loadShortcuts();
382   TApp::instance()->getCurrentScene()->setDirtyFlag(false);
383 
384   // La menuBar altro non è che una toolbar
385   // in cui posso inserire quanti custom widget voglio.
386   m_topBar = new TopBar(this);
387 
388   addToolBar(m_topBar);
389   addToolBarBreak(Qt::TopToolBarArea);
390 
391   m_stackedWidget = new QStackedWidget(this);
392 
393   // For the style sheet
394   m_stackedWidget->setObjectName("MainStackedWidget");
395   m_stackedWidget->setFrameStyle(QFrame::StyledPanel);
396 
397   // To give a border to the stackedWidget.
398   /*QFrame *centralWidget = new QFrame(this);
399 centralWidget->setFrameStyle(QFrame::StyledPanel);
400 centralWidget->setObjectName("centralWidget");
401 QHBoxLayout *centralWidgetLayout = new QHBoxLayout;
402 centralWidgetLayout->setMargin(3);
403 centralWidgetLayout->addWidget(m_stackedWidget);
404 centralWidget->setLayout(centralWidgetLayout);*/
405 
406   setCentralWidget(m_stackedWidget);
407 
408   // Leggo i settings
409   readSettings(argumentLayoutFileName);
410 
411   // Setto le stanze
412   QTabBar *roomTabWidget = m_topBar->getRoomTabWidget();
413   connect(m_stackedWidget, SIGNAL(currentChanged(int)),
414           SLOT(onCurrentRoomChanged(int)));
415   connect(roomTabWidget, SIGNAL(currentChanged(int)), m_stackedWidget,
416           SLOT(setCurrentIndex(int)));
417 
418   /*-- タイトルバーにScene名を表示する --*/
419   connect(TApp::instance()->getCurrentScene(), SIGNAL(nameSceneChanged()), this,
420           SLOT(changeWindowTitle()));
421   changeWindowTitle();
422 
423   // Connetto i comandi che sono in RoomTabWidget
424   connect(roomTabWidget, SIGNAL(indexSwapped(int, int)),
425           SLOT(onIndexSwapped(int, int)));
426   connect(roomTabWidget, SIGNAL(insertNewTabRoom()), SLOT(insertNewRoom()));
427   connect(roomTabWidget, SIGNAL(deleteTabRoom(int)), SLOT(deleteRoom(int)));
428   connect(roomTabWidget, SIGNAL(renameTabRoom(int, const QString)),
429           SLOT(renameRoom(int, const QString)));
430 
431   setCommandHandler("MI_Quit", this, &MainWindow::onQuit);
432   setCommandHandler("MI_Undo", this, &MainWindow::onUndo);
433   setCommandHandler("MI_Redo", this, &MainWindow::onRedo);
434   setCommandHandler("MI_NewScene", this, &MainWindow::onNewScene);
435   setCommandHandler("MI_LoadScene", this, &MainWindow::onLoadScene);
436   setCommandHandler("MI_LoadSubSceneFile", this, &MainWindow::onLoadSubScene);
437   setCommandHandler("MI_ResetRoomLayout", this, &MainWindow::resetRoomsLayout);
438   setCommandHandler(MI_AutoFillToggle, this, &MainWindow::autofillToggle);
439 
440   /*-- Animate tool + mode switching shortcuts --*/
441   setCommandHandler(MI_EditNextMode, this, &MainWindow::toggleEditNextMode);
442   setCommandHandler(MI_EditPosition, this, &MainWindow::toggleEditPosition);
443   setCommandHandler(MI_EditRotation, this, &MainWindow::toggleEditRotation);
444   setCommandHandler(MI_EditScale, this, &MainWindow::toggleEditNextScale);
445   setCommandHandler(MI_EditShear, this, &MainWindow::toggleEditNextShear);
446   setCommandHandler(MI_EditCenter, this, &MainWindow::toggleEditNextCenter);
447   setCommandHandler(MI_EditAll, this, &MainWindow::toggleEditNextAll);
448 
449   /*-- Selection tool + type switching shortcuts --*/
450   setCommandHandler(MI_SelectionNextType, this,
451                     &MainWindow::toggleSelectionNextType);
452   setCommandHandler(MI_SelectionRectangular, this,
453                     &MainWindow::toggleSelectionRectangular);
454   setCommandHandler(MI_SelectionFreehand, this,
455                     &MainWindow::toggleSelectionFreehand);
456   setCommandHandler(MI_SelectionPolyline, this,
457                     &MainWindow::toggleSelectionPolyline);
458 
459   /*-- Geometric tool + shape switching shortcuts --*/
460   setCommandHandler(MI_GeometricNextShape, this,
461                     &MainWindow::toggleGeometricNextShape);
462   setCommandHandler(MI_GeometricRectangle, this,
463                     &MainWindow::toggleGeometricRectangle);
464   setCommandHandler(MI_GeometricCircle, this,
465                     &MainWindow::toggleGeometricCircle);
466   setCommandHandler(MI_GeometricEllipse, this,
467                     &MainWindow::toggleGeometricEllipse);
468   setCommandHandler(MI_GeometricLine, this, &MainWindow::toggleGeometricLine);
469   setCommandHandler(MI_GeometricPolyline, this,
470                     &MainWindow::toggleGeometricPolyline);
471   setCommandHandler(MI_GeometricArc, this, &MainWindow::toggleGeometricArc);
472   setCommandHandler(MI_GeometricMultiArc, this,
473                     &MainWindow::toggleGeometricMultiArc);
474   setCommandHandler(MI_GeometricPolygon, this,
475                     &MainWindow::toggleGeometricPolygon);
476 
477   /*-- Type tool + style switching shortcuts --*/
478   setCommandHandler(MI_TypeNextStyle, this, &MainWindow::toggleTypeNextStyle);
479   setCommandHandler(MI_TypeOblique, this, &MainWindow::toggleTypeOblique);
480   setCommandHandler(MI_TypeRegular, this, &MainWindow::toggleTypeRegular);
481   setCommandHandler(MI_TypeBoldOblique, this,
482                     &MainWindow::toggleTypeBoldOblique);
483   setCommandHandler(MI_TypeBold, this, &MainWindow::toggleTypeBold);
484 
485   /*-- Fill tool + type/mode switching shortcuts --*/
486   setCommandHandler(MI_FillNextType, this, &MainWindow::toggleFillNextType);
487   setCommandHandler(MI_FillNormal, this, &MainWindow::toggleFillNormal);
488   setCommandHandler(MI_FillRectangular, this,
489                     &MainWindow::toggleFillRectangular);
490   setCommandHandler(MI_FillFreehand, this, &MainWindow::toggleFillFreehand);
491   setCommandHandler(MI_FillPolyline, this, &MainWindow::toggleFillPolyline);
492   setCommandHandler(MI_FillNextMode, this, &MainWindow::toggleFillNextMode);
493   setCommandHandler(MI_FillAreas, this, &MainWindow::toggleFillAreas);
494   setCommandHandler(MI_FillLines, this, &MainWindow::toggleFillLines);
495   setCommandHandler(MI_FillLinesAndAreas, this,
496                     &MainWindow::toggleFillLinesAndAreas);
497 
498   /*-- Eraser tool + type switching shortcuts --*/
499   setCommandHandler(MI_EraserNextType, this, &MainWindow::toggleEraserNextType);
500   setCommandHandler(MI_EraserNormal, this, &MainWindow::toggleEraserNormal);
501   setCommandHandler(MI_EraserRectangular, this,
502                     &MainWindow::toggleEraserRectangular);
503   setCommandHandler(MI_EraserFreehand, this, &MainWindow::toggleEraserFreehand);
504   setCommandHandler(MI_EraserPolyline, this, &MainWindow::toggleEraserPolyline);
505   setCommandHandler(MI_EraserSegment, this, &MainWindow::toggleEraserSegment);
506 
507   /*-- Tape tool + type/mode switching shortcuts --*/
508   setCommandHandler(MI_TapeNextType, this, &MainWindow::toggleTapeNextType);
509   setCommandHandler(MI_TapeNormal, this, &MainWindow::toggleTapeNormal);
510   setCommandHandler(MI_TapeRectangular, this,
511                     &MainWindow::toggleTapeRectangular);
512   setCommandHandler(MI_TapeNextMode, this, &MainWindow::toggleTapeNextMode);
513   setCommandHandler(MI_TapeEndpointToEndpoint, this,
514                     &MainWindow::toggleTapeEndpointToEndpoint);
515   setCommandHandler(MI_TapeEndpointToLine, this,
516                     &MainWindow::toggleTapeEndpointToLine);
517   setCommandHandler(MI_TapeLineToLine, this, &MainWindow::toggleTapeLineToLine);
518 
519   /*-- Style Picker tool + mode switching shortcuts --*/
520   setCommandHandler(MI_PickStyleNextMode, this,
521                     &MainWindow::togglePickStyleNextMode);
522   setCommandHandler(MI_PickStyleAreas, this, &MainWindow::togglePickStyleAreas);
523   setCommandHandler(MI_PickStyleLines, this, &MainWindow::togglePickStyleLines);
524   setCommandHandler(MI_PickStyleLinesAndAreas, this,
525                     &MainWindow::togglePickStyleLinesAndAreas);
526 
527   /*-- RGB Picker tool + type switching shortcuts --*/
528   setCommandHandler(MI_RGBPickerNextType, this,
529                     &MainWindow::toggleRGBPickerNextType);
530   setCommandHandler(MI_RGBPickerNormal, this,
531                     &MainWindow::toggleRGBPickerNormal);
532   setCommandHandler(MI_RGBPickerRectangular, this,
533                     &MainWindow::toggleRGBPickerRectangular);
534   setCommandHandler(MI_RGBPickerFreehand, this,
535                     &MainWindow::toggleRGBPickerFreehand);
536   setCommandHandler(MI_RGBPickerPolyline, this,
537                     &MainWindow::toggleRGBPickerPolyline);
538 
539   /*-- Skeleton tool + mode switching shortcuts --*/
540   setCommandHandler(MI_SkeletonNextMode, this,
541                     &MainWindow::ToggleSkeletonNextMode);
542   setCommandHandler(MI_SkeletonBuildSkeleton, this,
543                     &MainWindow::ToggleSkeletonBuildSkeleton);
544   setCommandHandler(MI_SkeletonAnimate, this,
545                     &MainWindow::ToggleSkeletonAnimate);
546   setCommandHandler(MI_SkeletonInverseKinematics, this,
547                     &MainWindow::ToggleSkeletonInverseKinematics);
548 
549   /*-- Plastic tool + mode switching shortcuts --*/
550   setCommandHandler(MI_PlasticNextMode, this,
551                     &MainWindow::TogglePlasticNextMode);
552   setCommandHandler(MI_PlasticEditMesh, this,
553                     &MainWindow::TogglePlasticEditMesh);
554   setCommandHandler(MI_PlasticPaintRigid, this,
555                     &MainWindow::TogglePlasticPaintRigid);
556   setCommandHandler(MI_PlasticBuildSkeleton, this,
557                     &MainWindow::TogglePlasticBuildSkeleton);
558   setCommandHandler(MI_PlasticAnimate, this, &MainWindow::TogglePlasticAnimate);
559 
560   setCommandHandler(MI_About, this, &MainWindow::onAbout);
561   setCommandHandler(MI_OpenOnlineManual, this, &MainWindow::onOpenOnlineManual);
562   setCommandHandler(MI_OpenWhatsNew, this, &MainWindow::onOpenWhatsNew);
563   setCommandHandler(MI_OpenCommunityForum, this,
564                     &MainWindow::onOpenCommunityForum);
565   setCommandHandler(MI_OpenReportABug, this, &MainWindow::onOpenReportABug);
566 
567   setCommandHandler(MI_MaximizePanel, this, &MainWindow::maximizePanel);
568   setCommandHandler(MI_FullScreenWindow, this, &MainWindow::fullScreenWindow);
569   setCommandHandler("MI_NewVectorLevel", this,
570                     &MainWindow::onNewVectorLevelButtonPressed);
571   setCommandHandler("MI_NewToonzRasterLevel", this,
572                     &MainWindow::onNewToonzRasterLevelButtonPressed);
573   setCommandHandler("MI_NewRasterLevel", this,
574                     &MainWindow::onNewRasterLevelButtonPressed);
575   setCommandHandler(MI_ClearCacheFolder, this, &MainWindow::clearCacheFolder);
576   // remove ffmpegCache if still exists from crashed exit
577   QString ffmpegCachePath =
578       ToonzFolder::getCacheRootFolder().getQString() + "//ffmpeg";
579   if (TSystem::doesExistFileOrLevel(TFilePath(ffmpegCachePath))) {
580     TSystem::rmDirTree(TFilePath(ffmpegCachePath));
581   }
582 }
583 
584 //-----------------------------------------------------------------------------
585 
~MainWindow()586 MainWindow::~MainWindow() {
587   TEnv::saveAllEnvVariables();
588   // cleanup ffmpeg cache
589   QString ffmpegCachePath =
590       ToonzFolder::getCacheRootFolder().getQString() + "//ffmpeg";
591   if (TSystem::doesExistFileOrLevel(TFilePath(ffmpegCachePath))) {
592     TSystem::rmDirTree(TFilePath(ffmpegCachePath));
593   }
594 }
595 
596 //-----------------------------------------------------------------------------
597 
changeWindowTitle()598 void MainWindow::changeWindowTitle() {
599   TApp *app         = TApp::instance();
600   ToonzScene *scene = app->getCurrentScene()->getScene();
601   if (!scene) return;
602 
603   TProject *project   = scene->getProject();
604   QString projectName = QString::fromStdString(project->getName().getName());
605 
606   QString sceneName = QString::fromStdWString(scene->getSceneName());
607 
608   if (sceneName.isEmpty()) sceneName = tr("Untitled");
609   if (app->getCurrentScene()->getDirtyFlag()) sceneName += QString("*");
610 
611   /*--- レイアウトファイル名を頭に表示させる ---*/
612   if (!m_layoutName.isEmpty()) sceneName.prepend(m_layoutName + " : ");
613 
614   QString name = sceneName + " [" + projectName + "] : " +
615                  QString::fromStdString(TEnv::getApplicationFullName());
616 
617   setWindowTitle(name);
618 }
619 
620 //-----------------------------------------------------------------------------
621 
changeWindowTitle(QString & str)622 void MainWindow::changeWindowTitle(QString &str) { setWindowTitle(str); }
623 
624 //-----------------------------------------------------------------------------
625 
startupFloatingPanels()626 void MainWindow::startupFloatingPanels() {
627   // Show all floating panels
628   DockLayout *currDockLayout = getCurrentRoom()->dockLayout();
629   int i;
630   for (i = 0; i < currDockLayout->count(); ++i) {
631     TPanel *currPanel = static_cast<TPanel *>(currDockLayout->widgetAt(i));
632     if (currPanel->isFloating()) currPanel->show();
633   }
634 }
635 
636 //-----------------------------------------------------------------------------
637 
getRoom(int index) const638 Room *MainWindow::getRoom(int index) const {
639   assert(index >= 0 && index < getRoomCount());
640   return dynamic_cast<Room *>(m_stackedWidget->widget(index));
641 }
642 
643 //-----------------------------------------------------------------------------
644 /*! Roomを名前から探す
645  */
getRoomByName(QString & roomName)646 Room *MainWindow::getRoomByName(QString &roomName) {
647   for (int i = 0; i < getRoomCount(); i++) {
648     Room *room = dynamic_cast<Room *>(m_stackedWidget->widget(i));
649     if (room) {
650       if (room->getName() == roomName) return room;
651     }
652   }
653   return 0;
654 }
655 
656 //-----------------------------------------------------------------------------
657 
getRoomCount() const658 int MainWindow::getRoomCount() const { return m_stackedWidget->count(); }
659 
660 //-----------------------------------------------------------------------------
661 
refreshWriteSettings()662 void MainWindow::refreshWriteSettings() { writeSettings(); }
663 
664 //-----------------------------------------------------------------------------
665 
readSettings(const QString & argumentLayoutFileName)666 void MainWindow::readSettings(const QString &argumentLayoutFileName) {
667   QTabBar *roomTabWidget = m_topBar->getRoomTabWidget();
668 
669   /*-- Pageを追加すると同時にMenubarを追加する --*/
670   StackedMenuBar *stackedMenuBar = m_topBar->getStackedMenuBar();
671 
672   std::vector<Room *> rooms;
673 
674   // leggo l'elenco dei layout
675   std::vector<TFilePath> roomPaths;
676 
677   if (readRoomList(roomPaths, argumentLayoutFileName)) {
678     if (!argumentLayoutFileName.isEmpty()) {
679       /*--
680        * タイトルバーに表示するレイアウト名を作る:_layoutがあればそこから省く。無ければ.txtのみ省く
681        * --*/
682       int pos = (argumentLayoutFileName.indexOf("_layout") == -1)
683                     ? argumentLayoutFileName.indexOf(".txt")
684                     : argumentLayoutFileName.indexOf("_layout");
685       m_layoutName = argumentLayoutFileName.left(pos);
686     }
687   }
688 
689   int i;
690   for (i = 0; i < (int)roomPaths.size(); i++) {
691     TFilePath roomPath = roomPaths[i];
692     if (TFileStatus(roomPath).doesExist()) {
693       Room *room = new Room(this);
694       room->load(roomPath);
695       m_stackedWidget->addWidget(room);
696       roomTabWidget->addTab(room->getName());
697 
698       /*- ここでMenuBarファイルをロードする -*/
699       std::string mbFileName = roomPath.getName() + "_menubar.xml";
700       stackedMenuBar->loadAndAddMenubar(ToonzFolder::getRoomsFile(mbFileName));
701 
702       // room->setDockOptions(QMainWindow::DockOptions(
703       //  (QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks) &
704       //  ~QMainWindow::AllowTabbedDocks));
705       rooms.push_back(room);
706     }
707   }
708 
709   // Read the flipbook history
710   FlipBookPool::instance()->load(ToonzFolder::getMyModuleDir() +
711                                  TFilePath("fliphistory.ini"));
712 
713   /*- レイアウト設定ファイルが見つからなかった場合、初期Roomの生成 -*/
714   // Se leggendo i settings non ho inizializzato le stanze lo faccio ora.
715   // Puo' accadere se si buttano i file di inizializzazione.
716   if (rooms.empty()) {
717     // CleanupRoom
718     Room *cleanupRoom = createCleanupRoom();
719     m_stackedWidget->addWidget(cleanupRoom);
720     rooms.push_back(cleanupRoom);
721     stackedMenuBar->createMenuBarByName(cleanupRoom->getName());
722 
723     // PltEditRoom
724     Room *pltEditRoom = createPltEditRoom();
725     m_stackedWidget->addWidget(pltEditRoom);
726     rooms.push_back(pltEditRoom);
727     stackedMenuBar->createMenuBarByName(pltEditRoom->getName());
728 
729     // InknPaintRoom
730     Room *inknPaintRoom = createInknPaintRoom();
731     m_stackedWidget->addWidget(inknPaintRoom);
732     rooms.push_back(inknPaintRoom);
733     stackedMenuBar->createMenuBarByName(inknPaintRoom->getName());
734 
735     // XsheetRoom
736     Room *xsheetRoom = createXsheetRoom();
737     m_stackedWidget->addWidget(xsheetRoom);
738     rooms.push_back(xsheetRoom);
739     stackedMenuBar->createMenuBarByName(xsheetRoom->getName());
740 
741     // BatchesRoom
742     Room *batchesRoom = createBatchesRoom();
743     m_stackedWidget->addWidget(batchesRoom);
744     rooms.push_back(batchesRoom);
745     stackedMenuBar->createMenuBarByName(batchesRoom->getName());
746 
747     // BrowserRoom
748     Room *browserRoom = createBrowserRoom();
749     m_stackedWidget->addWidget(browserRoom);
750     rooms.push_back(browserRoom);
751     stackedMenuBar->createMenuBarByName(browserRoom->getName());
752   }
753 
754   /*- If the layout files were loaded from template, then save them as private
755    * ones -*/
756   makePrivate(rooms);
757   writeRoomList(rooms);
758 
759   // Imposto la stanza corrente
760   TFilePath fp = ToonzFolder::getRoomsFile(currentRoomFileName);
761   Tifstream is(fp);
762   std::string currentRoomName;
763   is >> currentRoomName;
764   if (currentRoomName != "") {
765     int count = m_stackedWidget->count();
766     int index;
767     for (index = 0; index < count; index++)
768       if (getRoom(index)->getName().toStdString() == currentRoomName) break;
769     if (index < count) {
770       m_oldRoomIndex = index;
771       roomTabWidget->setCurrentIndex(index);
772       m_stackedWidget->setCurrentIndex(index);
773     }
774   }
775 
776   RecentFiles::instance()->loadRecentFiles();
777 }
778 
779 //-----------------------------------------------------------------------------
780 
writeSettings()781 void MainWindow::writeSettings() {
782   std::vector<Room *> rooms;
783   int i;
784 
785   // Flipbook history
786   DockLayout *currRoomLayout(getCurrentRoom()->dockLayout());
787   for (i = 0; i < currRoomLayout->count(); ++i) {
788     // Remove all floating flipbooks from current room and return them into
789     // the flipbook pool.
790     TPanel *panel = static_cast<TPanel *>(currRoomLayout->itemAt(i)->widget());
791     if (panel->isFloating() && panel->getPanelType() == "FlipBook") {
792       currRoomLayout->removeWidget(panel);
793       FlipBook *flipbook = static_cast<FlipBook *>(panel->widget());
794       FlipBookPool::instance()->push(flipbook);
795       --i;
796     }
797   }
798 
799   FlipBookPool::instance()->save();
800 
801   // Room layouts
802   for (i = 0; i < m_stackedWidget->count(); i++) {
803     Room *room = getRoom(i);
804     rooms.push_back(room);
805     room->save();
806   }
807   if (m_currentRoomsChoice == Preferences::instance()->getCurrentRoomChoice()) {
808     writeRoomList(rooms);
809   }
810 
811   // Current room settings
812   Tofstream os(ToonzFolder::getMyRoomsDir() + currentRoomFileName);
813   os << getCurrentRoom()->getName().toStdString();
814 
815   // Main window settings
816   TFilePath fp = ToonzFolder::getMyModuleDir() + TFilePath("mainwindow.ini");
817   QSettings settings(toQString(fp), QSettings::IniFormat);
818 
819   settings.setValue("MainWindowGeometry", saveGeometry());
820 }
821 
822 //-----------------------------------------------------------------------------
823 
createCleanupRoom()824 Room *MainWindow::createCleanupRoom() {
825   Room *cleanupRoom = new Room(this);
826   cleanupRoom->setName("Cleanup");
827   cleanupRoom->setObjectName("CleanupRoom");
828 
829   m_topBar->getRoomTabWidget()->addTab(tr("Cleanup"));
830 
831   DockLayout *layout = cleanupRoom->dockLayout();
832 
833   // Viewer
834   TPanel *viewer = TPanelFactory::createPanel(cleanupRoom, "ComboViewer");
835   if (viewer) {
836     cleanupRoom->addDockWidget(viewer);
837     layout->dockItem(viewer);
838     ComboViewerPanel *cvp = qobject_cast<ComboViewerPanel *>(viewer);
839     if (cvp)
840       // hide all parts
841       cvp->setVisiblePartsFlag(CVPARTS_None);
842   }
843 
844   // CleanupSettings
845   TPanel *cleanupSettingsPane =
846       TPanelFactory::createPanel(cleanupRoom, "CleanupSettings");
847   if (cleanupSettingsPane) {
848     cleanupRoom->addDockWidget(cleanupSettingsPane);
849     layout->dockItem(cleanupSettingsPane, viewer, Region::right);
850   }
851 
852   // Xsheet
853   TPanel *xsheetPane = TPanelFactory::createPanel(cleanupRoom, "Xsheet");
854   if (xsheetPane) {
855     cleanupRoom->addDockWidget(xsheetPane);
856     layout->dockItem(xsheetPane, viewer, Region::bottom);
857   }
858 
859   return cleanupRoom;
860 }
861 
862 //-----------------------------------------------------------------------------
863 
createPltEditRoom()864 Room *MainWindow::createPltEditRoom() {
865   Room *pltEditRoom = new Room(this);
866   pltEditRoom->setName("PltEdit");
867   pltEditRoom->setObjectName("PltEditRoom");
868 
869   m_topBar->getRoomTabWidget()->addTab(tr("PltEdit"));
870 
871   DockLayout *layout = pltEditRoom->dockLayout();
872 
873   // Viewer
874   TPanel *viewer = TPanelFactory::createPanel(pltEditRoom, "ComboViewer");
875   if (viewer) {
876     pltEditRoom->addDockWidget(viewer);
877     layout->dockItem(viewer);
878 
879     ComboViewerPanel *cvp = qobject_cast<ComboViewerPanel *>(viewer);
880     if (cvp) cvp->setVisiblePartsFlag(CVPARTS_TOOLBAR | CVPARTS_TOOLOPTIONS);
881   }
882 
883   // Palette
884   TPanel *palettePane = TPanelFactory::createPanel(pltEditRoom, "LevelPalette");
885   if (palettePane) {
886     pltEditRoom->addDockWidget(palettePane);
887     layout->dockItem(palettePane, viewer, Region::bottom);
888   }
889 
890   // StyleEditor
891   TPanel *styleEditorPane =
892       TPanelFactory::createPanel(pltEditRoom, "StyleEditor");
893   if (styleEditorPane) {
894     pltEditRoom->addDockWidget(styleEditorPane);
895     layout->dockItem(styleEditorPane, viewer, Region::left);
896   }
897 
898   // Xsheet
899   TPanel *xsheetPane = TPanelFactory::createPanel(pltEditRoom, "Xsheet");
900   if (xsheetPane) {
901     pltEditRoom->addDockWidget(xsheetPane);
902     layout->dockItem(xsheetPane, palettePane, Region::left);
903   }
904 
905   // Studio Palette
906   TPanel *studioPaletteViewer =
907       TPanelFactory::createPanel(pltEditRoom, "StudioPalette");
908   if (studioPaletteViewer) {
909     pltEditRoom->addDockWidget(studioPaletteViewer);
910     layout->dockItem(studioPaletteViewer, xsheetPane, Region::left);
911   }
912 
913   return pltEditRoom;
914 }
915 
916 //-----------------------------------------------------------------------------
917 
createInknPaintRoom()918 Room *MainWindow::createInknPaintRoom() {
919   Room *inknPaintRoom = new Room(this);
920   inknPaintRoom->setName("InknPaint");
921   inknPaintRoom->setObjectName("InknPaintRoom");
922 
923   m_topBar->getRoomTabWidget()->addTab(tr("InknPaint"));
924 
925   DockLayout *layout = inknPaintRoom->dockLayout();
926 
927   // Viewer
928   TPanel *viewer = TPanelFactory::createPanel(inknPaintRoom, "ComboViewer");
929   if (viewer) {
930     inknPaintRoom->addDockWidget(viewer);
931     layout->dockItem(viewer);
932   }
933 
934   // Palette
935   TPanel *palettePane =
936       TPanelFactory::createPanel(inknPaintRoom, "LevelPalette");
937   if (palettePane) {
938     inknPaintRoom->addDockWidget(palettePane);
939     layout->dockItem(palettePane, viewer, Region::bottom);
940   }
941 
942   // Filmstrip
943   TPanel *filmStripPane =
944       TPanelFactory::createPanel(inknPaintRoom, "FilmStrip");
945   if (filmStripPane) {
946     inknPaintRoom->addDockWidget(filmStripPane);
947     layout->dockItem(filmStripPane, viewer, Region::right);
948   }
949 
950   return inknPaintRoom;
951 }
952 
953 //-----------------------------------------------------------------------------
954 
createXsheetRoom()955 Room *MainWindow::createXsheetRoom() {
956   Room *xsheetRoom = new Room(this);
957   xsheetRoom->setName("Xsheet");
958   xsheetRoom->setObjectName("XsheetRoom");
959 
960   m_topBar->getRoomTabWidget()->addTab(tr("Xsheet"));
961 
962   DockLayout *layout = xsheetRoom->dockLayout();
963 
964   // Xsheet
965   TPanel *xsheetPane = TPanelFactory::createPanel(xsheetRoom, "Xsheet");
966   if (xsheetPane) {
967     xsheetRoom->addDockWidget(xsheetPane);
968     layout->dockItem(xsheetPane);
969   }
970 
971   // FunctionEditor
972   TPanel *functionEditorPane =
973       TPanelFactory::createPanel(xsheetRoom, "FunctionEditor");
974   if (functionEditorPane) {
975     xsheetRoom->addDockWidget(functionEditorPane);
976     layout->dockItem(functionEditorPane, xsheetPane, Region::right);
977   }
978 
979   return xsheetRoom;
980 }
981 
982 //-----------------------------------------------------------------------------
983 
createBatchesRoom()984 Room *MainWindow::createBatchesRoom() {
985   Room *batchesRoom = new Room(this);
986   batchesRoom->setName("Batches");
987   batchesRoom->setObjectName("BatchesRoom");
988 
989   m_topBar->getRoomTabWidget()->addTab("Batches");
990 
991   DockLayout *layout = batchesRoom->dockLayout();
992 
993   // Tasks
994   TPanel *tasksViewer = TPanelFactory::createPanel(batchesRoom, "Tasks");
995   if (tasksViewer) {
996     batchesRoom->addDockWidget(tasksViewer);
997     layout->dockItem(tasksViewer);
998   }
999 
1000   // BatchServers
1001   TPanel *batchServersViewer =
1002       TPanelFactory::createPanel(batchesRoom, "BatchServers");
1003   if (batchServersViewer) {
1004     batchesRoom->addDockWidget(batchServersViewer);
1005     layout->dockItem(batchServersViewer, tasksViewer, Region::right);
1006   }
1007 
1008   return batchesRoom;
1009 }
1010 
1011 //-----------------------------------------------------------------------------
1012 
createBrowserRoom()1013 Room *MainWindow::createBrowserRoom() {
1014   Room *browserRoom = new Room(this);
1015   browserRoom->setName("Browser");
1016   browserRoom->setObjectName("BrowserRoom");
1017 
1018   m_topBar->getRoomTabWidget()->addTab("Browser");
1019 
1020   DockLayout *layout = browserRoom->dockLayout();
1021 
1022   // Browser
1023   TPanel *browserPane = TPanelFactory::createPanel(browserRoom, "Browser");
1024   if (browserPane) {
1025     browserRoom->addDockWidget(browserPane);
1026     layout->dockItem(browserPane);
1027   }
1028 
1029   // Scene Cast
1030   TPanel *sceneCastPanel = TPanelFactory::createPanel(browserRoom, "SceneCast");
1031   if (sceneCastPanel) {
1032     browserRoom->addDockWidget(sceneCastPanel);
1033     layout->dockItem(sceneCastPanel, browserPane, Region::bottom);
1034   }
1035 
1036   return browserRoom;
1037 }
1038 
1039 //-----------------------------------------------------------------------------
1040 
getCurrentRoom() const1041 Room *MainWindow::getCurrentRoom() const {
1042   return getRoom(m_stackedWidget->currentIndex());
1043 }
1044 
1045 //-----------------------------------------------------------------------------
1046 
onUndo()1047 void MainWindow::onUndo() {
1048   bool ret = TUndoManager::manager()->undo();
1049   if (!ret) DVGui::error(QObject::tr("No more Undo operations available."));
1050 }
1051 
1052 //-----------------------------------------------------------------------------
1053 
onRedo()1054 void MainWindow::onRedo() {
1055   bool ret = TUndoManager::manager()->redo();
1056   if (!ret) DVGui::error(QObject::tr("No more Redo operations available."));
1057 }
1058 
1059 //-----------------------------------------------------------------------------
1060 
onNewScene()1061 void MainWindow::onNewScene() {
1062   IoCmd::newScene();
1063   CommandManager *cm = CommandManager::instance();
1064   cm->setChecked(MI_ShiftTrace, false);
1065   cm->setChecked(MI_EditShift, false);
1066   cm->setChecked(MI_NoShift, false);
1067   cm->setChecked(MI_VectorGuidedDrawing, false);
1068 }
1069 
1070 //-----------------------------------------------------------------------------
1071 
onLoadScene()1072 void MainWindow::onLoadScene() { IoCmd::loadScene(); }
1073 
1074 //-----------------------------------------------------------------------------
1075 
onLoadSubScene()1076 void MainWindow::onLoadSubScene() { IoCmd::loadSubScene(); }
1077 //-----------------------------------------------------------------------------
1078 
onUpgradeTabPro()1079 void MainWindow::onUpgradeTabPro() {}
1080 
1081 //-----------------------------------------------------------------------------
1082 
onAbout()1083 void MainWindow::onAbout() {
1084   QLabel *label  = new QLabel();
1085   QPixmap pixmap = QIcon(":Resources/splash.svg").pixmap(QSize(610, 344));
1086   pixmap.setDevicePixelRatio(QApplication::desktop()->devicePixelRatio());
1087   label->setPixmap(pixmap);
1088 
1089   DVGui::Dialog *dialog = new DVGui::Dialog(this, true);
1090   dialog->setWindowTitle(tr("About OpenToonz"));
1091   dialog->setTopMargin(0);
1092   dialog->addWidget(label);
1093 
1094   QString name = QString::fromStdString(TEnv::getApplicationFullName());
1095   name += " (built " __DATE__ " " __TIME__ ")";
1096   dialog->addWidget(new QLabel(name));
1097 
1098   QPushButton *button = new QPushButton(tr("Close"), dialog);
1099   button->setDefault(true);
1100   dialog->addButtonBarWidget(button);
1101   connect(button, SIGNAL(clicked()), dialog, SLOT(accept()));
1102 
1103   dialog->exec();
1104 }
1105 
1106 //-----------------------------------------------------------------------------
1107 
onOpenOnlineManual()1108 void MainWindow::onOpenOnlineManual() {
1109   QDesktopServices::openUrl(QUrl(tr("http://opentoonz.readthedocs.io")));
1110 }
1111 
1112 //-----------------------------------------------------------------------------
1113 
onOpenWhatsNew()1114 void MainWindow::onOpenWhatsNew() {
1115   QDesktopServices::openUrl(
1116       QUrl(tr("https://github.com/opentoonz/opentoonz/releases/latest")));
1117 }
1118 
1119 //-----------------------------------------------------------------------------
1120 
onOpenCommunityForum()1121 void MainWindow::onOpenCommunityForum() {
1122   QDesktopServices::openUrl(
1123       QUrl(tr("https://groups.google.com/forum/#!forum/opentoonz_en")));
1124 }
1125 
1126 //-----------------------------------------------------------------------------
1127 
onOpenReportABug()1128 void MainWindow::onOpenReportABug() {
1129   QString str = QString(
1130       tr("To report a bug, click on the button below to open a web browser "
1131          "window for OpenToonz's Issues page on https://github.com.  Click on "
1132          "the 'New issue' button and fill out the form."));
1133 
1134   std::vector<QString> buttons = {QObject::tr("Report a Bug"),
1135                                   QObject::tr("Close")};
1136   int ret = DVGui::MsgBox(DVGui::INFORMATION, str, buttons, 1);
1137   if (ret == 1)
1138     QDesktopServices::openUrl(
1139         QUrl("https://github.com/opentoonz/opentoonz/issues"));
1140 }
1141 //-----------------------------------------------------------------------------
1142 
autofillToggle()1143 void MainWindow::autofillToggle() {
1144   TPaletteHandle *h = TApp::instance()->getCurrentPalette();
1145   h->toggleAutopaint();
1146 }
1147 
resetRoomsLayout()1148 void MainWindow::resetRoomsLayout() {
1149   if (!m_saveSettingsOnQuit) return;
1150 
1151   m_saveSettingsOnQuit = false;
1152 
1153   TFilePath layoutDir = ToonzFolder::getMyRoomsDir();
1154   if (layoutDir != TFilePath()) {
1155     // TSystem::deleteFile(layoutDir);
1156     TSystem::rmDirTree(layoutDir);
1157   }
1158   /*if (layoutDir != TFilePath()) {
1159           try {
1160                   TFilePathSet fpset;
1161                   TSystem::readDirectory(fpset, layoutDir, true, false);
1162                   for (auto const& path : fpset) {
1163                           QString fn = toQString(path.withoutParentDir());
1164                           if (fn.startsWith("room") || fn.startsWith("popups"))
1165   {
1166                                   TSystem::deleteFile(path);
1167                           }
1168                   }
1169           } catch (...) {
1170           }
1171   }*/
1172 
1173   DVGui::info(
1174       QObject::tr("The rooms will be reset the next time you run Toonz."));
1175 }
1176 
maximizePanel()1177 void MainWindow::maximizePanel() {
1178   DockLayout *currDockLayout = getCurrentRoom()->dockLayout();
1179   if (currDockLayout->getMaximized() &&
1180       currDockLayout->getMaximized()->isMaximized()) {
1181     currDockLayout->getMaximized()->maximizeDock();  // release maximization
1182     return;
1183   }
1184 
1185   QPoint p            = mapFromGlobal(QCursor::pos());
1186   QWidget *currWidget = currDockLayout->containerOf(p);
1187   DockWidget *currW   = dynamic_cast<DockWidget *>(currWidget);
1188   if (currW) currW->maximizeDock();
1189 }
1190 
fullScreenWindow()1191 void MainWindow::fullScreenWindow() {
1192   if (isFullScreen())
1193     showNormal();
1194   else {
1195 #if defined(_WIN32)
1196     // http://doc.qt.io/qt-5/windows-issues.html#fullscreen-opengl-based-windows
1197     this->winId();
1198     QWindowsWindowFunctions::setHasBorderInFullScreen(this->windowHandle(),
1199                                                       true);
1200 #endif
1201     this->showFullScreen();
1202   }
1203 }
1204 
1205 //-----------------------------------------------------------------------------
1206 
onCurrentRoomChanged(int newRoomIndex)1207 void MainWindow::onCurrentRoomChanged(int newRoomIndex) {
1208   Room *oldRoom            = getRoom(m_oldRoomIndex);
1209   Room *newRoom            = getRoom(newRoomIndex);
1210   QList<TPanel *> paneList = oldRoom->findChildren<TPanel *>();
1211 
1212   // Change the parent of all the floating dockWidgets
1213   for (int i = 0; i < paneList.size(); i++) {
1214     TPanel *pane = paneList.at(i);
1215     if (pane->isFloating() && !pane->isHidden()) {
1216       QRect oldGeometry = pane->geometry();
1217       // Just setting the new parent is not enough for the new layout manager.
1218       // Must be removed from the old and added to the new.
1219       oldRoom->removeDockWidget(pane);
1220       newRoom->addDockWidget(pane);
1221       // pane->setParent(newRoom);
1222 
1223       // Some flags are lost when the parent changes.
1224       pane->setFloating(true);
1225       pane->setGeometry(oldGeometry);
1226       pane->show();
1227     }
1228   }
1229   m_oldRoomIndex = newRoomIndex;
1230   TSelection::setCurrent(0);
1231 }
1232 
1233 //-----------------------------------------------------------------------------
1234 
onIndexSwapped(int firstIndex,int secondIndex)1235 void MainWindow::onIndexSwapped(int firstIndex, int secondIndex) {
1236   assert(firstIndex >= 0 && secondIndex >= 0);
1237   Room *mainWindow = getRoom(firstIndex);
1238   m_stackedWidget->removeWidget(mainWindow);
1239   m_stackedWidget->insertWidget(secondIndex, mainWindow);
1240 }
1241 
1242 //-----------------------------------------------------------------------------
1243 
insertNewRoom()1244 void MainWindow::insertNewRoom() {
1245   Room *room = new Room(this);
1246   room->setName("room");
1247   if (m_saveSettingsOnQuit) makePrivate(room);
1248   m_stackedWidget->insertWidget(0, room);
1249 
1250   // Finally, old room index is increased by 1
1251   m_oldRoomIndex++;
1252 }
1253 
1254 //-----------------------------------------------------------------------------
1255 
deleteRoom(int index)1256 void MainWindow::deleteRoom(int index) {
1257   Room *room = getRoom(index);
1258 
1259   TFilePath fp = room->getPath();
1260   try {
1261     TSystem::deleteFile(fp);
1262   } catch (...) {
1263     DVGui::error(tr("Cannot delete") + toQString(fp));
1264     // Se non ho rimosso la stanza devo rimettere il tab!!
1265     m_topBar->getRoomTabWidget()->insertTab(index, room->getName());
1266     return;
1267   }
1268 
1269   /*- delete menubar settings file as well -*/
1270   std::string mbFileName = fp.getName() + "_menubar.xml";
1271   TFilePath mbFp         = fp.getParentDir() + mbFileName;
1272   TSystem::deleteFile(mbFp);
1273 
1274   // The old room index must be updated if index < of it
1275   if (index < m_oldRoomIndex) m_oldRoomIndex--;
1276 
1277   m_stackedWidget->removeWidget(room);
1278   delete room;
1279 }
1280 
1281 //-----------------------------------------------------------------------------
1282 
renameRoom(int index,const QString name)1283 void MainWindow::renameRoom(int index, const QString name) {
1284   Room *room = getRoom(index);
1285   room->setName(name);
1286   if (m_saveSettingsOnQuit) room->save();
1287 }
1288 
1289 //-----------------------------------------------------------------------------
1290 
onMenuCheckboxChanged()1291 void MainWindow::onMenuCheckboxChanged() {
1292   QAction *action = qobject_cast<QAction *>(sender());
1293 
1294   int isChecked = action->isChecked();
1295 
1296   CommandManager *cm = CommandManager::instance();
1297 
1298   if (cm->getAction(MI_ViewCamera) == action)
1299     ViewCameraToggleAction = isChecked;
1300   else if (cm->getAction(MI_ViewTable) == action)
1301     ViewTableToggleAction = isChecked;
1302   else if (cm->getAction(MI_ToggleEditInPlace) == action)
1303     EditInPlaceToggleAction = isChecked;
1304   else if (cm->getAction(MI_ViewBBox) == action)
1305     ViewBBoxToggleAction = isChecked;
1306   else if (cm->getAction(MI_FieldGuide) == action)
1307     FieldGuideToggleAction = isChecked;
1308   else if (cm->getAction(MI_RasterizePli) == action) {
1309     if (!QGLPixelBuffer::hasOpenGLPbuffers()) isChecked = 0;
1310     RasterizePliToggleAction = isChecked;
1311   } else if (cm->getAction(MI_SafeArea) == action)
1312     SafeAreaToggleAction = isChecked;
1313   else if (cm->getAction(MI_ViewColorcard) == action)
1314     ViewColorcardToggleAction = isChecked;
1315   else if (cm->getAction(MI_ViewGuide) == action)
1316     ViewGuideToggleAction = isChecked;
1317   else if (cm->getAction(MI_ViewRuler) == action)
1318     ViewRulerToggleAction = isChecked;
1319   else if (cm->getAction(MI_TCheck) == action)
1320     TCheckToggleAction = isChecked;
1321   else if (cm->getAction(MI_DockingCheck) == action)
1322     DockingCheckToggleAction = isChecked;
1323   else if (cm->getAction(MI_ICheck) == action)
1324     ICheckToggleAction = isChecked;
1325   else if (cm->getAction(MI_Ink1Check) == action)
1326     Ink1CheckToggleAction = isChecked;
1327   else if (cm->getAction(MI_PCheck) == action)
1328     PCheckToggleAction = isChecked;
1329   else if (cm->getAction(MI_BCheck) == action)
1330     BCheckToggleAction = isChecked;
1331   else if (cm->getAction(MI_GCheck) == action)
1332     GCheckToggleAction = isChecked;
1333   else if (cm->getAction(MI_ACheck) == action)
1334     ACheckToggleAction = isChecked;
1335   else if (cm->getAction(MI_IOnly) == action)
1336     IOnlyToggleAction = isChecked;
1337   else if (cm->getAction(MI_Link) == action)
1338     LinkToggleAction = isChecked;
1339   else if (cm->getAction(MI_ShiftTrace) == action)
1340     ShiftTraceToggleAction = isChecked;
1341   else if (cm->getAction(MI_EditShift) == action)
1342     EditShiftToggleAction = isChecked;
1343   else if (cm->getAction(MI_NoShift) == action)
1344     NoShiftToggleAction = isChecked;
1345   else if (cm->getAction(MI_TouchGestureControl) == action)
1346     TouchGestureControl = isChecked;
1347 }
1348 
1349 //-----------------------------------------------------------------------------
1350 
showEvent(QShowEvent * event)1351 void MainWindow::showEvent(QShowEvent *event) {
1352   getCurrentRoom()->layout()->setEnabled(true);  // See main function in
1353                                                  // main.cpp
1354   if (Preferences::instance()->isStartupPopupEnabled() &&
1355       !m_startupPopupShown) {
1356     StartupPopup *startupPopup = new StartupPopup();
1357     startupPopup->show();
1358     m_startupPopupShown = true;
1359   }
1360 }
1361 extern const char *applicationName;
1362 extern const char *applicationVersion;
1363 //-----------------------------------------------------------------------------
checkForUpdates()1364 void MainWindow::checkForUpdates() {
1365   // Since there is only a single version of Opentoonz, we can do a simple check
1366   // against a string
1367   QString updateUrl("http://opentoonz.github.io/opentoonz-version.txt");
1368 
1369   m_updateChecker = new UpdateChecker(updateUrl);
1370   connect(m_updateChecker, SIGNAL(done(bool)), this,
1371           SLOT(onUpdateCheckerDone(bool)));
1372 }
1373 //-----------------------------------------------------------------------------
1374 
onUpdateCheckerDone(bool error)1375 void MainWindow::onUpdateCheckerDone(bool error) {
1376   if (error) {
1377     // Get the last update date
1378     return;
1379   }
1380 
1381   int const software_version =
1382       get_version_code_from(TEnv::getApplicationVersion());
1383   int const latest_version =
1384       get_version_code_from(m_updateChecker->getLatestVersion().toStdString());
1385   if (software_version < latest_version) {
1386     QStringList buttons;
1387     buttons.push_back(QObject::tr("Visit Web Site"));
1388     buttons.push_back(QObject::tr("Cancel"));
1389     DVGui::MessageAndCheckboxDialog *dialog = DVGui::createMsgandCheckbox(
1390         DVGui::INFORMATION,
1391         QObject::tr("An update is available for this software.\nVisit the Web "
1392                     "site for more information."),
1393         QObject::tr("Check for the latest version on launch."), buttons, 0,
1394         Qt::Checked);
1395     int ret = dialog->exec();
1396     if (dialog->getChecked() == Qt::Unchecked)
1397       Preferences::instance()->setValue(latestVersionCheckEnabled, false);
1398     dialog->deleteLater();
1399     if (ret == 1) {
1400       // Write the new last date to file
1401       QDesktopServices::openUrl(QObject::tr("https://opentoonz.github.io/e/"));
1402     }
1403   }
1404 
1405   disconnect(m_updateChecker);
1406   m_updateChecker->deleteLater();
1407 }
1408 //-----------------------------------------------------------------------------
1409 
closeEvent(QCloseEvent * event)1410 void MainWindow::closeEvent(QCloseEvent *event) {
1411   // il riferimento alla variabile booleana doExit viene passato a tutti gli
1412   // slot che catturano l'emissione
1413   // del segnale. Impostando a false tale variabile, l'applicazione non viene
1414   // chiusa!
1415   bool doExit = true;
1416   emit exit(doExit);
1417   if (!doExit) {
1418     event->ignore();
1419     return;
1420   }
1421 
1422   if (!IoCmd::saveSceneIfNeeded(QApplication::tr("Quit"))) {
1423     event->ignore();
1424     return;
1425   }
1426 
1427   // sto facendo quit. interrompo (il prima possibile) le threads
1428   IconGenerator::instance()->clearRequests();
1429 
1430   if (m_saveSettingsOnQuit) writeSettings();
1431 
1432   // svuoto la directory di output
1433   TFilePath outputsDir = TEnv::getStuffDir() + "outputs";
1434   TFilePathSet fps;
1435   if (TFileStatus(outputsDir).isDirectory()) {
1436     TSystem::readDirectory(fps, outputsDir);
1437     TFilePathSet::iterator fpsIt;
1438     for (fpsIt = fps.begin(); fpsIt != fps.end(); ++fpsIt) {
1439       TFilePath fp = *fpsIt;
1440       if (TSystem::doesExistFileOrLevel(fp)) {
1441         try {
1442           TSystem::removeFileOrLevel(fp);
1443         } catch (...) {
1444         }
1445       }
1446     }
1447   }
1448 
1449   TImageCache::instance()->clear(true);
1450 
1451   event->accept();
1452   TThread::shutdown();
1453   qApp->quit();
1454 }
1455 
1456 //-----------------------------------------------------------------------------
1457 
createAction(const char * id,const char * name,const QString & defaultShortcut,CommandType type,const char * iconSVGName)1458 QAction *MainWindow::createAction(const char *id, const char *name,
1459                                   const QString &defaultShortcut,
1460                                   CommandType type, const char *iconSVGName) {
1461   QAction *action = new DVAction(tr(name), this);
1462 
1463 #if !defined(_WIN32)
1464   bool visible = Preferences::instance()->getBoolValue(showIconsInMenu);
1465   action->setIconVisibleInMenu(visible);
1466 #endif
1467 
1468   // In Qt5.15.2 - Windows, QMenu stylesheet has alignment issue when one item
1469   // has icon and another has not one. (See
1470   // https://bugreports.qt.io/browse/QTBUG-90242 for details.) To avoid the
1471   // problem here we attach the temporary icons for every actions which have no
1472   // icons. The temporary icon is visible in 20x20 pixel size (for command bar)
1473   // with first 2 upper-case-letters in the command id, and is transparent in
1474   // 16x16 pixel size so that it is hidden in menu bar. I put the transparent
1475   // icon instead of using setIconVisibleInMenu(false) to avoid another
1476   // alignment issue that the shortcut text overlaps command name.
1477   if (!iconSVGName || !*iconSVGName) {
1478 #ifdef _WIN32
1479     action->setIcon(createTemporaryIconFromName(name));
1480 #endif
1481     // do nothing for other platforms
1482   } else
1483     action->setIcon(createQIcon(iconSVGName, false, true));
1484   addAction(action);
1485 #ifdef MACOSX
1486   // To prevent the wrong menu items (due to MacOS menu naming conventions),
1487   // from
1488   // taking Preferences, Quit, or About roles (sometimes happens unexpectedly in
1489   // translations) - all menu items should have "NoRole"
1490   //  except for Preferences, Quit, and About
1491   if (strcmp(id, MI_Preferences) == 0)
1492     action->setMenuRole(QAction::PreferencesRole);
1493   else if (strcmp(id, MI_Quit) == 0)
1494     action->setMenuRole(QAction::QuitRole);
1495   else if (strcmp(id, MI_About) == 0)
1496     action->setMenuRole(QAction::AboutRole);
1497   else
1498     action->setMenuRole(QAction::NoRole);
1499 #endif
1500   CommandManager::instance()->define(id, type, defaultShortcut.toStdString(),
1501                                      action);
1502   return action;
1503 }
1504 
1505 //-----------------------------------------------------------------------------
1506 
createRightClickMenuAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1507 QAction *MainWindow::createRightClickMenuAction(const char *id,
1508                                                 const char *name,
1509                                                 const QString &defaultShortcut,
1510                                                 const char *iconSVGName) {
1511   return createAction(id, name, defaultShortcut, RightClickMenuCommandType,
1512                       iconSVGName);
1513 }
1514 
1515 //-----------------------------------------------------------------------------
1516 
createMenuFileAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1517 QAction *MainWindow::createMenuFileAction(const char *id, const char *name,
1518                                           const QString &defaultShortcut,
1519                                           const char *iconSVGName) {
1520   return createAction(id, name, defaultShortcut, MenuFileCommandType,
1521                       iconSVGName);
1522 }
1523 
1524 //-----------------------------------------------------------------------------
1525 
createMenuEditAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1526 QAction *MainWindow::createMenuEditAction(const char *id, const char *name,
1527                                           const QString &defaultShortcut,
1528                                           const char *iconSVGName) {
1529   return createAction(id, name, defaultShortcut, MenuEditCommandType,
1530                       iconSVGName);
1531 }
1532 
1533 //-----------------------------------------------------------------------------
1534 
createMenuScanCleanupAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1535 QAction *MainWindow::createMenuScanCleanupAction(const char *id,
1536                                                  const char *name,
1537                                                  const QString &defaultShortcut,
1538                                                  const char *iconSVGName) {
1539   return createAction(id, name, defaultShortcut, MenuScanCleanupCommandType,
1540                       iconSVGName);
1541 }
1542 
1543 //-----------------------------------------------------------------------------
1544 
createMenuLevelAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1545 QAction *MainWindow::createMenuLevelAction(const char *id, const char *name,
1546                                            const QString &defaultShortcut,
1547                                            const char *iconSVGName) {
1548   return createAction(id, name, defaultShortcut, MenuLevelCommandType,
1549                       iconSVGName);
1550 }
1551 
1552 //-----------------------------------------------------------------------------
1553 
createMenuXsheetAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1554 QAction *MainWindow::createMenuXsheetAction(const char *id, const char *name,
1555                                             const QString &defaultShortcut,
1556                                             const char *iconSVGName) {
1557   return createAction(id, name, defaultShortcut, MenuXsheetCommandType,
1558                       iconSVGName);
1559 }
1560 
1561 //-----------------------------------------------------------------------------
1562 
createMenuCellsAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1563 QAction *MainWindow::createMenuCellsAction(const char *id, const char *name,
1564                                            const QString &defaultShortcut,
1565                                            const char *iconSVGName) {
1566   return createAction(id, name, defaultShortcut, MenuCellsCommandType,
1567                       iconSVGName);
1568 }
1569 
1570 //-----------------------------------------------------------------------------
1571 
createMenuViewAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1572 QAction *MainWindow::createMenuViewAction(const char *id, const char *name,
1573                                           const QString &defaultShortcut,
1574                                           const char *iconSVGName) {
1575   return createAction(id, name, defaultShortcut, MenuViewCommandType,
1576                       iconSVGName);
1577 }
1578 
1579 //-----------------------------------------------------------------------------
1580 
createMenuWindowsAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1581 QAction *MainWindow::createMenuWindowsAction(const char *id, const char *name,
1582                                              const QString &defaultShortcut,
1583                                              const char *iconSVGName) {
1584   return createAction(id, name, defaultShortcut, MenuWindowsCommandType,
1585                       iconSVGName);
1586 }
1587 
1588 //-----------------------------------------------------------------------------
1589 
createMenuPlayAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1590 QAction *MainWindow::createMenuPlayAction(const char *id, const char *name,
1591                                           const QString &defaultShortcut,
1592                                           const char *iconSVGName) {
1593   return createAction(id, name, defaultShortcut, MenuPlayCommandType,
1594                       iconSVGName);
1595 }
1596 
1597 //-----------------------------------------------------------------------------
1598 
createMenuRenderAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1599 QAction *MainWindow::createMenuRenderAction(const char *id, const char *name,
1600                                             const QString &defaultShortcut,
1601                                             const char *iconSVGName) {
1602   return createAction(id, name, defaultShortcut, MenuRenderCommandType,
1603                       iconSVGName);
1604 }
1605 
1606 //-----------------------------------------------------------------------------
1607 
createMenuHelpAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1608 QAction *MainWindow::createMenuHelpAction(const char *id, const char *name,
1609                                           const QString &defaultShortcut,
1610                                           const char *iconSVGName) {
1611   return createAction(id, name, defaultShortcut, MenuHelpCommandType,
1612                       iconSVGName);
1613 }
1614 
1615 //-----------------------------------------------------------------------------
1616 
createRGBAAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1617 QAction *MainWindow::createRGBAAction(const char *id, const char *name,
1618                                       const QString &defaultShortcut,
1619                                       const char *iconSVGName) {
1620   return createAction(id, name, defaultShortcut, RGBACommandType, iconSVGName);
1621 }
1622 
1623 //-----------------------------------------------------------------------------
1624 
createFillAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1625 QAction *MainWindow::createFillAction(const char *id, const char *name,
1626                                       const QString &defaultShortcut,
1627                                       const char *iconSVGName) {
1628   return createAction(id, name, defaultShortcut, FillCommandType, iconSVGName);
1629 }
1630 //-----------------------------------------------------------------------------
1631 
createMenuAction(const char * id,const char * name,QList<QString> list)1632 QAction *MainWindow::createMenuAction(const char *id, const char *name,
1633                                       QList<QString> list) {
1634   QMenu *menu     = new DVMenuAction(tr(name), this, list);
1635   QAction *action = menu->menuAction();
1636   CommandManager::instance()->define(id, MenuCommandType, "", action);
1637   return action;
1638 }
1639 
1640 //-----------------------------------------------------------------------------
1641 
createViewerAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1642 QAction *MainWindow::createViewerAction(const char *id, const char *name,
1643                                         const QString &defaultShortcut,
1644                                         const char *iconSVGName) {
1645   return createAction(id, name, defaultShortcut, ZoomCommandType, iconSVGName);
1646 }
1647 
1648 //-----------------------------------------------------------------------------
1649 
createVisualizationButtonAction(const char * id,const char * name,const char * iconSVGName)1650 QAction *MainWindow::createVisualizationButtonAction(const char *id,
1651                                                      const char *name,
1652                                                      const char *iconSVGName) {
1653   return createAction(id, name, "", VisualizationButtonCommandType,
1654                       iconSVGName);
1655 }
1656 
1657 //-----------------------------------------------------------------------------
1658 
createMiscAction(const char * id,const char * name,const char * defaultShortcut)1659 QAction *MainWindow::createMiscAction(const char *id, const char *name,
1660                                       const char *defaultShortcut) {
1661   QAction *action = new DVAction(tr(name), this);
1662   CommandManager::instance()->define(id, MiscCommandType, defaultShortcut,
1663                                      action);
1664   return action;
1665 }
1666 
1667 //-----------------------------------------------------------------------------
1668 
createToolOptionsAction(const char * id,const char * name,const QString & defaultShortcut)1669 QAction *MainWindow::createToolOptionsAction(const char *id, const char *name,
1670                                              const QString &defaultShortcut) {
1671   QAction *action = new DVAction(tr(name), this);
1672   addAction(action);
1673   CommandManager::instance()->define(id, ToolModifierCommandType,
1674                                      defaultShortcut.toStdString(), action);
1675   return action;
1676 }
1677 
1678 //-----------------------------------------------------------------------------
1679 
createStopMotionAction(const char * id,const char * name,const QString & defaultShortcut,const char * iconSVGName)1680 QAction *MainWindow::createStopMotionAction(const char *id, const char *name,
1681                                             const QString &defaultShortcut,
1682                                             const char *iconSVGName) {
1683   return createAction(id, name, defaultShortcut, StopMotionCommandType,
1684                       iconSVGName);
1685 }
1686 
1687 //-----------------------------------------------------------------------------
1688 
createToggle(const char * id,const char * name,const QString & defaultShortcut,bool startStatus,CommandType type,const char * iconSVGName)1689 QAction *MainWindow::createToggle(const char *id, const char *name,
1690                                   const QString &defaultShortcut,
1691                                   bool startStatus, CommandType type,
1692                                   const char *iconSVGName) {
1693   QAction *action = createAction(id, name, defaultShortcut, type, iconSVGName);
1694   // Remove if the icon is not set. Checkbox will be drawn by style sheet.
1695   if (!iconSVGName || !*iconSVGName) action->setIcon(QIcon());
1696   action->setCheckable(true);
1697   if (startStatus == true) action->trigger();
1698   bool ret =
1699       connect(action, SIGNAL(changed()), this, SLOT(onMenuCheckboxChanged()));
1700   assert(ret);
1701   return action;
1702 }
1703 
1704 //-----------------------------------------------------------------------------
1705 
createToolAction(const char * id,const char * iconName,const char * name,const QString & defaultShortcut)1706 QAction *MainWindow::createToolAction(const char *id, const char *iconName,
1707                                       const char *name,
1708                                       const QString &defaultShortcut) {
1709   QIcon icon      = createQIcon(iconName);
1710   QAction *action = new DVAction(icon, tr(name), this);
1711   action->setCheckable(true);
1712   action->setActionGroup(m_toolsActionGroup);
1713 
1714   // When the viewer is maximized (not fullscreen) the toolbar is hided and the
1715   // action are disabled,
1716   // so the tool shortcuts don't work.
1717   // Adding tool actions to the main window solve this problem!
1718   addAction(action);
1719 
1720   CommandManager::instance()->define(id, ToolCommandType,
1721                                      defaultShortcut.toStdString(), action);
1722   return action;
1723 }
1724 
1725 //-----------------------------------------------------------------------------
1726 
defineActions()1727 void MainWindow::defineActions() {
1728   QAction *menuAct;
1729 
1730   // Menu - File
1731 
1732   createMenuFileAction(MI_NewScene, QT_TR_NOOP("&New Scene"), "Ctrl+N",
1733                        "new_scene");
1734   createMenuFileAction(MI_LoadScene, QT_TR_NOOP("&Load Scene..."), "Ctrl+L",
1735                        "load_scene");
1736   createMenuFileAction(MI_SaveScene, QT_TR_NOOP("&Save Scene"), "Ctrl+Shift+S",
1737                        "save_scene");
1738   createMenuFileAction(MI_SaveSceneAs, QT_TR_NOOP("&Save Scene As..."), "",
1739                        "save_scene_as");
1740   createMenuFileAction(MI_SaveAll, QT_TR_NOOP("&Save All"), "Ctrl+S",
1741                        "saveall");
1742   menuAct = createMenuFileAction(MI_RevertScene, QT_TR_NOOP("&Revert Scene"),
1743                                  "", "revert_scene");
1744   menuAct->setEnabled(false);
1745   QList<QString> files;
1746   createMenuFileAction(MI_LoadFolder, QT_TR_NOOP("&Load Folder..."), "",
1747                        "load_folder");
1748   createMenuFileAction(MI_LoadSubSceneFile,
1749                        QT_TR_NOOP("&Load As Sub-xsheet..."), "",
1750                        "load_as_sub_xsheet");
1751   createMenuAction(MI_OpenRecentScene, QT_TR_NOOP("&Open Recent Scene File"),
1752                    files);
1753   createMenuAction(MI_OpenRecentLevel, QT_TR_NOOP("&Open Recent Level File"),
1754                    files);
1755   createMenuFileAction(MI_ClearRecentScene,
1756                        QT_TR_NOOP("&Clear Recent Scene File List"), "");
1757   createMenuFileAction(MI_ClearRecentLevel,
1758                        QT_TR_NOOP("&Clear Recent level File List"), "");
1759   createMenuFileAction(MI_ConvertFileWithInput, QT_TR_NOOP("&Convert File..."),
1760                        "", "convert");
1761   createMenuFileAction(MI_LoadColorModel, QT_TR_NOOP("&Load Color Model..."),
1762                        "", "load_colormodel");
1763   createMenuFileAction(MI_ImportMagpieFile,
1764                        QT_TR_NOOP("&Import Toonz Lip Sync File..."), "",
1765                        "dialogue_import");
1766   createMenuFileAction(MI_NewProject, QT_TR_NOOP("&New Project..."), "");
1767   createMenuFileAction(MI_ProjectSettings, QT_TR_NOOP("&Project Settings..."),
1768                        "");
1769   createMenuFileAction(MI_SaveDefaultSettings,
1770                        QT_TR_NOOP("&Save Default Settings"), "");
1771   createMenuFileAction(MI_SoundTrack, QT_TR_NOOP("&Export Soundtrack"), "");
1772   createMenuFileAction(MI_Preferences, QT_TR_NOOP("&Preferences..."), "Ctrl+U",
1773                        "gear");
1774   createMenuFileAction(MI_ShortcutPopup, QT_TR_NOOP("&Configure Shortcuts..."),
1775                        "", "shortcuts");
1776   createMenuFileAction(MI_PrintXsheet, QT_TR_NOOP("&Print Xsheet"), "",
1777                        "printer");
1778   createMenuFileAction(
1779       MI_ExportXDTS,
1780       QT_TRANSLATE_NOOP("MainWindow",
1781                         "Export Exchange Digital Time Sheet (XDTS)"),
1782       "");
1783   createMenuFileAction("MI_RunScript", QT_TR_NOOP("Run Script..."), "",
1784                        "run_script");
1785   createMenuFileAction("MI_OpenScriptConsole",
1786                        QT_TR_NOOP("Open Script Console..."), "", "console");
1787   createMenuFileAction(MI_Print, QT_TR_NOOP("&Print Current Frame..."),
1788                        "Ctrl+P", "printer");
1789   createMenuFileAction(MI_Quit, QT_TR_NOOP("&Quit"), "Ctrl+Q", "quit");
1790 #ifndef NDEBUG
1791   createMenuFileAction("MI_ReloadStyle", QT_TR_NOOP("Reload qss"), "");
1792 #endif
1793   createMenuAction(MI_LoadRecentImage, QT_TR_NOOP("&Load Recent Image Files"),
1794                    files);
1795   createMenuFileAction(MI_ClearRecentImage,
1796                        QT_TR_NOOP("&Clear Recent Flipbook Image List"), "");
1797   createMenuFileAction(MI_ClearCacheFolder, QT_TR_NOOP("&Clear Cache Folder"),
1798                        "", "clear_cache");
1799 
1800   // Menu - Edit
1801 
1802   createMenuEditAction(MI_SelectAll, QT_TR_NOOP("&Select All"), "Ctrl+A",
1803                        "select_all");
1804   createMenuEditAction(MI_InvertSelection, QT_TR_NOOP("&Invert Selection"), "",
1805                        "invert_selection");
1806   createMenuEditAction(MI_Undo, QT_TR_NOOP("&Undo"), "Ctrl+Z", "undo");
1807   createMenuEditAction(MI_Redo, QT_TR_NOOP("&Redo"), "Ctrl+Y", "redo");
1808   createMenuEditAction(MI_Cut, QT_TR_NOOP("&Cut"), "Ctrl+X", "cut");
1809   createMenuEditAction(MI_Copy, QT_TR_NOOP("&Copy"), "Ctrl+C", "content_copy");
1810   createMenuEditAction(MI_Paste, QT_TR_NOOP("&Paste Insert"), "Ctrl+V",
1811                        "paste");
1812   createMenuEditAction(MI_PasteAbove, QT_TR_NOOP("&Paste Insert Above/After"),
1813                        "Ctrl+Shift+V", "paste_above_after");
1814   createMenuEditAction(MI_PasteDuplicate, QT_TR_NOOP("&Paste as a Copy"), "",
1815                        "paste_duplicate");
1816   createMenuEditAction(MI_PasteInto, QT_TR_NOOP("&Paste Into"), "",
1817                        "paste_into");
1818   createMenuEditAction(MI_Clear, QT_TR_NOOP("&Delete"), "Del", "delete");
1819   createMenuEditAction(MI_Insert, QT_TR_NOOP("&Insert"), "Ins", "insert");
1820   createMenuEditAction(MI_InsertAbove, QT_TR_NOOP("&Insert Above/After"),
1821                        "Shift+Ins", "insert_above_after");
1822   createMenuEditAction(MI_Group, QT_TR_NOOP("&Group"), "Ctrl+G", "group");
1823   createMenuEditAction(MI_Ungroup, QT_TR_NOOP("&Ungroup"), "Ctrl+Shift+G",
1824                        "ungroup");
1825   createMenuEditAction(MI_EnterGroup, QT_TR_NOOP("&Enter Group"), "",
1826                        "enter_group");
1827   createMenuEditAction(MI_ExitGroup, QT_TR_NOOP("&Exit Group"), "",
1828                        "leave_group");
1829   createMenuEditAction(MI_SendBack, QT_TR_NOOP("&Move to Back"), "Ctrl+[",
1830                        "move_to_back");
1831   createMenuEditAction(MI_SendBackward, QT_TR_NOOP("&Move Back One"), "[",
1832                        "move_back_one");
1833   createMenuEditAction(MI_BringForward, QT_TR_NOOP("&Move Forward One"), "]",
1834                        "move_forward_one");
1835   createMenuEditAction(MI_BringToFront, QT_TR_NOOP("&Move to Front"), "Ctrl+]",
1836                        "move_to_front");
1837 
1838   // Menu - Scan & Cleanup
1839 
1840   createMenuScanCleanupAction(
1841       MI_DefineScanner, QT_TR_NOOP("&Define Scanner..."), "", "define_scanner");
1842   createMenuScanCleanupAction(MI_ScanSettings, QT_TR_NOOP("&Scan Settings..."),
1843                               "", "scanner_settings");
1844   createMenuScanCleanupAction(MI_Scan, QT_TR_NOOP("&Scan"), "", "scanner");
1845   createMenuScanCleanupAction(MI_Autocenter, QT_TR_NOOP("&Autocenter..."), "",
1846                               "autocenter");
1847   menuAct = createToggle(MI_SetScanCropbox, QT_TR_NOOP("&Set Cropbox"), "", 0,
1848                          MenuScanCleanupCommandType, "set_cropbox");
1849   SetScanCropboxCheck::instance()->setToggle(menuAct);
1850   QString scannerType = QSettings().value("CurrentScannerType").toString();
1851   if (scannerType == "TWAIN") menuAct->setDisabled(true);
1852   menuAct = createMenuScanCleanupAction(
1853       MI_ResetScanCropbox, QT_TR_NOOP("&Reset Cropbox"), "", "reset_cropbox");
1854   if (scannerType == "TWAIN") menuAct->setDisabled(true);
1855   createMenuScanCleanupAction(MI_CleanupSettings,
1856                               QT_TR_NOOP("&Cleanup Settings..."), "",
1857                               "cleanup_settings");
1858   menuAct = createToggle(MI_CleanupPreview, QT_TR_NOOP("&Preview Cleanup"), "",
1859                          0, MenuScanCleanupCommandType, "cleanup_preview");
1860   CleanupPreviewCheck::instance()->setToggle(menuAct);
1861   menuAct = createToggle(MI_CameraTest, QT_TR_NOOP("&Camera Test"), "", 0,
1862                          MenuScanCleanupCommandType, "camera_test");
1863   CameraTestCheck::instance()->setToggle(menuAct);
1864   createToggle(MI_OpacityCheck, QT_TR_NOOP("&Opacity Check"), "Alt+1", false,
1865                MenuScanCleanupCommandType, "opacity_check");
1866   createMenuScanCleanupAction(MI_Cleanup, QT_TR_NOOP("&Cleanup"), "",
1867                               "cleanup");
1868   createMenuScanCleanupAction(MI_PencilTest, QT_TR_NOOP("&Camera Capture..."),
1869                               "", "camera_capture");
1870 
1871   // Menu - Level
1872 
1873   createMenuLevelAction(MI_NewLevel, QT_TR_NOOP("&New Level..."), "Alt+N",
1874                         "new_document");
1875   createMenuLevelAction(MI_NewVectorLevel, QT_TR_NOOP("&New Vector Level"), "",
1876                         "new_vector_level");
1877   createMenuLevelAction(MI_NewToonzRasterLevel,
1878                         QT_TR_NOOP("&New Toonz Raster Level"), "",
1879                         "new_toonz_raster_level");
1880   createMenuLevelAction(MI_NewRasterLevel, QT_TR_NOOP("&New Raster Level"), "",
1881                         "new_raster_level");
1882   createMenuLevelAction(MI_LoadLevel, QT_TR_NOOP("&Load Level..."), "",
1883                         "load_level");
1884   createMenuLevelAction(MI_SaveLevel, QT_TR_NOOP("&Save Level"), "",
1885                         "save_level");
1886   createMenuLevelAction(MI_SaveAllLevels, QT_TR_NOOP("&Save All Levels"), "",
1887                         "save_all_levels");
1888   createMenuLevelAction(MI_SaveLevelAs, QT_TR_NOOP("&Save Level As..."), "",
1889                         "save_level_as");
1890   createMenuLevelAction(MI_ExportLevel, QT_TR_NOOP("&Export Level..."), "",
1891                         "export_level");
1892   createMenuLevelAction(MI_RemoveEndpoints,
1893                         QT_TR_NOOP("&Remove Vector Overflow"), "",
1894                         "remove_vector_overflow");
1895   createMenuLevelAction(MI_AddFrames, QT_TR_NOOP("&Add Frames..."), "",
1896                         "add_cells");
1897   createMenuLevelAction(MI_Renumber, QT_TR_NOOP("&Renumber..."), "",
1898                         "renumber");
1899   createMenuLevelAction(MI_ReplaceLevel, QT_TR_NOOP("&Replace Level..."), "",
1900                         "replace_level");
1901   createMenuLevelAction(MI_RevertToCleanedUp,
1902                         QT_TR_NOOP("&Revert to Cleaned Up"), "",
1903                         "revert_level_to_cleanup");
1904   createMenuLevelAction(MI_RevertToLastSaved, QT_TR_NOOP("&Reload"), "",
1905                         "reload_level");
1906   createMenuLevelAction(MI_ExposeResource, QT_TR_NOOP("&Expose in Xsheet"), "");
1907   createMenuLevelAction(MI_EditLevel, QT_TR_NOOP("&Display in Level Strip"),
1908                         "");
1909   createMenuLevelAction(MI_LevelSettings, QT_TR_NOOP("&Level Settings..."), "",
1910                         "level_settings");
1911   createMenuLevelAction(MI_AdjustLevels, QT_TR_NOOP("Adjust Levels..."), "",
1912                         "histograms");
1913   createMenuLevelAction(MI_AdjustThickness, QT_TR_NOOP("Adjust Thickness..."),
1914                         "", "thickness");
1915   createMenuLevelAction(MI_Antialias, QT_TR_NOOP("&Antialias..."), "",
1916                         "antialias");
1917   createMenuLevelAction(MI_Binarize, QT_TR_NOOP("&Binarize..."), "",
1918                         "binarize");
1919   createMenuLevelAction(MI_BrightnessAndContrast,
1920                         QT_TR_NOOP("&Brightness and Contrast..."), "",
1921                         "brightness_contrast");
1922   createMenuLevelAction(MI_LinesFade, QT_TR_NOOP("&Color Fade..."), "",
1923                         "colorfade");
1924   menuAct = createMenuLevelAction(MI_CanvasSize, QT_TR_NOOP("&Canvas Size..."),
1925                                   "", "resize");
1926   menuAct->setDisabled(true);
1927   createMenuLevelAction(MI_FileInfo, QT_TR_NOOP("&Info..."), "", "level_info");
1928   createMenuLevelAction(MI_RemoveUnused,
1929                         QT_TR_NOOP("&Remove All Unused Levels"), "",
1930                         "remove_unused_levels");
1931   createMenuLevelAction(MI_ReplaceParentDirectory,
1932                         QT_TR_NOOP("&Replace Parent Directory..."), "",
1933                         "replace_parent_directory");
1934   createMenuLevelAction(MI_NewNoteLevel, QT_TR_NOOP("New Note Level"), "",
1935                         "new_note_level");
1936   createMenuLevelAction(MI_ConvertToVectors,
1937                         QT_TR_NOOP("Convert to Vectors..."), "");
1938   createMenuLevelAction(MI_ConvertToToonzRaster,
1939                         QT_TR_NOOP("Vectors to Toonz Raster"), "");
1940   createMenuLevelAction(
1941       MI_ConvertVectorToVector,
1942       QT_TRANSLATE_NOOP("MainWindow",
1943                         "Replace Vectors with Simplified Vectors"),
1944       "");
1945   createMenuLevelAction(MI_Tracking, QT_TR_NOOP("Tracking..."), "",
1946                         "tracking_options");
1947 
1948   // Menu - Xsheet
1949 
1950   createMenuXsheetAction(MI_SceneSettings, QT_TR_NOOP("&Scene Settings..."), "",
1951                          "scene_settings");
1952   createMenuXsheetAction(MI_CameraSettings, QT_TR_NOOP("&Camera Settings..."),
1953                          "", "camera_settings");
1954   createMenuXsheetAction(MI_OpenChild, QT_TR_NOOP("&Open Sub-Xsheet"), "",
1955                          "sub_enter");
1956   createMenuXsheetAction(MI_CloseChild, QT_TR_NOOP("&Close Sub-Xsheet"), "",
1957                          "sub_leave");
1958   createMenuXsheetAction(MI_ExplodeChild, QT_TR_NOOP("Explode Sub-Xsheet"), "",
1959                          "sub_explode");
1960   createMenuXsheetAction(MI_Collapse, QT_TR_NOOP("Collapse"), "",
1961                          "sub_collapse");
1962   createToggle(MI_ToggleEditInPlace, QT_TR_NOOP("&Toggle Edit In Place"), "",
1963                EditInPlaceToggleAction ? 1 : 0, MenuXsheetCommandType,
1964                "sub_edit_in_place");
1965   createMenuXsheetAction(MI_SaveSubxsheetAs,
1966                          QT_TR_NOOP("&Save Sub-Xsheet As..."), "",
1967                          "sub_xsheet_saveas");
1968   createMenuXsheetAction(MI_Resequence, QT_TR_NOOP("Resequence"), "",
1969                          "resequence");
1970   createMenuXsheetAction(MI_CloneChild, QT_TR_NOOP("Clone Sub-Xsheet"), "",
1971                          "sub_clone");
1972   createMenuXsheetAction(MI_ApplyMatchLines,
1973                          QT_TR_NOOP("&Apply Match Lines..."), "",
1974                          "apply_match_lines");
1975   createMenuXsheetAction(MI_MergeCmapped, QT_TR_NOOP("&Merge Tlv Levels..."),
1976                          "", "merge_levels_tlv");
1977   createMenuXsheetAction(MI_DeleteMatchLines, QT_TR_NOOP("&Delete Match Lines"),
1978                          "", "delete_match_lines");
1979   createMenuXsheetAction(MI_DeleteInk, QT_TR_NOOP("&Delete Lines..."), "",
1980                          "delete_lines");
1981   createMenuXsheetAction(MI_MergeColumns, QT_TR_NOOP("&Merge Levels"), "",
1982                          "merge_levels");
1983   createMenuXsheetAction(MI_InsertFx, QT_TR_NOOP("&New FX..."), "Ctrl+F",
1984                          "fx_new");
1985   createMenuXsheetAction(MI_NewOutputFx, QT_TR_NOOP("&New Output"), "Alt+O",
1986                          "output");
1987   createMenuXsheetAction(MI_InsertSceneFrame, QT_TR_NOOP("Insert Frame"), "",
1988                          "insert_frame");
1989   createMenuXsheetAction(MI_RemoveSceneFrame, QT_TR_NOOP("Remove Frame"), "",
1990                          "remove_frame");
1991   createMenuXsheetAction(MI_InsertGlobalKeyframe,
1992                          QT_TR_NOOP("Insert Multiple Keys"), "",
1993                          "insert_multiple_keys");
1994   createMenuXsheetAction(MI_RemoveGlobalKeyframe,
1995                          QT_TR_NOOP("Remove Multiple Keys"), "",
1996                          "remove_multiple_keys");
1997   createMenuXsheetAction(MI_RemoveEmptyColumns,
1998                          QT_TR_NOOP("Remove Empty Columns"), "",
1999                          "remove_empty_columns");
2000   createMenuXsheetAction(MI_LipSyncPopup,
2001                          QT_TR_NOOP("&Apply Lip Sync Data to Column"), "Alt+L",
2002                          "dialogue");
2003 
2004   // Menu - Cells
2005 
2006   createMenuCellsAction(MI_MergeFrames, QT_TR_NOOP("&Merge"), "", "merge");
2007   createMenuCellsAction(MI_Reverse, QT_TR_NOOP("&Reverse"), "", "reverse");
2008   createMenuCellsAction(MI_Swing, QT_TR_NOOP("&Swing"), "", "swing");
2009   createMenuCellsAction(MI_Random, QT_TR_NOOP("&Random"), "", "random");
2010   createMenuCellsAction(MI_Increment, QT_TR_NOOP("&Autoexpose"), "",
2011                         "autoexpose");
2012   createMenuCellsAction(MI_Dup, QT_TR_NOOP("&Repeat..."), "", "repeat");
2013   createMenuCellsAction(MI_ResetStep, QT_TR_NOOP("&Reset Step"), "",
2014                         "step_reset");
2015   createMenuCellsAction(MI_IncreaseStep, QT_TR_NOOP("&Increase Step"), "'",
2016                         "step_plus");
2017   createMenuCellsAction(MI_DecreaseStep, QT_TR_NOOP("&Decrease Step"), ";",
2018                         "step_minus");
2019   createMenuCellsAction(MI_Step2, QT_TR_NOOP("&Step 2"), "", "step_2");
2020   createMenuCellsAction(MI_Step3, QT_TR_NOOP("&Step 3"), "", "step_3");
2021   createMenuCellsAction(MI_Step4, QT_TR_NOOP("&Step 4"), "", "step_4");
2022   createMenuCellsAction(MI_Each2, QT_TR_NOOP("&Each 2"), "");
2023   createMenuCellsAction(MI_Each3, QT_TR_NOOP("&Each 3"), "");
2024   createMenuCellsAction(MI_Each4, QT_TR_NOOP("&Each 4"), "");
2025   createMenuCellsAction(MI_Rollup, QT_TR_NOOP("&Roll Up"), "", "rollup");
2026   createMenuCellsAction(MI_Rolldown, QT_TR_NOOP("&Roll Down"), "", "rolldown");
2027   createMenuCellsAction(MI_TimeStretch, QT_TR_NOOP("&Time Stretch..."), "",
2028                         "time_stretch");
2029   createMenuCellsAction(MI_CreateBlankDrawing,
2030                         QT_TR_NOOP("&Create Blank Drawing"), "Alt+D",
2031                         "add_cell");
2032   createMenuCellsAction(MI_Duplicate, QT_TR_NOOP("&Duplicate Drawing  "), "D",
2033                         "duplicate_drawing");
2034   createMenuCellsAction(MI_Autorenumber, QT_TR_NOOP("&Autorenumber"), "",
2035                         "renumber");
2036   createMenuCellsAction(MI_CloneLevel, QT_TR_NOOP("&Clone Cells"), "",
2037                         "clone_cells");
2038   createMenuCellsAction(MI_DrawingSubForward,
2039                         QT_TR_NOOP("Drawing Substitution Forward"), "W");
2040   createMenuCellsAction(MI_DrawingSubBackward,
2041                         QT_TR_NOOP("Drawing Substitution Backward"), "Q");
2042   createMenuCellsAction(MI_DrawingSubGroupForward,
2043                         QT_TR_NOOP("Similar Drawing Substitution Forward"),
2044                         "Alt+W");
2045   createMenuCellsAction(MI_DrawingSubGroupBackward,
2046                         QT_TR_NOOP("Similar Drawing Substitution Backward"),
2047                         "Alt+Q");
2048   createMenuCellsAction(MI_Reframe1, QT_TR_NOOP("Reframe on 1's"), "", "on_1s");
2049   createMenuCellsAction(MI_Reframe2, QT_TR_NOOP("Reframe on 2's"), "", "on_2s");
2050   createMenuCellsAction(MI_Reframe3, QT_TR_NOOP("Reframe on 3's"), "", "on_3s");
2051   createMenuCellsAction(MI_Reframe4, QT_TR_NOOP("Reframe on 4's"), "", "on_4s");
2052   createMenuCellsAction(MI_ReframeWithEmptyInbetweens,
2053                         QT_TR_NOOP("Reframe with Empty Inbetweens..."), "",
2054                         "on_with_empty");
2055   createMenuCellsAction(MI_AutoInputCellNumber,
2056                         QT_TR_NOOP("Auto Input Cell Number..."), "",
2057                         "auto_input_cell_number");
2058   createMenuCellsAction(MI_FillEmptyCell, QT_TR_NOOP("&Fill In Empty Cells"),
2059                         "", "fill_empty_cells");
2060 
2061   // Menu - Play
2062 
2063   createToggle(MI_Link, QT_TR_NOOP("Link Flipbooks"), "",
2064                LinkToggleAction ? 1 : 0, MenuPlayCommandType, "flipbook_link");
2065   createMenuPlayAction(MI_Play, QT_TR_NOOP("Play"), "P", "play");
2066   createMenuPlayAction(MI_ShortPlay, QT_TR_NOOP("Short Play"), "Alt+P");
2067   createMenuPlayAction(MI_Loop, QT_TR_NOOP("Loop"), "L", "loop");
2068   createMenuPlayAction(MI_Pause, QT_TR_NOOP("Pause"), "", "pause");
2069   createMenuPlayAction(MI_FirstFrame, QT_TR_NOOP("First Frame"), "Alt+,",
2070                        "framefirst");
2071   createMenuPlayAction(MI_LastFrame, QT_TR_NOOP("Last Frame"), "Alt+.",
2072                        "framelast");
2073   createMenuPlayAction(MI_PrevFrame, QT_TR_NOOP("Previous Frame"), "Shift+,",
2074                        "frameprev");
2075   createMenuPlayAction(MI_NextFrame, QT_TR_NOOP("Next Frame"), "Shift+.",
2076                        "framenext");
2077   createMenuPlayAction(MI_NextDrawing, QT_TR_NOOP("Next Drawing"), ".",
2078                        "next_drawing");
2079   createMenuPlayAction(MI_PrevDrawing, QT_TR_NOOP("Previous Drawing"), ",",
2080                        "prev_drawing");
2081   createMenuPlayAction(MI_NextStep, QT_TR_NOOP("Next Step"), "", "nextstep");
2082   createMenuPlayAction(MI_PrevStep, QT_TR_NOOP("Previous Step"), "",
2083                        "prevstep");
2084   createMenuPlayAction(MI_NextKeyframe, QT_TR_NOOP("Next Key"), "Ctrl+.",
2085                        "nextkey");
2086   createMenuPlayAction(MI_PrevKeyframe, QT_TR_NOOP("Previous Key"), "Ctrl+,",
2087                        "prevkey");
2088 
2089   // Menu - Render
2090 
2091   createMenuRenderAction(MI_OutputSettings, QT_TR_NOOP("&Output Settings..."),
2092                          "Ctrl+O", "output_settings");
2093   createMenuRenderAction(MI_PreviewSettings, QT_TR_NOOP("&Preview Settings..."),
2094                          "", "preview_settings");
2095   createMenuRenderAction(MI_Render, QT_TR_NOOP("&Render"), "Ctrl+Shift+R",
2096                          "render_clapboard");
2097   createMenuRenderAction(MI_FastRender, QT_TR_NOOP("&Fast Render to MP4"),
2098                          "Alt+R", "fast_render_mp4");
2099   createMenuRenderAction(MI_Preview, QT_TR_NOOP("&Preview"), "Ctrl+R",
2100                          "preview");
2101   createMenuRenderAction(MI_SavePreviewedFrames,
2102                          QT_TR_NOOP("&Save Previewed Frames"), "",
2103                          "save_previewed_frames");
2104   createRightClickMenuAction(MI_OpenPltGizmo, QT_TR_NOOP("&Palette Gizmo"), "",
2105                              "palettegizmo");
2106   createRightClickMenuAction(MI_EraseUnusedStyles,
2107                              QT_TR_NOOP("&Delete Unused Styles"), "");
2108 
2109   // Menu - View
2110 
2111   createToggle(MI_ViewCamera, QT_TR_NOOP("&Camera Box"), "",
2112                ViewCameraToggleAction ? 1 : 0, MenuViewCommandType);
2113   createToggle(MI_ViewTable, QT_TR_NOOP("&Table"), "",
2114                ViewTableToggleAction ? 1 : 0, MenuViewCommandType);
2115   createToggle(MI_FieldGuide, QT_TR_NOOP("&Field Guide"), "Shift+G",
2116                FieldGuideToggleAction ? 1 : 0, MenuViewCommandType);
2117   createToggle(MI_ViewBBox, QT_TR_NOOP("&Raster Bounding Box"), "",
2118                ViewBBoxToggleAction ? 1 : 0, MenuViewCommandType);
2119   createToggle(MI_SafeArea, QT_TR_NOOP("&Safe Area"), "",
2120                SafeAreaToggleAction ? 1 : 0, MenuViewCommandType);
2121   createToggle(MI_ViewColorcard, QT_TR_NOOP("&Camera BG Color"), "",
2122                ViewColorcardToggleAction ? 1 : 0, MenuViewCommandType);
2123   createToggle(MI_ViewGuide, QT_TR_NOOP("&Guide"), "",
2124                ViewGuideToggleAction ? 1 : 0, MenuViewCommandType);
2125   createToggle(MI_ViewRuler, QT_TR_NOOP("&Ruler"), "",
2126                ViewRulerToggleAction ? 1 : 0, MenuViewCommandType);
2127   createToggle(MI_TCheck, QT_TR_NOOP("&Transparency Check  "), "",
2128                TCheckToggleAction ? 1 : 0, MenuViewCommandType,
2129                "transparency_check");
2130   menuAct = createToggle(MI_ICheck, QT_TR_NOOP("&Ink Check"), "",
2131                          ICheckToggleAction ? 1 : 0, MenuViewCommandType,
2132                          "ink_check");
2133   // make InkCheck and Ink1Check exclusive
2134   connect(menuAct, SIGNAL(triggered(bool)), this,
2135           SLOT(onInkCheckTriggered(bool)));
2136   menuAct = createToggle(MI_Ink1Check, QT_TR_NOOP("&Ink#1 Check"), "",
2137                          Ink1CheckToggleAction ? 1 : 0, MenuViewCommandType,
2138                          "ink_no1_check");
2139   // make InkCheck and Ink1Check exclusive
2140   connect(menuAct, SIGNAL(triggered(bool)), this,
2141           SLOT(onInk1CheckTriggered(bool)));
2142   createToggle(MI_PCheck, QT_TR_NOOP("&Paint Check"), "",
2143                PCheckToggleAction ? 1 : 0, MenuViewCommandType, "paint_check");
2144   createToggle(MI_IOnly, QT_TR_NOOP("Inks &Only"), "",
2145                IOnlyToggleAction ? 1 : 0, MenuViewCommandType, "inks_only");
2146   createToggle(MI_GCheck, QT_TR_NOOP("&Fill Check"), "",
2147                GCheckToggleAction ? 1 : 0, MenuViewCommandType, "fill_check");
2148   createToggle(MI_BCheck, QT_TR_NOOP("&Black BG Check"), "",
2149                BCheckToggleAction ? 1 : 0, MenuViewCommandType,
2150                "blackbg_check");
2151   createToggle(MI_ACheck, QT_TR_NOOP("&Gap Check"), "",
2152                ACheckToggleAction ? 1 : 0, MenuViewCommandType, "gap_check");
2153   createToggle(MI_ShiftTrace, QT_TR_NOOP("Shift and Trace"), "", false,
2154                MenuViewCommandType, "shift_and_trace");
2155   createToggle(MI_EditShift, QT_TR_NOOP("Edit Shift"), "", false,
2156                MenuViewCommandType, "shift_and_trace_edit");
2157   createToggle(MI_NoShift, QT_TR_NOOP("No Shift"), "", false,
2158                MenuViewCommandType, "shift_and_trace_no_shift");
2159   CommandManager::instance()->enable(MI_EditShift, false);
2160   CommandManager::instance()->enable(MI_NoShift, false);
2161   createAction(MI_ResetShift, QT_TR_NOOP("Reset Shift"), "",
2162                MenuViewCommandType, "shift_and_trace_reset");
2163   createToggle(MI_VectorGuidedDrawing, QT_TR_NOOP("Vector Guided Drawing"), "",
2164                Preferences::instance()->isGuidedDrawingEnabled(),
2165                MenuViewCommandType, "view_guided_drawing");
2166   if (QGLPixelBuffer::hasOpenGLPbuffers())
2167     createToggle(MI_RasterizePli, QT_TR_NOOP("&Visualize Vector As Raster"), "",
2168                  RasterizePliToggleAction ? 1 : 0, MenuViewCommandType,
2169                  "view_vector_as_raster");
2170   else
2171     RasterizePliToggleAction = 0;
2172 
2173   // Menu - Windows
2174 
2175   createMenuWindowsAction(MI_OpenFileBrowser, QT_TR_NOOP("&File Browser"), "",
2176                           "filebrowser");
2177   createMenuWindowsAction(MI_OpenFileViewer, QT_TR_NOOP("&Flipbook"), "",
2178                           "flipbook");
2179   createMenuWindowsAction(MI_OpenFunctionEditor, QT_TR_NOOP("&Function Editor"),
2180                           "", "function_editor");
2181   createMenuWindowsAction(MI_OpenFilmStrip, QT_TR_NOOP("&Level Strip"), "",
2182                           "level_strip");
2183   createMenuWindowsAction(MI_OpenPalette, QT_TR_NOOP("&Palette"), "",
2184                           "palette");
2185   createMenuWindowsAction(MI_OpenTasks, QT_TR_NOOP("&Tasks"), "", "tasks");
2186   createMenuWindowsAction(MI_OpenBatchServers, QT_TR_NOOP("&Batch Servers"), "",
2187                           "batchservers");
2188   createMenuWindowsAction(MI_OpenTMessage, QT_TR_NOOP("&Message Center"), "",
2189                           "messagecenter");
2190   createMenuWindowsAction(MI_OpenColorModel, QT_TR_NOOP("&Color Model"), "",
2191                           "colormodel");
2192   createMenuWindowsAction(MI_OpenStudioPalette, QT_TR_NOOP("&Studio Palette"),
2193                           "", "studiopalette");
2194   createMenuWindowsAction(MI_OpenSchematic, QT_TR_NOOP("&Schematic"), "",
2195                           "schematic");
2196   createMenuWindowsAction(MI_FxParamEditor, QT_TR_NOOP("&FX Editor"), "Ctrl+K",
2197                           "fx_settings");
2198   createMenuWindowsAction(MI_OpenCleanupSettings,
2199                           QT_TR_NOOP("&Cleanup Settings"), "",
2200                           "cleanup_settings");
2201   createMenuWindowsAction(MI_OpenFileBrowser2, QT_TR_NOOP("&Scene Cast"), "",
2202                           "scenecast");
2203   createMenuWindowsAction(MI_OpenStyleControl, QT_TR_NOOP("&Style Editor"), "",
2204                           "styleeditor");
2205   createMenuWindowsAction(MI_OpenToolbar, QT_TR_NOOP("&Toolbar"), "", "tool");
2206   createMenuWindowsAction(MI_OpenToolOptionBar, QT_TR_NOOP("&Tool Option Bar"),
2207                           "", "tool_options");
2208   createMenuWindowsAction(MI_OpenCommandToolbar, QT_TR_NOOP("&Command Bar"), "",
2209                           "star");
2210 #if defined(x64)
2211   createMenuWindowsAction(MI_OpenStopMotionPanel,
2212                           QT_TR_NOOP("&Stop Motion Controls"), "");
2213 #endif
2214   createMenuWindowsAction(MI_OpenLevelView, QT_TR_NOOP("&Viewer"), "",
2215                           "viewer");
2216   createMenuWindowsAction(MI_OpenXshView, QT_TR_NOOP("&Xsheet"), "", "xsheet");
2217   createMenuWindowsAction(MI_OpenTimelineView, QT_TR_NOOP("&Timeline"), "",
2218                           "timeline");
2219   createMenuWindowsAction(MI_OpenComboViewer, QT_TR_NOOP("&ComboViewer"), "",
2220                           "comboviewer");
2221   createMenuWindowsAction(MI_OpenHistoryPanel, QT_TR_NOOP("&History"), "Ctrl+H",
2222                           "history");
2223   createMenuWindowsAction(MI_AudioRecording, QT_TR_NOOP("Record Audio"),
2224                           "Alt+A", "recordaudio");
2225   createMenuWindowsAction(MI_ResetRoomLayout,
2226                           QT_TR_NOOP("&Reset to Default Rooms"), "");
2227   createMenuWindowsAction(MI_MaximizePanel, QT_TR_NOOP("Toggle Maximize Panel"),
2228                           "`", "fit_to_window");
2229   createMenuWindowsAction(MI_FullScreenWindow,
2230                           QT_TR_NOOP("Toggle Main Window's Full Screen Mode"),
2231                           "Ctrl+`", "toggle_fullscreen");
2232   createMenuHelpAction(MI_About, QT_TR_NOOP("&About OpenToonz..."), "", "info");
2233   createMenuWindowsAction(MI_StartupPopup, QT_TR_NOOP("&Startup Popup..."),
2234                           "Alt+S", "opentoonz");
2235   createMenuWindowsAction(MI_OpenGuidedDrawingControls,
2236                           QT_TR_NOOP("Guided Drawing Controls"), "",
2237                           "guided_drawing");
2238   menuAct =
2239       createToggle(MI_DockingCheck, QT_TR_NOOP("&Lock Room Panes"), "",
2240                    DockingCheckToggleAction ? 1 : 0, MenuWindowsCommandType);
2241   DockingCheck::instance()->setToggle(menuAct);
2242 
2243   // Menu - Help
2244 
2245   createMenuHelpAction(MI_OpenOnlineManual, QT_TR_NOOP("&Online Manual..."),
2246                        "F1", "manual");
2247   createMenuHelpAction(MI_OpenWhatsNew, QT_TR_NOOP("&What's New..."), "",
2248                        "web");
2249   createMenuHelpAction(MI_OpenCommunityForum, QT_TR_NOOP("&Community Forum..."),
2250                        "", "web");
2251   createMenuHelpAction(MI_OpenReportABug, QT_TR_NOOP("&Report a Bug..."), "",
2252                        "web");
2253 
2254   // Fill
2255 
2256   createFillAction(
2257       MI_AutoFillToggle,
2258       QT_TRANSLATE_NOOP("MainWindow",
2259                         "Toggle Autofill on Current Palette Color"),
2260       "Shift+A");
2261 
2262   // Right Click
2263 
2264   createRightClickMenuAction(MI_SavePaletteAs,
2265                              QT_TR_NOOP("&Save Palette As..."), "");
2266   createRightClickMenuAction(MI_OverwritePalette, QT_TR_NOOP("&Save Palette"),
2267                              "");
2268   createRightClickMenuAction(MI_RegeneratePreview,
2269                              QT_TR_NOOP("&Regenerate Preview"), "");
2270   createRightClickMenuAction(MI_RegenerateFramePr,
2271                              QT_TR_NOOP("&Regenerate Frame Preview"), "");
2272   createRightClickMenuAction(MI_ClonePreview, QT_TR_NOOP("&Clone Preview"), "");
2273   createRightClickMenuAction(MI_FreezePreview,
2274                              QT_TR_NOOP("&Freeze//Unfreeze Preview"), "");
2275   CommandManager::instance()->setToggleTexts(
2276       MI_FreezePreview, tr("Freeze Preview"), tr("Unfreeze Preview"));
2277   createRightClickMenuAction(MI_SavePreset, QT_TR_NOOP("&Save As Preset"), "");
2278   createRightClickMenuAction(MI_PreviewFx, QT_TR_NOOP("Preview Fx"), "");
2279   createRightClickMenuAction(MI_PasteValues, QT_TR_NOOP("&Paste Color && Name"),
2280                              "");
2281   createRightClickMenuAction(MI_PasteColors, QT_TR_NOOP("Paste Color"), "");
2282   createRightClickMenuAction(MI_PasteNames, QT_TR_NOOP("Paste Name"), "");
2283   createRightClickMenuAction(MI_GetColorFromStudioPalette,
2284                              QT_TR_NOOP("Get Color from Studio Palette"), "");
2285   createRightClickMenuAction(MI_ToggleLinkToStudioPalette,
2286                              QT_TR_NOOP("Toggle Link to Studio Palette"), "");
2287   createRightClickMenuAction(MI_RemoveReferenceToStudioPalette,
2288                              QT_TR_NOOP("Remove Reference to Studio Palette"),
2289                              "");
2290   createRightClickMenuAction(MI_ViewFile, QT_TR_NOOP("&View..."), "",
2291                              "view_file");
2292   createRightClickMenuAction(MI_ToggleXSheetToolbar,
2293                              QT_TR_NOOP("Toggle XSheet Toolbar"), "");
2294   createRightClickMenuAction(MI_ToggleXsheetCameraColumn,
2295                              QT_TR_NOOP("Show/Hide Xsheet Camera Column"), "");
2296   createRightClickMenuAction(MI_SetKeyframes, QT_TR_NOOP("&Set Key"), "Z",
2297                              "set_key");
2298   createRightClickMenuAction(MI_ShiftKeyframesDown,
2299                              QT_TR_NOOP("&Shift Keys Down"), "",
2300                              "shift_keys_down");
2301   createRightClickMenuAction(MI_ShiftKeyframesUp, QT_TR_NOOP("&Shift Keys Up"),
2302                              "", "shift_keys_up");
2303   createRightClickMenuAction(MI_PasteNumbers, QT_TR_NOOP("&Paste Numbers"), "",
2304                              "paste_numbers");
2305   createRightClickMenuAction(MI_Histogram, QT_TR_NOOP("&Histogram"), "");
2306   createRightClickMenuAction(MI_BlendColors, QT_TR_NOOP("&Blend colors"), "");
2307   createToggle(MI_OnionSkin, QT_TR_NOOP("Onion Skin Toggle"), "/", false,
2308                RightClickMenuCommandType, "onionskin_toggle");
2309   createToggle(MI_ZeroThick, QT_TR_NOOP("Zero Thick Lines"), "Shift+/", false,
2310                RightClickMenuCommandType);
2311   createToggle(MI_CursorOutline, QT_TR_NOOP("Toggle Cursor Size Outline"), "",
2312                false, RightClickMenuCommandType);
2313   createRightClickMenuAction(MI_ToggleCurrentTimeIndicator,
2314                              QT_TR_NOOP("Toggle Current Time Indicator"), "");
2315   createRightClickMenuAction(MI_DuplicateFile, QT_TR_NOOP("Duplicate"), "",
2316                              "duplicate");
2317   createRightClickMenuAction(MI_ShowFolderContents,
2318                              QT_TR_NOOP("Show Folder Contents"), "",
2319                              "show_folder_contents");
2320   createRightClickMenuAction(MI_ConvertFiles, QT_TR_NOOP("Convert..."), "",
2321                              "convert");
2322   createRightClickMenuAction(MI_CollectAssets, QT_TR_NOOP("Collect Assets"),
2323                              "");
2324   createRightClickMenuAction(MI_ImportScenes, QT_TR_NOOP("Import Scene"), "",
2325                              "load_scene");
2326   createRightClickMenuAction(MI_ExportScenes, QT_TR_NOOP("Export Scene..."), "",
2327                              "scene_export");
2328 
2329   createRightClickMenuAction(MI_RemoveLevel, QT_TR_NOOP("Remove Level"), "",
2330                              "remove_level");
2331   createRightClickMenuAction(MI_AddToBatchRenderList,
2332                              QT_TR_NOOP("Add As Render Task"), "",
2333                              "render_add");
2334   createRightClickMenuAction(MI_AddToBatchCleanupList,
2335                              QT_TR_NOOP("Add As Cleanup Task"), "",
2336                              "cleanup_add");
2337   createRightClickMenuAction(MI_SelectRowKeyframes,
2338                              QT_TR_NOOP("Select All Keys in this Frame"), "");
2339   createRightClickMenuAction(MI_SelectColumnKeyframes,
2340                              QT_TR_NOOP("Select All Keys in this Column"), "");
2341   createRightClickMenuAction(MI_SelectAllKeyframes,
2342                              QT_TR_NOOP("Select All Keys"), "");
2343   createRightClickMenuAction(MI_SelectAllKeyframesNotBefore,
2344                              QT_TR_NOOP("Select All Following Keys"), "");
2345   createRightClickMenuAction(MI_SelectAllKeyframesNotAfter,
2346                              QT_TR_NOOP("Select All Previous Keys"), "");
2347   createRightClickMenuAction(MI_SelectPreviousKeysInColumn,
2348                              QT_TR_NOOP("Select Previous Keys in this Column"),
2349                              "");
2350   createRightClickMenuAction(MI_SelectFollowingKeysInColumn,
2351                              QT_TR_NOOP("Select Following Keys in this Column"),
2352                              "");
2353   createRightClickMenuAction(MI_SelectPreviousKeysInRow,
2354                              QT_TR_NOOP("Select Previous Keys in this Frame"),
2355                              "");
2356   createRightClickMenuAction(MI_SelectFollowingKeysInRow,
2357                              QT_TR_NOOP("Select Following Keys in this Frame"),
2358                              "");
2359   createRightClickMenuAction(MI_InvertKeyframeSelection,
2360                              QT_TR_NOOP("Invert Key Selection"), "");
2361   createRightClickMenuAction(MI_SetAcceleration, QT_TR_NOOP("Set Acceleration"),
2362                              "");
2363   createRightClickMenuAction(MI_SetDeceleration, QT_TR_NOOP("Set Deceleration"),
2364                              "");
2365   createRightClickMenuAction(MI_SetConstantSpeed,
2366                              QT_TR_NOOP("Set Constant Speed"), "");
2367   createRightClickMenuAction(MI_ResetInterpolation,
2368                              QT_TR_NOOP("Reset Interpolation"), "");
2369   createRightClickMenuAction(MI_UseLinearInterpolation,
2370                              QT_TR_NOOP("Linear Interpolation"), "");
2371   createRightClickMenuAction(MI_UseSpeedInOutInterpolation,
2372                              QT_TR_NOOP("Speed In / Speed Out Interpolation"),
2373                              "");
2374   createRightClickMenuAction(MI_UseEaseInOutInterpolation,
2375                              QT_TR_NOOP("Ease In / Ease Out Interpolation"),
2376                              "");
2377   createRightClickMenuAction(MI_UseEaseInOutPctInterpolation,
2378                              QT_TR_NOOP("Ease In / Ease Out (%) Interpolation"),
2379                              "");
2380   createRightClickMenuAction(MI_UseExponentialInterpolation,
2381                              QT_TR_NOOP("Exponential Interpolation"), "");
2382   createRightClickMenuAction(MI_UseExpressionInterpolation,
2383                              QT_TR_NOOP("Expression Interpolation"), "");
2384   createRightClickMenuAction(MI_UseFileInterpolation,
2385                              QT_TR_NOOP("File Interpolation"), "");
2386   createRightClickMenuAction(MI_UseConstantInterpolation,
2387                              QT_TR_NOOP("Constant Interpolation"), "");
2388   createRightClickMenuAction(MI_FoldColumns, QT_TR_NOOP("Fold Column"), "",
2389                              "fold_column");
2390   createRightClickMenuAction(MI_ActivateThisColumnOnly,
2391                              QT_TR_NOOP("Show This Only"), "");
2392   createRightClickMenuAction(MI_ActivateSelectedColumns,
2393                              QT_TR_NOOP("Show Selected"), "");
2394   createRightClickMenuAction(MI_ActivateAllColumns, QT_TR_NOOP("Show All"), "");
2395   createRightClickMenuAction(MI_DeactivateSelectedColumns,
2396                              QT_TR_NOOP("Hide Selected"), "");
2397   createRightClickMenuAction(MI_DeactivateAllColumns, QT_TR_NOOP("Hide All"),
2398                              "");
2399   createRightClickMenuAction(MI_ToggleColumnsActivation,
2400                              QT_TR_NOOP("Toggle Show/Hide"), "");
2401   createRightClickMenuAction(MI_EnableThisColumnOnly,
2402                              QT_TR_NOOP("ON This Only"), "");
2403   createRightClickMenuAction(MI_EnableSelectedColumns,
2404                              QT_TR_NOOP("ON Selected"), "");
2405   createRightClickMenuAction(MI_EnableAllColumns, QT_TR_NOOP("ON All"), "");
2406   createRightClickMenuAction(MI_DisableAllColumns, QT_TR_NOOP("OFF All"), "");
2407   createRightClickMenuAction(MI_DisableSelectedColumns,
2408                              QT_TR_NOOP("OFF Selected"), "");
2409   createRightClickMenuAction(MI_SwapEnabledColumns, QT_TR_NOOP("Swap ON/OFF"),
2410                              "");
2411   createRightClickMenuAction(MI_LockThisColumnOnly,
2412                              QT_TR_NOOP("Lock This Only"), "Shift+L");
2413   createRightClickMenuAction(MI_LockSelectedColumns,
2414                              QT_TR_NOOP("Lock Selected"), "Ctrl+Shift+L");
2415   createRightClickMenuAction(MI_LockAllColumns, QT_TR_NOOP("Lock All"),
2416                              "Ctrl+Alt+Shift+L");
2417   createRightClickMenuAction(MI_UnlockSelectedColumns,
2418                              QT_TR_NOOP("Unlock Selected"), "Ctrl+Shift+U");
2419   createRightClickMenuAction(MI_UnlockAllColumns, QT_TR_NOOP("Unlock All"),
2420                              "Ctrl+Alt+Shift+U");
2421   createRightClickMenuAction(MI_ToggleColumnLocks,
2422                              QT_TR_NOOP("Swap Lock/Unlock"), "");
2423   createRightClickMenuAction(MI_DeactivateUpperColumns,
2424                              QT_TR_NOOP("Hide Upper Columns"), "");
2425   createRightClickMenuAction(MI_SeparateColors,
2426                              QT_TR_NOOP("Separate Colors..."), "",
2427                              "separate_colors");
2428 
2429   // Tools
2430 
2431   createToolAction(T_Edit, "animate", QT_TR_NOOP("Animate Tool"), "A");
2432   createToolAction(T_Selection, "selection", QT_TR_NOOP("Selection Tool"), "S");
2433   createToolAction(T_Brush, "brush", QT_TR_NOOP("Brush Tool"), "B");
2434   createToolAction(T_Geometric, "geometric", QT_TR_NOOP("Geometric Tool"), "G");
2435   createToolAction(T_Type, "type", QT_TR_NOOP("Type Tool"), "Y");
2436   createToolAction(T_Fill, "fill", QT_TR_NOOP("Fill Tool"), "F");
2437   createToolAction(T_PaintBrush, "paintbrush", QT_TR_NOOP("Paint Brush Tool"),
2438                    "");
2439   createToolAction(T_Eraser, "eraser", QT_TR_NOOP("Eraser Tool"), "E");
2440   createToolAction(T_Tape, "tape", QT_TR_NOOP("Tape Tool"), "T");
2441   createToolAction(T_StylePicker, "stylepicker",
2442                    QT_TR_NOOP("Style Picker Tool"), "K");
2443   createToolAction(T_RGBPicker, "rgbpicker", QT_TR_NOOP("RGB Picker Tool"),
2444                    "R");
2445   createToolAction(T_ControlPointEditor, "controlpointeditor",
2446                    QT_TR_NOOP("Control Point Editor Tool"), "C");
2447   createToolAction(T_Pinch, "pinch", QT_TR_NOOP("Pinch Tool"), "M");
2448   createToolAction(T_Pump, "pump", QT_TR_NOOP("Pump Tool"), "");
2449   createToolAction(T_Magnet, "magnet", QT_TR_NOOP("Magnet Tool"), "");
2450   createToolAction(T_Bender, "bender", QT_TR_NOOP("Bender Tool"), "");
2451   createToolAction(T_Iron, "iron", QT_TR_NOOP("Iron Tool"), "");
2452 
2453   createToolAction(T_Cutter, "cutter", QT_TR_NOOP("Cutter Tool"), "");
2454   createToolAction(T_Skeleton, "skeleton", QT_TR_NOOP("Skeleton Tool"), "V");
2455   createToolAction(T_Tracker, "radar", QT_TR_NOOP("Tracker Tool"), "");
2456   createToolAction(T_Hook, "hook", QT_TR_NOOP("Hook Tool"), "O");
2457   createToolAction(T_Zoom, "zoom", QT_TR_NOOP("Zoom Tool"), "Shift+Space");
2458   createToolAction(T_Rotate, "rotate", QT_TR_NOOP("Rotate Tool"), "Ctrl+Space");
2459   createToolAction(T_Hand, "hand", QT_TR_NOOP("Hand Tool"), "Space");
2460   createToolAction(T_Plastic, "plastic", QT_TR_NOOP("Plastic Tool"), "X");
2461   createToolAction(T_Ruler, "ruler", QT_TR_NOOP("Ruler Tool"), "");
2462   createToolAction(T_Finger, "finger", QT_TR_NOOP("Finger Tool"), "");
2463 
2464   /*-- Animate tool + mode switching shortcuts --*/
2465   createAction(MI_EditNextMode, QT_TR_NOOP("Animate Tool - Next Mode"), "",
2466                ToolCommandType);
2467   createAction(MI_EditPosition, QT_TR_NOOP("Animate Tool - Position"), "",
2468                ToolCommandType, "edit_position");
2469   createAction(MI_EditRotation, QT_TR_NOOP("Animate Tool - Rotation"), "",
2470                ToolCommandType, "edit_rotation");
2471   createAction(MI_EditScale, QT_TR_NOOP("Animate Tool - Scale"), "",
2472                ToolCommandType, "edit_scale");
2473   createAction(MI_EditShear, QT_TR_NOOP("Animate Tool - Shear"), "",
2474                ToolCommandType, "edit_shear");
2475   createAction(MI_EditCenter, QT_TR_NOOP("Animate Tool - Center"), "",
2476                ToolCommandType, "edit_center");
2477   createAction(MI_EditAll, QT_TR_NOOP("Animate Tool - All"), "",
2478                ToolCommandType, "edit_all");
2479 
2480   /*-- Selection tool + type switching shortcuts --*/
2481   createAction(MI_SelectionNextType, QT_TR_NOOP("Selection Tool - Next Type"),
2482                "", ToolCommandType);
2483   createAction(MI_SelectionRectangular,
2484                QT_TR_NOOP("Selection Tool - Rectangular"), "", ToolCommandType,
2485                "selection_rectangular");
2486   createAction(MI_SelectionFreehand, QT_TR_NOOP("Selection Tool - Freehand"),
2487                "", ToolCommandType, "selection_freehand");
2488   createAction(MI_SelectionPolyline, QT_TR_NOOP("Selection Tool - Polyline"),
2489                "", ToolCommandType, "selection_polyline");
2490 
2491   /*-- Geometric tool + shape switching shortcuts --*/
2492   createAction(MI_GeometricNextShape, QT_TR_NOOP("Geometric Tool - Next Shape"),
2493                "", ToolCommandType);
2494   createAction(MI_GeometricRectangle, QT_TR_NOOP("Geometric Tool - Rectangle"),
2495                "", ToolCommandType, "geometric_rectangle");
2496   createAction(MI_GeometricCircle, QT_TR_NOOP("Geometric Tool - Circle"), "",
2497                ToolCommandType, "geometric_circle");
2498   createAction(MI_GeometricEllipse, QT_TR_NOOP("Geometric Tool - Ellipse"), "",
2499                ToolCommandType, "geometric_ellipse");
2500   createAction(MI_GeometricLine, QT_TR_NOOP("Geometric Tool - Line"), "",
2501                ToolCommandType, "geometric_line");
2502   createAction(MI_GeometricPolyline, QT_TR_NOOP("Geometric Tool - Polyline"),
2503                "", ToolCommandType, "geometric_polyline");
2504   createAction(MI_GeometricArc, QT_TR_NOOP("Geometric Tool - Arc"), "",
2505                ToolCommandType, "geometric_arc");
2506   createAction(MI_GeometricMultiArc, QT_TR_NOOP("Geometric Tool - MultiArc"),
2507                "", ToolCommandType, "geometric_multiarc");
2508   createAction(MI_GeometricPolygon, QT_TR_NOOP("Geometric Tool - Polygon"), "",
2509                ToolCommandType, "geometric_polygon");
2510 
2511   /*-- Type tool + style switching shortcuts --*/
2512   createAction(MI_TypeNextStyle, QT_TR_NOOP("Type Tool - Next Style"), "",
2513                ToolCommandType);
2514   createAction(MI_TypeOblique, QT_TR_NOOP("Type Tool - Oblique"), "",
2515                ToolCommandType);
2516   createAction(MI_TypeRegular, QT_TR_NOOP("Type Tool - Regular"), "",
2517                ToolCommandType);
2518   createAction(MI_TypeBoldOblique, QT_TR_NOOP("Type Tool - Bold Oblique"), "",
2519                ToolCommandType);
2520   createAction(MI_TypeBold, QT_TR_NOOP("Type Tool - Bold"), "",
2521                ToolCommandType);
2522 
2523   /*-- Fill tool + type/mode switching shortcuts --*/
2524   createAction(MI_FillNextType, QT_TR_NOOP("Fill Tool - Next Type"), "",
2525                ToolCommandType);
2526   createAction(MI_FillNormal, QT_TR_NOOP("Fill Tool - Normal"), "",
2527                ToolCommandType, "fill_normal");
2528   createAction(MI_FillRectangular, QT_TR_NOOP("Fill Tool - Rectangular"), "",
2529                ToolCommandType, "fill_rectangular");
2530   createAction(MI_FillFreehand, QT_TR_NOOP("Fill Tool - Freehand"), "",
2531                ToolCommandType, "fill_freehand");
2532   createAction(MI_FillPolyline, QT_TR_NOOP("Fill Tool - Polyline"), "",
2533                ToolCommandType, "fill_polyline");
2534   createAction(MI_FillNextMode, QT_TR_NOOP("Fill Tool - Next Mode"), "",
2535                ToolCommandType);
2536   createAction(MI_FillAreas, QT_TR_NOOP("Fill Tool - Areas"), "",
2537                ToolCommandType, "fill_mode_areas");
2538   createAction(MI_FillLines, QT_TR_NOOP("Fill Tool - Lines"), "",
2539                ToolCommandType, "fill_mode_lines");
2540   createAction(MI_FillLinesAndAreas, QT_TR_NOOP("Fill Tool - Lines & Areas"),
2541                "", ToolCommandType, "fill_mode_lines_areas");
2542 
2543   /*-- Eraser tool + type switching shortcuts --*/
2544   createAction(MI_EraserNextType, QT_TR_NOOP("Eraser Tool - Next Type"), "",
2545                ToolCommandType);
2546   createAction(MI_EraserNormal, QT_TR_NOOP("Eraser Tool - Normal"), "",
2547                ToolCommandType, "eraser_normal");
2548   createAction(MI_EraserRectangular, QT_TR_NOOP("Eraser Tool - Rectangular"),
2549                "", ToolCommandType, "eraser_rectangular");
2550   createAction(MI_EraserFreehand, QT_TR_NOOP("Eraser Tool - Freehand"), "",
2551                ToolCommandType, "eraser_freehand");
2552   createAction(MI_EraserPolyline, QT_TR_NOOP("Eraser Tool - Polyline"), "",
2553                ToolCommandType, "eraser_polyline");
2554   createAction(MI_EraserSegment, QT_TR_NOOP("Eraser Tool - Segment"), "",
2555                ToolCommandType, "eraser_segment");
2556 
2557   /*-- Tape tool + type/mode switching shortcuts --*/
2558   createAction(MI_TapeNextType, QT_TR_NOOP("Tape Tool - Next Type"), "",
2559                ToolCommandType);
2560   createAction(MI_TapeNormal, QT_TR_NOOP("Tape Tool - Normal"), "",
2561                ToolCommandType);
2562   createAction(MI_TapeRectangular, QT_TR_NOOP("Tape Tool - Rectangular"), "",
2563                ToolCommandType);
2564   createAction(MI_TapeNextMode, QT_TR_NOOP("Tape Tool - Next Mode"), "",
2565                ToolCommandType);
2566   createAction(MI_TapeEndpointToEndpoint,
2567                QT_TR_NOOP("Tape Tool - Endpoint to Endpoint"), "",
2568                ToolCommandType);
2569   createAction(MI_TapeEndpointToLine,
2570                QT_TR_NOOP("Tape Tool - Endpoint to Line"), "", ToolCommandType);
2571   createAction(MI_TapeLineToLine, QT_TR_NOOP("Tape Tool - Line to Line"), "",
2572                ToolCommandType);
2573 
2574   /*-- Style Picker tool + mode switching shortcuts --*/
2575   createAction(MI_PickStyleNextMode,
2576                QT_TR_NOOP("Style Picker Tool - Next Mode"), "",
2577                ToolCommandType);
2578   createAction(MI_PickStyleAreas, QT_TR_NOOP("Style Picker Tool - Areas"), "",
2579                ToolCommandType);
2580   createAction(MI_PickStyleLines, QT_TR_NOOP("Style Picker Tool - Lines"), "",
2581                ToolCommandType);
2582   createAction(MI_PickStyleLinesAndAreas,
2583                QT_TR_NOOP("Style Picker Tool - Lines & Areas"), "",
2584                ToolCommandType);
2585 
2586   /*-- RGB Picker tool + type switching shortcuts --*/
2587   createAction(MI_RGBPickerNextType, QT_TR_NOOP("RGB Picker Tool - Next Type"),
2588                "", ToolCommandType);
2589   createAction(MI_RGBPickerNormal, QT_TR_NOOP("RGB Picker Tool - Normal"), "",
2590                ToolCommandType);
2591   createAction(MI_RGBPickerRectangular,
2592                QT_TR_NOOP("RGB Picker Tool - Rectangular"), "",
2593                ToolCommandType);
2594   createAction(MI_RGBPickerFreehand, QT_TR_NOOP("RGB Picker Tool - Freehand"),
2595                "", ToolCommandType);
2596   createAction(MI_RGBPickerPolyline, QT_TR_NOOP("RGB Picker Tool - Polyline"),
2597                "", ToolCommandType);
2598 
2599   /*-- Skeleton tool + mode switching shortcuts --*/
2600   createAction(MI_SkeletonNextMode, QT_TR_NOOP("Skeleton Tool - Next Mode"), "",
2601                ToolCommandType);
2602   createAction(MI_SkeletonBuildSkeleton,
2603                QT_TR_NOOP("Skeleton Tool - Build Skeleton"), "",
2604                ToolCommandType);
2605   createAction(MI_SkeletonAnimate, QT_TR_NOOP("Skeleton Tool - Animate"), "",
2606                ToolCommandType);
2607   createAction(MI_SkeletonInverseKinematics,
2608                QT_TR_NOOP("Skeleton Tool - Inverse Kinematics"), "",
2609                ToolCommandType);
2610 
2611   /*-- Plastic tool + mode switching shortcuts --*/
2612   createAction(MI_PlasticNextMode, QT_TR_NOOP("Plastic Tool - Next Mode"), "",
2613                ToolCommandType);
2614   createAction(MI_PlasticEditMesh, QT_TR_NOOP("Plastic Tool - Edit Mesh"), "",
2615                ToolCommandType);
2616   createAction(MI_PlasticPaintRigid, QT_TR_NOOP("Plastic Tool - Paint Rigid"),
2617                "", ToolCommandType);
2618   createAction(MI_PlasticBuildSkeleton,
2619                QT_TR_NOOP("Plastic Tool - Build Skeleton"), "",
2620                ToolCommandType);
2621   createAction(MI_PlasticAnimate, QT_TR_NOOP("Plastic Tool - Animate"), "",
2622                ToolCommandType);
2623 
2624   // Tool Modifiers
2625 
2626   createToolOptionsAction(MI_SelectNextGuideStroke,
2627                           QT_TR_NOOP("Select Next Frame Guide Stroke"), "");
2628   createToolOptionsAction(MI_SelectPrevGuideStroke,
2629                           QT_TR_NOOP("Select Previous Frame Guide Stroke"), "");
2630   createToolOptionsAction(
2631       MI_SelectBothGuideStrokes,
2632       QT_TRANSLATE_NOOP("MainWindow",
2633                         "Select Prev && Next Frame Guide Strokes"),
2634       "");
2635   createToolOptionsAction(MI_SelectGuideStrokeReset,
2636                           QT_TR_NOOP("Reset Guide Stroke Selections"), "");
2637   createToolOptionsAction(MI_TweenGuideStrokes,
2638                           QT_TR_NOOP("Tween Selected Guide Strokes"), "");
2639   createToolOptionsAction(MI_TweenGuideStrokeToSelected,
2640                           QT_TR_NOOP("Tween Guide Strokes to Selected"), "");
2641   createToolOptionsAction(MI_SelectGuidesAndTweenMode,
2642                           QT_TR_NOOP("Select Guide Strokes && Tween Mode"), "");
2643   createToolOptionsAction(MI_FlipNextGuideStroke,
2644                           QT_TR_NOOP("Flip Next Guide Stroke Direction"), "");
2645   createToolOptionsAction(MI_FlipPrevGuideStroke,
2646                           QT_TR_NOOP("Flip Previous Guide Stroke Direction"),
2647                           "");
2648   createToolOptionsAction("A_ToolOption_GlobalKey", QT_TR_NOOP("Global Key"),
2649                           "");
2650 
2651   createToolOptionsAction("A_IncreaseMaxBrushThickness",
2652                           QT_TR_NOOP("Brush size - Increase max"), "I");
2653   createToolOptionsAction("A_DecreaseMaxBrushThickness",
2654                           QT_TR_NOOP("Brush size - Decrease max"), "U");
2655   createToolOptionsAction("A_IncreaseMinBrushThickness",
2656                           QT_TR_NOOP("Brush size - Increase min"), "J");
2657   createToolOptionsAction("A_DecreaseMinBrushThickness",
2658                           QT_TR_NOOP("Brush size - Decrease min"), "H");
2659   createToolOptionsAction("A_IncreaseBrushHardness",
2660                           QT_TR_NOOP("Brush hardness - Increase"), "");
2661   createToolOptionsAction("A_DecreaseBrushHardness",
2662                           QT_TR_NOOP("Brush hardness - Decrease"), "");
2663   createToolOptionsAction("A_ToolOption_SnapSensitivity",
2664                           QT_TR_NOOP("Snap Sensitivity"), "");
2665   createToolOptionsAction("A_ToolOption_AutoGroup", QT_TR_NOOP("Auto Group"),
2666                           "");
2667   createToolOptionsAction("A_ToolOption_BreakSharpAngles",
2668                           QT_TR_NOOP("Break sharp angles"), "");
2669   createToolOptionsAction("A_ToolOption_FrameRange", QT_TR_NOOP("Frame range"),
2670                           "F6");
2671   createToolOptionsAction("A_ToolOption_IK", QT_TR_NOOP("Inverse Kinematics"),
2672                           "");
2673   createToolOptionsAction("A_ToolOption_Invert", QT_TR_NOOP("Invert"), "");
2674   createToolOptionsAction("A_ToolOption_Manual", QT_TR_NOOP("Manual"), "");
2675   createToolOptionsAction("A_ToolOption_OnionSkin", QT_TR_NOOP("Onion skin"),
2676                           "");
2677   createToolOptionsAction("A_ToolOption_Orientation", QT_TR_NOOP("Orientation"),
2678                           "");
2679   createToolOptionsAction("A_ToolOption_PencilMode", QT_TR_NOOP("Pencil Mode"),
2680                           "");
2681   createToolOptionsAction("A_ToolOption_PreserveThickness",
2682                           QT_TR_NOOP("Preserve Thickness"), "");
2683   createToolOptionsAction("A_ToolOption_PressureSensitivity",
2684                           QT_TR_NOOP("Pressure Sensitivity"), "Shift+P");
2685   createToolOptionsAction("A_ToolOption_SegmentInk", QT_TR_NOOP("Segment Ink"),
2686                           "F8");
2687   createToolOptionsAction("A_ToolOption_Selective", QT_TR_NOOP("Selective"),
2688                           "F7");
2689   createToolOptionsAction("A_ToolOption_DrawOrder",
2690                           QT_TR_NOOP("Brush Tool - Draw Order"), "");
2691   createToolOptionsAction("A_ToolOption_Smooth", QT_TR_NOOP("Smooth"), "");
2692   createToolOptionsAction("A_ToolOption_Snap", QT_TR_NOOP("Snap"), "");
2693   createToolOptionsAction("A_ToolOption_AutoSelectDrawing",
2694                           QT_TR_NOOP("Auto Select Drawing"), "");
2695   createToolOptionsAction("A_ToolOption_Autofill", QT_TR_NOOP("Auto Fill"), "");
2696   createToolOptionsAction("A_ToolOption_JoinVectors",
2697                           QT_TR_NOOP("Join Vectors"), "");
2698   createToolOptionsAction("A_ToolOption_ShowOnlyActiveSkeleton",
2699                           QT_TR_NOOP("Show Only Active Skeleton"), "");
2700   createToolOptionsAction("A_ToolOption_RasterEraser",
2701                           QT_TR_NOOP("Brush Tool - Eraser (Raster option)"),
2702                           "");
2703   createToolOptionsAction("A_ToolOption_LockAlpha",
2704                           QT_TR_NOOP("Brush Tool - Lock Alpha"), "");
2705   createToolOptionsAction("A_ToolOption_BrushPreset",
2706                           QT_TR_NOOP("Brush Preset"), "");
2707   createToolOptionsAction("A_ToolOption_GeometricShape",
2708                           QT_TR_NOOP("Geometric Shape"), "");
2709   createToolOptionsAction("A_ToolOption_GeometricShape:Rectangle",
2710                           QT_TR_NOOP("Geometric Shape Rectangle"), "");
2711   createToolOptionsAction("A_ToolOption_GeometricShape:Circle",
2712                           QT_TR_NOOP("Geometric Shape Circle"), "");
2713   createToolOptionsAction("A_ToolOption_GeometricShape:Ellipse",
2714                           QT_TR_NOOP("Geometric Shape Ellipse"), "");
2715   createToolOptionsAction("A_ToolOption_GeometricShape:Line",
2716                           QT_TR_NOOP("Geometric Shape Line"), "");
2717   createToolOptionsAction("A_ToolOption_GeometricShape:Polyline",
2718                           QT_TR_NOOP("Geometric Shape Polyline"), "");
2719   createToolOptionsAction("A_ToolOption_GeometricShape:Arc",
2720                           QT_TR_NOOP("Geometric Shape Arc"), "");
2721   createToolOptionsAction("A_ToolOption_GeometricShape:MultiArc",
2722                           QT_TR_NOOP("Geometric Shape MultiArc"), "");
2723   createToolOptionsAction("A_ToolOption_GeometricShape:Polygon",
2724                           QT_TR_NOOP("Geometric Shape Polygon"), "");
2725   createToolOptionsAction("A_ToolOption_GeometricEdge",
2726                           QT_TR_NOOP("Geometric Edge"), "");
2727   createToolOptionsAction("A_ToolOption_Mode", QT_TR_NOOP("Mode"), "");
2728   menuAct = createToolOptionsAction("A_ToolOption_Mode:Areas",
2729                                     QT_TR_NOOP("Mode - Areas"), "");
2730   menuAct->setIcon(createQIcon("mode_areas"));
2731   menuAct = createToolOptionsAction("A_ToolOption_Mode:Lines",
2732                                     QT_TR_NOOP("Mode - Lines"), "");
2733   menuAct->setIcon(createQIcon("mode_lines"));
2734   menuAct = createToolOptionsAction("A_ToolOption_Mode:Lines & Areas",
2735                                     QT_TR_NOOP("Mode - Lines && Areas"), "");
2736   menuAct->setIcon(createQIcon("mode_areas_lines"));
2737   createToolOptionsAction("A_ToolOption_Mode:Endpoint to Endpoint",
2738                           QT_TR_NOOP("Mode - Endpoint to Endpoint"), "");
2739   createToolOptionsAction("A_ToolOption_Mode:Endpoint to Line",
2740                           QT_TR_NOOP("Mode - Endpoint to Line"), "");
2741   createToolOptionsAction("A_ToolOption_Mode:Line to Line",
2742                           QT_TR_NOOP("Mode - Line to Line"), "");
2743   createToolOptionsAction("A_ToolOption_Type", QT_TR_NOOP("Type"), "");
2744 
2745   menuAct = createToolOptionsAction("A_ToolOption_Type:Normal",
2746                                     QT_TR_NOOP("Type - Normal"), "");
2747   menuAct->setIcon(createQIcon("type_normal"));
2748 
2749   menuAct = createToolOptionsAction("A_ToolOption_Type:Rectangular",
2750                                     QT_TR_NOOP("Type - Rectangular"), "F5");
2751   menuAct->setIcon(createQIcon("type_rectangular"));
2752 
2753   menuAct = createToolOptionsAction("A_ToolOption_Type:Freehand",
2754                                     QT_TR_NOOP("Type - Freehand"), "");
2755   menuAct->setIcon(createQIcon("type_lasso"));
2756 
2757   menuAct = createToolOptionsAction("A_ToolOption_Type:Polyline",
2758                                     QT_TR_NOOP("Type - Polyline"), "");
2759   menuAct->setIcon(createQIcon("type_polyline"));
2760   menuAct = createToolOptionsAction("A_ToolOption_Type:Segment",
2761                                     QT_TR_NOOP("Type - Segment"), "");
2762   menuAct->setIcon(createQIcon("type_erase_segment"));
2763 
2764   createToolOptionsAction("A_ToolOption_TypeFont", QT_TR_NOOP("TypeTool Font"),
2765                           "");
2766   createToolOptionsAction("A_ToolOption_TypeSize", QT_TR_NOOP("TypeTool Size"),
2767                           "");
2768   createToolOptionsAction("A_ToolOption_TypeStyle",
2769                           QT_TR_NOOP("TypeTool Style"), "");
2770   createToolOptionsAction("A_ToolOption_TypeStyle:Oblique",
2771                           QT_TR_NOOP("TypeTool Style - Oblique"), "");
2772   createToolOptionsAction("A_ToolOption_TypeStyle:Regular",
2773                           QT_TR_NOOP("TypeTool Style - Regular"), "");
2774   createToolOptionsAction("A_ToolOption_TypeStyle:Bold Oblique",
2775                           QT_TR_NOOP("TypeTool Style - Bold Oblique"), "");
2776   createToolOptionsAction("A_ToolOption_TypeStyle:Bold",
2777                           QT_TR_NOOP("TypeTool Style - Bold"), "");
2778 
2779   createToolOptionsAction("A_ToolOption_EditToolActiveAxis",
2780                           QT_TR_NOOP("Active Axis"), "");
2781   createToolOptionsAction("A_ToolOption_EditToolActiveAxis:Position",
2782                           QT_TR_NOOP("Active Axis - Position"), "");
2783   createToolOptionsAction("A_ToolOption_EditToolActiveAxis:Rotation",
2784                           QT_TR_NOOP("Active Axis - Rotation"), "");
2785   createToolOptionsAction("A_ToolOption_EditToolActiveAxis:Scale",
2786                           QT_TR_NOOP("Active Axis - Scale"), "");
2787   createToolOptionsAction("A_ToolOption_EditToolActiveAxis:Shear",
2788                           QT_TR_NOOP("Active Axis - Shear"), "");
2789   createToolOptionsAction("A_ToolOption_EditToolActiveAxis:Center",
2790                           QT_TR_NOOP("Active Axis - Center"), "");
2791   createToolOptionsAction("A_ToolOption_EditToolActiveAxis:All",
2792                           QT_TR_NOOP("Active Axis - All"), "");
2793 
2794   createToolOptionsAction("A_ToolOption_SkeletonMode",
2795                           QT_TR_NOOP("Skeleton Mode"), "");
2796   createToolOptionsAction("A_ToolOption_SkeletonMode:Edit Mesh",
2797                           QT_TR_NOOP("Edit Mesh Mode"), "");
2798   createToolOptionsAction("A_ToolOption_SkeletonMode:Paint Rigid",
2799                           QT_TR_NOOP("Paint Rigid Mode"), "");
2800   createToolOptionsAction("A_ToolOption_SkeletonMode:Build Skeleton",
2801                           QT_TR_NOOP("Build Skeleton Mode"), "");
2802   createToolOptionsAction("A_ToolOption_SkeletonMode:Animate",
2803                           QT_TR_NOOP("Animate Mode"), "");
2804   createToolOptionsAction("A_ToolOption_SkeletonMode:Inverse Kinematics",
2805                           QT_TR_NOOP("Inverse Kinematics Mode"), "");
2806   createToolOptionsAction("A_ToolOption_AutoSelect:None",
2807                           QT_TR_NOOP("None Pick Mode"), "");
2808   createToolOptionsAction("A_ToolOption_AutoSelect:Column",
2809                           QT_TR_NOOP("Column Pick Mode"), "");
2810   createToolOptionsAction("A_ToolOption_AutoSelect:Pegbar",
2811                           QT_TR_NOOP("Pegbar Pick Mode"), "");
2812   menuAct = createToolOptionsAction("A_ToolOption_PickScreen",
2813                                     QT_TR_NOOP("Pick Screen"), "");
2814   menuAct->setIcon(createQIcon("pickscreen"));
2815   createToolOptionsAction("A_ToolOption_Meshify", QT_TR_NOOP("Create Mesh"),
2816                           "");
2817 
2818   menuAct =
2819       createToolOptionsAction("A_ToolOption_AutopaintLines",
2820                               QT_TR_NOOP("Fill Tool - Autopaint Lines"), "");
2821   menuAct->setIcon(createQIcon("fill_auto"));
2822 
2823   // Visualization
2824 
2825   createViewerAction(V_ZoomIn, QT_TR_NOOP("Zoom In"), "+");
2826   createViewerAction(V_ZoomOut, QT_TR_NOOP("Zoom Out"), "-");
2827   createViewerAction(V_ViewReset, QT_TR_NOOP("Reset View"), "Alt+0");
2828   createViewerAction(V_ZoomFit, QT_TR_NOOP("Fit to Window"), "Alt+9");
2829   createViewerAction(V_ZoomReset, QT_TR_NOOP("Reset Zoom"), "");
2830   createViewerAction(V_RotateReset, QT_TR_NOOP("Reset Rotation"), "");
2831   createViewerAction(V_PositionReset, QT_TR_NOOP("Reset Position"), "");
2832 
2833   createViewerAction(V_ActualPixelSize, QT_TR_NOOP("Actual Pixel Size"), "N");
2834   createViewerAction(V_FlipX, QT_TR_NOOP("Flip Viewer Horizontally"), "");
2835   createViewerAction(V_FlipY, QT_TR_NOOP("Flip Viewer Vertically"), "");
2836   createViewerAction(V_ShowHideFullScreen, QT_TR_NOOP("Show//Hide Full Screen"),
2837                      "Alt+F");
2838   CommandManager::instance()->setToggleTexts(V_ShowHideFullScreen,
2839                                              tr("Full Screen Mode"),
2840                                              tr("Exit Full Screen Mode"));
2841   createViewerAction(MI_CompareToSnapshot, QT_TR_NOOP("Compare to Snapshot"),
2842                      "");
2843 
2844   // Following actions are for adding "Visualization" menu items to the command
2845   // bar. They are separated from the original actions in order to avoid
2846   // assigning shortcut keys. They must be triggered only from pressing buttons
2847   // in the command bar. Assinging shortcut keys and registering as MenuItem
2848   // will break a logic of ShortcutZoomer. So here we register separate items
2849   // and bypass the command.
2850   createVisualizationButtonAction(VB_ViewReset, QT_TR_NOOP("Reset View"),
2851                                   "reset");
2852   createVisualizationButtonAction(VB_ZoomFit, QT_TR_NOOP("Fit to Window"),
2853                                   "fit_to_window");
2854   createVisualizationButtonAction(VB_ZoomReset, QT_TR_NOOP("Reset Zoom"));
2855   createVisualizationButtonAction(VB_RotateReset, QT_TR_NOOP("Reset Rotation"));
2856   createVisualizationButtonAction(VB_PositionReset,
2857                                   QT_TR_NOOP("Reset Position"));
2858   createVisualizationButtonAction(
2859       VB_ActualPixelSize, QT_TR_NOOP("Actual Pixel Size"), "actual_pixel_size");
2860   createVisualizationButtonAction(
2861       VB_FlipX, QT_TR_NOOP("Flip Viewer Horizontally"), "fliphoriz_off");
2862   createVisualizationButtonAction(
2863       VB_FlipY, QT_TR_NOOP("Flip Viewer Vertically"), "flipvert_off");
2864 
2865   // Misc
2866 
2867   menuAct =
2868       createToggle(MI_TouchGestureControl, QT_TR_NOOP("&Touch Gesture Control"),
2869                    "", TouchGestureControl ? 1 : 0, MiscCommandType, "touch");
2870   menuAct->setEnabled(true);
2871   ;
2872   createMiscAction(MI_CameraStage, QT_TR_NOOP("&Camera Settings..."), "");
2873   menuAct =
2874       createMiscAction(MI_RefreshTree, QT_TR_NOOP("Refresh Folder Tree"), "");
2875   menuAct->setIconText(tr("Refresh"));
2876   menuAct->setIcon(createQIcon("refresh", false, true));
2877   createMiscAction("A_FxSchematicToggle",
2878                    QT_TR_NOOP("Toggle FX/Stage schematic"), "");
2879 
2880   // RGBA
2881 
2882   createRGBAAction(MI_RedChannel, QT_TR_NOOP("Red Channel"), "");
2883   createRGBAAction(MI_GreenChannel, QT_TR_NOOP("Green Channel"), "");
2884   createRGBAAction(MI_BlueChannel, QT_TR_NOOP("Blue Channel"), "");
2885   createRGBAAction(MI_MatteChannel, QT_TR_NOOP("Alpha Channel"), "");
2886   createRGBAAction(MI_RedChannelGreyscale, QT_TR_NOOP("Red Channel Greyscale"),
2887                    "");
2888   createRGBAAction(MI_GreenChannelGreyscale,
2889                    QT_TR_NOOP("Green Channel Greyscale"), "");
2890   createRGBAAction(MI_BlueChannelGreyscale,
2891                    QT_TR_NOOP("Blue Channel Greyscale"), "");
2892 
2893   // Stop Motion
2894 
2895 #if defined(x64)
2896   createStopMotionAction(MI_StopMotionExportImageSequence,
2897                          QT_TR_NOOP("&Export Stop Motion Image Sequence"), "");
2898   createStopMotionAction(MI_StopMotionCapture,
2899                          QT_TR_NOOP("Capture Stop Motion Frame"), "");
2900   createStopMotionAction(MI_StopMotionRaiseOpacity,
2901                          QT_TR_NOOP("Raise Stop Motion Opacity"), "");
2902   createStopMotionAction(MI_StopMotionLowerOpacity,
2903                          QT_TR_NOOP("Lower Stop Motion Opacity"), "");
2904   createStopMotionAction(MI_StopMotionToggleLiveView,
2905                          QT_TR_NOOP("Toggle Stop Motion Live View"), "");
2906 #ifdef WITH_CANON
2907   createStopMotionAction(MI_StopMotionToggleZoom,
2908                          QT_TR_NOOP("Toggle Stop Motion Zoom"), "");
2909   createStopMotionAction(MI_StopMotionPickFocusCheck,
2910                          QT_TR_NOOP("Pick Focus Check Location"), "");
2911 #endif  // WITH_CANON
2912   createStopMotionAction(MI_StopMotionLowerSubsampling,
2913                          QT_TR_NOOP("Lower Stop Motion Level Subsampling"), "");
2914   createStopMotionAction(MI_StopMotionRaiseSubsampling,
2915                          QT_TR_NOOP("Raise Stop Motion Level Subsampling"), "");
2916   createStopMotionAction(MI_StopMotionJumpToCamera,
2917                          QT_TR_NOOP("Go to Stop Motion Insert Frame"), "");
2918   createStopMotionAction(MI_StopMotionRemoveFrame,
2919                          QT_TR_NOOP("Remove frame before Stop Motion Camera"),
2920                          "");
2921   createStopMotionAction(MI_StopMotionNextFrame,
2922                          QT_TR_NOOP("Next Frame including Stop Motion Camera"),
2923                          "");
2924   createStopMotionAction(MI_StopMotionToggleUseLiveViewImages,
2925                          QT_TR_NOOP("Show original live view images."), "");
2926 #endif  // x64
2927 }
2928 
2929 //-----------------------------------------------------------------------------
2930 
onInkCheckTriggered(bool on)2931 void MainWindow::onInkCheckTriggered(bool on) {
2932   if (!on) return;
2933   QAction *ink1CheckAction =
2934       CommandManager::instance()->getAction(MI_Ink1Check);
2935   if (ink1CheckAction) ink1CheckAction->setChecked(false);
2936 }
2937 
2938 //-----------------------------------------------------------------------------
2939 
onInk1CheckTriggered(bool on)2940 void MainWindow::onInk1CheckTriggered(bool on) {
2941   if (!on) return;
2942   QAction *inkCheckAction = CommandManager::instance()->getAction(MI_ICheck);
2943   if (inkCheckAction) inkCheckAction->setChecked(false);
2944 }
2945 
2946 //-----------------------------------------------------------------------------
2947 /*-- Animate tool + mode switching shortcuts --*/
toggleEditNextMode()2948 void MainWindow::toggleEditNextMode() {
2949   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Edit)
2950     CommandManager::instance()
2951         ->getAction("A_ToolOption_EditToolActiveAxis")
2952         ->trigger();
2953   else
2954     CommandManager::instance()->getAction(T_Edit)->trigger();
2955 }
2956 
toggleEditPosition()2957 void MainWindow::toggleEditPosition() {
2958   CommandManager::instance()->getAction(T_Edit)->trigger();
2959   CommandManager::instance()
2960       ->getAction("A_ToolOption_EditToolActiveAxis:Position")
2961       ->trigger();
2962 }
2963 
toggleEditRotation()2964 void MainWindow::toggleEditRotation() {
2965   CommandManager::instance()->getAction(T_Edit)->trigger();
2966   CommandManager::instance()
2967       ->getAction("A_ToolOption_EditToolActiveAxis:Rotation")
2968       ->trigger();
2969 }
2970 
toggleEditNextScale()2971 void MainWindow::toggleEditNextScale() {
2972   CommandManager::instance()->getAction(T_Edit)->trigger();
2973   CommandManager::instance()
2974       ->getAction("A_ToolOption_EditToolActiveAxis:Scale")
2975       ->trigger();
2976 }
2977 
toggleEditNextShear()2978 void MainWindow::toggleEditNextShear() {
2979   CommandManager::instance()->getAction(T_Edit)->trigger();
2980   CommandManager::instance()
2981       ->getAction("A_ToolOption_EditToolActiveAxis:Shear")
2982       ->trigger();
2983 }
2984 
toggleEditNextCenter()2985 void MainWindow::toggleEditNextCenter() {
2986   CommandManager::instance()->getAction(T_Edit)->trigger();
2987   CommandManager::instance()
2988       ->getAction("A_ToolOption_EditToolActiveAxis:Center")
2989       ->trigger();
2990 }
2991 
toggleEditNextAll()2992 void MainWindow::toggleEditNextAll() {
2993   CommandManager::instance()->getAction(T_Edit)->trigger();
2994   CommandManager::instance()
2995       ->getAction("A_ToolOption_EditToolActiveAxis:All")
2996       ->trigger();
2997 }
2998 
2999 //---------------------------------------------------------------------------------------
3000 /*-- Selection tool + type switching shortcuts --*/
toggleSelectionNextType()3001 void MainWindow::toggleSelectionNextType() {
3002   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Selection)
3003     CommandManager::instance()->getAction("A_ToolOption_Type")->trigger();
3004   else
3005     CommandManager::instance()->getAction(T_Selection)->trigger();
3006 }
3007 
toggleSelectionRectangular()3008 void MainWindow::toggleSelectionRectangular() {
3009   CommandManager::instance()->getAction(T_Selection)->trigger();
3010   CommandManager::instance()
3011       ->getAction("A_ToolOption_Type:Rectangular")
3012       ->trigger();
3013 }
3014 
toggleSelectionFreehand()3015 void MainWindow::toggleSelectionFreehand() {
3016   CommandManager::instance()->getAction(T_Selection)->trigger();
3017   CommandManager::instance()
3018       ->getAction("A_ToolOption_Type:Freehand")
3019       ->trigger();
3020 }
3021 
toggleSelectionPolyline()3022 void MainWindow::toggleSelectionPolyline() {
3023   CommandManager::instance()->getAction(T_Selection)->trigger();
3024   CommandManager::instance()
3025       ->getAction("A_ToolOption_Type:Polyline")
3026       ->trigger();
3027 }
3028 
3029 //---------------------------------------------------------------------------------------
3030 /*-- Geometric tool + shape switching shortcuts --*/
toggleGeometricNextShape()3031 void MainWindow::toggleGeometricNextShape() {
3032   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Geometric)
3033     CommandManager::instance()
3034         ->getAction("A_ToolOption_GeometricShape")
3035         ->trigger();
3036   else
3037     CommandManager::instance()->getAction(T_Geometric)->trigger();
3038 }
3039 
toggleGeometricRectangle()3040 void MainWindow::toggleGeometricRectangle() {
3041   CommandManager::instance()->getAction(T_Geometric)->trigger();
3042   CommandManager::instance()
3043       ->getAction("A_ToolOption_GeometricShape:Rectangle")
3044       ->trigger();
3045 }
3046 
toggleGeometricCircle()3047 void MainWindow::toggleGeometricCircle() {
3048   CommandManager::instance()->getAction(T_Geometric)->trigger();
3049   CommandManager::instance()
3050       ->getAction("A_ToolOption_GeometricShape:Circle")
3051       ->trigger();
3052 }
3053 
toggleGeometricEllipse()3054 void MainWindow::toggleGeometricEllipse() {
3055   CommandManager::instance()->getAction(T_Geometric)->trigger();
3056   CommandManager::instance()
3057       ->getAction("A_ToolOption_GeometricShape:Ellipse")
3058       ->trigger();
3059 }
3060 
toggleGeometricLine()3061 void MainWindow::toggleGeometricLine() {
3062   CommandManager::instance()->getAction(T_Geometric)->trigger();
3063   CommandManager::instance()
3064       ->getAction("A_ToolOption_GeometricShape:Line")
3065       ->trigger();
3066 }
3067 
toggleGeometricPolyline()3068 void MainWindow::toggleGeometricPolyline() {
3069   CommandManager::instance()->getAction(T_Geometric)->trigger();
3070   CommandManager::instance()
3071       ->getAction("A_ToolOption_GeometricShape:Polyline")
3072       ->trigger();
3073 }
3074 
toggleGeometricArc()3075 void MainWindow::toggleGeometricArc() {
3076   CommandManager::instance()->getAction(T_Geometric)->trigger();
3077   CommandManager::instance()
3078       ->getAction("A_ToolOption_GeometricShape:Arc")
3079       ->trigger();
3080 }
3081 
toggleGeometricMultiArc()3082 void MainWindow::toggleGeometricMultiArc() {
3083   CommandManager::instance()->getAction(T_Geometric)->trigger();
3084   CommandManager::instance()
3085       ->getAction("A_ToolOption_GeometricShape:MultiArc")
3086       ->trigger();
3087 }
3088 
toggleGeometricPolygon()3089 void MainWindow::toggleGeometricPolygon() {
3090   CommandManager::instance()->getAction(T_Geometric)->trigger();
3091   CommandManager::instance()
3092       ->getAction("A_ToolOption_GeometricShape:Polygon")
3093       ->trigger();
3094 }
3095 //---------------------------------------------------------------------------------------
3096 /*-- Type tool + mode switching shortcuts --*/
toggleTypeNextStyle()3097 void MainWindow::toggleTypeNextStyle() {
3098   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Type)
3099     CommandManager::instance()->getAction("A_ToolOption_TypeStyle")->trigger();
3100   else
3101     CommandManager::instance()->getAction(T_Type)->trigger();
3102 }
3103 
toggleTypeOblique()3104 void MainWindow::toggleTypeOblique() {
3105   CommandManager::instance()->getAction(T_Type)->trigger();
3106   CommandManager::instance()
3107       ->getAction("A_ToolOption_TypeStyle:Oblique")
3108       ->trigger();
3109 }
3110 
toggleTypeRegular()3111 void MainWindow::toggleTypeRegular() {
3112   CommandManager::instance()->getAction(T_Type)->trigger();
3113   CommandManager::instance()
3114       ->getAction("A_ToolOption_TypeStyle:Regular")
3115       ->trigger();
3116 }
3117 
toggleTypeBoldOblique()3118 void MainWindow::toggleTypeBoldOblique() {
3119   CommandManager::instance()->getAction(T_Type)->trigger();
3120   CommandManager::instance()
3121       ->getAction("A_ToolOption_TypeStyle:Bold Oblique")
3122       ->trigger();
3123 }
3124 
toggleTypeBold()3125 void MainWindow::toggleTypeBold() {
3126   CommandManager::instance()->getAction(T_Type)->trigger();
3127   CommandManager::instance()
3128       ->getAction("A_ToolOption_TypeStyle:Bold")
3129       ->trigger();
3130 }
3131 
3132 //---------------------------------------------------------------------------------------
3133 /*-- Fill tool + type/mode switching shortcuts --*/
toggleFillNextType()3134 void MainWindow::toggleFillNextType() {
3135   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Fill)
3136     CommandManager::instance()->getAction("A_ToolOption_Type")->trigger();
3137   else
3138     CommandManager::instance()->getAction(T_Fill)->trigger();
3139 }
3140 
toggleFillNormal()3141 void MainWindow::toggleFillNormal() {
3142   CommandManager::instance()->getAction(T_Fill)->trigger();
3143   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3144 }
3145 
toggleFillRectangular()3146 void MainWindow::toggleFillRectangular() {
3147   CommandManager::instance()->getAction(T_Fill)->trigger();
3148   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3149   CommandManager::instance()
3150       ->getAction("A_ToolOption_Type:Rectangular")
3151       ->trigger();
3152 }
3153 
toggleFillFreehand()3154 void MainWindow::toggleFillFreehand() {
3155   CommandManager::instance()->getAction(T_Fill)->trigger();
3156   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3157   CommandManager::instance()
3158       ->getAction("A_ToolOption_Type:Freehand")
3159       ->trigger();
3160 }
3161 
toggleFillPolyline()3162 void MainWindow::toggleFillPolyline() {
3163   CommandManager::instance()->getAction(T_Fill)->trigger();
3164   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3165   CommandManager::instance()
3166       ->getAction("A_ToolOption_Type:Polyline")
3167       ->trigger();
3168 }
3169 
toggleFillNextMode()3170 void MainWindow::toggleFillNextMode() {
3171   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Fill)
3172     CommandManager::instance()->getAction("A_ToolOption_Mode")->trigger();
3173   else
3174     CommandManager::instance()->getAction(T_Fill)->trigger();
3175 }
3176 
toggleFillAreas()3177 void MainWindow::toggleFillAreas() {
3178   CommandManager::instance()->getAction(T_Fill)->trigger();
3179   CommandManager::instance()->getAction("A_ToolOption_Mode:Areas")->trigger();
3180 }
3181 
toggleFillLines()3182 void MainWindow::toggleFillLines() {
3183   CommandManager::instance()->getAction(T_Fill)->trigger();
3184   CommandManager::instance()->getAction("A_ToolOption_Mode:Lines")->trigger();
3185 }
3186 
toggleFillLinesAndAreas()3187 void MainWindow::toggleFillLinesAndAreas() {
3188   CommandManager::instance()->getAction(T_Fill)->trigger();
3189   CommandManager::instance()
3190       ->getAction("A_ToolOption_Mode:Lines & Areas")
3191       ->trigger();
3192 }
3193 
3194 //---------------------------------------------------------------------------------------
3195 /*-- Eraser tool + type switching shortcuts --*/
toggleEraserNextType()3196 void MainWindow::toggleEraserNextType() {
3197   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Eraser)
3198     CommandManager::instance()->getAction("A_ToolOption_Type")->trigger();
3199   else
3200     CommandManager::instance()->getAction(T_Eraser)->trigger();
3201 }
3202 
toggleEraserNormal()3203 void MainWindow::toggleEraserNormal() {
3204   CommandManager::instance()->getAction(T_Eraser)->trigger();
3205   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3206 }
3207 
toggleEraserRectangular()3208 void MainWindow::toggleEraserRectangular() {
3209   CommandManager::instance()->getAction(T_Eraser)->trigger();
3210   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3211   CommandManager::instance()
3212       ->getAction("A_ToolOption_Type:Rectangular")
3213       ->trigger();
3214 }
3215 
toggleEraserFreehand()3216 void MainWindow::toggleEraserFreehand() {
3217   CommandManager::instance()->getAction(T_Eraser)->trigger();
3218   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3219   CommandManager::instance()
3220       ->getAction("A_ToolOption_Type:Freehand")
3221       ->trigger();
3222 }
3223 
toggleEraserPolyline()3224 void MainWindow::toggleEraserPolyline() {
3225   CommandManager::instance()->getAction(T_Eraser)->trigger();
3226   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3227   CommandManager::instance()
3228       ->getAction("A_ToolOption_Type:Polyline")
3229       ->trigger();
3230 }
3231 
toggleEraserSegment()3232 void MainWindow::toggleEraserSegment() {
3233   CommandManager::instance()->getAction(T_Eraser)->trigger();
3234   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3235   CommandManager::instance()->getAction("A_ToolOption_Type:Segment")->trigger();
3236 }
3237 //---------------------------------------------------------------------------------------
3238 /*-- Tape tool + type/mode switching shortcuts --*/
toggleTapeNextType()3239 void MainWindow::toggleTapeNextType() {
3240   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Tape)
3241     CommandManager::instance()->getAction("A_ToolOption_Type")->trigger();
3242   else
3243     CommandManager::instance()->getAction(T_Tape)->trigger();
3244 }
3245 
toggleTapeNormal()3246 void MainWindow::toggleTapeNormal() {
3247   CommandManager::instance()->getAction(T_Tape)->trigger();
3248   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3249 }
3250 
toggleTapeRectangular()3251 void MainWindow::toggleTapeRectangular() {
3252   CommandManager::instance()->getAction(T_Tape)->trigger();
3253   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3254   CommandManager::instance()
3255       ->getAction("A_ToolOption_Type:Rectangular")
3256       ->trigger();
3257 }
3258 
toggleTapeNextMode()3259 void MainWindow::toggleTapeNextMode() {
3260   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Tape)
3261     CommandManager::instance()->getAction("A_ToolOption_Mode")->trigger();
3262   else
3263     CommandManager::instance()->getAction(T_Tape)->trigger();
3264 }
3265 
toggleTapeEndpointToEndpoint()3266 void MainWindow::toggleTapeEndpointToEndpoint() {
3267   CommandManager::instance()->getAction(T_Tape)->trigger();
3268   CommandManager::instance()
3269       ->getAction("A_ToolOption_Mode:Endpoint to Endpoint")
3270       ->trigger();
3271 }
3272 
toggleTapeEndpointToLine()3273 void MainWindow::toggleTapeEndpointToLine() {
3274   CommandManager::instance()->getAction(T_Tape)->trigger();
3275   CommandManager::instance()
3276       ->getAction("A_ToolOption_Mode:Endpoint to Line")
3277       ->trigger();
3278 }
3279 
toggleTapeLineToLine()3280 void MainWindow::toggleTapeLineToLine() {
3281   CommandManager::instance()->getAction(T_Tape)->trigger();
3282   CommandManager::instance()
3283       ->getAction("A_ToolOption_Mode:Line to Line")
3284       ->trigger();
3285 }
3286 
3287 //---------------------------------------------------------------------------------------
3288 /*-- Style Picker tool + mode switching shortcuts --*/
togglePickStyleNextMode()3289 void MainWindow::togglePickStyleNextMode() {
3290   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_StylePicker)
3291     CommandManager::instance()->getAction("A_ToolOption_Mode")->trigger();
3292   else
3293     CommandManager::instance()->getAction(T_StylePicker)->trigger();
3294 }
3295 
togglePickStyleAreas()3296 void MainWindow::togglePickStyleAreas() {
3297   CommandManager::instance()->getAction(T_StylePicker)->trigger();
3298   CommandManager::instance()->getAction("A_ToolOption_Mode:Areas")->trigger();
3299 }
3300 
togglePickStyleLines()3301 void MainWindow::togglePickStyleLines() {
3302   CommandManager::instance()->getAction(T_StylePicker)->trigger();
3303   CommandManager::instance()->getAction("A_ToolOption_Mode:Lines")->trigger();
3304 }
3305 
togglePickStyleLinesAndAreas()3306 void MainWindow::togglePickStyleLinesAndAreas() {
3307   CommandManager::instance()->getAction(T_StylePicker)->trigger();
3308   CommandManager::instance()
3309       ->getAction("A_ToolOption_Mode:Lines & Areas")
3310       ->trigger();
3311 }
3312 //-----------------------------------------------------------------------------
3313 /*-- RGB Picker tool + type switching shortcuts --*/
toggleRGBPickerNextType()3314 void MainWindow::toggleRGBPickerNextType() {
3315   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_RGBPicker)
3316     CommandManager::instance()->getAction("A_ToolOption_Type")->trigger();
3317   else
3318     CommandManager::instance()->getAction(T_RGBPicker)->trigger();
3319 }
3320 
toggleRGBPickerNormal()3321 void MainWindow::toggleRGBPickerNormal() {
3322   CommandManager::instance()->getAction(T_RGBPicker)->trigger();
3323   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3324 }
3325 
toggleRGBPickerRectangular()3326 void MainWindow::toggleRGBPickerRectangular() {
3327   CommandManager::instance()->getAction(T_RGBPicker)->trigger();
3328   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3329   CommandManager::instance()
3330       ->getAction("A_ToolOption_Type:Rectangular")
3331       ->trigger();
3332 }
3333 
toggleRGBPickerFreehand()3334 void MainWindow::toggleRGBPickerFreehand() {
3335   CommandManager::instance()->getAction(T_RGBPicker)->trigger();
3336   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3337   CommandManager::instance()
3338       ->getAction("A_ToolOption_Type:Freehand")
3339       ->trigger();
3340 }
3341 
toggleRGBPickerPolyline()3342 void MainWindow::toggleRGBPickerPolyline() {
3343   CommandManager::instance()->getAction(T_RGBPicker)->trigger();
3344   CommandManager::instance()->getAction("A_ToolOption_Type:Normal")->trigger();
3345   CommandManager::instance()
3346       ->getAction("A_ToolOption_Type:Polyline")
3347       ->trigger();
3348 }
3349 //-----------------------------------------------------------------------------
3350 /*-- Skeleton tool + type switching shortcuts --*/
ToggleSkeletonNextMode()3351 void MainWindow::ToggleSkeletonNextMode() {
3352   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Skeleton)
3353     CommandManager::instance()
3354         ->getAction("A_ToolOption_SkeletonMode")
3355         ->trigger();
3356   else
3357     CommandManager::instance()->getAction(T_Skeleton)->trigger();
3358 }
3359 
ToggleSkeletonBuildSkeleton()3360 void MainWindow::ToggleSkeletonBuildSkeleton() {
3361   CommandManager::instance()->getAction(T_Skeleton)->trigger();
3362   CommandManager::instance()
3363       ->getAction("A_ToolOption_SkeletonMode:Build Skeleton")
3364       ->trigger();
3365 }
3366 
ToggleSkeletonAnimate()3367 void MainWindow::ToggleSkeletonAnimate() {
3368   CommandManager::instance()->getAction(T_Skeleton)->trigger();
3369   CommandManager::instance()
3370       ->getAction("A_ToolOption_SkeletonMode:Animate")
3371       ->trigger();
3372 }
3373 
ToggleSkeletonInverseKinematics()3374 void MainWindow::ToggleSkeletonInverseKinematics() {
3375   CommandManager::instance()->getAction(T_Skeleton)->trigger();
3376   CommandManager::instance()
3377       ->getAction("A_ToolOption_SkeletonMode:Inverse Kinematics")
3378       ->trigger();
3379 }
3380 
3381 //-----------------------------------------------------------------------------
3382 /*-- Plastic tool + mode switching shortcuts --*/
TogglePlasticNextMode()3383 void MainWindow::TogglePlasticNextMode() {
3384   if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Plastic)
3385     CommandManager::instance()
3386         ->getAction("A_ToolOption_SkeletonMode")
3387         ->trigger();
3388   else
3389     CommandManager::instance()->getAction(T_Plastic)->trigger();
3390 }
3391 
TogglePlasticEditMesh()3392 void MainWindow::TogglePlasticEditMesh() {
3393   CommandManager::instance()->getAction(T_Plastic)->trigger();
3394   CommandManager::instance()
3395       ->getAction("A_ToolOption_SkeletonMode:Edit Mesh")
3396       ->trigger();
3397 }
3398 
TogglePlasticPaintRigid()3399 void MainWindow::TogglePlasticPaintRigid() {
3400   CommandManager::instance()->getAction(T_Plastic)->trigger();
3401   CommandManager::instance()
3402       ->getAction("A_ToolOption_SkeletonMode:Paint Rigid")
3403       ->trigger();
3404 }
3405 
TogglePlasticBuildSkeleton()3406 void MainWindow::TogglePlasticBuildSkeleton() {
3407   CommandManager::instance()->getAction(T_Plastic)->trigger();
3408   CommandManager::instance()
3409       ->getAction("A_ToolOption_SkeletonMode:Build Skeleton")
3410       ->trigger();
3411 }
3412 
TogglePlasticAnimate()3413 void MainWindow::TogglePlasticAnimate() {
3414   CommandManager::instance()->getAction(T_Plastic)->trigger();
3415   CommandManager::instance()
3416       ->getAction("A_ToolOption_SkeletonMode:Animate")
3417       ->trigger();
3418 }
3419 
3420 //-----------------------------------------------------------------------------
3421 
onNewVectorLevelButtonPressed()3422 void MainWindow::onNewVectorLevelButtonPressed() {
3423   int defaultLevelType = Preferences::instance()->getDefLevelType();
3424   Preferences::instance()->setValue(DefLevelType, PLI_XSHLEVEL);
3425   CommandManager::instance()->execute("MI_NewLevel");
3426   Preferences::instance()->setValue(DefLevelType, defaultLevelType);
3427 }
3428 
3429 //-----------------------------------------------------------------------------
3430 
onNewToonzRasterLevelButtonPressed()3431 void MainWindow::onNewToonzRasterLevelButtonPressed() {
3432   int defaultLevelType = Preferences::instance()->getDefLevelType();
3433   Preferences::instance()->setValue(DefLevelType, TZP_XSHLEVEL);
3434   CommandManager::instance()->execute("MI_NewLevel");
3435   Preferences::instance()->setValue(DefLevelType, defaultLevelType);
3436 }
3437 
3438 //-----------------------------------------------------------------------------
3439 
onNewRasterLevelButtonPressed()3440 void MainWindow::onNewRasterLevelButtonPressed() {
3441   int defaultLevelType = Preferences::instance()->getDefLevelType();
3442   Preferences::instance()->setValue(DefLevelType, OVL_XSHLEVEL);
3443   CommandManager::instance()->execute("MI_NewLevel");
3444   Preferences::instance()->setValue(DefLevelType, defaultLevelType);
3445 }
3446 
3447 //-----------------------------------------------------------------------------
3448 // delete unused files / folders in the cache
clearCacheFolder()3449 void MainWindow::clearCacheFolder() {
3450   // currently cache folder is used for following purposes
3451   // 1. $CACHE/[ProcessID] : for disk swap of image cache.
3452   //    To be deleted on exit. Remains on crash.
3453   // 2. $CACHE/ffmpeg : ffmpeg cache.
3454   //    To be cleared on the end of rendering, on exist and on launch.
3455   // 3. $CACHE/temp : untitled scene data.
3456   //    To be deleted on switching or exiting scenes. Remains on crash.
3457 
3458   // So, this function will delete all files / folders in $CACHE
3459   // except the following items:
3460   // 1. $CACHE/[Current ProcessID]
3461   // 2. $CACHE/temp/[Current scene folder] if the current scene is untitled
3462 
3463   TFilePath cacheRoot = ToonzFolder::getCacheRootFolder();
3464   if (cacheRoot.isEmpty()) cacheRoot = TEnv::getStuffDir() + "cache";
3465 
3466   TFilePathSet filesToBeRemoved;
3467 
3468   TSystem::readDirectory(filesToBeRemoved, cacheRoot, false);
3469 
3470   // keep the imagecache folder
3471   filesToBeRemoved.remove(cacheRoot + std::to_string(TSystem::getProcessId()));
3472   // keep the untitled scene data folder
3473   if (TApp::instance()->getCurrentScene()->getScene()->isUntitled()) {
3474     filesToBeRemoved.remove(cacheRoot + "temp");
3475     TFilePathSet untitledData =
3476         TSystem::readDirectory(cacheRoot + "temp", false);
3477     untitledData.remove(TApp::instance()
3478                             ->getCurrentScene()
3479                             ->getScene()
3480                             ->getScenePath()
3481                             .getParentDir());
3482     filesToBeRemoved.insert(filesToBeRemoved.end(), untitledData.begin(),
3483                             untitledData.end());
3484   }
3485 
3486   // return if there is no files/folders to be deleted
3487   if (filesToBeRemoved.size() == 0) {
3488     QMessageBox::information(
3489         this, tr("Clear Cache Folder"),
3490         tr("There are no unused items in the cache folder."));
3491     return;
3492   }
3493 
3494   QString message(tr("Deleting the following items:\n"));
3495   int count = 0;
3496   for (const auto &fileToBeRemoved : filesToBeRemoved) {
3497     QString dirPrefix =
3498         (TFileStatus(fileToBeRemoved).isDirectory()) ? tr("<DIR> ") : "";
3499     message +=
3500         "   " + dirPrefix + (fileToBeRemoved - cacheRoot).getQString() + "\n";
3501     count++;
3502     if (count == 5) break;
3503   }
3504   if (filesToBeRemoved.size() > 5)
3505     message +=
3506         tr("   ... and %1 more items\n").arg(filesToBeRemoved.size() - 5);
3507 
3508   message +=
3509       tr("\nAre you sure?\n\nN.B. Make sure you are not running another "
3510          "process of OpenToonz,\nor you may delete necessary files for it.");
3511 
3512   QMessageBox::StandardButton ret = QMessageBox::question(
3513       this, tr("Clear Cache Folder"), message,
3514       QMessageBox::StandardButtons(QMessageBox::Ok | QMessageBox::Cancel));
3515 
3516   if (ret != QMessageBox::Ok) return;
3517 
3518   for (const auto &fileToBeRemoved : filesToBeRemoved) {
3519     try {
3520       if (TFileStatus(fileToBeRemoved).isDirectory())
3521         TSystem::rmDirTree(fileToBeRemoved);
3522       else
3523         TSystem::deleteFile(fileToBeRemoved);
3524     } catch (TException &e) {
3525       QMessageBox::warning(
3526           this, tr("Clear Cache Folder"),
3527           tr("Can't delete %1 : ").arg(fileToBeRemoved.getQString()) +
3528               QString::fromStdWString(e.getMessage()));
3529     } catch (...) {
3530       QMessageBox::warning(
3531           this, tr("Clear Cache Folder"),
3532           tr("Can't delete %1 : ").arg(fileToBeRemoved.getQString()));
3533     }
3534   }
3535 }
3536 
3537 //-----------------------------------------------------------------------------
3538 
3539 class ReloadStyle final : public MenuItemHandler {
3540 public:
ReloadStyle()3541   ReloadStyle() : MenuItemHandler("MI_ReloadStyle") {}
execute()3542   void execute() override {
3543     QString currentStyle = Preferences::instance()->getCurrentStyleSheet();
3544     qApp->setStyleSheet(currentStyle);
3545   }
3546 } reloadStyle;
3547 
onQuit()3548 void MainWindow::onQuit() { close(); }
3549 
3550 //=============================================================================
3551 // RecentFiles
3552 //=============================================================================
3553 
RecentFiles()3554 RecentFiles::RecentFiles()
3555     : m_recentScenes(), m_recentSceneProjects(), m_recentLevels() {}
3556 
3557 //-----------------------------------------------------------------------------
3558 
instance()3559 RecentFiles *RecentFiles::instance() {
3560   static RecentFiles _instance;
3561   return &_instance;
3562 }
3563 
3564 //-----------------------------------------------------------------------------
3565 
~RecentFiles()3566 RecentFiles::~RecentFiles() {}
3567 
3568 //-----------------------------------------------------------------------------
3569 
addFilePath(QString path,FileType fileType,QString projectName)3570 void RecentFiles::addFilePath(QString path, FileType fileType,
3571                               QString projectName) {
3572   QList<QString> files =
3573       (fileType == Scene)
3574           ? m_recentScenes
3575           : (fileType == Level) ? m_recentLevels : m_recentFlipbookImages;
3576   int i;
3577   for (i = 0; i < files.size(); i++)
3578     if (files.at(i) == path) {
3579       files.removeAt(i);
3580       if (fileType == Scene) m_recentSceneProjects.removeAt(i);
3581     }
3582   files.insert(0, path);
3583   if (fileType == Scene) m_recentSceneProjects.insert(0, projectName);
3584   int maxSize = 10;
3585   if (files.size() > maxSize) {
3586     files.removeAt(maxSize);
3587     if (fileType == Scene) m_recentSceneProjects.removeAt(maxSize);
3588   }
3589 
3590   if (fileType == Scene)
3591     m_recentScenes = files;
3592   else if (fileType == Level)
3593     m_recentLevels = files;
3594   else
3595     m_recentFlipbookImages = files;
3596 
3597   refreshRecentFilesMenu(fileType);
3598   saveRecentFiles();
3599 }
3600 
3601 //-----------------------------------------------------------------------------
3602 
moveFilePath(int fromIndex,int toIndex,FileType fileType)3603 void RecentFiles::moveFilePath(int fromIndex, int toIndex, FileType fileType) {
3604   if (fileType == Scene) {
3605     m_recentScenes.move(fromIndex, toIndex);
3606     m_recentSceneProjects.move(fromIndex, toIndex);
3607   } else if (fileType == Level)
3608     m_recentLevels.move(fromIndex, toIndex);
3609   else
3610     m_recentFlipbookImages.move(fromIndex, toIndex);
3611   saveRecentFiles();
3612 }
3613 
3614 //-----------------------------------------------------------------------------
3615 
removeFilePath(int index,FileType fileType)3616 void RecentFiles::removeFilePath(int index, FileType fileType) {
3617   if (fileType == Scene) {
3618     m_recentScenes.removeAt(index);
3619     m_recentSceneProjects.removeAt(index);
3620   } else if (fileType == Level)
3621     m_recentLevels.removeAt(index);
3622   saveRecentFiles();
3623 }
3624 
3625 //-----------------------------------------------------------------------------
3626 
getFilePath(int index,FileType fileType) const3627 QString RecentFiles::getFilePath(int index, FileType fileType) const {
3628   return (fileType == Scene)
3629              ? m_recentScenes[index]
3630              : (fileType == Level) ? m_recentLevels[index]
3631                                    : m_recentFlipbookImages[index];
3632 }
3633 
3634 //-----------------------------------------------------------------------------
3635 
getFileProject(int index) const3636 QString RecentFiles::getFileProject(int index) const {
3637   if (index >= m_recentScenes.size() || index >= m_recentSceneProjects.size())
3638     return "-";
3639   return m_recentSceneProjects[index];
3640 }
3641 
getFileProject(QString fileName) const3642 QString RecentFiles::getFileProject(QString fileName) const {
3643   for (int index = 0; index < m_recentScenes.size(); index++)
3644     if (m_recentScenes[index] == fileName) return m_recentSceneProjects[index];
3645 
3646   return "-";
3647 }
3648 
3649 //-----------------------------------------------------------------------------
3650 
clearRecentFilesList(FileType fileType)3651 void RecentFiles::clearRecentFilesList(FileType fileType) {
3652   if (fileType == Scene) {
3653     m_recentScenes.clear();
3654     m_recentSceneProjects.clear();
3655   } else if (fileType == Level)
3656     m_recentLevels.clear();
3657   else
3658     m_recentFlipbookImages.clear();
3659 
3660   refreshRecentFilesMenu(fileType);
3661   saveRecentFiles();
3662 }
3663 
3664 //-----------------------------------------------------------------------------
3665 
loadRecentFiles()3666 void RecentFiles::loadRecentFiles() {
3667   TFilePath fp = ToonzFolder::getMyModuleDir() + TFilePath("RecentFiles.ini");
3668   QSettings settings(toQString(fp), QSettings::IniFormat);
3669   int i;
3670 
3671   QList<QVariant> scenes = settings.value(QString("Scenes")).toList();
3672   if (!scenes.isEmpty()) {
3673     for (i = 0; i < scenes.size(); i++)
3674       m_recentScenes.append(scenes.at(i).toString());
3675   } else {
3676     QString scene = settings.value(QString("Scenes")).toString();
3677     if (!scene.isEmpty()) m_recentScenes.append(scene);
3678   }
3679 
3680   // Load scene's projects info. This is for display purposes only. For
3681   // backwards compatibility it is stored and maintained separately.
3682   QList<QVariant> sceneProjects =
3683       settings.value(QString("SceneProjects")).toList();
3684   if (!sceneProjects.isEmpty()) {
3685     for (i = 0; i < sceneProjects.size(); i++)
3686       m_recentSceneProjects.append(sceneProjects.at(i).toString());
3687   } else {
3688     QString sceneProject = settings.value(QString("SceneProjects")).toString();
3689     if (!sceneProject.isEmpty()) m_recentSceneProjects.append(sceneProject);
3690   }
3691   // Should be 1-to-1. If we're short, append projects list with "-".
3692   while (m_recentSceneProjects.size() < m_recentScenes.size())
3693     m_recentSceneProjects.append("-");
3694 
3695   QList<QVariant> levels = settings.value(QString("Levels")).toList();
3696   if (!levels.isEmpty()) {
3697     for (i = 0; i < levels.size(); i++) {
3698       QString path = levels.at(i).toString();
3699 #ifdef x64
3700       if (path.endsWith(".mov") || path.endsWith(".3gp") ||
3701           path.endsWith(".pct") || path.endsWith(".pict"))
3702         continue;
3703 #endif
3704       m_recentLevels.append(path);
3705     }
3706   } else {
3707     QString level = settings.value(QString("Levels")).toString();
3708     if (!level.isEmpty()) m_recentLevels.append(level);
3709   }
3710 
3711   QList<QVariant> flipImages =
3712       settings.value(QString("FlipbookImages")).toList();
3713   if (!flipImages.isEmpty()) {
3714     for (i = 0; i < flipImages.size(); i++)
3715       m_recentFlipbookImages.append(flipImages.at(i).toString());
3716   } else {
3717     QString flipImage = settings.value(QString("FlipbookImages")).toString();
3718     if (!flipImage.isEmpty()) m_recentFlipbookImages.append(flipImage);
3719   }
3720 
3721   refreshRecentFilesMenu(Scene);
3722   refreshRecentFilesMenu(Level);
3723   refreshRecentFilesMenu(Flip);
3724 }
3725 
3726 //-----------------------------------------------------------------------------
3727 
saveRecentFiles()3728 void RecentFiles::saveRecentFiles() {
3729   TFilePath fp = ToonzFolder::getMyModuleDir() + TFilePath("RecentFiles.ini");
3730   QSettings settings(toQString(fp), QSettings::IniFormat);
3731   settings.setValue(QString("Scenes"), QVariant(m_recentScenes));
3732   settings.setValue(QString("SceneProjects"), QVariant(m_recentSceneProjects));
3733   settings.setValue(QString("Levels"), QVariant(m_recentLevels));
3734   settings.setValue(QString("FlipbookImages"),
3735                     QVariant(m_recentFlipbookImages));
3736 }
3737 
3738 //-----------------------------------------------------------------------------
3739 
getFilesNameList(FileType fileType)3740 QList<QString> RecentFiles::getFilesNameList(FileType fileType) {
3741   QList<QString> files =
3742       (fileType == Scene)
3743           ? m_recentScenes
3744           : (fileType == Level) ? m_recentLevels : m_recentFlipbookImages;
3745   QList<QString> names;
3746   int i;
3747   for (i = 0; i < files.size(); i++) {
3748     TFilePath path(files.at(i).toStdWString());
3749     QString str, number;
3750     names.append(number.number(i + 1) + QString(". ") +
3751                  str.fromStdWString(path.getWideString()));
3752   }
3753   return names;
3754 }
3755 
3756 //-----------------------------------------------------------------------------
3757 
refreshRecentFilesMenu(FileType fileType)3758 void RecentFiles::refreshRecentFilesMenu(FileType fileType) {
3759   CommandId id = (fileType == Scene) ? MI_OpenRecentScene
3760                                      : (fileType == Level) ? MI_OpenRecentLevel
3761                                                            : MI_LoadRecentImage;
3762   QAction *act = CommandManager::instance()->getAction(id);
3763   if (!act) return;
3764   DVMenuAction *menu = dynamic_cast<DVMenuAction *>(act->menu());
3765   if (!menu) return;
3766   QList<QString> names = getFilesNameList(fileType);
3767   if (names.isEmpty())
3768     menu->setEnabled(false);
3769   else {
3770     CommandId clearActionId =
3771         (fileType == Scene)
3772             ? MI_ClearRecentScene
3773             : (fileType == Level) ? MI_ClearRecentLevel : MI_ClearRecentImage;
3774     menu->setActions(names);
3775     menu->addSeparator();
3776     QAction *clearAction = CommandManager::instance()->getAction(clearActionId);
3777     assert(clearAction);
3778     menu->addAction(clearAction);
3779     if (!menu->isEnabled()) menu->setEnabled(true);
3780   }
3781 }
3782