RinUI 0.0.9.1.post1__tar.gz → 0.0.10__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 (114) hide show
  1. {rinui-0.0.9.1.post1/RinUI.egg-info → rinui-0.0.10}/PKG-INFO +2 -2
  2. {rinui-0.0.9.1.post1 → rinui-0.0.10}/README.md +1 -1
  3. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/__init__.py +1 -1
  4. rinui-0.0.10/RinUI/__pycache__/__init__.cpython-38.pyc +0 -0
  5. rinui-0.0.10/RinUI/components/BasicInput/PillButton.qml +11 -0
  6. rinui-0.0.10/RinUI/components/BasicInput/RoundButton.qml +27 -0
  7. rinui-0.0.10/RinUI/components/DateAndTime/DatePicker.qml +140 -0
  8. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/DateAndTime/PickerView.qml +11 -4
  9. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/MenusAndToolbars/Menu.qml +5 -3
  10. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/MenusAndToolbars/MenuItem.qml +13 -0
  11. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Navigation/NavigationView.qml +3 -0
  12. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/StatusAndInfo/InfoBar.qml +7 -1
  13. rinui-0.0.10/RinUI/components/Text/TextArea.qml +146 -0
  14. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Text/TextField.qml +48 -0
  15. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/qmldir +1 -0
  16. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/core/__pycache__/__init__.cpython-38.pyc +0 -0
  17. rinui-0.0.10/RinUI/core/__pycache__/config.cpython-38.pyc +0 -0
  18. rinui-0.0.10/RinUI/core/__pycache__/launcher.cpython-38.pyc +0 -0
  19. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/core/config.py +11 -0
  20. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/core/launcher.py +18 -18
  21. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/qmldir +5 -0
  22. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/themes/utils.qml +5 -1
  23. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/FluentWindowBase.qml +6 -6
  24. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/TitleBar.qml +4 -0
  25. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/window/ApplicationWindow.qml +1 -1
  26. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/window/Window.qml +7 -0
  27. {rinui-0.0.9.1.post1 → rinui-0.0.10/RinUI.egg-info}/PKG-INFO +2 -2
  28. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI.egg-info/SOURCES.txt +3 -1
  29. {rinui-0.0.9.1.post1 → rinui-0.0.10}/pyproject.toml +1 -1
  30. rinui-0.0.9.1.post1/RinUI/__pycache__/__init__.cpython-38.pyc +0 -0
  31. rinui-0.0.9.1.post1/RinUI/components/DateAndTime/DatePicker.qml +0 -115
  32. rinui-0.0.9.1.post1/RinUI/components/Utils/Blur.qml +0 -42
  33. rinui-0.0.9.1.post1/RinUI/core/__pycache__/config.cpython-38.pyc +0 -0
  34. rinui-0.0.9.1.post1/RinUI/core/__pycache__/launcher.cpython-38.pyc +0 -0
  35. {rinui-0.0.9.1.post1 → rinui-0.0.10}/LICENSE +0 -0
  36. {rinui-0.0.9.1.post1 → rinui-0.0.10}/MANIFEST.in +0 -0
  37. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/assets/fonts/FluentSystemIcons-Index.js +0 -0
  38. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/assets/fonts/FluentSystemIcons-Resizable.ttf +0 -0
  39. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/assets/img/default_app_icon.png +0 -0
  40. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Base.qml +0 -0
  41. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/Button.qml +0 -0
  42. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/CheckBox.qml +0 -0
  43. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/ComboBox.qml +0 -0
  44. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/DropDownButton.qml +0 -0
  45. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/Hyperlink.qml +0 -0
  46. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/RadioButton.qml +0 -0
  47. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/Slider.qml +0 -0
  48. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/Switch.qml +0 -0
  49. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/ToggleButton.qml +0 -0
  50. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/ToolButton.qml +0 -0
  51. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ContextMenu.qml +0 -0
  52. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/DateAndTime/TimePicker.qml +0 -0
  53. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/DialogsAndFlyouts/Dialog.qml +0 -0
  54. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/DialogsAndFlyouts/DialogButtonBox.qml +0 -0
  55. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/DialogsAndFlyouts/Flyout.qml +0 -0
  56. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/DialogsAndFlyouts/Popup.qml +0 -0
  57. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/FocusIndicator.qml +0 -0
  58. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/IconWidget.qml +0 -0
  59. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Indicator.qml +0 -0
  60. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Layout/Expander.qml +0 -0
  61. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Layout/SettingExpander.qml +0 -0
  62. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Layout/SettingItem.qml +0 -0
  63. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/Clip.qml +0 -0
  64. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/Frame.qml +0 -0
  65. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/ListView.qml +0 -0
  66. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/ListViewDelegate.qml +0 -0
  67. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/SettingCard.qml +0 -0
  68. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/TableView.qml +0 -0
  69. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/TableViewDelegate.qml +0 -0
  70. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/MenusAndToolbars/MenuBar.qml +0 -0
  71. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/MenusAndToolbars/MenuItemGroup.qml +0 -0
  72. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/MenusAndToolbars/MenuSeparator.qml +0 -0
  73. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/MenusAndToolbars/ToolSeparator.qml +0 -0
  74. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Navigation/ErrorPage.qml +0 -0
  75. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Navigation/NavigationBar.qml +0 -0
  76. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Navigation/NavigationItem.qml +0 -0
  77. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Navigation/NavigationSubItem.qml +0 -0
  78. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Navigation/SelectorBar.qml +0 -0
  79. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ScrollBar.qml +0 -0
  80. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ScrollView.qml +0 -0
  81. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Shadow.qml +0 -0
  82. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/StatusAndInfo/InfoBadge.qml +0 -0
  83. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/StatusAndInfo/ProgressBar.qml +0 -0
  84. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/StatusAndInfo/Toast.qml +0 -0
  85. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/StatusAndInfo/ToolTip.qml +0 -0
  86. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Text/SpinBox.qml +0 -0
  87. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Text/Text.qml +0 -0
  88. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Text/TextInput.qml +0 -0
  89. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/config/rin_ui.json +0 -0
  90. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/core/__init__.py +0 -0
  91. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/core/__pycache__/theme.cpython-38.pyc +0 -0
  92. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/core/theme.py +0 -0
  93. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/hooks/__init__.py +0 -0
  94. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/hooks/hook-RinUI.py +0 -0
  95. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/themes/dark.qml +0 -0
  96. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/themes/light.qml +0 -0
  97. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/themes/qmldir +0 -0
  98. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/themes/theme.qml +0 -0
  99. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/Animation.qml +0 -0
  100. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/FloatLayer.qml +0 -0
  101. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/FontIconLoader.qml +0 -0
  102. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/Position.qml +0 -0
  103. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/Severity.qml +0 -0
  104. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/Typography.qml +0 -0
  105. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/qmldir +0 -0
  106. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/CtrlBtn.qml +0 -0
  107. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/FluentPage.qml +0 -0
  108. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/FluentWindow.qml +0 -0
  109. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/qmldir +0 -0
  110. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI.egg-info/dependency_links.txt +0 -0
  111. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI.egg-info/entry_points.txt +0 -0
  112. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI.egg-info/requires.txt +0 -0
  113. {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI.egg-info/top_level.txt +0 -0
  114. {rinui-0.0.9.1.post1 → rinui-0.0.10}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: RinUI
3
- Version: 0.0.9.1.post1
3
+ Version: 0.0.10
4
4
  Summary: A Fluent Design-like UI library for Qt Quick (QML) based on PySide6
5
5
  Author-email: RinLit <lintu233_qwq@icloud.com>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -53,7 +53,7 @@ With simple configuration, you can quickly develop elegant UI interfaces in the
53
53
 
54
54
  ## 🪄 Usage
55
55
 
56
- You can install RinUI via pip: (coming soon, but now you can install via test-pypi)
56
+ You can install RinUI via pip:
57
57
  ```bash
58
58
  pip install RinUI
59
59
  ```
@@ -38,7 +38,7 @@ With simple configuration, you can quickly develop elegant UI interfaces in the
38
38
 
39
39
  ## 🪄 Usage
40
40
 
41
- You can install RinUI via pip: (coming soon, but now you can install via test-pypi)
41
+ You can install RinUI via pip:
42
42
  ```bash
43
43
  pip install RinUI
44
44
  ```
@@ -1,4 +1,4 @@
1
1
  from .core import *
2
2
 
3
- __version__ = "0.0.9.1"
3
+ __version__ = "0.0.10"
4
4
  __author__ = "RinLit"
@@ -0,0 +1,11 @@
1
+ import QtQuick 2.15
2
+ import QtQuick.Controls.Basic 2.15
3
+ import QtQuick.Layouts 2.15
4
+ import "../../themes"
5
+ import "../../components"
6
+
7
+ RoundButton {
8
+ id: root
9
+ highlighted: checked
10
+ checkable: true
11
+ }
@@ -0,0 +1,27 @@
1
+ import QtQuick 2.15
2
+ import QtQuick.Controls.Basic 2.15
3
+ import QtQuick.Layouts 2.15
4
+ import Qt5Compat.GraphicalEffects
5
+ import "../../themes"
6
+ import "../../components"
7
+
8
+ Button {
9
+ id: root
10
+ property alias radius: background.radius
11
+ backgroundColor: highlighted ? primaryColor : Theme.currentTheme.colors.controlQuaternaryColor
12
+
13
+ background: Rectangle {
14
+ id: background
15
+ anchors.fill: parent
16
+ color: hovered ? hoverColor : backgroundColor
17
+ radius: height / 2
18
+
19
+ border.width: Theme.currentTheme.appearance.borderWidth // 边框宽度 / Border Width
20
+ border.color: flat ? "transparent" :
21
+ enabled ? highlighted ? primaryColor : Theme.currentTheme.colors.controlBorderColor :
22
+ highlighted ? Theme.currentTheme.colors.disabledColor : Theme.currentTheme.colors.controlBorderColor
23
+
24
+ Behavior on color { ColorAnimation { duration: Utils.appearanceSpeed; easing.type: Easing.OutQuart } }
25
+ opacity: flat && !hovered || !hoverable ? 0 : 1
26
+ }
27
+ }
@@ -0,0 +1,140 @@
1
+ import QtQuick 2.15
2
+ import QtQuick.Controls.Basic 2.15
3
+ import QtQuick.Layouts 2.15
4
+ import "../../themes"
5
+ import "../../components"
6
+
7
+ Button {
8
+ id: datePickerButton
9
+
10
+ property bool yearVisible: true
11
+
12
+ property alias year: pickerView.value3
13
+ property alias month: pickerView.value1
14
+ property alias monthIndex: pickerView.index1
15
+ property alias day: pickerView.value2
16
+
17
+ property int startYear: 1925
18
+ property int endYear: 2125
19
+
20
+ readonly property var monthModel: (new Array(12)).fill(0).map((_, i) => i + 1).map(getMonthName)
21
+ readonly property int maxDays: new Date(pickerView.value3 || new Date().getFullYear(), pickerView.index1 + 1, 0).getDate()
22
+
23
+ implicitWidth: 250
24
+ padding: 0
25
+
26
+ property string date: {
27
+ if (!pickerView.gotData) return ""
28
+ let y = typeof year === "number"? parseInt(year) : new Date().getFullYear()
29
+ let m = parseInt(monthModel.indexOf(month) + 1)
30
+ let d = parseInt(day)
31
+ return y + "-" + m + "-" + d
32
+ }
33
+
34
+ function setDate(yyyymmdd) {
35
+ // format
36
+ if (!yyyymmdd || typeof yyyymmdd !== "string"
37
+ || !yyyymmdd.match(/^\d{4}[-\/]\d{1,2}[-\/]\d{1,2}$/))
38
+ return false
39
+ let parts = yyyymmdd.split(/[-\/]/) // 使用正则分割符号 '-' 或 '/'
40
+ let y = parseInt(parts[0])
41
+ let m = parseInt(parts[1])
42
+ let d = parseInt(parts[2])
43
+
44
+ if (m >= 1 && m <= 12 && d >= 1 && d <= 31) {
45
+ pickerView.value3 = y.toString()
46
+ pickerView.value1 = getMonthName(m)
47
+ pickerView.value2 = d.toString()
48
+ pickerView.gotData = true
49
+ return true
50
+ }
51
+ return -1
52
+ }
53
+
54
+ // 根据 locale 决定顺序
55
+ property var dateOrder: {
56
+ let fmt = Qt.locale().dateFormat(Locale.ShortFormat)
57
+ let order = []
58
+ if (fmt.indexOf("y") < fmt.indexOf("M") && fmt.indexOf("M") < fmt.indexOf("d"))
59
+ order = ["year", "month", "day"]
60
+ else if (fmt.indexOf("M") < fmt.indexOf("d") && fmt.indexOf("d") < fmt.indexOf("y"))
61
+ order = ["month", "day", "year"]
62
+ else if (fmt.indexOf("d") < fmt.indexOf("M") && fmt.indexOf("M") < fmt.indexOf("y"))
63
+ order = ["day", "month", "year"]
64
+
65
+ if (!yearVisible) {
66
+ order = order.filter(item => item !== "year")
67
+ }
68
+ return order
69
+ }
70
+
71
+ // locale获取月份名称
72
+ function getMonthName(num) {
73
+ return datePicker.locale.monthName(num - 1)
74
+ }
75
+
76
+ onClicked: pickerView.open()
77
+
78
+ contentItem: RowLayout {
79
+ anchors.fill: parent
80
+ spacing: 0
81
+
82
+ Repeater {
83
+ model: dateOrder
84
+
85
+ delegate: Item {
86
+ Layout.fillWidth: true
87
+ Layout.maximumWidth: datePickerButton.implicitWidth / model.length
88
+ implicitHeight: 32
89
+
90
+ Text {
91
+ anchors.centerIn: parent
92
+ color: pickerView.gotData ? Theme.currentTheme.colors.textColor
93
+ : Theme.currentTheme.colors.textSecondaryColor
94
+
95
+ text: {
96
+ const type = modelData
97
+ if (!pickerView.gotData) {
98
+ if (type === "year") return qsTr("year")
99
+ if (type === "month") return qsTr("month")
100
+ if (type === "day") return qsTr("day")
101
+ }
102
+ if (type === "year") return year
103
+ if (type === "month") return month
104
+ if (type === "day") return day
105
+ return ""
106
+ }
107
+ }
108
+ ToolSeparator {
109
+ anchors.right: parent.right
110
+ anchors.verticalCenter: parent.verticalCenter
111
+ implicitHeight: parent.implicitHeight
112
+ visible: index !== dateOrder.length - 1
113
+ }
114
+ }
115
+ }
116
+ }
117
+
118
+ PickerView {
119
+ id: pickerView
120
+ width: parent.width
121
+
122
+ model3: yearVisible
123
+ ? (
124
+ startYear <= endYear
125
+ ? Array.apply(null, {length: endYear - startYear + 1}).map((_, i) => startYear + i)
126
+ : []
127
+ )
128
+ : undefined
129
+ model1: monthModel
130
+ model2: Array.from({ length: maxDays }, (_, i) => i + 1) // 天
131
+
132
+ // 初始值
133
+ value3: yearVisible ? (new Date().getFullYear()) : undefined
134
+ value1: getMonthName(new Date().getMonth() + 1)
135
+ value2: new Date().getDate()
136
+ gotData: false
137
+
138
+ onValueChanged: gotData = true
139
+ }
140
+ }
@@ -17,15 +17,21 @@ Popup {
17
17
  property var value2: undefined
18
18
  property var value3: undefined
19
19
 
20
+ property alias index1: hours.currentIndex
21
+ property alias index2: minutes.currentIndex
22
+ property alias index3: added.currentIndex
23
+
20
24
  property var model1: 12
21
25
  property var model2: 60
22
26
  property var model3: [qsTr("AM"), qsTr("PM")]
23
27
 
24
- readonly property bool gotData: typeof value1!== "undefined" && typeof value2!== "undefined"
28
+ property bool gotData: typeof value1!== "undefined" && typeof value2!== "undefined"
29
+
30
+ signal valueChanged(var value1, var value2, var value3)
25
31
 
26
32
  function formatText(count, modelData) {
27
- let data = count === 60 ? modelData : modelData;
28
- return data.toString().length < 2 && count !== 12 ? "0" + data
33
+ let data = modelData;
34
+ return data.toString().length < 2 && count === 60 ? "0" + data
29
35
  : data === 0 && count === 12 ? 12 : data
30
36
  }
31
37
 
@@ -136,6 +142,7 @@ Popup {
136
142
  value1 = hours.currentItem.text
137
143
  value2 = minutes.currentItem.text
138
144
  typeof model3 !== "undefined" ? value3 = added.currentItem.text : undefined
145
+ valueChanged(value1, value2, value3)
139
146
  root.close()
140
147
  }
141
148
  }
@@ -184,7 +191,7 @@ Popup {
184
191
  )
185
192
  added.positionViewAtIndex(
186
193
  typeof value3 === "undefined" ? 0
187
- : typeof model3 === "number" ? value3 : model3.indexOf(value3), Tumbler.Center
194
+ : typeof model3 === "number" ? value3 : model3.indexOf(parseInt(value3)), Tumbler.Center
188
195
  )
189
196
  }
