Merge lp:~mac9416/keryx/unstable into lp:keryx/stable
- unstable
- Merge into stable
Proposed by
mac9416
Status: | Approved |
---|---|
Approved by: | mac9416 |
Approved revision: | 180 |
Proposed branch: | lp:~mac9416/keryx/unstable |
Merge into: | lp:keryx/stable |
Diff against target: |
102898 lines (+2394/-99183) 69 files modified
app.fil (+1/-1) build.bat (+13/-0) build.sh (+15/-0) doc/INSTALL (+0/-24) doc/README (+2/-86) doc/config.rst (+8/-0) doc/debian.rst (+5/-0) doc/index.rst (+32/-0) doc/keryx.conf (+0/-29) doc/lib.rst (+8/-0) doc/log.rst (+8/-0) doc/package.rst (+8/-0) doc/plugins.rst (+12/-0) doc/project.rst (+8/-0) doc/source.rst (+8/-0) doc/tutorial.rst (+68/-0) doc/version.rst (+8/-0) keryx.py (+29/-110) keryx.spec (+29/-0) lib/__init__.py (+90/-29) lib/config.py (+0/-113) lib/consts.py (+0/-150) lib/debian.py (+530/-0) lib/install.sh (+101/-0) lib/log.py (+25/-21) lib/package.py (+43/-0) lib/plugins.py (+0/-88) lib/project.py (+95/-85) lib/source.py (+41/-0) lib/tests/test_source.py (+14/-0) lib/version.py (+207/-0) lib/wxkeryx/__init__.py (+16/-17) lib/wxkeryx/delayedresult.py (+63/-75) lib/wxkeryx/download.py (+176/-171) lib/wxkeryx/editor.py (+17/-15) lib/wxkeryx/main.py (+306/-284) lib/wxkeryx/misc.py (+219/-170) lib/wxkeryx/options.py (+0/-300) lib/wxkeryx/startDialog.py (+110/-132) messages.pot (+16/-16) plugins/ColorMap.py (+0/-66) plugins/Debian.py (+0/-747) plugins/Search.py (+0/-148) projects/hardy-32-bit-default/debian.conf (+0/-5) projects/hardy-32-bit-default/hardy-32-bit.keryx (+0/-2) projects/hardy-32-bit-default/lists/status (+0/-15138) projects/hardy-32-bit-default/sources/sources.list (+0/-52) projects/hardy-64-bit-default/debian.conf (+0/-5) projects/hardy-64-bit-default/hardy-64-bit.keryx (+0/-2) projects/hardy-64-bit-default/lists/status (+0/-14740) projects/hardy-64-bit-default/sources/sources.list (+0/-52) projects/jaunty-32-bit-default/debian.conf (+0/-5) projects/jaunty-32-bit-default/jaunty-32-bit.keryx (+0/-2) projects/jaunty-32-bit-default/lists/status (+0/-15966) projects/jaunty-32-bit-default/sources/sources.list (+0/-53) projects/jaunty-64-bit-default/debian.conf (+0/-5) projects/jaunty-64-bit-default/jaunty-64-bit.keryx (+0/-2) projects/jaunty-64-bit-default/lists/status (+0/-16924) projects/jaunty-64-bit-default/sources/sources.list (+0/-53) projects/karmic-32-bit-default/debian.conf (+0/-5) projects/karmic-32-bit-default/karmic-32-bit.keryx (+0/-2) projects/karmic-32-bit-default/lists/status (+0/-16622) projects/karmic-32-bit-default/sources/sources.list (+0/-52) projects/karmic-64-bit-default/debian.conf (+0/-5) projects/karmic-64-bit-default/karmic-64-bit.keryx (+0/-2) projects/karmic-64-bit-default/lists/status (+0/-16504) projects/karmic-64-bit-default/sources/sources.list (+0/-52) requirements.txt (+1/-0) setup.py (+62/-56) |
To merge this branch: | bzr merge lp:~mac9416/keryx/unstable |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
mac9416 | Approve | ||
Review via email: mp+325135@code.launchpad.net |
Commit message
Description of the change
This is a not-too-beautiful refactoring of 0.92.4. But it's functional.
To post a comment you must log in.
Unmerged revisions
- 183. By mac9416
-
But seriously, last change for 0.92.5
- 182. By mac9416
-
Final changes for 0.92.5 release
- 181. By mac9416
-
Updated spec, added missing lib file.
- 180. By mac9416
-
release 0.92.5
- 179. By mac9416
-
Cleaned up the start dialog
- 178. By mac9416
-
Removed default projects
- 177. By mac9416
-
Got rid of keryx.conf. Convention > Configuration.
- 176. By mac9416
-
Added tools to build a Linux executable.
- 175. By mac9416
-
Clean up the Debian library
- 174. By mac9416
-
Even more config.py cleanup
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'app.fil' |
2 | --- app.fil 2010-01-27 00:19:45 +0000 |
3 | +++ app.fil 2017-06-11 16:11:12 +0000 |
4 | @@ -13,7 +13,7 @@ |
5 | ./lib/wxkeryx/main.py |
6 | ./lib/wxkeryx/misc.py |
7 | ./lib/wxkeryx/options.py |
8 | -./lib/wxkeryx/startDialog.py |
9 | +./lib/wxkeryx/StartDialog.py |
10 | ./plugins/ColorMap.py |
11 | ./plugins/Debian.py |
12 | ./plugins/Search.py |
13 | |
14 | === added file 'build.bat' |
15 | --- build.bat 1970-01-01 00:00:00 +0000 |
16 | +++ build.bat 2017-06-11 16:11:12 +0000 |
17 | @@ -0,0 +1,13 @@ |
18 | +rem Get rid of any existing build. |
19 | +rd /s /q dist |
20 | + |
21 | +rem Build the executable. |
22 | +pyinstaller keryx.spec --log-level WARN |
23 | + |
24 | +rem Move important assets to the dist directory. |
25 | +xcopy /e /i doc dist\doc |
26 | +xcopy /e /i locale dist\locale |
27 | +xcopy /e /i pixmaps dist\pixmaps |
28 | + |
29 | +rem Get rid of pyinstaller's temp directories. The interesting stuff is in dist. |
30 | +rd /s /q build __pycache__ |
31 | \ No newline at end of file |
32 | |
33 | === added file 'build.sh' |
34 | --- build.sh 1970-01-01 00:00:00 +0000 |
35 | +++ build.sh 2017-06-11 16:11:12 +0000 |
36 | @@ -0,0 +1,15 @@ |
37 | +#!/usr/bin/env bash |
38 | + |
39 | +# Get rid of any existing build. |
40 | +rm -r dist |
41 | + |
42 | +# Build the executable. |
43 | +pyinstaller keryx.spec --log-level WARN |
44 | + |
45 | +# Move important assets to the dist directory. |
46 | +cp -r doc/ dist/ |
47 | +cp -r locale/ dist/ |
48 | +cp -r pixmaps/ dist/ |
49 | + |
50 | +# Get rid of pyinstaller's temp directories. The interesting stuff is in dist. |
51 | +rm -r build __pycache__ |
52 | \ No newline at end of file |
53 | |
54 | === removed file 'doc/INSTALL' |
55 | --- doc/INSTALL 2009-08-09 19:36:06 +0000 |
56 | +++ doc/INSTALL 1970-01-01 00:00:00 +0000 |
57 | @@ -1,24 +0,0 @@ |
58 | -========================== |
59 | - Installing: |
60 | -========================== |
61 | - |
62 | -Windows: No installation required. Just run keryx.exe from the win32 directory |
63 | - |
64 | -Linux: No install required as long as Python and wxPython are installed. |
65 | - Just run 'python keryx.py' or './keryx.py' if it is set as executable. |
66 | - |
67 | -========================== |
68 | - Building: |
69 | -========================== |
70 | - |
71 | -py2exe is required to build a proper windows executable. |
72 | - |
73 | -WARNING: Issues with Python 2.6 prevent succesful builds. |
74 | - |
75 | -Run 'python setup.py py2exe' to build a win32 binary. This has been tested using |
76 | -the following: |
77 | - |
78 | -Python 2.5.4 |
79 | -wxPython 2.8.9.1 unicode |
80 | -Py2exe 0.6.9 |
81 | -Pywin32 |
82 | \ No newline at end of file |
83 | |
84 | === modified file 'doc/README' |
85 | --- doc/README 2010-02-13 02:43:32 +0000 |
86 | +++ doc/README 2017-06-11 16:11:12 +0000 |
87 | @@ -7,8 +7,7 @@ |
88 | Contact/Support: |
89 | ========================== |
90 | |
91 | - Website: http://keryxproject.org |
92 | - Email: Chris Oliver <excid3@gmail.com> |
93 | + Email: Michael Crenshaw <mac9416@gmail.com> |
94 | Launchpad Project: http://launchpad.net/keryx |
95 | |
96 | ========================== |
97 | @@ -30,77 +29,12 @@ |
98 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
99 | |
100 | ========================== |
101 | - Requirements |
102 | -========================== |
103 | - |
104 | -Windows: None |
105 | - |
106 | -Linux: Python, wxPython |
107 | - |
108 | -Ubuntu users need the following packages in order to have wxPython successfully |
109 | -installed: |
110 | - |
111 | -libwxbase2.8-0 |
112 | -libwxgtk2.8-0 |
113 | -python-wxversion |
114 | -python-wxgtk2.8 |
115 | - |
116 | -wxPython is only required for using Keryx's interface. Project creation can be |
117 | -done via command line parameters. See USAGE for more information. |
118 | - |
119 | -========================== |
120 | -Installation Instructions: |
121 | -========================== |
122 | - |
123 | -Extract the Keryx archive anywhere (typically a usb device). |
124 | - |
125 | -========================== |
126 | - Usage: |
127 | -========================== |
128 | -Keryx is based around the concept of 'projects'. Each project keeps track of the |
129 | -software versions that are installed on that computer. To get started you must |
130 | -first create a project on that computer. |
131 | - |
132 | -If you are unable to install wxPython but have Python installed you can still |
133 | -create projects. In a console run: |
134 | - |
135 | -'python keryx.py --create <project name> <plugin name>' |
136 | - |
137 | -and Keryx will create a new project in the project directory. This is helpful |
138 | -for Ubuntu server users along with users who have not installed wxPython yet. |
139 | -The only <plugin name> currently available is debian. |
140 | - |
141 | -Once you have created this project, make sure you have a copy on your usb device |
142 | -that will be used to run Keryx from on a computer with highspeed internet. |
143 | - |
144 | -Keryx can be run on ANY computer with Python and wxPython installed, meaning |
145 | -Windows, Mac and Linux computers. Running Keryx on any Windows computer is |
146 | -nothing more than running 'keryx.exe'. If you are running Keryx using Python, cd |
147 | -to the directory and run 'python keryx.py' to start. Some environments support |
148 | -running a python application by double clicking it as well. |
149 | - |
150 | -After you have Keryx running on an internet connected host, downloading packages |
151 | -is as simple as opening your project and selecting the packages to download. |
152 | -Keryx will automatically select the package dependencies for you making sure |
153 | -that nothing is left behind. Any packages you download are saved to your |
154 | -project's folder in the 'packages' directory. |
155 | - |
156 | -When you are finished you can return to your project computer and install the |
157 | -packages through the usual way. |
158 | - |
159 | -========================== |
160 | -Uninstallation/Upgrading: |
161 | -========================== |
162 | - |
163 | -Extract the newest version over top, replacing all files. |
164 | - |
165 | -========================== |
166 | Thanks: |
167 | ========================== |
168 | |
169 | Buran Ayuthia |
170 | John Gleissner |
171 | -mac9416 |
172 | +mac9416 |
173 | jacseen |
174 | Kevin Buente |
175 | Douglass Clem |
176 | @@ -110,21 +44,3 @@ |
177 | Ingelrest François - Plugin framework base |
178 | heylove - Logo is based off areao.42-Icons |
179 | Anyone else I forgot to mention |
180 | - |
181 | -========================== |
182 | - Additional Notes: |
183 | -========================== |
184 | - |
185 | -Command line parameters: |
186 | - |
187 | --h or --help Displays this message |
188 | --v or --version Displays Keryx version number |
189 | ---create <project name> <plugin name> Creates a new project in the default |
190 | - directory with name of <project name> |
191 | - and type project <plugin name> |
192 | ---config <file> Uses <file> to as configuration file |
193 | - |
194 | -Due to py2exe's nature, information printed to the console is NOT displayed. |
195 | -While the command line parameters will still work properly, no indication of |
196 | -success will be shown in the console. The information will still be written in |
197 | -the log files for further review. |
198 | |
199 | === removed directory 'doc/Tutorial_Files' |
200 | === removed file 'doc/Tutorial_Files/Create_Project.png' |
201 | Binary files doc/Tutorial_Files/Create_Project.png 2010-03-13 19:04:52 +0000 and doc/Tutorial_Files/Create_Project.png 1970-01-01 00:00:00 +0000 differ |
202 | === removed file 'doc/Tutorial_Files/Install_Packages.png' |
203 | Binary files doc/Tutorial_Files/Install_Packages.png 2010-03-13 19:04:52 +0000 and doc/Tutorial_Files/Install_Packages.png 1970-01-01 00:00:00 +0000 differ |
204 | === removed file 'doc/Tutorial_Files/Installing_Packages.png' |
205 | Binary files doc/Tutorial_Files/Installing_Packages.png 2010-03-13 19:04:52 +0000 and doc/Tutorial_Files/Installing_Packages.png 1970-01-01 00:00:00 +0000 differ |
206 | === removed file 'doc/Tutorial_Files/Open_Project.png' |
207 | Binary files doc/Tutorial_Files/Open_Project.png 2010-03-13 19:04:52 +0000 and doc/Tutorial_Files/Open_Project.png 1970-01-01 00:00:00 +0000 differ |
208 | === added file 'doc/config.rst' |
209 | --- doc/config.rst 1970-01-01 00:00:00 +0000 |
210 | +++ doc/config.rst 2017-06-11 16:11:12 +0000 |
211 | @@ -0,0 +1,8 @@ |
212 | +======================================= |
213 | +lib.config - Configure Keryx's behavior |
214 | +======================================= |
215 | + |
216 | +.. contents:: |
217 | + |
218 | +.. automodule:: lib.config |
219 | + :members: |
220 | \ No newline at end of file |
221 | |
222 | === added file 'doc/debian.rst' |
223 | --- doc/debian.rst 1970-01-01 00:00:00 +0000 |
224 | +++ doc/debian.rst 2017-06-11 16:11:12 +0000 |
225 | @@ -0,0 +1,5 @@ |
226 | +lib.debian - APT support |
227 | +======================== |
228 | + |
229 | +.. automodule:: lib.debian |
230 | + :members: |
231 | \ No newline at end of file |
232 | |
233 | === added file 'doc/index.rst' |
234 | --- doc/index.rst 1970-01-01 00:00:00 +0000 |
235 | +++ doc/index.rst 2017-06-11 16:11:12 +0000 |
236 | @@ -0,0 +1,32 @@ |
237 | +.. Keryx documentation master file, created by |
238 | + sphinx-quickstart on Sun May 7 20:29:57 2017. |
239 | + You can adapt this file completely to your liking, but it should at least |
240 | + contain the root `toctree` directive. |
241 | + |
242 | +=================== |
243 | +Keryx documentation |
244 | +=================== |
245 | + |
246 | +Contents: |
247 | + |
248 | +.. toctree:: |
249 | + :maxdepth: 1 |
250 | + |
251 | + tutorial |
252 | + lib |
253 | + config |
254 | + debian |
255 | + package |
256 | + project |
257 | + source |
258 | + version |
259 | + plugins |
260 | + log |
261 | + |
262 | +================== |
263 | +Indices and tables |
264 | +================== |
265 | + |
266 | +* :ref:`genindex` |
267 | +* :ref:`modindex` |
268 | +* :ref:`search` |
269 | |
270 | === removed file 'doc/keryx.conf' |
271 | --- doc/keryx.conf 2010-02-16 02:44:28 +0000 |
272 | +++ doc/keryx.conf 1970-01-01 00:00:00 +0000 |
273 | @@ -1,29 +0,0 @@ |
274 | -#### Default values #### |
275 | -LogDir=../logs |
276 | -LocaleDir=../locale |
277 | -PluginsDir=../plugins |
278 | -ProjectsDir=../projects |
279 | -PixmapsDir=../pixmaps |
280 | -ThemesDir=../pixmaps/themes |
281 | -DefaultTheme=../pixmaps/themes/default |
282 | -CurrentTheme=../pixmaps/themes/default |
283 | - |
284 | -#### Examples #### |
285 | - |
286 | -#LogDir=../logs |
287 | -#LocaleDir=../locale |
288 | -#PackagesDir=../packages |
289 | -#PixmapsDir=../pixmaps |
290 | -#PluginsDir=../plugins |
291 | -#ProjectsDir=../projects |
292 | -#ThemesDir=../pixmaps/themes |
293 | -#DefaultTheme=../pixmaps/themes/default |
294 | -#CurrentTheme=../pixmaps/themes/default |
295 | - |
296 | -### Proxy configuration ### |
297 | -# Leave ProxyUsername and ProxyPassword commented |
298 | -# when the proxy does not require them. |
299 | - |
300 | -#HTTPProxy=http://127.0.0.1:8880 |
301 | -#ProxyUsername=username |
302 | -#ProxyPassword=password |
303 | |
304 | === added file 'doc/lib.rst' |
305 | --- doc/lib.rst 1970-01-01 00:00:00 +0000 |
306 | +++ doc/lib.rst 2017-06-11 16:11:12 +0000 |
307 | @@ -0,0 +1,8 @@ |
308 | +============================== |
309 | +lib - Tools to make Keryx work |
310 | +============================== |
311 | + |
312 | +.. contents:: |
313 | + |
314 | +.. automodule:: lib |
315 | + :members: |
316 | \ No newline at end of file |
317 | |
318 | === added file 'doc/log.rst' |
319 | --- doc/log.rst 1970-01-01 00:00:00 +0000 |
320 | +++ doc/log.rst 2017-06-11 16:11:12 +0000 |
321 | @@ -0,0 +1,8 @@ |
322 | +============================= |
323 | +lib.log - Log Keryx's actions |
324 | +============================= |
325 | + |
326 | +.. contents:: |
327 | + |
328 | +.. automodule:: lib.log |
329 | + :members: |
330 | \ No newline at end of file |
331 | |
332 | === added file 'doc/package.rst' |
333 | --- doc/package.rst 1970-01-01 00:00:00 +0000 |
334 | +++ doc/package.rst 2017-06-11 16:11:12 +0000 |
335 | @@ -0,0 +1,8 @@ |
336 | +====================================== |
337 | +lib.Package - Represent an APT package |
338 | +====================================== |
339 | + |
340 | +.. contents:: |
341 | + |
342 | +.. automodule:: lib.package |
343 | + :members: |
344 | \ No newline at end of file |
345 | |
346 | === added file 'doc/plugins.rst' |
347 | --- doc/plugins.rst 1970-01-01 00:00:00 +0000 |
348 | +++ doc/plugins.rst 2017-06-11 16:11:12 +0000 |
349 | @@ -0,0 +1,12 @@ |
350 | +========================================= |
351 | +lib.plugins - Add UI elements dynamically |
352 | +========================================= |
353 | + |
354 | +.. contents:: |
355 | + |
356 | +.. deprecated:: 0.93 |
357 | + This module was deprecated in 0.93 to reduce complexity. UI elements |
358 | + currently inserted dynamically will soon be hard-coded into the interface. |
359 | + |
360 | +.. automodule:: lib.plugins |
361 | + :members: |
362 | \ No newline at end of file |
363 | |
364 | === added file 'doc/project.rst' |
365 | --- doc/project.rst 1970-01-01 00:00:00 +0000 |
366 | +++ doc/project.rst 2017-06-11 16:11:12 +0000 |
367 | @@ -0,0 +1,8 @@ |
368 | +==================================== |
369 | +lib.project - Manage a Keryx project |
370 | +==================================== |
371 | + |
372 | +.. contents:: |
373 | + |
374 | +.. automodule:: lib.project |
375 | + :members: |
376 | \ No newline at end of file |
377 | |
378 | === added file 'doc/source.rst' |
379 | --- doc/source.rst 1970-01-01 00:00:00 +0000 |
380 | +++ doc/source.rst 2017-06-11 16:11:12 +0000 |
381 | @@ -0,0 +1,8 @@ |
382 | +==================================== |
383 | +lib.source - Manage software sources |
384 | +==================================== |
385 | + |
386 | +.. contents:: |
387 | + |
388 | +.. automodule:: lib.source |
389 | + :members: |
390 | \ No newline at end of file |
391 | |
392 | === added file 'doc/tutorial.rst' |
393 | --- doc/tutorial.rst 1970-01-01 00:00:00 +0000 |
394 | +++ doc/tutorial.rst 2017-06-11 16:11:12 +0000 |
395 | @@ -0,0 +1,68 @@ |
396 | +############## |
397 | +Keryx Tutorial |
398 | +############## |
399 | + |
400 | +.. contents:: |
401 | + |
402 | +************* |
403 | +Getting Keryx |
404 | +************* |
405 | + |
406 | +Grab Keryx from the Download page and extract it to your flash drive. |
407 | + |
408 | +************** |
409 | +Starting Keryx |
410 | +************** |
411 | + |
412 | +On Linux |
413 | +======== |
414 | + |
415 | +Navigate to the keryx/linux directory on your flash drive and double-click the 'keryx' icon. |
416 | + |
417 | +On Windows |
418 | +========== |
419 | + |
420 | +Navigate to the keryx/win32 directory on your flash drive and double-click the 'keryx' or 'keryx.exe' icon. |
421 | + |
422 | +************************************* |
423 | +Creating a Project (Offline Computer) |
424 | +************************************* |
425 | + |
426 | +After starting Keryx, enter the name of your project (or leave the default) and click 'New Project'. |
427 | + |
428 | +When asked whether you would like to download the latest package lists, choose 'No', then exit Keryx. |
429 | + |
430 | +*********************************** |
431 | +Opening a Project (Online Computer) |
432 | +*********************************** |
433 | + |
434 | +Start Keryx and choose your project from the bottom drop-down menu. Then click 'Open Project'. |
435 | + |
436 | +If you would like to have the latest packages available for download, choose 'Yes' when prompted whether to download latest package lists (recommended). |
437 | + |
438 | +************************************** |
439 | +Installing Packages (Offline Computer) |
440 | +************************************** |
441 | + |
442 | +Open your project and select 'Install Packages' from the 'Project' menu. Check all the packages you want to install and click 'Continue'. |
443 | + |
444 | +A terminal will display the progress of package installation. After installation is complete, press ENTER. |
445 | + |
446 | +So that Keryx will know that you have installed new packages, you should now update the project status (Project > Update Status). |
447 | + |
448 | +***************************** |
449 | +What if something goes wrong? |
450 | +***************************** |
451 | + |
452 | +There are several ways to get help with a problem. You can |
453 | + |
454 | + * report a bug on Launchpad |
455 | + * ask on the Forums or on Launchpad |
456 | + * contact our mailing list |
457 | + * chat with us in #keryx on Freenode |
458 | + |
459 | +***************************** |
460 | +And if everything goes right? |
461 | +***************************** |
462 | + |
463 | +Please consider donating to the project! |
464 | \ No newline at end of file |
465 | |
466 | === added file 'doc/version.rst' |
467 | --- doc/version.rst 1970-01-01 00:00:00 +0000 |
468 | +++ doc/version.rst 2017-06-11 16:11:12 +0000 |
469 | @@ -0,0 +1,8 @@ |
470 | +================================================== |
471 | +lib.version - Tools to handle APT package versions |
472 | +================================================== |
473 | + |
474 | +.. contents:: |
475 | + |
476 | +.. automodule:: lib.version |
477 | + :members: |
478 | \ No newline at end of file |
479 | |
480 | === modified file 'keryx.py' |
481 | --- keryx.py 2010-03-12 03:02:38 +0000 |
482 | +++ keryx.py 2017-06-11 16:11:12 +0000 |
483 | @@ -19,122 +19,41 @@ |
484 | |
485 | # Import commands here, even though we don't use it because debian.py uses it |
486 | # and our plugin system confuses pyinstaller. We need to manually specify this |
487 | -# in keryx so that pyinstaller can grab it and bundle the code |
488 | - |
489 | -# Import modules to satisfy plugin dependencies: |
490 | -import commands |
491 | - |
492 | -# Then import everything else. |
493 | -import os |
494 | +# in Keryx so that pyinstaller can grab it and bundle the code |
495 | + |
496 | import sys |
497 | |
498 | -from lib import consts |
499 | - |
500 | -##################### |
501 | -# Set configuration # |
502 | -##################### |
503 | -if ('--config' in sys.argv): # If config is specified |
504 | - index = sys.argv.index('--config') |
505 | - try: filename = sys.argv[index + 1] |
506 | - except: |
507 | - print 'ERROR: No config filename given' |
508 | - sys.exit(1) |
509 | - |
510 | - |
511 | - # Reinitialize consts if the a specific file has been passed |
512 | - import lib.config |
513 | - lib.config.fromFile(filename) |
514 | - |
515 | -# Else if file_config exists, load it |
516 | -elif os.path.exists(consts.file_config): |
517 | - import lib.config |
518 | - lib.config.fromFile(consts.file_config) |
519 | - |
520 | -# Import log and project AFTER configuration has been set |
521 | -from lib import log, project |
522 | - |
523 | -################ |
524 | -# Translations # |
525 | -################ |
526 | +from lib import config, log |
527 | + |
528 | +# Handle translations |
529 | +import gettext |
530 | +import locale |
531 | + |
532 | +_ = gettext.gettext |
533 | +gettext.install(config.name.lower(), config.locale_dir) |
534 | + |
535 | +lang, encoding = locale.getdefaultlocale() |
536 | + |
537 | try: |
538 | - import gettext |
539 | - import locale |
540 | - gettext.install(consts.appNameShort, consts.dirLocale, unicode=True) |
541 | - |
542 | - lang = locale.getdefaultlocale()[0] |
543 | - lang = gettext.translation(consts.appNameShort, consts.dirLocale, languages=[lang]) |
544 | + lang = gettext.translation(config.name.lower(), |
545 | + config.locale_dir, |
546 | + languages=[lang]) |
547 | lang.install() |
548 | -except: pass |
549 | +except FileNotFoundError: |
550 | + print(_('Could not locate a translation file for your language.')) |
551 | |
552 | -#TODO: Set wxWidgets translation information |
553 | +# TODO: Set wxWidgets translation information |
554 | |
555 | -################### |
556 | -# Parse arguments # |
557 | -################### |
558 | -if ('--help' in sys.argv) or ('-h' in sys.argv): |
559 | - log.info(consts.parameters) |
560 | - sys.exit(0) |
561 | - |
562 | +# Parse arguments |
563 | if ('--version' in sys.argv) or ('-v' in sys.argv): |
564 | - log.info('%s %s' % (consts.appName, consts.appVersion)) |
565 | + log.info('%s %s' % (config.name, config.version)) |
566 | sys.exit(0) |
567 | |
568 | -if ('--create' in sys.argv): |
569 | - import platform |
570 | - from lib import plugins, project |
571 | - try: |
572 | - index = sys.argv.index('--create') |
573 | - name = sys.argv[index + 1] |
574 | - plugin_name = 'debian' |
575 | - except: |
576 | - log.error(_('Unable to create project')) |
577 | - sys.exit(1) |
578 | - plugins.load(consts.dirPlugins, '', False) # Don't load interface plugins |
579 | - for item in range(0,len(plugins.OSPluginList)): |
580 | - if plugin_name == plugins.OSPluginList[item][0].lower(): |
581 | - # Append new project |
582 | - project.projects.append(project.Project()) |
583 | - proj = project.projects[len(project.projects) - 1] |
584 | - |
585 | - # Create project |
586 | - success, filename = proj.CreateKeryx(name, |
587 | - plugins.OSPluginList[item][0], |
588 | - plugins.OSPluginList[item][1]) |
589 | - |
590 | - if success: |
591 | - log.info(_('Project created successfully.')) |
592 | - sys.exit(0) |
593 | - log.error(_('Unable to create project.')) |
594 | - log.info(_('Make sure a project by this name does not already exist and you have selected the right plugin for this project.')) |
595 | - sys.exit(1) |
596 | - |
597 | - |
598 | -WXVER = "2.8" |
599 | - |
600 | -if not hasattr(sys, "frozen"): # If this isn't a compiled version of Keryx... |
601 | - import wxversion |
602 | - if wxversion.checkInstalled(WXVER): |
603 | - wxversion.select(WXVER) |
604 | - else: |
605 | - import wx |
606 | - app = wx.PySimpleApp() |
607 | - wx.MessageBox("Warning: The requested version of wxPython is not installed.\n" |
608 | - "Please install version %s" % WXVER, |
609 | - "wxPython Version Warning") |
610 | - app.MainLoop() |
611 | - |
612 | -############################# |
613 | -# Attempt to load interface # |
614 | -############################# |
615 | -#try: |
616 | -if 1: |
617 | - import lib.wxkeryx |
618 | - lib.wxkeryx.Start() |
619 | -#except Exception, e: |
620 | - #print e |
621 | -# log.error(_('Unable to load interface.')) |
622 | -# log.info(_('Make sure you have wxPython installed.')) |
623 | -# log.info(_('Read the README for details on installing wxPython')) |
624 | -# log.info(_('You can you \'python keryx.py --create\' to create a new project through the command-line if you do not have wxPython installed')) |
625 | -# log.info(_('Use \'python keryx.py --help\' to see all command-line parameters.')) |
626 | -# sys.exit(1) |
627 | +if not hasattr(sys, 'frozen'): # If this isn't a compiled version of Keryx... |
628 | + import wx |
629 | + app = wx.App() |
630 | + app.MainLoop() |
631 | + |
632 | +# Attempt to load interface |
633 | +from lib import wxkeryx |
634 | +wxkeryx.start() |
635 | |
636 | === added file 'keryx.spec' |
637 | --- keryx.spec 1970-01-01 00:00:00 +0000 |
638 | +++ keryx.spec 2017-06-11 16:11:12 +0000 |
639 | @@ -0,0 +1,29 @@ |
640 | +# -*- mode: python -*- |
641 | + |
642 | +block_cipher = None |
643 | + |
644 | + |
645 | +a = Analysis(['keryx.py'], |
646 | + pathex=['/home/tony/PycharmProjects/keryx'], |
647 | + binaries=[], |
648 | + datas=[], |
649 | + hiddenimports=[], |
650 | + hookspath=[], |
651 | + runtime_hooks=[], |
652 | + excludes=[], |
653 | + win_no_prefer_redirects=False, |
654 | + win_private_assemblies=False, |
655 | + cipher=block_cipher) |
656 | +pyz = PYZ(a.pure, a.zipped_data, |
657 | + cipher=block_cipher) |
658 | +exe = EXE(pyz, |
659 | + a.scripts, |
660 | + a.binaries, |
661 | + a.zipfiles, |
662 | + a.datas, |
663 | + name='keryx', |
664 | + debug=False, |
665 | + strip=False, |
666 | + upx=True, |
667 | + console=False, |
668 | + icon='pixmaps/keryx.ico') |
669 | |
670 | === modified file 'lib/__init__.py' |
671 | --- lib/__init__.py 2010-03-05 00:06:56 +0000 |
672 | +++ lib/__init__.py 2017-06-11 16:11:12 +0000 |
673 | @@ -17,30 +17,54 @@ |
674 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
675 | |
676 | import os |
677 | -import webbrowser |
678 | - |
679 | -import consts |
680 | +import subprocess |
681 | + |
682 | +from . import config |
683 | + |
684 | + |
685 | +class FreeSpaceUnavailable(Exception): |
686 | + """This means there's no way to get the free space on some device.""" |
687 | + pass |
688 | |
689 | try: |
690 | - import win32file |
691 | + from win32file import GetDiskFreeSpaceEx |
692 | except ImportError: |
693 | - pass # Probably not a Windows system. |
694 | - |
695 | -def driveFreeSpace(): |
696 | - """Retrieves the cwd's filesystem stats""" |
697 | - if os.name == 'posix': # get free space if they have statvfs |
698 | - data = os.statvfs(consts.cwd) |
699 | + def GetDiskFreeSpaceEx(drive): |
700 | + """This is a placeholder for if win32file is unavailable. |
701 | + |
702 | + :param str drive: the name of the drive to check for free space |
703 | + """ |
704 | + raise FreeSpaceUnavailable |
705 | + |
706 | + |
707 | +def drive_free_space(): |
708 | + """Retrieve the current working directory's free space. |
709 | + |
710 | + :return: the remaining space in KiB, MiB, or GiB |
711 | + :rtype: str |
712 | + """ |
713 | + if os.name == 'posix': # get free space if they have statvfs |
714 | + data = os.statvfs(config.cwd) |
715 | return convert_file_size(float(data[0] * data[4])) |
716 | if os.name == 'nt': |
717 | - drive = os.path.splitdrive(consts.cwd)[0] # Gets drive letter |
718 | - d_size = win32file.GetDiskFreeSpaceEx(drive) |
719 | + drive = os.path.splitdrive(config.cwd)[0] # Gets drive letter |
720 | + try: |
721 | + d_size = GetDiskFreeSpaceEx(drive) |
722 | + except FreeSpaceUnavailable: |
723 | + return 'Unavailable' |
724 | return convert_file_size(d_size[2]) |
725 | # unsupported OS, return error |
726 | return 'Unavailable' |
727 | + |
728 | + |
729 | +def convert_file_size(num_bytes): |
730 | + """Convert file size from bytes to appropriate size. |
731 | |
732 | -def convert_file_size(bytes): |
733 | - """Converts file size from bytes to appropriate size""" |
734 | - kb = bytes / 1024.0 |
735 | + :param int num_bytes: the number of bytes to be formatted |
736 | + :return: a nice representation of the size, in KiB, MiB, or GiB |
737 | + :rtype: str |
738 | + """ |
739 | + kb = num_bytes / 1024.0 |
740 | if kb < 1000: |
741 | return '%.1f %s' % (kb, 'KiB') |
742 | mb = kb / 1024.0 |
743 | @@ -49,12 +73,9 @@ |
744 | gb = mb / 1024.0 |
745 | return '%.2f %s' % (gb, 'GiB') |
746 | |
747 | -def browserOpen(url): |
748 | - """Opens default browser to url""" |
749 | - webbrowser.open(url) |
750 | |
751 | def utf(desc): |
752 | - """Returns string in fully UTF compatible format""" |
753 | + """Convert the string to a fully UTF compatible format.""" |
754 | new_word = '' |
755 | for letter in desc: |
756 | if ord(letter) > 128: |
757 | @@ -62,14 +83,54 @@ |
758 | new_word += letter |
759 | return new_word |
760 | |
761 | -def joinUrl(first, last): |
762 | - """ Returns full URL """ |
763 | - if first.endswith('/'): |
764 | - if last.startswith('/'): return first + last[1:] |
765 | - else: return first + last |
766 | + |
767 | +def join_url(first, *args): |
768 | + """Combines the given elements into a full URL. |
769 | + |
770 | + :param str first: the first part of the URL |
771 | + :param str args: subsequent parts of the URL |
772 | + :return: a complete URL from the given parts |
773 | + :rtype: str |
774 | + """ |
775 | + if len(args) == 0: |
776 | + return first |
777 | + elif len(args) == 1: |
778 | + return first.strip('/') + '/' + args[0].strip('/') |
779 | else: |
780 | - if last.startswith('/'): return first + last |
781 | - else: return first + '/' + last |
782 | - |
783 | - |
784 | - |
785 | + return join_url(first.strip('/') + '/' + args[0].strip('/'), *args[1:]) |
786 | + |
787 | + |
788 | +def run_root(program, args=''): |
789 | + """Run the given program with the given arguments, gaining root privileges |
790 | + using some GUI-based su/sudo program. The first available from among the |
791 | + choices gksu, gksudo, kdesu, and kdesudo will be used. |
792 | + |
793 | + :param str program: the command to be run |
794 | + :param str args: the arguments to run with the command |
795 | + :return: a success/error code and a message |
796 | + :rtype: list(int, str) |
797 | + """ |
798 | + # Find an available privilege-escalating tool. |
799 | + root = '' |
800 | + for a in ('gksu', 'gksudo', 'kdesu', 'kdesudo'): |
801 | + if subprocess.run('which ' + a).returncode == 0: |
802 | + root = a |
803 | + break |
804 | + |
805 | + # Give compatible GUI su's a shorter command description |
806 | + if root.startswith('gk'): |
807 | + description = '%s %s' % (program, args) |
808 | + if len(description) > 50: |
809 | + description = '--description \'%s...\'' % (description[:46]) |
810 | + else: # Certain su GUIs do not accept alternate descriptions |
811 | + description = '' |
812 | + |
813 | + # If no tool was available, return an error code. |
814 | + # TODO: actually raise an error. |
815 | + if root == '': |
816 | + return 64, 'Could not find superuser access' |
817 | + |
818 | + # Attempt to run the program as root. |
819 | + proc = subprocess.run('%s %s -- %s %s' % |
820 | + (root, description, program, args)) |
821 | + return proc.returncode, '' |
822 | |
823 | === added file 'lib/config.py' |
824 | --- lib/config.py 1970-01-01 00:00:00 +0000 |
825 | +++ lib/config.py 2017-06-11 16:11:12 +0000 |
826 | @@ -0,0 +1,96 @@ |
827 | +import os |
828 | +import sys |
829 | +from os.path import abspath, join |
830 | +from gettext import gettext as _ |
831 | + |
832 | +cwd = abspath(os.path.dirname(sys.argv[0])) |
833 | + |
834 | + |
835 | +class Theme: |
836 | + """Represents a GUI theme by defining UI elements (mostly icons).""" |
837 | + def __init__(self, theme_dir): |
838 | + """Set theme asset paths according to the given theme directory. |
839 | + |
840 | + :param str theme_dir: the directory containing a UI theme |
841 | + """ |
842 | + self.path = theme_dir |
843 | + self.icon_about = join(self.path, 'about.png') |
844 | + self.icon_arrow_down = join(self.path, 'arrow_down.png') |
845 | + self.icon_arrow_up = join(self.path, 'arrow_up.png') |
846 | + self.icon_book_open = join(self.path, 'book_open.png') |
847 | + self.icon_bug_report = join(self.path, 'bug.png') |
848 | + self.icon_close = join(self.path, 'close.png') |
849 | + self.icon_donate = join(self.path, 'donate.png') |
850 | + self.icon_download = join(self.path, 'download.png') |
851 | + self.icon_downloaded = join(self.path, 'downloaded.png') |
852 | + self.icon_error = join(self.path, 'error.png') |
853 | + self.icon_find = join(self.path, 'find.png') |
854 | + self.icon_help = join(self.path, 'help.png') |
855 | + self.icon_home = join(self.path, 'home.png') |
856 | + self.icon_install = join(self.path, 'install.png') |
857 | + self.icon_layout = join(self.path, 'layout.png') |
858 | + self.icon_new = join(self.path, 'new.png') |
859 | + self.icon_open = join(self.path, 'open.png') |
860 | + self.icon_options = join(self.path, 'options.png') |
861 | + self.icon_package = join(self.path, 'package.png') |
862 | + self.icon_plugin = join(self.path, 'plugin.png') |
863 | + self.icon_plugin_add = join(self.path, 'plugin_add.png') |
864 | + self.icon_plugin_disable = join(self.path, 'plugin_disabled.png') |
865 | + self.icon_project_details = join(self.path, 'project_details.png') |
866 | + self.icon_quit = join(self.path, 'quit.png') |
867 | + self.icon_refresh = join(self.path, 'refresh.png') |
868 | + self.icon_sources = join(self.path, 'sources.png') |
869 | + self.icon_translate = join(self.path, 'translate.png') |
870 | + self.icon_update = join(self.path, 'update.png') |
871 | + self.icon_updates = join(self.path, 'get_updates.png') |
872 | + self.icon_uptodate = join(self.path, 'uptodate.png') |
873 | + |
874 | +# Strings |
875 | +name = 'Keryx' |
876 | +subtitle = _('Bringing Updates Home.') |
877 | +version = '0.92.5' |
878 | + |
879 | +authors = 'Chris Oliver\nBuran Ayuthia\nmac9416\njacseen' |
880 | +email = 'excid3@gmail.com' |
881 | +artists = 'Chris Oliver' |
882 | +docwriters = 'Chris Oliver' |
883 | +translators = '' |
884 | +copyright = '(C) 2008-2009 Chris Oliver' |
885 | +description = name + _(' is a package manager for computers without internet.') |
886 | +license = name + ' is free software; you can redistribute ' \ |
887 | + 'it and/or modify it under the terms of the GNU General Public ' \ |
888 | + 'License as published by the Free Software Foundation; either ' \ |
889 | + 'version 2 of the License, or (at your option) any later version.\n' \ |
890 | + 'Keryx is distributed in the hope that it will be useful, but ' \ |
891 | + 'WITHOUT ANY WARRANTY; without even the implied warranty of ' \ |
892 | + 'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ' \ |
893 | + 'General Public License for more details. You should have received ' \ |
894 | + 'a copy of the GNU General Public License along with Keryx; if ' \ |
895 | + 'not, write to the Free Software Foundation, Inc., 59 Temple ' \ |
896 | + 'Place, Suite 330, Boston, MA 02111-1307 USA' |
897 | + |
898 | +# URLs |
899 | +bug_url = 'https://bugs.launchpad.net/keryx' |
900 | +donate_url = 'http://keryxproject.org/donate' |
901 | +help_url = 'http://keryxproject.org/forum' |
902 | +homepage_url = 'http://keryxproject.org' |
903 | +tutorial_url = join(cwd, 'doc', 'sphinx', 'tutorial.html') |
904 | +translate_url = 'https://translations.launchpad.net/keryx' |
905 | + |
906 | +# Directories |
907 | +locale_dir = abspath(join(cwd, 'locale')) |
908 | +log_dir = abspath(join(cwd, 'logs')) |
909 | +projects_dir = abspath(join(cwd, 'projects')) |
910 | + |
911 | +# Files |
912 | +log_path = join(log_dir, 'log') |
913 | + |
914 | +# UI assets paths |
915 | +pixmaps_dir = join(cwd, 'pixmaps') |
916 | +themes_dir = join(pixmaps_dir, 'themes') |
917 | +default_theme_dir = join(themes_dir, 'default') |
918 | +theme = Theme(default_theme_dir) |
919 | + |
920 | +# Logo |
921 | +ico_path = join(pixmaps_dir, 'keryx.ico') |
922 | +logo_path = join(pixmaps_dir, 'keryx.png') |
923 | |
924 | === removed file 'lib/config.py' |
925 | --- lib/config.py 2010-03-13 19:04:52 +0000 |
926 | +++ lib/config.py 1970-01-01 00:00:00 +0000 |
927 | @@ -1,113 +0,0 @@ |
928 | -# -*- coding: utf-8 -*- |
929 | -# |
930 | -# Author: Chris Oliver (excid3@gmail.com) |
931 | -# |
932 | -# This program is free software; you can redistribute it and/or modify |
933 | -# it under the terms of the GNU General Public License as published by |
934 | -# the Free Software Foundation; either version 2 of the License, or |
935 | -# (at your option) any later version. |
936 | -# |
937 | -# This program is distributed in the hope that it will be useful, |
938 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
939 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
940 | -# GNU Library General Public License for more details. |
941 | -# |
942 | -# You should have received a copy of the GNU General Public License |
943 | -# along with this program; if not, write to the Free Software |
944 | -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
945 | - |
946 | -import consts |
947 | -import os.path |
948 | -#from gettext import gettext as _ |
949 | - |
950 | -def genDir(val): |
951 | - return os.path.abspath(os.path.join(consts.cwd, val)) |
952 | - |
953 | -def fromFile(filename): |
954 | - # Import settings |
955 | - try: |
956 | - print 'Loading config: ' + filename |
957 | - consts.file_config = filename |
958 | - data = open(filename, 'r').read() |
959 | - data = data.split('\n') |
960 | - for item in data: |
961 | - try: |
962 | - key, val = item.split('=') |
963 | - if key == 'LogDir': |
964 | - consts.LogPath = val |
965 | - consts.dirLog = genDir(val) |
966 | - consts.fileLog = os.path.join(consts.dirLog, 'log') |
967 | - if key == 'LocaleDir': |
968 | - consts.LocalePath = val |
969 | - consts.dirLocale = genDir(val) |
970 | -# if key == 'PackagesDir': |
971 | -# consts.PackagesPath = val |
972 | -# consts.dirPackages = genDir(val) |
973 | - if key == 'PixmapsDir': |
974 | - consts.PixmapsPath = val |
975 | - consts.dirPixmaps = genDir(val) |
976 | - pixmapsChange() |
977 | - if key == 'PluginsDir': |
978 | - consts.PluginsPath = val |
979 | - consts.dirPlugins = genDir(val) |
980 | - if key == 'ProjectsDir': |
981 | - consts.ProjectsPath = val |
982 | - consts.dirProjects = genDir(val) |
983 | - if key == 'ThemesDir': |
984 | - consts.ThemesPath = val |
985 | - consts.dirThemes = genDir(val) |
986 | - if key == 'DefaultTheme': |
987 | - consts.ThemeDefaultPath = val |
988 | - consts.dirThemeDefault = genDir(val) |
989 | - if key == 'CurrentTheme': |
990 | - consts.CurrentThemePath = val |
991 | - consts.dirCurrentTheme = genDir(val) |
992 | - themeChange() |
993 | - if key == 'HTTPProxy': |
994 | - consts.proxy_enabled = True |
995 | - consts.http_proxy = {'http':val} |
996 | - if key == 'ProxyUsername': consts.proxy_username = val |
997 | - if key == 'ProxyPassword': consts.proxy_password = val |
998 | - except: pass |
999 | - consts.file_config = filename # Set the file_config location, so that if the config is change, settings go back to there |
1000 | - except Exception, e: |
1001 | - print e |
1002 | - |
1003 | -def pixmapsChange(): |
1004 | - # Logo |
1005 | - consts.fileIco = os.path.join(consts.dirPixmaps,'keryx.ico') |
1006 | - consts.fileLogo = os.path.join(consts.dirPixmaps,'keryx.png') |
1007 | - |
1008 | -def themeChange(): |
1009 | - """Load theme images""" |
1010 | - consts.icon_about = os.path.join(consts.dirCurrentTheme, 'about.png') |
1011 | - consts.icon_arrow_down = os.path.join(consts.dirCurrentTheme, 'arrow_down.png') |
1012 | - consts.icon_arrow_up = os.path.join(consts.dirCurrentTheme, 'arrow_up.png') |
1013 | - consts.icon_bug_report = os.path.join(consts.dirCurrentTheme, 'bug.png') |
1014 | - consts.icon_book_open = os.path.join(consts.dirCurrentTheme, 'book_open.png') |
1015 | - consts.icon_close = os.path.join(consts.dirCurrentTheme, 'close.png') |
1016 | - consts.icon_donate = os.path.join(consts.dirCurrentTheme, 'donate.png') |
1017 | - consts.icon_download = os.path.join(consts.dirCurrentTheme, 'download.png') |
1018 | - #icon_download_package = os.path.join(dirCurrentTheme, 'download_package.png') |
1019 | - consts.icon_downloaded = os.path.join(consts.dirCurrentTheme, 'downloaded.png') |
1020 | - consts.icon_error = os.path.join(consts.dirCurrentTheme, 'error.png') |
1021 | - consts.icon_find = os.path.join(consts.dirCurrentTheme, 'find.png') |
1022 | - consts.icon_help = os.path.join(consts.dirCurrentTheme, 'help.png') |
1023 | - consts.icon_home = os.path.join(consts.dirCurrentTheme, 'home.png') |
1024 | - consts.icon_install = os.path.join(consts.dirCurrentTheme, 'install.png') |
1025 | - consts.icon_layout = os.path.join(consts.dirCurrentTheme, 'layout.png') |
1026 | - consts.icon_new = os.path.join(consts.dirCurrentTheme, 'new.png') |
1027 | - consts.icon_open = os.path.join(consts.dirCurrentTheme, 'open.png') |
1028 | - consts.icon_options = os.path.join(consts.dirCurrentTheme, 'options.png') |
1029 | - consts.icon_package = os.path.join(consts.dirCurrentTheme, 'package.png') |
1030 | - consts.icon_plugin = os.path.join(consts.dirCurrentTheme, 'plugin.png') |
1031 | - consts.icon_plugin_add = os.path.join(consts.dirCurrentTheme, 'plugin_add.png') |
1032 | - consts.icon_plugin_disable = os.path.join(consts.dirCurrentTheme, 'plugin_disabled.png') |
1033 | - consts.icon_project_details = os.path.join(consts.dirCurrentTheme, 'project_details.png') |
1034 | - consts.icon_quit = os.path.join(consts.dirCurrentTheme, 'quit.png') |
1035 | - consts.icon_refresh = os.path.join(consts.dirCurrentTheme, 'refresh.png') |
1036 | - consts.icon_sources = os.path.join(consts.dirCurrentTheme, 'sources.png') |
1037 | - consts.icon_translate = os.path.join(consts.dirCurrentTheme, 'translate.png') |
1038 | - consts.icon_update = os.path.join(consts.dirCurrentTheme, 'update.png') |
1039 | - consts.icon_updates = os.path.join(consts.dirCurrentTheme, 'get_updates.png') |
1040 | - consts.icon_uptodate = os.path.join(consts.dirCurrentTheme, 'uptodate.png') |
1041 | |
1042 | === removed file 'lib/consts.py' |
1043 | --- lib/consts.py 2010-03-13 19:04:52 +0000 |
1044 | +++ lib/consts.py 1970-01-01 00:00:00 +0000 |
1045 | @@ -1,150 +0,0 @@ |
1046 | -# -*- coding: utf-8 -*- |
1047 | -# |
1048 | -# Author: Chris Oliver (excid3@gmail.com) |
1049 | -# |
1050 | -# This program is free software; you can redistribute it and/or modify |
1051 | -# it under the terms of the GNU General Public License as published by |
1052 | -# the Free Software Foundation; either version 2 of the License, or |
1053 | -# (at your option) any later version. |
1054 | -# |
1055 | -# This program is distributed in the hope that it will be useful, |
1056 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1057 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1058 | -# GNU Library General Public License for more details. |
1059 | -# |
1060 | -# You should have received a copy of the GNU General Public License |
1061 | -# along with this program; if not, write to the Free Software |
1062 | -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1063 | - |
1064 | -import os |
1065 | -import sys |
1066 | -from gettext import gettext as _ |
1067 | - |
1068 | -cwd = os.path.abspath(os.path.dirname(sys.argv[0])) |
1069 | - |
1070 | -# Strings |
1071 | -appName = 'Keryx' |
1072 | -appVersion = '0.92.4' |
1073 | -appNameShort = 'keryx' |
1074 | -appFileExt = '.keryx' |
1075 | -appComments = _('Bringing Updates Home.') |
1076 | -filterDesc = _('Keryx Project Files') + ' | (*' + appFileExt + ')' |
1077 | - |
1078 | -authors = 'Chris Oliver\nBuran Ayuthia\nmac9416\njacseen' |
1079 | -email = 'excid3@gmail.com' |
1080 | -artists = 'Chris Oliver' |
1081 | -docwriters = 'Chris Oliver' |
1082 | -translators = '' |
1083 | -copyright = '(C) 2008-2009 Chris Oliver' |
1084 | -description = appName + _(' is a package manager for computers without internet.') |
1085 | -license = appName + _(""" is free software; you can redistribute it and/or |
1086 | -modify it under the terms of the GNU General Public License as published by the |
1087 | -Free Software Foundation; either version 2 of the License, or (at your option) |
1088 | -any later version. |
1089 | - |
1090 | -Keryx is distributed in the hope that it will be useful, but WITHOUT ANY |
1091 | -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
1092 | -PARTICULAR PURPOSE. See the GNU General Public License for more details. You |
1093 | -should have received a copy of the GNU General Public License along with Keryx; |
1094 | -if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite |
1095 | -330, Boston, MA 02111-1307 USA""") |
1096 | - |
1097 | -welcome_message = _('Welcome to ') + appName |
1098 | - |
1099 | -parameters=""" |
1100 | -Command line parameters: |
1101 | --h or --help Displays this message |
1102 | --v or --version Displays Keryx version number |
1103 | ---create <project name> <plugin name> Creates a new project in the default |
1104 | - directory with name of <project name> |
1105 | - and type project <plugin name> |
1106 | ---config <file> Uses <file> to as configuration file\n""" |
1107 | - |
1108 | -# Proxy |
1109 | -proxy_enabled = False |
1110 | -http_proxy = {} |
1111 | -proxy_username = '' |
1112 | -proxy_password = '' |
1113 | - |
1114 | -# URLs |
1115 | -urlBug = 'https://bugs.launchpad.net/keryx' |
1116 | -urlDonate = 'http://keryxproject.org/donate' |
1117 | -urlHelp = 'http://keryxproject.org/forum' |
1118 | -urlHomepage = 'http://keryxproject.org' |
1119 | -urlTutorial = os.path.join(os.path.join(cwd, 'doc'), 'Tutorial.html') |
1120 | -urlTranslate = 'https://translations.launchpad.net/keryx' |
1121 | - |
1122 | -columns = [(_("S"), 50), (_("Package Name"), 200), (_("Installed Version"), 200), (_("Latest Version"), 200), (_("Description"), 200)] |
1123 | - |
1124 | -# Directories |
1125 | -LocalePath = 'locale' |
1126 | -LogPath = 'logs' |
1127 | -#PackagesPath = 'packages' |
1128 | -PixmapsPath = 'pixmaps' |
1129 | -PluginsPath = 'plugins' |
1130 | -ProjectsPath = 'projects' |
1131 | -ThemesPath = PixmapsPath + '/themes' |
1132 | -ThemeDefaultPath = ThemesPath + '/default' |
1133 | -CurrentThemePath = ThemeDefaultPath |
1134 | - |
1135 | -dirLocale = os.path.abspath(os.path.join(cwd, LocalePath)) |
1136 | -dirLog = os.path.abspath(os.path.join(cwd, LogPath)) |
1137 | -#dirPackages = os.path.abspath(os.path.join(cwd, PackagesPath)) |
1138 | -dirPixmaps = os.path.abspath(os.path.join(cwd, PixmapsPath)) |
1139 | -dirPlugins = os.path.abspath(os.path.join(cwd, PluginsPath)) |
1140 | -dirProjects = os.path.abspath(os.path.join(cwd, ProjectsPath)) |
1141 | -dirThemes = os.path.abspath(os.path.join(cwd, ThemesPath)) |
1142 | -dirThemeDefault = os.path.abspath(os.path.join(cwd, ThemeDefaultPath)) |
1143 | -dirCurrentTheme = os.path.abspath(os.path.join(cwd, CurrentThemePath)) |
1144 | - |
1145 | -# Files |
1146 | -configFilename = appNameShort + '.conf' |
1147 | -file_config = os.path.join(cwd, configFilename) |
1148 | -fileLog = os.path.join(dirLog, 'log') |
1149 | - |
1150 | -# Filetypes |
1151 | -wildcard = '%s (*.keryx)|*.keryx|' \ |
1152 | - '%s (*.*)|*.*' % (_("Keryx project"), _("All files")) |
1153 | -wildcard_plugin = '%s (*.py)|*.py|' \ |
1154 | - '%s (*.*)|*.*' % (_("Python File"), _("All files")) |
1155 | - |
1156 | -# Logo |
1157 | -fileIco = os.path.join(dirPixmaps,'keryx.ico') |
1158 | -fileLogo = os.path.join(dirPixmaps,'keryx.png') |
1159 | - |
1160 | -# Load theme images |
1161 | -icon_about = os.path.join(dirCurrentTheme, 'about.png') |
1162 | -icon_arrow_down = os.path.join(dirCurrentTheme, 'arrow_down.png') |
1163 | -icon_arrow_up = os.path.join(dirCurrentTheme, 'arrow_up.png') |
1164 | -icon_book_open = os.path.join(dirCurrentTheme, 'book_open.png') |
1165 | -icon_bug_report = os.path.join(dirCurrentTheme, 'bug.png') |
1166 | -icon_close = os.path.join(dirCurrentTheme, 'close.png') |
1167 | -icon_donate = os.path.join(dirCurrentTheme, 'donate.png') |
1168 | -icon_download = os.path.join(dirCurrentTheme, 'download.png') |
1169 | -#icon_download_package = os.path.join(dirCurrentTheme, 'download_package.png') |
1170 | -icon_downloaded = os.path.join(dirCurrentTheme, 'downloaded.png') |
1171 | -icon_error = os.path.join(dirCurrentTheme, 'error.png') |
1172 | -icon_find = os.path.join(dirCurrentTheme, 'find.png') |
1173 | -icon_help = os.path.join(dirCurrentTheme, 'help.png') |
1174 | -icon_home = os.path.join(dirCurrentTheme, 'home.png') |
1175 | -icon_install = os.path.join(dirCurrentTheme, 'install.png') |
1176 | -icon_layout = os.path.join(dirCurrentTheme, 'layout.png') |
1177 | -icon_new = os.path.join(dirCurrentTheme, 'new.png') |
1178 | -icon_open = os.path.join(dirCurrentTheme, 'open.png') |
1179 | -icon_options = os.path.join(dirCurrentTheme, 'options.png') |
1180 | -icon_package = os.path.join(dirCurrentTheme, 'package.png') |
1181 | -icon_plugin = os.path.join(dirCurrentTheme, 'plugin.png') |
1182 | -icon_plugin_add = os.path.join(dirCurrentTheme, 'plugin_add.png') |
1183 | -icon_plugin_disable = os.path.join(dirCurrentTheme, 'plugin_disabled.png') |
1184 | -icon_project_details = os.path.join(dirCurrentTheme, 'project_details.png') |
1185 | -icon_quit = os.path.join(dirCurrentTheme, 'quit.png') |
1186 | -icon_refresh = os.path.join(dirCurrentTheme, 'refresh.png') |
1187 | -icon_sources = os.path.join(dirCurrentTheme, 'sources.png') |
1188 | -icon_translate = os.path.join(dirCurrentTheme, 'translate.png') |
1189 | -icon_update = os.path.join(dirCurrentTheme, 'update.png') |
1190 | -icon_updates = os.path.join(dirCurrentTheme, 'get_updates.png') |
1191 | -icon_uptodate = os.path.join(dirCurrentTheme, 'uptodate.png') |
1192 | - |
1193 | -#color_error = wx.Color(255,118,106) |
1194 | -#color_update = "light blue" |
1195 | -#color_uptodate = wx.Color(150, 235, 140) |
1196 | |
1197 | === added file 'lib/debian.py' |
1198 | --- lib/debian.py 1970-01-01 00:00:00 +0000 |
1199 | +++ lib/debian.py 2017-06-11 16:11:12 +0000 |
1200 | @@ -0,0 +1,530 @@ |
1201 | +# -*- coding: utf-8 -*- |
1202 | +# |
1203 | +# Author: Chris Oliver (excid3@gmail.com) |
1204 | +# |
1205 | +# This program is free software; you can redistribute it and/or modify |
1206 | +# it under the terms of the GNU General Public License as published by |
1207 | +# the Free Software Foundation; either version 2 of the License, or |
1208 | +# (at your option) any later version. |
1209 | +# |
1210 | +# This program is distributed in the hope that it will be useful, |
1211 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1212 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1213 | +# GNU Library General Public License for more details. |
1214 | +# |
1215 | +# You should have received a copy of the GNU General Public License |
1216 | +# along with this program; if not, write to the Free Software |
1217 | +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1218 | + |
1219 | +import os |
1220 | +import platform |
1221 | +import shutil |
1222 | +import subprocess |
1223 | +from gettext import gettext as _ |
1224 | +from os.path import join as path_join |
1225 | + |
1226 | +import lib |
1227 | +from lib import config |
1228 | +from lib import log |
1229 | +from lib import run_root |
1230 | +from lib.source import Source |
1231 | +from lib.package import Package |
1232 | +from lib.version import version_compare |
1233 | + |
1234 | + |
1235 | +FILE = 'debian.conf' |
1236 | + |
1237 | +# Set this plugin's attributes |
1238 | +NAME = 'Debian' |
1239 | +TYPE = 'OS' |
1240 | +VERSION = '0.92.4' |
1241 | +AUTHOR = 'Chris Oliver <excid3@gmail.com>' |
1242 | + |
1243 | + |
1244 | +def is_os(): |
1245 | + """Determines whether the current OS uses APT |
1246 | + |
1247 | + :return: true if the current OS uses APT, false otherwise |
1248 | + :rtype: bool |
1249 | + """ |
1250 | + return os.path.exists('/etc/apt/') |
1251 | + |
1252 | + |
1253 | +def create_project(name): |
1254 | + """Creates project files |
1255 | + |
1256 | + :param str name: the name of the new project being created |
1257 | + """ |
1258 | + dir_new = path_join(config.projects_dir, name) |
1259 | + |
1260 | + # Copy relevant files to the project directory. |
1261 | + __grab_files(dir_new) |
1262 | + |
1263 | + # Write project info to a file in the project directory. |
1264 | + with open(path_join(dir_new, FILE), 'w') as outfile: |
1265 | + outfile.write('Computer Name: %s\n' % get_comp_name() + |
1266 | + 'OS Name: %s\n' % get_os_name() + |
1267 | + 'OS Version: %s\n' % get_os_version() + |
1268 | + 'Architecture: %s\n' % get_os_arch() + |
1269 | + 'Kernel: %s\n' % get_kernel_name()) |
1270 | + |
1271 | + |
1272 | +def load_local_package_list(directory, arch): |
1273 | + """Load package information from locally-stored lists. |
1274 | + |
1275 | + :param str directory: the directory to load lists from |
1276 | + :param str arch: the OS architecture to load lists for |
1277 | + :return: a dict populated with package information |
1278 | + :rtype: dict |
1279 | + """ |
1280 | + list_dir = path_join(directory, 'lists') |
1281 | + debs = __parse_sources(directory) |
1282 | + filenames = __files_from_debs(debs, arch) |
1283 | + installed = __get_installed(directory) |
1284 | + |
1285 | + # Initialize vars |
1286 | + packages = {} |
1287 | + |
1288 | + for item in filenames: |
1289 | + # TODO: better enforce zipping/unzipping of list files. |
1290 | + path = path_join(list_dir, item) |
1291 | + if not os.path.exists(path): |
1292 | + path = path.strip('.gz') |
1293 | + with open(path, 'r') as data: |
1294 | + url = 'http://%s' % item.split('_dists')[0].replace('_', '/') |
1295 | + # Append all packages to list |
1296 | + packages = __read_packages(data, installed, packages, url) |
1297 | + |
1298 | + return packages |
1299 | + |
1300 | + |
1301 | +def load_remote_package_list(directory, arch): |
1302 | + """Get information to load package lists from the project's repos. |
1303 | + |
1304 | + :param str directory: the project's directory, to load source info from |
1305 | + :param str arch: '32bit' or '64bit' |
1306 | + :return: pairs of (url, destination) pairs |
1307 | + :rtype: list(list) |
1308 | + """ |
1309 | + list_dir = path_join(directory, 'lists') |
1310 | + debs = __parse_sources(directory) |
1311 | + # TODO: extract hashes for list files from Release files |
1312 | + # and 'return zip(urls, temp_names, checksums)' instead |
1313 | + temp_names = __files_from_debs(debs, arch, list_dir) |
1314 | + urls = __urls_from_debs(debs, arch) |
1315 | + |
1316 | + # FIXME: don't return a list, just fix everything that expects a list |
1317 | + # instead of an iterator. |
1318 | + return list(zip(urls, temp_names)) # Returns urls, gzip file locations |
1319 | + |
1320 | + |
1321 | +def get_dependencies(directory, all_packages, package_name): |
1322 | + """Takes package name and returns package information for each dependency |
1323 | + (recursive). |
1324 | + |
1325 | + :param str directory: the directory to place downloaded packages in |
1326 | + :param dict all_packages: the dict holding all the package info |
1327 | + :param str package_name: the name of the package to get dependencies for |
1328 | + :return: a list of URLs to download package dependencies |
1329 | + :rtype: list(str) |
1330 | + """ |
1331 | + urls = [] |
1332 | + if package_name not in all_packages: |
1333 | + return {} |
1334 | + values = all_packages.get(package_name) |
1335 | + depends = values.depends.split(', ') |
1336 | + depends += values.recommends.split(', ') # APT treats recommends as depends |
1337 | + depends += values.pre_depends.split(', ') # pre-depends are important too |
1338 | + filename = values.filename.split('/') # Get the parts for the pkg filename |
1339 | + urls.append((values.filename, |
1340 | + path_join(directory, filename[-1]), |
1341 | + values.checksums)) |
1342 | + values.installed_version = values.version |
1343 | + all_packages[package_name] = values |
1344 | + |
1345 | + for item in depends: |
1346 | + data = item.split() |
1347 | + if not data == []: |
1348 | + # Get dependencies for this package too if it isn't already |
1349 | + # installed |
1350 | + if data[0] in all_packages \ |
1351 | + and not all_packages.get(data[0]).installed_version: |
1352 | + urls += get_dependencies(directory, |
1353 | + all_packages, |
1354 | + data[0]) |
1355 | + |
1356 | + return urls |
1357 | + |
1358 | + |
1359 | +def get_sources(directory): |
1360 | + """Get the filename of main sources file, relative to directory. |
1361 | + |
1362 | + :param str directory: the directory holding APT state files |
1363 | + :return: the path to the sources.list file |
1364 | + :rtype: str |
1365 | + """ |
1366 | + return path_join(directory, 'sources', 'sources.list') |
1367 | + |
1368 | + |
1369 | +def install_cache(project_dir, script_name, move=False): |
1370 | + """Transfer index files to the APT cache. Uses sh script called as 'root'. |
1371 | + |
1372 | + :param str project_dir: the directory holding the project |
1373 | + :param str script_name: the name of the script which will place the files |
1374 | + :param bool move: flags whether files should be moved rather than copied |
1375 | + :return: flag whether the process was successful |
1376 | + :rtype: bool |
1377 | + """ |
1378 | + packs_dir = path_join(project_dir, 'packages') |
1379 | + # Make sure there are packages to install |
1380 | + if not os.path.exists(packs_dir): |
1381 | + log.error(_('%s does not exist: no packages to be installed') % |
1382 | + packs_dir) |
1383 | + return False |
1384 | + |
1385 | + # If we're missing the partial dir, APT will throw a fit. |
1386 | + partial_dir = path_join(packs_dir, 'partial') |
1387 | + if not os.path.exists(partial_dir): |
1388 | + os.mkdir(partial_dir) |
1389 | + |
1390 | + script_path = path_join(project_dir, '%s.sh' % script_name) |
1391 | + shutil.copyfile(path_join(config.cwd, 'lib', 'install.sh'), script_path) |
1392 | + |
1393 | + if move: |
1394 | + transfer = '-move' |
1395 | + else: |
1396 | + transfer = '' |
1397 | + |
1398 | + log.info(_('install_cache: launching script as root')) |
1399 | + run = run_root('sh', '%s %s %s' % (script_path, project_dir, transfer)) |
1400 | + if run[0] != 0: |
1401 | + log.error('exit code:%i\n%s' % (run[0], run[1])) |
1402 | + log.info(_('install_cache: failed')) |
1403 | + return False |
1404 | + log.info(_('install_cache: transfer success')) |
1405 | + return True |
1406 | + |
1407 | + |
1408 | +def install_packs(project_dir, pack_names): |
1409 | + """Install the listed packages using downloaded package files in the given |
1410 | + project directory. |
1411 | + |
1412 | + :param str project_dir: the directory of the current project |
1413 | + :param list(str) pack_names: names of the packages to be installed |
1414 | + :return: a flag whether the process was successful |
1415 | + :rtype: bool |
1416 | + """ |
1417 | + packs_dir = path_join(project_dir, 'packages') |
1418 | + run = run_root('xterm', |
1419 | + '-e sh -c \"apt-get -y -o ' |
1420 | + 'dir::cache::archives=\\\"%s\\\" ' |
1421 | + '--allow-unauthenticated install %s; echo \\\"' |
1422 | + 'Press [ENTER] to exit.\\\"; ' |
1423 | + 'read x\"' % (packs_dir, pack_names)) |
1424 | + if run[0] != 0: |
1425 | + log.error(_('exit code:%i\n%s' % (run[0], run[1]))) |
1426 | + log.info(_('Failed to start Xterm as root')) |
1427 | + return False |
1428 | + return True |
1429 | + |
1430 | + |
1431 | +def update_status(out_dir, status_path='/var/lib/dpkg/status'): |
1432 | + """Update the project's status file (list of installed packages). |
1433 | + |
1434 | + :param str out_dir: the directory to place the status file in |
1435 | + :param str status_path: the path to the new status file |
1436 | + :return: a flag whether the process was successful |
1437 | + :rtype: bool |
1438 | + """ |
1439 | + lists_dir = path_join(out_dir, 'lists') |
1440 | + outfile = path_join(lists_dir, 'status') |
1441 | + outfile_bak = path_join(lists_dir, 'status.bak') |
1442 | + # Back up the current status file. |
1443 | + run_root('cp', '%s %s' % (outfile, outfile_bak)) |
1444 | + # Copy in the new status file. |
1445 | + run_root('cp', '%s %s' % (status_path, outfile)) |
1446 | + # TODO: check for error from 'cp', return False |
1447 | + return True # Everything went well. |
1448 | + |
1449 | + |
1450 | +def __read_packages(infile, installed, packages, main_url=''): |
1451 | + """Read package info from the given index file, include information from the |
1452 | + list of currently-installed packages, and add it to the current list of |
1453 | + packages. |
1454 | + |
1455 | + :param File infile: the opened index file to read package data from |
1456 | + :param list installed: the list of packages installed on the system |
1457 | + :param dict packages: the list of already-parsed packages |
1458 | + :return: packages dictionary with additional package info added |
1459 | + :rtype: dict |
1460 | + """ |
1461 | + # Create a new package object. We don't know its name yet. |
1462 | + current = Package('', checksums={}) |
1463 | + |
1464 | + for line in infile: |
1465 | + # Excuse how unreadable this next section is. It could be implemented by |
1466 | + # checking .startswith('Keyname:') for each one, but that's slow. Don't |
1467 | + # Try to narrow these down further unless you get a full listing of |
1468 | + # index file key names. False positives abound. |
1469 | + if line[0] == 'P': |
1470 | + # Pre-depends |
1471 | + if line[0:3] == 'Pre': |
1472 | + current.pre_depends = line[13:-1] |
1473 | + # Package |
1474 | + elif line[0:8] == 'Package:': |
1475 | + current.name = line[9:-1] |
1476 | + # Version |
1477 | + elif line[0] == 'V' and line[0:3] == 'Ver': |
1478 | + current.version = line[9:-1] |
1479 | + elif line[0] == 'D': |
1480 | + # Depends |
1481 | + if line[0:3] == 'Dep': |
1482 | + current.depends = line[9:-1] |
1483 | + # Description |
1484 | + elif line[0:12] == 'Description:': |
1485 | + current.description = lib.utf(line[13:-1]) |
1486 | + # Filename |
1487 | + elif line[0] == 'F': |
1488 | + current.filename = lib.join_url(main_url, line[10:-1]) |
1489 | + elif line[0] == 'S': |
1490 | + # Size |
1491 | + if line[1] == 'i': |
1492 | + current.size = int(line[6:-1]) |
1493 | + # SHA1 |
1494 | + elif line[3] == '1': |
1495 | + current.checksums['SHA1'] = line[6:-1] |
1496 | + # SHA256 |
1497 | + elif line[3] == '2': |
1498 | + current.checksums['SHA256'] = line[8:-1] |
1499 | + # Recommends |
1500 | + elif line[0] == 'R' and line[0:3] == 'Rec': |
1501 | + current.recommends = line[12:-1] |
1502 | + # MD5sum |
1503 | + elif line[0] == 'M' and line[1] == 'D': |
1504 | + current.checksums['MD5sum'] = line[8:-1] |
1505 | + elif line[0] == '\n' and current.name != '': |
1506 | + # Finished reading this package, append it |
1507 | + # Set the packages installed version |
1508 | + __update_package(current, installed, packages) |
1509 | + packages[current.name] = current |
1510 | + current = Package('', checksums={}) |
1511 | + |
1512 | + return packages |
1513 | + |
1514 | + |
1515 | +def __update_package(package, installed, packages): |
1516 | + """Update package information based on packages already installed. |
1517 | + |
1518 | + :param Package package: the package to be compared to installed packages |
1519 | + :param dict installed: the dict of currently installed packages |
1520 | + :param dict packages: the dict of already-parsed packages |
1521 | + """ |
1522 | + # Package already exists so update values if need be |
1523 | + if package.name in packages: |
1524 | + if version_compare(packages[package.name].version, package.version) \ |
1525 | + == 2: |
1526 | + return # If it's an older one, skip it |
1527 | + |
1528 | + # If there's no installed version, move on. |
1529 | + if package.name not in installed: |
1530 | + return |
1531 | + |
1532 | + installed_version = installed[package.name].version |
1533 | + package.status = version_compare(installed_version, package.version) |
1534 | + package.installed_version = installed_version |
1535 | + |
1536 | + packages[package.name] = package # Set package info |
1537 | + |
1538 | + |
1539 | +def __grab_files(directory): |
1540 | + """Grab files necessary for a Debian project. |
1541 | + |
1542 | + :param str directory: the directory to place APT files in |
1543 | + """ |
1544 | + dir_lists = path_join(directory, 'lists') |
1545 | + dir_sources = path_join(directory, 'sources') |
1546 | + |
1547 | + shutil.copytree('/etc/apt/', dir_sources) |
1548 | + try: |
1549 | + shutil.copytree('/var/lib/apt/lists/', dir_lists) |
1550 | + except shutil.Error: |
1551 | + # Certain files in this directory require root. There's no more specific |
1552 | + # error to catch. If for some reason not all the necessary files get |
1553 | + # copied, that'll be dealt with in the code that uses them. |
1554 | + pass |
1555 | + shutil.copyfile('/var/lib/dpkg/status', |
1556 | + path_join(dir_lists, 'status')) |
1557 | + shutil.copyfile('/var/lib/dpkg/status', |
1558 | + path_join(dir_lists, 'status.bak')) |
1559 | + |
1560 | + |
1561 | +def __parse_sources(directory): |
1562 | + """Get a list of all deb entries for project. |
1563 | + |
1564 | + :param str directory: the directory holding source files to be parsed |
1565 | + :return: a list of deb source lines from source files in the given dir |
1566 | + :rtype: list |
1567 | + """ |
1568 | + sources = [] |
1569 | + sources_dir = path_join(directory, 'sources') |
1570 | + |
1571 | + # Parse main source file |
1572 | + main_source = path_join(sources_dir, 'sources.list') |
1573 | + if os.path.exists(main_source): |
1574 | + sources += __parse_source_file(main_source) |
1575 | + |
1576 | + # Parse extra source files |
1577 | + sources_d_dir = path_join(sources_dir, 'sources.list.d') |
1578 | + if os.path.exists(sources_d_dir): |
1579 | + for item in os.listdir(sources_d_dir): |
1580 | + if item.endswith('.list'): |
1581 | + sources += __parse_source_file(path_join(sources_d_dir, item)) |
1582 | + |
1583 | + return sources |
1584 | + |
1585 | + |
1586 | +def __parse_source_file(location): |
1587 | + """Get a specific source file's deb (repo/source) entries. |
1588 | + |
1589 | + :param str location: the path to the source file to be parsed |
1590 | + :return: a list of deb lines from this file |
1591 | + :rtype: list |
1592 | + """ |
1593 | + found = [] |
1594 | + infile = open(location) |
1595 | + for line in infile: |
1596 | + # TODO: Add support for more protocols |
1597 | + if line.startswith('deb http://'): |
1598 | + if line.endswith('\n'): |
1599 | + found.append(line[:-1]) |
1600 | + else: |
1601 | + found.append(line) |
1602 | + return found |
1603 | + |
1604 | + |
1605 | +def __files_from_debs(deb_list, arch, directory=''): |
1606 | + """Generates package index filenames based on the given entries from source |
1607 | + file "deb" entries. |
1608 | + |
1609 | + :param list deb_list: a list of deb source lines |
1610 | + :param str arch: either '32bit' or '64bit' |
1611 | + :param str directory: the directory to prepend to the retrieved filenames |
1612 | + :return: the file names/paths for the index files related to the given repos |
1613 | + :rtype: generator |
1614 | + """ |
1615 | + for line in deb_list: |
1616 | + source = Source(line, arch) |
1617 | + for filename in source.filenames: |
1618 | + path = path_join(directory, filename) |
1619 | + yield path |
1620 | + |
1621 | + |
1622 | +def __urls_from_debs(deb_list, arch): |
1623 | + """Return URLs for all index files associated with the repos specified in |
1624 | + deb_list. |
1625 | + |
1626 | + :param list deb_list: a list of deb source lines |
1627 | + :param str arch: either '32bit' or '64bit' |
1628 | + :return: the URLs for the index files related to the given repos |
1629 | + :rtype: generator |
1630 | + """ |
1631 | + for line in deb_list: |
1632 | + source = Source(line, arch) |
1633 | + for url in source.urls: |
1634 | + yield url |
1635 | + |
1636 | + |
1637 | +def __get_installed(directory): |
1638 | + """Get a list of installed packages. |
1639 | + |
1640 | + :param str directory: the directory holding package info files |
1641 | + :return: a dict of installed Packages with package.name as their keys |
1642 | + :rtype: dict(Package) |
1643 | + """ |
1644 | + with open(path_join(directory, 'lists', 'status'), 'r') as status: |
1645 | + installed = {} |
1646 | + current = Package('') |
1647 | + for line in status: |
1648 | + if line.startswith('Package:'): |
1649 | + current.name = line[9:-1] |
1650 | + elif line.startswith('Version:'): |
1651 | + current.version = line[9:-1] |
1652 | + elif line.startswith('Status:'): |
1653 | + current.status = line[8:-1] |
1654 | + elif line.startswith('\n') \ |
1655 | + and current.status == 'install ok installed': |
1656 | + installed[current.name] = current |
1657 | + current = Package('') |
1658 | + |
1659 | + return installed |
1660 | + |
1661 | + |
1662 | +def get_comp_name(): |
1663 | + """Get the name of this computer. |
1664 | + |
1665 | + :return: the name of this computer |
1666 | + :rtype: str |
1667 | + """ |
1668 | + system, node, release, version, machine, processor = platform.uname() |
1669 | + return system |
1670 | + |
1671 | + |
1672 | +def get_os_name(): |
1673 | + """Get the name of this computers operating system. |
1674 | + |
1675 | + :return: the computer's OS name |
1676 | + :rtype: str |
1677 | + """ |
1678 | + process = subprocess.run(['cat', '/etc/issue.net'], stdout=subprocess.PIPE) |
1679 | + output = str(process.stdout) |
1680 | + if process.returncode != 0: |
1681 | + log.error(_('Problem retrieving Debian version')) |
1682 | + os_name = output.split()[0] |
1683 | + return os_name |
1684 | + |
1685 | + |
1686 | +def get_os_version(): |
1687 | + """Get the version of this computer's operating system. |
1688 | + |
1689 | + :return: the OS version |
1690 | + :rtype: str |
1691 | + """ |
1692 | + process = subprocess.run(['cat', '/etc/issue.net'], stdout=subprocess.PIPE) |
1693 | + output = str(process.stdout) |
1694 | + if process.returncode != 0: |
1695 | + log.error(_('Problem retrieving Debian version')) |
1696 | + os_version = output.split()[1] |
1697 | + return os_version |
1698 | + |
1699 | + |
1700 | +def get_os_arch(): |
1701 | + """Get the architecture of this computer's operating system. Return value is |
1702 | + either '32bit' or '64bit'. |
1703 | + |
1704 | + :return: the OS's architecture |
1705 | + :rtype: str |
1706 | + """ |
1707 | + # platform doesn't reliably get the architecture when compiled. So get |
1708 | + # it more cleverly. |
1709 | + process = subprocess.run(['apt-get', '-v'], stdout=subprocess.PIPE) |
1710 | + apt_version = str(process.stdout) |
1711 | + if 'i386' in apt_version: |
1712 | + os_arch = '32bit' |
1713 | + elif 'amd64' in apt_version: |
1714 | + os_arch = '64bit' |
1715 | + else: |
1716 | + log.error(_('Unable to detect architecture. Defaulting to 64-bit. ' |
1717 | + 'If this is incorrect, edit your project\'s ' |
1718 | + 'debian.conf.')) |
1719 | + os_arch = '64bit' |
1720 | + return os_arch |
1721 | + |
1722 | + |
1723 | +def get_kernel_name(): |
1724 | + """Get the name of this computer's kernel. |
1725 | + |
1726 | + :return: the name of the kernel |
1727 | + :rtype: str |
1728 | + """ |
1729 | + system, node, release, version, machine, processor = platform.uname() |
1730 | + return release |
1731 | |
1732 | === added file 'lib/install.sh' |
1733 | --- lib/install.sh 1970-01-01 00:00:00 +0000 |
1734 | +++ lib/install.sh 2017-06-11 16:11:12 +0000 |
1735 | @@ -0,0 +1,101 @@ |
1736 | +#!/bin/sh - |
1737 | +# |
1738 | +# Keryx 0.92.4 install script |
1739 | +# |
1740 | +# Used to transfer the necessary files back to a computer |
1741 | +# from a project so that the downloaded packages can |
1742 | +# be installed. |
1743 | +# |
1744 | +# Usage <script.sh> [<project directory>] ['-move'] |
1745 | +# |
1746 | +# written by jacseen, class=amateur :) |
1747 | +# http://keryxproject.org mailto:keryx@lists.launchpad.net |
1748 | + |
1749 | +if [ -n "$1" ] && [ -e "$1" ] |
1750 | +then |
1751 | +proj="$1" |
1752 | +shift |
1753 | +else |
1754 | +proj="$(pwd)" |
1755 | +fi |
1756 | +cd "$proj" |
1757 | + |
1758 | +if [ -n "$1" ] && [ "$1" = "-move" ] |
1759 | +then |
1760 | +transfer="mov" |
1761 | +else |
1762 | +transfer="copy" |
1763 | +fi |
1764 | + |
1765 | +slists=lists |
1766 | +tlists=/var/lib/apt/lists |
1767 | +#spacks=packages |
1768 | +#tpacks=/var/cache/apt/archives |
1769 | +ssources=sources |
1770 | +tsources=/etc/apt |
1771 | + |
1772 | +#Find all index files, skipping the 'status' files and copy them |
1773 | +cd ./"$slists"/ |
1774 | +if [ ! $? = 0 ] #if cannot cd into lists, not project dir |
1775 | +then |
1776 | +echo "Not project dir: $(pwd)" |
1777 | +exit 65 |
1778 | +fi |
1779 | +filelist=`find -maxdepth 1 -iname '*_dists_*'` |
1780 | + |
1781 | +#TODO:attain lock on folder $tlists to be package-manager-friendly |
1782 | +# will be attained directly with python in later versions |
1783 | + |
1784 | +for fn in $filelist |
1785 | +do |
1786 | +cp -t "$tlists" "$fn" |
1787 | +if [ ! $? = 0 ] |
1788 | +then |
1789 | + echo "Failure when copying list: $fn" |
1790 | + exit 66 |
1791 | +fi |
1792 | +done |
1793 | + |
1794 | +#TODO:release lock on folder $tlists |
1795 | + |
1796 | +### Debs will no longer be moved to the cache. The downloads directory will ### |
1797 | +### Be made Temporary cache. ### |
1798 | + |
1799 | +#Find all downloaded packages and move to cache |
1800 | +#cd ../"$spacks"/ |
1801 | +#filelist=`find -maxdepth 1 -name '*.deb'` |
1802 | + |
1803 | +#TODO:attain lock on folder $tpacks to be package-manager-friendly |
1804 | +# will be attained directly with python in later versions |
1805 | + |
1806 | +#for fn in $filelist |
1807 | +#do |
1808 | +# if [ $transfer = "mov" ] |
1809 | +# then |
1810 | +# mv -f -t "$tpacks" "$fn" |
1811 | +# else |
1812 | +# cp -t "$tpacks" "$fn" |
1813 | +# fi |
1814 | +# if [ ! $? = 0 ] |
1815 | +# then |
1816 | +# echo "Failure when ${transfer}ing package: $fn" |
1817 | +# exit 67 |
1818 | +# fi |
1819 | +#done |
1820 | + |
1821 | +#TODO:release lock on folder $tpacks |
1822 | + |
1823 | +#Update the main sources.list file in case it was changed in keryx |
1824 | + |
1825 | +cd ../"$ssources"/ |
1826 | +cp -t "$tsources" "sources.list" |
1827 | +if [ ! $? = 0 ] |
1828 | +then |
1829 | +echo "Failure when copying sources.list" |
1830 | +exit 68 |
1831 | +fi |
1832 | + |
1833 | +# Update the APT caches with the latest lists |
1834 | +apt-cache gencaches |
1835 | + |
1836 | +exit 0 |
1837 | \ No newline at end of file |
1838 | |
1839 | === modified file 'lib/log.py' |
1840 | --- lib/log.py 2010-02-20 04:17:16 +0000 |
1841 | +++ lib/log.py 2017-06-11 16:11:12 +0000 |
1842 | @@ -16,36 +16,40 @@ |
1843 | # along with this program; if not, write to the Free Software |
1844 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1845 | |
1846 | -import consts |
1847 | +from . import config |
1848 | import logging |
1849 | import os |
1850 | -import sys |
1851 | |
1852 | from logging.handlers import RotatingFileHandler |
1853 | |
1854 | # Make sure the directory exists |
1855 | -if not os.path.exists(consts.dirLog): |
1856 | - os.mkdir(consts.dirLog) |
1857 | - |
1858 | -try: |
1859 | - __logHandler = RotatingFileHandler(consts.fileLog, maxBytes=0, backupCount=2) |
1860 | - __logHandler.doRollover() |
1861 | - __logHandler.setFormatter(logging.Formatter('[%(asctime)s] %(levelname)-7s %(message)s', datefmt='%y-%m-%d %H:%M:%S')) |
1862 | - |
1863 | - logger = logging.getLogger(consts.appNameShort) |
1864 | - logger.setLevel(logging.INFO) |
1865 | - logger.addHandler(__logHandler) |
1866 | -except: |
1867 | - print 'Unable to start Keryx' |
1868 | - print 'Make sure no other instances of Keryx are still running.' |
1869 | - sys.exit(1) |
1870 | +if not os.path.exists(config.log_dir): |
1871 | + os.mkdir(config.log_dir) |
1872 | + |
1873 | +__logHandler = RotatingFileHandler(config.log_path, maxBytes=0, backupCount=2) |
1874 | +__logHandler.doRollover() |
1875 | +__logHandler.setFormatter( |
1876 | + logging.Formatter('[%(asctime)s] %(levelname)-7s %(message)s', |
1877 | + datefmt='%y-%m-%d %H:%M:%S')) |
1878 | + |
1879 | +logger = logging.getLogger(config.name.lower()) |
1880 | +logger.setLevel(logging.INFO) |
1881 | +logger.addHandler(__logHandler) |
1882 | + |
1883 | |
1884 | def info(status): |
1885 | - """Prints status to log file and to console""" |
1886 | + """Print status to log file and to console. |
1887 | + |
1888 | + :param str status: the status to be logged |
1889 | + """ |
1890 | logger.info(status) |
1891 | - print status |
1892 | + print(status) |
1893 | + |
1894 | |
1895 | def error(status): |
1896 | - """Prints error to log file and to console""" |
1897 | + """Print error to log file and to console. |
1898 | + |
1899 | + :param str status: the status to be logged |
1900 | + """ |
1901 | logger.error(status) |
1902 | - print status |
1903 | + print(status) |
1904 | |
1905 | === added file 'lib/package.py' |
1906 | --- lib/package.py 1970-01-01 00:00:00 +0000 |
1907 | +++ lib/package.py 2017-06-11 16:11:12 +0000 |
1908 | @@ -0,0 +1,43 @@ |
1909 | +class Package: |
1910 | + """Represents a package in the APT system, as described in the lists from |
1911 | + some package repository. |
1912 | + """ |
1913 | + def __init__(self, |
1914 | + name, |
1915 | + version='', |
1916 | + description='', |
1917 | + filename='', |
1918 | + size='', |
1919 | + depends='', |
1920 | + recommends='', |
1921 | + pre_depends='', |
1922 | + checksums=None, |
1923 | + status='', |
1924 | + installed_version=''): |
1925 | + """Sets the initial values for this Package. |
1926 | + |
1927 | + :param str name: the name of this package |
1928 | + :param str version: the version of this package |
1929 | + :param str description: the description of this package |
1930 | + :param str filename: the filename of this package |
1931 | + :param str size: the size of this package |
1932 | + :param list depends: a list of packages this one depends on |
1933 | + :type depends: None or list |
1934 | + :param recommends: a list of packages this one recommends |
1935 | + :type recommends: None or list |
1936 | + :param pre_depends: a list of pre-dependencies for this package |
1937 | + :type pre_depends: None or list |
1938 | + :param checksums: a dictionary of algorithm: checksum pairs |
1939 | + :type checksums: None or dict |
1940 | + """ |
1941 | + self.name = name |
1942 | + self.version = version |
1943 | + self.description = description |
1944 | + self.filename = filename |
1945 | + self.size = size |
1946 | + self.depends = depends |
1947 | + self.recommends = recommends |
1948 | + self.pre_depends = pre_depends |
1949 | + self.checksums = checksums |
1950 | + self.status = status |
1951 | + self.installed_version = installed_version |
1952 | |
1953 | === removed file 'lib/plugins.py' |
1954 | --- lib/plugins.py 2010-02-20 04:17:16 +0000 |
1955 | +++ lib/plugins.py 1970-01-01 00:00:00 +0000 |
1956 | @@ -1,88 +0,0 @@ |
1957 | -# -*- coding: utf-8 -*- |
1958 | -# |
1959 | -# Author: Chris Oliver (excid3@gmail.com) |
1960 | -# |
1961 | -# This program is free software; you can redistribute it and/or modify |
1962 | -# it under the terms of the GNU General Public License as published by |
1963 | -# the Free Software Foundation; either version 2 of the License, or |
1964 | -# (at your option) any later version. |
1965 | -# |
1966 | -# This program is distributed in the hope that it will be useful, |
1967 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1968 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1969 | -# GNU Library General Public License for more details. |
1970 | -# |
1971 | -# You should have received a copy of the GNU General Public License |
1972 | -# along with this program; if not, write to the Free Software |
1973 | -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1974 | - |
1975 | -import consts |
1976 | -import os.path |
1977 | -import re |
1978 | -import sys |
1979 | - |
1980 | -import log |
1981 | - |
1982 | -OSPluginList = [] |
1983 | -InterfacePluginList = [] |
1984 | -app = None |
1985 | -fail = False |
1986 | - |
1987 | -class pluginBase(object): |
1988 | - """Used to make sure plugins have necessary functions""" |
1989 | - def __init__(self): pass |
1990 | - def IsOS(self): pass |
1991 | - def cleanup(self): pass |
1992 | - |
1993 | - # Interface plugins |
1994 | - def getWidgets(self, instance): self.app = instance |
1995 | - |
1996 | - # OS Plugins |
1997 | - def createProject(self): pass |
1998 | - def loadProject(self): pass |
1999 | - def loadLocalPackageList(self): pass |
2000 | - def loadInternetPackageList(self): pass |
2001 | - def getDependencies(self): pass |
2002 | - def getSources(self): pass |
2003 | - def installCache(self): pass |
2004 | - def installRepo(self): pass |
2005 | - |
2006 | - |
2007 | -def load(dir, instance, load_interface_plugins=True): |
2008 | - """Enumerates a list of plugins in a directory""" |
2009 | - app = instance |
2010 | - |
2011 | - # Make sure dir exists |
2012 | - if not os.path.isdir(dir): |
2013 | - log.info(_('Cannot find ') + consts.dirPlugins + _(', exiting.')) |
2014 | - return |
2015 | - |
2016 | - # Try to load each file in plugins dir |
2017 | - sys.path.insert(0, dir) |
2018 | - for file in os.listdir(dir): |
2019 | - if file.endswith('.py'): |
2020 | - status = initialize(file) |
2021 | - if status != None: # Plugin loaded correctly |
2022 | - status[1].getWidgets(instance) # Give all interface plugins widget tree |
2023 | - # FIXME: Give plugins that have the attribute set only |
2024 | - if status[2] == 'OS': OSPluginList.append(status) |
2025 | - elif status[2] == 'Interface' and load_interface_plugins: |
2026 | - #status[1].getWidgets(instance) # Give all interface plugins widget tree |
2027 | - InterfacePluginList.append(status) |
2028 | - |
2029 | - if fail: log.info(_('Plugin(s) have failed to load. This may be due to not having python-wxversion installed.')) |
2030 | - |
2031 | -def initialize(file): |
2032 | - """Initializes plugin given filename and returns its instance""" |
2033 | - try: |
2034 | - plugin = __import__(re.sub('\.pyc?$', '', file)) |
2035 | - if not hasattr(plugin, 'PLUGIN_NAME'): return |
2036 | - name = getattr(plugin, 'PLUGIN_NAME') |
2037 | - instance = getattr(plugin, name)() |
2038 | - ptype = getattr(plugin, 'PLUGIN_TYPE') |
2039 | - version = getattr(plugin, 'PLUGIN_VERSION') |
2040 | - log.info(_('Plugin loaded: ') + file[:-3] + ' v' + version) |
2041 | - return [name, instance, ptype, version] |
2042 | - except Exception, e: |
2043 | - log.error(file + _(' failed to load.')) |
2044 | - log.error(e) |
2045 | |
2046 | === modified file 'lib/project.py' |
2047 | --- lib/project.py 2010-02-20 04:17:16 +0000 |
2048 | +++ lib/project.py 2017-06-11 16:11:12 +0000 |
2049 | @@ -17,104 +17,114 @@ |
2050 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
2051 | |
2052 | import os |
2053 | -from threading import Thread |
2054 | - |
2055 | -import consts |
2056 | -import log |
2057 | -import plugins |
2058 | + |
2059 | +import time |
2060 | + |
2061 | +from lib import debian |
2062 | +from . import config |
2063 | +from . import log |
2064 | |
2065 | # Make sure the directory exists |
2066 | -if not os.path.exists(consts.dirProjects): |
2067 | - os.mkdir(consts.dirProjects) |
2068 | - |
2069 | -# List of currently opened projects |
2070 | -projects = [] |
2071 | +if not os.path.exists(config.projects_dir): |
2072 | + os.mkdir(config.projects_dir) |
2073 | + |
2074 | +# The currently-opened project |
2075 | +current = None |
2076 | + |
2077 | + |
2078 | +class ProjectExistsException(Exception): |
2079 | + pass |
2080 | + |
2081 | + |
2082 | +def create_project(project_name): |
2083 | + """Create a project with the given name and plugin.""" |
2084 | + # Get the full path of the new project's directory |
2085 | + project_dir = os.path.join(config.projects_dir, project_name) |
2086 | + |
2087 | + # Make sure a project by that name doesn't already exist |
2088 | + if os.path.exists(project_dir): |
2089 | + raise ProjectExistsException |
2090 | + |
2091 | + # Write the basic project information to the project directory |
2092 | + os.mkdir(project_dir) |
2093 | + |
2094 | + # Write the remaining project information to the project file |
2095 | + debian.create_project(project_name) |
2096 | + |
2097 | + log.info('Created project: ' + project_name) |
2098 | + |
2099 | |
2100 | class Project(object): |
2101 | """Stores project information and common tasks""" |
2102 | - def __init__(self, name="", dir="", plugin="", comp="", os="", ver="", arch="", kernel=""): |
2103 | + def __init__(self, |
2104 | + name='', |
2105 | + directory='', |
2106 | + plugin=None, |
2107 | + comp='', |
2108 | + os_name='', |
2109 | + ver='', |
2110 | + arch='', |
2111 | + kernel=''): |
2112 | self.name = name |
2113 | - self.dir = dir |
2114 | + self.dir = directory |
2115 | self.plugin = plugin |
2116 | - self.computername = comp |
2117 | - self.os = os |
2118 | - self.version = ver |
2119 | - self.architecture = arch |
2120 | - self.kernel = kernel |
2121 | + self.comp_name = comp |
2122 | + self.os_name = os_name |
2123 | + self.os_version = ver |
2124 | + self.os_arch = arch |
2125 | + self.kernel_name = kernel |
2126 | self.packages = {} |
2127 | |
2128 | - def GetData(self): |
2129 | - return [self.name, self.dir, self.os, self.version, self.architecture, self.kernel] |
2130 | + def get_data(self): |
2131 | + return [self.name, |
2132 | + self.dir, |
2133 | + self.os_name, |
2134 | + self.os_version, |
2135 | + self.os_arch, |
2136 | + self.kernel_name] |
2137 | |
2138 | - def SetData(self, name="", dir="", plugin="", comp="", os="", ver="", arch="", kernel=""): |
2139 | + def set_data(self, |
2140 | + name='', |
2141 | + directory='', |
2142 | + plugin=None, |
2143 | + comp='', |
2144 | + os_name='', |
2145 | + ver='', |
2146 | + arch='', |
2147 | + kernel=''): |
2148 | self.name = name |
2149 | - self.dir = dir |
2150 | + self.dir = directory |
2151 | self.plugin = plugin |
2152 | - self.computername = comp |
2153 | - self.os = os |
2154 | - self.version = ver |
2155 | - self.architecture = arch |
2156 | - self.kernel = kernel |
2157 | - |
2158 | - |
2159 | - |
2160 | - """Project manipulation functions""" |
2161 | - |
2162 | - def CreateKeryx(self, name, pluginName, plugin): |
2163 | - """Creates a project""" |
2164 | - try: |
2165 | - #if 1: |
2166 | - dirProj = os.path.join(consts.dirProjects, name) |
2167 | - if os.path.exists(dirProj): return False, '' # False, '' means that files were changed |
2168 | - filename = os.path.join(dirProj, name) + consts.appFileExt |
2169 | - os.mkdir(dirProj) |
2170 | - projFile = open(filename, 'wb') |
2171 | - projFile.write(name + '\n' + pluginName) |
2172 | - projFile.close() |
2173 | - log.info('Created project: ' + name) |
2174 | - plugin.createProject(name) #Create plugin information |
2175 | - return True, filename |
2176 | - except: |
2177 | - return False, name |
2178 | - |
2179 | - def OpenKeryx(self, name): |
2180 | + self.comp_name = comp |
2181 | + self.os_name = os_name |
2182 | + self.os_version = ver |
2183 | + self.os_arch = arch |
2184 | + self.kernel_name = kernel |
2185 | + |
2186 | + def open_project(self, name): |
2187 | """Opens a project""" |
2188 | - try: |
2189 | - infile = open(name, 'rb') |
2190 | - data = infile.read() |
2191 | - infile.close() |
2192 | - data = data.split('\n') |
2193 | - |
2194 | - self.name = data[0] |
2195 | - self.dir = os.path.dirname(name) |
2196 | - self.plugin_name = data[1] |
2197 | - |
2198 | - #Initialize plugin |
2199 | - for item in plugins.OSPluginList: |
2200 | - if item[0] == data[1]: |
2201 | - self.plugin = item[1] # Set plugin to correct one |
2202 | - info = self.plugin.loadProject(self.dir) |
2203 | - |
2204 | - self.computername = info[0] |
2205 | - self.os = info[1] |
2206 | - self.version = info[2] |
2207 | - self.architecture = info[3] |
2208 | - self.kernel = info[4] |
2209 | - |
2210 | - return True |
2211 | - except: |
2212 | - return False |
2213 | - |
2214 | - def getDependencies(self, package): |
2215 | + self.name = name |
2216 | + self.dir = os.path.join(config.projects_dir, name) |
2217 | + |
2218 | + self.comp_name = debian.get_comp_name() |
2219 | + self.os_name = debian.get_os_name() |
2220 | + self.os_version = debian.get_os_version() |
2221 | + self.os_arch = debian.get_os_arch() |
2222 | + self.kernel_name = debian.get_kernel_name() |
2223 | + |
2224 | + def get_dependencies(self, package): |
2225 | """Gets dependencies for package""" |
2226 | - return self.plugin.getDependencies(os.path.join(self.dir, 'packages'), self.packages, package) |
2227 | - |
2228 | - def getUrls(self): |
2229 | - return self.plugin.loadInternetPackageList(self.dir, self.architecture) |
2230 | - |
2231 | - def loadLocal(self, jobID, abortEvent): |
2232 | - self.packages = self.plugin.loadLocalPackageList(self.dir, self.architecture) |
2233 | + return debian.get_dependencies(os.path.join(self.dir, 'packages'), |
2234 | + self.packages, |
2235 | + package) |
2236 | + |
2237 | + def get_urls(self): |
2238 | + return debian.load_remote_package_list(self.dir, self.os_arch) |
2239 | + |
2240 | + def load_local(self, jobID, abortEvent): |
2241 | + self.packages = debian.load_local_package_list(self.dir, self.os_arch) |
2242 | + |
2243 | return True |
2244 | |
2245 | - def getSources(self): |
2246 | - return self.plugin.getSources(self.dir) |
2247 | + def get_sources(self): |
2248 | + return debian.get_sources(self.dir) |
2249 | |
2250 | === added file 'lib/source.py' |
2251 | --- lib/source.py 1970-01-01 00:00:00 +0000 |
2252 | +++ lib/source.py 2017-06-11 16:11:12 +0000 |
2253 | @@ -0,0 +1,41 @@ |
2254 | +from lib import join_url |
2255 | + |
2256 | + |
2257 | +class Source: |
2258 | + """Represents a line from an APT sources file.""" |
2259 | + def __init__(self, line, arch): |
2260 | + """Sets up the source's information based on the given deb line. |
2261 | + |
2262 | + :param str line: a line from an APT sources file |
2263 | + :param str arch: either '32bit' or '64bit' |
2264 | + """ |
2265 | + self.line = line |
2266 | + self.arch = arch |
2267 | + self.urls = self.__get_urls() |
2268 | + self.filenames = self.__get_filenames() |
2269 | + |
2270 | + def __get_urls(self): |
2271 | + """Get the URLs of index files associated with this source.""" |
2272 | + parts = self.line.split() |
2273 | + repo_url = parts[1] |
2274 | + dist = parts[2] |
2275 | + for section in parts[3:]: |
2276 | + url = join_url(repo_url, 'dists', dist, section) |
2277 | + |
2278 | + if self.arch == '32bit': |
2279 | + url = join_url(url, 'binary-i386/Packages.gz') |
2280 | + elif self.arch == '64bit': |
2281 | + url = join_url(url, 'binary-amd64/Packages.gz') |
2282 | + |
2283 | + yield url |
2284 | + |
2285 | + def __get_filenames(self): |
2286 | + """Get a list of filenames for index files in this repo. It's the path |
2287 | + to the file on the server with slashes replaced by underscores and the |
2288 | + .gz file extension removed. |
2289 | + """ |
2290 | + for url in self.urls: |
2291 | + # Simply remove the protocol designator and replace slashes with |
2292 | + # underscores. |
2293 | + path = url.split('//')[1] |
2294 | + yield path.replace('/', '_') |
2295 | |
2296 | === added directory 'lib/tests' |
2297 | === added file 'lib/tests/__init__.py' |
2298 | === added file 'lib/tests/test_source.py' |
2299 | --- lib/tests/test_source.py 1970-01-01 00:00:00 +0000 |
2300 | +++ lib/tests/test_source.py 2017-06-11 16:11:12 +0000 |
2301 | @@ -0,0 +1,14 @@ |
2302 | +from unittest import TestCase |
2303 | +from lib.source import Source |
2304 | + |
2305 | + |
2306 | +class TestSource(TestCase): |
2307 | + def test_urls(self): |
2308 | + source = Source('deb http://security.ubuntu.com/ubuntu xenial-security ' |
2309 | + 'main restricted', |
2310 | + '64bit') |
2311 | + |
2312 | + # Make sure the class knows there are two URLs associated with that line |
2313 | + self.assertEqual(sum(1 for _ in source.urls), 2) |
2314 | + |
2315 | + # TODO: test more things |
2316 | |
2317 | === added file 'lib/version.py' |
2318 | --- lib/version.py 1970-01-01 00:00:00 +0000 |
2319 | +++ lib/version.py 2017-06-11 16:11:12 +0000 |
2320 | @@ -0,0 +1,207 @@ |
2321 | +def version_compare(str1, str2): |
2322 | + ver1 = Version(str1) |
2323 | + ver2 = Version(str2) |
2324 | + |
2325 | + ver_type = ('epoch', 'upstream', 'debian') |
2326 | + test_type = (0, 2, 1) |
2327 | + |
2328 | + parse1 = [] |
2329 | + parse2 = [] |
2330 | + |
2331 | + version_list1 = (ver1.epoch(), ver1.upstream(), ver1.debian_version()) |
2332 | + version_list2 = (ver2.epoch(), ver2.upstream(), ver2.debian_version()) |
2333 | + |
2334 | + for index in range(3): |
2335 | + equal = __compare_info(version_list1[index], version_list2[index], ver_type[index]) |
2336 | + if equal != 0: |
2337 | + break |
2338 | + |
2339 | + return equal |
2340 | + |
2341 | + |
2342 | +def __compare_info(string1, string2, ver_type): |
2343 | + equal = 0 |
2344 | + if string1 and string2: # Both strings contain a value |
2345 | + parse1 = parse_version(string1) |
2346 | + parse2 = parse_version(string2) |
2347 | + |
2348 | + max = len(parse1) |
2349 | + if len(parse1) > len(parse2): |
2350 | + max = len(parse2) |
2351 | + # Go through the parsed list of the version number, broken down by |
2352 | + # type |
2353 | + for count in range(max): |
2354 | + compare1 = parse1[count][1] |
2355 | + type1 = parse1[count][0] |
2356 | + compare2 = parse2[count][1] |
2357 | + type2 = parse2[count][0] |
2358 | + if type1 == 'alpha' and type2 == 'alpha' or \ |
2359 | + type1 == 'num' and type2 == 'num' or \ |
2360 | + type1 == 'delimit' and type2 == 'delimit': |
2361 | + if compare1 < compare2: |
2362 | + equal = 1 |
2363 | + break |
2364 | + elif compare1 > compare2: |
2365 | + equal = 2 |
2366 | + break |
2367 | + elif type1 == 'alpha' and type2 == 'num' or \ |
2368 | + type1 == 'alpha' and type2 == 'delimit' or \ |
2369 | + type1 == 'alpha' and type2 == 'tilde' or \ |
2370 | + type1 == 'num' and type2 == 'tilde' or \ |
2371 | + type1 == 'delimit' and type2 == 'num' or \ |
2372 | + type1 == 'delimit' and type2 == 'tilde': |
2373 | + equal = 2 |
2374 | + break |
2375 | + elif type1 == 'num' and type2 == 'alpha' or \ |
2376 | + type1 == 'num' and type2 == 'delimit' or \ |
2377 | + type1 == 'tilde' and type2 == 'alpha' or \ |
2378 | + type1 == 'tilde' and type2 == 'num' or \ |
2379 | + type1 == 'tilde' and type2 == 'delimit' or \ |
2380 | + type1 == 'delimit' and type2 == 'alpha': |
2381 | + equal = 1 |
2382 | + break |
2383 | + elif type1 == 'tilde' and type2 == 'tilde': |
2384 | + # The more tilde characters, the less its value |
2385 | + if len(str(compare1)) > len(str(compare2)): |
2386 | + equal = 1 |
2387 | + break |
2388 | + elif len(str(compare1)) < len(str(compare2)): |
2389 | + equal = 2 |
2390 | + break |
2391 | + if equal == 0: |
2392 | + if len(parse1) > max: |
2393 | + compare1 = parse1[max][1] |
2394 | + type1 = parse1[max][0] |
2395 | +# print compare1, |
2396 | +# print type1 |
2397 | + if type1 == 'num' or \ |
2398 | + type1 == 'alpha' or \ |
2399 | + type1 == 'delimit': |
2400 | + equal = 2 |
2401 | + elif type1 == 'tilde': |
2402 | + equal = 1 |
2403 | + elif len(parse2) > max: |
2404 | + compare2 = parse2[max][1] |
2405 | + type2 = parse2[max][0] |
2406 | + if type2 == 'num' or \ |
2407 | + type2 == 'alpha' or \ |
2408 | + type2 == 'delimit': |
2409 | + equal = 1 |
2410 | + elif type1 == 'tilde': |
2411 | + equal = 2 |
2412 | + |
2413 | + elif ver_type == 'epoch' and string1 and not string2 or \ |
2414 | + ver_type == 'debian' and not string1 and string2: |
2415 | + equal = 1 |
2416 | + elif ver_type == 'debian' and string1 and not string2 or \ |
2417 | + ver_type == 'epoch' and not string1 and string2: |
2418 | + equal = 2 |
2419 | + |
2420 | + return equal |
2421 | + |
2422 | + |
2423 | +def parse_version(version): |
2424 | + version_list = [] |
2425 | + |
2426 | + # Tracks the current string type (num, alpha, delimit, tilde) |
2427 | + build_type = '' |
2428 | + string_val = '' |
2429 | + |
2430 | + for char in version: |
2431 | + if __type_changed(build_type, char): |
2432 | + # If the build type is not empty (there is a string ready to be |
2433 | + # appended) |
2434 | + if build_type: |
2435 | + if string_val.isdigit(): |
2436 | + # Convert string to integer |
2437 | + version_list.append([build_type, int(string_val)]) |
2438 | + string_val = '' |
2439 | + else: |
2440 | + version_list.append([build_type, string_val]) |
2441 | + string_val = '' |
2442 | + build_type = __get_type(char) |
2443 | + string_val += char |
2444 | + |
2445 | + if build_type: |
2446 | + if string_val.isdigit(): |
2447 | + version_list.append([build_type, int(string_val)]) |
2448 | + else: |
2449 | + version_list.append([build_type, string_val]) |
2450 | + |
2451 | + return version_list # returns a list of [build_type, string_val] |
2452 | + |
2453 | + |
2454 | +def __type_changed(build_type, char): |
2455 | + ret_val = False |
2456 | + |
2457 | + if (char.isdigit() and build_type != 'num') or \ |
2458 | + (char.isalpha() and build_type != 'alpha') or \ |
2459 | + (build_type == 'num' and not char.isdigit()) or \ |
2460 | + (build_type == 'alpha' and not char.isalpha()) or \ |
2461 | + (build_type == 'tilde' and char != '~') or \ |
2462 | + (build_type == 'delimit' and (char == '~' or char.isdigit() or char.isalpha())): |
2463 | + ret_val = True |
2464 | + |
2465 | + return ret_val |
2466 | + |
2467 | + |
2468 | +def __get_type(char): |
2469 | + ret_type = '' |
2470 | + if char.isalpha(): |
2471 | + ret_type = 'alpha' |
2472 | + elif char.isdigit(): |
2473 | + ret_type = 'num' |
2474 | + elif char == '~': |
2475 | + ret_type = 'tilde' |
2476 | + else: |
2477 | + ret_type = 'delimit' |
2478 | + |
2479 | + return ret_type |
2480 | + |
2481 | + |
2482 | +class Version: |
2483 | + """This class represents the version of a package and provides certain tools |
2484 | + to learn information about that version. |
2485 | + """ |
2486 | + def __init__(self, ver_string): |
2487 | + self.version = ver_string |
2488 | + self.epoch_value = self.__get_epoch(self.version) |
2489 | + upstream_deb = self.__get_upstrdeb(self.version) |
2490 | + self.upstream_value = upstream_deb[0] |
2491 | + self.debver_value = upstream_deb[1] |
2492 | + |
2493 | + def epoch(self): |
2494 | + return self.epoch_value |
2495 | + |
2496 | + def upstream(self): |
2497 | + return self.upstream_value |
2498 | + |
2499 | + def debian_version(self): |
2500 | + return self.debver_value |
2501 | + |
2502 | + def __get_epoch(self, str1): |
2503 | + ret_epoch = [] |
2504 | + epoch = str1.split(':') |
2505 | + if len(epoch) > 1: |
2506 | + ret_epoch = epoch[0] |
2507 | + |
2508 | + return ret_epoch |
2509 | + |
2510 | + def __get_upstrdeb(self, str1): |
2511 | + ver_list = [] |
2512 | + version = str1.split('-') |
2513 | + |
2514 | + debver = '' |
2515 | + upstream = '' |
2516 | + |
2517 | + if len(version) > 1: |
2518 | + debver = version[len(version) - 1] |
2519 | + for index in range(len(version) - 1): |
2520 | + if index == 0: |
2521 | + upstream = version[index] |
2522 | + else: |
2523 | + upstream += '-' + version[index] |
2524 | + else: |
2525 | + upstream = str1 |
2526 | + |
2527 | + return [upstream, debver] |
2528 | |
2529 | === modified file 'lib/wxkeryx/__init__.py' |
2530 | --- lib/wxkeryx/__init__.py 2010-02-20 04:17:16 +0000 |
2531 | +++ lib/wxkeryx/__init__.py 2017-06-11 16:11:12 +0000 |
2532 | @@ -16,34 +16,33 @@ |
2533 | # along with this program; if not, write to the Free Software |
2534 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
2535 | |
2536 | -import wx |
2537 | - |
2538 | -from lib import consts, log, project |
2539 | -from main import MainApp |
2540 | -from startDialog import startDialog |
2541 | - |
2542 | -class wxKeryx(wx.App): |
2543 | +import wx |
2544 | +from gettext import gettext as _ |
2545 | + |
2546 | +from lib import config, log, project |
2547 | +from .main import MainApp |
2548 | +from .startDialog import StartDialog |
2549 | + |
2550 | + |
2551 | +class WxKeryx(wx.App): |
2552 | def OnInit(self): |
2553 | log.info(_('wxWidgets interface loaded')) |
2554 | - wx.InitAllImageHandlers() |
2555 | - main = MainApp(None, -1, consts.appName + " v" + consts.appVersion) |
2556 | + main = MainApp(None, -1, config.name + ' v' + config.version) |
2557 | self.SetTopWindow(main) |
2558 | main.Show() |
2559 | main.SetFocus() |
2560 | |
2561 | - start = startDialog(None, -1, '') |
2562 | + start = StartDialog() |
2563 | success = start.ShowModal() |
2564 | start.Destroy() |
2565 | |
2566 | - if success == wx.ID_CANCEL: main.Close() |
2567 | + if success == wx.ID_CANCEL: |
2568 | + main.Close() |
2569 | else: |
2570 | - main.Refresh(project.projects[len(project.projects) - 1].GetData()) |
2571 | + main.Refresh(project.current.get_data()) |
2572 | self.MainLoop() |
2573 | return 1 |
2574 | |
2575 | -# end of class wxKeryx |
2576 | |
2577 | -def Start(): |
2578 | -# import gettext |
2579 | -# gettext.install(consts.appNameShort) |
2580 | - keryx = wxKeryx(0) |
2581 | +def start(): |
2582 | + WxKeryx(0) |
2583 | |
2584 | === modified file 'lib/wxkeryx/delayedresult.py' |
2585 | --- lib/wxkeryx/delayedresult.py 2010-02-20 04:17:16 +0000 |
2586 | +++ lib/wxkeryx/delayedresult.py 2017-06-11 16:11:12 +0000 |
2587 | @@ -1,11 +1,14 @@ |
2588 | -import os.path |
2589 | +import os.path |
2590 | +import urllib |
2591 | import wx |
2592 | -import wx.lib.delayedresult as delayedresult |
2593 | - |
2594 | -import lib |
2595 | -from lib import consts, log |
2596 | - |
2597 | -class thread(wx.Frame): |
2598 | +import wx.lib.delayedresult as delayedresult |
2599 | +from gettext import gettext as _ |
2600 | + |
2601 | +from lib import log |
2602 | +from lib import config |
2603 | + |
2604 | + |
2605 | +class Thread(wx.Frame): |
2606 | """This demos simplistic use of delayedresult module.""" |
2607 | def __init__(self, parent, func, endfunc): |
2608 | wx.Frame.__init__(self, None, title=_("Loading...")) |
2609 | @@ -13,81 +16,64 @@ |
2610 | self.function = func |
2611 | self.endfunction = endfunc |
2612 | |
2613 | - self.SetIcon(wx.Icon(consts.fileIco, wx.BITMAP_TYPE_ICO)) |
2614 | + self.SetIcon(wx.Icon(config.ico_path, wx.BITMAP_TYPE_ICO)) |
2615 | panel = wx.Panel(self) |
2616 | - loading = wx.StaticText(panel, -1, _("This may take a while. Please be patient.")) |
2617 | + loading = wx.StaticText(panel, -1, _("This may take a while. Please be " |
2618 | + "patient.")) |
2619 | self.gauge = wx.Gauge(panel) |
2620 | - #cancelBtn = wx.Button(panel, -1, "Cancel") |
2621 | - |
2622 | - #self.cur = wx.StaticText(panel, -1, "Current Transfer:") |
2623 | - #self.cur.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, "")) |
2624 | - #self.current = wx.StaticText(panel) |
2625 | - #self.download_gauge = wx.Gauge(panel) |
2626 | - #self.status = wx.TextCtrl(panel, style=wx.TE_MULTILINE|wx.TE_READONLY) |
2627 | - |
2628 | - #status = wx.BoxSizer() |
2629 | - #status.Add(self.cur, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5) |
2630 | - #status.Add(self.current, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5) |
2631 | |
2632 | main = wx.BoxSizer(wx.VERTICAL) |
2633 | - main.Add(loading, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5) |
2634 | - main.Add(self.gauge, 0, wx.EXPAND|wx.ALL, 5) |
2635 | - #main.Add(status) |
2636 | - #main.Add(self.download_gauge, 0, wx.EXPAND|wx.ALL, 5) |
2637 | - #main.Add(self.status, 1, wx.EXPAND|wx.ALL, 5) |
2638 | - #main.Add(cancelBtn, 0, wx.ALIGN_RIGHT|wx.ALL, 5) |
2639 | + main.Add(loading, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5) |
2640 | + main.Add(self.gauge, 0, wx.EXPAND | wx.ALL, 5) |
2641 | |
2642 | panel.SetSizer(main) |
2643 | - self.SetSize(wx.Size(300,100)) |
2644 | + self.SetSize(wx.Size(300, 100)) |
2645 | self.Center() |
2646 | self.Show() |
2647 | |
2648 | self.jobID = 0 |
2649 | self.abortEvent = delayedresult.AbortEvent() |
2650 | - self.Bind(wx.EVT_CLOSE, self.OnClose) |
2651 | - #self.Bind(wx.EVT_BUTTON, self.handleAbort, cancelBtn) |
2652 | - self.Bind(wx.EVT_TIMER, self.TimerHandler) |
2653 | + self.Bind(wx.EVT_CLOSE, self.on_close) |
2654 | + self.Bind(wx.EVT_TIMER, self.timer_handler) |
2655 | |
2656 | self.timer = wx.Timer(self) |
2657 | self.timer.Start(100) |
2658 | |
2659 | self.parent.Enable(False) |
2660 | - self.handleGet(None) |
2661 | + self.handle_get(None) |
2662 | |
2663 | - def TimerHandler(self, event): |
2664 | + def timer_handler(self, event): |
2665 | self.gauge.Pulse() |
2666 | |
2667 | - def OnClose(self, event): |
2668 | + def on_close(self, event): |
2669 | """Only needed because in demo, closing the window does not kill the |
2670 | app, so worker thread continues and sends result to dead frame; normally |
2671 | - your app would exit so this would not happen.""" |
2672 | + your app would exit so this would not happen. |
2673 | + """ |
2674 | #if self.buttonAbort.IsEnabled(): |
2675 | #self.log( "Exiting: Aborting job %s" % self.jobID ) |
2676 | - #self.handleAbort(None) |
2677 | + #self.handle_abort(None) |
2678 | self.Show() |
2679 | |
2680 | - def handleGet(self, event): |
2681 | + def handle_get(self, event): |
2682 | """Compute result in separate thread, doesn't affect GUI response.""" |
2683 | - #self.buttonGet.Enable(False) |
2684 | - #self.buttonAbort.Enable(True) |
2685 | self.abortEvent.clear() |
2686 | self.jobID += 1 |
2687 | |
2688 | - #log.info( "Starting job %s in producer thread: GUI remains responsive" |
2689 | - # % self.jobID ) |
2690 | - delayedresult.startWorker(self._resultConsumer, self.function, |
2691 | - wargs=(self.jobID,self.abortEvent), jobID=self.jobID) |
2692 | + delayedresult.startWorker(self._result_consumer, self.function, |
2693 | + wargs=(self.jobID, self.abortEvent), |
2694 | + jobID=self.jobID) |
2695 | |
2696 | - |
2697 | - def _resultProducer(self, jobID, abortEvent): |
2698 | + def _result_producer(self, job_id, abort_event): |
2699 | """Downloads the files in self.files""" |
2700 | |
2701 | msg = "Downloading %i file(s)\n" % len(self.files) |
2702 | - wx.CallAfter(self.LogMessage, msg) |
2703 | + wx.CallAfter(self.log_message, msg) |
2704 | |
2705 | success = True |
2706 | for data in self.files: |
2707 | - if abortEvent(): return [1, self.files] |
2708 | + if abort_event(): |
2709 | + return [1, self.files] |
2710 | |
2711 | url = data[0] |
2712 | file = data[1] |
2713 | @@ -97,61 +83,63 @@ |
2714 | end = end[len(end) - 1] |
2715 | |
2716 | msg = "%s%s %s" % (protocol, site, end) |
2717 | - wx.CallAfter(self.SetFile, msg) |
2718 | + wx.CallAfter(self.set_file, msg) |
2719 | |
2720 | - try: # Attempt to download the file |
2721 | + try: # Attempt to download the file |
2722 | urllib.urlretrieve(url, file, self.progress) |
2723 | - #TODO: Generate md5hashes for these files |
2724 | + # TODO: Generate md5hashes for these files |
2725 | |
2726 | msg = "Success: %s\nSaved to: %s\n" % (url, file) |
2727 | - wx.CallAfter(self.LogMessage, msg) |
2728 | + wx.CallAfter(self.log_message, msg) |
2729 | |
2730 | - except IOError, e: # Failed downloading |
2731 | + except IOError as e: # Failed downloading |
2732 | success = False |
2733 | msg = "Failed: %s\nReason: %s\n" % (url, str(e)) |
2734 | - wx.CallAfter(self.LogMessage, msg) |
2735 | + wx.CallAfter(self.log_message, msg) |
2736 | |
2737 | - if success == True: |
2738 | - wx.CallAfter(self.DisplayMessage,_("All downloads have been completed successfully."), _("Download Complete")) |
2739 | - result = [0,self.files] |
2740 | + if success: |
2741 | + wx.CallAfter(self.display_message, _("All downloads have been " |
2742 | + "completed successfully."), |
2743 | + _("Download Complete")) |
2744 | + result = [0, self.files] |
2745 | else: |
2746 | - wx.CallAfter(self.DisplayMessage, _("Some downloads failed to complete.") + "\n" +_("Please check") + " " + os.path.join(consts.dirLog, "log") + " " + _("for more details."), _("Download Failed")) |
2747 | - result = [1,self.files] |
2748 | + wx.CallAfter(self.display_message, _("Some downloads failed to complete.") + "\n" + _("Please check") + " " + config.log_path + " " + _("for more details."), _("Download Failed")) |
2749 | + result = [1, self.files] |
2750 | return result |
2751 | |
2752 | def progress(self, blocks, size, total): |
2753 | - if blocks*size > total: fraction = float(total)/float(total) |
2754 | - else: fraction = float(blocks*size)/float(total) |
2755 | + if blocks*size > total: |
2756 | + fraction = float(total)/float(total) |
2757 | + else: |
2758 | + fraction = float(blocks*size)/float(total) |
2759 | |
2760 | - wx.CallAfter(self.SetGauge, int(round(fraction*100,2))) |
2761 | + wx.CallAfter(self.set_gauge, int(round(fraction * 100, 2))) |
2762 | |
2763 | - def LogMessage(self, msg): |
2764 | + def log_message(self, msg): |
2765 | log.info(msg) |
2766 | self.status.AppendText(msg) |
2767 | - def DisplayMessage(self, msg, caption): |
2768 | + |
2769 | + def display_message(self, msg, caption): |
2770 | wx.MessageBox(msg, caption) |
2771 | - def SetGauge(self, val): |
2772 | + |
2773 | + def set_gauge(self, val): |
2774 | self.download_gauge.SetValue(val) |
2775 | - def SetFile(self, val): |
2776 | + |
2777 | + def set_file(self, val): |
2778 | self.current.SetLabel(val) |
2779 | |
2780 | - def handleAbort(self, event): |
2781 | + def handle_abort(self, event): |
2782 | """Abort the result computation.""" |
2783 | - log.info( "Aborting result for job %s" % self.jobID ) |
2784 | + log.info("Aborting result for job %s" % self.jobID) |
2785 | #self.buttonGet.Enable(True) |
2786 | #self.buttonAbort.Enable(False) |
2787 | self.abortEvent.set() |
2788 | |
2789 | - |
2790 | - def _resultConsumer(self, delayedResult): |
2791 | - jobID = delayedResult.getJobID() |
2792 | + def _result_consumer(self, delayed_result): |
2793 | + jobID = delayed_result.getJobID() |
2794 | assert jobID == self.jobID |
2795 | - try: |
2796 | - result = delayedResult.get() |
2797 | - except Exception, exc: |
2798 | - log.info( "Result for job %s raised exception: %s" % (jobID, exc) ) |
2799 | - return |
2800 | - |
2801 | + result = delayed_result.get() |
2802 | + |
2803 | # output result |
2804 | #log.info( "Got result for job %s: %s" % (jobID, result) ) |
2805 | self.parent.Enable() |
2806 | |
2807 | === modified file 'lib/wxkeryx/download.py' |
2808 | --- lib/wxkeryx/download.py 2010-02-20 04:17:16 +0000 |
2809 | +++ lib/wxkeryx/download.py 2017-06-11 16:11:12 +0000 |
2810 | @@ -1,48 +1,54 @@ |
2811 | -import os.path |
2812 | -import urllib |
2813 | -import wx |
2814 | +import os.path |
2815 | +import urllib.request |
2816 | +import wx |
2817 | import hashlib |
2818 | -import wx.lib.delayedresult as delayedresult |
2819 | - |
2820 | +import wx.lib.delayedresult as delayedresult |
2821 | +from gettext import gettext as _ |
2822 | + |
2823 | import lib |
2824 | -from lib import consts, log |
2825 | - |
2826 | -class download(wx.Frame): |
2827 | +from lib import log |
2828 | +from lib import config |
2829 | + |
2830 | + |
2831 | +class Download(wx.Frame): |
2832 | """This demos simplistic use of delayedresult module.""" |
2833 | def __init__(self, parent, endfunc, files, extract=False, overwrite=False): |
2834 | - wx.Frame.__init__(self, None, title=_("Downloading...")) |
2835 | + self.theme = config.theme |
2836 | + wx.Frame.__init__(self, parent, title=_('Downloading...')) |
2837 | self.parent = parent |
2838 | self.files = files |
2839 | self.function = endfunc |
2840 | - self.extract = extract |
2841 | - self.overwrite = overwrite |
2842 | + self.extract = extract |
2843 | + self.overwrite = overwrite |
2844 | self.retries = 1 |
2845 | |
2846 | - #TODO: Add overwrite function |
2847 | + # TODO: Add overwrite function |
2848 | |
2849 | - self.SetIcon(wx.Icon(consts.fileIco, wx.BITMAP_TYPE_ICO)) |
2850 | + self.SetIcon(wx.Icon(config.ico_path, wx.BITMAP_TYPE_ICO)) |
2851 | panel = wx.Panel(self) |
2852 | - loading = wx.StaticText(panel, -1, _("This may take a while. Please be patient.")) |
2853 | + loading = wx.StaticText(panel, -1, _('This may take a while. ' |
2854 | + 'Please be patient.')) |
2855 | self.gauge = wx.Gauge(panel) |
2856 | - #cancelBtn = wx.Button(panel, -1, "Cancel") |
2857 | |
2858 | - self.cur = wx.StaticText(panel, -1, _("Current Transfer:")) |
2859 | - self.cur.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, "")) |
2860 | - self.current = wx.StaticText(panel, -1, "\n") |
2861 | + self.cur = wx.StaticText(panel, -1, _('Current Transfer:')) |
2862 | + self.cur.SetFont(wx.Font(8, |
2863 | + wx.FONTFAMILY_DEFAULT, |
2864 | + wx.FONTSTYLE_NORMAL, |
2865 | + wx.FONTWEIGHT_BOLD)) |
2866 | + self.current = wx.StaticText(panel, -1, '\n') |
2867 | self.download_gauge = wx.Gauge(panel) |
2868 | - self.status = wx.TextCtrl(panel, style=wx.TE_MULTILINE|wx.TE_READONLY) |
2869 | + self.status = wx.TextCtrl(panel, style=wx.TE_MULTILINE | wx.TE_READONLY) |
2870 | |
2871 | status = wx.BoxSizer() |
2872 | - status.Add(self.cur, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5) |
2873 | - status.Add(self.current, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5) |
2874 | + status.Add(self.cur, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) |
2875 | + status.Add(self.current, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) |
2876 | |
2877 | main = wx.BoxSizer(wx.VERTICAL) |
2878 | - main.Add(loading, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5) |
2879 | - main.Add(self.gauge, 0, wx.EXPAND|wx.ALL, 5) |
2880 | + main.Add(loading, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5) |
2881 | + main.Add(self.gauge, 0, wx.EXPAND | wx.ALL, 5) |
2882 | main.Add(status) |
2883 | - main.Add(self.download_gauge, 0, wx.EXPAND|wx.ALL, 5) |
2884 | - main.Add(self.status, 1, wx.EXPAND|wx.ALL, 5) |
2885 | - #main.Add(cancelBtn, 0, wx.ALIGN_RIGHT|wx.ALL, 5) |
2886 | + main.Add(self.download_gauge, 0, wx.EXPAND | wx.ALL, 5) |
2887 | + main.Add(self.status, 1, wx.EXPAND | wx.ALL, 5) |
2888 | |
2889 | panel.SetSizer(main) |
2890 | self.Center() |
2891 | @@ -50,218 +56,217 @@ |
2892 | |
2893 | self.jobID = 0 |
2894 | self.abortEvent = delayedresult.AbortEvent() |
2895 | - self.Bind(wx.EVT_CLOSE, self.OnClose) |
2896 | - #self.Bind(wx.EVT_BUTTON, self.handleAbort, cancelBtn) |
2897 | - self.Bind(wx.EVT_TIMER, self.TimerHandler) |
2898 | + self.Bind(wx.EVT_CLOSE, self.on_close) |
2899 | + self.Bind(wx.EVT_TIMER, self.timer_handler) |
2900 | |
2901 | self.timer = wx.Timer(self) |
2902 | self.timer.Start(100) |
2903 | |
2904 | self.parent.Enable(False) |
2905 | - self.handleGet(None) |
2906 | - |
2907 | - def TimerHandler(self, event): self.gauge.Pulse() |
2908 | - |
2909 | - def OnClose(self, event): |
2910 | + self.handle_get(None) |
2911 | + |
2912 | + def timer_handler(self, event): |
2913 | + self.gauge.Pulse() |
2914 | + |
2915 | + def on_close(self, event): |
2916 | """Only needed because in demo, closing the window does not kill the |
2917 | app, so worker thread continues and sends result to dead frame; normally |
2918 | your app would exit so this would not happen.""" |
2919 | #if self.buttonAbort.IsEnabled(): |
2920 | #self.log( "Exiting: Aborting job %s" % self.jobID ) |
2921 | - #self.handleAbort(None) |
2922 | + #self.handle_abort(None) |
2923 | self.Show() |
2924 | |
2925 | - def handleGet(self, event): |
2926 | + def handle_get(self, event): |
2927 | """Compute result in separate thread, doesn't affect GUI response.""" |
2928 | - #self.buttonGet.Enable(False) |
2929 | - #self.buttonAbort.Enable(True) |
2930 | self.abortEvent.clear() |
2931 | self.jobID += 1 |
2932 | |
2933 | - log.info( "Starting job %s in producer thread: GUI remains responsive" |
2934 | - % self.jobID ) |
2935 | - delayedresult.startWorker(self._resultConsumer, self._resultProducer, |
2936 | - wargs=(self.jobID,self.abortEvent), jobID=self.jobID) |
2937 | - |
2938 | - |
2939 | - def _resultProducer(self, jobID, abortEvent): |
2940 | + log.info("Starting job %s in producer thread: GUI remains responsive" % |
2941 | + self.jobID) |
2942 | + delayedresult.startWorker(self._result_consumer, |
2943 | + self._result_producer, |
2944 | + wargs=(self.jobID, self.abortEvent), |
2945 | + jobID=self.jobID) |
2946 | + |
2947 | + def _result_producer(self, jobID, abort_event): |
2948 | """Downloads the files in self.files""" |
2949 | self.numfiles = len(self.files) |
2950 | msg = _("Downloading ") + str(self.numfiles) + " " + _("file(s)") + "\n" |
2951 | - wx.CallAfter(self.LogMessage, msg) |
2952 | + wx.CallAfter(self.log_message, msg) |
2953 | |
2954 | - if consts.proxy_enabled: |
2955 | - if consts.http_proxy['http'][0:7] != 'http://': |
2956 | - proxy = {'http://':consts.http_proxy['http']} |
2957 | - else: |
2958 | - proxy = consts.http_proxy |
2959 | - downloader = Downloader(proxy) |
2960 | - else: |
2961 | - downloader = Downloader() |
2962 | + downloader = Downloader() |
2963 | |
2964 | failed = self.files[:] |
2965 | self.numfile = 0 |
2966 | for data in self.files: |
2967 | - if abortEvent(): return [1, failed] |
2968 | + if abort_event(): |
2969 | + return [1, failed] |
2970 | url = data[0] |
2971 | - filepath = data[1] |
2972 | - end = url.split('/') |
2973 | - protocol = end[0] + '//' |
2974 | - site = end[2] |
2975 | - end = end[len(end) - 1] |
2976 | - if len(data) <= 2: |
2977 | - checksum = {} |
2978 | - else: |
2979 | + filepath = data[1] |
2980 | + end = url.split('/')[-1] |
2981 | + if len(data) <= 2: |
2982 | + checksum = {} |
2983 | + else: |
2984 | checksum = data[2] |
2985 | |
2986 | - msg = _("Starting") + " " + end |
2987 | - wx.CallAfter(self.SetFile, msg) |
2988 | - #TODO: Change this to file progress (move to self.progress) |
2989 | + msg = _('Starting') + ' ' + end |
2990 | + wx.CallAfter(self.set_file, msg) |
2991 | + # TODO: Change this to file progress (move to self.progress) |
2992 | |
2993 | self.curfile = end |
2994 | self.numfile += 1 |
2995 | - if os.path.exists(filepath): |
2996 | - if not self.overwrite: |
2997 | - if self._verify(filepath, checksum) >= 1: |
2998 | - msg = _("Skipped: ") + end + "\n" + _("Reason: ") + _("File already exists.") + "\n" |
2999 | - wx.CallAfter(self.LogMessage, msg) |
3000 | - failed.remove(data) |
3001 | - continue |
3002 | - else: |
3003 | - msg = _("Deleted: ") + filepath + "\n" + _("Reason: ") + _("Existing file failed checksum verify.") + "\n" |
3004 | - wx.CallAfter(self.LogMessage, msg) |
3005 | - os.remove(filepath) |
3006 | - retries = 0 |
3007 | - success = False |
3008 | - while retries <= self.retries: |
3009 | - |
3010 | - try: # Attempt to download the file |
3011 | - msg = _("Downloading: ") + url + "\n" |
3012 | - if retries != 0: msg = _("Retrying: ")+"[%i/%i] " % (retries, self.retries) + url + "\n" |
3013 | - wx.CallAfter(self.LogMessage, msg) |
3014 | + if os.path.exists(filepath): |
3015 | + if not self.overwrite and self._verify(filepath, checksum) >= 1: |
3016 | + msg = _("Skipped: ") + end + "\n" + _("Reason: ") + \ |
3017 | + _("File already exists.") + "\n" |
3018 | + wx.CallAfter(self.log_message, msg) |
3019 | + failed.remove(data) |
3020 | + continue |
3021 | + else: |
3022 | + msg = _("Deleted: ") + filepath + "\n" + \ |
3023 | + _("Reason: ") + \ |
3024 | + _("Existing file failed checksum verify.") + "\n" |
3025 | + wx.CallAfter(self.log_message, msg) |
3026 | + os.remove(filepath) |
3027 | + retries = 0 |
3028 | + success = False |
3029 | + while retries <= self.retries: |
3030 | + try: # Attempt to download the file |
3031 | + msg = _("Downloading: ") + url + "\n" |
3032 | + if retries != 0: |
3033 | + msg = _("Retrying: ") + "[%i/%i] " % (retries, self.retries) + url + "\n" |
3034 | + wx.CallAfter(self.log_message, msg) |
3035 | |
3036 | downloader.retrieve(url, filepath, self.progress) |
3037 | |
3038 | - if self._verify(filepath, checksum) == 0: |
3039 | + if self._verify(filepath, checksum) == 0: |
3040 | msg = _("Failed verify: ") + filepath + "\n" |
3041 | - wx.CallAfter(self.LogMessage, msg) |
3042 | + wx.CallAfter(self.log_message, msg) |
3043 | os.remove(filepath) |
3044 | - retries += 1 |
3045 | + retries += 1 |
3046 | continue |
3047 | |
3048 | - success = True |
3049 | - failed.remove(data) |
3050 | + success = True |
3051 | + failed.remove(data) |
3052 | msg = _("Success: ") + filepath + "\n" |
3053 | - wx.CallAfter(self.LogMessage, msg) |
3054 | - |
3055 | + wx.CallAfter(self.log_message, msg) |
3056 | + |
3057 | if self.extract: |
3058 | msg = _("Extracting") + " " + end |
3059 | - wx.CallAfter(self.SetFile, msg) |
3060 | + wx.CallAfter(self.set_file, msg) |
3061 | try: |
3062 | import gzip |
3063 | infile = gzip.open(filepath, 'rb') |
3064 | - outfile = open(filepath[:-3], 'wb') |
3065 | + outfile = open(filepath.strip('.gz'), 'wb') |
3066 | outfile.write(infile.read()) |
3067 | outfile.close() |
3068 | infile.close() |
3069 | os.remove(filepath) |
3070 | except: # Failed to extract |
3071 | msg = _("Unable to extract: ") + filepath |
3072 | - wx.CallAfter(self.LogMessage, msg) |
3073 | - break |
3074 | - |
3075 | - except IOError, e: # Failed downloading |
3076 | - msg = _("Failed: ") + url + "\n" + _("Reason: ") + str(e) + "\n" |
3077 | - wx.CallAfter(self.LogMessage, msg) |
3078 | - retries += 1 |
3079 | - |
3080 | - |
3081 | - msg = _("Downloaded: ") + str(len(self.files) - len(failed)) + ", " + _("Failed: ") + str(len(failed)) + "\n" |
3082 | - wx.CallAfter(self.LogMessage, msg) |
3083 | - if failed == []: |
3084 | - wx.CallAfter(self.DisplayMessage,_("All downloads have been completed successfully."), _("Download Complete")) |
3085 | - result = [0,failed] |
3086 | - else: |
3087 | - wx.CallAfter(self.DisplayMessage, _("Some downloads failed to complete.") + "\n" +_("Please check") + " " + os.path.join(consts.dirLog, "log") + " " + _("for more details."), _("Download Failed")) |
3088 | - result = [1,failed] |
3089 | - return result |
3090 | - |
3091 | - def _verify(self, filename, checksum, cspriority=['SHA256','SHA1','MD5sum']): |
3092 | - """ Does a hash check on 'filename' as per hashes in 'checksum' dict. Currently only supports sha256, sha1, md5.""" |
3093 | - if cspriority != []: |
3094 | - checks = [x for x in cspriority if checksum.has_key(x)] |
3095 | - if checks == []: return 2 |
3096 | - else: |
3097 | - checks = checksum.keys() |
3098 | - if checks == []: return 2 |
3099 | - |
3100 | - if checks[0] == 'SHA256': |
3101 | - check = hashlib.sha256() |
3102 | - elif checks[0] == 'SHA1': |
3103 | - check = hashlib.sha1() |
3104 | - elif checks[0] == 'MD5sum': |
3105 | - check = hashlib.md5() |
3106 | - else: |
3107 | - return 2 |
3108 | - |
3109 | - try: |
3110 | - fd = open(filename, 'rb') |
3111 | + wx.CallAfter(self.log_message, msg) |
3112 | + break |
3113 | + |
3114 | + except IOError as e: # Failed downloading |
3115 | + msg = _("Failed: ") + url + "\n" + \ |
3116 | + _("Reason: ") + str(e) + "\n" |
3117 | + wx.CallAfter(self.log_message, msg) |
3118 | + retries += 1 |
3119 | + |
3120 | + msg = _("Downloaded: ") + str(len(self.files) - len(failed)) + ", " + \ |
3121 | + _("Failed: ") + str(len(failed)) + "\n" |
3122 | + wx.CallAfter(self.log_message, msg) |
3123 | + """if not failed: |
3124 | + wx.CallAfter(wx.MessageBox, |
3125 | + _('All downloads have been completed successfully.'), |
3126 | + _('Download Complete')) |
3127 | + result = [0, []] |
3128 | + else: |
3129 | + wx.CallAfter(wx.MessageBox, |
3130 | + _("Some downloads failed to complete.") + |
3131 | + "\n" + _("Please check") + " " |
3132 | + + config.log_path + " " |
3133 | + + _("for more details."), _("Download Failed")) |
3134 | + result = [1, failed]""" |
3135 | + return [0, []]#result |
3136 | + |
3137 | + def _verify(self, |
3138 | + filename, |
3139 | + checksum, |
3140 | + cspriority=('SHA256', 'SHA1', 'MD5sum')): |
3141 | + """Does a hash check on 'filename' as per hashes in 'checksum' dict. |
3142 | + Currently only supports sha256, sha1, md5. |
3143 | + """ |
3144 | + if cspriority: |
3145 | + checks = [x for x in cspriority if x in checksum] |
3146 | + if not checks: |
3147 | + return 2 |
3148 | + else: |
3149 | + checks = checksum.keys() |
3150 | + if checks: |
3151 | + return 2 |
3152 | + |
3153 | + if checks[0] == 'SHA256': |
3154 | + check = hashlib.sha256() |
3155 | + elif checks[0] == 'SHA1': |
3156 | + check = hashlib.sha1() |
3157 | + elif checks[0] == 'MD5sum': |
3158 | + check = hashlib.md5() |
3159 | + else: |
3160 | + return 2 |
3161 | + |
3162 | + with open(filename, 'rb') as fd: |
3163 | data = fd.read(1024*64) |
3164 | while data: |
3165 | check.update(data) |
3166 | - data=fd.read(1024*64) |
3167 | - fd.close() |
3168 | - if check.hexdigest() == checksum[checks[0]]: |
3169 | - return 1 |
3170 | - return 0 |
3171 | - except: |
3172 | - return 2 |
3173 | + data = fd.read(1024*64) |
3174 | + if check.hexdigest() == checksum[checks[0]]: |
3175 | + return 1 |
3176 | + return 0 |
3177 | |
3178 | def progress(self, blocks, size, total): |
3179 | - if blocks*size > total: fraction = float(total)/float(total) |
3180 | - else: fraction = float(blocks*size)/float(total) |
3181 | - |
3182 | - wx.CallAfter(self.SetGauge, int(round(fraction*100,2))) |
3183 | - msg = self.curfile + "\n" + str(int(round(fraction*100,2))) + " % of " + lib.convert_file_size(total) + " - File "+ str(self.numfile) + "/" + str(self.numfiles) |
3184 | - wx.CallAfter(self.SetFile, msg) |
3185 | - |
3186 | - def LogMessage(self, msg): |
3187 | + if blocks*size > total: |
3188 | + fraction = float(total)/float(total) |
3189 | + else: |
3190 | + fraction = float(blocks*size)/float(total) |
3191 | + |
3192 | + wx.CallAfter(self.set_gauge, int(round(fraction * 100, 2))) |
3193 | + msg = self.curfile + "\n" + str(int(round(fraction*100, 2))) + \ |
3194 | + " % of " + lib.convert_file_size(total) + " - File " + \ |
3195 | + str(self.numfile) + "/" + str(self.numfiles) |
3196 | + wx.CallAfter(self.set_file, msg) |
3197 | + |
3198 | + def log_message(self, msg): |
3199 | log.info(msg[:-1]) |
3200 | self.status.AppendText(msg) |
3201 | - def DisplayMessage(self, msg, caption): |
3202 | - wx.MessageBox(msg, caption) |
3203 | - def SetGauge(self, val): |
3204 | + |
3205 | + def set_gauge(self, val): |
3206 | self.download_gauge.SetValue(val) |
3207 | - def SetFile(self, val): |
3208 | + |
3209 | + def set_file(self, val): |
3210 | self.current.SetLabel(val) |
3211 | |
3212 | - def handleAbort(self, event): |
3213 | + def handle_abort(self, event): |
3214 | """Abort the result computation.""" |
3215 | - log.info( "Aborting result for job %s" % self.jobID ) |
3216 | + log.info("Aborting result for job %s" % self.jobID) |
3217 | #self.buttonGet.Enable(True) |
3218 | #self.buttonAbort.Enable(False) |
3219 | self.abortEvent.set() |
3220 | |
3221 | - |
3222 | - def _resultConsumer(self, delayedResult): |
3223 | + def _result_consumer(self, delayedResult): |
3224 | jobID = delayedResult.getJobID() |
3225 | assert jobID == self.jobID |
3226 | - try: |
3227 | - result = delayedResult.get() |
3228 | - except Exception, exc: |
3229 | - log.info( "Result for job %s raised exception: %s" % (jobID, exc) ) |
3230 | - return |
3231 | + result = delayedResult.get() |
3232 | |
3233 | # output result |
3234 | #log.info( "Got result for job %s: %s" % (jobID, result) ) |
3235 | self.parent.Enable() |
3236 | - self.Destroy() |
3237 | - if self.function: self.function() |
3238 | - |
3239 | -class Downloader(urllib.FancyURLopener): |
3240 | - def __init__(self, proxy={}): |
3241 | - urllib.FancyURLopener.__init__(self, proxy) |
3242 | - |
3243 | - def prompt_user_passwd(self, host='', realm=''): |
3244 | - return (consts.proxy_username, consts.proxy_password) |
3245 | - |
3246 | + self.DestroyLater() |
3247 | + if self.function: |
3248 | + self.function() |
3249 | + |
3250 | + |
3251 | +class Downloader(urllib.request.FancyURLopener): |
3252 | + def __init__(self): |
3253 | + urllib.request.FancyURLopener.__init__(self, {}) |
3254 | |
3255 | === modified file 'lib/wxkeryx/editor.py' |
3256 | --- lib/wxkeryx/editor.py 2010-02-20 04:17:16 +0000 |
3257 | +++ lib/wxkeryx/editor.py 2017-06-11 16:11:12 +0000 |
3258 | @@ -1,25 +1,26 @@ |
3259 | -import platform |
3260 | +import platform |
3261 | import wx |
3262 | -from lib import consts, project |
3263 | +from lib import config |
3264 | + |
3265 | |
3266 | class FileEditor(wx.Dialog): |
3267 | def __init__(self, window_name, filename): |
3268 | - wx.Dialog.__init__(self, None, -1, window_name)#, size=(300, 300)) |
3269 | - self.SetIcon(wx.Icon(consts.fileIco, wx.BITMAP_TYPE_ICO)) |
3270 | + wx.Dialog.__init__(self, None, -1, window_name) |
3271 | + self.SetIcon(wx.Icon(config.ico_path, wx.BITMAP_TYPE_ICO)) |
3272 | sizer = wx.BoxSizer(wx.VERTICAL) |
3273 | self.txt = wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_RICH2) |
3274 | self.txt.LoadFile(filename) |
3275 | sizer.Add(self.txt, 1, wx.EXPAND|wx.ALL, 3) |
3276 | |
3277 | # Add buttons |
3278 | - btnsizer = wx.StdDialogButtonSizer() |
3279 | - btnSave = wx.Button(self, wx.ID_OK, 'Save') |
3280 | - btnSave.SetDefault() |
3281 | - btnsizer.AddButton(btnSave) |
3282 | - btnCancel = wx.Button(self, wx.ID_CANCEL) |
3283 | - btnsizer.AddButton(btnCancel) |
3284 | - btnsizer.Realize() |
3285 | - sizer.Add(btnsizer, 0, wx.ALIGN_BOTTOM|wx.ALIGN_RIGHT|wx.ALL, 5) |
3286 | + btn_sizer = wx.StdDialogButtonSizer() |
3287 | + btn_save = wx.Button(self, wx.ID_OK, 'Save') |
3288 | + btn_save.SetDefault() |
3289 | + btn_sizer.AddButton(btn_save) |
3290 | + btn_cancel = wx.Button(self, wx.ID_CANCEL) |
3291 | + btn_sizer.AddButton(btn_cancel) |
3292 | + btn_sizer.Realize() |
3293 | + sizer.Add(btn_sizer, 0, wx.ALIGN_BOTTOM|wx.ALIGN_RIGHT|wx.ALL, 5) |
3294 | |
3295 | self.SetSizer(sizer) |
3296 | |
3297 | @@ -30,7 +31,8 @@ |
3298 | def comment(self, event): |
3299 | location = 0 |
3300 | for line in self.txt.GetValue().split('\n'): |
3301 | - if line.find('#') != -1: # line contains a comment |
3302 | - self.txt.SetStyle(location + line.index('#'), len(line)+location, wx.TextAttr("RED")) |
3303 | + if line.find('#') != -1: # line contains a comment |
3304 | + self.txt.SetStyle(location + line.index('#'), |
3305 | + len(line) + location, |
3306 | + wx.TextAttr("RED")) |
3307 | location += len(line) + 1 |
3308 | - |
3309 | |
3310 | === modified file 'lib/wxkeryx/main.py' |
3311 | --- lib/wxkeryx/main.py 2010-03-13 19:04:52 +0000 |
3312 | +++ lib/wxkeryx/main.py 2017-06-11 16:11:12 +0000 |
3313 | @@ -18,44 +18,63 @@ |
3314 | |
3315 | import os.path |
3316 | import sys |
3317 | +import webbrowser |
3318 | + |
3319 | +import time |
3320 | import wx |
3321 | +import wx.adv |
3322 | import wx.lib.buttons as buttons |
3323 | -import wx.lib.filebrowsebutton as filebrowse |
3324 | from wx.lib.mixins.listctrl import CheckListCtrlMixin |
3325 | |
3326 | import lib |
3327 | -from lib import consts, log, plugins, project |
3328 | -from startDialog import startDialog |
3329 | -from misc import detailsTab, ProportionalSplitter, VirtualList |
3330 | -from options import optionDialog |
3331 | -from delayedresult import thread |
3332 | -from download import download |
3333 | -from editor import FileEditor |
3334 | +from lib import log, project |
3335 | +from .startDialog import StartDialog |
3336 | +from .misc import DetailsTab, ProportionalSplitter, VirtualList |
3337 | +from .delayedresult import Thread |
3338 | +from .download import Download |
3339 | +from .editor import FileEditor |
3340 | + |
3341 | +from gettext import gettext as _ |
3342 | + |
3343 | +from lib import config |
3344 | + |
3345 | |
3346 | class MainApp(wx.Frame): |
3347 | def __init__(self, *args, **kwds): |
3348 | + self.theme = config.theme |
3349 | kwds["style"] = wx.DEFAULT_FRAME_STYLE |
3350 | wx.Frame.__init__(self, *args, **kwds) |
3351 | - self.splitter = ProportionalSplitter(self)#, style=wx.SP_3D|wx.SP_BORDER) |
3352 | + self.splitter = ProportionalSplitter(self) |
3353 | self.panel = wx.Panel(self.splitter) |
3354 | self.notebook = wx.Notebook(self.panel, -1, style=wx.NB_BOTTOM) |
3355 | - self.project_notebook_pane = wx.Panel(self.notebook, -1, style=wx.TAB_TRAVERSAL) |
3356 | - self.SetIcon(wx.Icon(consts.fileIco, wx.BITMAP_TYPE_ICO)) |
3357 | + self.project_notebook_pane = wx.Panel(self.notebook, |
3358 | + -1, |
3359 | + style=wx.TAB_TRAVERSAL) |
3360 | + self.SetIcon(wx.Icon(config.ico_path, wx.BITMAP_TYPE_ICO)) |
3361 | self.statusbar = self.CreateStatusBar(1, 0) |
3362 | |
3363 | # Side Buttons |
3364 | self.buttonPanel = wx.Panel(self) |
3365 | - self.downloadButton = buttons.GenBitmapTextButton(self.buttonPanel, -1, wx.Bitmap(consts.icon_download), _("Download"))#, size=(95, 25)) |
3366 | - self.updatesButton = buttons.GenBitmapTextButton(self.buttonPanel, -1, wx.Bitmap(consts.icon_updates), _("Get Updates"))#, size=(95, 25)) |
3367 | - self.refreshButton = buttons.GenBitmapTextButton(self.buttonPanel, -1, wx.Bitmap(consts.icon_refresh), _("Refresh"))#, size=(95, 25)) |
3368 | - #self.updateStatusButton = buttons.GenBitmapTextButton(self.buttonPanel, -1, wx.Bitmap(consts.icon_refresh), _("Update Status"))#, size=(95, 25)) |
3369 | + self.downloadButton = buttons.GenBitmapTextButton(self.buttonPanel, |
3370 | + -1, |
3371 | + wx.Bitmap(self.theme.icon_download), |
3372 | + _("Download")) |
3373 | + self.updatesButton = buttons.GenBitmapTextButton(self.buttonPanel, |
3374 | + -1, |
3375 | + wx.Bitmap(self.theme.icon_updates), |
3376 | + _("Get Updates")) |
3377 | + self.refreshButton = buttons.GenBitmapTextButton(self.buttonPanel, |
3378 | + -1, |
3379 | + wx.Bitmap(self.theme.icon_refresh), |
3380 | + _("Refresh")) |
3381 | |
3382 | self.notebook_il = wx.ImageList(16, 16) |
3383 | - self.notebook_il.Add(wx.Bitmap(consts.icon_project_details)) |
3384 | + self.notebook_il.Add(wx.Bitmap(self.theme.icon_project_details)) |
3385 | self.notebook.SetImageList(self.notebook_il) |
3386 | |
3387 | - self.projectDetails = wx.TextCtrl(self.project_notebook_pane, style = wx.TE_MULTILINE | wx.TE_RICH |wx.TE_READONLY) |
3388 | - self.details = detailsTab(self.notebook) |
3389 | + self.projectDetails = wx.TextCtrl(self.project_notebook_pane, |
3390 | + style=wx.TE_MULTILINE | wx.TE_RICH | wx.TE_READONLY) |
3391 | + self.details = DetailsTab(self.notebook) |
3392 | |
3393 | # Create list view |
3394 | self.list = VirtualList(self.splitter, self.details) |
3395 | @@ -67,123 +86,163 @@ |
3396 | self.__do_layout() |
3397 | self.__bind_events() |
3398 | |
3399 | - plugins.load(consts.dirPlugins, self) |
3400 | - for name, instance, type, ver in plugins.InterfacePluginList: instance.start() |
3401 | - |
3402 | - if len(plugins.OSPluginList) < 1: |
3403 | - wx.MessageBox(_("No OS plugins were loaded. Make sure you have OS plugins in ") + |
3404 | - consts.dirPlugins + ". " + _("Check the log for more details.")) |
3405 | - sys.exit(1) |
3406 | - |
3407 | def __popup_menu(self): |
3408 | self.popupmenu = wx.Menu() |
3409 | - #FIXME: popup menu items cannot display bitmap properly? |
3410 | + # FIXME: popup menu items cannot display bitmap properly? |
3411 | item = self.popupmenu.Append(-1, _("Download")) |
3412 | self.Bind(wx.EVT_MENU, self.OnDownload, item) |
3413 | - item = self.popupmenu.Append(-1, _("View Details")) |
3414 | - self.Bind(wx.EVT_MENU, self.OnDetails, item) |
3415 | - self.list.Bind(wx.EVT_CONTEXT_MENU, self.OnShowPopup) |
3416 | + self.list.Bind(wx.EVT_CONTEXT_MENU, self.on_show_popup) |
3417 | |
3418 | def __create_menu(self): |
3419 | # Menu Bar |
3420 | self.menubar = wx.MenuBar() |
3421 | self.fileFile = wx.Menu() |
3422 | - self.fileClose = wx.MenuItem(self.fileFile, wx.NewId(), _("&Close Project...\tCtrl+X"), _("Closes the current project"), wx.ITEM_NORMAL) |
3423 | - self.fileClose.SetBitmap(wx.Bitmap(consts.icon_close)) |
3424 | - self.fileFile.AppendItem(self.fileClose) |
3425 | + self.fileClose = wx.MenuItem(self.fileFile, |
3426 | + wx.NewId(), |
3427 | + _("&Close Project...\tCtrl+X"), |
3428 | + _("Closes the current project"), |
3429 | + wx.ITEM_NORMAL) |
3430 | + self.fileClose.SetBitmap(wx.Bitmap(self.theme.icon_close)) |
3431 | + self.fileFile.Append(self.fileClose) |
3432 | self.fileFile.AppendSeparator() |
3433 | - self.fileQuit = wx.MenuItem(self.fileFile, wx.NewId(), _("&Quit\tCtrl+Q"), _("Quit this application"), wx.ITEM_NORMAL) |
3434 | - self.fileQuit.SetBitmap(wx.Bitmap(consts.icon_quit)) |
3435 | - self.fileFile.AppendItem(self.fileQuit) |
3436 | + self.fileQuit = wx.MenuItem(self.fileFile, |
3437 | + wx.NewId(), |
3438 | + _("&Quit\tCtrl+Q"), |
3439 | + _("Quit this application"), |
3440 | + wx.ITEM_NORMAL) |
3441 | + self.fileQuit.SetBitmap(wx.Bitmap(self.theme.icon_quit)) |
3442 | + self.fileFile.Append(self.fileQuit) |
3443 | self.menubar.Append(self.fileFile, _("&File")) |
3444 | |
3445 | tmp_menu = wx.Menu() |
3446 | - self.editOptions = wx.MenuItem(tmp_menu, wx.NewId(), _("&Options...\tCtrl+O"), _("Open options dialog"), wx.ITEM_NORMAL) |
3447 | - self.editOptions.SetBitmap(wx.Bitmap(consts.icon_options)) |
3448 | - tmp_menu.AppendItem(self.editOptions) |
3449 | - self.menubar.Append(tmp_menu, _("&Edit")) |
3450 | - |
3451 | - tmp_menu = wx.Menu() |
3452 | - self.projRefresh = wx.MenuItem(tmp_menu, wx.NewId(), _("&Refresh\tCtrl+R"), _("Refresh package list"), wx.ITEM_NORMAL) |
3453 | - self.projRefresh.SetBitmap(wx.Bitmap(consts.icon_refresh)) |
3454 | - tmp_menu.AppendItem(self.projRefresh) |
3455 | - tmp_menu.AppendSeparator() |
3456 | - self.projUpdates = wx.MenuItem(tmp_menu, wx.NewId(), _("Get &Updates\tCtrl+U"), _("Grabs all packages that have updates"), wx.ITEM_NORMAL) |
3457 | - self.projUpdates.SetBitmap(wx.Bitmap(consts.icon_updates)) |
3458 | - tmp_menu.AppendItem(self.projUpdates) |
3459 | - self.projDownload = wx.MenuItem(tmp_menu, wx.NewId(), _("&Download Package\tCtrl+D"), _("Downloads selected package"), wx.ITEM_NORMAL) |
3460 | - self.projDownload.SetBitmap(wx.Bitmap(consts.icon_download)) |
3461 | - tmp_menu.AppendItem(self.projDownload) |
3462 | - self.projInstall = wx.MenuItem(tmp_menu, wx.NewId(), _("&Install Packages..."), _("Helps you install packages onto Project Machine"), wx.ITEM_NORMAL) |
3463 | - self.projInstall.SetBitmap(wx.Bitmap(consts.icon_install)) |
3464 | - tmp_menu.AppendItem(self.projInstall) |
3465 | - self.projUpdateStatus = wx.MenuItem(tmp_menu, wx.NewId(), _("&Update Status"), _("Regrabs the list of installed packages"), wx.ITEM_NORMAL) |
3466 | - self.projUpdateStatus.SetBitmap(wx.Bitmap(consts.icon_refresh)) |
3467 | - tmp_menu.AppendItem(self.projUpdateStatus) |
3468 | - tmp_menu.AppendSeparator() |
3469 | - self.projDetails = wx.MenuItem(tmp_menu, wx.NewId(), _("&View Details\tCtrl+V"), _("Shows details of selected package"), wx.ITEM_NORMAL) |
3470 | - self.projDetails.SetBitmap(wx.Bitmap(consts.icon_package)) |
3471 | - tmp_menu.AppendItem(self.projDetails) |
3472 | - tmp_menu.AppendSeparator() |
3473 | - self.projSources = wx.MenuItem(tmp_menu, wx.NewId(), _("&Edit Sources...\tCtrl+E"), _("Edit project sources"), wx.ITEM_NORMAL) |
3474 | - self.projSources.SetBitmap(wx.Bitmap(consts.icon_sources)) |
3475 | - tmp_menu.AppendItem(self.projSources) |
3476 | + self.projRefresh = wx.MenuItem(tmp_menu, |
3477 | + wx.NewId(), |
3478 | + _("&Refresh\tCtrl+R"), |
3479 | + _("Refresh package list"), |
3480 | + wx.ITEM_NORMAL) |
3481 | + self.projRefresh.SetBitmap(wx.Bitmap(self.theme.icon_refresh)) |
3482 | + tmp_menu.Append(self.projRefresh) |
3483 | + tmp_menu.AppendSeparator() |
3484 | + self.projUpdates = wx.MenuItem(tmp_menu, |
3485 | + wx.NewId(), |
3486 | + _("Get &Updates\tCtrl+U"), |
3487 | + _("Grabs all packages that have updates"), |
3488 | + wx.ITEM_NORMAL) |
3489 | + self.projUpdates.SetBitmap(wx.Bitmap(self.theme.icon_updates)) |
3490 | + tmp_menu.Append(self.projUpdates) |
3491 | + self.projDownload = wx.MenuItem(tmp_menu, |
3492 | + wx.NewId(), |
3493 | + _("&Download Package\tCtrl+D"), |
3494 | + _("Downloads selected package"), |
3495 | + wx.ITEM_NORMAL) |
3496 | + self.projDownload.SetBitmap(wx.Bitmap(self.theme.icon_download)) |
3497 | + tmp_menu.Append(self.projDownload) |
3498 | + self.projInstall = wx.MenuItem(tmp_menu, |
3499 | + wx.NewId(), |
3500 | + _("&Install Packages..."), |
3501 | + _("Helps you install packages onto " |
3502 | + "Project Machine"), |
3503 | + wx.ITEM_NORMAL) |
3504 | + self.projInstall.SetBitmap(wx.Bitmap(self.theme.icon_install)) |
3505 | + tmp_menu.Append(self.projInstall) |
3506 | + self.projUpdateStatus = wx.MenuItem(tmp_menu, |
3507 | + wx.NewId(), |
3508 | + _("&Update Status"), |
3509 | + _("Regrabs the list of installed " |
3510 | + "packages"), |
3511 | + wx.ITEM_NORMAL) |
3512 | + self.projUpdateStatus.SetBitmap(wx.Bitmap(self.theme.icon_refresh)) |
3513 | + tmp_menu.Append(self.projUpdateStatus) |
3514 | + tmp_menu.AppendSeparator() |
3515 | + self.projSources = wx.MenuItem(tmp_menu, |
3516 | + wx.NewId(), |
3517 | + _("&Edit Sources...\tCtrl+E"), |
3518 | + _("Edit project sources"), |
3519 | + wx.ITEM_NORMAL) |
3520 | + self.projSources.SetBitmap(wx.Bitmap(self.theme.icon_sources)) |
3521 | + tmp_menu.Append(self.projSources) |
3522 | |
3523 | self.menubar.Append(tmp_menu, _("&Project")) |
3524 | |
3525 | tmp_menu = wx.Menu() |
3526 | - self.helpHomepage = wx.MenuItem(tmp_menu, wx.NewId(), _("&Homepage"), _("Visit the website"), wx.ITEM_NORMAL) |
3527 | - self.helpHomepage.SetBitmap(wx.Bitmap(consts.icon_home)) |
3528 | - tmp_menu.AppendItem(self.helpHomepage) |
3529 | - self.helpTutorial = wx.MenuItem(tmp_menu, wx.NewId(), _("&Tutorial"), _("Read the tutorial"), wx.ITEM_NORMAL) |
3530 | - self.helpTutorial.SetBitmap(wx.Bitmap(consts.icon_book_open)) |
3531 | - tmp_menu.AppendItem(self.helpTutorial) |
3532 | - self.helpOnline = wx.MenuItem(tmp_menu, wx.NewId(), _("&Get Help Online"), _("Visit the forums"), wx.ITEM_NORMAL) |
3533 | - self.helpOnline.SetBitmap(wx.Bitmap(consts.icon_help)) |
3534 | - tmp_menu.AppendItem(self.helpOnline) |
3535 | - self.helpTranslate = wx.MenuItem(tmp_menu, wx.NewId(), _("&Translate This Application"), _("Help translate to other languages"), wx.ITEM_NORMAL) |
3536 | - self.helpTranslate.SetBitmap(wx.Bitmap(consts.icon_translate)) |
3537 | - tmp_menu.AppendItem(self.helpTranslate) |
3538 | - self.helpReport = wx.MenuItem(tmp_menu, wx.NewId(), _("R&eport A Problem"), _("Report a bug"), wx.ITEM_NORMAL) |
3539 | - self.helpReport.SetBitmap(wx.Bitmap(consts.icon_bug_report)) |
3540 | - tmp_menu.AppendItem(self.helpReport) |
3541 | - tmp_menu.AppendSeparator() |
3542 | - self.helpDonate = wx.MenuItem(tmp_menu, wx.NewId(), _("&Donate"), _("Make a donation"), wx.ITEM_NORMAL) |
3543 | - self.helpDonate.SetBitmap(wx.Bitmap(consts.icon_donate)) |
3544 | - tmp_menu.AppendItem(self.helpDonate) |
3545 | - tmp_menu.AppendSeparator() |
3546 | - self.helpAbout = wx.MenuItem(tmp_menu, wx.NewId(), _("&About..."), _("About " + consts.appName), wx.ITEM_NORMAL) |
3547 | - self.helpAbout.SetBitmap(wx.Bitmap(consts.icon_about)) |
3548 | - tmp_menu.AppendItem(self.helpAbout) |
3549 | - self.menubar.Append(tmp_menu, _("&Help")) |
3550 | + self.helpHomepage = wx.MenuItem(tmp_menu, |
3551 | + wx.NewId(), |
3552 | + _("&Homepage"), |
3553 | + _("Visit the website"), |
3554 | + wx.ITEM_NORMAL) |
3555 | + self.helpHomepage.SetBitmap(wx.Bitmap(self.theme.icon_home)) |
3556 | + tmp_menu.Append(self.helpHomepage) |
3557 | + self.helpTutorial = wx.MenuItem(tmp_menu, |
3558 | + wx.NewId(), |
3559 | + _("&Tutorial"), |
3560 | + _("Read the tutorial"), |
3561 | + wx.ITEM_NORMAL) |
3562 | + self.helpTutorial.SetBitmap(wx.Bitmap(self.theme.icon_book_open)) |
3563 | + tmp_menu.Append(self.helpTutorial) |
3564 | + self.helpOnline = wx.MenuItem(tmp_menu, |
3565 | + wx.NewId(), |
3566 | + _("&Get Help Online"), |
3567 | + _("Visit the forums"), |
3568 | + wx.ITEM_NORMAL) |
3569 | + self.helpOnline.SetBitmap(wx.Bitmap(self.theme.icon_help)) |
3570 | + tmp_menu.Append(self.helpOnline) |
3571 | + self.helpTranslate = wx.MenuItem(tmp_menu, |
3572 | + wx.NewId(), |
3573 | + _("&Translate This Application"), |
3574 | + _("Help translate to other languages"), |
3575 | + wx.ITEM_NORMAL) |
3576 | + self.helpTranslate.SetBitmap(wx.Bitmap(self.theme.icon_translate)) |
3577 | + tmp_menu.Append(self.helpTranslate) |
3578 | + self.helpReport = wx.MenuItem(tmp_menu, |
3579 | + wx.NewId(), |
3580 | + _("R&eport A Problem"), |
3581 | + _("Report a bug"), |
3582 | + wx.ITEM_NORMAL) |
3583 | + self.helpReport.SetBitmap(wx.Bitmap(self.theme.icon_bug_report)) |
3584 | + tmp_menu.Append(self.helpReport) |
3585 | + tmp_menu.AppendSeparator() |
3586 | + self.helpDonate = wx.MenuItem(tmp_menu, |
3587 | + wx.NewId(), |
3588 | + _("&Donate"), |
3589 | + _("Make a donation"), |
3590 | + wx.ITEM_NORMAL) |
3591 | + self.helpDonate.SetBitmap(wx.Bitmap(self.theme.icon_donate)) |
3592 | + tmp_menu.Append(self.helpDonate) |
3593 | + tmp_menu.AppendSeparator() |
3594 | + self.helpAbout = wx.MenuItem(tmp_menu, |
3595 | + wx.NewId(), |
3596 | + _("&About..."), |
3597 | + _("About " + config.name), |
3598 | + wx.ITEM_NORMAL) |
3599 | + self.helpAbout.SetBitmap(wx.Bitmap(self.theme.icon_about)) |
3600 | + tmp_menu.Append(self.helpAbout) |
3601 | + self.menubar.Append(tmp_menu, |
3602 | + _("&Help")) |
3603 | self.SetMenuBar(self.menubar) |
3604 | # Menu Bar end |
3605 | |
3606 | def __bind_events(self): |
3607 | - self.Bind(wx.EVT_MENU, self.OnClose, self.fileClose) |
3608 | - self.Bind(wx.EVT_MENU, self.OnQuit, self.fileQuit) |
3609 | - self.Bind(wx.EVT_MENU, self.OnOptions, self.editOptions) |
3610 | - self.Bind(wx.EVT_MENU, self.OnHomepage, self.helpHomepage) |
3611 | - self.Bind(wx.EVT_MENU, self.OnTutorial, self.helpTutorial) |
3612 | - self.Bind(wx.EVT_MENU, self.OnHelpOnline, self.helpOnline) |
3613 | - self.Bind(wx.EVT_MENU, self.OnTranslate, self.helpTranslate) |
3614 | - self.Bind(wx.EVT_MENU, self.OnReport, self.helpReport) |
3615 | - self.Bind(wx.EVT_MENU, self.OnDonate, self.helpDonate) |
3616 | - self.Bind(wx.EVT_MENU, self.OnAbout, self.helpAbout) |
3617 | + self.Bind(wx.EVT_MENU, self.on_close, self.fileClose) |
3618 | + self.Bind(wx.EVT_MENU, self.on_quit, self.fileQuit) |
3619 | + self.Bind(wx.EVT_MENU, self.on_homepage, self.helpHomepage) |
3620 | + self.Bind(wx.EVT_MENU, self.on_tutorial, self.helpTutorial) |
3621 | + self.Bind(wx.EVT_MENU, self.on_help_online, self.helpOnline) |
3622 | + self.Bind(wx.EVT_MENU, self.on_translate, self.helpTranslate) |
3623 | + self.Bind(wx.EVT_MENU, self.on_report, self.helpReport) |
3624 | + self.Bind(wx.EVT_MENU, self.on_donate, self.helpDonate) |
3625 | + self.Bind(wx.EVT_MENU, self.on_about, self.helpAbout) |
3626 | |
3627 | self.Bind(wx.EVT_MENU, self.OnRefresh, self.projRefresh) |
3628 | self.Bind(wx.EVT_MENU, self.OnUpdates, self.projUpdates) |
3629 | self.Bind(wx.EVT_MENU, self.OnDownload, self.projDownload) |
3630 | self.Bind(wx.EVT_MENU, self.OnInstall, self.projInstall) |
3631 | self.Bind(wx.EVT_MENU, self.OnUpdateStatus, self.projUpdateStatus) |
3632 | - self.Bind(wx.EVT_MENU, self.OnDetails, self.projDetails) |
3633 | self.Bind(wx.EVT_MENU, self.OnSources, self.projSources) |
3634 | |
3635 | self.Bind(wx.EVT_BUTTON, self.OnDownload, self.downloadButton) |
3636 | self.Bind(wx.EVT_BUTTON, self.OnRefresh, self.refreshButton) |
3637 | - #self.Bind(wx.EVT_BUTTON, self.OnUpdateStatus, self.updateStatusButton) |
3638 | self.Bind(wx.EVT_BUTTON, self.OnUpdates, self.updatesButton) |
3639 | - self.Bind(wx.EVT_CLOSE, self.Closing) |
3640 | + self.Bind(wx.EVT_CLOSE, self.closing) |
3641 | |
3642 | def __set_properties(self): |
3643 | self.SetSize((700, 500)) |
3644 | @@ -204,14 +263,16 @@ |
3645 | sizer_buttons.Add(self.downloadButton, 0, wx.ALL, 3) |
3646 | sizer_buttons.Add(self.updatesButton, 0, wx.ALL, 3) |
3647 | sizer_buttons.Add(self.refreshButton, 0, wx.ALL, 3) |
3648 | - #sizer_buttons.Add(self.updateStatusButton, 0, wx.ALL, 3) |
3649 | - #sizer_bottom.Add(sizer_buttons, 0, wx.ALIGN_CENTER_VERTICAL, 0) |
3650 | self.buttonPanel.SetSizer(sizer_buttons) |
3651 | |
3652 | sizer_project = wx.BoxSizer(wx.VERTICAL) |
3653 | sizer_project.Add(self.projectDetails, 1, wx.EXPAND, 0) |
3654 | self.project_notebook_pane.SetSizer(sizer_project) |
3655 | - self.notebook.InsertPage(0, self.project_notebook_pane, _("Project Details"), False, 0) |
3656 | + self.notebook.InsertPage(0, |
3657 | + self.project_notebook_pane, |
3658 | + _("Project Details"), |
3659 | + False, |
3660 | + 0) |
3661 | sizer_bottom.Add(self.notebook, 1, wx.EXPAND, 0) |
3662 | self.panel.SetSizer(sizer_bottom) |
3663 | self.notebook.SetSelection(0) |
3664 | @@ -223,143 +284,122 @@ |
3665 | self.Layout() |
3666 | self.Centre() |
3667 | |
3668 | - def OnShowPopup(self, evt): |
3669 | + def on_show_popup(self, evt): |
3670 | pos = evt.GetPosition() |
3671 | pos = self.ScreenToClient(pos) |
3672 | self.PopupMenu(self.popupmenu, pos) |
3673 | |
3674 | - def Closing(self, event): # Cleanup cleanup, everybody do your share |
3675 | - #self.thread.StopThreads() |
3676 | - #self.thread.Destroy() |
3677 | - log.info(_("Cleaning up plugins")) |
3678 | - for name, instance, type, version in plugins.InterfacePluginList: instance.cleanup() |
3679 | + def closing(self, event): # Cleanup cleanup, everybody do your share |
3680 | log.info(_("Shutting down")) |
3681 | self.Destroy() |
3682 | |
3683 | - def OnClose(self, event): |
3684 | + def on_close(self, event): |
3685 | self.list.DeleteAllItems() |
3686 | self.projectDetails.Clear() |
3687 | - self.list.tabpage.SetPackage() |
3688 | - start = startDialog(None, -1, '') |
3689 | + self.list.tabpage.set_package() |
3690 | + start = StartDialog() |
3691 | success = start.ShowModal() |
3692 | start.Destroy() |
3693 | |
3694 | if success == wx.ID_CANCEL: |
3695 | self.Close() |
3696 | else: |
3697 | - self.Refresh(project.projects[len(project.projects) - 1].GetData()) |
3698 | - |
3699 | - def OnQuit(self, event): self.Close() |
3700 | - def OnHomepage(self, event): lib.browserOpen(consts.urlHomepage) |
3701 | - def OnTutorial(self, event): lib.browserOpen(consts.urlTutorial) |
3702 | - def OnHelpOnline(self, event): lib.browserOpen(consts.urlHelp) |
3703 | - def OnTranslate(self, event): lib.browserOpen(consts.urlTranslate) |
3704 | - def OnReport(self, event): lib.browserOpen(consts.urlBug) |
3705 | - def OnDonate(self, event): lib.browserOpen(consts.urlDonate) |
3706 | - def OnAbout(self, event): |
3707 | - info = wx.AboutDialogInfo() |
3708 | - |
3709 | - info.SetIcon(wx.Icon(consts.fileLogo, wx.BITMAP_TYPE_PNG)) |
3710 | - info.SetName(consts.appName) |
3711 | - info.SetVersion(consts.appVersion) |
3712 | - info.SetDescription(consts.description) |
3713 | - info.SetCopyright(consts.copyright) |
3714 | - info.SetWebSite(consts.urlHomepage) |
3715 | - info.SetLicence(consts.license) |
3716 | - info.AddDeveloper(consts.authors) |
3717 | - info.AddDocWriter(consts.docwriters) |
3718 | - info.AddArtist(consts.artists) |
3719 | - info.AddTranslator(consts.translators) |
3720 | - |
3721 | - wx.AboutBox(info) |
3722 | + self.Refresh(lib.project.current.get_data()) |
3723 | + |
3724 | + def on_quit(self, event): |
3725 | + self.Close() |
3726 | + |
3727 | + def on_homepage(self, event): |
3728 | + webbrowser.open(config.homepage_url) |
3729 | + |
3730 | + def on_tutorial(self, event): |
3731 | + webbrowser.open(config.tutorial_url) |
3732 | + |
3733 | + def on_help_online(self, event): |
3734 | + webbrowser.open(config.help_url) |
3735 | + |
3736 | + def on_translate(self, event): |
3737 | + webbrowser.open(config.translate_url) |
3738 | + |
3739 | + def on_report(self, event): |
3740 | + webbrowser.open(config.bug_url) |
3741 | + |
3742 | + def on_donate(self, event): |
3743 | + webbrowser.open(config.donate_url) |
3744 | + |
3745 | + def on_about(self, event): |
3746 | + info = wx.adv.AboutDialogInfo() |
3747 | + |
3748 | + info.SetIcon(wx.Icon(config.logo_path, wx.BITMAP_TYPE_PNG)) |
3749 | + info.SetName(config.name) |
3750 | + info.SetVersion(config.version) |
3751 | + info.SetDescription(config.description) |
3752 | + info.SetCopyright(config.copyright) |
3753 | + info.SetWebSite(config.homepage_url) |
3754 | + info.SetLicence(config.license) |
3755 | + info.AddDeveloper(config.authors) |
3756 | + info.AddDocWriter(config.docwriters) |
3757 | + info.AddArtist(config.artists) |
3758 | + info.AddTranslator(config.translators) |
3759 | + |
3760 | + wx.adv.AboutBox(info) |
3761 | |
3762 | def OnSources(self, event): |
3763 | - proj = project.projects[len(project.projects) - 1] |
3764 | - name = proj.getSources() + _(' - Sources Editor') |
3765 | - edit = FileEditor(name, proj.getSources()) |
3766 | + proj = project.current |
3767 | + name = proj.get_sources() + _(' - Sources Editor') |
3768 | + edit = FileEditor(name, proj.get_sources()) |
3769 | if edit.ShowModal() == wx.ID_OK: |
3770 | - edit.txt.SaveFile(proj.getSources()) |
3771 | - if wx.MessageBox(_("Sources have changed. Would you like to reload the package list?"), _("Save Successful"), wx.YES_NO) == 2: #wx.ID_YES: |
3772 | + edit.txt.SaveFile(proj.get_sources()) |
3773 | + if wx.MessageBox(_("Sources have changed. Would you like to reload " |
3774 | + "the package list?"), |
3775 | + _("Save Successful"), |
3776 | + wx.YES_NO) == 2: #wx.ID_YES: |
3777 | self.OnRefresh(None) |
3778 | edit.Destroy() |
3779 | |
3780 | - def OnOptions(self, event): |
3781 | - options = optionDialog(None, -1, '') |
3782 | - if options.ShowModal() == wx.ID_OK: |
3783 | - # Set settings |
3784 | - consts.proxy_enabled = options.proxyCheckBox.GetValue() |
3785 | - conf = open(consts.file_config, 'w') |
3786 | - conf.write('LogDir=' + options.logCtrl.GetValue() + '\n' + |
3787 | - #'LocaleDir=' + options.localeCtrl.GetValue() + '\n' + |
3788 | - #'PackagesDir=' + options.packagesCtrl.GetValue() + '\n' + |
3789 | - 'PluginsDir=' + options.pluginsCtrl.GetValue() + '\n' + |
3790 | - 'ProjectsDir=' + options.projectsCtrl.GetValue() + '\n' + |
3791 | - 'PixmapsDir=' + options.pixmapsCtrl.GetValue() + '\n' + |
3792 | - 'ThemesDir=' + options.themesCtrl.GetValue() + '\n' + |
3793 | - 'DefaultTheme=' + options.defaultThemeCtrl.GetValue() + '\n' + |
3794 | - 'CurrentTheme=' + options.defaultThemeCtrl.GetValue() + '\n') |
3795 | - |
3796 | - if options.proxyCheckBox.GetValue(): |
3797 | - proxy_url = 'http://%s:%s' % (options.proxy_url.GetValue(), options.proxy_port.GetValue()) |
3798 | - consts.http_proxy = {'http': proxy_url} |
3799 | - conf.write('HTTPProxy=' + proxy_url + '\n' + |
3800 | - 'ProxyUsername=' + options.proxy_username.GetValue() + '\n' + |
3801 | - 'ProxyPassword=' + options.proxy_password.GetValue() + '\n') |
3802 | - conf.close() |
3803 | - wx.MessageBox(_("If you changed a folder location, changes take affect after restarting Keryx."), _("Saved Changes")) |
3804 | - options.Destroy() |
3805 | - |
3806 | def OnDownload(self, event): |
3807 | # Downloads selected package and dependencies |
3808 | - try: |
3809 | - selected = self.list.GetSelectedItem() |
3810 | - if selected: files = project.projects[len(project.projects) - 1].getDependencies(selected[1]) |
3811 | - except: |
3812 | - return |
3813 | - |
3814 | - # Generate filename list. |
3815 | - list = "" |
3816 | - for i in range(len(files)): |
3817 | - list += files[i][0] + "\n" |
3818 | + selected = self.list.get_selected_item() |
3819 | + if selected: |
3820 | + files = project.current.get_dependencies(selected.name) |
3821 | + |
3822 | + # Generate filename list. |
3823 | + list = "" |
3824 | + for f in files: |
3825 | + list += f[0] + "\n" |
3826 | |
3827 | # Confirm downloads |
3828 | - dlg = ScrolledMessageDialog(None, _("Confirm Download"), _("Do you wish to download the following") + " " + str(len(files)) + " " + _("files?"), list) |
3829 | - #dlg = wx.MessageDialog(None, _("Do you wish to download the following") + " " + str(len(files)) + " " + _("files?") + list, _("Confirm Downloads"), wx.YES_NO | wx.ICON_QUESTION) |
3830 | + dlg = ScrolledMessageDialog(None, |
3831 | + _("Confirm Download"), |
3832 | + _("Do you wish to download the following") |
3833 | + + " " + str(len(files)) + " " + _("files?"), |
3834 | + list) |
3835 | result = dlg.ShowModal() == wx.ID_OK |
3836 | dlg.Destroy() |
3837 | |
3838 | # User doesn't want to download them |
3839 | if not result: |
3840 | - self.Refresh(project.projects[len(project.projects) -1].GetData()) |
3841 | - #self.downloadedLists() |
3842 | return |
3843 | |
3844 | # Make sure packages directory exists |
3845 | - dir = os.path.join(project.projects[len(project.projects) -1].dir, 'packages') |
3846 | + dir = os.path.join(project.current.dir, 'packages') |
3847 | if not os.path.exists(dir): |
3848 | os.mkdir(dir) |
3849 | |
3850 | - ######################################################### |
3851 | - # FIXME: Return to the plugin for post download cleanup # |
3852 | - ######################################################### |
3853 | - frame = download(self, None, files) |
3854 | - #self.downloads.files = files |
3855 | - #self.thread.start(self, self.downloads.start, None) #self.downloadedLsts) # Do nothing after the packages are downloaded |
3856 | - #a.start(self, lists.start, None) # New thread |
3857 | - |
3858 | - # If it fails, reset the package lists, in other words, reload the list again. |
3859 | - |
3860 | - #self.download.downloads = files |
3861 | - #self.download.start() |
3862 | - |
3863 | - #FIXME: If any package fails to download, set package installed version to blank |
3864 | - #list of failed files now stored in frame[1] as returned by download.py |
3865 | - |
3866 | + # FIXME: Return to the plugin for post download cleanup |
3867 | + Download(self, None, files) |
3868 | + |
3869 | + # FIXME: If any package fails to download, set package installed version |
3870 | + # to blank list of failed files now stored in frame[1] as returned by |
3871 | + # download.py |
3872 | + |
3873 | def OnInstall(self, event): |
3874 | # Get the necessary information for package installation |
3875 | - projdir = project.projects[len(project.projects) -1].dir |
3876 | + projdir = project.current.dir |
3877 | spacksdir = os.path.join(projdir, 'packages') |
3878 | - spacks = [x for x in os.listdir(spacksdir) if os.path.isfile(os.path.join(spacksdir, x)) and (os.path.splitext(x)[1] == '.deb')] |
3879 | + spacks = [x for x in os.listdir(spacksdir) |
3880 | + if os.path.isfile(os.path.join(spacksdir, x)) and |
3881 | + (os.path.splitext(x)[1] == '.deb')] |
3882 | packnames = sorted([x[:x.find('_')] for x in spacks]) |
3883 | |
3884 | # Ask what packages need to be installed |
3885 | @@ -373,7 +413,7 @@ |
3886 | if result == wx.ID_CANCEL: |
3887 | return |
3888 | |
3889 | - result = project.projects[len(project.projects) - 1].plugin.installCache(project.projects[len(project.projects) -1].dir, 'installcache') |
3890 | + result = project.current.plugin.install_cache(project.current.dir, 'installcache') |
3891 | if not result: |
3892 | wx.MessageBox(_("Failed to update the APT cache. Aborting " \ |
3893 | "installation."), |
3894 | @@ -381,19 +421,18 @@ |
3895 | return |
3896 | |
3897 | # Install the packages |
3898 | - projdir = project.projects[len(project.projects) -1].dir |
3899 | - result = project.projects[len(project.projects) - 1]. \ |
3900 | - plugin.installPacks(projdir, ' '.join(packnames)) |
3901 | + projdir = project.current.dir |
3902 | + result = project.current.plugin.install_packs(projdir, ' '.join(packnames)) |
3903 | if result: |
3904 | - wx.MessageBox(_("Package installation finished. You should update " \ |
3905 | + wx.MessageBox(_("Package installation finished. You should update " |
3906 | "your project status (Project > Update Status)."), |
3907 | _("Installation finished")) |
3908 | else: |
3909 | - wx.MessageBox(_("An error occurred while installing your " \ |
3910 | - "packages. Make sure no other package manager is " \ |
3911 | - "running when you try to Install the packages. " \ |
3912 | - "Check the log for more details.\n\nAnother " \ |
3913 | - "option is installing the packages by hand using " \ |
3914 | + wx.MessageBox(_("An error occurred while installing your " |
3915 | + "packages. Make sure no other package manager is " |
3916 | + "running when you try to Install the packages. " |
3917 | + "Check the log for more details.\n\nAnother " |
3918 | + "option is installing the packages by hand using " |
3919 | "apt-get."), |
3920 | _("Install Error")) |
3921 | |
3922 | @@ -405,97 +444,78 @@ |
3923 | |
3924 | # Make sure we have updates |
3925 | if len(updates) == 0: |
3926 | - return wx.MessageBox(_("No updates available. Your computer is up-to-date."),_("No updates")) |
3927 | + return wx.MessageBox(_("No updates available. Your computer is " |
3928 | + "up-to-date."), |
3929 | + _("No updates")) |
3930 | |
3931 | - # Got a list of package names, lets generate a list of filenames to download |
3932 | + # Got a list of package names, lets generate a list of filenames to |
3933 | + # download |
3934 | for item in updates: |
3935 | - files += project.projects[len(project.projects) - 1].getDependencies(item) |
3936 | + files += project.current.get_dependencies(item) |
3937 | |
3938 | # Make sure packages directory exists |
3939 | - dir = os.path.join(project.projects[len(project.projects) - 1].dir, 'packages') |
3940 | + dir = os.path.join(project.current.dir, 'packages') |
3941 | if not os.path.exists(dir): |
3942 | os.mkdir(dir) |
3943 | |
3944 | - frame = download(self, None, files) |
3945 | - |
3946 | - def OnDetails(self, event): |
3947 | - for i in range(self.notebook.GetPageCount()): # Find the details page and select it |
3948 | - if self.notebook.GetPageText(i) == _("Package Details"): self.notebook.SetSelection(i) |
3949 | - |
3950 | -# def OnOpen(self, event): |
3951 | -# dlg = wx.FileDialog(self, message=_("Choose a file"), |
3952 | -# defaultDir=consts.dirProjects, |
3953 | -# defaultFile="", |
3954 | -# wildcard=consts.wildcard, |
3955 | -# style=wx.OPEN | wx.CHANGE_DIR) |
3956 | - |
3957 | -# # Show the dialog and retrieve the user response. If it is the OK response, |
3958 | -# # process the data |
3959 | -# if dlg.ShowModal() == wx.ID_OK: |
3960 | -# paths = dlg.GetPaths() |
3961 | -# data = project.openKeryx(paths[0]) |
3962 | -# dlg.Destroy() |
3963 | -# if data: |
3964 | -# proj = project.project(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]) |
3965 | -# project.projects[len(project.projects) -1] = proj # variable must be initialized |
3966 | -# self.Refresh(project.projects[len(project.projects) -1].GetData()) |
3967 | - |
3968 | -# def OnNew(self, event): |
3969 | -# dlg = wx.TextEntryDialog(self, _("What would you like to name your new project?"), |
3970 | -# _('New Project'), platform.node()) |
3971 | -# if dlg.ShowModal() == wx.ID_OK: |
3972 | -# response = dlg.GetValue() |
3973 | -# #print response |
3974 | -# dlg.Destroy() |
3975 | + Download(self, None, files) |
3976 | |
3977 | def OnUpdateStatus(self, event): |
3978 | - dlg = wx.MessageDialog(None, _("This will update Keryx about which packages are installed on your computer. Only run this on the computer you created this project on.\n\n" + \ |
3979 | - "Would you like to continue?"), |
3980 | - _("Update Status"), wx.YES_NO | wx.ICON_QUESTION) |
3981 | + dlg = wx.MessageDialog(None, |
3982 | + _("This will update Keryx about which packages " |
3983 | + "are installed on your computer. Only run " |
3984 | + "this on the computer you created this " |
3985 | + "project on.\n\nWould you like to continue?"), |
3986 | + _("Update Status"), wx.YES_NO | wx.ICON_QUESTION) |
3987 | result = dlg.ShowModal() |
3988 | dlg.Destroy() |
3989 | if result == wx.ID_NO: |
3990 | return |
3991 | success = self.UpdateStatus() |
3992 | if success: |
3993 | - dlg = wx.MessageBox(_("Status update Succeeded."), |
3994 | + wx.MessageBox(_("Status update Succeeded."), |
3995 | _("Status Update Succeeded")) |
3996 | self.loadLocal() |
3997 | else: |
3998 | - dlg = wx.MessageBox(_("Status update failed. Try running Keryx as root (using 'sudo')."), |
3999 | - _("Status Update Failed"), wx.ICON_ERROR) |
4000 | + wx.MessageBox(_("Status update failed. Try running Keryx as root " |
4001 | + "(using 'sudo')."), |
4002 | + _("Status Update Failed"), |
4003 | + wx.ICON_ERROR) |
4004 | + |
4005 | def UpdateStatus(self): |
4006 | - project_dir = project.projects[len(project.projects) -1].dir |
4007 | - return project.projects[len(project.projects) - 1].plugin.updateStatus(project_dir) |
4008 | - |
4009 | - |
4010 | + project_dir = project.current.dir |
4011 | + return project.current.plugin.update_status(project_dir) |
4012 | + |
4013 | def OnRefresh(self, event): |
4014 | - self.Refresh(project.projects[len(project.projects) -1].GetData()) |
4015 | + self.Refresh(project.current.get_data()) |
4016 | + |
4017 | def Refresh(self, data): |
4018 | - self.SetTitle(data[0] + " - " + consts.appName + " v" + consts.appVersion) |
4019 | + self.SetTitle(data[0] + " - " + config.name + " v" + config.version) |
4020 | self.projectDetails.Clear() |
4021 | self.projectDetails.AppendText(data[0] + '\n') |
4022 | - if data[2] != '': self.projectDetails.AppendText(_("Operating System:") + '\t' + data[2] + '\n') |
4023 | - if data[3] != '': self.projectDetails.AppendText(_("Version:") + '\t' + data[3] + '\n') |
4024 | - if data[4] != '': self.projectDetails.AppendText(_("Kernel:") + '\t' + data[5] + '\n') |
4025 | - if data[5] != '': self.projectDetails.AppendText(_("Architecture:") + '\t' + data[4] + '\n') |
4026 | - self.projectDetails.AppendText(_("Drive Free Space:") + '\t' + lib.driveFreeSpace() + '\n') |
4027 | - #self.projectDetails.AppendText("%s\n%s\t%s\n%s\t%s\n%s\t%s\n%s\t%s\n%s\t%s" % |
4028 | - # (data[0], os, data[2], v, data[3], k, data[4], a, data[5], f, lib.driveFreeSpace())) |
4029 | + if data[2] != '': |
4030 | + self.projectDetails.AppendText(_("Operating System:") + '\t' + data[2] + '\n') |
4031 | + if data[3] != '': |
4032 | + self.projectDetails.AppendText(_("Version:") + '\t' + data[3] + '\n') |
4033 | + if data[4] != '': |
4034 | + self.projectDetails.AppendText(_("Kernel:") + '\t' + data[5] + '\n') |
4035 | + if data[5] != '': |
4036 | + self.projectDetails.AppendText(_("Architecture:") + '\t' + data[4] + '\n') |
4037 | + self.projectDetails.AppendText(_("Drive Free Space:") + '\t' + lib.drive_free_space() + '\n') |
4038 | |
4039 | points = self.projectDetails.GetFont().GetPointSize() |
4040 | style = wx.Font(points, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD) |
4041 | self.projectDetails.SetStyle(0, len(data[0]), wx.TextAttr("black", wx.NullColour, style)) |
4042 | |
4043 | # Get index file URLs. |
4044 | - urls = project.projects[len(project.projects) -1].getUrls() |
4045 | + urls = project.current.get_urls() |
4046 | |
4047 | # Inquire whether latest package list should be downloaded |
4048 | - #dlg = wx.MessageDialog(None, _('Download the latest package list?'), |
4049 | - # _("Download latest?"), wx.YES_NO | wx.ICON_QUESTION) |
4050 | urls_string = '\n'.join(['\n'.join(x) for x in urls]) |
4051 | - dlg = ScrolledMessageDialog(None, _("Download Latest?"), |
4052 | - _("Download the latest package lists?"), urls_string) |
4053 | + dlg = ScrolledMessageDialog(None, |
4054 | + _("Download Latest?"), |
4055 | + _("Download the latest package lists?"), |
4056 | + urls_string) |
4057 | |
4058 | result = dlg.ShowModal() |
4059 | dlg.Destroy() |
4060 | @@ -503,29 +523,28 @@ |
4061 | # Load package list |
4062 | self.SetStatusText(_("Loading packages") + "...", 0) |
4063 | |
4064 | - if result == wx.ID_OK: frame = download(self, self.loadLocal, urls, True) |
4065 | - else: self.loadLocal() |
4066 | - |
4067 | + if result == wx.ID_OK: |
4068 | + Download(self, self.loadLocal, urls, True) |
4069 | + else: |
4070 | + self.loadLocal() |
4071 | |
4072 | def loadLocal(self, result=None): |
4073 | #TODO: Verify downloads? |
4074 | - thread(self, project.projects[len(project.projects) - 1].loadLocal, self.loadPackages) |
4075 | + Thread(self, project.current.load_local, self.loadPackages) |
4076 | |
4077 | def loadPackages(self, result=None): |
4078 | - proj = project.projects[len(project.projects) - 1] |
4079 | - #self.thread.Start(project.LocalPackagesThread(proj), None) |
4080 | - self.list.SetMap(proj.packages) |
4081 | - self.list.SortListItems(1, 1) # Sort column 1, ascending A->Z order |
4082 | + proj = project.current |
4083 | + self.list.set_map(proj.packages) |
4084 | + self.list.SortListItems(1) # Sort column 1, ascending A->Z order |
4085 | |
4086 | - self.SetStatusText(str(len(proj.packages.keys())) + " " + _("Packages"),0) |
4087 | + self.SetStatusText(str(len(proj.packages.keys())) + " " + _("Packages"), 0) |
4088 | |
4089 | # end of class MainApp |
4090 | |
4091 | -# Begin mac9416's wonderful custom dialog! |
4092 | |
4093 | class ScrolledMessageDialog(wx.Dialog): |
4094 | def __init__(self, parent, title, caption, msg, |
4095 | - pos=wx.DefaultPosition, size=(400,250), |
4096 | + pos=wx.DefaultPosition, size=(400, 250), |
4097 | style=wx.DEFAULT_DIALOG_STYLE): |
4098 | wx.Dialog.__init__(self, parent, -1, title, pos, size, style) |
4099 | x, y = pos |
4100 | @@ -553,6 +572,7 @@ |
4101 | sizer.Add(btnSizer, 0, wx.ALIGN_RIGHT | wx.TOP | wx.BOTTOM, 10) |
4102 | self.SetSizerAndFit(sizer) |
4103 | |
4104 | + |
4105 | class SelectPackagesDialog(wx.Dialog): |
4106 | """Dialog for selection of packages to be installed""" |
4107 | def __init__(self, parent, id, title, items): |
4108 | @@ -602,6 +622,7 @@ |
4109 | for index in range(self.check_list.list.GetItemCount()): |
4110 | self.check_list.list.CheckItem(index, False) |
4111 | |
4112 | + |
4113 | class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin): |
4114 | def __init__(self, parent): |
4115 | wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT) |
4116 | @@ -611,6 +632,7 @@ |
4117 | def OnItemActivated(self, evt): |
4118 | self.ToggleItem(evt.m_itemIndex) |
4119 | |
4120 | + |
4121 | class CheckListPanel(wx.Panel): |
4122 | def __init__(self, parent, items): |
4123 | wx.Panel.__init__(self, parent, -1) |
4124 | |
4125 | === modified file 'lib/wxkeryx/misc.py' |
4126 | --- lib/wxkeryx/misc.py 2010-02-20 04:17:16 +0000 |
4127 | +++ lib/wxkeryx/misc.py 2017-06-11 16:11:12 +0000 |
4128 | @@ -16,158 +16,176 @@ |
4129 | # along with this program; if not, write to the Free Software |
4130 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
4131 | |
4132 | -import os.path |
4133 | -import urllib |
4134 | import wx |
4135 | -import wx.lib.delayedresult as delayedresult |
4136 | -import wx.lib.mixins.listctrl as listmix |
4137 | - |
4138 | +import wx.lib.mixins.listctrl as listmix |
4139 | +from gettext import gettext as _ |
4140 | + |
4141 | import lib |
4142 | -from lib import consts, log |
4143 | - |
4144 | -class VirtualList(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ColumnSorterMixin): |
4145 | - def __init__(self, parent, tabpage, data = {}): |
4146 | - wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_SINGLE_SEL|wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES) |
4147 | +from lib import config |
4148 | +from lib.package import Package |
4149 | + |
4150 | + |
4151 | +class VirtualList(wx.ListCtrl, |
4152 | + listmix.ListCtrlAutoWidthMixin, |
4153 | + listmix.ColumnSorterMixin): |
4154 | + def __init__(self, parent, tabpage, data={}): |
4155 | + self.theme = config.theme |
4156 | + wx.ListCtrl.__init__(self, |
4157 | + parent, |
4158 | + -1, |
4159 | + style=wx.LC_SINGLE_SEL | |
4160 | + wx.LC_REPORT | |
4161 | + wx.LC_VIRTUAL | |
4162 | + wx.LC_HRULES | |
4163 | + wx.LC_VRULES) |
4164 | self.tabpage = tabpage |
4165 | # Add some art |
4166 | self.il = wx.ImageList(16, 16) |
4167 | - self.sm_up = self.il.Add(wx.Bitmap(consts.icon_arrow_up)) |
4168 | - self.sm_dn = self.il.Add(wx.Bitmap(consts.icon_arrow_down)) |
4169 | - self.uptodate = self.il.Add(wx.Bitmap(consts.icon_uptodate)) |
4170 | - self.update = self.il.Add(wx.Bitmap(consts.icon_update)) |
4171 | - self.error = self.il.Add(wx.Bitmap(consts.icon_error)) |
4172 | - self.downloaded = self.il.Add(wx.Bitmap(consts.icon_downloaded)) |
4173 | + self.sm_up = self.il.Add(wx.Bitmap(self.theme.icon_arrow_up)) |
4174 | + self.sm_dn = self.il.Add(wx.Bitmap(self.theme.icon_arrow_down)) |
4175 | + self.uptodate = self.il.Add(wx.Bitmap(self.theme.icon_uptodate)) |
4176 | + self.update = self.il.Add(wx.Bitmap(self.theme.icon_update)) |
4177 | + self.error = self.il.Add(wx.Bitmap(self.theme.icon_error)) |
4178 | + self.downloaded = self.il.Add(wx.Bitmap(self.theme.icon_downloaded)) |
4179 | self.SetImageList(self.il, wx.IMAGE_LIST_SMALL) |
4180 | |
4181 | # Add some attributes (colourful background for each item rows) |
4182 | self.attrUpdate = wx.ListItemAttr() |
4183 | - self.attrUpdate.SetBackgroundColour("light blue") # blue |
4184 | + self.attrUpdate.SetBackgroundColour("light blue") # blue |
4185 | self.attrUptodate = wx.ListItemAttr() |
4186 | - self.attrUptodate.SetBackgroundColour(wx.Color(150, 235, 140)) # green |
4187 | + self.attrUptodate.SetBackgroundColour(wx.Colour(150, 235, 140)) # green |
4188 | self.attrError = wx.ListItemAttr() |
4189 | - self.attrError.SetBackgroundColour(wx.Color(255, 118, 106)) # red |
4190 | + self.attrError.SetBackgroundColour(wx.Colour(255, 118, 106)) # red |
4191 | self.attrDownloaded = wx.ListItemAttr() |
4192 | - self.attrDownloaded.SetBackgroundColour(wx.Color(255, 215, 100)) # yellow |
4193 | + self.attrDownloaded.SetBackgroundColour(wx.Colour(255, 215, 100)) # yellow |
4194 | |
4195 | # Build the columns |
4196 | count = 0 |
4197 | - for title, width in consts.columns: |
4198 | + |
4199 | + columns = [(_('S'), 50), |
4200 | + (_('Package Name'), 200), |
4201 | + (_('Installed Version'), 200), |
4202 | + (_('Latest Version'), 200), |
4203 | + (_('Description'), 200)] |
4204 | + |
4205 | + for title, width in columns: |
4206 | self.InsertColumn(count, title) |
4207 | self.SetColumnWidth(count, width) |
4208 | count += 1 |
4209 | - #self.InsertColumn(0, _("S")) |
4210 | - #self.InsertColumn(1, _("Package Name")) |
4211 | - #self.InsertColumn(2, _("Installed Version")) |
4212 | - #self.InsertColumn(3, _("Latest Version")) |
4213 | - #self.InsertColumn(4, _("Description")) |
4214 | - |
4215 | - #self.SetColumnWidth(0, 50) |
4216 | - #self.SetColumnWidth(1, 200) |
4217 | - #self.SetColumnWidth(2, 200) |
4218 | - #self.SetColumnWidth(3, 200) |
4219 | - #self.SetColumnWidth(4, 200) |
4220 | - |
4221 | - #These two should probably be passed to init more cleanly |
4222 | - #setting the numbers of items = number of elements in the dictionary |
4223 | - self.SetMap(data) |
4224 | + |
4225 | + # These two should probably be passed to init more cleanly setting the |
4226 | + # numbers of items = number of elements in the dictionary |
4227 | + self.set_map(data) |
4228 | self.currentItem = None |
4229 | |
4230 | - #mixins |
4231 | + # mixins |
4232 | listmix.ListCtrlAutoWidthMixin.__init__(self) |
4233 | listmix.ColumnSorterMixin.__init__(self, 3) |
4234 | |
4235 | - #sort by genre (column 2), A->Z ascending order (1) |
4236 | - #self.SortListItems(0, 1) |
4237 | - |
4238 | - #events |
4239 | - self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected) |
4240 | - self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated) |
4241 | - self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnItemDeselected) |
4242 | - |
4243 | - def SetMap(self, dataMap): |
4244 | - self.itemDataMap = dataMap |
4245 | - self.itemIndexMap = dataMap.keys() |
4246 | - self.SetItemCount(len(dataMap)) |
4247 | - self.tabpage.SetPackage() |
4248 | + # events |
4249 | + self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_item_selected) |
4250 | + self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self._on_item_selected) |
4251 | + self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self._on_item_deselected) |
4252 | + |
4253 | + def set_map(self, data_map): |
4254 | + self.itemDataMap = data_map |
4255 | + self.itemIndexMap = data_map.keys() |
4256 | + self.SetItemCount(len(data_map)) |
4257 | + self.tabpage.set_package() |
4258 | self.Refresh() |
4259 | |
4260 | - def OnColClick(self,event): event.Skip() |
4261 | - |
4262 | - def GetSelectedItem(self): return self.itemDataMap[self.itemIndexMap[self.currentItem]] |
4263 | - |
4264 | - def OnItemSelected(self, event): |
4265 | - self.currentItem = event.m_itemIndex |
4266 | - index=self.itemIndexMap[self.currentItem] |
4267 | - self.tabpage.SetPackage(self.itemDataMap[index]) |
4268 | - |
4269 | - def OnItemActivated(self, event): |
4270 | - self.currentItem = event.m_itemIndex |
4271 | - #print 'item activated' |
4272 | - |
4273 | - def getColumnText(self, index, col): |
4274 | + def on_col_click(self, event): |
4275 | + event.Skip() |
4276 | + |
4277 | + def get_selected_item(self): |
4278 | + return self.itemDataMap[self.itemIndexMap[self.currentItem]] |
4279 | + |
4280 | + def on_item_selected(self, event): |
4281 | + self.currentItem = event.Index |
4282 | + index = self.itemIndexMap[self.currentItem] |
4283 | + self.tabpage.set_package(self.itemDataMap[index]) |
4284 | + |
4285 | + def _on_item_selected(self, event): |
4286 | + self.currentItem = event.m_itemIndex |
4287 | + |
4288 | + def get_column_text(self, index, col): |
4289 | item = self.GetItem(index, col) |
4290 | return item.GetText() |
4291 | |
4292 | - def OnItemDeselected(self, evt): |
4293 | + def _on_item_deselected(self, evt): |
4294 | pass |
4295 | |
4296 | def OnGetItemText(self, item, col): |
4297 | - index=self.itemIndexMap[item] |
4298 | - s = self.itemDataMap[index][col] |
4299 | - return s |
4300 | + index = self.itemIndexMap[item] |
4301 | + if col == 0: |
4302 | + return self.itemDataMap[index].status |
4303 | + elif col == 1: |
4304 | + return self.itemDataMap[index].name |
4305 | + elif col == 2: |
4306 | + return self.itemDataMap[index].installed_version |
4307 | + elif col == 3: |
4308 | + return self.itemDataMap[index].version |
4309 | + elif col == 4: |
4310 | + return self.itemDataMap[index].description |
4311 | |
4312 | def OnGetItemImage(self, item): |
4313 | - index=self.itemIndexMap[item] |
4314 | - icon=self.itemDataMap[index][0] |
4315 | + index = self.itemIndexMap[item] |
4316 | + icon = self.itemDataMap[index].status |
4317 | |
4318 | - if icon==0: |
4319 | + if icon == 0: |
4320 | return self.uptodate |
4321 | - elif icon==1: |
4322 | + elif icon == 1: |
4323 | return self.update |
4324 | - elif icon==2: |
4325 | + elif icon == 2: |
4326 | return self.error |
4327 | - elif icon==3: |
4328 | + elif icon == 3: |
4329 | return self.downloaded |
4330 | else: |
4331 | return -1 |
4332 | |
4333 | def OnGetItemAttr(self, item): |
4334 | - index=self.itemIndexMap[item] |
4335 | - update=self.itemDataMap[index][0] |
4336 | + index = self.itemIndexMap[item] |
4337 | + update = self.itemDataMap[index].status |
4338 | |
4339 | - if update==0: |
4340 | + if update == 0: |
4341 | return self.attrUptodate |
4342 | - elif update==1: |
4343 | + elif update == 1: |
4344 | return self.attrUpdate |
4345 | - elif update==2: |
4346 | + elif update == 2: |
4347 | return self.attrError |
4348 | - elif update==3: |
4349 | + elif update == 3: |
4350 | return self.attrDownloaded |
4351 | else: |
4352 | return None |
4353 | |
4354 | - def SortItems(self,sorter=cmp): |
4355 | + def SortItems(self, sorter): |
4356 | items = list(self.itemDataMap.keys()) |
4357 | - items.sort(sorter) |
4358 | + items.sort() |
4359 | self.itemIndexMap = items |
4360 | |
4361 | # redraw the list |
4362 | self.Refresh() |
4363 | |
4364 | # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py |
4365 | - def GetListCtrl(self): return self |
4366 | + def GetListCtrl(self): |
4367 | + return self |
4368 | |
4369 | # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py |
4370 | - def GetSortImages(self): return (self.sm_dn, self.sm_up) |
4371 | - |
4372 | -# end of class VirtualList |
4373 | - |
4374 | -class detailsTab(object): |
4375 | + def GetSortImages(self): |
4376 | + return (self.sm_dn, self.sm_up) |
4377 | + |
4378 | + |
4379 | +class DetailsTab(object): |
4380 | def __init__(self, notebook): |
4381 | + self.theme = config.theme |
4382 | self.notebook = notebook |
4383 | self.pane = wx.Panel(self.notebook, -1, style=wx.TAB_TRAVERSAL) |
4384 | - index = self.notebook.GetImageList().Add(wx.Bitmap(consts.icon_package)) |
4385 | - self.details = wx.TextCtrl(self.pane, style = wx.TE_MULTILINE | wx.TE_RICH | wx.TE_READONLY) |
4386 | + index = self.notebook.GetImageList().\ |
4387 | + Add(wx.Bitmap(self.theme.icon_package)) |
4388 | + self.details = wx.TextCtrl(self.pane, |
4389 | + style=wx.TE_MULTILINE | |
4390 | + wx.TE_RICH | |
4391 | + wx.TE_READONLY) |
4392 | |
4393 | attr = wx.TextAttr() |
4394 | attr.SetTabs([400]) |
4395 | @@ -178,92 +196,123 @@ |
4396 | self.pane.SetSizer(sizer) |
4397 | self.notebook.AddPage(self.pane, _("Package Details"), False, index) |
4398 | |
4399 | - def SetPackage(self, stats = ['','','','','','','',0]): |
4400 | + def set_package(self, stats=Package('')): |
4401 | self.details.Clear() |
4402 | - if stats[1] == '': return |
4403 | - |
4404 | - update = stats[0] |
4405 | - name = stats[1] |
4406 | - inst = stats[2] |
4407 | - latest = stats[3] |
4408 | - descrip = stats[4] |
4409 | - depends = stats[5] |
4410 | - filename = stats[6] |
4411 | - size = lib.convert_file_size(stats[7]) |
4412 | - |
4413 | - if not name == '': self.details.AppendText(name + '\n') |
4414 | - if not descrip == '': self.details.AppendText(_("Description:\t") + descrip + '\n') |
4415 | - if not inst == '': self.details.AppendText(_("Installed Version:\t") + inst + '\n') |
4416 | - if not latest == '': self.details.AppendText(_("Latest Version:\t") + latest + '\n') |
4417 | - if not depends =='': self.details.AppendText(_("Dependencies:\t") + depends + '\n') |
4418 | - if not size == '': self.details.AppendText(_("Size:\t") + size + '\n') |
4419 | - if not filename == '': self.details.AppendText(_("Filename:\t") + filename + '\n') |
4420 | - #self.details.AppendText("%s\n%s\t%s\n%s\t%s\n%s\t%s\n%s\t%s\n%s\t%s\n%s\t%s" % |
4421 | - # (name, d, descrip, i, inst, l, latest, dep, depends, s, size, f, filename)) |
4422 | + if stats.name == '': |
4423 | + return |
4424 | + |
4425 | + update = stats.status |
4426 | + name = stats.name |
4427 | + inst = stats.installed_version |
4428 | + latest = stats.version |
4429 | + descrip = stats.description |
4430 | + depends = stats.depends |
4431 | + filename = stats.filename |
4432 | + size = lib.convert_file_size(stats.size) |
4433 | + |
4434 | + if not name == '': |
4435 | + self.details.AppendText(name + '\n') |
4436 | + if not descrip == '': |
4437 | + self.details.AppendText(_("Description:\t") + descrip + '\n') |
4438 | + if not inst == '': |
4439 | + self.details.AppendText(_("Installed Version:\t") + inst + '\n') |
4440 | + if not latest == '': |
4441 | + self.details.AppendText(_("Latest Version:\t") + latest + '\n') |
4442 | + if not depends == '': |
4443 | + self.details.AppendText(_("Dependencies:\t") + depends + '\n') |
4444 | + if not size == '': |
4445 | + self.details.AppendText(_("Size:\t") + size + '\n') |
4446 | + if not filename == '': |
4447 | + self.details.AppendText(_("Filename:\t") + filename + '\n') |
4448 | |
4449 | # Fixes scrolling issue |
4450 | self.details.ScrollLines(-15) |
4451 | |
4452 | points = self.details.GetFont().GetPointSize() |
4453 | - style = wx.Font(points, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD) |
4454 | - self.details.SetStyle(0, len(name), wx.TextAttr("black", wx.NullColour, style)) |
4455 | + style = wx.Font(points, |
4456 | + wx.FONTFAMILY_DEFAULT, |
4457 | + wx.FONTSTYLE_NORMAL, |
4458 | + wx.FONTWEIGHT_BOLD) |
4459 | + self.details.SetStyle(0, |
4460 | + len(name), |
4461 | + wx.TextAttr("black", wx.NullColour, style)) |
4462 | |
4463 | -# end of class detailsTab |
4464 | |
4465 | class ProportionalSplitter(wx.SplitterWindow): |
4466 | - def __init__(self,parent, id = -1, proportion=0.60, size = wx.DefaultSize, **kwargs): |
4467 | - wx.SplitterWindow.__init__(self,parent,id,wx.Point(0, 0),size, **kwargs) |
4468 | - self.SetMinimumPaneSize(50) #the minimum size of a pane. |
4469 | - self.proportion = proportion |
4470 | - if not 0 < self.proportion < 1: |
4471 | - raise ValueError, "proportion value for ProportionalSplitter must be between 0 and 1." |
4472 | - self.ResetSash() |
4473 | - self.Bind(wx.EVT_SIZE, self.OnReSize) |
4474 | - self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnSashChanged, id=id) |
4475 | - ##hack to set sizes on first paint event |
4476 | - self.Bind(wx.EVT_PAINT, self.OnPaint) |
4477 | - self.firstpaint = True |
4478 | - |
4479 | - def SplitHorizontally(self, win1, win2): |
4480 | - if self.GetParent() is None: return False |
4481 | - return wx.SplitterWindow.SplitHorizontally(self, win1, win2, |
4482 | - int(round(self.GetParent().GetSize().GetHeight() * self.proportion))) |
4483 | - |
4484 | - def SplitVertically(self, win1, win2): |
4485 | - if self.GetParent() is None: return False |
4486 | - return wx.SplitterWindow.SplitVertically(self, win1, win2, |
4487 | - int(round(self.GetParent().GetSize().GetWidth() * self.proportion))) |
4488 | - |
4489 | - def GetExpectedSashPosition(self): |
4490 | - if self.GetSplitMode() == wx.SPLIT_HORIZONTAL: |
4491 | - tot = max(self.GetMinimumPaneSize(),self.GetParent().GetClientSize().height) |
4492 | - else: |
4493 | - tot = max(self.GetMinimumPaneSize(),self.GetParent().GetClientSize().width) |
4494 | - return int(round(tot * self.proportion)) |
4495 | - |
4496 | - def ResetSash(self): |
4497 | - self.SetSashPosition(self.GetExpectedSashPosition()) |
4498 | - |
4499 | - def OnReSize(self, event): |
4500 | - """Window has been resized, so we need to adjust the sash based on self.proportion.""" |
4501 | - self.ResetSash() |
4502 | - event.Skip() |
4503 | - |
4504 | - def OnSashChanged(self, event): |
4505 | - """We'll change self.proportion now based on where user dragged the sash.""" |
4506 | - pos = float(self.GetSashPosition()) |
4507 | - if self.GetSplitMode() == wx.SPLIT_HORIZONTAL: |
4508 | - tot = max(self.GetMinimumPaneSize(),self.GetParent().GetClientSize().height) |
4509 | - else: |
4510 | - tot = max(self.GetMinimumPaneSize(),self.GetParent().GetClientSize().width) |
4511 | - self.proportion = pos / tot |
4512 | - event.Skip() |
4513 | - |
4514 | - def OnPaint(self,event): |
4515 | - if self.firstpaint: |
4516 | - if self.GetSashPosition() != self.GetExpectedSashPosition(): |
4517 | - self.ResetSash() |
4518 | - self.firstpaint = False |
4519 | - event.Skip() |
4520 | - |
4521 | -# end of class ProportionalSplitter |
4522 | + def __init__(self, |
4523 | + parent, |
4524 | + id=-1, |
4525 | + proportion=0.60, |
4526 | + size=wx.DefaultSize, |
4527 | + **kwargs): |
4528 | + wx.SplitterWindow.__init__(self, |
4529 | + parent, |
4530 | + id, |
4531 | + wx.Point(0, 0), |
4532 | + size, |
4533 | + **kwargs) |
4534 | + self.SetMinimumPaneSize(50) |
4535 | + self.proportion = proportion |
4536 | + if not 0 < self.proportion < 1: |
4537 | + raise ValueError("proportion value for " |
4538 | + "ProportionalSplitter must be between 0 " |
4539 | + "and 1.") |
4540 | + self.ResetSash() |
4541 | + self.Bind(wx.EVT_SIZE, self.OnReSize) |
4542 | + self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, |
4543 | + self.OnSashChanged, |
4544 | + id=id) |
4545 | + self.Bind(wx.EVT_PAINT, self.OnPaint) |
4546 | + self.firstpaint = True |
4547 | + |
4548 | + def SplitHorizontally(self, win1, win2): |
4549 | + if self.GetParent() is None: return False |
4550 | + return wx.SplitterWindow.SplitHorizontally(self, win1, win2, |
4551 | + int(round(self.GetParent().GetSize().GetHeight() * |
4552 | + self.proportion))) |
4553 | + |
4554 | + def SplitVertically(self, win1, win2): |
4555 | + if self.GetParent() is None: return False |
4556 | + return wx.SplitterWindow.SplitVertically(self, win1, win2, |
4557 | + int(round(self.GetParent().GetSize().GetWidth() * |
4558 | + self.proportion))) |
4559 | + |
4560 | + def GetExpectedSashPosition(self): |
4561 | + if self.GetSplitMode() == wx.SPLIT_HORIZONTAL: |
4562 | + tot = max(self.GetMinimumPaneSize(), |
4563 | + self.GetParent().GetClientSize().height) |
4564 | + else: |
4565 | + tot = max(self.GetMinimumPaneSize(), |
4566 | + self.GetParent().GetClientSize().width) |
4567 | + return int(round(tot * self.proportion)) |
4568 | + |
4569 | + def ResetSash(self): |
4570 | + self.SetSashPosition(self.GetExpectedSashPosition()) |
4571 | + |
4572 | + def OnReSize(self, event): |
4573 | + """Window has been resized, so we need to adjust the sash based on |
4574 | + self.proportion. |
4575 | + """ |
4576 | + self.ResetSash() |
4577 | + event.Skip() |
4578 | + |
4579 | + def OnSashChanged(self, event): |
4580 | + """We'll change self.proportion now based on where user dragged the |
4581 | + sash. |
4582 | + """ |
4583 | + pos = float(self.GetSashPosition()) |
4584 | + if self.GetSplitMode() == wx.SPLIT_HORIZONTAL: |
4585 | + tot = max(self.GetMinimumPaneSize(), |
4586 | + self.GetParent().GetClientSize().height) |
4587 | + else: |
4588 | + tot = max(self.GetMinimumPaneSize(), |
4589 | + self.GetParent().GetClientSize().width) |
4590 | + self.proportion = pos / tot |
4591 | + event.Skip() |
4592 | + |
4593 | + def OnPaint(self, event): |
4594 | + if self.firstpaint: |
4595 | + if self.GetSashPosition() != self.GetExpectedSashPosition(): |
4596 | + self.ResetSash() |
4597 | + self.firstpaint = False |
4598 | + event.Skip() |
4599 | |
4600 | === removed file 'lib/wxkeryx/options.py' |
4601 | --- lib/wxkeryx/options.py 2010-03-05 00:06:56 +0000 |
4602 | +++ lib/wxkeryx/options.py 1970-01-01 00:00:00 +0000 |
4603 | @@ -1,300 +0,0 @@ |
4604 | -# -*- coding: utf-8 -*- |
4605 | -# |
4606 | -# Author: Chris Oliver (excid3@gmail.com) |
4607 | -# |
4608 | -# This program is free software; you can redistribute it and/or modify |
4609 | -# it under the terms of the GNU General Public License as published by |
4610 | -# the Free Software Foundation; either version 2 of the License, or |
4611 | -# (at your option) any later version. |
4612 | -# |
4613 | -# This program is distributed in the hope that it will be useful, |
4614 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
4615 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4616 | -# GNU Library General Public License for more details. |
4617 | -# |
4618 | -# You should have received a copy of the GNU General Public License |
4619 | -# along with this program; if not, write to the Free Software |
4620 | -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
4621 | - |
4622 | -import os.path |
4623 | -import shutil |
4624 | -import wx |
4625 | -import wx.lib.buttons as buttons |
4626 | -import wx.lib.colourselect as csel |
4627 | - |
4628 | -from lib import consts, plugins |
4629 | - |
4630 | -class optionDialog(wx.Dialog): |
4631 | - def __init__(self, *args, **kwds): |
4632 | - kwds["style"] = wx.DEFAULT_DIALOG_STYLE |
4633 | - wx.Dialog.__init__(self, *args, **kwds) |
4634 | - self.SetTitle(_("Options")) |
4635 | - self.SetIcon(wx.Icon(consts.fileIco, wx.BITMAP_TYPE_ICO)) |
4636 | - sizer = wx.BoxSizer(wx.VERTICAL) |
4637 | - |
4638 | - # Add notebook |
4639 | - self.notebook = wx.Notebook(self) |
4640 | - self.notebook_il = wx.ImageList(16, 16) |
4641 | - self.notebook_il.Add(wx.Bitmap(consts.icon_layout)) |
4642 | - self.notebook_il.Add(wx.Bitmap(consts.icon_download)) |
4643 | - self.notebook_il.Add(wx.Bitmap(consts.icon_plugin)) |
4644 | - self.notebook.SetImageList(self.notebook_il) |
4645 | - sizer.Add(self.notebook, 1, wx.EXPAND|wx.TOP|wx.RIGHT|wx.LEFT, 5) |
4646 | - |
4647 | - # Add line |
4648 | - line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL) |
4649 | - sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.LEFT|wx.TOP, 5) |
4650 | - |
4651 | - # Add buttons |
4652 | - btnsizer = wx.StdDialogButtonSizer() |
4653 | - btn = wx.Button(self, wx.ID_OK) |
4654 | - btn.SetDefault() |
4655 | - btnsizer.AddButton(btn) |
4656 | - btn = wx.Button(self, wx.ID_CANCEL) |
4657 | - btnsizer.AddButton(btn) |
4658 | - btnsizer.Realize() |
4659 | - sizer.Add(btnsizer, 0, wx.ALIGN_BOTTOM|wx.ALIGN_RIGHT|wx.ALL, 5) |
4660 | - |
4661 | - self.addTabs() |
4662 | - self.SetSizer(sizer) |
4663 | - self.Fit() |
4664 | - |
4665 | - def addTabs(self): |
4666 | - pane = wx.Panel(self.notebook, -1, style=wx.TAB_TRAVERSAL) |
4667 | - vert = wx.BoxSizer(wx.VERTICAL) |
4668 | - |
4669 | - txt = wx.StaticText(pane, -1, _("All directories should be relative paths.")) |
4670 | - vert.Add(txt, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4671 | - |
4672 | - sizer = wx.BoxSizer() |
4673 | - txt = wx.StaticText(pane, -1, _("Log Directory:")) |
4674 | - sizer.Add(txt, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4675 | - self.logCtrl = wx.TextCtrl(pane, -1, consts.LogPath, size=wx.Size(250,-1)) |
4676 | - sizer.Add(self.logCtrl, 1, wx.ALL, 3) |
4677 | - vert.Add(sizer, 0, wx.EXPAND) |
4678 | - |
4679 | - sizer = wx.BoxSizer() |
4680 | - txt = wx.StaticText(pane, -1, _("Locale Directory:")) |
4681 | - sizer.Add(txt, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4682 | - self.localeCtrl = wx.TextCtrl(pane, -1, consts.LocalePath) |
4683 | - sizer.Add(self.localeCtrl, 1, wx.ALL, 3) |
4684 | - vert.Add(sizer, 0, wx.EXPAND) |
4685 | - |
4686 | - #sizer = wx.BoxSizer() |
4687 | - #txt = wx.StaticText(pane, -1, _("Packages Directory:")) |
4688 | - #sizer.Add(txt, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4689 | - #self.packagesCtrl = wx.TextCtrl(pane, -1, consts.PackagesPath) |
4690 | - #sizer.Add(self.packagesCtrl, 1, wx.ALL, 3) |
4691 | - #vert.Add(sizer, 0, wx.EXPAND) |
4692 | - |
4693 | - sizer = wx.BoxSizer(wx.HORIZONTAL) |
4694 | - txt = wx.StaticText(pane, -1, _("Plugins Directory:")) |
4695 | - sizer.Add(txt, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4696 | - self.pluginsCtrl = wx.TextCtrl(pane, -1, consts.PluginsPath) |
4697 | - sizer.Add(self.pluginsCtrl, 1, wx.ALL, 3) |
4698 | - vert.Add(sizer, 0, wx.EXPAND) |
4699 | - |
4700 | - sizer = wx.BoxSizer(wx.HORIZONTAL) |
4701 | - txt = wx.StaticText(pane, -1, _("Projects Directory:")) |
4702 | - sizer.Add(txt, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4703 | - self.projectsCtrl = wx.TextCtrl(pane, -1, consts.ProjectsPath) |
4704 | - sizer.Add(self.projectsCtrl, 1, wx.ALL, 3) |
4705 | - vert.Add(sizer, 0, wx.EXPAND) |
4706 | - |
4707 | - sizer = wx.BoxSizer(wx.HORIZONTAL) |
4708 | - txt = wx.StaticText(pane, -1, _("Themes Directory:")) |
4709 | - sizer.Add(txt, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4710 | - self.pixmapsCtrl = wx.TextCtrl(pane, -1, consts.PixmapsPath) |
4711 | - sizer.Add(self.pixmapsCtrl, 1, wx.ALL, 3) |
4712 | - vert.Add(sizer, 0, wx.EXPAND) |
4713 | - |
4714 | - sizer = wx.BoxSizer(wx.HORIZONTAL) |
4715 | - txt = wx.StaticText(pane, -1, _("Themes Directory:")) |
4716 | - sizer.Add(txt, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4717 | - self.themesCtrl = wx.TextCtrl(pane, -1, consts.ThemesPath) |
4718 | - sizer.Add(self.themesCtrl, 1, wx.ALL, 3) |
4719 | - vert.Add(sizer, 0, wx.EXPAND) |
4720 | - |
4721 | - sizer = wx.BoxSizer(wx.HORIZONTAL) |
4722 | - txt = wx.StaticText(pane, -1, _("Default Theme Directory:")) |
4723 | - sizer.Add(txt, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4724 | - self.defaultThemeCtrl = wx.TextCtrl(pane, -1, consts.ThemeDefaultPath) |
4725 | - sizer.Add(self.defaultThemeCtrl, 1, wx.ALL, 3) |
4726 | - vert.Add(sizer, 0, wx.EXPAND) |
4727 | - |
4728 | - pane.SetSizer(vert) |
4729 | - self.notebook.AddPage(pane, _("Directories"), False, 0) |
4730 | - |
4731 | - ### Second page ### THIS PAGE IS USED FOR THE PROXY |
4732 | - pane = wx.Panel(self.notebook, -1, style=wx.TAB_TRAVERSAL) |
4733 | - vert = wx.BoxSizer(wx.VERTICAL) |
4734 | - # vert keeps track of the vertical objects in the page (rows) |
4735 | - |
4736 | - self.proxyCheckBox= wx.CheckBox(pane, -1, "Enable proxy support") |
4737 | - self.proxyCheckBox.SetValue(consts.proxy_enabled) # Set proxy value |
4738 | - vert.Add(self.proxyCheckBox, 0, wx.ALL, 3) |
4739 | - |
4740 | - # Make a bold font. |
4741 | - bold_font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD)#, False, u'Comic Sans MS') |
4742 | - |
4743 | - sizer = wx.BoxSizer(wx.HORIZONTAL) |
4744 | - # Add the "URL:" static text. |
4745 | - url = wx.StaticText(pane, -1, _("URL: ")) |
4746 | - url.SetFont(bold_font) |
4747 | - sizer.Add(url, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4748 | - # Add the "http://" static text. |
4749 | - http = wx.StaticText(pane, -1, _("http://")) |
4750 | - sizer.Add(http, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4751 | - # Add the URL text box. |
4752 | - self.proxy_url = wx.TextCtrl(pane, -1, '') |
4753 | - sizer.Add(self.proxy_url, 1, wx.ALL, 3) |
4754 | - # Add the ":" static text. |
4755 | - colon = wx.StaticText(pane, -1, _(":")) |
4756 | - sizer.Add(colon, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4757 | - # Add the port text box. |
4758 | - self.proxy_port = wx.TextCtrl(pane, -1, '') |
4759 | - sizer.Add(self.proxy_port, 1, wx.ALL, 3) |
4760 | - vert.Add(sizer, 0, wx.EXPAND) |
4761 | - |
4762 | - sizer = wx.BoxSizer(wx.HORIZONTAL) |
4763 | - txt = wx.StaticText(pane, -1, _("Username:")) |
4764 | - txt.SetFont(bold_font) |
4765 | - sizer.Add(txt, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4766 | - self.proxy_username = wx.TextCtrl(pane, -1, consts.proxy_username) |
4767 | - sizer.Add(self.proxy_username, 1, wx.ALL, 3) |
4768 | - vert.Add(sizer, 0, wx.EXPAND) |
4769 | - |
4770 | - sizer = wx.BoxSizer(wx.HORIZONTAL) |
4771 | - txt = wx.StaticText(pane, -1, _("Password:")) |
4772 | - txt.SetFont(bold_font) |
4773 | - sizer.Add(txt, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 3) |
4774 | - self.proxy_password = wx.TextCtrl(pane, -1, consts.proxy_password, style=wx.TE_PASSWORD) |
4775 | - sizer.Add(self.proxy_password, 1, wx.ALL, 3) |
4776 | - vert.Add(sizer, 0, wx.EXPAND) |
4777 | - |
4778 | - pane.SetSizer(vert) |
4779 | - self.notebook.AddPage(pane, _("Download Options"), False, 1) |
4780 | - |
4781 | - self.LoadProxy() |
4782 | - self.OnChecked(None) # Enable/Disable proxy textbox based on checkbox status |
4783 | - self.Bind(wx.EVT_CHECKBOX, self.OnChecked, self.proxyCheckBox) |
4784 | - |
4785 | - ### Third page ### |
4786 | - pane = wx.Panel(self.notebook, -1, style=wx.TAB_TRAVERSAL) |
4787 | - sizer = wx.BoxSizer(wx.VERTICAL) |
4788 | - |
4789 | - txt = wx.StaticText(pane, -1, _("Loaded plugins:")) |
4790 | - txt.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, "")) |
4791 | - sizer.Add(txt, 0, wx.ALL, 3) |
4792 | - |
4793 | - self.pluginList = wx.ListBox(pane) |
4794 | - sizer.Add(self.pluginList, 1, wx.EXPAND, 0) |
4795 | - |
4796 | - self.fill() |
4797 | - |
4798 | - sizer2 = wx.BoxSizer(wx.HORIZONTAL) |
4799 | - self.disableBtn = buttons.GenBitmapTextButton(pane, -1, wx.Bitmap(consts.icon_plugin_disable), _("Disable"))#, size=(120, 25)) |
4800 | - sizer2.Add(self.disableBtn, 0, wx.ALL, 3) |
4801 | - self.Bind(wx.EVT_BUTTON, self.OnDisable, self.disableBtn) |
4802 | - |
4803 | - #bmp = wx.Bitmap(os.path.join(consts.dirPixmaps, 'plugin_go.png')) |
4804 | - #self.disableBtn = buttons.GenBitmapTextButton(pane, -1, bmp, _("Start"))#, size=(120, 25)) |
4805 | - #sizer2.Add(self.disableBtn, 0, wx.ALL, 3) |
4806 | - |
4807 | - self.addBtn = buttons.GenBitmapTextButton(pane, -1, wx.Bitmap(consts.icon_plugin_add), _("Add"))#, size=(120, 25)) |
4808 | - sizer2.Add(self.addBtn, 0, wx.ALL, 3) |
4809 | - self.Bind(wx.EVT_BUTTON, self.OnAdd, self.addBtn) |
4810 | - |
4811 | - #bmp = wx.Bitmap(os.path.join(consts.dirPixmaps, 'plugin_edit.png')) |
4812 | - #self.disableBtn = buttons.GenBitmapTextButton(pane, -1, bmp, _("Edit"))#, size=(120, 25)) |
4813 | - #sizer2.Add(self.disableBtn, 0, wx.ALL, 3) |
4814 | - |
4815 | - #bmp = wx.Bitmap(os.path.join(consts.dirPixmaps, 'plugin_delete.png')) |
4816 | - #self.disableBtn = buttons.GenBitmapTextButton(pane, -1, bmp, _("Delete"))#, size=(120, 25)) |
4817 | - #sizer2.Add(self.disableBtn, 0, wx.ALL, 3) |
4818 | - |
4819 | - sizer.Add(sizer2) |
4820 | - pane.SetSizer(sizer) |
4821 | - self.notebook.AddPage(pane, _("Plugins"), False, 2) |
4822 | - |
4823 | - def OnChecked(self, evt): |
4824 | - if self.proxyCheckBox.GetValue(): |
4825 | - self.proxy_url.Enable() |
4826 | - self.proxy_port.Enable() |
4827 | - self.proxy_username.Enable() |
4828 | - self.proxy_password.Enable() |
4829 | - else: |
4830 | - self.proxy_url.Disable() |
4831 | - self.proxy_port.Disable() |
4832 | - self.proxy_username.Disable() |
4833 | - self.proxy_password.Disable() |
4834 | - |
4835 | - def LoadProxy(self): |
4836 | - """So right here, we've got to grab the value from the config and set it in the interface""" |
4837 | - try: |
4838 | - url = consts.http_proxy['http'] |
4839 | - (url, port) = (url.split(':')[1][2:], url.split(':')[-1]) |
4840 | - self.proxy_url.SetValue(url) |
4841 | - self.proxy_port.SetValue(port) |
4842 | - except: |
4843 | - pass |
4844 | - |
4845 | - def fill(self): # Fill plugin list |
4846 | - self.pluginList.Clear() |
4847 | - for item in plugins.OSPluginList: self.pluginList.Append(item[0]) |
4848 | - for item in plugins.InterfacePluginList: self.pluginList.Append(item[0]) |
4849 | - |
4850 | - def OnAdd(self, evt): |
4851 | - dlg = wx.FileDialog(self, message=_("Choose a file"), |
4852 | - defaultDir = consts.cwd, |
4853 | - defaultFile = "", |
4854 | - wildcard = consts.wildcard_plugin, |
4855 | - style=wx.OPEN | wx.CHANGE_DIR) |
4856 | - |
4857 | - # Show the dialog and retrieve the user response. If it is the OK response, |
4858 | - # process the data |
4859 | - if dlg.ShowModal() == wx.ID_OK: |
4860 | - file = dlg.GetPaths() |
4861 | - dlg.Destroy() |
4862 | - if file[0]: |
4863 | - # Copy the file to the plugins directory |
4864 | - shutil.copyfile(file[0], os.path.join(consts.dirPlugins, os.path.basename(file[0]))) |
4865 | - else: |
4866 | - return |
4867 | - |
4868 | - wx.MessageBox(_("Plugin installed successfully. Restart Keryx to load the plugin."), _("Install Successful")) |
4869 | - |
4870 | - def OnDisable(self, evt): |
4871 | - def disable(instance): |
4872 | - try: |
4873 | - instance.cleanup() |
4874 | - wx.MessageBox(_("Plugin disabled successfully.")) |
4875 | - return True |
4876 | - except: return False |
4877 | - |
4878 | - temp = [] |
4879 | - for item in plugins.OSPluginList: |
4880 | - if item[0] == self.pluginList.Items[self.pluginList.GetSelection()]: |
4881 | - if disable(item[1]): # Successfully disabled |
4882 | - temp = [] |
4883 | - for i in plugins.OSPluginList: |
4884 | - if i[0] != item[0]: temp.append(i) |
4885 | - plugins.OSPluginList = temp |
4886 | - self.fill() |
4887 | - return |
4888 | - |
4889 | - for item in plugins.InterfacePluginList: |
4890 | - if item[0] == self.pluginList.Items[self.pluginList.GetSelection()]: |
4891 | - if disable(item[1]): # Successfully disabled |
4892 | - for i in plugins.InterfacePluginList: |
4893 | - if i[0] != item[0]: temp.append(i) |
4894 | - plugins.InterfacePluginList = temp |
4895 | - self.fill() |
4896 | - return |
4897 | - |
4898 | - wx.MessageBox(_("Unable to find plugin.")) |
4899 | - return False |
4900 | - |
4901 | -# end of class optionDialog |
4902 | - |
4903 | - |
4904 | |
4905 | === modified file 'lib/wxkeryx/startDialog.py' |
4906 | --- lib/wxkeryx/startDialog.py 2010-10-23 18:57:40 +0000 |
4907 | +++ lib/wxkeryx/startDialog.py 2017-06-11 16:11:12 +0000 |
4908 | @@ -16,163 +16,141 @@ |
4909 | # along with this program; if not, write to the Free Software |
4910 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
4911 | |
4912 | -import lib.project, os.path, platform, wx |
4913 | +import os.path |
4914 | +import platform |
4915 | +import wx |
4916 | import wx.lib.buttons as buttons |
4917 | -from lib import consts, log, plugins |
4918 | -from lib.project import Project |
4919 | - |
4920 | -class startDialog(wx.Dialog): |
4921 | + |
4922 | +import lib.project |
4923 | +from lib.project import Project, ProjectExistsException |
4924 | +from lib import config |
4925 | +from lib import debian |
4926 | + |
4927 | +from gettext import gettext as _ |
4928 | + |
4929 | + |
4930 | +class StartDialog(wx.Dialog): |
4931 | """Startup dialog""" |
4932 | - def __init__(self, *args, **kwds): |
4933 | - kwds["style"] = wx.DEFAULT_DIALOG_STYLE |
4934 | - wx.Dialog.__init__(self, *args, **kwds) |
4935 | - self.SetIcon(wx.Icon(consts.fileIco, wx.BITMAP_TYPE_ICO)) |
4936 | - self.bitmap = wx.StaticBitmap(self, -1, wx.Bitmap(consts.fileLogo)) |
4937 | - self.welcomeText = wx.StaticText(self, -1, consts.welcome_message) |
4938 | - self.newText = wx.StaticText(self, -1, _("To get started, create a new project on your offline computer.")) |
4939 | - self.nameTextCtrl = wx.TextCtrl(self, -1, platform.node())#, size=(120,20)) |
4940 | - self.choice = wx.Choice(self, -1, choices=[], style=wx.CB_SORT) |
4941 | - |
4942 | - # Append the plugins into the combo box |
4943 | - for name, instance, type, ver in plugins.OSPluginList: |
4944 | - self.choice.Append(name) |
4945 | - self.choice.Select(0) |
4946 | - |
4947 | - self.newProjectButton = buttons.GenBitmapTextButton(self, -1, wx.Bitmap(consts.icon_new), _("New Project"))#, size=(110, 25)) |
4948 | + def __init__(self): |
4949 | + self.theme = config.theme |
4950 | + wx.Dialog.__init__(self, None, -1, _('Welcome to ') + config.name) |
4951 | + self.SetIcon(wx.Icon(config.ico_path, wx.BITMAP_TYPE_ICO)) |
4952 | + self.bitmap = wx.StaticBitmap(self, -1, wx.Bitmap(config.logo_path)) |
4953 | + self.welcomeText = wx.StaticText(self, |
4954 | + -1, |
4955 | + _('Welcome to ') + config.name) |
4956 | + self.welcomeText.SetFont(wx.Font(8, |
4957 | + wx.FONTFAMILY_DEFAULT, |
4958 | + wx.FONTSTYLE_NORMAL, |
4959 | + wx.FONTWEIGHT_BOLD, |
4960 | + 0, |
4961 | + '')) |
4962 | + self.newText = wx.StaticText(self, -1, _('To get started, create a new ' |
4963 | + 'project on your offline ' |
4964 | + 'computer.')) |
4965 | + self.nameTextCtrl = wx.TextCtrl(self, -1, platform.node()) |
4966 | + |
4967 | + self.newProjectButton = \ |
4968 | + buttons.GenBitmapTextButton(self, |
4969 | + -1, |
4970 | + wx.Bitmap(self.theme.icon_new), |
4971 | + _('New Project')) |
4972 | self.static_line = wx.StaticLine(self, -1) |
4973 | - self.openTxt = wx.StaticText(self, -1, _("Open a project:")) |
4974 | - self.openProjBox = wx.Choice(self, -1, choices=[_('Browse...')], style=wx.CB_SORT) |
4975 | + self.openTxt = wx.StaticText(self, -1, _('Open a project:')) |
4976 | + self.openProjectBox = wx.Choice(self, |
4977 | + -1, |
4978 | + choices=[_('Browse...')], |
4979 | + style=wx.CB_SORT) |
4980 | |
4981 | self.projects = [] |
4982 | - for root, dirs, files in os.walk(consts.dirProjects): |
4983 | - for item in files: |
4984 | - if item.endswith(consts.appFileExt): |
4985 | - self.openProjBox.Append(item[:-6]) |
4986 | - self.projects.append(os.path.join(root, item)) |
4987 | + for thing in os.listdir(config.projects_dir): |
4988 | + if os.path.isdir(os.path.join(config.projects_dir, thing)): |
4989 | + self.openProjectBox.Append(thing) |
4990 | + self.projects.append(os.path.join(config.projects_dir, thing)) |
4991 | |
4992 | - try: |
4993 | - self.openProjBox.Select(1) |
4994 | - except: |
4995 | - self.openProjBox.Select(0) |
4996 | - |
4997 | - self.openProjectButton = buttons.GenBitmapTextButton(self, -1, wx.Bitmap(consts.icon_open), _("Open Project"))#, size=(120, 25)) |
4998 | - |
4999 | - self.SetTitle(consts.welcome_message) |
5000 | - self.welcomeText.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, "")) |
The diff has been truncated for viewing.