src/eric7/Project/ProjectResourcesBrowser.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
17 from EricWidgets.EricApplication import ericApp 17 from EricWidgets.EricApplication import ericApp
18 from EricWidgets import EricMessageBox, EricFileDialog 18 from EricWidgets import EricMessageBox, EricFileDialog
19 from EricWidgets.EricProgressDialog import EricProgressDialog 19 from EricWidgets.EricProgressDialog import EricProgressDialog
20 20
21 from .ProjectBrowserModel import ( 21 from .ProjectBrowserModel import (
22 ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem, 22 ProjectBrowserFileItem,
23 ProjectBrowserDirectoryItem, ProjectBrowserResourceType 23 ProjectBrowserSimpleDirectoryItem,
24 ProjectBrowserDirectoryItem,
25 ProjectBrowserResourceType,
24 ) 26 )
25 from .ProjectBaseBrowser import ProjectBaseBrowser 27 from .ProjectBaseBrowser import ProjectBaseBrowser
26 28
27 import UI.PixmapCache 29 import UI.PixmapCache
28 from UI.NotificationWidget import NotificationTypes 30 from UI.NotificationWidget import NotificationTypes
32 34
33 35
34 class ProjectResourcesBrowser(ProjectBaseBrowser): 36 class ProjectResourcesBrowser(ProjectBaseBrowser):
35 """ 37 """
36 A class used to display the resources part of the project. 38 A class used to display the resources part of the project.
37 39
38 @signal appendStderr(str) emitted after something was received from 40 @signal appendStderr(str) emitted after something was received from
39 a QProcess on stderr 41 a QProcess on stderr
40 @signal showMenu(str, QMenu) emitted when a menu is about to be shown. 42 @signal showMenu(str, QMenu) emitted when a menu is about to be shown.
41 The name of the menu and a reference to the menu are given. 43 The name of the menu and a reference to the menu are given.
42 """ 44 """
45
43 appendStderr = pyqtSignal(str) 46 appendStderr = pyqtSignal(str)
44 showMenu = pyqtSignal(str, QMenu) 47 showMenu = pyqtSignal(str, QMenu)
45 48
46 RCFilenameFormatPython = "{0}_rc.py" 49 RCFilenameFormatPython = "{0}_rc.py"
47 RCFilenameFormatRuby = "{0}_rc.rb" 50 RCFilenameFormatRuby = "{0}_rc.rb"
48 51
49 def __init__(self, project, parent=None): 52 def __init__(self, project, parent=None):
50 """ 53 """
51 Constructor 54 Constructor
52 55
53 @param project reference to the project object 56 @param project reference to the project object
54 @param parent parent widget of this browser (QWidget) 57 @param parent parent widget of this browser (QWidget)
55 """ 58 """
56 ProjectBaseBrowser.__init__(self, project, ProjectBrowserResourceType, 59 ProjectBaseBrowser.__init__(self, project, ProjectBrowserResourceType, parent)
57 parent) 60
58 61 self.selectedItemsFilter = [
59 self.selectedItemsFilter = [ProjectBrowserFileItem, 62 ProjectBrowserFileItem,
60 ProjectBrowserSimpleDirectoryItem] 63 ProjectBrowserSimpleDirectoryItem,
61 64 ]
62 self.setWindowTitle(self.tr('Resources')) 65
63 66 self.setWindowTitle(self.tr("Resources"))
64 self.setWhatsThis(self.tr( 67
65 """<b>Project Resources Browser</b>""" 68 self.setWhatsThis(
66 """<p>This allows to easily see all resources contained in the""" 69 self.tr(
67 """ current project. Several actions can be executed via the""" 70 """<b>Project Resources Browser</b>"""
68 """ context menu.</p>""" 71 """<p>This allows to easily see all resources contained in the"""
69 )) 72 """ current project. Several actions can be executed via the"""
70 73 """ context menu.</p>"""
74 )
75 )
76
71 self.compileProc = None 77 self.compileProc = None
72 78
73 def _createPopupMenus(self): 79 def _createPopupMenus(self):
74 """ 80 """
75 Protected overloaded method to generate the popup menu. 81 Protected overloaded method to generate the popup menu.
76 """ 82 """
77 self.menuActions = [] 83 self.menuActions = []
78 self.multiMenuActions = [] 84 self.multiMenuActions = []
79 self.dirMenuActions = [] 85 self.dirMenuActions = []
80 self.dirMultiMenuActions = [] 86 self.dirMultiMenuActions = []
81 87
82 self.menu = QMenu(self) 88 self.menu = QMenu(self)
83 if self.project.getProjectType() in [ 89 if self.project.getProjectType() in [
84 "PyQt5", "PyQt5C", 90 "PyQt5",
85 "PySide2", "PySide2C", "PySide6", "PySide6C" 91 "PyQt5C",
92 "PySide2",
93 "PySide2C",
94 "PySide6",
95 "PySide6C",
86 ]: 96 ]:
97 self.menu.addAction(self.tr("Compile resource"), self.__compileResource)
87 self.menu.addAction( 98 self.menu.addAction(
88 self.tr('Compile resource'), 99 self.tr("Compile all resources"), self.__compileAllResources
89 self.__compileResource) 100 )
90 self.menu.addAction(
91 self.tr('Compile all resources'),
92 self.__compileAllResources)
93 self.menu.addSeparator() 101 self.menu.addSeparator()
94 self.menu.addAction( 102 self.menu.addAction(
95 self.tr('Configure rcc Compiler'), 103 self.tr("Configure rcc Compiler"), self.__configureRccCompiler
96 self.__configureRccCompiler) 104 )
97 self.menu.addSeparator() 105 self.menu.addSeparator()
98 else: 106 else:
99 if self.hooks["compileResource"] is not None: 107 if self.hooks["compileResource"] is not None:
100 self.menu.addAction( 108 self.menu.addAction(
101 self.hooksMenuEntries.get( 109 self.hooksMenuEntries.get(
102 "compileResource", 110 "compileResource", self.tr("Compile resource")
103 self.tr('Compile resource')), 111 ),
104 self.__compileResource) 112 self.__compileResource,
113 )
105 if self.hooks["compileAllResources"] is not None: 114 if self.hooks["compileAllResources"] is not None:
106 self.menu.addAction( 115 self.menu.addAction(
107 self.hooksMenuEntries.get( 116 self.hooksMenuEntries.get(
108 "compileAllResources", 117 "compileAllResources", self.tr("Compile all resources")
109 self.tr('Compile all resources')), 118 ),
110 self.__compileAllResources) 119 self.__compileAllResources,
120 )
111 if ( 121 if (
112 self.hooks["compileResource"] is not None or 122 self.hooks["compileResource"] is not None
113 self.hooks["compileAllResources"] is not None 123 or self.hooks["compileAllResources"] is not None
114 ): 124 ):
115 self.menu.addSeparator() 125 self.menu.addSeparator()
116 self.menu.addAction(self.tr('Open'), self.__openFile) 126 self.menu.addAction(self.tr("Open"), self.__openFile)
117 self.menu.addSeparator() 127 self.menu.addSeparator()
118 act = self.menu.addAction(self.tr('Rename file'), self._renameFile) 128 act = self.menu.addAction(self.tr("Rename file"), self._renameFile)
119 self.menuActions.append(act) 129 self.menuActions.append(act)
120 act = self.menu.addAction( 130 act = self.menu.addAction(self.tr("Remove from project"), self._removeFile)
121 self.tr('Remove from project'), self._removeFile)
122 self.menuActions.append(act) 131 self.menuActions.append(act)
123 act = self.menu.addAction(self.tr('Delete'), self.__deleteFile) 132 act = self.menu.addAction(self.tr("Delete"), self.__deleteFile)
124 self.menuActions.append(act) 133 self.menuActions.append(act)
125 self.menu.addSeparator() 134 self.menu.addSeparator()
126 if self.project.getProjectType() in [ 135 if self.project.getProjectType() in [
127 "PyQt5", "PyQt5C", 136 "PyQt5",
128 "PySide2", "PySide2C", "PySide6", "PySide6C" 137 "PyQt5C",
138 "PySide2",
139 "PySide2C",
140 "PySide6",
141 "PySide6C",
129 ]: 142 ]:
130 self.menu.addAction( 143 self.menu.addAction(self.tr("New resource..."), self.__newResource)
131 self.tr('New resource...'), self.__newResource)
132 else: 144 else:
133 if self.hooks["newResource"] is not None: 145 if self.hooks["newResource"] is not None:
134 self.menu.addAction( 146 self.menu.addAction(
135 self.hooksMenuEntries.get( 147 self.hooksMenuEntries.get(
136 "newResource", 148 "newResource", self.tr("New resource...")
137 self.tr('New resource...')), self.__newResource) 149 ),
150 self.__newResource,
151 )
152 self.menu.addAction(self.tr("Add resources..."), self.__addResourceFiles)
138 self.menu.addAction( 153 self.menu.addAction(
139 self.tr('Add resources...'), self.__addResourceFiles) 154 self.tr("Add resources directory..."), self.__addResourcesDirectory
140 self.menu.addAction( 155 )
141 self.tr('Add resources directory...'),
142 self.__addResourcesDirectory)
143 self.menu.addSeparator() 156 self.menu.addSeparator()
144 self.menu.addAction( 157 self.menu.addAction(self.tr("Copy Path to Clipboard"), self._copyToClipboard)
145 self.tr('Copy Path to Clipboard'), self._copyToClipboard)
146 self.menu.addSeparator() 158 self.menu.addSeparator()
147 self.menu.addAction( 159 self.menu.addAction(self.tr("Expand all directories"), self._expandAllDirs)
148 self.tr('Expand all directories'), self._expandAllDirs) 160 self.menu.addAction(self.tr("Collapse all directories"), self._collapseAllDirs)
149 self.menu.addAction(
150 self.tr('Collapse all directories'), self._collapseAllDirs)
151 self.menu.addSeparator() 161 self.menu.addSeparator()
152 self.menu.addAction(self.tr('Configure...'), self._configure) 162 self.menu.addAction(self.tr("Configure..."), self._configure)
153 163
154 self.backMenu = QMenu(self) 164 self.backMenu = QMenu(self)
155 if self.project.getProjectType() in [ 165 if self.project.getProjectType() in [
156 "PyQt5", "PyQt5C", 166 "PyQt5",
157 "PySide2", "PySide2C", "PySide6", "PySide6C" 167 "PyQt5C",
168 "PySide2",
169 "PySide2C",
170 "PySide6",
171 "PySide6C",
158 ]: 172 ]:
159 self.backMenu.addAction( 173 self.backMenu.addAction(
160 self.tr('Compile all resources'), 174 self.tr("Compile all resources"), self.__compileAllResources
161 self.__compileAllResources) 175 )
162 self.backMenu.addSeparator() 176 self.backMenu.addSeparator()
163 self.backMenu.addAction( 177 self.backMenu.addAction(
164 self.tr('Configure rcc Compiler'), 178 self.tr("Configure rcc Compiler"), self.__configureRccCompiler
165 self.__configureRccCompiler) 179 )
166 self.backMenu.addSeparator() 180 self.backMenu.addSeparator()
167 self.backMenu.addAction( 181 self.backMenu.addAction(self.tr("New resource..."), self.__newResource)
168 self.tr('New resource...'), self.__newResource)
169 else: 182 else:
170 if self.hooks["compileAllResources"] is not None: 183 if self.hooks["compileAllResources"] is not None:
171 self.backMenu.addAction( 184 self.backMenu.addAction(
172 self.hooksMenuEntries.get( 185 self.hooksMenuEntries.get(
173 "compileAllResources", 186 "compileAllResources", self.tr("Compile all resources")
174 self.tr('Compile all resources')), 187 ),
175 self.__compileAllResources) 188 self.__compileAllResources,
189 )
176 self.backMenu.addSeparator() 190 self.backMenu.addSeparator()
177 if self.hooks["newResource"] is not None: 191 if self.hooks["newResource"] is not None:
178 self.backMenu.addAction( 192 self.backMenu.addAction(
179 self.hooksMenuEntries.get( 193 self.hooksMenuEntries.get(
180 "newResource", 194 "newResource", self.tr("New resource...")
181 self.tr('New resource...')), self.__newResource) 195 ),
196 self.__newResource,
197 )
182 self.backMenu.addAction( 198 self.backMenu.addAction(
183 self.tr('Add resources...'), self.project.addResourceFiles) 199 self.tr("Add resources..."), self.project.addResourceFiles
200 )
184 self.backMenu.addAction( 201 self.backMenu.addAction(
185 self.tr('Add resources directory...'), 202 self.tr("Add resources directory..."), self.project.addResourceDir
186 self.project.addResourceDir) 203 )
187 self.backMenu.addSeparator() 204 self.backMenu.addSeparator()
205 self.backMenu.addAction(self.tr("Expand all directories"), self._expandAllDirs)
188 self.backMenu.addAction( 206 self.backMenu.addAction(
189 self.tr('Expand all directories'), self._expandAllDirs) 207 self.tr("Collapse all directories"), self._collapseAllDirs
190 self.backMenu.addAction( 208 )
191 self.tr('Collapse all directories'), self._collapseAllDirs)
192 self.backMenu.addSeparator() 209 self.backMenu.addSeparator()
193 self.backMenu.addAction(self.tr('Configure...'), self._configure) 210 self.backMenu.addAction(self.tr("Configure..."), self._configure)
194 self.backMenu.setEnabled(False) 211 self.backMenu.setEnabled(False)
195 212
196 # create the menu for multiple selected files 213 # create the menu for multiple selected files
197 self.multiMenu = QMenu(self) 214 self.multiMenu = QMenu(self)
198 if self.project.getProjectType() in [ 215 if self.project.getProjectType() in [
199 "PyQt5", "PyQt5C", 216 "PyQt5",
200 "PySide2", "PySide2C", "PySide6", "PySide6C" 217 "PyQt5C",
218 "PySide2",
219 "PySide2C",
220 "PySide6",
221 "PySide6C",
201 ]: 222 ]:
202 act = self.multiMenu.addAction( 223 act = self.multiMenu.addAction(
203 self.tr('Compile resources'), 224 self.tr("Compile resources"), self.__compileSelectedResources
204 self.__compileSelectedResources) 225 )
205 self.multiMenu.addSeparator() 226 self.multiMenu.addSeparator()
206 self.multiMenu.addAction( 227 self.multiMenu.addAction(
207 self.tr('Configure rcc Compiler'), 228 self.tr("Configure rcc Compiler"), self.__configureRccCompiler
208 self.__configureRccCompiler) 229 )
209 self.multiMenu.addSeparator() 230 self.multiMenu.addSeparator()
210 else: 231 else:
211 if self.hooks["compileSelectedResources"] is not None: 232 if self.hooks["compileSelectedResources"] is not None:
212 act = self.multiMenu.addAction( 233 act = self.multiMenu.addAction(
213 self.hooksMenuEntries.get( 234 self.hooksMenuEntries.get(
214 "compileSelectedResources", 235 "compileSelectedResources", self.tr("Compile resources")
215 self.tr('Compile resources')), 236 ),
216 self.__compileSelectedResources) 237 self.__compileSelectedResources,
238 )
217 self.multiMenu.addSeparator() 239 self.multiMenu.addSeparator()
218 self.multiMenu.addAction(self.tr('Open'), self.__openFile) 240 self.multiMenu.addAction(self.tr("Open"), self.__openFile)
219 self.multiMenu.addSeparator() 241 self.multiMenu.addSeparator()
220 act = self.multiMenu.addAction( 242 act = self.multiMenu.addAction(self.tr("Remove from project"), self._removeFile)
221 self.tr('Remove from project'), self._removeFile)
222 self.multiMenuActions.append(act) 243 self.multiMenuActions.append(act)
223 act = self.multiMenu.addAction( 244 act = self.multiMenu.addAction(self.tr("Delete"), self.__deleteFile)
224 self.tr('Delete'), self.__deleteFile)
225 self.multiMenuActions.append(act) 245 self.multiMenuActions.append(act)
226 self.multiMenu.addSeparator() 246 self.multiMenu.addSeparator()
247 self.multiMenu.addAction(self.tr("Expand all directories"), self._expandAllDirs)
227 self.multiMenu.addAction( 248 self.multiMenu.addAction(
228 self.tr('Expand all directories'), self._expandAllDirs) 249 self.tr("Collapse all directories"), self._collapseAllDirs
229 self.multiMenu.addAction( 250 )
230 self.tr('Collapse all directories'), self._collapseAllDirs)
231 self.multiMenu.addSeparator() 251 self.multiMenu.addSeparator()
232 self.multiMenu.addAction(self.tr('Configure...'), self._configure) 252 self.multiMenu.addAction(self.tr("Configure..."), self._configure)
233 253
234 self.dirMenu = QMenu(self) 254 self.dirMenu = QMenu(self)
235 if self.project.getProjectType() in [ 255 if self.project.getProjectType() in [
236 "PyQt5", "PyQt5C", 256 "PyQt5",
237 "PySide2", "PySide2C", "PySide6", "PySide6C" 257 "PyQt5C",
258 "PySide2",
259 "PySide2C",
260 "PySide6",
261 "PySide6C",
238 ]: 262 ]:
239 self.dirMenu.addAction( 263 self.dirMenu.addAction(
240 self.tr('Compile all resources'), 264 self.tr("Compile all resources"), self.__compileAllResources
241 self.__compileAllResources) 265 )
242 self.dirMenu.addSeparator() 266 self.dirMenu.addSeparator()
243 self.dirMenu.addAction( 267 self.dirMenu.addAction(
244 self.tr('Configure rcc Compiler'), 268 self.tr("Configure rcc Compiler"), self.__configureRccCompiler
245 self.__configureRccCompiler) 269 )
246 self.dirMenu.addSeparator() 270 self.dirMenu.addSeparator()
247 else: 271 else:
248 if self.hooks["compileAllResources"] is not None: 272 if self.hooks["compileAllResources"] is not None:
249 self.dirMenu.addAction( 273 self.dirMenu.addAction(
250 self.hooksMenuEntries.get( 274 self.hooksMenuEntries.get(
251 "compileAllResources", 275 "compileAllResources", self.tr("Compile all resources")
252 self.tr('Compile all resources')), 276 ),
253 self.__compileAllResources) 277 self.__compileAllResources,
278 )
254 self.dirMenu.addSeparator() 279 self.dirMenu.addSeparator()
255 act = self.dirMenu.addAction( 280 act = self.dirMenu.addAction(self.tr("Remove from project"), self._removeDir)
256 self.tr('Remove from project'), self._removeDir)
257 self.dirMenuActions.append(act) 281 self.dirMenuActions.append(act)
258 act = self.dirMenu.addAction( 282 act = self.dirMenu.addAction(self.tr("Delete"), self._deleteDirectory)
259 self.tr('Delete'), self._deleteDirectory)
260 self.dirMenuActions.append(act) 283 self.dirMenuActions.append(act)
261 self.dirMenu.addSeparator() 284 self.dirMenu.addSeparator()
285 self.dirMenu.addAction(self.tr("New resource..."), self.__newResource)
286 self.dirMenu.addAction(self.tr("Add resources..."), self.__addResourceFiles)
262 self.dirMenu.addAction( 287 self.dirMenu.addAction(
263 self.tr('New resource...'), self.__newResource) 288 self.tr("Add resources directory..."), self.__addResourcesDirectory
289 )
290 self.dirMenu.addSeparator()
291 self.dirMenu.addAction(self.tr("Copy Path to Clipboard"), self._copyToClipboard)
292 self.dirMenu.addSeparator()
293 self.dirMenu.addAction(self.tr("Expand all directories"), self._expandAllDirs)
264 self.dirMenu.addAction( 294 self.dirMenu.addAction(
265 self.tr('Add resources...'), self.__addResourceFiles) 295 self.tr("Collapse all directories"), self._collapseAllDirs
266 self.dirMenu.addAction( 296 )
267 self.tr('Add resources directory...'),
268 self.__addResourcesDirectory)
269 self.dirMenu.addSeparator() 297 self.dirMenu.addSeparator()
270 self.dirMenu.addAction( 298 self.dirMenu.addAction(self.tr("Configure..."), self._configure)
271 self.tr('Copy Path to Clipboard'), self._copyToClipboard) 299
272 self.dirMenu.addSeparator()
273 self.dirMenu.addAction(
274 self.tr('Expand all directories'), self._expandAllDirs)
275 self.dirMenu.addAction(
276 self.tr('Collapse all directories'), self._collapseAllDirs)
277 self.dirMenu.addSeparator()
278 self.dirMenu.addAction(self.tr('Configure...'), self._configure)
279
280 self.dirMultiMenu = QMenu(self) 300 self.dirMultiMenu = QMenu(self)
281 if self.project.getProjectType() in [ 301 if self.project.getProjectType() in [
282 "PyQt5", "PyQt5C", 302 "PyQt5",
283 "PySide2", "PySide2C", "PySide6", "PySide6C" 303 "PyQt5C",
304 "PySide2",
305 "PySide2C",
306 "PySide6",
307 "PySide6C",
284 ]: 308 ]:
285 self.dirMultiMenu.addAction( 309 self.dirMultiMenu.addAction(
286 self.tr('Compile all resources'), 310 self.tr("Compile all resources"), self.__compileAllResources
287 self.__compileAllResources) 311 )
288 self.dirMultiMenu.addSeparator() 312 self.dirMultiMenu.addSeparator()
289 self.dirMultiMenu.addAction( 313 self.dirMultiMenu.addAction(
290 self.tr('Configure rcc Compiler'), 314 self.tr("Configure rcc Compiler"), self.__configureRccCompiler
291 self.__configureRccCompiler) 315 )
292 self.dirMultiMenu.addSeparator() 316 self.dirMultiMenu.addSeparator()
293 else: 317 else:
294 if self.hooks["compileAllResources"] is not None: 318 if self.hooks["compileAllResources"] is not None:
295 self.dirMultiMenu.addAction( 319 self.dirMultiMenu.addAction(
296 self.hooksMenuEntries.get( 320 self.hooksMenuEntries.get(
297 "compileAllResources", 321 "compileAllResources", self.tr("Compile all resources")
298 self.tr('Compile all resources')), 322 ),
299 self.__compileAllResources) 323 self.__compileAllResources,
324 )
300 self.dirMultiMenu.addSeparator() 325 self.dirMultiMenu.addSeparator()
301 self.dirMultiMenu.addAction( 326 self.dirMultiMenu.addAction(
302 self.tr('Add resources...'), 327 self.tr("Add resources..."), self.project.addResourceFiles
303 self.project.addResourceFiles) 328 )
304 self.dirMultiMenu.addAction( 329 self.dirMultiMenu.addAction(
305 self.tr('Add resources directory...'), 330 self.tr("Add resources directory..."), self.project.addResourceDir
306 self.project.addResourceDir) 331 )
307 self.dirMultiMenu.addSeparator() 332 self.dirMultiMenu.addSeparator()
308 self.dirMultiMenu.addAction( 333 self.dirMultiMenu.addAction(
309 self.tr('Expand all directories'), self._expandAllDirs) 334 self.tr("Expand all directories"), self._expandAllDirs
335 )
310 self.dirMultiMenu.addAction( 336 self.dirMultiMenu.addAction(
311 self.tr('Collapse all directories'), self._collapseAllDirs) 337 self.tr("Collapse all directories"), self._collapseAllDirs
338 )
312 self.dirMultiMenu.addSeparator() 339 self.dirMultiMenu.addSeparator()
313 self.dirMultiMenu.addAction( 340 self.dirMultiMenu.addAction(self.tr("Configure..."), self._configure)
314 self.tr('Configure...'), self._configure) 341
315
316 self.menu.aboutToShow.connect(self.__showContextMenu) 342 self.menu.aboutToShow.connect(self.__showContextMenu)
317 self.multiMenu.aboutToShow.connect(self.__showContextMenuMulti) 343 self.multiMenu.aboutToShow.connect(self.__showContextMenuMulti)
318 self.dirMenu.aboutToShow.connect(self.__showContextMenuDir) 344 self.dirMenu.aboutToShow.connect(self.__showContextMenuDir)
319 self.dirMultiMenu.aboutToShow.connect(self.__showContextMenuDirMulti) 345 self.dirMultiMenu.aboutToShow.connect(self.__showContextMenuDirMulti)
320 self.backMenu.aboutToShow.connect(self.__showContextMenuBack) 346 self.backMenu.aboutToShow.connect(self.__showContextMenuBack)
321 self.mainMenu = self.menu 347 self.mainMenu = self.menu
322 348
323 def _contextMenuRequested(self, coord): 349 def _contextMenuRequested(self, coord):
324 """ 350 """
325 Protected slot to show the context menu. 351 Protected slot to show the context menu.
326 352
327 @param coord the position of the mouse pointer (QPoint) 353 @param coord the position of the mouse pointer (QPoint)
328 """ 354 """
329 if not self.project.isOpen(): 355 if not self.project.isOpen():
330 return 356 return
331 357
332 with contextlib.suppress(Exception): 358 with contextlib.suppress(Exception):
333 categories = self.getSelectedItemsCountCategorized( 359 categories = self.getSelectedItemsCountCategorized(
334 [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem]) 360 [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem]
361 )
335 cnt = categories["sum"] 362 cnt = categories["sum"]
336 if cnt <= 1: 363 if cnt <= 1:
337 index = self.indexAt(coord) 364 index = self.indexAt(coord)
338 if index.isValid(): 365 if index.isValid():
339 self._selectSingleItem(index) 366 self._selectSingleItem(index)
340 categories = self.getSelectedItemsCountCategorized( 367 categories = self.getSelectedItemsCountCategorized(
341 [ProjectBrowserFileItem, 368 [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem]
342 ProjectBrowserSimpleDirectoryItem]) 369 )
343 cnt = categories["sum"] 370 cnt = categories["sum"]
344 371
345 bfcnt = categories[str(ProjectBrowserFileItem)] 372 bfcnt = categories[str(ProjectBrowserFileItem)]
346 sdcnt = categories[str(ProjectBrowserSimpleDirectoryItem)] 373 sdcnt = categories[str(ProjectBrowserSimpleDirectoryItem)]
347 if cnt > 1 and cnt == bfcnt: 374 if cnt > 1 and cnt == bfcnt:
348 self.multiMenu.popup(self.mapToGlobal(coord)) 375 self.multiMenu.popup(self.mapToGlobal(coord))
349 elif cnt > 1 and cnt == sdcnt: 376 elif cnt > 1 and cnt == sdcnt:
357 self.dirMenu.popup(self.mapToGlobal(coord)) 384 self.dirMenu.popup(self.mapToGlobal(coord))
358 else: 385 else:
359 self.backMenu.popup(self.mapToGlobal(coord)) 386 self.backMenu.popup(self.mapToGlobal(coord))
360 else: 387 else:
361 self.backMenu.popup(self.mapToGlobal(coord)) 388 self.backMenu.popup(self.mapToGlobal(coord))
362 389
363 def __showContextMenu(self): 390 def __showContextMenu(self):
364 """ 391 """
365 Private slot called by the menu aboutToShow signal. 392 Private slot called by the menu aboutToShow signal.
366 """ 393 """
367 ProjectBaseBrowser._showContextMenu(self, self.menu) 394 ProjectBaseBrowser._showContextMenu(self, self.menu)
368 395
369 self.showMenu.emit("Main", self.menu) 396 self.showMenu.emit("Main", self.menu)
370 397
371 def __showContextMenuMulti(self): 398 def __showContextMenuMulti(self):
372 """ 399 """
373 Private slot called by the multiMenu aboutToShow signal. 400 Private slot called by the multiMenu aboutToShow signal.
374 """ 401 """
375 ProjectBaseBrowser._showContextMenuMulti(self, self.multiMenu) 402 ProjectBaseBrowser._showContextMenuMulti(self, self.multiMenu)
376 403
377 self.showMenu.emit("MainMulti", self.multiMenu) 404 self.showMenu.emit("MainMulti", self.multiMenu)
378 405
379 def __showContextMenuDir(self): 406 def __showContextMenuDir(self):
380 """ 407 """
381 Private slot called by the dirMenu aboutToShow signal. 408 Private slot called by the dirMenu aboutToShow signal.
382 """ 409 """
383 ProjectBaseBrowser._showContextMenuDir(self, self.dirMenu) 410 ProjectBaseBrowser._showContextMenuDir(self, self.dirMenu)
384 411
385 self.showMenu.emit("MainDir", self.dirMenu) 412 self.showMenu.emit("MainDir", self.dirMenu)
386 413
387 def __showContextMenuDirMulti(self): 414 def __showContextMenuDirMulti(self):
388 """ 415 """
389 Private slot called by the dirMultiMenu aboutToShow signal. 416 Private slot called by the dirMultiMenu aboutToShow signal.
390 """ 417 """
391 ProjectBaseBrowser._showContextMenuDirMulti(self, self.dirMultiMenu) 418 ProjectBaseBrowser._showContextMenuDirMulti(self, self.dirMultiMenu)
392 419
393 self.showMenu.emit("MainDirMulti", self.dirMultiMenu) 420 self.showMenu.emit("MainDirMulti", self.dirMultiMenu)
394 421
395 def __showContextMenuBack(self): 422 def __showContextMenuBack(self):
396 """ 423 """
397 Private slot called by the backMenu aboutToShow signal. 424 Private slot called by the backMenu aboutToShow signal.
398 """ 425 """
399 ProjectBaseBrowser._showContextMenuBack(self, self.backMenu) 426 ProjectBaseBrowser._showContextMenuBack(self, self.backMenu)
400 427
401 self.showMenu.emit("MainBack", self.backMenu) 428 self.showMenu.emit("MainBack", self.backMenu)
402 429
403 def __addResourceFiles(self): 430 def __addResourceFiles(self):
404 """ 431 """
405 Private method to add resource files to the project. 432 Private method to add resource files to the project.
406 """ 433 """
407 itm = self.model().item(self.currentIndex()) 434 itm = self.model().item(self.currentIndex())
408 if isinstance(itm, ProjectBrowserFileItem): 435 if isinstance(itm, ProjectBrowserFileItem):
409 dn = os.path.dirname(itm.fileName()) 436 dn = os.path.dirname(itm.fileName())
410 elif isinstance( 437 elif isinstance(
411 itm, 438 itm, (ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem)
412 (ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem)
413 ): 439 ):
414 dn = itm.dirName() 440 dn = itm.dirName()
415 else: 441 else:
416 dn = None 442 dn = None
417 self.project.addFiles('resource', dn) 443 self.project.addFiles("resource", dn)
418 444
419 def __addResourcesDirectory(self): 445 def __addResourcesDirectory(self):
420 """ 446 """
421 Private method to add resource files of a directory to the project. 447 Private method to add resource files of a directory to the project.
422 """ 448 """
423 itm = self.model().item(self.currentIndex()) 449 itm = self.model().item(self.currentIndex())
424 if isinstance(itm, ProjectBrowserFileItem): 450 if isinstance(itm, ProjectBrowserFileItem):
425 dn = os.path.dirname(itm.fileName()) 451 dn = os.path.dirname(itm.fileName())
426 elif isinstance( 452 elif isinstance(
427 itm, 453 itm, (ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem)
428 (ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem)
429 ): 454 ):
430 dn = itm.dirName() 455 dn = itm.dirName()
431 else: 456 else:
432 dn = None 457 dn = None
433 self.project.addDirectory('resource', dn) 458 self.project.addDirectory("resource", dn)
434 459
435 def _openItem(self): 460 def _openItem(self):
436 """ 461 """
437 Protected slot to handle the open popup menu entry. 462 Protected slot to handle the open popup menu entry.
438 """ 463 """
439 self.__openFile() 464 self.__openFile()
440 465
441 def __openFile(self): 466 def __openFile(self):
442 """ 467 """
443 Private slot to handle the Open menu action. 468 Private slot to handle the Open menu action.
444 """ 469 """
445 itmList = self.getSelectedItems() 470 itmList = self.getSelectedItems()
446 for itm in itmList[:]: 471 for itm in itmList[:]:
447 if isinstance(itm, ProjectBrowserFileItem): 472 if isinstance(itm, ProjectBrowserFileItem):
448 self.sourceFile.emit(itm.fileName()) 473 self.sourceFile.emit(itm.fileName())
449 474
450 def __newResource(self): 475 def __newResource(self):
451 """ 476 """
452 Private slot to handle the New Resource menu action. 477 Private slot to handle the New Resource menu action.
453 """ 478 """
454 itm = self.model().item(self.currentIndex()) 479 itm = self.model().item(self.currentIndex())
460 except AttributeError: 485 except AttributeError:
461 try: 486 try:
462 path = itm.dirName() 487 path = itm.dirName()
463 except AttributeError: 488 except AttributeError:
464 path = os.path.join(self.project.ppath, itm.data(0)) 489 path = os.path.join(self.project.ppath, itm.data(0))
465 490
466 if self.hooks["newResource"] is not None: 491 if self.hooks["newResource"] is not None:
467 self.hooks["newResource"](path) 492 self.hooks["newResource"](path)
468 else: 493 else:
469 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( 494 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter(
470 self, 495 self,
471 self.tr("New Resource"), 496 self.tr("New Resource"),
472 path, 497 path,
473 self.tr("Qt Resource Files (*.qrc)"), 498 self.tr("Qt Resource Files (*.qrc)"),
474 "", 499 "",
475 EricFileDialog.DontConfirmOverwrite) 500 EricFileDialog.DontConfirmOverwrite,
476 501 )
502
477 if not fname: 503 if not fname:
478 # user aborted or didn't enter a filename 504 # user aborted or didn't enter a filename
479 return 505 return
480 506
481 fpath = pathlib.Path(fname) 507 fpath = pathlib.Path(fname)
482 if not fpath.suffix: 508 if not fpath.suffix:
483 ex = selectedFilter.split("(*")[1].split(")")[0] 509 ex = selectedFilter.split("(*")[1].split(")")[0]
484 if ex: 510 if ex:
485 fpath = fpath.with_suffix(ex) 511 fpath = fpath.with_suffix(ex)
486 if fpath.exists(): 512 if fpath.exists():
487 res = EricMessageBox.yesNo( 513 res = EricMessageBox.yesNo(
488 self, 514 self,
489 self.tr("New Resource"), 515 self.tr("New Resource"),
490 self.tr("The file already exists! Overwrite it?"), 516 self.tr("The file already exists! Overwrite it?"),
491 icon=EricMessageBox.Warning) 517 icon=EricMessageBox.Warning,
518 )
492 if not res: 519 if not res:
493 # user selected to not overwrite 520 # user selected to not overwrite
494 return 521 return
495 522
496 try: 523 try:
497 newline = (None if self.project.useSystemEol() 524 newline = (
498 else self.project.getEolString()) 525 None if self.project.useSystemEol() else self.project.getEolString()
499 with fpath.open('w', encoding="utf-8", 526 )
500 newline=newline) as rcfile: 527 with fpath.open("w", encoding="utf-8", newline=newline) as rcfile:
501 rcfile.write('<!DOCTYPE RCC>\n') 528 rcfile.write("<!DOCTYPE RCC>\n")
502 rcfile.write('<RCC version="1.0">\n') 529 rcfile.write('<RCC version="1.0">\n')
503 rcfile.write('<qresource>\n') 530 rcfile.write("<qresource>\n")
504 rcfile.write('</qresource>\n') 531 rcfile.write("</qresource>\n")
505 rcfile.write('</RCC>\n') 532 rcfile.write("</RCC>\n")
506 except OSError as e: 533 except OSError as e:
507 EricMessageBox.critical( 534 EricMessageBox.critical(
508 self, 535 self,
509 self.tr("New Resource"), 536 self.tr("New Resource"),
510 self.tr( 537 self.tr(
511 "<p>The new resource file <b>{0}</b> could not" 538 "<p>The new resource file <b>{0}</b> could not"
512 " be created.<br>Problem: {1}</p>") 539 " be created.<br>Problem: {1}</p>"
513 .format(fpath, str(e))) 540 ).format(fpath, str(e)),
541 )
514 return 542 return
515 543
516 self.project.appendFile(str(fpath)) 544 self.project.appendFile(str(fpath))
517 self.sourceFile.emit(str(fpath)) 545 self.sourceFile.emit(str(fpath))
518 546
519 def __deleteFile(self): 547 def __deleteFile(self):
520 """ 548 """
521 Private method to delete a resource file from the project. 549 Private method to delete a resource file from the project.
522 """ 550 """
523 itmList = self.getSelectedItems() 551 itmList = self.getSelectedItems()
524 552
525 files = [] 553 files = []
526 fullNames = [] 554 fullNames = []
527 for itm in itmList: 555 for itm in itmList:
528 fn2 = itm.fileName() 556 fn2 = itm.fileName()
529 fullNames.append(fn2) 557 fullNames.append(fn2)
530 fn = self.project.getRelativePath(fn2) 558 fn = self.project.getRelativePath(fn2)
531 files.append(fn) 559 files.append(fn)
532 560
533 from UI.DeleteFilesConfirmationDialog import ( 561 from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
534 DeleteFilesConfirmationDialog 562
535 )
536 dlg = DeleteFilesConfirmationDialog( 563 dlg = DeleteFilesConfirmationDialog(
537 self.parent(), 564 self.parent(),
538 self.tr("Delete resources"), 565 self.tr("Delete resources"),
539 self.tr( 566 self.tr(
540 "Do you really want to delete these resources from the" 567 "Do you really want to delete these resources from the" " project?"
541 " project?"), 568 ),
542 files) 569 files,
543 570 )
571
544 if dlg.exec() == QDialog.DialogCode.Accepted: 572 if dlg.exec() == QDialog.DialogCode.Accepted:
545 for fn2, fn in zip(fullNames, files): 573 for fn2, fn in zip(fullNames, files):
546 self.closeSourceWindow.emit(fn2) 574 self.closeSourceWindow.emit(fn2)
547 self.project.deleteFile(fn) 575 self.project.deleteFile(fn)
548 576
549 ########################################################################### 577 ###########################################################################
550 ## Methods to handle the various compile commands 578 ## Methods to handle the various compile commands
551 ########################################################################### 579 ###########################################################################
552 580
553 def __readStdout(self): 581 def __readStdout(self):
554 """ 582 """
555 Private slot to handle the readyReadStandardOutput signal of the 583 Private slot to handle the readyReadStandardOutput signal of the
556 pyrcc5/pyside2-rcc/pyside6-rcc process. 584 pyrcc5/pyside2-rcc/pyside6-rcc process.
557 """ 585 """
558 if self.compileProc is None: 586 if self.compileProc is None:
559 return 587 return
560 self.compileProc.setReadChannel(QProcess.ProcessChannel.StandardOutput) 588 self.compileProc.setReadChannel(QProcess.ProcessChannel.StandardOutput)
561 589
562 while self.compileProc and self.compileProc.canReadLine(): 590 while self.compileProc and self.compileProc.canReadLine():
563 self.buf += str(self.compileProc.readLine(), 591 self.buf += str(
564 Preferences.getSystem("IOEncoding"), 592 self.compileProc.readLine(),
565 'replace') 593 Preferences.getSystem("IOEncoding"),
566 594 "replace",
595 )
596
567 def __readStderr(self): 597 def __readStderr(self):
568 """ 598 """
569 Private slot to handle the readyReadStandardError signal of the 599 Private slot to handle the readyReadStandardError signal of the
570 pyrcc5/pyside2-rcc/pyside6-rcc process. 600 pyrcc5/pyside2-rcc/pyside6-rcc process.
571 """ 601 """
572 if self.compileProc is None: 602 if self.compileProc is None:
573 return 603 return
574 604
575 ioEncoding = Preferences.getSystem("IOEncoding") 605 ioEncoding = Preferences.getSystem("IOEncoding")
576 606
577 self.compileProc.setReadChannel(QProcess.ProcessChannel.StandardError) 607 self.compileProc.setReadChannel(QProcess.ProcessChannel.StandardError)
578 while self.compileProc and self.compileProc.canReadLine(): 608 while self.compileProc and self.compileProc.canReadLine():
579 s = self.rccCompiler + ': ' 609 s = self.rccCompiler + ": "
580 error = str(self.compileProc.readLine(), 610 error = str(self.compileProc.readLine(), ioEncoding, "replace")
581 ioEncoding, 'replace')
582 s += error 611 s += error
583 self.appendStderr.emit(s) 612 self.appendStderr.emit(s)
584 613
585 def __compileQRCDone(self, exitCode, exitStatus): 614 def __compileQRCDone(self, exitCode, exitStatus):
586 """ 615 """
587 Private slot to handle the finished signal of the compile process. 616 Private slot to handle the finished signal of the compile process.
588 617
589 @param exitCode exit code of the process (integer) 618 @param exitCode exit code of the process (integer)
590 @param exitStatus exit status of the process (QProcess.ExitStatus) 619 @param exitStatus exit status of the process (QProcess.ExitStatus)
591 """ 620 """
592 self.compileRunning = False 621 self.compileRunning = False
593 ericApp().getObject("ViewManager").enableEditorsCheckFocusIn(True) 622 ericApp().getObject("ViewManager").enableEditorsCheckFocusIn(True)
594 ui = ericApp().getObject("UserInterface") 623 ui = ericApp().getObject("UserInterface")
595 if ( 624 if exitStatus == QProcess.ExitStatus.NormalExit and exitCode == 0 and self.buf:
596 exitStatus == QProcess.ExitStatus.NormalExit and
597 exitCode == 0 and
598 self.buf
599 ):
600 ofn = os.path.join(self.project.ppath, self.compiledFile) 625 ofn = os.path.join(self.project.ppath, self.compiledFile)
601 try: 626 try:
602 newline = (None if self.project.useSystemEol() 627 newline = (
603 else self.project.getEolString()) 628 None if self.project.useSystemEol() else self.project.getEolString()
629 )
604 with open(ofn, "w", encoding="utf-8", newline=newline) as f: 630 with open(ofn, "w", encoding="utf-8", newline=newline) as f:
605 for line in self.buf.splitlines(): 631 for line in self.buf.splitlines():
606 f.write(line + "\n") 632 f.write(line + "\n")
607 if self.compiledFile not in self.project.pdata["SOURCES"]: 633 if self.compiledFile not in self.project.pdata["SOURCES"]:
608 self.project.appendFile(ofn) 634 self.project.appendFile(ofn)
609 ui.showNotification( 635 ui.showNotification(
610 UI.PixmapCache.getPixmap("resourcesCompiler48"), 636 UI.PixmapCache.getPixmap("resourcesCompiler48"),
611 self.tr("Resource Compilation"), 637 self.tr("Resource Compilation"),
612 self.tr("The compilation of the resource file" 638 self.tr("The compilation of the resource file" " was successful."),
613 " was successful.")) 639 )
614 except OSError as msg: 640 except OSError as msg:
615 if not self.noDialog: 641 if not self.noDialog:
616 EricMessageBox.information( 642 EricMessageBox.information(
617 self, 643 self,
618 self.tr("Resource Compilation"), 644 self.tr("Resource Compilation"),
619 self.tr( 645 self.tr(
620 "<p>The compilation of the resource file" 646 "<p>The compilation of the resource file"
621 " failed.</p><p>Reason: {0}</p>").format(str(msg))) 647 " failed.</p><p>Reason: {0}</p>"
648 ).format(str(msg)),
649 )
622 else: 650 else:
623 ui.showNotification( 651 ui.showNotification(
624 UI.PixmapCache.getPixmap("resourcesCompiler48"), 652 UI.PixmapCache.getPixmap("resourcesCompiler48"),
625 self.tr("Resource Compilation"), 653 self.tr("Resource Compilation"),
626 self.tr( 654 self.tr("The compilation of the resource file failed."),
627 "The compilation of the resource file failed."),
628 kind=NotificationTypes.CRITICAL, 655 kind=NotificationTypes.CRITICAL,
629 timeout=0) 656 timeout=0,
657 )
630 self.compileProc = None 658 self.compileProc = None
631 659
632 def __compileQRC(self, fn, noDialog=False, progress=None): 660 def __compileQRC(self, fn, noDialog=False, progress=None):
633 """ 661 """
634 Private method to compile a .qrc file to a .py file. 662 Private method to compile a .qrc file to a .py file.
635 663
636 @param fn filename of the .ui file to be compiled 664 @param fn filename of the .ui file to be compiled
637 @param noDialog flag indicating silent operations 665 @param noDialog flag indicating silent operations
638 @param progress reference to the progress dialog 666 @param progress reference to the progress dialog
639 @return reference to the compile process (QProcess) 667 @return reference to the compile process (QProcess)
640 """ 668 """
641 self.compileProc = QProcess() 669 self.compileProc = QProcess()
642 args = [] 670 args = []
643 self.buf = "" 671 self.buf = ""
644 672
645 if self.project.getProjectLanguage() == "Python3": 673 if self.project.getProjectLanguage() == "Python3":
646 if self.project.getProjectType() in ["PyQt5", "PyQt5C"]: 674 if self.project.getProjectType() in ["PyQt5", "PyQt5C"]:
647 self.rccCompiler = Utilities.generatePyQtToolPath('pyrcc5') 675 self.rccCompiler = Utilities.generatePyQtToolPath("pyrcc5")
648 elif self.project.getProjectType() in ["PySide2", "PySide2C"]: 676 elif self.project.getProjectType() in ["PySide2", "PySide2C"]:
649 self.rccCompiler = Utilities.generatePySideToolPath( 677 self.rccCompiler = Utilities.generatePySideToolPath(
650 'pyside2-rcc', variant=2) 678 "pyside2-rcc", variant=2
679 )
651 elif self.project.getProjectType() in ["PySide6", "PySide6C"]: 680 elif self.project.getProjectType() in ["PySide6", "PySide6C"]:
652 self.rccCompiler = Utilities.generatePySideToolPath( 681 self.rccCompiler = Utilities.generatePySideToolPath(
653 'pyside6-rcc', variant=6) 682 "pyside6-rcc", variant=6
683 )
654 else: 684 else:
655 return None 685 return None
656 defaultParameters = self.project.getDefaultRccCompilerParameters() 686 defaultParameters = self.project.getDefaultRccCompilerParameters()
657 rccParameters = self.project.pdata["RCCPARAMS"] 687 rccParameters = self.project.pdata["RCCPARAMS"]
658 if ( 688 if (
659 rccParameters["CompressionThreshold"] != 689 rccParameters["CompressionThreshold"]
660 defaultParameters["CompressionThreshold"] 690 != defaultParameters["CompressionThreshold"]
661 ): 691 ):
662 args.append("-threshold") 692 args.append("-threshold")
663 args.append(str(rccParameters["CompressionThreshold"])) 693 args.append(str(rccParameters["CompressionThreshold"]))
664 if ( 694 if rccParameters["CompressLevel"] != defaultParameters["CompressLevel"]:
665 rccParameters["CompressLevel"] !=
666 defaultParameters["CompressLevel"]
667 ):
668 args.append("-compress") 695 args.append("-compress")
669 args.append(str(rccParameters["CompressLevel"])) 696 args.append(str(rccParameters["CompressLevel"]))
670 if ( 697 if (
671 rccParameters["CompressionDisable"] != 698 rccParameters["CompressionDisable"]
672 defaultParameters["CompressionDisable"] 699 != defaultParameters["CompressionDisable"]
673 ): 700 ):
674 args.append("-no-compress") 701 args.append("-no-compress")
675 if rccParameters["PathPrefix"] != defaultParameters["PathPrefix"]: 702 if rccParameters["PathPrefix"] != defaultParameters["PathPrefix"]:
676 args.append("-root") 703 args.append("-root")
677 args.append(rccParameters["PathPrefix"]) 704 args.append(rccParameters["PathPrefix"])
678 else: 705 else:
679 return None 706 return None
680 707
681 rcc = self.rccCompiler 708 rcc = self.rccCompiler
682 709
683 ofn, ext = os.path.splitext(fn) 710 ofn, ext = os.path.splitext(fn)
684 fn = os.path.join(self.project.ppath, fn) 711 fn = os.path.join(self.project.ppath, fn)
685 712
686 dirname, filename = os.path.split(ofn) 713 dirname, filename = os.path.split(ofn)
687 if self.project.getProjectLanguage() == "Python3": 714 if self.project.getProjectLanguage() == "Python3":
688 self.compiledFile = os.path.join( 715 self.compiledFile = os.path.join(
689 dirname, self.RCFilenameFormatPython.format(filename)) 716 dirname, self.RCFilenameFormatPython.format(filename)
717 )
690 elif self.project.getProjectLanguage() == "Ruby": 718 elif self.project.getProjectLanguage() == "Ruby":
691 self.compiledFile = os.path.join( 719 self.compiledFile = os.path.join(
692 dirname, self.RCFilenameFormatRuby.format(filename)) 720 dirname, self.RCFilenameFormatRuby.format(filename)
693 721 )
722
694 args.append(fn) 723 args.append(fn)
695 self.compileProc.finished.connect(self.__compileQRCDone) 724 self.compileProc.finished.connect(self.__compileQRCDone)
696 self.compileProc.readyReadStandardOutput.connect(self.__readStdout) 725 self.compileProc.readyReadStandardOutput.connect(self.__readStdout)
697 self.compileProc.readyReadStandardError.connect(self.__readStderr) 726 self.compileProc.readyReadStandardError.connect(self.__readStderr)
698 727
699 self.noDialog = noDialog 728 self.noDialog = noDialog
700 self.compileProc.start(rcc, args) 729 self.compileProc.start(rcc, args)
701 procStarted = self.compileProc.waitForStarted(5000) 730 procStarted = self.compileProc.waitForStarted(5000)
702 if procStarted: 731 if procStarted:
703 self.compileRunning = True 732 self.compileRunning = True
707 self.compileRunning = False 736 self.compileRunning = False
708 if progress is not None: 737 if progress is not None:
709 progress.cancel() 738 progress.cancel()
710 EricMessageBox.critical( 739 EricMessageBox.critical(
711 self, 740 self,
712 self.tr('Process Generation Error'), 741 self.tr("Process Generation Error"),
713 self.tr( 742 self.tr(
714 'Could not start {0}.<br>' 743 "Could not start {0}.<br>" "Ensure that it is in the search path."
715 'Ensure that it is in the search path.' 744 ).format(self.rccCompiler),
716 ).format(self.rccCompiler)) 745 )
717 return None 746 return None
718 747
719 def __compileResource(self): 748 def __compileResource(self):
720 """ 749 """
721 Private method to compile a resource to a source file. 750 Private method to compile a resource to a source file.
722 """ 751 """
723 itm = self.model().item(self.currentIndex()) 752 itm = self.model().item(self.currentIndex())
725 fn = self.project.getRelativePath(fn2) 754 fn = self.project.getRelativePath(fn2)
726 if self.hooks["compileResource"] is not None: 755 if self.hooks["compileResource"] is not None:
727 self.hooks["compileResource"](fn) 756 self.hooks["compileResource"](fn)
728 else: 757 else:
729 self.__compileQRC(fn) 758 self.__compileQRC(fn)
730 759
731 def __compileAllResources(self): 760 def __compileAllResources(self):
732 """ 761 """
733 Private method to compile all resources to source files. 762 Private method to compile all resources to source files.
734 """ 763 """
735 if self.hooks["compileAllResources"] is not None: 764 if self.hooks["compileAllResources"] is not None:
736 self.hooks["compileAllResources"](self.project.pdata["RESOURCES"]) 765 self.hooks["compileAllResources"](self.project.pdata["RESOURCES"])
737 else: 766 else:
738 numResources = len(self.project.pdata["RESOURCES"]) 767 numResources = len(self.project.pdata["RESOURCES"])
739 progress = EricProgressDialog( 768 progress = EricProgressDialog(
740 self.tr("Compiling resources..."), 769 self.tr("Compiling resources..."),
741 self.tr("Abort"), 0, numResources, 770 self.tr("Abort"),
742 self.tr("%v/%m Resources"), self) 771 0,
772 numResources,
773 self.tr("%v/%m Resources"),
774 self,
775 )
743 progress.setModal(True) 776 progress.setModal(True)
744 progress.setMinimumDuration(0) 777 progress.setMinimumDuration(0)
745 progress.setWindowTitle(self.tr("Resources")) 778 progress.setWindowTitle(self.tr("Resources"))
746 779
747 for prog, fn in enumerate(self.project.pdata["RESOURCES"]): 780 for prog, fn in enumerate(self.project.pdata["RESOURCES"]):
748 progress.setValue(prog) 781 progress.setValue(prog)
749 if progress.wasCanceled(): 782 if progress.wasCanceled():
750 break 783 break
751 proc = self.__compileQRC(fn, True, progress) 784 proc = self.__compileQRC(fn, True, progress)
754 QThread.msleep(100) 787 QThread.msleep(100)
755 QApplication.processEvents() 788 QApplication.processEvents()
756 else: 789 else:
757 break 790 break
758 progress.setValue(numResources) 791 progress.setValue(numResources)
759 792
760 def __compileSelectedResources(self): 793 def __compileSelectedResources(self):
761 """ 794 """
762 Private method to compile selected resources to source files. 795 Private method to compile selected resources to source files.
763 """ 796 """
764 items = self.getSelectedItems() 797 items = self.getSelectedItems()
765 files = [self.project.getRelativePath(itm.fileName()) 798 files = [self.project.getRelativePath(itm.fileName()) for itm in items]
766 for itm in items] 799
767
768 if self.hooks["compileSelectedResources"] is not None: 800 if self.hooks["compileSelectedResources"] is not None:
769 self.hooks["compileSelectedResources"](files) 801 self.hooks["compileSelectedResources"](files)
770 else: 802 else:
771 numResources = len(files) 803 numResources = len(files)
772 progress = EricProgressDialog( 804 progress = EricProgressDialog(
773 self.tr("Compiling resources..."), 805 self.tr("Compiling resources..."),
774 self.tr("Abort"), 0, numResources, 806 self.tr("Abort"),
775 self.tr("%v/%m Resources"), self) 807 0,
808 numResources,
809 self.tr("%v/%m Resources"),
810 self,
811 )
776 progress.setModal(True) 812 progress.setModal(True)
777 progress.setMinimumDuration(0) 813 progress.setMinimumDuration(0)
778 progress.setWindowTitle(self.tr("Resources")) 814 progress.setWindowTitle(self.tr("Resources"))
779 815
780 for prog, fn in enumerate(files): 816 for prog, fn in enumerate(files):
781 progress.setValue(prog) 817 progress.setValue(prog)
782 if progress.wasCanceled(): 818 if progress.wasCanceled():
783 break 819 break
784 if not fn.endswith('.ui.h'): 820 if not fn.endswith(".ui.h"):
785 proc = self.__compileQRC(fn, True, progress) 821 proc = self.__compileQRC(fn, True, progress)
786 if proc is not None: 822 if proc is not None:
787 while proc.state() == QProcess.ProcessState.Running: 823 while proc.state() == QProcess.ProcessState.Running:
788 QThread.msleep(100) 824 QThread.msleep(100)
789 QApplication.processEvents() 825 QApplication.processEvents()
790 else: 826 else:
791 break 827 break
792 progress.setValue(numResources) 828 progress.setValue(numResources)
793 829
794 def __checkResourcesNewer(self, filename, mtime): 830 def __checkResourcesNewer(self, filename, mtime):
795 """ 831 """
796 Private method to check, if any file referenced in a resource 832 Private method to check, if any file referenced in a resource
797 file is newer than a given time. 833 file is newer than a given time.
798 834
799 @param filename filename of the resource file (string) 835 @param filename filename of the resource file (string)
800 @param mtime modification time to check against 836 @param mtime modification time to check against
801 @return flag indicating some file is newer (boolean) 837 @return flag indicating some file is newer (boolean)
802 """ 838 """
803 try: 839 try:
804 with open(filename, "r", encoding="utf-8") as f: 840 with open(filename, "r", encoding="utf-8") as f:
805 buf = f.read() 841 buf = f.read()
806 except OSError: 842 except OSError:
807 return False 843 return False
808 844
809 qrcDirName = os.path.dirname(filename) 845 qrcDirName = os.path.dirname(filename)
810 lbuf = "" 846 lbuf = ""
811 for line in buf.splitlines(): 847 for line in buf.splitlines():
812 line = line.strip() 848 line = line.strip()
813 if ( 849 if line.lower().startswith("<file>") or line.lower().startswith("<file "):
814 line.lower().startswith("<file>") or
815 line.lower().startswith("<file ")
816 ):
817 lbuf = line 850 lbuf = line
818 elif lbuf: 851 elif lbuf:
819 lbuf = "{0}{1}".format(lbuf, line) 852 lbuf = "{0}{1}".format(lbuf, line)
820 if lbuf.lower().endswith("</file>"): 853 if lbuf.lower().endswith("</file>"):
821 rfile = lbuf.split(">", 1)[1].split("<", 1)[0] 854 rfile = lbuf.split(">", 1)[1].split("<", 1)[0]
822 if not os.path.isabs(rfile): 855 if not os.path.isabs(rfile):
823 rfile = os.path.join(qrcDirName, rfile) 856 rfile = os.path.join(qrcDirName, rfile)
824 if ( 857 if os.path.exists(rfile) and os.stat(rfile).st_mtime > mtime:
825 os.path.exists(rfile) and
826 os.stat(rfile).st_mtime > mtime
827 ):
828 return True 858 return True
829 859
830 lbuf = "" 860 lbuf = ""
831 861
832 return False 862 return False
833 863
834 def compileChangedResources(self): 864 def compileChangedResources(self):
835 """ 865 """
836 Public method to compile all changed resources to source files. 866 Public method to compile all changed resources to source files.
837 """ 867 """
838 if self.hooks["compileChangedResources"] is not None: 868 if self.hooks["compileChangedResources"] is not None:
839 self.hooks["compileChangedResources"]( 869 self.hooks["compileChangedResources"](self.project.pdata["RESOURCES"])
840 self.project.pdata["RESOURCES"])
841 else: 870 else:
842 if len(self.project.pdata["RESOURCES"]) == 0: 871 if len(self.project.pdata["RESOURCES"]) == 0:
843 # The project does not contain resource files 872 # The project does not contain resource files
844 return 873 return
845 874
846 progress = EricProgressDialog( 875 progress = EricProgressDialog(
847 self.tr("Determining changed resources..."), 876 self.tr("Determining changed resources..."),
848 self.tr("Abort"), 0, 100, self.tr("%v/%m Resources"), self) 877 self.tr("Abort"),
878 0,
879 100,
880 self.tr("%v/%m Resources"),
881 self,
882 )
849 progress.setMinimumDuration(0) 883 progress.setMinimumDuration(0)
850 progress.setWindowTitle(self.tr("Resources")) 884 progress.setWindowTitle(self.tr("Resources"))
851 885
852 # get list of changed resources 886 # get list of changed resources
853 changedResources = [] 887 changedResources = []
854 progress.setMaximum(len(self.project.pdata["RESOURCES"])) 888 progress.setMaximum(len(self.project.pdata["RESOURCES"]))
855 for prog, fn in enumerate(self.project.pdata["RESOURCES"]): 889 for prog, fn in enumerate(self.project.pdata["RESOURCES"]):
856 progress.setValue(prog) 890 progress.setValue(prog)
857 QApplication.processEvents() 891 QApplication.processEvents()
858 ifn = os.path.join(self.project.ppath, fn) 892 ifn = os.path.join(self.project.ppath, fn)
859 if self.project.getProjectLanguage() == "Python3": 893 if self.project.getProjectLanguage() == "Python3":
860 dirname, filename = os.path.split(os.path.splitext(ifn)[0]) 894 dirname, filename = os.path.split(os.path.splitext(ifn)[0])
861 ofn = os.path.join( 895 ofn = os.path.join(
862 dirname, self.RCFilenameFormatPython.format(filename)) 896 dirname, self.RCFilenameFormatPython.format(filename)
897 )
863 elif self.project.getProjectLanguage() == "Ruby": 898 elif self.project.getProjectLanguage() == "Ruby":
864 dirname, filename = os.path.split(os.path.splitext(ifn)[0]) 899 dirname, filename = os.path.split(os.path.splitext(ifn)[0])
865 ofn = os.path.join( 900 ofn = os.path.join(
866 dirname, self.RCFilenameFormatRuby.format(filename)) 901 dirname, self.RCFilenameFormatRuby.format(filename)
902 )
867 else: 903 else:
868 return 904 return
869 if ( 905 if (
870 not os.path.exists(ofn) or 906 not os.path.exists(ofn)
871 os.stat(ifn).st_mtime > os.stat(ofn).st_mtime or 907 or os.stat(ifn).st_mtime > os.stat(ofn).st_mtime
872 self.__checkResourcesNewer(ifn, os.stat(ofn).st_mtime) 908 or self.__checkResourcesNewer(ifn, os.stat(ofn).st_mtime)
873 ): 909 ):
874 changedResources.append(fn) 910 changedResources.append(fn)
875 progress.setValue(len(self.project.pdata["RESOURCES"])) 911 progress.setValue(len(self.project.pdata["RESOURCES"]))
876 QApplication.processEvents() 912 QApplication.processEvents()
877 913
878 if changedResources: 914 if changedResources:
879 progress.setLabelText( 915 progress.setLabelText(self.tr("Compiling changed resources..."))
880 self.tr("Compiling changed resources..."))
881 progress.setMaximum(len(changedResources)) 916 progress.setMaximum(len(changedResources))
882 progress.setValue(0) 917 progress.setValue(0)
883 QApplication.processEvents() 918 QApplication.processEvents()
884 for prog, fn in enumerate(changedResources): 919 for prog, fn in enumerate(changedResources):
885 progress.setValue(prog) 920 progress.setValue(prog)
892 QApplication.processEvents() 927 QApplication.processEvents()
893 else: 928 else:
894 break 929 break
895 progress.setValue(len(changedResources)) 930 progress.setValue(len(changedResources))
896 QApplication.processEvents() 931 QApplication.processEvents()
897 932
898 def handlePreferencesChanged(self): 933 def handlePreferencesChanged(self):
899 """ 934 """
900 Public slot used to handle the preferencesChanged signal. 935 Public slot used to handle the preferencesChanged signal.
901 """ 936 """
902 ProjectBaseBrowser.handlePreferencesChanged(self) 937 ProjectBaseBrowser.handlePreferencesChanged(self)
903 938
904 def __configureRccCompiler(self): 939 def __configureRccCompiler(self):
905 """ 940 """
906 Private slot to configure some non-common rcc compiler options. 941 Private slot to configure some non-common rcc compiler options.
907 """ 942 """
908 from .RccCompilerOptionsDialog import RccCompilerOptionsDialog 943 from .RccCompilerOptionsDialog import RccCompilerOptionsDialog
909 944
910 params = self.project.pdata["RCCPARAMS"] 945 params = self.project.pdata["RCCPARAMS"]
911 946
912 dlg = RccCompilerOptionsDialog(params) 947 dlg = RccCompilerOptionsDialog(params)
913 if dlg.exec() == QDialog.DialogCode.Accepted: 948 if dlg.exec() == QDialog.DialogCode.Accepted:
914 threshold, compression, noCompression, root = dlg.getData() 949 threshold, compression, noCompression, root = dlg.getData()
915 if threshold != params["CompressionThreshold"]: 950 if threshold != params["CompressionThreshold"]:
916 params["CompressionThreshold"] = threshold 951 params["CompressionThreshold"] = threshold
922 params["CompressionDisable"] = noCompression 957 params["CompressionDisable"] = noCompression
923 self.project.setDirty(True) 958 self.project.setDirty(True)
924 if root != params["PathPrefix"]: 959 if root != params["PathPrefix"]:
925 params["PathPrefix"] = root 960 params["PathPrefix"] = root
926 self.project.setDirty(True) 961 self.project.setDirty(True)
927 962
928 ########################################################################### 963 ###########################################################################
929 ## Support for hooks below 964 ## Support for hooks below
930 ########################################################################### 965 ###########################################################################
931 966
932 def _initHookMethods(self): 967 def _initHookMethods(self):
933 """ 968 """
934 Protected method to initialize the hooks dictionary. 969 Protected method to initialize the hooks dictionary.
935 970
936 Supported hook methods are: 971 Supported hook methods are:
937 <ul> 972 <ul>
938 <li>compileResource: takes filename as parameter</li> 973 <li>compileResource: takes filename as parameter</li>
939 <li>compileAllResources: takes list of filenames as parameter</li> 974 <li>compileAllResources: takes list of filenames as parameter</li>
940 <li>compileChangedResources: takes list of filenames as parameter</li> 975 <li>compileChangedResources: takes list of filenames as parameter</li>
941 <li>compileSelectedResources: takes list of all form filenames as 976 <li>compileSelectedResources: takes list of all form filenames as
942 parameter</li> 977 parameter</li>
943 <li>newResource: takes full directory path of new file as 978 <li>newResource: takes full directory path of new file as
944 parameter</li> 979 parameter</li>
945 </ul> 980 </ul>
946 981
947 <b>Note</b>: Filenames are relative to the project directory, if not 982 <b>Note</b>: Filenames are relative to the project directory, if not
948 specified differently. 983 specified differently.
949 """ 984 """
950 self.hooks = { 985 self.hooks = {
951 "compileResource": None, 986 "compileResource": None,

eric ide

mercurial