py10x-universe 0.1.3__py3-none-any.whl

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 (214) hide show
  1. core_10x/__init__.py +42 -0
  2. core_10x/backbone/__init__.py +0 -0
  3. core_10x/backbone/backbone_store.py +59 -0
  4. core_10x/backbone/backbone_traitable.py +30 -0
  5. core_10x/backbone/backbone_user.py +66 -0
  6. core_10x/backbone/bound_data_domain.py +49 -0
  7. core_10x/backbone/namespace.py +101 -0
  8. core_10x/backbone/vault.py +38 -0
  9. core_10x/code_samples/__init__.py +0 -0
  10. core_10x/code_samples/_package_manifest.py +3 -0
  11. core_10x/code_samples/directories.py +181 -0
  12. core_10x/code_samples/person.py +76 -0
  13. core_10x/concrete_traits.py +356 -0
  14. core_10x/conftest.py +12 -0
  15. core_10x/curve.py +321 -0
  16. core_10x/data_domain.py +48 -0
  17. core_10x/data_domain_binder.py +45 -0
  18. core_10x/directory.py +250 -0
  19. core_10x/entity.py +8 -0
  20. core_10x/entity_filter.py +5 -0
  21. core_10x/environment_variables.py +147 -0
  22. core_10x/exec_control.py +84 -0
  23. core_10x/experimental/__init__.py +0 -0
  24. core_10x/experimental/data_protocol_ex.py +34 -0
  25. core_10x/global_cache.py +121 -0
  26. core_10x/manual_tests/__init__.py +0 -0
  27. core_10x/manual_tests/calendar_test.py +35 -0
  28. core_10x/manual_tests/ctor_update_bug.py +58 -0
  29. core_10x/manual_tests/debug_graph_on.py +17 -0
  30. core_10x/manual_tests/debug_graphoff_inside_graph_on.py +28 -0
  31. core_10x/manual_tests/enum_bits_test.py +17 -0
  32. core_10x/manual_tests/env_vars_trivial_test.py +12 -0
  33. core_10x/manual_tests/existing_traitable.py +33 -0
  34. core_10x/manual_tests/k10x_test1.py +13 -0
  35. core_10x/manual_tests/named_constant_test.py +121 -0
  36. core_10x/manual_tests/nucleus_trivial_test.py +42 -0
  37. core_10x/manual_tests/polars_test.py +14 -0
  38. core_10x/manual_tests/py_class_test.py +4 -0
  39. core_10x/manual_tests/rc_test.py +42 -0
  40. core_10x/manual_tests/rdate_test.py +12 -0
  41. core_10x/manual_tests/reference_serialization_bug.py +19 -0
  42. core_10x/manual_tests/resource_trivial_test.py +10 -0
  43. core_10x/manual_tests/store_uri_test.py +6 -0
  44. core_10x/manual_tests/trait_definition_test.py +19 -0
  45. core_10x/manual_tests/trait_filter_test.py +15 -0
  46. core_10x/manual_tests/trait_flag_modification_test.py +42 -0
  47. core_10x/manual_tests/trait_modification_bug.py +26 -0
  48. core_10x/manual_tests/traitable_as_of_test.py +82 -0
  49. core_10x/manual_tests/traitable_heir_test.py +39 -0
  50. core_10x/manual_tests/traitable_history_test.py +41 -0
  51. core_10x/manual_tests/traitable_serialization_test.py +54 -0
  52. core_10x/manual_tests/traitable_trivial_test.py +71 -0
  53. core_10x/manual_tests/trivial_graph_test.py +16 -0
  54. core_10x/manual_tests/ts_class_association_test.py +64 -0
  55. core_10x/manual_tests/ts_trivial_test.py +35 -0
  56. core_10x/named_constant.py +425 -0
  57. core_10x/nucleus.py +81 -0
  58. core_10x/package_manifest.py +85 -0
  59. core_10x/package_refactoring.py +153 -0
  60. core_10x/py_class.py +431 -0
  61. core_10x/rc.py +155 -0
  62. core_10x/rdate.py +339 -0
  63. core_10x/resource.py +189 -0
  64. core_10x/roman_number.py +67 -0
  65. core_10x/testlib/__init__.py +0 -0
  66. core_10x/testlib/test_store.py +240 -0
  67. core_10x/testlib/traitable_history_tests.py +787 -0
  68. core_10x/testlib/ts_tests.py +280 -0
  69. core_10x/trait.py +377 -0
  70. core_10x/trait_definition.py +176 -0
  71. core_10x/trait_filter.py +205 -0
  72. core_10x/trait_method_error.py +36 -0
  73. core_10x/traitable.py +1082 -0
  74. core_10x/traitable_cli.py +153 -0
  75. core_10x/traitable_heir.py +33 -0
  76. core_10x/traitable_id.py +31 -0
  77. core_10x/ts_store.py +172 -0
  78. core_10x/ts_store_type.py +26 -0
  79. core_10x/ts_union.py +147 -0
  80. core_10x/ui_hint.py +153 -0
  81. core_10x/unit_tests/test_concrete_traits.py +156 -0
  82. core_10x/unit_tests/test_converters.py +51 -0
  83. core_10x/unit_tests/test_curve.py +157 -0
  84. core_10x/unit_tests/test_directory.py +54 -0
  85. core_10x/unit_tests/test_documentation.py +172 -0
  86. core_10x/unit_tests/test_environment_variables.py +15 -0
  87. core_10x/unit_tests/test_filters.py +239 -0
  88. core_10x/unit_tests/test_graph.py +348 -0
  89. core_10x/unit_tests/test_named_constant.py +98 -0
  90. core_10x/unit_tests/test_rc.py +11 -0
  91. core_10x/unit_tests/test_rdate.py +484 -0
  92. core_10x/unit_tests/test_trait_method_error.py +80 -0
  93. core_10x/unit_tests/test_trait_modification.py +19 -0
  94. core_10x/unit_tests/test_traitable.py +959 -0
  95. core_10x/unit_tests/test_traitable_history.py +1 -0
  96. core_10x/unit_tests/test_ts_store.py +1 -0
  97. core_10x/unit_tests/test_ts_union.py +369 -0
  98. core_10x/unit_tests/test_ui_nodes.py +81 -0
  99. core_10x/unit_tests/test_xxcalendar.py +471 -0
  100. core_10x/vault/__init__.py +0 -0
  101. core_10x/vault/sec_keys.py +133 -0
  102. core_10x/vault/security_keys_old.py +168 -0
  103. core_10x/vault/vault.py +56 -0
  104. core_10x/vault/vault_traitable.py +56 -0
  105. core_10x/vault/vault_user.py +70 -0
  106. core_10x/xdate_time.py +136 -0
  107. core_10x/xnone.py +71 -0
  108. core_10x/xxcalendar.py +228 -0
  109. infra_10x/__init__.py +0 -0
  110. infra_10x/manual_tests/__init__.py +0 -0
  111. infra_10x/manual_tests/test_misc.py +16 -0
  112. infra_10x/manual_tests/test_prepare_filter_and_pipeline.py +25 -0
  113. infra_10x/mongodb_admin.py +111 -0
  114. infra_10x/mongodb_store.py +346 -0
  115. infra_10x/mongodb_utils.py +129 -0
  116. infra_10x/unit_tests/conftest.py +13 -0
  117. infra_10x/unit_tests/test_mongo_db.py +36 -0
  118. infra_10x/unit_tests/test_mongo_history.py +1 -0
  119. py10x_universe-0.1.3.dist-info/METADATA +406 -0
  120. py10x_universe-0.1.3.dist-info/RECORD +214 -0
  121. py10x_universe-0.1.3.dist-info/WHEEL +4 -0
  122. py10x_universe-0.1.3.dist-info/licenses/LICENSE +21 -0
  123. ui_10x/__init__.py +0 -0
  124. ui_10x/apps/__init__.py +0 -0
  125. ui_10x/apps/collection_editor_app.py +100 -0
  126. ui_10x/choice.py +212 -0
  127. ui_10x/collection_editor.py +135 -0
  128. ui_10x/concrete_trait_widgets.py +220 -0
  129. ui_10x/conftest.py +8 -0
  130. ui_10x/entity_stocker.py +173 -0
  131. ui_10x/examples/__init__.py +0 -0
  132. ui_10x/examples/_guess_word_data.py +14076 -0
  133. ui_10x/examples/collection_editor.py +17 -0
  134. ui_10x/examples/date_selector.py +14 -0
  135. ui_10x/examples/entity_stocker.py +18 -0
  136. ui_10x/examples/guess_word.py +392 -0
  137. ui_10x/examples/message_box.py +20 -0
  138. ui_10x/examples/multi_choice.py +17 -0
  139. ui_10x/examples/py_data_browser.py +66 -0
  140. ui_10x/examples/radiobox.py +29 -0
  141. ui_10x/examples/single_choice.py +31 -0
  142. ui_10x/examples/style_sheet.py +47 -0
  143. ui_10x/examples/trivial_entity_editor.py +18 -0
  144. ui_10x/platform.py +20 -0
  145. ui_10x/platform_interface.py +517 -0
  146. ui_10x/py_data_browser.py +249 -0
  147. ui_10x/qt6/__init__.py +0 -0
  148. ui_10x/qt6/conftest.py +8 -0
  149. ui_10x/qt6/manual_tests/__init__.py +0 -0
  150. ui_10x/qt6/manual_tests/basic_test.py +35 -0
  151. ui_10x/qt6/platform_implementation.py +275 -0
  152. ui_10x/qt6/utils.py +665 -0
  153. ui_10x/rio/__init__.py +0 -0
  154. ui_10x/rio/apps/examples/examples/__init__.py +22 -0
  155. ui_10x/rio/apps/examples/examples/components/__init__.py +3 -0
  156. ui_10x/rio/apps/examples/examples/components/collection_editor.py +15 -0
  157. ui_10x/rio/apps/examples/examples/pages/collection_editor.py +21 -0
  158. ui_10x/rio/apps/examples/examples/pages/login_page.py +88 -0
  159. ui_10x/rio/apps/examples/examples/pages/style_sheet.py +21 -0
  160. ui_10x/rio/apps/examples/rio.toml +14 -0
  161. ui_10x/rio/component_builder.py +497 -0
  162. ui_10x/rio/components/__init__.py +9 -0
  163. ui_10x/rio/components/group_box.py +31 -0
  164. ui_10x/rio/components/labeled_checkbox.py +18 -0
  165. ui_10x/rio/components/line_edit.py +37 -0
  166. ui_10x/rio/components/radio_button.py +32 -0
  167. ui_10x/rio/components/separator.py +24 -0
  168. ui_10x/rio/components/splitter.py +121 -0
  169. ui_10x/rio/components/tree_view.py +75 -0
  170. ui_10x/rio/conftest.py +35 -0
  171. ui_10x/rio/internals/__init__.py +0 -0
  172. ui_10x/rio/internals/app.py +192 -0
  173. ui_10x/rio/manual_tests/__init__.py +0 -0
  174. ui_10x/rio/manual_tests/basic_test.py +24 -0
  175. ui_10x/rio/manual_tests/splitter.py +27 -0
  176. ui_10x/rio/platform_implementation.py +91 -0
  177. ui_10x/rio/style_sheet.py +53 -0
  178. ui_10x/rio/unit_tests/test_collection_editor.py +68 -0
  179. ui_10x/rio/unit_tests/test_internals.py +630 -0
  180. ui_10x/rio/unit_tests/test_style_sheet.py +37 -0
  181. ui_10x/rio/widgets/__init__.py +46 -0
  182. ui_10x/rio/widgets/application.py +109 -0
  183. ui_10x/rio/widgets/button.py +48 -0
  184. ui_10x/rio/widgets/button_group.py +60 -0
  185. ui_10x/rio/widgets/calendar.py +23 -0
  186. ui_10x/rio/widgets/checkbox.py +24 -0
  187. ui_10x/rio/widgets/dialog.py +137 -0
  188. ui_10x/rio/widgets/group_box.py +27 -0
  189. ui_10x/rio/widgets/layout.py +34 -0
  190. ui_10x/rio/widgets/line_edit.py +37 -0
  191. ui_10x/rio/widgets/list.py +105 -0
  192. ui_10x/rio/widgets/message_box.py +70 -0
  193. ui_10x/rio/widgets/scroll_area.py +31 -0
  194. ui_10x/rio/widgets/spacer.py +6 -0
  195. ui_10x/rio/widgets/splitter.py +45 -0
  196. ui_10x/rio/widgets/text_edit.py +28 -0
  197. ui_10x/rio/widgets/tree.py +89 -0
  198. ui_10x/rio/widgets/unit_tests/test_button.py +101 -0
  199. ui_10x/rio/widgets/unit_tests/test_button_group.py +33 -0
  200. ui_10x/rio/widgets/unit_tests/test_calendar.py +114 -0
  201. ui_10x/rio/widgets/unit_tests/test_checkbox.py +109 -0
  202. ui_10x/rio/widgets/unit_tests/test_group_box.py +158 -0
  203. ui_10x/rio/widgets/unit_tests/test_label.py +43 -0
  204. ui_10x/rio/widgets/unit_tests/test_line_edit.py +140 -0
  205. ui_10x/rio/widgets/unit_tests/test_list.py +146 -0
  206. ui_10x/table_header_view.py +305 -0
  207. ui_10x/table_view.py +174 -0
  208. ui_10x/trait_editor.py +189 -0
  209. ui_10x/trait_widget.py +131 -0
  210. ui_10x/traitable_editor.py +200 -0
  211. ui_10x/traitable_view.py +131 -0
  212. ui_10x/unit_tests/conftest.py +8 -0
  213. ui_10x/unit_tests/test_platform.py +9 -0
  214. ui_10x/utils.py +661 -0
