Merge lp:~dcaro/clicompanion/fix-623475 into lp:clicompanion
- fix-623475
- Merge into trunk
Proposed by
David Caro
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Duane Hinnen | ||||
Approved revision: | 108 | ||||
Merge reported by: | Duane Hinnen | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp:~dcaro/clicompanion/fix-623475 | ||||
Merge into: | lp:clicompanion | ||||
Diff against target: |
442 lines (+218/-55) 5 files modified
clicompanionlib/config.py (+2/-0) clicompanionlib/menus_buttons.py (+98/-42) clicompanionlib/plugins.py (+2/-0) clicompanionlib/tabs.py (+93/-12) clicompanionlib/view.py (+23/-1) |
||||
To merge this branch: | bzr merge lp:~dcaro/clicompanion/fix-623475 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Duane Hinnen | Approve | ||
David Caro | Needs Resubmitting | ||
Marek Bardoński | Needs Fixing | ||
Review via email: mp+88612@code.launchpad.net |
Commit message
Description of the change
Added the job control options in the toplevel menu and the right-click menu, also reorganized the toplevel menu entries.
To post a comment you must log in.
Revision history for this message
David Caro (dcaro) wrote : | # |
Fixed, please, can you review it again?
Thanks,
David
review:
Needs Resubmitting
- 108. By David Caro "<email address hidden>"
-
Fixed cancel button error
Revision history for this message
Marek Bardoński (bdfhjk) wrote : | # |
Ok, I will try do it tomorrow. Now I'm participating in Facebook Hacker Cup
Round 1.
Thanks!
Revision history for this message
David Caro (dcaro) wrote : | # |
Good luck!
Revision history for this message
Duane Hinnen (duanedesign) wrote : | # |
It looks good.
I am blown away by the recent work.
Things are looking really good.
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'clicompanionlib/config.py' |
2 | --- clicompanionlib/config.py 2012-01-12 20:51:02 +0000 |
3 | +++ clicompanionlib/config.py 2012-01-28 19:42:29 +0000 |
4 | @@ -73,6 +73,7 @@ |
5 | ## shift+ctrl+D (not shift+ctrl+d). And the function keys go uppercase (F10). |
6 | DEFAULT_KEY_BINDINGS = { |
7 | 'run_command': 'F4', |
8 | + 'cancel_command': 'ctrl+C', |
9 | 'add_command': 'F5', |
10 | 'remove_command': 'F6', |
11 | 'edit_command': 'unused', |
12 | @@ -95,6 +96,7 @@ |
13 | ## actibated |
14 | KEY_BINDINGS = { |
15 | 'run_command': 'Run command', |
16 | + 'cancel_command': 'Cancel command', |
17 | 'add_command': 'Add command', |
18 | 'remove_command': 'Remove command', |
19 | 'edit_command': 'Edit command', |
20 | |
21 | === modified file 'clicompanionlib/menus_buttons.py' |
22 | --- clicompanionlib/menus_buttons.py 2012-01-08 00:48:43 +0000 |
23 | +++ clicompanionlib/menus_buttons.py 2012-01-28 19:42:29 +0000 |
24 | @@ -31,6 +31,18 @@ |
25 | __gsignals__ = { |
26 | 'run_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
27 | ()), |
28 | + 'cancel_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
29 | + ()), |
30 | + 'stop_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
31 | + ()), |
32 | + 'resume_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
33 | + ()), |
34 | + 'background_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
35 | + ()), |
36 | + 'foreground_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
37 | + ()), |
38 | + 'bgrun_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
39 | + ()), |
40 | 'add_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
41 | ()), |
42 | 'remove_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
43 | @@ -49,77 +61,112 @@ |
44 | |
45 | def __init__(self, config): |
46 | gtk.MenuBar.__init__(self) |
47 | + |
48 | + ##FILE MENU ## |
49 | + file_menu = gtk.MenuItem(_("File")) |
50 | menu = gtk.Menu() |
51 | - #color = gtk.gdk.Color(65555, 62000, 65555) |
52 | - #menu.modify_bg(gtk.STATE_NORMAL, color) |
53 | - root_menu = gtk.MenuItem(_("File")) |
54 | - root_menu.set_submenu(menu) |
55 | - |
56 | - menu2 = gtk.Menu() |
57 | - #color = gtk.gdk.Color(65555, 62000, 60000) |
58 | - #menu2.modify_bg(gtk.STATE_NORMAL, color) |
59 | - root_menu2 = gtk.MenuItem(_("Help")) |
60 | - root_menu2.set_submenu(menu2) |
61 | - |
62 | - ##FILE MENU ## |
63 | + file_menu.set_submenu(menu) |
64 | + ## Make 'User Preferences' file menu entry |
65 | + menu_item5 = gtk.MenuItem(_("Preferences")) |
66 | + menu.append(menu_item5) |
67 | + menu_item5.connect("activate", lambda *x: self.emit('preferences')) |
68 | + ## Make 'Quit' file menu entry |
69 | + menu_item6 = gtk.MenuItem(_("Quit")) |
70 | + menu.append(menu_item6) |
71 | + menu_item6.connect("activate", lambda *x: self.emit('quit')) |
72 | + |
73 | + ## Make 'Process' menu entry |
74 | + p_menu = gtk.MenuItem(_("Process")) |
75 | + proc_menu = gtk.Menu() |
76 | + p_menu.set_submenu(proc_menu) |
77 | + ## Submenu Abort |
78 | + subitem = gtk.ImageMenuItem(gtk.STOCK_STOP) |
79 | + subitem.set_label(_('Abort (Ctrl+c)')) |
80 | + proc_menu.add(subitem) |
81 | + subitem.connect('activate', |
82 | + lambda *x: self.emit('cancel_command')) |
83 | + ## Submenu Pause |
84 | + subitem = gtk.ImageMenuItem(gtk.STOCK_MEDIA_PAUSE) |
85 | + subitem.set_label(_('Pause (Ctrl+s)')) |
86 | + proc_menu.add(subitem) |
87 | + subitem.connect('activate', |
88 | + lambda *x: self.emit('stop_command')) |
89 | + ## Submenu Resume |
90 | + subitem = gtk.ImageMenuItem(gtk.STOCK_MEDIA_PLAY) |
91 | + subitem.set_label(_('Resume (Ctrl+q)')) |
92 | + proc_menu.add(subitem) |
93 | + subitem.connect('activate', |
94 | + lambda *x: self.emit('resume_command')) |
95 | + ## Submenu Background Suspend |
96 | + subitem = gtk.ImageMenuItem(gtk.STOCK_GOTO_BOTTOM) |
97 | + subitem.set_label(_('Stop and Background (Ctrl+z)')) |
98 | + proc_menu.add(subitem) |
99 | + subitem.connect('activate', |
100 | + lambda *x: self.emit('background_command')) |
101 | + ## Submenu Resume |
102 | + subitem = gtk.ImageMenuItem(gtk.STOCK_GO_UP) |
103 | + subitem.set_label(_('Foreground (%)')) |
104 | + proc_menu.add(subitem) |
105 | + subitem.connect('activate', |
106 | + lambda *x: self.emit('foreground_command')) |
107 | + ## Submenu Resume |
108 | + subitem = gtk.ImageMenuItem(gtk.STOCK_GO_DOWN) |
109 | + subitem.set_label(_('Run background (% &)')) |
110 | + proc_menu.add(subitem) |
111 | + subitem.connect('activate', |
112 | + lambda *x: self.emit('bgrun_command')) |
113 | + |
114 | + |
115 | + ## Command menu |
116 | + c_menu = gtk.MenuItem(_("Command")) |
117 | + com_menu = gtk.Menu() |
118 | + c_menu.set_submenu(com_menu) |
119 | ## Make 'Run' menu entry |
120 | menu_item1 = gtk.MenuItem(_("Run Command")) |
121 | - menu.append(menu_item1) |
122 | + com_menu.append(menu_item1) |
123 | menu_item1.connect("activate", lambda *x: self.emit('run_command')) |
124 | - menu_item1.show() |
125 | - |
126 | ## Make 'Add' file menu entry |
127 | menu_item2 = gtk.MenuItem(_("Add Command")) |
128 | - menu.append(menu_item2) |
129 | + com_menu.append(menu_item2) |
130 | menu_item2.connect("activate", lambda *x: self.emit('add_command')) |
131 | - menu_item2.show() |
132 | - |
133 | ## Make 'Remove' file menu entry |
134 | menu_item3 = gtk.MenuItem(_("Remove Command")) |
135 | - menu.append(menu_item3) |
136 | + com_menu.append(menu_item3) |
137 | menu_item3.connect("activate", lambda *x: self.emit('remove_command')) |
138 | - menu_item3.show() |
139 | |
140 | + ## Terminal menu |
141 | + t_menu = gtk.MenuItem(_("Terminal")) |
142 | + term_menu = gtk.Menu() |
143 | + t_menu.set_submenu(term_menu) |
144 | ## Make 'Add Tab' file menu entry |
145 | menu_item4 = gtk.MenuItem(_("Add Tab")) |
146 | - menu.append(menu_item4) |
147 | + term_menu.append(menu_item4) |
148 | menu_item4.connect("activate", lambda *x: self.emit('add_tab')) |
149 | - menu_item4.show() |
150 | - |
151 | ## Make 'Close Tab' file menu entry |
152 | menu_item4 = gtk.MenuItem(_("Close Tab")) |
153 | - menu.append(menu_item4) |
154 | + term_menu.append(menu_item4) |
155 | menu_item4.connect("activate", lambda *x: self.emit('close_tab')) |
156 | - menu_item4.show() |
157 | - |
158 | - ## Make 'User Preferences' file menu entry |
159 | - menu_item5 = gtk.MenuItem(_("Preferences")) |
160 | - menu.append(menu_item5) |
161 | - menu_item5.connect("activate", lambda *x: self.emit('preferences')) |
162 | - menu_item5.show() |
163 | - |
164 | - ## Make 'Quit' file menu entry |
165 | - menu_item6 = gtk.MenuItem(_("Quit")) |
166 | - menu.append(menu_item6) |
167 | - menu_item6.connect("activate", lambda *x: self.emit('quit')) |
168 | - menu_item6.show() |
169 | + |
170 | |
171 | ## HELP MENU ## |
172 | + help_menu = gtk.MenuItem(_("Help")) |
173 | + menu2 = gtk.Menu() |
174 | + help_menu.set_submenu(menu2) |
175 | ## Make 'About' file menu entry |
176 | menu_item11 = gtk.MenuItem(_("About")) |
177 | menu2.append(menu_item11) |
178 | menu_item11.connect("activate", lambda *x: cc_helpers.show_about()) |
179 | - menu_item11.show() |
180 | - |
181 | ## Make 'Help' file menu entry |
182 | menu_item22 = gtk.MenuItem(_("Help-online")) |
183 | menu2.append(menu_item22) |
184 | menu_item22.connect("activate", lambda *x: webbrowser.open( |
185 | "http://launchpad.net/clicompanion")) |
186 | - menu_item22.show() |
187 | |
188 | - self.append(root_menu) # Menu bar(file) |
189 | - self.append(root_menu2) # Menu bar(help) |
190 | + self.append(file_menu) |
191 | + self.append(c_menu) |
192 | + self.append(p_menu) |
193 | + self.append(t_menu) |
194 | + self.append(help_menu) |
195 | self.show_all() |
196 | |
197 | |
198 | @@ -127,6 +174,8 @@ |
199 | __gsignals__ = { |
200 | 'run_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
201 | ()), |
202 | + 'cancel_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
203 | + ()), |
204 | 'add_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
205 | ()), |
206 | 'remove_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
207 | @@ -156,6 +205,13 @@ |
208 | bbox.add(buttonRun) |
209 | buttonRun.connect("clicked", lambda *x: self.emit('run_command')) |
210 | buttonRun.set_tooltip_text(_("Click to run a highlighted command")) |
211 | + |
212 | + # Cancel button |
213 | + buttonCancel = gtk.Button(stock=gtk.STOCK_CANCEL) |
214 | + bbox.add(buttonCancel) |
215 | + buttonCancel.connect("clicked", lambda *x: self.emit('cancel_command')) |
216 | + buttonCancel.set_tooltip_text(_("Click to cancel the running command")) |
217 | + |
218 | # Add button |
219 | buttonAdd = gtk.Button(stock=gtk.STOCK_ADD) |
220 | bbox.add(buttonAdd) |
221 | |
222 | === modified file 'clicompanionlib/plugins.py' |
223 | --- clicompanionlib/plugins.py 2012-01-11 20:16:12 +0000 |
224 | +++ clicompanionlib/plugins.py 2012-01-28 19:42:29 +0000 |
225 | @@ -148,6 +148,8 @@ |
226 | __gsignals__ = { |
227 | 'run_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
228 | (str, str, str)), |
229 | + 'cancel_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
230 | + ()), |
231 | 'add_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
232 | (str, str, str)), |
233 | 'remove_command': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, |
234 | |
235 | === modified file 'clicompanionlib/tabs.py' |
236 | --- clicompanionlib/tabs.py 2012-01-12 20:51:02 +0000 |
237 | +++ clicompanionlib/tabs.py 2012-01-28 19:42:29 +0000 |
238 | @@ -223,7 +223,7 @@ |
239 | menuPopup3.set_label(_('Rename')) |
240 | popupMenu.add(menuPopup3) |
241 | menuPopup3.connect('activate', lambda x: self.rename()) |
242 | - ## right-click popup menu Add Tab |
243 | + ## right-click popup menu Configure |
244 | menuPopup3 = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES) |
245 | menuPopup3.set_label(_('Configure')) |
246 | popupMenu.add(menuPopup3) |
247 | @@ -233,6 +233,48 @@ |
248 | menuPopup3.set_label(_('Add tab')) |
249 | popupMenu.add(menuPopup3) |
250 | menuPopup3.connect('activate', lambda x: self.emit('add_tab')) |
251 | + ## right-click popup menu Process |
252 | + menu_signal = gtk.ImageMenuItem(gtk.STOCK_JUMP_TO) |
253 | + menu_signal.set_label(_('Process')) |
254 | + submenu_signal = gtk.Menu() |
255 | + menu_signal.set_submenu(submenu_signal) |
256 | + popupMenu.add(menu_signal) |
257 | + ## Submenu Abort |
258 | + subitem = gtk.ImageMenuItem(gtk.STOCK_STOP) |
259 | + subitem.set_label(_('Abort (Ctrl+c)')) |
260 | + submenu_signal.add(subitem) |
261 | + subitem.connect('activate', |
262 | + lambda *x: self.cancel_command()) |
263 | + ## Submenu Pause |
264 | + subitem = gtk.ImageMenuItem(gtk.STOCK_MEDIA_PAUSE) |
265 | + subitem.set_label(_('Pause (Ctrl+s)')) |
266 | + submenu_signal.add(subitem) |
267 | + subitem.connect('activate', |
268 | + lambda *x: self.stop_command()) |
269 | + ## Submenu Resume |
270 | + subitem = gtk.ImageMenuItem(gtk.STOCK_MEDIA_PLAY) |
271 | + subitem.set_label(_('Resume (Ctrl+q)')) |
272 | + submenu_signal.add(subitem) |
273 | + subitem.connect('activate', |
274 | + lambda *x: self.resume_command()) |
275 | + ## Submenu Background Suspend |
276 | + subitem = gtk.ImageMenuItem(gtk.STOCK_GOTO_BOTTOM) |
277 | + subitem.set_label(_('Stop and Background (Ctrl+z)')) |
278 | + submenu_signal.add(subitem) |
279 | + subitem.connect('activate', |
280 | + lambda *x: self.background_command()) |
281 | + ## Submenu Foreground |
282 | + subitem = gtk.ImageMenuItem(gtk.STOCK_GO_UP) |
283 | + subitem.set_label(_('Foreground (%)')) |
284 | + submenu_signal.add(subitem) |
285 | + subitem.connect('activate', |
286 | + lambda *x: self.foreground_command()) |
287 | + ## Submenu Background run |
288 | + subitem = gtk.ImageMenuItem(gtk.STOCK_GO_DOWN) |
289 | + subitem.set_label(_('Run in background (% &)')) |
290 | + submenu_signal.add(subitem) |
291 | + subitem.connect('activate', |
292 | + lambda *x: self.bgrun_command()) |
293 | ## right-click popup menu Profiles |
294 | menuit_prof = gtk.MenuItem() |
295 | menuit_prof.set_label(_('Profiles')) |
296 | @@ -301,6 +343,24 @@ |
297 | self.show() |
298 | self.grab_focus() |
299 | |
300 | + def cancel_command(self): |
301 | + self.vte.feed_child(chr(3)) |
302 | + |
303 | + def stop_command(self): |
304 | + self.vte.feed_child(chr(19)) |
305 | + |
306 | + def resume_command(self): |
307 | + self.vte.feed_child(chr(17)) |
308 | + |
309 | + def background_command(self): |
310 | + self.vte.feed_child(chr(26)) |
311 | + |
312 | + def foreground_command(self): |
313 | + self.vte.feed_child('%\n') |
314 | + |
315 | + def bgrun_command(self): |
316 | + self.vte.feed_child('% &\n') |
317 | + |
318 | def change_profile(self, profile): |
319 | dbg(profile) |
320 | self.profile = 'profile::' + profile |
321 | @@ -445,12 +505,37 @@ |
322 | if self.get_n_pages() == 1: |
323 | self.emit('quit') |
324 | |
325 | - def run_command(self, cmd, ui, desc): |
326 | - ## get the current notebook page so the function knows which terminal |
327 | - ## to run the command in. |
328 | + def get_page(self): |
329 | + ## get the current notebook page |
330 | pagenum = self.get_current_page() |
331 | - page = self.get_nth_page(pagenum) |
332 | - page.run_command(cmd, ui, desc) |
333 | + return self.get_nth_page(pagenum) |
334 | + |
335 | + def run_command(self, cmd, ui, desc): |
336 | + self.get_page().run_command(cmd, ui, desc) |
337 | + self.focus() |
338 | + |
339 | + def cancel_command(self): |
340 | + self.get_page().cancel_command() |
341 | + self.focus() |
342 | + |
343 | + def stop_command(self): |
344 | + self.get_page().stop_command() |
345 | + self.focus() |
346 | + |
347 | + def resume_command(self): |
348 | + self.get_page().resume_command() |
349 | + self.focus() |
350 | + |
351 | + def background_command(self): |
352 | + self.get_page().background_command() |
353 | + self.focus() |
354 | + |
355 | + def foreground_command(self): |
356 | + self.get_page().foreground_command() |
357 | + self.focus() |
358 | + |
359 | + def bgrun_command(self): |
360 | + self.get_page().bgrun_command() |
361 | self.focus() |
362 | |
363 | def update_all_term_config(self, config=None): |
364 | @@ -467,11 +552,7 @@ |
365 | tab.update_config(config) |
366 | |
367 | def copy(self): |
368 | - page = self.get_current_page() |
369 | - term = self.get_nth_page(page) |
370 | - term.vte.copy_clipboard() |
371 | + self.get_page().vte.copy_clipboard() |
372 | |
373 | def paste(self, text): |
374 | - page = self.get_current_page() |
375 | - term = self.get_nth_page(page) |
376 | - term.vte.feed_child(text) |
377 | + self.get_page().vte.feed_child(text) |
378 | |
379 | === modified file 'clicompanionlib/view.py' |
380 | --- clicompanionlib/view.py 2012-01-12 20:51:02 +0000 |
381 | +++ clicompanionlib/view.py 2012-01-28 19:42:29 +0000 |
382 | @@ -296,21 +296,37 @@ |
383 | self.vpane.pack2(self.l_vbox, True, True) |
384 | self.add(self.vpane) |
385 | |
386 | - ## signals |
387 | + ## signals from the tab plugins (LocalCommandsList and so) |
388 | self.cmd_notebook.connect('run_command', |
389 | lambda wdg, *args: self.term_notebook.run_command(*args)) |
390 | self.cmd_notebook.connect('show_man', |
391 | lambda wgt, cmd: cc_helpers.ManPage(cmd).run()) |
392 | self.cmd_notebook.connect('quit', lambda *x: gtk.main_quit()) |
393 | + ## Signals from the terminals notebook |
394 | self.term_notebook.connect('quit', lambda *x: gtk.main_quit()) |
395 | self.term_notebook.connect('preferences', lambda *x: self.edit_pref()) |
396 | + ## expander |
397 | self.expander.connect('notify::expanded', |
398 | lambda *x: self.expanded_cb()) |
399 | + ## Signals on the main window |
400 | self.connect("delete_event", self.delete_event) |
401 | self.connect("key-press-event", self.key_clicked) |
402 | + ## Signals from the menus |
403 | menu_bar.connect('quit', lambda *x: gtk.main_quit()) |
404 | menu_bar.connect('run_command', |
405 | lambda *x: self.cmd_notebook.run_command()) |
406 | + menu_bar.connect('cancel_command', |
407 | + lambda *x: self.term_notebook.cancel_command()) |
408 | + menu_bar.connect('stop_command', |
409 | + lambda *x: self.term_notebook.stop_command()) |
410 | + menu_bar.connect('resume_command', |
411 | + lambda *x: self.term_notebook.resume_command()) |
412 | + menu_bar.connect('background_command', |
413 | + lambda *x: self.term_notebook.background_command()) |
414 | + menu_bar.connect('foreground_command', |
415 | + lambda *x: self.term_notebook.foreground_command()) |
416 | + menu_bar.connect('bgrun_command', |
417 | + lambda *x: self.term_notebook.bgrun_command()) |
418 | menu_bar.connect('add_command', |
419 | lambda *x: self.cmd_notebook.add_command()) |
420 | menu_bar.connect('edit_command', |
421 | @@ -320,9 +336,12 @@ |
422 | menu_bar.connect('preferences', lambda *x: self.edit_pref()) |
423 | menu_bar.connect('add_tab', lambda *x: self.term_notebook.add_tab()) |
424 | menu_bar.connect('close_tab', lambda *x: self.term_notebook.quit_tab()) |
425 | + ## signals from the buttons |
426 | self.button_box.connect('quit', lambda *x: gtk.main_quit()) |
427 | self.button_box.connect('run_command', |
428 | lambda *x: self.cmd_notebook.run_command()) |
429 | + self.button_box.connect('cancel_command', |
430 | + lambda *x: self.term_notebook.cancel_command()) |
431 | self.button_box.connect('add_command', |
432 | lambda *x: self.cmd_notebook.add_command()) |
433 | self.button_box.connect('edit_command', |
434 | @@ -441,6 +460,9 @@ |
435 | def run_command(self): |
436 | self.cmd_notebook.run_command() |
437 | |
438 | + def cancel_command(self): |
439 | + self.term_notebook.cancel_command() |
440 | + |
441 | def add_command(self): |
442 | self.cmd_notebook.add_command() |
443 |
Thanks David!
I noticed, that 'cancel' button not work. Trace:
---- lib/python2. 7/dist- packages/ clicompanionlib /view.py" , line 344, in <lambda> notebook. cancel_ command( ))
Traceback (most recent call last):
File "/usr/local/
lambda *x: self.cmd_
AttributeError: 'CommandsNotebook' object has no attribute 'cancel_command'
---