From ad49aedaad3acece200ea92fd5d5a5b3e19c143b Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Fri, 6 Jan 2023 14:07:15 +0100 Subject: desktop dependent widgets early port --- tagit/dialogues/__init__.py | 59 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 tagit/dialogues/__init__.py (limited to 'tagit/dialogues') diff --git a/tagit/dialogues/__init__.py b/tagit/dialogues/__init__.py new file mode 100644 index 0000000..bee5bf4 --- /dev/null +++ b/tagit/dialogues/__init__.py @@ -0,0 +1,59 @@ +"""Popup dialogues. + +A dialogue can be opened from the main application. +It appears on top of the application and prevent its use until the dialogue +is closed. A dialogue contains buttons whose presses can be captured. + +>>> dlg = LabelDialogue(text='Hello world') +>>> dlg.bind(on_ok=...) +>>> dlg.bind(on_cancel=...) +>>> dlg.open() + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import typing + +# inner-module imports +##from .spash import Splash +#from .autoinput import AutoTextInput +#from .console import Console +#from .dir_creator import DirCreator +#from .dir_picker import DirPicker +#from .error import Error +#from .export import Export +#from .file_creator import FileCreator +#from .file_picker import FilePicker +#from .message import Message +#from .numeric_input import NumericInput +#from .path_creator import PathCreator +#from .path_picker import PathPicker +#from .progress import Progress +#from .project import Project +#from .simple_input import SimpleInput +#from .stoken import TokenEdit +#from .yesno import YesNo + +# exports +__all__: typing.Sequence[str] = ( + #'Console', + #'DirCreator', + #'DirPicker', + #'Error', + #'Export', + #'FileCreator', + #'FilePicker', + #'Message', + #'NumericInput', + #'PathCreator', + #'PathPicker', + #'Progress', + #'Project', + #'SimpleInput', + #'TokenEdit', + #'YesNo', + ) + +## EOF ## -- cgit v1.2.3 From 9c366758665d9cfee7796ee45a8167a5412ae9ae Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Fri, 13 Jan 2023 09:49:10 +0100 Subject: filter early port, parsing adaptions --- tagit/dialogues/__init__.py | 14 ++--- tagit/dialogues/autoinput.py | 73 +++++++++++++++++++++++++ tagit/dialogues/dialogue.kv | 114 ++++++++++++++++++++++++++++++++++++++++ tagit/dialogues/dialogue.py | 108 +++++++++++++++++++++++++++++++++++++ tagit/dialogues/error.py | 45 ++++++++++++++++ tagit/dialogues/license.t | 33 ++++++++++++ tagit/dialogues/simple_input.kv | 30 +++++++++++ tagit/dialogues/simple_input.py | 55 +++++++++++++++++++ tagit/dialogues/stoken.py | 40 ++++++++++++++ 9 files changed, 505 insertions(+), 7 deletions(-) create mode 100644 tagit/dialogues/autoinput.py create mode 100644 tagit/dialogues/dialogue.kv create mode 100644 tagit/dialogues/dialogue.py create mode 100644 tagit/dialogues/error.py create mode 100644 tagit/dialogues/license.t create mode 100644 tagit/dialogues/simple_input.kv create mode 100644 tagit/dialogues/simple_input.py create mode 100644 tagit/dialogues/stoken.py (limited to 'tagit/dialogues') diff --git a/tagit/dialogues/__init__.py b/tagit/dialogues/__init__.py index bee5bf4..d7792cb 100644 --- a/tagit/dialogues/__init__.py +++ b/tagit/dialogues/__init__.py @@ -18,11 +18,11 @@ import typing # inner-module imports ##from .spash import Splash -#from .autoinput import AutoTextInput +from .autoinput import AutoTextInput #from .console import Console #from .dir_creator import DirCreator #from .dir_picker import DirPicker -#from .error import Error +from .error import Error #from .export import Export #from .file_creator import FileCreator #from .file_picker import FilePicker @@ -32,8 +32,8 @@ import typing #from .path_picker import PathPicker #from .progress import Progress #from .project import Project -#from .simple_input import SimpleInput -#from .stoken import TokenEdit +from .simple_input import SimpleInput +from .stoken import TokenEdit #from .yesno import YesNo # exports @@ -41,7 +41,7 @@ __all__: typing.Sequence[str] = ( #'Console', #'DirCreator', #'DirPicker', - #'Error', + 'Error', #'Export', #'FileCreator', #'FilePicker', @@ -51,8 +51,8 @@ __all__: typing.Sequence[str] = ( #'PathPicker', #'Progress', #'Project', - #'SimpleInput', - #'TokenEdit', + 'SimpleInput', + 'TokenEdit', #'YesNo', ) diff --git a/tagit/dialogues/autoinput.py b/tagit/dialogues/autoinput.py new file mode 100644 index 0000000..a036ed4 --- /dev/null +++ b/tagit/dialogues/autoinput.py @@ -0,0 +1,73 @@ +"""This is a simple example of how to use suggestion text. + +In this example you setup a word_list at the begining. In this case +'the the quick brown fox jumps over the lazy old dog'. This list along +with any new word written word in the textinput is available as a +suggestion when you are typing. You can press tab to auto complete the text. + +Based on & thanks to akshayaurora: + https://gist.github.com/akshayaurora/fa5a68980af585e355668e5adce5f98b + +Part of the tagit module. +A copy of the license is provided with the project. +Modifications authored by: Matthias Baumgartner, 2022 +""" +# standard imports +from bisect import bisect + +# kivy imports +from kivy.uix.textinput import TextInput +import kivy.properties as kp + +# exports +__all__ = ('AutoTextInput', ) + + +## code ## + +class AutoTextInput(TextInput): + + sep = kp.StringProperty(',') + suffix = kp.StringProperty(' ') + vocabulary = kp.ListProperty() + + def on_suggestion_text(self, wx, value): + if not value: + return + + super(AutoTextInput, self).on_suggestion_text(wx, value) + + def keyboard_on_key_down(self, window, keycode, text, modifiers): + if self.suggestion_text and keycode[1] == 'tab': # complete suggestion_text + self.insert_text(self.suggestion_text + self.sep + self.suffix) + self.suggestion_text = '' + return True + return super(AutoTextInput, self).keyboard_on_key_down(window, keycode, text, modifiers) + + def on_text(self, wx, value): + # include all current text from textinput into the word list + # the kind of behavior sublime text has + + # what's on the current line + temp = value[:value.rfind(self.sep)].split(self.sep) + temp = [s.strip() for s in temp] + # combine with static vocabulary + wordlist = sorted(set(self.vocabulary + temp)) + + # get prefix + prefix = value[value.rfind(self.sep)+1:].strip() + if not prefix: + return + + # binary search on (sorted) wordlist + pos = bisect(wordlist, prefix) + + # check if matching string found + if pos == len(wordlist) or not wordlist[pos].startswith(prefix): + self.suggestion_text = '' + return + + # fetch suffix from wordlist + self.suggestion_text = wordlist[pos][len(prefix):] + +## EOF ## diff --git a/tagit/dialogues/dialogue.kv b/tagit/dialogues/dialogue.kv new file mode 100644 index 0000000..e23f0db --- /dev/null +++ b/tagit/dialogues/dialogue.kv @@ -0,0 +1,114 @@ +#:import get_root tagit.utils.get_root +# FIXME: remove need for get_root + +<-Dialogue>: + auto_dismiss: True + ok_on_enter: True + +: + + orientation: 'vertical' + padding: '12dp' + size_hint: 0.66, None + height: self.minimum_height + + canvas: + # mask main window + Color: + rgba: 0,0,0, 0.7 * self.parent._anim_alpha + Rectangle: + size: self.parent._window.size if self.parent._window else (0, 0) + + # solid background color + Color: + rgb: 1, 1, 1 + BorderImage: + source: self.parent.background + border: self.parent.border + pos: self.pos + size: self.size + + +: + # nothing to do + +: + title: '' + title_color: 1,1,1,1 + + Label: + text: root.title + size_hint_y: None + height: self.texture_size[1] + dp(16) + text_size: self.width - dp(16), None + font_size: '16sp' + color: root.title_color + bold: True + halign: 'center' + valing: 'middle' + + canvas.before: + # Background + Color: + rgb: 0.2, 0.2, 0.2 + Rectangle: + size: self.size + pos: self.pos + + # top border + #Color: + # rgb: 0.5, 0.5, 0.5 + #Line: + # points: self.x, self.y + self.height, self.x + self.width, self.y + self.height + # width: 2 + + # bottom border + #Color: + # rgb: 0.5, 0.5, 0.5 + #Line: + # points: self.x, self.y, self.x + self.width, self.y + # width: 2 + + # small space + Label: + size_hint_y: None + height: 12 + + +: + orientation: 'vertical' + size_hint_y: None + height: dp(48+8) + + # small space + Label: + size_hint_y: None + height: dp(8) + + # here come the buttons + + +: + ok_text: 'OK' + + Button: + text: root.ok_text + on_press: get_root(self).ok() + + +: + cancel_text: 'Cancel' + ok_text: 'OK' + ok_enabled: True + + BoxLayout: + orientation: 'horizontal' + Button: + text: root.cancel_text + on_press: get_root(self).cancel() + Button: + text: root.ok_text + on_press: get_root(self).ok() + disabled: not root.ok_enabled + +## EOF ## diff --git a/tagit/dialogues/dialogue.py b/tagit/dialogues/dialogue.py new file mode 100644 index 0000000..1aa0e9a --- /dev/null +++ b/tagit/dialogues/dialogue.py @@ -0,0 +1,108 @@ +"""Popup dialogue. + +Rougly based on code from https://gist.github.com/kived/742397a80d61e6be225a +by Ryan Pessa. The license is provided in the source folder. + +Part of the tagit module. +A copy of the license is provided with the project. +Modifications authored by: Matthias Baumgartner, 2022 +""" +# standard imports +import os + +# kivy imports +from kivy.lang import Builder +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.popup import Popup +import kivy.properties as kp + +# exports +__all__ = ('Dialogue', ) + + +## code ## + +# Load kv +Builder.load_file(os.path.join(os.path.dirname(__file__), 'dialogue.kv')) + +# classes +class Dialogue(Popup): + """Popup dialogue base class. + + Use like below: + + >>> dlg = Dialogue() + >>> dlg.bind(on_ok=....) + >>> dlg.open() + + """ + + ok_on_enter = kp.BooleanProperty() + + __events__ = ('on_ok', 'on_cancel') + + def __init__(self, *args, **kwargs): + super(Dialogue, self).__init__(*args, **kwargs) + from kivy.core.window import Window + # assumes that the first widget created controls the keyboard + #Window.children[-1].request_exclusive_keyboard() + # Alternatively, you can bind a function (self._on_keyboard) to on_keyboard + # which returns True. This stops the event from being processed by the main + # window. + # However, this still does not keep the 'enter' from 'on_text_validate' from + # being processed by the main window. + Window.bind(on_keyboard=self._on_keyboard) + # By binding to on_key_down, the key can trigger the ok action. + # This also prevents the enter event to be processed by the main window, + # unlike the 'on_text_validate' of TextInput. + Window.bind(on_key_down=self._key_down) + + def _on_keyboard(self, *args, **kwargs): + # block events from processing in the main window + return True + + def _key_down(self, instance, key, scancode, codepoint, modifiers): + if key == 13 and self.ok_on_enter: + self.ok() + return True + # must not stop other events such that ctrl up/down reach the browser + + def ok(self): + """User pressed the OK button.""" + self.dispatch('on_ok') + self.dismiss() + + def cancel(self): + """User pressed the Cancel button.""" + self.dispatch('on_cancel') + self.dismiss() + + def on_dismiss(self): + from kivy.core.window import Window + # assumes that the first widget created controls the keyboard + #Window.children[-1].release_exclusive_keyboard() + Window.unbind(on_keyboard=self._on_keyboard) + Window.unbind(on_key_down=self._key_down) + super(Dialogue, self).on_dismiss() + + def on_ok(self): + """Event prototype.""" + pass + + def on_cancel(self): + """Event prototype.""" + pass + +# helper classes + +# content bases +class DialogueContentBase(BoxLayout): pass +class DialogueContentTitle(DialogueContentBase): pass +class DialogueContentNoTitle(DialogueContentBase): pass + +# buttons +class DialogueButtons(BoxLayout): pass +class DialogueButtons_One(DialogueButtons): pass +class DialogueButtons_Two(DialogueButtons): pass + +## EOF ## diff --git a/tagit/dialogues/error.py b/tagit/dialogues/error.py new file mode 100644 index 0000000..d93f853 --- /dev/null +++ b/tagit/dialogues/error.py @@ -0,0 +1,45 @@ +"""Dialogue to show an error message. + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# kivy imports +from kivy.lang import Builder +import kivy.properties as kp + +# inner-module imports +from .dialogue import Dialogue + +# exports +__all__ = ('Error', ) + + +## code ## + +# load kv +Builder.load_string(''' +: + text: '' + ok_on_enter: False + + DialogueContentNoTitle: + + Label: + markup: True + text: root.text + size_hint_y: None + color: 1, 0, 0, 1 + height: self.texture_size[1] + dp(16) + text_size: self.width - dp(16), None + halign: 'center' + + DialogueButtons_One: +''') + +# classes +class Error(Dialogue): + """Error message.""" + text = kp.StringProperty('') + +## EOF ## diff --git a/tagit/dialogues/license.t b/tagit/dialogues/license.t new file mode 100644 index 0000000..bbd2830 --- /dev/null +++ b/tagit/dialogues/license.t @@ -0,0 +1,33 @@ + +The dialogues are based on the following code: + +https://gist.github.com/kived/742397a80d61e6be225a + +It ships with license, provided below: + +>>> The following license shall apply to all Public Gists owned by account. It +>>> shall never apply to any Secret Gists, for which no license of any sort is +>>> granted. +>>> +>>> Copyright (c) 2015- Ryan Pessa +>>> +>>> Permission is hereby granted, free of charge, to any person obtaining a copy +>>> of this software and associated documentation files (the "Software"), to deal +>>> in the Software without restriction, including without limitation the rights +>>> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +>>> copies of the Software, and to permit persons to whom the Software is +>>> furnished to do so, subject to the following conditions: +>>> +>>> The above copyright notice and this permission notice shall be included in +>>> all copies or substantial portions of the Software. +>>> +>>> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +>>> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +>>> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +>>> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +>>> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +>>> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +>>> THE SOFTWARE. + +Code modification are subject to the license of the tagit software. + diff --git a/tagit/dialogues/simple_input.kv b/tagit/dialogues/simple_input.kv new file mode 100644 index 0000000..b7deb9c --- /dev/null +++ b/tagit/dialogues/simple_input.kv @@ -0,0 +1,30 @@ + +#:import AutoTextInput tagit.dialogues + +: + text: '' + ok_on_enter: True + cancel_on_defocus: True + + DialogueContentNoTitle: + + #AutoTextInput: + TextInput: + vocabulary: root.suggestions + sep: root.suggestion_sep + suffix: root.suggestion_suffix + focus: True + text: root.text + size_hint_y: None + multiline: False + height: self.minimum_height + text_size: self.width - dp(16), None + halign: 'center' + + on_text: root.text = self.text + on_focus: root.on_text_focus(*args) + #on_text_validate: root.ok() # handled via the ok_on_enter mechanism + + DialogueButtons_Two: + +## EOF ## diff --git a/tagit/dialogues/simple_input.py b/tagit/dialogues/simple_input.py new file mode 100644 index 0000000..d7cc69f --- /dev/null +++ b/tagit/dialogues/simple_input.py @@ -0,0 +1,55 @@ +"""Dialogue with a single-line text input field. + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import os + +# kivy imports +from kivy.lang import Builder +import kivy.properties as kp + +# inner-module imports +from .dialogue import Dialogue + +# exports +__all__ = ('SimpleInput', ) + + +## code ## + +# load kv +Builder.load_file(os.path.join(os.path.dirname(__file__), 'simple_input.kv')) + +# classes +class SimpleInput(Dialogue): + """Dialogue with a single-line text input field. + + Pass the default text as **text**. + + >>> SimpleInput(text='Hello world').open() + + In case of touch events, they need to be inhibited to change the focus. + + >>> FocusBehavior.ignored_touch.append(touch) + + """ + + # Defocus problem: + # Buttons defocus when on_press, but on_release is ok. + # Touch events must be blocked via FocusBehavior + + text = kp.StringProperty('') + cancel_on_defocus = kp.BooleanProperty(True) + suggestions = kp.ListProperty() + suggestion_sep = kp.StringProperty(',') + suggestion_suffix = kp.StringProperty(' ') + + + def on_text_focus(self, instance, focus): + if not focus and self.cancel_on_defocus: + self.dismiss() + +## EOF ## diff --git a/tagit/dialogues/stoken.py b/tagit/dialogues/stoken.py new file mode 100644 index 0000000..6e5427a --- /dev/null +++ b/tagit/dialogues/stoken.py @@ -0,0 +1,40 @@ +"""Search token editor + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 + +""" +# kivy imports +from kivy.lang import Builder +import kivy.properties as kp + +# inner-module imports +from .simple_input import SimpleInput + +# exports +__all__ = ('TokenEdit', ) + + +## code ## + +# Load kv +Builder.load_string(''' +#:import AutoTextInput tagit.dialogues + +: + text: '' + ok_on_enter: True + cancel_on_defocus: True +''') + +# classes +class TokenEdit(SimpleInput): + """Search token editor + """ + # TODO: Currently this is no different than SimpleInput. + # It should be extend to specify the type and getting help + # with editing ranges and alternative selection. + pass + +## EOF ## -- cgit v1.2.3 From f59878447c8367b50fe3eebefb80484b2a380394 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Fri, 13 Jan 2023 10:38:21 +0100 Subject: status dialogues port: numeric input and console --- tagit/dialogues/__init__.py | 8 ++--- tagit/dialogues/console.kv | 30 +++++++++++++++++ tagit/dialogues/console.py | 37 +++++++++++++++++++++ tagit/dialogues/numeric_input.py | 72 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 tagit/dialogues/console.kv create mode 100644 tagit/dialogues/console.py create mode 100644 tagit/dialogues/numeric_input.py (limited to 'tagit/dialogues') diff --git a/tagit/dialogues/__init__.py b/tagit/dialogues/__init__.py index d7792cb..f63ec87 100644 --- a/tagit/dialogues/__init__.py +++ b/tagit/dialogues/__init__.py @@ -19,7 +19,7 @@ import typing # inner-module imports ##from .spash import Splash from .autoinput import AutoTextInput -#from .console import Console +from .console import Console #from .dir_creator import DirCreator #from .dir_picker import DirPicker from .error import Error @@ -27,7 +27,7 @@ from .error import Error #from .file_creator import FileCreator #from .file_picker import FilePicker #from .message import Message -#from .numeric_input import NumericInput +from .numeric_input import NumericInput #from .path_creator import PathCreator #from .path_picker import PathPicker #from .progress import Progress @@ -38,7 +38,7 @@ from .stoken import TokenEdit # exports __all__: typing.Sequence[str] = ( - #'Console', + 'Console', #'DirCreator', #'DirPicker', 'Error', @@ -46,7 +46,7 @@ __all__: typing.Sequence[str] = ( #'FileCreator', #'FilePicker', #'Message', - #'NumericInput', + 'NumericInput', #'PathCreator', #'PathPicker', #'Progress', diff --git a/tagit/dialogues/console.kv b/tagit/dialogues/console.kv new file mode 100644 index 0000000..b68227d --- /dev/null +++ b/tagit/dialogues/console.kv @@ -0,0 +1,30 @@ + +: + text: '' + title: 'tagit log console' + ok_on_enter: False + init_at_bottom: True + + DialogueContentTitle: + title: root.title + size_hint_y: 0.6 + + ScrollView: + scroll_y: 0 if root.init_at_bottom else 1 + + Label: + text: root.text + size_hint_y: None + height: self.texture_size[1] + text_size: self.width, None + bold: True + font_name: resource_find('DejaVuSansMono.ttf') # monospace font + markup: True + multiline: True + halign: 'left' + + DialogueButtons_One: + ok_text: "close" + # FIXME: Inform that this action will not terminate the underlying process + +## EOF ## diff --git a/tagit/dialogues/console.py b/tagit/dialogues/console.py new file mode 100644 index 0000000..282b378 --- /dev/null +++ b/tagit/dialogues/console.py @@ -0,0 +1,37 @@ +""" + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import os + +# kivy imports +from kivy.clock import mainthread +from kivy.lang import Builder +import kivy.properties as kp + +# inner-module imports +from .dialogue import Dialogue + +# exports +__all__ = ('Console', ) + + +## code ## + +# load kv +Builder.load_file(os.path.join(os.path.dirname(__file__), 'console.kv')) + +# classes +class Console(Dialogue): + """Dialogue with console output.""" + + text = kp.StringProperty('') + + @mainthread + def update(self, sender, text): + self.text = '\n'.join(text) + +## EOF ## diff --git a/tagit/dialogues/numeric_input.py b/tagit/dialogues/numeric_input.py new file mode 100644 index 0000000..63491d2 --- /dev/null +++ b/tagit/dialogues/numeric_input.py @@ -0,0 +1,72 @@ +"""Dialogue with a slider. + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# kivy imports +from kivy.lang import Builder +import kivy.properties as kp + +# inner-module imports +from .dialogue import Dialogue + +# exports +__all__ = ('NumericInput', ) + + +## code ## + +# load kv +Builder.load_string(''' + +: + value: int(slider.value) + init_value: 0 + + DialogueContentNoTitle: + + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: 50 + + Label: + text: str(root.lo) + size_hint_x: None + width: self.texture_size[0] + + Slider: + id: slider + orientation: 'horizontal' + min: root.lo + max: root.hi + step: 1 + value: root.init_value + + Label: + text: str(root.hi) + size_hint_x: None + width: self.texture_size[0] + + Label: + text: str(root.value) + size_hint: 1, None + height: self.texture_size[1] + halign: 'center' + + DialogueButtons_Two: + +''') + +# classes +class NumericInput(Dialogue): + """Dialogue with a slider.""" + + lo = kp.NumericProperty(0) + hi = kp.NumericProperty(100) + value = kp.NumericProperty(0) + init_value = kp.NumericProperty(0) + + +## EOF ## -- cgit v1.2.3 From 5a818f9e90c7758f2f77de822390b7f4bf4f9ef5 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Fri, 13 Jan 2023 10:44:58 +0100 Subject: dialogues cleanup --- tagit/dialogues/__init__.py | 9 ++------- tagit/dialogues/message.py | 47 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 tagit/dialogues/message.py (limited to 'tagit/dialogues') diff --git a/tagit/dialogues/__init__.py b/tagit/dialogues/__init__.py index f63ec87..a467699 100644 --- a/tagit/dialogues/__init__.py +++ b/tagit/dialogues/__init__.py @@ -17,20 +17,17 @@ Author: Matthias Baumgartner, 2022 import typing # inner-module imports -##from .spash import Splash from .autoinput import AutoTextInput from .console import Console #from .dir_creator import DirCreator #from .dir_picker import DirPicker from .error import Error -#from .export import Export #from .file_creator import FileCreator #from .file_picker import FilePicker -#from .message import Message +from .message import Message from .numeric_input import NumericInput #from .path_creator import PathCreator #from .path_picker import PathPicker -#from .progress import Progress #from .project import Project from .simple_input import SimpleInput from .stoken import TokenEdit @@ -42,14 +39,12 @@ __all__: typing.Sequence[str] = ( #'DirCreator', #'DirPicker', 'Error', - #'Export', #'FileCreator', #'FilePicker', - #'Message', + 'Message', 'NumericInput', #'PathCreator', #'PathPicker', - #'Progress', #'Project', 'SimpleInput', 'TokenEdit', diff --git a/tagit/dialogues/message.py b/tagit/dialogues/message.py new file mode 100644 index 0000000..ab67180 --- /dev/null +++ b/tagit/dialogues/message.py @@ -0,0 +1,47 @@ +"""Dialogue to show some message. + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# kivy imports +from kivy.lang import Builder +import kivy.properties as kp + +# inner-module imports +from .dialogue import Dialogue + +# exports +__all__ = ('Message', ) + + +## code ## + +# load kv +Builder.load_string(''' +: + text: '' + align: 'center' + textcolor: 1,1,1,1 + + DialogueContentNoTitle: + Label: + text: root.text + size_hint_y: None + color: root.textcolor + height: self.texture_size[1] + dp(16) + text_size: self.width - dp(16), None + halign: root.align + markup: True + + DialogueButtons_One: +''') + +# classes +class Message(Dialogue): + """Dialogue to show a text message.""" + text = kp.StringProperty() + align = kp.StringProperty() + textcolor: kp.ListProperty() + +## EOF ## -- cgit v1.2.3 From 4d0ce7fb62eaad3a1f705ec3c77744e3ebc96a9e Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sun, 29 Jan 2023 11:31:16 +0100 Subject: session actions port --- tagit/dialogues/__init__.py | 8 ++++---- tagit/dialogues/file_picker.py | 39 +++++++++++++++++++++++++++++++++++++++ tagit/dialogues/path_picker.kv | 27 +++++++++++++++++++++++++++ tagit/dialogues/path_picker.py | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 tagit/dialogues/file_picker.py create mode 100644 tagit/dialogues/path_picker.kv create mode 100644 tagit/dialogues/path_picker.py (limited to 'tagit/dialogues') diff --git a/tagit/dialogues/__init__.py b/tagit/dialogues/__init__.py index a467699..3647bf0 100644 --- a/tagit/dialogues/__init__.py +++ b/tagit/dialogues/__init__.py @@ -23,11 +23,11 @@ from .console import Console #from .dir_picker import DirPicker from .error import Error #from .file_creator import FileCreator -#from .file_picker import FilePicker +from .file_picker import FilePicker from .message import Message from .numeric_input import NumericInput #from .path_creator import PathCreator -#from .path_picker import PathPicker +from .path_picker import PathPicker #from .project import Project from .simple_input import SimpleInput from .stoken import TokenEdit @@ -40,11 +40,11 @@ __all__: typing.Sequence[str] = ( #'DirPicker', 'Error', #'FileCreator', - #'FilePicker', + 'FilePicker', 'Message', 'NumericInput', #'PathCreator', - #'PathPicker', + 'PathPicker', #'Project', 'SimpleInput', 'TokenEdit', diff --git a/tagit/dialogues/file_picker.py b/tagit/dialogues/file_picker.py new file mode 100644 index 0000000..283adb6 --- /dev/null +++ b/tagit/dialogues/file_picker.py @@ -0,0 +1,39 @@ +"""Dialogue to pick a file. + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import os + +# kivy imports +from kivy.lang import Builder + +# inner-module imports +from .path_picker import PathPicker +from .error import Error + +# exports +__all__ = ('FilePicker', ) + + +## code ## + +# load kv +Builder.load_string(''' +: + dirselect: False + title: 'Please select a file' +''') + +# classes +class FilePicker(PathPicker): + """Dialogue with a file browser to select a file.""" + def ok(self): + if not os.path.exists(self.path) or not os.path.isfile(self.path): + Error(text='Please select a file').open() + else: + super(FilePicker, self).ok() + +## EOF ## diff --git a/tagit/dialogues/path_picker.kv b/tagit/dialogues/path_picker.kv new file mode 100644 index 0000000..1837b80 --- /dev/null +++ b/tagit/dialogues/path_picker.kv @@ -0,0 +1,27 @@ +#:import join os.path.join +#:import pwd os.path.curdir + +: + path: '' + title: 'Please select a file or directory' + filters: [] + dirselect: True + + DialogueContentTitle: + title: root.title + size_hint_y: 0.8 + + FileChooserListView: + text_size: self.width - dp(16), None + halign: 'center' + dirselect: root.dirselect + path: pwd + filters: root.filters + + on_selection: root.path = join(self.path, self.selection[0]); buttons.ok_enabled = True + + DialogueButtons_Two: + id: buttons + ok_enabled: False + +## EOF ## diff --git a/tagit/dialogues/path_picker.py b/tagit/dialogues/path_picker.py new file mode 100644 index 0000000..25bbf32 --- /dev/null +++ b/tagit/dialogues/path_picker.py @@ -0,0 +1,41 @@ +"""Dialogue to pick a file or directory. + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import os + +# kivy imports +from kivy.lang import Builder +import kivy.properties as kp + +# inner-module imports +from .dialogue import Dialogue +from .error import Error + +# exports +__all__ = ('PathPicker', ) + + +## code ## + +# load kv +Builder.load_file(os.path.join(os.path.dirname(__file__), 'path_picker.kv')) + +# classes +class PathPicker(Dialogue): + """Dialogue with a file browser to select a file or directory.""" + + title = kp.StringProperty('') + path = kp.StringProperty('') + filters = kp.ListProperty() + + def ok(self): + if not os.path.exists(self.path): + Error(text='Please select a file or directory').open() + else: + super(PathPicker, self).ok() + +## EOF ## -- cgit v1.2.3 From 0fe45bb93b7a62afa7b8b04145607aca9e57af13 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sun, 29 Jan 2023 11:38:22 +0100 Subject: cleanup --- tagit/dialogues/__init__.py | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'tagit/dialogues') diff --git a/tagit/dialogues/__init__.py b/tagit/dialogues/__init__.py index 3647bf0..beed253 100644 --- a/tagit/dialogues/__init__.py +++ b/tagit/dialogues/__init__.py @@ -19,36 +19,24 @@ import typing # inner-module imports from .autoinput import AutoTextInput from .console import Console -#from .dir_creator import DirCreator -#from .dir_picker import DirPicker from .error import Error -#from .file_creator import FileCreator from .file_picker import FilePicker from .message import Message from .numeric_input import NumericInput -#from .path_creator import PathCreator from .path_picker import PathPicker -#from .project import Project from .simple_input import SimpleInput from .stoken import TokenEdit -#from .yesno import YesNo # exports __all__: typing.Sequence[str] = ( 'Console', - #'DirCreator', - #'DirPicker', 'Error', - #'FileCreator', 'FilePicker', 'Message', 'NumericInput', - #'PathCreator', 'PathPicker', - #'Project', 'SimpleInput', 'TokenEdit', - #'YesNo', ) ## EOF ## -- cgit v1.2.3 From 580caf6f5c9b795f9c38b9c970efce12d006ce1d Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Fri, 17 Feb 2023 08:25:44 +0100 Subject: New UI design * Moved style definitions to its own file (themes/default) * Updated the desktop.kv to the new UI design * Removed planes * Adjusted port config --- tagit/dialogues/dialogue.kv | 63 ++++++++++----------------------------------- tagit/dialogues/dialogue.py | 6 ++--- 2 files changed, 16 insertions(+), 53 deletions(-) (limited to 'tagit/dialogues') diff --git a/tagit/dialogues/dialogue.kv b/tagit/dialogues/dialogue.kv index e23f0db..e2cab66 100644 --- a/tagit/dialogues/dialogue.kv +++ b/tagit/dialogues/dialogue.kv @@ -6,68 +6,28 @@ ok_on_enter: True : - orientation: 'vertical' padding: '12dp' size_hint: 0.66, None height: self.minimum_height - canvas: - # mask main window - Color: - rgba: 0,0,0, 0.7 * self.parent._anim_alpha - Rectangle: - size: self.parent._window.size if self.parent._window else (0, 0) - - # solid background color - Color: - rgb: 1, 1, 1 - BorderImage: - source: self.parent.background - border: self.parent.border - pos: self.pos - size: self.size - : # nothing to do + +: + : title: '' title_color: 1,1,1,1 - Label: + DialogueTitle: text: root.title size_hint_y: None height: self.texture_size[1] + dp(16) text_size: self.width - dp(16), None - font_size: '16sp' color: root.title_color - bold: True - halign: 'center' - valing: 'middle' - - canvas.before: - # Background - Color: - rgb: 0.2, 0.2, 0.2 - Rectangle: - size: self.size - pos: self.pos - - # top border - #Color: - # rgb: 0.5, 0.5, 0.5 - #Line: - # points: self.x, self.y + self.height, self.x + self.width, self.y + self.height - # width: 2 - - # bottom border - #Color: - # rgb: 0.5, 0.5, 0.5 - #Line: - # points: self.x, self.y, self.x + self.width, self.y - # width: 2 # small space Label: @@ -75,7 +35,10 @@ height: 12 -: + +: + +: orientation: 'vertical' size_hint_y: None height: dp(48+8) @@ -88,25 +51,25 @@ # here come the buttons -: +: ok_text: 'OK' - Button: + DialogueButton: text: root.ok_text on_press: get_root(self).ok() -: +: cancel_text: 'Cancel' ok_text: 'OK' ok_enabled: True BoxLayout: orientation: 'horizontal' - Button: + DialogueButton: text: root.cancel_text on_press: get_root(self).cancel() - Button: + DialogueButton: text: root.ok_text on_press: get_root(self).ok() disabled: not root.ok_enabled diff --git a/tagit/dialogues/dialogue.py b/tagit/dialogues/dialogue.py index 1aa0e9a..bf72a28 100644 --- a/tagit/dialogues/dialogue.py +++ b/tagit/dialogues/dialogue.py @@ -101,8 +101,8 @@ class DialogueContentTitle(DialogueContentBase): pass class DialogueContentNoTitle(DialogueContentBase): pass # buttons -class DialogueButtons(BoxLayout): pass -class DialogueButtons_One(DialogueButtons): pass -class DialogueButtons_Two(DialogueButtons): pass +class DialogueButtonRow(BoxLayout): pass +class DialogueButtons_One(DialogueButtonRow): pass +class DialogueButtons_Two(DialogueButtonRow): pass ## EOF ## -- cgit v1.2.3