source: deluge/ui/gtkui/connectionmanager.py@ af6b27

2.0.x develop
Last change on this file since af6b27 was af6b27, checked in by Calum Lind <calumlind+deluge@gmail.com>, 9 years ago

[Lint] Add flake8-quotes to tox and fix bad quotes

  • Property mode set to 100644
File size: 28.4 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com>
4#
5# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
6# the additional special exception to link portions of this program with the OpenSSL library.
7# See LICENSE for more details.
8#
9
10import hashlib
11import logging
12import os
13import time
14from socket import gethostbyname
15
16import gtk
17from twisted.internet import reactor
18
19import deluge.component as component
20from deluge.common import resource_filename
21from deluge.configmanager import ConfigManager, get_config_dir
22from deluge.error import AuthenticationRequired, BadLoginError, IncompatibleClient
23from deluge.ui.client import Client, client
24from deluge.ui.common import get_localhost_auth
25from deluge.ui.gtkui.common import get_deluge_icon, get_logo
26from deluge.ui.gtkui.dialogs import AuthenticationDialog, ErrorDialog
27
28log = logging.getLogger(__name__)
29
30DEFAULT_HOST = '127.0.0.1'
31DEFAULT_PORT = 58846
32
33HOSTLIST_COL_ID = 0
34HOSTLIST_COL_HOST = 1
35HOSTLIST_COL_PORT = 2
36HOSTLIST_COL_STATUS = 3
37HOSTLIST_COL_USER = 4
38HOSTLIST_COL_PASS = 5
39HOSTLIST_COL_VERSION = 6
40
41
42HOSTLIST_PIXBUFS = [
43 # This is populated in ConnectionManager.show
44]
45
46HOSTLIST_STATUS = [
47 'Offline',
48 'Online',
49 'Connected'
50]
51
52
53def cell_render_host(column, cell, model, row, data):
54 host, port, username = model.get(row, *data)
55 text = host + ':' + str(port)
56 if username:
57 text = username + '@' + text
58 cell.set_property('text', text)
59
60
61def cell_render_status(column, cell, model, row, data):
62 status = model[row][data]
63 pixbuf = None
64 if status in HOSTLIST_STATUS:
65 pixbuf = HOSTLIST_PIXBUFS[HOSTLIST_STATUS.index(status)]
66
67 cell.set_property('pixbuf', pixbuf)
68
69
70class ConnectionManager(component.Component):
71 def __init__(self):
72 component.Component.__init__(self, 'ConnectionManager')
73 self.gtkui_config = ConfigManager('gtkui.conf')
74 self.config = self.__load_config()
75 self.running = False
76
77 # Component overrides
78 def start(self):
79 pass
80
81 def stop(self):
82 # Close this dialog when we are shutting down
83 if self.running:
84 self.connection_manager.response(gtk.RESPONSE_CLOSE)
85
86 def shutdown(self):
87 pass
88
89 def __load_config(self):
90 auth_file = get_config_dir('auth')
91 if not os.path.exists(auth_file):
92 from deluge.common import create_localclient_account
93 create_localclient_account()
94
95 localclient_username, localclient_password = get_localhost_auth()
96 default_config = {
97 'hosts': [(
98 hashlib.sha1(str(time.time())).hexdigest(),
99 DEFAULT_HOST,
100 DEFAULT_PORT,
101 localclient_username,
102 localclient_password
103 )]
104 }
105 config = ConfigManager('hostlist.conf.1.2', defaults=default_config, file_version=2)
106 config.run_converter((0, 1), 2, self.__migrate_config_1_to_2)
107 return config
108
109 # Public methods
110 def show(self):
111 """
112 Show the ConnectionManager dialog.
113 """
114 self.config = self.__load_config()
115 # Get the gtk builder file for the connection manager
116 self.builder = gtk.Builder()
117 # The main dialog
118 self.builder.add_from_file(resource_filename(
119 'deluge.ui.gtkui', os.path.join('glade', 'connection_manager.ui')
120 ))
121 # The add host dialog
122 self.builder.add_from_file(resource_filename(
123 'deluge.ui.gtkui', os.path.join('glade', 'connection_manager.addhost.ui')
124 ))
125 # The ask password dialog
126 self.builder.add_from_file(resource_filename(
127 'deluge.ui.gtkui', os.path.join('glade', 'connection_manager.askpassword.ui')
128 ))
129 self.window = component.get('MainWindow')
130
131 # Setup the ConnectionManager dialog
132 self.connection_manager = self.builder.get_object('connection_manager')
133 self.connection_manager.set_transient_for(self.window.window)
134
135 self.connection_manager.set_icon(get_deluge_icon())
136
137 self.builder.get_object('image1').set_from_pixbuf(get_logo(32))
138
139 self.askpassword_dialog = self.builder.get_object('askpassword_dialog')
140 self.askpassword_dialog.set_transient_for(self.connection_manager)
141 self.askpassword_dialog.set_icon(get_deluge_icon())
142 self.askpassword_dialog_entry = self.builder.get_object('askpassword_dialog_entry')
143
144 self.hostlist = self.builder.get_object('hostlist')
145
146 # Create status pixbufs
147 if not HOSTLIST_PIXBUFS:
148 for stock_id in (gtk.STOCK_NO, gtk.STOCK_YES, gtk.STOCK_CONNECT):
149 HOSTLIST_PIXBUFS.append(
150 self.connection_manager.render_icon(
151 stock_id, gtk.ICON_SIZE_MENU
152 )
153 )
154
155 # Create the host list gtkliststore
156 # id-hash, hostname, port, status, username, password, version
157 self.liststore = gtk.ListStore(str, str, int, str, str, str, str)
158
159 # Setup host list treeview
160 self.hostlist.set_model(self.liststore)
161 render = gtk.CellRendererPixbuf()
162 column = gtk.TreeViewColumn(_('Status'), render)
163 column.set_cell_data_func(render, cell_render_status, 3)
164 self.hostlist.append_column(column)
165 render = gtk.CellRendererText()
166 column = gtk.TreeViewColumn(_('Host'), render, text=HOSTLIST_COL_HOST)
167 column.set_cell_data_func(render, cell_render_host, (1, 2, 4))
168 column.set_expand(True)
169 self.hostlist.append_column(column)
170 render = gtk.CellRendererText()
171 column = gtk.TreeViewColumn(_('Version'), render, text=HOSTLIST_COL_VERSION)
172 self.hostlist.append_column(column)
173
174 # Connect the signals to the handlers
175 self.builder.connect_signals(self)
176 self.hostlist.get_selection().connect(
177 'changed', self.on_hostlist_selection_changed
178 )
179
180 # Load any saved host entries
181 self.__load_hostlist()
182 self.__load_options()
183 self.__update_list()
184
185 self.running = True
186 # Trigger the on_selection_changed code and select the first host
187 # if possible
188 self.hostlist.get_selection().unselect_all()
189 if len(self.liststore) > 0:
190 self.hostlist.get_selection().select_path('0')
191
192 # Run the dialog
193 self.connection_manager.run()
194 self.running = False
195
196 # Save the toggle options
197 self.__save_options()
198 self.__save_hostlist()
199
200 self.connection_manager.destroy()
201 del self.builder
202 del self.window
203 del self.connection_manager
204 del self.liststore
205 del self.hostlist
206
207 def add_host(self, host, port, username='', password=''):
208 """
209 Adds a host to the list.
210
211 :param host: str, the hostname
212 :param port: int, the port
213 :param username: str, the username to login as
214 :param password: str, the password to login with
215
216 """
217 # Check to see if there is already an entry for this host and return
218 # if thats the case
219 for entry in self.liststore:
220 if [entry[HOSTLIST_COL_HOST], entry[HOSTLIST_COL_PORT], entry[HOSTLIST_COL_USER]] == [host, port, username]:
221 raise Exception('Host already in list!')
222
223 # Host isn't in the list, so lets add it
224 row = self.liststore.append()
225 self.liststore[row][HOSTLIST_COL_ID] = hashlib.sha1(str(time.time())).hexdigest()
226 self.liststore[row][HOSTLIST_COL_HOST] = host
227 self.liststore[row][HOSTLIST_COL_PORT] = port
228 self.liststore[row][HOSTLIST_COL_USER] = username
229 self.liststore[row][HOSTLIST_COL_PASS] = password
230 self.liststore[row][HOSTLIST_COL_STATUS] = 'Offline'
231
232 # Save the host list to file
233 self.__save_hostlist()
234
235 # Update the status of the hosts
236 self.__update_list()
237
238 # Private methods
239 def __save_hostlist(self):
240 """
241 Save the current hostlist to the config file.
242 """
243 # Grab the hosts from the liststore
244 self.config['hosts'] = []
245 for row in self.liststore:
246 self.config['hosts'].append((row[HOSTLIST_COL_ID],
247 row[HOSTLIST_COL_HOST],
248 row[HOSTLIST_COL_PORT],
249 row[HOSTLIST_COL_USER],
250 row[HOSTLIST_COL_PASS]))
251
252 self.config.save()
253
254 def __load_hostlist(self):
255 """
256 Load saved host entries
257 """
258 for host in self.config['hosts']:
259 new_row = self.liststore.append()
260 self.liststore[new_row][HOSTLIST_COL_ID] = host[0]
261 self.liststore[new_row][HOSTLIST_COL_HOST] = host[1]
262 self.liststore[new_row][HOSTLIST_COL_PORT] = host[2]
263 self.liststore[new_row][HOSTLIST_COL_USER] = host[3]
264 self.liststore[new_row][HOSTLIST_COL_PASS] = host[4]
265 self.liststore[new_row][HOSTLIST_COL_STATUS] = 'Offline'
266 self.liststore[new_row][HOSTLIST_COL_VERSION] = ''
267
268 def __get_host_row(self, host_id):
269 """
270 Returns the row in the liststore for `:param:host_id` or None
271
272 """
273 for row in self.liststore:
274 if host_id == row[HOSTLIST_COL_ID]:
275 return row
276 return None
277
278 def __update_list(self):
279 """Updates the host status"""
280 if not hasattr(self, 'liststore'):
281 # This callback was probably fired after the window closed
282 return
283
284 def on_connect(result, c, host_id):
285 # Return if the deferred callback was done after the dialog was closed
286 if not self.running:
287 return
288 row = self.__get_host_row(host_id)
289
290 def on_info(info, c):
291 if not self.running:
292 return
293 if row:
294 row[HOSTLIST_COL_STATUS] = 'Online'
295 row[HOSTLIST_COL_VERSION] = info
296 self.__update_buttons()
297 c.disconnect()
298
299 def on_info_fail(reason, c):
300 if not self.running:
301 return
302 if row:
303 row[HOSTLIST_COL_STATUS] = 'Offline'
304 self.__update_buttons()
305 c.disconnect()
306
307 d = c.daemon.info()
308 d.addCallback(on_info, c)
309 d.addErrback(on_info_fail, c)
310
311 def on_connect_failed(reason, host_id):
312 if not self.running:
313 return
314 row = self.__get_host_row(host_id)
315 if row:
316 row[HOSTLIST_COL_STATUS] = 'Offline'
317 row[HOSTLIST_COL_VERSION] = ''
318 self.__update_buttons()
319
320 for row in self.liststore:
321 host_id = row[HOSTLIST_COL_ID]
322 host = row[HOSTLIST_COL_HOST]
323 port = row[HOSTLIST_COL_PORT]
324 user = row[HOSTLIST_COL_USER]
325
326 if client.connected() and (
327 gethostbyname(host),
328 port,
329 'localclient' if not user and host in ('127.0.0.1', 'localhost') else user
330 ) == client.connection_info():
331 def on_info(info, row):
332 if not self.running:
333 return
334 log.debug('Client connected, query info: %s', info)
335 row[HOSTLIST_COL_VERSION] = info
336 self.__update_buttons()
337
338 row[HOSTLIST_COL_STATUS] = 'Connected'
339 log.debug("Query daemon's info")
340 client.daemon.info().addCallback(on_info, row)
341 continue
342
343 # Create a new Client instance
344 c = Client()
345 d = c.connect(host, port, skip_authentication=True)
346 d.addCallback(on_connect, c, host_id)
347 d.addErrback(on_connect_failed, host_id)
348
349 def __load_options(self):
350 """
351 Set the widgets to show the correct options from the config.
352 """
353 self.builder.get_object('chk_autoconnect').set_active(
354 self.gtkui_config['autoconnect']
355 )
356 self.builder.get_object('chk_autostart').set_active(
357 self.gtkui_config['autostart_localhost']
358 )
359 self.builder.get_object('chk_donotshow').set_active(
360 not self.gtkui_config['show_connection_manager_on_start']
361 )
362
363 def __save_options(self):
364 """
365 Set options in gtkui config from the toggle buttons.
366 """
367 self.gtkui_config['autoconnect'] = self.builder.get_object('chk_autoconnect').get_active()
368 self.gtkui_config['autostart_localhost'] = self.builder.get_object('chk_autostart').get_active()
369 self.gtkui_config['show_connection_manager_on_start'] = not self.builder.get_object(
370 'chk_donotshow').get_active()
371
372 def __update_buttons(self):
373 """
374 Updates the buttons states.
375 """
376 if len(self.liststore) == 0:
377 # There is nothing in the list
378 self.builder.get_object('button_startdaemon').set_sensitive(True)
379 self.builder.get_object('button_connect').set_sensitive(False)
380 self.builder.get_object('button_removehost').set_sensitive(False)
381 self.builder.get_object('image_startdaemon').set_from_stock(
382 gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU)
383 self.builder.get_object('label_startdaemon').set_text('_Start Daemon')
384
385 model, row = self.hostlist.get_selection().get_selected()
386 if not row:
387 self.builder.get_object('button_edithost').set_sensitive(False)
388 return
389
390 self.builder.get_object('button_edithost').set_sensitive(True)
391
392 # Get some values about the selected host
393 status = model[row][HOSTLIST_COL_STATUS]
394 host = model[row][HOSTLIST_COL_HOST]
395 port = model[row][HOSTLIST_COL_PORT]
396 user = model[row][HOSTLIST_COL_USER]
397 passwd = model[row][HOSTLIST_COL_PASS]
398
399 log.debug('Status: %s', status)
400 # Check to see if we have a localhost entry selected
401 localhost = False
402 if host in ('127.0.0.1', 'localhost'):
403 localhost = True
404
405 # Make sure buttons are sensitive at start
406 self.builder.get_object('button_startdaemon').set_sensitive(True)
407 self.builder.get_object('button_connect').set_sensitive(True)
408 self.builder.get_object('button_removehost').set_sensitive(True)
409
410 # See if this is the currently connected host
411 if status == 'Connected':
412 # Display a disconnect button if we're connected to this host
413 self.builder.get_object('button_connect').set_label('gtk-disconnect')
414 self.builder.get_object('button_removehost').set_sensitive(False)
415 else:
416 self.builder.get_object('button_connect').set_label('gtk-connect')
417 if status == 'Offline' and not localhost:
418 self.builder.get_object('button_connect').set_sensitive(False)
419
420 # Check to see if the host is online
421 if status == 'Connected' or status == 'Online':
422 self.builder.get_object('image_startdaemon').set_from_stock(
423 gtk.STOCK_STOP, gtk.ICON_SIZE_MENU)
424 self.builder.get_object('label_startdaemon').set_text(
425 _('_Stop Daemon'))
426
427 # Update the start daemon button if the selected host is localhost
428 if localhost and status == 'Offline':
429 # The localhost is not online
430 self.builder.get_object('image_startdaemon').set_from_stock(
431 gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU)
432 self.builder.get_object('label_startdaemon').set_text(
433 _('_Start Daemon'))
434
435 if client.connected() and (host, port, user) == client.connection_info():
436 # If we're connected, we can stop the dameon
437 self.builder.get_object('button_startdaemon').set_sensitive(True)
438 elif user and passwd:
439 # In this case we also have all the info to shutdown the daemon
440 self.builder.get_object('button_startdaemon').set_sensitive(True)
441 else:
442 # Can't stop non localhost daemons, specially without the necessary info
443 self.builder.get_object('button_startdaemon').set_sensitive(False)
444
445 # Make sure label is displayed correctly using mnemonics
446 self.builder.get_object('label_startdaemon').set_use_underline(True)
447
448 def start_daemon(self, port, config):
449 """
450 Attempts to start a daemon process and will show an ErrorDialog if unable
451 to.
452 """
453 try:
454 return client.start_daemon(port, config)
455 except OSError as ex:
456 from errno import ENOENT
457 if ex.errno == ENOENT:
458 ErrorDialog(
459 _('Unable to start daemon!'),
460 _("Deluge cannot find the 'deluged' executable, it is "
461 'likely that you forgot to install the deluged package '
462 "or it's not in your PATH.")).run()
463 return False
464 else:
465 raise ex
466 except Exception:
467 import traceback
468 import sys
469 tb = sys.exc_info()
470 ErrorDialog(
471 _('Unable to start daemon!'),
472 _('Please examine the details for more information.'),
473 details=traceback.format_exc(tb[2])).run()
474
475 # Signal handlers
476 def __connect(self, host_id, host, port, username, password,
477 skip_authentication=False, try_counter=0):
478 def do_connect(*args):
479 d = client.connect(host, port, username, password, skip_authentication)
480 d.addCallback(self.__on_connected, host_id)
481 d.addErrback(self.__on_connected_failed, host_id, host, port,
482 username, password, try_counter)
483 return d
484
485 if client.connected():
486 return client.disconnect().addCallback(do_connect)
487 else:
488 return do_connect()
489
490 def __on_connected(self, daemon_info, host_id):
491 if self.gtkui_config['autoconnect']:
492 self.gtkui_config['autoconnect_host_id'] = host_id
493 if self.running:
494 # When connected to a client, and then trying to connect to another,
495 # this component will be stopped(while the connect deferred is
496 # running), so, self.connection_manager will be deleted.
497 # If that's not the case, close the dialog.
498 self.connection_manager.response(gtk.RESPONSE_OK)
499 component.start()
500
501 def __on_connected_failed(self, reason, host_id, host, port, user, passwd,
502 try_counter):
503 log.debug('Failed to connect: %s', reason.value)
504
505 if reason.check(AuthenticationRequired, BadLoginError):
506 log.debug('PasswordRequired exception')
507 dialog = AuthenticationDialog(reason.value.message, reason.value.username)
508
509 def dialog_finished(response_id, host, port, user):
510 if response_id == gtk.RESPONSE_OK:
511 self.__connect(host_id, host, port,
512 user and user or dialog.get_username(),
513 dialog.get_password())
514 d = dialog.run().addCallback(dialog_finished, host, port, user)
515 return d
516
517 elif reason.trap(IncompatibleClient):
518 dialog = ErrorDialog(
519 _('Incompatible Client'), reason.value.message
520 )
521 return dialog.run()
522
523 if try_counter:
524 log.info('Retrying connection.. Retries left: %s', try_counter)
525 return reactor.callLater(
526 0.5, self.__connect, host_id, host, port, user, passwd,
527 try_counter=try_counter - 1
528 )
529
530 msg = str(reason.value)
531 if not self.builder.get_object('chk_autostart').get_active():
532 msg += '\n' + _('Auto-starting the daemon locally is not enabled. '
533 'See "Options" on the "Connection Manager".')
534 ErrorDialog(_('Failed To Connect'), msg).run()
535
536 def on_button_connect_clicked(self, widget=None):
537 model, row = self.hostlist.get_selection().get_selected()
538 if not row:
539 return
540 status = model[row][HOSTLIST_COL_STATUS]
541 if status == 'Connected':
542 def on_disconnect(reason):
543 self.__update_list()
544 client.disconnect().addCallback(on_disconnect)
545 return
546
547 host_id = model[row][HOSTLIST_COL_ID]
548 host = model[row][HOSTLIST_COL_HOST]
549 port = model[row][HOSTLIST_COL_PORT]
550 user = model[row][HOSTLIST_COL_USER]
551 password = model[row][HOSTLIST_COL_PASS]
552
553 if (status == 'Offline' and self.builder.get_object('chk_autostart').get_active() and
554 host in ('127.0.0.1', 'localhost')):
555 if not self.start_daemon(port, get_config_dir()):
556 log.debug('Failed to auto-start daemon')
557 return
558 return self.__connect(
559 host_id, host, port, user, password, try_counter=6
560 )
561 return self.__connect(host_id, host, port, user, password)
562
563 def on_button_close_clicked(self, widget):
564 self.connection_manager.response(gtk.RESPONSE_CLOSE)
565
566 def on_button_addhost_clicked(self, widget):
567 log.debug('on_button_addhost_clicked')
568 dialog = self.builder.get_object('addhost_dialog')
569 dialog.set_transient_for(self.connection_manager)
570 dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
571 hostname_entry = self.builder.get_object('entry_hostname')
572 port_spinbutton = self.builder.get_object('spinbutton_port')
573 username_entry = self.builder.get_object('entry_username')
574 password_entry = self.builder.get_object('entry_password')
575 button_addhost_save = self.builder.get_object('button_addhost_save')
576 button_addhost_save.hide()
577 button_addhost_add = self.builder.get_object('button_addhost_add')
578 button_addhost_add.show()
579 response = dialog.run()
580 if response == 1:
581 username = username_entry.get_text()
582 password = password_entry.get_text()
583 hostname = hostname_entry.get_text()
584
585 if (not password and not username or username == 'localclient') and hostname in ['127.0.0.1', 'localhost']:
586 username, password = get_localhost_auth()
587
588 # We add the host
589 try:
590 self.add_host(hostname, port_spinbutton.get_value_as_int(),
591 username, password)
592 except Exception as ex:
593 ErrorDialog(_('Error Adding Host'), ex).run()
594
595 username_entry.set_text('')
596 password_entry.set_text('')
597 hostname_entry.set_text('')
598 port_spinbutton.set_value(58846)
599 dialog.hide()
600
601 def on_button_edithost_clicked(self, widget=None):
602 log.debug('on_button_edithost_clicked')
603 model, row = self.hostlist.get_selection().get_selected()
604 status = model[row][HOSTLIST_COL_STATUS]
605 if status == 'Connected':
606 def on_disconnect(reason):
607 self.__update_list()
608 client.disconnect().addCallback(on_disconnect)
609 return
610
611 dialog = self.builder.get_object('addhost_dialog')
612 dialog.set_transient_for(self.connection_manager)
613 dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
614 hostname_entry = self.builder.get_object('entry_hostname')
615 port_spinbutton = self.builder.get_object('spinbutton_port')
616 username_entry = self.builder.get_object('entry_username')
617 password_entry = self.builder.get_object('entry_password')
618 button_addhost_save = self.builder.get_object('button_addhost_save')
619 button_addhost_save.show()
620 button_addhost_add = self.builder.get_object('button_addhost_add')
621 button_addhost_add.hide()
622
623 username_entry.set_text(self.liststore[row][HOSTLIST_COL_USER])
624 password_entry.set_text(self.liststore[row][HOSTLIST_COL_PASS])
625 hostname_entry.set_text(self.liststore[row][HOSTLIST_COL_HOST])
626 port_spinbutton.set_value(self.liststore[row][HOSTLIST_COL_PORT])
627
628 response = dialog.run()
629
630 if response == 2:
631 username = username_entry.get_text()
632 password = password_entry.get_text()
633 hostname = hostname_entry.get_text()
634
635 if (not password and not username or username == 'localclient') and hostname in ['127.0.0.1', 'localhost']:
636 username, password = get_localhost_auth()
637
638 self.liststore[row][HOSTLIST_COL_HOST] = hostname
639 self.liststore[row][HOSTLIST_COL_PORT] = port_spinbutton.get_value_as_int()
640 self.liststore[row][HOSTLIST_COL_USER] = username
641 self.liststore[row][HOSTLIST_COL_PASS] = password
642 self.liststore[row][HOSTLIST_COL_STATUS] = 'Offline'
643
644 # Save the host list to file
645 self.__save_hostlist()
646
647 # Update the status of the hosts
648 self.__update_list()
649
650 username_entry.set_text('')
651 password_entry.set_text('')
652 hostname_entry.set_text('')
653 port_spinbutton.set_value(58846)
654 dialog.hide()
655
656 def on_button_removehost_clicked(self, widget):
657 log.debug('on_button_removehost_clicked')
658 # Get the selected rows
659 paths = self.hostlist.get_selection().get_selected_rows()[1]
660 for path in paths:
661 self.liststore.remove(self.liststore.get_iter(path))
662
663 # Update the hostlist
664 self.__update_list()
665
666 # Save the host list
667 self.__save_hostlist()
668
669 def on_button_startdaemon_clicked(self, widget):
670 log.debug('on_button_startdaemon_clicked')
671 if self.liststore.iter_n_children(None) < 1:
672 # There is nothing in the list, so lets create a localhost entry
673 self.add_host(DEFAULT_HOST, DEFAULT_PORT, *get_localhost_auth())
674 # ..and start the daemon.
675 self.start_daemon(
676 DEFAULT_PORT, get_config_dir()
677 )
678 return
679
680 paths = self.hostlist.get_selection().get_selected_rows()[1]
681 if len(paths) < 1:
682 return
683
684 status = self.liststore[paths[0]][HOSTLIST_COL_STATUS]
685 host = self.liststore[paths[0]][HOSTLIST_COL_HOST]
686 port = self.liststore[paths[0]][HOSTLIST_COL_PORT]
687 user = self.liststore[paths[0]][HOSTLIST_COL_USER]
688 password = self.liststore[paths[0]][HOSTLIST_COL_PASS]
689
690 if host not in ('127.0.0.1', 'localhost'):
691 return
692
693 if status in ('Online', 'Connected'):
694 # We need to stop this daemon
695 # Call the shutdown method on the daemon
696 def on_daemon_shutdown(d):
697 # Update display to show change
698 reactor.callLater(0.8, self.__update_list)
699 if client.connected() and client.connection_info() == (host, port, user):
700 client.daemon.shutdown().addCallback(on_daemon_shutdown)
701 elif user and password:
702 # Create a new client instance
703 c = Client()
704
705 def on_connect(d, c):
706 log.debug('on_connect')
707 c.daemon.shutdown().addCallback(on_daemon_shutdown)
708
709 c.connect(host, port, user, password).addCallback(on_connect, c)
710
711 elif status == 'Offline':
712 self.start_daemon(port, get_config_dir())
713 reactor.callLater(0.8, self.__update_list)
714
715 def on_button_refresh_clicked(self, widget):
716 self.__update_list()
717
718 def on_hostlist_row_activated(self, tree, path, view_column):
719 self.on_button_connect_clicked()
720
721 def on_hostlist_selection_changed(self, treeselection):
722 self.__update_buttons()
723
724 def on_askpassword_dialog_connect_button_clicked(self, widget):
725 log.debug('on on_askpassword_dialog_connect_button_clicked')
726 self.askpassword_dialog.response(gtk.RESPONSE_OK)
727
728 def on_askpassword_dialog_entry_activate(self, entry):
729 self.askpassword_dialog.response(gtk.RESPONSE_OK)
730
731 def __migrate_config_1_to_2(self, config):
732 localclient_username, localclient_password = get_localhost_auth()
733 if not localclient_username:
734 # Nothing to do here, there's no auth file
735 return
736 for idx, (_, host, _, username, _) in enumerate(config['hosts'][:]):
737 if host in ('127.0.0.1', 'localhost'):
738 if not username:
739 config['hosts'][idx][3] = localclient_username
740 config['hosts'][idx][4] = localclient_password
741 return config
Note: See TracBrowser for help on using the repository browser.