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,)) |
