- Plot Area Tab view can now be toggled, added entry in View Menu and shortcut key CTRL+F10

- All the tabs in the GUI right side are (Plot Are, Preferences etc) are now detachable to a separate windows which when closed it returns in the previous location in the toolbar. Those detached tabs can be also reattached by drag and drop.
This commit is contained in:
Marius Stanciu 2019-02-01 14:51:49 +02:00 committed by Marius
parent 080d148b37
commit f4da8c8c68
6 changed files with 511 additions and 64 deletions

View File

@ -1032,6 +1032,7 @@ class App(QtCore.QObject):
self.ui.menuview_zoom_in.triggered.connect(lambda: self.plotcanvas.zoom(1 / 1.5)) self.ui.menuview_zoom_in.triggered.connect(lambda: self.plotcanvas.zoom(1 / 1.5))
self.ui.menuview_zoom_out.triggered.connect(lambda: self.plotcanvas.zoom(1.5)) self.ui.menuview_zoom_out.triggered.connect(lambda: self.plotcanvas.zoom(1.5))
self.ui.menuview_toggle_fscreen.triggered.connect(self.on_fullscreen) self.ui.menuview_toggle_fscreen.triggered.connect(self.on_fullscreen)
self.ui.menuview_toggle_parea.triggered.connect(self.on_toggle_plotarea)
self.ui.menuview_toggle_grid.triggered.connect(self.on_toggle_grid) self.ui.menuview_toggle_grid.triggered.connect(self.on_toggle_grid)
self.ui.menuview_toggle_axis.triggered.connect(self.on_toggle_axis) self.ui.menuview_toggle_axis.triggered.connect(self.on_toggle_axis)
self.ui.menuview_toggle_workspace.triggered.connect(self.on_workspace_menu) self.ui.menuview_toggle_workspace.triggered.connect(self.on_workspace_menu)
@ -2752,13 +2753,29 @@ class App(QtCore.QObject):
if self.toggle_fscreen is False: if self.toggle_fscreen is False:
for tb in self.ui.findChildren(QtWidgets.QToolBar): for tb in self.ui.findChildren(QtWidgets.QToolBar):
tb.setVisible(False) tb.setVisible(False)
self.ui.notebook.setVisible(False) self.ui.splitter_left.setVisible(False)
self.toggle_fscreen = True self.toggle_fscreen = True
else: else:
self.restore_toolbar_view() self.restore_toolbar_view()
self.ui.notebook.setVisible(True) self.ui.splitter_left.setVisible(True)
self.toggle_fscreen = False self.toggle_fscreen = False
def on_toggle_plotarea(self):
try:
name = self.ui.plot_tab_area.widget(0).objectName()
except AttributeError:
self.ui.plot_tab_area.addTab(self.ui.plot_tab, "Plot Area")
# remove the close button from the Plot Area tab (first tab index = 0) as this one will always be ON
self.ui.plot_tab_area.protectTab(0)
return
if name != 'plotarea':
self.ui.plot_tab_area.insertTab(0, self.ui.plot_tab, "Plot Area")
# remove the close button from the Plot Area tab (first tab index = 0) as this one will always be ON
self.ui.plot_tab_area.protectTab(0)
else:
self.ui.plot_tab_area.closeTab(0)
def on_toggle_axis(self): def on_toggle_axis(self):
if self.toggle_axis is False: if self.toggle_axis is False:
self.plotcanvas.v_line.set_data(color=(0.70, 0.3, 0.3, 1.0)) self.plotcanvas.v_line.set_data(color=(0.70, 0.3, 0.3, 1.0))
@ -3751,6 +3768,10 @@ class App(QtCore.QObject):
if event.key == 'S': if event.key == 'S':
self.on_file_saveproject() self.on_file_saveproject()
# Toggle Plot Area
if event.key == 'F10':
self.on_toggle_plotarea()
return return
elif self.key_modifiers == QtCore.Qt.AltModifier: elif self.key_modifiers == QtCore.Qt.AltModifier:
# place holder for further shortcut key # place holder for further shortcut key
@ -3791,6 +3812,7 @@ class App(QtCore.QObject):
if event.key == 'F10': if event.key == 'F10':
self.on_fullscreen() self.on_fullscreen()
return
elif self.key_modifiers == QtCore.Qt.ShiftModifier: elif self.key_modifiers == QtCore.Qt.ShiftModifier:
# place holder for further shortcut key # place holder for further shortcut key
@ -3825,7 +3847,6 @@ class App(QtCore.QObject):
if event.key == 'Y': if event.key == 'Y':
self.on_skewy() self.on_skewy()
return
else: else:
if event.key == 'F1': if event.key == 'F1':
webbrowser.open(self.manual_url) webbrowser.open(self.manual_url)
@ -3918,6 +3939,17 @@ class App(QtCore.QObject):
def on_shortcut_list(self): def on_shortcut_list(self):
# add the tab if it was closed
self.ui.plot_tab_area.addTab(self.ui.shortcuts_tab, "Key Shortcut List")
# delete the absolute and relative position and messages in the infobar
self.ui.position_label.setText("")
self.ui.rel_position_label.setText("")
# Switch plot_area to preferences page
self.ui.plot_tab_area.setCurrentWidget(self.ui.shortcuts_tab)
self.ui.show()
msg = '''<b>Shortcut list</b><br> msg = '''<b>Shortcut list</b><br>
<br> <br>
<b>~:</b> Show Shortcut List<br> <b>~:</b> Show Shortcut List<br>

