Merge branch 'dev'

This commit is contained in:
Jan
2023-03-17 11:20:55 +01:00
25 changed files with 314 additions and 0 deletions

3
.gitignore vendored
View File

@@ -127,3 +127,6 @@ dmypy.json
# Pyre type checker
.pyre/
# Kivy
.buildozer/

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -0,0 +1 @@
<mxfile host="app.diagrams.net" modified="2023-03-06T11:09:54.626Z" agent="5.0 (Windows)" etag="DccbIbGf31_jB3hpeEkb" version="21.0.2" type="device"><diagram name="Seite-1" id="MAx1qc_yxkcqeCQ3BJs1">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</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

12
requirements.txt Normal file
View File

@@ -0,0 +1,12 @@
certifi==2022.12.7
charset-normalizer==3.1.0
docutils==0.19
idna==3.4
Kivy==2.1.0
Kivy-Garden==0.1.5
kivymd==1.1.1
Pillow==9.4.0
Pygments==2.14.0
requests==2.28.2
urllib3==1.26.15
watchdog

1
sources.md Normal file
View File

@@ -0,0 +1 @@
- icons von: [Google fonts](https://fonts.google.com/icons?selected=Material+Symbols+Rounded:shopping_bag:FILL@0;wght@400;GRAD@0;opsz@48&icon.style=Rounded)

130
src/main.py Normal file
View File

@@ -0,0 +1,130 @@
from os import name
from kivy.app import App
from kivy.properties import ListProperty, StringProperty, BooleanProperty, ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Label
from kivy.metrics import dp
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.core.window import Window
from kivymd.app import MDApp
from kivymd.uix.button import MDFlatButton
from kivymd.uix.card.card import MDBoxLayout
from kivymd.uix.dialog import MDDialog
from kivymd.uix.menu import MDDropdownMenu
from kivymd.uix.list import OneLineAvatarIconListItem
from setting_widgets.setting_fields import SettingTextField, SettingToggleField, SettingDropDownField
LANGUAGES = { "DE": "Deutsch", "EN": "English", "FR": "Francais" }
Window.size = (400, 800)
class ShoppingEntry(OneLineAvatarIconListItem):
def __init__(self, text, **kwargs):
super().__init__(**kwargs)
self.text = text
self.is_checked = False
def delete(self, shopping_entry):
self.parent.remove_widget(shopping_entry)
class AddDialog(MDBoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
class ShoppingEntryScreen(Screen):
add_dialog = None
def open_add_popup(self):
if self.add_dialog:
return
# SPRACHE
buttons = [
MDFlatButton(text='Abbrechen', on_release=self.close_add_popup),
MDFlatButton(text='Bestätigen', on_release=lambda args: self.add_shopping_entry("Text"))
]
# SPRACHE
self.add_dialog = MDDialog(
title='Eintrag hinzufügen',
type='custom',
content_cls=AddDialog(),
buttons=buttons
)
self.add_dialog.open()
# *args ist noetig, da weitere Parameter mitgegeben werden, die aber nicht genutzt werden
def close_add_popup(self, *args):
if not self.add_dialog:
return
self.add_dialog.dismiss()
self.add_dialog = None
def add_shopping_entry(self, text):
self.ids['shopping_list'].add_widget(ShoppingEntry(text=text))
self.close_add_popup()
def delete_entry(self):
pass
def navigate_to_settings(self):
self.manager.transition.direction = 'left'
self.manager.current = 'settings'
class SettingsScreen(Screen):
#languages = ListProperty(["Deutsch", "English", "Francais"])
def __init__(self, **kwargs):
super().__init__(**kwargs)
menu_items = [
{
"viewclass": "OneLineListItem",
"text": f"{LANGUAGES.get(language_key)}",
"height": dp(56),
"on_release": lambda x=f"{LANGUAGES.get(language_key)}": self.set_item(language_key),
} for language_key in LANGUAGES.keys()
]
self.menu = MDDropdownMenu(
caller=self.ids.language_drop_down,
items=menu_items,
position="center",
width_mult=4,
)
self.menu.bind()
def navigate_to_shopping_list(self):
self.manager.transition.direction = 'right'
self.manager.current = 'shopping'
def show_languages_menu(self):
self.menu.open()
def set_item(self, language_key):
language = LANGUAGES.get(language_key)
self.ids.language_drop_down.set_item(language)
self.menu.dismiss()
class ShoppingListApp(MDApp):
def build(self):
self.theme_cls.primary_palette = "Teal"
self.theme_cls.theme_style = "Light"
self.title = 'Shopping List App'
sm = ScreenManager()
sm.add_widget(ShoppingEntryScreen(name='shopping'))
sm.add_widget(SettingsScreen(name='settings'))
return sm
if __name__ == "__main__":
app = ShoppingListApp()
app.run()

BIN
src/res/add_circle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 B

BIN
src/res/arrow_back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

BIN
src/res/delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

BIN
src/res/expand_more.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

BIN
src/res/filter_list.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

BIN
src/res/settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
src/res/shopping_bag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

View File

@@ -0,0 +1,3 @@
from .setting_fields import SettingTextField
from .setting_fields import SettingToggleField
from .setting_fields import SettingDropDownField

View File

@@ -0,0 +1,20 @@
<SettingTextField>:
divider: None
_no_ripple_effect: True
RightTextField:
id: setting_right_text_field
<SettingToggleField>:
divider: None
_no_ripple_effect: True
RightToggleField:
id: setting_right_toggle_field
<SettingDropDownField>:
divider: None
_no_ripple_effect: True
RightDropDownField:
id: setting_right_dropdown_field

View File

@@ -0,0 +1,31 @@
from kivymd.uix.dropdownitem import MDDropDownItem
from kivymd.uix.list import BaseListItem, OneLineRightIconListItem, IRightBodyTouch
from kivymd.uix.selectioncontrol.selectioncontrol import MDSwitch
from kivymd.uix.textfield import MDTextField
from kivy.lang import Builder
Builder.load_file("setting_widgets\setting_fields.kv")
# ===== TextField =====
class SettingTextField(OneLineRightIconListItem):
"""DOCS"""
class RightTextField(IRightBodyTouch, MDTextField):
"""DOCS"""
# ===== ToggleField =====
class SettingToggleField(OneLineRightIconListItem):
"""DOCS"""
class RightToggleField(IRightBodyTouch, MDSwitch):
"""DOCS"""
# ===== DropDownField =====
class SettingDropDownField(OneLineRightIconListItem):
"""DOCS"""
class RightDropDownField(IRightBodyTouch, MDDropDownItem):
"""DOCS"""

113
src/shoppinglist.kv Normal file
View File

@@ -0,0 +1,113 @@
<ShoppingEntry>:
id: shopping_entry
markup: True
ImageLeftWidget:
MDCheckbox:
id: shopping_entry_check
# bind to property
IconRightWidget:
icon: 'res/delete.png'
on_release: root.delete(shopping_entry)
<AddDialog>:
size_hint: 1, None
height: '40dp'
orientation: 'vertical'
spacing: '5dp'
MDTextField:
id: shopping_entry_text
pos_hint: { 'center_y': 0.4 }
# SPRACHE
hint_text: 'Neuer Eintrag'
<ShoppingEntryScreen>:
MDBoxLayout:
orientation: 'vertical'
pos_hint: { 'center_x': 0.5, 'center_y': 0.5 }
MDTopAppBar:
#SPRACHE
title: 'Shopping-List-App'
md_bg_color: app.theme_cls.primary_color
specific_text_color: '#000000'
right_action_items: [['res/settings.png', lambda x: root.navigate_to_settings()]]
ScrollView:
size_hint: 0.85, 0.85
pos_hint: { 'center_y': 1, 'center_x': 0.5 }
MDList:
id: shopping_list
MDFloatingActionButton:
icon: 'plus'
elevation_normal: 5
# bottom align is complicated
pos_hint: { 'top': (self.height/root.height)*1.5, 'right':0.95 }
on_release: root.open_add_popup()
<SettingsScreen>:
MDBoxLayout:
orientation: 'vertical'
MDTopAppBar:
#SPRACHE
title: 'Shopping-List-App'
md_bg_color: app.theme_cls.primary_color
specific_text_color: '#000000'
left_action_items: [['res/arrow_back.png', lambda x: root.navigate_to_shopping_list()]]
MDBoxLayout:
orientation: 'horizontal'
pos_hint: { 'center_x': 0.5 }
size_hint: (0.7, 0.25)
# SPRACHE
MDLabel:
text: 'Sprache'
MDDropDownItem:
id: language_drop_down
text: 'Deutsch'
on_release: root.show_languages_menu()
MDBoxLayout:
orientation: 'horizontal'
pos_hint: { 'center_x': 0.5 }
size_hint: (0.7, 0.25)
# SPRACHE
SettingToggleField:
text: 'Theme'
MDBoxLayout:
orientation: 'horizontal'
pos_hint: { 'center_x': 0.5 }
size_hint: (0.7, 0.25)
# SPRACHE
SettingTextField:
text: 'MQTT-Server'
MDBoxLayout:
orientation: 'horizontal'
pos_hint: { 'center_x': 0.5 }
size_hint: (0.7, 0.25)
# SPRACHE
SettingTextField:
text: 'MQTT-Topic'
MDBoxLayout:
orientation: 'horizontal'
pos_hint: { 'center_x': 0.5 }
size_hint: (0.7, 0.25)
# SPRACHE
SettingTextField:
text: 'MQTT-Benutzername'
MDBoxLayout:
orientation: 'horizontal'
pos_hint: { 'center_x': 0.5 }
size_hint: (0.7, 0.25)
# SPRACHE
SettingTextField:
text: 'MQTT-Passwort'