Merge lp:~jordy-provost/terminator/custom_commands_submenus into lp:terminator/gtk3
- custom_commands_submenus
- Merge into gtk3
Status: | Needs review |
---|---|
Proposed branch: | lp:~jordy-provost/terminator/custom_commands_submenus |
Merge into: | lp:terminator/gtk3 |
Diff against target: |
896 lines (+436/-394) 1 file modified
terminatorlib/plugins/custom_commands.py (+436/-394) |
To merge this branch: | bzr merge lp:~jordy-provost/terminator/custom_commands_submenus |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexander van Teijlingen (community) | Approve | ||
Jordy PROVOST (community) | Approve | ||
Terminator | Pending | ||
Review via email: mp+351362@code.launchpad.net |
Commit message
- Permit to create submenus in a more graphical way (instead of using '/' in command names)
- Fixes for indentation coherence (first level is 4 spaces, second is 8, third is 12, etc...)
- Clean some trailing spaces, and spaces only lines
Description of the change
Alexander van Teijlingen (a.vant) wrote : | # |
Also tested on Debian [9] Stretch and working
x86_64 & python2
Good feature imo
Bryce Harrington (bryce) wrote : | # |
Unfortunately the whitespace changes make it hard to spot the actual code changes, but conceptually this sounds interesting.
Jordy PROVOST (jordy-provost) wrote : | # |
Ok, since the review is still pending, i suppose that the merge will not be accepted ?
Unfortunately, i will be forced to maintain a confidential/
Unmerged revisions
- 1804. By Jordy PROVOST
-
Add graphical way to create submenus and fixes for identation coherence (4spaces)
Preview Diff
1 | === modified file 'terminatorlib/plugins/custom_commands.py' | |||
2 | --- terminatorlib/plugins/custom_commands.py 2017-02-06 11:09:36 +0000 | |||
3 | +++ terminatorlib/plugins/custom_commands.py 2018-07-26 15:00:50 +0000 | |||
4 | @@ -7,7 +7,7 @@ | |||
5 | 7 | 7 | ||
6 | 8 | # Fix imports when testing this file directly | 8 | # Fix imports when testing this file directly |
7 | 9 | if __name__ == '__main__': | 9 | if __name__ == '__main__': |
9 | 10 | sys.path.append( os.path.join(os.path.dirname(__file__), "../..")) | 10 | sys.path.append( os.path.join(os.path.dirname(__file__), "../..")) |
10 | 11 | 11 | ||
11 | 12 | from gi.repository import Gtk | 12 | from gi.repository import Gtk |
12 | 13 | from gi.repository import GObject | 13 | from gi.repository import GObject |
13 | @@ -16,7 +16,7 @@ | |||
14 | 16 | from terminatorlib.translation import _ | 16 | from terminatorlib.translation import _ |
15 | 17 | from terminatorlib.util import get_config_dir, err, dbg, gerr | 17 | from terminatorlib.util import get_config_dir, err, dbg, gerr |
16 | 18 | 18 | ||
18 | 19 | (CC_COL_ENABLED, CC_COL_NAME, CC_COL_COMMAND) = range(0,3) | 19 | (CC_COL_ENABLED, CC_COL_NAME, CC_COL_COMMAND, CC_COL_CUSTOMSUBMENU) = range(0,4) |
19 | 20 | 20 | ||
20 | 21 | # Every plugin you want Terminator to load *must* be listed in 'AVAILABLE' | 21 | # Every plugin you want Terminator to load *must* be listed in 'AVAILABLE' |
21 | 22 | AVAILABLE = ['CustomCommandsMenu'] | 22 | AVAILABLE = ['CustomCommandsMenu'] |
22 | @@ -28,217 +28,233 @@ | |||
23 | 28 | conf_file = os.path.join(get_config_dir(),"custom_commands") | 28 | conf_file = os.path.join(get_config_dir(),"custom_commands") |
24 | 29 | 29 | ||
25 | 30 | def __init__( self): | 30 | def __init__( self): |
47 | 31 | config = Config() | 31 | config = Config() |
48 | 32 | sections = config.plugin_get_config(self.__class__.__name__) | 32 | sections = config.plugin_get_config(self.__class__.__name__) |
49 | 33 | if not isinstance(sections, dict): | 33 | if not isinstance(sections, dict): |
50 | 34 | return | 34 | return |
51 | 35 | noord_cmds = [] | 35 | noord_cmds = [] |
52 | 36 | for part in sections: | 36 | for part in sections: |
53 | 37 | s = sections[part] | 37 | s = sections[part] |
54 | 38 | if not (s.has_key("name") and s.has_key("command")): | 38 | if not (s.has_key("name") and s.has_key("command")): |
55 | 39 | print "CustomCommandsMenu: Ignoring section %s" % s | 39 | print "CustomCommandsMenu: Ignoring section %s" % s |
56 | 40 | continue | 40 | continue |
57 | 41 | name = s["name"] | 41 | name = s["name"] |
58 | 42 | command = s["command"] | 42 | command = s["command"] |
59 | 43 | enabled = s["enabled"] and s["enabled"] or False | 43 | enabled = s["enabled"] and s["enabled"] or False |
60 | 44 | if s.has_key("position"): | 44 | try: |
61 | 45 | self.cmd_list[int(s["position"])] = {'enabled' : enabled, | 45 | customsubmenu = s["submenu"] |
62 | 46 | 'name' : name, | 46 | except: |
63 | 47 | 'command' : command | 47 | customsubmenu = '' |
64 | 48 | } | 48 | if s.has_key("position"): |
65 | 49 | else: | 49 | self.cmd_list[int(s["position"])] = {'enabled' : enabled, |
45 | 50 | noord_cmds.append( | ||
46 | 51 | {'enabled' : enabled, | ||
66 | 52 | 'name' : name, | 50 | 'name' : name, |
70 | 53 | 'command' : command | 51 | 'command' : command, |
71 | 54 | } | 52 | 'submenu' : customsubmenu |
72 | 55 | ) | 53 | } |
73 | 54 | else: | ||
74 | 55 | noord_cmds.append( | ||
75 | 56 | {'enabled' : enabled, | ||
76 | 57 | 'name' : name, | ||
77 | 58 | 'command' : command, | ||
78 | 59 | 'submenu' : customsubmenu | ||
79 | 60 | } | ||
80 | 61 | ) | ||
81 | 62 | |||
82 | 56 | for cmd in noord_cmds: | 63 | for cmd in noord_cmds: |
83 | 57 | self.cmd_list[len(self.cmd_list)] = cmd | 64 | self.cmd_list[len(self.cmd_list)] = cmd |
84 | 58 | 65 | ||
85 | 66 | |||
86 | 59 | def callback(self, menuitems, menu, terminal): | 67 | def callback(self, menuitems, menu, terminal): |
87 | 60 | """Add our menu items to the menu""" | 68 | """Add our menu items to the menu""" |
88 | 61 | submenus = {} | ||
89 | 62 | item = Gtk.MenuItem.new_with_mnemonic(_('_Custom Commands')) | 69 | item = Gtk.MenuItem.new_with_mnemonic(_('_Custom Commands')) |
90 | 63 | menuitems.append(item) | 70 | menuitems.append(item) |
95 | 64 | 71 | pluginsubmenu = Gtk.Menu() | |
96 | 65 | submenu = Gtk.Menu() | 72 | item.set_submenu(pluginsubmenu) |
93 | 66 | item.set_submenu(submenu) | ||
94 | 67 | |||
97 | 68 | menuitem = Gtk.MenuItem.new_with_mnemonic(_('_Preferences')) | 73 | menuitem = Gtk.MenuItem.new_with_mnemonic(_('_Preferences')) |
98 | 69 | menuitem.connect("activate", self.configure) | 74 | menuitem.connect("activate", self.configure) |
101 | 70 | submenu.append(menuitem) | 75 | pluginsubmenu.append(menuitem) |
100 | 71 | |||
102 | 72 | menuitem = Gtk.SeparatorMenuItem() | 76 | menuitem = Gtk.SeparatorMenuItem() |
104 | 73 | submenu.append(menuitem) | 77 | pluginsubmenu.append(menuitem) |
105 | 78 | try: | ||
106 | 79 | customsubmenus = sorted(set(self.cmd_list[key]['submenu'] for key in sorted(self.cmd_list.keys()))) | ||
107 | 80 | except: | ||
108 | 81 | customsubmenus = [] | ||
109 | 82 | |||
110 | 83 | submenus_dict = {} | ||
111 | 84 | for customsubmenustr in customsubmenus: | ||
112 | 85 | if customsubmenustr != '': | ||
113 | 86 | menuitem = Gtk.MenuItem(_(customsubmenustr)) | ||
114 | 87 | pluginsubmenu.append(menuitem) | ||
115 | 88 | customsubmenu = Gtk.Menu() | ||
116 | 89 | menuitem.set_submenu(customsubmenu) | ||
117 | 90 | submenus_dict[customsubmenustr] = customsubmenu | ||
118 | 74 | 91 | ||
119 | 75 | theme = Gtk.IconTheme.get_default() | 92 | theme = Gtk.IconTheme.get_default() |
120 | 93 | |||
121 | 76 | for command in [ self.cmd_list[key] for key in sorted(self.cmd_list.keys()) ] : | 94 | for command in [ self.cmd_list[key] for key in sorted(self.cmd_list.keys()) ] : |
151 | 77 | if not command['enabled']: | 95 | if not command['enabled']: |
152 | 78 | continue | 96 | continue |
153 | 79 | exe = command['command'].split(' ')[0] | 97 | exe = command['command'].split(' ')[0] |
154 | 80 | iconinfo = theme.choose_icon([exe], Gtk.IconSize.MENU, Gtk.IconLookupFlags.USE_BUILTIN) | 98 | iconinfo = theme.choose_icon([exe], Gtk.IconSize.MENU, Gtk.IconLookupFlags.USE_BUILTIN) |
155 | 81 | leaf_name = command['name'].split('/')[-1] | 99 | if iconinfo: |
156 | 82 | branch_names = command['name'].split('/')[:-1] | 100 | image = Gtk.Image() |
157 | 83 | target_submenu = submenu | 101 | image.set_from_icon_name(exe, Gtk.IconSize.MENU) |
158 | 84 | parent_submenu = submenu | 102 | menuitem = Gtk.ImageMenuItem(command['name']) |
159 | 85 | for idx in range(len(branch_names)): | 103 | menuitem.set_image(image) |
160 | 86 | lookup_name = '/'.join(branch_names[0:idx+1]) | 104 | else: |
161 | 87 | target_submenu = submenus.get(lookup_name, None) | 105 | menuitem = Gtk.MenuItem(command["name"]) |
162 | 88 | if not target_submenu: | 106 | terminals = terminal.terminator.get_target_terms(terminal) |
163 | 89 | item = Gtk.MenuItem(_(branch_names[idx])) | 107 | menuitem.connect("activate", self._execute, {'terminals' : terminals, 'command' : command['command'] }) |
164 | 90 | parent_submenu.append(item) | 108 | if command['submenu'] and command['submenu'] != '': |
165 | 91 | target_submenu = Gtk.Menu() | 109 | customsubmenustr = command['submenu'] |
166 | 92 | item.set_submenu(target_submenu) | 110 | customsubmenu = submenus_dict[customsubmenustr] |
167 | 93 | submenus[lookup_name] = target_submenu | 111 | customsubmenu.append(menuitem) |
168 | 94 | parent_submenu = target_submenu | 112 | else: |
169 | 95 | if iconinfo: | 113 | pluginsubmenu.append(menuitem) |
170 | 96 | image = Gtk.Image() | 114 | |
171 | 97 | image.set_from_icon_name(exe, Gtk.IconSize.MENU) | 115 | |
143 | 98 | menuitem = Gtk.ImageMenuItem(leaf_name) | ||
144 | 99 | menuitem.set_image(image) | ||
145 | 100 | else: | ||
146 | 101 | menuitem = Gtk.MenuItem(leaf_name) | ||
147 | 102 | terminals = terminal.terminator.get_target_terms(terminal) | ||
148 | 103 | menuitem.connect("activate", self._execute, {'terminals' : terminals, 'command' : command['command'] }) | ||
149 | 104 | target_submenu.append(menuitem) | ||
150 | 105 | |||
172 | 106 | def _save_config(self): | 116 | def _save_config(self): |
190 | 107 | config = Config() | 117 | config = Config() |
191 | 108 | config.plugin_del_config(self.__class__.__name__) | 118 | config.plugin_del_config(self.__class__.__name__) |
192 | 109 | i = 0 | 119 | i = 0 |
193 | 110 | for command in [ self.cmd_list[key] for key in sorted(self.cmd_list.keys()) ] : | 120 | for command in [ self.cmd_list[key] for key in sorted(self.cmd_list.keys()) ] : |
194 | 111 | enabled = command['enabled'] | 121 | enabled = command['enabled'] |
195 | 112 | name = command['name'] | 122 | name = command['name'] |
196 | 113 | command = command['command'] | 123 | try: |
197 | 114 | 124 | submenu = command['submenu'] | |
198 | 115 | item = {} | 125 | except: |
199 | 116 | item['enabled'] = enabled | 126 | submenu = '' |
200 | 117 | item['name'] = name | 127 | command = command['command'] |
201 | 118 | item['command'] = command | 128 | |
202 | 119 | item['position'] = i | 129 | item = {} |
203 | 120 | 130 | item['enabled'] = enabled | |
204 | 121 | config.plugin_set(self.__class__.__name__, name, item) | 131 | item['name'] = name |
205 | 122 | i = i + 1 | 132 | item['command'] = command |
206 | 123 | config.save() | 133 | item['position'] = i |
207 | 134 | item['submenu'] = submenu | ||
208 | 135 | |||
209 | 136 | config.plugin_set(self.__class__.__name__, name, item) | ||
210 | 137 | i = i + 1 | ||
211 | 138 | config.save() | ||
212 | 124 | 139 | ||
213 | 125 | def _execute(self, widget, data): | 140 | def _execute(self, widget, data): |
219 | 126 | command = data['command'] | 141 | command = data['command'] |
220 | 127 | if command[-1] != '\n': | 142 | if command[-1] != '\n': |
221 | 128 | command = command + '\n' | 143 | command = command + '\n' |
222 | 129 | for terminal in data['terminals']: | 144 | for terminal in data['terminals']: |
223 | 130 | terminal.vte.feed_child(command, len(command)) | 145 | terminal.vte.feed_child(command, len(command)) |
224 | 131 | 146 | ||
225 | 132 | def configure(self, widget, data = None): | 147 | def configure(self, widget, data = None): |
335 | 133 | ui = {} | 148 | ui = {} |
336 | 134 | dbox = Gtk.Dialog( | 149 | dbox = Gtk.Dialog( |
337 | 135 | _("Custom Commands Configuration"), | 150 | _("Custom Commands Configuration"), |
338 | 136 | None, | 151 | None, |
339 | 137 | Gtk.DialogFlags.MODAL, | 152 | Gtk.DialogFlags.MODAL, |
340 | 138 | ( | 153 | ( |
341 | 139 | _("_Cancel"), Gtk.ResponseType.REJECT, | 154 | _("_Cancel"), Gtk.ResponseType.REJECT, |
342 | 140 | _("_OK"), Gtk.ResponseType.ACCEPT | 155 | _("_OK"), Gtk.ResponseType.ACCEPT |
343 | 141 | ) | 156 | ) |
344 | 142 | ) | 157 | ) |
345 | 143 | dbox.set_transient_for(widget.get_toplevel()) | 158 | dbox.set_transient_for(widget.get_toplevel()) |
346 | 144 | 159 | ||
347 | 145 | icon_theme = Gtk.IconTheme.get_default() | 160 | icon_theme = Gtk.IconTheme.get_default() |
348 | 146 | if icon_theme.lookup_icon('terminator-custom-commands', 48, 0): | 161 | if icon_theme.lookup_icon('terminator-custom-commands', 48, 0): |
349 | 147 | dbox.set_icon_name('terminator-custom-commands') | 162 | dbox.set_icon_name('terminator-custom-commands') |
350 | 148 | else: | 163 | else: |
351 | 149 | dbg('Unable to load Terminator custom command icon') | 164 | dbg('Unable to load Terminator custom command icon') |
352 | 150 | icon = dbox.render_icon(Gtk.STOCK_DIALOG_INFO, Gtk.IconSize.BUTTON) | 165 | icon = dbox.render_icon(Gtk.STOCK_DIALOG_INFO, Gtk.IconSize.BUTTON) |
353 | 151 | dbox.set_icon(icon) | 166 | dbox.set_icon(icon) |
354 | 152 | 167 | ||
355 | 153 | store = Gtk.ListStore(bool, str, str) | 168 | store = Gtk.ListStore(bool, str, str, str) |
356 | 154 | 169 | ||
357 | 155 | for command in [ self.cmd_list[key] for key in sorted(self.cmd_list.keys()) ]: | 170 | for command in [ self.cmd_list[key] for key in sorted(self.cmd_list.keys()) ]: |
358 | 156 | store.append([command['enabled'], command['name'], command['command']]) | 171 | store.append([command['enabled'], command['name'], command['command'], command['submenu']]) |
359 | 157 | 172 | treeview = Gtk.TreeView(store) | |
360 | 158 | treeview = Gtk.TreeView(store) | 173 | |
361 | 159 | #treeview.connect("cursor-changed", self.on_cursor_changed, ui) | 174 | selection = treeview.get_selection() |
362 | 160 | selection = treeview.get_selection() | 175 | selection.set_mode(Gtk.SelectionMode.SINGLE) |
363 | 161 | selection.set_mode(Gtk.SelectionMode.SINGLE) | 176 | selection.connect("changed", self.on_selection_changed, ui) |
364 | 162 | selection.connect("changed", self.on_selection_changed, ui) | 177 | ui['treeview'] = treeview |
365 | 163 | ui['treeview'] = treeview | 178 | |
366 | 164 | 179 | renderer = Gtk.CellRendererToggle() | |
367 | 165 | renderer = Gtk.CellRendererToggle() | 180 | renderer.connect('toggled', self.on_toggled, ui) |
368 | 166 | renderer.connect('toggled', self.on_toggled, ui) | 181 | column = Gtk.TreeViewColumn(_("Enabled"), renderer, active=CC_COL_ENABLED) |
369 | 167 | column = Gtk.TreeViewColumn(_("Enabled"), renderer, active=CC_COL_ENABLED) | 182 | treeview.append_column(column) |
370 | 168 | treeview.append_column(column) | 183 | |
371 | 169 | 184 | renderer = Gtk.CellRendererText() | |
372 | 170 | renderer = Gtk.CellRendererText() | 185 | column = Gtk.TreeViewColumn(_("Name"), renderer, text=CC_COL_NAME) |
373 | 171 | column = Gtk.TreeViewColumn(_("Name"), renderer, text=CC_COL_NAME) | 186 | treeview.append_column(column) |
374 | 172 | treeview.append_column(column) | 187 | |
375 | 173 | 188 | renderer = Gtk.CellRendererText() | |
376 | 174 | renderer = Gtk.CellRendererText() | 189 | column = Gtk.TreeViewColumn(_("Submenu"), renderer, text=CC_COL_CUSTOMSUBMENU) |
377 | 175 | column = Gtk.TreeViewColumn(_("Command"), renderer, text=CC_COL_COMMAND) | 190 | treeview.append_column(column) |
378 | 176 | treeview.append_column(column) | 191 | |
379 | 177 | 192 | renderer = Gtk.CellRendererText() | |
380 | 178 | scroll_window = Gtk.ScrolledWindow() | 193 | column = Gtk.TreeViewColumn(_("Command"), renderer, text=CC_COL_COMMAND) |
381 | 179 | scroll_window.set_size_request(500, 250) | 194 | treeview.append_column(column) |
382 | 180 | scroll_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) | 195 | |
383 | 181 | scroll_window.add_with_viewport(treeview) | 196 | scroll_window = Gtk.ScrolledWindow() |
384 | 182 | 197 | scroll_window.set_size_request(500, 250) | |
385 | 183 | hbox = Gtk.HBox() | 198 | scroll_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) |
386 | 184 | hbox.pack_start(scroll_window, True, True, 0) | 199 | scroll_window.add_with_viewport(treeview) |
387 | 185 | dbox.vbox.pack_start(hbox, True, True, 0) | 200 | |
388 | 186 | 201 | hbox = Gtk.HBox() | |
389 | 187 | button_box = Gtk.VBox() | 202 | hbox.pack_start(scroll_window, True, True, 0) |
390 | 188 | 203 | dbox.vbox.pack_start(hbox, True, True, 0) | |
391 | 189 | button = Gtk.Button(_("Top")) | 204 | |
392 | 190 | button_box.pack_start(button, False, True, 0) | 205 | button_box = Gtk.VBox() |
393 | 191 | button.connect("clicked", self.on_goto_top, ui) | 206 | |
394 | 192 | button.set_sensitive(False) | 207 | button = Gtk.Button(_("Top")) |
395 | 193 | ui['button_top'] = button | 208 | button_box.pack_start(button, False, True, 0) |
396 | 194 | 209 | button.connect("clicked", self.on_goto_top, ui) | |
397 | 195 | button = Gtk.Button(_("Up")) | 210 | button.set_sensitive(False) |
398 | 196 | button_box.pack_start(button, False, True, 0) | 211 | ui['button_top'] = button |
399 | 197 | button.connect("clicked", self.on_go_up, ui) | 212 | |
400 | 198 | button.set_sensitive(False) | 213 | button = Gtk.Button(_("Up")) |
401 | 199 | ui['button_up'] = button | 214 | button_box.pack_start(button, False, True, 0) |
402 | 200 | 215 | button.connect("clicked", self.on_go_up, ui) | |
403 | 201 | button = Gtk.Button(_("Down")) | 216 | button.set_sensitive(False) |
404 | 202 | button_box.pack_start(button, False, True, 0) | 217 | ui['button_up'] = button |
405 | 203 | button.connect("clicked", self.on_go_down, ui) | 218 | |
406 | 204 | button.set_sensitive(False) | 219 | button = Gtk.Button(_("Down")) |
407 | 205 | ui['button_down'] = button | 220 | button_box.pack_start(button, False, True, 0) |
408 | 206 | 221 | button.connect("clicked", self.on_go_down, ui) | |
409 | 207 | button = Gtk.Button(_("Last")) | 222 | button.set_sensitive(False) |
410 | 208 | button_box.pack_start(button, False, True, 0) | 223 | ui['button_down'] = button |
411 | 209 | button.connect("clicked", self.on_goto_last, ui) | 224 | |
412 | 210 | button.set_sensitive(False) | 225 | button = Gtk.Button(_("Last")) |
413 | 211 | ui['button_last'] = button | 226 | button_box.pack_start(button, False, True, 0) |
414 | 212 | 227 | button.connect("clicked", self.on_goto_last, ui) | |
415 | 213 | button = Gtk.Button(_("New")) | 228 | button.set_sensitive(False) |
416 | 214 | button_box.pack_start(button, False, True, 0) | 229 | ui['button_last'] = button |
417 | 215 | button.connect("clicked", self.on_new, ui) | 230 | |
418 | 216 | ui['button_new'] = button | 231 | button = Gtk.Button(_("New")) |
419 | 217 | 232 | button_box.pack_start(button, False, True, 0) | |
420 | 218 | button = Gtk.Button(_("Edit")) | 233 | button.connect("clicked", self.on_new, ui) |
421 | 219 | button_box.pack_start(button, False, True, 0) | 234 | ui['button_new'] = button |
422 | 220 | button.set_sensitive(False) | 235 | |
423 | 221 | button.connect("clicked", self.on_edit, ui) | 236 | button = Gtk.Button(_("Edit")) |
424 | 222 | ui['button_edit'] = button | 237 | button_box.pack_start(button, False, True, 0) |
425 | 223 | 238 | button.set_sensitive(False) | |
426 | 224 | button = Gtk.Button(_("Delete")) | 239 | button.connect("clicked", self.on_edit, ui) |
427 | 225 | button_box.pack_start(button, False, True, 0) | 240 | ui['button_edit'] = button |
428 | 226 | button.connect("clicked", self.on_delete, ui) | 241 | |
429 | 227 | button.set_sensitive(False) | 242 | button = Gtk.Button(_("Delete")) |
430 | 228 | ui['button_delete'] = button | 243 | button_box.pack_start(button, False, True, 0) |
431 | 229 | 244 | button.connect("clicked", self.on_delete, ui) | |
432 | 230 | 245 | button.set_sensitive(False) | |
433 | 231 | 246 | ui['button_delete'] = button | |
434 | 232 | hbox.pack_start(button_box, False, True, 0) | 247 | |
435 | 233 | self.dbox = dbox | 248 | hbox.pack_start(button_box, False, True, 0) |
436 | 234 | dbox.show_all() | 249 | self.dbox = dbox |
437 | 235 | res = dbox.run() | 250 | dbox.show_all() |
438 | 236 | if res == Gtk.ResponseType.ACCEPT: | 251 | res = dbox.run() |
439 | 237 | self.update_cmd_list(store) | 252 | if res == Gtk.ResponseType.ACCEPT: |
440 | 238 | self._save_config() | 253 | self.update_cmd_list(store) |
441 | 239 | del(self.dbox) | 254 | self._save_config() |
442 | 240 | dbox.destroy() | 255 | del(self.dbox) |
443 | 241 | return | 256 | dbox.destroy() |
444 | 257 | return | ||
445 | 242 | 258 | ||
446 | 243 | 259 | ||
447 | 244 | def update_cmd_list(self, store): | 260 | def update_cmd_list(self, store): |
448 | @@ -246,223 +262,249 @@ | |||
449 | 246 | self.cmd_list = {} | 262 | self.cmd_list = {} |
450 | 247 | i=0 | 263 | i=0 |
451 | 248 | while iter: | 264 | while iter: |
462 | 249 | (enabled, name, command) = store.get(iter, | 265 | (enabled, name, command, submenu) = store.get(iter, |
463 | 250 | CC_COL_ENABLED, | 266 | CC_COL_ENABLED, |
464 | 251 | CC_COL_NAME, | 267 | CC_COL_NAME, |
465 | 252 | CC_COL_COMMAND) | 268 | CC_COL_COMMAND, |
466 | 253 | self.cmd_list[i] = {'enabled' : enabled, | 269 | CC_COL_CUSTOMSUBMENU) |
467 | 254 | 'name': name, | 270 | self.cmd_list[i] = {'enabled' : enabled, |
468 | 255 | 'command' : command} | 271 | 'name': name, |
469 | 256 | iter = store.iter_next(iter) | 272 | 'command' : command, |
470 | 257 | i = i + 1 | 273 | 'submenu' : submenu} |
471 | 258 | 274 | iter = store.iter_next(iter) | |
472 | 275 | i = i + 1 | ||
473 | 276 | |||
474 | 259 | 277 | ||
475 | 260 | def on_toggled(self, widget, path, data): | 278 | def on_toggled(self, widget, path, data): |
485 | 261 | treeview = data['treeview'] | 279 | treeview = data['treeview'] |
486 | 262 | store = treeview.get_model() | 280 | store = treeview.get_model() |
487 | 263 | iter = store.get_iter(path) | 281 | iter = store.get_iter(path) |
488 | 264 | (enabled, name, command) = store.get(iter, | 282 | (enabled, name, command, submenu) = store.get(iter, |
489 | 265 | CC_COL_ENABLED, | 283 | CC_COL_ENABLED, |
490 | 266 | CC_COL_NAME, | 284 | CC_COL_NAME, |
491 | 267 | CC_COL_COMMAND | 285 | CC_COL_COMMAND, |
492 | 268 | ) | 286 | CC_COL_CUSTOMSUBMENU) |
493 | 269 | store.set_value(iter, CC_COL_ENABLED, not enabled) | 287 | store.set_value(iter, CC_COL_ENABLED, not enabled) |
494 | 270 | 288 | ||
495 | 271 | 289 | ||
496 | 272 | def on_selection_changed(self,selection, data=None): | 290 | def on_selection_changed(self,selection, data=None): |
540 | 273 | treeview = selection.get_tree_view() | 291 | treeview = selection.get_tree_view() |
541 | 274 | (model, iter) = selection.get_selected() | 292 | (model, iter) = selection.get_selected() |
542 | 275 | data['button_top'].set_sensitive(iter is not None) | 293 | data['button_top'].set_sensitive(iter is not None) |
543 | 276 | data['button_up'].set_sensitive(iter is not None) | 294 | data['button_up'].set_sensitive(iter is not None) |
544 | 277 | data['button_down'].set_sensitive(iter is not None) | 295 | data['button_down'].set_sensitive(iter is not None) |
545 | 278 | data['button_last'].set_sensitive(iter is not None) | 296 | data['button_last'].set_sensitive(iter is not None) |
546 | 279 | data['button_edit'].set_sensitive(iter is not None) | 297 | data['button_edit'].set_sensitive(iter is not None) |
547 | 280 | data['button_delete'].set_sensitive(iter is not None) | 298 | data['button_delete'].set_sensitive(iter is not None) |
548 | 281 | 299 | ||
549 | 282 | def _create_command_dialog(self, enabled_var = False, name_var = "", command_var = ""): | 300 | def _create_command_dialog(self, enabled_var = False, name_var = "", command_var = "", submenu_var = ""): |
550 | 283 | dialog = Gtk.Dialog( | 301 | dialog = Gtk.Dialog( |
551 | 284 | _("New Command"), | 302 | _("New Command"), |
552 | 285 | None, | 303 | None, |
553 | 286 | Gtk.DialogFlags.MODAL, | 304 | Gtk.DialogFlags.MODAL, |
554 | 287 | ( | 305 | ( |
555 | 288 | _("_Cancel"), Gtk.ResponseType.REJECT, | 306 | Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT, |
556 | 289 | _("_OK"), Gtk.ResponseType.ACCEPT | 307 | Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT |
557 | 290 | ) | 308 | ) |
558 | 291 | ) | 309 | ) |
559 | 292 | dialog.set_transient_for(self.dbox) | 310 | dialog.set_transient_for(self.dbox) |
560 | 293 | table = Gtk.Table(3, 2) | 311 | table = Gtk.Table(3, 2) |
561 | 294 | 312 | ||
562 | 295 | label = Gtk.Label(label=_("Enabled:")) | 313 | label = Gtk.Label(label=_("Enabled:")) |
563 | 296 | table.attach(label, 0, 1, 0, 1) | 314 | table.attach(label, 0, 1, 0, 1) |
564 | 297 | enabled = Gtk.CheckButton() | 315 | enabled = Gtk.CheckButton() |
565 | 298 | enabled.set_active(enabled_var) | 316 | enabled.set_active(enabled_var) |
566 | 299 | table.attach(enabled, 1, 2, 0, 1) | 317 | table.attach(enabled, 1, 2, 0, 1) |
567 | 300 | 318 | ||
568 | 301 | label = Gtk.Label(label=_("Name:")) | 319 | label = Gtk.Label(label=_("Name:")) |
569 | 302 | table.attach(label, 0, 1, 1, 2) | 320 | table.attach(label, 0, 1, 1, 2) |
570 | 303 | name = Gtk.Entry() | 321 | name = Gtk.Entry() |
571 | 304 | name.set_text(name_var) | 322 | name.set_text(name_var) |
572 | 305 | table.attach(name, 1, 2, 1, 2) | 323 | table.attach(name, 1, 2, 1, 2) |
573 | 306 | 324 | ||
574 | 307 | label = Gtk.Label(label=_("Command:")) | 325 | label = Gtk.Label(label=_("Submenu:")) |
575 | 308 | table.attach(label, 0, 1, 2, 3) | 326 | table.attach(label, 0, 1, 2, 3) |
576 | 309 | command = Gtk.Entry() | 327 | submenu = Gtk.Entry() |
577 | 310 | command.set_text(command_var) | 328 | submenu.set_text(submenu_var) |
578 | 311 | table.attach(command, 1, 2, 2, 3) | 329 | table.attach(submenu, 1, 2, 2, 3) |
579 | 312 | 330 | ||
580 | 313 | dialog.vbox.pack_start(table, True, True, 0) | 331 | label = Gtk.Label(label=_("Command:")) |
581 | 314 | dialog.show_all() | 332 | table.attach(label, 0, 1, 3, 4) |
582 | 315 | return (dialog,enabled,name,command) | 333 | command = Gtk.Entry() |
583 | 334 | command.set_text(command_var) | ||
584 | 335 | table.attach(command, 1, 2, 3, 4) | ||
585 | 336 | |||
586 | 337 | dialog.vbox.pack_start(table, True, True, 0) | ||
587 | 338 | dialog.show_all() | ||
588 | 339 | return (dialog,enabled,name,command,submenu) | ||
589 | 316 | 340 | ||
590 | 317 | def on_new(self, button, data): | 341 | def on_new(self, button, data): |
622 | 318 | (dialog,enabled,name,command) = self._create_command_dialog() | 342 | (dialog,enabled,name,command,submenu) = self._create_command_dialog() |
623 | 319 | res = dialog.run() | 343 | res = dialog.run() |
624 | 320 | item = {} | 344 | item = {} |
625 | 321 | if res == Gtk.ResponseType.ACCEPT: | 345 | if res == Gtk.ResponseType.ACCEPT: |
626 | 322 | item['enabled'] = enabled.get_active() | 346 | item['enabled'] = enabled.get_active() |
627 | 323 | item['name'] = name.get_text() | 347 | item['name'] = name.get_text() |
628 | 324 | item['command'] = command.get_text() | 348 | item['submenu'] = submenu.get_text() |
629 | 325 | if item['name'] == '' or item['command'] == '': | 349 | item['command'] = command.get_text() |
630 | 326 | err = Gtk.MessageDialog(dialog, | 350 | if item['name'] == '' or item['command'] == '': |
631 | 327 | Gtk.DialogFlags.MODAL, | 351 | err = Gtk.MessageDialog(dialog, |
632 | 328 | Gtk.MessageType.ERROR, | 352 | Gtk.DialogFlags.MODAL, |
633 | 329 | Gtk.ButtonsType.CLOSE, | 353 | Gtk.MessageType.ERROR, |
634 | 330 | _("You need to define a name and command") | 354 | Gtk.ButtonsType.CLOSE, |
635 | 331 | ) | 355 | _("You need to define a name and command") |
636 | 332 | err.run() | 356 | ) |
637 | 333 | err.destroy() | 357 | err.run() |
638 | 334 | else: | 358 | err.destroy() |
639 | 335 | # we have a new command | 359 | else: |
640 | 336 | store = data['treeview'].get_model() | 360 | # we have a new command |
641 | 337 | iter = store.get_iter_first() | 361 | store = data['treeview'].get_model() |
642 | 338 | name_exist = False | 362 | iter = store.get_iter_first() |
643 | 339 | while iter != None: | 363 | name_exist = False |
644 | 340 | if store.get_value(iter,CC_COL_NAME) == item['name']: | 364 | while iter != None: |
645 | 341 | name_exist = True | 365 | if store.get_value(iter,CC_COL_NAME) == item['name']: |
646 | 342 | break | 366 | name_exist = True |
647 | 343 | iter = store.iter_next(iter) | 367 | break |
648 | 344 | if not name_exist: | 368 | iter = store.iter_next(iter) |
649 | 345 | store.append((item['enabled'], item['name'], item['command'])) | 369 | if not name_exist: |
650 | 346 | else: | 370 | store.append((item['enabled'], item['name'], item['command'], item['submenu'])) |
651 | 347 | gerr(_("Name *%s* already exist") % item['name']) | 371 | else: |
652 | 348 | dialog.destroy() | 372 | gerr(_("Name *%s* already exist") % item['name']) |
653 | 373 | dialog.destroy() | ||
654 | 374 | |||
655 | 349 | 375 | ||
656 | 350 | def on_goto_top(self, button, data): | 376 | def on_goto_top(self, button, data): |
665 | 351 | treeview = data['treeview'] | 377 | treeview = data['treeview'] |
666 | 352 | selection = treeview.get_selection() | 378 | selection = treeview.get_selection() |
667 | 353 | (store, iter) = selection.get_selected() | 379 | (store, iter) = selection.get_selected() |
668 | 354 | 380 | ||
669 | 355 | if not iter: | 381 | if not iter: |
670 | 356 | return | 382 | return |
671 | 357 | firstiter = store.get_iter_first() | 383 | |
672 | 358 | store.move_before(iter, firstiter) | 384 | firstiter = store.get_iter_first() |
673 | 385 | store.move_before(iter, firstiter) | ||
674 | 386 | |||
675 | 359 | 387 | ||
676 | 360 | def on_go_up(self, button, data): | 388 | def on_go_up(self, button, data): |
694 | 361 | treeview = data['treeview'] | 389 | treeview = data['treeview'] |
695 | 362 | selection = treeview.get_selection() | 390 | selection = treeview.get_selection() |
696 | 363 | (store, iter) = selection.get_selected() | 391 | (store, iter) = selection.get_selected() |
697 | 364 | 392 | ||
698 | 365 | if not iter: | 393 | if not iter: |
699 | 366 | return | 394 | return |
700 | 367 | 395 | ||
701 | 368 | tmpiter = store.get_iter_first() | 396 | tmpiter = store.get_iter_first() |
702 | 369 | 397 | ||
703 | 370 | if(store.get_path(tmpiter) == store.get_path(iter)): | 398 | if(store.get_path(tmpiter) == store.get_path(iter)): |
704 | 371 | return | 399 | return |
705 | 372 | 400 | ||
706 | 373 | while tmpiter: | 401 | while tmpiter: |
707 | 374 | next = store.iter_next(tmpiter) | 402 | next = store.iter_next(tmpiter) |
708 | 375 | if(store.get_path(next) == store.get_path(iter)): | 403 | |
709 | 376 | store.swap(iter, tmpiter) | 404 | if(store.get_path(next) == store.get_path(iter)): |
710 | 377 | break | 405 | store.swap(iter, tmpiter) |
711 | 406 | break | ||
712 | 407 | |||
713 | 378 | tmpiter = next | 408 | tmpiter = next |
714 | 379 | 409 | ||
715 | 410 | |||
716 | 380 | def on_go_down(self, button, data): | 411 | def on_go_down(self, button, data): |
726 | 381 | treeview = data['treeview'] | 412 | treeview = data['treeview'] |
727 | 382 | selection = treeview.get_selection() | 413 | selection = treeview.get_selection() |
728 | 383 | (store, iter) = selection.get_selected() | 414 | (store, iter) = selection.get_selected() |
729 | 384 | 415 | ||
730 | 385 | if not iter: | 416 | if not iter: |
731 | 386 | return | 417 | return |
732 | 387 | next = store.iter_next(iter) | 418 | next = store.iter_next(iter) |
733 | 388 | if next: | 419 | if next: |
734 | 389 | store.swap(iter, next) | 420 | store.swap(iter, next) |
735 | 421 | |||
736 | 390 | 422 | ||
737 | 391 | def on_goto_last(self, button, data): | 423 | def on_goto_last(self, button, data): |
753 | 392 | treeview = data['treeview'] | 424 | treeview = data['treeview'] |
754 | 393 | selection = treeview.get_selection() | 425 | selection = treeview.get_selection() |
755 | 394 | (store, iter) = selection.get_selected() | 426 | (store, iter) = selection.get_selected() |
756 | 395 | 427 | ||
757 | 396 | if not iter: | 428 | if not iter: |
758 | 397 | return | 429 | return |
759 | 398 | lastiter = iter | 430 | |
760 | 399 | tmpiter = store.get_iter_first() | 431 | lastiter = iter |
761 | 400 | while tmpiter: | 432 | tmpiter = store.get_iter_first() |
762 | 401 | lastiter = tmpiter | 433 | |
763 | 402 | tmpiter = store.iter_next(tmpiter) | 434 | while tmpiter: |
764 | 403 | 435 | lastiter = tmpiter | |
765 | 404 | store.move_after(iter, lastiter) | 436 | tmpiter = store.iter_next(tmpiter) |
766 | 405 | 437 | ||
767 | 406 | 438 | store.move_after(iter, lastiter) | |
768 | 439 | |||
769 | 440 | |||
770 | 407 | def on_delete(self, button, data): | 441 | def on_delete(self, button, data): |
779 | 408 | treeview = data['treeview'] | 442 | treeview = data['treeview'] |
780 | 409 | selection = treeview.get_selection() | 443 | selection = treeview.get_selection() |
781 | 410 | (store, iter) = selection.get_selected() | 444 | (store, iter) = selection.get_selected() |
782 | 411 | if iter: | 445 | |
783 | 412 | store.remove(iter) | 446 | if iter: |
784 | 413 | 447 | store.remove(iter) | |
785 | 414 | return | 448 | |
786 | 415 | 449 | return | |
787 | 450 | |||
788 | 451 | |||
789 | 416 | def on_edit(self, button, data): | 452 | def on_edit(self, button, data): |
837 | 417 | treeview = data['treeview'] | 453 | treeview = data['treeview'] |
838 | 418 | selection = treeview.get_selection() | 454 | selection = treeview.get_selection() |
839 | 419 | (store, iter) = selection.get_selected() | 455 | (store, iter) = selection.get_selected() |
840 | 420 | 456 | ||
841 | 421 | if not iter: | 457 | if not iter: |
842 | 422 | return | 458 | return |
843 | 423 | 459 | ||
844 | 424 | (dialog,enabled,name,command) = self._create_command_dialog( | 460 | (dialog,enabled,name,command,submenu) = self._create_command_dialog( |
845 | 425 | enabled_var = store.get_value(iter, CC_COL_ENABLED), | 461 | enabled_var = store.get_value(iter, CC_COL_ENABLED), |
846 | 426 | name_var = store.get_value(iter, CC_COL_NAME), | 462 | name_var = store.get_value(iter, CC_COL_NAME), |
847 | 427 | command_var = store.get_value(iter, CC_COL_COMMAND) | 463 | command_var = store.get_value(iter, CC_COL_COMMAND), |
848 | 428 | ) | 464 | submenu_var=store.get_value(iter, CC_COL_CUSTOMSUBMENU) |
849 | 429 | res = dialog.run() | 465 | ) |
850 | 430 | item = {} | 466 | |
851 | 431 | if res == Gtk.ResponseType.ACCEPT: | 467 | res = dialog.run() |
852 | 432 | item['enabled'] = enabled.get_active() | 468 | item = {} |
853 | 433 | item['name'] = name.get_text() | 469 | |
854 | 434 | item['command'] = command.get_text() | 470 | if res == Gtk.ResponseType.ACCEPT: |
855 | 435 | if item['name'] == '' or item['command'] == '': | 471 | item['enabled'] = enabled.get_active() |
856 | 436 | err = Gtk.MessageDialog(dialog, | 472 | item['name'] = name.get_text() |
857 | 437 | Gtk.DialogFlags.MODAL, | 473 | item['command'] = command.get_text() |
858 | 438 | Gtk.MessageType.ERROR, | 474 | item['submenu'] = submenu.get_text() |
859 | 439 | Gtk.ButtonsType.CLOSE, | 475 | |
860 | 440 | _("You need to define a name and command") | 476 | if item['name'] == '' or item['command'] == '': |
861 | 441 | ) | 477 | err = Gtk.MessageDialog(dialog, |
862 | 442 | err.run() | 478 | Gtk.DialogFlags.MODAL, |
863 | 443 | err.destroy() | 479 | Gtk.MessageType.ERROR, |
864 | 444 | else: | 480 | Gtk.ButtonsType.CLOSE, |
865 | 445 | tmpiter = store.get_iter_first() | 481 | _("You need to define a name and command") |
866 | 446 | name_exist = False | 482 | ) |
867 | 447 | while tmpiter != None: | 483 | err.run() |
868 | 448 | if store.get_path(tmpiter) != store.get_path(iter) and store.get_value(tmpiter,CC_COL_NAME) == item['name']: | 484 | err.destroy() |
869 | 449 | name_exist = True | 485 | else: |
870 | 450 | break | 486 | tmpiter = store.get_iter_first() |
871 | 451 | tmpiter = store.iter_next(tmpiter) | 487 | name_exist = False |
872 | 452 | if not name_exist: | 488 | while tmpiter != None: |
873 | 453 | store.set(iter, | 489 | if store.get_path(tmpiter) != store.get_path(iter) and store.get_value(tmpiter,CC_COL_NAME) == item['name']: |
874 | 454 | CC_COL_ENABLED,item['enabled'], | 490 | name_exist = True |
875 | 455 | CC_COL_NAME, item['name'], | 491 | break |
876 | 456 | CC_COL_COMMAND, item['command'] | 492 | tmpiter = store.iter_next(tmpiter) |
877 | 457 | ) | 493 | if not name_exist: |
878 | 458 | else: | 494 | store.set(iter, |
879 | 459 | gerr(_("Name *%s* already exist") % item['name']) | 495 | CC_COL_ENABLED,item['enabled'], |
880 | 460 | 496 | CC_COL_NAME, item['name'], | |
881 | 461 | dialog.destroy() | 497 | CC_COL_COMMAND, item['command'], |
882 | 462 | 498 | CC_COL_CUSTOMSUBMENU, item['submenu'] | |
883 | 463 | 499 | ) | |
884 | 500 | else: | ||
885 | 501 | gerr(_("Name *%s* already exist") % item['name']) | ||
886 | 502 | |||
887 | 503 | dialog.destroy() | ||
888 | 504 | |||
889 | 505 | |||
890 | 464 | if __name__ == '__main__': | 506 | if __name__ == '__main__': |
894 | 465 | c = CustomCommandsMenu() | 507 | c = CustomCommandsMenu() |
895 | 466 | c.configure(None, None) | 508 | c.configure(None, None) |
896 | 467 | Gtk.main() | 509 | Gtk.main() |
897 | 468 | 510 |
Tested on Debian Stretch and Buster without any problem.
Indentation fix does not change the behaviour but improve readability for further changes.