| 1 |
""" |
|---|
| 2 |
The main application window. |
|---|
| 3 |
""" |
|---|
| 4 |
|
|---|
| 5 |
import gobject, gtk |
|---|
| 6 |
|
|---|
| 7 |
from zope import interface, component |
|---|
| 8 |
from gaphor.interfaces import IActionProvider |
|---|
| 9 |
from interfaces import IUIComponent |
|---|
| 10 |
|
|---|
| 11 |
from gaphor import UML |
|---|
| 12 |
from gaphor.core import _, inject, action, radio_action, build_action_group, transactional |
|---|
| 13 |
from namespace import NamespaceModel, NamespaceView |
|---|
| 14 |
from diagramtab import DiagramTab |
|---|
| 15 |
from toolbox import Toolbox |
|---|
| 16 |
from diagramtoolbox import TOOLBOX_ACTIONS |
|---|
| 17 |
from propertyeditor import PropertyEditor |
|---|
| 18 |
from toplevelwindow import ToplevelWindow |
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
from interfaces import IDiagramSelectionChange |
|---|
| 22 |
from gaphor.interfaces import IServiceEvent, IActionExecutedEvent |
|---|
| 23 |
from event import DiagramSelectionChange |
|---|
| 24 |
from gaphor.application import Application |
|---|
| 25 |
from gaphor.services.filemanager import FileManagerStateChanged |
|---|
| 26 |
|
|---|
| 27 |
class MainWindow(ToplevelWindow): |
|---|
| 28 |
""" |
|---|
| 29 |
The main window for the application. |
|---|
| 30 |
It contains a Namespace-based tree view and a menu and a statusbar. |
|---|
| 31 |
""" |
|---|
| 32 |
interface.implements(IActionProvider) |
|---|
| 33 |
|
|---|
| 34 |
properties = inject('properties') |
|---|
| 35 |
element_factory = inject('element_factory') |
|---|
| 36 |
action_manager = inject('action_manager') |
|---|
| 37 |
file_manager = inject('file_manager') |
|---|
| 38 |
|
|---|
| 39 |
title = 'Gaphor' |
|---|
| 40 |
size = property(lambda s: s.properties.get('ui.window-size', (760, 580))) |
|---|
| 41 |
menubar_path = '/mainwindow' |
|---|
| 42 |
toolbar_path = '/mainwindow-toolbar' |
|---|
| 43 |
|
|---|
| 44 |
menu_xml = """ |
|---|
| 45 |
<ui> |
|---|
| 46 |
<menubar name="mainwindow"> |
|---|
| 47 |
<menu action="file"> |
|---|
| 48 |
<placeholder name="primary" /> |
|---|
| 49 |
<separator /> |
|---|
| 50 |
<menu action="file-export" /> |
|---|
| 51 |
<menu action="file-import" /> |
|---|
| 52 |
<separator /> |
|---|
| 53 |
<placeholder name="secondary" /> |
|---|
| 54 |
<placeholder name="ternary" /> |
|---|
| 55 |
<separator /> |
|---|
| 56 |
<menuitem action="file-quit" /> |
|---|
| 57 |
</menu> |
|---|
| 58 |
<menu action="edit"> |
|---|
| 59 |
<placeholder name="primary" /> |
|---|
| 60 |
<placeholder name="secondary" /> |
|---|
| 61 |
<placeholder name="ternary" /> |
|---|
| 62 |
</menu> |
|---|
| 63 |
<menu action="diagram"> |
|---|
| 64 |
<menuitem action="tree-view-create-diagram" /> |
|---|
| 65 |
<menuitem action="tree-view-create-package" /> |
|---|
| 66 |
<separator /> |
|---|
| 67 |
<menuitem action="tree-view-delete-diagram" /> |
|---|
| 68 |
<menuitem action="tree-view-delete-package" /> |
|---|
| 69 |
<separator /> |
|---|
| 70 |
<placeholder name="primary" /> |
|---|
| 71 |
<placeholder name="secondary" /> |
|---|
| 72 |
<placeholder name="ternary" /> |
|---|
| 73 |
</menu> |
|---|
| 74 |
<menu action="tools"> |
|---|
| 75 |
<placeholder name="primary" /> |
|---|
| 76 |
<placeholder name="secondary" /> |
|---|
| 77 |
<placeholder name="ternary" /> |
|---|
| 78 |
</menu> |
|---|
| 79 |
<menu action="window"> |
|---|
| 80 |
<placeholder name="primary" /> |
|---|
| 81 |
<placeholder name="secondary" /> |
|---|
| 82 |
<placeholder name="ternary" /> |
|---|
| 83 |
</menu> |
|---|
| 84 |
<menu action="help"> |
|---|
| 85 |
<placeholder name="primary" /> |
|---|
| 86 |
<placeholder name="secondary" /> |
|---|
| 87 |
<placeholder name="ternary" /> |
|---|
| 88 |
</menu> |
|---|
| 89 |
</menubar> |
|---|
| 90 |
<toolbar name='mainwindow-toolbar'> |
|---|
| 91 |
</toolbar> |
|---|
| 92 |
<toolbar action="tools"> |
|---|
| 93 |
</toolbar> |
|---|
| 94 |
<popup action="namespace-popup"> |
|---|
| 95 |
<menuitem action="tree-view-open" /> |
|---|
| 96 |
<menuitem action="tree-view-rename" /> |
|---|
| 97 |
<separator /> |
|---|
| 98 |
<menuitem action="tree-view-create-diagram" /> |
|---|
| 99 |
<menuitem action="tree-view-create-package" /> |
|---|
| 100 |
<separator /> |
|---|
| 101 |
<menuitem action="tree-view-delete-diagram" /> |
|---|
| 102 |
<menuitem action="tree-view-delete-package" /> |
|---|
| 103 |
<separator /> |
|---|
| 104 |
<menuitem action="tree-view-refresh" /> |
|---|
| 105 |
</popup> |
|---|
| 106 |
</ui> |
|---|
| 107 |
""" |
|---|
| 108 |
|
|---|
| 109 |
def __init__(self): |
|---|
| 110 |
ToplevelWindow.__init__(self) |
|---|
| 111 |
|
|---|
| 112 |
self.notebook_map = {} |
|---|
| 113 |
|
|---|
| 114 |
self._tree_view = None |
|---|
| 115 |
|
|---|
| 116 |
self.action_group = build_action_group(self) |
|---|
| 117 |
for name, label in (('file', '_File'), |
|---|
| 118 |
('file-export', '_Export'), |
|---|
| 119 |
('file-import', '_Import'), |
|---|
| 120 |
('edit', '_Edit'), |
|---|
| 121 |
('diagram', '_Diagram'), |
|---|
| 122 |
('tools', '_Tools'), |
|---|
| 123 |
('window', '_Window'), |
|---|
| 124 |
('help', '_Help')): |
|---|
| 125 |
a = gtk.Action(name, label, None, None) |
|---|
| 126 |
a.set_property('hide-if-empty', False) |
|---|
| 127 |
self.action_group.add_action(a) |
|---|
| 128 |
self._tab_ui_settings = None |
|---|
| 129 |
|
|---|
| 130 |
tree_model = property(lambda s: s.tree_view.get_model()) |
|---|
| 131 |
|
|---|
| 132 |
tree_view = property(lambda s: s._tree_view) |
|---|
| 133 |
|
|---|
| 134 |
def get_filename(self): |
|---|
| 135 |
""" |
|---|
| 136 |
Return the file name of the currently opened model. |
|---|
| 137 |
""" |
|---|
| 138 |
return self.file_manager.filename |
|---|
| 139 |
|
|---|
| 140 |
def get_current_diagram_tab(self): |
|---|
| 141 |
""" |
|---|
| 142 |
Get the currently opened and viewed DiagramTab, shown on the right |
|---|
| 143 |
side of the main window. |
|---|
| 144 |
See also: get_current_diagram(), get_current_diagram_view(). |
|---|
| 145 |
""" |
|---|
| 146 |
return self.get_current_tab() |
|---|
| 147 |
|
|---|
| 148 |
def get_current_diagram(self): |
|---|
| 149 |
""" |
|---|
| 150 |
Return the Diagram associated with the viewed DiagramTab. |
|---|
| 151 |
See also: get_current_diagram_tab(), get_current_diagram_view(). |
|---|
| 152 |
""" |
|---|
| 153 |
tab = self.get_current_diagram_tab() |
|---|
| 154 |
return tab and tab.get_diagram() |
|---|
| 155 |
|
|---|
| 156 |
def get_current_diagram_view(self): |
|---|
| 157 |
""" |
|---|
| 158 |
Return the DiagramView associated with the viewed DiagramTab. |
|---|
| 159 |
See also: get_current_diagram_tab(), get_current_diagram(). |
|---|
| 160 |
""" |
|---|
| 161 |
tab = self.get_current_diagram_tab() |
|---|
| 162 |
return tab and tab.get_view() |
|---|
| 163 |
|
|---|
| 164 |
def ask_to_close(self): |
|---|
| 165 |
""" |
|---|
| 166 |
Ask user to close window. |
|---|
| 167 |
""" |
|---|
| 168 |
dialog = gtk.MessageDialog(self.window, |
|---|
| 169 |
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, |
|---|
| 170 |
gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, |
|---|
| 171 |
_("Quit Gaphor?")) |
|---|
| 172 |
answer = dialog.run() |
|---|
| 173 |
dialog.destroy() |
|---|
| 174 |
return answer == gtk.RESPONSE_YES |
|---|
| 175 |
|
|---|
| 176 |
def show_diagram(self, diagram): |
|---|
| 177 |
""" |
|---|
| 178 |
Show a Diagram element in a new tab. |
|---|
| 179 |
If a tab is already open, show that one instead. |
|---|
| 180 |
""" |
|---|
| 181 |
|
|---|
| 182 |
for tab in self.get_tabs(): |
|---|
| 183 |
if tab.get_diagram() is diagram: |
|---|
| 184 |
self.set_current_page(tab) |
|---|
| 185 |
return tab |
|---|
| 186 |
|
|---|
| 187 |
tab = DiagramTab(self) |
|---|
| 188 |
tab.set_diagram(diagram) |
|---|
| 189 |
widget = tab.construct() |
|---|
| 190 |
self.add_tab(tab, widget, tab.title) |
|---|
| 191 |
self.set_current_page(tab) |
|---|
| 192 |
|
|---|
| 193 |
return tab |
|---|
| 194 |
|
|---|
| 195 |
def ui_component(self): |
|---|
| 196 |
""" |
|---|
| 197 |
Create the widgets that make up the main window. |
|---|
| 198 |
""" |
|---|
| 199 |
model = NamespaceModel(self.element_factory) |
|---|
| 200 |
view = NamespaceView(model, self.element_factory) |
|---|
| 201 |
scrolled_window = gtk.ScrolledWindow() |
|---|
| 202 |
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) |
|---|
| 203 |
scrolled_window.set_shadow_type(gtk.SHADOW_IN) |
|---|
| 204 |
scrolled_window.add(view) |
|---|
| 205 |
view.show() |
|---|
| 206 |
|
|---|
| 207 |
view.connect_after('event-after', self._on_view_event) |
|---|
| 208 |
view.connect('row-activated', self._on_view_row_activated) |
|---|
| 209 |
view.connect_after('cursor-changed', self._on_view_cursor_changed) |
|---|
| 210 |
|
|---|
| 211 |
vbox = gtk.VBox() |
|---|
| 212 |
vbox.pack_start(scrolled_window, expand=True) |
|---|
| 213 |
scrolled_window.show() |
|---|
| 214 |
|
|---|
| 215 |
paned = gtk.HPaned() |
|---|
| 216 |
paned.set_property('position', 160) |
|---|
| 217 |
paned.pack1(vbox) |
|---|
| 218 |
vbox.show() |
|---|
| 219 |
|
|---|
| 220 |
notebook = gtk.Notebook() |
|---|
| 221 |
notebook.set_scrollable(True) |
|---|
| 222 |
notebook.set_show_border(False) |
|---|
| 223 |
|
|---|
| 224 |
notebook.connect_after('switch-page', self._on_notebook_switch_page) |
|---|
| 225 |
notebook.connect_after('page-removed', self._on_notebook_page_removed) |
|---|
| 226 |
|
|---|
| 227 |
self.property_editor = PropertyEditor() |
|---|
| 228 |
pe_notebook = self.property_editor.construct() |
|---|
| 229 |
pe_notebook.set_size_request(-1, 50) |
|---|
| 230 |
|
|---|
| 231 |
second_paned = gtk.VPaned() |
|---|
| 232 |
second_paned.set_property('position', |
|---|
| 233 |
int(self.properties.get('ui.property-editor-position', 600))) |
|---|
| 234 |
second_paned.pack1(notebook) |
|---|
| 235 |
notebook.show() |
|---|
| 236 |
second_paned.pack2(pe_notebook) |
|---|
| 237 |
pe_notebook.show() |
|---|
| 238 |
|
|---|
| 239 |
paned.pack2(second_paned) |
|---|
| 240 |
second_paned.show() |
|---|
| 241 |
paned.show() |
|---|
| 242 |
|
|---|
| 243 |
second_paned.connect('notify::position', |
|---|
| 244 |
self._on_property_editor_notify_position) |
|---|
| 245 |
|
|---|
| 246 |
self.notebook = notebook |
|---|
| 247 |
self._tree_view = view |
|---|
| 248 |
|
|---|
| 249 |
vbox.set_border_width(3) |
|---|
| 250 |
|
|---|
| 251 |
toolbox = Toolbox(TOOLBOX_ACTIONS) |
|---|
| 252 |
vbox.pack_start(toolbox, expand=False) |
|---|
| 253 |
toolbox.show() |
|---|
| 254 |
|
|---|
| 255 |
self._toolbox = toolbox |
|---|
| 256 |
|
|---|
| 257 |
return paned |
|---|
| 258 |
|
|---|
| 259 |
def construct(self): |
|---|
| 260 |
super(MainWindow, self).construct() |
|---|
| 261 |
|
|---|
| 262 |
self.window.connect('delete-event', self._on_window_delete) |
|---|
| 263 |
|
|---|
| 264 |
|
|---|
| 265 |
self.window.set_property('allow-shrink', True) |
|---|
| 266 |
self.window.connect('size-allocate', self._on_window_size_allocate) |
|---|
| 267 |
self.window.connect('destroy', self._on_window_destroy) |
|---|
| 268 |
|
|---|
| 269 |
Application.register_handler(self._action_executed) |
|---|
| 270 |
|
|---|
| 271 |
def _update_toolbox(self, action_group): |
|---|
| 272 |
""" |
|---|
| 273 |
Update the buttons in the toolbox. Each button should be connected |
|---|
| 274 |
by an action. Each button is assigned a special _action_name_ |
|---|
| 275 |
attribute that can be used to fetch the action from the ui manager. |
|---|
| 276 |
""" |
|---|
| 277 |
for button in self._toolbox.buttons: |
|---|
| 278 |
|
|---|
| 279 |
action_name = button.action_name |
|---|
| 280 |
action = action_group.get_action(action_name) |
|---|
| 281 |
if action: |
|---|
| 282 |
action.connect_proxy(button) |
|---|
| 283 |
|
|---|
| 284 |
|
|---|
| 285 |
|
|---|
| 286 |
def add_tab(self, tab_id, contents, label): |
|---|
| 287 |
""" |
|---|
| 288 |
Create a new tab on the notebook with window as its contents. |
|---|
| 289 |
Returns: The page number of the tab. |
|---|
| 290 |
""" |
|---|
| 291 |
self.notebook_map[contents] = tab_id |
|---|
| 292 |
|
|---|
| 293 |
l = gtk.Label(label) |
|---|
| 294 |
|
|---|
| 295 |
self.notebook.append_page(contents, l) |
|---|
| 296 |
page_num = self.notebook.page_num(contents) |
|---|
| 297 |
|
|---|
| 298 |
return page_num |
|---|
| 299 |
|
|---|
| 300 |
def get_current_tab(self): |
|---|
| 301 |
""" |
|---|
| 302 |
Return the window (DiagramTab) that is currently visible on the |
|---|
| 303 |
notebook. |
|---|
| 304 |
""" |
|---|
| 305 |
current = self.notebook.get_current_page() |
|---|
| 306 |
content = self.notebook.get_nth_page(current) |
|---|
| 307 |
return self.notebook_map.get(content) |
|---|
| 308 |
|
|---|
| 309 |
def set_current_page(self, tab): |
|---|
| 310 |
""" |
|---|
| 311 |
Force a specific tab (DiagramTab) to the foreground. |
|---|
| 312 |
""" |
|---|
| 313 |
for p, t in self.notebook_map.iteritems(): |
|---|
| 314 |
if tab is t: |
|---|
| 315 |
num = self.notebook.page_num(p) |
|---|
| 316 |
self.notebook.set_current_page(num) |
|---|
| 317 |
return |
|---|
| 318 |
|
|---|
| 319 |
def set_tab_label(self, tab, label): |
|---|
| 320 |
for p, t in self.notebook_map.iteritems(): |
|---|
| 321 |
if tab is t: |
|---|
| 322 |
l = gtk.Label(label) |
|---|
| 323 |
l.show() |
|---|
| 324 |
self.notebook.set_tab_label(p, l) |
|---|
| 325 |
|
|---|
| 326 |
def get_tabs(self): |
|---|
| 327 |
return self.notebook_map.values() |
|---|
| 328 |
|
|---|
| 329 |
def remove_tab(self, tab): |
|---|
| 330 |
""" |
|---|
| 331 |
Remove the tab from the notebook. Tab is such a thing as |
|---|
| 332 |
a DiagramTab. |
|---|
| 333 |
""" |
|---|
| 334 |
for p, t in self.notebook_map.iteritems(): |
|---|
| 335 |
if tab is t: |
|---|
| 336 |
num = self.notebook.page_num(p) |
|---|
| 337 |
self.notebook.remove_page(num) |
|---|
| 338 |
del self.notebook_map[p] |
|---|
| 339 |
return |
|---|
| 340 |
|
|---|
| 341 |
def select_element(self, element): |
|---|
| 342 |
""" |
|---|
| 343 |
Select an element from the Namespace view. |
|---|
| 344 |
The element is selected. After this an action may be executed, |
|---|
| 345 |
such as OpenModelElement, which will try to open the element (if it's |
|---|
| 346 |
a Diagram). |
|---|
| 347 |
""" |
|---|
| 348 |
path = self.tree_model.path_from_element(element) |
|---|
| 349 |
|
|---|
| 350 |
if len(path) > 1: |
|---|
| 351 |
self._tree_view.expand_row(path[:-1], False) |
|---|
| 352 |
selection = self._tree_view.get_selection() |
|---|
| 353 |
selection.select_path(path) |
|---|
| 354 |
self._on_view_cursor_changed(self._tree_view) |
|---|
| 355 |
|
|---|
| 356 |
|
|---|
| 357 |
|
|---|
| 358 |
@component.adapter(FileManagerStateChanged) |
|---|
| 359 |
def _action_executed(self, event): |
|---|
| 360 |
|
|---|
| 361 |
print 'action:', event.service |
|---|
| 362 |
if event.service is self.file_manager: |
|---|
| 363 |
filename = self.file_manager.filename |
|---|
| 364 |
if self.window: |
|---|
| 365 |
if filename: |
|---|
| 366 |
title = '%s - %s' % (self.title, filename) |
|---|
| 367 |
else: |
|---|
| 368 |
title = self.title |
|---|
| 369 |
self.window.set_title(title) |
|---|
| 370 |
|
|---|
| 371 |
|
|---|
| 372 |
def _on_window_destroy(self, window): |
|---|
| 373 |
""" |
|---|
| 374 |
Window is destroyed... Quit the application. |
|---|
| 375 |
""" |
|---|
| 376 |
self._tree_view = None |
|---|
| 377 |
self.window = None |
|---|
| 378 |
if gobject.main_depth() > 0: |
|---|
| 379 |
gtk.main_quit() |
|---|
| 380 |
Application.unregister_handler(self._action_executed) |
|---|
| 381 |
|
|---|
| 382 |
def _on_tab_destroy(self, widget): |
|---|
| 383 |
tab = self.notebook_map[widget] |
|---|
| 384 |
assert isinstance(tab, DiagramTab) |
|---|
| 385 |
self.remove_tab(tab) |
|---|
| 386 |
|
|---|
| 387 |
def _on_window_delete(self, window = None, event = None): |
|---|
| 388 |
return not self.ask_to_close() |
|---|
| 389 |
|
|---|
| 390 |
def _on_view_event(self, view, event): |
|---|
| 391 |
""" |
|---|
| 392 |
Show a popup menu if button3 was pressed on the TreeView. |
|---|
| 393 |
""" |
|---|
| 394 |
|
|---|
| 395 |
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3: |
|---|
| 396 |
menu = self.ui_manager.get_widget('/namespace-popup') |
|---|
| 397 |
menu.popup(None, None, None, event.button, event.time) |
|---|
| 398 |
|
|---|
| 399 |
|
|---|
| 400 |
def _on_view_row_activated(self, view, path, column): |
|---|
| 401 |
""" |
|---|
| 402 |
Double click on an element in the tree view. |
|---|
| 403 |
""" |
|---|
| 404 |
self.action_manager.execute('tree-view-open') |
|---|
| 405 |
|
|---|
| 406 |
def _on_view_cursor_changed(self, view): |
|---|
| 407 |
""" |
|---|
| 408 |
Another row is selected, execute a dummy action. |
|---|
| 409 |
""" |
|---|
| 410 |
element = view.get_selected_element() |
|---|
| 411 |
self.action_group.get_action('tree-view-create-diagram').props.sensitive = isinstance(element, UML.Package) |
|---|
| 412 |
self.action_group.get_action('tree-view-create-package').props.sensitive = isinstance(element, UML.Package) |
|---|
| 413 |
|
|---|
| 414 |
self.action_group.get_action('tree-view-delete-diagram').props.visible = isinstance(element, UML.Diagram) |
|---|
| 415 |
self.action_group.get_action('tree-view-delete-package').props.visible = isinstance(element, UML.Package) and not element.presentation |
|---|
| 416 |
|
|---|
| 417 |
self.action_group.get_action('tree-view-open').props.sensitive = isinstance(element, UML.Diagram) |
|---|
| 418 |
|
|---|
| 419 |
def _insensivate_toolbox(self): |
|---|
| 420 |
for button in self._toolbox.buttons: |
|---|
| 421 |
button.set_property('sensitive', False) |
|---|
| 422 |
|
|---|
| 423 |
def _on_notebook_page_removed(self, notebook, tab, page_num): |
|---|
| 424 |
if self._tab_ui_settings: |
|---|
| 425 |
action_group, ui_id = self._tab_ui_settings |
|---|
| 426 |
self.ui_manager.remove_action_group(action_group) |
|---|
| 427 |
self.ui_manager.remove_ui(ui_id) |
|---|
| 428 |
self._insensivate_toolbox() |
|---|
| 429 |
self._tab_ui_settings = None |
|---|
| 430 |
if notebook.get_current_page() != -1: |
|---|
| 431 |
self._on_notebook_switch_page(notebook, None, notebook.get_current_page()) |
|---|
| 432 |
|
|---|
| 433 |
def _on_notebook_switch_page(self, notebook, tab, page_num): |
|---|
| 434 |
""" |
|---|
| 435 |
Another page (tab) is put on the front of the diagram notebook. |
|---|
| 436 |
A dummy action is executed. |
|---|
| 437 |
""" |
|---|
| 438 |
if self._tab_ui_settings: |
|---|
| 439 |
action_group, ui_id = self._tab_ui_settings |
|---|
| 440 |
self.ui_manager.remove_action_group(action_group) |
|---|
| 441 |
self.ui_manager.remove_ui(ui_id) |
|---|
| 442 |
self._tab_ui_settings = None |
|---|
| 443 |
|
|---|
| 444 |
content = self.notebook.get_nth_page(page_num) |
|---|
| 445 |
tab = self.notebook_map.get(content) |
|---|
| 446 |
assert isinstance(tab, DiagramTab), str(tab) |
|---|
| 447 |
|
|---|
| 448 |
self.ui_manager.insert_action_group(tab.action_group, -1) |
|---|
| 449 |
ui_id = self.ui_manager.add_ui_from_string(tab.menu_xml) |
|---|
| 450 |
self._tab_ui_settings = tab.action_group, ui_id |
|---|
| 451 |
log.debug('Menus updated with %s, %d' % self._tab_ui_settings) |
|---|
| 452 |
self._update_toolbox(tab.toolbox.action_group) |
|---|
| 453 |
|
|---|
| 454 |
|
|---|
| 455 |
component.handle(DiagramSelectionChange(tab.view, tab.view.focused_item, tab.view.selected_items)) |
|---|
| 456 |
|
|---|
| 457 |
def _on_window_size_allocate(self, window, allocation): |
|---|
| 458 |
""" |
|---|
| 459 |
Store the window size in a property. |
|---|
| 460 |
""" |
|---|
| 461 |
self.properties.set('ui.window-size', (allocation.width, allocation.height)) |
|---|
| 462 |
|
|---|
| 463 |
def _on_property_editor_notify_position(self, paned, arg): |
|---|
| 464 |
self.properties.set('ui.property-editor-position', |
|---|
| 465 |
paned.get_position()) |
|---|
| 466 |
|
|---|
| 467 |
|
|---|
| 468 |
|
|---|
| 469 |
@action(name='file-quit', stock_id='gtk-quit') |
|---|
| 470 |
def quit(self): |
|---|
| 471 |
self.ask_to_close() and gtk.main_quit() |
|---|
| 472 |
|
|---|
| 473 |
@action(name='tree-view-open', label='_Open') |
|---|
| 474 |
def tree_view_open_selected(self): |
|---|
| 475 |
element = self._tree_view.get_selected_element() |
|---|
| 476 |
if isinstance(element, UML.Diagram): |
|---|
| 477 |
self.show_diagram(element) |
|---|
| 478 |
else: |
|---|
| 479 |
log.debug('No action defined for element %s' % type(element).__name__) |
|---|
| 480 |
|
|---|
| 481 |
@action(name='tree-view-rename', label=_('Rename')) |
|---|
| 482 |
def tree_view_rename_selected(self): |
|---|
| 483 |
view = self._tree_view |
|---|
| 484 |
element = view.get_selected_element() |
|---|
| 485 |
path = view.get_model().path_from_element(element) |
|---|
| 486 |
column = view.get_column(0) |
|---|
| 487 |
cell = column.get_cell_renderers()[1] |
|---|
| 488 |
cell.set_property('editable', 1) |
|---|
| 489 |
cell.set_property('text', element.name) |
|---|
| 490 |
view.set_cursor(path, column, True) |
|---|
| 491 |
cell.set_property('editable', 0) |
|---|
| 492 |
|
|---|
| 493 |
@action(name='tree-view-create-diagram', label=_('_New diagram'), stock_id='gaphor-diagram') |
|---|
| 494 |
@transactional |
|---|
| 495 |
def |
|---|