601 addRecentlyOpenedFile(path); |
575 addRecentlyOpenedFile(path); |
602 } |
576 } |
603 } |
577 } |
604 } |
578 } |
605 ); |
579 ); |
606 QObject::connect(ui.actionSettingsEditor, &QAction::triggered, [&defaultKeyboardShortcuts, &restoreSettings, &settingsChanged, &ui]{ |
580 QObject::connect(mainWindow.actionSettingsEditor, &QAction::triggered, [&defaultKeyboardShortcuts, &restoreSettings, &settingsChanged, &mainWindow]{ |
607 if (ui.mdiArea->findChildren<SettingsEditor*>().isEmpty()) { |
581 if (mainWindow.mdiArea->findChildren<SettingsEditor*>().isEmpty()) { |
608 auto* const settingsEditor = createSubWindow<SettingsEditor>(ui.mdiArea, defaultKeyboardShortcuts); |
582 auto* const settingsEditor = createSubWindow<SettingsEditor>(mainWindow.mdiArea, defaultKeyboardShortcuts); |
609 QObject::connect(&settingsChanged, &Signal::triggered, settingsEditor, &SettingsEditor::loadSettings); |
583 QObject::connect(&settingsChanged, &Signal::triggered, settingsEditor, &SettingsEditor::loadSettings); |
610 QObject::connect(settingsEditor, &SettingsEditor::settingsChanged, restoreSettings); |
584 QObject::connect(settingsEditor, &SettingsEditor::settingsChanged, restoreSettings); |
611 settingsEditor->setAttribute(Qt::WA_DeleteOnClose); |
585 settingsEditor->setAttribute(Qt::WA_DeleteOnClose); |
612 settingsEditor->show(); |
586 settingsEditor->show(); |
613 } |
587 } |
614 }); |
588 }); |
615 QObject::connect(ui.actionQuit, &QAction::triggered, &mainWindow, &QMainWindow::close); |
589 QObject::connect(mainWindow.actionQuit, &QAction::triggered, &mainWindow, &QMainWindow::close); |
616 #if 0 |
590 #if 0 |
617 QObject::connect(ui.actionAdjustGridToView, &QAction::triggered, [&]{ |
591 QObject::connect(ui.actionAdjustGridToView, &QAction::triggered, [&]{ |
618 if (ModelData* data = currentModelData(&ui, &documents)) { |
592 if (ModelData* data = currentModelData(&ui, &documents)) { |
619 adjustGridToView(data->canvas.get()); |
593 adjustGridToView(data->canvas.get()); |
620 } |
594 } |
621 }); |
595 }); |
622 #endif |
596 #endif |
623 QObject::connect(ui.actionClose, &QAction::triggered, [&ui, &documents]{ |
597 QObject::connect(mainWindow.actionClose, &QAction::triggered, [&mainWindow, &documents]{ |
624 if (ModelData* data = currentModelData(&ui, &documents)) { |
598 if (ModelData* data = currentModelData(&mainWindow, &documents)) { |
625 // TODO |
599 // TODO |
626 } |
600 } |
627 }); |
601 }); |
628 const auto save = [&addRecentlyOpenedFile, &documents, &mainWindow](ModelId modelId){ |
602 const auto save = [&addRecentlyOpenedFile, &mainWindow](DocumentManager* documents, ModelId modelId){ |
629 QString error; |
603 QString error; |
630 QTextStream errorStream{&error}; |
604 QTextStream errorStream{&error}; |
631 const bool succeeded = documents.saveModel(modelId, errorStream); |
605 const bool succeeded = documents->saveModel(modelId, errorStream); |
632 if (not succeeded) |
606 if (not succeeded) |
633 { |
607 { |
634 QMessageBox::critical(&mainWindow, QObject::tr("Save error"), error); |
608 QMessageBox::critical(&mainWindow, QObject::tr("Save error"), error); |
635 } |
609 } |
636 else |
610 else |
637 { |
611 { |
638 const QString* pathPtr = documents.modelPath(modelId); |
612 const QString* pathPtr = documents->modelPath(modelId); |
639 if (pathPtr != nullptr) { |
613 if (pathPtr != nullptr) { |
640 addRecentlyOpenedFile(*pathPtr); |
614 addRecentlyOpenedFile(*pathPtr); |
641 } |
615 } |
642 } |
616 } |
643 };; |
617 }; |
644 const auto actionSaveAs = [&documents, &libraries, &mainWindow, &save, &ui]{ |
618 const auto actionSaveAs = [&documents, &libraries, &mainWindow, &save]{ |
645 const std::optional<ModelId> modelId = findCurrentModelId(&ui); |
619 const std::optional<ModelId> modelId = findCurrentModelId(&mainWindow); |
646 if (modelId.has_value()) |
620 if (modelId.has_value()) |
647 { |
621 { |
648 const QString* pathPtr = documents.modelPath(*modelId); |
622 const QString* pathPtr = documents.modelPath(*modelId); |
649 QString defaultPath = (pathPtr != nullptr) ? *pathPtr : ""; |
623 QString defaultPath = (pathPtr != nullptr) ? *pathPtr : ""; |
650 const QString newPath = QFileDialog::getSaveFileName( |
624 const QString newPath = QFileDialog::getSaveFileName( |
655 ); |
629 ); |
656 if (not newPath.isEmpty()) { |
630 if (not newPath.isEmpty()) { |
657 QString error; |
631 QString error; |
658 QTextStream errorStream{&error}; |
632 QTextStream errorStream{&error}; |
659 documents.setModelPath(*modelId, newPath, libraries, errorStream); |
633 documents.setModelPath(*modelId, newPath, libraries, errorStream); |
660 QMdiSubWindow* const subWindow = ui.mdiArea->currentSubWindow(); |
634 QMdiSubWindow* const subWindow = mainWindow.mdiArea->currentSubWindow(); |
661 if (subWindow != nullptr) { |
635 if (subWindow != nullptr) { |
662 subWindow->setWindowTitle(tabName(QFileInfo{newPath})); |
636 subWindow->setWindowTitle(tabName(QFileInfo{newPath})); |
663 } |
637 } |
664 save(*modelId); |
638 save(&documents, *modelId); |
665 } |
639 } |
666 } |
640 } |
667 }; |
641 }; |
668 QObject::connect(ui.actionSaveAs, &QAction::triggered, actionSaveAs); |
642 QObject::connect(mainWindow.actionSaveAs, &QAction::triggered, actionSaveAs); |
669 QObject::connect(ui.actionSave, &QAction::triggered, [ |
643 QObject::connect(mainWindow.actionSave, &QAction::triggered, [ |
670 &actionSaveAs, |
644 &actionSaveAs, |
671 &documents, |
645 &documents, |
672 &save, |
646 &save, |
673 &ui] |
647 &mainWindow] |
674 { |
648 { |
675 const std::optional<ModelId> modelId = findCurrentModelId(&ui); |
649 const std::optional<ModelId> modelId = findCurrentModelId(&mainWindow); |
676 if (modelId.has_value()) { |
650 if (modelId.has_value()) { |
677 const QString* path = documents.modelPath(*modelId); |
651 const QString* path = documents.modelPath(*modelId); |
678 if (path == nullptr or path->isEmpty()) { |
652 if (path == nullptr or path->isEmpty()) { |
679 actionSaveAs(); |
653 actionSaveAs(); |
680 } |
654 } |
681 else { |
655 else { |
682 save(*modelId); |
656 save(&documents, *modelId); |
683 } |
657 } |
684 } |
658 } |
685 }); |
659 }); |
686 QObject::connect(ui.actionDrawAxes, &QAction::triggered, [ |
660 QObject::connect(mainWindow.actionDrawAxes, &QAction::triggered, [ |
687 &documents, |
661 &documents, |
688 &renderPreferences, |
662 &renderPreferences, |
689 &saveSettings, |
663 &saveSettings, |
690 &ui] |
664 &mainWindow] |
691 (bool drawAxes) |
665 (bool drawAxes) |
692 { |
666 { |
693 renderPreferences.drawAxes = drawAxes; |
667 renderPreferences.drawAxes = drawAxes; |
694 saveSettings(); |
668 saveSettings(); |
695 updateRenderPreferences(&ui, &renderPreferences, &documents); |
669 updateRenderPreferences(&mainWindow, &renderPreferences, &documents); |
696 }); |
670 }); |
697 QObject::connect(ui.actionWireframe, &QAction::triggered, [ |
671 QObject::connect(mainWindow.actionWireframe, &QAction::triggered, [ |
698 &documents, |
672 &documents, |
699 &renderPreferences, |
673 &renderPreferences, |
700 &saveSettings, |
674 &saveSettings, |
701 &ui] |
675 &mainWindow] |
702 (bool enabled) |
676 (bool enabled) |
703 { |
677 { |
704 renderPreferences.wireframe = enabled; |
678 renderPreferences.wireframe = enabled; |
705 saveSettings(); |
679 saveSettings(); |
706 updateRenderPreferences(&ui, &renderPreferences, &documents); |
680 updateRenderPreferences(&mainWindow, &renderPreferences, &documents); |
707 }); |
681 }); |
708 for (auto data : ::renderStyleButtons) { |
682 QObject::connect(&mainWindow, &MainWindow::renderStyleSelected, [ |
709 QAction* action = data.memberInstance(&ui); |
683 &documents, |
710 QObject::connect(action, &QAction::triggered, [&, data]{ |
684 &mainWindow, |
711 renderPreferences.style = data.payload; |
685 &renderPreferences, |
712 saveSettings(); |
686 &saveSettings] |
713 updateRenderPreferences(&ui, &renderPreferences, &documents); |
687 (gl::RenderStyle newStyle) |
714 }); |
688 { |
715 } |
689 renderPreferences.style = newStyle; |
716 const auto checkEditingModeAction = [&ui, &documents](EditingMode mode) { |
690 saveSettings(); |
717 const bool hasDocument = currentModelData(&ui, &documents) != nullptr; |
691 updateRenderPreferences(&mainWindow, &renderPreferences, &documents); |
718 for (QAction* action : ui.editingModesToolBar->actions()) { |
692 }); |
|
693 const auto checkEditingModeAction = [&mainWindow, &documents](EditingMode mode) { |
|
694 const bool hasDocument = currentModelData(&mainWindow, &documents) != nullptr; |
|
695 for (QAction* action : mainWindow.editingModesToolBar->actions()) { |
719 action->setEnabled(hasDocument); |
696 action->setEnabled(hasDocument); |
720 action->setChecked(hasDocument and action->data().value<EditingMode>() == mode); |
697 action->setChecked(hasDocument and action->data().value<EditingMode>() == mode); |
721 } |
698 } |
722 }; |
699 }; |
723 initializeTools(&ui, &toolWidgets, &mainWindow); |
700 initializeTools(&mainWindow, &toolWidgets, &mainWindow); |
724 for (QAction* action : ui.editingModesToolBar->actions()) { |
701 for (QAction* action : mainWindow.editingModesToolBar->actions()) { |
725 QObject::connect(action, &QAction::triggered, [ |
702 QObject::connect(action, &QAction::triggered, [ |
726 action, |
703 action, |
727 &checkEditingModeAction, |
704 &checkEditingModeAction, |
728 &documents, |
705 &documents, |
729 &ui] |
706 &mainWindow] |
730 { |
707 { |
731 if (ModelData* data = currentModelData(&ui, &documents)) { |
708 if (ModelData* data = currentModelData(&mainWindow, &documents)) { |
732 const EditingMode mode = action->data().value<EditingMode>(); |
709 const EditingMode mode = action->data().value<EditingMode>(); |
733 data->tools->setEditMode(mode); |
710 data->tools->setEditMode(mode); |
734 checkEditingModeAction(mode); |
711 checkEditingModeAction(mode); |
735 } |
712 } |
736 }); |
713 }); |
737 } |
714 } |
738 QObject::connect(ui.mdiArea, &QMdiArea::subWindowActivated, [ |
715 QObject::connect(mainWindow.mdiArea, &QMdiArea::subWindowActivated, [ |
739 &checkEditingModeAction, |
716 &checkEditingModeAction, |
740 &documents, |
717 &documents, |
741 &ui, |
718 &mainWindow, |
742 &updateTitle] |
719 &updateTitle] |
743 (QMdiSubWindow* subWindow) |
720 (QMdiSubWindow* subWindow) |
744 { |
721 { |
745 ModelSubWindow* modelSubWindow = qobject_cast<ModelSubWindow*>(subWindow); |
722 ModelSubWindow* modelSubWindow = qobject_cast<ModelSubWindow*>(subWindow); |
746 if (modelSubWindow != nullptr) { |
723 if (modelSubWindow != nullptr) { |
747 if (ModelData* data = documents.findPayload<ModelData>(modelSubWindow->modelId)) { |
724 if (ModelData* data = documents.findPayload<ModelData>(modelSubWindow->modelId)) { |
748 checkEditingModeAction(data->tools->currentEditingMode()); |
725 checkEditingModeAction(data->tools->currentEditingMode()); |
749 ui.modelEdit->setDocument(data->model); |
726 mainWindow.modelEdit->setDocument(data->model); |
750 ui.modelEdit->setTextCursor(*data->textcursor); |
727 mainWindow.modelEdit->setTextCursor(*data->textcursor); |
751 } |
728 } |
752 } |
729 } |
753 else { |
730 else { |
754 checkEditingModeAction(EditingMode::SelectMode); |
731 checkEditingModeAction(EditingMode::SelectMode); |
755 } |
732 } |
756 ui.modelEdit->setEnabled(modelSubWindow != nullptr); |
733 mainWindow.modelEdit->setEnabled(modelSubWindow != nullptr); |
757 updateTitle(); |
734 updateTitle(); |
758 }); |
735 }); |
759 ui.messageLog->setModel(&messageLog); |
736 mainWindow.messageLog->setModel(&messageLog); |
760 QObject::connect(ui.actionAboutQt, &QAction::triggered, &app, &QApplication::aboutQt); |
737 QObject::connect(mainWindow.actionAboutQt, &QAction::triggered, &app, &QApplication::aboutQt); |
761 QObject::connect(&documents, &DocumentManager::message, &messageLog, &MessageLog::addMessage); |
738 QObject::connect(&documents, &DocumentManager::message, &messageLog, &MessageLog::addMessage); |
762 QObject::connect(&messageLog, &MessageLog::rowsAboutToBeInserted, [&ui]{ |
739 QObject::connect(&messageLog, &MessageLog::rowsAboutToBeInserted, [&mainWindow]{ |
763 const auto bar = ui.messageLog->verticalScrollBar(); |
740 const auto bar = mainWindow.messageLog->verticalScrollBar(); |
764 ui.messageLog->setProperty("shouldAutoScroll", bar->value() == bar->maximum()); |
741 mainWindow.messageLog->setProperty("shouldAutoScroll", bar->value() == bar->maximum()); |
765 }); |
742 }); |
766 QObject::connect(&messageLog, &MessageLog::rowsInserted, [&ui]{ |
743 QObject::connect(&messageLog, &MessageLog::rowsInserted, [&mainWindow]{ |
767 ui.messageLog->resizeRowsToContents(); |
744 mainWindow.messageLog->resizeRowsToContents(); |
768 if (ui.messageLog->property("shouldAutoScroll").toBool()) { |
745 if (mainWindow.messageLog->property("shouldAutoScroll").toBool()) { |
769 ui.messageLog->scrollToBottom(); |
746 mainWindow.messageLog->scrollToBottom(); |
770 } |
747 } |
771 }); |
748 }); |
772 QObject::connect( |
749 QObject::connect( |
773 toolWidgets.circleToolOptions, |
750 toolWidgets.circleToolOptions, |
774 &CircleToolOptionsWidget::optionsChanged, |
751 &CircleToolOptionsWidget::optionsChanged, |
775 [&ui, &documents](const CircleToolOptions& options) { |
752 [&mainWindow, &documents](const CircleToolOptions& options) { |
776 if (ModelData* data = currentModelData(&ui, &documents)) { |
753 if (ModelData* data = currentModelData(&mainWindow, &documents)) { |
777 data->tools->setCircleToolOptions(options); |
754 data->tools->setCircleToolOptions(options); |
778 } |
755 } |
779 }); |
756 }); |
780 QObject::connect( |
757 QObject::connect( |
781 ui.actionMakeUnofficial, |
758 mainWindow.actionMakeUnofficial, |
782 &QAction::triggered, |
759 &QAction::triggered, |
783 [&documents, &ui]{ |
760 [&documents, &mainWindow]{ |
784 if (ModelData* data = currentModelData(&ui, &documents)) { |
761 if (ModelData* data = currentModelData(&mainWindow, &documents)) { |
785 QTextDocument* const model = data->model; |
762 QTextDocument* const model = data->model; |
786 for (const ModelAction& action : ldraw::makeUnofficial(model)) { |
763 for (const ModelAction& action : ldraw::makeUnofficial(model)) { |
787 executeAction(model, action); |
764 executeAction(model, action); |
788 } |
765 } |
789 } |
766 } |
790 }); |
767 }); |
791 QObject::connect( |
768 QObject::connect( |
792 ui.actionAbout, |
769 mainWindow.actionAbout, |
793 &QAction::triggered, |
770 &QAction::triggered, |
794 [&mainWindow, &ui]{ |
771 [&mainWindow]{ |
795 // Make sure that there's an OpenGL context active, otherwise |
772 // Make sure that there's an OpenGL context active, otherwise |
796 // we cannot obtain OpenGL information |
773 // we cannot obtain OpenGL information |
797 if (ui.mdiArea->findChildren<ModelSubWindow*>().empty()) { |
774 if (mainWindow.mdiArea->findChildren<ModelSubWindow*>().empty()) { |
798 ui.actionNew->trigger(); |
775 mainWindow.actionNew->trigger(); |
799 } |
776 } |
800 about(&mainWindow); |
777 about(&mainWindow); |
801 } |
778 } |
802 ); |
779 ); |
803 QObject::connect( |
780 QObject::connect( |
804 ui.modelEdit, |
781 mainWindow.modelEdit, |
805 &QPlainTextEdit::textChanged, |
782 &QPlainTextEdit::textChanged, |
806 [&documents, &libraries, &ui]{ |
783 [&documents, &libraries, &mainWindow]{ |
807 if (ModelData* data = currentModelData(&ui, &documents)) { |
784 if (ModelData* data = currentModelData(&mainWindow, &documents)) { |
808 documents.loadDependenciesForAllModels(libraries); |
785 documents.loadDependenciesForAllModels(libraries); |
809 data->canvas->update(); |
786 data->canvas->update(); |
810 } |
787 } |
811 }); |
788 }); |
812 mainWindow.tabifyDockWidget(ui.messageLogDock, ui.toolOptionsDock); |
789 mainWindow.tabifyDockWidget(mainWindow.messageLogDock, mainWindow.toolOptionsDock); |
813 mainWindow.restoreGeometry(setting<Setting::MainWindowGeometry>()); |
790 mainWindow.restoreGeometry(setting<Setting::MainWindowGeometry>()); |
814 mainWindow.restoreState(setting<Setting::MainWindowState>()); |
791 mainWindow.restoreState(setting<Setting::MainWindowState>()); |
815 // If a dock is made floating and the app is closed, the dock becomes invisible |
792 // If a dock is made floating and the app is closed, the dock becomes invisible |
816 // after the restoreState call. So we make them visible again here. |
793 // after the restoreState call. So we make them visible again here. |
817 for (QDockWidget* dock : mainWindow.findChildren<QDockWidget*>()) { |
794 for (QDockWidget* dock : mainWindow.findChildren<QDockWidget*>()) { |
818 dock->setVisible(true); |
795 dock->setVisible(true); |
819 } |
796 } |
820 restoreSettings(); |
797 restoreSettings(); |
821 updateRenderPreferences(&ui, &renderPreferences, &documents); |
798 updateRenderPreferences(&mainWindow, &renderPreferences, &documents); |
822 ui.actionAbout->setText(ui.actionAbout->text().arg(CMAKE_PROJECT_NAME)); |
799 mainWindow.actionAbout->setText(mainWindow.actionAbout->text().arg(CMAKE_PROJECT_NAME)); |
823 updateTitle(); |
800 updateTitle(); |
824 mainWindow.show(); |
801 mainWindow.show(); |
825 const int result = app.exec(); |
802 const int result = app.exec(); |
826 saveSettings(); |
803 saveSettings(); |
827 return result; |
804 return result; |