ui_10x/qt6/utils.py ADDED
@@ -0,0 +1,665 @@
1
+ #TODO: delete this file, it is duplicated in ui_10x.utils
2
+ assert False, "use ui_10x.utils"
3
+ # from datetime import date
4
+ # import inspect
5
+ # import platform
6
+ #
7
+ # from PyQt6.QtWidgets import QLabel, QWidget, QCalendarWidget, QMessageBox, QGroupBox, QButtonGroup, QRadioButton, QApplication
8
+ # from PyQt6.QtWidgets import QListWidget, QLineEdit, QTreeWidgetItem, QTreeWidget, QSizePolicy
9
+ # from PyQt6.QtWidgets import QFrame, QVBoxLayout, QHBoxLayout, QSplitter, QDialog, QScrollArea, QPushButton, QStyle
10
+ # from PyQt6.QtCore import Qt, QObject, QThread, pyqtSignal, QBuffer, QIODevice #, QByteArray
11
+ # from PyQt6.QtGui import QColor, QGuiApplication, QPixmap
12
+ #
13
+ # # from asu.nx.directory import Directory
14
+ #
15
+ # from core_10x.named_constant import NamedConstant
16
+ # from core_10x.rc import RC
17
+ # from core_10x.global_cache import cache, singleton
18
+ #
19
+ # class UxAsync(QObject):
20
+ # SIGNAL = pyqtSignal()
21
+ # s_instances = {}
22
+ #
23
+ # @classmethod
24
+ # def _check_thread(cls, bound_method):
25
+ # if QThread.currentThread() != QGuiApplication.instance().thread():
26
+ # raise RuntimeError(f'You must have called UxAsync.init({bound_method.__name__}) in the UI thread')
27
+ #
28
+ # @classmethod
29
+ # def init(cls, bound_method):
30
+ # instance = cls.s_instances.get(bound_method)
31
+ # if not instance:
32
+ # cls._check_thread(bound_method)
33
+ # instance = cls()
34
+ # cls.s_instances[bound_method] = instance
35
+ #
36
+ # instance.SIGNAL.connect(bound_method, type = Qt.ConnectionType.QueuedConnection)
37
+ #
38
+ # return instance
39
+ #
40
+ # @classmethod
41
+ # def call(cls, bound_method):
42
+ # instance = cls.init(bound_method)
43
+ # instance.SIGNAL.emit()
44
+ #
45
+ # class UxRadioBox(QGroupBox):
46
+ # def __init__(self, named_constant_class, title = '', horizontal = False, default_value: NamedConstant = None):
47
+ # assert inspect.isclass(named_constant_class) and issubclass(named_constant_class, NamedConstant), 'subclass of NamedConstant is expected'
48
+ #
49
+ # self.nm_class = named_constant_class
50
+ # self.values = values = list(named_constant_class.s_dir.values())
51
+ #
52
+ # if default_value is None:
53
+ # default = 0
54
+ # else:
55
+ # assert isinstance(default_value, named_constant_class), f'{named_constant_class} - unknown default_values = {default_value}'
56
+ # for i, c_def in enumerate(values):
57
+ # if c_def is default_value:
58
+ # default = i
59
+ # break
60
+ # else:
61
+ # assert False, f'{default_value} is not found'
62
+ #
63
+ # if title:
64
+ # super().__init__(title)
65
+ # else:
66
+ # super().__init__()
67
+ #
68
+ #
69
+ # lay = QHBoxLayout() if horizontal else QVBoxLayout()
70
+ # self.setLayout(lay)
71
+ #
72
+ # self.group = group = QButtonGroup()
73
+ # for i, c_def in enumerate(named_constant_class.s_dir.values()):
74
+ # rb = QRadioButton(c_def.label)
75
+ # lay.addWidget(rb)
76
+ # group.addButton(rb, id = i)
77
+ # group.button(default).setChecked(True)
78
+ #
79
+ # def choice(self):
80
+ # i = self.group.checkedId()
81
+ # return self.values[i]
82
+ #
83
+ # def uxSeparator(horizontal = True) -> QLabel:
84
+ # direction = QFrame.Shape.HLine if horizontal else QFrame.Shape.VLine
85
+ # sep = QLabel()
86
+ # sep.setFrameStyle(direction | QFrame.Shadow.Sunken)
87
+ # return sep
88
+ #
89
+ # def uxToClipboard(text: str, **kwargs):
90
+ # cp = QGuiApplication.clipboard()
91
+ # cp.setText(text)
92
+ #
93
+ # def uxFromClipboard(**kwargs) -> str:
94
+ # cp = QGuiApplication.clipboard()
95
+ # return cp.text()
96
+ #
97
+ # def uxSuccess(text: str, parent = None, title = ''):
98
+ # if not title:
99
+ # title = 'Success'
100
+ # if not parent:
101
+ # parent = None
102
+ # QMessageBox.information(parent, title, text)
103
+ #
104
+ # def uxWarning(text: str, parent = None, title = ''):
105
+ # if not title:
106
+ # title = 'Warning'
107
+ # if not parent:
108
+ # parent = None
109
+ # QMessageBox.warning(parent, title, text)
110
+ #
111
+ # def uxAnswer(question: str, parent = None, title = '') -> bool:
112
+ # if not title:
113
+ # title = 'Waiting for your answer...'
114
+ # if not parent:
115
+ # parent = None
116
+ # sb = QMessageBox.question(parent, title, question)
117
+ # return True if sb == QMessageBox.StandardButton.Yes else False
118
+ #
119
+ # def uxMultiChoiceAnswer(named_constant_class, parent = None, title = '', default_value: NamedConstant = None):
120
+ # if not title:
121
+ # title = 'Pick one of the choices below:'
122
+ #
123
+ # if not parent:
124
+ # parent = None
125
+ #
126
+ # box = UxRadioBox(named_constant_class, default_value = default_value)
127
+ # d = UxDialog(box, parent = parent, title = title, cancel = '')
128
+ # d.exec()
129
+ # return box.choice()
130
+ #
131
+ # def uxPushButton(label: str, callback = None, style_icon = None, flat = False):
132
+ # if style_icon:
133
+ # if isinstance(style_icon, str):
134
+ # style_icon = getattr(QStyle, 'SP_' + style_icon, None)
135
+ # assert style_icon, f"Unknown style_icon = '{style_icon}'"
136
+ #
137
+ # assert isinstance(style_icon, int), 'Currently only str or int are supported for style_icon'
138
+ #
139
+ # style = QApplication.style()
140
+ # icon = style.standardIcon(style_icon)
141
+ # button = QPushButton(icon, label)
142
+ # else:
143
+ # button = QPushButton(label)
144
+ #
145
+ # if callback:
146
+ # button.clicked.connect(callback)
147
+ #
148
+ # if flat:
149
+ # button.setFlat(True)
150
+ #
151
+ # return button
152
+ #
153
+ # class UxDialog(QDialog):
154
+ # def _createButton(self, ok: bool, button_spec) -> QPushButton:
155
+ # if not button_spec:
156
+ # return None
157
+ #
158
+ # if isinstance(button_spec, str):
159
+ # label = button_spec
160
+ # icon = ''
161
+ #
162
+ # elif isinstance(button_spec, tuple):
163
+ # try:
164
+ # label, icon = button_spec
165
+ # except Exception:
166
+ # return None
167
+ #
168
+ # else:
169
+ # return None
170
+ #
171
+ # cb = self.onOk if ok else self.onCancel
172
+ # return uxPushButton(label, callback = cb, style_icon = icon)
173
+ #
174
+ # def __init__(
175
+ # self,
176
+ # w: QWidget,
177
+ # parent: QWidget = None,
178
+ # title: str = None,
179
+ # ok = 'Ok',
180
+ # cancel = 'Cancel',
181
+ # accept_callback = None,
182
+ # cancel_callback = None,
183
+ # min_width = 0,
184
+ # min_height = 0,
185
+ # window_flags = None
186
+ # ):
187
+ # """
188
+ # :param w: a QWidget to show
189
+ # :param parent: parent widget, if any
190
+ # :param title: dialog title
191
+ # :param accept_callback: context.method, where: method( context ) -> RC
192
+ # :param ok, cancel: labels and corresponding roles for Ok and Cancel buttons. No button if empty
193
+ # """
194
+ # super().__init__( parent )
195
+ # if title:
196
+ # self.setWindowTitle( title )
197
+ #
198
+ # if window_flags is None:
199
+ # window_flags = Qt.WindowType.CustomizeWindowHint | Qt.WindowType.Window | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint
200
+ #
201
+ # self.setWindowFlags(window_flags)
202
+ # self.accept_callback = accept_callback
203
+ # self.cancel_callback = cancel_callback if cancel_callback else self.reject
204
+ #
205
+ # if ok:
206
+ # ok = self._createButton(True, ok)
207
+ # if cancel:
208
+ # cancel = self._createButton(False, cancel)
209
+ #
210
+ # lay = QVBoxLayout()
211
+ # self.setLayout(lay)
212
+ #
213
+ # lay.addWidget(w)
214
+ #
215
+ # self.w_message = QLabel()
216
+ # self.w_message.setStyleSheet('color: red;')
217
+ # lay.addWidget(self.w_message)
218
+ #
219
+ # if ok or cancel:
220
+ # lay.addWidget(uxSeparator())
221
+ #
222
+ # bar = QHBoxLayout()
223
+ # lay.addLayout(bar)
224
+ #
225
+ # bar.addWidget(QLabel(), stretch = 1)
226
+ # if ok:
227
+ # bar.addWidget(ok)
228
+ # if cancel:
229
+ # bar.addWidget(cancel)
230
+ #
231
+ # if min_width > 0:
232
+ # self.setMinimumWidth(min_width)
233
+ # if min_height > 0:
234
+ # self.setMinimumHeight(min_height)
235
+ #
236
+ # def onOk(self):
237
+ # if self.accept_callback:
238
+ # rc = self.accept_callback()
239
+ # if not rc:
240
+ # self.message(rc.err())
241
+ # return
242
+ #
243
+ # self.done(1)
244
+ #
245
+ # def onCancel(self):
246
+ # self.reject()
247
+ # self.done(0)
248
+ #
249
+ # def message(self, text: str):
250
+ # self.w_message.setText(text)
251
+ #
252
+ # def uxPickDate(title = 'Pick a Date', show_date: date = None, grid = True, default = None):
253
+ # cal = QCalendarWidget()
254
+ # cal.setGridVisible(bool(grid))
255
+ # if show_date:
256
+ # cal.setSelectedDate(show_date)
257
+ # dlg = UxDialog(cal, title = title)
258
+ # rc = dlg.exec()
259
+ #
260
+ # return cal.selectedDate().toPyDate() if rc else default
261
+ #
262
+ # class UxStyleSheet:
263
+ # @classmethod
264
+ # def dumps(cls, data: dict) -> str:
265
+ # return '\n'.join(f'{name}: {value};' for name, value in data.items())
266
+ #
267
+ # @classmethod
268
+ # def loads(cls, sheet: str) -> dict:
269
+ # res = {}
270
+ # pairs = sheet.split(';')
271
+ # for pair in pairs:
272
+ # pair = pair.strip()
273
+ # if pair:
274
+ # name_value = pair.split(':')
275
+ # if len(name_value) == 2:
276
+ # name = name_value[0].strip()
277
+ # value = name_value[1].strip()
278
+ # res[name] = value
279
+ #
280
+ # return res
281
+ #
282
+ # @classmethod
283
+ # def slice(cls, w: QWidget, *attr_names) -> list:
284
+ # data = cls.loads(w.styleSheet())
285
+ # return [ data.get(name) for name in attr_names ]
286
+ #
287
+ # @classmethod
288
+ # def update(cls, w: QWidget, sheet_update: str, replace = False):
289
+ # if not replace:
290
+ # sh = w.styleSheet()
291
+ # data = cls.loads(sh)
292
+ # update_data = cls.loads(sheet_update)
293
+ # data.update(update_data)
294
+ # new_sh = cls.dumps(data)
295
+ # else:
296
+ # new_sh = sheet_update
297
+ #
298
+ # w.setStyleSheet(new_sh)
299
+ #
300
+ # @classmethod
301
+ # def _color(cls, style_sheet: str, attr_name: str):
302
+ # data = cls.loads(style_sheet)
303
+ # str_color = data.get(attr_name)
304
+ # return QColor(str_color) if str_color else None
305
+ #
306
+ # @classmethod
307
+ # def fg_color(cls, style_sheet: str) -> QColor:
308
+ # return cls._color(style_sheet, 'color')
309
+ #
310
+ # @classmethod
311
+ # def bg_color(cls, style_sheet: str) -> QColor:
312
+ # return cls._color(style_sheet, 'background-color')
313
+ #
314
+ # @classmethod
315
+ # def color(cls, style_sheet: str, background = False) -> QColor:
316
+ # return cls.bg_color(style_sheet) if background else cls.fg_color(style_sheet)
317
+ #
318
+ # s_verticalAlignmentMap = {
319
+ # -1: Qt.AlignmentFlag.AlignTop,
320
+ # 0: Qt.AlignmentFlag.AlignVCenter,
321
+ # 1: Qt.AlignmentFlag.AlignBottom,
322
+ # }
323
+ # s_horizontalAlignmentMap = {
324
+ # -1: Qt.AlignmentFlag.AlignLeft,
325
+ # 0: Qt.AlignmentFlag.AlignCenter,
326
+ # 1: Qt.AlignmentFlag.AlignRight,
327
+ # }
328
+ # def uxTextAlignment(align_value: int, horizontal = True) -> int:
329
+ # if horizontal:
330
+ # return s_horizontalAlignmentMap.get(align_value, Qt.AlignmentFlag.AlignRight) | Qt.AlignmentFlag.AlignVCenter
331
+ #
332
+ # raise NotImplementedError
333
+ #
334
+ # class UX_SCROLL:
335
+ # OFF = Qt.ScrollBarPolicy.ScrollBarAlwaysOff
336
+ # ON = Qt.ScrollBarPolicy.ScrollBarAlwaysOn
337
+ # AS_NEEDED = Qt.ScrollBarPolicy.ScrollBarAsNeeded
338
+ #
339
+ # def uxMakeScrollable(w: QWidget, h = UX_SCROLL.AS_NEEDED, v = UX_SCROLL.AS_NEEDED) -> QWidget:
340
+ # if h is UX_SCROLL.OFF and v is UX_SCROLL.OFF:
341
+ # return w
342
+ #
343
+ # sa = QScrollArea()
344
+ # sa.setWidget(w)
345
+ # sa.setHorizontalScrollBarPolicy(h)
346
+ # sa.setVerticalScrollBarPolicy(v)
347
+ # return sa
348
+ #
349
+ # class UxSearchableList(QGroupBox):
350
+ # def __init__(
351
+ # self,
352
+ # text_widget: QLineEdit = None,
353
+ # reset_selection = True,
354
+ # choices: list = None,
355
+ # select_hook = None,
356
+ # sort = False,
357
+ # case_sensitive = False,
358
+ # title = ''
359
+ # ):
360
+ # """
361
+ # :param text_widget: if an external text_widget given, it is used, otherwise its own is created on top of the list
362
+ # :param reset_selection: if True, text_widget will be reset on new selection
363
+ # :param choices: all choices
364
+ # :param select_hook: if given, will be called after a new selection is made: select_hook( selected_choice: str )
365
+ # :param sort: sort choices if True
366
+ # :param case_sensitive: whether to search with case sensitivity
367
+ # :param title: an optional title
368
+ # """
369
+ # super().__init__()
370
+ # self.m_sort = sort
371
+ # self.m_initialChoices = choices if not sort else sorted( choices )
372
+ # self.m_currentChoices = self.m_initialChoices
373
+ # self.m_hook = select_hook
374
+ # self.m_resetSelection = reset_selection
375
+ # self.m_caseSensitive = case_sensitive
376
+ # self.m_choice = None
377
+ #
378
+ # if title:
379
+ # self.setTitle( title)
380
+ # lay = QVBoxLayout()
381
+ #
382
+ # if text_widget:
383
+ # self.m_field = text_widget
384
+ # else:
385
+ # self.m_field = QLineEdit()
386
+ # lay.addWidget( self.m_field )
387
+ # self.m_field.textEdited.connect( self.processInput )
388
+ #
389
+ # self.m_list = QListWidget()
390
+ #
391
+ # self.m_list.addItems( self.m_initialChoices )
392
+ # self.m_list.clicked.connect( self.itemSelected )
393
+ # lay.addWidget( self.m_list )
394
+ #
395
+ # self.setLayout( lay )
396
+ #
397
+ # def addChoice( self, choice: str ):
398
+ # if not choice in self.m_initialChoices:
399
+ # self.m_initialChoices.append( choice )
400
+ # if self.m_sort:
401
+ # self.m_initialChoices = sorted( self.m_initialChoices )
402
+ #
403
+ # self.m_list.clear()
404
+ # self.m_list.addItems( self.m_initialChoices )
405
+ #
406
+ # def removeChoice( self, choice: str ):
407
+ # if choice in self.m_initialChoices:
408
+ # self.m_initialChoices.remove( choice )
409
+ # self.m_list.clear()
410
+ # self.m_list.addItems( self.m_initialChoices )
411
+ #
412
+ # def processInput( self, input ):
413
+ # self.m_list.clear()
414
+ # if not input:
415
+ # self.m_currentChoices = self.m_initialChoices
416
+ # else:
417
+ # if not self.m_currentChoices:
418
+ # self.m_currentChoices = self.m_initialChoices
419
+ #
420
+ # if not self.m_caseSensitive:
421
+ # input = input.lower()
422
+ # self.m_currentChoices = [ s for s in self.m_currentChoices if not s.lower().find( input ) == -1 ]
423
+ # else:
424
+ # self.m_currentChoices = [ s for s in self.m_currentChoices if not s.find( input ) == -1 ]
425
+ #
426
+ # self.m_list.addItems( self.m_currentChoices )
427
+ #
428
+ # def itemSelected( self, item ):
429
+ # i = item.row()
430
+ # text = self.m_currentChoices[ i ]
431
+ # self.reset()
432
+ #
433
+ # items = self.m_list.findItems( text, Qt.MatchExactly )
434
+ # if len( items ):
435
+ # items[ 0 ].setSelected( True )
436
+ # text_s = '' if self.m_resetSelection else text
437
+ # self.m_field.setText( text_s )
438
+ #
439
+ # self.m_choice = text
440
+ # if self.m_hook:
441
+ # self.m_hook( text )
442
+ #
443
+ # def choice( self ) -> str:
444
+ # return self.m_choice
445
+ #
446
+ # def reset( self ):
447
+ # if not self.m_currentChoices == self.m_initialChoices:
448
+ # self.m_currentChoices = self.m_initialChoices
449
+ # self.m_list.clear()
450
+ # self.m_list.addItems( self.m_initialChoices )
451
+ #
452
+ # # class UxTreeViewer( QTreeWidget ):
453
+ # # s_labelMaxLength = 40
454
+ # #
455
+ # # def __init__( self, dir: Directory, select_hook = None, label_max_length = -1, expand = False, **kwargs ):
456
+ # # super().__init__()
457
+ # # if label_max_length < 0:
458
+ # # label_max_length = self.s_labelMaxLength
459
+ # #
460
+ # # self.m_dir = dir
461
+ # # self.m_selectHook = select_hook
462
+ # #
463
+ # # dir_value = dir.dir_value()
464
+ # # dir_name = dir.dir_name()
465
+ # # if dir_value and dir_name and dir_name != dir_value:
466
+ # # num_cols = 2
467
+ # # header_labels = [ dir.dir_name(), 'Description' ]
468
+ # # else:
469
+ # # num_cols = 1
470
+ # # header_labels = [ dir.show_value() ]
471
+ # #
472
+ # # self.m_numCols = num_cols
473
+ # # self.setColumnCount( num_cols )
474
+ # # self.setHeaderLabels( header_labels )
475
+ # # self.itemClicked.connect( self.typeTreeItemClicked )
476
+ # #
477
+ # # for subdir in dir.dir_members().values(): # -- without the root!
478
+ # # self.createTree( subdir, self, label_max_length, num_cols )
479
+ # #
480
+ # # if expand:
481
+ # # for i in range( self.topLevelItemCount() ):
482
+ # # top = self.topLevelItem( i )
483
+ # # top.setExpanded( True )
484
+ # #
485
+ # # self.resizeColumnToContents( 0 )
486
+ # # if num_cols == 2:
487
+ # # self.resizeColumnToContents( 1 )
488
+ # # self.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding )
489
+ # #
490
+ # # class TreeItem( QTreeWidgetItem ):
491
+ # # def __init__( self, parent_node, dir: Directory ):
492
+ # # super().__init__( parent_node )
493
+ # # self.m_dir = dir
494
+ # #
495
+ # # def dir( self ): return self.m_dir
496
+ # #
497
+ # # @classmethod
498
+ # # def createTree( cls, dir: Directory, parent_node, label_max_length: int, num_cols: int ):
499
+ # # node = cls.TreeItem( parent_node, dir )
500
+ # # show_value = dir.show_value()
501
+ # # node.setText( 0, show_value )
502
+ # # if num_cols == 2:
503
+ # # label = dir.dir_name()
504
+ # # if label and label != show_value:
505
+ # # if len( label ) > label_max_length:
506
+ # # label = label[ :label_max_length ] + '...'
507
+ # #
508
+ # # node.setText( 1, label )
509
+ # #
510
+ # # node.setToolTip( num_cols - 1, dir.dir_name() )
511
+ # #
512
+ # # for subdir in dir.dir_members().values():
513
+ # # cls.createTree( subdir, node, label_max_length, num_cols )
514
+ # #
515
+ # # def typeTreeItemClicked( self, item: QTreeWidgetItem ):
516
+ # # self.onTagSelected( item.dir() )
517
+ # #
518
+ # # def onTagSelected( self, dir: Directory ):
519
+ # # if self.m_selectHook:
520
+ # # self.m_selectHook( dir )
521
+ #
522
+ # # class UxPixmap:
523
+ # # COLOR_AUTO = Qt.ColorScheme.AutoColor
524
+ # # COLOR_DITHER = Qt.ColorScheme.ColorOnly
525
+ # # COLOR_MONO = Qt.ColorScheme.MonoOnly
526
+ # # RATIO_IGNORE = Qt.ColorScheme.IgnoreAspectRatio
527
+ # # RATIO_KEEP = Qt.ColorScheme.KeepAspectRatio
528
+ # # RATIO_KEEP_EXP = Qt.ColorScheme.KeepAspectRatioByExpanding
529
+ # #
530
+ # # s_sourceTypeMap = {
531
+ # # str: QPixmap.load,
532
+ # # bytes: QPixmap.loadFromData,
533
+ # # bytearray: QPixmap.loadFromData,
534
+ # # }
535
+ # # def __init__( self, source = None, image_format = '', color_flags = COLOR_AUTO ):
536
+ # # self.m_pixmap = QPixmap()
537
+ # # rc = self.load( source, image_format = image_format, color_flags = color_flags )
538
+ # # if not rc:
539
+ # # raise RuntimeError( rc.err() )
540
+ # #
541
+ # # def load( self, source, image_format = '', color_flags = COLOR_AUTO ) -> RC:
542
+ # # if not source:
543
+ # # return RC( True )
544
+ # #
545
+ # # method = self.s_sourceTypeMap.get( type( source ) )
546
+ # # if not method:
547
+ # # return RC( False, f'UxPixmap - unknown type of source = {type( source )}' )
548
+ # #
549
+ # # rc = method( self.m_pixmap, source, format = image_format, flags = color_flags )
550
+ # # if not rc:
551
+ # # return RC( False, f'UxPixmap - failed to initialize from source = {source}' )
552
+ # #
553
+ # # return RC( True )
554
+ # #
555
+ # # def _toData( self, array: bytearray, format = '', quality = -1 ) -> bool:
556
+ # # buffer = QBuffer( array )
557
+ # # buffer.open( QIODevice.WriteOnly )
558
+ # # return self.m_pixmap.save( buffer, format = format, quality = quality )
559
+ # #
560
+ # # s_destinationTypeMap = {
561
+ # # str: QPixmap.save,
562
+ # # bytearray: _toData,
563
+ # # }
564
+ # # def save( self, destination, color_format = '', quality = -1 ) -> RC:
565
+ # # method = self.s_destinationTypeMap.get( type( destination ) )
566
+ # # if not method:
567
+ # # return RC( False, f'UxPixmap - unknown destination type = {type( destination )}' )
568
+ # #
569
+ # # rc = method( self, destination, format = color_format, quality = quality )
570
+ # # if not rc:
571
+ # # return RC( False, f'UxPixmap - failed to save to destination = {destination}' )
572
+ # #
573
+ # # return RC( True )
574
+ # #
575
+ # # def render( self, label: QLabel, w = 0, h = 0, scaled = RATIO_IGNORE, smooth = True ):
576
+ # # transform_mode = Qt.SmoothTransformation if smooth else Qt.FastTransformation
577
+ # # pixmap = self.m_pixmap
578
+ # # if w > 0 and h > 0:
579
+ # # pixmap = pixmap.scaled( w, h, aspectRatioMode = scaled, transformMode = transform_mode )
580
+ # # label.setPixmap( pixmap )
581
+ #
582
+ # @singleton
583
+ # class UxClipBoard:
584
+ # def __init__(self):
585
+ # self.dir = {}
586
+ # self.entity = None
587
+ # self.trait_name = ''
588
+ #
589
+ # # def copy(self, tag: str, value):
590
+ # # self.dir[tag] = value
591
+ # #
592
+ # # def paste(self, tag: str):
593
+ # # return self.dir.get(tag)
594
+ # #
595
+ # # def clear(self):
596
+ # # self.dir = {}
597
+ # #
598
+ # # def default_tag( self ) -> str:
599
+ # # assert self.entity and self.trait_name, 'entity and trait name are not defined'
600
+ # #
601
+ # # cls = self.entity.__class__
602
+ # # trait = cls.trait(self.trait_name)
603
+ # # assert trait, f"{cls}: unknown trait '{self.trait_name}'"
604
+ # # #tag_label = trait.label if trait.label else self.trait_name
605
+ # # tag_label = self.trait_name
606
+ # # return f"{self.entity}: '{tag_label}'"
607
+ # #
608
+ # # def layout(self) -> QWidget:
609
+ # # w = QWidget()
610
+ # # lay = QVBoxLayout()
611
+ # # w.setLayout(lay)
612
+ # #
613
+ # # add_row = QHBoxLayout()
614
+ # # add_b = uxPushButton('Add', callback = self.onCopy)
615
+ # # self.m_addNameWidget = add_name = QLineEdit()
616
+ # # add_name.setText(self.default_tag())
617
+ # # add_row.addWidget(add_b)
618
+ # # add_row.addWidget(add_name)
619
+ # # lay.addLayout(add_row)
620
+ # #
621
+ # # lay.addWidget(uxSeparator())
622
+ # #
623
+ # # self.m_sl = sl = UxSearchableList(choices = list( self.dir.keys() ), select_hook = self.onPaste, title = 'Use Data')
624
+ # # lay.addWidget(sl)
625
+ # #
626
+ # # return w
627
+ # #
628
+ # # def popup(self, parent_widget: QWidget, entity, trait_name: str):
629
+ # # self.m_parent = parent_widget
630
+ # # self.entity = entity
631
+ # # self.trait_name = trait_name
632
+ # # self.m_d = d = UxDialog(self.layout(), parent = parent_widget, cancel = '', title = 'Copy or Paste Data')
633
+ # # d.exec()
634
+ # #
635
+ # # def onCopy(self):
636
+ # # name = self.m_addNameWidget.text()
637
+ # # if name:
638
+ # # value = self.entity.get_value( self.trait_name )
639
+ # # if value is not None:
640
+ # # self.copy( name, value )
641
+ # #
642
+ # # self.m_d.close()
643
+ # #
644
+ # # def onPaste( self, name: str ):
645
+ # # value = self.paste( name )
646
+ # # if value is not None:
647
+ # # rc = self.m_entity.setValue( self.m_traitName, value )
648
+ # # if not rc:
649
+ # # uxWarning(
650
+ # # f"Data '{name}' is not suitable for '{self.m_entity.trait( self.m_traitName ).m_label}'",
651
+ # # parent = self.m_parent,
652
+ # # title = 'Invalid Data'
653
+ # # )
654
+ # #
655
+ # # self.m_d.close()
656
+ #
657
+ # @cache
658
+ # def uxInit(style = '') -> QApplication:
659
+ # if not style:
660
+ # style = platform.system()
661
+ #
662
+ # app = QApplication([])
663
+ # app.setStyle(style)
664
+ # return app
665
+ #
ui_10x/rio/__init__.py ADDED
File without changes
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+
3
+ from ui_10x.rio.component_builder import UserSessionContext
4
+
5
+ import rio
6
+
7
+ theme = rio.Theme.from_colors(
8
+ primary_color=rio.Color.from_hex('01dffdff'),
9
+ secondary_color=rio.Color.from_hex('0083ffff'),
10
+ )
11
+
12
+
13
+ def on_session_start(session):
14
+ session.attach(UserSessionContext(host='localhost', dbname='test')) # TODO: backbone
15
+
16
+
17
+ app = rio.App(
18
+ name='ui_10x.rio.apps.examples',
19
+ description='Rio pages based on components created using ui_10x.platform_interface',
20
+ theme=theme,
21
+ on_session_start=on_session_start,
22
+ )
@@ -0,0 +1,3 @@
1
+ from .collection_editor import CollectionEditorComponent
2
+
3
+ __all__ = ['CollectionEditorComponent']
@@ -0,0 +1,15 @@
1
+ from __future__ import annotations
2
+
3
+ from ui_10x.collection_editor import Collection, CollectionEditor
4
+ from ui_10x.rio.component_builder import UserSessionContext
5
+ from ui_10x.utils import UxDialog
6
+
7
+ import rio
8
+
9
+
10
+ class CollectionEditorComponent(rio.Component):
11
+ collection_class: type = None
12
+
13
+ def build(self) -> rio.Component:
14
+ with self.session[UserSessionContext]:
15
+ return UxDialog(CollectionEditor(coll=Collection(cls=self.collection_class)).main_widget()).build(self.session)