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.
- {rinui-0.0.9.1.post1/RinUI.egg-info → rinui-0.0.10}/PKG-INFO +2 -2
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/README.md +1 -1
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/__init__.py +1 -1
- rinui-0.0.10/RinUI/__pycache__/__init__.cpython-38.pyc +0 -0
- rinui-0.0.10/RinUI/components/BasicInput/PillButton.qml +11 -0
- rinui-0.0.10/RinUI/components/BasicInput/RoundButton.qml +27 -0
- rinui-0.0.10/RinUI/components/DateAndTime/DatePicker.qml +140 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/DateAndTime/PickerView.qml +11 -4
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/MenusAndToolbars/Menu.qml +5 -3
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/MenusAndToolbars/MenuItem.qml +13 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Navigation/NavigationView.qml +3 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/StatusAndInfo/InfoBar.qml +7 -1
- rinui-0.0.10/RinUI/components/Text/TextArea.qml +146 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Text/TextField.qml +48 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/qmldir +1 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/core/__pycache__/__init__.cpython-38.pyc +0 -0
- rinui-0.0.10/RinUI/core/__pycache__/config.cpython-38.pyc +0 -0
- rinui-0.0.10/RinUI/core/__pycache__/launcher.cpython-38.pyc +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/core/config.py +11 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/core/launcher.py +18 -18
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/qmldir +5 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/themes/utils.qml +5 -1
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/FluentWindowBase.qml +6 -6
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/TitleBar.qml +4 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/window/ApplicationWindow.qml +1 -1
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/window/Window.qml +7 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10/RinUI.egg-info}/PKG-INFO +2 -2
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI.egg-info/SOURCES.txt +3 -1
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/pyproject.toml +1 -1
- rinui-0.0.9.1.post1/RinUI/__pycache__/__init__.cpython-38.pyc +0 -0
- rinui-0.0.9.1.post1/RinUI/components/DateAndTime/DatePicker.qml +0 -115
- rinui-0.0.9.1.post1/RinUI/components/Utils/Blur.qml +0 -42
- rinui-0.0.9.1.post1/RinUI/core/__pycache__/config.cpython-38.pyc +0 -0
- rinui-0.0.9.1.post1/RinUI/core/__pycache__/launcher.cpython-38.pyc +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/LICENSE +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/MANIFEST.in +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/assets/fonts/FluentSystemIcons-Index.js +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/assets/fonts/FluentSystemIcons-Resizable.ttf +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/assets/img/default_app_icon.png +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Base.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/Button.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/CheckBox.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/ComboBox.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/DropDownButton.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/Hyperlink.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/RadioButton.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/Slider.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/Switch.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/ToggleButton.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/BasicInput/ToolButton.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ContextMenu.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/DateAndTime/TimePicker.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/DialogsAndFlyouts/Dialog.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/DialogsAndFlyouts/DialogButtonBox.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/DialogsAndFlyouts/Flyout.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/DialogsAndFlyouts/Popup.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/FocusIndicator.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/IconWidget.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Indicator.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Layout/Expander.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Layout/SettingExpander.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Layout/SettingItem.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/Clip.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/Frame.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/ListView.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/ListViewDelegate.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/SettingCard.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/TableView.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ListAndCollections/TableViewDelegate.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/MenusAndToolbars/MenuBar.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/MenusAndToolbars/MenuItemGroup.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/MenusAndToolbars/MenuSeparator.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/MenusAndToolbars/ToolSeparator.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Navigation/ErrorPage.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Navigation/NavigationBar.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Navigation/NavigationItem.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Navigation/NavigationSubItem.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Navigation/SelectorBar.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ScrollBar.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/ScrollView.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Shadow.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/StatusAndInfo/InfoBadge.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/StatusAndInfo/ProgressBar.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/StatusAndInfo/Toast.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/StatusAndInfo/ToolTip.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Text/SpinBox.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Text/Text.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/components/Text/TextInput.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/config/rin_ui.json +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/core/__init__.py +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/core/__pycache__/theme.cpython-38.pyc +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/core/theme.py +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/hooks/__init__.py +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/hooks/hook-RinUI.py +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/themes/dark.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/themes/light.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/themes/qmldir +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/themes/theme.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/Animation.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/FloatLayer.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/FontIconLoader.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/Position.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/Severity.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/Typography.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/utils/qmldir +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/CtrlBtn.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/FluentPage.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/FluentWindow.qml +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI/windows/qmldir +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI.egg-info/dependency_links.txt +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI.egg-info/entry_points.txt +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI.egg-info/requires.txt +0 -0
- {rinui-0.0.9.1.post1 → rinui-0.0.10}/RinUI.egg-info/top_level.txt +0 -0
- {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.
|
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:
|
56
|
+
You can install RinUI via pip:
|
57
57
|
```bash
|
58
58
|
pip install RinUI
|
59
59
|
```
|
Binary file
|
@@ -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
|
-
|
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 =
|
28
|
-
return data.toString().length < 2 && count
|
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:
|
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: (
|
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
|
Binary file
|
Binary file
|
Binary file
|
@@ -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
|
-
|
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.
|