~nataliabidart/ubuntuone-control-panel/disable-files

« back to all changes in this revision

Viewing changes to ubuntuone/controlpanel/gtk/gui.py

  • Committer: Natalia B. Bidart
  • Date: 2011-04-01 20:05:07 UTC
  • mfrom: (117.1.5 ubuntuone-control-panel)
  • Revision ID: natalia.bidart@canonical.com-20110401200507-9hl6n7pg5spwelaz
MergedĀ trunkĀ in.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# -*- coding: utf-8 -*-
2
2
 
3
3
# Authors: Natalia B Bidart <natalia.bidart@canonical.com>
 
4
#          Eric Casteleijn <eric.casteleijn@canonical.com>
4
5
#
5
6
# Copyright 2010 Canonical Ltd.
6
7
#
31
32
import gobject
32
33
import ubuntu_sso
33
34
 
 
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,
36
38
    PING_URL_KEY)
41
43
    PING_URL as U1_PING_URL, DESCRIPTION as U1_DESCRIPTION)
42
44
# pylint: enable=E0611,F0401
43
45
 
 
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)
54
60
 
55
61
from ubuntuone.controlpanel.gtk import package_manager, TRANSLATION_DOMAIN
56
62
 
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
67
74
KILOBYTES = 1024
68
75
NO_OP = lambda *a, **kw: None
74
81
    logger.error('Error handler received: %r, %r', args, kwargs)
75
82
 
76
83
 
 
84
def register_service(bus):
 
85
    """Try to register DBus service for making sure we run only one instance.
 
86
 
 
87
    Return True if succesfully registered, False if already running.
 
88
    """
 
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
 
92
 
 
93
 
 
94
def publish_service(window=None, switch_to='', alert=False):
 
95
    """Publish the service on DBus."""
 
96
    if window is None:
 
97
        window = ControlPanelWindow(switch_to=switch_to, alert=alert)
 
98
    return ControlPanelService(window)
 
99
 
 
100
 
 
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)
 
107
    else:
 
108
        obj = bus.get_object(DBUS_BUS_NAME_GUI, DBUS_PATH_GUI)
 
109
        service = dbus.Interface(obj, dbus_interface=DBUS_IFACE_GUI)
 
110
 
 
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)
 
114
            gtk.main_quit()
 
115
 
 
116
        def gui_reply_handler(*args, **kwargs):
 
117
            """Exit when done."""
 
118
            gtk.main_quit()
 
119
 
 
120
        service.switch_to_alert(
 
121
            switch_to, alert, reply_handler=gui_reply_handler,
 
122
            error_handler=gui_error_handler)
 
123
 
 
124
    gtk.main()
 
125
 
 
126
 
77
127
def filter_by_app_name(f):
78
128
    """Excecute 'f' filtering by app_name."""
79
129
 
192
242
        self.message.set_markup(message)
193
243
 
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."""
197
 
        if message == None:
 
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)
 
252
            if error_msg:
 
253
                message = "%s (%s: %s)" % (VALUE_ERROR, error_type, error_msg)
 
254
            else:
 
255
                message = "%s (%s)" % (VALUE_ERROR, error_type)
 
256
 
 
257
        assert message is not None
199
258
 
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."""
512
 
        self.on_error()
 
571
        self.on_error(error_dict=error_dict)
513
572
 
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."""
830
 
        self.on_error()
 
889
        self.on_error(error_dict=error_dict)
831
890
        self.is_processing = False
832
891
 
833
892
    @log_call(logger.warning)
1153
1212
    @log_call(logger.debug)
1154
1213
    def load(self):
1155
1214
        """Load info."""
 
1215
        self.replications.hide()
1156
1216
        if self.install_box is not None:
1157
1217
            self.itself.remove(self.install_box)
1158
1218
            self.install_box = None
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()
1164
1223
 
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)
1214
1273
        else:
1215
 
            self.on_error()
 
1274
            self.on_error(error_dict=error_dict)
1216
1275
 
1217
1276
 
1218
1277
class FileSyncStatus(gtk.HBox, ControlPanelMixin):
1543
1602
 
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)
1549
1608
 
1566
1625
            self.next_page()
1567
1626
 
1568
1627
 
 
1628
class ControlPanelService(dbus.service.Object):
 
1629
    """DBUS service that exposes some of the window's methods."""
 
1630
 
 
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)
 
1637
 
 
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."""
 
1642
        if panel:
 
1643
            self.window.switch_to(panel)
 
1644
        if alert:
 
1645
            self.window.draw_attention()
 
1646
 
 
1647
 
1569
1648
class ControlPanelWindow(gtk.Window):
1570
1649
    """The main window for the Ubuntu One control panel."""
1571
1650
 
1573
1652
 
1574
1653
    def __init__(self, switch_to=None, alert=False):
1575
1654
        super(ControlPanelWindow, self).__init__()
1576
 
 
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')
1581
1659
 
1582
1660
        self.connect('delete-event', lambda w, e: gtk.main_quit())
1583
1661
        if alert:
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()
1587
1663
        else:
1588
1664
            self.present()
1589
1665
 
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:
1599
 
                button.clicked()
1600
 
            else:
1601
 
                logger.warning('Could not start at panel: %r.', switch_to)
 
1672
            self.switch_to(switch_to)
1602
1673
 
1603
1674
        logger.debug('%s: started (window size %r).',
1604
1675
                     self.__class__.__name__, self.get_size_request())
1605
1676
 
 
1677
    def draw_attention(self):
 
1678
        """Draw attention to the control panel."""
 
1679
        self.present_with_time(1)
 
1680
        self.set_urgency_hint(True)
 
1681
 
 
1682
    def switch_to(self, panel):
 
1683
        """Switch to named panel."""
 
1684
        button = getattr(
 
1685
            self.control_panel.management, '%s_button' % panel, None)
 
1686
        if button is not None:
 
1687
            button.clicked()
 
1688
        else:
 
1689
            logger.warning('Could not start at panel: %r.', panel)
 
1690
 
1606
1691
    def main(self):
1607
1692
        """Run the main loop of the widget toolkit."""
1608
1693
        logger.debug('Starting GTK main loop.')