View File

@ -268,6 +268,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
self.menuview.addSeparator() self.menuview.addSeparator()
self.menuview_toggle_fscreen = self.menuview.addAction( self.menuview_toggle_fscreen = self.menuview.addAction(
QtGui.QIcon('share/fscreen32.png'), "&Toggle FullScreen\tALT+F10") QtGui.QIcon('share/fscreen32.png'), "&Toggle FullScreen\tALT+F10")
self.menuview_toggle_parea = self.menuview.addAction(
QtGui.QIcon('share/plot32.png'), "&Toggle Plot Area\tCTRL+F10")
self.menuview.addSeparator() self.menuview.addSeparator()
self.menuview_toggle_grid = self.menuview.addAction(QtGui.QIcon('share/grid32.png'), "&Toggle Grid\tG") self.menuview_toggle_grid = self.menuview.addAction(QtGui.QIcon('share/grid32.png'), "&Toggle Grid\tG")
@ -408,52 +410,8 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
self.addToolBar(self.geo_edit_toolbar) self.addToolBar(self.geo_edit_toolbar)
self.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar') self.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar')
self.snap_toolbar.setObjectName('Snap_TB') self.snap_toolbar.setObjectName('Snap_TB')
# self.snap_toolbar.setMaximumHeight(30)
self.addToolBar(self.snap_toolbar) self.addToolBar(self.snap_toolbar)
# if self.app.gui_defaults['global_theme'] == 'standard':
# self.toolbarfile = QtWidgets.QToolBar('File Toolbar')
# self.toolbarfile.setObjectName('File_TB')
# self.addToolBar(self.toolbarfile)
# self.toolbargeo = QtWidgets.QToolBar('Edit Toolbar')
# self.toolbargeo.setObjectName('Edit_TB')
# self.addToolBar(self.toolbargeo)
# self.toolbarview = QtWidgets.QToolBar('View Toolbar')
# self.toolbarview.setObjectName('View_TB')
# self.addToolBar(self.toolbarview)
# self.toolbartools = QtWidgets.QToolBar('Tools Toolbar')
# self.toolbartools.setObjectName('Tools_TB')
# self.addToolBar(self.toolbartools)
# self.exc_edit_toolbar = QtWidgets.QToolBar('Excellon Editor Toolbar')
# self.exc_edit_toolbar.setObjectName('ExcEditor_TB')
# self.addToolBar(self.exc_edit_toolbar)
# self.geo_edit_toolbar = QtWidgets.QToolBar('Geometry Editor Toolbar')
# self.geo_edit_toolbar.setVisible(False)
# self.geo_edit_toolbar.setObjectName('GeoEditor_TB')
# self.addToolBar(self.geo_edit_toolbar)
# self.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar')
# self.snap_toolbar.setObjectName('Snap_TB')
# elif self.app.defaults['global_theme'] == 'compact':
# self.toolbarfile = QtWidgets.QToolBar('File Toolbar')
# self.toolbarfile.setObjectName('File_TB')
# self.addToolBar(self.toolbarfile)
# self.toolbargeo = QtWidgets.QToolBar('Edit Toolbar')
# self.toolbargeo.setObjectName('Edit_TB')
# self.addToolBar(self.toolbargeo)
# self.toolbarview = QtWidgets.QToolBar('View Toolbar')
# self.toolbarview.setObjectName('View_TB')
# self.addToolBar(self.toolbarview)
# self.toolbartools = QtWidgets.QToolBar('Tools Toolbar')
# self.toolbartools.setObjectName('Tools_TB')
# self.addToolBar(self.toolbartools)
# self.exc_edit_toolbar = QtWidgets.QToolBar('Excellon Editor Toolbar')
# self.exc_edit_toolbar.setObjectName('ExcEditor_TB')
# self.addToolBar(self.exc_edit_toolbar)
# self.geo_edit_toolbar = QtWidgets.QToolBar('Geometry Editor Toolbar')
# self.geo_edit_toolbar.setVisible(False)
# self.geo_edit_toolbar.setObjectName('GeoEditor_TB')
# self.addToolBar(self.geo_edit_toolbar)
# self.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar')
# self.snap_toolbar.setObjectName('Snap_TB')
# self.addToolBar(self.snap_toolbar)
### File Toolbar ### ### File Toolbar ###
self.file_open_gerber_btn = self.toolbarfile.addAction(QtGui.QIcon('share/flatcam_icon32.png'), self.file_open_gerber_btn = self.toolbarfile.addAction(QtGui.QIcon('share/flatcam_icon32.png'),
@ -580,15 +538,10 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
self.notebook = QtWidgets.QTabWidget() self.notebook = QtWidgets.QTabWidget()
self.splitter.addWidget(self.notebook) self.splitter.addWidget(self.notebook)
# if self.app.defaults['global_theme'] == 'standard': self.splitter_left = QtWidgets.QSplitter(Qt.Vertical)
# self.splitter.addWidget(self.notebook) self.splitter.addWidget(self.splitter_left)
# elif self.app.defaults['global_theme'] == 'compact': self.splitter_left.addWidget(self.notebook)
# self.splitter_2 = QtWidgets.QSplitter(Qt.Vertical) self.splitter_left.setHandleWidth(0)
# self.splitter.addWidget(self.splitter_2)
# self.splitter_2.addWidget(self.notebook)
# self.splitter_2.setHandleWidth(0)
# self.snap_toolbar.setMaximumHeight(30)
# self.splitter_2.addWidget(self.snap_toolbar)
### Project ### ### Project ###
self.project_tab = QtWidgets.QWidget() self.project_tab = QtWidgets.QWidget()
@ -620,16 +573,19 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
self.right_lay = QtWidgets.QVBoxLayout() self.right_lay = QtWidgets.QVBoxLayout()
self.right_lay.setContentsMargins(0, 0, 0, 0) self.right_lay.setContentsMargins(0, 0, 0, 0)
self.right_widget.setLayout(self.right_lay) self.right_widget.setLayout(self.right_lay)
self.plot_tab_area = FCTab() # self.plot_tab_area = FCTab()
self.plot_tab_area = FCDetachableTab()
self.right_lay.addWidget(self.plot_tab_area) self.right_lay.addWidget(self.plot_tab_area)
self.plot_tab_area.setTabsClosable(True) self.plot_tab_area.setTabsClosable(True)
plot_tab = QtWidgets.QWidget() self.plot_tab = QtWidgets.QWidget()
self.plot_tab_area.addTab(plot_tab, "Plot Area") self.plot_tab.setObjectName("plotarea")
self.plot_tab_area.addTab(self.plot_tab, "Plot Area")
self.right_layout = QtWidgets.QVBoxLayout() self.right_layout = QtWidgets.QVBoxLayout()
self.right_layout.setContentsMargins(2, 2, 2, 2) self.right_layout.setContentsMargins(2, 2, 2, 2)
plot_tab.setLayout(self.right_layout) self.plot_tab.setLayout(self.right_layout)
# remove the close button from the Plot Area tab (first tab index = 0) as this one will always be ON # remove the close button from the Plot Area tab (first tab index = 0) as this one will always be ON
self.plot_tab_area.protectTab(0) self.plot_tab_area.protectTab(0)
@ -759,6 +715,13 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
"which is the file storing the working default preferences.") "which is the file storing the working default preferences.")
self.pref_tab_bottom_layout_2.addWidget(self.pref_save_button) self.pref_tab_bottom_layout_2.addWidget(self.pref_save_button)
########################################
### HERE WE BUILD THE SHORTCUTS LIST. TAB AREA ###
########################################
self.shortcuts_tab = QtWidgets.QWidget()
self.sh_tab_layout = QtWidgets.QVBoxLayout(self.shortcuts_tab)
self.sh_tab_layout.setContentsMargins(2, 2, 2, 2)
############################################################## ##############################################################
### HERE WE BUILD THE CONTEXT MENU FOR RMB CLICK ON CANVAS ### ### HERE WE BUILD THE CONTEXT MENU FOR RMB CLICK ON CANVAS ###
@ -918,7 +881,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
# restore the Toolbar State from file # restore the Toolbar State from file
try: try:
with open(self.app.data_path + '\state.config', 'rb') as stream: with open(self.app.data_path + '\gui_state.config', 'rb') as stream:
self.restoreState(QtCore.QByteArray(stream.read())) self.restoreState(QtCore.QByteArray(stream.read()))
log.debug("FlatCAMGUI.__init__() --> UI state restored.") log.debug("FlatCAMGUI.__init__() --> UI state restored.")
except IOError: except IOError:
@ -992,7 +955,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
if self.app.should_we_quit is True: if self.app.should_we_quit is True:
# save toolbar state to file # save toolbar state to file
with open(self.app.data_path + '\state.config', 'wb') as stream: with open(self.app.data_path + '\gui_state.config', 'wb') as stream:
stream.write(self.saveState().data()) stream.write(self.saveState().data())
log.debug("FlatCAMGUI.__init__() --> UI state saved.") log.debug("FlatCAMGUI.__init__() --> UI state saved.")
QtWidgets.qApp.quit() QtWidgets.qApp.quit()

