bootstack 0.1.0a5__tar.gz → 0.1.0a6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bootstack-0.1.0a5/src/bootstack.egg-info → bootstack-0.1.0a6}/PKG-INFO +1 -1
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/pyproject.toml +2 -2
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/__init__.py +7 -2
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/style.py +4 -1
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/widgets.py +3 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/__init__.py +4 -1
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/add.py +2 -2
- bootstack-0.1.0a6/src/bootstack/cli/icons.py +28 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/sqlite_source.py +60 -53
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/field.py +21 -5
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/form.py +1 -2
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tableview/tableview.py +19 -19
- {bootstack-0.1.0a5 → bootstack-0.1.0a6/src/bootstack.egg-info}/PKG-INFO +1 -1
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack.egg-info/SOURCES.txt +1 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/LICENSE +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/MANIFEST.in +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/NOTICE +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/README.md +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/setup.cfg +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/__main__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/app.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/constants.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/data.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/dialogs.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/i18n.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/localization.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/menu.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/utils.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/bootstack-dark.ico +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/bootstack-light.ico +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/bootstack-transparent.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/bootstack.ico +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/bootstack.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/badge-pill.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/badge-square.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/border.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-compact.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-horizontal-after-compact.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-horizontal-after-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-horizontal-before-compact.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-horizontal-before-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-horizontal-center-compact.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-horizontal-center-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-vertical-after-compact.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-vertical-after-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-vertical-before-compact.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-vertical-before-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-vertical-center-compact.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-vertical-center-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/checkbox-checked.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/checkbox-indeterminate.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/checkbox-unchecked.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/field.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/input-after-compact.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/input-after-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/input-before-compact.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/input-before-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/input-compact.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/input-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/list-item-separated.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/list-item.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/manifest.toml +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/menu-item.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/nav-button-compact.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/nav-button-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/nav-icon-button-compact.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/nav-icon-button-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/notebook-client-border.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/notebook-tab-active.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/notebook-tab-bar.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/notebook-tab-normal.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/notebook-tab-pill.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/progress-bar-horizontal-striped.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/progress-bar-solid.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/progress-bar-thin.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/progress-bar-vertical-striped.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/radio-selected.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/radio-unselected.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/scrollbar-horizontal.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/scrollbar-vertical.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/slider-handle-focus.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/slider-handle.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/slider-track-horizontal.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/slider-track-vertical.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/switch-off.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/switch-on.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/tabs-bar-horizontal.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/tabs-bar-vertical.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/tabs-pill.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/amber-dark.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/amber-light.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/aurora-dark.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/aurora-light.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/bootstrap-dark.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/bootstrap-light.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/classic-dark.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/classic-light.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/docs-dark.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/docs-light.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/forest-dark.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/forest-light.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/ocean-dark.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/ocean-light.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/rose-dark.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/rose-light.json +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/badge-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/badge-pill.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/border.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button-group-horizontal-after.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button-group-horizontal-before.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button-group-horizontal-center.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button-group-vertical-after.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button-group-vertical-before.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button-group-vertical-center.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/checkbox-checked.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/checkbox-indeterminate.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/checkbox-unchecked.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/field.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/icon-button.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/input-inner.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/input-prefix.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/input-suffix.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/input.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/list-item-focus.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/list-item-separated.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/menu-item-separated.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-client-border.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-pill-active.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-pill-inactive.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-tab-active.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-tab-border.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-tab-normal.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-underline.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/progress-bar-horizontal-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/progress-bar-horizontal-striped.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/progress-bar-vertical-default.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/progress-bar-vertical-striped.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/progress-trough-horizontal.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/progress-trough-vertical.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/radio-selected.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/radio-unselected.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/scrollbar-horizontal-rounded.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/scrollbar-vertical-rounded.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/separator-horizontal.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/separator-vertical.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/slider-handle-focus.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/slider-handle.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/slider-track-horizontal.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/slider-track-vertical.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/switch-off.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/switch-on.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/tabs-bar-horizontal.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/tabs-bar-vertical.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/tabs-pill.png +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/__main__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/build.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/config.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/demo.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/doctor.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/list_cmd.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/promote.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/pyinstaller.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/run.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/start.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/templates/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/constants.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/after.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/bind.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/bindtags.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/busy.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/clipboard.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/focus.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/grab.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/grid.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/localization.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/pack.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/place.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/selection.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/signals.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/winfo.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/colorutils.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/exceptions.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/images.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/localization/README.md +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/localization/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/localization/intl_format.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/localization/msgcat.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/localization/specs.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/mixins/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/mixins/ttk_state.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/mixins/widget.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/publisher.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/signals/README.md +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/signals/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/signals/integration.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/signals/signal.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/signals/types.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/validation/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/validation/types.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/validation/validation_result.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/validation/validation_rules.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/variables.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/README.md +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/base.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/file_source.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/memory_source.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/types.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/colorchooser.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/colordropper.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/datedialog.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/dialog.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/filterdialog.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/fontdialog.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/formdialog.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/message.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/query.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/py.typed +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/app.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/base_window.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/events.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/menu.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/shortcuts.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/tk_patch.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/toplevel.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/utility.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/visual_focus.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/window_utilities.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/bootstyle.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/bootstyle_builder_base.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/bootstyle_builder_mixed.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/bootstyle_builder_tk.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/bootstyle_builder_ttk.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/badge.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/button.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/buttongroup.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/calendar.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/checkbutton.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/combobox.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/contextmenu.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/entry.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/expander.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/field.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/frame.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/label.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/labelframe.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/listview.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/menubar.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/menubutton.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/notebook.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/panedwindow.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/progressbar.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/radiobutton.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/scale.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/scrollbar.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/separator.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/sidenav.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/sizegrip.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/spinbox.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/switch.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/tabitem.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/toolbutton.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/tooltip.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/treeview.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/utils.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders_tk/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders_tk/defaults.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/element.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/style.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/theme_provider.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/tk_patch.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/token_maps.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/types.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/typography.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/utility.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/themes/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/themes/standard.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/themes/user.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/accordion.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/appshell.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/buttongroup.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/calendar.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/compositeframe.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/contextmenu.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/dateentry.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/dropdownbutton.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/expander.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/floodgauge.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/labeledscale.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/list/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/list/listitem.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/list/listview.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/menubar.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/meter.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/numericentry.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/pagestack.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/passwordentry.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/pathentry.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/radiogroup.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/scrolledtext.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/scrolledtext.pyi +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/scrollview.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/selectbox.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/sidenav/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/sidenav/group.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/sidenav/header.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/sidenav/item.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/sidenav/separator.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/sidenav/view.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/spinnerentry.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tableview/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tableview/types.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tabs/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tabs/tabitem.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tabs/tabs.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tabs/tabview.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/textentry.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/timeentry.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/toast.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/togglegroup.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/toolbar.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tooltip.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/internal/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/internal/wrapper_base.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/configure_mixin.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/entry_mixin.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/font_mixin.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/icon_mixin.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/localization_mixin.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/signal_mixin.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/validation_mixin.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/parts/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/parts/numberentry_part.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/parts/spinnerentry_part.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/parts/textentry_part.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/__init__.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/badge.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/button.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/card.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/checkbutton.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/checktoggle.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/combobox.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/entry.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/frame.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/gridframe.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/label.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/labelframe.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/menubutton.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/notebook.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/optionmenu.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/packframe.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/panedwindow.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/progressbar.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/radiobutton.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/radiotoggle.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/scale.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/scrollbar.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/separator.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/sizegrip.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/spinbox.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/switch.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/treeview.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/types.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack.egg-info/dependency_links.txt +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack.egg-info/entry_points.txt +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack.egg-info/requires.txt +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack.egg-info/top_level.txt +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/tests/test_togglegroup.py +0 -0
- {bootstack-0.1.0a5 → bootstack-0.1.0a6}/tests/test_variables.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bootstack
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.0a6
|
|
4
4
|
Summary: A full UI framework for Python desktop apps built on tkinter — rich widgets, theming, and application structure out of the box.
|
|
5
5
|
Author-email: Israel Dryer <israel.dryer@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "bootstack"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.0a6"
|
|
8
8
|
description = "A full UI framework for Python desktop apps built on tkinter — rich widgets, theming, and application structure out of the box."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -82,7 +82,7 @@ where = ["src"]
|
|
|
82
82
|
]
|
|
83
83
|
|
|
84
84
|
[tool.bumpversion]
|
|
85
|
-
current_version = "0.1.
|
|
85
|
+
current_version = "0.1.0a6"
|
|
86
86
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)((?P<pre>a|b|rc)(?P<pre_n>\\d+))?"
|
|
87
87
|
serialize = [
|
|
88
88
|
"{major}.{minor}.{patch}{pre}{pre_n}",
|
|
@@ -50,6 +50,7 @@ if TYPE_CHECKING:
|
|
|
50
50
|
from bootstack.api.style import (
|
|
51
51
|
Font,
|
|
52
52
|
Style,
|
|
53
|
+
Typography,
|
|
53
54
|
get_style,
|
|
54
55
|
get_style_builder,
|
|
55
56
|
get_theme,
|
|
@@ -58,6 +59,7 @@ if TYPE_CHECKING:
|
|
|
58
59
|
toggle_theme,
|
|
59
60
|
get_theme_color,
|
|
60
61
|
get_themes,
|
|
62
|
+
register_user_theme,
|
|
61
63
|
)
|
|
62
64
|
from bootstack.api.widgets import (
|
|
63
65
|
Button,
|
|
@@ -80,6 +82,8 @@ if TYPE_CHECKING:
|
|
|
80
82
|
Label,
|
|
81
83
|
LabelFrame,
|
|
82
84
|
LabeledScale,
|
|
85
|
+
ListItem,
|
|
86
|
+
ListView,
|
|
83
87
|
MenuBar,
|
|
84
88
|
MenuButton,
|
|
85
89
|
Meter,
|
|
@@ -158,10 +162,11 @@ _MODULE_EXPORTS = {
|
|
|
158
162
|
],
|
|
159
163
|
# Style & Theming
|
|
160
164
|
"bootstack.api.style": [
|
|
161
|
-
"BootstrapIcon", "Font", "Style",
|
|
165
|
+
"BootstrapIcon", "Font", "Style", "Typography",
|
|
162
166
|
"get_style", "get_style_builder", "get_theme",
|
|
163
167
|
"get_theme_provider", "set_theme", "get_theme_color",
|
|
164
168
|
"toggle_theme", "get_themes",
|
|
169
|
+
"register_user_theme",
|
|
165
170
|
],
|
|
166
171
|
# Widgets
|
|
167
172
|
"bootstack.api.widgets": [
|
|
@@ -173,7 +178,7 @@ _MODULE_EXPORTS = {
|
|
|
173
178
|
"RadioToggle",
|
|
174
179
|
"Calendar", "ContextMenu", "ContextMenuItem", "DateEntry",
|
|
175
180
|
"Accordion", "DropdownButton", "Expander", "Field", "FieldOptions", "FloodGauge", "Form",
|
|
176
|
-
"GridFrame", "LabeledScale", "MenuBar", "Meter",
|
|
181
|
+
"GridFrame", "LabeledScale", "ListItem", "ListView", "MenuBar", "Meter",
|
|
177
182
|
"SideNav", "SideNavItem", "SideNavGroup",
|
|
178
183
|
"SideNavHeader", "SideNavSeparator",
|
|
179
184
|
"NumericEntry", "PackFrame", "PageStack",
|
|
@@ -6,12 +6,14 @@ from ttkbootstrap_icons_bs import BootstrapIcon
|
|
|
6
6
|
|
|
7
7
|
from bootstack.style.style import (Style, get_style, get_style_builder, get_theme, get_theme_color,
|
|
8
8
|
get_theme_provider, set_theme, toggle_theme, get_themes)
|
|
9
|
-
from bootstack.style.
|
|
9
|
+
from bootstack.style.theme_provider import register_user_theme
|
|
10
|
+
from bootstack.style.typography import Font, Typography
|
|
10
11
|
|
|
11
12
|
__all__ = [
|
|
12
13
|
"BootstrapIcon",
|
|
13
14
|
"Font",
|
|
14
15
|
"Style",
|
|
16
|
+
"Typography",
|
|
15
17
|
"get_style",
|
|
16
18
|
"get_style_builder",
|
|
17
19
|
"get_theme",
|
|
@@ -20,4 +22,5 @@ __all__ = [
|
|
|
20
22
|
"get_theme_provider",
|
|
21
23
|
"get_theme_color",
|
|
22
24
|
"get_themes",
|
|
25
|
+
"register_user_theme",
|
|
23
26
|
]
|
|
@@ -35,6 +35,7 @@ from bootstack.widgets.primitives.gridframe import GridFrame
|
|
|
35
35
|
from bootstack.widgets.primitives.label import Label
|
|
36
36
|
from bootstack.widgets.primitives.labelframe import LabelFrame
|
|
37
37
|
from bootstack.widgets.composites.labeledscale import LabeledScale
|
|
38
|
+
from bootstack.widgets.composites.list import ListItem, ListView
|
|
38
39
|
from bootstack.widgets.composites.menubar import MenuBar
|
|
39
40
|
from bootstack.widgets.primitives.menubutton import MenuButton
|
|
40
41
|
from bootstack.widgets.composites.meter import Meter
|
|
@@ -93,6 +94,8 @@ __all__ = [
|
|
|
93
94
|
"Label",
|
|
94
95
|
"LabelFrame",
|
|
95
96
|
"LabeledScale",
|
|
97
|
+
"ListItem",
|
|
98
|
+
"ListView",
|
|
96
99
|
"MenuBar",
|
|
97
100
|
"SideNav",
|
|
98
101
|
"SideNavItem",
|
|
@@ -20,6 +20,7 @@ Usage:
|
|
|
20
20
|
bootstack list themes List available themes
|
|
21
21
|
bootstack doctor Diagnose project and environment health
|
|
22
22
|
bootstack gallery Launch the widget gallery
|
|
23
|
+
bootstack icons Browse Bootstrap Icons
|
|
23
24
|
"""
|
|
24
25
|
|
|
25
26
|
from __future__ import annotations
|
|
@@ -28,7 +29,7 @@ import argparse
|
|
|
28
29
|
import sys
|
|
29
30
|
from typing import Sequence
|
|
30
31
|
|
|
31
|
-
from bootstack.cli import add, build, doctor, list_cmd, promote, run, start
|
|
32
|
+
from bootstack.cli import add, build, doctor, icons, list_cmd, promote, run, start
|
|
32
33
|
from bootstack.cli.demo import run_demo
|
|
33
34
|
|
|
34
35
|
|
|
@@ -50,6 +51,7 @@ Examples:
|
|
|
50
51
|
bootstack list themes List available themes
|
|
51
52
|
bootstack doctor Diagnose project and environment health
|
|
52
53
|
bootstack gallery Launch the widget gallery
|
|
54
|
+
bootstack icons Browse Bootstrap Icons
|
|
53
55
|
|
|
54
56
|
For more information on a command:
|
|
55
57
|
bootstack <command> --help
|
|
@@ -82,6 +84,7 @@ For more information on a command:
|
|
|
82
84
|
add.add_parser(subparsers)
|
|
83
85
|
list_cmd.add_parser(subparsers)
|
|
84
86
|
doctor.add_parser(subparsers)
|
|
87
|
+
icons.add_parser(subparsers)
|
|
85
88
|
|
|
86
89
|
# Gallery command
|
|
87
90
|
gallery_parser = subparsers.add_parser(
|
|
@@ -305,7 +305,7 @@ def run_add_theme(args: argparse.Namespace) -> None:
|
|
|
305
305
|
print()
|
|
306
306
|
print(" from bootstack.style.theme_provider import register_user_theme")
|
|
307
307
|
print(f' register_user_theme("{theme_name}", "themes/{theme_name}.json")')
|
|
308
|
-
print(f' app =
|
|
308
|
+
print(f' app = bs.App(theme="{theme_name}")')
|
|
309
309
|
|
|
310
310
|
|
|
311
311
|
def run_add_i18n(args: argparse.Namespace) -> None:
|
|
@@ -340,7 +340,7 @@ def run_add_i18n(args: argparse.Namespace) -> None:
|
|
|
340
340
|
print("Next steps:")
|
|
341
341
|
print(" 1. Add translatable strings to your .po files")
|
|
342
342
|
print(" 2. Compile with: msgfmt locales/<lang>/LC_MESSAGES/messages.po -o locales/<lang>/LC_MESSAGES/messages.mo")
|
|
343
|
-
print(" 3. Use translations in code:
|
|
343
|
+
print(" 3. Use translations in code: bs.L('Hello')")
|
|
344
344
|
|
|
345
345
|
|
|
346
346
|
_BASE_SHADES = {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Icons command — delegates to the ttkbootstrap-icons browser."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def add_parser(subparsers: argparse._SubParsersAction) -> None:
|
|
11
|
+
parser = subparsers.add_parser(
|
|
12
|
+
"icons",
|
|
13
|
+
help="Browse Bootstrap Icons available in bootstack",
|
|
14
|
+
description=(
|
|
15
|
+
"Launch the Bootstrap Icons browser.\n\n"
|
|
16
|
+
"Delegates to the ttkbootstrap-icons tool bundled with the "
|
|
17
|
+
"ttkbootstrap_icons_bs package. Any icon name shown there can "
|
|
18
|
+
"be used as the icon= parameter on any bootstack widget."
|
|
19
|
+
),
|
|
20
|
+
)
|
|
21
|
+
parser.set_defaults(func=lambda args: run_icons())
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def run_icons() -> None:
|
|
25
|
+
scripts = Path(sys.executable).parent
|
|
26
|
+
name = "ttkbootstrap-icons.exe" if sys.platform == "win32" else "ttkbootstrap-icons"
|
|
27
|
+
result = subprocess.run([str(scripts / name)])
|
|
28
|
+
sys.exit(result.returncode)
|
|
@@ -34,6 +34,10 @@ from typing import Any, Dict, List, Optional, Union, Sequence
|
|
|
34
34
|
from bootstack.datasource.base import BaseDataSource
|
|
35
35
|
from bootstack.datasource.types import Primitive, Record
|
|
36
36
|
|
|
37
|
+
# Internal column names — reserved by SqliteDataSource, never exposed to user data.
|
|
38
|
+
_ROW_ID = "_bs_row_id"
|
|
39
|
+
_ROW_SEL = "_bs_selected"
|
|
40
|
+
|
|
37
41
|
|
|
38
42
|
class SqliteDataSource(BaseDataSource):
|
|
39
43
|
"""SQLite-backed data manager with pagination, filtering, sorting, and CRUD operations.
|
|
@@ -61,8 +65,9 @@ class SqliteDataSource(BaseDataSource):
|
|
|
61
65
|
- The database connection persists for the lifetime of the object
|
|
62
66
|
- Close the connection explicitly with conn.close() if needed
|
|
63
67
|
- Schema is inferred from first record's data types
|
|
64
|
-
-
|
|
65
|
-
-
|
|
68
|
+
- An internal row-identity column (_bs_row_id) is added automatically as PRIMARY KEY
|
|
69
|
+
- An internal selection column (_bs_selected) is added automatically for selection tracking
|
|
70
|
+
- These internal columns are filtered out of the display column list automatically
|
|
66
71
|
"""
|
|
67
72
|
|
|
68
73
|
def __init__(self, name: str = ":memory:", page_size: int = 10):
|
|
@@ -121,12 +126,12 @@ class SqliteDataSource(BaseDataSource):
|
|
|
121
126
|
using_dicts = True
|
|
122
127
|
|
|
123
128
|
if using_dicts:
|
|
124
|
-
# Ensure helper columns
|
|
129
|
+
# Ensure internal helper columns
|
|
125
130
|
for i, record in enumerate(records):
|
|
126
|
-
if
|
|
127
|
-
record[
|
|
128
|
-
if
|
|
129
|
-
record[
|
|
131
|
+
if _ROW_ID not in record:
|
|
132
|
+
record[_ROW_ID] = i
|
|
133
|
+
if _ROW_SEL not in record:
|
|
134
|
+
record[_ROW_SEL] = 0
|
|
130
135
|
|
|
131
136
|
self._columns = list(records[0].keys())
|
|
132
137
|
col_types = {col: self._infer_type(records[0][col]) for col in self._columns}
|
|
@@ -136,25 +141,25 @@ class SqliteDataSource(BaseDataSource):
|
|
|
136
141
|
keys = list(column_keys or [])
|
|
137
142
|
if not keys:
|
|
138
143
|
keys = [str(i) for i in range(len(first))]
|
|
139
|
-
need_id =
|
|
140
|
-
|
|
144
|
+
need_id = _ROW_ID not in keys
|
|
145
|
+
need_sel = _ROW_SEL not in keys
|
|
141
146
|
if need_id:
|
|
142
|
-
keys.append(
|
|
143
|
-
if
|
|
144
|
-
keys.append(
|
|
147
|
+
keys.append(_ROW_ID)
|
|
148
|
+
if need_sel:
|
|
149
|
+
keys.append(_ROW_SEL)
|
|
145
150
|
self._columns = keys
|
|
146
151
|
|
|
147
152
|
# Infer types from first row (pad to keys length)
|
|
148
153
|
padded_first = list(first) + [None] * (len(keys) - len(first))
|
|
149
|
-
if need_id and
|
|
150
|
-
padded_first[keys.index(
|
|
151
|
-
if
|
|
152
|
-
padded_first[keys.index(
|
|
154
|
+
if need_id and _ROW_ID in keys:
|
|
155
|
+
padded_first[keys.index(_ROW_ID)] = 0
|
|
156
|
+
if need_sel and _ROW_SEL in keys:
|
|
157
|
+
padded_first[keys.index(_ROW_SEL)] = 0
|
|
153
158
|
col_types = {col: self._infer_type(padded_first[idx]) for idx, col in enumerate(keys)}
|
|
154
159
|
|
|
155
160
|
rows_to_insert = []
|
|
156
|
-
id_idx = keys.index(
|
|
157
|
-
sel_idx = keys.index(
|
|
161
|
+
id_idx = keys.index(_ROW_ID) if _ROW_ID in keys else None
|
|
162
|
+
sel_idx = keys.index(_ROW_SEL) if _ROW_SEL in keys else None
|
|
158
163
|
value_len = len(keys)
|
|
159
164
|
for i, row in enumerate(records):
|
|
160
165
|
base_values = list(row[: value_len]) + [""] * (value_len - len(row))
|
|
@@ -165,7 +170,7 @@ class SqliteDataSource(BaseDataSource):
|
|
|
165
170
|
rows_to_insert.append(tuple(base_values))
|
|
166
171
|
|
|
167
172
|
col_definitions = ", ".join(
|
|
168
|
-
f"{self._quote_identifier(col)} {col_types[col]}" + (" PRIMARY KEY" if col ==
|
|
173
|
+
f"{self._quote_identifier(col)} {col_types[col]}" + (" PRIMARY KEY" if col == _ROW_ID else "")
|
|
169
174
|
for col in self._columns
|
|
170
175
|
)
|
|
171
176
|
placeholders = ", ".join("?" for _ in self._columns)
|
|
@@ -241,11 +246,11 @@ class SqliteDataSource(BaseDataSource):
|
|
|
241
246
|
|
|
242
247
|
def create_record(self, record: Dict[str, Any]) -> int:
|
|
243
248
|
"""Create new record and return its ID."""
|
|
244
|
-
if
|
|
245
|
-
record[
|
|
249
|
+
if _ROW_ID not in record:
|
|
250
|
+
record[_ROW_ID] = self._generate_new_id()
|
|
246
251
|
|
|
247
|
-
if
|
|
248
|
-
record[
|
|
252
|
+
if _ROW_SEL not in record:
|
|
253
|
+
record[_ROW_SEL] = 0
|
|
249
254
|
|
|
250
255
|
# Ensure table exists (handles empty datasources)
|
|
251
256
|
self._ensure_table_for_record(record)
|
|
@@ -257,11 +262,11 @@ class SqliteDataSource(BaseDataSource):
|
|
|
257
262
|
|
|
258
263
|
with self.conn:
|
|
259
264
|
self.conn.execute(f"INSERT INTO {self._table} ({cols}) VALUES ({placeholders})", values)
|
|
260
|
-
return record[
|
|
265
|
+
return record[_ROW_ID]
|
|
261
266
|
|
|
262
267
|
def read_record(self, record_id: Any) -> Optional[Dict[str, Any]]:
|
|
263
268
|
"""Retrieve single record by ID."""
|
|
264
|
-
cursor = self.conn.execute(f"SELECT * FROM {self._table} WHERE
|
|
269
|
+
cursor = self.conn.execute(f"SELECT * FROM {self._table} WHERE {_ROW_ID} = ?", (record_id,))
|
|
265
270
|
row = cursor.fetchone()
|
|
266
271
|
return dict(row) if row else None
|
|
267
272
|
|
|
@@ -272,19 +277,19 @@ class SqliteDataSource(BaseDataSource):
|
|
|
272
277
|
set_clause = ", ".join(f"{self._quote_identifier(k)} = ?" for k in updates)
|
|
273
278
|
values = tuple(updates.values()) + (record_id,)
|
|
274
279
|
with self.conn:
|
|
275
|
-
cur = self.conn.execute(f"UPDATE {self._table} SET {set_clause} WHERE
|
|
280
|
+
cur = self.conn.execute(f"UPDATE {self._table} SET {set_clause} WHERE {_ROW_ID} = ?", values)
|
|
276
281
|
return cur.rowcount > 0
|
|
277
282
|
|
|
278
283
|
def delete_record(self, record_id: Any) -> bool:
|
|
279
284
|
"""Delete record by ID."""
|
|
280
285
|
with self.conn:
|
|
281
|
-
cur = self.conn.execute(f"DELETE FROM {self._table} WHERE
|
|
286
|
+
cur = self.conn.execute(f"DELETE FROM {self._table} WHERE {_ROW_ID} = ?", (record_id,))
|
|
282
287
|
return cur.rowcount > 0
|
|
283
288
|
|
|
284
289
|
def _generate_new_id(self) -> int:
|
|
285
290
|
"""Generate next available integer ID."""
|
|
286
291
|
try:
|
|
287
|
-
cursor = self.conn.execute(f"SELECT MAX(
|
|
292
|
+
cursor = self.conn.execute(f"SELECT MAX({_ROW_ID}) FROM {self._table}")
|
|
288
293
|
max_id = cursor.fetchone()[0]
|
|
289
294
|
except Exception:
|
|
290
295
|
max_id = 0
|
|
@@ -301,23 +306,23 @@ class SqliteDataSource(BaseDataSource):
|
|
|
301
306
|
pass
|
|
302
307
|
|
|
303
308
|
cols = list(self._columns) if self._columns else list(record.keys())
|
|
304
|
-
if
|
|
305
|
-
cols.append(
|
|
306
|
-
if
|
|
307
|
-
cols.append(
|
|
309
|
+
if _ROW_ID not in cols:
|
|
310
|
+
cols.append(_ROW_ID)
|
|
311
|
+
if _ROW_SEL not in cols:
|
|
312
|
+
cols.append(_ROW_SEL)
|
|
308
313
|
self._columns = cols
|
|
309
314
|
|
|
310
315
|
col_types = {}
|
|
311
316
|
for c in cols:
|
|
312
|
-
if c ==
|
|
317
|
+
if c == _ROW_ID:
|
|
313
318
|
col_types[c] = "INTEGER"
|
|
314
|
-
elif c ==
|
|
319
|
+
elif c == _ROW_SEL:
|
|
315
320
|
col_types[c] = "INTEGER"
|
|
316
321
|
else:
|
|
317
322
|
col_types[c] = self._infer_type(record.get(c))
|
|
318
323
|
|
|
319
324
|
col_definitions = ", ".join(
|
|
320
|
-
f"{self._quote_identifier(col)} {col_types[col]}" + (" PRIMARY KEY" if col ==
|
|
325
|
+
f"{self._quote_identifier(col)} {col_types[col]}" + (" PRIMARY KEY" if col == _ROW_ID else "")
|
|
321
326
|
for col in cols
|
|
322
327
|
)
|
|
323
328
|
with self.conn:
|
|
@@ -337,40 +342,40 @@ class SqliteDataSource(BaseDataSource):
|
|
|
337
342
|
"""Select all records (optionally only current page)."""
|
|
338
343
|
self._ensure_selected_column()
|
|
339
344
|
if current_page_only:
|
|
340
|
-
ids = [row[
|
|
345
|
+
ids = [row[_ROW_ID] for row in self.get_page()]
|
|
341
346
|
if not ids:
|
|
342
347
|
return 0
|
|
343
348
|
placeholders = ", ".join("?" for _ in ids)
|
|
344
|
-
query = f"UPDATE {self._table} SET
|
|
349
|
+
query = f"UPDATE {self._table} SET {_ROW_SEL} = 1 WHERE {_ROW_ID} IN ({placeholders})"
|
|
345
350
|
with self.conn:
|
|
346
351
|
cur = self.conn.execute(query, ids)
|
|
347
352
|
return cur.rowcount
|
|
348
353
|
else:
|
|
349
354
|
with self.conn:
|
|
350
|
-
cur = self.conn.execute(f"UPDATE {self._table} SET
|
|
355
|
+
cur = self.conn.execute(f"UPDATE {self._table} SET {_ROW_SEL} = 1")
|
|
351
356
|
return cur.rowcount
|
|
352
357
|
|
|
353
358
|
def unselect_all(self, current_page_only: bool = False) -> int:
|
|
354
359
|
"""Unselect all records (optionally only current page)."""
|
|
355
360
|
self._ensure_selected_column()
|
|
356
361
|
if current_page_only:
|
|
357
|
-
ids = [row[
|
|
362
|
+
ids = [row[_ROW_ID] for row in self.get_page()]
|
|
358
363
|
if not ids:
|
|
359
364
|
return 0
|
|
360
365
|
placeholders = ", ".join("?" for _ in ids)
|
|
361
|
-
query = f"UPDATE {self._table} SET
|
|
366
|
+
query = f"UPDATE {self._table} SET {_ROW_SEL} = 0 WHERE {_ROW_ID} IN ({placeholders})"
|
|
362
367
|
with self.conn:
|
|
363
368
|
cur = self.conn.execute(query, ids)
|
|
364
369
|
return cur.rowcount
|
|
365
370
|
else:
|
|
366
371
|
with self.conn:
|
|
367
|
-
cur = self.conn.execute(f"UPDATE {self._table} SET
|
|
372
|
+
cur = self.conn.execute(f"UPDATE {self._table} SET {_ROW_SEL} = 0")
|
|
368
373
|
return cur.rowcount
|
|
369
374
|
|
|
370
375
|
def get_selected(self, page: Optional[int] = None) -> List[Dict[str, Any]]:
|
|
371
376
|
"""Get selected records, optionally paginated."""
|
|
372
377
|
self._ensure_selected_column()
|
|
373
|
-
query = f"SELECT * FROM {self._table} WHERE
|
|
378
|
+
query = f"SELECT * FROM {self._table} WHERE {_ROW_SEL} = 1"
|
|
374
379
|
|
|
375
380
|
if page is not None:
|
|
376
381
|
offset = page * self.page_size
|
|
@@ -380,28 +385,30 @@ class SqliteDataSource(BaseDataSource):
|
|
|
380
385
|
return [dict(row) for row in cursor.fetchall()]
|
|
381
386
|
|
|
382
387
|
def _ensure_selected_column(self):
|
|
383
|
-
"""Add
|
|
384
|
-
if
|
|
388
|
+
"""Add selection column to table if it doesn't exist."""
|
|
389
|
+
if _ROW_SEL not in self._columns:
|
|
385
390
|
with self.conn:
|
|
386
|
-
self.conn.execute(f"ALTER TABLE {self._table} ADD COLUMN
|
|
387
|
-
self._columns.append(
|
|
391
|
+
self.conn.execute(f"ALTER TABLE {self._table} ADD COLUMN {_ROW_SEL} INTEGER DEFAULT 0")
|
|
392
|
+
self._columns.append(_ROW_SEL)
|
|
388
393
|
|
|
389
394
|
def selected_count(self) -> int:
|
|
390
395
|
"""Get total number of selected records."""
|
|
391
396
|
self._ensure_selected_column()
|
|
392
|
-
query = f"SELECT COUNT(*) FROM {self._table} WHERE
|
|
397
|
+
query = f"SELECT COUNT(*) FROM {self._table} WHERE {_ROW_SEL} = 1"
|
|
393
398
|
return self.conn.execute(query).fetchone()[0]
|
|
394
399
|
|
|
395
400
|
def _set_selected_flag(self, record_id: Any, flag: int) -> bool:
|
|
396
401
|
"""Set selection flag for record by ID."""
|
|
397
|
-
if
|
|
398
|
-
# Add selected column if it doesn't exist
|
|
402
|
+
if _ROW_SEL not in self._columns:
|
|
399
403
|
with self.conn:
|
|
400
|
-
self.conn.execute(f"ALTER TABLE {self._table} ADD COLUMN
|
|
401
|
-
self._columns.append(
|
|
404
|
+
self.conn.execute(f"ALTER TABLE {self._table} ADD COLUMN {_ROW_SEL} INTEGER DEFAULT 0")
|
|
405
|
+
self._columns.append(_ROW_SEL)
|
|
402
406
|
|
|
403
407
|
with self.conn:
|
|
404
|
-
cur = self.conn.execute(
|
|
408
|
+
cur = self.conn.execute(
|
|
409
|
+
f"UPDATE {self._table} SET {_ROW_SEL} = ? WHERE {_ROW_ID} = ?",
|
|
410
|
+
(flag, record_id),
|
|
411
|
+
)
|
|
405
412
|
return cur.rowcount > 0
|
|
406
413
|
|
|
407
414
|
# === DATA EXPORT ===
|
|
@@ -411,7 +418,7 @@ class SqliteDataSource(BaseDataSource):
|
|
|
411
418
|
self._ensure_selected_column()
|
|
412
419
|
query = f"SELECT * FROM {self._table}"
|
|
413
420
|
if not include_all:
|
|
414
|
-
query += " WHERE
|
|
421
|
+
query += f" WHERE {_ROW_SEL} = 1"
|
|
415
422
|
|
|
416
423
|
cursor = self.conn.execute(query)
|
|
417
424
|
rows = cursor.fetchall()
|
|
@@ -176,8 +176,8 @@ class Field(EntryMixin, Frame):
|
|
|
176
176
|
show_message_explicit = 'show_message' in kwargs
|
|
177
177
|
show_message = kwargs.pop('show_message', show_message)
|
|
178
178
|
|
|
179
|
-
# Auto-enable show_message if
|
|
180
|
-
if message and not show_message_explicit:
|
|
179
|
+
# Auto-enable show_message if there is any chance a message will be shown
|
|
180
|
+
if (message or required) and not show_message_explicit:
|
|
181
181
|
show_message = True
|
|
182
182
|
|
|
183
183
|
accent = kwargs.pop('accent', None)
|
|
@@ -266,8 +266,19 @@ class Field(EntryMixin, Frame):
|
|
|
266
266
|
self.signal = self._entry.textsignal
|
|
267
267
|
|
|
268
268
|
# enty validation
|
|
269
|
-
|
|
270
|
-
|
|
269
|
+
_add_rule = self._entry.add_validation_rule
|
|
270
|
+
_add_rules = self._entry.add_validation_rules
|
|
271
|
+
|
|
272
|
+
def add_validation_rule(rule_type, **kwargs):
|
|
273
|
+
self._reserve_message_space()
|
|
274
|
+
_add_rule(rule_type, **kwargs)
|
|
275
|
+
|
|
276
|
+
def add_validation_rules(rules):
|
|
277
|
+
self._reserve_message_space()
|
|
278
|
+
_add_rules(rules)
|
|
279
|
+
|
|
280
|
+
self.add_validation_rule = add_validation_rule
|
|
281
|
+
self.add_validation_rules = add_validation_rules
|
|
271
282
|
self.validation = self._entry.validate
|
|
272
283
|
|
|
273
284
|
# Copy Field's delegate handlers to entry for configuration forwarding
|
|
@@ -421,6 +432,11 @@ class Field(EntryMixin, Frame):
|
|
|
421
432
|
instance.bind('<FocusIn>', lambda _: self._field.state(['focus']), add=True)
|
|
422
433
|
instance.bind('<FocusOut>', lambda _: self._field.state(['!focus']), add=True)
|
|
423
434
|
|
|
435
|
+
def _reserve_message_space(self) -> None:
|
|
436
|
+
if not self._show_messages:
|
|
437
|
+
self._show_messages = True
|
|
438
|
+
self._message_lbl.pack(side='top', fill='x', padx=4)
|
|
439
|
+
|
|
424
440
|
def _show_error(self, event: Any) -> None:
|
|
425
441
|
"""Display a validation error message below the input field."""
|
|
426
442
|
self._message_lbl['text'] = event.data['message']
|
|
@@ -429,7 +445,7 @@ class Field(EntryMixin, Frame):
|
|
|
429
445
|
|
|
430
446
|
def _clear_error(self, _: Any) -> None:
|
|
431
447
|
"""Clear the error message and restore the original message text."""
|
|
432
|
-
self._message_lbl['text'] = self._message_text
|
|
448
|
+
self._message_lbl['text'] = self._message_text or ''
|
|
433
449
|
self._message_lbl['accent'] = "secondary"
|
|
434
450
|
|
|
435
451
|
def _set_addons_state(self, disabled: bool) -> None:
|
|
@@ -629,8 +629,7 @@ class Form(Frame):
|
|
|
629
629
|
def _build_buttons(self, parent: Frame, buttons: Sequence[ButtonInput]) -> None:
|
|
630
630
|
parsed = self._normalize_buttons(buttons)
|
|
631
631
|
for spec in reversed(parsed):
|
|
632
|
-
|
|
633
|
-
btn_color = getattr(spec, 'color', None) or spec.bootstyle
|
|
632
|
+
btn_color = getattr(spec, 'accent', None) or getattr(spec, 'color', None) or getattr(spec, 'bootstyle', None)
|
|
634
633
|
btn_variant = getattr(spec, 'variant', None)
|
|
635
634
|
|
|
636
635
|
if not btn_color:
|
{bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tableview/tableview.py
RENAMED
|
@@ -17,7 +17,7 @@ from bootstack.widgets.types import Master
|
|
|
17
17
|
|
|
18
18
|
from ttkbootstrap_icons_bs import BootstrapIcon
|
|
19
19
|
from bootstack.style.style import get_style
|
|
20
|
-
from bootstack.datasource.sqlite_source import SqliteDataSource
|
|
20
|
+
from bootstack.datasource.sqlite_source import SqliteDataSource, _ROW_ID, _ROW_SEL
|
|
21
21
|
from bootstack.widgets.primitives.button import Button
|
|
22
22
|
from bootstack.runtime.utility import bind_right_click
|
|
23
23
|
from bootstack.widgets.composites.contextmenu import ContextMenu
|
|
@@ -382,7 +382,7 @@ class TableView(Frame):
|
|
|
382
382
|
new_id = self._datasource.create_record(dict(rec))
|
|
383
383
|
rec = dict(rec)
|
|
384
384
|
if new_id is not None:
|
|
385
|
-
rec[
|
|
385
|
+
rec[_ROW_ID] = new_id
|
|
386
386
|
inserted.append(rec)
|
|
387
387
|
except Exception:
|
|
388
388
|
logger.exception("Failed to insert record")
|
|
@@ -392,13 +392,13 @@ class TableView(Frame):
|
|
|
392
392
|
self.event_generate("<<RowInsert>>", data={"records": inserted})
|
|
393
393
|
|
|
394
394
|
def update_rows(self, rows: list[dict]) -> None:
|
|
395
|
-
"""Update rows by id; each dict must include
|
|
395
|
+
"""Update rows by internal row id; each dict must include the internal row-id key."""
|
|
396
396
|
updated: list[dict] = []
|
|
397
397
|
for rec in rows:
|
|
398
|
-
rec_id = rec.get(
|
|
398
|
+
rec_id = rec.get(_ROW_ID)
|
|
399
399
|
if rec_id is None:
|
|
400
400
|
continue
|
|
401
|
-
updates = {k: v for k, v in rec.items() if k !=
|
|
401
|
+
updates = {k: v for k, v in rec.items() if k != _ROW_ID}
|
|
402
402
|
try:
|
|
403
403
|
self._datasource.update_record(rec_id, updates)
|
|
404
404
|
updated.append(rec)
|
|
@@ -417,7 +417,7 @@ class TableView(Frame):
|
|
|
417
417
|
rec = {}
|
|
418
418
|
if isinstance(item, dict):
|
|
419
419
|
rec = item
|
|
420
|
-
rec_id = item.get(
|
|
420
|
+
rec_id = item.get(_ROW_ID)
|
|
421
421
|
else:
|
|
422
422
|
rec_id = item
|
|
423
423
|
if rec_id is None:
|
|
@@ -425,7 +425,7 @@ class TableView(Frame):
|
|
|
425
425
|
try:
|
|
426
426
|
self._datasource.delete_record(rec_id)
|
|
427
427
|
if not rec:
|
|
428
|
-
rec = {
|
|
428
|
+
rec = {_ROW_ID: rec_id}
|
|
429
429
|
deleted.append(rec)
|
|
430
430
|
except Exception:
|
|
431
431
|
logger.exception("Failed to delete record id=%s", rec_id)
|
|
@@ -689,7 +689,7 @@ class TableView(Frame):
|
|
|
689
689
|
if not inferred:
|
|
690
690
|
inferred = getattr(self._datasource, "_columns", []) or []
|
|
691
691
|
|
|
692
|
-
inferred = [c for c in inferred if c not in (
|
|
692
|
+
inferred = [c for c in inferred if c not in (_ROW_ID, _ROW_SEL)]
|
|
693
693
|
if not inferred:
|
|
694
694
|
inferred = ["value"]
|
|
695
695
|
|
|
@@ -1326,7 +1326,7 @@ class TableView(Frame):
|
|
|
1326
1326
|
form_options.setdefault('resizable', True)
|
|
1327
1327
|
|
|
1328
1328
|
# Build buttons: Cancel, Delete (only for existing records), Save
|
|
1329
|
-
if record and
|
|
1329
|
+
if record and _ROW_ID in record:
|
|
1330
1330
|
buttons: list[str | dict] = ['Cancel']
|
|
1331
1331
|
if self._editing['deleting']:
|
|
1332
1332
|
buttons.append({"text": "Delete", "role": "secondary", "result": "delete"})
|
|
@@ -1353,21 +1353,21 @@ class TableView(Frame):
|
|
|
1353
1353
|
return
|
|
1354
1354
|
|
|
1355
1355
|
# Handle delete action
|
|
1356
|
-
if result == "delete" and record and
|
|
1356
|
+
if result == "delete" and record and _ROW_ID in record:
|
|
1357
1357
|
try:
|
|
1358
|
-
self._datasource.delete_record(record[
|
|
1358
|
+
self._datasource.delete_record(record[_ROW_ID])
|
|
1359
1359
|
self._clear_cache()
|
|
1360
1360
|
self._load_page(self._current_page)
|
|
1361
1361
|
except Exception:
|
|
1362
|
-
logger.exception("Failed to delete record id=%s", record[
|
|
1362
|
+
logger.exception("Failed to delete record id=%s", record[_ROW_ID])
|
|
1363
1363
|
return
|
|
1364
1364
|
|
|
1365
1365
|
data = result
|
|
1366
1366
|
new_id = None
|
|
1367
|
-
if record and
|
|
1368
|
-
rec_id = record[
|
|
1367
|
+
if record and _ROW_ID in record:
|
|
1368
|
+
rec_id = record[_ROW_ID]
|
|
1369
1369
|
updates = dict(data)
|
|
1370
|
-
updates.pop(
|
|
1370
|
+
updates.pop(_ROW_ID, None)
|
|
1371
1371
|
try:
|
|
1372
1372
|
logger.debug("Updating record id=%s with %s", rec_id, updates)
|
|
1373
1373
|
self._datasource.update_record(rec_id, updates)
|
|
@@ -1539,7 +1539,7 @@ class TableView(Frame):
|
|
|
1539
1539
|
return
|
|
1540
1540
|
iid = sel[0]
|
|
1541
1541
|
rec = self._row_map.get(iid, {})
|
|
1542
|
-
rec_id = rec.get(
|
|
1542
|
+
rec_id = rec.get(_ROW_ID)
|
|
1543
1543
|
if rec_id is not None:
|
|
1544
1544
|
try:
|
|
1545
1545
|
self._datasource.delete_record(rec_id)
|
|
@@ -1557,7 +1557,7 @@ class TableView(Frame):
|
|
|
1557
1557
|
rec = dict(self._row_map.get(iid) or {})
|
|
1558
1558
|
if rec:
|
|
1559
1559
|
deleted_records.append(rec)
|
|
1560
|
-
rec_id = rec.get(
|
|
1560
|
+
rec_id = rec.get(_ROW_ID)
|
|
1561
1561
|
if rec_id is not None:
|
|
1562
1562
|
try:
|
|
1563
1563
|
self._datasource.delete_record(rec_id)
|
|
@@ -1629,7 +1629,7 @@ class TableView(Frame):
|
|
|
1629
1629
|
try:
|
|
1630
1630
|
rid = str(record_id)
|
|
1631
1631
|
for iid, rec in self._row_map.items():
|
|
1632
|
-
if str(rec.get(
|
|
1632
|
+
if str(rec.get(_ROW_ID)) == rid:
|
|
1633
1633
|
self._tree.selection_set(iid)
|
|
1634
1634
|
self._tree.see(iid)
|
|
1635
1635
|
break
|
|
@@ -1646,7 +1646,7 @@ class TableView(Frame):
|
|
|
1646
1646
|
rows = self._datasource.get_page(page_idx)
|
|
1647
1647
|
except Exception:
|
|
1648
1648
|
break
|
|
1649
|
-
if any(str(rec.get(
|
|
1649
|
+
if any(str(rec.get(_ROW_ID)) == rid for rec in rows):
|
|
1650
1650
|
return page_idx
|
|
1651
1651
|
except Exception:
|
|
1652
1652
|
pass
|