327:2aa15daa0216 | 328:3ea38fd469ca |
---|---|
19 #include "src/settingseditor/settingseditor.h" | 19 #include "src/settingseditor/settingseditor.h" |
20 #include "src/ui/circletooloptionswidget.h" | 20 #include "src/ui/circletooloptionswidget.h" |
21 #include "src/ui/objecteditor.h" | 21 #include "src/ui/objecteditor.h" |
22 #include "src/version.h" | 22 #include "src/version.h" |
23 #include "src/widgets/colorselectdialog.h" | 23 #include "src/widgets/colorselectdialog.h" |
24 #include "src/parser.h" | |
24 #include <GL/glew.h> | 25 #include <GL/glew.h> |
25 | 26 |
26 static const QDir LOCALE_DIR {":/locale"}; | 27 static const QDir LOCALE_DIR {":/locale"}; |
27 | 28 |
28 class ModelSubWindow : public QMdiSubWindow | 29 class ModelSubWindow : public QMdiSubWindow |
46 { | 47 { |
47 Q_OBJECT | 48 Q_OBJECT |
48 public: | 49 public: |
49 ModelData(QObject* parent) : QObject {parent} {} | 50 ModelData(QObject* parent) : QObject {parent} {} |
50 std::unique_ptr<PartRenderer> canvas; | 51 std::unique_ptr<PartRenderer> canvas; |
51 std::unique_ptr<QItemSelectionModel> itemSelectionModel; | |
52 std::unique_ptr<EditTools> tools; | 52 std::unique_ptr<EditTools> tools; |
53 std::unique_ptr<AxesLayer> axesLayer; | 53 std::unique_ptr<AxesLayer> axesLayer; |
54 std::unique_ptr<GridLayer> gridLayer; | 54 std::unique_ptr<GridLayer> gridLayer; |
55 std::unique_ptr<QTextDocument> textbuffer; | |
56 std::unique_ptr<QTextCursor> textcursor; | |
55 Model* model; | 57 Model* model; |
56 }; | 58 }; |
57 | 59 |
58 class Signal final : public QObject | 60 class Signal final : public QObject |
59 { | 61 { |
399 return subWindow; | 401 return subWindow; |
400 } | 402 } |
401 | 403 |
402 static QSet<ElementId> resolveIdsFromSelection(const ModelData* data) | 404 static QSet<ElementId> resolveIdsFromSelection(const ModelData* data) |
403 { | 405 { |
404 const auto selection = data->itemSelectionModel->selection(); | 406 // const auto selection = data->itemSelectionModel->selection(); |
405 QSet<ElementId> selectedIndexes; | 407 QSet<ElementId> selectedIndexes; |
406 for (const QModelIndex& qindex : selection.indexes()) { | 408 /* for (const QModelIndex& qindex : selection.indexes()) { |
407 const std::size_t row = unsigned_cast(qindex.row()); | 409 const std::size_t row = unsigned_cast(qindex.row()); |
408 selectedIndexes.insert(data->model->idAt(row)); | 410 selectedIndexes.insert(data->model->idAt(row)); |
409 } | 411 } |
410 return selectedIndexes; | 412 */ return selectedIndexes; |
411 } | 413 } |
412 | 414 |
413 int main(int argc, char *argv[]) | 415 int main(int argc, char *argv[]) |
414 { | 416 { |
415 doQtRegistrations(); | 417 doQtRegistrations(); |
425 ColorTable colorTable; | 427 ColorTable colorTable; |
426 gl::RenderPreferences renderPreferences; | 428 gl::RenderPreferences renderPreferences; |
427 MessageLog messageLog; | 429 MessageLog messageLog; |
428 Signal settingsChanged; | 430 Signal settingsChanged; |
429 ui.setupUi(&mainWindow); | 431 ui.setupUi(&mainWindow); |
432 QFont monospace{"Monospace"}; | |
433 monospace.setStyleHint(QFont::TypeWriter); | |
434 monospace.setPointSize(10); | |
435 monospace.setFixedPitch(true); | |
436 ui.modelEdit->setFont(monospace); | |
430 ToolWidgets toolWidgets{ | 437 ToolWidgets toolWidgets{ |
431 .circleToolOptions = new CircleToolOptionsWidget{&mainWindow}, | 438 .circleToolOptions = new CircleToolOptionsWidget{&mainWindow}, |
432 .objectEditor = new ObjectEditor{&mainWindow}, | 439 .objectEditor = new ObjectEditor{&mainWindow}, |
433 }; | 440 }; |
434 const auto updateTitle = [&ui, &mainWindow]{ | 441 const auto updateTitle = [&ui, &mainWindow]{ |
460 } | 467 } |
461 }; | 468 }; |
462 const auto executeAction = [&]( | 469 const auto executeAction = [&]( |
463 Model* model, const ModelAction& action | 470 Model* model, const ModelAction& action |
464 ) { | 471 ) { |
472 /* | |
465 std::visit(overloaded{ | 473 std::visit(overloaded{ |
466 [model](const AppendToModel& action){ | 474 [model](const AppendToModel& action){ |
467 model->append(action.newElement); | 475 model->append(action.newElement); |
468 }, | 476 }, |
469 [model](const DeleteFromModel& action){ | 477 [model](const DeleteFromModel& action){ |
471 }, | 479 }, |
472 [model](const ModifyModel& action){ | 480 [model](const ModifyModel& action){ |
473 model->assignAt(action.position, action.newElement); | 481 model->assignAt(action.position, action.newElement); |
474 }, | 482 }, |
475 }, action); | 483 }, action); |
484 */ | |
476 }; | 485 }; |
477 const auto restoreSettings = [&]{ | 486 const auto restoreSettings = [&]{ |
478 recentlyOpenedFiles = setting<Setting::RecentFiles>(); | 487 recentlyOpenedFiles = setting<Setting::RecentFiles>(); |
479 renderPreferences = loadRenderPreferences(); | 488 renderPreferences = loadRenderPreferences(); |
480 libraries.restoreFromSettings(); | 489 libraries.restoreFromSettings(); |
500 Model* model = documents.getModelById(modelId); | 509 Model* model = documents.getModelById(modelId); |
501 if (model != nullptr) { | 510 if (model != nullptr) { |
502 ModelData* data = new ModelData(&documents); | 511 ModelData* data = new ModelData(&documents); |
503 data->tools = std::make_unique<EditTools>(); | 512 data->tools = std::make_unique<EditTools>(); |
504 data->canvas = std::make_unique<PartRenderer>(model, &documents, colorTable); | 513 data->canvas = std::make_unique<PartRenderer>(model, &documents, colorTable); |
505 data->itemSelectionModel = std::make_unique<QItemSelectionModel>(); | |
506 data->itemSelectionModel->setModel(model); | |
507 data->axesLayer = std::make_unique<AxesLayer>(); | 514 data->axesLayer = std::make_unique<AxesLayer>(); |
508 constexpr glm::mat4 XZ = {{1, 0, 0, 0}, {0, 0, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 1}}; | 515 constexpr glm::mat4 XZ = {{1, 0, 0, 0}, {0, 0, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 1}}; |
509 data->gridLayer = std::make_unique<GridLayer>(); | 516 data->gridLayer = std::make_unique<GridLayer>(); |
510 data->gridLayer->setGridMatrix(XZ); | 517 data->gridLayer->setGridMatrix(XZ); |
511 data->tools->setGridMatrix(XZ); | 518 data->tools->setGridMatrix(XZ); |
512 data->model = model; | 519 data->model = model; |
513 data->canvas->addRenderLayer(data->axesLayer.get()); | 520 data->canvas->addRenderLayer(data->axesLayer.get()); |
514 data->canvas->setLayerEnabled(data->axesLayer.get(), setting<Setting::DrawAxes>()); | 521 data->canvas->setLayerEnabled(data->axesLayer.get(), setting<Setting::DrawAxes>()); |
515 data->canvas->addRenderLayer(data->gridLayer.get()); | 522 data->canvas->addRenderLayer(data->gridLayer.get()); |
516 data->canvas->addRenderLayer(data->tools.get()); | 523 data->canvas->addRenderLayer(data->tools.get()); |
524 QString modeltext; | |
525 QTextStream stream{&modeltext}; | |
526 ::save(*model, &stream); | |
527 data->textbuffer = std::make_unique<QTextDocument>(); | |
528 data->textbuffer->setPlainText(modeltext); | |
529 data->textbuffer->setDocumentLayout(new QPlainTextDocumentLayout(data->textbuffer.get())); | |
530 data->textcursor = std::make_unique<QTextCursor>(data->textbuffer.get()); | |
517 documents.setModelPayload(modelId, data); | 531 documents.setModelPayload(modelId, data); |
518 QObject::connect( | 532 QObject::connect( |
519 data->tools.get(), | 533 data->tools.get(), |
520 &EditTools::modelAction, | 534 &EditTools::modelAction, |
521 std::bind(executeAction, model, std::placeholders::_1)); | 535 std::bind(executeAction, model, std::placeholders::_1)); |
522 QObject::connect( | |
523 data->itemSelectionModel.get(), | |
524 &QItemSelectionModel::selectionChanged, | |
525 [modelId, &documents, &toolWidgets]{ | |
526 ModelData* data = findModelData(&documents, modelId); | |
527 if (data != nullptr) { | |
528 data->canvas->setSelection(resolveIdsFromSelection(data)); | |
529 /* | |
530 if (indices.size() == 1) { | |
531 opt<std::size_t> index = data->model->find(*indices.begin()); | |
532 if (index.has_value()) { | |
533 toolWidgets.objectEditor->setObject((*data->model)[*index]); | |
534 } | |
535 } | |
536 else { | |
537 toolWidgets.objectEditor->reset(); | |
538 } | |
539 */ | |
540 } | |
541 }); | |
542 data->canvas->setRenderPreferences(renderPreferences); | 536 data->canvas->setRenderPreferences(renderPreferences); |
543 QObject::connect( | 537 QObject::connect( |
544 data->tools.get(), | 538 data->tools.get(), |
545 &EditTools::newStatusText, | 539 &EditTools::newStatusText, |
546 [&](const QString& newStatusText) { | 540 [&](const QString& newStatusText) { |
547 mainWindow.statusBar()->showMessage(newStatusText); | 541 mainWindow.statusBar()->showMessage(newStatusText); |
548 }); | 542 }); |
543 #if 0 | |
549 QObject::connect( | 544 QObject::connect( |
550 data->tools.get(), | 545 data->tools.get(), |
551 &EditTools::select, | 546 &EditTools::select, |
552 [modelId, &documents](const QSet<ElementId>& indices, bool retain) { | 547 [modelId, &documents](const QSet<ElementId>& indices, bool retain) { |
553 ModelData* data = findModelData(&documents, modelId); | 548 ModelData* data = findModelData(&documents, modelId); |
554 if (data != nullptr) { | 549 if (data != nullptr) { |
555 if (not retain) { | 550 if (not retain) { |
556 data->itemSelectionModel->clear(); | 551 data->textcursor->clearSelection(); |
557 } | 552 } |
558 for (const ElementId id : indices) { | 553 for (const ElementId id : indices) { |
559 opt<int> index = data->model->find(id); | 554 opt<int> index = data->model->find(id); |
560 if (index.has_value()) { | 555 if (index.has_value()) { |
561 const QModelIndex qindex = data->model->index(*index); | 556 const QModelIndex qindex = data->model->index(*index); |
562 data->itemSelectionModel->select(qindex, QItemSelectionModel::Select); | 557 data->itemSelectionModel->select(qindex, QItemSelectionModel::Select); |
563 } | 558 } |
564 } | 559 } |
565 } | 560 } |
566 }); | 561 }); |
562 #endif | |
567 QObject::connect(&settingsChanged, &Signal::triggered, [modelId, &documents]{ | 563 QObject::connect(&settingsChanged, &Signal::triggered, [modelId, &documents]{ |
568 ModelData* data = findModelData(&documents, modelId); | 564 ModelData* data = findModelData(&documents, modelId); |
569 if (data != nullptr) { | 565 if (data != nullptr) { |
570 data->gridLayer->settingsChanged(); | 566 data->gridLayer->settingsChanged(); |
571 } | 567 } |
673 else { | 669 else { |
674 save(*modelId); | 670 save(*modelId); |
675 } | 671 } |
676 } | 672 } |
677 }); | 673 }); |
678 QObject::connect(ui.actionDelete, &QAction::triggered, [&]{ | |
679 if (Model* model = currentModelBody(&ui, &documents)) { | |
680 std::vector<int> selectedRows = rows(ui.modelListView->selectionModel()->selectedRows()); | |
681 std::sort(selectedRows.begin(), selectedRows.end(), std::greater<int>{}); | |
682 for (int row : selectedRows) { | |
683 executeAction(model, DeleteFromModel{.position = unsigned_cast(row)}); | |
684 } | |
685 } | |
686 }); | |
687 QObject::connect(ui.actionDrawAxes, &QAction::triggered, [&](bool drawAxes){ | 674 QObject::connect(ui.actionDrawAxes, &QAction::triggered, [&](bool drawAxes){ |
688 renderPreferences.drawAxes = drawAxes; | 675 renderPreferences.drawAxes = drawAxes; |
689 saveSettings(); | 676 saveSettings(); |
690 updateRenderPreferences(&ui, &renderPreferences, &documents); | 677 updateRenderPreferences(&ui, &renderPreferences, &documents); |
691 }); | 678 }); |
723 [&](QMdiSubWindow* subWindow) { | 710 [&](QMdiSubWindow* subWindow) { |
724 ModelSubWindow* modelSubWindow = qobject_cast<ModelSubWindow*>(subWindow); | 711 ModelSubWindow* modelSubWindow = qobject_cast<ModelSubWindow*>(subWindow); |
725 if (modelSubWindow != nullptr) { | 712 if (modelSubWindow != nullptr) { |
726 if (ModelData* data = documents.findPayload<ModelData>(modelSubWindow->modelId)) { | 713 if (ModelData* data = documents.findPayload<ModelData>(modelSubWindow->modelId)) { |
727 checkEditingModeAction(data->tools->currentEditingMode()); | 714 checkEditingModeAction(data->tools->currentEditingMode()); |
728 if (data->itemSelectionModel != nullptr) { | 715 ui.modelEdit->setDocument(data->textbuffer.get()); |
729 ui.modelListView->setModel(data->model); | 716 ui.modelEdit->setTextCursor(*data->textcursor); |
730 ui.modelListView->setSelectionModel(data->itemSelectionModel.get()); | |
731 } | |
732 } | 717 } |
733 } | 718 } |
734 else { | 719 else { |
735 checkEditingModeAction(EditingMode::SelectMode); | 720 checkEditingModeAction(EditingMode::SelectMode); |
736 } | 721 } |
779 } | 764 } |
780 about(&mainWindow); | 765 about(&mainWindow); |
781 } | 766 } |
782 ); | 767 ); |
783 QObject::connect( | 768 QObject::connect( |
784 ui.actionCopy, | 769 ui.modelEdit, |
785 &QAction::triggered, | 770 &QPlainTextEdit::textChanged, |
786 [&]{ | 771 [&]{ |
787 if (Model* model = currentModelBody(&ui, &documents)) { | 772 if (ModelData* data = currentModelData(&ui, &documents)) { |
788 std::vector<int> selectedRows = rows(ui.modelListView->selectionModel()->selectedRows()); | 773 Model* const model = data->model; |
789 QString text; | 774 model->clear(); |
790 for (int row : selectedRows) { | 775 QString text = ui.modelEdit->toPlainText(); |
791 const std::size_t i = static_cast<std::size_t>(row); | 776 QTextStream stream{&text}; |
792 text += modelElementToString((*model)[i]); | 777 Parser parser(stream); |
793 text += QStringLiteral("\r\n"); | 778 parser.parseBody(*data->model); |
794 } | 779 data->canvas->update(); |
795 app.clipboard()->setText(text); | |
796 } | 780 } |
797 }); | 781 }); |
798 mainWindow.tabifyDockWidget(ui.messageLogDock, ui.toolOptionsDock); | 782 mainWindow.tabifyDockWidget(ui.messageLogDock, ui.toolOptionsDock); |
799 mainWindow.restoreGeometry(setting<Setting::MainWindowGeometry>()); | 783 mainWindow.restoreGeometry(setting<Setting::MainWindowGeometry>()); |
800 mainWindow.restoreState(setting<Setting::MainWindowState>()); | 784 mainWindow.restoreState(setting<Setting::MainWindowState>()); |