View File

@ -1,4 +1,6 @@
from PyQt5 import QtGui, QtCore, QtWidgets, QtWidgets from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import pyqtSignal, pyqtSlot
from copy import copy from copy import copy
import re import re
import logging import logging
@ -550,6 +552,448 @@ class FCTab(QtWidgets.QTabWidget):
self.tabBar().setTabButton(currentIndex, QtWidgets.QTabBar.RightSide, None) self.tabBar().setTabButton(currentIndex, QtWidgets.QTabBar.RightSide, None)
class FCDetachableTab(QtWidgets.QTabWidget):
# From here: https://stackoverflow.com/questions/47267195/in-pyqt4-is-it-possible-to-detach-tabs-from-a-qtabwidget
def __init__(self, parent=None):
super().__init__()
self.tabBar = self.FCTabBar(self)
self.tabBar.onDetachTabSignal.connect(self.detachTab)
self.tabBar.onMoveTabSignal.connect(self.moveTab)
self.tabBar.detachedTabDropSignal.connect(self.detachedTabDrop)
self.setTabBar(self.tabBar)
# Used to keep a reference to detached tabs since their QMainWindow
# does not have a parent
self.detachedTabs = {}
# Close all detached tabs if the application is closed explicitly
QtWidgets.qApp.aboutToQuit.connect(self.closeDetachedTabs) # @UndefinedVariable
self.setTabsClosable(True)
self.tabCloseRequested.connect(self.closeTab)
def deleteTab(self, currentIndex):
widget = self.widget(currentIndex)
if widget is not None:
widget.deleteLater()
self.removeTab(currentIndex)
def closeTab(self, currentIndex):
self.removeTab(currentIndex)
def protectTab(self, currentIndex):
# self.FCTabBar().setTabButton(currentIndex, QtWidgets.QTabBar.RightSide, None)
self.tabBar.setTabButton(currentIndex, QtWidgets.QTabBar.RightSide, None)
##
# The default movable functionality of QTabWidget must remain disabled
# so as not to conflict with the added features
def setMovable(self, movable):
pass
##
# Move a tab from one position (index) to another
#
# @param fromIndex the original index location of the tab
# @param toIndex the new index location of the tab
@pyqtSlot(int, int)
def moveTab(self, fromIndex, toIndex):
widget = self.widget(fromIndex)
icon = self.tabIcon(fromIndex)
text = self.tabText(fromIndex)
self.removeTab(fromIndex)
self.insertTab(toIndex, widget, icon, text)
self.setCurrentIndex(toIndex)
##
# Detach the tab by removing it's contents and placing them in
# a DetachedTab window
#
# @param index the index location of the tab to be detached
# @param point the screen position for creating the new DetachedTab window
@pyqtSlot(int, QtCore.QPoint)
def detachTab(self, index, point):
# Get the tab content
name = self.tabText(index)
icon = self.tabIcon(index)
if icon.isNull():
icon = self.window().windowIcon()
contentWidget = self.widget(index)
try:
contentWidgetRect = contentWidget.frameGeometry()
except AttributeError:
return
# Create a new detached tab window
detachedTab = self.FCDetachedTab(name, contentWidget)
detachedTab.setWindowModality(QtCore.Qt.NonModal)
detachedTab.setWindowIcon(icon)
detachedTab.setGeometry(contentWidgetRect)
detachedTab.onCloseSignal.connect(self.attachTab)
detachedTab.onDropSignal.connect(self.tabBar.detachedTabDrop)
detachedTab.move(point)
detachedTab.show()
# Create a reference to maintain access to the detached tab
self.detachedTabs[name] = detachedTab
##
# Re-attach the tab by removing the content from the DetachedTab window,
# closing it, and placing the content back into the DetachableTabWidget
#
# @param contentWidget the content widget from the DetachedTab window
# @param name the name of the detached tab
# @param icon the window icon for the detached tab
# @param insertAt insert the re-attached tab at the given index
def attachTab(self, contentWidget, name, icon, insertAt=None):
# Make the content widget a child of this widget
contentWidget.setParent(self)
# Remove the reference
del self.detachedTabs[name]
# Create an image from the given icon (for comparison)
if not icon.isNull():
try:
tabIconPixmap = icon.pixmap(icon.availableSizes()[0])
tabIconImage = tabIconPixmap.toImage()
except IndexError:
tabIconImage = None
else:
tabIconImage = None
# Create an image of the main window icon (for comparison)
if not icon.isNull():
try:
windowIconPixmap = self.window().windowIcon().pixmap(icon.availableSizes()[0])
windowIconImage = windowIconPixmap.toImage()
except IndexError:
windowIconImage = None
else:
windowIconImage = None
# Determine if the given image and the main window icon are the same.
# If they are, then do not add the icon to the tab
if tabIconImage == windowIconImage:
if insertAt == None:
index = self.addTab(contentWidget, name)
else:
index = self.insertTab(insertAt, contentWidget, name)
else:
if insertAt == None:
index = self.addTab(contentWidget, icon, name)
else:
index = self.insertTab(insertAt, contentWidget, icon, name)
# Make this tab the current tab
if index > -1:
self.setCurrentIndex(index)
##
# Remove the tab with the given name, even if it is detached
#
# @param name the name of the tab to be removed
def removeTabByName(self, name):
# Remove the tab if it is attached
attached = False
for index in range(self.count()):
if str(name) == str(self.tabText(index)):
self.removeTab(index)
attached = True
break
# If the tab is not attached, close it's window and
# remove the reference to it
if not attached:
for key in self.detachedTabs:
if str(name) == str(key):
self.detachedTabs[key].onCloseSignal.disconnect()
self.detachedTabs[key].close()
del self.detachedTabs[key]
break
##
# Handle dropping of a detached tab inside the DetachableTabWidget
#
# @param name the name of the detached tab
# @param index the index of an existing tab (if the tab bar
# determined that the drop occurred on an
# existing tab)
# @param dropPos the mouse cursor position when the drop occurred
@QtCore.pyqtSlot(str, int, QtCore.QPoint)
def detachedTabDrop(self, name, index, dropPos):
# If the drop occurred on an existing tab, insert the detached
# tab at the existing tab's location
if index > -1:
# Create references to the detached tab's content and icon
contentWidget = self.detachedTabs[name].contentWidget
icon = self.detachedTabs[name].windowIcon()
# Disconnect the detached tab's onCloseSignal so that it
# does not try to re-attach automatically
self.detachedTabs[name].onCloseSignal.disconnect()
# Close the detached
self.detachedTabs[name].close()
# Re-attach the tab at the given index
self.attachTab(contentWidget, name, icon, index)
# If the drop did not occur on an existing tab, determine if the drop
# occurred in the tab bar area (the area to the side of the QTabBar)
else:
# Find the drop position relative to the DetachableTabWidget
tabDropPos = self.mapFromGlobal(dropPos)
# If the drop position is inside the DetachableTabWidget...
if self.rect().contains(tabDropPos):
# If the drop position is inside the tab bar area (the
# area to the side of the QTabBar) or there are not tabs
# currently attached...
if tabDropPos.y() < self.tabBar.height() or self.count() == 0:
# Close the detached tab and allow it to re-attach
# automatically
self.detachedTabs[name].close()
##
# Close all tabs that are currently detached.
def closeDetachedTabs(self):
listOfDetachedTabs = []
for key in self.detachedTabs:
listOfDetachedTabs.append(self.detachedTabs[key])
for detachedTab in listOfDetachedTabs:
detachedTab.close()
##
# When a tab is detached, the contents are placed into this QMainWindow. The tab
# can be re-attached by closing the dialog or by dragging the window into the tab bar
class FCDetachedTab(QtWidgets.QMainWindow):
onCloseSignal = pyqtSignal(QtWidgets.QWidget, str, QtGui.QIcon)
onDropSignal = pyqtSignal(str, QtCore.QPoint)
def __init__(self, name, contentWidget):
QtWidgets.QMainWindow.__init__(self, None)
self.setObjectName(name)
self.setWindowTitle(name)
self.contentWidget = contentWidget
self.setCentralWidget(self.contentWidget)
self.contentWidget.show()
self.windowDropFilter = self.WindowDropFilter()
self.installEventFilter(self.windowDropFilter)
self.windowDropFilter.onDropSignal.connect(self.windowDropSlot)
##
# Handle a window drop event
#
# @param dropPos the mouse cursor position of the drop
@QtCore.pyqtSlot(QtCore.QPoint)
def windowDropSlot(self, dropPos):
self.onDropSignal.emit(self.objectName(), dropPos)
##
# If the window is closed, emit the onCloseSignal and give the
# content widget back to the DetachableTabWidget
#
# @param event a close event
def closeEvent(self, event):
self.onCloseSignal.emit(self.contentWidget, self.objectName(), self.windowIcon())
##
# An event filter class to detect a QMainWindow drop event
class WindowDropFilter(QtCore.QObject):
onDropSignal = pyqtSignal(QtCore.QPoint)
def __init__(self):
QtCore.QObject.__init__(self)
self.lastEvent = None
##
# Detect a QMainWindow drop event by looking for a NonClientAreaMouseMove (173)
# event that immediately follows a Move event
#
# @param obj the object that generated the event
# @param event the current event
def eventFilter(self, obj, event):
# If a NonClientAreaMouseMove (173) event immediately follows a Move event...
if self.lastEvent == QtCore.QEvent.Move and event.type() == 173:
# Determine the position of the mouse cursor and emit it with the
# onDropSignal
mouseCursor = QtGui.QCursor()
dropPos = mouseCursor.pos()
self.onDropSignal.emit(dropPos)
self.lastEvent = event.type()
return True
else:
self.lastEvent = event.type()
return False
class FCTabBar(QtWidgets.QTabBar):
onDetachTabSignal = pyqtSignal(int, QtCore.QPoint)
onMoveTabSignal = pyqtSignal(int, int)
detachedTabDropSignal = pyqtSignal(str, int, QtCore.QPoint)
def __init__(self, parent=None):
QtWidgets.QTabBar.__init__(self, parent)
self.setAcceptDrops(True)
self.setElideMode(QtCore.Qt.ElideRight)
self.setSelectionBehaviorOnRemove(QtWidgets.QTabBar.SelectLeftTab)
self.dragStartPos = QtCore.QPoint()
self.dragDropedPos = QtCore.QPoint()
self.mouseCursor = QtGui.QCursor()
self.dragInitiated = False
# Send the onDetachTabSignal when a tab is double clicked
#
# @param event a mouse double click event
def mouseDoubleClickEvent(self, event):
event.accept()
self.onDetachTabSignal.emit(self.tabAt(event.pos()), self.mouseCursor.pos())
# Set the starting position for a drag event when the mouse button is pressed
#
# @param event a mouse press event
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.dragStartPos = event.pos()
self.dragDropedPos.setX(0)
self.dragDropedPos.setY(0)
self.dragInitiated = False
QtWidgets.QTabBar.mousePressEvent(self, event)
# Determine if the current movement is a drag. If it is, convert it into a QDrag. If the
# drag ends inside the tab bar, emit an onMoveTabSignal. If the drag ends outside the tab
# bar, emit an onDetachTabSignal.
#
# @param event a mouse move event
def mouseMoveEvent(self, event):
# Determine if the current movement is detected as a drag
if not self.dragStartPos.isNull() and ((event.pos() - self.dragStartPos).manhattanLength() < QtWidgets.QApplication.startDragDistance()):
self.dragInitiated = True
# If the current movement is a drag initiated by the left button
if (((event.buttons() & QtCore.Qt.LeftButton)) and self.dragInitiated):
# Stop the move event
finishMoveEvent = QtGui.QMouseEvent(QtCore.QEvent.MouseMove, event.pos(), QtCore.Qt.NoButton, QtCore.Qt.NoButton, QtCore.Qt.NoModifier)
QtWidgets.QTabBar.mouseMoveEvent(self, finishMoveEvent)
# Convert the move event into a drag
drag = QtGui.QDrag(self)
mimeData = QtCore.QMimeData()
# mimeData.setData('action', 'application/tab-detach')
drag.setMimeData(mimeData)
# screen = QScreen(self.parentWidget().currentWidget().winId())
# Create the appearance of dragging the tab content
pixmap = self.parent().widget(self.tabAt(self.dragStartPos)).grab()
targetPixmap = QtGui.QPixmap(pixmap.size())
targetPixmap.fill(QtCore.Qt.transparent)
painter = QtGui.QPainter(targetPixmap)
painter.setOpacity(0.85)
painter.drawPixmap(0, 0, pixmap)
painter.end()
drag.setPixmap(targetPixmap)
# Initiate the drag
dropAction = drag.exec_(QtCore.Qt.MoveAction | QtCore.Qt.CopyAction)
# For Linux: Here, drag.exec_() will not return MoveAction on Linux. So it
# must be set manually
if self.dragDropedPos.x() != 0 and self.dragDropedPos.y() != 0:
dropAction = QtCore.Qt.MoveAction
# If the drag completed outside of the tab bar, detach the tab and move
# the content to the current cursor position
if dropAction == QtCore.Qt.IgnoreAction:
event.accept()
self.onDetachTabSignal.emit(self.tabAt(self.dragStartPos), self.mouseCursor.pos())
# Else if the drag completed inside the tab bar, move the selected tab to the new position
elif dropAction == QtCore.Qt.MoveAction:
if not self.dragDropedPos.isNull():
event.accept()
self.onMoveTabSignal.emit(self.tabAt(self.dragStartPos), self.tabAt(self.dragDropedPos))
else:
QtWidgets.QTabBar.mouseMoveEvent(self, event)
# Determine if the drag has entered a tab position from another tab position
#
# @param event a drag enter event
def dragEnterEvent(self, event):
mimeData = event.mimeData()
# formats = mcd imeData.formats()
# if formats.contains('action') and mimeData.data('action') == 'application/tab-detach':
# event.acceptProposedAction()
QtWidgets.QTabBar.dragMoveEvent(self, event)
# Get the position of the end of the drag
#
# @param event a drop event
def dropEvent(self, event):
self.dragDropedPos = event.pos()
QtWidgets.QTabBar.dropEvent(self, event)
# Determine if the detached tab drop event occurred on an existing tab,
# then send the event to the DetachableTabWidget
def detachedTabDrop(self, name, dropPos):
tabDropPos = self.mapFromGlobal(dropPos)
index = self.tabAt(tabDropPos)
self.detachedTabDropSignal.emit(name, index, dropPos)
class VerticalScrollArea(QtWidgets.QScrollArea): class VerticalScrollArea(QtWidgets.QScrollArea):
""" """
This widget extends QtGui.QScrollArea to make a vertical-only This widget extends QtGui.QScrollArea to make a vertical-only

