|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2014 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the Web project plugin. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 import os |
|
13 |
|
14 from PyQt5.QtCore import QObject, QTranslator |
|
15 from PyQt5.QtWidgets import QMenu |
|
16 |
|
17 from E5Gui.E5Application import e5App |
|
18 |
|
19 import Preferences |
|
20 |
|
21 try: |
|
22 from bs4 import BeautifulSoup # __IGNORE_EXCEPTION__ |
|
23 BeautifulSoupAvailable = True |
|
24 except ImportError: |
|
25 BeautifulSoup = None |
|
26 BeautifulSoupAvailable = False |
|
27 |
|
28 # Start-Of-Header |
|
29 name = "PluginProjectWeb" |
|
30 author = "Detlev Offenbach <detlev@die-offenbachs.de>" |
|
31 autoactivate = True |
|
32 deactivateable = True |
|
33 version = "0.1.0" |
|
34 className = "ProjectWebPlugin" |
|
35 packageName = "ProjectWeb" |
|
36 shortDescription = "Support for Web projects and web related tools." |
|
37 longDescription = ( |
|
38 """This plug-in provides support for ordinary web projects and some web""" |
|
39 """ related tools.\n\nIt requires BeautifulSoup4 for some of its""" |
|
40 """ functionality.""" |
|
41 ) |
|
42 needsRestart = False |
|
43 pyqtApi = 2 |
|
44 python2Compatible = True |
|
45 # End-Of-Header |
|
46 |
|
47 error = "" |
|
48 |
|
49 |
|
50 class ProjectWebPlugin(QObject): |
|
51 """ |
|
52 Class implementing the Web project plugin. |
|
53 """ |
|
54 def __init__(self, ui): |
|
55 """ |
|
56 Constructor |
|
57 |
|
58 @param ui reference to the user interface object (UI.UserInterface) |
|
59 """ |
|
60 super(ProjectWebPlugin, self).__init__(ui) |
|
61 self.__ui = ui |
|
62 self.__initialize() |
|
63 |
|
64 self.__translator = None |
|
65 self.__loadTranslator() |
|
66 |
|
67 self.__initMenu() |
|
68 |
|
69 def __initialize(self): |
|
70 """ |
|
71 Private slot to (re)initialize the plugin. |
|
72 """ |
|
73 self.__e5project = e5App().getObject("Project") |
|
74 |
|
75 self.__editors = {} |
|
76 |
|
77 def activate(self): |
|
78 """ |
|
79 Public method to activate this plugin. |
|
80 |
|
81 @return tuple of None and activation status (boolean) |
|
82 """ |
|
83 global error |
|
84 error = "" # clear previous error |
|
85 |
|
86 if self.__ui.versionIsNewer('6.0.0', '20141229'): |
|
87 self.__e5project.registerProjectType( |
|
88 "Web", self.tr("Web"), |
|
89 self.fileTypesCallback, progLanguages=["JavaScript"]) |
|
90 else: |
|
91 self.__e5project.registerProjectType( |
|
92 "Web", self.tr("Web"), |
|
93 self.fileTypesCallback) |
|
94 |
|
95 from Project.ProjectBrowser import SourcesBrowserFlag, \ |
|
96 FormsBrowserFlag, OthersBrowserFlag |
|
97 Preferences.setProjectBrowserFlagsDefault( |
|
98 "Web", |
|
99 SourcesBrowserFlag | FormsBrowserFlag | OthersBrowserFlag, |
|
100 ) |
|
101 |
|
102 self.__ui.showMenu.connect(self.__populateMenu) |
|
103 |
|
104 e5App().getObject("ViewManager").editorOpenedEd.connect( |
|
105 self.__editorOpened) |
|
106 e5App().getObject("ViewManager").editorClosedEd.connect( |
|
107 self.__editorClosed) |
|
108 |
|
109 for editor in e5App().getObject("ViewManager").getOpenEditors(): |
|
110 self.__editorOpened(editor) |
|
111 |
|
112 return None, True |
|
113 |
|
114 def deactivate(self): |
|
115 """ |
|
116 Public method to deactivate this plugin. |
|
117 """ |
|
118 self.__e5project.unregisterProjectType("Django") |
|
119 |
|
120 self.__ui.showMenu.disconnect(self.__populateMenu) |
|
121 |
|
122 e5App().getObject("ViewManager").editorOpenedEd.disconnect( |
|
123 self.__editorOpened) |
|
124 e5App().getObject("ViewManager").editorClosedEd.disconnect( |
|
125 self.__editorClosed) |
|
126 |
|
127 for editor, acts in self.__editors.items(): |
|
128 ## editor.showMenu.disconnect(self.__editorShowMenu) |
|
129 menu = editor.getMenu("Tools") |
|
130 if menu is not None: |
|
131 for act in acts: |
|
132 menu.removeAction(act) |
|
133 |
|
134 self.__initialize() |
|
135 |
|
136 def __loadTranslator(self): |
|
137 """ |
|
138 Private method to load the translation file. |
|
139 """ |
|
140 if self.__ui is not None: |
|
141 loc = self.__ui.getLocale() |
|
142 if loc and loc != "C": |
|
143 locale_dir = os.path.join( |
|
144 os.path.dirname(__file__), "ProjectWeb", "i18n") |
|
145 translation = "web_%s" % loc |
|
146 translator = QTranslator(None) |
|
147 loaded = translator.load(translation, locale_dir) |
|
148 if loaded: |
|
149 self.__translator = translator |
|
150 e5App().installTranslator(self.__translator) |
|
151 else: |
|
152 print("Warning: translation file '{0}' could not be" |
|
153 " loaded.".format(translation)) |
|
154 print("Using default.") |
|
155 |
|
156 def fileTypesCallback(self): |
|
157 """ |
|
158 Public method to get the filetype associations of the Web project type. |
|
159 |
|
160 @return dictionary with file type associations |
|
161 """ |
|
162 if self.__e5project.getProjectType() == "Web": |
|
163 fileTypes = { |
|
164 "*.html": "FORMS", |
|
165 "*.htm": "FORMS", |
|
166 "*.js": "SOURCES", |
|
167 } |
|
168 else: |
|
169 fileTypes = {} |
|
170 return fileTypes |
|
171 |
|
172 def __initMenu(self): |
|
173 """ |
|
174 Private method to initialize the web tools menu. |
|
175 """ |
|
176 self.__menu = QMenu(self.tr("Web")) |
|
177 |
|
178 # TODO: add our actions here |
|
179 self.__html5ToCss3Act = self.__menu.addAction(self.tr( |
|
180 "HTML5 to CSS3"), self.__htm5ToCss3) |
|
181 |
|
182 self.__menu.aboutToShow.connect(self.__menuAboutToShow) |
|
183 |
|
184 def __menuAboutToShow(self): |
|
185 """ |
|
186 Private slot to prepare the menu before it is shown. |
|
187 """ |
|
188 editor = e5App().getObject("ViewManager").activeWindow() |
|
189 selectionAvailable = bool(editor and editor.selectedText() != "") |
|
190 |
|
191 self.__html5ToCss3Act.setEnabled( |
|
192 selectionAvailable and BeautifulSoupAvailable) |
|
193 |
|
194 def __populateMenu(self, name, menu): |
|
195 """ |
|
196 Private slot to populate the tools menu with our entries. |
|
197 |
|
198 @param name name of the menu (string) |
|
199 @param menu reference to the menu to be populated (QMenu) |
|
200 """ |
|
201 if name != "Tools": |
|
202 return |
|
203 |
|
204 ## editor = e5App().getObject("ViewManager").activeWindow() |
|
205 ## |
|
206 if not menu.isEmpty(): |
|
207 menu.addSeparator() |
|
208 |
|
209 act = menu.addMenu(self.__menu) |
|
210 # TODO: check this |
|
211 ## act.setEnabled(editor is not None and editor.selectedText() != '') |
|
212 |
|
213 def __editorOpened(self, editor): |
|
214 """ |
|
215 Private slot called, when a new editor was opened. |
|
216 |
|
217 @param editor reference to the new editor (QScintilla.Editor) |
|
218 """ |
|
219 menu = editor.getMenu("Tools") |
|
220 if menu is not None: |
|
221 self.__editors[editor] = [] |
|
222 if not menu.isEmpty(): |
|
223 act = menu.addSeparator() |
|
224 self.__editors[editor].append(act) |
|
225 act = menu.addMenu(self.__menu) |
|
226 self.__editors[editor].append(act) |
|
227 ## editor.showMenu.connect(self.__editorShowMenu) |
|
228 |
|
229 def __editorClosed(self, editor): |
|
230 """ |
|
231 Private slot called, when an editor was closed. |
|
232 |
|
233 @param editor reference to the editor (QScintilla.Editor) |
|
234 """ |
|
235 try: |
|
236 del self.__editors[editor] |
|
237 except KeyError: |
|
238 pass |
|
239 |
|
240 ## def __editorShowMenu(self, menuName, menu, editor): |
|
241 ## """ |
|
242 ## Private slot called, when the the editor context menu or a submenu is |
|
243 ## about to be shown. |
|
244 ## |
|
245 ## @param menuName name of the menu to be shown (string) |
|
246 ## @param menu reference to the menu (QMenu) |
|
247 ## @param editor reference to the editor |
|
248 ## """ |
|
249 ## if menuName == "Tools": |
|
250 ## # TODO: check this |
|
251 ## self.__menu.setEnabled(editor.selectedText() != '') |
|
252 ## |
|
253 def __htm5ToCss3(self): |
|
254 """ |
|
255 Private slot handling the HTML5 to CSS3 conversion. |
|
256 """ |
|
257 # TODO: implement this |
|
258 from ProjectWeb.Html5ToCss3Converter import Html5ToCss3Converter |
|
259 vm = e5App().getObject("ViewManager") |
|
260 editor = vm.activeWindow() |
|
261 html = editor.selectedText() |
|
262 |
|
263 converter = Html5ToCss3Converter(html) |
|
264 |
|
265 css3 = converter.getCss3() |
|
266 |
|
267 if css3: |
|
268 vm.newEditor() |
|
269 newEditor = vm.activeWindow() |
|
270 newEditor.setText(css3) |
|
271 newEditor.setLanguage("dummy.css") |