# HG changeset patch # User Goffi # Date 1553070584 -3600 # Node ID 89ba66464329557e9c42a850e4bdfcf998d2b51f # Parent a5dfc789eeaf9c204270eedb8f605f9a2b267737 profile manager: don't use anymore deprecated ListView + use dp() for sizes of buttons instead of relative size. diff -r a5dfc789eeaf -r 89ba66464329 cagou/core/profile_manager.py --- a/cagou/core/profile_manager.py Wed Mar 20 09:29:44 2019 +0100 +++ b/cagou/core/profile_manager.py Wed Mar 20 09:29:44 2019 +0100 @@ -23,53 +23,16 @@ from .constants import Const as C from sat_frontends.quick_frontend.quick_profile_manager import QuickProfileManager from kivy.uix.boxlayout import BoxLayout -from kivy.uix import listview -from kivy.uix.button import Button +from kivy.uix.togglebutton import ToggleButton from kivy.uix.screenmanager import ScreenManager, Screen -from kivy.adapters import listadapter from kivy.metrics import sp from kivy import properties from cagou import G -class ProfileItem(listview.ListItemButton): - pass - - -class ProfileListAdapter(listadapter.ListAdapter): - - def __init__(self, pm, *args, **kwargs): - super(ProfileListAdapter, self).__init__(*args, **kwargs) - self.pm = pm - - def closeUI(self, xmlui): - self.pm.screen_manager.transition.direction = 'right' - self.pm.screen_manager.current = 'profiles' - - def showUI(self, xmlui): - xmlui.setCloseCb(self.closeUI) - if xmlui.type == 'popup': - xmlui.bind(on_touch_up=lambda obj, value: self.closeUI(xmlui)) - self.pm.xmlui_screen.clear_widgets() - self.pm.xmlui_screen.add_widget(xmlui) - self.pm.screen_manager.transition.direction = 'left' - self.pm.screen_manager.current = 'xmlui' - - def select_item_view(self, view): - def authenticate_cb(data, cb_id, profile): - if C.bool(data.pop('validated', C.BOOL_FALSE)): - super(ProfileListAdapter, self).select_item_view(view) - G.host.actionManager(data, callback=authenticate_cb, ui_show_cb=self.showUI, profile=profile) - - G.host.launchAction(C.AUTHENTICATE_PROFILE_ID, callback=authenticate_cb, profile=view.text) - - -class ConnectButton(Button): - - def __init__(self, profile_screen): - self.profile_screen = profile_screen - self.pm = profile_screen.pm - super(ConnectButton, self).__init__() +class ProfileItem(ToggleButton): + ps = properties.ObjectProperty() + index = properties.NumericProperty(0) class NewProfileScreen(Screen): @@ -88,7 +51,10 @@ def onCreationSuccess(self, profile): self.pm.profiles_screen.reload() - G.host.bridge.profileStartSession(self.password.text, profile, callback=lambda dummy: self._sessionStarted(profile), errback=self.onCreationFailure) + G.host.bridge.profileStartSession( + self.password.text, profile, + callback=lambda dummy: self._sessionStarted(profile), + errback=self.onCreationFailure) def _sessionStarted(self, profile): jid = self.jid.text.strip() @@ -101,7 +67,10 @@ name = self.profile_name.text.strip() # XXX: we use XMPP password for profile password to simplify # if user want to change profile password, he can do it in preferences - G.host.bridge.profileCreate(name, self.password.text, u'', callback=lambda: self.onCreationSuccess(name), errback=self.onCreationFailure) + G.host.bridge.profileCreate( + name, self.password.text, u'', + callback=lambda: self.onCreationSuccess(name), + errback=self.onCreationFailure) class DeleteProfilesScreen(Screen): @@ -124,30 +93,25 @@ for profile in to_delete: log.info(u"Deleteing profile [{}]".format(profile)) - G.host.bridge.asyncDeleteProfile(profile, callback=deleteInc, errback=deleteInc) + G.host.bridge.asyncDeleteProfile( + profile, callback=deleteInc, errback=deleteInc) class ProfilesScreen(Screen): layout = properties.ObjectProperty(None) + profiles = properties.ListProperty() def __init__(self, pm): self.pm = pm - self.list_adapter = ProfileListAdapter(pm, - data=[], - cls=ProfileItem, - args_converter=self.converter, - selection_mode='multiple', - allow_empty_selection=True, - ) super(ProfilesScreen, self).__init__(name=u'profiles') - self.layout.add_widget(listview.ListView(adapter=self.list_adapter)) - connect_btn = ConnectButton(self) - self.layout.add_widget(connect_btn) self.reload() def _profilesListGetCb(self, profiles): profiles.sort() - self.list_adapter.data = profiles + self.profiles = profiles + for idx, profile in enumerate(profiles): + item = ProfileItem(ps=self, index=idx, text=profile, group='profiles') + self.layout.add_widget(item) def converter(self, row_idx, obj): return {'text': obj, @@ -156,10 +120,12 @@ def reload(self): """Reload profiles list""" + self.layout.clear_widgets() G.host.bridge.profilesListGet(callback=self._profilesListGetCb) class ProfileManager(QuickProfileManager, BoxLayout): + selected = properties.ObjectProperty(None) def __init__(self, autoconnect=None): QuickProfileManager.__init__(self, G.host, autoconnect) @@ -174,6 +140,40 @@ self.screen_manager.add_widget(self.new_profile_screen) self.screen_manager.add_widget(self.delete_profiles_screen) self.add_widget(self.screen_manager) + self.bind(selected=self.onProfileSelect) + + def closeUI(self, xmlui): + self.screen_manager.transition.direction = 'right' + self.screen_manager.current = 'profiles' + + def showUI(self, xmlui): + xmlui.setCloseCb(self.closeUI) + if xmlui.type == 'popup': + xmlui.bind(on_touch_up=lambda obj, value: self.closeUI(xmlui)) + self.xmlui_screen.clear_widgets() + self.xmlui_screen.add_widget(xmlui) + self.screen_manager.transition.direction = 'left' + self.screen_manager.current = 'xmlui' + + def onProfileSelect(self, __, selected): + if not selected: + return + def authenticate_cb(data, cb_id, profile): + if not C.bool(data.pop('validated', C.BOOL_FALSE)): + # profile didn't validate, we unselect it + selected.state = 'normal' + self.selected = '' + else: + # state may have been modified so we need to be sure it's down + selected.state = 'down' + self.selected = selected + G.host.actionManager(data, callback=authenticate_cb, ui_show_cb=self.showUI, + profile=profile) + + G.host.launchAction(C.AUTHENTICATE_PROFILE_ID, callback=authenticate_cb, + profile=selected.text) def getProfiles(self): - return [pi.text for pi in self.profiles_screen.list_adapter.selection] + # for now we restrict to a single profile in Cagou + # TODO: handle multi-profiles + return [self.selected.text] if self.selected else [] diff -r a5dfc789eeaf -r 89ba66464329 cagou/kv/profile_manager.kv --- a/cagou/kv/profile_manager.kv Wed Mar 20 09:29:44 2019 +0100 +++ b/cagou/kv/profile_manager.kv Wed Mar 20 09:29:44 2019 +0100 @@ -17,8 +17,13 @@ : Label: + size_hint: 1, None + text_size: root.width, None + width: self.texture_size[0] + height: self.texture_size[1] + dp(20) text: "Profile Manager" - size_hint: 1,0.05 + halign: "center" + bold: True : size_hint: 1, None @@ -31,7 +36,8 @@ write_tab: False : - size_hint: 1, 0.2 + size_hint: 1, None + height: dp(40) : @@ -43,13 +49,16 @@ orientation: "vertical" Label: + size_hint: 1, None + text_size: root.width, None + size: self.texture_size text: "Creation of a new profile" - bold: True - size_hint: 1, 0.1 + halign: "center" Label: text: root.error_msg bold: True - size_hint: 1, 0.1 + size_hint: 1, None + height: dp(40) color: 1,0,0,1 GridLayout: cols: 2 @@ -71,10 +80,12 @@ password: True Widget: - size_hint: 1, 0.2 + size_hint: 1, None + height: dp(50) Widget: - size_hint: 1, 0.2 + size_hint: 1, None + height: dp(50) PMButton: text: "OK" @@ -94,75 +105,93 @@ orientation: "vertical" Label: + size_hint: 1, None + text_size: root.width, None + size: self.texture_size text: "Are you sure you want to delete the following profiles?" - size_hint: 1, 0.1 + halign: "center" Label: - text: u'\n'.join([i.text for i in root.pm.profiles_screen.list_adapter.selection]) + size_hint: 1, None + text_size: root.width, None + height: self.texture_size[1] + dp(60) + width: self.texture_size[0] + halign: "center" + # for now we only handle single selection + text: u'\n'.join([i.text for i in [root.pm.selected]]) if root.pm.selected else u'' bold: True Label: + size_hint: 1, None + text_size: root.width, dp(30) + height: self.texture_size[1] text: u'/!\\ WARNING: this operation is irreversible' color: 1,0,0,1 bold: True - size_hint: 1, 0.2 - + halign: "center" + valign: "top" GridLayout: cols: 2 - - Button: + PMButton: text: "Delete" - size_hint: 1, 0.2 on_press: root.doDelete() - Button: + PMButton: text: "Cancel" - size_hint: 1, 0.2 on_press: root.pm.screen_manager.transition.direction = 'right' root.pm.screen_manager.current = 'profiles' - Widget: - : layout: layout BoxLayout: - id: layout orientation: 'vertical' Label: + size_hint: 1, None + text_size: root.width, None + size: self.texture_size text: "Select a profile or create a new one" - size_hint: 1,0.05 + halign: "center" GridLayout: cols: 2 - size_hint: 1, 0.1 + size_hint: 1, None + height: dp(40) Button: - size_hint: 1, 0.1 text: "New" on_press: root.pm.screen_manager.transition.direction = 'left' root.pm.screen_manager.current = 'new_profile' Button: - disabled: not root.list_adapter.selection + disabled: not root.pm.selected text: "Delete" - size_hint: 1, 0.1 on_press: root.pm.screen_manager.transition.direction = 'left' root.pm.screen_manager.current = 'delete_profiles' - - -: - text: "Connect" - size_hint: 1, 0.1 - disabled: not self.profile_screen.list_adapter.selection - on_press: self.pm._onConnectProfiles() + ScrollView + BoxLayout: + size_hint: 1, None + height: self.minimum_height + orientation: "vertical" + id: layout + Button + text: "Connect" + size_hint: 1, None + height: dp(40) + disabled: not root.pm.selected + on_press: root.pm._onConnectProfiles() : + size_hint: 1, None background_normal: "" background_down: "" deselected_color: (1,1,1,1) if self.index%2 else (0.87,0.87,0.87,1) selected_color: 0.67,1.0,1.0,1 + selected: self.state == 'down' color: 0,0,0,1 + background_color: self.selected_color if self.selected else self.deselected_color + on_press: self.ps.pm.selected = self if self.selected else '' + height: dp(30)