- Timestamp:
- 10/02/08 05:02:59 (4 years ago)
- Location:
- trunk/chavier
- Files:
-
- 1 added
- 2 modified
-
app.py (modified) (2 diffs)
-
dialogs.py (added)
-
gui.py (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/chavier/app.py
r107 r108 1 # Copyright (c) 2007-2008 by Lorenzo Gil Sanchez <lorenzo.gil.sanchez@gmail.com> 2 # 3 # This file is part of Chavier. 4 # 5 # Chavier is free software: you can redistribute it and/or modify 6 # it under the terms of the GNU Lesser General Public License as published by 7 # the Free Software Foundation, either version 3 of the License, or 8 # (at your option) any later version. 9 # 10 # Chavier is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU Lesser General Public License for more details. 14 # 15 # You should have received a copy of the GNU Lesser General Public License 16 # along with Chavier. If not, see <http://www.gnu.org/licenses/>. 17 1 18 import cairo 2 19 … … 107 124 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) 108 125 chart_factory = self.CHART_TYPES[chart_type] 109 chart = chart_factory(surface, DEFAULT_OPTIONS)126 chart = chart_factory(surface, options) 110 127 chart.addDataset(datasets) 111 128 chart.render() -
trunk/chavier/gui.py
r107 r108 1 # Copyright (c) 2007-2008 by Lorenzo Gil Sanchez <lorenzo.gil.sanchez@gmail.com> 2 # 3 # This file is part of Chavier. 4 # 5 # Chavier is free software: you can redistribute it and/or modify 6 # it under the terms of the GNU Lesser General Public License as published by 7 # the Free Software Foundation, either version 3 of the License, or 8 # (at your option) any later version. 9 # 10 # Chavier is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU Lesser General Public License for more details. 14 # 15 # You should have received a copy of the GNU Lesser General Public License 16 # along with Chavier. If not, see <http://www.gnu.org/licenses/>. 17 1 18 import pygtk 2 19 pygtk.require('2.0') 3 20 import gtk 21 22 from chavier.dialogs import ( 23 TextInputDialog, PointDialog, OptionDialog, RandomGeneratorDialog, 24 AboutDialog, 25 ) 4 26 5 27 class GUI(object): … … 96 118 ('refresh', gtk.STOCK_REFRESH, None, '<ctrl>r', 97 119 'Update the chart', self.refresh), 120 121 ('tools', None, '_Tools', None, 'Tools', None), 122 ('random-points', gtk.STOCK_EXECUTE, '_Generate random points', 123 '<ctrl>g', 'Generate random points', 124 self.generate_random_points), 125 ('help', None, '_Help', None, 'Help', None), 126 ('about', gtk.STOCK_ABOUT, None, None, 'About this program', 127 self.about), 98 128 ]) 99 129 action_group.add_radio_actions([ … … 136 166 <menuitem action="scatter"/> 137 167 </menu> 168 <menu action="tools"> 169 <menuitem action="random-points"/> 170 </menu> 171 <menu action="help"> 172 <menuitem action="about"/> 173 </menu> 138 174 </menubar> 139 175 <toolbar name="ToolBar"> … … 187 223 treeview.append_column(column2) 188 224 225 treeview.connect('row-activated', self.dataset_treeview_row_activated) 226 189 227 scrolled_window = gtk.ScrolledWindow() 190 228 scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) … … 209 247 self.options_treeview.expand_all() 210 248 249 self.options_treeview.connect('row-activated', 250 self.options_treeview_row_activated) 251 211 252 scrolled_window = gtk.ScrolledWindow() 212 253 scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) … … 220 261 value_type = types[name] 221 262 if isinstance(value, dict): 222 current_parent = self.options_store.append(parent_node, (name, None, None)) 263 current_parent = self.options_store.append(parent_node, 264 (name, None, None)) 223 265 self._fill_options_store(value, current_parent, value_type) 224 266 225 267 else: 226 print value_type227 268 if value is not None: 228 269 value = str(value) … … 261 302 def _get_options(self, iter): 262 303 options = {} 263 first_child = self.options_store.iter_children(iter)264 if first_child is not None:265 name = self.options_store.get_value(iter, 0)266 options[name] = self._get_options(first_child)267 268 iter = self.options_store.iter_next(iter)269 304 while iter is not None: 270 name = self.options_store.get_value(iter, 0) 271 options[name] = self._get_options(iter) 305 name, value, value_type = self.options_store.get(iter, 0, 1, 2) 306 if value_type is None: 307 child = self.options_store.iter_children(iter) 308 options[name] = self._get_options(child) 309 else: 310 if value is not None: 311 converter = str_converters[value_type] 312 value = converter(value) 313 options[name] = value 314 272 315 iter = self.options_store.iter_next(iter) 273 316 274 317 return options 318 319 def _edit_point_internal(self, model, iter): 320 x, y = model.get(iter, 0, 1) 321 322 dialog = PointDialog(self.main_window, x, y) 323 response = dialog.run() 324 if response == gtk.RESPONSE_ACCEPT: 325 x, y = dialog.get_point() 326 model.set(iter, 0, x, 1, y) 327 self.refresh() 328 dialog.destroy() 329 330 def _edit_option_internal(self, model, iter): 331 name, value, value_type = model.get(iter, 0, 1, 2) 332 parents = [] 333 parent = model.iter_parent(iter) 334 while parent is not None: 335 parents.append(model.get_value(parent, 0)) 336 parent = model.iter_parent(parent) 337 parents.reverse() 338 parents.append(name) 339 label = u'.'.join(parents) 340 341 dialog = OptionDialog(self.main_window, label, value, value_type) 342 response = dialog.run() 343 if response == gtk.RESPONSE_ACCEPT: 344 new_value = dialog.get_value() 345 if new_value == "": 346 new_value = None 347 model.set_value(iter, 1, new_value) 348 self.refresh() 349 dialog.destroy() 275 350 276 351 # Event and signal handlers … … 299 374 if self.surface is not None: 300 375 self.refresh() 376 377 def dataset_treeview_row_activated(self, treeview, path, view_column): 378 model = treeview.get_model() 379 iter = model.get_iter(path) 380 self._edit_point_internal(model, iter) 381 382 def options_treeview_row_activated(self, treeview, path, view_column): 383 model = treeview.get_model() 384 iter = model.get_iter(path) 385 self._edit_option_internal(model, iter) 301 386 302 387 # Action handlers … … 374 459 return 375 460 376 x, y = model.get(selected, 0, 1) 377 378 dialog = PointDialog(self.main_window, x, y) 379 response = dialog.run() 380 if response == gtk.RESPONSE_ACCEPT: 381 x, y = dialog.get_point() 382 model.set(selected, 0, x, 1, y) 383 self.refresh() 384 dialog.destroy() 461 self._edit_point_internal(model, selected) 385 462 386 463 def edit_option(self, action): … … 391 468 return 392 469 393 name, value, value_type = model.get(selected, 0, 1, 2) 394 parents = [] 395 parent = model.iter_parent(selected) 396 while parent is not None: 397 parents.append(model.get_value(parent, 0)) 398 parent = model.iter_parent(parent) 399 parents.reverse() 400 parents.append(name) 401 label = u'.'.join(parents) 402 403 dialog = OptionDialog(self.main_window, label, value, value_type) 404 response = dialog.run() 405 if response == gtk.RESPONSE_ACCEPT: 406 new_value = dialog.get_value() 407 model.set_value(selected, 1, new_value) 408 self.refresh() 409 dialog.destroy() 470 self._edit_option_internal(model, selected) 410 471 411 472 def refresh(self, action=None): … … 417 478 chart_type = self._get_chart_type() 418 479 alloc = self.drawing_area.get_allocation() 419 self.surface = self.app.get_chart(datasets, None, chart_type,480 self.surface = self.app.get_chart(datasets, options, chart_type, 420 481 alloc.width, alloc.height) 421 482 self.drawing_area.queue_draw() … … 423 484 self.surface = None 424 485 486 def generate_random_points(self, action=None): 487 tab = self._get_current_dataset_tab() 488 assert tab is not None 489 490 treeview = tab.get_children()[0] 491 model = treeview.get_model() 492 493 dialog = RandomGeneratorDialog(self.main_window) 494 response = dialog.run() 495 if response == gtk.RESPONSE_ACCEPT: 496 points = dialog.generate_points() 497 for point in points: 498 model.append(point) 499 self.refresh() 500 dialog.destroy() 501 502 def about(self, action=None): 503 dialog = AboutDialog(self.main_window) 504 dialog.run() 505 dialog.destroy() 506 425 507 # Public API 426 508 def run(self): 427 509 gtk.main() 428 510 429 class TextInputDialog(gtk.Dialog): 430 431 def __init__(self, toplevel_window, suggested_name): 432 flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT 433 buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, 434 gtk.STOCK_OK, gtk.RESPONSE_ACCEPT) 435 super(TextInputDialog, self).__init__(u'Enter a name for the dataset', 436 toplevel_window, flags, buttons) 437 self.set_default_size(300, -1) 438 439 hbox = gtk.HBox(spacing=6) 440 hbox.set_border_width(12) 441 442 label = gtk.Label(u'Name') 443 hbox.pack_start(label, False, False) 444 445 self.entry = gtk.Entry() 446 self.entry.set_text(suggested_name) 447 self.entry.set_activates_default(True) 448 hbox.pack_start(self.entry, True, True) 449 450 self.vbox.pack_start(hbox, False, False) 451 452 self.vbox.show_all() 453 454 self.set_default_response(gtk.RESPONSE_ACCEPT) 455 456 def get_name(self): 457 return self.entry.get_text() 458 459 460 class PointDialog(gtk.Dialog): 461 def __init__(self, toplevel_window, initial_x, initial_y): 462 flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT 463 buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, 464 gtk.STOCK_OK, gtk.RESPONSE_ACCEPT) 465 super(PointDialog, self).__init__(u'Enter the point values', 466 toplevel_window, flags, buttons) 467 468 initials = {u'x': str(initial_x), u'y': str(initial_y)} 469 self.entries = {} 470 for coordinate in (u'x', u'y'): 471 hbox = gtk.HBox(spacing=6) 472 hbox.set_border_width(12) 473 474 label = gtk.Label(coordinate) 475 hbox.pack_start(label, False, False) 476 477 entry = gtk.Entry() 478 entry.set_activates_default(True) 479 entry.set_text(initials[coordinate]) 480 hbox.pack_start(entry, True, True) 481 482 self.entries[coordinate] = entry 483 484 self.vbox.pack_start(hbox, False, False) 485 486 self.vbox.show_all() 487 488 self.set_default_response(gtk.RESPONSE_ACCEPT) 489 490 def get_point(self): 491 return (float(self.entries[u'x'].get_text()), 492 float(self.entries[u'y'].get_text())) 493 494 495 class OptionDialog(gtk.Dialog): 496 def __init__(self, toplevel_window, label, value, value_type): 497 flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT 498 buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, 499 gtk.STOCK_OK, gtk.RESPONSE_ACCEPT) 500 super(OptionDialog, self).__init__(u'Enter the option value', 501 toplevel_window, flags, buttons) 502 503 504 hbox = gtk.HBox(spacing=6) 505 hbox.set_border_width(12) 506 507 label = gtk.Label(label) 508 hbox.pack_start(label, False, False) 509 510 self.entry = gtk.Entry() 511 self.entry.set_text(value) 512 self.entry.set_activates_default(True) 513 hbox.pack_start(self.entry, True, True) 514 515 self.vbox.pack_start(hbox, False, False) 516 517 self.vbox.show_all() 518 519 self.set_default_response(gtk.RESPONSE_ACCEPT) 520 521 def get_value(self): 522 return self.entry.get_text() 523 524 525 def warning(window, msg): 526 dialog = gtk.MessageDialog(window, 527 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, 528 gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, msg) 529 dialog.run() 530 dialog.destroy() 511 512 def str2bool(str): 513 if str.lower() == "true": 514 return True 515 else: 516 return False 517 518 str_converters = { 519 str: str, 520 int: int, 521 float: float, 522 unicode: unicode, 523 bool: str2bool, 524 }
