Mercurial > pyarq-presupuestos
comparison Gtk/gui.py @ 1:2ac1551ad2ab version 0.0.0
add code
author | Miguel Ángel Bárcena Rodríguez <miguelangel@obraencurso.es> |
---|---|
date | Sun, 31 Oct 2010 20:07:33 +0100 |
parents | |
children | a221c14c3c31 |
comparison
equal
deleted
inserted
replaced
0:a1703c4f2990 | 1:2ac1551ad2ab |
---|---|
1 # -*- coding: utf-8 -*- | |
2 ## File gui.py | |
3 ## This file is part of pyArq-Presupuestos. | |
4 ## | |
5 ## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez | |
6 ## <miguelangel@obraencurso.es> | |
7 ## | |
8 ## pyArq-Presupuestos is free software: you can redistribute it and/or modify | |
9 ## it under the terms of the GNU General Public License as published by | |
10 ## the Free Software Foundation, either version 3 of the License, or | |
11 ## (at your option) any later version. | |
12 ## | |
13 ## pyArq-Presupuestos is distributed in the hope that it will be useful, | |
14 ## but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 ## GNU General Public License for more details. | |
17 ## | |
18 ## You should have received a copy of the GNU General Public License | |
19 ## along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 ## | |
21 | |
22 """Gui module | |
23 | |
24 The MainWindow class contain the toplevel WINDOW, | |
25 this window have a notebook with a page for each budget. | |
26 Each budget or notebook page is showed by the Page class, this class contain | |
27 the main widget showed in a page notebook. | |
28 The main widget can show the budget information in several panes. | |
29 This panes are ordened in gtk.Paned represented for the class Paned which can | |
30 have 2 viewes represented for the View class or other gtk.Paned that have other | |
31 viewes or more gtk.Paned. | |
32 The view can have diferente type of widgets to show the budget information. | |
33 The DecompositionList class show the decompositon list information of a record | |
34 The Measure class show de measure information of a record | |
35 The TextWindow class show the long description of a record | |
36 The Sheet class class show the sheet of condition information of a record | |
37 | |
38 The views can send signal to the others. | |
39 All the viewes ordered in panes can be or not be connected to the others, | |
40 if there are connecteded to the others when the user change the active code in | |
41 one of the panes the active code change in the others. | |
42 | |
43 """ | |
44 # TODO: Config file | |
45 | |
46 # Standar Modules | |
47 import os | |
48 import time | |
49 import pygtk | |
50 pygtk.require('2.0') | |
51 import gtk | |
52 import gobject | |
53 import weakref | |
54 | |
55 # pyArq-Presupuestos Modules | |
56 from Gtk import importFiebdc | |
57 from Generic import base | |
58 from Generic import fiebdc | |
59 from Generic import durusdatabase | |
60 from Generic import utils | |
61 from Generic import globals | |
62 from Generic import openwith | |
63 | |
64 # Load default icon | |
65 if os.path.exists(globals.getAppPath("ICON")): | |
66 icon = gtk.gdk.pixbuf_new_from_file(globals.getAppPath("ICON")) | |
67 gtk.window_set_default_icon_list(icon) | |
68 else: | |
69 print utils.mapping(_("The icon file does not exist. '$1'"), | |
70 (globals.getAppPath("ICON"),)) | |
71 | |
72 # Autodetect desktop | |
73 if globals.desktop["autodetect"] is True: | |
74 openwith.autodetect_desktop() | |
75 print utils.mapping(_("pyArq-Presupuestos running on $1"), | |
76 (globals.desktop["desktop"],)) | |
77 | |
78 class MainWindow(object): | |
79 """gui.MainWindow: | |
80 | |
81 Description: | |
82 Creates and shows the main window. | |
83 This is the interface base class. | |
84 Constructor: | |
85 gui.MainWindow(): Returns the newly created main window instance | |
86 Ancestry: | |
87 +-- object | |
88 +-- MainWindow | |
89 Atributes: | |
90 "window": Main window widget ("gtk.Window" object) | |
91 "__budget_temp_list": Temporal list of budgets | |
92 "__budget_list": List of budgets ("base.Budget" objects) | |
93 "__page_list": List of pages ("Page" object) | |
94 "__notebook": Notebook widget ("gtk.Notebook" object) | |
95 "__general_action_group": the "General" action group | |
96 Methods: | |
97 __init__(self) | |
98 _main(self) | |
99 _addBudget(self, budget) | |
100 _appendPage(self) | |
101 _testBudgetList(self) | |
102 _menuitemImportFiebdc(self, widget) | |
103 _menuitemImportPriceDatabase(self, widget) | |
104 _menuitemOpenPriceDatabase(self, widget) | |
105 _menuitemOpen | |
106 _menuitemClose(self, widget) | |
107 _menuitemText(self, widget) | |
108 _delete_event(self, widget, event) | |
109 _destroy(self, widget) | |
110 """ | |
111 # TODO:* Can choose open budget in new window | |
112 # TODO:* gtk.Action for menu and toolbar | |
113 # TODO:* Can choose show more than one notebook in the same window or | |
114 # TODO: can show basedata notebook in a side pane | |
115 __ui = '''<ui> | |
116 <menubar name="MenuBar"> | |
117 <menu action="File"> | |
118 <menuitem action="ImportFiebdc"/> | |
119 <menuitem action="Close"/> | |
120 </menu> | |
121 <menu action="View"> | |
122 <menuitem action="Text"/> | |
123 </menu> | |
124 <menu action="Test"> | |
125 <menuitem action="ImportFiebdcPriceDatabase"/> | |
126 <menuitem action="OpenPriceDatabase"/> | |
127 </menu> | |
128 </menubar> | |
129 <toolbar name="ToolBar"> | |
130 <toolitem action="ImportFiebdc"/> | |
131 <separator/> | |
132 <toolitem action="Close"/> | |
133 <separator name="sep1"/> | |
134 </toolbar> | |
135 </ui>''' | |
136 | |
137 def __init__(self): | |
138 """def __init__(self) | |
139 | |
140 Initialize the atributes "__budget_list" and "__page_list" without data. | |
141 Creates the widgets "window" and "__notebook". | |
142 """ | |
143 self.__budget_temp_list = [] | |
144 self.__budget_list = [] | |
145 self.__page_list = [] | |
146 # Main window | |
147 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) | |
148 self.window.set_default_size(771, 570) | |
149 self.window.set_title("Presupuestos") | |
150 self.window.set_border_width(0) | |
151 self.window.connect("destroy", self._destroy) | |
152 self.window.connect("delete_event", self._delete_event) | |
153 # Vertical box | |
154 _vbox1 = gtk.VBox(False, 0) | |
155 self.window.add(_vbox1) | |
156 _vbox1.show() | |
157 #Uimanager | |
158 _uimanager = gtk.UIManager() | |
159 _accelgroup = _uimanager.get_accel_group() | |
160 self.window.add_accel_group(_accelgroup) | |
161 _general_action_group = gtk.ActionGroup("General") | |
162 self.__general_action_group = _general_action_group | |
163 _general_action_group.add_actions( | |
164 [("File", None, _("_File"), None), | |
165 ("ImportFiebdc", gtk.STOCK_OPEN, _('_Import Fiebdc'), "", 'NPI', | |
166 self._menuitemImportFiebdc), | |
167 ("Close", gtk.STOCK_CLOSE, _("_Close"), None, 'NPI', | |
168 self._menuitemClose), | |
169 ("View", None, _("_View")), | |
170 ("Text", None, _("_Text"), None, 'NPI', | |
171 self._menuitemText), | |
172 ("Test", None, _("_Test")), | |
173 ('ImportFiebdcPriceDatabase', gtk.STOCK_OPEN, | |
174 _("Import Fiebdc _price database"), "", "NPI", | |
175 self._menuitemImportPriceDatabase ), | |
176 ("OpenPriceDatabase", gtk.STOCK_OPEN, _('_Open price database'), | |
177 "", 'NPI', self._menuitemOpenPriceDatabase), | |
178 ]) | |
179 _uimanager.insert_action_group(_general_action_group, 0) | |
180 _uimanager.add_ui_from_string(self.__ui) | |
181 _menu_bar = _uimanager.get_widget("/MenuBar") | |
182 _vbox1.pack_start(_menu_bar, False, False, 0) | |
183 _toolbar = _uimanager.get_widget("/ToolBar") | |
184 _toolbar.get_settings().set_long_property("gtk-toolbar-icon-size", | |
185 gtk.ICON_SIZE_SMALL_TOOLBAR, "pyArq-Presupuestos:toolbar") | |
186 _vbox1.pack_start(_toolbar, False, False, 0) | |
187 # Notebook | |
188 self.__notebook = gtk.Notebook() | |
189 _vbox1.pack_start(self.__notebook, True, True, 0) | |
190 self.__notebook.set_tab_pos(gtk.POS_TOP) | |
191 self.__notebook.set_show_tabs(True) | |
192 self.__notebook.set_show_border(True) | |
193 self.__notebook.set_scrollable(True) | |
194 self.__notebook.show() | |
195 self._main() | |
196 | |
197 def _main(self): | |
198 """def main(self) | |
199 | |
200 Shows window and starts the GTK+ event processing loop. | |
201 """ | |
202 self.window.show() | |
203 gtk.main() | |
204 | |
205 def _addBudget(self, budget): | |
206 """def _addBudget(self, budget) | |
207 | |
208 budget: "base.Budget" object | |
209 | |
210 Appends a budget in the "__budget_list" | |
211 """ | |
212 if budget != None: | |
213 _budget = budget | |
214 if _budget in self.__budget_temp_list: | |
215 self.__budget_temp_list.remove(_budget) | |
216 self.__budget_list.append(_budget) | |
217 | |
218 def _appendPage(self): | |
219 """def _appendPage(self) | |
220 | |
221 Creates a new page (instance of "Page class") from the last budget in | |
222 __budget_list, appends this page in the "__page_list" and shows the | |
223 page widget in the notebook widget. | |
224 """ | |
225 _last_budget = self.__budget_list[-1] | |
226 _page = Page(_last_budget) | |
227 self.__notebook.append_page(_page.widget, _page.title) | |
228 self.__page_list.append(_page) | |
229 | |
230 def _testBudgetList2(self): | |
231 """def _testBudgetList2(self) | |
232 | |
233 Test if the number of budgets ("__budget_list") is greater | |
234 than the number of pages ("__page_list"), if it is greater | |
235 appendPage method is called to create a page to show the new budget | |
236 and save the budget in a durus file. | |
237 """ | |
238 if len(self.__budget_list) > len(self.__page_list): | |
239 self._appendPage() | |
240 #-# in test mode | |
241 # TODO: It must be in a thread | |
242 _last_budget = self.__budget_list[-1] | |
243 _path = globals.getHomePath("DURUS-DATABASE") | |
244 _file_whit_path_bc3 = _last_budget.filename | |
245 _filename_bc3 = _file_whit_path_bc3.split("/")[-1] | |
246 _filename = _filename_bc3.split(".")[-2] | |
247 _file = _path + _filename + ".durus" | |
248 print utils.mapping(_("Saving file: $1"), (_file,)) | |
249 _time = time.time() | |
250 _durus_file = durusdatabase.DurusFile(_file,True) | |
251 _durus_file.setBudget(_last_budget) | |
252 _durus_file.close() | |
253 print utils.mapping(_("Saving time: $1 seconds"), | |
254 (("%.2f" %(time.time()-_time) ),)) | |
255 #-# | |
256 return False | |
257 return True | |
258 | |
259 def _menuitemImportFiebdc(self, widget): | |
260 """def _menuitemImportFiebdc(self, widget) | |
261 | |
262 widget: the widget where the event is emitted from | |
263 Callback to open a budget file. | |
264 Inits a timeout to test if a budgets is appended to "__budget_list" | |
265 calling _testBudgetList method if it is true. | |
266 | |
267 Creates and shows a window to open a budget file. | |
268 """ | |
269 _budget = base.Budget() | |
270 self.__budget_temp_list.append(_budget) | |
271 _budget_file = fiebdc.Read() | |
272 _read_method = _budget_file.readFile | |
273 _filename = "file" | |
274 _exit_method = _budget_file.cancel | |
275 _file_window = importFiebdc.FileSelectionWindow(self, | |
276 _read_method, _budget, _filename, _exit_method) | |
277 | |
278 def _menuitemImportPriceDatabase(self, widget): | |
279 """def _menuitemImportPriceDatabase(self, widget) | |
280 | |
281 widget: the widget where the event is emitted from | |
282 Callback to open a budget file. | |
283 Inits a timeout to test if a budgets is appended to "__budget_list" | |
284 calling _testBudgetList method if it is true. | |
285 | |
286 Creates and shows a window to open a budget file. | |
287 """ | |
288 #TODO: change timeout, it is deprecated | |
289 #TODO: the .durus file must be direted saved | |
290 gobject.timeout_add(100, self._testBudgetList2) | |
291 _budget = base.Budget() | |
292 self.__budget_temp_list.append(_budget) | |
293 _budget_file = fiebdc.Read() | |
294 _read_method = _budget_file.readFile | |
295 _filename = "file" | |
296 _exit_method = _budget_file.cancel | |
297 _file_window = importFiebdc.FileSelectionWindow(self, | |
298 _read_method, _budget, _filename, _exit_method) | |
299 | |
300 def _menuitemOpenPriceDatabase(self, widget): | |
301 """def _menuitemImportPriceDatabase(self, widget) | |
302 | |
303 widget: the widget where the event is emitted from | |
304 Callback to open a budget file. | |
305 Inits a timeout to test if a budgets is appended to "__budget_list" | |
306 calling _testBudgetList method if it is true. | |
307 | |
308 Creates and shows a window to open a budget file. | |
309 """ | |
310 _openDialog = OpenDurusDatabase(self._OpenDurusDatabase) | |
311 _openDialog.main() | |
312 | |
313 def _OpenDurusDatabase(self, file): | |
314 """def _menuitemImportFiebdc(self, widget) | |
315 | |
316 widget: the widget where the event is emitted from | |
317 | |
318 Callback to open a budget file from a durus file. | |
319 """ | |
320 _file = file | |
321 print utils.mapping(_("Loading file: $1:"), (_file,)) | |
322 _time = time.time() | |
323 _durus_file = durusdatabase.DurusFile(_file,False) | |
324 _budget = _durus_file.getBudget() | |
325 _durus_file.close() | |
326 print utils.mapping(("Loadig time: $1 seconds"), | |
327 (("%.2f" %(time.time()-_time)),)) | |
328 self.__budget_list.append(_budget) | |
329 _page = Page(_budget) | |
330 self.__notebook.append_page(_page.widget, _page.title) | |
331 self.__page_list.append(_page) | |
332 | |
333 def _menuitemClose(self, widget): | |
334 """def _menuitemClose(self, widget) | |
335 | |
336 widget: the widget where the event is emitted from | |
337 | |
338 Callback to close a budget file. | |
339 """ | |
340 _page_num = self.__notebook.get_current_page() | |
341 if _page_num == -1: | |
342 return | |
343 _page = self.__page_list.pop(_page_num) | |
344 if isinstance(_page, Page): | |
345 #not loading budget | |
346 self.__budget_list.pop(_page_num) | |
347 _page.clear() | |
348 self.__notebook.remove_page(_page_num) | |
349 | |
350 def _menuitemText(self, widget): | |
351 """_menuitemText(self, widget) | |
352 | |
353 widget: the widget where the event is emitted from | |
354 | |
355 Creates and shows a window showing text description | |
356 using a instance of TextWindow class. | |
357 """ | |
358 _page_num = self.__notebook.get_current_page() | |
359 if _page_num == -1: | |
360 return | |
361 _budget = self.__budget_list[_page_num] | |
362 _page = self.__page_list[_page_num] | |
363 _code = _page.getActiveCode() | |
364 _concepto = _budget.getRecord(_code) | |
365 _text = _concepto.text | |
366 _window = TextWindow(_code, _text) | |
367 _window.main() | |
368 | |
369 def _delete_event(self, widget, event): | |
370 """_delete_event(self, widget, event) | |
371 | |
372 widget: the widget where the event is emitted from | |
373 event: the "gtk.gdk.Event" | |
374 | |
375 Method connected to "delete_event" signal of main window widget | |
376 This signal is emitted when a user press the close titlebar button. | |
377 It Returns True so the signal "destroy" is emitted. | |
378 """ | |
379 for _page in self.__page_list: | |
380 _page.clear() | |
381 return False # -> destroy | |
382 | |
383 def _destroy(self, widget): | |
384 """_destroy(self, widget) | |
385 | |
386 widget: the widget where the event is emitted from | |
387 Method connected to "destroy" signal of main window widget | |
388 | |
389 This signal is emited when the method connected to "delete_event" | |
390 signal returns True or when the program call the destroy() method of | |
391 the gtk.Window widget. | |
392 The window is closed and the GTK+ event processing loop is ended. | |
393 """ | |
394 gtk.main_quit() | |
395 | |
396 def getNotebook(self): | |
397 return self.__notebook | |
398 def getPageList(self): | |
399 return self.__page_list | |
400 def getBudgetList(self): | |
401 return self.__budget_list | |
402 | |
403 class EmptyPage(object): | |
404 """ | |
405 """ | |
406 def __init__(self, mainWindow, readFileMethod, budget, filename, | |
407 cancelMethod): | |
408 """def __init__(self, mainWindow, readFileMethod, budget, filename, | |
409 cancelMethod) | |
410 | |
411 """ | |
412 self.__mainWindow = mainWindow | |
413 self.__readFileMethod = readFileMethod | |
414 self.__budget = budget | |
415 self.__filename = filename | |
416 self.__cancelMethod = cancelMethod | |
417 self.__children = None | |
418 self.__cancel = [False, False] | |
419 self.__progress = 0.0 | |
420 self.__widget = gtk.VBox() | |
421 self.__main_item = None | |
422 self.__widget.show() | |
423 self.__throbber = gtk.Image() | |
424 self.__throbber.set_from_file(globals.getAppPath("THROBBER-ICON")) | |
425 self.__throbber.show() | |
426 self.__animationThobber = gtk.gdk.PixbufAnimation( | |
427 globals.getAppPath("THROBBER-GIF")) | |
428 self.__quietThobber = self.__throbber.get_pixbuf() | |
429 self.__budget_icon = gtk.gdk.pixbuf_new_from_file_at_size( | |
430 globals.getAppPath("BUDGET-ICON"), 16, 16) | |
431 _filename = os.path.basename(filename) | |
432 _rootfilename = os.path.splitext(_filename)[0] | |
433 if not _rootfilename == "": | |
434 _filename = _rootfilename | |
435 _titleLabel = gtk.Label(_filename) | |
436 _titleLabel.show() | |
437 self.__title = gtk.HBox() | |
438 self.__title.add(self.__throbber) | |
439 self.__title.add(_titleLabel) | |
440 self.__statusbar = gtk.Statusbar() | |
441 self.__statuscontext = self.__statusbar.get_context_id("Statusbar") | |
442 self.__statusbar.show() | |
443 _align = gtk.Alignment(0.5, 0.5, 0, 0) | |
444 _iconVbox = gtk.VBox() | |
445 _pyArqIcon = gtk.Image() | |
446 _pyArqIcon.set_from_file(globals.getAppPath("PYARQ-ICON")) | |
447 _pyArqIcon.show() | |
448 _iconVbox.pack_start(_pyArqIcon, True, True, 0) | |
449 _link = gtk.LinkButton("http://pyarq.obraencurso.es", | |
450 "http://pyarq.obraencurso.es") | |
451 _iconVbox.pack_start(_link, True, True, 0) | |
452 _link.show() | |
453 _iconVbox.show() | |
454 _align.add(_iconVbox) | |
455 _align.show() | |
456 self.__widget.pack_start(_align, True, True, 0) | |
457 _progressframe = gtk.Frame() | |
458 _progressframe.set_shadow_type(gtk.SHADOW_IN) | |
459 _progressframe.show() | |
460 self.__progress_bar = gtk.ProgressBar() | |
461 self.__progress_bar.show() | |
462 _progressframe.add(self.__progress_bar) | |
463 self.__statusbar.pack_start(_progressframe, False, False, 0) | |
464 self.__widget.pack_end(self.__statusbar, False, True, 0) | |
465 self.__main_item = None | |
466 | |
467 def run(self): | |
468 self.__statusbar.push(self.__statuscontext, _("Time: 0s")) | |
469 self.__throbber.set_from_animation(self.__animationThobber) | |
470 self._launchChildren() | |
471 self._launchTimeout() | |
472 | |
473 def progress(self, percent): | |
474 _progress = str(int(round(100 * percent,0))) | |
475 self.__progress = percent | |
476 | |
477 def stopLoading(self): | |
478 self.__throbber.set_from_pixbuf(self.__budget_icon) | |
479 self.__progress_bar.hide() | |
480 self.__statusbar.pop(self.__statuscontext) | |
481 | |
482 def _launchChildren(self): | |
483 """_launchChildren(self) | |
484 | |
485 Launch the thread to read the file | |
486 """ | |
487 if self.__children is None: | |
488 self.__children = importFiebdc.Thread(self, self.__mainWindow, | |
489 self.__readFileMethod, self.__budget, self.__filename, | |
490 self.__cancelMethod) | |
491 self.__children.start() | |
492 | |
493 def _launchTimeout(self): | |
494 """def _launchTimeout(self) | |
495 | |
496 Launch the timeouts: | |
497 1- update progress bar | |
498 2- update time label | |
499 3- If the other timetouts are stoped the window is closed | |
500 """ | |
501 gobject.timeout_add(500, self._updateProgressBar) | |
502 gobject.timeout_add(1000, self._updateLabel, time.time()) | |
503 self.__cancel = [False, False] | |
504 gobject.timeout_add(1000, self._autoClose) | |
505 | |
506 def _updateProgressBar(self): | |
507 """def _updateProgressBar(self) | |
508 | |
509 update progress bar in a timeout | |
510 If the thread end or is canceled the timeout is stoped | |
511 """ | |
512 if self.__children is None or self.__children.isCanceled() == True: | |
513 self.__cancel[0] = True | |
514 return False | |
515 else: | |
516 self.__progress_bar.set_fraction(self.__progress) | |
517 _text = "%s%%" %str(int(round(100 * self.__progress,0))) | |
518 self.__progress_bar.set_text(_text) | |
519 return True | |
520 | |
521 def _updateLabel(self, _time): | |
522 """def _updateProgressBar(self) | |
523 | |
524 update time label in a timeout | |
525 If the thread end or is canceled the timeout is stoped | |
526 """ | |
527 if self.__children is None or self.__children.isCanceled() == True: | |
528 self.__cancel[1] = True | |
529 return False | |
530 else: | |
531 _time = time.time() - _time | |
532 _text = utils.mapping(_("Time: $1"), ("%.0f" %_time,)) | |
533 self.__statusbar.pop(self.__statuscontext) | |
534 self.__statusbar.push(self.__statuscontext, _text) | |
535 return True | |
536 | |
537 def _autoClose(self): | |
538 """def _updateProgressBar(self) | |
539 | |
540 If the time label and progress bar timeouts are stoped the window is | |
541 closed and ist tiemeout is stoped | |
542 """ | |
543 if self.__cancel == [ True, True ]: | |
544 return False | |
545 else: | |
546 return True | |
547 | |
548 def closeWindow(self): | |
549 """def closeWindow(self) | |
550 | |
551 Sets the __children atribute to None | |
552 This causes that the timeouts is ended. | |
553 This method is called from thread when it is finished | |
554 TODO: it must called threadFinished or somethig | |
555 """ | |
556 self.__children = None | |
557 self.stopLoading() | |
558 _page = Page(self.__budget) | |
559 _children = self.__widget.get_children() | |
560 for _child in _children: | |
561 self.__widget.remove(_child) | |
562 self.__widget.pack_start(_page.widget, True, True, 0) | |
563 _noteBook = self.__mainWindow.getNotebook() | |
564 _pageIndex = _noteBook.page_num(self.__widget) | |
565 self.__mainWindow.getPageList()[_pageIndex] = _page | |
566 def threadCanceled(self): | |
567 """def threadCanceled(self) | |
568 | |
569 Sets the __children atribute to None | |
570 This causes that the timeouts is ended. | |
571 This method is called from thread when is canceled | |
572 TODO: it must called threadFinished or somethig | |
573 """ | |
574 self.__children = None | |
575 self.stopLoading() | |
576 | |
577 def clear(self): | |
578 """def clear(self) | |
579 | |
580 Cancel thread | |
581 """ | |
582 self.__children.cancel() | |
583 | |
584 def getWidget(self): | |
585 """def getWidget(self) | |
586 | |
587 Return de main widget to show in the page | |
588 """ | |
589 return self.__widget | |
590 | |
591 def getTitle(self): | |
592 """def getTtle(self) | |
593 | |
594 Return the title of the page, a gtk.Label objetc | |
595 """ | |
596 return self.__title | |
597 | |
598 widget = property(getWidget, None, None, | |
599 "Main widget showed in the pane") | |
600 title = property(getTitle, None, None, | |
601 "Page Title") | |
602 | |
603 class Page(object): | |
604 """gui.Page: | |
605 | |
606 Description: | |
607 It creates and shows a page in the notebook from a budget object. | |
608 The page can show the budget information in several panes ordered | |
609 according to "panes_list" information. | |
610 Constructor: | |
611 gui.Page(budget, active_code=None): | |
612 budget: budget to be showed in this page (base.Budget object) | |
613 active_code: the code of the active record | |
614 Returns the newly created Page instance | |
615 Ancestry: | |
616 +-- object | |
617 +-- Page | |
618 Atributes: | |
619 "budget": Read-Write. Budget to show in the page. (base.obra object) | |
620 "panes_list": Read. info list for create the panes | |
621 ej: [ "v", pane1, pane2 ] , [ "h", pane1, pane2 ] | |
622 [ "v", [ "h", pane1, pane2 ], [ "h", pane1, pane2 ] ] | |
623 pane types: | |
624 * "DecompositionList": its creates a "DecompositionList" object | |
625 * "RecordDescription" : its creates a "Description" objetc | |
626 * "Measure": its creates a "Measure" objetc | |
627 * "FileView": its creates a "FileView" objet | |
628 * "CompanyView": its creates a "CompanyView" object | |
629 "widget": Read. Notebook page Widget. (a gtk.VBox instance) | |
630 "title": Read. Notebook page title (gtk.Label object) | |
631 "__active_path_record": The active path record | |
632 "__main_item": main item in the page, can be a View object or a Paned | |
633 object | |
634 Methods: | |
635 __init__(self, budget=None, active_code=None) | |
636 propagateMessageFrom(self, message, path, arg=None) | |
637 sendMessageTo(self, pane, message, path, arg=None) | |
638 clear(self) | |
639 getItem(self,path) | |
640 setMainItem(self, item) | |
641 itemsFactory(self, list_paned, path=(0,)) | |
642 setActivePathRecord(self, path_record) | |
643 getTitle(self) | |
644 getWidget(self) | |
645 setBudget(self, budget) | |
646 getBudget(self) | |
647 getPanesList(self) | |
648 """ | |
649 # TODO: * The panes can be ordered as the user wishes | |
650 # TODO: * Panes in windows | |
651 # TODO: * pane types | |
652 # TODO: * General budget properties (is better a dialog?) | |
653 | |
654 def __init__(self, budget, path_record=(0,)): | |
655 """def __init__(self, budget=None, active_code=None) | |
656 | |
657 budget: "base.Budget" object | |
658 active_code: the code of the active record | |
659 Sets the atributes | |
660 * __panes_list: info to create the panes | |
661 * budget (base.Budget object) | |
662 * active_code | |
663 """ | |
664 #TODO: __panes_list should come from config file... | |
665 self.__widget = gtk.VBox() | |
666 self.__panes_list = [ "v", "DecompositionList", [ "v", "Measure", | |
667 "RecordDescription" ]] | |
668 self.__main_item = None | |
669 self.setBudget(budget) | |
670 self.setActivePathRecord(path_record) | |
671 self.__widget.show() | |
672 | |
673 def propagateMessageFrom(self, message, path, arg=None): | |
674 """def propagateMessageFrom(self, message, path, arg=None) | |
675 | |
676 message: string message | |
677 path: tuple that represents the pane path which emits the message | |
678 arg: arguments for the message | |
679 if message is "change_active" arg is the path record | |
680 | |
681 The panes are connectted to this method to send messages to other panes | |
682 """ | |
683 _budget = self.__budget | |
684 if message == "change_active" and _budget.hasPath(arg): | |
685 self.sendMessageTo(self.__main_item, message, path, arg) | |
686 elif message == "autoclose": | |
687 self._closeItem(path) | |
688 elif message == "split h": | |
689 self._splitItem(path, "h") | |
690 elif message == "split v": | |
691 self._splitItem(path, "v") | |
692 | |
693 def sendMessageTo(self, pane, message, path, arg=None): | |
694 """def sendMessageTo(self, pane,message, path, arg=None) | |
695 pane: the receiver pane | |
696 message: string message | |
697 path: tuple that represents the pane path which emits the message | |
698 arg: arguments for the message | |
699 | |
700 Sends a message to a pane | |
701 """ | |
702 if not pane.path == path: | |
703 pane.runMessage(message, path, arg) | |
704 | |
705 def clear(self): | |
706 """def clear(self) | |
707 | |
708 Clear atributes | |
709 """ | |
710 self.propagateMessageFrom("clear", (0,)) | |
711 | |
712 del self.__budget | |
713 del self.__panes_list | |
714 del self.__widget | |
715 del self.__title | |
716 del self.__active_path_record | |
717 del self.__main_item | |
718 | |
719 def getItem(self,path): | |
720 """def getItem(self, path | |
721 | |
722 Return the item whith the path "path", it can return a Paned instance | |
723 or a View instance | |
724 """ | |
725 _item = self.__main_item | |
726 if len(path) == 1: | |
727 return _item | |
728 else: | |
729 return _item.getItem(path[1:]) | |
730 | |
731 def setMainItem(self, item): | |
732 """setMainItem(self,item) | |
733 | |
734 Sets a new main item in the page | |
735 """ | |
736 if not self.__main_item is None: | |
737 _old_main_widget = self.__main_item.widget | |
738 self.__widget.remove(_old_main_widget) | |
739 self.__main_item = item | |
740 _main_widget = self.__main_item.widget | |
741 _main_widget.show() | |
742 self.__widget.pack_start(_main_widget, True, True, 0) | |
743 | |
744 def _splitItem(self, path, orientation): | |
745 """_splitItem(self, path, orientation) | |
746 | |
747 Splits the item that is identifies by the path and the orientation | |
748 """ | |
749 _item = self.getItem(path) | |
750 _parent = self.getItem(path[:-1]) | |
751 _item.setPath(path+ (0,)) | |
752 _item_clone0 = _item.getClone(path + (0,)) | |
753 _item_clone1 = _item.getClone(path + (1,)) | |
754 _paned = Paned(orientation, path, _item_clone0, _item_clone1) | |
755 if len(path) > 1: | |
756 _parent.setItem(path[-1], [_paned]) | |
757 else: | |
758 self.setMainItem(_paned) | |
759 | |
760 def _closeItem(self, path): | |
761 """_closeItem(self, path) | |
762 | |
763 Closes the item that is identifies by the path | |
764 """ | |
765 _item = self.getItem(path) | |
766 if len(path) > 1: | |
767 # There are more than one item | |
768 _parent = self.getItem(path[:-1]) | |
769 _brothers = [ _brother for _brother in _parent] | |
770 _brothers.remove(_item) | |
771 _brother = _brothers[0] | |
772 | |
773 _parent.widget.remove(_brother.widget) | |
774 _brother.path = path[:-1] | |
775 if len(path) > 2: | |
776 _grandparent = self.getItem(path[:-2]) | |
777 _grandparent.setItem(path[-2], [_brother]) | |
778 _parent.widget.destroy() | |
779 _parent.clear() | |
780 _item.clear() | |
781 else: | |
782 _grandparent = self | |
783 _grandparent.setMainItem(_brother) | |
784 _parent.widget.destroy() | |
785 _parent.clear() | |
786 _item.clear() | |
787 else: | |
788 # Thre is only one item in the page, it can not be closed | |
789 pass | |
790 | |
791 def itemsFactory(self, list_paned, path=(0,)): | |
792 """def itemsFactory(self, list_paned, path(0,)) | |
793 | |
794 list_paned: list in "__panes_list" format | |
795 [ "v" or "h", panel1_type, panel2_type] | |
796 which contains the info for create the widgets. | |
797 panel types: | |
798 * "DecompositionList" | |
799 * "RecordDescription" | |
800 * "Measure" | |
801 * "Sheet of Conditions" | |
802 * "FileView" | |
803 * "CompanyView" | |
804 path: tuple that represents the item path in the page | |
805 | |
806 Creates the items and widgets and returns the main item | |
807 """ | |
808 if not isinstance(list_paned , list): | |
809 raise ValueError, _("The value must be a list") | |
810 if list_paned[0] == "v" or list_paned[0] == "h": | |
811 if len(list_paned) != 3: | |
812 raise ValueError, _("Incorrect len") | |
813 if not isinstance(list_paned[1],list): | |
814 list_paned[1] = [list_paned[1]] | |
815 if not isinstance(list_paned[2],list): | |
816 list_paned[2] = [list_paned[2]] | |
817 _item1 = self.itemsFactory(list_paned[1],path + (0,)) | |
818 _item2 = self.itemsFactory(list_paned[2],path + (1,)) | |
819 _item = Paned(list_paned[0], path, _item1, _item2) | |
820 elif list_paned[0] == "DecompositionList": | |
821 _item = View( "DecompositionList", self.__budget, | |
822 weakref.ref(self), path, self.__active_path_record) | |
823 elif list_paned[0] == "RecordDescription": | |
824 _item = View( "RecordDescription", self.__budget,weakref.ref(self), | |
825 path, self.__active_path_record) | |
826 elif list_paned[0] == "Measure": | |
827 _item = View( "Measure", self.__budget, weakref.ref(self), path, | |
828 self.__active_path_record) | |
829 elif list_paned[0] == "Sheet of Conditions": | |
830 _item = Sheet(sef.__budget, weakref.ref(self), path, | |
831 self.__active_path_record) | |
832 elif list_paned[0] == "FileView": | |
833 _item = FileView(sef.__budget, weakref.ref(self), path, | |
834 self.__active_path_record) | |
835 elif list_paned[0] == "CompanyView": | |
836 _item = CompanyView(sef.__budget, weakref.ref(self), path, | |
837 self.__active_path_record) | |
838 else: | |
839 _item = None | |
840 raise ValueError, utils.mapping(_("Incorrect item $1"), | |
841 (str(list_paned[0]),)) | |
842 return _item | |
843 | |
844 def setActivePathRecord(self, path_record): | |
845 """def setActivePathRecord(self, path_record) | |
846 | |
847 path_record: the active record path | |
848 | |
849 Sets the active record path | |
850 """ | |
851 if self.__budget.hasPath(path_record): | |
852 self.__active_path_record = path_record | |
853 else: | |
854 raise ValueError, utils.mapping(_("The budget does not have the "\ | |
855 "path record: $1"), (str(path_record),)) | |
856 | |
857 def getTitle(self): | |
858 """def getTtle(self) | |
859 | |
860 Return the title of the page, a gtk.Label objetc | |
861 """ | |
862 return self.__title | |
863 | |
864 def getWidget(self): | |
865 """def getWidget(self) | |
866 | |
867 Return de main widget to show in the pane | |
868 """ | |
869 return self.__widget | |
870 | |
871 def setBudget(self, budget): | |
872 """def setBudget(self, budget) | |
873 | |
874 budget: a base.Budget object | |
875 | |
876 Sets the budget and the active code atributes, | |
877 creates the page title and the widgets in the pane and | |
878 shows the main widget. | |
879 """ | |
880 if budget is None: | |
881 self.clear() | |
882 return | |
883 self.__budget = budget | |
884 self.setActivePathRecord((0,)) | |
885 ## Todo: change page title | |
886 self.__title = gtk.Label(self.__budget.getCode( | |
887 self.__active_path_record)) | |
888 _panes_list = self.__panes_list | |
889 self.__main_item = self.itemsFactory(_panes_list) | |
890 _main_widget = self.__main_item.getWidget() | |
891 _main_widget.show() | |
892 self.__widget.pack_start(_main_widget, True, True, 0) | |
893 | |
894 def getBudget(self): | |
895 """def getBudget(self) | |
896 | |
897 Return de budget, a "base.Budget" object. | |
898 """ | |
899 return self.__budget | |
900 | |
901 def getPanesList(self): | |
902 """def getPanesList(self) | |
903 | |
904 Return the panes list, info list for create the panes. | |
905 """ | |
906 return self.__panes_list | |
907 | |
908 budget = property(getBudget, setBudget, None, | |
909 "Budget to show, base.Budget object") | |
910 widget = property(getWidget, None, None, | |
911 "Main widget showed in the pane") | |
912 title = property(getTitle, None, None, | |
913 "Page Title") | |
914 panes_list = property(getPanesList, None, None, | |
915 "Info list for create the panes") | |
916 | |
917 class View(object): | |
918 """gui.View: | |
919 | |
920 Description: | |
921 It creates a view to show the budget info | |
922 Constructor: | |
923 View(view_type, budget, wr_page, path, active_path_record) | |
924 Ancestry: | |
925 +-- object | |
926 +-- Paned | |
927 Atributes: | |
928 "path": the tuple that identifies the view in the main notebook page | |
929 "widget": the main gtk widget to show in a view object, | |
930 a gtk.VBox object | |
931 "__view_type": the object type to show | |
932 * DecompositionList | |
933 * Description | |
934 * Measure | |
935 * Sheet of conditions | |
936 * FileView | |
937 * CompanyView | |
938 "__wr_page": weak reference to the page where the view must be showed | |
939 "__budget": the budget to show | |
940 "__view ": the object to show: | |
941 * DecompositionList object | |
942 * Description object | |
943 * Measure object | |
944 * Sheet object | |
945 * FileView object | |
946 * Comapany View | |
947 "__connected": boolean value, True means that the View object sends and | |
948 receives signals from/to others views | |
949 "__connected_button": a button to switch __connected True or False | |
950 Methods: | |
951 __init__(self) | |
952 getItem(self, path) | |
953 _closeItem(self, close_button) | |
954 _change_combo(self, combobox) | |
955 propagateMessgeFrom(self, message, path, arg=None) | |
956 runMessage(self, message, path, arg=None) | |
957 getWidget(self) | |
958 getPath(self) | |
959 setPath(self) | |
960 getClone(self, newpath) | |
961 clear(self) | |
962 """ | |
963 def __init__(self, view_type, budget, wr_page, path, active_path_record): | |
964 | |
965 """def __init__(self, view_type, budget, wr_page, path, | |
966 active_path_record) | |
967 view_type: the object type to show | |
968 * DecompositionList | |
969 * Description | |
970 * Measure | |
971 * Sheet | |
972 * FileView | |
973 * CompanyView | |
974 budget: the budget to show | |
975 wr_page: weak reference to the page where the view must be showed | |
976 path: the position or path of the view in the page notebook | |
977 active_path_record: the record path that must be showed | |
978 | |
979 Creates and shows a new view | |
980 """ | |
981 self.__active_path_record = active_path_record | |
982 self.__view_type = view_type | |
983 self.__wr_page = wr_page | |
984 self.__budget = budget | |
985 self.__path = path | |
986 self.__connected = True | |
987 # view_type liststore | |
988 _liststore = gtk.ListStore(str) | |
989 _liststore.append([_("Decomposition")]) #0 | |
990 _liststore.append([_("Description")]) #1 | |
991 _liststore.append([_("Measure")]) #2 | |
992 _liststore.append([_("Sheet of Conditions")]) #3 | |
993 _liststore.append([_("Files")]) #4 | |
994 _liststore.append([_("Companies")]) #5 | |
995 _combobox = gtk.ComboBox(_liststore) | |
996 _cell = gtk.CellRendererText() | |
997 _combobox.pack_start(_cell, True) | |
998 _combobox.add_attribute(_cell, 'text', 0) | |
999 _vbox = gtk.VBox() | |
1000 _vbox.show() | |
1001 _toolitem = gtk.ToolItem() | |
1002 _toolitem.set_expand(True) | |
1003 _toolitem.add(_vbox) | |
1004 _toolitem.show() | |
1005 self.__widget = gtk.Toolbar() | |
1006 self.__widget.insert(_toolitem, 0) | |
1007 _hbox = gtk.HBox() | |
1008 if view_type == "DecompositionList": | |
1009 self.__view = DecompositionList(budget, weakref.ref(self), | |
1010 path, active_path_record) | |
1011 _combobox.set_active(0) | |
1012 _view_icon = gtk.Image() | |
1013 _view_icon.set_from_file(globals.getAppPath("DECOMPOSITION-ICON")) | |
1014 elif view_type == "RecordDescription": | |
1015 self.__view = Description(budget, weakref.ref(self), | |
1016 path, active_path_record) | |
1017 _combobox.set_active(1) | |
1018 _view_icon = gtk.Image() | |
1019 _view_icon.set_from_file(globals.getAppPath("DESCRIPTION-ICON")) | |
1020 elif view_type == "Measure": | |
1021 self.__view = Measure(budget, weakref.ref(self), | |
1022 path, active_path_record) | |
1023 _combobox.set_active(2) | |
1024 _view_icon = gtk.Image() | |
1025 _view_icon.set_from_file(globals.getAppPath("MEASURE-ICON")) | |
1026 elif view_type == "Sheet of Conditions": | |
1027 self.__view = Sheet(budget, weakref.ref(self), | |
1028 path, active_path_record) | |
1029 _combobox.set_active(3) | |
1030 _view_icon = gtk.Image() | |
1031 _view_icon.set_from_file(globals.getAppPath("SHEET-ICON")) | |
1032 elif view_type == "FileView": | |
1033 self.__view = FileView(budget, weakref.ref(self), | |
1034 path, active_path_record) | |
1035 _combobox.set_active(4) | |
1036 _view_icon = gtk.Image() | |
1037 _view_icon.set_from_file(globals.getAppPath("SHEET-ICON")) | |
1038 elif view_type == "CompanyView": | |
1039 self.__view = CompanyView(budget, weakref.ref(self), path, | |
1040 active_path_record) | |
1041 _combobox.set_active(5) | |
1042 _view_icon = gtk.Image() | |
1043 _view_icon.set_from_file(globals.getAppPath("SHEET-ICON")) | |
1044 | |
1045 else: | |
1046 raise ValueError, _(utils.mapping("Invalid type of View: $1", | |
1047 view_type)) | |
1048 _view_icon.show() | |
1049 _combobox.connect("changed", self._change_combo) | |
1050 _combobox.show() | |
1051 _vbox.pack_start(_hbox,False) | |
1052 _vbox.pack_start(self.__view.widget, True, True) | |
1053 _hbox.pack_start(_view_icon, False, False,0) | |
1054 _hbox.pack_start(_combobox, False, False,0) | |
1055 _invisible = gtk.HBox() | |
1056 _invisible.show() | |
1057 _hbox.pack_start(_invisible, True, False,0) | |
1058 _icon_menu = gtk.Image() | |
1059 _icon_menu.set_from_file(globals.getAppPath("MENU-ICON")) | |
1060 _icon_menu.show() | |
1061 _menu_button = gtk.ToolButton() | |
1062 _menu_button.set_icon_widget(_icon_menu) | |
1063 _menu_button.connect("clicked", self._menu_view) | |
1064 _menu_button.show() | |
1065 _icon_connected = gtk.Image() | |
1066 _icon_connected.set_from_file(globals.getAppPath("CONNECTED-ICON")) | |
1067 _icon_connected.show() | |
1068 _hbox.pack_start(_menu_button, False, False, 0) | |
1069 self.__connected_button = gtk.ToolButton() | |
1070 self.__connected_button.set_icon_widget(_icon_connected) | |
1071 self.__connected_button.connect("clicked", self._connected) | |
1072 self.__connected_button.show() | |
1073 _hbox.pack_start(self.__connected_button, False, False, 0) | |
1074 _icon_close = gtk.Image() | |
1075 _icon_close.set_from_file(globals.getAppPath("CLOSE-ICON")) | |
1076 _icon_close.show() | |
1077 _close_button = gtk.ToolButton() | |
1078 _close_button.set_icon_widget(_icon_close) | |
1079 _close_button.connect("clicked", self._closeItem) | |
1080 _close_button.show() | |
1081 _hbox.pack_start(_close_button, False, False, 0) | |
1082 _hbox.show() | |
1083 self.__widget.show() | |
1084 | |
1085 def getItem(self, path): | |
1086 """def getItem(self, path) | |
1087 | |
1088 Return itself. | |
1089 """ | |
1090 return self | |
1091 | |
1092 def _closeItem(self, close_button): | |
1093 """_closeItem(self, widget) | |
1094 | |
1095 Method connected to the "clicked" signal of the _close_button widget | |
1096 Send the "autoclose" message to the page to close this view | |
1097 """ | |
1098 self.propagateMessageFrom( "autoclose", self.__path) | |
1099 | |
1100 def _change_combo(self, combobox): | |
1101 """_change_combo(self, combobox) | |
1102 | |
1103 Method connected to the "changed" signal of the _combobox widget | |
1104 It changes the view type to the type selected in the combobox | |
1105 """ | |
1106 _index = combobox.get_active() | |
1107 _budget = self.__view.budget | |
1108 _wr_page = self.__view.page | |
1109 _path = self.__view.path | |
1110 _path_record = self.__view.active_path_record | |
1111 _toolitem = self.__widget.get_nth_item(0) | |
1112 _vbox= _toolitem.get_children()[0] | |
1113 _hbox = _vbox.get_children()[0] | |
1114 _combobox = _hbox.get_children()[1] | |
1115 _hbox.remove(_combobox) | |
1116 _invisible = _hbox.get_children()[1] | |
1117 _hbox.remove(_invisible) | |
1118 _menu_button = _hbox.get_children()[1] | |
1119 _hbox.remove(_menu_button) | |
1120 _connected_button = _hbox.get_children()[1] | |
1121 _hbox.remove(_connected_button) | |
1122 _close_button = _hbox.get_children()[1] | |
1123 _hbox.remove(_close_button) | |
1124 _vbox.remove(self.__view.widget) | |
1125 _vbox.remove(_hbox) | |
1126 _hbox.destroy() | |
1127 _view_icon = gtk.Image() | |
1128 if _index == 0: | |
1129 self.__view = DecompositionList(_budget, _wr_page, _path, | |
1130 _path_record) | |
1131 | |
1132 _view_icon.set_from_file(globals.getAppPath("DECOMPOSITION-ICON")) | |
1133 self.__view_type = "DecompositionList" | |
1134 elif _index == 1: | |
1135 self.__view = Description(_budget, _wr_page, _path, | |
1136 _path_record) | |
1137 _view_icon.set_from_file(globals.getAppPath("DESCRIPTION-ICON")) | |
1138 self.__view_type = "RecordDescription" | |
1139 elif _index == 2: | |
1140 self.__view = Measure(_budget, _wr_page, _path, | |
1141 _path_record) | |
1142 _view_icon.set_from_file(globals.getAppPath("MEASURE-ICON")) | |
1143 self.__view_type = "Measure" | |
1144 elif _index == 3: | |
1145 self.__view = Sheet(_budget, _wr_page, _path, | |
1146 _path_record) | |
1147 _view_icon.set_from_file(globals.getAppPath("SHEET-ICON")) | |
1148 self.__view_type = "Sheet of Conditions" | |
1149 elif _index == 4: | |
1150 self.__view = FileView(_budget, _wr_page, _path, | |
1151 _path_record) | |
1152 _view_icon.set_from_file(globals.getAppPath("SHEET-ICON")) | |
1153 self.__view_type = "FileView" | |
1154 elif _index == 5: | |
1155 self.__view = CompanyView(_budget, _wr_page, _path, | |
1156 _path_record) | |
1157 _view_icon.set_from_file(globals.getAppPath("SHEET-ICON")) | |
1158 self.__view_type = "CompanyView" | |
1159 _view_icon.show() | |
1160 _hbox = gtk.HBox() | |
1161 _hbox.pack_start(_view_icon, False, False,0) | |
1162 _hbox.pack_start(_combobox, False, False,0) | |
1163 _hbox.pack_start(_invisible, True, False,0) | |
1164 _hbox.pack_start(_menu_button, False, False, 0) | |
1165 _hbox.pack_start(_connected_button, False, False, 0) | |
1166 _hbox.pack_start(_close_button, False, False, 0) | |
1167 _hbox.show() | |
1168 _vbox.pack_start(_hbox, False, False, 0) | |
1169 _vbox.pack_start(self.__view.widget, True, True, 0) | |
1170 | |
1171 def _menu_view(self, widget): | |
1172 """_menu_view(self, widget) | |
1173 | |
1174 Method connected to the "clicked" signal of the __connected_button | |
1175 It shows a popup menu with some options | |
1176 """ | |
1177 _menu_view = gtk.Menu() | |
1178 _item_leftright = gtk.MenuItem("Split View Left/Right") | |
1179 _menu_view.append(_item_leftright) | |
1180 _item_leftright.connect_object("activate", self._split_view, "h") | |
1181 _item_leftright.show() | |
1182 _item_topbottom = gtk.MenuItem("Split View Top/Bottom") | |
1183 _menu_view.append(_item_topbottom) | |
1184 _item_topbottom.connect_object("activate", self._split_view, "v") | |
1185 _item_topbottom.show() | |
1186 _item_close = gtk.MenuItem("close view") | |
1187 _menu_view.append(_item_close) | |
1188 _item_close.connect_object("activate", self._closeItem, None) | |
1189 _item_close.show() | |
1190 _menu_view.popup(None, None, None, 0, 0) | |
1191 | |
1192 def _split_view(self, orientation): | |
1193 """_menu_view(self, orientation) | |
1194 | |
1195 orientation: orientation split, "h" or "v" | |
1196 | |
1197 Method connected to the "activate" signal of the _item_leftright and | |
1198 _item_topbottom menu items. | |
1199 It sends the "split" message to the page to splits the view in the | |
1200 specified orientation | |
1201 """ | |
1202 self.propagateMessageFrom( "split " + orientation, self.__path) | |
1203 | |
1204 def _connected(self, widget): | |
1205 """_connected(self, widget) | |
1206 | |
1207 Method connected to the "clicked" signal of the _menu_button | |
1208 It changes the __connected atribute to True or False, if the | |
1209 _connected atribute is False the view do not send and receive messages | |
1210 to/from others views | |
1211 """ | |
1212 if self.__connected: | |
1213 _icon = gtk.Image() | |
1214 _icon.set_from_file(globals.getAppPath("DISCONNECTED-ICON")) | |
1215 _icon.show() | |
1216 self.__connected_button.set_icon_widget(_icon) | |
1217 self.__connected = False | |
1218 else: | |
1219 _icon = gtk.Image() | |
1220 _icon.set_from_file(globals.getAppPath("CONNECTED-ICON")) | |
1221 _icon.show() | |
1222 self.__connected_button.set_icon_widget(_icon) | |
1223 self.__connected = True | |
1224 | |
1225 def propagateMessageFrom(self, message, path, arg=None): | |
1226 """def propagateMessageFrom(self, message, path, arg=None) | |
1227 | |
1228 message: string message | |
1229 path: tuple that represents the pane path which emits the message | |
1230 arg: arguments for the message | |
1231 The panes are connectted to this method to send messages to other panes | |
1232 """ | |
1233 if self.__connected or message == "autoclose" or \ | |
1234 message == "split h" or message == "split v": | |
1235 self.__wr_page().propagateMessageFrom(message, path, arg) | |
1236 | |
1237 def runMessage(self, message, path, arg=None): | |
1238 """def runMessage(self, message, path, arg=None) | |
1239 | |
1240 message: the message type | |
1241 "change_active": change the active record | |
1242 "clear": clear instance | |
1243 path: tuple that identifies the pane in the notebook page | |
1244 arg: tuple whit two items: | |
1245 0: record path in the budget | |
1246 1: record code | |
1247 This method receives a message and executes its corresponding action | |
1248 """ | |
1249 if self.__connected: | |
1250 self.__view.runMessage(message, path, arg) | |
1251 if message == "change_active": | |
1252 if self.__budget.hasPath(arg): | |
1253 _path_record = arg | |
1254 self.__active_path_record = _path_record | |
1255 | |
1256 def getWidget(self): | |
1257 """def getWidget(self) | |
1258 | |
1259 Return de pane widget | |
1260 """ | |
1261 return self.__widget | |
1262 | |
1263 def getPath(self): | |
1264 """def getPath(self) | |
1265 | |
1266 return the tuple that identifies the pane in the notebook page | |
1267 """ | |
1268 return self.__view.path | |
1269 | |
1270 def setPath(self, path): | |
1271 """def setPath(self) | |
1272 | |
1273 set the tuple that identifies the pane in the notebook page | |
1274 """ | |
1275 self.__path = path | |
1276 self.__view.path = path | |
1277 | |
1278 def getClone(self, new_path): | |
1279 """getClone(self, new_path) | |
1280 | |
1281 new_path: the path that identifies the clone view in the page | |
1282 | |
1283 return a clone of itself | |
1284 """ | |
1285 return View(self.__view_type, self.__budget, self.__wr_page, | |
1286 new_path, self.__active_path_record) | |
1287 | |
1288 def clear(self): | |
1289 """clear(self) | |
1290 | |
1291 Clear the intance atributes | |
1292 """ | |
1293 del self.__wr_page | |
1294 del self.__budget | |
1295 del self.__path | |
1296 del self.__widget | |
1297 del self.__view | |
1298 del self.__connected | |
1299 del self.__connected_button | |
1300 | |
1301 path = property(getPath, setPath, None, | |
1302 "path that identifies the item in the notebook page") | |
1303 widget = property(getWidget, None, None, "View widget") | |
1304 | |
1305 class Paned(object): | |
1306 """gui.Paned: | |
1307 | |
1308 Description: | |
1309 It creates and shows gtk.Hpaned or gtk.Vpaned to show in page budget | |
1310 Constructor: | |
1311 Paned(orientation, widget1, widget2) | |
1312 orientation: The orientation of the pane separator, can be "v" or "h" | |
1313 widget1: the top or left pane widget | |
1314 widget2: the botton or right pane widget | |
1315 Returns the newly created Paned instance | |
1316 Ancestry: | |
1317 +-- object | |
1318 +-- Paned | |
1319 Atributes: | |
1320 "widget": Pane widget("gtk.VPaned" or "gtk.HPaned" object) | |
1321 "__orientation": The orientation of de gtk.Paned, can be "v" or "h" | |
1322 "__items": list of items showed in the paned, its can be View or Paned | |
1323 instances | |
1324 "__path": the paned path in the page | |
1325 Methods: | |
1326 __init__(self) | |
1327 __getitem__(self, item) | |
1328 getClone(self, new_path) | |
1329 getItem(self, path) | |
1330 runMessage(self, messge, path, arg=None) | |
1331 getWidget(self) | |
1332 {get/set}Path | |
1333 clear(self) | |
1334 """ | |
1335 # TODO: *control the position paned separator. Now is always 200 pixels | |
1336 # TODO: can be with a float(0.0-1.0) aspect ratio | |
1337 # TODO: 0.0 no space for widget1 | |
1338 # TODO: 1.0 all the space for widget1 | |
1339 # TODO: *control the position pane separator when the size of the window | |
1340 # TODO: change with the same ascpect ratio | |
1341 | |
1342 def __init__(self, orientation, path, item1, item2): | |
1343 """def __init__(self, oritentation, path, item1, item2) | |
1344 | |
1345 orientation: The orientation of de gtk.Paned, can be "v" or "h" | |
1346 path: the paned path in the page | |
1347 item1: the top or left pane object | |
1348 item2: the bottom or right pane object | |
1349 | |
1350 Creates and shows a new gtk.Paned | |
1351 """ | |
1352 self.__orientation = orientation | |
1353 if not isinstance(item1.widget, gtk.Widget) or \ | |
1354 not isinstance(item2.widget, gtk.Widget): | |
1355 raise ValueError, _("The item must be a widget object.") | |
1356 if orientation == "v": | |
1357 self.__widget = gtk.VPaned() | |
1358 elif orientation == "h": | |
1359 self.__widget = gtk.HPaned() | |
1360 else: | |
1361 raise ValueError, _("Invalid orientation.") | |
1362 self.__widget.pack1(item1.widget,True,False) | |
1363 self.__widget.pack2(item2.widget,True,False) | |
1364 self.__widget.set_position(200) | |
1365 self.__widget.show() | |
1366 self.__items = [item1, item2] | |
1367 self.__path = path | |
1368 | |
1369 def __getitem__(self, item): | |
1370 """__getitem__(self, item) | |
1371 | |
1372 Called to implement evaluation of self[key]. | |
1373 The accepted keys should be integers 0 or 1. | |
1374 """ | |
1375 return self.__items[item] | |
1376 | |
1377 def getClone(self, new_path): | |
1378 """getClone(self, new_path) | |
1379 | |
1380 Return a clone Paned instance with the path new_path | |
1381 """ | |
1382 return Paned(self.__orientation, new_path, | |
1383 self.__items[0].getClone(new_path + (0,)), | |
1384 self.__items[1].getClone(new_path + (1,))) | |
1385 | |
1386 def getItem(self,path): | |
1387 """def getItem(self, path) | |
1388 | |
1389 Return the item whith the specified path. | |
1390 """ | |
1391 _item = self.__items[path[0]] | |
1392 if len(path) == 1: | |
1393 return _item | |
1394 else: | |
1395 return _item.getItem(path[1:]) | |
1396 | |
1397 def setItem(self, path, item_list): | |
1398 """def setItem(self, path, item_list) | |
1399 | |
1400 Sets the first item in the item_list whith the especified path and | |
1401 remove the old item in this position. | |
1402 """ | |
1403 item = item_list[0] | |
1404 if path == 0 or path == 1: | |
1405 _old_item = self.__items[path] | |
1406 self.__widget.remove(_old_item.widget) | |
1407 self.__items[path] = item | |
1408 if path == 0: | |
1409 self.__widget.pack1(item.widget,True,False) | |
1410 else: | |
1411 self.__widget.pack2(item.widget,True,False) | |
1412 return True | |
1413 return False | |
1414 | |
1415 def runMessage(self, message, path, arg=None): | |
1416 """def runMessage(self, message, page_path, arg=None) | |
1417 | |
1418 message: the message type | |
1419 "change_active": change the active record | |
1420 "clear": clear instance | |
1421 page_path: tuple that identifies the pane in the notebook page | |
1422 arg: arguments | |
1423 | |
1424 This method receives a message and send this to the items of the paned | |
1425 """ | |
1426 for _item in self.__items: | |
1427 if not _item.path == path: | |
1428 _item.runMessage(message, path, arg) | |
1429 | |
1430 def getWidget(self): | |
1431 """def getWidget(self) | |
1432 | |
1433 Return de gtk.Paned widget | |
1434 """ | |
1435 return self.__widget | |
1436 | |
1437 def getPath(self): | |
1438 """def getPath(self) | |
1439 | |
1440 Return de Paned path in the notebook page | |
1441 """ | |
1442 return self.__path | |
1443 | |
1444 def setPath(self, path): | |
1445 """def setPath(self) | |
1446 | |
1447 sets the tuple that identifies the pane in the notebook page | |
1448 """ | |
1449 self.__path = path | |
1450 self.__items[0].path = path + (0,) | |
1451 self.__items[1].path = path + (1,) | |
1452 | |
1453 def clear(self): | |
1454 del self.__widget | |
1455 del self.__orientation | |
1456 del self.__items | |
1457 del self.__path | |
1458 | |
1459 widget = property(getWidget, None, None, "gtk.Paned widget") | |
1460 path = property(getPath, setPath, None, "Pane path in the notebook page") | |
1461 | |
1462 class TreeView(object): | |
1463 """gui.Treeviev: | |
1464 | |
1465 Description: | |
1466 It creates the columns in a treeview, is the base class for | |
1467 DescompositionList and Measure classes | |
1468 Constructor: | |
1469 TreView(args) | |
1470 args: list of tuples, the tuple items are: | |
1471 0.type: | |
1472 * index column | |
1473 * float column | |
1474 * text column | |
1475 * calculated column | |
1476 * calculated text | |
1477 * type column | |
1478 1. clicked method | |
1479 2. width | |
1480 3. text color | |
1481 4. backgruound colors | |
1482 5. model column index | |
1483 Ancestry: | |
1484 +-- object | |
1485 +-- TreeView | |
1486 Atributes: | |
1487 "columns": list of columns (gtk.TreeViewColumn isntances) | |
1488 Methods: | |
1489 __init__(self) | |
1490 __getitem__(self, item) | |
1491 createColumn(self, args) | |
1492 createTextBaseColumn(self,args) | |
1493 createBaseColumn(self,args) | |
1494 """ | |
1495 | |
1496 def __init__(self, args): | |
1497 """__init__(self, args) | |
1498 | |
1499 args: list of tuples, the tuple items are: | |
1500 0.type: | |
1501 * index column | |
1502 * float column | |
1503 * text column | |
1504 * calculated column | |
1505 * Calculated text | |
1506 * type column | |
1507 1. clicked method | |
1508 2. width | |
1509 3. text color | |
1510 4. backgruound colors | |
1511 5. model column index | |
1512 | |
1513 Create the columns form the args info calling creatheColumn to create | |
1514 each column | |
1515 """ | |
1516 self.columns = [ self.createColumn(arg) for arg in args ] | |
1517 self.columns.append(self.createColumn(("END",))) | |
1518 | |
1519 def createColumn(self, args): | |
1520 """createColumn(self, args) | |
1521 | |
1522 args: tuple with the args | |
1523 0.type: | |
1524 * index column | |
1525 * float column | |
1526 * text column | |
1527 * calculated column | |
1528 * calculated text | |
1529 * type column | |
1530 1. clicked method | |
1531 2. width | |
1532 3. text color | |
1533 4. backgruound colors | |
1534 5. model column index | |
1535 | |
1536 Return a column created whith the arg info | |
1537 """ | |
1538 if args[0] == "INDEX": | |
1539 _index_column = self.createBaseColumn(args) | |
1540 _text_index_cell = gtk.CellRendererText() | |
1541 _text_index_cell.set_property('foreground-gdk', | |
1542 gtk.gdk.color_parse(globals.color["TEXT"])) | |
1543 _pixbuf_index_cell = gtk.CellRendererPixbuf() | |
1544 _arrow_icon = gtk.gdk.pixbuf_new_from_file( | |
1545 globals.getAppPath("ARROW-ICON")) | |
1546 _pixbuf_index_cell.set_property("pixbuf", _arrow_icon) | |
1547 _index_column.pack_start(_text_index_cell, True) | |
1548 _index_column.pack_start(_pixbuf_index_cell, True) | |
1549 _index_column.set_cell_data_func(_text_index_cell, | |
1550 self.colorCell, | |
1551 [gtk.gdk.color_parse(globals.color["INDEX-UNEVEN"]), | |
1552 gtk.gdk.color_parse(globals.color["INDEX-EVEN"])]) | |
1553 return _index_column | |
1554 elif args[0] == "TEXT": | |
1555 _column, _cell = self.createTextBaseColumn(args) | |
1556 _column.add_attribute(_cell, 'text', args[5]) | |
1557 return _column | |
1558 elif args[0] == "FLOAT": | |
1559 _column, _cell = self.createTextBaseColumn(args) | |
1560 _column.add_attribute(_cell, 'text', args[5]) | |
1561 _column.get_cell_renderers()[0].set_property('xalign', 1.0) | |
1562 return _column | |
1563 elif args[0] == "CALCULATED": | |
1564 _column, cell = self.createTextBaseColumn(args) | |
1565 _column.get_cell_renderers()[0].set_property('xalign', 1.0) | |
1566 return _column | |
1567 elif args[0] == "CALCULATEDTEXT": | |
1568 _column, cell = self.createTextBaseColumn(args) | |
1569 return _column | |
1570 elif args[0] == "TYPE": | |
1571 _column = self.createBaseColumn(args) | |
1572 _type_cell1 = gtk.CellRendererPixbuf() | |
1573 _type_cell2 = gtk.CellRendererText() | |
1574 _type_cell2.set_property('foreground-gdk', args[3]) | |
1575 _column.pack_start(_type_cell1, True) | |
1576 _column.pack_start(_type_cell2, True) | |
1577 _column.add_attribute(_type_cell2, 'text', args[5]) | |
1578 _column.set_cell_data_func(_type_cell1, | |
1579 self.colorCell, args[4]) | |
1580 _column.set_cell_data_func(_type_cell2, | |
1581 self.colorCell, args[4]) | |
1582 return _column | |
1583 elif args[0] == "PIXBUF": | |
1584 _column = self.createBaseColumn(args) | |
1585 _type_cell1 = gtk.CellRendererPixbuf() | |
1586 _column.pack_start(_type_cell1, True) | |
1587 _column.set_cell_data_func(_type_cell1, | |
1588 self.colorCell, args[4]) | |
1589 return _column | |
1590 elif args[0] == "END": | |
1591 _end_column = gtk.TreeViewColumn() | |
1592 _end_column.set_clickable(False) | |
1593 _end_cell = gtk.CellRendererText() | |
1594 _end_cell.set_property('cell-background-gdk', | |
1595 gtk.gdk.color_parse(globals.color["UNEVEN"])) | |
1596 _end_column.pack_start(_end_cell, True) | |
1597 return _end_column | |
1598 return None | |
1599 | |
1600 def createTextBaseColumn(self,args): | |
1601 """createTextBaseColumn(self,args) | |
1602 | |
1603 args: tuple with the args | |
1604 0.type: | |
1605 * float column | |
1606 * text column | |
1607 * calculated column | |
1608 * calculated text | |
1609 1. clicked method | |
1610 2. width | |
1611 3. text color | |
1612 4. backgruound colors | |
1613 5. model column index | |
1614 | |
1615 Return a column and its CellREndererText | |
1616 """ | |
1617 _column = self.createBaseColumn(args) | |
1618 _cell = gtk.CellRendererText() | |
1619 _cell.set_property('foreground-gdk', args[3]) | |
1620 _column.pack_start(_cell, True) | |
1621 _column.set_cell_data_func(_cell, self.colorCell, args[4]) | |
1622 return _column, _cell | |
1623 | |
1624 def createBaseColumn(self,args): | |
1625 """createBaseColumn(self,args) | |
1626 | |
1627 args: tuple with the args | |
1628 0.type: | |
1629 * index column | |
1630 * float column | |
1631 * text column | |
1632 * calculated column | |
1633 * calculated text column | |
1634 * type column | |
1635 1. clicked method | |
1636 2. width | |
1637 3. text color | |
1638 4. backgruound colors | |
1639 5. model column index | |
1640 | |
1641 Return a column | |
1642 """ | |
1643 _column = gtk.TreeViewColumn() | |
1644 _column.set_clickable(True) | |
1645 _column.connect("clicked", args[1]) | |
1646 _column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) | |
1647 _column.set_fixed_width(args[2]) | |
1648 _column.set_resizable(True) | |
1649 return _column | |
1650 | |
1651 class DecompositionList(TreeView): | |
1652 """gui.DecompositionList: | |
1653 | |
1654 Description: | |
1655 Class to show a budget Decomposition List | |
1656 Constructor: | |
1657 DecompositionList(budget, page, path) | |
1658 budget: budget showed ("base.Budget" object) | |
1659 page: weak reference from Page instance which creates this class | |
1660 path: tuple that represents the view path in the Page | |
1661 Returns the newly created DecompositionList instance | |
1662 Ancestry: | |
1663 +-- object | |
1664 +-- TreeView | |
1665 +-- DecompositionList | |
1666 Atributes: | |
1667 "budget": Budget to show, base.obra instance. | |
1668 "widget or __scrolled_window": Window that contains the table, | |
1669 (gtk.ScrolledWindow) | |
1670 "path": Pane page identifier | |
1671 "page": weak reference from Page instance which creates this class | |
1672 "__active_color": background color of the active cell, a | |
1673 gtk.gdk.Color object | |
1674 "__chapter_background_colors": background colors of the Code | |
1675 column cells when there is a chapter record, | |
1676 list of gtk.gdk.Color objects [even cell, uneven cell] | |
1677 "__methond_message": Method to send messages to the page | |
1678 "__liststore": list model which store the list data | |
1679 (gtk.ListStore object) | |
1680 "__treeview": widget for displaying decomposition lists (gtk.TreeView) | |
1681 "__index_column": Index column (gtk.TreeViewColumn object) | |
1682 "__code_column": Record code column (gtk.TreeViewColumn) | |
1683 "__unit_column": Unit of measure column (gtk.TreeViewColumn) | |
1684 "__description_column": record's short description column | |
1685 (gtk.TreeViewColumn) | |
1686 "__measure_column": Measure column (gtk.TreeViewColumn) | |
1687 "__price_column": Price column (gtk.TreeViewColumn) | |
1688 "__amount_column": Amount column(gtk.TreeViewColumn) | |
1689 "__end_column": End empty column (gtk.TreeViewColumn) | |
1690 "__treeselection": active selection | |
1691 "__selection_control": state of the selection control (True/False) | |
1692 "__cursor": cursor position in the table | |
1693 Methods: | |
1694 __init__(self, budget) | |
1695 treeviewCursorChanged(self, treeview) | |
1696 treeviewClickedEvent(self, widget, event) | |
1697 treeviewKeyPressEvent(self, widget, event) | |
1698 moveCursor(self, treeview, step, count) | |
1699 controlSelection(self, selection) | |
1700 selectAll(self, column) | |
1701 setColumnsHeaders(self) | |
1702 setListstoreValues(self, puntero, treeiter=None) | |
1703 colorCell(self, column, cell_renderer, tree_model, iter, lcolor) | |
1704 _claculateAmount(self, row_path, tree_model) | |
1705 showParentRecord(self, column) | |
1706 showMessageRecord(self, camino,_code): | |
1707 showRowRecord(self, treeview, path, column) | |
1708 runMessage(self, messagem path, arg=None) | |
1709 _clear(self) | |
1710 getWidget(self) | |
1711 {get/set}Path | |
1712 {get/seg}Page | |
1713 getBudget(self) | |
1714 getActivePathRecord(self) | |
1715 """ | |
1716 | |
1717 def __init__(self, budget, page, path, path_record=(0,)): | |
1718 """def __init__(self, budget, page, path) | |
1719 | |
1720 budget: budget showed ("base.Budget" object) | |
1721 page: weak reference from Page instance which creates this class | |
1722 path: tuple that represents the path of the List in the Page | |
1723 | |
1724 Sets the init atributes | |
1725 Creates the init list values in self.__liststore from the budget | |
1726 showing the top record descomposition | |
1727 Creates the list in self.__treeview | |
1728 * Creates the columns and cell | |
1729 * Sets te the column headers values | |
1730 * Sets the selection properties | |
1731 * Connects the events | |
1732 """ | |
1733 # TODO: to group all columns in a dicctionary | |
1734 # Budget | |
1735 if not isinstance(budget, base.Budget): | |
1736 raise ValueError, _("Argument must be a Budget object") | |
1737 self.__budget = budget | |
1738 self.__page = page | |
1739 self.__path = path | |
1740 # ListStore | |
1741 self.__liststore = gtk.ListStore(object | |
1742 #, int, int, str, str, str, str, str,str | |
1743 ) | |
1744 if path_record is None: | |
1745 print _("DecompositionList.__init__: Record path can not be None") | |
1746 path_record = (0,) | |
1747 self.__active_path_record = path_record | |
1748 self.setListstoreValues(self.__active_path_record) | |
1749 # Treeview | |
1750 self.__treeview = gtk.TreeView(self.__liststore) | |
1751 self.__treeview.set_enable_search(False) | |
1752 self.__treeview.set_reorderable(False) | |
1753 self.__treeview.set_headers_clickable(True) | |
1754 self.__treeview.show() | |
1755 # Scrolled_window | |
1756 self.__scrolled_window = gtk.ScrolledWindow() | |
1757 self.__scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, | |
1758 gtk.POLICY_AUTOMATIC) | |
1759 self.__scrolled_window.add(self.__treeview) | |
1760 # colors | |
1761 _text_color = gtk.gdk.color_parse(globals.color["TEXT"]) | |
1762 _background_color = [ | |
1763 gtk.gdk.color_parse(globals.color["UNEVEN"]), | |
1764 gtk.gdk.color_parse(globals.color["EVEN"])] | |
1765 self.__chapter_background_colors = [ | |
1766 gtk.gdk.color_parse(globals.color["CHAPTER-UNEVEN"]), | |
1767 gtk.gdk.color_parse(globals.color["CHAPTER-EVEN"])] | |
1768 super(DecompositionList,self).__init__( | |
1769 [("INDEX",self.selectAll,42), | |
1770 ("CALCULATEDTEXT", self.showParentRecord, | |
1771 gtk.Label("A"*10).size_request()[0] +10, | |
1772 _text_color, _background_color), | |
1773 ("PIXBUF", self.showParentRecord, 26, _text_color, | |
1774 _background_color), | |
1775 ("CALCULATEDTEXT", self.showParentRecord, | |
1776 gtk.Label(_("a"*4)).size_request()[0] +10, | |
1777 _text_color, _background_color), | |
1778 ("CALCULATEDTEXT", self.showParentRecord, | |
1779 gtk.Label("a"*30).size_request()[0] +10, | |
1780 _text_color, _background_color), | |
1781 ("CALCULATED", self.showParentRecord, | |
1782 gtk.Label("a"*10).size_request()[0] +10, | |
1783 _text_color, _background_color), | |
1784 ("CALCULATED", self.showParentRecord, | |
1785 gtk.Label("a"*10).size_request()[0] +10, | |
1786 _text_color, _background_color), | |
1787 ("CALCULATED", self.showParentRecord, | |
1788 gtk.Label("a"*10).size_request()[0] +10, | |
1789 gtk.gdk.color_parse(globals.color["CALCULATED-TEXT"]), | |
1790 _background_color), | |
1791 ]) | |
1792 self.__index_column = self.columns[0] | |
1793 self.__code_column = self.columns[1] | |
1794 self.__type_column = self.columns[2] | |
1795 self.__unit_column = self.columns[3] | |
1796 self.__description_column = self.columns[4] | |
1797 self.__measure_column = self.columns[5] | |
1798 self.__price_column = self.columns[6] | |
1799 self.__amount_column = self.columns[7] | |
1800 self.__end_column = self.columns[8] | |
1801 # Index column | |
1802 self.__treeview.append_column(self.__index_column) | |
1803 # Code column | |
1804 self.__treeview.append_column(self.__code_column) | |
1805 # Type column | |
1806 self.__treeview.append_column(self.__type_column) | |
1807 self.chapter_icon = gtk.gdk.pixbuf_new_from_file( | |
1808 globals.getAppPath("CHAPTER-ICON")) | |
1809 self.unit_icon = gtk.gdk.pixbuf_new_from_file( | |
1810 globals.getAppPath("UNIT-ICON") ) | |
1811 self.material_icon = gtk.gdk.pixbuf_new_from_file( | |
1812 globals.getAppPath("MATERIAL-ICON") ) | |
1813 self.machinery_icon = gtk.gdk.pixbuf_new_from_file( | |
1814 globals.getAppPath("MACHINERY-ICON")) | |
1815 self.labourforce_icon = gtk.gdk.pixbuf_new_from_file( | |
1816 globals.getAppPath("LABOURFORCE-ICON")) | |
1817 self.__type_column.get_cell_renderers()[0].set_property("pixbuf", | |
1818 self.labourforce_icon) | |
1819 | |
1820 # Unit column | |
1821 self.__treeview.append_column(self.__unit_column) | |
1822 # Description column | |
1823 self.__treeview.append_column(self.__description_column) | |
1824 # Measure Column | |
1825 self.__treeview.append_column(self.__measure_column) | |
1826 # Price column | |
1827 self.__treeview.append_column(self.__price_column) | |
1828 # Amount column | |
1829 self.__treeview.append_column(self.__amount_column) | |
1830 # End Column | |
1831 self.__treeview.append_column(self.__end_column) | |
1832 # Connect | |
1833 self.__treeview.connect("row-activated", self.showRowRecord) | |
1834 self.__treeview.connect("move-cursor", self.moveCursor) | |
1835 self.__treeview.connect("key-press-event", self.treeviewKeyPressEvent) | |
1836 self.__treeview.connect("button-press-event", self.treeviewClickedEvent) | |
1837 self.__treeview.connect("cursor-changed", self.treeviewCursorChanged) | |
1838 # control selection | |
1839 self.__treeselection = self.__treeview.get_selection() | |
1840 self.__treeselection.set_mode(gtk.SELECTION_MULTIPLE) | |
1841 self.__treeselection.set_select_function(self.controlSelection) | |
1842 self.__selection_control = True | |
1843 if len(self.__liststore) > 0: | |
1844 self.__treeview.set_cursor_on_cell((0,),self.__unit_column, | |
1845 self.__unit_column.get_cell_renderers()[0],True) | |
1846 self.__treeview.grab_focus() | |
1847 self.__cursor = self.__treeview.get_cursor() | |
1848 # Show | |
1849 self.setColumnsHeaders() | |
1850 self.__scrolled_window.show() | |
1851 | |
1852 def treeviewCursorChanged(self, treeview): | |
1853 """def treeviewCursorChanged(self, treeview) | |
1854 | |
1855 treeview: treewiew widget | |
1856 Method connected to "cursor-changed" signal | |
1857 The "cursor-changed" signal is emitted when the cursor moves or is set | |
1858 Sets the new cursor position in self.__cursor, it is used to avoid | |
1859 unnecessary changes in cursor position. | |
1860 """ | |
1861 event = gtk.get_current_event() | |
1862 (_cursor_path, _column) = treeview.get_cursor() | |
1863 if event is None or event.type != gtk.gdk.BUTTON_RELEASE: | |
1864 if not _column is self.__index_column: | |
1865 self.__cursor = treeview.get_cursor() | |
1866 | |
1867 def treeviewClickedEvent(self, widget, event): | |
1868 """def treeviewClickedEvent(self, widget, event) | |
1869 | |
1870 widget: treewiew widget | |
1871 event: clicked event | |
1872 Method connected to "button-press-event" signal | |
1873 The "button-press-event" signal is emitted when a mouse button is | |
1874 pressed. | |
1875 Returns TRUE to stop other handlers from being invoked for the event. | |
1876 Returns FALSE to propagate the event further. | |
1877 | |
1878 The events in end column are ignored. | |
1879 If the user click in a row of the index column the cursor is moved to | |
1880 this row but not to the index column | |
1881 """ | |
1882 if event.button == 1: | |
1883 path_at_pos = self.__treeview.get_path_at_pos(int(event.x), | |
1884 int(event.y)) | |
1885 if not path_at_pos is None: | |
1886 _path_cursor, _column, _x, _y = path_at_pos | |
1887 if _column == self.columns[-1]: | |
1888 return True | |
1889 if _column is self.columns[0]: | |
1890 self.__cursor[0] == _path_cursor | |
1891 return False | |
1892 | |
1893 def treeviewKeyPressEvent(self, widget, event): | |
1894 """def treeviewKeyPressEvent(self, widget, event) | |
1895 | |
1896 widget: treewiew widget | |
1897 event: Key Press event | |
1898 Method connected to "key-press-event" signal | |
1899 The "key-press-event" signal is emitted when the user presses a key | |
1900 on the keyboard. | |
1901 Returns :TRUE to stop other handlers from being invoked for the event. | |
1902 Returns :FALSE to propagate the event further. | |
1903 | |
1904 If the user press the right cursor button and the cursor is in the | |
1905 amount column or pres the left cursor button and the cursor is | |
1906 in the code column the event is estoped, else the event is propagated. | |
1907 """ | |
1908 (_cursor_path, _column) = self.__treeview.get_cursor() | |
1909 if (event.keyval == gtk.keysyms.Right \ | |
1910 and _column == self.columns[-2]) \ | |
1911 or (event.keyval == gtk.keysyms.Left \ | |
1912 and _column == self.columns[1]): | |
1913 return True | |
1914 return False | |
1915 | |
1916 def moveCursor(self, treeview, step, count): | |
1917 """def treeviewKeyPressEvent(self, widget, event) | |
1918 | |
1919 treeview: the treeview that received the signal | |
1920 step: the movement step size | |
1921 count: the number of steps to take | |
1922 | |
1923 Method connected to "move-cursor" signal | |
1924 The "move-cursor" signal is emitted when the user moves the cursor | |
1925 using the Right, Left, Up or Down arrow keys or the Page Up, | |
1926 Page Down, Home and End keys. | |
1927 | |
1928 Returns :TRUE if the signal was handled. | |
1929 """ | |
1930 return False | |
1931 | |
1932 def controlSelection(self, selection): | |
1933 """def controlSelection(self, selection) | |
1934 | |
1935 selection: treeselection | |
1936 | |
1937 Method connected to set_selection_function() | |
1938 This method is called before any node is selected or unselected, | |
1939 giving some control over which nodes are selected. | |
1940 The selection function should return TRUE if the state | |
1941 of the node may be toggled, and FALSE if the state of the node should | |
1942 be left unchanged. | |
1943 | |
1944 The selection only run if the user click in the index column, else | |
1945 the previous selection is erased. | |
1946 """ | |
1947 _column = self.__treeview.get_cursor()[1] | |
1948 if _column is self.columns[0] \ | |
1949 or self.__selection_control == False: | |
1950 return True | |
1951 else: | |
1952 self.__selection_control = False | |
1953 self.__treeselection.unselect_all() | |
1954 self.__selection_control = True | |
1955 return False | |
1956 | |
1957 def selectAll(self, column): | |
1958 """def selectAll(self, column) | |
1959 | |
1960 column: index column | |
1961 Method connected to "clicked" event in the index column | |
1962 If the user clickes in the index column header selecs or deselects | |
1963 all rows | |
1964 """ | |
1965 (_model, _pathlist) = self.__treeselection.get_selected_rows() | |
1966 # it avoid to set cursor in the index column | |
1967 self.__treeview.set_cursor(self.__cursor[0], self.__cursor[1]) | |
1968 self.__selection_control = False | |
1969 if len(_pathlist) == 0: | |
1970 # select all | |
1971 self.__treeselection.select_all() | |
1972 else: | |
1973 # unselect all | |
1974 self.__treeselection.unselect_all() | |
1975 self.__selection_control = True | |
1976 | |
1977 def setColumnsHeaders(self): | |
1978 """def setColumnsHeaders(self) | |
1979 | |
1980 Sets the headers column values | |
1981 """ | |
1982 _path_record = self.__active_path_record | |
1983 _number = _path_record[-1] | |
1984 _budget = self.__budget | |
1985 _code = _budget.getCode(_path_record) | |
1986 _decomposition = _budget.getDecomposition(_path_record) | |
1987 _stryield = _budget.getStrYield(_decomposition.budgetMeasures[0], | |
1988 _budget.getRecord(_code).recordType) | |
1989 _record = _budget.getRecord(_code) | |
1990 _unit = _record.unit | |
1991 _description = _record.summary | |
1992 _price = _budget.getStrPriceFromRecord(self.budget.getActiveTitle(), | |
1993 _record) | |
1994 # TODO: round to decimal places in amount | |
1995 _amount = float(_stryield) * float(_price) | |
1996 if len(_path_record) == 1: # root record | |
1997 _amount = _price | |
1998 else: | |
1999 _parent_code = self.budget.getCode(self.__active_path_record[:-1]) | |
2000 _parent_record = self.__budget.getRecord(_parent_code) | |
2001 _amount = _budget.getStrAmount(self.__active_path_record) | |
2002 | |
2003 self.__code_column.set_title(_("Code") + chr(10) + "[" + _code + "]") | |
2004 self.__unit_column.set_title(_("Unit") + chr(10) + "[" + _unit + "]") | |
2005 self.__description_column.set_title( | |
2006 _("Description") + chr(10) + "[" + _description + "]") | |
2007 self.__measure_column.set_title( | |
2008 _("Measure") + chr(10) + "[" + _stryield + "]") | |
2009 self.__price_column.set_title( | |
2010 _("Price") + chr(10) + "[" + _price + "]") | |
2011 self.__amount_column.set_title( | |
2012 _("Amount") + chr(10) + "[" + str(_amount) + "]") | |
2013 | |
2014 | |
2015 def setListstoreValues(self, path_record): | |
2016 """def setListstoreValues(self, path_record) | |
2017 | |
2018 path_record: Record path in the budget | |
2019 Sets the liststore record values from a path record | |
2020 """ | |
2021 self.__liststore.clear() | |
2022 _budget = self.__budget | |
2023 if not _budget.hasPath(path_record): | |
2024 raise ValueError, _("Invalid path") | |
2025 else: | |
2026 _parent_code = _budget.getCode(path_record) | |
2027 for N,_code in enumerate(_budget.getchildren(_parent_code)): | |
2028 _decomposition = _budget.getNDecomposition(_parent_code, N) | |
2029 _record = _budget.getRecord(_code) | |
2030 _values = [_record, | |
2031 #_record.hierarchy, | |
2032 #_record.type, | |
2033 #_record.subtype, | |
2034 #_code, | |
2035 #_record.unit, | |
2036 #_record.summary, | |
2037 #_decomposition.yield_, | |
2038 #_decomposition.budget[0].yield_, | |
2039 #_record.prices[_budget.getActiveTitle()].prices] | |
2040 #_record.getPrice(_budget.getActiveTitle()) | |
2041 ] | |
2042 _treeiter = self.__liststore.append(_values) | |
2043 | |
2044 def colorCell(self, column, cell_renderer, tree_model, iter, lcolor): | |
2045 """def colorCell(self, column, cell_renderer, tree_model, iter, lcolor) | |
2046 | |
2047 column: the gtk.TreeViewColumn in the treeview | |
2048 cell_renderer: a gtk.CellRenderer | |
2049 tree_model: the gtk.TreeModel | |
2050 iter: gtk.TreeIter pointing at the row | |
2051 lcolor: list with 2 gtk colors for even and uneven record | |
2052 | |
2053 Method connected to "set_cell_data_func" of many column | |
2054 The set_cell_data_func() method sets the data function (or method) | |
2055 to use for the column gtk.CellRenderer specified by cell_renderer. | |
2056 This function (or method) is used instead of the standard attribute | |
2057 mappings for setting the column values, and should set the attributes | |
2058 of the cell renderer as appropriate. func may be None to remove the | |
2059 current data function. The signature of func is: | |
2060 -def celldatafunction(column, cell, model, iter, user_data) | |
2061 -def celldatamethod(self, column, cell, model, iter, user_data) | |
2062 where column is the gtk.TreeViewColumn in the treeview, cell is the | |
2063 gtk.CellRenderer for column, model is the gtk.TreeModel for the | |
2064 treeview and iter is the gtk.TreeIter pointing at the row. | |
2065 | |
2066 The method sets cell background color and text for all columns. | |
2067 """ | |
2068 _row_path = tree_model.get_path(iter) | |
2069 _number = _row_path[-1] | |
2070 _record = tree_model[_row_path][0] | |
2071 if column is self.__index_column: | |
2072 cell_renderer.set_property('text', str(_number + 1)) | |
2073 self.__index_column.get_cell_renderers()[1].set_property( | |
2074 'cell-background-gdk', lcolor[_number % 2]) | |
2075 elif column is self.__code_column: | |
2076 # if the record is a chapter | |
2077 if tree_model.get_value(iter, 0).recordType.hierarchy == 1: | |
2078 lcolor = self.__chapter_background_colors | |
2079 _code = _record.code | |
2080 cell_renderer.set_property('text', _code) | |
2081 elif column is self.__unit_column: | |
2082 _unit = _record.unit | |
2083 cell_renderer.set_property('text', _unit) | |
2084 elif column is self.__description_column: | |
2085 _summary = _record.summary | |
2086 cell_renderer.set_property('text', _summary) | |
2087 elif column is self.__measure_column: | |
2088 _parent_code = self.budget.getCode(self.__active_path_record) | |
2089 _parent_record = self.__budget.getRecord(_parent_code) | |
2090 _decomposition = _parent_record.children[_number] | |
2091 _stryield = self.__budget.getStrYield( | |
2092 _decomposition.budgetMeasures[0], _parent_record.recordType) | |
2093 cell_renderer.set_property('text', _stryield) | |
2094 elif column is self.__price_column: | |
2095 _price = self.budget.getStrPriceFromRecord( | |
2096 self.budget.getActiveTitle(), _record) | |
2097 cell_renderer.set_property('text', _price) | |
2098 elif column is self.__amount_column: | |
2099 _parent_code = self.budget.getCode(self.__active_path_record) | |
2100 _parent_record = self.__budget.getRecord(_parent_code) | |
2101 _amount = self.budget.getStrAmount( | |
2102 self.__active_path_record + (_number,)) | |
2103 cell_renderer.set_property('text', str(_amount)) | |
2104 elif column is self.__type_column: | |
2105 _hierarchy = tree_model[_row_path][0].recordType.hierarchy | |
2106 _type = tree_model[_row_path][0].recordType.type | |
2107 _subtype = tree_model[_row_path][0].recordType.subtype | |
2108 if _hierarchy == 1: | |
2109 cell_renderer.set_property("pixbuf",self.chapter_icon) | |
2110 else: | |
2111 if _type == 0: | |
2112 cell_renderer.set_property("pixbuf",self.unit_icon) | |
2113 elif _type == 1: | |
2114 cell_renderer.set_property("pixbuf", | |
2115 self.labourforce_icon) | |
2116 elif _type == 2: | |
2117 cell_renderer.set_property("pixbuf", | |
2118 self.machinery_icon) | |
2119 else: | |
2120 cell_renderer.set_property("pixbuf",self.material_icon) | |
2121 if self.__treeview.get_cursor() == (_row_path,column): | |
2122 cell_renderer.set_property('cell-background-gdk', | |
2123 gtk.gdk.color_parse(globals.color["ACTIVE"])) | |
2124 else: | |
2125 cell_renderer.set_property('cell-background-gdk', | |
2126 lcolor[_number % 2]) | |
2127 | |
2128 def showParentRecord(self, column): | |
2129 """def showParentRecord(self, column) | |
2130 | |
2131 column: the column that is clicked | |
2132 Method connected to "clicked" event of many columns | |
2133 Show the parent record | |
2134 """ | |
2135 _budget = self.__budget | |
2136 if len(self.__active_path_record) == 1: | |
2137 # The active record is the root record | |
2138 # This avoid to move the cursor to the clicked column | |
2139 self.__treeview.set_cursor(self.__cursor[0], self.__cursor[1]) | |
2140 else: | |
2141 _path_record = self.__active_path_record[:-1] | |
2142 _parent = self.__active_path_record[-1] | |
2143 self.__active_path_record = _path_record | |
2144 self.setColumnsHeaders() | |
2145 self.setListstoreValues(self.__active_path_record) | |
2146 arg = ( _path_record ) | |
2147 _page = self.__page() | |
2148 _page.propagateMessageFrom("change_active", self.__path, arg) | |
2149 self.__treeview.set_cursor(_parent, self.__cursor[1]) | |
2150 self.__cursor = self.__treeview.get_cursor() | |
2151 | |
2152 def showMessageRecord(self, record_path): | |
2153 """def showMessageRecord(self, record_path) | |
2154 | |
2155 record_path: the path of the record to show | |
2156 Method connected to "change_active" message | |
2157 Show the record especified in the "change_active" message | |
2158 """ | |
2159 _budget = self.__budget | |
2160 self.__active_path_record = record_path | |
2161 self.setColumnsHeaders() | |
2162 self.setListstoreValues(self.__active_path_record) | |
2163 self.__treeview.set_cursor((0,)) | |
2164 | |
2165 def showRowRecord(self, treeview, treeview_path, column): | |
2166 """def showRowRecord(self, treeview, treeview_path, column) | |
2167 | |
2168 treeview: treview to show | |
2169 treeview_path: the path of the record to show | |
2170 code: the code of the record to show | |
2171 | |
2172 Method connected to "row-activated" event | |
2173 The "row-activated" signal is emitted when the row_activated() method | |
2174 is called or the user double clicks a treeview row. | |
2175 "row-activated" is also emitted when a non-editable row is selected | |
2176 and one of the keys: Space, Shift+Space, Return or Enter is pressed. | |
2177 Show the especified record | |
2178 """ | |
2179 if not (column is self.__end_column) and \ | |
2180 not (column is self.__index_column): | |
2181 _budget = self.__budget | |
2182 _model = treeview.get_model() | |
2183 _iter = _model.get_iter(treeview_path) | |
2184 _code = _model.get_value(_iter, 0).code | |
2185 #_code = _model.get_value(_iter, 4) | |
2186 _path_record = self.__active_path_record + treeview_path | |
2187 if self.__budget.hasPath(_path_record): | |
2188 # if this record path is valid | |
2189 self.__active_path_record = _path_record | |
2190 self.setColumnsHeaders() | |
2191 self.setListstoreValues(self.__active_path_record) | |
2192 self.__treeview.set_cursor((0,)) | |
2193 _arg = ( _path_record ) | |
2194 _page = self.__page() | |
2195 _page.propagateMessageFrom("change_active", self.__path, | |
2196 _arg ) | |
2197 | |
2198 def runMessage(self, message, path, arg=None): | |
2199 """def runMessage(self, message, path, arg=None) | |
2200 | |
2201 message: the message type | |
2202 "change_active": change the active record | |
2203 "clear": clear instance | |
2204 path: tuple that identifies the pane in the notebook page | |
2205 arg: tuple whit two items: | |
2206 0: record path in the budget | |
2207 1: record code | |
2208 This method receives a message and executes its corresponding action | |
2209 """ | |
2210 _budget = self.__budget | |
2211 if message == "change_active": | |
2212 if _budget.hasPath(arg): | |
2213 _path_record = arg | |
2214 self.showMessageRecord( _path_record) | |
2215 elif message == "clear": | |
2216 self._clear() | |
2217 | |
2218 def _clear(self): | |
2219 """def _clear(self) | |
2220 | |
2221 it deletes the __budget value | |
2222 this would not be necessary if there were not circular references, | |
2223 which are pending to fix | |
2224 """ | |
2225 del self.__budget | |
2226 | |
2227 def getWidget(self): | |
2228 """def getWidget(self) | |
2229 | |
2230 return the main widget (gtk.ScrolledWindow) | |
2231 """ | |
2232 return self.__scrolled_window | |
2233 | |
2234 def getPath(self): | |
2235 """def getPath(self) | |
2236 | |
2237 return the tuple that identifies the pane in the notebook page | |
2238 """ | |
2239 return self.__path | |
2240 | |
2241 def setPath(self, path): | |
2242 """def setPath(self) | |
2243 | |
2244 sets the tuple that identifies the pane in the notebook page | |
2245 """ | |
2246 self.__path = path | |
2247 | |
2248 def getPage(self): | |
2249 """def getPage(self) | |
2250 | |
2251 return the Page | |
2252 """ | |
2253 return self.__page | |
2254 | |
2255 def setPage(self,page): | |
2256 """def setPage(self) | |
2257 | |
2258 set the Page | |
2259 """ | |
2260 self.__page = page | |
2261 | |
2262 def getBudget(self): | |
2263 """def getBudget(self) | |
2264 | |
2265 return the Budget objet | |
2266 """ | |
2267 return self.__budget | |
2268 | |
2269 def getActivePathRecord(self): | |
2270 """def getActivePathRecord(self) | |
2271 | |
2272 return the Active Path Record | |
2273 """ | |
2274 return self.__active_path_record | |
2275 | |
2276 widget = property(getWidget, None, None, | |
2277 "Pane configuration list") | |
2278 path = property(getPath, setPath, None, | |
2279 "path that identifie the item in the page notebook") | |
2280 page = property(getPage, setPage, None, | |
2281 "weak reference from Page instance which creates this class") | |
2282 budget = property(getBudget, None, None, | |
2283 "Budget object") | |
2284 active_path_record = property(getActivePathRecord, None, None, | |
2285 "Active path record") | |
2286 | |
2287 class Measure(TreeView): | |
2288 """gui.Measure: | |
2289 | |
2290 Description: | |
2291 Class to show a Measure List | |
2292 Constructor: | |
2293 Measure(budget, page, path) | |
2294 budget: budget showed ("base.Budget" object) | |
2295 page: weak reference from Page instance which creates this class | |
2296 path: tuple that represents the path of the List in the Page | |
2297 Returns the newly created DecompositionList instance | |
2298 Ancestry: | |
2299 +-- object | |
2300 +-- TreeView | |
2301 +-- DecompositionList | |
2302 Atributes: | |
2303 "budget": Budget to show, base.obra instance. | |
2304 "__active_path_record": path of the active record in the budget | |
2305 "widget or __scrolled_window": Window that contains the table, | |
2306 (gtk.ScrolledWindow) | |
2307 "path": Pane page identifier | |
2308 "page": weak reference from Page instance which creates this class | |
2309 "__active_color": The background color of the active cell as a | |
2310 gtk.gdk.Color object | |
2311 "__chapter_background_colors": The background colors of the Code | |
2312 column cells when there is a chapter record | |
2313 as a list of gtk.gdk.Color objects [even cell, uneven cell] | |
2314 "__methond_message": Method to send messages to the page | |
2315 "__liststore": list model which store the list data | |
2316 (gtk.ListStore object) | |
2317 "__treeview": widget for displaying decomposition lists (gtk.TreeView) | |
2318 "__index_column": Index column (gtk.TreeViewColumn object) | |
2319 "__code_column": Record code column (gtk.TreeViewColumn) | |
2320 "__unit_column": Unit of measure column (gtk.TreeViewColumn) | |
2321 "__description_column": record's short description column | |
2322 (gtk.TreeViewColumn) | |
2323 "__measure_column": Measure column (gtk.TreeViewColumn) | |
2324 "__price_column": Price column (gtk.TreeViewColumn) | |
2325 "__amount_column": Amount column(gtk.TreeViewColumn) | |
2326 "__end_column": End empty column (gtk.TreeViewColumn) | |
2327 "__treeselection": active selection | |
2328 "__selection_control": state of the selection control (True/False) | |
2329 "__cursor": Situation of the cursor in the table | |
2330 Methods: | |
2331 __init__(self, budget, page, path, path_record=(0,)) | |
2332 setListstoreValues(self, path_record) | |
2333 setColumnsHeaders(self) | |
2334 controlSelection(self, selection) | |
2335 showMessageRecord(self, record_path) | |
2336 treeviewCursorChanged(self, treeview) | |
2337 moveCursor(self, treeview, step, count) | |
2338 treeviewClickedEvent(self, widget, event) | |
2339 treeviewKeyPressEvent(self, widget, event) | |
2340 runMessage(self, message, path, arg=None) | |
2341 selectAll(self, column) | |
2342 colorCell(self, column, cell_renderer, tree_model, iter, lcolor) | |
2343 _clear(self) | |
2344 getWidget(self) | |
2345 {get/set}Path | |
2346 {get/set}Page | |
2347 getBudget(self) | |
2348 getActivePathRecord(self) | |
2349 """ | |
2350 | |
2351 def __init__(self, budget, page, path, path_record=(0,)): | |
2352 """def __init__(self, budget, page, path, path_record=(0,)) | |
2353 | |
2354 budget: budget: budget showed ("base.Budget" object) | |
2355 page: weak reference from Page instance which creates this class | |
2356 path: tuple that represents the path of the List in the Page | |
2357 path_record: path of the active record in the budget | |
2358 | |
2359 Sets the init atributes | |
2360 Creates the init list values in self.__liststore from the budget | |
2361 showing the top record from the record with path path_record | |
2362 Creates the list in self.__treeview | |
2363 * Creates the columns and cell | |
2364 * Sets te the column headers values | |
2365 * Sets the selection properties | |
2366 * Connects the events | |
2367 """ | |
2368 # Seting init args | |
2369 if not isinstance(budget, base.Budget): | |
2370 raise ValueError, _("Argument must be a Budget object") | |
2371 self.__budget = budget | |
2372 self.__page = page | |
2373 self.__path = path | |
2374 if not isinstance(path_record, tuple): | |
2375 print _("Record path must be a tuple") | |
2376 path_record = (0,) | |
2377 self.__active_path_record = path_record | |
2378 # ListStore | |
2379 self.__liststore = gtk.ListStore(object) | |
2380 self.setListstoreValues(self.__active_path_record) | |
2381 # Treeview | |
2382 self.__treeview = gtk.TreeView(self.__liststore) | |
2383 self.__treeview.set_enable_search(False) | |
2384 self.__treeview.set_reorderable(False) | |
2385 self.__treeview.set_headers_clickable(True) | |
2386 self.__treeview.show() | |
2387 # Scrolled_window | |
2388 self.__scrolled_window = gtk.ScrolledWindow() | |
2389 self.__scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, | |
2390 gtk.POLICY_AUTOMATIC) | |
2391 self.__scrolled_window.add(self.__treeview) | |
2392 # colors | |
2393 _text_color = gtk.gdk.color_parse(globals.color["TEXT"]) | |
2394 _calculated_text =gtk.gdk.color_parse(globals.color["CALCULATED-TEXT"]) | |
2395 _background_color = [ | |
2396 gtk.gdk.color_parse(globals.color["UNEVEN"]), | |
2397 gtk.gdk.color_parse(globals.color["EVEN"])] | |
2398 self.__chapter_background_colors = [ | |
2399 gtk.gdk.color_parse(globals.color["CHAPTER-UNEVEN"]), | |
2400 gtk.gdk.color_parse(globals.color["CHAPTER-EVEN"])] | |
2401 super(Measure,self).__init__( | |
2402 [("INDEX",self.selectAll,42), | |
2403 ("PIXBUF", self.passMethod, | |
2404 gtk.Label("A"*4).size_request()[0] +10, | |
2405 _text_color, _background_color), | |
2406 ("CALCULATEDTEXT", self.passMethod, | |
2407 gtk.Label("A"*12).size_request()[0] +10, | |
2408 _text_color, _background_color), | |
2409 ("CALCULATED", self.passMethod, | |
2410 gtk.Label("A"*5).size_request()[0] +10, | |
2411 _text_color, _background_color), | |
2412 ("CALCULATED", self.passMethod, | |
2413 gtk.Label("A"*7).size_request()[0] +10, | |
2414 _text_color, _background_color), | |
2415 ("CALCULATED", self.passMethod, | |
2416 gtk.Label("A"*7).size_request()[0] +10, | |
2417 _text_color, _background_color), | |
2418 ("CALCULATED", self.passMethod, | |
2419 gtk.Label("A"*7).size_request()[0] +10, | |
2420 _text_color, _background_color), | |
2421 ("CALCULATEDTEXT", self.passMethod, | |
2422 gtk.Label("A"*12).size_request()[0] +10, | |
2423 _text_color, _background_color), | |
2424 ("CALCULATED", self.passMethod, | |
2425 gtk.Label("A"*7).size_request()[0] +10, | |
2426 _calculated_text, _background_color), | |
2427 ("CALCULATED", self.passMethod, | |
2428 gtk.Label("A"*7).size_request()[0] +10, | |
2429 _calculated_text, _background_color), | |
2430 ]) | |
2431 self.__index_column = self.columns[0] | |
2432 self.__linetype_column = self.columns[1] | |
2433 self.__comment_column = self.columns[2] | |
2434 self.__units_column = self.columns[3] | |
2435 self.__length_column = self.columns[4] | |
2436 self.__width_column = self.columns[5] | |
2437 self.__height_column = self.columns[6] | |
2438 self.__formula_column = self.columns[7] | |
2439 self.__parcial_column = self.columns[8] | |
2440 self.__subtotal_column = self.columns[9] | |
2441 self.__end_column = self.columns[10] | |
2442 # Index column | |
2443 self.__treeview.append_column(self.__index_column) | |
2444 # Linetype column | |
2445 self.__treeview.append_column(self.__linetype_column) | |
2446 self.calculatedline_icon = gtk.gdk.pixbuf_new_from_file( | |
2447 globals.getAppPath("CALCULATEDLINE-ICON")) | |
2448 self.normalline_icon = gtk.gdk.pixbuf_new_from_file( | |
2449 globals.getAppPath("NORMALLINE-ICON") ) | |
2450 self.parcialline_icon = gtk.gdk.pixbuf_new_from_file( | |
2451 globals.getAppPath("PARCIALLINE-ICON") ) | |
2452 self.acumulatedline_icon = gtk.gdk.pixbuf_new_from_file( | |
2453 globals.getAppPath("ACUMULATEDLINE-ICON")) | |
2454 # Comment column | |
2455 self.__treeview.append_column(self.__comment_column) | |
2456 # Units column | |
2457 self.__treeview.append_column(self.__units_column) | |
2458 # Length column | |
2459 self.__treeview.append_column(self.__length_column) | |
2460 # Width_column | |
2461 self.__treeview.append_column(self.__width_column) | |
2462 # Height column | |
2463 self.__treeview.append_column(self.__height_column) | |
2464 # Formula column | |
2465 self.__treeview.append_column(self.__formula_column) | |
2466 # Parcial column | |
2467 self.__treeview.append_column(self.__parcial_column) | |
2468 # Subtotal column | |
2469 self.__treeview.append_column(self.__subtotal_column) | |
2470 # End Column | |
2471 self.__treeview.append_column(self.__end_column) | |
2472 # Connect | |
2473 self.__treeview.connect("move-cursor", self.moveCursor) | |
2474 self.__treeview.connect("key-press-event", self.treeviewKeyPressEvent) | |
2475 self.__treeview.connect("button-press-event", self.treeviewClickedEvent) | |
2476 self.__treeview.connect("cursor-changed", self.treeviewCursorChanged) | |
2477 # control selection | |
2478 self.__treeselection = self.__treeview.get_selection() | |
2479 self.__treeselection.set_mode(gtk.SELECTION_MULTIPLE) | |
2480 self.__treeselection.set_select_function(self.controlSelection) | |
2481 self.__selection_control = True | |
2482 self.__treeview.set_cursor_on_cell((1,), self.columns[1], | |
2483 self.columns[1].get_cell_renderers()[0],True) | |
2484 self.__treeview.grab_focus() | |
2485 self.__cursor = self.__treeview.get_cursor() | |
2486 # Show | |
2487 self.setColumnsHeaders() | |
2488 self.__scrolled_window.show() | |
2489 | |
2490 def passMethod(self, args): | |
2491 pass | |
2492 | |
2493 def setListstoreValues(self, path_record): | |
2494 """def setListstoreValues(self, path_record) | |
2495 | |
2496 path_record: Record path in the budget | |
2497 Sets the liststore record values from a path record | |
2498 """ | |
2499 self.__liststore.clear() | |
2500 _budget = self.__budget | |
2501 if not _budget.hasPath(path_record): | |
2502 raise ValueError, _("Invalid path") | |
2503 else: | |
2504 _measure = _budget.getMeasure(path_record) | |
2505 if isinstance(_measure, base.Measure): | |
2506 _lines = _measure.lines | |
2507 for _line in _lines: | |
2508 _values = [ | |
2509 _line, | |
2510 ## _line.type, | |
2511 ## _line.comment, | |
2512 ## _line.units, | |
2513 ## _line.length, | |
2514 ## _line.width, | |
2515 ## _line.height | |
2516 ] | |
2517 _treeiter = self.__liststore.append(_values) | |
2518 else: | |
2519 raise ValueError, utils.mapping(_("measure must be a Measure "\ | |
2520 "object. Type: $1"), (type(_measure),)) | |
2521 def setColumnsHeaders(self): | |
2522 """def setColumnsHeaders(self) | |
2523 | |
2524 Sets the headers column values | |
2525 """ | |
2526 _measure = self.__budget.getMeasure(self.__active_path_record) | |
2527 _DS = self.__budget.getDecimals("DS") | |
2528 _total = _measure.measure | |
2529 _total_str = ("%." + str(_DS) + "f" ) % _total | |
2530 self.columns[1].set_title(_("Type")) # Σ parcial Σ total | |
2531 self.columns[2].set_title(_("Comment")) | |
2532 self.columns[3].set_title(_("N\n(a)")) | |
2533 self.columns[4].set_title(_("Length\n(b)")) | |
2534 self.columns[5].set_title(_("Width\n(c)")) | |
2535 self.columns[6].set_title(_("Height\n(d)")) | |
2536 self.columns[7].set_title(_("Formula")) | |
2537 self.columns[8].set_title(_("Parcial\n[%s]" % _total_str)) | |
2538 self.columns[9].set_title(_("Subtotal")) | |
2539 def controlSelection(self, selection): | |
2540 """def controlSelection(self, selection) | |
2541 | |
2542 selection: treeselection | |
2543 | |
2544 Method connected to set_selection_function() | |
2545 This method is called before any node is selected or unselected, | |
2546 giving some control over which nodes are selected. | |
2547 The selection function should return TRUE if the state | |
2548 of the node may be toggled, and FALSE if the state of the node should | |
2549 be left unchanged. | |
2550 | |
2551 The selection only run if the user click in the index column, else | |
2552 the previous selection is erased. | |
2553 """ | |
2554 _column = self.__treeview.get_cursor()[1] | |
2555 if _column is self.columns[0] \ | |
2556 or self.__selection_control == False: | |
2557 return True | |
2558 else: | |
2559 self.__selection_control = False | |
2560 self.__treeselection.unselect_all() | |
2561 self.__selection_control = True | |
2562 return False | |
2563 | |
2564 def showMessageRecord(self, record_path): | |
2565 """def showMessageRecord(self, record_path) | |
2566 | |
2567 record_path: the path of the record to show | |
2568 Method connected to "change_active" message | |
2569 Show the record especified in the "change_active" message | |
2570 """ | |
2571 _budget = self.__budget | |
2572 self.__active_path_record = record_path | |
2573 self.setColumnsHeaders() | |
2574 self.setListstoreValues(self.__active_path_record) | |
2575 self.__treeview.set_cursor((0,)) | |
2576 | |
2577 def treeviewCursorChanged(self, treeview): | |
2578 """def treeviewCursorChanged(self, treeview) | |
2579 | |
2580 treeview: treewiew widget | |
2581 Method connected to "cursor-changed" signal | |
2582 The "cursor-changed" signal is emitted when the cursor moves or is set | |
2583 Sets the new cursor position in self.__cursor, it is used to avoid | |
2584 unnecessary changes in cursor position. | |
2585 """ | |
2586 event = gtk.get_current_event() | |
2587 (_cursor_path, _column) = treeview.get_cursor() | |
2588 if event is None or event.type != gtk.gdk.BUTTON_RELEASE: | |
2589 if not _column is self.__index_column: | |
2590 self.__cursor = treeview.get_cursor() | |
2591 | |
2592 def moveCursor(self, treeview, step, count): | |
2593 """def treeviewKeyPressEvent(self, widget, event) | |
2594 | |
2595 treeview: the treeview that received the signal | |
2596 step: the movement step size | |
2597 count: the number of steps to take | |
2598 | |
2599 Method connected to "move-cursor" signal | |
2600 The "move-cursor" signal is emitted when the user moves the cursor | |
2601 using the Right, Left, Up or Down arrow keys or the Page Up, | |
2602 Page Down, Home and End keys. | |
2603 | |
2604 Returns :TRUE if the signal was handled. | |
2605 """ | |
2606 return False | |
2607 | |
2608 def treeviewClickedEvent(self, widget, event): | |
2609 """def treeviewClickedEvent(self, widget, event) | |
2610 | |
2611 widget: treewiew widget | |
2612 event: clicked event | |
2613 Method connected to "button-press-event" signal | |
2614 The "button-press-event" signal is emitted when a mouse button is | |
2615 pressed. | |
2616 Returns TRUE to stop other handlers from being invoked for the event. | |
2617 Returns FALSE to propagate the event further. | |
2618 | |
2619 The events in end column are ignored. | |
2620 If the user click in a row of the index column the cursor is moved to | |
2621 this row but not to the index column | |
2622 """ | |
2623 if event.button == 1: | |
2624 path_at_pos = self.__treeview.get_path_at_pos(int(event.x), | |
2625 int(event.y)) | |
2626 if not path_at_pos is None: | |
2627 _path_cursor, _column, _x, _y = path_at_pos | |
2628 if _column == self.columns[-1]: | |
2629 return True | |
2630 if _column is self.columns[0]: | |
2631 self.__cursor[0] == _path_cursor | |
2632 return False | |
2633 | |
2634 def treeviewKeyPressEvent(self, widget, event): | |
2635 """def treeviewKeyPressEvent(self, widget, event) | |
2636 | |
2637 widget: treewiew widget | |
2638 event: Key Press event | |
2639 Method connected to "key-press-event" signal | |
2640 The "key-press-event" signal is emitted when the user presses a key | |
2641 on the keyboard. | |
2642 Returns :TRUE to stop other handlers from being invoked for the event. | |
2643 Returns :FALSE to propagate the event further. | |
2644 | |
2645 If the user press the right cursor button and the cursor is in the | |
2646 amount column or pres the left cursor button and the cursor is | |
2647 in the code column the event is estoped, else the event is propagated. | |
2648 """ | |
2649 (_cursor_path, _column) = self.__treeview.get_cursor() | |
2650 if (event.keyval == gtk.keysyms.Right \ | |
2651 and _column == self.columns[-2]) \ | |
2652 or (event.keyval == gtk.keysyms.Left \ | |
2653 and _column == self.columns[1]): | |
2654 return True | |
2655 return False | |
2656 | |
2657 def runMessage(self, message, path, arg=None): | |
2658 """def runMessage(self, message, path, arg=None) | |
2659 | |
2660 message: the message type | |
2661 "change_active": change the active record | |
2662 "clear": clear instance | |
2663 path: tuple that identifies the pane in the notebook page | |
2664 arg: tuple whit two items: | |
2665 0: record path in the budget | |
2666 1: record code | |
2667 This method receives a message and executes its corresponding action | |
2668 """ | |
2669 _budget = self.__budget | |
2670 if message == "change_active": | |
2671 if _budget.hasPath(arg): | |
2672 _path_record = arg | |
2673 self.showMessageRecord( _path_record) | |
2674 elif message == "clear": | |
2675 self._clear() | |
2676 | |
2677 def selectAll(self, column): | |
2678 """def selectAll(self, column) | |
2679 | |
2680 column: index column | |
2681 Method connected to "clicked" event in the index column | |
2682 If the user clickes in the index column header selecs or deselects | |
2683 all rows | |
2684 """ | |
2685 (_model, _pathlist) = self.__treeselection.get_selected_rows() | |
2686 # it avoid to set cursor in the index column | |
2687 self.__treeview.set_cursor(self.__cursor[0], self.__cursor[1]) | |
2688 self.__selection_control = False | |
2689 if len(_pathlist) == 0: | |
2690 # select all | |
2691 self.__treeselection.select_all() | |
2692 else: | |
2693 # unselect all | |
2694 self.__treeselection.unselect_all() | |
2695 self.__selection_control = True | |
2696 | |
2697 def colorCell(self, column, cell_renderer, tree_model, iter, lcolor): | |
2698 """def colorCell(self, column, cell_renderer, tree_model, iter, lcolor) | |
2699 | |
2700 column: the gtk.TreeViewColumn in the treeview | |
2701 cell_renderer: a gtk.CellRenderer | |
2702 tree_model: the gtk.TreeModel | |
2703 iter: gtk.TreeIter pointing at the row | |
2704 lcolor: list with 2 gtk colors for even and uneven record | |
2705 | |
2706 Method connected to "set_cell_data_func" of many column | |
2707 The set_cell_data_func() method sets the data function (or method) | |
2708 to use for the column gtk.CellRenderer specified by cell_renderer. | |
2709 This function (or method) is used instead of the standard attribute | |
2710 mappings for setting the column values, and should set the attributes | |
2711 of the cell renderer as appropriate. func may be None to remove the | |
2712 current data function. The signature of func is: | |
2713 -def celldatafunction(column, cell, model, iter, user_data) | |
2714 -def celldatamethod(self, column, cell, model, iter, user_data) | |
2715 where column is the gtk.TreeViewColumn in the treeview, cell is the | |
2716 gtk.CellRenderer for column, model is the gtk.TreeModel for the | |
2717 treeview and iter is the gtk.TreeIter pointing at the row. | |
2718 | |
2719 The method sets cell background color for all columns | |
2720 and text for index and amount columns. | |
2721 """ | |
2722 _row_path = tree_model.get_path(iter) | |
2723 _number = _row_path[-1] | |
2724 if column is self.__index_column: | |
2725 cell_renderer.set_property('text', str(_number + 1)) | |
2726 self.__index_column.get_cell_renderers()[1].set_property( | |
2727 'cell-background-gdk', lcolor[_number % 2]) | |
2728 elif column is self.__linetype_column: | |
2729 _measure = tree_model[_row_path][0] | |
2730 _type = _measure.lineType | |
2731 if _type == 0: | |
2732 cell_renderer.set_property("pixbuf",self.normalline_icon) | |
2733 elif _type == 1: | |
2734 cell_renderer.set_property("pixbuf",self.parcialline_icon) | |
2735 elif _type == 2: | |
2736 cell_renderer.set_property("pixbuf", | |
2737 self.acumulatedline_icon) | |
2738 else: #elif _type == 3: | |
2739 cell_renderer.set_property("pixbuf", | |
2740 self.calculatedline_icon) | |
2741 | |
2742 elif column is self.__comment_column: | |
2743 _measure = tree_model[_row_path][0] | |
2744 _comment = str(_measure.comment) | |
2745 cell_renderer.set_property('text', _comment) | |
2746 elif column is self.__units_column: | |
2747 _measure = tree_model[_row_path][0] | |
2748 _units = _measure.units | |
2749 if isinstance(_units, float): | |
2750 _DN = self.__budget.getDecimals("DN") | |
2751 _units = ("%." + str(_DN) + "f" ) % _units | |
2752 cell_renderer.set_property('text', _units) | |
2753 elif column is self.__length_column: | |
2754 _measure = tree_model[_row_path][0] | |
2755 _length = _measure.length | |
2756 if isinstance(_length, float): | |
2757 _DD = self.__budget.getDecimals("DD") | |
2758 _length = ("%." + str(_DD) + "f" ) % _length | |
2759 cell_renderer.set_property('text', _length) | |
2760 elif column is self.__width_column: | |
2761 _measure = tree_model[_row_path][0] | |
2762 _width = _measure.width | |
2763 if isinstance(_width, float): | |
2764 _DD = self.__budget.getDecimals("DD") | |
2765 _width = ("%." + str(_DD) + "f" ) % _width | |
2766 cell_renderer.set_property('text', _width) | |
2767 elif column is self.__height_column: | |
2768 _measure = tree_model[_row_path][0] | |
2769 _height = _measure.height | |
2770 if isinstance(_height, float): | |
2771 _DD = self.__budget.getDecimals("DD") | |
2772 _height = ("%." + str(_DD) + "f" ) % _height | |
2773 cell_renderer.set_property('text', _height) | |
2774 elif column is self.__formula_column: | |
2775 _measure = tree_model[_row_path][0] | |
2776 _formula = _measure.formula | |
2777 cell_renderer.set_property('text', _formula) | |
2778 elif column is self.__parcial_column: | |
2779 _measure_line = tree_model[_row_path][0] | |
2780 _parcial = _measure_line.parcial | |
2781 _type = _measure_line.lineType | |
2782 if _type == 1 or _type == 2: | |
2783 _parcial = "" | |
2784 else: | |
2785 if isinstance(_parcial, float): | |
2786 _DS = self.__budget.getDecimals("DS") | |
2787 _parcial = ("%." + str(_DS) + "f" ) % _parcial | |
2788 cell_renderer.set_property('text', _parcial) | |
2789 elif column is self.__subtotal_column: | |
2790 _measure_line = tree_model[_row_path][0] | |
2791 _type = _measure_line.lineType | |
2792 if _type == 1 or _type == 2: | |
2793 if _type == 1: | |
2794 _color = gtk.gdk.color_parse( | |
2795 globals.color["SUBTOTAL-PARCIAL"]) | |
2796 _subtotal = _measure_line.parcial_subtotal | |
2797 else: #elif _type == 2: | |
2798 _color = gtk.gdk.color_parse(globals.color["SUBTOTAL"]) | |
2799 _subtotal = _measure_line.acumulated_subtotal | |
2800 lcolor = [_color, _color] | |
2801 if isinstance(_subtotal, float): | |
2802 _DS = self.__budget.getDecimals("DS") | |
2803 _subtotal= ("%." + str(_DS) + "f" ) % _subtotal | |
2804 cell_renderer.set_property('text', _subtotal) | |
2805 else: | |
2806 cell_renderer.set_property('text', "") | |
2807 | |
2808 if self.__treeview.get_cursor() == (_row_path,column): | |
2809 cell_renderer.set_property('cell-background-gdk', | |
2810 gtk.gdk.color_parse(globals.color["ACTIVE"])) | |
2811 else: | |
2812 cell_renderer.set_property('cell-background-gdk', | |
2813 lcolor[_number % 2]) | |
2814 | |
2815 def _clear(self): | |
2816 """def _clear(self) | |
2817 | |
2818 it deletes the __budget value | |
2819 this would not be necessary if there were not circular references, | |
2820 which are pending to fix | |
2821 """ | |
2822 del self.__budget | |
2823 | |
2824 def getWidget(self): | |
2825 """def getWidget(self) | |
2826 | |
2827 return the main widget (gtk.ScrolledWindow) | |
2828 """ | |
2829 return self.__scrolled_window | |
2830 | |
2831 def getPath(self): | |
2832 """def getPath(self) | |
2833 | |
2834 return the tuple that identifies the pane in the notebook page | |
2835 """ | |
2836 return self.__path | |
2837 | |
2838 def setPath(self, path): | |
2839 """def setPath(self) | |
2840 | |
2841 sets the tuple that identifies the pane in the notebook page | |
2842 """ | |
2843 self.__path = path | |
2844 def getPage(self): | |
2845 """def getPage(self) | |
2846 | |
2847 return the Page | |
2848 """ | |
2849 return self.__page | |
2850 | |
2851 def setPage(self,page): | |
2852 """def setPage(self) | |
2853 | |
2854 set the Page | |
2855 """ | |
2856 self.__page = page | |
2857 | |
2858 def getBudget(self): | |
2859 """def getBudget(self) | |
2860 | |
2861 return the Budget objet | |
2862 """ | |
2863 return self.__budget | |
2864 | |
2865 def getActivePathRecord(self): | |
2866 """def getActivePathRecord(self) | |
2867 | |
2868 return the Active Path Record | |
2869 """ | |
2870 return self.__active_path_record | |
2871 | |
2872 widget = property(getWidget, None, None, | |
2873 "Pane configuration list") | |
2874 path = property(getPath, setPath, None, | |
2875 "Path that identifies the item in the page notebook") | |
2876 page = property(getPage, setPage, None, | |
2877 "Weak reference from Page instance which creates this class") | |
2878 budget = property(getBudget, None, None, | |
2879 "Budget object") | |
2880 active_path_record = property(getActivePathRecord, None, None, | |
2881 "Active Code") | |
2882 | |
2883 class Description(object): | |
2884 """gui.Description | |
2885 | |
2886 Description: | |
2887 Class to show a description text of a record in a pane | |
2888 Constructor: | |
2889 Description(budget, code) | |
2890 budget: budget | |
2891 code: code record | |
2892 Ancestry: | |
2893 +-- object | |
2894 +-- Description | |
2895 Atributes: | |
2896 "widget": the main widget (gtk.ScrolledWindow object) | |
2897 "path": the tuple that identifies the pane in the notebook page | |
2898 TODO | |
2899 "budget": The budget (base.obra objetc) | |
2900 "active_code": The active code of the record | |
2901 "__textbuffer": The textbuffer of the textview that contain | |
2902 the record text. | |
2903 "__label": The gtk.label with the title of the pane | |
2904 Methods: | |
2905 __init__(self, budget, code) | |
2906 setActiveCode(self, code) | |
2907 runMessage(self, message, nt, arg=None) | |
2908 _clear(self) | |
2909 getWidget(self) | |
2910 {get/set}Path | |
2911 {get/seg}Page | |
2912 getBudget(self) | |
2913 getActviCode(self) | |
2914 """ | |
2915 # TODO: make standar: "DecompositonList and Description" | |
2916 def __init__(self, budget, page, path, path_record=(0,)): | |
2917 """def __init__(self, budget, page, path, path_record=(0,)) | |
2918 | |
2919 budget: the budget (base.obra object) | |
2920 page: weak reference from Page instance which creates this class | |
2921 path: the path position of the description in the page | |
2922 path_record: the path of the active record | |
2923 | |
2924 Creates an shows the scroledwindow that contain the description text | |
2925 of the record to be showed in a pane. | |
2926 """ | |
2927 self.__budget = budget | |
2928 self.__page = page | |
2929 self.__path = path | |
2930 self.__active_path_record = path_record | |
2931 _budget = budget | |
2932 _text = _budget.getRecord(self.__budget.getCode( | |
2933 self.__active_path_record)).text | |
2934 _scrollwindow = gtk.ScrolledWindow() | |
2935 _scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, | |
2936 gtk.POLICY_AUTOMATIC) | |
2937 _textview = gtk.TextView() | |
2938 _textview.set_wrap_mode(gtk.WRAP_WORD) | |
2939 self.__textbuffer = _textview.get_buffer() | |
2940 self.__textbuffer.set_text(_text) | |
2941 _textview.show() | |
2942 _hbox = gtk.HBox() | |
2943 _hbox.pack_start(_textview, True, True, 5) | |
2944 _hbox.show() | |
2945 _vbox = gtk.VBox() | |
2946 self.__label = gtk.Label(utils.mapping(_("Description text of the "\ | |
2947 "record $1"), (self.__budget.getCode( | |
2948 self.__active_path_record),))) | |
2949 self.__label.set_alignment(0, 0) | |
2950 self.__label.show() | |
2951 _vbox.pack_start(self.__label, False, False, 5) | |
2952 _vbox.pack_start(_hbox, True, True, 5) | |
2953 _vbox.show() | |
2954 _scrollwindow.add_with_viewport(_vbox) | |
2955 _scrollwindow.show() | |
2956 self.__widget = _scrollwindow | |
2957 | |
2958 | |
2959 def setActivePathRecord(self, path_record): | |
2960 """def setActivePathRecord(self, path_record)) | |
2961 | |
2962 path_record: active path record | |
2963 Set the new path code to show its description text. | |
2964 """ | |
2965 _budget = self.__budget | |
2966 self.__active_path_record = path_record | |
2967 _code = _budget.getCode(self.__active_path_record) | |
2968 self.__label.set_text(utils.mapping(_("Description text of the record "\ | |
2969 "$1"), (_code,))) | |
2970 _text = _budget.getRecord(_code).text | |
2971 self.__textbuffer.set_text(_text) | |
2972 | |
2973 def runMessage(self, message, path, arg=None): | |
2974 """def runMessage(self, message, path, arg=None) | |
2975 | |
2976 message: the message type | |
2977 "change_active": change the active record | |
2978 "clear": clear instance | |
2979 path: tuple that identifies the pane in the notebook page | |
2980 arg: tuple whit two items: | |
2981 0: record path in the budget | |
2982 1: record code | |
2983 This method receives a message and executes its corresponding action | |
2984 """ | |
2985 _budget = self.__budget | |
2986 if message == "change_active": | |
2987 if _budget.hasPath(arg): | |
2988 self.setActivePathRecord(arg) | |
2989 elif message == "clear": | |
2990 self._clear() | |
2991 | |
2992 def _clear(self): | |
2993 """def _clear(self) | |
2994 | |
2995 Delete all instance atributes | |
2996 """ | |
2997 del self.__widget | |
2998 del self.__path | |
2999 del self.__budget | |
3000 del self.__active_code | |
3001 del self.__textbuffer | |
3002 del self.__label | |
3003 | |
3004 def getWidget(self): | |
3005 """def getWidget(self) | |
3006 | |
3007 return the main widget (gtk.ScrolledWindow) | |
3008 """ | |
3009 return self.__widget | |
3010 | |
3011 def getPath(self): | |
3012 """def getPath(self) | |
3013 | |
3014 return the tuple that identifies the pane in the notebook page | |
3015 """ | |
3016 return self.__path | |
3017 | |
3018 def setPath(self, path): | |
3019 """def setPath(self) | |
3020 | |
3021 sets the tuple that identifies the pane in the notebook page | |
3022 """ | |
3023 self.__path = path | |
3024 | |
3025 def getPage(self): | |
3026 """def getPage(self) | |
3027 | |
3028 return the weak reference from Page instance | |
3029 """ | |
3030 return self.__page | |
3031 | |
3032 def setPage(self, page): | |
3033 """def setPage(self) | |
3034 | |
3035 set the weak reference from Page instance | |
3036 """ | |
3037 self.__page = page | |
3038 | |
3039 def getBudget(self): | |
3040 """def getBudget(self) | |
3041 | |
3042 return the budget object | |
3043 """ | |
3044 return self.__budget | |
3045 | |
3046 def getActivePathRecord(self): | |
3047 """def getActivePathRecord(self) | |
3048 | |
3049 return the Active Path Record | |
3050 """ | |
3051 return self.__active_path_record | |
3052 | |
3053 path = property(getPath, setPath, None, | |
3054 "Path that identifie the item in the page notebook") | |
3055 widget = property(getWidget, None, None, | |
3056 "The main widget (gtk.ScrolledWindow)") | |
3057 page = property(getPage, setPage, None, | |
3058 "Weak reference from Page instance which creates this class") | |
3059 budget = property(getBudget, None, None, | |
3060 "Budget object") | |
3061 active_path_record = property(getActivePathRecord, None, None, | |
3062 "Active Path Record") | |
3063 | |
3064 class Sheet(object): | |
3065 """gui.Sheet | |
3066 | |
3067 Description: | |
3068 Class to show a sheeet of conditions text of a record in a pane | |
3069 Constructor: | |
3070 Sheet(budget, code) | |
3071 budget: budget object | |
3072 code: code record | |
3073 Ancestry: | |
3074 +-- object | |
3075 +-- Sheet | |
3076 Atributes: | |
3077 "widget": the main widget (gtk.ScrolledWindow object) | |
3078 "path": the tuple that identifies the pane in the notebook page | |
3079 "budget": The budget (base.obra objetc) | |
3080 "active_path_record": The active path record | |
3081 "page": weak reference from Page instance which creates this class | |
3082 | |
3083 "__textbuffer": The textbuffer of the textview that contain | |
3084 the record text. | |
3085 "__label": The gtk.label with the title of the pane | |
3086 "__field_liststore": the field liststore | |
3087 "__field_treeview": the field treeview | |
3088 "__field_selection": the field selected in field treview | |
3089 "__section_liststore": the section liststore | |
3090 "__section_treeview": the section treeview | |
3091 "__section_selection": the section selected in the section treeview | |
3092 Methods: | |
3093 __init__(self, budget, code) | |
3094 setFields(self) | |
3095 setSection(self) | |
3096 setText(self) | |
3097 field_controlSelection(self, selection) | |
3098 section_controlSelection(self, selection) | |
3099 runMessage(self, message, nt, arg=None) | |
3100 _clear(self) | |
3101 getWidget(self) | |
3102 {get/set}Path | |
3103 {get/set}Page | |
3104 getBudget(self) | |
3105 getActviPathRecord(self) | |
3106 """ | |
3107 def __init__(self, budget, page, path, path_record=(0,)): | |
3108 """def __init__(self, budget, page, path, path_record=(0,)) | |
3109 | |
3110 budget: the budget (base.obra object) | |
3111 page: weak reference from Page instance which creates this class | |
3112 path: the path position of the description in the page | |
3113 path_record: the path of the active record | |
3114 Creates an shows the scroledwindow that contain the description text | |
3115 of the record to be showed in a pane. | |
3116 """ | |
3117 self.__budget = budget | |
3118 self.__page = page | |
3119 self.__path = path | |
3120 self.__active_path_record = path_record | |
3121 _budget = budget | |
3122 | |
3123 _main_box = gtk.VBox() | |
3124 | |
3125 self.__label = gtk.Label(utils.mapping(_("Sheet of Conditions of the "\ | |
3126 "record $1"), (self.__budget.getCode( | |
3127 self.__active_path_record),))) | |
3128 self.__label.set_alignment(0, 0) | |
3129 self.__label.show() | |
3130 | |
3131 _frame = gtk.Frame() | |
3132 _frame.set_shadow_type(gtk.SHADOW_IN) | |
3133 _frame_box = gtk.VBox() | |
3134 _list_box = gtk.HBox() | |
3135 | |
3136 self.__field_liststore = gtk.ListStore(str, str) | |
3137 self.__field_treeview = gtk.TreeView(self.__field_liststore) | |
3138 _field_treeselection = self.__field_treeview.get_selection() | |
3139 _field_treeselection.set_mode(gtk.SELECTION_SINGLE) | |
3140 self.__field_selection = None | |
3141 _field_treeselection.set_select_function( | |
3142 self.field_controlSelection) | |
3143 self.__field_treeview.show() | |
3144 _fieldcode_cell = gtk.CellRendererText() | |
3145 _field_column = gtk.TreeViewColumn(_("Field")) | |
3146 _field_column.pack_start(_fieldcode_cell, False) | |
3147 _field_cell = gtk.CellRendererText() | |
3148 _field_column.pack_end(_field_cell, True) | |
3149 _field_column.add_attribute(_fieldcode_cell, "text", 0) | |
3150 _field_column.add_attribute(_field_cell, "text", 1) | |
3151 self.__field_treeview.append_column(_field_column) | |
3152 _field_scrollwindow = gtk.ScrolledWindow() | |
3153 _field_scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, | |
3154 gtk.POLICY_AUTOMATIC) | |
3155 _field_scrollwindow.add(self.__field_treeview) | |
3156 _field_scrollwindow.show() | |
3157 | |
3158 self.__section_liststore = gtk.ListStore(str, str) | |
3159 self.__section_treeview = gtk.TreeView(self.__section_liststore) | |
3160 _section_treeselection = self.__section_treeview.get_selection() | |
3161 _section_treeselection.set_mode(gtk.SELECTION_SINGLE) | |
3162 self.__section_selection = None | |
3163 _section_treeselection.set_select_function( | |
3164 self.section_controlSelection) | |
3165 self.__section_treeview.show() | |
3166 _sectioncode_cell = gtk.CellRendererText() | |
3167 _section_column = gtk.TreeViewColumn(_("Section")) | |
3168 _section_column.pack_start(_sectioncode_cell, False) | |
3169 _section_column.add_attribute(_sectioncode_cell, "text", 0) | |
3170 _section_cell = gtk.CellRendererText() | |
3171 _section_column.pack_end(_section_cell, True) | |
3172 _section_column.add_attribute(_section_cell, "text", 1) | |
3173 self.__section_treeview.append_column(_section_column) | |
3174 _section_scrollwindow = gtk.ScrolledWindow() | |
3175 _section_scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, | |
3176 gtk.POLICY_AUTOMATIC) | |
3177 _section_scrollwindow.add(self.__section_treeview) | |
3178 _section_scrollwindow.show() | |
3179 | |
3180 _list_box.pack_start(_field_scrollwindow, True, True, 5) | |
3181 _list_box.pack_start(_section_scrollwindow, True, True, 5) | |
3182 _list_box.show() | |
3183 | |
3184 _scrollwindow = gtk.ScrolledWindow() | |
3185 _scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, | |
3186 gtk.POLICY_AUTOMATIC) | |
3187 _textview = gtk.TextView() | |
3188 _textview.set_wrap_mode(gtk.WRAP_WORD) | |
3189 self.__textbuffer = _textview.get_buffer() | |
3190 _textview.show() | |
3191 _hbox = gtk.HBox() | |
3192 _hbox.pack_start(_textview, True, True, 5) | |
3193 _hbox.show() | |
3194 | |
3195 _frame_box.pack_start(self.__label, False, False, 5) | |
3196 _frame_box.pack_start(_list_box, False, False, 5) | |
3197 _frame_box.show() | |
3198 _frame.add(_frame_box) | |
3199 _frame.show() | |
3200 _main_box.pack_start(_frame, False) | |
3201 | |
3202 | |
3203 _vbox = gtk.VBox() | |
3204 _vbox.pack_start(_hbox, True, True, 5) | |
3205 _vbox.show() | |
3206 _main_box.pack_start(_scrollwindow, True, True, 5) | |
3207 _main_box.show() | |
3208 | |
3209 _scrollwindow.add_with_viewport(_vbox) | |
3210 _scrollwindow.show() | |
3211 self.__widget = _main_box | |
3212 | |
3213 self.setFields() | |
3214 | |
3215 def setFields(self): | |
3216 """setFields(self) | |
3217 | |
3218 Set the fields items in the field treeview | |
3219 """ | |
3220 _record = self.__budget.getRecord(self.__budget.getCode( | |
3221 self.__active_path_record)) | |
3222 _sheet = _record.getSheet() | |
3223 _field_list = _sheet.getFields() | |
3224 self.__field_liststore.clear() | |
3225 for _field in _field_list: | |
3226 _field_text = self.__budget.getSheetField(_field) | |
3227 _iter = self.__field_liststore.append([_field, _field_text]) | |
3228 _treeselection = self.__field_treeview.get_selection() | |
3229 _treeselection.select_path(0) | |
3230 | |
3231 def setSection(self): | |
3232 """setSection(self) | |
3233 | |
3234 Set the section items in the section treeview | |
3235 """ | |
3236 self.__section_liststore.clear() | |
3237 if not self.__field_selection is None: | |
3238 _record = self.__budget.getRecord(self.__budget.getCode( | |
3239 self.__active_path_record)) | |
3240 _sheet = _record.getSheet() | |
3241 _section_list = _sheet.getSections(self.__field_selection) | |
3242 for _section in _section_list: | |
3243 _section_text = self.__budget.getSheetSection(_section) | |
3244 _iter = self.__section_liststore.append([_section, _section_text]) | |
3245 _treeselection = self.__section_treeview.get_selection() | |
3246 _treeselection.select_path(0) | |
3247 | |
3248 def setText(self): | |
3249 """setText(self) | |
3250 | |
3251 Set the text in the textview | |
3252 """ | |
3253 if not self.__section_selection is None and\ | |
3254 not self.__field_selection is None: | |
3255 _record = self.__budget.getRecord(self.__budget.getCode( | |
3256 self.__active_path_record)) | |
3257 _sheet = _record.getSheet() | |
3258 _paragraph_code = _sheet.getParagraph(self.__field_selection, | |
3259 self.__section_selection) | |
3260 _paragraph = self.__budget.getSheetParagraph(_paragraph_code) | |
3261 self.__textbuffer.set_text(_paragraph) | |
3262 else: | |
3263 self.__textbuffer.set_text("") | |
3264 | |
3265 def field_controlSelection(self, selection): | |
3266 """def controlSelection(self, selection) | |
3267 | |
3268 selection: treeselection | |
3269 | |
3270 Method connected to set_selection_function() in field treeview | |
3271 This method is called before any node is selected or unselected, | |
3272 giving some control over which nodes are selected. | |
3273 The selection function should return TRUE if the state | |
3274 of the node may be toggled, and FALSE if the state of the node should | |
3275 be left unchanged. | |
3276 | |
3277 When a user select a row in the field treeview the section treeview is | |
3278 reloaded to show the sections of this field and already the text sheet. | |
3279 """ | |
3280 _treeiter = self.__field_liststore.get_iter(selection) | |
3281 self.__field_selection = self.__field_liststore.get_value(_treeiter, 0) | |
3282 self.setSection() | |
3283 return True | |
3284 | |
3285 def section_controlSelection(self, selection): | |
3286 """def controlSelection(self, selection) | |
3287 | |
3288 selection: treeselection | |
3289 | |
3290 Method connected to set_selection_function() in sector treeview | |
3291 This method is called before any node is selected or unselected, | |
3292 giving some control over which nodes are selected. | |
3293 The selection function should return TRUE if the state | |
3294 of the node may be toggled, and FALSE if the state of the node should | |
3295 be left unchanged. | |
3296 | |
3297 When a user select a row in the field treeview the text sheet for this | |
3298 section in showed | |
3299 """ | |
3300 _treeiter = self.__section_liststore.get_iter(selection) | |
3301 self.__section_selection = self.__section_liststore.get_value(_treeiter, 0) | |
3302 self.setText() | |
3303 return True | |
3304 | |
3305 def setActivePathRecord(self, path_record): | |
3306 """def setActivePathRecord(self, path_record)) | |
3307 | |
3308 path_record: active path record | |
3309 | |
3310 Set the new path code to show its sheet of condition text. | |
3311 """ | |
3312 self.__field_selection = None | |
3313 self.__field_liststore.clear() | |
3314 self.__section_selection = None | |
3315 self.__section_liststore.clear() | |
3316 self.__textbuffer.set_text("") | |
3317 _budget = self.__budget | |
3318 self.__active_path_record = path_record | |
3319 _code = _budget.getCode(self.__active_path_record) | |
3320 self.__label.set_text(utils.mapping(_("Sheet2 of Conditions of the "\ | |
3321 "record $1"), (_code,))) | |
3322 self.setFields() | |
3323 | |
3324 def runMessage(self, message, path, arg=None): | |
3325 """def runMessage(self, message, path, arg=None) | |
3326 | |
3327 message: the message type | |
3328 "change_active": change the active record | |
3329 "clear": clear instance | |
3330 path: tuple that identifies the pane in the notebook page | |
3331 arg: tuple whit two items: | |
3332 0: record path in the budget | |
3333 1: record code | |
3334 This method receives a message and executes its corresponding action | |
3335 """ | |
3336 _budget = self.__budget | |
3337 if message == "change_active": | |
3338 if _budget.hasPath(arg): | |
3339 self.setActivePathRecord(arg) | |
3340 elif message == "clear": | |
3341 self._clear() | |
3342 | |
3343 def _clear(self): | |
3344 """def _clear(self) | |
3345 | |
3346 Deletes all the instance atributes | |
3347 """ | |
3348 del self.__page | |
3349 del self.__widget | |
3350 del self.__path | |
3351 del self.__budget | |
3352 del self.__active_code | |
3353 del self.__textbuffer | |
3354 del self.__label | |
3355 del self.__textbuffer | |
3356 del self.__label | |
3357 del self.__field_liststore | |
3358 del self.__field_treeview | |
3359 del self.__field_selection | |
3360 del self.__section_liststore | |
3361 del self.__section_treeview | |
3362 del self.__section_selection | |
3363 | |
3364 def getWidget(self): | |
3365 """def getWidget(self) | |
3366 | |
3367 return the main widget (gtk.ScrolledWindow) | |
3368 """ | |
3369 return self.__widget | |
3370 | |
3371 def getPath(self): | |
3372 """def getPath(self) | |
3373 | |
3374 return the tuple that identifies the pane in the notebook page | |
3375 """ | |
3376 return self.__page | |
3377 | |
3378 def setPath(self, path): | |
3379 """def setPath(self) | |
3380 | |
3381 sets the tuple that identifies the pane in the notebook page | |
3382 """ | |
3383 self.__path = path | |
3384 | |
3385 def getPage(self): | |
3386 """def getPage(self) | |
3387 | |
3388 return the weak reference from Page instance | |
3389 """ | |
3390 return self.__page | |
3391 | |
3392 def setPage(self, page): | |
3393 """def setPage(self) | |
3394 | |
3395 set the weak reference from Page instance | |
3396 """ | |
3397 self.__page = page | |
3398 | |
3399 def getBudget(self): | |
3400 """def getBudget(self) | |
3401 | |
3402 return the budget object | |
3403 """ | |
3404 return self.__budget | |
3405 | |
3406 def getActivePathRecord(self): | |
3407 """def getActivePathRecord(self) | |
3408 | |
3409 return the Active Path Record | |
3410 """ | |
3411 return self.__active_path_record | |
3412 | |
3413 path = property(getPath, setPath, None, | |
3414 "Path that identifie the item in the page notebook") | |
3415 widget = property(getWidget, None, None, | |
3416 "Lista de configuracion de vistas") | |
3417 page = property(getPage, setPage, None, | |
3418 "Weak reference from Page instance which creates this class") | |
3419 budget = property(getBudget, None, None, | |
3420 "Budget object") | |
3421 active_path_record = property(getActivePathRecord, None, None, | |
3422 "Active Path Record") | |
3423 | |
3424 class FileView(object): | |
3425 """gui.FileView | |
3426 | |
3427 Description: | |
3428 Class to show the file icons of a record in a pane | |
3429 Constructor: | |
3430 Description(budget, code) | |
3431 budget: budget | |
3432 code: code record | |
3433 Ancestry: | |
3434 +-- object | |
3435 +-- Description | |
3436 Atributes: | |
3437 "widget": the main widget (gtk.ScrolledWindow object) | |
3438 "__icon_box": the box that contains the icon | |
3439 "path": the tuple that identifies the pane in the notebook page | |
3440 "budget": The budget (base.obra objetc) | |
3441 "active_code": The active code of the record | |
3442 Methods: | |
3443 __init__(self, budget, code) | |
3444 setActiveCode(self, code) | |
3445 runMessage(self, message, nt, arg=None) | |
3446 _clear(self) | |
3447 getWidget(self) | |
3448 {get/set}Path | |
3449 {get/seg}Page | |
3450 getBudget(self) | |
3451 getActviCode(self) | |
3452 """ | |
3453 | |
3454 def __init__(self, budget, page, path, path_record=(0,)): | |
3455 """def __init__(self, budget, page, path, path_record=(0,)) | |
3456 | |
3457 budget: the budget (base.obra object) | |
3458 page: weak reference from Page instance which creates this class | |
3459 path: the path position of the description in the page | |
3460 path_record: the path of the active record | |
3461 | |
3462 Creates an shows the scroledwindow that contain icon files | |
3463 of the record to be showed in a pane. | |
3464 """ | |
3465 self.__budget = budget | |
3466 self.__page = page | |
3467 self.__path = path | |
3468 self.__active_path_record = path_record | |
3469 self.__active_code = budget.getCode(self.__active_path_record) | |
3470 _budget = budget | |
3471 _record = self.__budget.getRecord(self.__budget.getCode( | |
3472 self.__active_path_record)) | |
3473 | |
3474 self.__icon_box = self.getIconBox(_record) | |
3475 _scrollwindow = gtk.ScrolledWindow() | |
3476 _scrollwindow.set_policy(gtk.POLICY_ALWAYS, | |
3477 gtk.POLICY_NEVER) | |
3478 | |
3479 self.__icon_box.show() | |
3480 _scrollwindow.add_with_viewport(self.__icon_box) | |
3481 _scrollwindow.show() | |
3482 self.__widget = _scrollwindow | |
3483 | |
3484 def getIconBox(self, record): | |
3485 """getIconBox(self, record) | |
3486 | |
3487 record: the active record object | |
3488 | |
3489 Creates and returns the box whith te icon files of the active record. | |
3490 """ | |
3491 ## TODO: add others filetypes: avi, pdf, ppt... | |
3492 _files = record.getFiles() | |
3493 _hbox = gtk.HBox() | |
3494 _frame = gtk.Frame() | |
3495 _frame.set_shadow_type(gtk.SHADOW_IN) | |
3496 for _file in _files: | |
3497 _path = os.path.dirname(self.__budget.filename) | |
3498 _file_path = os.path.join(_path, _file.name) | |
3499 _filetype = utils.getFiletype(_file_path) | |
3500 _box = gtk.VBox() | |
3501 if _filetype == "image": | |
3502 _event_box = gtk.EventBox() | |
3503 try: | |
3504 _image_pixbuf = gtk.gdk.pixbuf_new_from_file(_file_path) | |
3505 _image_pixbuf = _image_pixbuf.scale_simple(64, 64, | |
3506 gtk.gdk.INTERP_BILINEAR) | |
3507 except: | |
3508 _image_pixbuf = gtk.gdk.pixbuf_new_from_file( | |
3509 globals.getAppPath("IMAGE-ICON")) | |
3510 _image_pixbuf = _image_pixbuf.scale_simple(64, 64, | |
3511 gtk.gdk.INTERP_BILINEAR) | |
3512 _image_icon = gtk.Image() | |
3513 _image_icon.set_from_pixbuf(_image_pixbuf) | |
3514 _image_icon.show() | |
3515 _event_box.add(_image_icon) | |
3516 _box.pack_start(_event_box, False, False, 5) | |
3517 _event_box.connect("button-press-event", self.launchFile, | |
3518 "image", _file_path) | |
3519 _event_box.show() | |
3520 | |
3521 elif _filetype == "dxf": | |
3522 _event_box = gtk.EventBox() | |
3523 _dxf_icon = gtk.Image() | |
3524 _dxf_pixbuf = gtk.gdk.pixbuf_new_from_file( | |
3525 globals.getAppPath("DXF-ICON")) | |
3526 _dxf_pixbuf = _dxf_pixbuf.scale_simple(64, 64, | |
3527 gtk.gdk.INTERP_BILINEAR) | |
3528 _dxf_icon.set_from_pixbuf(_dxf_pixbuf) | |
3529 _dxf_icon.show() | |
3530 _event_box.add(_dxf_icon) | |
3531 _box.pack_start(_event_box, False, False, 5) | |
3532 _event_box.connect("button-press-event", self.launchFile, | |
3533 "dxf", _file_path) | |
3534 _event_box.show() | |
3535 _label_event_box = gtk.EventBox() | |
3536 _label = gtk.Label(_file.name) | |
3537 _label_event_box.add(_label) | |
3538 _label_event_box.show() | |
3539 _label.show() | |
3540 _box.pack_start(_label_event_box, False, False, 5) | |
3541 _box.show() | |
3542 _hbox.pack_start(_box, False, False, 5) | |
3543 _hbox.show() | |
3544 _frame.add(_hbox) | |
3545 return _frame | |
3546 | |
3547 def launchFile(self, widget, event, kind, file_path): | |
3548 """launchFile(self, widget, event, kind, file_path) | |
3549 | |
3550 widget: the widget that emit the signal | |
3551 event: the event that emit the signal | |
3552 king: kind of file | |
3553 file_path: the path file to be launch | |
3554 | |
3555 Launch the file if a double click emit the signal. | |
3556 Method connected to "button-press-event" signal in images event box | |
3557 """ | |
3558 if event.type is gtk.gdk._2BUTTON_PRESS: | |
3559 openwith.launch_file(kind, file_path) | |
3560 | |
3561 def setActivePathRecord(self, path_record): | |
3562 """def setActivePathRecord(self, path_record)) | |
3563 | |
3564 path_record: active path record | |
3565 Set the new path code to show its description text. | |
3566 """ | |
3567 _budget = self.__budget | |
3568 self.__active_path_record = path_record | |
3569 _code = _budget.getCode(self.__active_path_record) | |
3570 _record = self.__budget.getRecord(_code) | |
3571 self.__icon_box.destroy() | |
3572 self.__icon_box = self.getIconBox(_record) | |
3573 self.__icon_box.show() | |
3574 self.__widget.add_with_viewport(self.__icon_box) | |
3575 | |
3576 def runMessage(self, message, path, arg=None): | |
3577 """def runMessage(self, message, path, arg=None) | |
3578 | |
3579 message: the message type | |
3580 "change_active": change the active record | |
3581 "clear": clear instance | |
3582 path: tuple that identifies the pane in the notebook page | |
3583 arg: tuple whit two items: | |
3584 0: record path in the budget | |
3585 1: record code | |
3586 This method receives a message and executes its corresponding action | |
3587 """ | |
3588 _budget = self.__budget | |
3589 if message == "change_active": | |
3590 if _budget.hasPath(arg): | |
3591 self.setActivePathRecord(arg) | |
3592 elif message == "clear": | |
3593 self._clear() | |
3594 | |
3595 def _clear(self): | |
3596 """def _clear(self) | |
3597 | |
3598 Delete all instance atributes | |
3599 """ | |
3600 del self.__hbox | |
3601 del self.__widget | |
3602 del self.__path | |
3603 del self.__budget | |
3604 del self.__active_code | |
3605 | |
3606 def getWidget(self): | |
3607 """def getWidget(self) | |
3608 | |
3609 return the main widget (gtk.ScrolledWindow) | |
3610 """ | |
3611 return self.__widget | |
3612 | |
3613 def getPath(self): | |
3614 """def getPath(self) | |
3615 | |
3616 return the tuple that identifies the pane in the notebook page | |
3617 """ | |
3618 return self.__path | |
3619 | |
3620 def setPath(self, path): | |
3621 """def setPath(self) | |
3622 | |
3623 sets the tuple that identifies the pane in the notebook page | |
3624 """ | |
3625 self.__path = path | |
3626 | |
3627 def getPage(self): | |
3628 """def getPage(self) | |
3629 | |
3630 return the weak reference from Page instance | |
3631 """ | |
3632 return self.__page | |
3633 | |
3634 def setPage(self, page): | |
3635 """def setPage(self) | |
3636 | |
3637 set the weak reference from Page instance | |
3638 """ | |
3639 self.__page = page | |
3640 | |
3641 def getBudget(self): | |
3642 """def getBudget(self) | |
3643 | |
3644 return the budget object | |
3645 """ | |
3646 return self.__budget | |
3647 | |
3648 def getActivePathRecord(self): | |
3649 """def getActivePathRecord(self) | |
3650 | |
3651 return the Active Path Record | |
3652 """ | |
3653 return self.__active_path_record | |
3654 | |
3655 path = property(getPath, setPath, None, | |
3656 "Path that identifie the item in the page notebook") | |
3657 widget = property(getWidget, None, None, | |
3658 "The main widget (gtk.ScrolledWindow)") | |
3659 page = property(getPage, setPage, None, | |
3660 "Weak reference from Page instance which creates this class") | |
3661 budget = property(getBudget, None, None, | |
3662 "Budget object") | |
3663 active_path_record = property(getActivePathRecord, None, None, | |
3664 "Active Path Record") | |
3665 | |
3666 | |
3667 class TextWindow(object): | |
3668 """gui.TextWindow | |
3669 | |
3670 Description: | |
3671 Class to show a description text of a record in a new gtk window | |
3672 Constructor: | |
3673 TextWindow(code, text) | |
3674 code: code of the record | |
3675 text: description text of the record | |
3676 Ancestry: | |
3677 +-- object | |
3678 +-- TextWindow | |
3679 Atributes: | |
3680 Methods: | |
3681 __init__(self, code, text) | |
3682 main(self) | |
3683 destroy(self, widget) | |
3684 """ | |
3685 | |
3686 def __init__(self, code, text): | |
3687 """def __init__(self, code, text) | |
3688 | |
3689 code: code of the record | |
3690 text: description text of the record | |
3691 Creates an shows the window. | |
3692 """ | |
3693 _window = gtk.Window(gtk.WINDOW_TOPLEVEL) | |
3694 _window.set_resizable(True) | |
3695 _window.set_default_size(700, 300) | |
3696 _window.set_title(utils.mapping(_("$1 text"), (code,))) | |
3697 _window.set_border_width(0) | |
3698 _box1 = gtk.VBox(False, 0) | |
3699 _window.add(_box1) | |
3700 _box1.show() | |
3701 _sw = gtk.ScrolledWindow() | |
3702 _sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | |
3703 _textview = gtk.TextView() | |
3704 _textview.set_wrap_mode(gtk.WRAP_WORD) | |
3705 _textbuffer = _textview.get_buffer() | |
3706 _sw.add(_textview) | |
3707 _sw.show() | |
3708 _textview.show() | |
3709 _box1.pack_start(_sw) | |
3710 _textbuffer.set_text(text) | |
3711 _window.connect("destroy", self.destroy) | |
3712 _window.show() | |
3713 | |
3714 def main(self): | |
3715 """def main(self) | |
3716 | |
3717 Starts the GTK+ event processing loop. | |
3718 """ | |
3719 gtk.main() | |
3720 | |
3721 def destroy(self, widget): | |
3722 """destroy(self, widget) | |
3723 widget: the widget where the event is emitted from | |
3724 Method connected to "destroy" signal of window widget | |
3725 This signal is emited when the method connected to "delete_event" | |
3726 signal returns True or when the program call the destroy() method of | |
3727 the gtk.Window widget. | |
3728 The window is closed and the GTK+ event processing loop is ended. | |
3729 """ | |
3730 gtk.main_quit() | |
3731 | |
3732 class CompanyView(object): | |
3733 """gui.CompanyView: | |
3734 | |
3735 Description: | |
3736 Class to show the company records of a budget | |
3737 Constructor: | |
3738 CompanyView(budget, page, path) | |
3739 budget: budget showed ("base.Budget" object) | |
3740 page: weak reference from Page instance which creates this class | |
3741 path: tuple that represents the path of the List in the Page | |
3742 Returns the newly created CompanyView instance | |
3743 Ancestry: | |
3744 +-- object | |
3745 +-- CompanyView | |
3746 Atributes: | |
3747 "budget": Budget to show, base.obra instance. | |
3748 "active_path_record" | |
3749 "widget": Window that contains the main widget, | |
3750 (gtk.ScrolledWindow) | |
3751 "path": Pane page identifier | |
3752 "page": weak reference from Page instance which creates this class | |
3753 "__methond_message": Method to send messages to the page | |
3754 Methods: | |
3755 __init__(self, budget, page, path, path_record=(0,)) | |
3756 runMessage(self, message, path, arg=None) | |
3757 _clear(self) | |
3758 getWidget(self) | |
3759 {get/set}Path | |
3760 {get/set}Page | |
3761 getBudget(self) | |
3762 getActivePathRecord(self) | |
3763 """ | |
3764 | |
3765 def __init__(self, budget, page, path, path_record=(0,)): | |
3766 """def __init__(self, budget, page, path, path_record=(0,)) | |
3767 | |
3768 budget: budget: budget showed ("base.Budget" object) | |
3769 page: weak reference from Page instance which creates this class | |
3770 path: tuple that represents the path of the List in the Page | |
3771 path_record: path of the active record in the budget | |
3772 | |
3773 Sets the init atributes | |
3774 Creates the | |
3775 | |
3776 """ | |
3777 self.__selection = None | |
3778 # Seting init args | |
3779 if not isinstance(budget, base.Budget): | |
3780 raise ValueError, _("Argument must be a Budget object") | |
3781 self.__budget = budget | |
3782 self.__page = page | |
3783 self.__path = path | |
3784 self.__active_path_record = path_record | |
3785 # HVox | |
3786 self.__hbox = gtk.HPaned() | |
3787 self.__hbox.set_position(230) | |
3788 # TreeStore | |
3789 self.__treestore = gtk.TreeStore(str, str) | |
3790 self.setTreeStoreValues() | |
3791 # Select Treeview | |
3792 self.__select_treeview = gtk.TreeView(self.__treestore) | |
3793 self.__select_treeview.set_enable_search(False) | |
3794 self.__select_treeview.set_reorderable(False) | |
3795 self.__select_treeview.set_headers_visible(False) | |
3796 self.__select_treeview.show() | |
3797 # Scrolled_window | |
3798 self.__scrolled_window = gtk.ScrolledWindow() | |
3799 self.__scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, | |
3800 gtk.POLICY_AUTOMATIC) | |
3801 self.__scrolled_window.add(self.__select_treeview) | |
3802 # colors | |
3803 _text_color = gtk.gdk.color_parse(globals.color["TEXT"]) | |
3804 _background_color = [ | |
3805 gtk.gdk.color_parse(globals.color["UNEVEN"]), | |
3806 gtk.gdk.color_parse(globals.color["EVEN"])] | |
3807 self.__code_column = gtk.TreeViewColumn() | |
3808 self.__code_column.set_clickable(True) | |
3809 self.__code_column.set_fixed_width(200) | |
3810 _code_cell = gtk.CellRendererText() | |
3811 _code_cell.set_property('foreground-gdk', _text_color) | |
3812 self.__code_column.pack_start(_code_cell, True) | |
3813 self.__code_column.add_attribute(_code_cell, 'text', 0) | |
3814 _summary_cell = gtk.CellRendererText() | |
3815 _summary_cell.set_property('foreground-gdk', _text_color) | |
3816 self.__code_column.pack_start(_summary_cell, True) | |
3817 self.__code_column.add_attribute(_summary_cell, 'text', 1) | |
3818 # Index column | |
3819 self.__select_treeview.append_column(self.__code_column) | |
3820 # control selection | |
3821 self.__treeselection = self.__select_treeview.get_selection() | |
3822 self.__treeselection.set_mode(gtk.SELECTION_SINGLE) | |
3823 self.__treeselection.set_select_function(self.controlSelection) | |
3824 # Show | |
3825 self.setColumnsHeaders() | |
3826 self.__scrolled_window.show() | |
3827 # Option View | |
3828 self.__option_View = OptionView("") | |
3829 # Selection | |
3830 self.__select_treeview.set_cursor((0,), None, False) | |
3831 self.__select_treeview.grab_focus() | |
3832 # | |
3833 self.__hbox.add1(self.__scrolled_window) | |
3834 self.__hbox.add2(self.__option_View.widget) | |
3835 self.__hbox.show() | |
3836 self.__widget = self.__hbox | |
3837 | |
3838 def setOptions(self, type): | |
3839 if type == "company": | |
3840 _options = [("code", _("Code"), "string", | |
3841 _("""Code that define the company""")), | |
3842 ("summary", _("Summary"), "string", | |
3843 _("""Summary of the company name""")), | |
3844 ("name", _("Name"), "string", | |
3845 _("""Complete name""")), | |
3846 ("cif", _("CIF"), "string", | |
3847 _("""Fiscal identifier number""")), | |
3848 ("web", _("Web"), "string", | |
3849 _("""Company web page""")), | |
3850 ("email", _("Email"), "string", | |
3851 _("""Company email""")), | |
3852 ] | |
3853 self.__option_View.setOptions(_options) | |
3854 elif type == "office": | |
3855 _options = [("type", _("Type"), "string", | |
3856 _("""Type of Office: | |
3857 C: Central office | |
3858 D: Local office | |
3859 R: Performer""")), | |
3860 ("subname", _("Name"), "string", | |
3861 _("Office name")), | |
3862 ("address", _("Address"), "string",""), | |
3863 ("postal code", _("Postal code"), "string",""), | |
3864 ("town", _("Town"), "string",""), | |
3865 ("province", _("Province"), "string",""), | |
3866 ("country", _("Country"), "string",""), | |
3867 ("phone", _("Phone"), "list", | |
3868 _("Phone numbers of the office")), | |
3869 ("fax", _("Fax"), "list", | |
3870 _("Fax numbers of the office")), | |
3871 ("contact person", _("Contact person"), "string", | |
3872 _("Contact persons in the office")), | |
3873 ] | |
3874 self.__option_View.setOptions(_options) | |
3875 else: | |
3876 print _("Unknow Option Type") | |
3877 def setOptionValues(self, company_key): | |
3878 self.__option_View.setValues(_values) | |
3879 | |
3880 def setTreeStoreValues(self): | |
3881 """def setListstoreValues(self) | |
3882 | |
3883 Sets the treestore values from the budget | |
3884 """ | |
3885 _budget = self.__budget | |
3886 _company_keys = _budget.getCompanyKeys() | |
3887 for _company_key in _company_keys: | |
3888 _company = _budget.getCompany(_company_key) | |
3889 _values = [_company_key, _company.summary] | |
3890 _treeiter = self.__treestore.append(None, _values) | |
3891 _offices = _company.offices | |
3892 for _office in _offices: | |
3893 # TODO: Test offices | |
3894 _values = [_office.officeType, _office.subname] | |
3895 self.__treestore.append(_treeiter, _values) | |
3896 | |
3897 def setColumnsHeaders(self): | |
3898 """def setColumnsHeaders(self) | |
3899 | |
3900 Sets the headers column values | |
3901 """ | |
3902 #self.columns[1].set_title(_("Type")) # Σ parcial Σ total | |
3903 #self.columns[2].set_title(_("Comment")) | |
3904 #self.columns[3].set_title(_("N")) | |
3905 #self.columns[4].set_title(_("Length")) | |
3906 #self.columns[5].set_title(_("Width")) | |
3907 #self.columns[6].set_title(_("Height")) | |
3908 pass | |
3909 | |
3910 def controlSelection(self, selection): | |
3911 """def controlSelection(self, selection) | |
3912 | |
3913 selection: selection | |
3914 | |
3915 Method connected to set_selection_function() | |
3916 This method is called before any node is selected or unselected, | |
3917 giving some control over which nodes are selected. | |
3918 The selection function should return TRUE if the state | |
3919 of the node may be toggled, and FALSE if the state of the node should | |
3920 be left unchanged. | |
3921 | |
3922 The selection changes the company/office in the option treeview | |
3923 """ | |
3924 if len(selection) == 1: | |
3925 # The selection is a company | |
3926 _company_key = self.__treestore[selection][0] | |
3927 _company = self.__budget.getCompany(_company_key) | |
3928 _selection = "company" | |
3929 _values = _company.values | |
3930 else: | |
3931 # The selection is a office | |
3932 _company_key = self.__treestore[selection[:1]][0] | |
3933 _company = self.__budget.getCompany(_company_key) | |
3934 _selection = "office" | |
3935 _office = _company.offices[selection[1]] | |
3936 _values = _office.values | |
3937 if not self.__selection == _selection: | |
3938 self.__selection = _selection | |
3939 self.setOptions(_selection) | |
3940 self.__option_View.setValues(_values) | |
3941 | |
3942 return True | |
3943 | |
3944 def showMessageRecord(self, record_path): | |
3945 """def showMessageRecord(self, record_path) | |
3946 | |
3947 record_path: the path of the record to show | |
3948 Method connected to "change_active" message | |
3949 Show the record especified in the "change_active" message | |
3950 """ | |
3951 self.__active_path_record = record_path | |
3952 | |
3953 def runMessage(self, message, path, arg=None): | |
3954 """def runMessage(self, message, path, arg=None) | |
3955 | |
3956 message: the message type | |
3957 "change_active": change the active record | |
3958 "clear": clear instance | |
3959 path: tuple that identifies the pane in the notebook page | |
3960 arg: tuple whit two items: | |
3961 0: record path in the budget | |
3962 1: record code | |
3963 This method receives a message and executes its corresponding action | |
3964 """ | |
3965 _budget = self.__budget | |
3966 if message == "change_active": | |
3967 if _budget.hasPath(arg): | |
3968 _path_record = arg | |
3969 self.showMessageRecord( _path_record) | |
3970 pass | |
3971 elif message == "clear": | |
3972 self._clear() | |
3973 | |
3974 def colorCell(self, column, cell_renderer, tree_model, iter, lcolor): | |
3975 """def colorCell(self, column, cell_renderer, tree_model, iter, lcolor) | |
3976 | |
3977 column: the gtk.TreeViewColumn in the treeview | |
3978 cell_renderer: a gtk.CellRenderer | |
3979 tree_model: the gtk.TreeModel | |
3980 iter: gtk.TreeIter pointing at the row | |
3981 lcolor: list with 2 gtk colors for even and uneven record | |
3982 | |
3983 Method connected to "set_cell_data_func" of many column | |
3984 The set_cell_data_func() method sets the data function (or method) | |
3985 to use for the column gtk.CellRenderer specified by cell_renderer. | |
3986 This function (or method) is used instead of the standard attribute | |
3987 mappings for setting the column values, and should set the attributes | |
3988 of the cell renderer as appropriate. func may be None to remove the | |
3989 current data function. The signature of func is: | |
3990 -def celldatafunction(column, cell, model, iter, user_data) | |
3991 -def celldatamethod(self, column, cell, model, iter, user_data) | |
3992 where column is the gtk.TreeViewColumn in the treeview, cell is the | |
3993 gtk.CellRenderer for column, model is the gtk.TreeModel for the | |
3994 treeview and iter is the gtk.TreeIter pointing at the row. | |
3995 | |
3996 The method sets cell background color for all columns | |
3997 and text for index and amount columns. | |
3998 """ | |
3999 _row_path = tree_model.get_path(iter) | |
4000 _number = _row_path[-1] | |
4001 if column is self.__index_column: | |
4002 cell_renderer.set_property('text', str(_number + 1)) | |
4003 self.__index_column.get_cell_renderers()[1].set_property( | |
4004 'cell-background-gdk', lcolor[_number % 2]) | |
4005 if self.__treeview.get_cursor() == (_row_path,column): | |
4006 cell_renderer.set_property('cell-background-gdk', | |
4007 gtk.gdk.color_parse(globals.color["ACTIVE"])) | |
4008 else: | |
4009 cell_renderer.set_property('cell-background-gdk', | |
4010 lcolor[_number % 2]) | |
4011 | |
4012 def _clear(self): | |
4013 """def _clear(self) | |
4014 | |
4015 it deletes the __budget value | |
4016 this would not be necessary if there were not circular references, | |
4017 which are pending to fix | |
4018 """ | |
4019 del self.__budget | |
4020 | |
4021 def getWidget(self): | |
4022 """def getWidget(self) | |
4023 | |
4024 return the main widget (gtk.ScrolledWindow) | |
4025 """ | |
4026 return self.__widget | |
4027 | |
4028 def getPath(self): | |
4029 """def getPath(self) | |
4030 | |
4031 return the tuple that identifies the pane in the notebook page | |
4032 """ | |
4033 return self.__path | |
4034 | |
4035 def setPath(self, path): | |
4036 """def setPath(self) | |
4037 | |
4038 sets the tuple that identifies the pane in the notebook page | |
4039 """ | |
4040 self.__path = path | |
4041 def getPage(self): | |
4042 """def getPage(self) | |
4043 | |
4044 return the Page | |
4045 """ | |
4046 return self.__page | |
4047 | |
4048 def setPage(self,page): | |
4049 """def setPage(self) | |
4050 | |
4051 set the Page | |
4052 """ | |
4053 self.__page = page | |
4054 | |
4055 def getBudget(self): | |
4056 """def getBudget(self) | |
4057 | |
4058 return the Budget objet | |
4059 """ | |
4060 return self.__budget | |
4061 | |
4062 def getActivePathRecord(self): | |
4063 """def getActivePathRecord(self) | |
4064 | |
4065 return the Active Path Record | |
4066 """ | |
4067 return self.__active_path_record | |
4068 | |
4069 active_path_record = property(getActivePathRecord, None, None, | |
4070 "Active path record") | |
4071 widget = property(getWidget, None, None, | |
4072 "main widget") | |
4073 path = property(getPath, setPath, None, | |
4074 "Path that identifies the item in the page notebook") | |
4075 page = property(getPage, setPage, None, | |
4076 "Weak reference from Page instance which creates this class") | |
4077 budget = property(getBudget, None, None, | |
4078 "Budget object") | |
4079 | |
4080 | |
4081 class OptionView(object): | |
4082 """gui.OptionView: | |
4083 | |
4084 Description: | |
4085 It creates a treeview whith the column "Option Name" "Value" | |
4086 and "Type" to show and edit Options | |
4087 Constructor: | |
4088 OptionView(option_list) | |
4089 option_list: list of options | |
4090 (option_name, type) | |
4091 Ancestry: | |
4092 +-- object | |
4093 +-- OptionView | |
4094 Atributes: | |
4095 "__liststore" | |
4096 "__treeview" | |
4097 "__option_column" | |
4098 "__value_column" | |
4099 "__type_column" | |
4100 "__treeselection" | |
4101 "__widget": Main windget | |
4102 "__option_list" | |
4103 "__option_dict" | |
4104 "__description_label" | |
4105 "option_types" | |
4106 "widget": __widget | |
4107 Methods: | |
4108 __init__(self, option_list) | |
4109 createColumn(self, args) | |
4110 createTextBaseColumn(self,args) | |
4111 createBaseColumn(self,args) | |
4112 """ | |
4113 | |
4114 def __init__(self, option_list): | |
4115 """__init__(self, option_list) | |
4116 | |
4117 """ | |
4118 self.__option_dict = {} | |
4119 self.__option_list = [] | |
4120 self.option_types = {"boolean" : _("Boolean"), | |
4121 "integer": _("Integer"), | |
4122 "string": _("Text"), | |
4123 "color" : _("Color"), | |
4124 "list" : _("List")} | |
4125 # ListStore | |
4126 self.__liststore = gtk.ListStore(str, str, str, str, str) | |
4127 # Treeview | |
4128 self.__treeview = gtk.TreeView(self.__liststore) | |
4129 self.__treeview.set_enable_search(False) | |
4130 self.__treeview.set_reorderable(False) | |
4131 self.__treeview.set_headers_clickable(False) | |
4132 # vbox | |
4133 _vbox = gtk.VBox() | |
4134 # Scrolled_window | |
4135 _scrolled_window = gtk.ScrolledWindow() | |
4136 _scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, | |
4137 gtk.POLICY_AUTOMATIC) | |
4138 _scrolled_window.add(self.__treeview) | |
4139 _scrolled_window.show() | |
4140 _vbox.pack_start(_scrolled_window) | |
4141 # colors | |
4142 _text_color = gtk.gdk.color_parse(globals.color["TEXT"]) | |
4143 _background_color = [ | |
4144 gtk.gdk.color_parse(globals.color["UNEVEN"]), | |
4145 gtk.gdk.color_parse(globals.color["EVEN"])] | |
4146 # Option Column | |
4147 self.__option_column = gtk.TreeViewColumn() | |
4148 self.__option_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) | |
4149 self.__option_column.set_fixed_width(150) | |
4150 self.__option_column.set_resizable(True) | |
4151 _option_cell = gtk.CellRendererText() | |
4152 _option_cell.set_property('foreground-gdk', _text_color) | |
4153 self.__option_column.pack_start(_option_cell, True) | |
4154 self.__option_column.set_cell_data_func(_option_cell, self.colorCell, | |
4155 _background_color) | |
4156 self.__option_column.set_title(_("Option name")) | |
4157 self.__option_column.add_attribute(_option_cell, 'text', 1) | |
4158 self.__treeview.append_column(self.__option_column) | |
4159 # Value Column | |
4160 self.__value_column = gtk.TreeViewColumn() | |
4161 self.__value_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) | |
4162 self.__value_column.set_fixed_width(275) | |
4163 self.__value_column.set_resizable(True) | |
4164 _value_cell = gtk.CellRendererText() | |
4165 _value_cell.set_property('foreground-gdk', _text_color) | |
4166 self.__value_column.pack_start(_value_cell, True) | |
4167 self.__value_column.set_cell_data_func(_value_cell, self.colorCell, | |
4168 _background_color) | |
4169 self.__value_column.set_title(_("Value")) | |
4170 self.__value_column.add_attribute(_value_cell, 'text', 2) | |
4171 self.__treeview.append_column(self.__value_column) | |
4172 # Type Column | |
4173 self.__type_column = gtk.TreeViewColumn() | |
4174 self.__type_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) | |
4175 self.__type_column.set_fixed_width(70) | |
4176 self.__type_column.set_resizable(True) | |
4177 _type_cell = gtk.CellRendererText() | |
4178 _type_cell.set_property('foreground-gdk', _text_color) | |
4179 self.__type_column.pack_start(_type_cell, True) | |
4180 self.__type_column.set_cell_data_func(_type_cell, self.colorCell, | |
4181 _background_color) | |
4182 self.__type_column.set_title(_("Type")) | |
4183 self.__treeview.append_column(self.__type_column) | |
4184 # End Column | |
4185 _end_column = gtk.TreeViewColumn() | |
4186 _end_column.set_clickable(False) | |
4187 _end_cell = gtk.CellRendererText() | |
4188 _end_cell.set_property('cell-background-gdk', | |
4189 gtk.gdk.color_parse(globals.color["UNEVEN"])) | |
4190 _end_column.pack_start(_end_cell, True) | |
4191 self.__treeview.append_column(_end_column) | |
4192 # Connect | |
4193 self.__treeview.connect("key-press-event", self.treeviewKeyPressEvent) | |
4194 self.__treeview.connect("button-press-event", self.treeviewClickedEvent) | |
4195 # control selection | |
4196 self.__treeselection = self.__treeview.get_selection() | |
4197 self.__treeselection.set_mode(gtk.SELECTION_MULTIPLE) | |
4198 self.__treeselection.set_select_function(self.controlSelection) | |
4199 # labels | |
4200 _frame = gtk.Frame() | |
4201 _frame.set_shadow_type(gtk.SHADOW_OUT) | |
4202 _vbox2 = gtk.VBox() | |
4203 _frame.add(_vbox2) | |
4204 _alignement = gtk.Alignment(xalign=0, yalign=0, xscale=0, yscale=0) | |
4205 _alignement.set_padding(0, 0, 12, 0) | |
4206 _label = gtk.Label() | |
4207 _label.set_markup("<b>" + _("Description:") + "</b>") | |
4208 _label.show() | |
4209 _alignement.add(_label) | |
4210 _alignement.show() | |
4211 _alignement2 = gtk.Alignment(xalign=0, yalign=0, xscale=0, yscale=0) | |
4212 _alignement2.set_padding(0, 0, 24, 0) | |
4213 self.__description_label = gtk.Label() | |
4214 self.__description_label.show() | |
4215 _alignement2.add(self.__description_label) | |
4216 _alignement2.show() | |
4217 _vbox2.pack_start(_alignement, False) | |
4218 _vbox2.pack_start(_alignement2, False) | |
4219 _vbox2.show() | |
4220 _frame.show() | |
4221 _vbox.pack_start(_frame, False) | |
4222 # Show | |
4223 self.__treeview.show() | |
4224 _vbox.show() | |
4225 self.__widget = _vbox | |
4226 | |
4227 def treeviewKeyPressEvent(self, widget, event): | |
4228 """def treeviewKeyPressEvent(self, widget, event) | |
4229 | |
4230 widget: treewiew widget | |
4231 event: Key Press event | |
4232 Method connected to "key-press-event" signal | |
4233 The "key-press-event" signal is emitted when the user presses a key | |
4234 on the keyboard. | |
4235 Returns :TRUE to stop other handlers from being invoked for the event. | |
4236 Returns :FALSE to propagate the event further. | |
4237 | |
4238 If the user press the right cursor button and the cursor is in the | |
4239 value column or pres the left cursor button and the cursor is | |
4240 in the value column the event is estoped, else the event is propagated. | |
4241 """ | |
4242 (_cursor_path, _column) = self.__treeview.get_cursor() | |
4243 if (event.keyval == gtk.keysyms.Right \ | |
4244 and _column == self.__value_column) \ | |
4245 or (event.keyval == gtk.keysyms.Left \ | |
4246 and _column == self.__value_column): | |
4247 return True | |
4248 else: | |
4249 _description = self.__liststore[_cursor_path][4] | |
4250 self.__description_label.set_text(_description) | |
4251 return False | |
4252 | |
4253 def treeviewClickedEvent(self, widget, event): | |
4254 """def treeviewClickedEvent(self, widget, event) | |
4255 | |
4256 widget: treewiew widget | |
4257 event: clicked event | |
4258 Method connected to "button-press-event" signal | |
4259 The "button-press-event" signal is emitted when a mouse button is | |
4260 pressed. | |
4261 Returns TRUE to stop other handlers from being invoked for the event. | |
4262 Returns FALSE to propagate the event further. | |
4263 | |
4264 The cursos is moved to value column. | |
4265 """ | |
4266 path_at_pos = self.__treeview.get_path_at_pos(int(event.x), | |
4267 int(event.y)) | |
4268 if not path_at_pos is None: | |
4269 _path_cursor, _column, _x, _y = path_at_pos | |
4270 _description = self.__liststore[_path_cursor][4] | |
4271 self.__description_label.set_text(_description) | |
4272 if _column == self.__value_column: | |
4273 return False | |
4274 else: | |
4275 self.__treeview.set_cursor(_path_cursor,self.__value_column, | |
4276 True) | |
4277 self.__treeview.grab_focus() | |
4278 return True | |
4279 return True | |
4280 | |
4281 def controlSelection(self, selection): | |
4282 """def controlSelection(self, selection) | |
4283 | |
4284 selection: treeselection | |
4285 | |
4286 Method connected to set_selection_function() | |
4287 This method is called before any node is selected or unselected, | |
4288 giving some control over which nodes are selected. | |
4289 The selection function should return TRUE if the state | |
4290 of the node may be toggled, and FALSE if the state of the node should | |
4291 be left unchanged. | |
4292 | |
4293 Return False so none row is selected | |
4294 """ | |
4295 return False | |
4296 | |
4297 | |
4298 def colorCell(self, column, cell_renderer, tree_model, iter, lcolor): | |
4299 """def colorCell(self, column, cell_renderer, tree_model, iter, lcolor) | |
4300 | |
4301 column: the gtk.TreeViewColumn in the treeview | |
4302 cell_renderer: a gtk.CellRenderer | |
4303 tree_model: the gtk.TreeModel | |
4304 iter: gtk.TreeIter pointing at the row | |
4305 lcolor: list with 2 gtk colors for even and uneven record | |
4306 | |
4307 Method connected to "set_cell_data_func" of the column | |
4308 The set_cell_data_func() method sets the data function (or method) | |
4309 to use for the column gtk.CellRenderer specified by cell_renderer. | |
4310 This function (or method) is used instead of the standard attribute | |
4311 mappings for setting the column values, and should set the attributes | |
4312 of the cell renderer as appropriate. func may be None to remove the | |
4313 current data function. The signature of func is: | |
4314 -def celldatafunction(column, cell, model, iter, user_data) | |
4315 -def celldatamethod(self, column, cell, model, iter, user_data) | |
4316 where column is the gtk.TreeViewColumn in the treeview, cell is the | |
4317 gtk.CellRenderer for column, model is the gtk.TreeModel for the | |
4318 treeview and iter is the gtk.TreeIter pointing at the row. | |
4319 | |
4320 The method sets cell background color for all columns | |
4321 and text for type column. | |
4322 """ | |
4323 _row_path = tree_model.get_path(iter) | |
4324 _number = _row_path[-1] | |
4325 if self.__treeview.get_cursor() == (_row_path,column): | |
4326 cell_renderer.set_property('cell-background-gdk', | |
4327 gtk.gdk.color_parse(globals.color["ACTIVE"])) | |
4328 else: | |
4329 cell_renderer.set_property('cell-background-gdk', | |
4330 lcolor[_number % 2]) | |
4331 if column is self.__type_column: | |
4332 _type = self.option_types[tree_model[_row_path][3]] | |
4333 cell_renderer.set_property('text', _type) | |
4334 | |
4335 def setOptions(self, option_list): | |
4336 """setOptions(self, option_list) | |
4337 | |
4338 option_list: list of tuples | |
4339 (option, option name, type) | |
4340 option: option identifier | |
4341 option name: a string with the option name | |
4342 Description: a string with the option description | |
4343 type: can be "boolean" | |
4344 "integer" | |
4345 "string" | |
4346 "color" | |
4347 Sets the Options in the treeview rows | |
4348 """ | |
4349 self.__option_dict = {} | |
4350 self.__option_list = [] | |
4351 self.__liststore.clear() | |
4352 if isinstance(option_list, list): | |
4353 for _option in option_list: | |
4354 if isinstance(_option, tuple) and len(_option) == 4: | |
4355 _option_key = _option[0] | |
4356 _option_name = _option[1] | |
4357 _option_type = _option[2] | |
4358 _option_description = _option[3] | |
4359 if isinstance(_option_key, str) and \ | |
4360 (isinstance(_option_name, str) or\ | |
4361 isinstance(_option_name, unicode))and \ | |
4362 _option_type in self.option_types.keys(): | |
4363 self.__liststore.append([_option_key, _option_name, "", | |
4364 _option_type, _option_description]) | |
4365 self.__option_dict[_option_key] = [_option_name, "", | |
4366 _option_type, _option_description] | |
4367 self.__option_list.append(_option_key) | |
4368 else: | |
4369 print _("Option values must be strings") | |
4370 else: | |
4371 print _("Option must be a tuple with 4 items") | |
4372 else: | |
4373 print _("Option list must be a list") | |
4374 return | |
4375 def setValues(self, values): | |
4376 """setValues(self, values) | |
4377 | |
4378 values: dictionary {option : value} | |
4379 | |
4380 Sets the Options values | |
4381 """ | |
4382 if isinstance(values, dict): | |
4383 for _option, _value in values.iteritems(): | |
4384 if _option in self.__option_dict: | |
4385 _type = self.__option_dict[_option][2] | |
4386 if _type == "boolean": | |
4387 if isinstance(_value, bool): | |
4388 _num = self.__option_list.index(_option) | |
4389 _iter = self.__liststore.get_iter((_num,)) | |
4390 self.__liststore.set_value(_iter, 2, _value) | |
4391 self.__option_dict[_option][1] = _value | |
4392 else: | |
4393 print _("Icorrect type, must be boolean") | |
4394 elif _type == "integer": | |
4395 try: | |
4396 _value = int(_value) | |
4397 except ValueError: | |
4398 print _("Icorrect type, must be integer") | |
4399 else: | |
4400 _num = self.__option_list.index(_option) | |
4401 _iter = self.__liststore.get_iter((_num,)) | |
4402 self.__liststore.set_value(_iter, 2, _value) | |
4403 self.__option_dict[_option][1] = _value | |
4404 elif _type == "string": | |
4405 if isinstance(_value, str): | |
4406 _num = self.__option_list.index(_option) | |
4407 _iter = self.__liststore.get_iter((_num,)) | |
4408 self.__liststore.set_value(_iter, 2, _value) | |
4409 self.__option_dict[_option][1] = _value | |
4410 else: | |
4411 print _("Icorrect type, must be string") | |
4412 elif _type == "list": | |
4413 if isinstance(_value, list): | |
4414 _num = self.__option_list.index(_option) | |
4415 _iter = self.__liststore.get_iter((_num,)) | |
4416 _str_value = "" | |
4417 for _item_value in _value: | |
4418 _str_value = _str_value + _item_value + "," | |
4419 if _str_value[-1] == ",": | |
4420 _str_value = _str_value[:-1] | |
4421 self.__liststore.set_value(_iter, 2, _str_value) | |
4422 self.__option_dict[_option][1] = _value | |
4423 else: | |
4424 print _("Icorrect type, must be list") | |
4425 elif _type == "color": | |
4426 if isinstance(_value, str): | |
4427 try: | |
4428 _color = gtk.gdk.color_parse(_value) | |
4429 except ValueError: | |
4430 print _("Icorrect type, must be a parseable " \ | |
4431 "color") | |
4432 else: | |
4433 _num = self.__option_list.index(_option) | |
4434 _iter = self.__liststore.get_iter((_num,)) | |
4435 self.__liststore.set_value(_iter, 2, _value) | |
4436 self.__option_dict[_option][1] = _value | |
4437 else: | |
4438 print _("Type must be boolean, integer, string or "\ | |
4439 "color") | |
4440 else: | |
4441 print _("Value must be in the option dict") | |
4442 else: | |
4443 print _("Values must be a dict") | |
4444 self.__treeview.set_cursor((0),self.__value_column, False) | |
4445 self.__treeview.grab_focus() | |
4446 (_cursor_path, _column) = self.__treeview.get_cursor() | |
4447 _description = self.__liststore[_cursor_path][4] | |
4448 self.__description_label.set_text(_description) | |
4449 | |
4450 def getWidget(self): | |
4451 """def getWidget(self) | |
4452 | |
4453 return the main widget (gtk.ScrolledWindow) | |
4454 """ | |
4455 return self.__widget | |
4456 widget = property(getWidget, None, None, | |
4457 "The main widget (gtk.ScrolledWindow)") | |
4458 | |
4459 | |
4460 class OpenDurusDatabase(object): | |
4461 """gui.OpenFiebdc | |
4462 | |
4463 Description: | |
4464 Class to show a dialog to open a durus price database | |
4465 Constructor: | |
4466 OpenDurusDatabase() | |
4467 Ancestry: | |
4468 +-- object | |
4469 +-- OpenDurusDatabase | |
4470 Atributes: | |
4471 "_openMethod": The method to open the file | |
4472 "__file": the filename to open | |
4473 "__window": the File Selection window | |
4474 Methods: | |
4475 __init__(self) | |
4476 setActiveCode(self, code) | |
4477 """ | |
4478 def __init__(self, openMethod): | |
4479 self.__openMethod = openMethod | |
4480 self.__file = None | |
4481 self.__window = gtk.FileSelection("Abrir Archivo") | |
4482 self.__window.connect("destroy", self.destroy) | |
4483 self.__window.ok_button.connect("clicked", self._openFile) | |
4484 self.__window.cancel_button.connect("clicked", | |
4485 lambda w: self.__window.destroy()) | |
4486 self.__window.set_filename(globals.getHomePath("DURUS-DATABASE")) | |
4487 self.__window.show() | |
4488 | |
4489 def destroy(self, widget): | |
4490 gtk.main_quit() | |
4491 | |
4492 def main(self): | |
4493 gtk.main() | |
4494 | |
4495 def _openFile(self, w): | |
4496 self.__file = self.__window.get_filename() | |
4497 _filename = os.path.basename(self.__file) | |
4498 _filename_list = _filename.split(".") | |
4499 _filename_ext = _filename_list[-1] | |
4500 if _filename == "": | |
4501 print _("No file selected") | |
4502 elif len(_filename_list) < 2 or _filename_ext != "durus": | |
4503 print _("The filename must have durus extension") | |
4504 else: | |
4505 try: | |
4506 self.__openMethod(self.__window.get_filename()) | |
4507 self.__window.destroy() | |
4508 except IOError: | |
4509 print utils.mapping("IOError, $1", (self.__file,)) |