35
from dbus.mainloop.glib import DBusGMainLoop
34
36
from ubuntu_sso import networkstate
35
37
from ubuntu_sso.credentials import (TC_URL_KEY, HELP_TEXT_KEY, WINDOW_ID_KEY,
41
43
PING_URL as U1_PING_URL, DESCRIPTION as U1_DESCRIPTION)
42
44
# pylint: enable=E0611,F0401
46
from ubuntuone.controlpanel.gtk import (
47
DBUS_IFACE_GUI, DBUS_BUS_NAME as DBUS_BUS_NAME_GUI,
48
DBUS_PATH as DBUS_PATH_GUI)
44
49
from ubuntuone.controlpanel.gtk.widgets import LabelLoading, PanelTitle
45
50
# Use ubiquity package when ready (LP: #673665)
46
51
from ubuntuone.controlpanel.gtk.widgets import GreyableBin
50
55
from ubuntuone.controlpanel.backend import (DEVICE_TYPE_PHONE,
51
56
DEVICE_TYPE_COMPUTER, bool_str)
52
57
from ubuntuone.controlpanel.logger import setup_logging, log_call
53
from ubuntuone.controlpanel.utils import get_data_file
58
from ubuntuone.controlpanel.utils import (get_data_file,
59
ERROR_TYPE, ERROR_MESSAGE)
55
61
from ubuntuone.controlpanel.gtk import package_manager, TRANSLATION_DOMAIN
63
69
ERROR_COLOR = 'red'
64
70
LOADING = _('Loading...')
65
71
VALUE_ERROR = _('Value could not be retrieved.')
72
UNKNOWN_ERROR = _('Unknown error')
66
73
WARNING_MARKUP = '<span foreground="%s"><b>%%s</b></span>' % ERROR_COLOR
68
75
NO_OP = lambda *a, **kw: None
74
81
logger.error('Error handler received: %r, %r', args, kwargs)
84
def register_service(bus):
85
"""Try to register DBus service for making sure we run only one instance.
87
Return True if succesfully registered, False if already running.
89
name = bus.request_name(DBUS_BUS_NAME_GUI,
90
dbus.bus.NAME_FLAG_DO_NOT_QUEUE)
91
return name != dbus.bus.REQUEST_NAME_REPLY_EXISTS
94
def publish_service(window=None, switch_to='', alert=False):
95
"""Publish the service on DBus."""
97
window = ControlPanelWindow(switch_to=switch_to, alert=alert)
98
return ControlPanelService(window)
101
def main(switch_to='', alert=False):
102
"""Hook the DBus listeners and start the main loop."""
103
DBusGMainLoop(set_as_default=True)
104
bus = dbus.SessionBus()
105
if register_service(bus):
106
publish_service(switch_to=switch_to, alert=alert)
108
obj = bus.get_object(DBUS_BUS_NAME_GUI, DBUS_PATH_GUI)
109
service = dbus.Interface(obj, dbus_interface=DBUS_IFACE_GUI)
111
def gui_error_handler(*args, **kwargs):
112
"""Log errors when calling D-Bus methods in a async way."""
113
logger.error('Error handler received: %r, %r', args, kwargs)
116
def gui_reply_handler(*args, **kwargs):
117
"""Exit when done."""
120
service.switch_to_alert(
121
switch_to, alert, reply_handler=gui_reply_handler,
122
error_handler=gui_error_handler)
77
127
def filter_by_app_name(f):
78
128
"""Excecute 'f' filtering by app_name."""
192
242
self.message.set_markup(message)
194
244
@log_call(logger.error)
195
def on_error(self, message=None):
245
def on_error(self, message=None, error_dict=None):
196
246
"""Use this callback to stop the Loading and set a warning message."""
247
if message is None and error_dict is None:
198
248
message = VALUE_ERROR
249
elif message is None and error_dict is not None:
250
error_type = error_dict.get(ERROR_TYPE, UNKNOWN_ERROR)
251
error_msg = error_dict.get(ERROR_MESSAGE)
253
message = "%s (%s: %s)" % (VALUE_ERROR, error_type, error_msg)
255
message = "%s (%s)" % (VALUE_ERROR, error_type)
257
assert message is not None
200
259
self.message.stop()
201
260
self.message.set_markup(WARNING_MARKUP % message)
509
568
@log_call(logger.error)
510
569
def on_volumes_info_error(self, error_dict=None):
511
570
"""Backend notifies of an error when fetching volumes info."""
571
self.on_error(error_dict=error_dict)
514
573
@log_call(logger.info)
515
574
def on_volume_settings_changed(self, volume_id):
827
886
@log_call(logger.error)
828
887
def on_devices_info_error(self, error_dict=None):
829
888
"""Backend notifies of an error when fetching volumes info."""
889
self.on_error(error_dict=error_dict)
831
890
self.is_processing = False
833
892
@log_call(logger.warning)
1160
1220
logger.info('load: has_desktopcouch? %r', self.has_desktopcouch)
1161
1221
if not self.has_desktopcouch:
1162
1222
self.message.set_text('')
1163
self.replications.hide()
1165
1224
self.install_box = InstallPackage(self.DESKTOPCOUCH_PKG)
1166
1225
self.install_box.connect('finished', self.load_replications)
1212
1271
error_dict.get('error_type', None) == 'NoPairingRecord':
1213
1272
self.on_error(self.NO_PAIRING_RECORD)
1274
self.on_error(error_dict=error_dict)
1218
1277
class FileSyncStatus(gtk.HBox, ControlPanelMixin):
1544
1603
def shutdown(self, *args, **kwargs):
1545
1604
"""Shutdown backend."""
1546
logger.info('Shutding down...')
1605
logger.info('Shutting down...')
1547
1606
self.backend.shutdown(reply_handler=NO_OP,
1548
1607
error_handler=error_handler)
1566
1625
self.next_page()
1628
class ControlPanelService(dbus.service.Object):
1629
"""DBUS service that exposes some of the window's methods."""
1631
def __init__(self, window):
1632
self.window = window
1633
bus_name = dbus.service.BusName(
1634
DBUS_BUS_NAME_GUI, bus=dbus.SessionBus())
1635
dbus.service.Object.__init__(
1636
self, bus_name=bus_name, object_path=DBUS_PATH_GUI)
1638
@log_call(logger.debug)
1639
@dbus.service.method(dbus_interface=DBUS_IFACE_GUI, in_signature='sb')
1640
def switch_to_alert(self, panel='', alert=False):
1641
"""Switch to named panel."""
1643
self.window.switch_to(panel)
1645
self.window.draw_attention()
1569
1648
class ControlPanelWindow(gtk.Window):
1570
1649
"""The main window for the Ubuntu One control panel."""
1574
1653
def __init__(self, switch_to=None, alert=False):
1575
1654
super(ControlPanelWindow, self).__init__()
1577
1655
self.set_title(self.TITLE % {'app_name': U1_APP_NAME})
1578
1656
self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
1579
1657
self.set_icon_name('ubuntuone')
1582
1660
self.connect('delete-event', lambda w, e: gtk.main_quit())
1584
# NOTE this should prevent focus stealing but it does not :(
1585
self.present_with_time(1)
1586
self.set_urgency_hint(True)
1662
self.draw_attention()
1593
1669
logger.info('Starting %s pointing at panel: %r.',
1594
1670
self.__class__.__name__, switch_to)
1595
1671
if switch_to is not None:
1596
button = getattr(self.control_panel.management,
1597
'%s_button' % switch_to, None)
1598
if button is not None:
1601
logger.warning('Could not start at panel: %r.', switch_to)
1672
self.switch_to(switch_to)
1603
1674
logger.debug('%s: started (window size %r).',
1604
1675
self.__class__.__name__, self.get_size_request())
1677
def draw_attention(self):
1678
"""Draw attention to the control panel."""
1679
self.present_with_time(1)
1680
self.set_urgency_hint(True)
1682
def switch_to(self, panel):
1683
"""Switch to named panel."""
1685
self.control_panel.management, '%s_button' % panel, None)
1686
if button is not None:
1689
logger.warning('Could not start at panel: %r.', panel)
1606
1691
def main(self):
1607
1692
"""Run the main loop of the widget toolkit."""
1608
1693
logger.debug('Starting GTK main loop.')