hotssh r39 - in trunk/hotssh: . hotvte
- From: walters svn gnome org
- To: svn-commits-list gnome org
- Subject: hotssh r39 - in trunk/hotssh: . hotvte
- Date: Tue, 29 Jul 2008 00:59:22 +0000 (UTC)
Author: walters
Date: Tue Jul 29 00:59:22 2008
New Revision: 39
URL: http://svn.gnome.org/viewvc/hotssh?rev=39&view=rev
Log:
Merge branch 'favicon'
Modified:
trunk/hotssh/hotvte/vteterm.py
trunk/hotssh/hotvte/vtewindow.py
trunk/hotssh/sshwindow.py
Modified: trunk/hotssh/hotvte/vteterm.py
==============================================================================
--- trunk/hotssh/hotvte/vteterm.py (original)
+++ trunk/hotssh/hotvte/vteterm.py Tue Jul 29 00:59:22 2008
@@ -132,7 +132,7 @@
gobject.timeout_add(250, self.__idle_do_cmd_fork, cmd, cwd, ptyfd, initbuf)
def __idle_do_cmd_fork(self, cmd, cwd, ptyfd, initbuf):
- _logger.debug("Forking cmd: %s", cmd)
+ _logger.debug("Forking cmd: %r", cmd)
self.__term.connect("child-exited", self._on_child_exited)
if cwd:
kwargs = {'directory': cwd}
Modified: trunk/hotssh/hotvte/vtewindow.py
==============================================================================
--- trunk/hotssh/hotvte/vtewindow.py (original)
+++ trunk/hotssh/hotvte/vtewindow.py Tue Jul 29 00:59:22 2008
@@ -43,6 +43,10 @@
yield (title, markup, None)
class TabbedVteWidget(VteTerminalWidget):
+ __gsignals__ = {
+ "metadata-changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
+ }
+
def __init__(self, cmd=None, *args, **kwargs):
super(TabbedVteWidget, self).__init__(cmd=cmd, *args, **kwargs)
self.__title = ' '.join(cmd)
@@ -50,6 +54,9 @@
def get_title(self):
return self.__title
+ def get_pixbuf(self):
+ return None
+
class VteWindow(gtk.Window):
__gsignals__ = {
"shutdown" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
@@ -138,9 +145,23 @@
def remote_new_tab(self, args, cwd):
return self.new_tab(args, cwd)
-
+
+ def __sync_metadata(self, widget):
+ title = widget.get_title()
+ label = widget.get_data('tab-label')
+ label.set_text(title)
+ self.__tips.set_tip(label, title)
+ img = widget.get_data('tab-image')
+ pixbuf_or_path = widget.get_pixbuf()
+ if isinstance(pixbuf_or_path,basestring):
+ pixbuf = gtk.gdk.pixbuf_new_from_file(pixbuf_or_path)
+ else:
+ pixbuf = pixbuf_or_path
+ img.set_from_pixbuf(pixbuf)
+
def append_widget(self, term):
idx = self.__notebook.append_page(term)
+ term.connect('metadata-changed', self.__sync_metadata)
term.get_vte().connect('selection-changed', self.__sync_selection_sensitive)
term.get_term().set_copy_paste_actions(self.__ag.get_action('Copy'), self.__ag.get_action('Paste'))
if hasattr(term, 'has_close'):
@@ -151,10 +172,8 @@
term.connect('close', self.__on_widget_close)
if hasattr(self.__notebook, 'set_tab_reorderable'):
self.__notebook.set_tab_reorderable(term, True)
- label = self.__add_widget_title(term)
- title = term.get_title()
- label.set_text(title)
- self.__tips.set_tip(label, title)
+ (label, icon) = self.__add_widget_title(term)
+ self.__sync_metadata(term)
term.show_all()
self.__notebook.set_current_page(idx)
term.get_vte().grab_focus()
@@ -249,6 +268,9 @@
def __add_widget_title(self, w):
hbox = gtk.HBox()
+ piximg = gtk.Image()
+ w.set_data('tab-image', piximg)
+ hbox.pack_start(piximg, expand=False, padding=6)
label = gtk.Label('<notitle>')
label.set_selectable(False)
label.set_ellipsize(pango.ELLIPSIZE_END)
@@ -267,10 +289,10 @@
hbox.pack_start(close, expand=False)
hbox.show_all()
self.__notebook.set_tab_label(w, hbox)
- w.set_data('hotwire-tab-label', label)
+ w.set_data('tab-label', label)
self.__notebook.set_tab_label_packing(w, True, True, gtk.PACK_START)
self.__sync_tabs_visible()
- return label
+ return (label, piximg)
def __close_tab(self, w):
self.__remove_page_widget(w)
Modified: trunk/hotssh/sshwindow.py
==============================================================================
--- trunk/hotssh/sshwindow.py (original)
+++ trunk/hotssh/sshwindow.py Tue Jul 29 00:59:22 2008
@@ -19,7 +19,7 @@
import os,sys,platform,logging,getopt,re
import locale,threading,subprocess,time
import signal,tempfile,shutil,stat,pwd
-import datetime, gettext
+import datetime,gettext,sha,commands,errno
from StringIO import StringIO
import xml.dom.minidom
@@ -58,6 +58,18 @@
symbols = libc.backtrace_symbols(btdata, c_int(btcount))
print symbols
+def userhost_pair_to_string(user, host, port=None):
+ host = hostport_pair_to_string(host, port)
+ if user:
+ return user + '@' + host
+ return host
+
+def hostport_pair_to_string(host, port=None):
+ hostport = host
+ if port is not None:
+ hostport += (':%s' % (port,))
+ return hostport
+
class HotSshAboutDialog(gtk.AboutDialog):
def __init__(self):
super(HotSshAboutDialog, self).__init__()
@@ -88,12 +100,17 @@
class SshConnectionHistory(object):
def __init__(self):
- self.__statedir = os.path.expanduser('~/.hotwire/state')
+ # We want to upgrade from the old Hotwire-derived location into the new ~/.hotssh
+ self.__oldstatedir = os.path.expanduser('~/.hotwire/state')
+ self.__statedir = os.path.expanduser('~/.hotssh')
try:
os.makedirs(self.__statedir)
except:
pass
- self.__path = path =os.path.join(self.__statedir, 'ssh.sqlite')
+ self.__path = path = os.path.join(self.__statedir, 'history.sqlite')
+ oldpath = os.path.join(self.__oldstatedir, 'ssh.sqlite')
+ if os.path.exists(oldpath) and not os.path.exists(self.__path):
+ shutil.copy2(oldpath, path)
self.__conn = sqlite3.connect(path, isolation_level=None)
cursor = self.__conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS Connections (bid INTEGER PRIMARY KEY AUTOINCREMENT, host TEXT, user TEXT, options TEXT, conntime DATETIME)''')
@@ -118,7 +135,7 @@
for user,host,options,conntime in cursor.execute(q, params):
if len(seen) >= limit:
break
- if user:
+ if user and host:
uhost = user+'@'+host
else:
uhost = host
@@ -132,10 +149,12 @@
for user,host,options,ts in self.get_recent_connections_search(host):
yield user
- def add_connection(self, host, user, options):
+ def add_connection(self, user, host, options):
+ if host is None or host == '':
+ return
cursor = self.__conn.cursor()
cursor.execute('''BEGIN TRANSACTION''')
- cursor.execute('''INSERT INTO Connections VALUES (NULL, ?, ?, ?, ?)''', (user, host, ' '.join(options), datetime.datetime.now()))
+ cursor.execute('''INSERT INTO Connections VALUES (NULL, ?, ?, ?, ?)''', (host, user, ' '.join(options), datetime.datetime.now()))
cursor.execute('''COMMIT''')
def get_color_for_host(self, host):
@@ -156,12 +175,27 @@
_history_instance = SshConnectionHistory()
return _history_instance
-class OpenSSHKnownHostsDB(object):
+class OpenSSHKnownHostsDB(gobject.GObject):
+ __gsignals__ = {
+ "changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, []),
+ }
def __init__(self):
super(OpenSSHKnownHostsDB, self).__init__()
self.__path = os.path.expanduser('~/.ssh/known_hosts')
self.__hostcache_ts_size = (None, None)
self.__hostcache = None
+ self.__faviconcache = os.path.expanduser('~/.hotssh/favicons')
+ self.__pixbufcache = {}
+
+ def __get_favicon_cache(self):
+ try:
+ os.makedirs(self.__faviconcache)
+ except OSError, e:
+ if e.errno == errno.EEXIST:
+ pass
+ else:
+ raise
+ return self.__faviconcache
def __read_hosts(self):
try:
@@ -170,7 +204,7 @@
except:
_logger.debug("failed to open known hosts")
return
- hosts = set()
+ hosts = {}
for line in f:
if not line or line.startswith('|'):
continue
@@ -179,8 +213,11 @@
host = hostip.split(',', 1)[0]
else:
host = hostip
+ hostkey_type,hostkey = rest.split(' ', 1)
+ hostkey_type = hostkey_type.strip()
+ hostkey = hostkey.strip()
host = host.strip()
- hosts.add(host)
+ hosts[host] = (hostkey_type, hostkey)
f.close()
return hosts
@@ -193,7 +230,49 @@
if ts_size is not None and self.__hostcache_ts_size != ts_size:
self.__hostcache = self.__read_hosts()
self.__hostcache_ts_size = ts_size
- return self.__hostcache
+ return self.__hostcache.iterkeys()
+
+ def get_favicon_for_host(self, host, port=None):
+ hostport = hostport_pair_to_string(host, port)
+ if self.__hostcache is None or (hostport not in self.__hostcache.iterkeys()):
+ return None
+ return self.get_favicon_for_hostkey(*self.__hostcache[hostport])
+
+ def render_cached_favicon(self, path):
+ bn = os.path.basename(path)
+ if bn not in self.__pixbufcache:
+ self.__pixbufcache[bn] = gtk.gdk.pixbuf_new_from_file_at_size(path, 16, 16)
+ return self.__pixbufcache[bn]
+
+ def __get_favicon_path(self, hostkey_type, hostkey):
+ hostkey_hash = sha.new(hostkey_type+hostkey).hexdigest()
+ return os.path.join(self.__get_favicon_cache(), hostkey_hash + '.png')
+
+ def get_favicon_for_hostkey(self, hostkey_type, hostkey):
+ cache = self.__get_favicon_cache()
+ if cache is None:
+ return None
+ path = self.__get_favicon_path(hostkey_type, hostkey)
+ try:
+ stbuf = os.stat(path)
+ except:
+ return None
+ return (path, stbuf[stat.ST_MTIME])
+
+ def save_favicon(self, host, port, favicon):
+ hostport = hostport_pair_to_string(host, port)
+ args = list(self.__hostcache[hostport])
+ args.append(favicon)
+ return self.save_favicon_for_hostkey(*args)
+
+ def save_favicon_for_hostkey(self, hostkey_type, hostkey, favicon_tmppath):
+ cache = self.__get_favicon_cache()
+ if cache is None:
+ return None
+ path = self.__get_favicon_path(hostkey_type, hostkey)
+ shutil.move(favicon_tmppath, path)
+ self.emit('changed')
+ return path
_openssh_hosts_db = OpenSSHKnownHostsDB()
@@ -376,6 +455,9 @@
self.__recent_view.get_selection().connect('changed', self.__on_recent_selected)
self.__recent_view.connect('row-activated', self.__on_recent_activated)
tab.add(self.__recent_view)
+ colidx = self.__recent_view.insert_column_with_data_func(-1, '',
+ gtk.CellRendererPixbuf(),
+ self.__render_favicon)
colidx = self.__recent_view.insert_column_with_data_func(-1, _('Connection'),
gtk.CellRendererText(),
self.__render_userhost)
@@ -434,7 +516,7 @@
def __render_userhost(self, col, cell, model, iter):
user = model.get_value(iter, 0)
host = model.get_value(iter, 1)
- if user:
+ if user and host:
userhost = user + '@' + host
else:
userhost = host
@@ -444,9 +526,20 @@
if name is None:
name = self.__default_username
self.__user_entry.set_text(name)
+
+ def __render_favicon(self, col, cell, model, it):
+ user = model.get_value(it, 0)
+ host = model.get_value(it, 1)
+ favicondata = _openssh_hosts_db.get_favicon_for_host(host, None)
+ if favicondata is not None:
+ (favicon_path,mtime) = favicondata
+ pixbuf = _openssh_hosts_db.render_cached_favicon(favicon_path)
+ cell.set_property('pixbuf',pixbuf)
+ else:
+ cell.set_property('pixbuf', None)
- def __render_time_recency(self, col, cell, model, iter, curtime):
- val = model.get_value(iter, 2)
+ def __render_time_recency(self, col, cell, model, it, curtime):
+ val = model.get_value(it, 2)
deltastr = timesince(val, curtime)
cell.set_property('text', deltastr)
@@ -609,6 +702,157 @@
# TODO - openssh should really do this out of the box
return ['-oControlMaster=auto', '-oControlPath=' + os.path.join(get_controlpath(), 'master-%r %h:%p')]
+class AsyncCommandWithOutput(gobject.GObject):
+ __gsignals__ = {
+ "timeout" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, [gobject.TYPE_STRING]),
+
+ "complete" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (bool,
+ int,
+ gobject.TYPE_STRING))
+ }
+
+ user = property(lambda self: self.__user)
+ host = property(lambda self: self.__host)
+ port = property(lambda self: self.__port)
+ output = property(lambda self: self.__output.get_value())
+
+ def __init__(self, user, host, port, cmdstart, cmdend, timeout=7000, hostappend='', getoutput=True):
+ super(AsyncCommandWithOutput, self).__init__()
+ self.__user = user
+ self.__host = host
+ self.__port = port
+ cmd = list(cmdstart)
+ cmd.extend(get_connection_sharing_args())
+ if port:
+ cmd.extend(['-p', str(port)])
+ if user:
+ cmd.append('-oUser=' + user)
+ # hostappend is a dirty hack to handle scp's syntax
+ cmd.extend(['-oBatchMode=true', host+hostappend])
+ cmd.extend(cmdend)
+ self.__cmd = cmd
+ self.__starttime = time.time()
+ nullf = open(os.path.devnull, 'w')
+ _logger.debug("starting subprocess cmd=%r", cmd)
+ if getoutput:
+ stdout_target = subprocess.PIPE
+ else:
+ stdout_target = nullf
+ self.__subproc = subprocess.Popen(cmd, stdout=stdout_target, stderr=nullf)
+ nullf.close()
+ if getoutput:
+ self.__io_watch_id = gobject.io_add_watch(self.__subproc.stdout,
+ gobject.IO_IN|gobject.IO_ERR|gobject.IO_HUP,
+ self.__on_io)
+ self.__output = StringIO()
+ self.__child_watch_id = gobject.child_watch_add(self.__subproc.pid, self.__on_exited)
+ self.__timeout_id = gobject.timeout_add(timeout, self.__on_timeout)
+
+ def __on_io(self, source, condition):
+ have_read = condition & gobject.IO_IN
+ if have_read:
+ _logger.debug("got status output")
+ self.__output.write(os.read(source.fileno(), 8192))
+ if ((condition & gobject.IO_HUP) or (condition & gobject.IO_ERR)):
+ source.close()
+ _logger.debug("got condition %s, cancelling status io check", condition)
+ return False
+ else:
+ return have_read
+
+ def __on_timeout(self):
+ _logger.debug("timeout for host=%r cmd=%r", self.__host, self.__cmd)
+ try:
+ os.kill(self.__subproc.pid, signal.SIGHUP)
+ except OSError, e:
+ _logger.debug("failed to signal pid %s", pid, exc_info=True)
+ pass
+ self.emit('timeout', self.__output.getvalue())
+ self.__timeout_id = 0
+ return False
+
+ def __on_exited(self, pid, condition):
+ _logger.debug("command exited host=%r condition=%r cmd=%r", self.__host, condition, self.__cmd)
+ if self.__timeout_id == 0:
+ _logger.debug("command exited (but timeout already run")
+ return
+ gobject.source_remove(self.__timeout_id)
+ self.__timeout_id = 0
+ self.emit('complete', condition == 0, time.time() - self.__starttime, self.__output.getvalue())
+ return False
+
+class FaviconRetriever(gobject.GObject):
+ __gsignals__ = {
+ "favicon-loaded" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, [str]),
+ }
+
+ user = property(lambda self: self.__user)
+ host = property(lambda self: self.__host)
+ port = property(lambda self: self.__port)
+
+ def __init__(self, user, host, port=None):
+ super(FaviconRetriever, self).__init__()
+ self.__user = user
+ self.__host = host
+ self.__port = port
+ self.__cached_mtime = None
+ self.__favicon_mtime = None
+ self.__tmp_favicon_path = None
+
+ hostport = userhost_pair_to_string(user, host, port)
+ _logger.debug("loading favicon for %s", hostport)
+ cmd = commands.mkarg('''python -c 'import os,sys,stat; print os.stat(sys.argv[1])[stat.ST_MTIME]' /etc/favicon.png''')
+ req = AsyncCommandWithOutput(user, host, port, ['ssh'], ['sh', '-c', cmd])
+ req.connect('timeout', self.__on_mtime_timeout)
+ req.connect('complete', self.__on_mtime_complete)
+ self.__active_req = req
+
+ def __on_mtime_timeout(self, req, curoutput):
+ _logger.debug("favicon mtime retrieval timeout")
+ return False
+
+ def __on_mtime_complete(self, req, status, elapsed_time, output):
+ _logger.debug("favicon mtime retrieval complete, status: %r", status)
+ if not status:
+ return False
+ mtime = int(output.strip())
+ self.__favicon_mtime = mtime
+ gobject.idle_add(self.__idle_start_scp)
+
+ @log_except(_logger)
+ def __idle_start_scp(self):
+ current = _openssh_hosts_db.get_favicon_for_host(self.__host, self.__port)
+ cached_mtime = 0
+ if current is not None:
+ (_, mtime) = current
+ cached_mtime = mtime
+ if self.__favicon_mtime > cached_mtime:
+ (fd, tmppath) = tempfile.mkstemp('.png', 'favicon')
+ self.__tmp_favicon_path = tmppath
+ os.close(fd)
+
+ _logger.debug("creating scp request")
+ req = AsyncCommandWithOutput(self.__user, self.__host, self.__port,
+ ['scp', '-p', '-q'], [tmppath],
+ hostappend=':/etc/favicon.png', timeout=15000, getoutput=False)
+ req.connect('timeout', self.__on_favicon_timeout)
+ req.connect('complete', self.__on_favicon_complete)
+ self.__active_req = req
+ else:
+ _logger.debug("favicon is up to date")
+ return False
+
+ def __on_favicon_timeout(self, req, elapsed):
+ _logger.debug("favicon data retrieval timeout (%r elapsed)", elapsed)
+ return False
+
+ def __on_favicon_complete(self, req, status, elapsed_time, output):
+ _logger.debug("favicon data retrieval complete; elapsed=%r status=%r", elapsed_time, status)
+ if not status:
+ return False
+ self.emit('favicon-loaded', self.__tmp_favicon_path)
+ return False
+
class HostConnectionMonitor(gobject.GObject):
__gsignals__ = {
"host-status" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,
@@ -674,7 +918,7 @@
return False
def __check_timeout(self, host):
- _logger.debug("timeout for host=%s", host)
+ _logger.debug("timeout for host=%r", host)
try:
(starttime, pid, timeout_id, child_watch_id, io_watch_id) = self.__check_statuses[host]
except KeyError, e:
@@ -714,6 +958,7 @@
"close" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, []),
# Emitted when we do a reconnect so that other tabs for this host can pick it up
"reconnect" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, []),
+ "metadata-changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
}
latency = property(lambda self: self.__latency)
@@ -725,16 +970,25 @@
ssh_opt_with_args = "bcDeFiLlmOopRSw"
ssh_opt_witouth_args = "1246AaCfgKkMNnqsTtVvXxY"
- def __init__(self, args, cwd, actions=None):
+ def __init__(self, args, cwd, actions=None, inituser=None, inithost=None):
super(SshTerminalWidget, self).__init__()
- self.__init_state()
+
self.__args = args
self.__sshcmd = list(get_base_sshcmd())
self.__cwd = cwd
- self.__host = None
+ self.__user = inituser
+ self.__host = inithost
self.__port = None
self.__sshopts = []
self.__actions = actions
+ self.__idle_start_favicon_id = 0
+ self.__favicon_path = None
+ self.__favicon_pixbuf = None
+ self.__favicon_retriever = None
+ self.__favicon_retriever_connections = []
+
+ self.__init_state()
+
enable_connection_sharing = True
need_arg = False
this_is_port = False
@@ -750,7 +1004,10 @@
self.__port = host_port[1]
else:
self.__host = arg
- self.__sshcmd.append(self.__host)
+ try:
+ (self.__user,self.__host) = self.__host.split('@', 1)
+ except ValueError, e:
+ pass
elif this_is_port:
self.__port = arg
this_is_port = False
@@ -768,6 +1025,10 @@
need_arg = False
self.__sshcmd.append(arg)
+ if self.__user:
+ self.__sshcmd.append('-oUser=' + self.__user)
+ self.__sshcmd.append(self.__host)
+
if not port_in_args and self.__port:
self.__sshcmd.append("-p")
self.__sshcmd.append(self.__port)
@@ -785,6 +1046,15 @@
self.ssh_connect()
def __init_state(self):
+ if self.__idle_start_favicon_id > 0:
+ gobject.source_remove(self.__idle_start_favicon_id)
+ self.__idle_start_favicon_id = 0
+ if self.__favicon_retriever is not None:
+ for sigid in self.__favicon_retriever_connections:
+ self.__favicon_retriever.disconnect(sigid)
+ self.__favicon_retriever_connections = []
+ self.__favicon_retriever = None
+
self.__global_connection_changed = False
self.__connecting_state = False
self.__connected = None
@@ -817,6 +1087,12 @@
def __sync_msg(self):
return
+
+ def __on_favicon_loaded(self, retriever, faviconpath):
+ _logger.debug("favicon loaded; path=%r", faviconpath)
+ self.__favicon_path = _openssh_hosts_db.save_favicon(self.__host, self.__port, faviconpath)
+ self.__favicon_pixbuf = _openssh_hosts_db.render_cached_favicon(self.__favicon_path)
+ self.emit('metadata-changed')
def ssh_connect(self):
self.__connecting_state = True
@@ -829,6 +1105,20 @@
term.emit('focus', True)
self.__msgarea_mgr.clear()
self.__sync_msg()
+
+ current = _openssh_hosts_db.get_favicon_for_host(self.__host, self.__port)
+ if current is not None:
+ (pixbufpath, mtime) = current
+ self.__favicon_path = pixbufpath
+ self.__favicon_pixbuf = _openssh_hosts_db.render_cached_favicon(pixbufpath)
+ self.__idle_start_favicon_id = gobject.timeout_add(3000, self.__idle_start_favicon)
+
+ def __idle_start_favicon(self):
+ if self.__favicon_retriever is not None:
+ return
+ self.__favicon_retriever = FaviconRetriever(self.__user, self.__host, self.__port)
+ sigid = self.__favicon_retriever.connect('favicon-loaded', self.__on_favicon_loaded)
+ self.__favicon_retriever_connections.append(sigid)
def ssh_reconnect(self):
# TODO - do this in a better way
@@ -877,10 +1167,16 @@
def get_title(self):
return self.get_host()
+
+ def get_pixbuf(self):
+ return self.__favicon_pixbuf
def get_host(self):
return self.__host
+ def get_user(self):
+ return self.__user
+
def get_port(self):
return self.__port
@@ -939,9 +1235,9 @@
self.__merge_ssh_ui()
- def __add_to_history(self, args):
- user = None
- host = None
+ def __add_to_history(self, args, inituser=None, inithost=None):
+ user = inituser
+ host = inithost
need_arg = False
options = []
@@ -954,7 +1250,7 @@
if need_arg:
options.append(arg)
- else:
+ elif host is None:
if arg.find('@') >= 0:
(user, host) = arg.split('@', 1)
else:
@@ -963,12 +1259,12 @@
self.__connhistory.add_connection(user, host, options)
- def new_tab(self, args, cwd):
- if len(args) == 0:
+ def new_tab(self, args, cwd, **kwargs):
+ if len(args) == 0 and len(kwargs) == 0:
self.open_connection_dialog(exit_on_cancel=True)
else:
- self.__add_to_history(args)
- term = SshTerminalWidget(args=args, cwd=cwd, actions=self.__action_group)
+ self.__add_to_history(args, **kwargs)
+ term = SshTerminalWidget(args=args, cwd=cwd, actions=self.__action_group, **kwargs)
self.append_widget(term)
def append_widget(self, w):
@@ -984,13 +1280,17 @@
if self.__in_reconnect:
return
self.__in_reconnect = True
+ changed_user = changed_widget.get_user()
changed_host = changed_widget.get_host()
- _logger.debug("reconnecting all widgets for host %s", changed_host)
+ changed_userhost = userhost_pair_to_string(changed_user, changed_host)
+ _logger.debug("reconnecting all widgets for host %s", changed_userhost)
for widget in self._get_notebook().get_children():
if changed_widget is widget:
continue
host = widget.get_host()
- if host != changed_host:
+ user = widget.get_user()
+ userhost = userhost_pair_to_string(user, host)
+ if userhost != changed_userhost:
continue
widget.ssh_reconnect()
self.__in_reconnect = False
@@ -1133,11 +1433,10 @@
def __copy_connection_cb(self, action):
notebook = self._get_notebook()
widget = notebook.get_nth_page(notebook.get_current_page())
+ user = widget.get_user()
host = widget.get_host()
opts = widget.get_options()
- args = list(opts)
- args.append(host)
- self.new_tab(args, None)
+ self.new_tab(widget.get_options(), None, inituser=user, inithost=host)
def open_connection_dialog(self, exit_on_cancel=False):
win = ConnectDialog(parent=self, history=self.__connhistory, local_avahi=self.__local_avahi)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]