# HG changeset patch # User Yuki KODAMA <endflow....@gmail.com> # Date 1252172007 -32400 # Node ID f0cb3646147c502f2a10c82e00c909d8fbf0cafe # Parent 2873a54f108a3cc2728459ba170f798abebf3811 hgcmd: buffer command output and show it with popup dialog
diff --git a/hggtk/hgcmd.py b/hggtk/hgcmd.py --- a/hggtk/hgcmd.py +++ b/hggtk/hgcmd.py @@ -178,103 +178,148 @@ else: return False +# CmdWidget style constans +STYLE_NORMAL = 'normal' # pbar + popup log viewer +STYLE_COMPACT = 'compact' # pbar + log viewer + class CmdWidget(gtk.VBox): - def __init__(self, textview=True, progressbar=True, buttons=False): + def __init__(self, style=STYLE_NORMAL): gtk.VBox.__init__(self) self.hgthread = None + self.last_pbar_update = 0 - # build UI - if textview: - cmdpane = gtk.ScrolledWindow() - cmdpane.set_shadow_type(gtk.SHADOW_ETCHED_IN) - cmdpane.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.textview = gtk.TextView(buffer=None) - self.textview.set_editable(False) - self.textview.modify_font(pango.FontDescription('Monospace')) - cmdpane.add(self.textview) - self.textbuffer = self.textview.get_buffer() - self.textbuffer.create_tag('error', weight=pango.WEIGHT_HEAVY, - foreground='#900000') - self.pack_start(cmdpane) + # log viewer + if style == STYLE_NORMAL: + self.log = CmdLogWidget() + self.pack_start(log) + elif style == STYLE_COMPACT: + self.dlg = CmdLogDialog() + self.log = self.dlg.get_logwidget() + else: + pass #FIXME should raise exception? - if progressbar: - self.last_pbar_update = 0 + # progress bar box + self.progbox = progbox = gtk.HBox() + self.pack_start(progbox) - self.progbox = progbox = gtk.HBox() - self.pack_start(progbox) + ## log button + if style == STYLE_COMPACT: + img = gtk.Image() + img.set_from_stock(gtk.STOCK_JUSTIFY_LEFT, + gtk.ICON_SIZE_SMALL_TOOLBAR) + self.log_btn = gtk.Button() + self.log_btn.set_image(img) + self.log_btn.set_relief(gtk.RELIEF_NONE) + self.log_btn.set_focus_on_click(False) + self.log_btn.connect('clicked', self.log_clicked) + progbox.pack_start(self.log_btn, False, False) - if buttons: - img = gtk.Image() - img.set_from_stock(gtk.STOCK_JUSTIFY_LEFT, - gtk.ICON_SIZE_SMALL_TOOLBAR) - self.popup_btn = gtk.Button() - self.popup_btn.set_image(img) - self.popup_btn.set_relief(gtk.RELIEF_NONE) - self.popup_btn.set_focus_on_click(False) - progbox.pack_start(self.popup_btn, False, False) + ## progress bar + self.pbar = gtk.ProgressBar() + progbox.pack_start(self.pbar) - self.pbar = gtk.ProgressBar() - progbox.pack_start(self.pbar) + ## stop & close buttons + if style == STYLE_COMPACT: + img = gtk.Image() + img.set_from_stock(gtk.STOCK_STOP, + gtk.ICON_SIZE_SMALL_TOOLBAR) + self.stop_btn = gtk.Button() + self.stop_btn.set_image(img) + self.stop_btn.set_relief(gtk.RELIEF_NONE) + self.stop_btn.set_focus_on_click(False) + self.stop_btn.connect('clicked', self.stop_clicked) + progbox.pack_start(self.stop_btn, False, False) - if buttons: - img = gtk.Image() - img.set_from_stock(gtk.STOCK_STOP, - gtk.ICON_SIZE_SMALL_TOOLBAR) - self.stop_btn = gtk.Button() - self.stop_btn.set_image(img) - self.stop_btn.set_relief(gtk.RELIEF_NONE) - self.stop_btn.set_focus_on_click(False) - self.stop_btn.connect('clicked', self.stop_clicked) - progbox.pack_start(self.stop_btn, False, False) + img = gtk.Image() + img.set_from_stock(gtk.STOCK_CLOSE, + gtk.ICON_SIZE_SMALL_TOOLBAR) + self.close_btn = gtk.Button() + self.close_btn.set_image(img) + self.close_btn.set_relief(gtk.RELIEF_NONE) + self.close_btn.set_focus_on_click(False) + self.close_btn.connect('clicked', self.close_clicked) + progbox.pack_start(self.close_btn, False, False) - img = gtk.Image() - img.set_from_stock(gtk.STOCK_CLOSE, - gtk.ICON_SIZE_SMALL_TOOLBAR) - self.close_btn = gtk.Button() - self.close_btn.set_image(img) - self.close_btn.set_relief(gtk.RELIEF_NONE) - self.close_btn.set_focus_on_click(False) - self.close_btn.connect('clicked', self.close_clicked) - progbox.pack_start(self.close_btn, False, False) - - def after_init(): - self.set_pbar_visible(False) - self.stop_btn.hide() - gobject.idle_add(after_init) + def after_init(): + self.set_pbar(False) + self.set_buttons(stop=False) + gobject.idle_add(after_init) ### public functions ### def execute(self, cmdline, callback, *args, **kargs): + """ + Execute passed command line using 'hgthread'. + When the command terminated, callback function is called + with return code. + + cmdline: command line string. + callback: function called after terminated the thread. + + def callback(returncode, ...) + + returncode: See the description of 'hgthread' about return code. + """ if self.hgthread and self.hgthread.isAlive(): return if self.hgthread is None: + self.log.clear() self.hgthread = hgthread.HgThread(cmdline[1:]) self.hgthread.start() gobject.timeout_add(10, self.process_queue, callback, args, kargs) def is_done(): - # show progressbar if it's still working + # show progress bar if it's still working if self.hgthread and self.hgthread.isAlive(): - self.set_pbar_visible(True) - self.stop_btn.show() - self.close_btn.hide() + self.set_pbar(True) + self.set_buttons(stop=True, close=False) return False gobject.timeout_add(500, is_done) def stop(self): + """ + Terminate the thread forcibly. + """ if self.hgthread: self.hgthread.terminate() + self.set_pbar(True) + self.set_buttons(stop=False, close=True) - def set_pbar_visible(self, visible): + def set_pbar(self, visible): + """ + Set visible property of the progress bar box. + + visible: if True, the progress bar box is shown. + """ if hasattr(self, 'progbox'): self.progbox.set_property('visible', visible) - def enable_buttons(self, popup=True, stop=True): - if hasattr(self, 'popup_btn'): - self.popup_btn.set_property('visible', popup) - if hasattr(self, 'stop_btn'): + def set_buttons(self, log=None, stop=None, close=None): + """ + Set visible properties of buttons on the progress bar box. + If omitted all argments, it does nothing. + + log: if True, log button is shown. (default: None) + stop: if True, stop button is shown. (default: None) + close: if True, close button is shown. (default: None) + """ + if not log is None and hasattr(self, 'log_btn'): + self.log_btn.set_property('visible', log) + if not stop is None and hasattr(self, 'stop_btn'): self.stop_btn.set_property('visible', stop) + if not close is None and hasattr(self, 'close_btn'): + self.close_btn.set_property('visible', close) + + def show_log(self): + """ + Show log viewer. + """ + if hasattr(self, 'dlg'): + if not self.dlg.get_property('visible'): + self.dlg.show_all() + else: + self.dlg.present() ### internal use functions ### @@ -297,33 +342,33 @@ """ self.hgthread.process_dialogs() - if hasattr(self, 'textbuffer'): - enditer = self.textbuffer.get_end_iter() - while self.hgthread.getqueue().qsize(): - try: - msg = self.hgthread.getqueue().get(0) - self.textbuffer.insert(enditer, hglib.toutf(msg)) - self.textview.scroll_to_mark(self.textbuffer.get_insert(), 0) - except Queue.Empty: - pass - while self.hgthread.geterrqueue().qsize(): - try: - msg = self.hgthread.geterrqueue().get(0) - self.textbuffer.insert_with_tags_by_name(enditer, msg, 'error') - self.textview.scroll_to_mark(self.textbuffer.get_insert(), 0) - except Queue.Empty: - pass + # output to buffer + while self.hgthread.getqueue().qsize(): + try: + msg = self.hgthread.getqueue().get(0) + self.log.append(hglib.toutf(msg)) + except Queue.Empty: + pass + while self.hgthread.geterrqueue().qsize(): + try: + msg = self.hgthread.geterrqueue().get(0) + self.log.append(hglib.toutf(msg), error=True) + except Queue.Empty: + pass + + # update progress bar self.update_progress() + + # check thread if not self.hgthread.isAlive(): returncode = self.hgthread.return_code() if returncode == 0: - self.set_pbar_visible(False) + self.set_pbar(False) else: - self.set_pbar_visible(True) - self.stop_btn.hide() - self.close_btn.show() + self.set_pbar(True) + self.set_buttons(stop=False, close=True) if returncode is None: - self.write(_('\n[command interrupted]')) + self.log.append(_('\n[command interrupted]')) self.hgthread = None def call_callback(): callback(returncode, *args, **kargs) @@ -332,19 +377,94 @@ else: return True # Continue polling - def write(self, msg, append=True): - if hasattr(self, 'textbuffer'): - msg = hglib.toutf(msg) - if append: - enditer = self.textbuffer.get_end_iter() - self.textbuffer.insert(enditer, msg) - else: - self.textbuffer.set_text(msg) + ### signal handlers ### - ### signal handlers ### + def log_clicked(self, button): + self.show_log() def stop_clicked(self, button): self.stop() def close_clicked(self, button): - self.set_pbar_visible(False) + self.set_pbar(False) + +class CmdLogWidget(gtk.VBox): + + def __init__(self): + gtk.VBox.__init__(self) + + # scrolled pane + pane = gtk.ScrolledWindow() + pane.set_shadow_type(gtk.SHADOW_ETCHED_IN) + pane.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.add(pane) + + # log textview + self.textview = gtk.TextView(buffer=None) + self.textview.set_editable(False) + self.textview.modify_font(pango.FontDescription('Monospace')) + pane.add(self.textview) + + # text buffer + self.buffer = self.textview.get_buffer() + self.buffer.create_tag('error', weight=pango.WEIGHT_HEAVY, + foreground='#900000') + + ### public functions ### + + def append(self, text, error=False): + """ + Insert the text to the end of TextView. + + text: string you want to append. + error: if True, append text with 'error' tag. (default: False) + """ + enditer = self.buffer.get_end_iter() + if error: + self.buffer.insert_with_tags_by_name(enditer, text, 'error') + else: + self.buffer.insert(enditer, text) + self.textview.scroll_to_mark(self.buffer.get_insert(), 0) + + def clear(self): + """ + Clear all text in TextView. + """ + self.buffer.delete(self.buffer.get_start_iter(), + self.buffer.get_end_iter()) + +class CmdLogDialog(gtk.Window): + + def __init__(self, title=_('Command Log')): + gtk.Window.__init__(self, type=gtk.WINDOW_TOPLEVEL) + gtklib.set_tortoise_icon(self, 'hg.ico') + self.set_title(title) + self.set_default_size(320, 240) + self.connect('delete-event', self.delete_event) + + # log viewer & buffer + self.log = CmdLogWidget() + self.add(self.log) + + # change window decorations + self.realize() + if self.window: + self.window.set_decorations(gtk.gdk.DECOR_BORDER | \ + gtk.gdk.DECOR_RESIZEH | \ + gtk.gdk.DECOR_TITLE | \ + gtk.gdk.DECOR_MENU | \ + gtk.gdk.DECOR_MINIMIZE) + + ### public functions ### + + def get_logwidget(self): + """ + Return CmdLogWidget instance. + """ + return self.log + + ### signal handlers ### + + def delete_event(self, widget, event): + self.hide() + return True diff --git a/hggtk/thgmq.py b/hggtk/thgmq.py --- a/hggtk/thgmq.py +++ b/hggtk/thgmq.py @@ -182,7 +182,7 @@ pane.add(self.list) ## command widget - self.cmd = hgcmd.CmdWidget(textview=False, buttons=True) + self.cmd = hgcmd.CmdWidget(style=hgcmd.STYLE_COMPACT) mainbox.pack_start(self.cmd, False, False) # accelerator
thg-kuy_rev3844.patch
Description: Binary data
------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july
_______________________________________________ Tortoisehg-develop mailing list Tortoisehg-develop@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tortoisehg-develop