src/main.cpp

changeset 353
c229d38f04c6
parent 352
59a31dd8a33a
child 354
91053052bb28
equal deleted inserted replaced
352:59a31dd8a33a 353:c229d38f04c6
372 SubWindow* subWindow = new SubWindow{args..., nullptr}; 372 SubWindow* subWindow = new SubWindow{args..., nullptr};
373 mdiArea->addSubWindow(subWindow); 373 mdiArea->addSubWindow(subWindow);
374 return subWindow; 374 return subWindow;
375 } 375 }
376 376
377 static void executeAction(QTextDocument* model, const ModelAction& action)
378 {
379 std::visit(overloaded{
380 [model](const AppendToModel& action){
381 QTextCursor cursor{model};
382 cursor.movePosition(QTextCursor::End);
383 const QString newText = modelElementToString(action.newElement);
384 // Make sure we have an empty line
385 if (not model->lastBlock().text().isEmpty()) {
386 cursor.insertBlock();
387 }
388 cursor.insertText(newText);
389 },
390 [](const DeleteFromModel&){},
391 [model](const ModifyModel& action){
392 QTextBlock block = model->findBlockByLineNumber((int) action.position);
393 if (block.isValid()) {
394 QTextCursor cursor{block};
395 cursor.select(QTextCursor::LineUnderCursor);
396 cursor.insertText(modelElementToString(action.newElement));
397 }
398 //model->assignAt(action.position, action.newElement);
399 },
400 }, action);
401 }
402
377 int main(int argc, char *argv[]) 403 int main(int argc, char *argv[])
378 { 404 {
379 doQtRegistrations(); 405 doQtRegistrations();
380 QApplication app{argc, argv}; 406 QApplication app{argc, argv};
381 QApplication::setWindowIcon(QIcon{":/icons/appicon.png"}); 407 QApplication::setWindowIcon(QIcon{":/icons/appicon.png"});
397 const auto updateTitle = [&ui, &mainWindow]{ 423 const auto updateTitle = [&ui, &mainWindow]{
398 mainWindow.setWindowTitle(title(&ui)); 424 mainWindow.setWindowTitle(title(&ui));
399 }; 425 };
400 const uiutilities::KeySequenceMap defaultKeyboardShortcuts = 426 const uiutilities::KeySequenceMap defaultKeyboardShortcuts =
401 uiutilities::makeKeySequenceMap(uiutilities::collectActions(&mainWindow)); 427 uiutilities::makeKeySequenceMap(uiutilities::collectActions(&mainWindow));
402 const auto saveSettings = [&]{ 428 const auto saveSettings = [
429 &libraries,
430 &mainWindow,
431 &recentlyOpenedFiles,
432 &renderPreferences,
433 &settingsChanged]
434 {
403 setSetting<Setting::MainWindowGeometry>(mainWindow.saveGeometry()); 435 setSetting<Setting::MainWindowGeometry>(mainWindow.saveGeometry());
404 setSetting<Setting::MainWindowState>(mainWindow.saveState()); 436 setSetting<Setting::MainWindowState>(mainWindow.saveState());
405 setSetting<Setting::RecentFiles>(recentlyOpenedFiles); 437 setSetting<Setting::RecentFiles>(recentlyOpenedFiles);
406 setSetting<Setting::RenderStyle>(renderPreferences.style); 438 setSetting<Setting::RenderStyle>(renderPreferences.style);
407 setSetting<Setting::DrawAxes>(renderPreferences.drawAxes); 439 setSetting<Setting::DrawAxes>(renderPreferences.drawAxes);
408 setSetting<Setting::Wireframe>(renderPreferences.wireframe); 440 setSetting<Setting::Wireframe>(renderPreferences.wireframe);
409 libraries.storeToSettings(); 441 libraries.storeToSettings();
410 settingsChanged.emit(); 442 settingsChanged.emit();
411 }; 443 };
412 const auto executeAction = [&]( 444 const auto openModelForEditing = [
413 QTextDocument* model, const ModelAction& action 445 &colorTable,
414 ) { 446 &documents,
415 std::visit(overloaded{ 447 &mainWindow,
416 [model](const AppendToModel& action){ 448 &messageLog,
417 QTextCursor cursor{model}; 449 &renderPreferences,
418 cursor.movePosition(QTextCursor::End); 450 &settingsChanged,
419 const QString newText = modelElementToString(action.newElement); 451 &ui]
420 // Make sure we have an empty line 452 (const ModelId modelId)
421 if (not model->lastBlock().text().isEmpty()) { 453 {
422 cursor.insertBlock();
423 }
424 cursor.insertText(newText);
425 },
426 [](const DeleteFromModel&){},
427 [model](const ModifyModel& action){
428 QTextBlock block = model->findBlockByLineNumber((int) action.position);
429 if (block.isValid()) {
430 QTextCursor cursor{block};
431 cursor.select(QTextCursor::LineUnderCursor);
432 cursor.insertText(modelElementToString(action.newElement));
433 }
434 //model->assignAt(action.position, actio邉󠄌n.newElement);
435 },
436 }, action);
437
438 };
439 const auto openModelForEditing = [&](const ModelId modelId){
440 QTextDocument* model = documents.getModelById(modelId); 454 QTextDocument* model = documents.getModelById(modelId);
441 if (model != nullptr) { 455 if (model != nullptr) {
442 ModelData* data = new ModelData(&documents); 456 ModelData* data = new ModelData(&documents);
443 data->tools = std::make_unique<EditTools>(); 457 data->tools = std::make_unique<EditTools>();
444 data->canvas = std::make_unique<PartRenderer>(model, &documents, colorTable); 458 data->canvas = std::make_unique<PartRenderer>(model, &documents, colorTable);
461 std::bind(executeAction, model, std::placeholders::_1)); 475 std::bind(executeAction, model, std::placeholders::_1));
462 data->canvas->setRenderPreferences(renderPreferences); 476 data->canvas->setRenderPreferences(renderPreferences);
463 QObject::connect( 477 QObject::connect(
464 data->tools.get(), 478 data->tools.get(),
465 &EditTools::newStatusText, 479 &EditTools::newStatusText,
466 [&](const QString& newStatusText) { 480 [&mainWindow](const QString& newStatusText) {
467 mainWindow.statusBar()->showMessage(newStatusText); 481 mainWindow.statusBar()->showMessage(newStatusText);
468 }); 482 });
469 #if 0 483 #if 0
470 QObject::connect( 484 QObject::connect(
471 data->tools.get(), 485 data->tools.get(),
506 subWindow->setWidget(data->canvas.get()); 520 subWindow->setWidget(data->canvas.get());
507 subWindow->setWindowTitle(tabName(fileInfo)); 521 subWindow->setWindowTitle(tabName(fileInfo));
508 subWindow->show(); 522 subWindow->show();
509 } 523 }
510 }; 524 };
511 const auto updateRecentlyOpenedDocumentsMenu = [&]{ 525 const auto updateRecentlyOpenedDocumentsMenu = [
526 &documents,
527 &libraries,
528 &mainWindow,
529 &openModelForEditing,
530 &recentlyOpenedFiles,
531 &ui]
532 {
512 rebuildRecentFilesMenu(ui.menuRecentFiles, recentlyOpenedFiles, &mainWindow); 533 rebuildRecentFilesMenu(ui.menuRecentFiles, recentlyOpenedFiles, &mainWindow);
513 for (QAction* action : ui.menuRecentFiles->actions()) { 534 for (QAction* action : ui.menuRecentFiles->actions()) {
514 QString path = action->data().toString(); 535 QString path = action->data().toString();
515 QObject::connect( 536 QObject::connect(
516 action, 537 action,
523 } 544 }
524 } 545 }
525 ); 546 );
526 } 547 }
527 }; 548 };
528 const auto restoreSettings = [&]{ 549 const auto restoreSettings = [
550 &colorTable,
551 &documents,
552 &libraries,
553 &mainWindow,
554 &recentlyOpenedFiles,
555 &renderPreferences,
556 &settingsChanged,
557 &ui,
558 &updateRecentlyOpenedDocumentsMenu]
559 {
529 recentlyOpenedFiles = setting<Setting::RecentFiles>(); 560 recentlyOpenedFiles = setting<Setting::RecentFiles>();
530 renderPreferences = loadRenderPreferences(); 561 renderPreferences = loadRenderPreferences();
531 libraries.restoreFromSettings(); 562 libraries.restoreFromSettings();
532 updateRecentlyOpenedDocumentsMenu(); 563 updateRecentlyOpenedDocumentsMenu();
533 colorTable = loadColors(&libraries); 564 colorTable = loadColors(&libraries);
535 ui.mdiArea->setViewMode(setting<Setting::ViewMode>()); 566 ui.mdiArea->setViewMode(setting<Setting::ViewMode>());
536 ui.retranslateUi(&mainWindow); 567 ui.retranslateUi(&mainWindow);
537 mainWindow.setToolButtonStyle(setting<Setting::ToolButtonStyle>()); 568 mainWindow.setToolButtonStyle(setting<Setting::ToolButtonStyle>());
538 settingsChanged.emit(); 569 settingsChanged.emit();
539 }; 570 };
540 const auto addRecentlyOpenedFile = [&](const QString& path){ 571 const auto addRecentlyOpenedFile = [
572 &recentlyOpenedFiles,
573 &saveSettings,
574 &updateRecentlyOpenedDocumentsMenu]
575 (const QString& path)
576 {
541 constexpr int maxRecentlyOpenedFiles = 10; 577 constexpr int maxRecentlyOpenedFiles = 10;
542 recentlyOpenedFiles.removeAll(path); 578 recentlyOpenedFiles.removeAll(path);
543 recentlyOpenedFiles.insert(0, path); 579 recentlyOpenedFiles.insert(0, path);
544 while (recentlyOpenedFiles.size() > maxRecentlyOpenedFiles) 580 while (recentlyOpenedFiles.size() > maxRecentlyOpenedFiles)
545 { 581 {
546 recentlyOpenedFiles.removeLast(); 582 recentlyOpenedFiles.removeLast();
547 } 583 }
548 saveSettings(); 584 saveSettings();
549 updateRecentlyOpenedDocumentsMenu(); 585 updateRecentlyOpenedDocumentsMenu();
550 }; 586 };
551 QObject::connect(ui.actionNew, &QAction::triggered, [&]{ 587 QObject::connect(ui.actionNew, &QAction::triggered,
552 openModelForEditing(documents.newModel()); 588 [&documents, &openModelForEditing]{
553 }); 589 openModelForEditing(documents.newModel());
554 QObject::connect(ui.actionOpen, &QAction::triggered, [&]{ 590 }
555 const QString path = getOpenModelPath(&mainWindow); 591 );
556 if (not path.isEmpty()) 592 QObject::connect(ui.actionOpen, &QAction::triggered,
593 [&addRecentlyOpenedFile, &documents, &libraries, &mainWindow, &openModelForEditing]
557 { 594 {
558 const std::optional<ModelId> id = openModelFromPath(path, &libraries, &documents, &mainWindow); 595 const QString path = getOpenModelPath(&mainWindow);
559 if (id.has_value()) { 596 if (not path.isEmpty())
560 openModelForEditing(id.value()); 597 {
561 addRecentlyOpenedFile(path); 598 const std::optional<ModelId> id = openModelFromPath(path, &libraries, &documents, &mainWindow);
562 } 599 if (id.has_value()) {
563 } 600 openModelForEditing(id.value());
564 }); 601 addRecentlyOpenedFile(path);
565 QObject::connect(ui.actionSettingsEditor, &QAction::triggered, [&]{ 602 }
603 }
604 }
605 );
606 QObject::connect(ui.actionSettingsEditor, &QAction::triggered, [&defaultKeyboardShortcuts, &restoreSettings, &settingsChanged, &ui]{
566 if (ui.mdiArea->findChildren<SettingsEditor*>().isEmpty()) { 607 if (ui.mdiArea->findChildren<SettingsEditor*>().isEmpty()) {
567 auto* const settingsEditor = createSubWindow<SettingsEditor>(ui.mdiArea, defaultKeyboardShortcuts); 608 auto* const settingsEditor = createSubWindow<SettingsEditor>(ui.mdiArea, defaultKeyboardShortcuts);
568 QObject::connect(&settingsChanged, &Signal::triggered, settingsEditor, &SettingsEditor::loadSettings); 609 QObject::connect(&settingsChanged, &Signal::triggered, settingsEditor, &SettingsEditor::loadSettings);
569 QObject::connect(settingsEditor, &SettingsEditor::settingsChanged, restoreSettings); 610 QObject::connect(settingsEditor, &SettingsEditor::settingsChanged, restoreSettings);
570 settingsEditor->setAttribute(Qt::WA_DeleteOnClose); 611 settingsEditor->setAttribute(Qt::WA_DeleteOnClose);
582 QObject::connect(ui.actionClose, &QAction::triggered, [&ui, &documents]{ 623 QObject::connect(ui.actionClose, &QAction::triggered, [&ui, &documents]{
583 if (ModelData* data = currentModelData(&ui, &documents)) { 624 if (ModelData* data = currentModelData(&ui, &documents)) {
584 // TODO 625 // TODO
585 } 626 }
586 }); 627 });
587 const auto save = [&](ModelId modelId){ 628 const auto save = [&addRecentlyOpenedFile, &documents, &mainWindow](ModelId modelId){
588 QString error; 629 QString error;
589 QTextStream errorStream{&error}; 630 QTextStream errorStream{&error};
590 const bool succeeded = documents.saveModel(modelId, errorStream); 631 const bool succeeded = documents.saveModel(modelId, errorStream);
591 if (not succeeded) 632 if (not succeeded)
592 { 633 {
598 if (pathPtr != nullptr) { 639 if (pathPtr != nullptr) {
599 addRecentlyOpenedFile(*pathPtr); 640 addRecentlyOpenedFile(*pathPtr);
600 } 641 }
601 } 642 }
602 };; 643 };;
603 const auto actionSaveAs = [&]{ 644 const auto actionSaveAs = [&documents, &libraries, &mainWindow, &save, &ui]{
604 const std::optional<ModelId> modelId = findCurrentModelId(&ui); 645 const std::optional<ModelId> modelId = findCurrentModelId(&ui);
605 if (modelId.has_value()) 646 if (modelId.has_value())
606 { 647 {
607 const QString* pathPtr = documents.modelPath(*modelId); 648 const QString* pathPtr = documents.modelPath(*modelId);
608 QString defaultPath = (pathPtr != nullptr) ? *pathPtr : ""; 649 QString defaultPath = (pathPtr != nullptr) ? *pathPtr : "";
623 save(*modelId); 664 save(*modelId);
624 } 665 }
625 } 666 }
626 }; 667 };
627 QObject::connect(ui.actionSaveAs, &QAction::triggered, actionSaveAs); 668 QObject::connect(ui.actionSaveAs, &QAction::triggered, actionSaveAs);
628 QObject::connect(ui.actionSave, &QAction::triggered, [&]{ 669 QObject::connect(ui.actionSave, &QAction::triggered, [
670 &actionSaveAs,
671 &documents,
672 &save,
673 &ui]
674 {
629 const std::optional<ModelId> modelId = findCurrentModelId(&ui); 675 const std::optional<ModelId> modelId = findCurrentModelId(&ui);
630 if (modelId.has_value()) { 676 if (modelId.has_value()) {
631 const QString* path = documents.modelPath(*modelId); 677 const QString* path = documents.modelPath(*modelId);
632 if (path == nullptr or path->isEmpty()) { 678 if (path == nullptr or path->isEmpty()) {
633 actionSaveAs(); 679 actionSaveAs();
635 else { 681 else {
636 save(*modelId); 682 save(*modelId);
637 } 683 }
638 } 684 }
639 }); 685 });
640 QObject::connect(ui.actionDrawAxes, &QAction::triggered, [&](bool drawAxes){ 686 QObject::connect(ui.actionDrawAxes, &QAction::triggered, [
687 &documents,
688 &renderPreferences,
689 &saveSettings,
690 &ui]
691 (bool drawAxes)
692 {
641 renderPreferences.drawAxes = drawAxes; 693 renderPreferences.drawAxes = drawAxes;
642 saveSettings(); 694 saveSettings();
643 updateRenderPreferences(&ui, &renderPreferences, &documents); 695 updateRenderPreferences(&ui, &renderPreferences, &documents);
644 }); 696 });
645 QObject::connect(ui.actionWireframe, &QAction::triggered, [&](bool enabled){ 697 QObject::connect(ui.actionWireframe, &QAction::triggered, [
698 &documents,
699 &renderPreferences,
700 &saveSettings,
701 &ui]
702 (bool enabled)
703 {
646 renderPreferences.wireframe = enabled; 704 renderPreferences.wireframe = enabled;
647 saveSettings(); 705 saveSettings();
648 updateRenderPreferences(&ui, &renderPreferences, &documents); 706 updateRenderPreferences(&ui, &renderPreferences, &documents);
649 }); 707 });
650 for (auto data : ::renderStyleButtons) { 708 for (auto data : ::renderStyleButtons) {
662 action->setChecked(hasDocument and action->data().value<EditingMode>() == mode); 720 action->setChecked(hasDocument and action->data().value<EditingMode>() == mode);
663 } 721 }
664 }; 722 };
665 initializeTools(&ui, &toolWidgets, &mainWindow); 723 initializeTools(&ui, &toolWidgets, &mainWindow);
666 for (QAction* action : ui.editingModesToolBar->actions()) { 724 for (QAction* action : ui.editingModesToolBar->actions()) {
667 QObject::connect(action, &QAction::triggered, [&, action]{ 725 QObject::connect(action, &QAction::triggered, [
726 action,
727 &checkEditingModeAction,
728 &documents,
729 &ui]
730 {
668 if (ModelData* data = currentModelData(&ui, &documents)) { 731 if (ModelData* data = currentModelData(&ui, &documents)) {
669 const EditingMode mode = action->data().value<EditingMode>(); 732 const EditingMode mode = action->data().value<EditingMode>();
670 data->tools->setEditMode(mode); 733 data->tools->setEditMode(mode);
671 checkEditingModeAction(mode); 734 checkEditingModeAction(mode);
672 } 735 }
673 }); 736 });
674 } 737 }
675 QObject::connect(ui.mdiArea, &QMdiArea::subWindowActivated, 738 QObject::connect(ui.mdiArea, &QMdiArea::subWindowActivated, [
676 [&](QMdiSubWindow* subWindow) { 739 &checkEditingModeAction,
740 &documents,
741 &ui,
742 &updateTitle]
743 (QMdiSubWindow* subWindow)
744 {
677 ModelSubWindow* modelSubWindow = qobject_cast<ModelSubWindow*>(subWindow); 745 ModelSubWindow* modelSubWindow = qobject_cast<ModelSubWindow*>(subWindow);
678 if (modelSubWindow != nullptr) { 746 if (modelSubWindow != nullptr) {
679 if (ModelData* data = documents.findPayload<ModelData>(modelSubWindow->modelId)) { 747 if (ModelData* data = documents.findPayload<ModelData>(modelSubWindow->modelId)) {
680 checkEditingModeAction(data->tools->currentEditingMode()); 748 checkEditingModeAction(data->tools->currentEditingMode());
681 ui.modelEdit->setDocument(data->model); 749 ui.modelEdit->setDocument(data->model);
689 updateTitle(); 757 updateTitle();
690 }); 758 });
691 ui.messageLog->setModel(&messageLog); 759 ui.messageLog->setModel(&messageLog);
692 QObject::connect(ui.actionAboutQt, &QAction::triggered, &app, &QApplication::aboutQt); 760 QObject::connect(ui.actionAboutQt, &QAction::triggered, &app, &QApplication::aboutQt);
693 QObject::connect(&documents, &DocumentManager::message, &messageLog, &MessageLog::addMessage); 761 QObject::connect(&documents, &DocumentManager::message, &messageLog, &MessageLog::addMessage);
694 QObject::connect(&messageLog, &MessageLog::rowsAboutToBeInserted, [&]{ 762 QObject::connect(&messageLog, &MessageLog::rowsAboutToBeInserted, [&ui]{
695 const auto bar = ui.messageLog->verticalScrollBar(); 763 const auto bar = ui.messageLog->verticalScrollBar();
696 ui.messageLog->setProperty("shouldAutoScroll", bar->value() == bar->maximum()); 764 ui.messageLog->setProperty("shouldAutoScroll", bar->value() == bar->maximum());
697 }); 765 });
698 QObject::connect(&messageLog, &MessageLog::rowsInserted, [&]{ 766 QObject::connect(&messageLog, &MessageLog::rowsInserted, [&ui]{
699 ui.messageLog->resizeRowsToContents(); 767 ui.messageLog->resizeRowsToContents();
700 if (ui.messageLog->property("shouldAutoScroll").toBool()) { 768 if (ui.messageLog->property("shouldAutoScroll").toBool()) {
701 ui.messageLog->scrollToBottom(); 769 ui.messageLog->scrollToBottom();
702 } 770 }
703 }); 771 });
710 } 778 }
711 }); 779 });
712 QObject::connect( 780 QObject::connect(
713 ui.actionMakeUnofficial, 781 ui.actionMakeUnofficial,
714 &QAction::triggered, 782 &QAction::triggered,
715 [&]{ 783 [&documents, &ui]{
716 if (ModelData* data = currentModelData(&ui, &documents)) { 784 if (ModelData* data = currentModelData(&ui, &documents)) {
717 QTextDocument* const model = data->model; 785 QTextDocument* const model = data->model;
718 for (const ModelAction& action : ldraw::makeUnofficial(model)) { 786 for (const ModelAction& action : ldraw::makeUnofficial(model)) {
719 executeAction(model, action); 787 executeAction(model, action);
720 } 788 }
733 } 801 }
734 ); 802 );
735 QObject::connect( 803 QObject::connect(
736 ui.modelEdit, 804 ui.modelEdit,
737 &QPlainTextEdit::textChanged, 805 &QPlainTextEdit::textChanged,
738 [&]{ 806 [&documents, &libraries, &ui]{
739 if (ModelData* data = currentModelData(&ui, &documents)) { 807 if (ModelData* data = currentModelData(&ui, &documents)) {
740 documents.loadDependenciesForAllModels(libraries); 808 documents.loadDependenciesForAllModels(libraries);
741 data->canvas->update(); 809 data->canvas->update();
742 } 810 }
743 }); 811 });

mercurial