190
197
  }
@@ -19,7 +19,8 @@ Menu {
19
19
  case Position.Right:
20
20
  return parent.width + 5
21
21
  default:
22
- return (parent.width - root.width) / 2
22
+ // return (parent.width - root.width) / 2
23
+ return root.x
23
24
  }
24
25
  }
25
26
 
@@ -33,7 +34,8 @@ Menu {
33
34
  case Position.Right:
34
35
  return (parent.height - root.height) / 2
35
36
  default:
36
- return -root.height + 5 // 默认顶部
37
+ // return -root.height + 5 // 默认顶部
38
+ return root.y
37
39
  }
38
40
  }
39
41
 
@@ -49,7 +51,7 @@ Menu {
49
51
  property: "opacity"
50
52
  from: 0
51
53
  to: 1
52
- duration: 70
54
+ duration: Utils.animationSpeed
53
55
  easing.type: Easing.InOutQuart
54
56
  }
55
57
  NumberAnimation {
@@ -116,4 +116,17 @@ MenuItem {
116
116
 
117
117
  Behavior on color { ColorAnimation { duration: Utils.animationSpeed; easing.type: Easing.OutQuart } }
118
118
  }
119
+
120
+ // States //
121
+ // 状态变化
122
+ states: [
123
+ State {
124
+ name: "disabled"
125
+ when: !enabled
126
+ PropertyChanges {
127
+ target: root
128
+ opacity: 0.3628
129
+ }
130
+ }
131
+ ]
119
132
  }
