From 9089fa6b1f7e55a1229ce912f86adbedc06106aa Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Sat, 16 Dec 2023 16:06:03 +0200 Subject: [PATCH] - when tabs are set as not detachable, double_clicking the Plot_Area tab will toggle the notebook area visibility - fixed the Full Screen issue with not remembering the toolbar's state before full screen event --- CHANGELOG.md | 5 ++ appGUI/GUIElements.py | 19 ++++- appGUI/MainGUI.py | 170 ++++++++++++++++++++++++++---------------- appMain.py | 14 +++- defaults.py | 14 ++-- 5 files changed, 143 insertions(+), 79 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f3ecaec..7217e868 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ CHANGELOG for FlatCAM Evo beta ================================================= +16.12.2023 + +- when tabs are set as not detachable, double_clicking the Plot_Area tab will toggle the notebook area visibility +- fixed the Full Screen issue with not remembering the toolbar's state before full screen event + 6.12.2023 - Paint Tool: fixed the calculation of object bounds diff --git a/appGUI/GUIElements.py b/appGUI/GUIElements.py index cd5e7358..5db4bf51 100644 --- a/appGUI/GUIElements.py +++ b/appGUI/GUIElements.py @@ -3489,10 +3489,10 @@ class FCDetachableTab(QtWidgets.QTabWidget): if val is True: self.tabBar.onDetachTabSignal.connect(self.detachTab) # the tab can be moved around - self.tabBar.can_be_dragged = True + self.tabBar.detachable = True else: # the detached tab can't be moved - self.tabBar.can_be_dragged = False + self.tabBar.detachable = False return val @@ -3918,7 +3918,10 @@ class FCDetachableTab(QtWidgets.QTabWidget): """ event.accept() - self.onDetachTabSignal.emit(self.tabAt(event.position().toPoint()), self.mouseCursor.pos()) + if self.detachable: + self.onDetachTabSignal.emit(self.tabAt(event.position().toPoint()), self.mouseCursor.pos()) + else: + super().mouseDoubleClickEvent(event) def mousePressEvent(self, event): """ @@ -3974,7 +3977,7 @@ class FCDetachableTab(QtWidgets.QTabWidget): self.dragInitiated = True # If the current movement is a drag initiated by the left button - if (event.buttons() & QtCore.Qt.MouseButton.LeftButton) and self.dragInitiated and self.can_be_dragged: + if (event.buttons() & QtCore.Qt.MouseButton.LeftButton) and self.dragInitiated and self.detachable: # Stop the move event finishMoveEvent = QtGui.QMouseEvent( QtCore.QEvent.Type.MouseMove, event.position(), QtCore.Qt.MouseButton.NoButton, @@ -4065,6 +4068,14 @@ class FCDetachableTab(QtWidgets.QTabWidget): self.detachedTabDropSignal.emit(name, index, dropPos) + @property + def detachable(self) -> bool: + return self.can_be_dragged + + @detachable.setter + def detachable(self, val: bool): + self.can_be_dragged = val + class FCDetachableTab2(FCDetachableTab): tab_closed_signal = QtCore.pyqtSignal(object, int) diff --git a/appGUI/MainGUI.py b/appGUI/MainGUI.py index 0ea7adb8..ceb0070f 100644 --- a/appGUI/MainGUI.py +++ b/appGUI/MainGUI.py @@ -102,6 +102,10 @@ class MainGUI(QtWidgets.QMainWindow): # Divine icon pack by Ipapun @ finicons.com + # Store the hidden toolbars here for fullScreen action + self.hidden_toolbars = [] + self.original_window_flags = self.windowFlags() + # ####################################################################### # ############ BUILDING THE GUI IS EXECUTED HERE ######################## # ####################################################################### @@ -1964,14 +1968,14 @@ class MainGUI(QtWidgets.QMainWindow): self.infobar.addWidget(self.fcinfo, stretch=1) self.infobar.addWidget(self.delta_coords_toolbar) - self.delta_coords_toolbar.setVisible(self.app.defaults["global_delta_coordsbar_show"]) + self.delta_coords_toolbar.setVisible(self.app.defaults["global_delta_coords_bar_show"]) self.infobar.addWidget(self.coords_toolbar) - self.coords_toolbar.setVisible(self.app.defaults["global_coordsbar_show"]) + self.coords_toolbar.setVisible(self.app.defaults["global_coords_bar_show"]) self.grid_toolbar.setMaximumHeight(24) self.infobar.addWidget(self.grid_toolbar) - self.grid_toolbar.setVisible(self.app.defaults["global_gridbar_show"]) + self.grid_toolbar.setVisible(self.app.defaults["global_grid_bar_show"]) self.status_toolbar.setMaximumHeight(24) self.infobar.addWidget(self.status_toolbar) @@ -2124,7 +2128,7 @@ class MainGUI(QtWidgets.QMainWindow): # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # Variable to store the status of the fullscreen event - self.toggle_fscreen = False + self.toggle_f_screen = False self.x_pos = None self.y_pos = None self.width = None @@ -2275,7 +2279,7 @@ class MainGUI(QtWidgets.QMainWindow): delta_coords_action = QtGui.QAction(self) delta_coords_action.setCheckable(True) delta_coords_action.setText(delta_coords_action_name) - delta_coords_action.setChecked(self.app.defaults["global_delta_coordsbar_show"]) + delta_coords_action.setChecked(self.app.defaults["global_delta_coords_bar_show"]) self.infobar.addAction(delta_coords_action) delta_coords_action.triggered.connect(self.toggle_delta_coords) @@ -2283,7 +2287,7 @@ class MainGUI(QtWidgets.QMainWindow): coords_action = QtGui.QAction(self) coords_action.setCheckable(True) coords_action.setText(coords_action_name) - coords_action.setChecked(self.app.defaults["global_coordsbar_show"]) + coords_action.setChecked(self.app.defaults["global_coords_bar_show"]) self.infobar.addAction(coords_action) coords_action.triggered.connect(self.toggle_coords) @@ -2291,7 +2295,7 @@ class MainGUI(QtWidgets.QMainWindow): grid_action = QtGui.QAction(self) grid_action.setCheckable(True) grid_action.setText(grid_action_name) - grid_action.setChecked(self.app.defaults["global_gridbar_show"]) + grid_action.setChecked(self.app.defaults["global_grid_bar_show"]) self.infobar.addAction(grid_action) grid_action.triggered.connect(self.toggle_gridbar) @@ -2304,15 +2308,15 @@ class MainGUI(QtWidgets.QMainWindow): status_action.triggered.connect(self.toggle_statusbar) def toggle_coords(self, checked): - self.app.options["global_coordsbar_show"] = checked + self.app.options["global_coords_bar_show"] = checked self.coords_toolbar.setVisible(checked) def toggle_delta_coords(self, checked): - self.app.options["global_delta_coordsbar_show"] = checked + self.app.options["global_delta_coords_bar_show"] = checked self.delta_coords_toolbar.setVisible(checked) def toggle_gridbar(self, checked): - self.app.options["global_gridbar_show"] = checked + self.app.options["global_grid_bar_show"] = checked self.grid_toolbar.setVisible(checked) def toggle_statusbar(self, checked): @@ -2771,65 +2775,101 @@ class MainGUI(QtWidgets.QMainWindow): # This will write the setting to the platform specific storage. del qsettings - def on_fullscreen(self, disable=False): + # def on_full_screen_toggled(self, disable=False): + # """ + # Toggles the full screen mode of the window. + # + # :param disable: Whether to disable full screen mode. Defaults to False. + # """ + # flags = self.windowFlags() + # if self.toggle_f_screen is False and disable is False: + # # self.ui.showFullScreen() + # self.setWindowFlags(flags | Qt.WindowType.FramelessWindowHint) + # a = self.geometry() + # self.x_pos = a.x() + # self.y_pos = a.y() + # self.width = a.width() + # self.height = a.height() + # self.titlebar_height = self.app.qapp.style().pixelMetric(QtWidgets.QStyle.PixelMetric.PM_TitleBarHeight) + # + # self.app.ui.showFullScreen() + # + # # hide all Toolbars + # for tb in self.findChildren(QtWidgets.QToolBar): + # if isinstance(tb, QtWidgets.QToolBar): + # tb.setVisible(False) + # + # self.coords_toolbar.setVisible(self.app.defaults["global_coords_bar_show"]) + # self.delta_coords_toolbar.setVisible(self.app.defaults["global_delta_coords_bar_show"]) + # self.grid_toolbar.setVisible(self.app.defaults["global_grid_bar_show"]) + # self.status_toolbar.setVisible(self.app.defaults["global_statusbar_show"]) + # + # self.splitter.setSizes([0, 1]) + # self.toggle_f_screen = True + # elif self.toggle_f_screen is True or disable is True: + # self.setWindowFlags(flags & ~Qt.WindowType.FramelessWindowHint) + # # the additions are made to account for the pixels we subtracted/added above in the (x, y, h, w) + # # self.setGeometry(self.x_pos+1, self.y_pos+self.titlebar_height+4, self.width, self.height) + # self.setGeometry(self.x_pos+1, self.y_pos+self.titlebar_height+13, self.width, self.height) + # + # self.showNormal() + # self.toggle_f_screen = False + + def on_full_screen_toggled(self, disable=False): + """ + Toggles the full screen mode of the window. + + :param disable: Whether to disable full screen mode. Defaults to False. """ - :param disable: - :return: - """ - flags = self.windowFlags() - if self.toggle_fscreen is False and disable is False: - # self.ui.showFullScreen() - self.setWindowFlags(flags | Qt.WindowType.FramelessWindowHint) - a = self.geometry() - self.x_pos = a.x() - self.y_pos = a.y() - self.width = a.width() - self.height = a.height() - self.titlebar_height = self.app.qapp.style().pixelMetric(QtWidgets.QStyle.PixelMetric.PM_TitleBarHeight) + if self.isFullScreen() or disable: + self.setWindowFlags(self.original_window_flags) - # set new geometry to full desktop rect - # Subtracting and adding the pixels below it's hack to bypass a bug in Qt5 and OpenGL that made that a - # window drawn with OpenGL in fullscreen will not show any other windows on top which means that menus and - # everything else will not work without this hack. This happen in Windows. - # https://bugreports.qt.io/browse/QTBUG-41309 - # desktop = self.app.qapp.desktop() - # screen = desktop.screenNumber(QtGui.QCursor.pos()) + # Restore visibility of all toolbars + for toolbar in self.hidden_toolbars: + toolbar.setVisible(True) + # Clear the list + self.hidden_toolbars = [] - # rec = desktop.screenGeometry(screen) - - # x = rec.x() - 1 - # y = rec.y() - 1 - # h = rec.height() + 2 - # w = rec.width() + 2 - # - # self.setGeometry(x, y, w, h) - # self.show() - - self.app.ui.showFullScreen() - - # hide all Toolbars - for tb in self.findChildren(QtWidgets.QToolBar): - if isinstance(tb, QtWidgets.QToolBar): - tb.setVisible(False) - - self.coords_toolbar.setVisible(self.app.defaults["global_coordsbar_show"]) - self.delta_coords_toolbar.setVisible(self.app.defaults["global_delta_coordsbar_show"]) - self.grid_toolbar.setVisible(self.app.defaults["global_gridbar_show"]) - self.status_toolbar.setVisible(self.app.defaults["global_statusbar_show"]) - - self.splitter.setSizes([0, 1]) - self.toggle_fscreen = True - elif self.toggle_fscreen is True or disable is True: - self.setWindowFlags(flags & ~Qt.WindowType.FramelessWindowHint) - # the additions are made to account for the pixels we subtracted/added above in the (x, y, h, w) - # self.setGeometry(self.x_pos+1, self.y_pos+self.titlebar_height+4, self.width, self.height) - self.setGeometry(self.x_pos+1, self.y_pos+self.titlebar_height+13, self.width, self.height) + # the additions are made to correct the restoration of the geometry of the window + self.setGeometry( + self.x_pos, + self.y_pos + self.titlebar_height, + self.width, + self.height + ) + # exit FullScreen mode self.showNormal() - self.restore_toolbar_view() - self.toggle_fscreen = False + return + + # Save and hide all visible toolbars + self.hidden_toolbars = [] + for toolbar in self.findChildren(QtWidgets.QToolBar): + if toolbar.isVisible(): + self.hidden_toolbars.append(toolbar) + toolbar.setVisible(False) + + self.original_window_flags = self.windowFlags() + self.setWindowFlags(self.windowFlags() | Qt.WindowType.FramelessWindowHint) # noqa + + # save the current geometry + current_geometry = self.geometry() + self.x_pos = current_geometry.x() + self.y_pos = current_geometry.y() + self.width = current_geometry.width() + self.height = current_geometry.height() + self.titlebar_height = self.app.qapp.style().pixelMetric(QtWidgets.QStyle.PixelMetric.PM_TitleBarHeight) + + # activate FullScreen + self.app.ui.showFullScreen() + + self.coords_toolbar.setVisible(self.app.defaults["global_coords_bar_show"]) + self.delta_coords_toolbar.setVisible(self.app.defaults["global_delta_coords_bar_show"]) + self.grid_toolbar.setVisible(self.app.defaults["global_grid_bar_show"]) + self.status_toolbar.setVisible(self.app.defaults["global_statusbar_show"]) + def on_toggle_plotarea(self): """ @@ -3217,7 +3257,7 @@ class MainGUI(QtWidgets.QMainWindow): # Toggle Fullscreen if key == QtCore.Qt.Key.Key_F10 or key == 'F10': - self.on_fullscreen() + self.on_full_screen_toggled() return # NO MODIFIER elif modifiers == QtCore.Qt.KeyboardModifier.NoModifier: @@ -3278,8 +3318,8 @@ class MainGUI(QtWidgets.QMainWindow): self.app.on_deselect_all() # if in full screen, exit to normal view - if self.toggle_fscreen is True: - self.on_fullscreen(disable=True) + if self.toggle_f_screen is True: + self.on_full_screen_toggled(disable=True) # try to disconnect the slot from Set Origin try: diff --git a/appMain.py b/appMain.py index 9f3adcfd..c485f774 100644 --- a/appMain.py +++ b/appMain.py @@ -1241,6 +1241,9 @@ class App(QtCore.QObject): # self.ui.notebook.callback_on_close = self.on_close_notebook_tab + # Plot Area double clicking + self.ui.plot_tab_area.tabBarDoubleClicked.connect(self.on_plot_area_tab_double_clicked) + # ########################################################################################################### # #################################### GUI PREFERENCES SIGNALS ############################################## # ########################################################################################################### @@ -1957,7 +1960,7 @@ class App(QtCore.QObject): self.ui.menuview_replot.triggered.connect(self.plot_all) self.ui.menuview_toggle_code_editor.triggered.connect(self.on_toggle_code_editor) - self.ui.menuview_toggle_fscreen.triggered.connect(self.ui.on_fullscreen) + self.ui.menuview_toggle_fscreen.triggered.connect(self.ui.on_full_screen_toggled) self.ui.menuview_toggle_parea.triggered.connect(self.ui.on_toggle_plotarea) self.ui.menuview_toggle_notebook.triggered.connect(self.ui.on_toggle_notebook) self.ui.menu_toggle_nb.triggered.connect(self.ui.on_toggle_notebook) @@ -6035,8 +6038,13 @@ class App(QtCore.QObject): pass # restore the coords toolbars - self.ui.toggle_coords(checked=self.options["global_coordsbar_show"]) - self.ui.toggle_delta_coords(checked=self.options["global_delta_coordsbar_show"]) + self.ui.toggle_coords(checked=self.options["global_coords_bar_show"]) + self.ui.toggle_delta_coords(checked=self.options["global_delta_coords_bar_show"]) + + def on_plot_area_tab_double_clicked(self, index: int): + # tab_obj_name = self.ui.plot_tab_area.widget(index).objectName() + # print(tab_obj_name) + self.ui.on_toggle_notebook() def on_notebook_closed(self): diff --git a/defaults.py b/defaults.py index d0846d33..aa6ac3db 100644 --- a/defaults.py +++ b/defaults.py @@ -32,8 +32,8 @@ class AppDefaults: "global_stats": dict(), "global_tabs_detachable": False, - "global_coordsbar_show": True, - "global_delta_coordsbar_show": False, + "global_coords_bar_show": True, + "global_delta_coords_bar_show": False, "global_statusbar_show": True, "global_jump_ref": 'abs', @@ -130,7 +130,7 @@ class AppDefaults: "global_project_autohide": True, # General App Settings - "global_gridbar_show": True, + "global_grid_bar_show": True, "global_gridx": 1.0, "global_gridy": 1.0, "global_snap_max": 0.05, @@ -894,7 +894,7 @@ class AppDefaults: """ Class that holds the default parameters used throughout the app. - :param callback: A method called each time that one of the values are changed in the self.defaults LouDict + :param callback: A method called each time that one of the values are changed in the "self.defaults" LouDict """ self.defaults = LoudDict() @@ -988,7 +988,7 @@ class AppDefaults: # log.debug("App defaults loaded from: %s" % filename) def __is_old_defaults(self, defaults: dict) -> bool: - """Takes a defaults dict and determines whether or not migration is necessary.""" + """Takes a defaults dict and determines whether migration is necessary.""" return 'version' not in defaults or defaults['version'] != self.factory_defaults['version'] def __migrate_old_defaults(self, defaults: dict) -> dict: @@ -996,7 +996,7 @@ class AppDefaults: migrated = {} for k, v in defaults.items(): if k in self.factory_defaults and k != 'version': - # check if the types are the same. Because some types (tuple, float, int etc) + # check if the types are the same. Because some types (tuple, float, int etc.) # may be stored as strings we check their types. try: target = eval(self.defaults[k]) @@ -1057,7 +1057,7 @@ class AppDefaults: def report_usage(self, resource): """ Increments usage counter for the given resource - in self.defaults['global_stats']. + in "self.defaults['global_stats']". :param resource: Name of the resource. :return: None