View File

@ -273,6 +273,11 @@ class ObjectCollection(QtCore.QAbstractItemModel):
if key == QtCore.Qt.Key_S: if key == QtCore.Qt.Key_S:
self.app.on_file_saveproject() self.app.on_file_saveproject()
# Toggle Plot Area
if key == QtCore.Qt.Key_F10:
self.app.on_toggle_plotarea()
return return
elif modifiers == QtCore.Qt.ShiftModifier: elif modifiers == QtCore.Qt.ShiftModifier:
@ -324,6 +329,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
if key == QtCore.Qt.Key_Y: if key == QtCore.Qt.Key_Y:
self.app.on_skewy() self.app.on_skewy()
return return
elif modifiers == QtCore.Qt.AltModifier: elif modifiers == QtCore.Qt.AltModifier:
# Eanble all plots # Eanble all plots
if key == Qt.Key_1: if key == Qt.Key_1:

View File

@ -18,6 +18,8 @@ CAD program, and create G-Code for Isolation routing.
- updated the camlib.CNCJob.scale() function so now the GCode is scaled also (quite a HACK :( it will need to be replaced at some point)). Units change work now on the GCODE also. - updated the camlib.CNCJob.scale() function so now the GCode is scaled also (quite a HACK :( it will need to be replaced at some point)). Units change work now on the GCODE also.
- added the bounds coordinates to the GCODE header - added the bounds coordinates to the GCODE header
- FlatCAM saves now to a file in self.data_path the toolbar positions and the position of TCL Shell - FlatCAM saves now to a file in self.data_path the toolbar positions and the position of TCL Shell
- Plot Area Tab view can now be toggled, added entry in View Menu and shortcut key CTRL+F10
- All the tabs in the GUI right side are (Plot Are, Preferences etc) are now detachable to a separate windows which when closed it returns in the previous location in the toolbar. Those detached tabs can be also reattached by drag and drop.
30.01.2019 30.01.2019

BIN
share/plot32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B