1
2
3 // Tnz6 includes
4 #include "mainwindow.h"
5 #include "flipbook.h"
6 #include "tapp.h"
7 #include "iocommand.h"
8 #include "previewfxmanager.h"
9 #include "cleanupsettingspopup.h"
10 #include "filebrowsermodel.h"
11 #include "expressionreferencemanager.h"
12
13 // TnzTools includes
14 #include "tools/tool.h"
15 #include "tools/toolcommandids.h"
16
17 // TnzQt includes
18 #include "toonzqt/dvdialog.h"
19 #include "toonzqt/menubarcommand.h"
20 #include "toonzqt/tmessageviewer.h"
21 #include "toonzqt/icongenerator.h"
22 #include "toonzqt/gutil.h"
23 #include "toonzqt/pluginloader.h"
24
25 // TnzStdfx includes
26 #include "stdfx/shaderfx.h"
27
28 // TnzLib includes
29 #include "toonz/preferences.h"
30 #include "toonz/toonzfolders.h"
31 #include "toonz/tproject.h"
32 #include "toonz/studiopalette.h"
33 #include "toonz/stylemanager.h"
34 #include "toonz/tscenehandle.h"
35 #include "toonz/txshsimplelevel.h"
36 #include "toonz/tproject.h"
37 #include "toonz/scriptengine.h"
38
39 // TnzSound includes
40 #include "tnzsound.h"
41
42 // TnzImage includes
43 #include "tnzimage.h"
44
45 // TnzBase includes
46 #include "permissionsmanager.h"
47 #include "tenv.h"
48 #include "tcli.h"
49
50 // TnzCore includes
51 #include "tsystem.h"
52 #include "tthread.h"
53 #include "tthreadmessage.h"
54 #include "tundo.h"
55 #include "tconvert.h"
56 #include "tiio_std.h"
57 #include "timagecache.h"
58 #include "tofflinegl.h"
59 #include "tpluginmanager.h"
60 #include "tsimplecolorstyles.h"
61 #include "toonz/imagestyles.h"
62 #include "tvectorbrushstyle.h"
63 #include "tfont.h"
64
65 #include "kis_tablet_support_win8.h"
66
67 #ifdef MACOSX
68 #include "tipc.h"
69 #endif
70
71 // Qt includes
72 #include <QApplication>
73 #include <QAbstractEventDispatcher>
74 #include <QAbstractNativeEventFilter>
75 #include <QSplashScreen>
76 #include <QGLPixelBuffer>
77 #include <QTranslator>
78 #include <QFileInfo>
79 #include <QSettings>
80 #include <QLibraryInfo>
81 #include <QHash>
82
83 #ifdef _WIN32
84 #ifndef x64
85 #include <float.h>
86 #endif
87 #include <QtPlatformHeaders/QWindowsWindowFunctions>
88 #endif
89
90 using namespace DVGui;
91
92 TEnv::IntVar EnvSoftwareCurrentFontSize("SoftwareCurrentFontSize", 12);
93
94 const char *rootVarName = "TOONZROOT";
95 const char *systemVarPrefix = "TOONZ";
96
97 #ifdef MACOSX
98 #include "tthread.h"
postThreadMsg(TThread::Message *)99 void postThreadMsg(TThread::Message *) {}
100 void qt_mac_set_menubar_merge(bool enable);
101 #endif
102
103 // Modifica per toonz (non servono questo tipo di licenze)
104 #define NO_LICENSE
105 //-----------------------------------------------------------------------------
106
fatalError(QString msg)107 static void fatalError(QString msg) {
108 DVGui::MsgBoxInPopup(
109 CRITICAL,
110 msg + "\n" +
111 QObject::tr("Installing %1 again could fix the problem.")
112 .arg(QString::fromStdString(TEnv::getApplicationFullName())));
113 exit(0);
114 }
115 //-----------------------------------------------------------------------------
116
lastWarningError(QString msg)117 static void lastWarningError(QString msg) {
118 DVGui::error(msg);
119 // exit(0);
120 }
121 //-----------------------------------------------------------------------------
122
toonzRunOutOfContMemHandler(unsigned long size)123 static void toonzRunOutOfContMemHandler(unsigned long size) {
124 #ifdef _WIN32
125 static bool firstTime = true;
126 if (firstTime) {
127 MessageBox(NULL, (LPCWSTR)L"Run out of contiguous physical memory: please save all and restart Toonz!",
128 (LPCWSTR)L"Warning", MB_OK | MB_SYSTEMMODAL);
129 firstTime = false;
130 }
131 #endif
132 }
133
134 //-----------------------------------------------------------------------------
135
136 // todo.. da mettere in qualche .h
137 DV_IMPORT_API void initStdFx();
138 DV_IMPORT_API void initColorFx();
139
140 //-----------------------------------------------------------------------------
141
142 //! Inizializzaza l'Environment di Toonz
143 /*! In particolare imposta la projectRoot e
144 la stuffDir, controlla se la directory di outputs esiste (e provvede a
145 crearla in caso contrario) verifica inoltre che stuffDir esista.
146 */
initToonzEnv(QHash<QString,QString> & argPathValues)147 static void initToonzEnv(QHash<QString, QString> &argPathValues) {
148 StudioPalette::enable(true);
149 TEnv::setRootVarName(rootVarName);
150 TEnv::setSystemVarPrefix(systemVarPrefix);
151
152 QHash<QString, QString>::const_iterator i = argPathValues.constBegin();
153 while (i != argPathValues.constEnd()) {
154 if (!TEnv::setArgPathValue(i.key().toStdString(), i.value().toStdString()))
155 DVGui::error(
156 QObject::tr("The qualifier %1 is not a valid key name. Skipping.")
157 .arg(i.key()));
158 ++i;
159 }
160
161 QCoreApplication::setOrganizationName("OpenToonz");
162 QCoreApplication::setOrganizationDomain("");
163 QCoreApplication::setApplicationName(
164 QString::fromStdString(TEnv::getApplicationName()));
165
166 /*-- TOONZROOTのPathの確認 --*/
167 // controllo se la xxxroot e' definita e corrisponde ad un folder esistente
168
169 /*-- ENGLISH: Confirm TOONZROOT Path
170 Check if the xxxroot is defined and corresponds to an existing folder
171 --*/
172
173 TFilePath stuffDir = TEnv::getStuffDir();
174 if (stuffDir == TFilePath())
175 fatalError("Undefined or empty: \"" + toQString(TEnv::getRootVarPath()) +
176 "\"");
177 else if (!TFileStatus(stuffDir).isDirectory())
178 fatalError("Folder \"" + toQString(stuffDir) +
179 "\" not found or not readable");
180
181 Tiio::defineStd();
182 initImageIo();
183 initSoundIo();
184 initStdFx();
185 initColorFx();
186
187 // TPluginManager::instance()->loadStandardPlugins();
188
189 TFilePath library = ToonzFolder::getLibraryFolder();
190
191 TRasterImagePatternStrokeStyle::setRootDir(library);
192 TVectorImagePatternStrokeStyle::setRootDir(library);
193 TVectorBrushStyle::setRootDir(library);
194
195 CustomStyleManager::setRootPath(library);
196
197 // sembra indispensabile nella lettura dei .tab 2.2:
198 TPalette::setRootDir(library);
199 TImageStyle::setLibraryDir(library);
200
201 // TProjectManager::instance()->enableTabMode(true);
202
203 TProjectManager *projectManager = TProjectManager::instance();
204
205 /*--
206 * TOONZPROJECTSのパスセットを取得する。(TOONZPROJECTSはセミコロンで区切って複数設定可能)
207 * --*/
208 TFilePathSet projectsRoots = ToonzFolder::getProjectsFolders();
209 TFilePathSet::iterator it;
210 for (it = projectsRoots.begin(); it != projectsRoots.end(); ++it)
211 projectManager->addProjectsRoot(*it);
212
213 /*-- もしまだ無ければ、TOONZROOT/sandboxにsandboxプロジェクトを作る --*/
214 projectManager->createSandboxIfNeeded();
215
216 /*
217 TProjectP project = projectManager->getCurrentProject();
218 Non dovrebbe servire per Tab:
219 project->setFolder(TProject::Drawings, TFilePath("$scenepath"));
220 project->setFolder(TProject::Extras, TFilePath("$scenepath"));
221 project->setUseScenePath(TProject::Drawings, false);
222 project->setUseScenePath(TProject::Extras, false);
223 */
224 // Imposto la rootDir per ImageCache
225
226 /*-- TOONZCACHEROOTの設定 --*/
227 TFilePath cacheDir = ToonzFolder::getCacheRootFolder();
228 if (cacheDir.isEmpty()) cacheDir = TEnv::getStuffDir() + "cache";
229 TImageCache::instance()->setRootDir(cacheDir);
230 }
231
232 //-----------------------------------------------------------------------------
233
script_output(int type,const QString & value)234 static void script_output(int type, const QString &value) {
235 if (type == ScriptEngine::ExecutionError ||
236 type == ScriptEngine::SyntaxError ||
237 type == ScriptEngine::UndefinedEvaluationResult ||
238 type == ScriptEngine::Warning)
239 std::cerr << value.toStdString() << std::endl;
240 else
241 std::cout << value.toStdString() << std::endl;
242 }
243
244 //-----------------------------------------------------------------------------
245
main(int argc,char * argv[])246 int main(int argc, char *argv[]) {
247 #ifdef Q_OS_WIN
248 // Enable standard input/output on Windows Platform for debug
249 BOOL consoleAttached = ::AttachConsole(ATTACH_PARENT_PROCESS);
250 if (consoleAttached) {
251 freopen("CON", "r", stdin);
252 freopen("CON", "w", stdout);
253 freopen("CON", "w", stderr);
254 }
255 #endif
256
257 // parsing arguments and qualifiers
258 TFilePath loadFilePath;
259 QString argumentLayoutFileName = "";
260 QHash<QString, QString> argumentPathValues;
261 if (argc > 1) {
262 TCli::Usage usage(argv[0]);
263 TCli::UsageLine usageLine;
264 TCli::FilePathArgument loadFileArg(
265 "filePath", "Source scene file to open or script file to run");
266 TCli::StringQualifier layoutFileQual(
267 "-layout filename",
268 "Custom layout file to be used, it should be saved in "
269 "$TOONZPROFILES\\layouts\\personal\\[CurrentLayoutName].[UserName]\\. "
270 "layouts.txt is used by default.");
271 usageLine = usageLine + layoutFileQual;
272
273 // system path qualifiers
274 std::map<QString, std::unique_ptr<TCli::QualifierT<TFilePath>>>
275 systemPathQualMap;
276 QString qualKey = QString("%1ROOT").arg(systemVarPrefix);
277 QString qualName = QString("-%1 folderpath").arg(qualKey);
278 QString qualHelp =
279 QString(
280 "%1 path. It will automatically set other system paths to %1 "
281 "unless individually specified with other qualifiers.")
282 .arg(qualKey);
283 systemPathQualMap[qualKey].reset(new TCli::QualifierT<TFilePath>(
284 qualName.toStdString(), qualHelp.toStdString()));
285 usageLine = usageLine + *systemPathQualMap[qualKey];
286
287 const std::map<std::string, std::string> &spm = TEnv::getSystemPathMap();
288 for (auto itr = spm.begin(); itr != spm.end(); ++itr) {
289 qualKey = QString("%1%2")
290 .arg(systemVarPrefix)
291 .arg(QString::fromStdString((*itr).first));
292 qualName = QString("-%1 folderpath").arg(qualKey);
293 qualHelp = QString("%1 path.").arg(qualKey);
294 systemPathQualMap[qualKey].reset(new TCli::QualifierT<TFilePath>(
295 qualName.toStdString(), qualHelp.toStdString()));
296 usageLine = usageLine + *systemPathQualMap[qualKey];
297 }
298 usage.add(usageLine);
299 usage.add(usageLine + loadFileArg);
300
301 if (!usage.parse(argc, argv)) exit(1);
302
303 loadFilePath = loadFileArg.getValue();
304 if (layoutFileQual.isSelected())
305 argumentLayoutFileName =
306 QString::fromStdString(layoutFileQual.getValue());
307 for (auto q_itr = systemPathQualMap.begin();
308 q_itr != systemPathQualMap.end(); ++q_itr) {
309 if (q_itr->second->isSelected())
310 argumentPathValues.insert(q_itr->first,
311 q_itr->second->getValue().getQString());
312 }
313
314 argc = 1;
315 }
316
317 // Enables high-DPI scaling. This attribute must be set before QApplication is
318 // constructed. Available from Qt 5.6.
319 #if QT_VERSION >= 0x050600
320 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
321 #endif
322
323 QApplication a(argc, argv);
324
325 #ifdef MACOSX
326 // This workaround is to avoid missing left button problem on Qt5.6.0.
327 // To invalidate m_rightButtonClicked in Qt/qnsview.mm, sending
328 // NSLeftButtonDown event before NSLeftMouseDragged event propagated to
329 // QApplication. See more details in ../mousedragfilter/mousedragfilter.mm.
330
331 #include "mousedragfilter.h"
332
333 class OSXMouseDragFilter final : public QAbstractNativeEventFilter {
334 bool leftButtonPressed = false;
335
336 public:
337 bool nativeEventFilter(const QByteArray &eventType, void *message,
338 long *) Q_DECL_OVERRIDE {
339 if (IsLeftMouseDown(message)) {
340 leftButtonPressed = true;
341 }
342 if (IsLeftMouseUp(message)) {
343 leftButtonPressed = false;
344 }
345
346 if (eventType == "mac_generic_NSEvent") {
347 if (IsLeftMouseDragged(message) && !leftButtonPressed) {
348 std::cout << "force mouse press event" << std::endl;
349 SendLeftMousePressEvent();
350 return true;
351 }
352 }
353 return false;
354 }
355 };
356
357 a.installNativeEventFilter(new OSXMouseDragFilter);
358 #endif
359
360 #ifdef Q_OS_WIN
361 // Since currently OpenToonz does not work with OpenGL of software or
362 // angle, force Qt to use desktop OpenGL
363 // FIXME: This options should be called before constructing the application.
364 // Thus, ANGLE seems to be enabled as of now.
365 a.setAttribute(Qt::AA_UseDesktopOpenGL, true);
366 #endif
367
368 // Some Qt objects are destroyed badly withouth a living qApp. So, we must
369 // enforce a way to either
370 // postpone the application destruction until the very end, OR ensure that
371 // sensible objects are
372 // destroyed before.
373
374 // Using a static QApplication only worked on Windows, and in any case C++
375 // respects the statics destruction
376 // order ONLY within the same library. On MAC, it made the app crash on exit
377 // o_o. So, nope.
378
379 std::unique_ptr<QObject> mainScope(new QObject(
380 &a)); // A QObject destroyed before the qApp is therefore explicitly
381 mainScope->setObjectName("mainScope"); // provided. It can be accessed by
382 // looking in the qApp's children.
383
384 #ifdef _WIN32
385 #ifndef x64
386 // Store the floating point control word. It will be re-set before Toonz
387 // initialization
388 // has ended.
389 unsigned int fpWord = 0;
390 _controlfp_s(&fpWord, 0, 0);
391 #endif
392 #endif
393
394 #ifdef _WIN32
395 // At least on windows, Qt's 4.5.2 native windows feature tend to create
396 // weird flickering effects when dragging panel separators.
397 a.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
398 #endif
399
400 // Enable to render smooth icons on high dpi monitors
401 a.setAttribute(Qt::AA_UseHighDpiPixmaps);
402 #if defined(_WIN32) && QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
403 // Compress tablet events with application attributes instead of implementing
404 // the delay-timer by ourselves
405 a.setAttribute(Qt::AA_CompressHighFrequencyEvents);
406 a.setAttribute(Qt::AA_CompressTabletEvents);
407 #endif
408
409 #ifdef _WIN32
410 // This attribute is set to make menubar icon to be always (16 x devPixRatio).
411 // Without this attribute the menu bar icon size becomes the same as tool bar
412 // when Windows scale is in 125%. Currently hiding the menu bar icon is done
413 // by setting transparent pixmap only in menu bar icon size. So the size must
414 // be different between for menu bar and for tool bar.
415 a.setAttribute(Qt::AA_Use96Dpi);
416 #endif
417
418 // Set the app's locale for numeric stuff to standard C. This is important for
419 // atof() and similar
420 // calls that are locale-dependant.
421 setlocale(LC_NUMERIC, "C");
422
423 // Set current directory to the bundle/application path - this is needed to have
424 // correct relative paths
425 #ifdef MACOSX
426 {
427 QDir appDir(QApplication::applicationDirPath());
428 appDir.cdUp(), appDir.cdUp(), appDir.cdUp();
429
430 bool ret = QDir::setCurrent(appDir.absolutePath());
431 assert(ret);
432 }
433 #endif
434
435 // Set icon theme search paths
436 QStringList themeSearchPathsList = {":/icons"};
437 QIcon::setThemeSearchPaths(themeSearchPathsList);
438 // qDebug() << "All icon theme search paths:" << QIcon::themeSearchPaths();
439
440 // Set show icons in menus flag (use iconVisibleInMenu to disable selectively)
441 QApplication::instance()->setAttribute(Qt::AA_DontShowIconsInMenus, false);
442
443 TEnv::setApplicationFileName(argv[0]);
444
445 // splash screen
446 QPixmap splashPixmap = QIcon(":Resources/splash.svg").pixmap(QSize(610, 344));
447 splashPixmap.setDevicePixelRatio(QApplication::desktop()->devicePixelRatio());
448 // QPixmap splashPixmap(":Resources/splash.png");
449 #ifdef _WIN32
450 QFont font("Segoe UI", -1);
451 #else
452 QFont font("Helvetica", -1);
453 #endif
454 font.setPixelSize(13);
455 font.setWeight(50);
456 a.setFont(font);
457
458 QString offsetStr("\n\n\n\n\n\n\n\n");
459
460 TSystem::hasMainLoop(true);
461
462 TMessageRepository::instance();
463
464 bool isRunScript = (loadFilePath.getType() == "toonzscript");
465
466 QSplashScreen splash(splashPixmap);
467 if (!isRunScript) splash.show();
468 a.processEvents();
469
470 splash.showMessage(offsetStr + "Initializing QGLFormat...", Qt::AlignCenter,
471 Qt::white);
472 a.processEvents();
473
474 // OpenGL
475 QGLFormat fmt;
476 fmt.setAlpha(true);
477 fmt.setStencil(true);
478 QGLFormat::setDefaultFormat(fmt);
479
480 glutInit(&argc, argv);
481
482 splash.showMessage(offsetStr + "Initializing Toonz environment ...",
483 Qt::AlignCenter, Qt::white);
484 a.processEvents();
485
486 // Install run out of contiguous memory callback
487 TBigMemoryManager::instance()->setRunOutOfContiguousMemoryHandler(
488 &toonzRunOutOfContMemHandler);
489
490 // Toonz environment
491 initToonzEnv(argumentPathValues);
492
493 // Initialize thread components
494 TThread::init();
495
496 TProjectManager *projectManager = TProjectManager::instance();
497 if (Preferences::instance()->isSVNEnabled()) {
498 // Read Version Control repositories and add it to project manager as
499 // "special" svn project root
500 VersionControl::instance()->init();
501 QList<SVNRepository> repositories =
502 VersionControl::instance()->getRepositories();
503 int count = repositories.size();
504 for (int i = 0; i < count; i++) {
505 SVNRepository r = repositories.at(i);
506
507 TFilePath localPath(r.m_localPath.toStdWString());
508 if (!TFileStatus(localPath).doesExist()) {
509 try {
510 TSystem::mkDir(localPath);
511 } catch (TException &e) {
512 fatalError(QString::fromStdWString(e.getMessage()));
513 }
514 }
515 projectManager->addSVNProjectsRoot(localPath);
516 }
517 }
518
519 #if defined(MACOSX) && defined(__LP64__)
520
521 // Load the shared memory settings
522 int shmmax = Preferences::instance()->getShmMax();
523 int shmseg = Preferences::instance()->getShmSeg();
524 int shmall = Preferences::instance()->getShmAll();
525 int shmmni = Preferences::instance()->getShmMni();
526
527 if (shmall <
528 0) // Make sure that at least 100 MB of shared memory are available
529 shmall = (tipc::shm_maxSharedPages() < (100 << 8)) ? (100 << 8) : -1;
530
531 tipc::shm_set(shmmax, shmseg, shmall, shmmni);
532
533 #endif
534
535 // DVDirModel must be instantiated after Version Control initialization...
536 FolderListenerManager::instance()->addListener(DvDirModel::instance());
537
538 splash.showMessage(offsetStr + "Loading Translator ...", Qt::AlignCenter,
539 Qt::white);
540 a.processEvents();
541
542 // Carico la traduzione contenuta in toonz.qm (se � presente)
543 QString languagePathString =
544 QString::fromStdString(::to_string(TEnv::getConfigDir() + "loc"));
545 #ifndef WIN32
546 // the merge of menu on osx can cause problems with different languages with
547 // the Preferences menu
548 // qt_mac_set_menubar_merge(false);
549 languagePathString += "/" + Preferences::instance()->getCurrentLanguage();
550 #else
551 languagePathString += "\\" + Preferences::instance()->getCurrentLanguage();
552 #endif
553 QTranslator translator;
554 translator.load("toonz", languagePathString);
555
556 // La installo
557 a.installTranslator(&translator);
558
559 // Carico la traduzione contenuta in toonzqt.qm (se e' presente)
560 QTranslator translator2;
561 translator2.load("toonzqt", languagePathString);
562 a.installTranslator(&translator2);
563
564 // Carico la traduzione contenuta in tnzcore.qm (se e' presente)
565 QTranslator tnzcoreTranslator;
566 tnzcoreTranslator.load("tnzcore", languagePathString);
567 qApp->installTranslator(&tnzcoreTranslator);
568
569 // Carico la traduzione contenuta in toonzlib.qm (se e' presente)
570 QTranslator toonzlibTranslator;
571 toonzlibTranslator.load("toonzlib", languagePathString);
572 qApp->installTranslator(&toonzlibTranslator);
573
574 // Carico la traduzione contenuta in colorfx.qm (se e' presente)
575 QTranslator colorfxTranslator;
576 colorfxTranslator.load("colorfx", languagePathString);
577 qApp->installTranslator(&colorfxTranslator);
578
579 // Carico la traduzione contenuta in tools.qm
580 QTranslator toolTranslator;
581 toolTranslator.load("tnztools", languagePathString);
582 qApp->installTranslator(&toolTranslator);
583
584 // load translation for file writers properties
585 QTranslator imageTranslator;
586 imageTranslator.load("image", languagePathString);
587 qApp->installTranslator(&imageTranslator);
588
589 QTranslator qtTranslator;
590 qtTranslator.load("qt_" + QLocale::system().name(),
591 QLibraryInfo::location(QLibraryInfo::TranslationsPath));
592 a.installTranslator(&qtTranslator);
593
594 // Aggiorno la traduzione delle properties di tutti i tools
595 TTool::updateToolsPropertiesTranslation();
596 // Apply translation to file writers properties
597 Tiio::updateFileWritersPropertiesTranslation();
598
599 // Force to have left-to-right layout direction in any language environment.
600 // This function has to be called after installTranslator().
601 a.setLayoutDirection(Qt::LeftToRight);
602
603 splash.showMessage(offsetStr + "Loading styles ...", Qt::AlignCenter,
604 Qt::white);
605 a.processEvents();
606
607 // Set default start icon theme
608 QIcon::setThemeName(Preferences::instance()->getIconTheme() ? "dark"
609 : "light");
610 // qDebug() << "Icon theme name:" << QIcon::themeName();
611
612 // stile
613 QApplication::setStyle("windows");
614
615 IconGenerator::setFilmstripIconSize(Preferences::instance()->getIconSize());
616
617 splash.showMessage(offsetStr + "Loading shaders ...", Qt::AlignCenter,
618 Qt::white);
619 a.processEvents();
620
621 loadShaderInterfaces(ToonzFolder::getLibraryFolder() + TFilePath("shaders"));
622
623 splash.showMessage(offsetStr + "Initializing OpenToonz ...", Qt::AlignCenter,
624 Qt::white);
625 a.processEvents();
626
627 TTool::setApplication(TApp::instance());
628 TApp::instance()->init();
629
630 splash.showMessage(offsetStr + "Loading Plugins...", Qt::AlignCenter,
631 Qt::white);
632 a.processEvents();
633 /* poll the thread ends:
634 絶対に必要なわけではないが PluginLoader は中で setup
635 ハンドラが常に固有のスレッドで呼ばれるよう main thread queue の blocking
636 をしているので
637 processEvents を行う必要がある
638 */
639 while (!PluginLoader::load_entries("")) {
640 a.processEvents();
641 }
642
643 splash.showMessage(offsetStr + "Creating main window ...", Qt::AlignCenter,
644 Qt::white);
645 a.processEvents();
646
647 /*-- Layoutファイル名をMainWindowのctorに渡す --*/
648 MainWindow w(argumentLayoutFileName);
649
650 if (isRunScript) {
651 // load script
652 if (TFileStatus(loadFilePath).doesExist()) {
653 // find project for this script file
654 TProjectManager *pm = TProjectManager::instance();
655 TProjectP sceneProject = pm->loadSceneProject(loadFilePath);
656 TFilePath oldProjectPath;
657 if (!sceneProject) {
658 std::cerr << QObject::tr(
659 "It is not possible to load the scene %1 because it "
660 "does not "
661 "belong to any project.")
662 .arg(loadFilePath.getQString())
663 .toStdString()
664 << std::endl;
665 return 1;
666 }
667 if (sceneProject && !sceneProject->isCurrent()) {
668 oldProjectPath = pm->getCurrentProjectPath();
669 pm->setCurrentProjectPath(sceneProject->getProjectPath());
670 }
671 ScriptEngine engine;
672 QObject::connect(&engine, &ScriptEngine::output, script_output);
673 QString s = QString::fromStdWString(loadFilePath.getWideString())
674 .replace("\\", "\\\\")
675 .replace("\"", "\\\"");
676 QString cmd = QString("run(\"%1\")").arg(s);
677 engine.evaluate(cmd);
678 engine.wait();
679 if (!oldProjectPath.isEmpty()) pm->setCurrentProjectPath(oldProjectPath);
680 return 1;
681 } else {
682 std::cerr << QObject::tr("Script file %1 does not exists.")
683 .arg(loadFilePath.getQString())
684 .toStdString()
685 << std::endl;
686 return 1;
687 }
688 }
689
690 #ifdef _WIN32
691 // http://doc.qt.io/qt-5/windows-issues.html#fullscreen-opengl-based-windows
692 if (w.windowHandle())
693 QWindowsWindowFunctions::setHasBorderInFullScreen(w.windowHandle(), true);
694 #endif
695
696 // Qt have started to support Windows Ink from 5.12.
697 // Unlike WinTab API used in Qt 5.9 the tablet behaviors are different and
698 // are (at least, for OT) problematic. The customized Qt5.15.2 are made with
699 // cherry-picking the WinTab feature to be officially introduced from 6.0.
700 // See https://github.com/shun-iwasawa/qt5/releases/tag/v5.15.2_wintab for
701 // details. The following feature can only be used with the customized Qt,
702 // with WITH_WINTAB build option, and in Windows-x64 build.
703
704 #ifdef WITH_WINTAB
705 bool useQtNativeWinInk = Preferences::instance()->isQtNativeWinInkEnabled();
706 QWindowsWindowFunctions::setWinTabEnabled(!useQtNativeWinInk);
707 #endif
708
709 splash.showMessage(offsetStr + "Loading style sheet ...", Qt::AlignCenter,
710 Qt::white);
711 a.processEvents();
712
713 // Carico lo styleSheet
714 QString currentStyle = Preferences::instance()->getCurrentStyleSheet();
715 a.setStyleSheet(currentStyle);
716
717 w.setWindowTitle(QString::fromStdString(TEnv::getApplicationFullName()));
718 if (TEnv::getIsPortable()) {
719 splash.showMessage(offsetStr + "Starting OpenToonz Portable ...",
720 Qt::AlignCenter, Qt::white);
721 } else {
722 splash.showMessage(offsetStr + "Starting main window ...", Qt::AlignCenter,
723 Qt::white);
724 }
725 a.processEvents();
726
727 TFilePath fp = ToonzFolder::getModuleFile("mainwindow.ini");
728 QSettings settings(toQString(fp), QSettings::IniFormat);
729 w.restoreGeometry(settings.value("MainWindowGeometry").toByteArray());
730
731 ExpressionReferenceManager::instance()->init();
732
733 #ifndef MACOSX
734 // Workaround for the maximized window case: Qt delivers two resize events,
735 // one in the normal geometry, before
736 // maximizing (why!?), the second afterwards - all inside the following show()
737 // call. This makes troublesome for
738 // the docking system to correctly restore the saved geometry. Fortunately,
739 // MainWindow::showEvent(..) gets called
740 // just between the two, so we can disable the currentRoom layout right before
741 // showing and re-enable it after
742 // the normal resize has happened.
743 if (w.isMaximized()) w.getCurrentRoom()->layout()->setEnabled(false);
744 #endif
745
746 QRect splashGeometry = splash.geometry();
747 splash.finish(&w);
748
749 a.setQuitOnLastWindowClosed(false);
750 // a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
751 if (Preferences::instance()->isLatestVersionCheckEnabled())
752 w.checkForUpdates();
753
754 w.show();
755
756 // Show floating panels only after the main window has been shown
757 w.startupFloatingPanels();
758
759 CommandManager::instance()->execute(T_Hand);
760 if (!loadFilePath.isEmpty()) {
761 splash.showMessage(
762 QString("Loading file '") + loadFilePath.getQString() + "'...",
763 Qt::AlignCenter, Qt::white);
764 loadFilePath = loadFilePath.withType("tnz");
765 if (TFileStatus(loadFilePath).doesExist()) IoCmd::loadScene(loadFilePath);
766 }
767
768 QFont *myFont;
769 QString fontName = Preferences::instance()->getInterfaceFont();
770 QString fontStyle = Preferences::instance()->getInterfaceFontStyle();
771
772 TFontManager *fontMgr = TFontManager::instance();
773 std::vector<std::wstring> typefaces;
774 bool isBold = false, isItalic = false, hasKerning = false;
775 try {
776 fontMgr->loadFontNames();
777 fontMgr->setFamily(fontName.toStdWString());
778 fontMgr->getAllTypefaces(typefaces);
779 isBold = fontMgr->isBold(fontName, fontStyle);
780 isItalic = fontMgr->isItalic(fontName, fontStyle);
781 hasKerning = fontMgr->hasKerning();
782 } catch (TFontCreationError &) {
783 // Do nothing. A default font should load
784 }
785
786 myFont = new QFont(fontName);
787 myFont->setPixelSize(EnvSoftwareCurrentFontSize);
788 myFont->setBold(isBold);
789 myFont->setItalic(isItalic);
790 myFont->setKerning(hasKerning);
791
792 a.setFont(*myFont);
793
794 QAction *action = CommandManager::instance()->getAction("MI_OpenTMessage");
795 if (action)
796 QObject::connect(TMessageRepository::instance(),
797 SIGNAL(openMessageCenter()), action, SLOT(trigger()));
798
799 QObject::connect(TUndoManager::manager(), SIGNAL(somethingChanged()),
800 TApp::instance()->getCurrentScene(), SLOT(setDirtyFlag()));
801
802 #ifdef _WIN32
803 #ifndef x64
804 // On 32-bit architecture, there could be cases in which initialization could
805 // alter the
806 // FPU floating point control word. I've seen this happen when loading some
807 // AVI coded (VFAPI),
808 // where 80-bit internal precision was used instead of the standard 64-bit
809 // (much faster and
810 // sufficient - especially considering that x86 truncates to 64-bit
811 // representation anyway).
812 // IN ANY CASE, revert to the original control word.
813 // In the x64 case these precision changes simply should not take place up to
814 // _controlfp_s
815 // documentation.
816 _controlfp_s(0, fpWord, -1);
817 #endif
818 #endif
819
820 #ifdef _WIN32
821 if (Preferences::instance()->isWinInkEnabled()) {
822 KisTabletSupportWin8 *penFilter = new KisTabletSupportWin8();
823 if (penFilter->init()) {
824 a.installNativeEventFilter(penFilter);
825 } else {
826 delete penFilter;
827 }
828 }
829 #endif
830
831 a.installEventFilter(TApp::instance());
832
833 int ret = a.exec();
834
835 TUndoManager::manager()->reset();
836 PreviewFxManager::instance()->reset();
837
838 #ifdef _WIN32
839 if (consoleAttached) {
840 ::FreeConsole();
841 }
842 #endif
843
844 return ret;
845 }
846