1# -*- coding: utf-8 -*- 2 3# Copyright (c) 2007 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> 4# 5 6""" 7Module implementing the QFileDialog wizard plugin. 8""" 9 10import re 11 12from PyQt5.QtCore import QObject 13from PyQt5.QtWidgets import QDialog 14 15from E5Gui.E5Application import e5App 16from E5Gui.E5Action import E5Action 17from E5Gui import E5MessageBox 18 19import UI.Info 20 21# Start-Of-Header 22name = "QFileDialog Wizard Plugin" 23author = "Detlev Offenbach <detlev@die-offenbachs.de>" 24autoactivate = True 25deactivateable = True 26version = UI.Info.VersionOnly 27className = "FileDialogWizard" 28packageName = "__core__" 29shortDescription = "Show the QFileDialog wizard." 30longDescription = """This plugin shows the QFileDialog wizard.""" 31pyqtApi = 2 32# End-Of-Header 33 34error = "" 35 36 37class FileDialogWizard(QObject): 38 """ 39 Class implementing the QFileDialog wizard plugin. 40 """ 41 def __init__(self, ui): 42 """ 43 Constructor 44 45 @param ui reference to the user interface object (UI.UserInterface) 46 """ 47 super().__init__(ui) 48 self.__ui = ui 49 50 # PyQt5 51 self.__pyqtRe = re.compile(r"(?:import|from)\s+PyQt([56])") 52 53 def activate(self): 54 """ 55 Public method to activate this plugin. 56 57 @return tuple of None and activation status (boolean) 58 """ 59 self.__initActions() 60 self.__initMenu() 61 62 return None, True 63 64 def deactivate(self): 65 """ 66 Public method to deactivate this plugin. 67 """ 68 menu = self.__ui.getMenu("wizards") 69 if menu: 70 menu.removeAction(self.qFileDialogAction) 71 menu.removeAction(self.e5FileDialogAction) 72 self.__ui.removeE5Actions( 73 [self.qFileDialogAction, self.e5FileDialogAction], 74 'wizards') 75 76 def __initActions(self): 77 """ 78 Private method to initialize the actions. 79 """ 80 self.qFileDialogAction = E5Action( 81 self.tr('QFileDialog Wizard'), 82 self.tr('Q&FileDialog Wizard...'), 0, 0, self, 83 'wizards_qfiledialog') 84 self.qFileDialogAction.setStatusTip(self.tr('QFileDialog Wizard')) 85 self.qFileDialogAction.setWhatsThis(self.tr( 86 """<b>QFileDialog Wizard</b>""" 87 """<p>This wizard opens a dialog for entering all the parameters""" 88 """ needed to create a QFileDialog. The generated code is""" 89 """ inserted at the current cursor position.</p>""" 90 )) 91 self.qFileDialogAction.triggered.connect(self.__handleQFileDialog) 92 93 self.e5FileDialogAction = E5Action( 94 self.tr('E5FileDialog Wizard'), 95 self.tr('E&5FileDialog Wizard...'), 0, 0, self, 96 'wizards_e5filedialog') 97 self.e5FileDialogAction.setStatusTip(self.tr('E5FileDialog Wizard')) 98 self.e5FileDialogAction.setWhatsThis(self.tr( 99 """<b>E5FileDialog Wizard</b>""" 100 """<p>This wizard opens a dialog for entering all the parameters""" 101 """ needed to create an E5FileDialog. The generated code is""" 102 """ inserted at the current cursor position.</p>""" 103 )) 104 self.e5FileDialogAction.triggered.connect(self.__handleE5FileDialog) 105 106 self.__ui.addE5Actions( 107 [self.qFileDialogAction, self.e5FileDialogAction], 108 'wizards') 109 110 def __initMenu(self): 111 """ 112 Private method to add the actions to the right menu. 113 """ 114 menu = self.__ui.getMenu("wizards") 115 if menu: 116 menu.addAction(self.e5FileDialogAction) 117 menu.addAction(self.qFileDialogAction) 118 119 def __callForm(self, editor, variant): 120 """ 121 Private method to display a dialog and get the code. 122 123 @param editor reference to the current editor 124 @type Editor 125 @param variant variant of code to be generated 126 (-1 = E5FileDialog, 0 = unknown, 5 = PyQt5) 127 @type int 128 @return the generated code (string) 129 """ 130 from WizardPlugins.FileDialogWizard.FileDialogWizardDialog import ( 131 FileDialogWizardDialog 132 ) 133 dlg = FileDialogWizardDialog(variant, None) 134 if dlg.exec() == QDialog.DialogCode.Accepted: 135 line, index = editor.getCursorPosition() 136 indLevel = editor.indentation(line) // editor.indentationWidth() 137 if editor.indentationsUseTabs(): 138 indString = '\t' 139 else: 140 indString = editor.indentationWidth() * ' ' 141 return (dlg.getCode(indLevel, indString), 1) 142 else: 143 return (None, 0) 144 145 def __handle(self, variant): 146 """ 147 Private method to handle the wizards action. 148 149 @param variant dialog variant to be generated 150 (E5FileDialog or QFileDialog) 151 @type str 152 @exception ValueError raised to indicate an illegal file dialog variant 153 """ 154 editor = e5App().getObject("ViewManager").activeWindow() 155 156 if editor is None: 157 E5MessageBox.critical( 158 self.__ui, 159 self.tr('No current editor'), 160 self.tr('Please open or create a file first.')) 161 else: 162 if variant not in ("QFileDialog", "E5FileDialog"): 163 raise ValueError("Illegal dialog variant given") 164 165 if variant == "QFileDialog": 166 match = self.__pyqtRe.search(editor.text()) 167 if match is None: 168 # unknown 169 dialogVariant = 0 170 else: 171 # PyQt5/PyQt6 172 dialogVariant = int(match.group(1)) 173 else: 174 # E5FileDialog 175 dialogVariant = -1 176 177 code, ok = self.__callForm(editor, dialogVariant) 178 if ok: 179 line, index = editor.getCursorPosition() 180 # It should be done on this way to allow undo 181 editor.beginUndoAction() 182 editor.insertAt(code, line, index) 183 editor.endUndoAction() 184 185 def __handleQFileDialog(self): 186 """ 187 Private slot to handle the wizard QFileDialog action. 188 """ 189 self.__handle("QFileDialog") 190 191 def __handleE5FileDialog(self): 192 """ 193 Private slot to handle the wizard E5FileDialog action. 194 """ 195 self.__handle("E5FileDialog") 196