Mercurial > libervia-desktop-kivy
diff libervia/desktop_kivy/core/common_widgets.py @ 493:b3cedbee561d
refactoring: rename `cagou` to `libervia.desktop_kivy` + update imports and names following backend changes
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 02 Jun 2023 18:26:16 +0200 |
parents | cagou/core/common_widgets.py@203755bbe0fe |
children | 196483685a63 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libervia/desktop_kivy/core/common_widgets.py Fri Jun 02 18:26:16 2023 +0200 @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 + +#Libervia Desktop-Kivy +# Copyright (C) 2016-2021 Jérôme Poisson (goffi@goffi.org) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +"""common advanced widgets, which can be reused everywhere.""" + +from kivy.clock import Clock +from kivy import properties +from kivy.metrics import dp +from kivy.uix.scatterlayout import ScatterLayout +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.label import Label +from libervia.backend.core.i18n import _ +from libervia.backend.core import log as logging +from libervia.desktop_kivy import G +from .behaviors import TouchMenuItemBehavior + +log = logging.getLogger(__name__) + + +class DelayedBoxLayout(BoxLayout): + """A BoxLayout with delayed layout, to avoid slowing down during resize""" + # XXX: thanks to Alexander Taylor for his blog post at + # https://blog.kivy.org/2019/07/a-delayed-resize-layout-in-kivy/ + + do_layout_event = properties.ObjectProperty(None, allownone=True) + layout_delay_s = properties.NumericProperty(0.2) + #: set this to X to force next X layouts to be done without delay + dont_delay_next_layouts = properties.NumericProperty(0) + + def do_layout(self, *args, **kwargs): + if self.do_layout_event is not None: + self.do_layout_event.cancel() + if self.dont_delay_next_layouts>0: + self.dont_delay_next_layouts-=1 + super().do_layout() + else: + real_do_layout = super().do_layout + self.do_layout_event = Clock.schedule_once( + lambda dt: real_do_layout(*args, **kwargs), + self.layout_delay_s) + + +class Identities(object): + + def __init__(self, entity_ids): + identities = {} + for cat, type_, name in entity_ids: + identities.setdefault(cat, {}).setdefault(type_, []).append(name) + client = identities.get('client', {}) + if 'pc' in client: + self.type = 'desktop' + elif 'phone' in client: + self.type = 'phone' + elif 'web' in client: + self.type = 'web' + elif 'console' in client: + self.type = 'console' + else: + self.type = 'desktop' + + self.identities = identities + + @property + def name(self): + first_identity = next(iter(self.identities.values())) + names = next(iter(first_identity.values())) + return names[0] + + +class ItemWidget(TouchMenuItemBehavior, BoxLayout): + name = properties.StringProperty() + base_width = properties.NumericProperty(dp(100)) + + +class DeviceWidget(ItemWidget): + + def __init__(self, main_wid, entity_jid, identities, **kw): + self.entity_jid = entity_jid + self.identities = identities + own_jid = next(iter(G.host.profiles.values())).whoami + self.own_device = entity_jid.bare == own_jid.bare + if self.own_device: + name = self.identities.name + elif self.entity_jid.node: + name = self.entity_jid.node + elif self.entity_jid == own_jid.domain: + name = _("your server") + else: + name = entity_jid + + super(DeviceWidget, self).__init__(name=name, main_wid=main_wid, **kw) + + @property + def profile(self): + return self.main_wid.profile + + def get_symbol(self): + if self.identities.type == 'desktop': + return 'desktop' + elif self.identities.type == 'phone': + return 'mobile' + elif self.identities.type == 'web': + return 'globe' + elif self.identities.type == 'console': + return 'terminal' + else: + return 'desktop' + + def do_item_action(self, touch): + pass + + +class CategorySeparator(Label): + pass + + +class ImageViewer(ScatterLayout): + source = properties.StringProperty() + + def on_touch_down(self, touch): + if touch.is_double_tap: + self.reset() + return True + return super().on_touch_down(touch) + + def reset(self): + self.rotation = 0 + self.scale = 1 + self.x = 0 + self.y = 0 + + +class ImagesGallery(BoxLayout): + """Show list of images in a Carousel, with some controls to downloads""" + sources = properties.ListProperty() + carousel = properties.ObjectProperty() + previous_slide = None + + def on_kv_post(self, __): + self.on_sources(None, self.sources) + self.previous_slide = self.carousel.current_slide + self.carousel.bind(current_slide=self.on_slide_change) + + def on_parent(self, __, parent): + # we hide the head widget to have full screen + G.host.app.show_head_widget(not bool(parent), animation=False) + + def on_sources(self, __, sources): + if not sources or not self.carousel: + return + self.carousel.clear_widgets() + for source in sources: + img = ImageViewer( + source=source, + ) + self.carousel.add_widget(img) + + def on_slide_change(self, __, slide): + if isinstance(self.previous_slide, ImageViewer): + self.previous_slide.reset() + + self.previous_slide = slide + + def key_input(self, window, key, scancode, codepoint, modifier): + if key == 27: + G.host.close_ui() + return True