@@ -18,6 +18,8 @@ RowLayout {
18
18
  property int pushEnterFromY: height
19
19
  property var window: parent // 窗口对象
20
20
 
21
+ signal pageChanged() // 页面切换信号
22
+
21
23
  id: navigationView
22
24
  anchors.fill: parent
23
25
 
@@ -195,6 +197,7 @@ RowLayout {
195
197
  navigationBar.lastPages.push(navigationBar.currentPage) // 记录当前页面
196
198
  navigationBar.lastPages = navigationBar.lastPages // refresh
197
199
  navigationBar.currentPage = page.toString()
200
+ pageChanged()
198
201
 
199
202
  if (page instanceof Component) {
200
203
  // let obj = page.createObject(stackView)
@@ -118,7 +118,13 @@ Frame {
118
118
  }
119
119
  Text {
120
120
  id: bodyText
121
- property bool wrap: (parent.width - titleText.width - custom.width - 24) < implicitWidth
121
+ property bool wrap: (
122
+ (
123
+ infoBar.width - iconWidget.width - rights.width - main.spacing * 2 - infoBar.padding * 2
124
+ - (titleText.width + custom.width + 24)
125
+ )
126
+ < implicitWidth
127
+ )
122
128
  width: wrap ?
123
129
  parent.width : implicitWidth
124
130
  typography: Typography.Body
@@ -0,0 +1,146 @@
1
+ import QtQuick 2.15
2
+ import Qt5Compat.GraphicalEffects
3
+ import QtQuick.Controls.Basic 2.15
4
+ import "../../themes"
5
+ import "../../components"
6
+
7
+ TextArea {
8
+ id: root
9
+
10
+ property bool frameless: false
11
+ property bool editable: true
12
+ property color primaryColor: Theme.currentTheme.colors.primaryColor
13
+
14
+ selectByMouse: true
15
+ enabled: editable
16
+
17
+ // Menu
18
+ Menu {
19
+ id: contextMenu
20
+ position: -1
21
+ Action {
22
+ icon.name: "ic_fluent_cut_20_regular"
23
+ text: qsTr("Cut")
24
+ enabled: root.selectedText.length > 0 && root.editable // 选中&可编辑
25
+ shortcut: "Ctrl+X"
26
+ onTriggered: root.cut()
27
+ }
28
+ Action {
29
+ icon.name: "ic_fluent_copy_20_regular"
30
+ text: qsTr("Copy")
31
+ enabled: root.selectedText.length > 0 // 选中内容
32
+ shortcut: "Ctrl+C"
33
+ onTriggered: root.copy()
34
+ }
35
+ Action {
36
+ icon.name: "ic_fluent_clipboard_paste_20_regular"
37
+ text: qsTr("Paste")
38
+ enabled: root.editable
39
+ shortcut: "Ctrl+V"
40
+ onTriggered: root.paste()
41
+ }
42
+ Action {
43
+ icon.name: " "
44
+ text: qsTr("Select All")
45
+ shortcut: "Ctrl+A"
46
+ onTriggered: root.selectAll()
47
+ }
48
+ }
49
+
50
+ MouseArea {
51
+ anchors.fill: parent
52
+ acceptedButtons: Qt.RightButton
53
+ propagateComposedEvents: true
54
+ onPressed: (mouse) => {
55
+ if (mouse.button === Qt.RightButton)
56
+ contextMenu.popup(mouse.scenePosition)
57
+ mouse.accepted = false
58
+ }
59
+
60
+ // 鼠标
61
+ cursorShape: Qt.IBeamCursor
62
+ }
63
+
64
+ // 背景 / Background //
65
+ background: Rectangle {
66
+ id: background
67
+ anchors.fill: parent
68
+ radius: Theme.currentTheme.appearance.buttonRadius
69
+ color: frameless ? "transparent" : Theme.currentTheme.colors.controlColor
70
+ clip: true
71
+ border.width: Theme.currentTheme.appearance.borderWidth
72
+ border.color: frameless ? root.activeFocus ? Theme.currentTheme.colors.controlBorderColor : "transparent" :
73
+ Theme.currentTheme.colors.controlBorderColor
74
+
75
+ layer.enabled: true
76
+ layer.smooth: true
77
+ layer.effect: OpacityMask {
78
+ maskSource: Rectangle {
79
+ width: background.width
80
+ height: background.height
81
+ radius: background.radius
82
+ }
83
+ }
84
+
85
+ // 底部指示器 / indicator //
86
+ Rectangle {
87
+ id: indicator
88
+ width: parent.width
89
+ anchors.horizontalCenter: parent.horizontalCenter
90
+ anchors.bottom: parent.bottom
91
+ radius: 999
92
+ height: root.activeFocus ? Theme.currentTheme.appearance.borderWidth * 2 : Theme.currentTheme.appearance.borderWidth
93
+ color: root.activeFocus ? primaryColor : frameless ? "transparent" : Theme.currentTheme.colors.textControlBorderColor
94
+
95
+ Behavior on color { ColorAnimation { duration: Utils.animationSpeed; easing.type: Easing.OutQuint } }
96
+ Behavior on height { NumberAnimation { duration: Utils.animationSpeed; easing.type: Easing.OutQuint } }
97
+ }
98
+ }
99
+
100
+ Behavior on opacity { NumberAnimation { duration: Utils.animationSpeed; easing.type: Easing.OutQuint } }
101
+
102
+
103
+ // 字体 / Font //
104
+ font.pixelSize: Theme.currentTheme.typography.bodySize
105
+
106
+ wrapMode: Text.WordWrap // 自动换行
107
+ selectionColor: Theme.currentTheme.colors.primaryColor
108
+ color: Theme.currentTheme.colors.textColor
109
+ placeholderTextColor: Theme.currentTheme.colors.textSecondaryColor
110
+
111
+ leftPadding: 12
112
+ rightPadding: 12
113
+ topPadding: 5
114
+ bottomPadding: 7
115
+
116
+ // 动画 / Animation //
117
+ Behavior on implicitHeight { NumberAnimation { duration: Utils.animationSpeed; easing.type: Easing.OutQuint } }
118
+
119
+ // 状态
120
+ states: [
121
+ State {
122
+ name: "disabled"
123
+ when: !enabled
124
+ PropertyChanges { // 禁用时禁止改变属性
125
+ target: root;
126
+ opacity: !editable ? 1 : 0.4
127
+ }
128
+ },
129
+ State {
130
+ name: "pressed&focused"
131
+ when: activeFocus
132
+ PropertyChanges {
133
+ target: background;
134
+ color: Theme.currentTheme.colors.controlInputActiveColor
135
+ }
136
+ },
137
+ State {
138
+ name: "hovered"
139
+ when: hovered
140
+ PropertyChanges {
141
+ target: background;
142
+ color: Theme.currentTheme.colors.controlSecondaryColor
143
+ }
144
+ }
145
+ ]
146
+ }
@@ -2,6 +2,7 @@ import QtQuick 2.15
2
2
  import Qt5Compat.GraphicalEffects
3
3
  import QtQuick.Controls.Basic 2.15
4
4
  import "../../themes"
5
+ import "../../components"
5
6
 
6
7
  TextField {
7
8
  id: root
@@ -13,6 +14,53 @@ TextField {
13
14
  selectByMouse: true
14
15
  enabled: editable
15
16
 
17
+ // Menu
18
+ Menu {
19
+ id: contextMenu
20
+ position: -1
21
+ Action {
22
+ icon.name: "ic_fluent_cut_20_regular"
23
+ text: qsTr("Cut")
24
+ enabled: root.selectedText.length > 0 && root.editable // 选中&可编辑
25
+ shortcut: "Ctrl+X"
26
+ onTriggered: root.cut()
27
+ }
28
+ Action {
29
+ icon.name: "ic_fluent_copy_20_regular"
30
+ text: qsTr("Copy")
31
+ enabled: root.selectedText.length > 0 // 选中内容
32
+ shortcut: "Ctrl+C"
33
+ onTriggered: root.copy()
34
+ }
35
+ Action {
36
+ icon.name: "ic_fluent_clipboard_paste_20_regular"
37
+ text: qsTr("Paste")
38
+ enabled: root.editable
39
+ shortcut: "Ctrl+V"
40
+ onTriggered: root.paste()
41
+ }
42
+ Action {
43
+ icon.name: " "
44
+ text: qsTr("Select All")
45
+ shortcut: "Ctrl+A"
46
+ onTriggered: root.selectAll()
47
+ }
48
+ }
49
+
50
+ MouseArea {
51
+ anchors.fill: parent
52
+ acceptedButtons: Qt.RightButton
53
+ propagateComposedEvents: true
54
+ onPressed: (mouse) => {
55
+ if (mouse.button === Qt.RightButton)
56
+ contextMenu.popup(mouse.scenePosition)
57
+ mouse.accepted = false
58
+ }
59
+
60
+ // 鼠标
61
+ cursorShape: Qt.IBeamCursor
62
+ }
63
+
16
64
  // 背景 / Background //
17
65
  background: Rectangle {
18
66
  id: background
@@ -14,6 +14,7 @@ ScrollView 1.0 ScrollView.qml
14
14
 
15
15
  # Basic Input
16
16
  Button 1.0 BasicInput/Button.qml
17
+ RoundButton 1.0 BasicInput/RoundButton.qml
17
18
  HyperlinkButton 1.0 BasicInput/HyperlinkButton.qml
18
19
  Slider 1.0 BasicInput/Slider.qml
19
20
  Hyperlink 1.0 BasicInput/Hyperlink.qml
@@ -1,6 +1,7 @@
1
1
  import os
2
2
  import json
3
3
  import platform
4
+ import sys
4
5
  from enum import Enum
5
6
 
6
7
 
@@ -22,8 +23,18 @@ def is_windows():
22
23
  return platform.system() == 'Windows'
23
24
 
24
25
 
26
+ def resource_path(relative_path):
27
+ """兼容 PyInstaller 打包和开发环境的路径"""
28
+ if hasattr(sys, '_MEIPASS'):
29
+ return os.path.join(sys._MEIPASS, relative_path)
30
+ return os.path.abspath(relative_path)
31
+
32
+
33
+ rinui_core_path = os.path.abspath(os.path.dirname(__file__)) # RinUI/core 目录
34
+
25
35
  BASE_DIR = os.path.abspath(os.getcwd())
26
36
  PATH = os.path.join(BASE_DIR, "RinUI/config")
37
+ RINUI_PATH = resource_path(os.path.join(rinui_core_path, "../../")) # 使用 resource_path 处理路径
27
38
  DEFAULT_CONFIG = {
28
39
  "language": "zh_CN",
29
40
  "theme": {
@@ -1,18 +1,12 @@
1
1
  import os
2
2
  import sys
3
3
 
4
- from PySide6.QtCore import QCoreApplication
4
+ from PySide6.QtCore import QCoreApplication, QUrl
5
+ from PySide6.QtGui import QIcon
5
6
  from PySide6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
6
7
  from PySide6.QtQml import QQmlApplicationEngine
7
8
  from .theme import ThemeManager
8
- from .config import BackdropEffect, is_windows, Theme
9
-
10
-
11
- def resource_path(relative_path):
12
- """兼容 PyInstaller 打包和开发环境的路径"""
13
- if hasattr(sys, '_MEIPASS'):
14
- return os.path.join(sys._MEIPASS, relative_path)
15
- return os.path.abspath(relative_path)
9
+ from .config import BackdropEffect, is_windows, Theme, RINUI_PATH
16
10
 
17
11
 
18
12
  class TestWindow(QWidget):
@@ -30,18 +24,12 @@ class TestWindow(QWidget):
30
24
 
31
25
 
32
26
  class RinUIWindow:
33
- # _instance = None
34
- #
35
- # def __new__(cls, *args, **kwargs): # 单例模式管理
36
- # if cls._instance is None:
37
- # cls._instance = super().__new__(cls)
38
- # return cls._instance
39
-
40
27
  def __init__(self, qml_path: str):
41
28
  """
42
29
  创建基于 RinUI 的 QML 应用程序。
43
30
  :param qml_path: str, QML 文件路径
44
31
  """
32
+ super().__init__()
45
33
  if hasattr(self, "_initialized") and self._initialized:
46
34
  return
47
35
  self._initialized = True
@@ -63,8 +51,7 @@ class RinUIWindow:
63
51
  def _setup_application(self):
64
52
  """Setup"""
65
53
  # RInUI 模块
66
- rinui_path = os.path.abspath(os.path.dirname(__file__)) # RinUI/core 目录
67
- rinui_import_path = resource_path(os.path.join(rinui_path, "../../")) # 使用 resource_path 处理路径
54
+ rinui_import_path = RINUI_PATH
68
55
  print(f"UI Module Path: {rinui_import_path}")
69
56
 
70
57
  if os.path.exists(rinui_import_path):
@@ -88,6 +75,19 @@ class RinUIWindow:
88
75
  self.theme_manager.set_window(self.root_window)
89
76
  self._apply_windows_effects() if self.autoSetWindowsEffect else None
90
77
 
78
+ def setIcon(self, path: str) -> None:
79
+ """
80
+ 设置应用程序图标。
81
+ :param path: str, 图标路径
82
+ :return:
83
+ """
84
+ app_instance = QApplication.instance()
85
+ if app_instance:
86
+ app_instance.setWindowIcon(QIcon(path)) # 设置应用程序图标
87
+ self.root_window.setProperty('icon', QUrl.fromLocalFile(path))
88
+ else:
89
+ raise RuntimeError("Cannot set icon before QApplication is created.")
90
+
91
91
  def _apply_windows_effects(self):
92
92
  """
93
93
  Apply Windows effects to the window.