commit bd93be6424acd91d74c95957326276aaf95d5250 Author: Juny Date: Tue Feb 13 17:26:45 2024 -0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0fcadbd --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build +compile_commands.json \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c53172b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.19) + +set(PROJECT "QuteSpectrometer") + +project(${PROJECT} VERSION 1.0.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +find_package(Qt6 COMPONENTS Widgets Qml QuickControls2 REQUIRED) + +add_executable(${PROJECT} + src/main.cpp + src/resources.qrc + src/Gui/Style/resources.qrc) + +target_link_libraries(${PROJECT} + Qt::Widgets + Qt::Qml + Qt::QuickControls2) + +if(CMAKE_BUILD_TYPE STREQUAL "Release") + set_property(TARGET ${PROJECT} PROPERTY WIN32_EXECUTABLE true) +endif() \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..770bb96 --- /dev/null +++ b/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2024 Juny +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted (subject to the limitations in the disclaimer +below) provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY +THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/src/Gui/App.qml b/src/Gui/App.qml new file mode 100644 index 0000000..2f7465a --- /dev/null +++ b/src/Gui/App.qml @@ -0,0 +1,7 @@ +pragma Singleton + +import QtQuick + +QtObject { + id: app +} \ No newline at end of file diff --git a/src/Gui/Splash.qml b/src/Gui/Splash.qml new file mode 100644 index 0000000..cdf9880 --- /dev/null +++ b/src/Gui/Splash.qml @@ -0,0 +1,22 @@ +import QtQuick +import QtQuick.Window +import QtQuick.Layouts +import QtQuick.Controls + +import "PStyle" +import "Login" + +Window { + visible: true + width: 640 + height: 480 + title: Qt.application.displayName + + PBackground { + anchors.fill: parent + + Login { + anchors.centerIn: parent + } + } +} \ No newline at end of file diff --git a/src/Gui/Style/PStyle/PBackground.qml b/src/Gui/Style/PStyle/PBackground.qml new file mode 100644 index 0000000..b994bc8 --- /dev/null +++ b/src/Gui/Style/PStyle/PBackground.qml @@ -0,0 +1,6 @@ +import QtQuick +import "." + +Rectangle { + color: PStyle.backColor +} \ No newline at end of file diff --git a/src/Gui/Style/PStyle/PBusyIndicator.qml b/src/Gui/Style/PStyle/PBusyIndicator.qml new file mode 100644 index 0000000..016218c --- /dev/null +++ b/src/Gui/Style/PStyle/PBusyIndicator.qml @@ -0,0 +1,66 @@ +import QtQuick +import QtQuick.Controls + +import "." + +BusyIndicator { + id: control + + contentItem: Item { + width: height + height: control.height + + Item { + id: item + + x: 0 + y: 0 + width: parent.width + height: parent.height + opacity: control.running ? 1 : 0 + + Behavior on opacity { + OpacityAnimator { + duration: PStyle.animationDuration + } + } + + RotationAnimator { + target: item + running: control.running && control.visible + from: 0 + to: 360 + loops: Animation.Infinite + duration: PStyle.animationDuration * 12 + } + + Repeater { + id: repeater + model: 5 + + Rectangle { + id: delegate + x: item.width / 2 - width / 2 + y: item.height / 2 - height / 2 + implicitWidth: 8 + implicitHeight: 8 + radius: width / 2 + color: Qt.darker(PStyle.foreColor, 1.2) + + required property int index + + transform: [ + Translate { + y: -Math.min(item.width, item.height) * 0.5 + 5 + }, + Rotation { + angle: delegate.index / repeater.count * 360 + origin.x: 5 + origin.y: 5 + } + ] + } + } + } + } +} diff --git a/src/Gui/Style/PStyle/PGroupBox.qml b/src/Gui/Style/PStyle/PGroupBox.qml new file mode 100644 index 0000000..3e2aaea --- /dev/null +++ b/src/Gui/Style/PStyle/PGroupBox.qml @@ -0,0 +1,22 @@ +import QtQuick +import QtQuick.Controls + +import "." + +GroupBox { + id: root + + label: PText { + font: PStyle.getFont(10) + text: root.title + } + + background: PBackground { + color: "transparent" + border.color: PStyle.foreColor + border.width: 1 + + y: parent.topPadding - parent.padding + height: parent.height - parent.topPadding + parent.padding + } +} \ No newline at end of file diff --git a/src/Gui/Style/PStyle/PIcon.qml b/src/Gui/Style/PStyle/PIcon.qml new file mode 100644 index 0000000..5fc056b --- /dev/null +++ b/src/Gui/Style/PStyle/PIcon.qml @@ -0,0 +1,25 @@ +import QtQuick +import Qt5Compat.GraphicalEffects + +Image { + id: icon + + property string name: "" + property int dimension: 18 + property color colorize: PStyle.foreColor + + cache: true + asynchronous: true + fillMode: Image.PreserveAspectFit + source: name ? `qrc:/Icons/${name}.svg` : "" + smooth: false + + sourceSize.width: name ? dimension : 0 + sourceSize.height: name ? dimension : 0 + + layer.enabled: ! Qt.colorEqual(colorize, "transparent") + layer.effect: ColorOverlay { + color: icon.colorize + cached: icon.cache + } +} \ No newline at end of file diff --git a/src/Gui/Style/PStyle/PIconButton.qml b/src/Gui/Style/PStyle/PIconButton.qml new file mode 100644 index 0000000..92010cd --- /dev/null +++ b/src/Gui/Style/PStyle/PIconButton.qml @@ -0,0 +1,23 @@ +import QtQuick.Controls +import QtQuick.Layouts +import "." + +PRawButton { + id: btn + + topPadding: 8 + bottomPadding: topPadding + rightPadding: 8 + leftPadding: rightPadding + + property alias pIcon: icon + + contentItem: RowLayout { + property alias buttonText: icon + + PIcon { + id: icon + name: "" + } + } +} \ No newline at end of file diff --git a/src/Gui/Style/PStyle/PInputField.qml b/src/Gui/Style/PStyle/PInputField.qml new file mode 100644 index 0000000..0f7cf4d --- /dev/null +++ b/src/Gui/Style/PStyle/PInputField.qml @@ -0,0 +1,26 @@ +import QtQuick.Layouts +import "." + +ColumnLayout { + property alias label: lbl.text + property alias placeholderText: tf.placeholderText + property alias tfText: tf.text + property alias pTf: tf + spacing: 2 + + signal tfChanged(text: string) + signal tfAccepted() + + PText { + id: lbl + font: PStyle.getFont(8) + } + + PTextField { + id: tf + Layout.fillWidth: true + + onTextEdited: tfChanged(text) + onAccepted: tfAccepted() + } +} \ No newline at end of file diff --git a/src/Gui/Style/PStyle/PRawButton.qml b/src/Gui/Style/PStyle/PRawButton.qml new file mode 100644 index 0000000..02a8e8b --- /dev/null +++ b/src/Gui/Style/PStyle/PRawButton.qml @@ -0,0 +1,86 @@ +import QtQuick +import QtQuick.Controls +import "." + +Button { + id: btn + hoverEnabled: true + scale: state === "Pressed" ? 0.96 : 1.0 + + background: PBackground { + id: background + color: btn.enabled ? Qt.darker(PStyle.backColor, 1.8) : Qt.lighter(PStyle.backColor, 2.4) + + border.width: 1 + border.color: btn.enabled ? PStyle.foreColor : Qt.darker(PStyle.foreColor, 1.4) // Qt.hsva(0, 1, 0.5, 1) + } + + states: [ + State { + name: "Hovering" + PropertyChanges { + target: background + color: Qt.lighter(PStyle.backColor, 1.6) + } + PropertyChanges { + target: contentItem.buttonText + colorize: Qt.lighter(PStyle.foreColor, 1.2) + } + }, + State { + name: "Pressed" + PropertyChanges { + target: background + color: Qt.darker(PStyle.backColor, 3) + } + PropertyChanges { + target: contentItem.buttonText + colorize: Qt.darker(PStyle.foreColor, 2.4) + } + } + ] + + transitions: [ + Transition { + from: "" + to: "Hovering" + ColorAnimation { + duration: PStyle.animationDuration + } + }, + + Transition { + from: "*" + to: "Pressed" + ColorAnimation { + duration: PStyle.animationDuration + } + } + ] + + Behavior on scale { + NumberAnimation { + duration: PStyle.animationDuration + easing.type: Easing.InOutQuad + } + } + + MouseArea { + enabled: btn.enabled + hoverEnabled: true + anchors.fill: btn + onEntered: { + btn.state = 'Hovering' + cursorShape = Qt.PointingHandCursor + } + onExited: { btn.state = '' } + onClicked: { btn.clicked() } + onPressed: { btn.state = "Pressed" } + onReleased: { + if (containsMouse) + btn.state = "Hovering" + else + btn.state = "" + } + } +} \ No newline at end of file diff --git a/src/Gui/Style/PStyle/PStackView.qml b/src/Gui/Style/PStyle/PStackView.qml new file mode 100644 index 0000000..b3a7416 --- /dev/null +++ b/src/Gui/Style/PStyle/PStackView.qml @@ -0,0 +1,41 @@ +import QtQuick +import QtQuick.Controls +import "." + +StackView { + pushEnter: Transition { + PropertyAnimation { + property: "opacity" + from: 0 + to: 1 + duration: PStyle.animationDuration + } + } + + pushExit: Transition { + PropertyAnimation { + property: "opacity" + from: 1 + to: 0 + duration: PStyle.animationDuration + } + } + + popEnter: Transition { + PropertyAnimation { + property: "opacity" + from: 0 + to: 1 + duration: PStyle.animationDuration + } + } + + popExit: Transition { + PropertyAnimation { + property: "opacity" + from: 1 + to: 0 + duration: PStyle.animationDuration + } + } +} \ No newline at end of file diff --git a/src/Gui/Style/PStyle/PStyle.qml b/src/Gui/Style/PStyle/PStyle.qml new file mode 100644 index 0000000..0140fce --- /dev/null +++ b/src/Gui/Style/PStyle/PStyle.qml @@ -0,0 +1,25 @@ +pragma Singleton + +import QtQuick + +QtObject { + property color foreColor: Qt.hsva(0, 0, 0.8, 1) + property color foreColorDim: Qt.darker(foreColor, 1.2) + + property color backColor: Qt.hsva(0, 0, 0.1, 1) + property color backColorDark: Qt.darker(backColor, 1.2) + + property double animationDuration: 100 + + property font font: Qt.font({ + family: "HackGen Console", + pointSize: 12, + }) + + function getFont(size = 12) { + return Qt.font({ + family: "HackGen Console", + pointSize: size, + }) + } +} \ No newline at end of file diff --git a/src/Gui/Style/PStyle/PText.qml b/src/Gui/Style/PStyle/PText.qml new file mode 100644 index 0000000..732b74d --- /dev/null +++ b/src/Gui/Style/PStyle/PText.qml @@ -0,0 +1,10 @@ +import QtQuick +import "." + +Text { + id: txt + property alias colorize: txt.color + + color: PStyle.foreColor + font: PStyle.font +} \ No newline at end of file diff --git a/src/Gui/Style/PStyle/PTextButton.qml b/src/Gui/Style/PStyle/PTextButton.qml new file mode 100644 index 0000000..fc422ba --- /dev/null +++ b/src/Gui/Style/PStyle/PTextButton.qml @@ -0,0 +1,22 @@ +import QtQuick.Controls +import QtQuick.Layouts +import "." + +PRawButton { + id: btn + + topPadding: 8 + bottomPadding: topPadding + rightPadding: text ? 24 : 8 + leftPadding: rightPadding + + contentItem: RowLayout { + property alias buttonText: txt + + PText { + id: txt + Layout.alignment: Qt.AlignHCenter + text: btn.text + } + } +} \ No newline at end of file diff --git a/src/Gui/Style/PStyle/PTextField.qml b/src/Gui/Style/PStyle/PTextField.qml new file mode 100644 index 0000000..90e44e9 --- /dev/null +++ b/src/Gui/Style/PStyle/PTextField.qml @@ -0,0 +1,19 @@ +import QtQuick.Controls +import "." + +TextField { + color: PStyle.foreColor + font: PStyle.font + placeholderTextColor: Qt.darker(PStyle.foreColor, 1.8) + padding: 8 + + background: PBackground { + id: background + color: Qt.darker(PStyle.backColor, 1.8) + + border.width: 1 + border.color: PStyle.foreColor + } + + property alias bBackground: background +} \ No newline at end of file diff --git a/src/Gui/Style/PStyle/qmldir b/src/Gui/Style/PStyle/qmldir new file mode 100644 index 0000000..317917e --- /dev/null +++ b/src/Gui/Style/PStyle/qmldir @@ -0,0 +1 @@ +singleton PStyle 1.0 PStyle.qml \ No newline at end of file diff --git a/src/Gui/Style/resources.qrc b/src/Gui/Style/resources.qrc new file mode 100644 index 0000000..9b36c91 --- /dev/null +++ b/src/Gui/Style/resources.qrc @@ -0,0 +1,17 @@ + + + PStyle/qmldir + PStyle/PStyle.qml + PStyle/PText.qml + PStyle/PBackground.qml + PStyle/PTextField.qml + PStyle/PInputField.qml + PStyle/PTextButton.qml + PStyle/PRawButton.qml + PStyle/PIconButton.qml + PStyle/PIcon.qml + PStyle/PBusyIndicator.qml + PStyle/PStackView.qml + PStyle/PGroupBox.qml + + \ No newline at end of file diff --git a/src/Gui/qmldir b/src/Gui/qmldir new file mode 100644 index 0000000..2838290 --- /dev/null +++ b/src/Gui/qmldir @@ -0,0 +1 @@ +singleton App 1.0 App.qml \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..be83a8c --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,42 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); + QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi); + + QApplication::setApplicationName("QuteSpectrometer"); + QApplication::setApplicationDisplayName("QuteSpectrometer"); + QApplication::setApplicationVersion("0.1"); + QQuickStyle::setStyle("Fusion"); + QApplication app(argc, argv); + + QQmlEngine *engine = new QQmlEngine(); + + QObject::connect(engine, &QQmlEngine::quit, &QApplication::quit); + engine->addImportPath("qrc:/"); + + QQmlContext *ctx = new QQmlContext(engine->rootContext()); + QQmlComponent component(engine, QUrl("qrc:/Splash.qml")); + + if (component.isError()) { + for (QQmlError e : component.errors()) + qCritical("%s:%d:%d: %s", e.url().toString().toStdString().c_str(), + e.line(), e.column(), e.description().toStdString().c_str()); + qFatal("One or more errors have occurred, exiting"); + } + + component.create(ctx); + + int ret = app.exec(); + delete ctx; + delete engine; + return ret; +} \ No newline at end of file diff --git a/src/resources.qrc b/src/resources.qrc new file mode 100644 index 0000000..ca7e6ec --- /dev/null +++ b/src/resources.qrc @@ -0,0 +1,12 @@ + + + Gui/Splash.qml + Gui/App.qml + Gui/qmldir + + + Gui/Login/Login.qml + Gui/Login/InstanceInput.qml + Gui/Login/LoadingInfo.qml + + \ No newline at end of file