PluginProjectFlask.py

branch
eric7
changeset 70
22e1d0f69668
parent 67
ca1f40d179ce
child 72
4557829a4acf
equal deleted inserted replaced
69:c31a4f756a04 70:22e1d0f69668
28 deactivateable = True 28 deactivateable = True
29 version = "10.0.0" 29 version = "10.0.0"
30 className = "ProjectFlaskPlugin" 30 className = "ProjectFlaskPlugin"
31 packageName = "ProjectFlask" 31 packageName = "ProjectFlask"
32 shortDescription = "Project support for Flask projects." 32 shortDescription = "Project support for Flask projects."
33 longDescription = ( 33 longDescription = """This plugin implements project support for Flask projects."""
34 """This plugin implements project support for Flask projects."""
35 )
36 needsRestart = False 34 needsRestart = False
37 pyqtApi = 2 35 pyqtApi = 2
38 # End-of-Header 36 # End-of-Header
39 37
40 error = "" 38 error = ""
43 41
44 42
45 def apiFiles(language): 43 def apiFiles(language):
46 """ 44 """
47 Module function to return the API files made available by this plugin. 45 Module function to return the API files made available by this plugin.
48 46
49 @param language language to get APIs for 47 @param language language to get APIs for
50 @type str 48 @type str
51 @return list of API filenames 49 @return list of API filenames
52 @rtype list of str 50 @rtype list of str
53 """ 51 """
54 if language in ["Python3"]: 52 if language in ["Python3"]:
55 apisDir = os.path.join(os.path.dirname(__file__), 53 apisDir = os.path.join(os.path.dirname(__file__), "ProjectFlask", "APIs")
56 "ProjectFlask", "APIs") 54 apis = glob.glob(os.path.join(apisDir, "*.api"))
57 apis = glob.glob(os.path.join(apisDir, '*.api'))
58 else: 55 else:
59 apis = [] 56 apis = []
60 return apis 57 return apis
61 58
62 59
63 def createFlaskPage(configDlg): 60 def createFlaskPage(configDlg):
64 """ 61 """
65 Module function to create the Flask configuration page. 62 Module function to create the Flask configuration page.
66 63
67 @param configDlg reference to the configuration dialog 64 @param configDlg reference to the configuration dialog
68 @type ConfigurationWidget 65 @type ConfigurationWidget
69 @return reference to the configuration page 66 @return reference to the configuration page
70 @rtype FlaskPage 67 @rtype FlaskPage
71 """ 68 """
72 global flaskPluginObject 69 global flaskPluginObject
73 from ProjectFlask.ConfigurationPage.FlaskPage import FlaskPage 70 from ProjectFlask.ConfigurationPage.FlaskPage import FlaskPage
71
74 page = FlaskPage(flaskPluginObject) 72 page = FlaskPage(flaskPluginObject)
75 return page 73 return page
76 74
77 75
78 def getConfigData(): 76 def getConfigData():
79 """ 77 """
80 Module function returning data as required by the configuration dialog. 78 Module function returning data as required by the configuration dialog.
81 79
82 @return dictionary containing the relevant data 80 @return dictionary containing the relevant data
83 @rtype dict 81 @rtype dict
84 """ 82 """
85 usesDarkPalette = ericApp().usesDarkPalette() 83 usesDarkPalette = ericApp().usesDarkPalette()
86 iconSuffix = "dark" if usesDarkPalette else "light" 84 iconSuffix = "dark" if usesDarkPalette else "light"
87 85
88 return { 86 return {
89 "flaskPage": [ 87 "flaskPage": [
90 QCoreApplication.translate("ProjectFlaskPlugin", "Flask"), 88 QCoreApplication.translate("ProjectFlaskPlugin", "Flask"),
91 os.path.join("ProjectFlask", "icons", 89 os.path.join("ProjectFlask", "icons", "flask-{0}".format(iconSuffix)),
92 "flask-{0}".format(iconSuffix)), 90 createFlaskPage,
93 createFlaskPage, None, None], 91 None,
92 None,
93 ],
94 } 94 }
95 95
96 96
97 def prepareUninstall(): 97 def prepareUninstall():
98 """ 98 """
105 105
106 class ProjectFlaskPlugin(QObject): 106 class ProjectFlaskPlugin(QObject):
107 """ 107 """
108 Class implementing the Flask project plugin. 108 Class implementing the Flask project plugin.
109 """ 109 """
110
110 PreferencesKey = "Flask" 111 PreferencesKey = "Flask"
111 112
112 lexerAssociations = { 113 lexerAssociations = {
113 "*.htm": "Pygments|HTML+Django/Jinja", 114 "*.htm": "Pygments|HTML+Django/Jinja",
114 "*.html": "Pygments|HTML+Django/Jinja", 115 "*.html": "Pygments|HTML+Django/Jinja",
115 } 116 }
116 117
117 def __init__(self, ui): 118 def __init__(self, ui):
118 """ 119 """
119 Constructor 120 Constructor
120 121
121 @param ui reference to the user interface object 122 @param ui reference to the user interface object
122 @type UserInterface 123 @type UserInterface
123 """ 124 """
124 QObject.__init__(self, ui) 125 QObject.__init__(self, ui)
125 self.__ui = ui 126 self.__ui = ui
126 self.__initialize() 127 self.__initialize()
127 128
128 self.__defaults = { 129 self.__defaults = {
129 "VirtualEnvironmentNamePy3": "", 130 "VirtualEnvironmentNamePy3": "",
130
131 "FlaskDocUrl": "https://flask.palletsprojects.com", 131 "FlaskDocUrl": "https://flask.palletsprojects.com",
132
133 "TranslationsEditor": "", 132 "TranslationsEditor": "",
134
135 "UseExternalBrowser": False, 133 "UseExternalBrowser": False,
136 } 134 }
137 if isWindowsPlatform(): 135 if isWindowsPlatform():
138 self.__defaults["AnsiColorScheme"] = "Windows 10" 136 self.__defaults["AnsiColorScheme"] = "Windows 10"
139 self.__defaults["ConsoleCommand"] = "cmd.exe /c" 137 self.__defaults["ConsoleCommand"] = "cmd.exe /c"
141 self.__defaults["AnsiColorScheme"] = "xterm" 139 self.__defaults["AnsiColorScheme"] = "xterm"
142 self.__defaults["ConsoleCommand"] = "xterm -e" 140 self.__defaults["ConsoleCommand"] = "xterm -e"
143 else: 141 else:
144 self.__defaults["AnsiColorScheme"] = "Ubuntu" 142 self.__defaults["AnsiColorScheme"] = "Ubuntu"
145 self.__defaults["ConsoleCommand"] = "konsole -e" 143 self.__defaults["ConsoleCommand"] = "konsole -e"
146 144
147 self.__translator = None 145 self.__translator = None
148 self.__loadTranslator() 146 self.__loadTranslator()
149 147
150 def __initialize(self): 148 def __initialize(self):
151 """ 149 """
152 Private slot to (re)initialize the plugin. 150 Private slot to (re)initialize the plugin.
153 """ 151 """
154 self.__object = None 152 self.__object = None
155 153
156 self.__mainMenu = None 154 self.__mainMenu = None
157 self.__mainAct = None 155 self.__mainAct = None
158 self.__separatorAct = None 156 self.__separatorAct = None
159 157
160 self.__ericProject = ericApp().getObject("Project") 158 self.__ericProject = ericApp().getObject("Project")
161 159
162 self.__supportedVariants = [] 160 self.__supportedVariants = []
163 161
164 def activate(self): 162 def activate(self):
165 """ 163 """
166 Public method to activate this plugin. 164 Public method to activate this plugin.
167 165
168 @return tuple of None and activation status 166 @return tuple of None and activation status
169 @rtype tuple of (None, bool) 167 @rtype tuple of (None, bool)
170 """ 168 """
171 global flaskPluginObject 169 global flaskPluginObject
172 flaskPluginObject = self 170 flaskPluginObject = self
173 171
174 usesDarkPalette = ericApp().usesDarkPalette() 172 usesDarkPalette = ericApp().usesDarkPalette()
175 iconSuffix = "dark" if usesDarkPalette else "light" 173 iconSuffix = "dark" if usesDarkPalette else "light"
176 174
177 self.__object = Project(self, iconSuffix, self.__ui) 175 self.__object = Project(self, iconSuffix, self.__ui)
178 self.__object.initActions() 176 self.__object.initActions()
179 ericApp().registerPluginObject("ProjectFlask", self.__object) 177 ericApp().registerPluginObject("ProjectFlask", self.__object)
180 178
181 self.__mainMenu = self.__object.initMenu() 179 self.__mainMenu = self.__object.initMenu()
182 180
183 self.__supportedVariants = self.__object.supportedPythonVariants() 181 self.__supportedVariants = self.__object.supportedPythonVariants()
184 182
185 if self.__supportedVariants: 183 if self.__supportedVariants:
186 self.__ericProject.registerProjectType( 184 self.__ericProject.registerProjectType(
187 "Flask", self.tr("Flask"), 185 "Flask",
186 self.tr("Flask"),
188 self.fileTypesCallback, 187 self.fileTypesCallback,
189 lexerAssociationCallback=self.lexerAssociationCallback, 188 lexerAssociationCallback=self.lexerAssociationCallback,
190 binaryTranslationsCallback=self.binaryTranslationsCallback, 189 binaryTranslationsCallback=self.binaryTranslationsCallback,
191 progLanguages=self.__supportedVariants[:]) 190 progLanguages=self.__supportedVariants[:],
192 191 )
192
193 from Project.ProjectBrowser import ( 193 from Project.ProjectBrowser import (
194 SourcesBrowserFlag, FormsBrowserFlag, TranslationsBrowserFlag, 194 SourcesBrowserFlag,
195 OthersBrowserFlag 195 FormsBrowserFlag,
196 ) 196 TranslationsBrowserFlag,
197 OthersBrowserFlag,
198 )
199
197 Preferences.setProjectBrowserFlagsDefault( 200 Preferences.setProjectBrowserFlagsDefault(
198 "Flask", 201 "Flask",
199 SourcesBrowserFlag | FormsBrowserFlag | 202 SourcesBrowserFlag
200 TranslationsBrowserFlag | OthersBrowserFlag, 203 | FormsBrowserFlag
201 ) 204 | TranslationsBrowserFlag
202 205 | OthersBrowserFlag,
206 )
207
203 if self.__ericProject.isOpen(): 208 if self.__ericProject.isOpen():
204 self.__projectOpened() 209 self.__projectOpened()
205 self.__object.projectOpenedHooks() 210 self.__object.projectOpenedHooks()
206 211
207 ericApp().getObject("Project").projectOpened.connect( 212 ericApp().getObject("Project").projectOpened.connect(self.__projectOpened)
208 self.__projectOpened) 213 ericApp().getObject("Project").projectClosed.connect(self.__projectClosed)
209 ericApp().getObject("Project").projectClosed.connect( 214 ericApp().getObject("Project").newProject.connect(self.__projectOpened)
210 self.__projectClosed) 215
211 ericApp().getObject("Project").newProject.connect(
212 self.__projectOpened)
213
214 ericApp().getObject("Project").projectOpenedHooks.connect( 216 ericApp().getObject("Project").projectOpenedHooks.connect(
215 self.__object.projectOpenedHooks) 217 self.__object.projectOpenedHooks
218 )
216 ericApp().getObject("Project").projectClosedHooks.connect( 219 ericApp().getObject("Project").projectClosedHooks.connect(
217 self.__object.projectClosedHooks) 220 self.__object.projectClosedHooks
221 )
218 ericApp().getObject("Project").newProjectHooks.connect( 222 ericApp().getObject("Project").newProjectHooks.connect(
219 self.__object.projectOpenedHooks) 223 self.__object.projectOpenedHooks
220 224 )
225
221 return None, True 226 return None, True
222 227
223 def deactivate(self): 228 def deactivate(self):
224 """ 229 """
225 Public method to deactivate this plugin. 230 Public method to deactivate this plugin.
226 """ 231 """
227 ericApp().unregisterPluginObject("ProjectFlask") 232 ericApp().unregisterPluginObject("ProjectFlask")
228 233
229 ericApp().getObject("Project").projectOpened.disconnect( 234 ericApp().getObject("Project").projectOpened.disconnect(self.__projectOpened)
230 self.__projectOpened) 235 ericApp().getObject("Project").projectClosed.disconnect(self.__projectClosed)
231 ericApp().getObject("Project").projectClosed.disconnect( 236 ericApp().getObject("Project").newProject.disconnect(self.__projectOpened)
232 self.__projectClosed) 237
233 ericApp().getObject("Project").newProject.disconnect(
234 self.__projectOpened)
235
236 ericApp().getObject("Project").projectOpenedHooks.disconnect( 238 ericApp().getObject("Project").projectOpenedHooks.disconnect(
237 self.__object.projectOpenedHooks) 239 self.__object.projectOpenedHooks
240 )
238 ericApp().getObject("Project").projectClosedHooks.disconnect( 241 ericApp().getObject("Project").projectClosedHooks.disconnect(
239 self.__object.projectClosedHooks) 242 self.__object.projectClosedHooks
243 )
240 ericApp().getObject("Project").newProjectHooks.disconnect( 244 ericApp().getObject("Project").newProjectHooks.disconnect(
241 self.__object.projectOpenedHooks) 245 self.__object.projectOpenedHooks
242 246 )
247
243 self.__ericProject.unregisterProjectType("Flask") 248 self.__ericProject.unregisterProjectType("Flask")
244 249
245 self.__object.projectClosedHooks() 250 self.__object.projectClosedHooks()
246 self.__projectClosed() 251 self.__projectClosed()
247 252
248 self.__initialize() 253 self.__initialize()
249 254
250 def __loadTranslator(self): 255 def __loadTranslator(self):
251 """ 256 """
252 Private method to load the translation file. 257 Private method to load the translation file.
253 """ 258 """
254 if self.__ui is not None: 259 if self.__ui is not None:
255 loc = self.__ui.getLocale() 260 loc = self.__ui.getLocale()
256 if loc and loc != "C": 261 if loc and loc != "C":
257 locale_dir = os.path.join( 262 locale_dir = os.path.join(
258 os.path.dirname(__file__), "ProjectFlask", "i18n") 263 os.path.dirname(__file__), "ProjectFlask", "i18n"
264 )
259 translation = "flask_{0}".format(loc) 265 translation = "flask_{0}".format(loc)
260 translator = QTranslator(None) 266 translator = QTranslator(None)
261 loaded = translator.load(translation, locale_dir) 267 loaded = translator.load(translation, locale_dir)
262 if loaded: 268 if loaded:
263 self.__translator = translator 269 self.__translator = translator
264 ericApp().installTranslator(self.__translator) 270 ericApp().installTranslator(self.__translator)
265 else: 271 else:
266 print("Warning: translation file '{0}' could not be" 272 print(
267 " loaded.".format(translation)) 273 "Warning: translation file '{0}' could not be"
274 " loaded.".format(translation)
275 )
268 print("Using default.") 276 print("Using default.")
269 277
270 def __projectOpened(self): 278 def __projectOpened(self):
271 """ 279 """
272 Private slot to handle the projectOpened signal. 280 Private slot to handle the projectOpened signal.
273 """ 281 """
274 if self.__ericProject.getProjectType() == "Flask": 282 if self.__ericProject.getProjectType() == "Flask":
275 projectToolsMenu = self.__ui.getMenu("project_tools") 283 projectToolsMenu = self.__ui.getMenu("project_tools")
276 insertBeforeAct = projectToolsMenu.actions()[0] 284 insertBeforeAct = projectToolsMenu.actions()[0]
277 self.__mainAct = projectToolsMenu.insertMenu( 285 self.__mainAct = projectToolsMenu.insertMenu(
278 insertBeforeAct, self.__mainMenu) 286 insertBeforeAct, self.__mainMenu
279 self.__separatorAct = projectToolsMenu.insertSeparator( 287 )
280 insertBeforeAct) 288 self.__separatorAct = projectToolsMenu.insertSeparator(insertBeforeAct)
281 289
282 def __projectClosed(self): 290 def __projectClosed(self):
283 """ 291 """
284 Private slot to handle the projectClosed signal. 292 Private slot to handle the projectClosed signal.
285 """ 293 """
286 if self.__mainAct is not None: 294 if self.__mainAct is not None:
288 projectToolsMenu.removeAction(self.__separatorAct) 296 projectToolsMenu.removeAction(self.__separatorAct)
289 projectToolsMenu.removeAction(self.__mainAct) 297 projectToolsMenu.removeAction(self.__mainAct)
290 self.__mainAct = None 298 self.__mainAct = None
291 self.__separatorAct = None 299 self.__separatorAct = None
292 self.__object.projectClosed() 300 self.__object.projectClosed()
293 301
294 def fileTypesCallback(self): 302 def fileTypesCallback(self):
295 """ 303 """
296 Public method get the filetype associations of the Django project type. 304 Public method get the filetype associations of the Django project type.
297 305
298 @return dictionary with file type associations 306 @return dictionary with file type associations
299 @rtype dict 307 @rtype dict
300 """ 308 """
301 fileTypes = ( 309 fileTypes = (
302 {"*.py": "SOURCES", 310 {
303 "*.js": "SOURCES", 311 "*.py": "SOURCES",
304 "*.html": "FORMS", 312 "*.js": "SOURCES",
305 "*.htm": "FORMS", 313 "*.html": "FORMS",
306 "*.pot": "TRANSLATIONS", 314 "*.htm": "FORMS",
307 "*.po": "TRANSLATIONS", 315 "*.pot": "TRANSLATIONS",
308 "*.mo": "TRANSLATIONS", } 316 "*.po": "TRANSLATIONS",
309 if self.__ericProject.getProjectType() == "Flask" else 317 "*.mo": "TRANSLATIONS",
310 {} 318 }
319 if self.__ericProject.getProjectType() == "Flask"
320 else {}
311 ) 321 )
312 return fileTypes 322 return fileTypes
313 323
314 def lexerAssociationCallback(self, filename): 324 def lexerAssociationCallback(self, filename):
315 """ 325 """
316 Public method to get the lexer association of the Django project type 326 Public method to get the lexer association of the Django project type
317 for a file. 327 for a file.
318 328
319 @param filename name of the file 329 @param filename name of the file
320 @type str 330 @type str
321 @return name of the lexer (Pygments lexers are prefixed with 331 @return name of the lexer (Pygments lexers are prefixed with
322 'Pygments|') 332 'Pygments|')
323 @rtype str 333 @rtype str
324 """ 334 """
325 for pattern, language in self.lexerAssociations.items(): 335 for pattern, language in self.lexerAssociations.items():
326 if fnmatch.fnmatch(filename, pattern): 336 if fnmatch.fnmatch(filename, pattern):
327 return language 337 return language
328 338
329 return "" 339 return ""
330 340
331 def binaryTranslationsCallback(self, filename): 341 def binaryTranslationsCallback(self, filename):
332 """ 342 """
333 Public method to determine the filename of a compiled translation file 343 Public method to determine the filename of a compiled translation file
334 given the translation source file. 344 given the translation source file.
335 345
336 @param filename name of the translation source file 346 @param filename name of the translation source file
337 @type str 347 @type str
338 @return name of the binary translation file 348 @return name of the binary translation file
339 @rtype str 349 @rtype str
340 """ 350 """
341 if filename.endswith(".po"): 351 if filename.endswith(".po"):
342 return filename.replace(".po", ".mo") 352 return filename.replace(".po", ".mo")
343 353
344 return filename 354 return filename
345 355
346 def getDefaultPreference(self, key): 356 def getDefaultPreference(self, key):
347 """ 357 """
348 Public method to get the default value for a setting. 358 Public method to get the default value for a setting.
349 359
350 @param key the key of the value to get 360 @param key the key of the value to get
351 @type str 361 @type str
352 @return the requested setting 362 @return the requested setting
353 @rtype any 363 @rtype any
354 """ 364 """
355 return self.__defaults[key] 365 return self.__defaults[key]
356 366
357 def getPreferences(self, key): 367 def getPreferences(self, key):
358 """ 368 """
359 Public method to retrieve the various settings. 369 Public method to retrieve the various settings.
360 370
361 @param key the key of the value to get 371 @param key the key of the value to get
362 @type str 372 @type str
363 @return the requested setting 373 @return the requested setting
364 @rtype any 374 @rtype any
365 """ 375 """
366 if key in ["UseExternalBrowser"]: 376 if key in ["UseExternalBrowser"]:
367 return Preferences.toBool(Preferences.Prefs.settings.value( 377 return Preferences.toBool(
368 self.PreferencesKey + "/" + key, self.__defaults[key])) 378 Preferences.Prefs.settings.value(
379 self.PreferencesKey + "/" + key, self.__defaults[key]
380 )
381 )
369 else: 382 else:
370 return Preferences.Prefs.settings.value( 383 return Preferences.Prefs.settings.value(
371 self.PreferencesKey + "/" + key, self.__defaults[key]) 384 self.PreferencesKey + "/" + key, self.__defaults[key]
372 385 )
386
373 def setPreferences(self, key, value): 387 def setPreferences(self, key, value):
374 """ 388 """
375 Public method to store the various settings. 389 Public method to store the various settings.
376 390
377 @param key the key of the setting to be set 391 @param key the key of the setting to be set
378 @type str 392 @type str
379 @param value the value to be set 393 @param value the value to be set
380 @type any 394 @type any
381 """ 395 """
382 Preferences.Prefs.settings.setValue( 396 Preferences.Prefs.settings.setValue(self.PreferencesKey + "/" + key, value)
383 self.PreferencesKey + "/" + key, value) 397
384
385 if key in ["VirtualEnvironmentNamePy3"]: 398 if key in ["VirtualEnvironmentNamePy3"]:
386 self.__reregisterProjectType() 399 self.__reregisterProjectType()
387 400
388 def __reregisterProjectType(self): 401 def __reregisterProjectType(self):
389 """ 402 """
390 Private method to re-register the project type. 403 Private method to re-register the project type.
391 """ 404 """
392 supportedVariants = self.__object.supportedPythonVariants() 405 supportedVariants = self.__object.supportedPythonVariants()
393 if supportedVariants != self.__supportedVariants: 406 if supportedVariants != self.__supportedVariants:
394 # step 1: unregister 407 # step 1: unregister
395 self.__ericProject.unregisterProjectType("Flask") 408 self.__ericProject.unregisterProjectType("Flask")
396 409
397 # step 2: register again with new language settings 410 # step 2: register again with new language settings
398 self.__supportedVariants = supportedVariants 411 self.__supportedVariants = supportedVariants
399 if self.__supportedVariants: 412 if self.__supportedVariants:
400 self.__ericProject.registerProjectType( 413 self.__ericProject.registerProjectType(
401 "Flask", 414 "Flask",
402 self.tr("Flask"), self.fileTypesCallback, 415 self.tr("Flask"),
416 self.fileTypesCallback,
403 lexerAssociationCallback=self.lexerAssociationCallback, 417 lexerAssociationCallback=self.lexerAssociationCallback,
404 binaryTranslationsCallback=self.binaryTranslationsCallback, 418 binaryTranslationsCallback=self.binaryTranslationsCallback,
405 progLanguages=self.__supportedVariants[:]) 419 progLanguages=self.__supportedVariants[:],
406 420 )
421
407 def getMenu(self, name): 422 def getMenu(self, name):
408 """ 423 """
409 Public method to get a reference to the requested menu. 424 Public method to get a reference to the requested menu.
410 425
411 @param name name of the menu 426 @param name name of the menu
412 @type str 427 @type str
413 @return reference to the menu or None, if no 428 @return reference to the menu or None, if no
414 menu with the given name exists 429 menu with the given name exists
415 @rtype QMenu or None 430 @rtype QMenu or None
416 """ 431 """
417 if self.__object is not None: 432 if self.__object is not None:
418 return self.__object.getMenu(name) 433 return self.__object.getMenu(name)
419 else: 434 else:
420 return None 435 return None
421 436
422 def getMenuNames(self): 437 def getMenuNames(self):
423 """ 438 """
424 Public method to get the names of all menus. 439 Public method to get the names of all menus.
425 440
426 @return menu names 441 @return menu names
427 @rtype list of str 442 @rtype list of str
428 """ 443 """
429 if self.__object is not None: 444 if self.__object is not None:
430 return list(self.__menus.keys()) 445 return list(self.__menus.keys())
431 else: 446 else:
432 return [] 447 return []
433 448
449
434 # 450 #
435 # eflag: noqa = M801 451 # eflag: noqa = M801

eric ide

mercurial