| | 70 | |
| | 71 | ('edit', None, '_Edit', None, 'Edit', None), |
| | 72 | ('add_dataset', gtk.STOCK_ADD, '_Add dataset', |
| | 73 | '<ctrl><alt>plus', 'Add another dataset', self.add_dataset), |
| | 74 | ('remove_dataset', gtk.STOCK_REMOVE, '_Remove dataset', |
| | 75 | '<ctrl><alt>minus', 'Remove the current dataset', |
| | 76 | self.remove_dataset), |
| | 77 | ('edit_dataset', gtk.STOCK_EDIT, '_Edit dataset name', |
| | 78 | '<ctrl><alt>e', 'Edit the name of the current dataset', |
| | 79 | self.edit_dataset), |
| | 80 | ('add_point', gtk.STOCK_ADD, 'Add _point', '<ctrl>plus', |
| | 81 | 'Add another point to the current dataset', self.add_point), |
| | 82 | ('remove_point', gtk.STOCK_REMOVE, 'Remove p_oint', |
| | 83 | '<ctrl>minus', |
| | 84 | 'Remove the current point of the current dataset', |
| | 85 | self.remove_point), |
| | 86 | ('edit_point', gtk.STOCK_EDIT, 'Edit po_int', '<ctrl>e', |
| | 87 | 'Edit the current point of the current dataset', |
| | 88 | self.edit_point), |
| | 89 | |
| 112 | | def _create_datasets_buttons(self): |
| 113 | | hbuttons = gtk.HButtonBox() |
| 114 | | hbuttons.set_layout(gtk.BUTTONBOX_END) |
| 115 | | |
| 116 | | add_button = gtk.Button(stock=gtk.STOCK_ADD) |
| 117 | | add_button.connect('clicked', self.add_dataset) |
| 118 | | hbuttons.pack_start(add_button, False, False) |
| 119 | | add_button.show() |
| 120 | | |
| 121 | | remove_button = gtk.Button(stock=gtk.STOCK_REMOVE) |
| 122 | | hbuttons.pack_start(remove_button, False, False) |
| 123 | | remove_button.show() |
| 124 | | remove_button.set_sensitive(False) |
| 125 | | |
| 126 | | return hbuttons |
| 127 | | |
| | 204 | def _get_current_dataset_tab(self): |
| | 205 | current_tab = self.datasets_notebook.get_current_page() |
| | 206 | if current_tab != -1: |
| | 207 | return self.datasets_notebook.get_nth_page(current_tab) |
| | 208 | |
| | 209 | def _create_dataset(self, name): |
| | 210 | scrolled_window = self._dataset_treeview_creator() |
| | 211 | scrolled_window.show() |
| | 212 | label = gtk.Label(name) |
| | 213 | self.datasets_notebook.append_page(scrolled_window, label) |
| | 214 | |
| | 215 | def _get_datasets(self): |
| | 216 | datasets = [] |
| | 217 | n_pages = self.datasets_notebook.get_n_pages() |
| | 218 | for i in range(n_pages): |
| | 219 | tab = self.datasets_notebook.get_nth_page(i) |
| | 220 | label = self.datasets_notebook.get_tab_label(tab) |
| | 221 | name = label.get_label() |
| | 222 | treeview = tab.get_children()[0] |
| | 223 | model = treeview.get_model() |
| | 224 | points = [(x, y) for x, y in model] |
| | 225 | datasets.append((name, points)) |
| | 226 | return datasets |
| | 227 | |
| | 237 | def drawing_area_expose_event(self, widget, event, data=None): |
| | 238 | if self.surface is None: |
| | 239 | return |
| | 240 | |
| | 241 | cr = widget.window.cairo_create() |
| | 242 | cr.rectangle(event.area.x, event.area.y, |
| | 243 | event.area.width, event.area.height) |
| | 244 | cr.clip() |
| | 245 | cr.set_source_surface(self.surface, 0, 0) |
| | 246 | cr.paint() |
| | 247 | |
| | 248 | def drawing_area_size_allocate_event(self, widget, event, data=None): |
| | 249 | if self.surface is not None: |
| | 250 | self.refresh() |
| | 251 | |
| 203 | | def refresh(self, action): |
| 204 | | pass |
| | 265 | def remove_dataset(self, action): |
| | 266 | current_tab = self.datasets_notebook.get_current_page() |
| | 267 | assert current_tab != -1 |
| | 268 | |
| | 269 | self.datasets_notebook.remove_page(current_tab) |
| | 270 | |
| | 271 | def edit_dataset(self, action): |
| | 272 | tab = self._get_current_dataset_tab() |
| | 273 | assert tab is not None |
| | 274 | |
| | 275 | label = self.datasets_notebook.get_tab_label(tab) |
| | 276 | name = label.get_label() |
| | 277 | dialog = TextInputDialog(self.main_window, name) |
| | 278 | response = dialog.run() |
| | 279 | if response == gtk.RESPONSE_ACCEPT: |
| | 280 | name = dialog.get_name() |
| | 281 | label.set_label(name) |
| | 282 | dialog.destroy() |
| | 283 | |
| | 284 | def add_point(self, action): |
| | 285 | tab = self._get_current_dataset_tab() |
| | 286 | assert tab is not None |
| | 287 | |
| | 288 | treeview = tab.get_children()[0] |
| | 289 | model = treeview.get_model() |
| | 290 | |
| | 291 | dialog = PointDialog(self.main_window, len(model) * 1.0, 0.0) |
| | 292 | response = dialog.run() |
| | 293 | if response == gtk.RESPONSE_ACCEPT: |
| | 294 | x, y = dialog.get_point() |
| | 295 | model.append((x, y)) |
| | 296 | self.refresh() |
| | 297 | dialog.destroy() |
| | 298 | |
| | 299 | def remove_point(self, action): |
| | 300 | tab = self._get_current_dataset_tab() |
| | 301 | assert tab is not None |
| | 302 | |
| | 303 | treeview = tab.get_children()[0] |
| | 304 | selection = treeview.get_selection() |
| | 305 | model, selected = selection.get_selected() |
| | 306 | if selected is None: |
| | 307 | warning(self.main_window, "You must select the point to remove") |
| | 308 | return |
| | 309 | |
| | 310 | model.remove(selected) |
| | 311 | self.refresh() |
| | 312 | |
| | 313 | def edit_point(self, action): |
| | 314 | tab = self._get_current_dataset_tab() |
| | 315 | assert tab is not None |
| | 316 | |
| | 317 | treeview = tab.get_children()[0] |
| | 318 | selection = treeview.get_selection() |
| | 319 | model, selected = selection.get_selected() |
| | 320 | if selected is None: |
| | 321 | warning(self.main_window, "You must select the point to edit") |
| | 322 | return |
| | 323 | |
| | 324 | x, y = model.get(selected, 0, 1) |
| | 325 | |
| | 326 | dialog = PointDialog(self.main_window, x, y) |
| | 327 | response = dialog.run() |
| | 328 | if response == gtk.RESPONSE_ACCEPT: |
| | 329 | x, y = dialog.get_point() |
| | 330 | model.set(selected, 0, x, 1, y) |
| | 331 | self.refresh() |
| | 332 | dialog.destroy() |
| | 333 | |
| | 334 | def refresh(self, action=None): |
| | 335 | datasets = self._get_datasets() |
| | 336 | # options = self._get_options() |
| | 337 | |
| | 338 | alloc = self.drawing_area.get_allocation() |
| | 339 | self.surface = self.app.get_chart(datasets, None, |
| | 340 | alloc.width, alloc.height) |
| | 341 | self.drawing_area.queue_draw() |
| | 342 | |
| | 343 | |
| | 374 | |
| | 375 | |
| | 376 | class PointDialog(gtk.Dialog): |
| | 377 | def __init__(self, toplevel_window, initial_x, initial_y): |
| | 378 | flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT |
| | 379 | buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, |
| | 380 | gtk.STOCK_OK, gtk.RESPONSE_ACCEPT) |
| | 381 | super(PointDialog, self).__init__(u'Enter a name for the dataset', |
| | 382 | toplevel_window, flags, buttons) |
| | 383 | |
| | 384 | initials = {u'x': str(initial_x), u'y': str(initial_y)} |
| | 385 | self.entries = {} |
| | 386 | for coordinate in (u'x', u'y'): |
| | 387 | hbox = gtk.HBox(spacing=6) |
| | 388 | hbox.set_border_width(12) |
| | 389 | |
| | 390 | label = gtk.Label(coordinate) |
| | 391 | hbox.pack_start(label, False, False) |
| | 392 | |
| | 393 | entry = gtk.Entry() |
| | 394 | entry.set_activates_default(True) |
| | 395 | entry.set_text(initials[coordinate]) |
| | 396 | hbox.pack_start(entry, True, True) |
| | 397 | |
| | 398 | self.entries[coordinate] = entry |
| | 399 | |
| | 400 | self.vbox.pack_start(hbox, False, False) |
| | 401 | |
| | 402 | self.vbox.show_all() |
| | 403 | |
| | 404 | self.set_default_response(gtk.RESPONSE_ACCEPT) |
| | 405 | |
| | 406 | def get_point(self): |
| | 407 | return (float(self.entries[u'x'].get_text()), |
| | 408 | float(self.entries[u'y'].get_text())) |
| | 409 | |
| | 410 | |
| | 411 | def warning(window, msg): |
| | 412 | dialog = gtk.MessageDialog(window, |
| | 413 | gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, |
| | 414 | gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, msg) |
| | 415 | dialog.run() |
| | 416 | dialog.destroy() |