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.
Files changed (430) hide show
  1. {bootstack-0.1.0a5/src/bootstack.egg-info → bootstack-0.1.0a6}/PKG-INFO +1 -1
  2. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/pyproject.toml +2 -2
  3. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/__init__.py +7 -2
  4. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/style.py +4 -1
  5. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/widgets.py +3 -0
  6. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/__init__.py +4 -1
  7. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/add.py +2 -2
  8. bootstack-0.1.0a6/src/bootstack/cli/icons.py +28 -0
  9. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/sqlite_source.py +60 -53
  10. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/field.py +21 -5
  11. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/form.py +1 -2
  12. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tableview/tableview.py +19 -19
  13. {bootstack-0.1.0a5 → bootstack-0.1.0a6/src/bootstack.egg-info}/PKG-INFO +1 -1
  14. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack.egg-info/SOURCES.txt +1 -0
  15. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/LICENSE +0 -0
  16. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/MANIFEST.in +0 -0
  17. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/NOTICE +0 -0
  18. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/README.md +0 -0
  19. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/setup.cfg +0 -0
  20. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/__main__.py +0 -0
  21. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/__init__.py +0 -0
  22. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/app.py +0 -0
  23. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/constants.py +0 -0
  24. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/data.py +0 -0
  25. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/dialogs.py +0 -0
  26. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/i18n.py +0 -0
  27. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/localization.py +0 -0
  28. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/menu.py +0 -0
  29. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/api/utils.py +0 -0
  30. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/__init__.py +0 -0
  31. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/bootstack-dark.ico +0 -0
  32. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/bootstack-light.ico +0 -0
  33. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/bootstack-transparent.png +0 -0
  34. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/bootstack.ico +0 -0
  35. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/bootstack.png +0 -0
  36. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/__init__.py +0 -0
  37. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/badge-pill.png +0 -0
  38. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/badge-square.png +0 -0
  39. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/border.png +0 -0
  40. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-compact.png +0 -0
  41. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-default.png +0 -0
  42. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-horizontal-after-compact.png +0 -0
  43. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-horizontal-after-default.png +0 -0
  44. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-horizontal-before-compact.png +0 -0
  45. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-horizontal-before-default.png +0 -0
  46. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-horizontal-center-compact.png +0 -0
  47. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-horizontal-center-default.png +0 -0
  48. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-vertical-after-compact.png +0 -0
  49. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-vertical-after-default.png +0 -0
  50. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-vertical-before-compact.png +0 -0
  51. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-vertical-before-default.png +0 -0
  52. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-vertical-center-compact.png +0 -0
  53. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/button-group-vertical-center-default.png +0 -0
  54. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/checkbox-checked.png +0 -0
  55. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/checkbox-indeterminate.png +0 -0
  56. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/checkbox-unchecked.png +0 -0
  57. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/field.png +0 -0
  58. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/input-after-compact.png +0 -0
  59. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/input-after-default.png +0 -0
  60. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/input-before-compact.png +0 -0
  61. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/input-before-default.png +0 -0
  62. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/input-compact.png +0 -0
  63. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/input-default.png +0 -0
  64. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/list-item-separated.png +0 -0
  65. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/list-item.png +0 -0
  66. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/manifest.toml +0 -0
  67. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/menu-item.png +0 -0
  68. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/nav-button-compact.png +0 -0
  69. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/nav-button-default.png +0 -0
  70. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/nav-icon-button-compact.png +0 -0
  71. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/nav-icon-button-default.png +0 -0
  72. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/notebook-client-border.png +0 -0
  73. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/notebook-tab-active.png +0 -0
  74. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/notebook-tab-bar.png +0 -0
  75. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/notebook-tab-normal.png +0 -0
  76. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/notebook-tab-pill.png +0 -0
  77. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/progress-bar-horizontal-striped.png +0 -0
  78. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/progress-bar-solid.png +0 -0
  79. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/progress-bar-thin.png +0 -0
  80. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/progress-bar-vertical-striped.png +0 -0
  81. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/radio-selected.png +0 -0
  82. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/radio-unselected.png +0 -0
  83. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/scrollbar-horizontal.png +0 -0
  84. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/scrollbar-vertical.png +0 -0
  85. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/slider-handle-focus.png +0 -0
  86. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/slider-handle.png +0 -0
  87. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/slider-track-horizontal.png +0 -0
  88. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/slider-track-vertical.png +0 -0
  89. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/switch-off.png +0 -0
  90. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/switch-on.png +0 -0
  91. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/tabs-bar-horizontal.png +0 -0
  92. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/tabs-bar-vertical.png +0 -0
  93. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/elements/tabs-pill.png +0 -0
  94. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
  95. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +0 -0
  96. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +0 -0
  97. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
  98. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +0 -0
  99. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
  100. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +0 -0
  101. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
  102. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +0 -0
  103. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
  104. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +0 -0
  105. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
  106. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +0 -0
  107. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
  108. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +0 -0
  109. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
  110. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +0 -0
  111. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
  112. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +0 -0
  113. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
  114. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +0 -0
  115. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
  116. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +0 -0
  117. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
  118. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +0 -0
  119. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
  120. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +0 -0
  121. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
  122. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +0 -0
  123. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
  124. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +0 -0
  125. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
  126. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +0 -0
  127. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
  128. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +0 -0
  129. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
  130. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +0 -0
  131. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
  132. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +0 -0
  133. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
  134. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +0 -0
  135. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
  136. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +0 -0
  137. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
  138. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +0 -0
  139. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/__init__.py +0 -0
  140. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/amber-dark.json +0 -0
  141. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/amber-light.json +0 -0
  142. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/aurora-dark.json +0 -0
  143. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/aurora-light.json +0 -0
  144. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/bootstrap-dark.json +0 -0
  145. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/bootstrap-light.json +0 -0
  146. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/classic-dark.json +0 -0
  147. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/classic-light.json +0 -0
  148. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/docs-dark.json +0 -0
  149. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/docs-light.json +0 -0
  150. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/forest-dark.json +0 -0
  151. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/forest-light.json +0 -0
  152. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/ocean-dark.json +0 -0
  153. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/ocean-light.json +0 -0
  154. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/rose-dark.json +0 -0
  155. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/themes/rose-light.json +0 -0
  156. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/__init__.py +0 -0
  157. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/badge-default.png +0 -0
  158. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/badge-pill.png +0 -0
  159. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/border.png +0 -0
  160. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button-group-horizontal-after.png +0 -0
  161. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button-group-horizontal-before.png +0 -0
  162. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button-group-horizontal-center.png +0 -0
  163. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button-group-vertical-after.png +0 -0
  164. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button-group-vertical-before.png +0 -0
  165. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button-group-vertical-center.png +0 -0
  166. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/button.png +0 -0
  167. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/checkbox-checked.png +0 -0
  168. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/checkbox-indeterminate.png +0 -0
  169. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/checkbox-unchecked.png +0 -0
  170. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/field.png +0 -0
  171. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/icon-button.png +0 -0
  172. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/input-inner.png +0 -0
  173. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/input-prefix.png +0 -0
  174. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/input-suffix.png +0 -0
  175. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/input.png +0 -0
  176. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/list-item-focus.png +0 -0
  177. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/list-item-separated.png +0 -0
  178. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/menu-item-separated.png +0 -0
  179. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-client-border.png +0 -0
  180. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-pill-active.png +0 -0
  181. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-pill-inactive.png +0 -0
  182. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-tab-active.png +0 -0
  183. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-tab-border.png +0 -0
  184. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-tab-normal.png +0 -0
  185. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/notebook-underline.png +0 -0
  186. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/progress-bar-horizontal-default.png +0 -0
  187. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/progress-bar-horizontal-striped.png +0 -0
  188. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/progress-bar-vertical-default.png +0 -0
  189. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/progress-bar-vertical-striped.png +0 -0
  190. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/progress-trough-horizontal.png +0 -0
  191. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/progress-trough-vertical.png +0 -0
  192. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/radio-selected.png +0 -0
  193. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/radio-unselected.png +0 -0
  194. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/scrollbar-horizontal-rounded.png +0 -0
  195. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/scrollbar-vertical-rounded.png +0 -0
  196. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/separator-horizontal.png +0 -0
  197. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/separator-vertical.png +0 -0
  198. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/slider-handle-focus.png +0 -0
  199. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/slider-handle.png +0 -0
  200. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/slider-track-horizontal.png +0 -0
  201. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/slider-track-vertical.png +0 -0
  202. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/switch-off.png +0 -0
  203. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/switch-on.png +0 -0
  204. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/tabs-bar-horizontal.png +0 -0
  205. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/tabs-bar-vertical.png +0 -0
  206. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/assets/widgets/tabs-pill.png +0 -0
  207. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/__main__.py +0 -0
  208. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/build.py +0 -0
  209. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/config.py +0 -0
  210. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/demo.py +0 -0
  211. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/doctor.py +0 -0
  212. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/list_cmd.py +0 -0
  213. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/promote.py +0 -0
  214. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/pyinstaller.py +0 -0
  215. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/run.py +0 -0
  216. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/start.py +0 -0
  217. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/cli/templates/__init__.py +0 -0
  218. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/constants.py +0 -0
  219. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/__init__.py +0 -0
  220. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/__init__.py +0 -0
  221. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/after.py +0 -0
  222. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/bind.py +0 -0
  223. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/bindtags.py +0 -0
  224. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/busy.py +0 -0
  225. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/clipboard.py +0 -0
  226. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/focus.py +0 -0
  227. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/grab.py +0 -0
  228. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/grid.py +0 -0
  229. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/localization.py +0 -0
  230. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/pack.py +0 -0
  231. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/place.py +0 -0
  232. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/selection.py +0 -0
  233. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/signals.py +0 -0
  234. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/capabilities/winfo.py +0 -0
  235. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/colorutils.py +0 -0
  236. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/exceptions.py +0 -0
  237. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/images.py +0 -0
  238. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/localization/README.md +0 -0
  239. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/localization/__init__.py +0 -0
  240. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/localization/intl_format.py +0 -0
  241. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/localization/msgcat.py +0 -0
  242. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/localization/specs.py +0 -0
  243. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/mixins/__init__.py +0 -0
  244. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/mixins/ttk_state.py +0 -0
  245. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/mixins/widget.py +0 -0
  246. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/publisher.py +0 -0
  247. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/signals/README.md +0 -0
  248. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/signals/__init__.py +0 -0
  249. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/signals/integration.py +0 -0
  250. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/signals/signal.py +0 -0
  251. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/signals/types.py +0 -0
  252. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/validation/__init__.py +0 -0
  253. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/validation/types.py +0 -0
  254. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/validation/validation_result.py +0 -0
  255. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/validation/validation_rules.py +0 -0
  256. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/core/variables.py +0 -0
  257. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/README.md +0 -0
  258. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/__init__.py +0 -0
  259. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/base.py +0 -0
  260. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/file_source.py +0 -0
  261. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/memory_source.py +0 -0
  262. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/datasource/types.py +0 -0
  263. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/__init__.py +0 -0
  264. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/colorchooser.py +0 -0
  265. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/colordropper.py +0 -0
  266. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/datedialog.py +0 -0
  267. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/dialog.py +0 -0
  268. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/filterdialog.py +0 -0
  269. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/fontdialog.py +0 -0
  270. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/formdialog.py +0 -0
  271. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/message.py +0 -0
  272. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/dialogs/query.py +0 -0
  273. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/py.typed +0 -0
  274. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/__init__.py +0 -0
  275. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/app.py +0 -0
  276. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/base_window.py +0 -0
  277. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/events.py +0 -0
  278. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/menu.py +0 -0
  279. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/shortcuts.py +0 -0
  280. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/tk_patch.py +0 -0
  281. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/toplevel.py +0 -0
  282. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/utility.py +0 -0
  283. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/visual_focus.py +0 -0
  284. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/runtime/window_utilities.py +0 -0
  285. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/__init__.py +0 -0
  286. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/bootstyle.py +0 -0
  287. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/bootstyle_builder_base.py +0 -0
  288. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/bootstyle_builder_mixed.py +0 -0
  289. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/bootstyle_builder_tk.py +0 -0
  290. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/bootstyle_builder_ttk.py +0 -0
  291. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/__init__.py +0 -0
  292. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/badge.py +0 -0
  293. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/button.py +0 -0
  294. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/buttongroup.py +0 -0
  295. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/calendar.py +0 -0
  296. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/checkbutton.py +0 -0
  297. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/combobox.py +0 -0
  298. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/contextmenu.py +0 -0
  299. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/entry.py +0 -0
  300. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/expander.py +0 -0
  301. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/field.py +0 -0
  302. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/frame.py +0 -0
  303. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/label.py +0 -0
  304. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/labelframe.py +0 -0
  305. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/listview.py +0 -0
  306. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/menubar.py +0 -0
  307. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/menubutton.py +0 -0
  308. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/notebook.py +0 -0
  309. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/panedwindow.py +0 -0
  310. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/progressbar.py +0 -0
  311. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/radiobutton.py +0 -0
  312. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/scale.py +0 -0
  313. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/scrollbar.py +0 -0
  314. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/separator.py +0 -0
  315. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/sidenav.py +0 -0
  316. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/sizegrip.py +0 -0
  317. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/spinbox.py +0 -0
  318. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/switch.py +0 -0
  319. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/tabitem.py +0 -0
  320. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/toolbutton.py +0 -0
  321. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/tooltip.py +0 -0
  322. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/treeview.py +0 -0
  323. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders/utils.py +0 -0
  324. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders_tk/__init__.py +0 -0
  325. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/builders_tk/defaults.py +0 -0
  326. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/element.py +0 -0
  327. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/style.py +0 -0
  328. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/theme_provider.py +0 -0
  329. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/tk_patch.py +0 -0
  330. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/token_maps.py +0 -0
  331. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/types.py +0 -0
  332. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/typography.py +0 -0
  333. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/style/utility.py +0 -0
  334. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/themes/__init__.py +0 -0
  335. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/themes/standard.py +0 -0
  336. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/themes/user.py +0 -0
  337. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/__init__.py +0 -0
  338. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/__init__.py +0 -0
  339. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/accordion.py +0 -0
  340. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/appshell.py +0 -0
  341. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/buttongroup.py +0 -0
  342. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/calendar.py +0 -0
  343. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/compositeframe.py +0 -0
  344. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/contextmenu.py +0 -0
  345. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/dateentry.py +0 -0
  346. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/dropdownbutton.py +0 -0
  347. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/expander.py +0 -0
  348. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/floodgauge.py +0 -0
  349. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/labeledscale.py +0 -0
  350. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/list/__init__.py +0 -0
  351. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/list/listitem.py +0 -0
  352. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/list/listview.py +0 -0
  353. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/menubar.py +0 -0
  354. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/meter.py +0 -0
  355. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/numericentry.py +0 -0
  356. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/pagestack.py +0 -0
  357. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/passwordentry.py +0 -0
  358. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/pathentry.py +0 -0
  359. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/radiogroup.py +0 -0
  360. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/scrolledtext.py +0 -0
  361. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/scrolledtext.pyi +0 -0
  362. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/scrollview.py +0 -0
  363. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/selectbox.py +0 -0
  364. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/sidenav/__init__.py +0 -0
  365. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/sidenav/group.py +0 -0
  366. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/sidenav/header.py +0 -0
  367. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/sidenav/item.py +0 -0
  368. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/sidenav/separator.py +0 -0
  369. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/sidenav/view.py +0 -0
  370. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/spinnerentry.py +0 -0
  371. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tableview/__init__.py +0 -0
  372. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tableview/types.py +0 -0
  373. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tabs/__init__.py +0 -0
  374. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tabs/tabitem.py +0 -0
  375. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tabs/tabs.py +0 -0
  376. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tabs/tabview.py +0 -0
  377. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/textentry.py +0 -0
  378. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/timeentry.py +0 -0
  379. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/toast.py +0 -0
  380. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/togglegroup.py +0 -0
  381. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/toolbar.py +0 -0
  382. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/composites/tooltip.py +0 -0
  383. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/internal/__init__.py +0 -0
  384. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/internal/wrapper_base.py +0 -0
  385. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/__init__.py +0 -0
  386. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/configure_mixin.py +0 -0
  387. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/entry_mixin.py +0 -0
  388. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/font_mixin.py +0 -0
  389. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/icon_mixin.py +0 -0
  390. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/localization_mixin.py +0 -0
  391. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/signal_mixin.py +0 -0
  392. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/mixins/validation_mixin.py +0 -0
  393. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/parts/__init__.py +0 -0
  394. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/parts/numberentry_part.py +0 -0
  395. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/parts/spinnerentry_part.py +0 -0
  396. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/parts/textentry_part.py +0 -0
  397. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/__init__.py +0 -0
  398. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/badge.py +0 -0
  399. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/button.py +0 -0
  400. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/card.py +0 -0
  401. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/checkbutton.py +0 -0
  402. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/checktoggle.py +0 -0
  403. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/combobox.py +0 -0
  404. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/entry.py +0 -0
  405. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/frame.py +0 -0
  406. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/gridframe.py +0 -0
  407. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/label.py +0 -0
  408. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/labelframe.py +0 -0
  409. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/menubutton.py +0 -0
  410. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/notebook.py +0 -0
  411. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/optionmenu.py +0 -0
  412. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/packframe.py +0 -0
  413. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/panedwindow.py +0 -0
  414. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/progressbar.py +0 -0
  415. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/radiobutton.py +0 -0
  416. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/radiotoggle.py +0 -0
  417. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/scale.py +0 -0
  418. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/scrollbar.py +0 -0
  419. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/separator.py +0 -0
  420. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/sizegrip.py +0 -0
  421. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/spinbox.py +0 -0
  422. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/switch.py +0 -0
  423. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/primitives/treeview.py +0 -0
  424. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack/widgets/types.py +0 -0
  425. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack.egg-info/dependency_links.txt +0 -0
  426. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack.egg-info/entry_points.txt +0 -0
  427. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack.egg-info/requires.txt +0 -0
  428. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/src/bootstack.egg-info/top_level.txt +0 -0
  429. {bootstack-0.1.0a5 → bootstack-0.1.0a6}/tests/test_togglegroup.py +0 -0
  430. {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.0a5
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.0a5"
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.0a5"
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.typography import Font
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 = ttk.App(theme="{theme_name}")')
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: ttk.mc('Hello')")
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
- - 'id' field is automatically set as PRIMARY KEY
65
- - 'selected' field is added automatically for selection tracking
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 "id" not in record:
127
- record["id"] = i
128
- if "selected" not in record:
129
- record["selected"] = 0
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 = "id" not in keys
140
- need_selected = "selected" not in keys
144
+ need_id = _ROW_ID not in keys
145
+ need_sel = _ROW_SEL not in keys
141
146
  if need_id:
142
- keys.append("id")
143
- if need_selected:
144
- keys.append("selected")
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 "id" in keys:
150
- padded_first[keys.index("id")] = 0
151
- if need_selected and "selected" in keys:
152
- padded_first[keys.index("selected")] = 0
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("id") if "id" in keys else None
157
- sel_idx = keys.index("selected") if "selected" in keys else None
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 == "id" else "")
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 "id" not in record:
245
- record["id"] = self._generate_new_id()
249
+ if _ROW_ID not in record:
250
+ record[_ROW_ID] = self._generate_new_id()
246
251
 
