diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/InitGui.py b/InitGui.py index 5b01e7a..c9af825 100644 --- a/InitGui.py +++ b/InitGui.py @@ -28,6 +28,7 @@ PIE_MENU_VERSION = "1.2.7" def pieMenuStart(): + """Main function that starts the Pie Menu.""" import math import operator import platform @@ -37,13 +38,38 @@ def pieMenuStart(): from PySide import QtGui import PieMenuLocator as locator - path = locator.path() - respath = path + "/Resources/icons/" - # global status variables selectionTriggered = False contextPhase = False + path = locator.path() + respath = path + "/Resources/icons/" + stylePath = path + "/Resources/style/" + + with open(stylePath + "Button.qss", "r") as file: + styleButton = file.read() + with open(stylePath + "MenuClose.qss", "r") as file: + styleMenuClose = file.read() + with open(stylePath + "Container.qss", "r") as file: + styleContainer = file.read() + with open(stylePath + "Combo.qss", "r") as file: + styleCombo = file.read() + with open(stylePath + "QuickMenu.qss", "r") as file: + styleQuickMenu = file.read() + with open(stylePath + "QuickMenuItem.qss", "r") as file: + styleQuickMenuItem = file.read() + + iconClose = respath + "PieMenuClose.svg" + iconMenu = respath + "PieMenuQuickMenu.svg" + iconUp = respath + "PieMenuUp.svg" + iconDown = respath + "PieMenuDown.svg" + iconAdd = respath + "PieMenuAdd.svg" + iconRemove = respath + "PieMenuRemove.svg" + iconRename = respath + "PieMenuRename.svg" + iconCopy = respath + "PieMenuCopy.svg" + iconRemoveCommand = respath + "PieMenuRemoveCommand.svg" + + def remObsoleteParams(): """Remove obsolete parameters from older versions.""" paramGet = App.ParamGet("User parameter:BaseApp/PieMenu") @@ -78,82 +104,15 @@ def addMenu(): addMenu() mw.workbenchActivated.connect(addMenu) - - + + def onPreferences(): """Open the preferences dialog.""" onControl() - styleButton = (""" - QToolButton { - background-color: lightGray; - border: 1px outset silver; - } - - QToolButton:disabled { - background-color: darkGray; - } - - QToolButton:hover { - background-color: lightBlue; - } - - QToolButton:checked { - background-color: lightGreen; - } - - QToolButton::menu-indicator { - subcontrol-origin: padding; - subcontrol-position: center center; - } - - """) - - styleMenuClose = (""" - QToolButton { - background-color: rgba(60,60,60,255); - color: silver; - border: 1px solid #1e1e1e; - } - - QToolButton::menu-indicator { - image: none; - } - - """) - - styleContainer = ("QMenu{background: transparent}") - - styleCombo = (""" - QComboBox { - background: transparent; - border: 1px solid transparent; - } - - """) - - styleQuickMenu = ("padding: 5px 10px 5px 10px") - - styleQuickMenuItem = (""" - QMenu::item { - padding: 5px 20px 5px 20px; - } - - """) - - iconClose = respath + "PieMenuClose.svg" - iconMenu = respath + "PieMenuQuickMenu.svg" - iconUp = respath + "PieMenuUp.svg" - iconDown = respath + "PieMenuDown.svg" - iconAdd = respath + "PieMenuAdd.svg" - iconRemove = respath + "PieMenuRemove.svg" - iconRename = respath + "PieMenuRename.svg" - iconCopy = respath + "PieMenuCopy.svg" - iconRemoveCommand = respath + "PieMenuRemoveCommand.svg" - - def radiusSize(buttonSize): + """Calculates border radius for QToolButton based on the given buttonSize.""" radius = str(math.trunc(buttonSize / 2)) @@ -161,6 +120,7 @@ def radiusSize(buttonSize): def iconSize(buttonSize): + """Calculates the size of an icon based on the given buttonSize.""" icon = buttonSize / 3 * 2 @@ -168,13 +128,14 @@ def iconSize(buttonSize): def closeButton(buttonSize=32): + """Style the close button.""" icon = iconSize(buttonSize) radius = radiusSize(buttonSize) button = QtGui.QToolButton() - button.setProperty("ButtonX", 0) - button.setProperty("ButtonY", 0) + button.setProperty("ButtonX", 0) # +, right + button.setProperty("ButtonY", 0) # +, down button.setGeometry(0, 0, buttonSize, buttonSize) button.setIconSize(QtCore.QSize(icon, icon)) button.setIcon(QtGui.QIcon(iconClose)) @@ -191,6 +152,7 @@ def onButton(): def quickMenu(buttonSize=20): + """Style the quick menu button""" icon = iconSize(buttonSize) radius = radiusSize(buttonSize) @@ -200,8 +162,8 @@ def quickMenu(buttonSize=20): button = QtGui.QToolButton() button.setMenu(menu) - button.setProperty("ButtonX", 0) - button.setProperty("ButtonY", 32) + button.setProperty("ButtonX", 0) # +,right + button.setProperty("ButtonY", 32) # +, down button.setGeometry(0, 0, buttonSize, buttonSize) button.setStyleSheet(styleMenuClose + radius) button.setIconSize(QtCore.QSize(icon, icon)) @@ -258,6 +220,7 @@ def quickMenu(buttonSize=20): prefButtonWidgetAction.setDefaultWidget(prefButton) def setChecked(): + """Update the state of checkBoxes according to data on saved parameters.""" paramGet = App.ParamGet("User parameter:BaseApp/PieMenu") if paramGet.GetString("TriggerMode") == "Hover": @@ -270,6 +233,11 @@ def setChecked(): else: pass + if paramGet.GetBool("EnableCustomTrigger"): + checkCustomShortcut.setChecked(True) + else: + checkCustomShortcut.setChecked(False) + setChecked() def onModeGroup(): @@ -393,7 +361,8 @@ def onMenuToolBar(): if len(commands) != 0: menu = QtGui.QMenu(i.windowTitle()) - menu.aboutToShow.connect(lambda sender=menu: onMenuToolbarGroup(sender)) + menu.aboutToShow.connect(lambda sender=menu: \ + onMenuToolbarGroup(sender)) menuToolBar.addMenu(menu) else: pass @@ -411,7 +380,7 @@ def isActualPie(text): else: idMenu = entry if idMenu == text: - return True; + return True return False @@ -434,7 +403,7 @@ def onMenuToolbarGroup(sender): sender.triggered.connect(lambda sender: onToolbarGroup(sender)) def onToolbarGroup(sender): - + paramGet = App.ParamGet("User parameter:BaseApp/PieMenu") if sender.text() == "Show": paramGet.SetBool("ToolBar", True) @@ -442,7 +411,7 @@ def onToolbarGroup(sender): newPieGroup = createPie(sender.data()) else: return - + workbenches = [] commands = [] @@ -455,9 +424,9 @@ def onToolbarGroup(sender): getGuiToolButtonData(sender.data(), None, None, workbenches) toolbar_desc = ", ".join(workbenches) toolbar_desc = toolbar_desc + ': ' + sender.data() - paramGet.SetString("ToolBar", toolbar_desc) + paramGet.SetString("ToolBar", toolbar_desc) PieMenuInstance.hide() - PieMenuInstance.showAtMouse(notKeyTriggered=True) + PieMenuInstance.showAtMouse(notKeyTriggered=True) toolbarGroup.triggered.connect(onToolbarGroup) @@ -514,7 +483,8 @@ def __init__(self): self.menu = QtGui.QMenu(mw) self.menuSize = 0 self.menu.setStyleSheet(styleContainer) - self.menu.setWindowFlags(self.menu.windowFlags() | QtCore.Qt.FramelessWindowHint) + self.menu.setWindowFlags(self.menu.windowFlags() | + QtCore.Qt.FramelessWindowHint) self.menu.setAttribute(QtCore.Qt.WA_TranslucentBackground) if compositingManager: @@ -630,12 +600,12 @@ def hide(self): self.menu.hide() def showAtMouse(self, notKeyTriggered=False): - + nonlocal selectionTriggered nonlocal contextPhase global lastPosX global lastPosY - + paramGet = App.ParamGet("User parameter:BaseApp/PieMenu") enableContext = paramGet.GetBool("EnableContext") @@ -705,14 +675,17 @@ def showAtMouse(self, notKeyTriggered=False): else: lastPosX = pos.x() lastPosY = pos.y() - + for i in self.buttons: - i.move(i.property("ButtonX") + (self.menuSize - i.size().width()) / 2, - i.property("ButtonY") + (self.menuSize - i.size().height()) / 2) + i.move(i.property("ButtonX") + + (self.menuSize - i.size().width()) / 2, + i.property("ButtonY") + + (self.menuSize - i.size().height()) / 2) i.setVisible(True) - self.menu.popup(QtCore.QPoint(pos.x() - self.menuSize / 2, pos.y() - self.menuSize / 2)) + self.menu.popup(QtCore.QPoint(pos.x() - self.menuSize / 2, pos.y() + - self.menuSize / 2)) sign = { @@ -731,6 +704,7 @@ def contextList(): contextAll.clear() + # Get current pieMenus using available index if indexList: indexList = indexList.split(".,.") @@ -820,7 +794,7 @@ def obj(): def listTopo(): - + nonlocal selectionTriggered nonlocal contextPhase @@ -957,7 +931,7 @@ def getActionData(action, actions, commands, workbenches): workbench = extractWorkbench(command) if workbenches is not None: - if not workbench in workbenches: + if workbench not in workbenches: workbenches.append(workbench) @@ -977,7 +951,7 @@ def actualizeWorkbenchActions(actions, toolList, actionMap): if i == "": pass elif i in actionMap: - if not actionMap[i] in actions: + if actionMap[i] not in actions: actions.append(actionMap[i]) else: cmd_parts = i.split("_") @@ -997,7 +971,7 @@ def actualizeWorkbenchActions(actions, toolList, actionMap): # after workbench activation actionMap has to be actualized Gui.activateWorkbench(cmdWb) return True - + return False @@ -1089,7 +1063,7 @@ def updateCommands(context=False): actionMapAll = getGuiActionMapAll() lastWorkbench = Gui.activeWorkbench() - + while actualizeWorkbenchActions(actions, toolList, actionMapAll): actionMapAll = getGuiActionMapAll() else: @@ -1101,6 +1075,15 @@ def updateCommands(context=False): def getGroup(mode=0): + """ + Obtain the parameter group. + + When: + mode = 0: read from comboBox at GUI + mode = 1: read from CurrentPie parameter + mode = 2: read from ContextPie parameter + If it doesn't exists return default PieMenu group + """ paramGet = App.ParamGet("User parameter:BaseApp/PieMenu") paramIndexGet = App.ParamGet("User parameter:BaseApp/PieMenu/Index") indexList = paramIndexGet.GetString("IndexList") @@ -1118,6 +1101,7 @@ def getGroup(mode=0): else: text = cBox.currentText() + # Get list of available groups if indexList: indexList = indexList.split(".,.") @@ -1132,6 +1116,8 @@ def getGroup(mode=0): group = None + # Iterate over thr available groups on indexList + # to find the group stored on `text` var for i in indexList: a = str(i) try: @@ -1145,8 +1131,10 @@ def getGroup(mode=0): pass if group: + # group was found, good pass else: + # return the default PieMenu group if 0 in indexList: group = paramIndexGet.GetGroup("0") else: @@ -1256,7 +1244,7 @@ def cBoxUpdate(): pieList.append(paramIndexGet.GetString(a)) duplicates = [] - for i in pieList: + for i in pieList: if i == currentPie: pass else: @@ -1283,6 +1271,7 @@ def onPieChange(): toolList() setDefaults() setCheckContext() + setCheckCustomShortcut() cBox.currentIndexChanged.connect(onPieChange) @@ -1357,9 +1346,6 @@ def splitIndexList(indexList): def createPie(text): - - - paramIndexGet = App.ParamGet("User parameter:BaseApp/PieMenu/Index") indexList = paramIndexGet.GetString("IndexList") @@ -1414,9 +1400,9 @@ def onButtonAddPieMenu(): text, ok = inputTextDialog("New menu") if not ok: return - + createPie(text) - + buttonAddPieMenu.clicked.connect(onButtonAddPieMenu) @@ -1463,7 +1449,7 @@ def onButtonRemovePieMenu(): paramIndexGet.RemGroup(a) paramIndexGet.RemString(a) - # special case treatment + # special case treatment if pie == currentPie: currentPie = "Default" try: @@ -1471,7 +1457,7 @@ def onButtonRemovePieMenu(): except TypeError: paramGet.SetString("CurrentPie", currentPie) if pie == contextPie: - paramGet.RemString("ContextPie") + paramGet.RemString("ContextPie") else: pass @@ -1490,8 +1476,8 @@ def onButtonRemovePieMenu(): buttonRenamePieMenu.setIcon(QtGui.QIcon(iconRename)) buttonRenamePieMenu.setMinimumHeight(30) buttonRenamePieMenu.setMinimumWidth(30) - - + + def onButtonRenamePieMenu(): text, ok = inputTextDialog("Rename menu") @@ -1528,8 +1514,8 @@ def onButtonRenamePieMenu(): pass cBoxUpdate() - buttonRenamePieMenu.clicked.connect(onButtonRenamePieMenu) - + buttonRenamePieMenu.clicked.connect(onButtonRenamePieMenu) + buttonCopyPieMenu = QtGui.QToolButton() buttonCopyPieMenu.setToolTip("Copy current pie menu") buttonCopyPieMenu.setIcon(QtGui.QIcon(iconCopy)) @@ -1547,12 +1533,12 @@ def getCurrentMenuIndex(currentMenuName): a = str(i) indexName = paramIndexGet.GetString(a) if indexName == currentMenuName: - return a; + return a return "-1" def copyIndexParams(grpOrg, grpCopy): - + valButOrg = grpOrg.GetInt("Button") valRadOrg = grpOrg.GetInt("Radius") tbOrg = grpOrg.GetString("ToolList") @@ -1586,9 +1572,9 @@ def copyContextParams(grpOrg, grpCopy): grpCntCopy.SetString("ObjectSign", objSgnOrg) grpCntCopy.SetInt("ObjectValue", objValOrg) - + def onButtonCopyPieMenu(): - + text, ok = inputTextDialog("Copy menu") if not ok: return @@ -1641,7 +1627,7 @@ def onButtonCopyPieMenu(): paramIndexGet.SetString(indexCopy, text) cBoxUpdate() - + buttonCopyPieMenu.clicked.connect(onButtonCopyPieMenu) labelRadius = QtGui.QLabel("Pie size") @@ -1818,7 +1804,7 @@ def onToolListWidget(): buttonList() toolListWidget.itemChanged.connect(onToolListWidget) - + def buttonList2ToolList(buttonListWidget): @@ -1849,7 +1835,7 @@ def onButtonUp(): buttonListWidget.insertItem(currentIndex - 1, currentItem) buttonListWidget.setCurrentRow(currentIndex - 1) buttonList2ToolList(buttonListWidget) - + buttonUp.clicked.connect(onButtonUp) buttonDown = QtGui.QToolButton() @@ -2057,6 +2043,7 @@ def onResetButton(): group.RemGroup("Context") setDefaults() setCheckContext() + setCheckCustomShortcut() resetButton.clicked.connect(onResetButton) @@ -2067,6 +2054,7 @@ def setDefaults(): vertexSign = groupContext.GetString("VertexSign") + # Make sure vertexSign has a valid value if vertexSign in sign: pass else: @@ -2241,7 +2229,7 @@ def setDefaultPie(restore=False): if 0 in indexList: if restore: group = paramIndexGet.GetGroup("0") - group.SetString("ToolList", ".,.".join(defaultTools)) + group.SetString("ToolList", ".,.".join(defaultTools)) else: pass else: @@ -2269,7 +2257,56 @@ def setDefaultPie(restore=False): group.SetInt("Radius", 100) group.SetInt("Button", 32) + def onTriggerSequenceChanged(seq): + seqAsString = seq.toString() + + if len(seqAsString) == 0: + return + + singleSequence = seqAsString.split(', ')[-1] + + keySequenceEdit.setKeySequence(singleSequence) + App.ParamGet("User parameter:BaseApp/PieMenu") \ + .SetString("CustomTriggerShortcut", singleSequence) + + if actionKey: + actionKey.setShortcut(keySequenceEdit.keySequence()) + + customShortcutLabel = QtGui.QLabel("Override 'TAB' shortcut") + checkCustomShortcut = QtGui.QCheckBox() + + def setCheckCustomShortcut(): + """Update editability of keySequenceEdit element.""" + paramGet = App.ParamGet("User parameter:BaseApp/PieMenu") + + if paramGet.GetBool("EnableCustomTrigger"): + keySequenceEdit.setEnabled(True) + else: + keySequenceEdit.setEnabled(False) + + def onCheckCustomShorcut(): + """Update PieMenu/EnableCustomTrigger value on checkBox change.""" + paramGet = App.ParamGet("User parameter:BaseApp/PieMenu") + + if checkCustomShortcut.isChecked(): + keySequenceEdit.setEnabled(True) + paramGet.SetBool("EnableCustomTrigger", 1) + else: + keySequenceEdit.setEnabled(False) + paramGet.SetBool("EnableCustomTrigger", 0) + # Removing the custom shortcut restores the TAB shortcut + paramGet.RemString("CustomTriggerShortcut") + + checkCustomShortcut.stateChanged.connect(onCheckCustomShorcut) + + keySequenceLabel = QtGui.QLabel("Custom trigger shortcut") + keySequenceEdit = QtGui.QKeySequenceEdit() + keySequenceEdit.setKeySequence(App.ParamGet("User parameter:BaseApp/PieMenu") \ + .GetString("CustomTriggerShortcut") or "TAB") + keySequenceEdit.keySequenceChanged.connect(onTriggerSequenceChanged) + def onControl(): + """Initializes the preferences dialog.""" global pieMenuDialog @@ -2285,6 +2322,16 @@ def onControl(): pieMenuTabLayout = QtGui.QVBoxLayout() pieMenuTab.setLayout(pieMenuTabLayout) + layoutNewShortcut = QtGui.QHBoxLayout() + layoutNewShortcut.addWidget(customShortcutLabel) + layoutNewShortcut.addStretch(1) + layoutNewShortcut.addWidget(checkCustomShortcut) + + layoutKeySequenceEdit = QtGui.QHBoxLayout() + layoutKeySequenceEdit.addWidget(keySequenceLabel) + layoutKeySequenceEdit.addStretch(1) + layoutKeySequenceEdit.addWidget(keySequenceEdit) + layoutAddRemove = QtGui.QHBoxLayout() layoutAddRemove.addWidget(cBox) layoutAddRemove.addWidget(buttonAddPieMenu) @@ -2302,10 +2349,12 @@ def onControl(): layoutButton.addStretch(1) layoutButton.addWidget(spinButton) - pieMenuTabLayout.insertLayout(0, layoutAddRemove) - pieMenuTabLayout.insertSpacing(1, 24) - pieMenuTabLayout.insertLayout(2, layoutRadius) - pieMenuTabLayout.insertLayout(3, layoutButton) + pieMenuTabLayout.insertLayout(0, layoutNewShortcut) + pieMenuTabLayout.insertLayout(1, layoutKeySequenceEdit) + pieMenuTabLayout.insertLayout(2, layoutAddRemove) + pieMenuTabLayout.insertSpacing(3, 24) + pieMenuTabLayout.insertLayout(4, layoutRadius) + pieMenuTabLayout.insertLayout(5, layoutButton) pieMenuTabLayout.addStretch(0) contextTab = QtGui.QWidget() @@ -2368,9 +2417,9 @@ def onControl(): def addAccessoriesMenu(): - + if mw.property("eventLoop"): - + startAM = False try: mw.mainWindowClosed @@ -2384,7 +2433,9 @@ def addAccessoriesMenu(): accessoriesMenu() + # Start of the application mw = Gui.getMainWindow() + actionKey = None start = True for action in mw.findChildren(QtGui.QAction): @@ -2428,7 +2479,7 @@ def addAccessoriesMenu(): actionKey = QtGui.QAction(mw) actionKey.setText("Invoke pie menu") actionKey.setObjectName("PieMenuShortCut") - actionKey.setShortcut(QtGui.QKeySequence("TAB")) + actionKey.setShortcut(keySequenceEdit.keySequence()) actionKey.triggered.connect(PieMenuInstance.showAtMouse) mw.addAction(actionKey) @@ -2440,4 +2491,4 @@ def addAccessoriesMenu(): else: pass -pieMenuStart() \ No newline at end of file +pieMenuStart() diff --git a/Resources/style/Button.qss b/Resources/style/Button.qss new file mode 100644 index 0000000..9223856 --- /dev/null +++ b/Resources/style/Button.qss @@ -0,0 +1,22 @@ +QToolButton { + background-color: lightGray; + border: 1px outset silver; +} + +QToolButton:disabled { + background-color: darkGray; +} + +QToolButton:hover { + background-color: lightBlue; +} + +QToolButton:checked { + background-color: lightGreen; +} + +QToolButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: center center; +} + diff --git a/Resources/style/Combo.qss b/Resources/style/Combo.qss new file mode 100644 index 0000000..383191c --- /dev/null +++ b/Resources/style/Combo.qss @@ -0,0 +1,5 @@ +QComboBox { + background: transparent; + border: 1px solid transparent; +} + diff --git a/Resources/style/Container.qss b/Resources/style/Container.qss new file mode 100644 index 0000000..fa428b4 --- /dev/null +++ b/Resources/style/Container.qss @@ -0,0 +1 @@ +QMenu{background: transparent} diff --git a/Resources/style/MenuClose.qss b/Resources/style/MenuClose.qss new file mode 100644 index 0000000..e0acfc7 --- /dev/null +++ b/Resources/style/MenuClose.qss @@ -0,0 +1,10 @@ +QToolButton { + background-color: rgba(60,60,60,255); + color: silver; + border: 1px solid #1e1e1e; +} + +QToolButton::menu-indicator { + image: none; +} + diff --git a/Resources/style/QuickMenu.qss b/Resources/style/QuickMenu.qss new file mode 100644 index 0000000..0290fa7 --- /dev/null +++ b/Resources/style/QuickMenu.qss @@ -0,0 +1 @@ +padding: 5px 10px 5px 10px diff --git a/Resources/style/QuickMenuItem.qss b/Resources/style/QuickMenuItem.qss new file mode 100644 index 0000000..40e6fbb --- /dev/null +++ b/Resources/style/QuickMenuItem.qss @@ -0,0 +1,4 @@ +QMenu::item { + padding: 5px 20px 5px 20px; +} +