# HG changeset patch # User Yuki KODAMA <[email protected]> # 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 [email protected] https://lists.sourceforge.net/lists/listinfo/tortoisehg-develop