247
- if "selected" not in record:
248
- record["selected"] = 0
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["id"]
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 id = ?", (record_id,))
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 id = ?", values)
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 id = ?", (record_id,))
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(id) FROM {self._table}")
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 "id" not in cols:
305
- cols.append("id")
306
- if "selected" not in cols:
307
- cols.append("selected")
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 == "id":
317
+ if c == _ROW_ID:
313
318
  col_types[c] = "INTEGER"
314
- elif c == "selected":
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 == "id" else "")
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["id"] for row in self.get_page()]
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 selected = 1 WHERE id IN ({placeholders})"
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 selected = 1")
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["id"] for row in self.get_page()]
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 selected = 0 WHERE id IN ({placeholders})"
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 selected = 0")
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 selected = 1"
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 'selected' column to table if it doesn't exist."""
384
- if "selected" not in self._columns:
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 selected INTEGER DEFAULT 0")
387
- self._columns.append("selected")
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 selected = 1"
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 "selected" not in self._columns:
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 selected INTEGER DEFAULT 0")
401
- self._columns.append("selected")
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(f"UPDATE {self._table} SET selected = ? WHERE id = ?", (flag, record_id))
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 selected = 1"
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 message is provided and user didn't explicitly disable it
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
- self.add_validation_rule = self._entry.add_validation_rule
270
- self.add_validation_rules = self._entry.add_validation_rules
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
- # Support both color and legacy bootstyle from DialogButton
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:
@@ -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["id"] = new_id
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 an 'id' key."""
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("id")
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 != "id"}
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("id")
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 = {"id": rec_id}
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 ("id", "selected")]
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 "id" in record:
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 "id" in record:
1356
+ if result == "delete" and record and _ROW_ID in record:
1357
1357
  try:
1358
- self._datasource.delete_record(record["id"])
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["id"])
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 "id" in record:
1368
- rec_id = record["id"]
1367
+ if record and _ROW_ID in record:
1368
+ rec_id = record[_ROW_ID]
1369
1369
  updates = dict(data)
1370
- updates.pop("id", None)
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("id")
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("id")
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("id")) == rid:
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("id")) == rid for rec in rows):
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