748
762
"""Load the device list."""
749
self.backend.devices_info()
763
self.backend.devices_info(reply_handler=NO_OP,
764
error_handler=error_handler)
750
765
self.message.start()
753
class ApplicationsPanel(UbuntuOneBin, ControlPanelMixin):
754
"""The applications panel."""
768
class InstallPackage(gtk.VBox, ControlPanelMixin):
769
"""A widget to process the install of a package."""
771
INSTALL_PACKAGE = _('You need to install the package <i>%(package_name)s'
772
'</i> in order to enable replication.')
773
INSTALLING = _('The package <i>%(package_name)s</i> is being installed, '
775
FAILED_INSTALL = _('The installation of <i>%(package_name)s</i> failed.')
776
SUCCESS_INSTALL = _('The installation of <i>%(package_name)s</i> '
779
def __init__(self, package_name):
780
gtk.VBox.__init__(self)
781
ControlPanelMixin.__init__(self, filename='install.ui')
782
self.add(self.itself)
784
self.package_name = package_name
785
self.package_manager = package_manager.PackageManager()
786
self.args = {'package_name': self.package_name}
787
self.transaction = None
789
self.progress_bar = None
790
self.install_label.set_markup(self.INSTALL_PACKAGE % self.args)
794
@package_manager.inline_callbacks
795
def on_install_button_clicked(self, button):
796
"""The install button was clicked."""
798
# create the install transaction
799
self.transaction = yield self.package_manager.install(
802
# create the progress bar and pack it to the box
803
self.progress_bar = package_manager.PackageManagerProgressBar(
805
self.progress_bar.show()
807
self.itself.remove(self.install_button_box)
808
self.itself.pack_start(self.progress_bar)
810
self.transaction.connect('finished', self.on_install_finished)
811
self.install_label.set_markup(self.INSTALLING % self.args)
812
yield self.transaction.run()
813
except: # pylint: disable=W0702
814
self._set_warning(self.FAILED_INSTALL % self.args,
817
@log_call(logger.info)
818
def on_install_finished(self, transaction, exit_code):
819
"""The installation finished."""
820
self.progress_bar.set_sensitive(False)
822
if exit_code != package_manager.aptdaemon.enums.EXIT_SUCCESS:
823
if hasattr(transaction, 'error'):
824
logger.error('transaction failed: %r', transaction.error)
825
self._set_warning(self.FAILED_INSTALL % self.args,
828
self.install_label.set_markup(self.SUCCESS_INSTALL % self.args)
829
self.emit('finished')
832
class Service(gtk.VBox, ControlPanelMixin):
835
CHANGE_ERROR = _('The settings could not be changed,\n'
836
'previous values were restored.')
838
def __init__(self, service_id, name, *args, **kwargs):
839
gtk.VBox.__init__(self)
840
ControlPanelMixin.__init__(self)
843
self.warning_label = gtk.Label()
844
self.pack_start(self.warning_label, expand=False)
846
self.button = gtk.CheckButton(label=name)
847
self.pack_start(self.button, expand=False)
852
class FilesService(Service):
853
"""The file sync service."""
855
FILES_SERVICE_NAME = _('Files')
858
Service.__init__(self, service_id='files',
859
name=self.FILES_SERVICE_NAME)
861
self.set_sensitive(False)
863
self.backend.connect_to_signal('FileSyncStatusChanged',
864
self.on_file_sync_status_changed)
865
self.backend.connect_to_signal('FilesEnabled', self.on_files_enabled)
866
self.backend.connect_to_signal('FilesDisabled', self.on_files_disabled)
868
self.backend.file_sync_status(reply_handler=NO_OP,
869
error_handler=error_handler)
871
@log_call(logger.debug)
872
def on_file_sync_status_changed(self, status):
873
"""File sync status changed."""
874
enabled = status != backend.FILE_SYNC_DISABLED
875
self.button.set_active(enabled)
877
if not self.is_sensitive():
878
# first time we're getting this event
879
self.button.connect('toggled', self.on_button_toggled)
880
self.set_sensitive(True)
882
def on_files_enabled(self):
883
"""Files service was enabled."""
884
self.on_file_sync_status_changed('enabled!')
886
def on_files_disabled(self):
887
"""Files service was disabled."""
888
self.on_file_sync_status_changed(backend.FILE_SYNC_DISABLED)
890
@log_call(logger.debug)
891
def on_button_toggled(self, button):
892
"""Button was toggled, exclude/replicate the service properly."""
893
logger.info('File sync enabled? %r', self.button.get_active())
894
if self.button.get_active():
895
self.backend.enable_files(reply_handler=NO_OP,
896
error_handler=error_handler)
898
self.backend.disable_files(reply_handler=NO_OP,
899
error_handler=error_handler)
902
class DesktopcouchService(Service):
903
"""A desktopcouch service."""
905
def __init__(self, service_id, name, enabled, dependency=None):
906
Service.__init__(self, service_id, name)
908
self.backend.connect_to_signal('ReplicationSettingsChanged',
909
self.on_replication_settings_changed)
910
self.backend.connect_to_signal('ReplicationSettingsChangeError',
911
self.on_replication_settings_change_error)
913
self.button.set_active(enabled)
915
self.dependency = None
916
if dependency is not None:
917
self.dependency = InstallPackage(dependency)
918
self.dependency.connect('finished', self.on_depedency_finished)
919
self.pack_start(self.dependency, expand=False)
920
self.button.set_sensitive(False)
922
self.button.connect('toggled', self.on_button_toggled)
924
def on_depedency_finished(self, widget):
925
"""The dependency was installed."""
926
self.button.set_sensitive(True)
927
self.remove(self.dependency)
928
self.dependency = None
930
@log_call(logger.debug)
931
def on_button_toggled(self, button):
932
"""Button was toggled, exclude/replicate the service properly."""
933
logger.info('Starting replication for %r? %r',
934
self.id, self.button.get_active())
936
args = {'enabled': bool_str(self.button.get_active())}
937
self.backend.change_replication_settings(self.id, args,
938
reply_handler=NO_OP, error_handler=error_handler)
940
@log_call(logger.info)
941
def on_replication_settings_changed(self, replication_id):
942
"""The change of settings for this replication succeded."""
943
if replication_id != self.id:
945
self.warning_label.set_text('')
947
@log_call(logger.error)
948
def on_replication_settings_change_error(self, replication_id,
950
"""The change of settings for this replication failed."""
951
if replication_id != self.id:
953
self.button.set_active(not self.button.get_active())
954
self._set_warning(self.CHANGE_ERROR, self.warning_label)
957
class ServicesPanel(UbuntuOneBin, ControlPanelMixin):
958
"""The services panel."""
756
960
TITLE = _('Ubuntu One services including data sync are enabled for the '
757
'data types and applications listed below:')
961
'data types and services listed below.')
962
CHOOSE_SERVICES = _('Choose services to synchronize with this computer:')
963
DESKTOPCOUCH_PKG = 'desktopcouch-ubuntuone'
964
BOOKMARKS = _('Bookmarks (Firefox)')
965
CONTACTS = _('Contacts (Evolution)')
966
NO_PAIRING_RECORD = _('There is no Ubuntu One pairing record.')
759
968
def __init__(self):
760
969
UbuntuOneBin.__init__(self)
761
ControlPanelMixin.__init__(self, filename='applications.ui')
970
ControlPanelMixin.__init__(self, filename='services.ui')
762
971
self.add(self.itself)
973
self.package_manager = package_manager.PackageManager()
974
self.install_box = None
976
self.backend.connect_to_signal('ReplicationsInfoReady',
977
self.on_replications_info_ready)
978
self.backend.connect_to_signal('ReplicationsInfoError',
979
self.on_replications_info_error)
981
self.files.pack_start(FilesService(), expand=False)
986
def has_desktopcouch(self):
987
"""Is desktopcouch installed?"""
988
return self.package_manager.is_installed(self.DESKTOPCOUCH_PKG)
990
@log_call(logger.debug)
993
if self.install_box is not None:
994
self.itself.remove(self.install_box)
995
self.install_box = None
997
logger.info('load: has_desktopcouch? %r', self.has_desktopcouch)
998
if not self.has_desktopcouch:
999
self.message.set_text('')
1000
self.replications.hide()
1002
self.install_box = InstallPackage(self.DESKTOPCOUCH_PKG)
1003
self.install_box.connect('finished', self.load_replications)
1004
self.itself.pack_start(self.install_box, expand=False)
1005
self.itself.reorder_child(self.install_box, 0)
1007
self.load_replications()
765
1009
self.message.stop()
766
self.message.set_text('Under construction')
1011
@log_call(logger.debug)
1012
def load_replications(self, *args):
1013
"""Load replications info."""
1014
# ask replications to the backend
1015
self.message.start()
1016
self.backend.replications_info(reply_handler=NO_OP,
1017
error_handler=error_handler)
1019
@log_call(logger.debug)
1020
def on_replications_info_ready(self, info):
1021
"""The replication info is ready."""
1022
self.on_success(self.CHOOSE_SERVICES)
1024
self.replications.show()
1026
if self.install_box is not None:
1027
self.itself.remove(self.install_box)
1028
self.install_box = None
1030
for child in self.replications.get_children():
1031
self.replications.remove(child)
1034
pkg = item['dependency']
1035
child = DesktopcouchService(service_id=item['replication_id'],
1036
name=item['name'], # self.BOOKMARKS,
1037
enabled=bool(item['enabled']),
1038
dependency=pkg if pkg else None)
1039
self.replications.pack_start(child, expand=False)
1041
@log_call(logger.error)
1042
def on_replications_info_error(self, error_dict=None):
1043
"""The replication info can not be retrieved."""
1044
if error_dict is not None and \
1045
error_dict.get('error_type', None) == 'NoPairingRecord':
1046
self.on_error(self.NO_PAIRING_RECORD)
769
1051
class ManagementPanel(gtk.VBox, ControlPanelMixin):
770
1052
"""The management panel.
772
The user can manage account, folders, devices and applications.
1054
The user can manage dashboard, folders, devices and services.