├── .gitignore ├── ContentList.qml ├── InputPage.qml ├── LICENSE ├── LeftSidebar.qml ├── PageManager.qml ├── README.md ├── WindowEntry.qml ├── WindowTilte.qml ├── common ├── Backed │ ├── Backed.cpp │ ├── Backed.h │ └── Backed.pri ├── BaseButton.qml ├── BaseCheckBox.qml ├── BaseSlider.qml ├── BaseTextField.qml ├── BaseToolTip.qml ├── DropPopup.qml ├── Frameless │ ├── frameless.cpp │ ├── frameless.h │ ├── frameless.pri │ ├── frameless.pro │ └── qml.qrc ├── ImageButton.qml ├── ScaleImageButton.qml ├── Sidebar.qml ├── SkinBaseButton.qml ├── SkinBaseButton2.qml ├── SkinImageButton.qml ├── SkinModel.qml ├── SkinPopup.qml ├── YaheiText.qml ├── qmlQianDialog │ ├── BlogDialog.qml │ ├── SkinQianDialog.qml │ ├── error.png │ ├── info.png │ ├── ok.png │ └── question.png ├── qmlQianHints │ ├── Message.qml │ ├── QianQuestionMark.qml │ ├── error.png │ ├── questionMark.png │ ├── questionMarkDarker.png │ ├── remind.png │ └── true.png └── qmlQianStretchList │ ├── QianStretchDalegate.qml │ ├── QianStretchEntry.qml │ └── icons │ └── indicator_right.png ├── main.cpp ├── main.qml ├── pages ├── BaseControlPage.qml ├── BaseOtherControlPage.qml ├── HintPage.qml └── QianProjectPages │ ├── QianDragViewPage │ ├── QianDragDelegate.qml │ ├── QianDragDelegateInformation.qml │ ├── QianDragView.qml │ ├── QianDragViewPage.qml │ ├── qiandrageventcatch.cpp │ ├── qiandrageventcatch.h │ └── remove.png │ ├── QianMergeWatermelonPage │ ├── Ball.qml │ ├── BallRun.js │ ├── FinishWindow.qml │ ├── GameCanvas.qml │ ├── MergeAnimal.qml │ ├── QianMergeWatermelonPage.qml │ ├── ScoreNumber.qml │ ├── audio │ │ ├── d2cb5a4f-1334-4eab-8578-a76aa028644e.mp3 │ │ ├── down.mp3 │ │ ├── down.wav │ │ ├── finish.mp3 │ │ ├── finish.wav │ │ ├── merge1.mp3 │ │ ├── merge1.wav │ │ ├── merge2.mp3 │ │ └── merge2.wav │ ├── icon │ │ ├── 1.png │ │ ├── ball1.png │ │ ├── ball10.png │ │ ├── ball11.png │ │ ├── ball2.png │ │ ├── ball3.png │ │ ├── ball4.png │ │ ├── ball5.png │ │ ├── ball6.png │ │ ├── ball7.png │ │ ├── ball8.png │ │ ├── ball9.png │ │ ├── bottomBack.png │ │ ├── finish.png │ │ ├── merge10.png │ │ ├── merge11 - 副本.png │ │ ├── merge11.png │ │ ├── merge2.png │ │ ├── merge3.png │ │ ├── merge4.png │ │ ├── merge5.png │ │ ├── merge6.png │ │ ├── merge7.png │ │ ├── merge8.png │ │ ├── merge9.png │ │ └── number1.png │ └── 介绍.png │ └── QianPhotoPage.qml ├── preview ├── linux.png └── windwos.png ├── qianWindow.pro ├── qml.qrc └── windowRes ├── Icon.rc ├── close.png ├── close2.png ├── close_hover.png ├── icon.ico ├── icon.png ├── max.png ├── minimize.png ├── normal.png └── skin.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.pro.user 2 | *.pro.user.* 3 | *.qbs.user 4 | *.qbs.user.* 5 | *.moc 6 | moc_*.cpp 7 | moc_*.h 8 | qrc_*.cpp 9 | ui_*.h 10 | /.qmake.cache 11 | /.qmake.stash 12 | build 13 | *.user 14 | -------------------------------------------------------------------------------- /ContentList.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Layouts 1.12 3 | import QtQuick.Controls 2.14 4 | import QtCharts 2.14 5 | import QtQuick.Controls.Material 2.12 6 | import Qt.Singleton 1.0 7 | import QtGraphicalEffects 1.14 8 | import "qrc:/common" 9 | Rectangle { 10 | id: contentList 11 | 12 | color: mainColor 13 | 14 | RowLayout { 15 | anchors.fill: parent 16 | anchors.rightMargin: 14 17 | anchors.leftMargin: leftSidebar.isOpen ? 14 : 0 18 | anchors.topMargin: 14 19 | anchors.bottomMargin: 14 20 | 21 | Behavior on anchors.leftMargin { 22 | NumberAnimation { duration: 100 } 23 | } 24 | 25 | spacing: 20 26 | LeftSidebar { 27 | id: leftSidebar 28 | Layout.fillHeight: true 29 | layoutPreferredWidth: skin.gradSupport ? 175 : 198 30 | bckColor: !skin.gradSupport && !skin.imageSupport ? skin.contentBackColor: 31 | !skin.light ? Qt.rgba(0,0,0, 0.7 - setting.skinOpacity * 0.38) : Qt.rgba(1,1,1, 0.20 + setting.skinOpacity * 0.68) 32 | 33 | } 34 | 35 | Rectangle { 36 | Layout.leftMargin: -leftSidebar.tailWidth 37 | Layout.fillHeight: true 38 | Layout.fillWidth: true 39 | 40 | radius: skin.gradSupport || skin.imageSupport ? 14 : 8 41 | color: !skin.gradSupport && !skin.imageSupport ? skin.contentBackColor : 42 | !skin.light ? Qt.rgba(0,0,0, 0.7 - setting.skinOpacity * 0.38) : Qt.rgba(1,1,1, 0.10 + setting.skinOpacity * 0.88) 43 | 44 | 45 | layer.enabled: skin.shadow 46 | layer.effect: DropShadow { 47 | color: !skin.gradSupport && !skin.imageSupport ? "#36000000" : "#36FFFFFF" 48 | radius: 8 49 | samples: 17 50 | } 51 | 52 | PageManager { 53 | id: pages 54 | anchors.fill: parent 55 | 56 | 57 | } 58 | } 59 | 60 | } 61 | 62 | Connections { 63 | target: leftSidebar.stretchEntry 64 | onSwitchPage: pages.switchPage(name) 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /InputPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Layouts 1.12 3 | import QtQuick.Controls 2.14 4 | import QtQuick.Controls.Material 2.12 5 | import QtQuick.Dialogs 1.3 6 | import "qrc:/common" 7 | 8 | Item { 9 | 10 | FileDialog { 11 | id: _file 12 | title: "打开文件" 13 | selectMultiple: true 14 | selectFolder: false 15 | nameFilters: ["all files (*.png *.jpg *.mp3 *.mp4 *.avi *.wav)"] 16 | onAccepted: { 17 | for(let i = 0; i < fileUrls.length; i++) { 18 | 19 | 20 | appendFile(fileUrls[i]) 21 | } 22 | 23 | } 24 | } 25 | 26 | ListModel { 27 | id: fileModel 28 | } 29 | 30 | function appendFile(fileLocal) { 31 | 32 | let arr = fileLocal.split("/") 33 | 34 | fileModel.append({"fileLocal": fileLocal, "name":arr[arr.length-1]}) 35 | 36 | } 37 | 38 | Component { 39 | id: _contentDelegate 40 | Item { 41 | id: block 42 | width: _content.cellWidth; height: _content.cellHeight 43 | clip: true 44 | ColumnLayout { 45 | anchors.fill: parent 46 | anchors.margins: 10 47 | spacing: 6 48 | Rectangle { 49 | Layout.fillWidth: true 50 | Layout.fillHeight: true 51 | radius: 5 52 | color: "#070709" 53 | Image { 54 | anchors.fill: parent 55 | anchors.margins: 4 56 | source: fileLocal 57 | fillMode: Image.PreserveAspectCrop 58 | } 59 | } 60 | YaheiText { 61 | text: name 62 | Layout.fillWidth: true 63 | elide: Text.ElideMiddle 64 | clip: true 65 | font.pixelSize: 14 66 | color: "#888" 67 | } 68 | } 69 | MouseArea { 70 | anchors.fill: parent 71 | onClicked: { 72 | _content.currentIndex = index; 73 | } 74 | } 75 | } 76 | } 77 | 78 | 79 | ColumnLayout { 80 | visible: fileModel.count 81 | anchors.fill: parent 82 | anchors.margins: 8 83 | SkinBaseButton { 84 | onClicked: _file.open() 85 | Layout.preferredHeight: 36 86 | Layout.preferredWidth: 88 87 | backRadius: 4 88 | 89 | contentItem: Item { 90 | RowLayout { 91 | anchors.centerIn: parent 92 | Rectangle { 93 | Layout.preferredHeight: 18 94 | Layout.preferredWidth: 18 95 | radius: 9 96 | color: "#00C1CD" 97 | YaheiText { 98 | text: "+" 99 | font.pixelSize: 14 100 | anchors.centerIn: parent 101 | anchors.verticalCenterOffset: -1 102 | color: "#FFF" 103 | } 104 | } 105 | 106 | YaheiText { 107 | text: "导入" 108 | font.pixelSize: 16 109 | color: "#fff" 110 | horizontalAlignment: Text.AlignHCenter 111 | verticalAlignment: Text.AlignVCenter 112 | } 113 | 114 | } 115 | 116 | 117 | } 118 | } 119 | 120 | GridView { 121 | id: _content 122 | Layout.fillHeight: true 123 | Layout.fillWidth: true 124 | model: fileModel 125 | cellWidth: parent.width/4 126 | cellHeight: cellWidth - 20 127 | delegate: _contentDelegate 128 | clip: true 129 | currentIndex: -1 130 | highlight: Rectangle { color:"transparent"; border.width: 3; border.color: "#00C1CD"; radius: 3 } 131 | } 132 | 133 | } 134 | 135 | 136 | 137 | SkinBaseButton { 138 | visible: !fileModel.count 139 | 140 | width: 260 141 | height: 180 142 | text: "" 143 | 144 | anchors.centerIn: parent 145 | 146 | onClicked: _file.open() 147 | 148 | ColumnLayout { 149 | anchors.centerIn: parent 150 | 151 | RowLayout { 152 | Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter 153 | 154 | Rectangle { 155 | Layout.preferredHeight: 18 156 | Layout.preferredWidth: 18 157 | radius: 9 158 | 159 | color: "#00C1CD" 160 | 161 | YaheiText { 162 | text: "+" 163 | font.pixelSize: 14 164 | anchors.centerIn: parent 165 | anchors.verticalCenterOffset: -1 166 | color: "#FFF" 167 | } 168 | } 169 | 170 | YaheiText { 171 | text: "导入" 172 | font.pixelSize: 18 173 | color: "#F5F5F5" 174 | } 175 | 176 | } 177 | YaheiText { 178 | text: "视频、音频、图片" 179 | font.pixelSize: 15 180 | color: "#33ffffff" 181 | } 182 | 183 | } 184 | 185 | 186 | 187 | } 188 | 189 | 190 | 191 | } 192 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 nuoqian 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LeftSidebar.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Layouts 1.14 3 | import QtQuick.Controls.Material 2.12 4 | import QtQuick.Controls 2.14 5 | import "qrc:/common" 6 | import "qrc:/common/qmlQianStretchList" 7 | Sidebar { 8 | z:100 9 | height: parent.height 10 | horizontalPosBase: Sidebar.PosToLeft 11 | property alias stretchEntry: _stretchEntry 12 | 13 | QianStretchEntry { 14 | id: _stretchEntry 15 | anchors.fill: contentObj 16 | clip: true 17 | 18 | } 19 | 20 | 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /PageManager.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Layouts 1.12 3 | import QtQuick.Controls 2.14 4 | import "qrc:/common" 5 | import "qrc:/pages" 6 | import "qrc:/pages/QianProjectPages" 7 | import "qrc:/pages/QianProjectPages/QianMergeWatermelonPage" 8 | import "qrc:/pages/QianProjectPages/QianDragViewPage" 9 | 10 | StackLayout { 11 | id: stack 12 | clip: true 13 | function switchPage(name) { 14 | for (var i = 0; i < stack.data.length; i++) { 15 | if (stack.data[i].name == name) { 16 | stack.currentIndex = i; 17 | break; 18 | } 19 | } 20 | } 21 | 22 | BaseControlPage { 23 | property string name: "Buttons" 24 | width: stack.width 25 | height: stack.height 26 | 27 | } 28 | BaseOtherControlPage { 29 | property string name: "Other" 30 | width: stack.width 31 | height: stack.height 32 | } 33 | HintPage{ 34 | property string name: "提示" 35 | width: stack.width 36 | height: stack.height 37 | } 38 | 39 | QianPhotoPage { 40 | property string name: "图片预览器" 41 | width: stack.width 42 | height: stack.height 43 | } 44 | 45 | QianMergeWatermelonPage { 46 | property string name: "合成大西瓜" 47 | width: stack.width 48 | height: stack.height 49 | } 50 | 51 | QianDragViewPage { 52 | property string name: "DragView" 53 | width: stack.width 54 | height: stack.height 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QianWindow 2 |
使用Qt5.14.2编译 or Qt5.15一键编译 3 |
已经测试windows/linux多平台编译完成 4 |
最新版本视频地址: B站演示入口 5 | 6 | ## Linux编译部分截图 7 | ![image](preview/linux.png) 8 | 9 | ## Windows编译部分截图 10 | ![image](preview/windwos.png) 11 | -------------------------------------------------------------------------------- /WindowEntry.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtGraphicalEffects 1.12 3 | import QtQuick.Layouts 1.12 4 | import QtQuick.Controls 2.14 5 | import Qt.Singleton 1.0 6 | import "qrc:/common" 7 | import "qrc:/common/qmlQianDialog" 8 | import "qrc:/common/qmlQianHints" 9 | Rectangle { 10 | id: windowEntry 11 | 12 | color: skin.mainColor 13 | gradient: skin.gradient 14 | 15 | 16 | 17 | Message{ 18 | id:messageTip 19 | z: 1 20 | parent: Overlay.overlay 21 | } 22 | 23 | function message(type, message) { 24 | if(type!=='success'&&type!=='error'&&type!=='info'){ 25 | return false 26 | } 27 | messageTip.open(type, message) 28 | } 29 | 30 | 31 | BlogDialog { 32 | id: skinQianDialog 33 | backParent: windowEntry 34 | parent: Overlay.overlay 35 | onAccept: { 36 | message('success', "You clicked the accept button!") 37 | skinQianDialog.close(); 38 | } 39 | } 40 | 41 | Component.onCompleted: { 42 | skinQianDialog.dialogOpen() 43 | } 44 | 45 | 46 | 47 | layer.enabled: skin.windowShadow && !appStartAnimation.running && !rootWindow.maximized? true : false 48 | layer.effect: DropShadow { 49 | color: "#000000" 50 | } 51 | 52 | ColumnLayout { 53 | anchors.fill: parent 54 | spacing: 0 55 | WindowTilte { 56 | color: skin.titleColor 57 | Layout.fillWidth: true 58 | Layout.preferredHeight: contentList.fullscreen ? 0 : 42 59 | Layout.alignment: Qt.AlignTop 60 | Behavior on Layout.preferredHeight { 61 | NumberAnimation { duration: 300 } 62 | } 63 | clip: true 64 | 65 | } 66 | ContentList { 67 | id: contentList 68 | Layout.fillHeight: true 69 | Layout.fillWidth: true 70 | } 71 | } 72 | 73 | SequentialAnimation { 74 | id: appStartAnimation 75 | running: true 76 | NumberAnimation { target: windowEntry; 77 | properties: "scale"; from: 0.3; to: 1.0; easing.type: Easing.InOutQuad; duration: 200 } 78 | 79 | } 80 | 81 | 82 | 83 | } 84 | -------------------------------------------------------------------------------- /WindowTilte.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Layouts 1.12 3 | import QtQuick.Controls 2.14 4 | import QtQuick.Controls.Material 2.12 5 | import Qt.Singleton 1.0 6 | import "qrc:/common" 7 | 8 | Rectangle { 9 | id: windowtitle 10 | 11 | MouseArea { 12 | anchors.fill: parent 13 | onDoubleClicked: { 14 | scaleInput.clicked(); 15 | } 16 | } 17 | 18 | RowLayout { 19 | z: 2 20 | anchors.fill: parent 21 | anchors.leftMargin: 8 22 | anchors.margins: 0 23 | Layout.margins: 0 24 | spacing: 0 25 | 26 | 27 | Image { 28 | antialiasing: true 29 | source: "qrc:/windowRes/icon.png" 30 | Layout.preferredWidth: 30 31 | Layout.preferredHeight: 30 32 | fillMode: Image.PreserveAspectFit 33 | } 34 | 35 | YaheiText { 36 | text: rootWindow.title 37 | font.pixelSize: 17 38 | color: "#FFF" 39 | Layout.fillWidth: true 40 | Layout.leftMargin: 3 41 | } 42 | 43 | 44 | ImageButton { 45 | imageSrc: "qrc:/windowRes/skin.png" 46 | Layout.alignment: Qt.AlignTop | Qt.AlignRight 47 | backHoverColor: "#22FFFFFF" 48 | BaseToolTip { 49 | visible: parent.hovered 50 | text: "主题" 51 | font.pixelSize: 12 52 | delay: 1000 53 | 54 | } 55 | onClicked: { 56 | skin_popup.open() 57 | } 58 | padding: 3 59 | 60 | } 61 | 62 | 63 | ImageButton { 64 | imageSrc: "qrc:/windowRes/minimize.png" 65 | Layout.alignment: Qt.AlignTop | Qt.AlignRight 66 | backHoverColor: "#22FFFFFF" 67 | 68 | 69 | BaseToolTip { 70 | visible: parent.hovered 71 | text: "最小化" 72 | font.pixelSize: 12 73 | delay: 1000 74 | 75 | } 76 | onClicked: { 77 | showMinimized() 78 | } 79 | padding: 1 80 | } 81 | ScaleImageButton { 82 | id: scaleInput 83 | backHoverColor:"#22FFFFFF" 84 | normalImage: "qrc:/windowRes/normal.png" 85 | maxImage: "qrc:/windowRes/max.png" 86 | 87 | BaseToolTip { 88 | visible: parent.hovered 89 | text: scaleInput.shrink ? "最大化" : "恢复" 90 | font.pixelSize: 12 91 | delay: 1000 92 | 93 | } 94 | 95 | Layout.alignment : Qt.AlignTop | Qt.AlignRight 96 | focusPolicy: Qt.NoFocus 97 | onShrinkChanged: { 98 | rootWindow.maximized = !shrink 99 | rootWindow.update(); 100 | } 101 | padding: 3 102 | 103 | } 104 | ImageButton { 105 | imageSrc: "qrc:/windowRes/close.png" 106 | //hoverimageSrc:"qrc:/windowRes/close_hover.png" 107 | Layout.alignment: Qt.AlignTop | Qt.AlignRight 108 | backHoverColor: "#FA5151" 109 | 110 | BaseToolTip { 111 | visible: parent.hovered 112 | text: "关闭" 113 | font.pixelSize: 12 114 | delay: 1000 115 | 116 | } 117 | onClicked: rootWindow.closeFunc() 118 | padding: 3 119 | } 120 | } 121 | 122 | SkinPopup { 123 | id: skin_popup 124 | } 125 | 126 | 127 | 128 | } 129 | -------------------------------------------------------------------------------- /common/Backed/Backed.cpp: -------------------------------------------------------------------------------- 1 | #include "Backed.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | Backed* Backed::m_instance = NULL; 10 | //----------------------------------------------------------------------------- 11 | Backed::Backed( QObject *parent) 12 | : QObject(parent) 13 | { 14 | 15 | 16 | } 17 | 18 | 19 | 20 | 21 | bool Backed::saveFile(QString path, const QString& data) 22 | { 23 | 24 | 25 | QFile file(path.remove("file:///")); 26 | 27 | if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { 28 | qWarning()<<"Backed::saveFile err:"< 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace HttpApi 11 | { 12 | 13 | }; 14 | // 后端通用类,负责与后端和前端交互 15 | // 诺谦 2022-08-20 16 | class Backed : public QObject 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | 22 | Q_INVOKABLE bool saveFile(QString path, const QString& data); 23 | Q_INVOKABLE bool copyFile(QString path, QString newPath); 24 | Q_INVOKABLE QString importFile(QString path); 25 | Q_INVOKABLE bool fileExists(QString path); 26 | 27 | 28 | 29 | Backed(QObject *parent = 0); 30 | static Backed* instance() 31 | { 32 | if(m_instance==NULL) { 33 | m_instance = new Backed(); 34 | } 35 | return m_instance; 36 | } 37 | 38 | signals: 39 | // 消息提示窗口提示 40 | void errorMessage(QString msg); 41 | void successMessage(QString msg); 42 | void infoMessage(QString msg); 43 | void modalMessage(QString msg, int msec = 2000); 44 | void message(QString msg, int msec = 2000); 45 | 46 | 47 | private slots: 48 | 49 | protected: 50 | 51 | 52 | private: 53 | static Backed *m_instance; // 阻塞实例 54 | }; 55 | 56 | // 定义一个回调类指针,用于接收回调. 57 | static QObject *Backed_qobject_provider(QQmlEngine *engine, QJSEngine *scriptEngine) 58 | { 59 | //Q_UNUSED: 向编译器指示参数未在函数的主体中使用。这可用于抑制编译器警告 60 | Q_UNUSED(engine) 61 | Q_UNUSED(scriptEngine) 62 | 63 | return Backed::instance(); 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /common/Backed/Backed.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | DEPENDPATH += $$PWD 3 | 4 | 5 | HEADERS += $$PWD/Backed.h \ 6 | 7 | SOURCES += $$PWD/Backed.cpp \ 8 | -------------------------------------------------------------------------------- /common/BaseButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.5 3 | import QtGraphicalEffects 1.12 4 | Button { 5 | id: container 6 | property string bckcolor: "#1AAD19" 7 | property string bckHoverColor: Qt.lighter(bckcolor, 0.8) 8 | property int backRadius: 2 9 | 10 | font.family: "Microsoft Yahei" 11 | font.pixelSize: 20 12 | implicitWidth: text.contentWidth + 24 13 | implicitHeight: text.contentHeight + 8 14 | contentItem: Text { 15 | id: text 16 | text: container.text 17 | font: container.font 18 | color: "#fff" 19 | horizontalAlignment: Text.AlignHCenter 20 | verticalAlignment: Text.AlignVCenter 21 | } 22 | background: Rectangle { 23 | anchors.fill: parent 24 | radius: backRadius 25 | color: container.down ? bckcolor : 26 | container.hovered ? bckHoverColor : bckcolor 27 | 28 | layer.enabled: true 29 | layer.effect: DropShadow { 30 | color: bckcolor 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /common/BaseCheckBox.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.5 3 | import QtQuick.Controls.Material 2.12 4 | CheckBox { 5 | indicator.width: 18 6 | indicator.height: 18 7 | font.family: "Microsoft Yahei" 8 | Material.accent: accentContrlColor 9 | 10 | } 11 | -------------------------------------------------------------------------------- /common/BaseSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.5 3 | import QtGraphicalEffects 1.12 4 | Slider { 5 | id: _slider 6 | anchors.verticalCenter: parent.verticalCenter 7 | background: Rectangle { 8 | x: _slider.leftPadding 9 | y: _slider.topPadding + _slider.availableHeight / 2 - height / 2 10 | implicitWidth: 120 11 | implicitHeight: 5 12 | width: _slider.availableWidth 13 | height: implicitHeight 14 | radius: 2 15 | color: "#bdbebf" 16 | gradient: Gradient { 17 | orientation: Gradient.Horizontal; 18 | GradientStop { position: 0.0; color: accentContrlColor } 19 | GradientStop { position: 1.0; color: "#FFFFFF" } 20 | 21 | } 22 | } 23 | 24 | handle: Rectangle { 25 | x: _slider.leftPadding + _slider.visualPosition * (_slider.availableWidth - width) 26 | y: _slider.topPadding + _slider.availableHeight / 2 - height / 2 27 | implicitWidth: 14 28 | implicitHeight: 14 29 | radius: 7 30 | color: "#FFF" 31 | layer.enabled: true 32 | layer.effect: DropShadow { 33 | color: accentContrlColor 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /common/BaseTextField.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.5 3 | import QtQuick.Controls.Material 2.12 4 | TextField { 5 | id: textfield 6 | selectByMouse: true 7 | font.family: "Microsoft Yahei" 8 | font.pixelSize: 16 9 | property color backColor: skin.light ? "#77FFFFFF" : "11000000" 10 | property color focusColor: Material.accent 11 | property color normalColor: Material.foreground 12 | 13 | topPadding: 3 14 | bottomPadding: 3 15 | leftPadding: 2 16 | rightPadding: 2 17 | 18 | background: Rectangle { 19 | implicitWidth: 200 20 | implicitHeight: 30 21 | color: backColor 22 | 23 | Rectangle { 24 | anchors.bottom: parent.bottom 25 | width: parent.width 26 | height: (textfield.hovered||textfield.focus) ? 2 :1 27 | color: textfield.focus ? focusColor : normalColor 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /common/BaseToolTip.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls.Material 2.12 3 | import QtQuick.Controls 2.12 4 | 5 | ToolTip { 6 | y: parent.height + 3 7 | leftMargin: 0 8 | rightMargin: 0 9 | topPadding: Qt.platform.os === "linux" ? 11 : 9 10 | leftPadding: 3 11 | rightPadding: 3 12 | Material.foreground: "#EEE" 13 | 14 | font.family: "Microsoft Yahei" 15 | delay: 1000 16 | 17 | } 18 | -------------------------------------------------------------------------------- /common/DropPopup.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | import QtQuick.Layouts 1.12 4 | import QtGraphicalEffects 1.12 5 | Popup { 6 | id: _popup 7 | property int bckRadius: 1 8 | 9 | property var backParent: undefined 10 | signal accept(); 11 | signal reject(); 12 | property alias acceptText: acceptBtn.text 13 | property alias rejectText: rejectBtn.text 14 | property bool acceptVisible: true 15 | property bool rejectVisible: true 16 | 17 | property bool bottomBtnsVisible: true 18 | 19 | 20 | implicitWidth: 300 21 | implicitHeight: 300 22 | 23 | background: Rectangle { 24 | id: back 25 | anchors.fill: parent 26 | radius: bckRadius 27 | color:skin.light ? "#fff" : "#171717" 28 | 29 | 30 | } 31 | padding: 0 32 | 33 | RowLayout { 34 | id: btns 35 | visible: bottomBtnsVisible 36 | parent: background 37 | anchors.bottom: parent.bottom 38 | anchors.bottomMargin: 12 39 | anchors.rightMargin: 20 40 | anchors.right: parent.right 41 | height: 24 42 | 43 | BaseButton { 44 | id: rejectBtn 45 | text: "取消" 46 | Layout.preferredHeight: 26 47 | Layout.preferredWidth: 68 48 | font.pixelSize: 13 49 | bckcolor: "#eeF65924" 50 | visible: rejectVisible 51 | backRadius: 2 52 | onClicked: { 53 | reject(); 54 | close(); 55 | } 56 | } 57 | 58 | SkinBaseButton { 59 | id: acceptBtn 60 | text: "确定" 61 | Layout.preferredHeight: 26 62 | Layout.preferredWidth: 68 63 | font.pixelSize: 13 64 | backRadius: 2 65 | visible: acceptVisible 66 | onClicked: { 67 | accept() 68 | } 69 | } 70 | } 71 | 72 | modal: true 73 | dim: false 74 | parent: Overlay.overlay 75 | Rectangle { 76 | visible: backParent == undefined ? false : _popup.visible 77 | opacity: _popup.opacity 78 | parent: backParent == undefined ? background : backParent 79 | anchors.fill: parent 80 | color: "#56000000" 81 | z:99999 82 | } 83 | 84 | 85 | x : Math.round((parent.width - _popup.width) / 2) 86 | y : Math.round((parent.height -_popup.height) / 2) 87 | 88 | focus: true 89 | closePolicy: Popup.CloseOnEscape 90 | 91 | enter: Transition { 92 | id: _enterAnima 93 | 94 | ScriptAction { 95 | script: { 96 | 97 | } 98 | } 99 | NumberAnimation { property: "opacity"; from: 0.3; to:1.0; duration: 300; } 100 | NumberAnimation { property: "y"; from: Math.round((_popup.parent.height - height) / 5); to: Math.round((_popup.parent.height - height) / 2); duration: 300; } 101 | ScriptAction { 102 | 103 | script: { 104 | if(contentChildren.length>0) 105 | btns.parent = contentChildren[0] 106 | } 107 | } 108 | } 109 | 110 | exit: Transition { 111 | id: _exitAnima 112 | 113 | NumberAnimation { target:_popup; property: "opacity"; from: 1.0; to: 0.3; duration: 300; } 114 | NumberAnimation { target:_popup; property: "y"; to: Math.round((_popup.parent.height - height) / 5); duration: 300; } 115 | 116 | // ScriptAction { 117 | // script: acceptFlg ? accept() : reject(); 118 | // } 119 | } 120 | 121 | 122 | } 123 | -------------------------------------------------------------------------------- /common/Frameless/frameless.cpp: -------------------------------------------------------------------------------- 1 | #include "frameless.h" 2 | #include 3 | #include 4 | 5 | FramelessWindow::FramelessWindow(QWindow *parent) 6 | : QQuickWindow (parent), 7 | m_resizable(true), 8 | m_event(Mouse_None) 9 | { 10 | setFlags(Qt::Window | Qt::FramelessWindowHint); 11 | QCoreApplication::instance()->installEventFilter(this); // 给自己加事件过滤器,用来实现拖动窗口 12 | 13 | 14 | m_monitorKeys.clear(); 15 | foreach(const auto& key, m_monitorKeysList) { 16 | m_monitorKeys[key._key] = key; 17 | } 18 | 19 | } 20 | 21 | bool FramelessWindow::maximized() 22 | { 23 | return windowStates() == Qt::WindowMaximized ? true : false; 24 | } 25 | 26 | void FramelessWindow::setMaximized(bool max) 27 | { 28 | if (!max) 29 | showNormal(); 30 | else 31 | showMaximized(); 32 | emit maximizedChanged(); 33 | emit resizeUpdate(this->size()); 34 | } 35 | 36 | bool FramelessWindow::eventFilter(QObject *obj, QEvent *evt) 37 | { 38 | QMouseEvent *mouse = dynamic_cast(evt); 39 | 40 | if(m_event != Mouse_None && evt->type() == QEvent::WindowStateChange) { 41 | unsetCursor(); 42 | m_event = Mouse_None; 43 | } else if(obj == this && mouse && windowStates() != Qt::WindowMaximized) { 44 | if(mouse->button() == Qt::LeftButton && mouse->type() == QEvent::MouseButtonPress) { //按下 45 | m_globalPressPos = mouse->globalPos(); 46 | m_pressPos = position(); 47 | m_preSize = size(); 48 | setCursorEvent(getMousePressEvent(mouse->pos())); 49 | } else if (m_event != Mouse_None && mouse->buttons() == Qt::LeftButton && 50 | mouse->type() == QEvent::MouseMove) { 51 | if (m_event == Mouse_Move) { // 按下鼠标移动中 52 | setPosition(m_pressPos + mouse->globalPos() - m_globalPressPos); 53 | } else if (m_event != Mouse_Move && m_resizable) { 54 | setCursorEvent(m_event); // 按下鼠标设置窗口大小中 55 | setWindowGeometry(mouse->globalPos()); 56 | } 57 | } else if(m_event != Mouse_None && mouse->button() == Qt::LeftButton && mouse->type() ==QEvent::MouseButtonRelease) { 58 | unsetCursor(); 59 | m_event = Mouse_None; 60 | } else if (m_event == Mouse_None && mouse->type() == QEvent::MouseMove) { // 鼠标徘徊 61 | MouseEvent currentEven = getResizeArea(mouse->pos()); 62 | setCursorEvent(currentEven, false); 63 | } 64 | } else if (m_monitorEnable && evt->type() == QEvent::KeyRelease) { 65 | checkMonitorKeys(obj, evt); 66 | } 67 | 68 | return QQuickWindow::eventFilter(obj,evt); 69 | } 70 | 71 | 72 | FramelessWindow::MouseEvent FramelessWindow::getMousePressEvent(const QPoint &pos) 73 | { 74 | int x = pos.x(); 75 | int y = pos.y(); 76 | int w = width(); 77 | int h = height(); 78 | int i; 79 | 80 | if (x <= 8 && y <= 8) { 81 | return Mouse_TopLeft; 82 | } else if (x >=(w - 8) && y <= 8) { 83 | return Mouse_TopRight; 84 | } else if (x <= 8 && y >= (h - 8)) { 85 | return Mouse_BottomLeft; 86 | } else if (x >=(w - 8) && y >= (h - 8)) { 87 | return Mouse_BottomRight; 88 | } else if (y <= 8) { 89 | return Mouse_Top; 90 | } else if (x <= 8 ) { 91 | return Mouse_Left; 92 | } else if (x >=(w - 8) ) { 93 | return Mouse_Right; 94 | } else if (y >= (h - 8)) { 95 | return Mouse_Bottom; 96 | } else { 97 | for (i = 0; i < m_moveArea.length(); i ++) { 98 | if (m_moveArea[i].contains(x, y)) 99 | return Mouse_Move; 100 | } 101 | return Mouse_None; 102 | } 103 | } 104 | 105 | FramelessWindow::MouseEvent FramelessWindow::getResizeArea(const QPoint &pos) 106 | { 107 | int x = pos.x(); 108 | int y = pos.y(); 109 | int w = width(); 110 | int h = height(); 111 | 112 | if (x <= 8 && y <= 8) { 113 | return Mouse_TopLeft; 114 | } else if (x >=(w - 8) && y <= 8) { 115 | return Mouse_TopRight; 116 | } else if (x <= 8 && y >= (h - 8)) { 117 | return Mouse_BottomLeft; 118 | } else if (x >=(w - 8) && y >= (h - 8)) { 119 | return Mouse_BottomRight; 120 | } else if (y <= 8) { 121 | return Mouse_Top; 122 | } else if (x <= 8 ) { 123 | return Mouse_Left; 124 | } else if (x >=(w - 8) ) { 125 | return Mouse_Right; 126 | } else if (y >= (h - 8)) { 127 | return Mouse_Bottom; 128 | } else { 129 | return Mouse_None; 130 | } 131 | } 132 | 133 | // 改变大小 134 | void FramelessWindow::setWindowGeometry(const QPoint &pos) 135 | { 136 | QPoint offset = m_globalPressPos - pos; 137 | 138 | if (m_globalPressPos == pos) 139 | return; 140 | 141 | 142 | switch (m_event) { 143 | case Mouse_TopLeft: 144 | setGeometryCalc(m_preSize + QSize(offset.x(), offset.y()), m_pressPos - offset); 145 | break; 146 | case Mouse_Top: 147 | setGeometryCalc(m_preSize + QSize(0, offset.y()), m_pressPos - QPoint(0, offset.y())); 148 | break; 149 | case Mouse_TopRight: 150 | setGeometryCalc(m_preSize - QSize(offset.x(), -offset.y()), m_pressPos - QPoint(0, offset.y())); 151 | break; 152 | case Mouse_Left: 153 | setGeometryCalc(m_preSize + QSize(offset.x(), 0), m_pressPos - QPoint(offset.x(), 0));; 154 | break; 155 | case Mouse_Right: 156 | setGeometryCalc(m_preSize - QSize(offset.x(), 0), position()); 157 | break; 158 | case Mouse_BottomLeft: 159 | setGeometryCalc(m_preSize + QSize(offset.x(), -offset.y()), m_pressPos - QPoint(offset.x(), 0)); 160 | break; 161 | case Mouse_Bottom: 162 | setGeometryCalc(m_preSize + QSize(0, -offset.y()), position()); 163 | break; 164 | case Mouse_BottomRight: 165 | setGeometryCalc(m_preSize - QSize(offset.x(), offset.y()), position()); 166 | break; 167 | default: 168 | break; 169 | } 170 | 171 | } 172 | 173 | void FramelessWindow::setGeometryCalc(const QSize &size, const QPoint &pos) 174 | { 175 | QPoint endPos = m_pressPos; 176 | QSize endSize = minimumSize(); 177 | if (size.width() > minimumWidth()) { 178 | endPos.setX(pos.x()); 179 | endSize.setWidth(size.width()); 180 | } else if (pos.x() != endPos.x()) { 181 | endPos.setX(m_pressPos.x() + m_preSize.width() - minimumWidth()); 182 | } 183 | 184 | if (size.height() > minimumHeight()) { 185 | endPos.setY(pos.y()); 186 | endSize.setHeight(size.height()); 187 | } else if (pos.y() != endPos.y()) { 188 | endPos.setY(m_pressPos.y() + m_preSize.height() - minimumHeight()); 189 | } 190 | setGeometry(QRect(endPos, endSize)); 191 | emit resizeUpdate(endSize); 192 | 193 | } 194 | 195 | 196 | void FramelessWindow::setCursorDrag(bool dragging) 197 | { 198 | setCursor(dragging ? Qt::OpenHandCursor : Qt::ArrowCursor); 199 | } 200 | 201 | 202 | void FramelessWindow::setCursorEvent(MouseEvent event, bool isRefrensh) 203 | { 204 | 205 | switch (event) { 206 | case Mouse_TopLeft: 207 | case Mouse_BottomRight: 208 | setCursor(Qt::SizeFDiagCursor); 209 | break; 210 | case Mouse_Top: 211 | case Mouse_Bottom: 212 | setCursor(Qt::SizeVerCursor); 213 | break; 214 | case Mouse_TopRight: 215 | case Mouse_BottomLeft: 216 | setCursor(Qt::SizeBDiagCursor); 217 | break; 218 | case Mouse_Left: 219 | case Mouse_Right: 220 | setCursor(Qt::SizeHorCursor); 221 | break; 222 | default : 223 | if(m_event != event) 224 | unsetCursor(); 225 | break; 226 | } 227 | if(isRefrensh) 228 | m_event = event; 229 | } 230 | 231 | 232 | void FramelessWindow::checkMonitorKeys(QObject *obj, QEvent *evt) 233 | { 234 | 235 | QKeyEvent *key = dynamic_cast(evt); 236 | if(!key) return; 237 | 238 | if(m_monitorKeys.contains((Qt::Key)key->key()) && obj == this) { 239 | 240 | bool modifiersCtrl = m_monitorKeys[(Qt::Key)key->key()]._modifiersCtrl; 241 | 242 | if(!modifiersCtrl && key->modifiers() == Qt::NoModifier) { 243 | emit monitorKeyPress((Qt::Key)key->key()); 244 | 245 | } else if(modifiersCtrl && key->modifiers() == Qt::ControlModifier) { 246 | emit monitorKeyPress((Qt::Key)key->key()); 247 | 248 | } 249 | } 250 | 251 | } 252 | -------------------------------------------------------------------------------- /common/Frameless/frameless.h: -------------------------------------------------------------------------------- 1 | #ifndef FRAMELESSWINDOW_H 2 | #define FRAMELESSWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | class MonitorKey 11 | { 12 | public: 13 | MonitorKey() {} 14 | 15 | MonitorKey (Qt::Key key, bool modifiersCtrl) : _key(key), _modifiersCtrl(modifiersCtrl) 16 | { } 17 | 18 | Qt::Key _key; 19 | bool _modifiersCtrl; 20 | 21 | }; 22 | 23 | 24 | class FramelessWindow : public QQuickWindow 25 | { 26 | Q_OBJECT 27 | Q_PROPERTY(bool monitorEnable MEMBER m_monitorEnable) 28 | Q_PROPERTY(bool resizable MEMBER m_resizable) 29 | Q_PROPERTY(QList moveArea MEMBER m_moveArea) 30 | Q_PROPERTY(bool maximized READ maximized WRITE setMaximized NOTIFY maximizedChanged) 31 | 32 | enum MouseEvent { 33 | Mouse_None = 0, 34 | Mouse_Pressed , 35 | Mouse_TopLeft , 36 | Mouse_Top, 37 | Mouse_TopRight, 38 | Mouse_Left, 39 | Mouse_Move, 40 | Mouse_Right, 41 | Mouse_BottomLeft, 42 | Mouse_Bottom, 43 | Mouse_BottomRight, 44 | }; 45 | 46 | public: 47 | explicit FramelessWindow(QWindow *parent = nullptr); 48 | bool maximized(); 49 | void setMaximized(bool max); 50 | 51 | Q_INVOKABLE void setCursorDrag(bool dragging); 52 | 53 | protected: 54 | bool eventFilter(QObject *obj, QEvent *evt) override; 55 | 56 | void checkMonitorKeys(QObject *obj, QEvent *evt); 57 | 58 | signals: 59 | void resizeUpdate(QSize size); 60 | void maximizedChanged(); 61 | void monitorKeyPress(Qt::Key key); 62 | 63 | private: 64 | MouseEvent getMousePressEvent(const QPoint &pos); 65 | MouseEvent getResizeArea(const QPoint &pos); 66 | void setWindowGeometry(const QPoint &pos); 67 | void setCursorEvent(MouseEvent event, bool isRefrensh = true); 68 | void setGeometryCalc(const QSize &size, const QPoint &pos); 69 | 70 | bool m_resizable; 71 | MouseEvent m_event; 72 | QPoint m_globalPressPos; // 鼠标按下的全局坐标 73 | QPoint m_pressPos; // 鼠标按下的应用程序内的坐标 74 | bool m_move; 75 | QSize m_preSize; 76 | QList m_moveArea; 77 | 78 | bool m_monitorEnable{true}; 79 | 80 | QList m_monitorKeysList{}; 81 | QHash m_monitorKeys; 82 | }; 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /common/Frameless/frameless.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | DEPENDPATH += $$PWD 3 | 4 | 5 | HEADERS += $$PWD/frameless.h \ 6 | 7 | SOURCES += $$PWD/frameless.cpp \ 8 | -------------------------------------------------------------------------------- /common/Frameless/frameless.pro: -------------------------------------------------------------------------------- 1 | QT += quick 2 | 3 | CONFIG += c++11 4 | 5 | # The following define makes your compiler emit warnings if you use 6 | # any Qt feature that has been marked deprecated (the exact warnings 7 | # depend on your compiler). Refer to the documentation for the 8 | # deprecated API to know how to port your code away from it. 9 | DEFINES += QT_DEPRECATED_WARNINGS 10 | 11 | # You can also make your code fail to compile if it uses deprecated APIs. 12 | # In order to do so, uncomment the following line. 13 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 14 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 15 | 16 | SOURCES += \ 17 | framelesswindow.cpp \ 18 | main.cpp 19 | 20 | RESOURCES += qml.qrc 21 | 22 | # Additional import path used to resolve QML modules in Qt Creator's code model 23 | QML_IMPORT_PATH = 24 | 25 | # Additional import path used to resolve QML modules just for Qt Quick Designer 26 | QML_DESIGNER_IMPORT_PATH = 27 | 28 | # Default rules for deployment. 29 | qnx: target.path = /tmp/$${TARGET}/bin 30 | else: unix:!android: target.path = /opt/$${TARGET}/bin 31 | !isEmpty(target.path): INSTALLS += target 32 | 33 | HEADERS += \ 34 | framelesswindow.h 35 | -------------------------------------------------------------------------------- /common/Frameless/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | 5 | 6 | -------------------------------------------------------------------------------- /common/ImageButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.5 3 | 4 | Button { 5 | id: container 6 | implicitWidth: 38 7 | implicitHeight: 24 8 | property var imageSrc: '' 9 | property var hoverimageSrc: null 10 | property var backHoverColor: 'transparent' 11 | property var backColor: 'transparent' 12 | property alias radius: back.radius 13 | 14 | clip: true 15 | padding: 0 16 | background: Rectangle { 17 | id: back 18 | anchors.fill: parent 19 | color: container.hovered ? backHoverColor : backColor 20 | Image { 21 | anchors.centerIn: parent 22 | antialiasing: true 23 | source: container.hovered ? (hoverimageSrc == null? imageSrc : hoverimageSrc) 24 | : imageSrc 25 | fillMode: Image.PreserveAspectFit 26 | 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /common/ScaleImageButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | 4 | Button { 5 | id: container 6 | implicitWidth: 38 7 | implicitHeight: 24 8 | property bool shrink: true 9 | property var normalImage: 'qrc:/res/scale1.png' 10 | property var maxImage: 'qrc:/res/scale0.png' 11 | 12 | property var backHoverColor: '#20334455' 13 | property var backColor: 'transparent' 14 | 15 | clip: true 16 | padding: 0 17 | background: Rectangle { 18 | anchors.fill: parent 19 | color: container.hovered ? backHoverColor : backColor 20 | Image { 21 | anchors.fill: parent 22 | anchors.margins: container.padding 23 | antialiasing: true 24 | source: shrink ? normalImage : maxImage 25 | fillMode: Image.PreserveAspectFit 26 | } 27 | } 28 | 29 | onClicked: { 30 | shrink = !shrink 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/Sidebar.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.5 3 | import QtGraphicalEffects 1.12 4 | import QtQml 2.14 5 | import QtGraphicalEffects 1.12 6 | import QtQuick.Layouts 1.12 7 | Item { 8 | id: container 9 | 10 | enum HorizontalPosBase { 11 | PosToLeft, 12 | PosToRight 13 | } 14 | 15 | 16 | property int horizontalPosBase: Sidebar.PosToLeft 17 | 18 | 19 | property int tailHeight: container.height*0.25 20 | property int tailSlopeHeight: container.height*0.008 21 | 22 | property bool enbale: true 23 | 24 | property bool isOpen: true 25 | 26 | 27 | property alias backOpacity : content.opacity 28 | property color bckColor: "#fff" 29 | property color btnColor : "#666" 30 | property var contentObj : content 31 | 32 | property real layoutPreferredWidth: 0 33 | 34 | property int tailWidth: layoutPreferredWidth ? layoutPreferredWidth*0.083 : container.width*0.083 35 | 36 | x: horizontalPosBase === Sidebar.PosToLeft ? isOpen ? 0 : -content.width 37 | : isOpen ? parent.width-width : parent.width-tailWidth 38 | Layout.preferredWidth: isOpen ? layoutPreferredWidth : tailWidth 39 | 40 | Behavior on x { 41 | NumberAnimation { duration:100 } 42 | } 43 | 44 | Behavior on Layout.preferredWidth { 45 | NumberAnimation { duration:100 } 46 | } 47 | 48 | MouseArea { 49 | id: bottomMouse 50 | anchors.fill: parent 51 | hoverEnabled: container.enbale 52 | 53 | } 54 | 55 | Rectangle { 56 | id: content 57 | width: parent.width-tailWidth 58 | height: parent.height 59 | x: horizontalPosBase === Sidebar.PosToLeft ? 0 : tailWidth 60 | color: bckColor 61 | visible: horizontalPosBase === Sidebar.PosToLeft ? (container.x == -content.width ? false : true ) : 62 | (container.x == parent.width-tailWidth ? false : true) 63 | radius: skin.gradSupport || skin.imageSupport ? 14 : 8 64 | clip: true 65 | onVisibleChanged: { 66 | canvas.requestPaint() 67 | } 68 | 69 | layer.enabled: skin.shadow 70 | layer.effect: DropShadow { 71 | color: !skin.gradSupport && !skin.imageSupport ? "#36000000" : "#36FFFFFF" 72 | radius: 8 73 | samples: 17 74 | 75 | } 76 | 77 | onColorChanged: canvas.requestPaint() 78 | } 79 | 80 | Canvas { 81 | id: canvas 82 | width: tailWidth 83 | height: tailHeight 84 | y: container.height/2 -height/2 85 | x: horizontalPosBase === Sidebar.PosToLeft ? parent.width-tailWidth : 0 86 | antialiasing: true 87 | smooth: true 88 | rotation: horizontalPosBase === Sidebar.PosToLeft ? 0 : 180 89 | opacity: !isOpen ? 1.0 : (isOpen && !(bottomMouse.containsMouse || mouse.containsMouse)) ? 0.0 : 1.0 90 | onPaint: { 91 | var ctx = getContext("2d"); 92 | ctx.clearRect(0,0, canvas.width, canvas.height); 93 | 94 | 95 | ctx.shadowBlur = skin.shadow 96 | ctx.shadowColor = !skin.gradSupport && !skin.imageSupport ? "#36000000" : "#36FFFFFF" 97 | 98 | ctx.fillStyle = bckColor; 99 | ctx.strokeStyle = mouse.containsMouse ? skin.accentColor : !skin.gradSupport && !skin.imageSupport ? "#36000000" : "#36FFFFFF" 100 | ctx.beginPath() 101 | 102 | ctx.moveTo(0,0) 103 | ctx.lineTo(canvas.width-2, tailSlopeHeight) 104 | ctx.lineTo(canvas.width-2, canvas.height - tailSlopeHeight) 105 | ctx.lineTo(0, canvas.height) 106 | ctx.closePath() 107 | ctx.stroke() 108 | ctx.fill() 109 | 110 | ctx.shadowBlur = 0 111 | 112 | ctx.fillStyle = skin.stretchColor 113 | 114 | ctx.beginPath() 115 | var arrowMargin = tailWidth*0.35 116 | var arrowHalfHeight = tailHeight*0.04 117 | 118 | if (isOpen) { 119 | context.moveTo(tailWidth-arrowMargin*1.2, height/2-arrowHalfHeight); 120 | context.lineTo(tailWidth-arrowMargin*1.2, height/2+arrowHalfHeight); 121 | context.lineTo(arrowMargin*0.7, height/2); 122 | } else { 123 | context.moveTo(arrowMargin*0.7, height/2-arrowHalfHeight); 124 | context.lineTo(arrowMargin*0.7, height/2+arrowHalfHeight); 125 | context.lineTo(tailWidth-arrowMargin*1.1, height/2); 126 | 127 | } 128 | context.closePath(); 129 | context.fill(); 130 | } 131 | MouseArea { 132 | id: mouse 133 | anchors.fill: parent 134 | hoverEnabled: container.enbale 135 | onContainsMouseChanged: canvas.requestPaint() 136 | onClicked: { 137 | isOpen = !isOpen 138 | canvas.requestPaint() 139 | } 140 | } 141 | 142 | Behavior on opacity { 143 | NumberAnimation { duration: 300 } 144 | } 145 | } 146 | 147 | 148 | 149 | } 150 | 151 | -------------------------------------------------------------------------------- /common/SkinBaseButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.5 3 | import QtGraphicalEffects 1.12 4 | Button { 5 | id: container 6 | property color bckcolor: accentContrlColor 7 | property string bckHoverColor: Qt.lighter(bckcolor, 0.8) 8 | property color textcolor: skin.light ? "#fff" : "#eee" 9 | property int backRadius: 3 10 | 11 | font.family: "Microsoft Yahei" 12 | font.pixelSize: 20 13 | implicitWidth: text.contentWidth + 24 14 | implicitHeight: text.contentHeight + 8 15 | 16 | contentItem: Text { 17 | id: text 18 | anchors.centerIn: parent 19 | text: container.text 20 | font: container.font 21 | color: textcolor 22 | horizontalAlignment: Text.AlignHCenter 23 | verticalAlignment: Text.AlignVCenter 24 | } 25 | background: Rectangle { 26 | anchors.fill: parent 27 | radius: backRadius 28 | color: bckcolor 29 | gradient: container.hovered ? skin.gradient : undefined 30 | Rectangle { 31 | anchors.fill: parent 32 | color: "#11000000" 33 | visible: container.hovered 34 | } 35 | layer.enabled: true 36 | layer.effect: DropShadow { 37 | color: bckcolor 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /common/SkinBaseButton2.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.5 3 | import QtGraphicalEffects 1.12 4 | import Qt.Singleton 1.0 5 | Button { 6 | id: container 7 | property color bckcolor: skin.light ? accentContrlColor : "#eee" 8 | property int backRadius: 3 9 | 10 | font.family: "Microsoft Yahei" 11 | font.pixelSize: 20 12 | implicitWidth: text.contentWidth + 24 13 | implicitHeight: text.contentHeight + 8 14 | contentItem: Text { 15 | id: text 16 | anchors.centerIn: parent 17 | text: container.text 18 | font: container.font 19 | color: bckcolor 20 | horizontalAlignment: Text.AlignHCenter 21 | verticalAlignment: Text.AlignVCenter 22 | } 23 | background: Rectangle { 24 | anchors.fill: parent 25 | radius: backRadius 26 | color: skin.light ? "#33FFFFFF" : "transparent" 27 | border.width: container.checked ? 3 : container.hovered ? 2 : 1 28 | border.color: container.checked ? Qt.lighter(bckcolor, 0.80) : container.hovered ? Qt.lighter(bckcolor, 0.88) : bckcolor 29 | 30 | layer.enabled: true 31 | layer.effect: DropShadow { 32 | color: bckcolor 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /common/SkinImageButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | import Qt.Singleton 1.0 4 | 5 | Button { 6 | id: container 7 | property int radius: 3 8 | property var imageSrc: '' 9 | implicitWidth: 21 10 | implicitHeight: 21 11 | clip: true 12 | 13 | background: Rectangle { 14 | id: back 15 | anchors.fill: container 16 | radius: container.radius 17 | // gradient: SkinSingleton.skins[setting.skinIndex] 18 | Image { 19 | anchors.fill: parent 20 | anchors.margins: container.radius 21 | source: imageSrc 22 | } 23 | Rectangle { 24 | anchors.fill: parent 25 | radius: container.radius 26 | color: !container.hovered? "#11000000" : "#11ffffff" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /common/SkinModel.qml: -------------------------------------------------------------------------------- 1 | pragma Singleton 2 | import QtQuick 2.12 3 | import QtQml.Models 2.12 4 | import QtQuick.Layouts 1.14 5 | import Qt.labs.settings 1.0 6 | 7 | Item { 8 | property alias exteriorComponent: _exteriorComponent 9 | property int skinCustomIdx: skins.length-1 10 | property bool skinCustomUpdate: false 11 | 12 | 13 | property list skins : [ 14 | Item { 15 | property string name : "简约白色" 16 | property bool windowShadow: true 17 | property bool shadow: true 18 | property string mainColor: "#f0f0f0" 19 | property string titleColor : "#4785FF" 20 | property string contentBackColor : "#FFF" 21 | 22 | property string accentColor : "#4785FF" 23 | property string accentContrlColor : "#4785FF" 24 | 25 | property string stretchColor : "#4785FF" 26 | property string stretchBackHoverColor : "#444785FF" 27 | property string stretchSelectColor: "#fff" 28 | property string stretchBackColor: "#F6F6F6" 29 | property string stretchSelectBackColor: "#4785FF" 30 | 31 | property string stretchFoldSelectColor: "#4785FF" 32 | property string stretchFoldBackColor: "transparent" 33 | 34 | 35 | property bool light : true 36 | 37 | property bool gradSupport: false 38 | property bool imageSupport: false 39 | 40 | 41 | }, 42 | 43 | Item{ 44 | property string name : "暗黑风格" 45 | property bool shadow: false 46 | property string mainColor: "#000" 47 | property string titleColor: "#070709" 48 | property string contentBackColor: "#252528" 49 | 50 | property string accentColor: "#eee" 51 | property string accentContrlColor: "#22ffffff" 52 | 53 | 54 | property string stretchColor : "#eee" 55 | property string stretchBackHoverColor : "#05ffffff" 56 | property string stretchSelectColor: "#00C1CD" 57 | property string stretchBackColor: "transparent" 58 | 59 | property string stretchSelectBackColor: "#11ffffff" 60 | 61 | 62 | property string stretchFoldSelectColor: "#00C1CD" 63 | property string stretchFoldBackColor: "#252528" 64 | property string stretchFoldBackSelectColor: "#343337" 65 | 66 | property bool light : false 67 | property bool gradSupport: false 68 | property bool imageSupport: false 69 | 70 | 71 | }, 72 | Item { 73 | property string name : "午夜巴黎" 74 | property bool windowShadow: true 75 | property bool shadow: true 76 | property string mainColor: "#44ffffff" 77 | property string titleColor : "transparent" 78 | property string contentBackColor : "#FFF" 79 | property string accentColor : "#7C56FF" 80 | property string accentContrlColor : "#7C56FF" 81 | 82 | property string stretchColor : "#4785FF" 83 | property string stretchBackHoverColor : "#11ffffff" 84 | property string stretchSelectColor: "#fff" 85 | property string stretchBackColor: "transparent" 86 | property string stretchSelectBackColor: "#ee6BB1FF" 87 | 88 | property string stretchFoldSelectColor: "#4785FF" 89 | property string stretchFoldBackColor: "transparent" 90 | 91 | 92 | property bool light : true 93 | property bool gradSupport: true 94 | property alias gradient: _gradient 95 | property bool imageSupport: false 96 | property real gradMainOpacity: 0.01 97 | 98 | 99 | 100 | Gradient { 101 | id: _gradient 102 | orientation: Gradient.Horizontal; 103 | GradientStop { position: 0.0; color: "#12B4FF" } 104 | GradientStop { position: 0.15; color: "#3297FF" } 105 | GradientStop { position: 1.0; color: "#B822FF" } 106 | } 107 | 108 | 109 | }, 110 | 111 | Item { 112 | property string name : "秋日暖阳" 113 | property bool windowShadow: true 114 | property bool shadow: true 115 | property string mainColor: "#44ffffff" 116 | property string titleColor : "transparent" 117 | property string contentBackColor : "#FFF" 118 | property string accentColor : "#FF5245" 119 | property string accentContrlColor : "#FF5245" 120 | 121 | // 伸展 122 | property string stretchColor : "#FF5146" 123 | property string stretchBackHoverColor : "#11ffffff" 124 | property string stretchSelectColor: "#fff" 125 | property string stretchBackColor: "transparent" 126 | property string stretchSelectBackColor: "#eeFF8A6D" 127 | 128 | property string stretchFoldSelectColor: "#FF5146" 129 | property string stretchFoldBackColor: "transparent" 130 | 131 | 132 | property bool light : true 133 | property bool gradSupport: true 134 | property alias gradient: _gradient2 135 | property bool imageSupport: false 136 | property real gradMainOpacity: 0.01 137 | 138 | 139 | 140 | Gradient { 141 | id: _gradient2 142 | orientation: Gradient.Horizontal; 143 | GradientStop { position: 0.0; color: "#FF7C20" } 144 | GradientStop { position: 0.3; color: "#FF4750" } 145 | GradientStop { position: 0.7; color: "#FF177A" } 146 | GradientStop { position: 1.0; color: "#FF0090" } 147 | } 148 | }, 149 | Item { 150 | property string name : "午夜巴黎(透明)" 151 | property bool windowShadow: false 152 | property bool shadow: false 153 | property string mainColor: "#44ffffff" 154 | property string titleColor : "transparent" 155 | property string contentBackColor : "#FFF" 156 | property string accentColor : "#7C56FF" 157 | property string accentContrlColor : "#7C56FF" 158 | 159 | // 伸展 160 | property string stretchColor : "#4785FF" 161 | property string stretchBackHoverColor : "#446BB1FF" 162 | property string stretchSelectColor: "#fff" 163 | property string stretchBackColor: "transparent" 164 | property string stretchSelectBackColor: "#886BB1FF" 165 | 166 | property string stretchFoldSelectColor: "#4785FF" 167 | property string stretchFoldBackColor: "transparent" 168 | 169 | 170 | property bool light : true 171 | property bool gradSupport: true 172 | property bool imageSupport: false 173 | property real gradMainOpacity: 0.01 174 | 175 | 176 | 177 | property alias gradient: _gradient3 178 | 179 | 180 | Gradient { 181 | id: _gradient3 182 | orientation: Gradient.Horizontal; 183 | GradientStop { position: 0.0; color: "#AA12B4FF" } 184 | GradientStop { position: 0.15; color: "#AA3297FF" } 185 | GradientStop { position: 1.0; color: "#AAB822FF" } 186 | } 187 | 188 | 189 | }, 190 | 191 | Item { 192 | property string name : "简约白色(透明)" 193 | property bool windowShadow: false 194 | property bool shadow: false 195 | property string mainColor: "#66FFFFFF" 196 | property string titleColor : "#aa4785FF" 197 | property string contentBackColor : "#baFFFFFF" 198 | 199 | property string accentColor : "#4785FF" 200 | property string accentContrlColor : "#4785FF" 201 | 202 | // 伸展 203 | property string stretchColor : "#4785FF" 204 | property string stretchBackHoverColor : "#11ffffff" 205 | property string stretchSelectColor: "#fff" 206 | property string stretchBackColor: "#AAF6F6F6" 207 | property string stretchSelectBackColor: "#AA4785FF" 208 | 209 | property string stretchFoldSelectColor: "#4785FF" 210 | property string stretchFoldBackColor: "transparent" 211 | 212 | 213 | property bool light : true 214 | 215 | property bool gradSupport: false 216 | property bool imageSupport: false 217 | 218 | 219 | 220 | }, 221 | 222 | Item { 223 | property string name : "蓝灰色" 224 | property bool windowShadow: true 225 | property bool shadow: true 226 | property string mainColor: "#77ffffff" 227 | property string titleColor : "transparent" 228 | property string contentBackColor : "#FFF" 229 | property string accentColor : "#507EA4" 230 | property string accentContrlColor : "#507EA4" 231 | 232 | property string stretchColor : "#507EA4" 233 | property string stretchBackHoverColor : "#11ffffff" 234 | property string stretchSelectColor: "#fff" 235 | property string stretchBackColor: "transparent" 236 | property string stretchSelectBackColor: "#C2D2DF" 237 | 238 | property string stretchFoldSelectColor: "#507EA4" 239 | property string stretchFoldBackColor: "transparent" 240 | 241 | 242 | property bool light : true 243 | property bool gradSupport: true 244 | property alias gradient: _gradient4 245 | property bool imageSupport: false 246 | property real gradMainOpacity: 0.51 247 | 248 | 249 | Gradient { 250 | id: _gradient4 251 | orientation: Gradient.Horizontal; 252 | GradientStop { position: 0.0; color: "#507EA4" } 253 | } 254 | } 255 | ] 256 | 257 | Component { 258 | id: _exteriorComponent 259 | Item { 260 | id: content 261 | property var skinTarget 262 | width: content.GridView.view.cellWidth; height: content.GridView.view.cellHeight 263 | clip: true 264 | Column { 265 | anchors.fill: parent 266 | spacing: 6 267 | anchors.topMargin: 10 268 | Rectangle { 269 | implicitWidth: content.width - 20 270 | implicitHeight: implicitWidth - 30 271 | anchors.horizontalCenter: parent.horizontalCenter 272 | color: skins[index].mainColor 273 | gradient: skins[index].gradient 274 | 275 | Image { 276 | visible: skins[index].imageSupport 277 | anchors.fill: parent 278 | source: !skins[index].imageSupport ? "" : skins[index].imageUrl 279 | fillMode: Image.PreserveAspectCrop 280 | mipmap: true 281 | } 282 | 283 | 284 | ColumnLayout { 285 | anchors.fill: parent 286 | spacing: 0 287 | z: 1 288 | Rectangle { 289 | Layout.preferredHeight: 14 290 | Layout.fillWidth: true 291 | color: skins[index].imageSupport ? "#33000000" : skins[index].titleColor 292 | 293 | } 294 | 295 | Rectangle { 296 | Layout.fillHeight: true 297 | Layout.fillWidth: true 298 | 299 | color: !skins[index].light ? "#44000000" : "#11ffffff" 300 | RowLayout { 301 | anchors.fill: parent 302 | anchors.margins: 6 303 | 304 | Rectangle { 305 | z: 2 306 | Layout.fillHeight: true 307 | Layout.preferredWidth: 40 308 | color: !skins[index].gradSupport && !skins[index].imageSupport ? skins[index].contentBackColor : 309 | !skins[index].light ? "#33000000" : "#33ffffff" 310 | radius: 4 311 | 312 | } 313 | 314 | Rectangle { 315 | z: 2 316 | Layout.fillHeight: true 317 | Layout.fillWidth: true 318 | color: !skins[index].gradSupport && !skins[index].imageSupport ? skins[index].contentBackColor : 319 | !skins[index].light ? "#33000000" : "#33ffffff" 320 | radius: 4 321 | } 322 | 323 | } 324 | } 325 | 326 | 327 | } 328 | } 329 | 330 | YaheiText { 331 | text: skins[index].name 332 | font.pixelSize: 14 333 | color: skins[content.GridView.view.currentIndex].accentColor 334 | opacity: 0.7 335 | anchors.horizontalCenter: parent.horizontalCenter 336 | } 337 | } 338 | MouseArea { 339 | anchors.fill: parent 340 | onClicked: { 341 | content.GridView.view.requestSwitchSkin(index) 342 | } 343 | } 344 | 345 | } 346 | 347 | } 348 | 349 | 350 | 351 | } 352 | -------------------------------------------------------------------------------- /common/SkinPopup.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | import QtQuick.Layouts 1.12 4 | import QtGraphicalEffects 1.12 5 | import Qt.labs.platform 1.0 6 | import Qt.Singleton 1.0 7 | import "qrc:/common" 8 | 9 | Popup { 10 | id: _popup 11 | 12 | 13 | 14 | 15 | background: Rectangle { 16 | implicitWidth: 650 17 | implicitHeight: 420 18 | radius: 1 19 | layer.enabled: true 20 | gradient: skin.gradient 21 | layer.effect: DropShadow { 22 | visible: !_enterAnima.running & !_exitAnima.running 23 | } 24 | Image { 25 | id: image 26 | visible: skin.imageSupport 27 | anchors.fill: parent 28 | source: !skin.imageSupport ? "" : skin.imageUrl 29 | fillMode: Image.PreserveAspectCrop 30 | } 31 | 32 | ColumnLayout { 33 | anchors.fill: parent 34 | spacing: 0 35 | Rectangle { 36 | color: skin.titleColor 37 | width: parent.width 38 | Layout.fillWidth: true 39 | Layout.preferredHeight: 33 40 | } 41 | Rectangle { 42 | color: skin.contentBackColor 43 | Layout.fillHeight: true 44 | Layout.fillWidth: true 45 | } 46 | } 47 | 48 | 49 | ImageButton { 50 | anchors.right: parent.right 51 | imageSrc: "qrc:/windowRes/close.png" 52 | // hoverimageSrc:"qrc:/res/close_hover.png" 53 | backHoverColor: "#FA5151" 54 | ToolTip.delay: 1000 55 | ToolTip.visible: hovered 56 | ToolTip.text: qsTr("关闭") 57 | onClicked: close(); 58 | } 59 | Image { 60 | antialiasing: true 61 | source: "qrc:/windowRes/icon.png" 62 | width: 24 63 | height: 24 64 | x: 4 65 | y: 2 66 | fillMode: Image.PreserveAspectFit 67 | } 68 | YaheiText { 69 | text: "主题装扮" 70 | font.pixelSize: 15 71 | x: 32 72 | y: 4 73 | color: "#FFF" 74 | } 75 | 76 | Row { 77 | spacing: 12 78 | anchors.bottom: parent.bottom 79 | anchors.left: parent.left 80 | anchors.leftMargin: 23 81 | anchors.bottomMargin: 5 82 | visible: skin.gradSupport || skin.imageSupport 83 | YaheiText { 84 | text: "透明度" 85 | font.pixelSize: 13 86 | color: skin.accentColor 87 | anchors.verticalCenter: parent.verticalCenter 88 | } 89 | BaseSlider { 90 | id: _slider 91 | from: 0.5 92 | to: 1.0 93 | value: setting.skinOpacity 94 | onMoved: { 95 | setting.skinOpacity = value; 96 | } 97 | } 98 | } 99 | 100 | Row { 101 | anchors.bottom: parent.bottom 102 | anchors.right: parent.right 103 | anchors.rightMargin: 23 104 | anchors.bottomMargin: 8 105 | spacing: 6 106 | 107 | SkinBaseButton { 108 | text: "自定义" 109 | height: 21 110 | width: 75 111 | font.pixelSize: 12 112 | anchors.verticalCenter: parent.verticalCenter 113 | backRadius: 5 114 | onClicked: { 115 | message('info', "暂不支持!") 116 | 117 | } 118 | } 119 | 120 | 121 | SkinBaseButton { 122 | text: "恢复默认" 123 | height: 21 124 | width: 75 125 | font.pixelSize: 12 126 | anchors.verticalCenter: parent.verticalCenter 127 | backRadius: 5 128 | onClicked: { 129 | _content.currentIndex = 1; 130 | setting.skinOpacity = 0.9 131 | } 132 | } 133 | } 134 | } 135 | 136 | 137 | GridView { 138 | id: _content 139 | anchors.fill: parent 140 | anchors.topMargin: 30 141 | anchors.bottomMargin: 30 142 | model: SkinSingleton.skins 143 | cellWidth: parent.width/4 144 | cellHeight: cellWidth 145 | delegate: SkinSingleton.exteriorComponent 146 | clip: true 147 | currentIndex: setting.skinIndex 148 | highlight: Rectangle { border.width: 2; color: "transparent"; border.color: accentColor; radius: 5 } 149 | onCurrentIndexChanged: { 150 | setting.skinIndex = currentIndex 151 | } 152 | 153 | function requestSwitchSkin(idx) { 154 | _content.currentIndex = idx; 155 | } 156 | } 157 | 158 | modal: true 159 | dim: false 160 | focus: true 161 | 162 | parent: Overlay.overlay 163 | x: Math.round((parent.width - width) / 2) 164 | y: Math.round((parent.height - height) / 2) 165 | 166 | closePolicy: Popup.CloseOnEscape 167 | 168 | enter: Transition { 169 | id: _enterAnima 170 | NumberAnimation { property: "scale"; from: 0.0; to: 1.0; duration: 200; easing.type : Easing.OutBack } 171 | NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 300; } 172 | ScriptAction { 173 | script: _content.positionViewAtIndex( setting.skinIndex, GridView.Center); 174 | } 175 | } 176 | exit: Transition { 177 | id: _exitAnima 178 | NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 300; } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /common/YaheiText.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | 3 | Text { 4 | id: _text 5 | font.pixelSize: 15 6 | font.family: "Microsoft Yahei" 7 | text: "text" 8 | color: accentColor 9 | } 10 | -------------------------------------------------------------------------------- /common/qmlQianDialog/BlogDialog.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.14 2 | import QtQuick.Controls 2.14 3 | import QtQuick.Layouts 1.14 4 | import QtLocation 5.14 5 | import QtQuick.Controls.Material 2.12 6 | import Qt.labs.platform 1.0 7 | import "qrc:/common" 8 | 9 | DropPopup { 10 | id: skinDialog 11 | 12 | 13 | readonly property string typeQuestion : "question.png" 14 | readonly property string typeError : "error.png" 15 | readonly property string typeInformation : "info.png" 16 | readonly property string typeSuccess : "ok.png" 17 | 18 | enum DialogType { 19 | DialogQuestion, 20 | DialogError, 21 | DialogInformation, 22 | DialogSuccess 23 | } 24 | 25 | z: 100 26 | 27 | width: contentLayout.width+80 < 340 ? 340 : contentLayout.width + 80 28 | height: !title.length ? contentLayout.height + 60 : contentLayout.height + 80 29 | 30 | 31 | property alias title: _title.text 32 | property alias icon: _icon.source 33 | 34 | property string accentColorStr: accentColor 35 | function dialogOpen() { 36 | 37 | icon = typeInformation 38 | rejectVisible = false 39 | open() 40 | } 41 | 42 | 43 | Item { 44 | anchors.fill: parent 45 | 46 | ImageButton { 47 | anchors.right: parent.right 48 | imageSrc: "qrc:/windowRes/close2.png" 49 | hoverimageSrc:"qrc:/windowRes/close_hover.png" 50 | backHoverColor: "#FA5151" 51 | BaseToolTip { 52 | visible: parent.hovered 53 | text: "关闭" 54 | font.pixelSize: 12 55 | delay: 1000 56 | } 57 | onClicked: close(); 58 | } 59 | 60 | ColumnLayout { 61 | id: dialogLayout 62 | width: skinDialog.width 63 | spacing: 0 64 | RowLayout { 65 | visible: title.length 66 | Layout.leftMargin: 6 67 | Layout.preferredHeight: 28 68 | YaheiText { 69 | id: _title 70 | font.pixelSize: 16 71 | color: tingeColor 72 | text: "关于QianWindow" 73 | } 74 | } 75 | Rectangle { 76 | visible: title.length 77 | height: 1 78 | color: tingeOpacityColor 79 | Layout.fillWidth: true 80 | } 81 | ColumnLayout { 82 | id: contentLayout 83 | Layout.margins: 20 84 | Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter 85 | RowLayout { 86 | Layout.topMargin: title != "" ? 0 : 20 87 | Layout.bottomMargin: 20 88 | Image { 89 | id: _icon 90 | antialiasing: true 91 | source: "info.png" 92 | Layout.preferredWidth: 40 93 | Layout.preferredHeight: 40 94 | fillMode: Image.PreserveAspectFit 95 | } 96 | 97 | YaheiText { 98 | text: `最新版本视频地址: B站演示入口` 99 | font.pixelSize: 15 100 | color: tingeColor 101 | onLinkActivated: Qt.openUrlExternally(link); 102 | } 103 | 104 | } 105 | 106 | } 107 | } 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /common/qmlQianDialog/SkinQianDialog.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.14 2 | import QtQuick.Controls 2.14 3 | import QtQuick.Layouts 1.14 4 | import QtLocation 5.14 5 | import QtQuick.Controls.Material 2.12 6 | import Qt.labs.platform 1.0 7 | import "qrc:/common" 8 | 9 | DropPopup { 10 | id: skinDialog 11 | 12 | 13 | readonly property string typeQuestion : "question.png" 14 | readonly property string typeError : "error.png" 15 | readonly property string typeInformation : "info.png" 16 | readonly property string typeSuccess : "ok.png" 17 | 18 | enum DialogType { 19 | DialogQuestion, 20 | DialogError, 21 | DialogInformation, 22 | DialogSuccess 23 | } 24 | 25 | z: 100 26 | 27 | width: contentLayout.width+80 < 340 ? 340 : contentLayout.width + 80 28 | height: !title.length ? contentLayout.height + 60 : contentLayout.height + 80 29 | 30 | property alias title: _title.text 31 | property alias text: _content.text 32 | property alias icon: _icon.source 33 | 34 | 35 | function dialogOpen(type, _text, _title = "") { 36 | 37 | icon = type == SkinQianDialog.DialogQuestion ? typeQuestion : 38 | type == SkinQianDialog.DialogError ? typeError : 39 | type == SkinQianDialog.DialogInformation ? typeInformation : typeSuccess 40 | 41 | rejectVisible = type == SkinQianDialog.DialogQuestion ? true : false 42 | 43 | title = _title 44 | text = _text 45 | open() 46 | } 47 | 48 | 49 | Item { 50 | anchors.fill: parent 51 | 52 | ImageButton { 53 | anchors.right: parent.right 54 | imageSrc: "qrc:/windowRes/close2.png" 55 | hoverimageSrc:"qrc:/windowRes/close_hover.png" 56 | backHoverColor: "#FA5151" 57 | BaseToolTip { 58 | visible: parent.hovered 59 | text: "关闭" 60 | font.pixelSize: 12 61 | delay: 1000 62 | } 63 | onClicked: close(); 64 | } 65 | 66 | ColumnLayout { 67 | id: dialogLayout 68 | width: skinDialog.width 69 | spacing: 0 70 | RowLayout { 71 | visible: title.length 72 | Layout.leftMargin: 6 73 | Layout.preferredHeight: 28 74 | YaheiText { 75 | id: _title 76 | font.pixelSize: 16 77 | color: tingeColor 78 | } 79 | } 80 | Rectangle { 81 | visible: title.length 82 | height: 1 83 | color: tingeOpacityColor 84 | Layout.fillWidth: true 85 | } 86 | ColumnLayout { 87 | id: contentLayout 88 | Layout.margins: 20 89 | Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter 90 | RowLayout { 91 | Layout.topMargin: title != "" ? 0 : 20 92 | Layout.bottomMargin: 20 93 | Image { 94 | id: _icon 95 | antialiasing: true 96 | source: "info.png" 97 | Layout.preferredWidth: 40 98 | Layout.preferredHeight: 40 99 | fillMode: Image.PreserveAspectFit 100 | } 101 | 102 | YaheiText { 103 | id: _content 104 | text: "" 105 | font.pixelSize: 15 106 | color: tingeColor 107 | } 108 | 109 | } 110 | 111 | } 112 | } 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /common/qmlQianDialog/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/common/qmlQianDialog/error.png -------------------------------------------------------------------------------- /common/qmlQianDialog/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/common/qmlQianDialog/info.png -------------------------------------------------------------------------------- /common/qmlQianDialog/ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/common/qmlQianDialog/ok.png -------------------------------------------------------------------------------- /common/qmlQianDialog/question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/common/qmlQianDialog/question.png -------------------------------------------------------------------------------- /common/qmlQianHints/Message.qml: -------------------------------------------------------------------------------- 1 | 2 | import QtQuick 2.10 3 | 4 | Rectangle { 5 | id: msgBox 6 | property alias text: msg.text 7 | property var type: "info" 8 | 9 | clip: true 10 | width: msg.contentWidth + 105 11 | height: 44 12 | color: type=== "info" ? "#fdf6ec" : type=== "success" ? "#f0f9eb" : "#fef0f0" 13 | border.color:type=== "info" ? "#faecd8" : type=== "success" ? "#e1f3d8" : "#fde2e2" 14 | radius: 5 15 | anchors.horizontalCenter: parent.horizontalCenter 16 | visible: false; 17 | 18 | function open(_type, _text) { 19 | type =_type 20 | text = _text 21 | 22 | animation.restart(); 23 | } 24 | 25 | Image { 26 | id: img 27 | source: type 28 | === "info" ? "remind.png" : type 29 | === "success" ? "true.png" : "error.png" 30 | width: 24 31 | height: 24 32 | anchors { 33 | verticalCenter: parent.verticalCenter 34 | left: parent.left 35 | leftMargin: 30 36 | } 37 | } 38 | Text { 39 | id: msg 40 | color: type=== "info" ? "#e6a23c" : type=== "success" ? "#67c23a" : "#f56c6c" 41 | font.pixelSize: 17 42 | font.family: "Microsoft Yahei" 43 | anchors { 44 | verticalCenter: img.verticalCenter 45 | left: img.right 46 | leftMargin: 10 47 | } 48 | } 49 | 50 | 51 | SequentialAnimation{ 52 | id: animation 53 | running: false 54 | ParallelAnimation { 55 | ScriptAction { 56 | script: msgBox.visible = true 57 | } 58 | NumberAnimation { 59 | target: msgBox 60 | property: "y" 61 | from: 0 62 | to: 40 63 | duration: 300 64 | easing.type : Easing.InOutQuad 65 | } 66 | NumberAnimation { 67 | target: msgBox 68 | property: "opacity" 69 | from: 0.3 70 | to: 1.0 71 | duration: 300 72 | easing.type : Easing.InOutQuad 73 | } 74 | } 75 | 76 | 77 | PauseAnimation { 78 | duration: 2000 79 | } 80 | 81 | ParallelAnimation { 82 | NumberAnimation { 83 | target: msgBox 84 | property: "y" 85 | from: 40 86 | to: 0 87 | duration: 300 88 | easing.type : Easing.InOutQuad 89 | } 90 | NumberAnimation { 91 | target: msgBox 92 | property: "opacity" 93 | from: 1.0 94 | to: 0.3 95 | duration: 300 96 | easing.type : Easing.InOutQuad 97 | } 98 | } 99 | 100 | ScriptAction { 101 | script: msgBox.visible = false 102 | } 103 | 104 | } 105 | } 106 | 107 | -------------------------------------------------------------------------------- /common/qmlQianHints/QianQuestionMark.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.5 3 | import "qrc:/common" 4 | 5 | Item { 6 | property string hint: "hint " 7 | implicitWidth: 22 8 | implicitHeight: 22 9 | 10 | Image { 11 | anchors.fill: parent 12 | anchors.margins: 1 13 | source: skin.light ? "questionMarkDarker.png" : "questionMark.png" 14 | mipmap: true 15 | } 16 | MouseArea { 17 | id: mouse 18 | anchors.fill: parent 19 | hoverEnabled: true 20 | 21 | } 22 | 23 | BaseToolTip { 24 | visible: mouse.containsMouse 25 | text: hint 26 | font.pixelSize: 13 27 | delay: 1 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /common/qmlQianHints/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/common/qmlQianHints/error.png -------------------------------------------------------------------------------- /common/qmlQianHints/questionMark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/common/qmlQianHints/questionMark.png -------------------------------------------------------------------------------- /common/qmlQianHints/questionMarkDarker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/common/qmlQianHints/questionMarkDarker.png -------------------------------------------------------------------------------- /common/qmlQianHints/remind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/common/qmlQianHints/remind.png -------------------------------------------------------------------------------- /common/qmlQianHints/true.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/common/qmlQianHints/true.png -------------------------------------------------------------------------------- /common/qmlQianStretchList/QianStretchDalegate.qml: -------------------------------------------------------------------------------- 1 | import QtQuick.Controls 2.14 2 | import QtQuick.Layouts 1.14 3 | import QtQuick 2.14 4 | import QtGraphicalEffects 1.14 5 | import Qt.Singleton 1.0 6 | Item { 7 | id: container 8 | width: skin.gradSupport ? ListView.view.width : ListView.view.width-10 9 | height: columnlayout.height 10 | 11 | 12 | property int itemLeftMargin: 10 + tier*10 13 | 14 | property int itemIndex: index 15 | property int crtIndex: container.ListView.view.currentIndex 16 | 17 | 18 | 19 | function checkCurrentIndexIsChild(subitem) { 20 | 21 | if(subitem.count <= 0) return false; 22 | 23 | for(let i = 0; i < subitem.count; i++) { 24 | let model = subitem.get(i); 25 | 26 | if(model.subItem.count > 0) { 27 | let ret = checkCurrentIndexIsChild(model.subItem); 28 | if(ret != null) { 29 | return ret; 30 | } 31 | } else { 32 | if(model.toIndex == strechCurrentIndex) 33 | return true; 34 | } 35 | 36 | } 37 | return false; 38 | 39 | } 40 | 41 | property int dataState: strechCurrentIndex == toIndex ? 0 : mouse.containsMouse ? 1 42 | : checkCurrentIndexIsChild(subItem) ? 2 : -1 43 | 44 | ColumnLayout { 45 | id: columnlayout 46 | anchors.centerIn: parent 47 | 48 | width: parent.width 49 | spacing: 0 50 | 51 | Item { 52 | id: content 53 | Layout.fillWidth: true 54 | Layout.preferredHeight: itemHeight 55 | 56 | 57 | Rectangle { 58 | id: frontRect 59 | anchors.fill: parent 60 | anchors.leftMargin: skin.gradSupport ? 28 : 18 61 | anchors.rightMargin: skin.gradSupport ? -frontRect.height/2 : 18 62 | anchors.topMargin: 9 63 | anchors.bottomMargin: 9 64 | 65 | color: !skin.light && dataState == 2 ? skin.stretchFoldBackSelectColor : subItem.count? skin.stretchFoldBackColor : 66 | toIndex == strechCurrentIndex ? skin.stretchSelectBackColor : 67 | mouse.containsMouse ? skin.stretchBackHoverColor : skin.stretchBackColor 68 | 69 | 70 | Behavior on color { 71 | ColorAnimation { duration: 200 } 72 | } 73 | 74 | radius: skin.gradSupport ? frontRect.height/2 : 6 75 | RowLayout { 76 | anchors.fill: parent 77 | anchors.margins: 10 78 | anchors.leftMargin: subItem.count > 0 && (skin.gradSupport) ? itemLeftMargin-20 : itemLeftMargin 79 | anchors.rightMargin: 20 80 | 81 | Image { 82 | visible: subItem.count > 0 ? true : false 83 | Layout.alignment : Qt.AlignVCenter | Qt.AlignLeft 84 | Layout.preferredWidth: 20 85 | Layout.preferredHeight: 20 86 | mipmap: true 87 | source: "./icons/indicator_right.png" 88 | rotation: !stretch ? 0 : 90 89 | 90 | Behavior on rotation { 91 | NumberAnimation { duration: 200 } 92 | } 93 | ColorOverlay{ 94 | anchors.fill: parent 95 | source: parent 96 | color: stretch ? skin.stretchFoldSelectColor : skin.stretchColor 97 | } 98 | 99 | } 100 | 101 | Text { 102 | Layout.leftMargin: 4 103 | font.family: "Microsoft Yahei" 104 | text: name 105 | font.pixelSize: 16 106 | color: stretch ? skin.stretchFoldSelectColor : 107 | toIndex == strechCurrentIndex ? skin.stretchSelectColor : skin.stretchColor 108 | 109 | 110 | elide: Text.ElideRight 111 | clip: true 112 | scale: tier < 4 ? 1.0 - tier*0.04 : 0.84 113 | 114 | } 115 | 116 | 117 | Rectangle { 118 | visible: hintNumber < 0 ? false : true 119 | Layout.preferredWidth: hintNum.contentWidth < 22 ? 22 : hintNum.contentWidth+6 120 | Layout.preferredHeight: 22 121 | 122 | 123 | color: "#FF5E54" 124 | radius: Layout.preferredHeight / 2 125 | Text { 126 | id: hintNum 127 | anchors.centerIn: parent 128 | font.family: "Microsoft Yahei" 129 | text: hintNumber > 999 ? "999+" : hintNumber 130 | font.pixelSize: 12 131 | color: "#FFF" 132 | } 133 | scale: tier < 4 ? 1.0 - tier*0.08 : 0.76 134 | } 135 | 136 | Item { 137 | Layout.fillWidth: true 138 | } 139 | 140 | 141 | } 142 | 143 | } 144 | 145 | 146 | 147 | 148 | MouseArea { 149 | id: mouse 150 | anchors.fill: parent 151 | hoverEnabled: true 152 | onClicked: { 153 | if(subItem.count > 0) { 154 | stretch = !stretch 155 | } else if(strechCurrentIndex != toIndex) { 156 | strechCurrentName = name 157 | strechCurrentIndex = toIndex 158 | switchPage(strechCurrentName) 159 | } 160 | } 161 | } 162 | } 163 | 164 | ListView { 165 | id: subView 166 | model: subItem 167 | Layout.fillWidth: true 168 | Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter 169 | 170 | Layout.preferredHeight: stretch ?subView.contentHeight : 0 171 | visible: true 172 | clip: true 173 | currentIndex: -1 174 | delegate: stretchList.delegate 175 | 176 | Behavior on Layout.preferredHeight { 177 | NumberAnimation { duration: 200 } 178 | } 179 | 180 | displaced: Transition { 181 | NumberAnimation { properties: "x,y"; duration: 90 } 182 | } 183 | } 184 | 185 | } 186 | 187 | 188 | } 189 | -------------------------------------------------------------------------------- /common/qmlQianStretchList/QianStretchEntry.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.14 3 | import QtQuick.Layouts 1.14 4 | import QtQml.Models 2.12 5 | import Qt.Singleton 1.0 6 | import "qrc:/common" 7 | 8 | Item { 9 | signal switchPage(string name) 10 | property int strechCurrentIndex: 0 11 | property int strechLength: 0 12 | 13 | property var itemsArrays: [ 14 | { 15 | name: "基础组件", 16 | stretch: true, 17 | subItem: [ 18 | { 19 | name: "Buttons", 20 | }, 21 | { 22 | name: "Other", 23 | }, 24 | { 25 | name: "提示", 26 | } 27 | ] 28 | }, 29 | 30 | { 31 | name: "个人开源", 32 | icon: "", 33 | stretch: false, 34 | subItem: [ 35 | { 36 | name: "合成大西瓜", 37 | }, 38 | { 39 | name: "图片预览器", 40 | }, 41 | { 42 | name: "DragView", 43 | } 44 | ] 45 | } 46 | ] 47 | 48 | 49 | ListModel { 50 | id: stretchModel 51 | dynamicRoles : true 52 | } 53 | 54 | 55 | property int itemHeight: 60 // 184 * 60 56 | property string strechCurrentName: "" 57 | property var alarmObjItem: null 58 | 59 | 60 | 61 | // 校验未知 62 | function checkUnknown(field, defaultData) { 63 | return field == undefined ? defaultData : field 64 | } 65 | 66 | function createModel(target, tier) { 67 | 68 | 69 | let idx = -999 70 | if( target.subItem == undefined || !target.subItem.length) { 71 | idx = strechLength 72 | strechLength += 1 73 | } 74 | 75 | 76 | return { 77 | 'name': target.name, 78 | 'icon': checkUnknown(target.icon, ""), 79 | 'hintNumber': checkUnknown(target.hintNumber, -1), 80 | 'stretch': checkUnknown(target.stretch, false), 81 | 'tier': tier, 82 | 'subItem' : [], 83 | 'toIndex' : idx, 84 | }; 85 | } 86 | 87 | function createModel2(name, icon, tier, toIndex, hintNumber) { 88 | 89 | return { 90 | 'name': name, 91 | 'icon': icon, 92 | 'hintNumber': hintNumber, 93 | 'stretch': false, 94 | 'tier': tier, 95 | 'subItem' : [], 96 | 'toIndex' : toIndex, 97 | }; 98 | } 99 | 100 | function appendSubItem(parent, subItem, tier) { 101 | if (subItem == undefined || subItem.length == 0) return; 102 | 103 | 104 | 105 | for(let i = 0; i < subItem.length; i++) { 106 | 107 | let model = createModel(subItem[i], tier); 108 | 109 | parent.subItem.append(model); 110 | 111 | let count = appendSubItem(parent.subItem.get(parent.subItem.count-1), subItem[i].subItem, tier+1); 112 | } 113 | } 114 | 115 | 116 | function searchItemByToIndex(parent, toIndex) { 117 | 118 | for(let i = 0; i < parent.count; i++) { 119 | 120 | let model = parent.get(i); 121 | 122 | if(model.toIndex == toIndex) 123 | return model; 124 | 125 | if(model.subItem.count > 0) { 126 | let ret = searchItemByToIndex(model.subItem, toIndex); 127 | if(ret != null) { 128 | return ret; 129 | } 130 | } 131 | } 132 | return null; 133 | } 134 | 135 | 136 | Component.onCompleted: { 137 | for(let i = 0; i < itemsArrays.length; i++) { 138 | 139 | let tier = 0; 140 | let model = createModel(itemsArrays[i], tier); 141 | stretchModel.append(model); 142 | appendSubItem(stretchModel.get(stretchModel.count-1), itemsArrays[i].subItem, tier+1); 143 | 144 | } 145 | 146 | } 147 | 148 | 149 | ColumnLayout { 150 | anchors.fill: parent 151 | ListView { 152 | id: stretchList 153 | Layout.fillHeight: true 154 | Layout.topMargin: 8 155 | Layout.bottomMargin: 8 156 | Layout.rightMargin: skin.gradSupport ? 0 :6 157 | Layout.fillWidth: true 158 | clip: true 159 | currentIndex: -1 160 | model: stretchModel 161 | 162 | 163 | 164 | delegate: QianStretchDalegate { 165 | } 166 | 167 | displaced: Transition { 168 | NumberAnimation { properties: "x,y"; duration: 90 } 169 | } 170 | 171 | ScrollBar.vertical: ScrollBar { 172 | id: scroll1 173 | policy: size<1.0? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff 174 | x: skin.gradSupport ? 8 : stretchList.width-8 175 | 176 | contentItem: Rectangle { 177 | implicitWidth: 8 178 | implicitHeight: 100 179 | radius: width / 2 180 | color: skin.light ? skin.stretchSelectBackColor : accentOpacityHoverColor 181 | } 182 | width: 8 183 | background: Item { 184 | 185 | } 186 | } 187 | } 188 | 189 | 190 | 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /common/qmlQianStretchList/icons/indicator_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/common/qmlQianStretchList/icons/indicator_right.png -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "frameless.h" 5 | #include 6 | #include 7 | #include 8 | #include "Backed.h" 9 | #include "./pages/QianProjectPages/QianDragViewPage/qiandrageventcatch.h" 10 | 11 | 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 16 | QCoreApplication::setOrganizationName("Some organization"); 17 | QApplication app(argc, argv); 18 | QQuickStyle::setStyle("Material"); 19 | 20 | 21 | QQmlApplicationEngine engine; 22 | 23 | qmlRegisterType("Qt.QianDragEventCatch", 1, 0, "QianDragEventCatch"); 24 | qmlRegisterType("Qt.Window", 1, 0, "Frameless"); 25 | qmlRegisterSingletonType(QUrl("qrc:/common/SkinModel.qml"), "Qt.Singleton", 1, 0, "SkinSingleton"); 26 | qmlRegisterSingletonType("Qt.Backed", 1, 0, "Backed", Backed_qobject_provider); 27 | 28 | 29 | const QUrl url(QStringLiteral("qrc:/main.qml")); 30 | QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, 31 | &app, [url](QObject *obj, const QUrl &objUrl) { 32 | if (!obj && url == objUrl) 33 | QCoreApplication::exit(-1); 34 | }, Qt::QueuedConnection); 35 | engine.load(url); 36 | 37 | return app.exec(); 38 | } 39 | -------------------------------------------------------------------------------- /main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.14 2 | import QtGraphicalEffects 1.12 3 | import Qt.Window 1.0 4 | import QtQuick.Window 2.14 5 | import Qt.Singleton 1.0 6 | import QtQuick.Controls.Material 2.12 7 | import Qt.labs.platform 1.1 8 | import Qt.labs.settings 1.0 9 | 10 | Frameless { 11 | id: rootWindow 12 | 13 | property string titleStr: "QianWindow" 14 | property var areas: [ 15 | Qt.rect(0, 0, 99999, 42) 16 | ] 17 | 18 | property color accentColor: SkinSingleton.skins[setting.skinIndex].accentColor // 皮肤深色 19 | property color accentContrlColor: SkinSingleton.skins[setting.skinIndex].accentContrlColor // 皮肤控件深色 20 | property color accentOpacityColor: Qt.rgba(accentColor.r, accentColor.g, accentColor.b, 0.5) // 皮肤控件深色透明 (一般用在滚动条) 21 | property color accentOpacityHoverColor: Qt.rgba(accentColor.r, accentColor.g, accentColor.b, 0.45) // 皮肤控件深色透明 淡色 (一般用在滚动条鼠标徘徊) 22 | 23 | property color tingeColor: skin.light ? "#555" : "#b1b1b1" // 皮肤淡色(白色皮肤为浅黑 黑色皮肤为灰色) 24 | property color tingeDrakerColor: Qt.darker(tingeColor, 1.2) // 皮肤谈深色 25 | 26 | 27 | 28 | property color tingeOpacityColor: skin.light ? "#11000000" : "#11FFFFFF" // 皮肤谈透明色 29 | property color tingeOpacityLightColor: skin.light ? "#06000000" : "#06FFFFFF" // 皮肤谈透明色(亮) 30 | 31 | 32 | property color mainColor: !skin.gradSupport && !skin.imageSupport ? skin.mainColor : 33 | !skin.light ? Qt.rgba(0,0,0, skin.gradMainOpacity - setting.skinOpacity * 0.48) : Qt.rgba(1,1,1, skin.gradMainOpacity + setting.skinOpacity * 0.28) 34 | 35 | property var skin: SkinSingleton.skins[setting.skinIndex] 36 | 37 | 38 | Material.accent: accentColor 39 | Material.theme: skin.light ? Material.Light : Material.Dark 40 | Material.foreground: tingeColor 41 | width: 1150 42 | height: 750 43 | visible: true 44 | title: titleStr 45 | color: "transparent" 46 | resizable: true 47 | moveArea: areas 48 | minimumWidth: 1130 49 | minimumHeight: 730 50 | 51 | function closeFunc() { 52 | close(); 53 | } 54 | 55 | WindowEntry { 56 | anchors.fill: parent 57 | anchors.margins: rootWindow.maximized ? 0 : 8 58 | radius: rootWindow.maximized ? 0 : 4 59 | } 60 | 61 | 62 | 63 | Settings { 64 | id: setting 65 | property int skinIndex: 1 66 | property real skinOpacity: 1 67 | property string skinCustomFile: "" 68 | fileName: "app.ini" 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /pages/BaseControlPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.14 2 | import QtQuick.Window 2.14 3 | import QtQuick.Layouts 1.12 4 | import QtQuick.Controls 2.14 5 | import QtQuick.Controls.Material 2.12 6 | import "qrc:/common" 7 | Item { 8 | property int leftWidth: 182 9 | property int fontsize: 19 10 | ColumnLayout { 11 | anchors.fill: parent 12 | anchors.rightMargin: 60 13 | anchors.topMargin: 30 14 | anchors.bottomMargin: 30 15 | anchors.leftMargin: 60 16 | spacing: 10 17 | 18 | RowLayout { 19 | YaheiText { 20 | text: "Buttons" 21 | font.pixelSize: fontsize 22 | Layout.preferredWidth: leftWidth 23 | Layout.alignment: Qt.AlignTop | Qt.AlignLeft 24 | } 25 | ColumnLayout { 26 | spacing: 20 27 | RowLayout { 28 | spacing: 20 29 | SkinBaseButton { 30 | font.pixelSize: 14 31 | backRadius: 4 32 | text: "SkinBtn1" 33 | 34 | } 35 | SkinBaseButton2 { 36 | font.pixelSize: 14 37 | backRadius: 4 38 | text: "SkinBtn2" 39 | } 40 | } 41 | 42 | RowLayout { 43 | spacing: 20 44 | BaseButton { 45 | text: "Blue" 46 | Layout.preferredHeight: 28 47 | Layout.preferredWidth: 78 48 | font.pixelSize: 14 49 | backRadius: 4 50 | bckcolor: "#4785FF" 51 | } 52 | 53 | BaseButton { 54 | bckcolor: "#EC3315" 55 | Layout.preferredHeight: 28 56 | Layout.preferredWidth: 78 57 | font.pixelSize: 14 58 | backRadius: 4 59 | text: "Red" 60 | 61 | } 62 | 63 | BaseButton { 64 | text: "Yellow" 65 | Layout.preferredHeight: 28 66 | Layout.preferredWidth: 78 67 | font.pixelSize: 14 68 | backRadius: 4 69 | bckcolor: "#ED9709" 70 | } 71 | } 72 | 73 | } 74 | } 75 | 76 | Rectangle { 77 | height: 1 78 | color: tingeOpacityColor 79 | Layout.fillWidth: true 80 | Layout.topMargin: 12 81 | } 82 | 83 | RowLayout { 84 | YaheiText { 85 | text: "RadioButton" 86 | font.pixelSize: fontsize 87 | Layout.preferredWidth: leftWidth 88 | Layout.alignment: Qt.AlignTop | Qt.AlignLeft 89 | Layout.topMargin: 12 90 | } 91 | ColumnLayout { 92 | RadioButton { 93 | font.pixelSize: fontsize - 2 94 | indicator.width: 18 95 | indicator.height: 18 96 | 97 | font.family: "Microsoft Yahei" 98 | text: "Option 1" 99 | 100 | } 101 | RadioButton { 102 | font.pixelSize: fontsize - 2 103 | indicator.width: 18 104 | indicator.height: 18 105 | font.family: "Microsoft Yahei" 106 | text: "Option 2" 107 | } 108 | RadioButton { 109 | enabled: false 110 | font.pixelSize: fontsize - 2 111 | indicator.width: 18 112 | indicator.height: 18 113 | font.family: "Microsoft Yahei" 114 | text: "Option 3" 115 | } 116 | 117 | } 118 | } 119 | 120 | Rectangle { 121 | height: 1 122 | color: tingeOpacityColor 123 | Layout.fillWidth: true 124 | } 125 | 126 | RowLayout { 127 | YaheiText { 128 | text: "CheckBox" 129 | font.pixelSize: fontsize 130 | Layout.preferredWidth: leftWidth 131 | Layout.alignment: Qt.AlignTop | Qt.AlignLeft 132 | Layout.topMargin: 12 133 | 134 | } 135 | ColumnLayout { 136 | BaseCheckBox { 137 | font.pixelSize: fontsize - 2 138 | text: "Option 1" 139 | 140 | } 141 | BaseCheckBox { 142 | font.pixelSize: fontsize - 2 143 | text: "Option 2" 144 | } 145 | BaseCheckBox { 146 | enabled: false 147 | font.pixelSize: fontsize - 2 148 | text: "Option 3" 149 | } 150 | 151 | } 152 | } 153 | 154 | Rectangle { 155 | height: 1 156 | color: tingeOpacityColor 157 | Layout.fillWidth: true 158 | } 159 | 160 | RowLayout { 161 | YaheiText { 162 | text: "Switch" 163 | font.pixelSize: fontsize 164 | Layout.preferredWidth: leftWidth 165 | Layout.alignment: Qt.AlignTop | Qt.AlignLeft 166 | Layout.topMargin: 12 167 | 168 | } 169 | 170 | RowLayout { 171 | spacing: 20 172 | Switch { 173 | font.pixelSize: fontsize - 2 174 | indicator.height: 18 175 | font.family: "Microsoft Yahei" 176 | text: "Blue" 177 | Material.accent: "#4785FF" 178 | } 179 | Switch { 180 | font.pixelSize: fontsize - 2 181 | indicator.height: 18 182 | font.family: "Microsoft Yahei" 183 | text: "Red" 184 | Material.accent: "#EC3315" 185 | } 186 | Switch { 187 | enabled: false 188 | font.pixelSize: fontsize - 2 189 | indicator.height: 18 190 | font.family: "Microsoft Yahei" 191 | text: "Disable" 192 | 193 | } 194 | 195 | } 196 | 197 | } 198 | 199 | 200 | Item { 201 | Layout.fillHeight: true 202 | Layout.fillWidth: true 203 | } 204 | 205 | } 206 | 207 | } 208 | -------------------------------------------------------------------------------- /pages/BaseOtherControlPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.14 2 | import QtQuick.Window 2.14 3 | import QtQuick.Layouts 1.12 4 | import QtQuick.Controls 2.14 5 | import QtQuick.Controls.Material 2.12 6 | import "qrc:/common" 7 | Item { 8 | 9 | property int leftWidth: 182 10 | property int fontsize: 19 11 | ColumnLayout { 12 | anchors.fill: parent 13 | anchors.rightMargin: 60 14 | anchors.topMargin: 30 15 | anchors.bottomMargin: 30 16 | anchors.leftMargin: 60 17 | spacing: 22 18 | 19 | RowLayout { 20 | YaheiText { 21 | text: "Progress Bar" 22 | font.pixelSize: fontsize 23 | Layout.preferredWidth: leftWidth 24 | Layout.alignment: Qt.AlignTop | Qt.AlignLeft 25 | } 26 | ColumnLayout { 27 | spacing: 20 28 | ProgressBar { 29 | id: progress 30 | indeterminate: false 31 | implicitWidth: 220 32 | value: 0 33 | 34 | NumberAnimation on value { 35 | id: progressAnimation 36 | from: 0 37 | to: 1 38 | duration: 2000 39 | running: true 40 | loops: Animation.Infinite 41 | } 42 | } 43 | 44 | ProgressBar { 45 | indeterminate: true 46 | implicitWidth: 220 47 | } 48 | 49 | } 50 | } 51 | 52 | Rectangle { 53 | height: 1 54 | color: tingeOpacityColor 55 | Layout.fillWidth: true 56 | } 57 | 58 | RowLayout { 59 | YaheiText { 60 | text: "BusyIndicator" 61 | font.pixelSize: fontsize 62 | Layout.preferredWidth: leftWidth 63 | Layout.alignment: Qt.AlignTop | Qt.AlignLeft 64 | } 65 | ColumnLayout { 66 | spacing: 20 67 | RowLayout { 68 | spacing: 20 69 | BusyIndicator { 70 | running: true 71 | 72 | } 73 | 74 | BusyIndicator { 75 | running: true 76 | Material.accent: "#4785FF" 77 | 78 | } 79 | BusyIndicator { 80 | running: true 81 | Material.accent: "#EC3315" 82 | 83 | } 84 | BusyIndicator { 85 | running: true 86 | Material.accent: "#ED9709" 87 | 88 | } 89 | 90 | } 91 | 92 | } 93 | } 94 | Rectangle { 95 | height: 1 96 | color: tingeOpacityColor 97 | Layout.fillWidth: true 98 | } 99 | 100 | RowLayout { 101 | YaheiText { 102 | text: "Dial" 103 | font.pixelSize: fontsize 104 | Layout.preferredWidth: leftWidth 105 | Layout.alignment: Qt.AlignTop | Qt.AlignLeft 106 | } 107 | ColumnLayout { 108 | spacing: 20 109 | RowLayout { 110 | spacing: 20 111 | Dial { 112 | } 113 | 114 | Dial { 115 | Material.accent: "#4785FF" 116 | 117 | } 118 | Dial { 119 | Material.accent: "#EC3315" 120 | 121 | } 122 | Dial { 123 | Material.accent: "#ED9709" 124 | 125 | } 126 | 127 | } 128 | } 129 | } 130 | Rectangle { 131 | height: 1 132 | color: tingeOpacityColor 133 | Layout.fillWidth: true 134 | } 135 | 136 | 137 | RowLayout { 138 | YaheiText { 139 | text: "Slider" 140 | font.pixelSize: fontsize 141 | Layout.preferredWidth: leftWidth 142 | Layout.alignment: Qt.AlignTop | Qt.AlignLeft 143 | } 144 | ColumnLayout { 145 | spacing: 10 146 | RowLayout { 147 | spacing: 20 148 | YaheiText { 149 | text: "Skin Slider" 150 | font.pixelSize: fontsize 151 | Layout.preferredWidth: 134 152 | } 153 | Slider { 154 | from: 1 155 | value: 25 156 | to: 100 157 | } 158 | } 159 | 160 | RowLayout { 161 | spacing: 20 162 | YaheiText { 163 | text: "Blue Slider" 164 | font.pixelSize: fontsize 165 | Layout.preferredWidth: 134 166 | } 167 | Slider { 168 | from: 1 169 | value: 25 170 | to: 100 171 | Material.accent: "#4785FF" 172 | } 173 | } 174 | 175 | RowLayout { 176 | spacing: 20 177 | YaheiText { 178 | text: "Red Slider" 179 | font.pixelSize: fontsize 180 | Layout.preferredWidth: 134 181 | } 182 | Slider { 183 | from: 1 184 | value: 25 185 | to: 100 186 | Material.accent: "#EC3315" 187 | } 188 | } 189 | 190 | RowLayout { 191 | spacing: 20 192 | 193 | YaheiText { 194 | text: "Yellow Slider" 195 | font.pixelSize: fontsize 196 | Layout.preferredWidth: 134 197 | } 198 | Slider { 199 | from: 1 200 | value: 25 201 | to: 100 202 | Material.accent: "#ED9709" 203 | } 204 | } 205 | 206 | 207 | } 208 | } 209 | 210 | 211 | 212 | Item { 213 | Layout.fillHeight: true 214 | Layout.fillWidth: true 215 | } 216 | 217 | 218 | 219 | 220 | 221 | } 222 | 223 | } 224 | -------------------------------------------------------------------------------- /pages/HintPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.14 2 | import QtQuick.Window 2.14 3 | import QtQuick.Layouts 1.12 4 | import QtQuick.Controls 2.14 5 | import QtQuick.Controls.Material 2.12 6 | import "qrc:/common" 7 | import "qrc:/common/qmlQianHints" 8 | import "qrc:/common/qmlQianDialog" 9 | Item { 10 | property int leftWidth: 182 11 | property int fontsize: 19 12 | 13 | Message{ 14 | id:messageTip 15 | z: 1 16 | parent: Overlay.overlay 17 | } 18 | 19 | function message(type, message) { 20 | if(type!=='success'&&type!=='error'&&type!=='info'){ 21 | return false 22 | } 23 | messageTip.open(type, message) 24 | } 25 | 26 | SkinQianDialog { 27 | id: skinQianDialog 28 | backParent: windowEntry 29 | parent: Overlay.overlay 30 | onAccept: { 31 | message('success', "You clicked the accept button!") 32 | skinQianDialog.close(); 33 | } 34 | } 35 | 36 | 37 | 38 | ColumnLayout { 39 | anchors.fill: parent 40 | anchors.rightMargin: 60 41 | anchors.topMargin: 30 42 | anchors.bottomMargin: 30 43 | anchors.leftMargin: 60 44 | spacing: 22 45 | 46 | RowLayout { 47 | YaheiText { 48 | text: "Top Hint" 49 | font.pixelSize: fontsize 50 | Layout.preferredWidth: leftWidth 51 | Layout.alignment: Qt.AlignTop | Qt.AlignLeft 52 | } 53 | ColumnLayout { 54 | spacing: 20 55 | 56 | SkinBaseButton { 57 | font.pixelSize: 14 58 | backRadius: 4 59 | text: "Info" 60 | onClicked: message('info', "You clicked the info button!") 61 | } 62 | SkinBaseButton { 63 | font.pixelSize: 14 64 | backRadius: 4 65 | text: "Error" 66 | onClicked: message('error', "You clicked the error button!") 67 | } 68 | SkinBaseButton { 69 | font.pixelSize: 14 70 | backRadius: 4 71 | text: "Success" 72 | onClicked: message('success', "You clicked the success button!") 73 | } 74 | 75 | } 76 | } 77 | 78 | Rectangle { 79 | height: 1 80 | color: tingeOpacityColor 81 | Layout.fillWidth: true 82 | } 83 | 84 | RowLayout { 85 | YaheiText { 86 | text: "对话框" 87 | font.pixelSize: fontsize 88 | Layout.preferredWidth: leftWidth 89 | Layout.alignment: Qt.AlignTop | Qt.AlignLeft 90 | } 91 | ColumnLayout { 92 | spacing: 20 93 | RowLayout { 94 | spacing: 40 95 | SkinBaseButton { 96 | font.pixelSize: 14 97 | backRadius: 4 98 | text: "无标题询问" 99 | onClicked: skinQianDialog.dialogOpen(SkinQianDialog.DialogQuestion, "是否需要清理任务?") 100 | } 101 | SkinBaseButton { 102 | font.pixelSize: 14 103 | backRadius: 4 104 | text: "带标题询问" 105 | onClicked: skinQianDialog.dialogOpen(SkinQianDialog.DialogQuestion, "是否需要清理任务?", "任务清理") 106 | } 107 | } 108 | 109 | RowLayout { 110 | spacing: 40 111 | BaseButton { 112 | font.pixelSize: 14 113 | backRadius: 4 114 | text: "无标题成功" 115 | bckcolor: "#4785FF" 116 | onClicked: skinQianDialog.dialogOpen(SkinQianDialog.DialogSuccess, "任务清理完成! 请重启软件生效!") 117 | } 118 | BaseButton { 119 | font.pixelSize: 14 120 | backRadius: 4 121 | text: "带标题成功" 122 | bckcolor: "#4785FF" 123 | onClicked: skinQianDialog.dialogOpen(SkinQianDialog.DialogSuccess, "任务清理完成! 请重启软件生效!", "任务清理") 124 | } 125 | } 126 | RowLayout { 127 | spacing: 40 128 | BaseButton { 129 | font.pixelSize: 14 130 | backRadius: 4 131 | text: "无标题提示" 132 | bckcolor: "#16B7BF" 133 | onClicked: skinQianDialog.dialogOpen(SkinQianDialog.DialogInformation, "当前没有任务可以清理!") 134 | } 135 | BaseButton { 136 | font.pixelSize: 14 137 | backRadius: 4 138 | text: "带标题提示" 139 | bckcolor: "#16B7BF" 140 | onClicked: skinQianDialog.dialogOpen(SkinQianDialog.DialogInformation, "当前没有任务可以清理!", "任务清理") 141 | } 142 | } 143 | 144 | RowLayout { 145 | spacing: 40 146 | BaseButton { 147 | font.pixelSize: 14 148 | backRadius: 4 149 | text: "无标题错误" 150 | bckcolor: "#EC3315" 151 | onClicked: skinQianDialog.dialogOpen(SkinQianDialog.DialogError, "清理任务失败,请检查用户权限!") 152 | } 153 | BaseButton { 154 | font.pixelSize: 14 155 | backRadius: 4 156 | text: "带标题错误" 157 | bckcolor: "#EC3315" 158 | onClicked: skinQianDialog.dialogOpen(SkinQianDialog.DialogError, "清理任务失败,请检查用户权限!", "任务清理") 159 | } 160 | } 161 | 162 | 163 | } 164 | } 165 | 166 | Rectangle { 167 | height: 1 168 | color: tingeOpacityColor 169 | Layout.fillWidth: true 170 | } 171 | 172 | RowLayout { 173 | YaheiText { 174 | text: "提示标记" 175 | font.pixelSize: fontsize 176 | Layout.preferredWidth: leftWidth 177 | Layout.alignment: Qt.AlignTop | Qt.AlignLeft 178 | } 179 | ColumnLayout { 180 | spacing: 20 181 | 182 | RowLayout { 183 | BaseCheckBox { 184 | font.pixelSize: fontsize - 2 185 | text: "开启GPU渲染" 186 | 187 | } 188 | QianQuestionMark { 189 | hint: "如果支持GPU,开启GPU渲染更加流畅" 190 | } 191 | 192 | } 193 | 194 | RowLayout { 195 | BaseCheckBox { 196 | font.pixelSize: fontsize - 2 197 | text: "开启安全防护" 198 | } 199 | QianQuestionMark { 200 | hint: "开启后不被其他恶意软件篡改" 201 | } 202 | 203 | } 204 | 205 | 206 | 207 | 208 | } 209 | } 210 | 211 | 212 | 213 | 214 | 215 | 216 | Item { 217 | Layout.fillHeight: true 218 | Layout.fillWidth: true 219 | } 220 | 221 | } 222 | 223 | } 224 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianDragViewPage/QianDragDelegate.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Layouts 1.14 3 | import QtQuick.Controls 2.14 4 | Item { 5 | id: container 6 | signal closeRequest() 7 | height: ListView.view.height 8 | width: contentLayout.width 9 | states: State { 10 | name: "remove"; 11 | PropertyChanges { target: container; y: ListView.view.height } 12 | } 13 | 14 | transitions: Transition { 15 | SequentialAnimation { 16 | NumberAnimation { properties: "y"; duration: 200 } 17 | ScriptAction { script: closeRequest() } 18 | } 19 | } 20 | 21 | function informationContains(x, y) { 22 | if(x >= information.x && (x) <= information.x + information.width 23 | && y >= information.y && (y) <= information.y + information.height) 24 | return true 25 | 26 | return false 27 | } 28 | 29 | RowLayout { 30 | id: contentLayout 31 | Layout.margins: 4 32 | y: (container.height - itemHeight)/2 33 | spacing: 0 34 | Rectangle { 35 | radius: 2 36 | Layout.preferredHeight: itemHeight 37 | Layout.preferredWidth: interval 38 | visible: (index == dragDelegate.dragIndex) && (index != dragDelegate.pressIndex) 39 | && (index-1 != dragDelegate.pressIndex) 40 | color: "#FED963" 41 | } 42 | 43 | QianDragDelegateInformation { 44 | id: information 45 | isSelect: container.ListView.view.currentIndex == index 46 | opacity: dragDelegate.pressIndex == index ? 0.6 : 1.0 47 | onRequestRemove: { 48 | container.state = "remove"; 49 | } 50 | modelData: model 51 | Behavior on color { 52 | ColorAnimation { duration: 200 } 53 | } 54 | } 55 | Rectangle { 56 | radius: 1 57 | Layout.preferredHeight: itemHeight 58 | Layout.preferredWidth: interval 59 | 60 | visible: index+1 == container.ListView.view.count && (index+1 == dragDelegate.dragIndex) && (index != dragDelegate.pressIndex) 61 | color: "#FED963" 62 | 63 | } 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianDragViewPage/QianDragDelegateInformation.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Layouts 1.14 3 | import QtQuick.Controls 2.14 4 | import QtGraphicalEffects 1.14 5 | import ".." 6 | import "qrc:/common" 7 | Rectangle { 8 | id: container 9 | property var modelData: null 10 | property bool isSelect: false 11 | signal requestRemove() 12 | 13 | radius: itemRadius 14 | Layout.margins: 4 15 | implicitHeight: itemHeight 16 | implicitWidth: itemWidth 17 | color: isSelect ? "#FED963" : skin.light ? "#F1F1F1" : "#222" 18 | clip: true 19 | 20 | layer.enabled: true 21 | layer.effect: DropShadow { 22 | horizontalOffset: 1 23 | verticalOffset: 1 24 | color: "#000" 25 | } 26 | 27 | ImageButton { 28 | anchors.top: parent.top 29 | anchors.right: parent.right 30 | anchors.topMargin: 5 31 | anchors.rightMargin: 5 32 | width: 49 33 | height: 49 34 | imageSrc: "qrc:/pages/QianProjectPages/QianDragViewPage/remove.png" 35 | backHoverColor: skin.light ? "#02000000" : "#11FFFFFF" 36 | ToolTip.delay: 1000 37 | ToolTip.visible: hovered 38 | ToolTip.text: qsTr("删除") 39 | onClicked: requestRemove() 40 | } 41 | 42 | Text { 43 | anchors.centerIn: parent 44 | color: isSelect ? "#AC2727" : skin.light ? "#F2732E" : "#FED963"; 45 | text: modelData == null ? "" : modelData.name 46 | font.pixelSize: itemPixSize 47 | font.family: "Microsoft Yahei" 48 | elide: Text.ElideRight 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianDragViewPage/QianDragView.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.14 2 | import QtQuick.Controls 2.14 3 | import Qt.QianDragEventCatch 1.0 4 | 5 | Flickable { 6 | id: contains 7 | property real itemWidth: 140 8 | property real itemHeight: 180 9 | property int itemPixSize: 20 10 | property int interval: 4 11 | property int itemRadius: 5 12 | property int animatioMoveIndex: -1 13 | property int maxFlickVelocity: 0 14 | property alias chatView : _chatView 15 | 16 | 17 | function append(text) { 18 | modelData.append({"name": text}) 19 | chatView.positionViewAtIndex(modelData.count-1, ListView.End) 20 | } 21 | 22 | QianDragEventCatch { 23 | id: dragCatch 24 | container: contains 25 | filterObj: _chatView 26 | 27 | property bool isDrag: false 28 | property int pressMouseX: 0 29 | property int pressMouseY: 0 30 | property int pressItemX: 0 31 | property int pressItemY: 0 32 | property int pressIndex: -1 33 | 34 | onReleased: { 35 | chatView.interactive = true 36 | if (!dragDelegate.visible) { 37 | chatView.currentIndex = chatView.currentIndex == pressIndex ? -1 : pressIndex 38 | } else { 39 | isDrag = false; 40 | dragDelegate.finish() 41 | } 42 | } 43 | onPressed: { 44 | if(mouseY >= (chatView.height - itemHeight)/2 && mouseY <= (chatView.height + itemHeight)/2) { 45 | chatView.interactive = false 46 | pressIndex = chatView.indexAt(mouseX+chatView.contentX, mouseY); 47 | if(pressIndex<0) { 48 | catchEnable = false 49 | chatView.interactive = true 50 | return; 51 | } 52 | let item = chatView.itemAtIndex(pressIndex) 53 | if(item == null) { 54 | catchEnable = false 55 | chatView.interactive = true 56 | return; 57 | } 58 | let contains = item.informationContains(mouseX-item.x, mouseY -item.y) 59 | isDrag = false; 60 | pressMouseX = mouseX; 61 | pressMouseY = mouseY; 62 | pressItemX = item.x - chatView.contentX 63 | pressItemY = (chatView.height - itemHeight)/2; 64 | 65 | } else { 66 | isDrag = false 67 | catchEnable = false 68 | chatView.interactive = true 69 | } 70 | } 71 | onMoved: { 72 | if (isDrag == false && (Math.abs(pressMouseX-mouseX) > 4 || Math.abs(pressMouseY-mouseY) > 4) && !scrollAnimation.running) { 73 | dragDelegate.show(chatView.model.get(pressIndex), 74 | pressItemX, mouseX, pressIndex, pressItemY, mouseY) 75 | isDrag = true 76 | } else if (isDrag) { 77 | dragDelegate.move(mouseX, mouseY) 78 | } 79 | } 80 | } 81 | 82 | 83 | ListView { 84 | id: _chatView 85 | anchors.fill: parent 86 | currentIndex: -1 87 | 88 | orientation: ListView.Horizontal 89 | 90 | Component.onCompleted: { 91 | for(var i = 0; i < 5; i++) { 92 | modelData.append({"name": "数据块" + i}) 93 | } 94 | } 95 | 96 | model: ListModel { 97 | id: modelData 98 | } 99 | 100 | 101 | 102 | 103 | ScrollBar.horizontal: ScrollBar { 104 | id: scroll 105 | policy: size<1.0? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff 106 | 107 | contentItem: Rectangle { 108 | implicitHeight: 6 109 | implicitWidth: 100 110 | radius: 3 111 | color: scroll.pressed ? accentOpacityColor 112 | : accentOpacityHoverColor 113 | border.color: "#AAEF3007" 114 | border.width: dragDelegate.visible && (scroll.position == 0 || scroll.position >=(1.0 - scroll.visualSize)) ? 1 : 0 115 | 116 | 117 | } 118 | background: Item { 119 | 120 | } 121 | 122 | NumberAnimation on position { 123 | id: scrollAnimation 124 | duration: 300 125 | running: false 126 | function requestStart(from, to, duration) { 127 | scrollAnimation.from = from 128 | scrollAnimation.to = to 129 | scrollAnimation.duration = duration 130 | scrollAnimation.restart() 131 | } 132 | onRunningChanged: { 133 | if(!scrollAnimation.running && dragCatch.isDrag) { 134 | if(dragDelegate.visible) dragDelegate.update() 135 | } 136 | } 137 | } 138 | } 139 | 140 | NumberAnimation on x { 141 | id: xAnimation 142 | duration: 300 143 | running: false 144 | function requestStart(from, to) { 145 | xAnimation.from = from 146 | xAnimation.to = to 147 | xAnimation.restart() 148 | } 149 | 150 | } 151 | 152 | 153 | add: Transition { 154 | NumberAnimation { properties: "y"; from: -chatView.height; to: 0; duration: 150 } 155 | } 156 | move: Transition { 157 | NumberAnimation { properties: "x,y"; duration: 180 } 158 | } 159 | 160 | moveDisplaced: Transition { 161 | SequentialAnimation { 162 | ScriptAction{ 163 | script: { 164 | let item = chatView.itemAtIndex(animatioMoveIndex) 165 | if(item != null) item.z = 100 166 | } 167 | } 168 | 169 | NumberAnimation { properties: "x,y"; duration: 180 } 170 | ScriptAction{ 171 | script: { 172 | let item = chatView.itemAtIndex(animatioMoveIndex) 173 | if(item != null) item.z = 1 174 | } 175 | } 176 | } 177 | } 178 | displaced: Transition { 179 | NumberAnimation { properties: "x,y"; duration: 180 } 180 | } 181 | 182 | delegate: QianDragDelegate { 183 | id: delegate 184 | onCloseRequest: { 185 | chatView.model.remove(index) 186 | } 187 | } 188 | QianDragDelegateInformation { 189 | id: dragDelegate 190 | visible: false 191 | height: itemHeight 192 | width: itemWidth 193 | property int pressX: 0 194 | property int pressY: 0 195 | property int baseY: 0 196 | property int baseX: 0 197 | property int dragIndex: -99 198 | property int pressIndex: -99 199 | function show(data,baseX,preX,pressIndex, baseY,preY) { 200 | dragDelegate.modelData = data 201 | dragDelegate.pressIndex = pressIndex 202 | dragDelegate.isSelect = pressIndex == chatView.currentIndex 203 | pressX = preX 204 | x = baseX 205 | dragDelegate.baseX = baseX 206 | dragDelegate.baseY = baseY 207 | pressY = preY 208 | y = baseY 209 | visible = true 210 | } 211 | 212 | function finish() { 213 | visible = false 214 | var index = dragIndex; 215 | if (index > 1 && pressIndex itemWidth/2 ? index+1 : index; 235 | } 236 | 237 | let to; 238 | let step; 239 | 240 | if(x < itemWidth/4 && scroll.position > 0) { 241 | let step = scroll.visualSize*0.12; 242 | to = scroll.position - step 243 | if(to < 0) { 244 | to = 0 245 | } 246 | scrollAnimation.requestStart(scroll.position, to, 200) 247 | } else if(scrollAnimation.running && x >= itemWidth/4 && x <= itemWidth/4 && scroll.position > 0) { 248 | scrollAnimation.stop() 249 | } else if(x >= (chatView.width-itemWidth*0.75) && scroll.visualSize > 0 && scroll.position <(1.0 - scroll.visualSize)) { 250 | let step = scroll.visualSize*0.12; 251 | to = scroll.position + step 252 | if(to > 1.0 - scroll.visualSize) { 253 | to = 1.0 - scroll.visualSize 254 | } 255 | scrollAnimation.requestStart(scroll.position, to, 200) 256 | } 257 | 258 | } 259 | 260 | function move(mvX, mvY) { 261 | var movex = mvX - pressX 262 | x = movex + baseX 263 | var movey = mvY - pressY 264 | y = movey + baseY 265 | update(); 266 | } 267 | 268 | } 269 | } 270 | 271 | } 272 | 273 | 274 | 275 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianDragViewPage/QianDragViewPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.14 2 | import QtQuick.Window 2.14 3 | import QtQuick.Layouts 1.12 4 | import QtQuick.Controls 2.14 5 | import QtQuick.Controls.Material 2.12 6 | import "qrc:/common" 7 | Item { 8 | 9 | property int index: 5 10 | ColumnLayout { 11 | anchors.fill: parent 12 | anchors.margins: 10 13 | spacing: 22 14 | 15 | property int index: 5 16 | 17 | RowLayout { 18 | Layout.fillWidth: true 19 | 20 | spacing: 5 21 | BaseTextField { 22 | id: input 23 | Layout.fillWidth: true 24 | Layout.preferredHeight: 32 25 | text: "数据块" + index 26 | font.pixelSize: 18 27 | font.family: "Microsoft Yahei" 28 | 29 | 30 | } 31 | SkinBaseButton { 32 | id: btn 33 | text: "添加" 34 | font.pixelSize: 17 35 | backRadius: 4 36 | onClicked: { 37 | if (input.text.length > 0) { 38 | list.append(input.text) 39 | index += 1 40 | input.text = "数据块" + index 41 | } 42 | } 43 | } 44 | } 45 | 46 | QianDragView { 47 | id: list 48 | Layout.fillWidth: true 49 | Layout.fillHeight: true 50 | clip: true 51 | } 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianDragViewPage/qiandrageventcatch.cpp: -------------------------------------------------------------------------------- 1 | #include "qiandrageventcatch.h" 2 | #include 3 | #include 4 | QianDragEventCatch::QianDragEventCatch(QObject *parent) : QObject(parent) 5 | { 6 | 7 | } 8 | 9 | 10 | QianDragEventCatch::~QianDragEventCatch() 11 | { 12 | if (_container) 13 | _container->removeEventFilter(this); 14 | 15 | if (_filterObj) 16 | _filterObj->removeEventFilter(this); 17 | 18 | } 19 | 20 | void QianDragEventCatch::setContainer(QObject *target) 21 | { 22 | if (!target) return; 23 | 24 | if (_container != target) { 25 | if (_container) _container->removeEventFilter(this); 26 | target->installEventFilter(this); 27 | _container = target; 28 | emit containerChanged(); 29 | } 30 | } 31 | 32 | void QianDragEventCatch::setFilterObj(QObject *target) 33 | { 34 | if (!target) return; 35 | 36 | if (_filterObj != target) { 37 | if (_filterObj) _filterObj->removeEventFilter(this); 38 | target->installEventFilter(this); 39 | _filterObj = target; 40 | emit filterObjChanged(); 41 | } 42 | } 43 | 44 | 45 | bool QianDragEventCatch::eventFilter(QObject *obj, QEvent *evt) 46 | { 47 | QMouseEvent *mouse = dynamic_cast(evt); 48 | if(mouse ) { 49 | if(mouse->button() == Qt::LeftButton && mouse->type() == QEvent::MouseButtonPress) { 50 | _catchEnable = true; 51 | emit pressed(mouse->pos().x(), mouse->pos().y()); 52 | } else if(mouse->buttons() == Qt::LeftButton && mouse->type() == QEvent::MouseMove && _catchEnable) { 53 | emit moved(mouse->pos().x(), mouse->pos().y()); 54 | } else if(mouse->button() == Qt::LeftButton && mouse->type() ==QEvent::MouseButtonRelease && _catchEnable) { 55 | emit released(mouse->pos().x(), mouse->pos().y()); 56 | } 57 | } 58 | return QObject::eventFilter(obj, evt); 59 | } 60 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianDragViewPage/qiandrageventcatch.h: -------------------------------------------------------------------------------- 1 | #ifndef QianDragEventCatch_H 2 | #define QianDragEventCatch_H 3 | 4 | #include 5 | 6 | class QianDragEventCatch : public QObject 7 | { 8 | Q_OBJECT 9 | Q_PROPERTY(QObject* container READ container WRITE setContainer NOTIFY containerChanged) 10 | Q_PROPERTY(QObject* filterObj READ filterObj WRITE setFilterObj NOTIFY filterObjChanged) 11 | 12 | Q_PROPERTY(bool catchEnable MEMBER _catchEnable NOTIFY catchEnableChanged) 13 | signals: 14 | void containerChanged(); 15 | void filterObjChanged(); 16 | void catchEnableChanged(); 17 | 18 | public: 19 | explicit QianDragEventCatch(QObject *parent = nullptr); 20 | ~QianDragEventCatch(); 21 | 22 | QObject *container() { return _container; } 23 | void setContainer(QObject *container); 24 | 25 | QObject *filterObj() { return _filterObj; } 26 | void setFilterObj(QObject *container); 27 | 28 | 29 | bool eventFilter(QObject *obj, QEvent *evt); 30 | 31 | 32 | signals: 33 | void released(int mouseX, int mouseY); 34 | void pressed(int mouseX, int mouseY); 35 | void moved(int mouseX, int mouseY); 36 | 37 | protected: 38 | 39 | QObject *_container{nullptr}; 40 | QObject *_filterObj{nullptr}; 41 | bool _catchEnable{true}; 42 | }; 43 | 44 | #endif // QianDragEventCatch_H 45 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianDragViewPage/remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianDragViewPage/remove.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/Ball.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 小球控件 3 | ** Author : 诺谦 https://blog.csdn.net/qq_37997682/article/details/126640154 4 | ** Create : 2021-5-24 5 | ****************************************************************************/ 6 | 7 | import QtQuick 2.12 8 | Image { 9 | id: img 10 | 11 | property var pointX: 0 12 | property var pointY: 0 13 | property var preX: 0 14 | property var preY: 0 15 | property var vx: 0 16 | property var vy: 0 17 | property var r: 0 18 | property var cor: 0 // 碰撞后的能量损失值,为 1 表示碰撞后不会损失能量 19 | property var mass: 0 // 小球质量,球体越大,质量越大 20 | property var rotate: 0 21 | property var ballType: 0 // 小球类型 22 | property var shapeChange: false // 形状是否在改变中,创建小球的时候,形状会慢慢变大,此时用户不能立即降落小球 23 | property var mergeSrc: "" // 合并时的动画资源 24 | property var mergeStart: false // 启动合并动画显示 25 | property var endPointX: 0 // 合并时的终点x坐标 26 | property var endPointY: 0 // 启动合的终点y坐标 27 | 28 | Behavior on width { 29 | NumberAnimation { 30 | id: widthAnima; duration: 300; 31 | 32 | 33 | onRunningChanged: shapeChange = running; 34 | } 35 | } 36 | 37 | Behavior on height { NumberAnimation { duration: 300; } } 38 | 39 | fillMode: Image.Stretch 40 | mipmap: true 41 | x: pointX - width/2 42 | y: pointY - height/2 43 | width: 0 44 | height: 0 45 | 46 | NumberAnimation on pointX { 47 | id: enPointXAnimation 48 | running: mergeStart == true 49 | to: endPointX; duration: 300 50 | } 51 | NumberAnimation on pointY { 52 | id: enPointYAnimation 53 | running: mergeStart == true 54 | to: endPointY; duration: 300 55 | } 56 | 57 | NumberAnimation on rotate { 58 | id: rotateAnimation 59 | running: mergeStart == true 60 | to: calcEndRotate() 61 | duration: 300 62 | onFinished: { 63 | preX = pointX 64 | preY = pointY 65 | mergeStart = false 66 | } 67 | } 68 | 69 | function calcEndRotate() { 70 | 71 | let distance = Math.sqrt(Math.pow((endPointX - pointX),2) + Math.pow((endPointY - pointY),2)); 72 | 73 | if (endPointX > pointX) // 往右 74 | return rotation + 360/(2 * r * 3.14) * distance * 0.5; 75 | else // 往左 76 | return rotation - 360/(2 * r * 3.14) * distance * 0.5; 77 | 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/BallRun.js: -------------------------------------------------------------------------------- 1 | .import QtQuick 2.0 as QQ 2 | 3 | 4 | var ballData = [ 5 | { 6 | "radius" : 125, 7 | "cor" : 0.2, 8 | "image" : "icon/ball1.png", 9 | "mergeImage" : "icon/merge2.png", 10 | }, 11 | { 12 | "radius" : 115, 13 | "cor" : 0.3, 14 | "image" : "icon/ball2.png", 15 | "mergeImage" : "icon/merge3.png", 16 | }, 17 | { 18 | "radius" : 105, 19 | "cor" : 0.3, 20 | "image" : "icon/ball3.png", 21 | "mergeImage" : "icon/merge4.png", 22 | }, 23 | { 24 | "radius" : 95, 25 | "cor" : 0.3, 26 | "image" : "icon/ball4.png", 27 | "mergeImage" : "icon/merge5.png", 28 | }, 29 | { 30 | "radius" : 80, 31 | "cor" : 0.3, 32 | "image" : "icon/ball5.png", 33 | "mergeImage" : "icon/merge6.png", 34 | }, 35 | { 36 | "radius" : 70, 37 | "cor" : 0.3, 38 | "image" : "icon/ball6.png", 39 | "mergeImage" : "icon/merge7.png", 40 | }, 41 | { 42 | "radius" : 60, 43 | "cor" : 0.3, 44 | "image" : "icon/ball7.png", 45 | "mergeImage" : "icon/merge8.png", 46 | }, 47 | { 48 | "radius" : 50, 49 | "cor" : 0.3, 50 | "image" : "icon/ball8.png", 51 | "mergeImage" : "icon/merge9.png", 52 | }, 53 | { 54 | "radius" : 40, 55 | "cor" : 0.3, 56 | "image" : "icon/ball9.png", 57 | "mergeImage" : "icon/merge10.png", 58 | }, 59 | { 60 | "radius" : 30, 61 | "cor" : 0.3, 62 | "image" : "icon/ball10.png", 63 | "mergeImage" : "icon/merge11.png", 64 | }, 65 | { 66 | "radius" : 20, 67 | "cor" : 0.1, 68 | "image" : "icon/ball11.png", 69 | "mergeImage" : "icon/merge11.png", 70 | }, 71 | ]; 72 | 73 | var component; 74 | var mergeComponent; 75 | var balls = new Array(0); 76 | var currentBall = null; 77 | 78 | 79 | function getBallData() { 80 | 81 | if (balls.length < 3) // 开场前3个都为葡萄 82 | return ballData.length - 1; 83 | 84 | else if (balls.length < 6) 85 | return Math.random() < 0.55 ? ballData.length - 1 : 86 | Math.random() < 0.55 ? ballData.length - 2 : 87 | Math.random() < 0.88 ? ballData.length - 3 : 88 | Math.random() < 0.77 ? ballData.length - 4 : 89 | Math.random() < 0.66 ? ballData.length - 5 : ballData.length - 6; 90 | 91 | else 92 | return Math.random() < 0.35 ? ballData.length - 1 : 93 | Math.random() < 0.25 ? ballData.length - 2 : 94 | Math.random() < 0.36 ? ballData.length - 3 : 95 | Math.random() < 0.40 ? ballData.length - 4 : ballData.length - 5; 96 | } 97 | 98 | 99 | function newBall(x) { 100 | if (component == null) 101 | component = Qt.createComponent("Ball.qml"); 102 | 103 | if (component.status == QQ.Component.Ready) { 104 | let index = getBallData(); 105 | 106 | if (x < ballData[index].radius) { 107 | x = ballData[index].radius 108 | } else if (x + ballData[index].radius > width) { 109 | x = width - ballData[index].radius 110 | } 111 | 112 | var dynamicObject = component.createObject(canvas, 113 | { pointX: x, 114 | pointY: ballData[index].radius, 115 | r: ballData[index].radius, 116 | cor: ballData[index].cor, 117 | source: ballData[index].image, 118 | mass: ballData[index].radius * ballData[index].radius, 119 | ballType: index, 120 | mergeSrc : ballData[index].mergeImage, 121 | }); 122 | dynamicObject.width = ballData[index].radius * 2; 123 | dynamicObject.height = ballData[index].radius * 2; 124 | currentBall = dynamicObject 125 | 126 | } 127 | } 128 | 129 | 130 | function currentBallMove(x) { 131 | if (currentBall == null) { 132 | return false; 133 | } 134 | if (x < currentBall.r || x + currentBall.r > width) { 135 | return false; 136 | } 137 | 138 | currentBall.pointX = x ; 139 | return true; 140 | } 141 | 142 | function currentBallStartDown() { 143 | if (currentBall == null) { 144 | return false; 145 | } 146 | 147 | 148 | if ( currentBall.shapeChange == true) { 149 | return false; 150 | } 151 | 152 | currentBall.vy = 10; 153 | balls[balls.length] = currentBall 154 | currentBall = null 155 | return true; 156 | } 157 | 158 | const edgeCorX = 0.2; 159 | const edgeCorY = 0.2; 160 | const ballAy = 1; 161 | function ballsMove() { 162 | for (var i in balls) { 163 | var ball = balls[i]; 164 | 165 | 166 | ball.vy += ballAy; 167 | 168 | ball.preX = ball.pointX 169 | ball.preY = ball.pointY 170 | ball.pointX += ball.vx; 171 | ball.pointY += ball.vy; 172 | 173 | if (ball.pointX < ball.r) { 174 | ball.pointX = ball.r 175 | ball.vx = -ball.vx * edgeCorX 176 | if (Math.abs(ball.vx)<0.1) ball.vx = 0 177 | 178 | } else if (ball.pointX + ball.r > width) { 179 | ball.pointX = width - ball.r 180 | ball.vx = -ball.vx * edgeCorX 181 | if (Math.abs(ball.vx)<0.1) ball.vx = 0 182 | 183 | } 184 | 185 | if (ball.pointY < ball.r) { 186 | ball.pointY = ball.r 187 | ball.vy = -ball.vy * edgeCorY 188 | } else if (ball.pointY + ball.r > height) { 189 | ballIsDown(ball); 190 | ball.pointY = height - ball.r 191 | ball.vy = -ball.vy * edgeCorY 192 | } 193 | 194 | 195 | } 196 | } 197 | 198 | 199 | 200 | function collide() { 201 | 202 | for (let i = 0; i < balls.length; i++) { 203 | let ball1 = balls[i] 204 | for (let j = i + 1; j < balls.length; j++) { 205 | let ball2 = balls[j] 206 | let distance = Math.sqrt(Math.pow((ball1.pointX - ball2.pointX),2) + Math.pow((ball1.pointY - ball2.pointY),2)); 207 | let radius = ball1.r + ball2.r; 208 | 209 | if (distance > radius) continue; 210 | 211 | 212 | if (!ball1.mergeStart && !ball2.mergeStart && ball1.ballType == ball2.ballType && ball2.ballType > 0) { 213 | mergeBall(j,i); 214 | return; 215 | } 216 | else 217 | changeSpeedAndDirection(ball1, ball2, distance, radius); 218 | } 219 | } 220 | } 221 | 222 | function ballsRotate() { 223 | 224 | for (let i = 0; i < balls.length; i++) { 225 | var ball = balls[i] 226 | if (ball.mergeStart) continue 227 | let distance = Math.sqrt(Math.pow((ball.pointX - ball.preX),2) + Math.pow((ball.pointY - ball.preY),2)); 228 | 229 | if (Math.abs(distance) && ball.vy < 10 ) { 230 | if (ball.vx > 0) { 231 | ball.rotation += 360/(2 * ball.r * 3.14) * distance; 232 | } 233 | else { 234 | ball.rotation -= 360/(2 * ball.r * 3.14) * distance; 235 | } 236 | if (Math.abs(ball.vx) < 0.1) 237 | ball.vx = 0 238 | 239 | } 240 | } 241 | } 242 | 243 | 244 | function changeSpeedAndDirection(ball1, ball2, distance, radius) { 245 | 246 | 247 | if (distance < radius) { 248 | let dd = radius - distance; 249 | let offsetC = radius - distance; 250 | let ballOffsetX = (ball1.pointX - ball2.pointX) / radius * offsetC ; 251 | let ballOffsetY = Math.abs((ball1.pointY - ball2.pointY) / radius * offsetC); 252 | 253 | let ball1MassRation = ball2.mass / (ball1.mass+ball2.mass); 254 | let ball2MassRation = ball1.mass / (ball1.mass+ball2.mass); 255 | 256 | ball1.pointX += ballOffsetX * ball1MassRation; 257 | ball2.pointX -= ballOffsetX * ball2MassRation; 258 | if (ball1.pointY > ball2.pointY) ball2.pointY -= ballOffsetY; 259 | else ball1.pointY -= ballOffsetY; 260 | 261 | } 262 | let dx = ball1.pointX - ball2.pointX 263 | let dy = ball1.pointY - ball2.pointY 264 | 265 | let ex = dx / radius; let ey = dy / radius; 266 | 267 | let v1n = ex * ball1.vx + ey * ball1.vy 268 | let v2n = ex * ball2.vx + ey * ball2.vy 269 | if(v1n >= v2n) return; 270 | let v1nn = ball1.cor * ((ball1.mass - ball2.mass) * v1n + 2 *ball2.mass *v2n ) / (ball1.mass +ball2.mass) 271 | let v2nn = ball2.cor * ((ball2.mass - ball1.mass) * v2n + 2 *ball1.mass *v1n ) / (ball1.mass +ball2.mass) 272 | 273 | let ux = -dy / radius; let uy = dx / radius; 274 | let v1t =ux * ball1.vx + uy*ball1.vy 275 | let v2t = ux * ball2.vx + uy * ball2.vy 276 | 277 | ball1.vx = v1nn*ex +v1t*ux; 278 | ball1.vy = v1nn*ex +v1t*uy; 279 | 280 | ball2.vx = v2nn*ex +v2t*ux; 281 | ball2.vy = v2nn*ex +v2t*uy; 282 | 283 | 284 | if (v1n == 0 && v1t ==0 && v2t == 0) { 285 | ball2.vx += 0.1 286 | ball2.vy += 0.3 287 | } 288 | 289 | } 290 | 291 | function mergeBall(i, j) { 292 | let ball1 = balls[i] 293 | let ball2 = balls[j] 294 | 295 | 296 | 297 | ball1.endPointX = ball1.pointX + (ball2.pointX - ball1.pointX) / 2 298 | ball1.endPointY = ball1.pointY + (ball2.pointY - ball1.pointY) / 2 299 | 300 | if (ball1.vy > 10) 301 | ball1.vy = 0 302 | 303 | if (ball1.endPointX < ball1.r) { 304 | ball1.endPointX = ball1.r 305 | } else if (ball1.endPointX + ball1.r > width) { 306 | ball1.endPointX = width - ball1.r 307 | } 308 | 309 | if (ball1.endPointY < ball1.r) { 310 | ball1.endPointY = ball1.r 311 | } else if (ball1.endPointY + ball1.r > height) { 312 | ball1.endPointY = height - ball.r 313 | } 314 | 315 | ball2.destroy(); 316 | balls[j] = null; 317 | balls.splice(j, 1); 318 | 319 | score += (ballData.length - ball1.ballType) * 2 320 | ball1.ballType -= 1 321 | ball1.mergeSrc = ballData[ball1.ballType].mergeImage; 322 | 323 | ball1.r = ballData[ball1.ballType].radius 324 | ball1.cor = ballData[ball1.ballType].cor 325 | ball1.mass = ball1.r * ball1.r 326 | ball1.source = ballData[ball1.ballType].image 327 | ball1.width = ball1.r * 2; 328 | ball1.height = ball1.r * 2; 329 | ball1.vx = 0 330 | ball1.vy = 0 331 | 332 | ball1.mergeStart = true 333 | 334 | newMergeAnimal(ball1.endPointX,ball1.endPointY,ball1.r,ballData[ball1.ballType].mergeImage); 335 | } 336 | 337 | 338 | function ballOverflow() { 339 | 340 | for (var i in balls) { 341 | let ball = balls[i] 342 | if (!ball.mergeStart && Math.abs(ball.vy) < 0.3 && Math.abs(ball.vx) < 0.3 && (ball.y < lineDashY)) { 343 | 344 | if (currentBall != null) { 345 | balls[balls.length] = currentBall 346 | currentBall = null 347 | } 348 | return true 349 | } 350 | } 351 | return false 352 | } 353 | 354 | function ballCloseAnimal() { 355 | 356 | var minY = 999999 357 | var index = -1 358 | 359 | for (var i in balls) { 360 | if (balls[i].pointY < minY) { 361 | minY = balls[i].pointY 362 | index = i 363 | } 364 | } 365 | 366 | if (index >= 0) { 367 | let image = balls[index].ballType > 0 ? balls[index].ballType -1 : balls[index].ballType 368 | 369 | newMergeAnimal(balls[index].pointX, 370 | balls[index].pointY, 371 | balls[index].r, 372 | ballData[image].mergeImage); 373 | 374 | balls[index].destroy(); 375 | balls[index] = null; 376 | balls.splice(index, 1); 377 | } 378 | return index 379 | } 380 | 381 | 382 | function process() { 383 | 384 | if (!finish) { 385 | ballsMove(); 386 | collide(); 387 | ballsRotate(); 388 | if (ballOverflow()) { 389 | finish = 1 390 | } 391 | } 392 | else if (finish == 1) { 393 | let date = new Date; 394 | let totalMs = date - preBallLeaveDate; 395 | 396 | if (totalMs > 60) { 397 | if (ballCloseAnimal() >= 0) { 398 | preBallLeaveDate = date 399 | } else { 400 | finish = 2 401 | finishSound.play() 402 | 403 | } 404 | } 405 | } 406 | } 407 | 408 | 409 | function newMergeAnimal(pointX, pointY, radius, image) { 410 | 411 | if (mergeComponent == null) 412 | mergeComponent = Qt.createComponent("MergeAnimal.qml"); 413 | 414 | if (mergeComponent.status == QQ.Component.Ready) { 415 | 416 | var dynamicMerge = mergeComponent.createObject(canvas, 417 | { x: pointX - radius * 1.3, 418 | y: pointY - radius * 1.3, 419 | width: radius * 2.6, 420 | height: radius * 2.6, 421 | mergeSrc: image, 422 | }); 423 | 424 | } else { 425 | console.log("error loading block component"); 426 | return false; 427 | } 428 | 429 | mergeSound1.play() 430 | mergeSound2.play() 431 | return true; 432 | } 433 | 434 | function ballIsDown(ball) { 435 | if (ball.vy > 30) 436 | downSound.play(); 437 | } 438 | 439 | 440 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/FinishWindow.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Layouts 1.12 3 | 4 | Rectangle { 5 | id: finishWind 6 | property int score: 1200 7 | color: "#80000000" 8 | z: 501 9 | 10 | ColumnLayout { 11 | anchors.centerIn: parent 12 | spacing: 40 13 | 14 | Row { 15 | spacing: 20 16 | Layout.alignment: Qt.AlignCenter 17 | Image { 18 | source: "icon/finish.png" 19 | width: 58 20 | height: 58 21 | } 22 | ScoreNumber { 23 | id: scoreNumber 24 | height: 58 25 | value: finishWind.score 26 | } 27 | } 28 | 29 | Text { 30 | Layout.alignment: Qt.AlignCenter 31 | Layout.fillWidth: true 32 | color: "#FFFFFF" 33 | font.pixelSize: 40 34 | font.family: "Microsoft Yahei" 35 | font.letterSpacing: 28 36 | text: "游戏结束" 37 | horizontalAlignment: Text.AlignHCenter 38 | } 39 | 40 | Text { 41 | Layout.alignment: Qt.AlignCenter 42 | Layout.fillWidth: true 43 | color: "#FFFFFF" 44 | font.pixelSize: 17 45 | font.family: "Microsoft Yahei" 46 | font.letterSpacing: 5 47 | text: "点击重新开始" 48 | horizontalAlignment: Text.AlignHCenter 49 | } 50 | 51 | } 52 | 53 | 54 | NumberAnimation on opacity { 55 | from: 0; to: 1.0; duration: 600; running: finishWind.visible 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/GameCanvas.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 游戏界面-负责刷新小球运动轨迹等 3 | ** Author : 诺谦 https://blog.csdn.net/qq_37997682/article/details/126640154 4 | ** Create : 2021-5-24 5 | ****************************************************************************/ 6 | 7 | import QtQuick 2.12 8 | import "BallRun.js" as BallRes 9 | import QtMultimedia 5.10 10 | Canvas { 11 | id: canvas 12 | 13 | visible: true 14 | property int score: 0 15 | property int lineDashY: 100 16 | property int finish: 0 // 0 : 未结束 1: 结束动画 2: 结束界面 17 | property var preBallLeaveDate: new Date 18 | onPaint: { 19 | var context = getContext('2d') 20 | var preDate = new Date; 21 | 22 | function draw() { 23 | BallRes.process(); 24 | requestAnimationFrame(draw); 25 | } 26 | 27 | drawLineDash(); 28 | draw(); 29 | } 30 | 31 | MouseArea { 32 | id : area 33 | anchors.fill: parent 34 | hoverEnabled: true 35 | onPositionChanged: { 36 | if (!finish ) BallRes.currentBallMove(mouseX) 37 | } 38 | onClicked: { 39 | if (!finish && BallRes.currentBallStartDown()) { 40 | BallRes.newBall(area.mouseX) 41 | } 42 | else if (finish == 2) { 43 | finish = 0 44 | score = 0 45 | BallRes.newBall(area.mouseX) 46 | } 47 | } 48 | } 49 | 50 | function drawLineDash() { 51 | context.setLineDash( [ 6, 6, 3] ); 52 | context.lineWidth = 4; 53 | context.clearRect(0, lineDashY - 4, canvas.width, lineDashY + 4); 54 | context.strokeStyle = "#91431E" 55 | context.lineCap = "round" 56 | context.moveTo(0, lineDashY); 57 | context.lineTo(canvas.width, lineDashY); 58 | context.stroke(); 59 | } 60 | 61 | 62 | 63 | SoundEffect { 64 | id: downSound 65 | source: "audio/down.wav" 66 | } 67 | 68 | SoundEffect { 69 | id: mergeSound1 70 | volume: 0.6 71 | source: "audio/merge1.wav" 72 | } 73 | 74 | SoundEffect { 75 | id: mergeSound2 76 | source: "audio/merge2.wav" 77 | } 78 | 79 | SoundEffect { 80 | id: finishSound 81 | source: "audio/finish.wav" 82 | } 83 | 84 | ScoreNumber { 85 | id: scoreNumber 86 | x: 10 87 | y: 20 88 | value: score 89 | } 90 | 91 | Component.onCompleted: BallRes.newBall(area.mouseX); 92 | 93 | } 94 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/MergeAnimal.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 小球合并时,产生的动画控件 3 | ** Author : 诺谦 https://blog.csdn.net/qq_37997682/article/details/126640154 4 | ** Create : 2021-5-24 5 | ****************************************************************************/ 6 | 7 | import QtQuick 2.12 8 | import QtMultimedia 5.10 9 | Item { 10 | property var mergeSrc: "" 11 | property var modelSize: 5 12 | 13 | id: merge 14 | 15 | Repeater { 16 | model: modelSize 17 | Image { 18 | fillMode: Image.Stretch 19 | anchors.fill: parent 20 | source: mergeSrc 21 | rotation: Math.random()*90 22 | opacity: (modelSize - index) / modelSize // 0 -> 1 23 | scale: (modelSize - index) / modelSize // 0 -> 1 24 | 25 | NumberAnimation on opacity { 26 | id: mergeAnimation 27 | running: true 28 | to: 1.0; duration: 200 29 | onFinished: merge.animationFinished() 30 | } 31 | } 32 | } 33 | 34 | 35 | 36 | 37 | function animationFinished() { 38 | this.destroy(100); 39 | } 40 | Timer { 41 | 42 | running: true 43 | interval: 300 44 | onTriggered: merge.destroy() 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/QianMergeWatermelonPage.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 主界面 3 | ** Author : 诺谦 https://blog.csdn.net/qq_37997682/article/details/126640154 4 | ** Create : 2021-5-24 5 | ****************************************************************************/ 6 | 7 | import QtQuick 2.12 8 | import QtQuick.Controls 2.12 9 | import QtQuick.Layouts 1.14 10 | Item { 11 | id: screen 12 | 13 | 14 | Rectangle { 15 | anchors.fill: parent 16 | anchors.margins: 10 17 | color: "transparent" 18 | clip: true 19 | 20 | Rectangle { 21 | id: home 22 | width: parent.width; 23 | height: parent.height - 80 24 | color: skin.light ? "#FFE89D" : "#AAFFE89D" 25 | GameCanvas { 26 | id: gameCanvas 27 | anchors.fill: parent 28 | } 29 | 30 | } 31 | Image { 32 | id: background 33 | width: parent.width; 34 | height: 80 35 | anchors.top: home.bottom 36 | source: "icon/bottomBack.png" 37 | fillMode: Image.PreserveAspectCrop 38 | opacity: skin.light ? 1.0 : 0.8 39 | } 40 | FinishWindow { 41 | anchors.fill: parent 42 | visible: gameCanvas.finish == 2 43 | score: gameCanvas.score 44 | } 45 | } 46 | 47 | 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/ScoreNumber.qml: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 成绩值显示控件 3 | ** Author : 诺谦 https://blog.csdn.net/qq_37997682/article/details/126640154 4 | ** Create : 2021-5-24 5 | ****************************************************************************/ 6 | 7 | import QtQuick 2.12 8 | 9 | Canvas { 10 | property int value: 1200 11 | property var numberWidth: numberImage.sourceSize.width / 10 12 | property var numberHeight: numberImage.sourceSize.height 13 | property var drawWidth: numberWidth * height / numberHeight 14 | 15 | id: canvas 16 | width: drawWidth * value.toString().length 17 | height: 40 18 | z: 50 19 | onPaint: { 20 | var context = getContext('2d') 21 | context.clearRect(0,0, canvas.width, canvas.height); 22 | var scoreStr = value.toString() 23 | var dy = 0 24 | var spacing = 5 25 | var dx = canvas.width/2 - ((drawWidth + spacing) * scoreStr.length - spacing)/2; 26 | 27 | for (var i in scoreStr) { 28 | context.drawImage(numberImage, numberImage.getNumberX(parseInt(scoreStr[i])), 0, numberWidth,numberHeight, 29 | dx, dy, drawWidth, height); 30 | dx += drawWidth - spacing 31 | } 32 | } 33 | 34 | Image { 35 | id : numberImage 36 | 37 | source: "icon/number1.png" 38 | visible: false 39 | mipmap: true 40 | 41 | function getNumberX(num) { 42 | return sourceSize.width / 10 * num 43 | } 44 | } 45 | onValueChanged: canvas.requestPaint() 46 | } 47 | -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/audio/d2cb5a4f-1334-4eab-8578-a76aa028644e.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/audio/d2cb5a4f-1334-4eab-8578-a76aa028644e.mp3 -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/audio/down.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/audio/down.mp3 -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/audio/down.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/audio/down.wav -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/audio/finish.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/audio/finish.mp3 -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/audio/finish.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/audio/finish.wav -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/audio/merge1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/audio/merge1.mp3 -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/audio/merge1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/audio/merge1.wav -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/audio/merge2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/audio/merge2.mp3 -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/audio/merge2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/audio/merge2.wav -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/1.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/ball1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/ball1.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/ball10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/ball10.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/ball11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/ball11.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/ball2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/ball2.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/ball3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/ball3.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/ball4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/ball4.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/ball5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/ball5.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/ball6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/ball6.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/ball7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/ball7.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/ball8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/ball8.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/ball9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/ball9.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/bottomBack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/bottomBack.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/finish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/finish.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/merge10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/merge10.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/merge11 - 副本.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/merge11 - 副本.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/merge11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/merge11.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/merge2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/merge2.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/merge3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/merge3.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/merge4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/merge4.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/merge5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/merge5.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/merge6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/merge6.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/merge7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/merge7.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/merge8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/merge8.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/merge9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/merge9.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/icon/number1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/icon/number1.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianMergeWatermelonPage/介绍.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/pages/QianProjectPages/QianMergeWatermelonPage/介绍.png -------------------------------------------------------------------------------- /pages/QianProjectPages/QianPhotoPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.14 2 | import QtQuick.Window 2.14 3 | import QtQuick.Layouts 1.12 4 | import QtQuick.Controls 2.14 5 | import QtQuick.Controls.Material 2.12 6 | import Qt.labs.platform 1.1 7 | import QtGraphicalEffects 1.14 8 | import "qrc:/common" 9 | Item { 10 | id: container 11 | property string picturesLocation : ""; 12 | property var imageNameFilters : ["所有图片格式 (*.png; *.jpg; *.bmp; *.gif; *.jpeg)"]; 13 | property var pictureList : [] 14 | property alias pictureIndex : view.currentIndex 15 | property var scaleMax : 800 // 最大800% 16 | property var scaleMin : 10 // 最小10% 17 | property var titleColor : "#E8E8E8" 18 | 19 | 20 | property var ctrlSliderList : [ 21 | ["放大", scaleMin, scaleMax , photoImage.scale * 100 , "%"], 22 | ["旋转", -180, 180 , photoImage.rotation, "°"], 23 | ] 24 | 25 | Material.foreground: tingeDrakerColor 26 | FileDialog { 27 | id: fileDialog 28 | title: "请打开图片(可以多选)" 29 | fileMode: FileDialog.OpenFiles 30 | folder: picturesLocation 31 | nameFilters: imageNameFilters 32 | onAccepted: { 33 | pictureList = files 34 | view.currentIndex = -1 35 | view.currentIndex = 0 36 | } 37 | onFolderChanged: picturesLocation = folder 38 | } 39 | 40 | Rectangle { 41 | id: back 42 | radius: 8 43 | color: skin.light ? "#F4F4F4" : "#22000000" 44 | anchors.fill: parent 45 | anchors.margins: 4 46 | clip: true 47 | 48 | antialiasing: true 49 | } 50 | 51 | 52 | Flickable { 53 | id: flick 54 | anchors.fill: back 55 | clip: true 56 | 57 | MouseArea { 58 | anchors.fill: parent 59 | onWheel: { 60 | console.log( photoImage.rotation, wheel.angleDelta.y); 61 | if (wheel.modifiers & Qt.ControlModifier) { // ctrl + 滑轮 则进行旋转图片 62 | photoImage.rotation += wheel.angleDelta.y / 120 * 5; 63 | if (photoImage.rotation > 180) 64 | photoImage.rotation = 180 65 | else if (photoImage.rotation < -180) 66 | photoImage.rotation = -180 67 | if (Math.abs(photoImage.rotation) < 4) 68 | photoImage.rotation = 0; 69 | } else { 70 | photoImage.scale += photoImage.scale * wheel.angleDelta.y / 120 / 10; 71 | if (photoImage.scale > scaleMax / 100) 72 | photoImage.scale = scaleMax / 100 73 | else if (photoImage.scale < scaleMin / 100) 74 | photoImage.scale = scaleMin / 100 75 | } 76 | } 77 | } 78 | Image { 79 | id: photoImage 80 | fillMode: Image.Pad 81 | source: (typeof pictureList[pictureIndex] === 'undefined') ? "" : pictureList[pictureIndex] 82 | smooth: true 83 | mipmap: true 84 | antialiasing: true 85 | Component.onCompleted: { 86 | x = parent.width / 2 - width / 2 87 | y = parent.height / 2 - height / 2 88 | pictureList.length = 0 89 | } 90 | 91 | onStatusChanged: { 92 | if(status == Image.Ready) { 93 | photoImage.x = (imageBack.width) / 2 - photoImage.width / 2 94 | photoImage.y = (imageBack.height) / 2 - photoImage.height / 2 95 | 96 | console.log("back.width imageBack.width", back.width, imageBack.width, photoImage.width) 97 | 98 | 99 | photoImage.scale = 1.0 100 | photoImage.rotation = 0 101 | 102 | } 103 | 104 | } 105 | 106 | PinchArea { 107 | anchors.fill: parent 108 | pinch.target: parent 109 | pinch.minimumRotation: -180 // 设置拿捏旋转图片最大最小比例 110 | pinch.maximumRotation: 180 111 | pinch.minimumScale: 0.1 // 设置拿捏缩放图片最小最大比例 112 | pinch.maximumScale: 10 113 | pinch.dragAxis: Pinch.XAndYAxis 114 | } 115 | 116 | MouseArea { 117 | anchors.fill: parent 118 | drag.target: parent 119 | drag.axis: Drag.XAndYAxis 120 | drag.minimumX: 20 - photoImage.width 121 | drag.maximumX: flick.width - 20 122 | drag.minimumY: 20 - photoImage.height 123 | drag.maximumY: flick.height - 20 124 | } 125 | 126 | } 127 | } 128 | 129 | ColumnLayout { 130 | id: _source 131 | anchors.fill: back 132 | anchors.margins: 4 133 | spacing: 4 134 | RowLayout { 135 | Layout.fillHeight: true 136 | Layout.fillWidth: true 137 | spacing: 1 138 | 139 | Item { 140 | id: imageBack 141 | Layout.fillHeight: true 142 | Layout.fillWidth: true 143 | } 144 | 145 | Rectangle { 146 | Layout.fillHeight: true 147 | Layout.preferredWidth : 220 148 | color: skin.light ? "#99FFFFFF" : "#88000000" 149 | 150 | radius: 8 151 | 152 | 153 | GroupBox { 154 | id: fileGroup 155 | title: "文件选项" 156 | 157 | y:5 158 | width: parent.width 159 | font.family: "Microsoft Yahei" 160 | background.scale: 0.9 161 | 162 | ColumnLayout { 163 | anchors.centerIn: parent 164 | spacing: 12 165 | Repeater { 166 | model : ListModel { 167 | id: fileModel 168 | ListElement { name: "打开文件"; } 169 | ListElement { name: "上一张"; } 170 | ListElement { name: "下一张"; } 171 | 172 | } 173 | SkinBaseButton { 174 | text: fileModel.get(index).name 175 | font.pixelSize: 15 176 | onPressed: fileGroupPressed(index) 177 | Layout.preferredWidth: 92 178 | Layout.preferredHeight: 30 179 | backRadius: 6 180 | 181 | } 182 | } 183 | } 184 | } 185 | 186 | 187 | GroupBox { 188 | id: ctrlGroup 189 | title: "图片控制" 190 | width: parent.width 191 | font.family: "Microsoft Yahei" 192 | anchors.top: fileGroup.bottom 193 | anchors.topMargin: 5 194 | background.scale: 0.9 195 | 196 | ColumnLayout { 197 | width: parent.width-10 198 | Repeater { 199 | model : 2 200 | RowLayout { 201 | YaheiText { 202 | leftPadding: 4 203 | text: ctrlSliderList[index][0] 204 | horizontalAlignment: Text.AlignRight 205 | font.pixelSize: 14 206 | } 207 | Slider { 208 | id: ctrlSlider 209 | Layout.fillWidth: true 210 | from: ctrlSliderList[index][1] 211 | value: ctrlSliderList[index][3] 212 | to: ctrlSliderList[index][2] 213 | stepSize: 1 214 | onMoved: setCtrlValue(index, value); 215 | } 216 | YaheiText { 217 | Layout.preferredWidth : 40 218 | color: tingeColor 219 | text: parseInt(ctrlSliderList[index][3].toString()) + ctrlSliderList[index][4] 220 | } 221 | } 222 | } 223 | } 224 | } 225 | 226 | GroupBox { 227 | id: imageInfoGroup 228 | title: "基本信息" 229 | width: parent.width 230 | font.family: "Microsoft Yahei" 231 | height: 170 232 | anchors.top: ctrlGroup.bottom 233 | anchors.topMargin: 5 234 | background.scale: 0.9 235 | 236 | 237 | ColumnLayout { 238 | width: parent.width-10 239 | spacing: 16 240 | YaheiText { 241 | text: "尺寸: " + photoImage.sourceSize.width + "X" + photoImage.sourceSize.height 242 | font.pixelSize: 14 243 | color: tingeColor 244 | leftPadding: 4 245 | } 246 | YaheiText { 247 | text: "路径: " + ((typeof pictureList[pictureIndex] === 'undefined') ? 248 | "等待打开文件..." : pictureList[pictureIndex].replace("file:///","")) 249 | 250 | Layout.preferredWidth: parent.width - 20 251 | Layout.preferredHeight: 80 252 | wrapMode: Text.Wrap 253 | font.pixelSize: 14 254 | color: tingeColor 255 | leftPadding: 4 256 | } 257 | 258 | } 259 | } 260 | 261 | } 262 | 263 | 264 | } 265 | 266 | Rectangle { 267 | id: images 268 | Behavior on Layout.preferredHeight { NumberAnimation { duration: 250 } } 269 | Layout.fillWidth: true 270 | Layout.preferredHeight: 130 271 | color: skin.light ? "#99FFFFFF" : "#88000000" 272 | radius: 8 273 | 274 | ColumnLayout { 275 | anchors.fill: parent 276 | Button { 277 | id: imageCtrlBtn 278 | Layout.alignment: Qt.AlignVCenter | Qt. AlignRight 279 | text: images.Layout.preferredHeight <= 30 ? "展开("+pictureList.length+")" : 280 | "收起("+pictureList.length+")" 281 | 282 | z: 100 283 | background: Rectangle { 284 | color: "transparent" 285 | } 286 | contentItem: Label { 287 | id: btnForeground 288 | text: parent.text 289 | font.family: "Microsoft Yahei" 290 | font.pixelSize: 14 291 | color: imageCtrlBtn.hovered ? tingeColor : tingeDrakerColor 292 | horizontalAlignment: Text.AlignHCenter 293 | verticalAlignment: Text.AlignVCenter 294 | } 295 | onPressed: { 296 | if (text.indexOf("收起") >= 0) { 297 | images.Layout.preferredHeight = 30 298 | } else { 299 | images.Layout.preferredHeight = 130 300 | } 301 | } 302 | } 303 | 304 | ListView { 305 | id: view 306 | Layout.fillHeight: true 307 | Layout.fillWidth: true 308 | spacing: 4 309 | orientation: ListView.Horizontal 310 | ScrollBar.horizontal: ScrollBar { 311 | id: scroll1 312 | policy: size<1.0? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff 313 | 314 | contentItem: Rectangle { 315 | implicitHeight: 8 316 | implicitWidth: 100 317 | radius: height / 2 318 | color: scroll1.pressed ? accentOpacityColor 319 | : accentOpacityHoverColor 320 | } 321 | height: 8 322 | background: Item { 323 | 324 | } 325 | } 326 | 327 | model: pictureList.length 328 | 329 | 330 | delegate: Rectangle { 331 | implicitWidth: 85 332 | implicitHeight: 85 333 | Image { 334 | anchors.fill:parent 335 | anchors.margins: 6 336 | antialiasing: true 337 | fillMode: Image.PreserveAspectFit 338 | source: pictureList[index] 339 | } 340 | border.color: view.currentIndex == index ? accentContrlColor : "transparent" 341 | color: tingeOpacityLightColor 342 | radius: 3 343 | 344 | MouseArea { 345 | anchors.fill: parent 346 | onClicked: view.currentIndex = index 347 | } 348 | Component.onCompleted: console.log("pictureList[index]",pictureList[index]) 349 | } 350 | 351 | 352 | 353 | } 354 | } 355 | } 356 | 357 | } 358 | 359 | 360 | 361 | function fileGroupPressed(index) { 362 | switch (index) { 363 | case 0 : fileDialog.open(); break; 364 | case 1 : openNewImageAndUpdateScroll(pictureIndex - 1); break; 365 | case 2 : openNewImageAndUpdateScroll(pictureIndex + 1); break; 366 | } 367 | } 368 | 369 | 370 | function setCtrlValue(index, value) { 371 | switch (index) { 372 | case 0 : photoImage.scale = value / 100; break; 373 | case 1 : photoImage.rotation = value; break; 374 | } 375 | } 376 | 377 | 378 | 379 | function openNewImageAndUpdateScroll(index) { 380 | if (index < 0 || index >= pictureList.length) { 381 | return false 382 | } 383 | pictureIndex = index 384 | view.positionViewAtIndex( pictureIndex, ListView.Beginning) 385 | 386 | return true 387 | } 388 | 389 | 390 | } 391 | -------------------------------------------------------------------------------- /preview/linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/preview/linux.png -------------------------------------------------------------------------------- /preview/windwos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/preview/windwos.png -------------------------------------------------------------------------------- /qianWindow.pro: -------------------------------------------------------------------------------- 1 | QT += quick 2 | QT += quickcontrols2 3 | QT += widgets 4 | 5 | CONFIG += c++11 6 | CONFIG += resources_big 7 | # The following define makes your compiler emit warnings if you use 8 | # any Qt feature that has been marked deprecated (the exact warnings 9 | # depend on your compiler). Refer to the documentation for the 10 | # deprecated API to know how to port your code away from it. 11 | DEFINES += QT_DEPRECATED_WARNINGS 12 | 13 | # You can also make your code fail to compile if it uses deprecated APIs. 14 | # In order to do so, uncomment the following line. 15 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 16 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 17 | 18 | SOURCES += \ 19 | main.cpp \ 20 | pages/QianProjectPages/QianDragViewPage/qiandrageventcatch.cpp \ 21 | 22 | RESOURCES += qml.qrc 23 | include(./common/Frameless/frameless.pri) 24 | include(./common/Backed/Backed.pri) 25 | 26 | 27 | #INCLUDEPATH += $$PWD/pages/QianProjectPages/QianDragViewPage 28 | 29 | win32 { 30 | RC_FILE += ./windowRes/Icon.rc 31 | } 32 | 33 | 34 | # Additional import path used to resolve QML modules in Qt Creator's code model 35 | QML_IMPORT_PATH = 36 | 37 | # Additional import path used to resolve QML modules just for Qt Quick Designer 38 | QML_DESIGNER_IMPORT_PATH = 39 | 40 | # Default rules for deployment. 41 | qnx: target.path = /tmp/$${TARGET}/bin 42 | else: unix:!android: target.path = /opt/$${TARGET}/bin 43 | !isEmpty(target.path): INSTALLS += target 44 | 45 | HEADERS += \ 46 | pages/QianProjectPages/QianDragViewPage/qiandrageventcatch.h \ 47 | -------------------------------------------------------------------------------- /qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | common/SkinModel.qml 5 | ContentList.qml 6 | LeftSidebar.qml 7 | WindowEntry.qml 8 | WindowTilte.qml 9 | common/SkinImageButton.qml 10 | common/ImageButton.qml 11 | common/ScaleImageButton.qml 12 | common/Sidebar.qml 13 | common/BaseToolTip.qml 14 | common/YaheiText.qml 15 | common/BaseSlider.qml 16 | windowRes/close.png 17 | windowRes/close_hover.png 18 | windowRes/close2.png 19 | windowRes/icon.png 20 | windowRes/max.png 21 | windowRes/minimize.png 22 | windowRes/normal.png 23 | windowRes/skin.png 24 | InputPage.qml 25 | common/BaseButton.qml 26 | common/SkinPopup.qml 27 | common/SkinBaseButton.qml 28 | PageManager.qml 29 | pages/BaseControlPage.qml 30 | common/SkinBaseButton2.qml 31 | pages/BaseOtherControlPage.qml 32 | common/DropPopup.qml 33 | common/BaseCheckBox.qml 34 | common/qmlQianStretchList/QianStretchDalegate.qml 35 | common/qmlQianStretchList/QianStretchEntry.qml 36 | common/qmlQianStretchList/icons/indicator_right.png 37 | pages/QianProjectPages/QianPhotoPage.qml 38 | pages/QianProjectPages/QianMergeWatermelonPage/Ball.qml 39 | pages/QianProjectPages/QianMergeWatermelonPage/BallRun.js 40 | pages/QianProjectPages/QianMergeWatermelonPage/FinishWindow.qml 41 | pages/QianProjectPages/QianMergeWatermelonPage/GameCanvas.qml 42 | pages/QianProjectPages/QianMergeWatermelonPage/MergeAnimal.qml 43 | pages/QianProjectPages/QianMergeWatermelonPage/QianMergeWatermelonPage.qml 44 | pages/QianProjectPages/QianMergeWatermelonPage/ScoreNumber.qml 45 | pages/QianProjectPages/QianMergeWatermelonPage/audio/d2cb5a4f-1334-4eab-8578-a76aa028644e.mp3 46 | pages/QianProjectPages/QianMergeWatermelonPage/audio/down.mp3 47 | pages/QianProjectPages/QianMergeWatermelonPage/audio/down.wav 48 | pages/QianProjectPages/QianMergeWatermelonPage/audio/finish.mp3 49 | pages/QianProjectPages/QianMergeWatermelonPage/audio/finish.wav 50 | pages/QianProjectPages/QianMergeWatermelonPage/audio/merge1.mp3 51 | pages/QianProjectPages/QianMergeWatermelonPage/audio/merge1.wav 52 | pages/QianProjectPages/QianMergeWatermelonPage/audio/merge2.mp3 53 | pages/QianProjectPages/QianMergeWatermelonPage/audio/merge2.wav 54 | pages/QianProjectPages/QianMergeWatermelonPage/icon/1.png 55 | pages/QianProjectPages/QianMergeWatermelonPage/icon/ball1.png 56 | pages/QianProjectPages/QianMergeWatermelonPage/icon/ball2.png 57 | pages/QianProjectPages/QianMergeWatermelonPage/icon/ball3.png 58 | pages/QianProjectPages/QianMergeWatermelonPage/icon/ball4.png 59 | pages/QianProjectPages/QianMergeWatermelonPage/icon/ball5.png 60 | pages/QianProjectPages/QianMergeWatermelonPage/icon/ball6.png 61 | pages/QianProjectPages/QianMergeWatermelonPage/icon/ball7.png 62 | pages/QianProjectPages/QianMergeWatermelonPage/icon/ball8.png 63 | pages/QianProjectPages/QianMergeWatermelonPage/icon/ball9.png 64 | pages/QianProjectPages/QianMergeWatermelonPage/icon/ball10.png 65 | pages/QianProjectPages/QianMergeWatermelonPage/icon/ball11.png 66 | pages/QianProjectPages/QianMergeWatermelonPage/icon/bottomBack.png 67 | pages/QianProjectPages/QianMergeWatermelonPage/icon/finish.png 68 | pages/QianProjectPages/QianMergeWatermelonPage/icon/merge2.png 69 | pages/QianProjectPages/QianMergeWatermelonPage/icon/merge3.png 70 | pages/QianProjectPages/QianMergeWatermelonPage/icon/merge4.png 71 | pages/QianProjectPages/QianMergeWatermelonPage/icon/merge5.png 72 | pages/QianProjectPages/QianMergeWatermelonPage/icon/merge6.png 73 | pages/QianProjectPages/QianMergeWatermelonPage/icon/merge7.png 74 | pages/QianProjectPages/QianMergeWatermelonPage/icon/merge8.png 75 | pages/QianProjectPages/QianMergeWatermelonPage/icon/merge9.png 76 | pages/QianProjectPages/QianMergeWatermelonPage/icon/merge10.png 77 | pages/QianProjectPages/QianMergeWatermelonPage/icon/merge11.png 78 | pages/QianProjectPages/QianMergeWatermelonPage/icon/number1.png 79 | pages/QianProjectPages/QianDragViewPage/QianDragDelegate.qml 80 | pages/QianProjectPages/QianDragViewPage/QianDragDelegateInformation.qml 81 | pages/QianProjectPages/QianDragViewPage/QianDragView.qml 82 | pages/QianProjectPages/QianDragViewPage/QianDragViewPage.qml 83 | pages/QianProjectPages/QianDragViewPage/remove.png 84 | common/BaseTextField.qml 85 | common/qmlQianHints/error.png 86 | common/qmlQianHints/Message.qml 87 | common/qmlQianHints/remind.png 88 | common/qmlQianHints/true.png 89 | common/qmlQianDialog/info.png 90 | common/qmlQianDialog/SkinQianDialog.qml 91 | common/qmlQianHints/QianQuestionMark.qml 92 | common/qmlQianHints/questionMark.png 93 | common/qmlQianHints/questionMarkDarker.png 94 | common/qmlQianDialog/error.png 95 | common/qmlQianDialog/ok.png 96 | common/qmlQianDialog/question.png 97 | pages/HintPage.qml 98 | common/qmlQianDialog/BlogDialog.qml 99 | 100 | 101 | -------------------------------------------------------------------------------- /windowRes/Icon.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON DISCARDABLE "icon.ico" 2 | -------------------------------------------------------------------------------- /windowRes/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/windowRes/close.png -------------------------------------------------------------------------------- /windowRes/close2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/windowRes/close2.png -------------------------------------------------------------------------------- /windowRes/close_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/windowRes/close_hover.png -------------------------------------------------------------------------------- /windowRes/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/windowRes/icon.ico -------------------------------------------------------------------------------- /windowRes/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/windowRes/icon.png -------------------------------------------------------------------------------- /windowRes/max.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/windowRes/max.png -------------------------------------------------------------------------------- /windowRes/minimize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/windowRes/minimize.png -------------------------------------------------------------------------------- /windowRes/normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/windowRes/normal.png -------------------------------------------------------------------------------- /windowRes/skin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuoqian-lgtm/QianWindow/91d2685f78defaf77bc8ccb5490a17e3ba14291a/windowRes/skin.png --------------------------------------------------------------------------------