diff --git a/.gitignore b/.gitignore index 338a6553..57705ddf 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ etc/installer/packages/Degate/meta/package.xml doc/build/* !doc/build/.keepme doc/config/DoxyFile +.cache diff --git a/src/GUI/MainWindow.cc b/src/GUI/MainWindow.cc index ab3282b5..40c8f397 100644 --- a/src/GUI/MainWindow.cc +++ b/src/GUI/MainWindow.cc @@ -19,11 +19,11 @@ * */ -#include "MainWindow.h" -#include "GUI/Dialog/ProgressDialog.h" -#include "GUI/Dialog/AboutDialog.h" -#include "Core/Version.h" #include "Core/Utils/CrashReport.h" +#include "Core/Version.h" +#include "GUI/Dialog/AboutDialog.h" +#include "GUI/Dialog/ProgressDialog.h" +#include "MainWindow.h" #include @@ -39,10 +39,22 @@ namespace degate { MainWindow::MainWindow(int width, int height) : status_bar(this), tools_group(this), updater(this) { - if (width == 0 || height == 0) - resize(QGuiApplication::screenAt(this->pos())->availableGeometry().size() * 0.7); + auto* current_window_screen = QGuiApplication::screenAt(this->pos()); + if (width > 0 && height > 0) + { + resize(width, height); + } + else if (current_window_screen != nullptr) + { + resize(current_window_screen->availableGeometry().size() * 0.7); + } else + { + width = (width <= 0) ? 800 : width; + height = (height <= 0) ? 600 : height; + resize(width, height); + } setWindowTitle("Degate"); setWindowIcon(QIcon(":/degate_logo.png")); @@ -67,7 +79,7 @@ namespace degate QObject::connect(project_import_action, SIGNAL(triggered()), this, SLOT(on_menu_project_importer())); project_export_action = project_menu->addAction(""); - project_export_action->setShortcut(Qt::CTRL + Qt::Key_S); + project_export_action->setShortcut(Qt::CTRL | Qt::Key_S); QObject::connect(project_export_action, SIGNAL(triggered()), this, SLOT(on_menu_project_save())); project_recent_projects_submenu = project_menu->addMenu(""); @@ -77,7 +89,10 @@ namespace degate project_menu->addSeparator(); project_create_subproject_action = project_menu->addAction(""); - QObject::connect(project_create_subproject_action, SIGNAL(triggered()), this, SLOT(on_menu_project_create_subproject())); + QObject::connect(project_create_subproject_action, + SIGNAL(triggered()), + this, + SLOT(on_menu_project_create_subproject())); project_menu->addSeparator(); project_settings_action = project_menu->addAction(""); @@ -125,7 +140,10 @@ namespace degate show_annotations_name_view_action = view_menu->addAction(""); show_annotations_name_view_action->setCheckable(true); show_annotations_name_view_action->setChecked(true); - QObject::connect(show_annotations_name_view_action, SIGNAL(toggled(bool)), workspace, SLOT(show_annotations_name(bool))); + QObject::connect(show_annotations_name_view_action, + SIGNAL(toggled(bool)), + workspace, + SLOT(show_annotations_name(bool))); show_emarkers_view_action = view_menu->addAction(""); show_emarkers_view_action->setCheckable(true); @@ -135,7 +153,10 @@ namespace degate show_emarkers_name_view_action = view_menu->addAction(""); show_emarkers_name_view_action->setCheckable(true); show_emarkers_name_view_action->setChecked(true); - QObject::connect(show_emarkers_name_view_action, SIGNAL(toggled(bool)), workspace, SLOT(show_emarkers_name(bool))); + QObject::connect(show_emarkers_name_view_action, + SIGNAL(toggled(bool)), + workspace, + SLOT(show_emarkers_name(bool))); show_vias_view_action = view_menu->addAction(""); show_vias_view_action->setCheckable(true); @@ -211,14 +232,12 @@ namespace degate gate_menu->addSeparator(); auto_name_gates_rows_action = gate_menu->addAction(""); - QObject::connect(auto_name_gates_rows_action, &QAction::triggered, this, [this]() - { + QObject::connect(auto_name_gates_rows_action, &QAction::triggered, this, [this]() { on_menu_gate_automatic_naming(AutoNameGates::ORIENTATION::ALONG_ROWS); }); auto_name_gates_columns_action = gate_menu->addAction(""); - QObject::connect(auto_name_gates_columns_action, &QAction::triggered, this, [this]() - { + QObject::connect(auto_name_gates_columns_action, &QAction::triggered, this, [this]() { on_menu_gate_automatic_naming(AutoNameGates::ORIENTATION::ALONG_COLS); }); @@ -255,29 +274,46 @@ namespace degate remove_objects_action = logic_menu->addAction(""); remove_objects_action->setShortcut(Qt::Key_Delete); - QObject::connect(remove_objects_action, SIGNAL(triggered()), this, SLOT(on_menu_logic_remove_selected_objects())); + QObject::connect(remove_objects_action, + SIGNAL(triggered()), + this, + SLOT(on_menu_logic_remove_selected_objects())); interconnect_objects_action = logic_menu->addAction(""); - interconnect_objects_action->setShortcut(Qt::CTRL + Qt::Key_C); - QObject::connect(interconnect_objects_action, SIGNAL(triggered()), this, SLOT(on_menu_logic_interconnect_selected_objects())); + interconnect_objects_action->setShortcut(Qt::CTRL | Qt::Key_C); + QObject::connect(interconnect_objects_action, + SIGNAL(triggered()), + this, + SLOT(on_menu_logic_interconnect_selected_objects())); isolate_objects_action = logic_menu->addAction(""); - isolate_objects_action->setShortcut(Qt::CTRL + Qt::Key_X); - QObject::connect(isolate_objects_action, SIGNAL(triggered()), this, SLOT(on_menu_logic_isolate_selected_objects())); + isolate_objects_action->setShortcut(Qt::CTRL | Qt::Key_X); + QObject::connect(isolate_objects_action, + SIGNAL(triggered()), + this, + SLOT(on_menu_logic_isolate_selected_objects())); move_selected_gates_into_module = logic_menu->addAction(""); - QObject::connect(move_selected_gates_into_module, SIGNAL(triggered()), this, SLOT(on_menu_logic_move_selected_gates_into_module())); + QObject::connect(move_selected_gates_into_module, + SIGNAL(triggered()), + this, + SLOT(on_menu_logic_move_selected_gates_into_module())); inspect_selected_object_action = logic_menu->addAction(""); - QObject::connect(inspect_selected_object_action, SIGNAL(triggered()), this, SLOT( - on_menu_logic_inspect_selected_object())); + QObject::connect(inspect_selected_object_action, + SIGNAL(triggered()), + this, + SLOT(on_menu_logic_inspect_selected_object())); // Matching menu matching_menu = menu_bar.addMenu(""); template_matching_action = matching_menu->addAction(""); - QObject::connect(template_matching_action, SIGNAL(triggered()), this, SLOT(on_menu_matching_template_matching())); + QObject::connect(template_matching_action, + SIGNAL(triggered()), + this, + SLOT(on_menu_matching_template_matching())); via_matching_action = matching_menu->addAction(""); QObject::connect(via_matching_action, SIGNAL(triggered()), this, SLOT(on_menu_matching_via_matching())); @@ -298,8 +334,7 @@ namespace degate help_menu->addSeparator(); check_updates_action = help_menu->addAction(""); - QObject::connect(check_updates_action, &QAction::triggered, this, [this]() - { + QObject::connect(check_updates_action, &QAction::triggered, this, [this]() { on_menu_help_check_updates(true, false); }); @@ -328,7 +363,8 @@ namespace degate // Status bar - status_bar.setStyleSheet("QStatusBar::item { border: none; } QStatusBar QLabel { border: 3px solid black; border-radius: 0px; padding: 2px; }"); + status_bar.setStyleSheet("QStatusBar::item { border: none; } QStatusBar QLabel { border: 3px solid black; " + "border-radius: 0px; padding: 2px; }"); setStatusBar(&status_bar); status_bar.showMessage(tr("Initialization..."), SECOND(DEFAULT_STATUS_MESSAGE_DURATION)); @@ -337,7 +373,10 @@ namespace degate status_bar.addPermanentWidget(&status_bar_coords); change_status_bar_coords(0, 0); - QObject::connect(workspace, SIGNAL(mouse_coords_changed(int, int)), this, SLOT(change_status_bar_coords(int, int))); + QObject::connect(workspace, + SIGNAL(mouse_coords_changed(int, int)), + this, + SLOT(change_status_bar_coords(int, int))); update_status_bar_layer_info(); @@ -409,17 +448,19 @@ namespace degate QThreadPool::globalInstance()->setMaxThreadCount(Configuration::get_max_concurrent_thread_count()); - // Workaround for a bug on Windows that occurs when using QOpenGLWidget + fullscreen mode. - // See: https://doc.qt.io/qt-6/windows-issues.html#fullscreen-opengl-based-windows. - #ifdef SYS_WINDOWS - HWND handle = reinterpret_cast(window()->winId()); - SetWindowLongPtr(handle, GWL_STYLE, GetWindowLongPtr(handle, GWL_STYLE) | WS_BORDER); - #endif +// Workaround for a bug on Windows that occurs when using QOpenGLWidget + fullscreen mode. +// See: https://doc.qt.io/qt-6/windows-issues.html#fullscreen-opengl-based-windows. +#ifdef SYS_WINDOWS + HWND handle = reinterpret_cast(window()->winId()); + SetWindowLongPtr(handle, GWL_STYLE, GetWindowLongPtr(handle, GWL_STYLE) | WS_BORDER); +#endif // Check for updates. if (PREFERENCES_HANDLER.get_preferences().automatic_updates_check) { - QTimer::singleShot(0, [this](){ on_menu_help_check_updates(false, true); }); + QTimer::singleShot(0, [this]() { + on_menu_help_check_updates(false, true); + }); } reload_recent_projects_list(); @@ -695,7 +736,7 @@ namespace degate { res = dialog.exec(); } - catch(const std::exception& e) + catch (const std::exception& e) { std::cerr << e.what() << '\n'; } @@ -704,7 +745,8 @@ namespace degate { project = dialog.get_project(); - project->get_logic_model()->set_current_layer(get_prev_enabled_layer(project->get_logic_model())->get_layer_pos()); + project->get_logic_model()->set_current_layer( + get_prev_enabled_layer(project->get_logic_model())->get_layer_pos()); workspace->set_project(project); @@ -713,9 +755,8 @@ namespace degate status_bar.showMessage(tr("Created a new project."), SECOND(DEFAULT_STATUS_MESSAGE_DURATION)); } else - { - status_bar.showMessage(tr("New project creation operation cancelled."), SECOND(DEFAULT_STATUS_MESSAGE_DURATION)); - } + status_bar.showMessage(tr("New project creation operation cancelled."), + SECOND(DEFAULT_STATUS_MESSAGE_DURATION)); } void MainWindow::on_menu_project_create_subproject() @@ -726,7 +767,8 @@ namespace degate boost::format f("subproject_%1%"); f % project->get_logic_model()->get_new_object_id(); - SubProjectAnnotation_shptr new_annotation(new SubProjectAnnotation(workspace->get_safe_area_selection(), f.str())); + SubProjectAnnotation_shptr new_annotation( + new SubProjectAnnotation(workspace->get_safe_area_selection(), f.str())); new_annotation->set_fill_color(project->get_default_color(DEFAULT_COLOR_ANNOTATION)); new_annotation->set_frame_color(project->get_default_color(DEFAULT_COLOR_ANNOTATION_FRAME)); @@ -735,7 +777,8 @@ namespace degate if (res == QDialog::Accepted) { - project->get_logic_model()->add_object(project->get_logic_model()->get_current_layer()->get_layer_pos(), new_annotation); + project->get_logic_model()->add_object(project->get_logic_model()->get_current_layer()->get_layer_pos(), + new_annotation); workspace->reset_area_selection(); workspace->update_screen(); @@ -796,7 +839,8 @@ namespace degate { if (project == nullptr) { - status_bar.showMessage(tr("Failed to import new background image : no project opened."), SECOND(DEFAULT_STATUS_MESSAGE_DURATION)); + status_bar.showMessage(tr("Failed to import new background image : no project opened."), + SECOND(DEFAULT_STATUS_MESSAGE_DURATION)); return; } @@ -807,7 +851,8 @@ namespace degate if (res.isNull()) { - status_bar.showMessage(tr("New background image import cancelled."), SECOND(DEFAULT_STATUS_MESSAGE_DURATION)); + status_bar.showMessage(tr("New background image import cancelled."), + SECOND(DEFAULT_STATUS_MESSAGE_DURATION)); return; } @@ -818,10 +863,11 @@ namespace degate nullptr); // Set the job to start the background loading. - progress_dialog.set_job([file_name, this]() - { - load_new_background_image(project->get_logic_model()->get_current_layer(), project->get_project_directory(), file_name); - }); + progress_dialog.set_job([file_name, this]() { + load_new_background_image(project->get_logic_model()->get_current_layer(), + project->get_project_directory(), + file_name); + }); // Start the process progress_dialog.exec(); @@ -836,7 +882,8 @@ namespace degate { workspace->update_background(); - status_bar.showMessage(tr("Imported a new background image for the layer."), SECOND(DEFAULT_STATUS_MESSAGE_DURATION)); + status_bar.showMessage(tr("Imported a new background image for the layer."), + SECOND(DEFAULT_STATUS_MESSAGE_DURATION)); project_changed(); } @@ -857,13 +904,9 @@ namespace degate return; } - auto new_gate_template = std::make_shared(workspace->get_safe_area_selection() - .get_width(), - workspace->get_safe_area_selection() - .get_height()); - grab_template_images(project->get_logic_model(), - new_gate_template, - workspace->get_safe_area_selection()); + auto new_gate_template = std::make_shared(workspace->get_safe_area_selection().get_width(), + workspace->get_safe_area_selection().get_height()); + grab_template_images(project->get_logic_model(), new_gate_template, workspace->get_safe_area_selection()); new_gate_template->set_object_id(project->get_logic_model()->get_new_object_id()); new_gate_template->set_fill_color(project->get_default_color(DEFAULT_COLOR_GATE)); new_gate_template->set_frame_color(project->get_default_color(DEFAULT_COLOR_GATE_FRAME)); @@ -881,7 +924,8 @@ namespace degate if (res == QDialog::Accepted) { - project->get_logic_model()->add_object(project->get_logic_model()->get_current_layer()->get_layer_pos(), new_gate); + project->get_logic_model()->add_object(project->get_logic_model()->get_current_layer()->get_layer_pos(), + new_gate); project->get_logic_model()->update_ports(new_gate); workspace->reset_area_selection(); @@ -1047,7 +1091,8 @@ namespace degate if (res == QDialog::Accepted) { - project->get_logic_model()->add_object(project->get_logic_model()->get_current_layer()->get_layer_pos(), new_annotation); + project->get_logic_model()->add_object(project->get_logic_model()->get_current_layer()->get_layer_pos(), + new_annotation); workspace->reset_area_selection(); workspace->update_annotations(); @@ -1158,7 +1203,9 @@ namespace degate if (!objects.check_for_all(&is_interconnectable)) { - QMessageBox::warning(this, tr("Error during interconnect"), tr("One of the objects you selected cannot have connections at all.")); + QMessageBox::warning(this, + tr("Error during interconnect"), + tr("One of the objects you selected cannot have connections at all.")); return; } @@ -1178,7 +1225,9 @@ namespace degate if (!objects.check_for_all(&is_interconnectable)) { - QMessageBox::warning(this, tr("Error during interconnect"), tr("One of the objects you selected cannot have connections at all.")); + QMessageBox::warning(this, + tr("Error during interconnect"), + tr("One of the objects you selected cannot have connections at all.")); return; } @@ -1324,13 +1373,12 @@ namespace degate void MainWindow::on_menu_help_open_help() { - static auto add_shortcut = [](const QString& shortcut, const QString& text){ + static auto add_shortcut = [](const QString& shortcut, const QString& text) { return "" + shortcut + "" + text + ""; }; const QString help_message = - "
" + - tr("Shortcuts:") + "
" + + "
" + tr("Shortcuts:") + "
" + add_shortcut(tr("LEFT click:"), tr("Object selection")) + add_shortcut(tr("RIGHT click:"), tr("Context menu")) + @@ -1342,14 +1390,7 @@ namespace degate "
"; - QMessageBox help(tr("Degate help"), - help_message, - QMessageBox::Icon::NoIcon, - QMessageBox::Button::Ok, - QMessageBox::Button::NoButton, - QMessageBox::Button::NoButton, - this - ); + QMessageBox help(QMessageBox::NoIcon, tr("Degate help"), help_message, QMessageBox::StandardButton::Ok, this); auto* about_layout = help.findChild(); QMargins about_margins = about_layout->contentsMargins(); @@ -1427,21 +1468,19 @@ namespace degate void MainWindow::update_status_bar_layer_info() { - std::map types = { - {Layer::UNDEFINED, tr("Undefined")}, - {Layer::TRANSISTOR, tr("Transistor")}, - {Layer::LOGIC, tr("Logic")}, - {Layer::METAL, tr("Metal")} - }; + std::map types = {{Layer::UNDEFINED, tr("Undefined")}, + {Layer::TRANSISTOR, tr("Transistor")}, + {Layer::LOGIC, tr("Logic")}, + {Layer::METAL, tr("Metal")}}; if (project != nullptr) { QString status_bar_message = tr("Layer: %1/%2 (%3)"); - status_bar_layer.setText(status_bar_message - .arg(project->get_logic_model()->get_current_layer()->get_layer_pos() + 1) - .arg(project->get_logic_model()->get_num_layers()) - .arg(types[project->get_logic_model()->get_current_layer()->get_layer_type()])); + status_bar_layer.setText( + status_bar_message.arg(project->get_logic_model()->get_current_layer()->get_layer_pos() + 1) + .arg(project->get_logic_model()->get_num_layers()) + .arg(types[project->get_logic_model()->get_current_layer()->get_layer_type()])); } else { @@ -1454,7 +1493,8 @@ namespace degate if (project == nullptr) return; - project->get_logic_model()->set_current_layer(get_next_enabled_layer(project->get_logic_model())->get_layer_pos()); + project->get_logic_model()->set_current_layer( + get_next_enabled_layer(project->get_logic_model())->get_layer_pos()); update_status_bar_layer_info(); @@ -1466,7 +1506,8 @@ namespace degate if (project == nullptr) return; - project->get_logic_model()->set_current_layer(get_prev_enabled_layer(project->get_logic_model())->get_layer_pos()); + project->get_logic_model()->set_current_layer( + get_prev_enabled_layer(project->get_logic_model())->get_layer_pos()); update_status_bar_layer_info(); @@ -1489,10 +1530,8 @@ namespace degate try { std::shared_ptr imported_project = nullptr; - // First try, in worker thread - progress_dialog.set_job([&] - { + progress_dialog.set_job([&] { try { imported_project = project_importer.import_all(path); @@ -1524,7 +1563,8 @@ namespace degate if (imported_project == nullptr) { QMessageBox::StandardButton reply; - reply = QMessageBox::question(this, tr("Subproject"), + reply = QMessageBox::question(this, + tr("Subproject"), tr("The project/subproject do not exist, do you want to create it?"), QMessageBox::Yes | QMessageBox::No); @@ -1564,8 +1604,8 @@ namespace degate { QMessageBox::warning(this, tr("Project/Subproject import failed"), - tr("The project/subproject cannot be imported (maybe corrupted).") + "\n\n" - + tr("Error") + ": " + QString::fromStdString(error_message)); + tr("The project/subproject cannot be imported (maybe corrupted).") + "\n\n" + + tr("Error") + ": " + QString::fromStdString(error_message)); status_bar.showMessage(tr("Project/Subproject import failed."), SECOND(DEFAULT_STATUS_MESSAGE_DURATION)); return; @@ -1641,7 +1681,10 @@ namespace degate connect(&annotation_create_context_action, SIGNAL(triggered()), this, SLOT(on_menu_annotation_create())); context_menu.addAction(&annotation_create_context_action); - connect(&gate_template_create_context_action, SIGNAL(triggered()), this, SLOT(on_menu_gate_new_gate_template())); + connect(&gate_template_create_context_action, + SIGNAL(triggered()), + this, + SLOT(on_menu_gate_new_gate_template())); context_menu.addAction(&gate_template_create_context_action); connect(&gate_create_context_action, SIGNAL(triggered()), this, SLOT(on_menu_gate_new_gate())); @@ -1666,7 +1709,10 @@ namespace degate connect(&gate_edit_context_action, SIGNAL(triggered()), this, SLOT(on_menu_gate_edit())); context_menu.addAction(&gate_edit_context_action); - connect(&move_selected_gates_into_module_context_action, SIGNAL(triggered()), this, SLOT(on_menu_logic_move_selected_gates_into_module())); + connect(&move_selected_gates_into_module_context_action, + SIGNAL(triggered()), + this, + SLOT(on_menu_logic_move_selected_gates_into_module())); context_menu.addAction(&move_selected_gates_into_module_context_action); } else if (is_of_object_type(object)) @@ -1701,18 +1747,27 @@ namespace degate if (workspace->get_selected_objects().check_for_all(&is_interconnectable)) { - connect(&inspect_selected_object_context_action, SIGNAL(triggered()), this, SLOT(on_menu_logic_inspect_selected_object())); + connect(&inspect_selected_object_context_action, + SIGNAL(triggered()), + this, + SLOT(on_menu_logic_inspect_selected_object())); context_menu.addAction(&inspect_selected_object_context_action); context_menu.addSeparator(); if (workspace->get_selected_objects().size() >= 2) { - connect(&interconnect_selected_objects_context_action, SIGNAL(triggered()), this, SLOT(on_menu_logic_interconnect_selected_objects())); + connect(&interconnect_selected_objects_context_action, + SIGNAL(triggered()), + this, + SLOT(on_menu_logic_interconnect_selected_objects())); context_menu.addAction(&interconnect_selected_objects_context_action); } - connect(&isolate_selected_objects_context_action, SIGNAL(triggered()), this, SLOT(on_menu_logic_isolate_selected_objects())); + connect(&isolate_selected_objects_context_action, + SIGNAL(triggered()), + this, + SLOT(on_menu_logic_isolate_selected_objects())); context_menu.addAction(&isolate_selected_objects_context_action); } } @@ -1741,7 +1796,8 @@ namespace degate if (project == nullptr) return; - EMarker_shptr new_emarker = std::make_shared(context_menu_mouse_position.x(), context_menu_mouse_position.y()); + EMarker_shptr new_emarker = + std::make_shared(context_menu_mouse_position.x(), context_menu_mouse_position.y()); new_emarker->set_fill_color(project->get_default_color(DEFAULT_COLOR_EMARKER)); EMarkerEditDialog dialog(this, new_emarker); @@ -1749,7 +1805,8 @@ namespace degate if (res == QDialog::Accepted) { - project->get_logic_model()->add_object(project->get_logic_model()->get_current_layer()->get_layer_pos(), new_emarker); + project->get_logic_model()->add_object(project->get_logic_model()->get_current_layer()->get_layer_pos(), + new_emarker); workspace->update_emarkers(); @@ -1764,7 +1821,9 @@ namespace degate if (project == nullptr) return; - Via_shptr new_via = std::make_shared(context_menu_mouse_position.x(), context_menu_mouse_position.y(), Via::DIRECTION_UNDEFINED); + Via_shptr new_via = std::make_shared(context_menu_mouse_position.x(), + context_menu_mouse_position.y(), + Via::DIRECTION_UNDEFINED); new_via->set_diameter(project->get_default_via_diameter()); ViaEditDialog dialog(this, new_via, project); @@ -1975,12 +2034,12 @@ namespace degate for (auto it = list.rbegin(); it != list.rend(); it++) { auto element = *it; - auto* action = project_recent_projects_submenu->addAction(QString::fromStdString(element.first + " (" + element.second + ")")); + auto* action = project_recent_projects_submenu->addAction( + QString::fromStdString(element.first + " (" + element.second + ")")); - QObject::connect(action, &QAction::triggered, this, [=]() - { - open_project(element.second); + QObject::connect(action, &QAction::triggered, this, [=]() { + open_project(element.second); }); } } -} +} // namespace degate