add book
This commit is contained in:
40
Qt6QMLBeginnersCode/1.Introduction/1-DemoApp/CMakeLists.txt
Normal file
40
Qt6QMLBeginnersCode/1.Introduction/1-DemoApp/CMakeLists.txt
Normal file
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) Daniel Gakwaya.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(DemoApp VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
qt_add_executable(app1-DemoApp
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app1-DemoApp
|
||||
URI DemoApp
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
set_target_properties(app1-DemoApp PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app1-DemoApp
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
install(TARGETS app1-DemoApp
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
18
Qt6QMLBeginnersCode/1.Introduction/1-DemoApp/Main.qml
Normal file
18
Qt6QMLBeginnersCode/1.Introduction/1-DemoApp/Main.qml
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import QtQuick
|
||||
|
||||
Window {
|
||||
visible: true
|
||||
width: 640
|
||||
height: 480
|
||||
title: qsTr("Hello World")
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text : "Hello World";
|
||||
color: "red"
|
||||
font.pointSize: 20
|
||||
}
|
||||
}
|
||||
40
Qt6QMLBeginnersCode/1.Introduction/1-DemoApp/main.cpp
Normal file
40
Qt6QMLBeginnersCode/1.Introduction/1-DemoApp/main.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QDebug>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
|
||||
&app, []() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("DemoApp", "Main");
|
||||
|
||||
return app.exec();
|
||||
|
||||
|
||||
/*
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
const QUrl url(u"qrc:/1-DemoApp/main.qml"_qs);
|
||||
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
|
||||
&app, [url](QObject *obj, const QUrl &objUrl) {
|
||||
qDebug() << "url : " << url;
|
||||
qDebug() << "objUrl : " << objUrl;
|
||||
if (!obj && url == objUrl)
|
||||
QCoreApplication::exit(-1);
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
engine.load(url);
|
||||
|
||||
return app.exec();
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(TodoList VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.8)
|
||||
|
||||
qt_add_executable(TodoList
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(TodoList
|
||||
URI TodoList
|
||||
VERSION 1.0
|
||||
QML_FILES
|
||||
# Main View
|
||||
src/views/MainView.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(TodoList PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.app01_todolist_starter
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(TodoList
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS TodoList
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("TodoList", "MainView");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import QtQuick
|
||||
|
||||
Window {
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: qsTr("Hello World")
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(TodoList VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Quick QuickControls2)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.8)
|
||||
|
||||
qt_add_executable(TodoList
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(TodoList
|
||||
URI TodoList
|
||||
VERSION 1.0
|
||||
QML_FILES
|
||||
# Main View
|
||||
src/views/MainView.qml
|
||||
|
||||
# Components
|
||||
src/components/AppHeader.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(TodoList PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.app01_todolist_starter
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(TodoList
|
||||
PRIVATE Qt6::Quick
|
||||
Qt6::QuickControls2
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS TodoList
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,79 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: 80
|
||||
|
||||
signal toggleDarkMode()
|
||||
|
||||
// Properties that will be bound from parent
|
||||
property color textColor: "#333333"
|
||||
property color textSecondary: "#999999"
|
||||
property bool darkMode: false
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
RowLayout{
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 8
|
||||
anchors.rightMargin: 8
|
||||
spacing: 12
|
||||
|
||||
// App icon
|
||||
Text {
|
||||
text: "📝"
|
||||
font.pixelSize: 32
|
||||
}
|
||||
|
||||
// App title and subtitle
|
||||
Column {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: "My Tasks"
|
||||
font.pixelSize: 28
|
||||
font.weight: Font.Bold
|
||||
color: root.textColor
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Stay organized, stay productive")
|
||||
font.pixelSize: 12
|
||||
color: root.textSecondary
|
||||
opacity: 0.8
|
||||
}
|
||||
}
|
||||
|
||||
// Dark mode toggle
|
||||
Button {
|
||||
id: themeToggle
|
||||
Layout.preferredWidth: 50
|
||||
Layout.preferredHeight: 50
|
||||
|
||||
background: Rectangle {
|
||||
color: themeToggle.pressed ?
|
||||
(root.darkMode ? "#404040" : "#e0e0e0") :
|
||||
(root.darkMode ? "#2d2d2d" : "#f5f5f5")
|
||||
radius: 25
|
||||
border.color: root.darkMode ? "#555555" : "#d0d0d0"
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
contentItem: Text{
|
||||
text: root.darkMode ? "☀️" : "🌙"
|
||||
font.pixelSize: 20
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
// Emit the signal when the button is clicked
|
||||
onClicked: root.toggleDarkMode()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQuickStyle>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
// Set Qt Quick Controls style to Basic to enable customization
|
||||
QQuickStyle::setStyle("Basic");
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("TodoList", "MainView");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
ApplicationWindow {
|
||||
id: root
|
||||
width: 400
|
||||
height: 700
|
||||
visible: true
|
||||
title: qsTr("My Tasks")
|
||||
|
||||
|
||||
// Theme properties
|
||||
property bool darkMode: false
|
||||
property color backgroundColor: darkMode ? "#1e1e1e" : "#f0f2f5"
|
||||
property color primaryColor: "#007aff"
|
||||
property color textColor: darkMode ? "#ffffff" : "#333333"
|
||||
property color cardColor: darkMode ? "#2d2d2d" : "#ffffff"
|
||||
property color completedColor: darkMode ? "#666666" : "#999999"
|
||||
|
||||
// Background
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.backgroundColor
|
||||
}
|
||||
|
||||
//The components of the ui
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 20
|
||||
spacing: 20
|
||||
|
||||
//Placeholder for header (we'll add this next)
|
||||
/*
|
||||
Rectangle{
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 80
|
||||
color: "transparent"
|
||||
border.color: root.textColor
|
||||
border.width: 1
|
||||
|
||||
Text{
|
||||
anchors.centerIn: parent
|
||||
text: "Header will go here"
|
||||
color: root.textColor
|
||||
}
|
||||
}
|
||||
*/
|
||||
AppHeader {
|
||||
id: header
|
||||
Layout.fillWidth: true
|
||||
textColor: root.textColor
|
||||
textSecondary: root.completedColor
|
||||
darkMode: root.darkMode
|
||||
onToggleDarkMode: root.darkMode = !root.darkMode
|
||||
}
|
||||
|
||||
//The actual AppHeader component to replace the place holder
|
||||
|
||||
//Add a spacer to push things up. Will remove later
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(TodoList VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Quick QuickControls2)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.8)
|
||||
|
||||
qt_add_executable(TodoList
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(TodoList
|
||||
URI TodoList
|
||||
VERSION 1.0
|
||||
QML_FILES
|
||||
# Main View
|
||||
src/views/MainView.qml
|
||||
|
||||
# Components
|
||||
src/components/AppHeader.qml
|
||||
src/components/AddTaskBar.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(TodoList PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.app01_todolist_starter
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(TodoList
|
||||
PRIVATE Qt6::Quick
|
||||
Qt6::QuickControls2
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS TodoList
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,106 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: 60
|
||||
|
||||
signal taskAdded(string taskText)
|
||||
|
||||
property color backgroundColor: "#ffffff"
|
||||
property color textColor: "#333333"
|
||||
property color primaryColor: "#007aff"
|
||||
property bool darkMode: false
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.backgroundColor
|
||||
radius: 12
|
||||
border.color: root.darkMode ? "#404040" : "#e0e0e0"
|
||||
border.width: 1
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
spacing: 12
|
||||
|
||||
// Add icon
|
||||
Rectangle {
|
||||
Layout.preferredWidth: 36
|
||||
Layout.preferredHeight: 36
|
||||
color: root.primaryColor
|
||||
radius: 18
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "+"
|
||||
color: "#ffffff"
|
||||
font.pixelSize: 20
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
|
||||
// Text input
|
||||
TextField {
|
||||
id: taskInput
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 36
|
||||
placeholderText: qsTr("Add a new task...")
|
||||
placeholderTextColor: root.darkMode ? "#888888" : "#999999"
|
||||
color: root.textColor
|
||||
font.pixelSize: 16
|
||||
selectByMouse: true
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
border.color: "transparent"
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: root.addTask()
|
||||
Keys.onEnterPressed: root.addTask()
|
||||
|
||||
}
|
||||
|
||||
// Add button
|
||||
Button {
|
||||
id: addButton
|
||||
Layout.preferredWidth: 80
|
||||
Layout.preferredHeight: 36
|
||||
text: qsTr("Add")
|
||||
enabled: taskInput.text.trim().length > 0
|
||||
|
||||
background: Rectangle {
|
||||
color: addButton.enabled ?
|
||||
(addButton.pressed ? Qt.darker(root.primaryColor, 1.2) : root.primaryColor) :
|
||||
(root.darkMode ? "#404040" : "#e0e0e0")
|
||||
radius: 8
|
||||
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: addButton.text
|
||||
color: addButton.enabled ? "#ffffff" : (root.darkMode ? "#888888" : "#cccccc")
|
||||
font.pixelSize: 14
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
}
|
||||
|
||||
onClicked: root.addTask()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addTask() {
|
||||
//TODO: Implement task addition logic
|
||||
console.log("Task added.")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: 80
|
||||
|
||||
signal toggleDarkMode()
|
||||
|
||||
// Properties that will be bound from parent
|
||||
property color textColor: "#333333"
|
||||
property color textSecondary: "#999999"
|
||||
property bool darkMode: false
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
RowLayout{
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 8
|
||||
anchors.rightMargin: 8
|
||||
spacing: 12
|
||||
|
||||
// App icon
|
||||
Text {
|
||||
text: "📝"
|
||||
font.pixelSize: 32
|
||||
}
|
||||
|
||||
// App title and subtitle
|
||||
Column {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: "My Tasks"
|
||||
font.pixelSize: 28
|
||||
font.weight: Font.Bold
|
||||
color: root.textColor
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Stay organized, stay productive")
|
||||
font.pixelSize: 12
|
||||
color: root.textSecondary
|
||||
opacity: 0.8
|
||||
}
|
||||
}
|
||||
|
||||
// Dark mode toggle
|
||||
Button {
|
||||
id: themeToggle
|
||||
Layout.preferredWidth: 50
|
||||
Layout.preferredHeight: 50
|
||||
|
||||
background: Rectangle {
|
||||
color: themeToggle.pressed ?
|
||||
(root.darkMode ? "#404040" : "#e0e0e0") :
|
||||
(root.darkMode ? "#2d2d2d" : "#f5f5f5")
|
||||
radius: 25
|
||||
border.color: root.darkMode ? "#555555" : "#d0d0d0"
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
contentItem: Text{
|
||||
text: root.darkMode ? "☀️" : "🌙"
|
||||
font.pixelSize: 20
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
// Emit the signal when the button is clicked
|
||||
onClicked: root.toggleDarkMode()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
22
Qt6QMLBeginnersCode/10-TodoListApp/03_task_bar/src/main.cpp
Normal file
22
Qt6QMLBeginnersCode/10-TodoListApp/03_task_bar/src/main.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQuickStyle>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
// Set Qt Quick Controls style to Basic to enable customization
|
||||
QQuickStyle::setStyle("Basic");
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("TodoList", "MainView");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
ApplicationWindow {
|
||||
id: root
|
||||
width: 400
|
||||
height: 700
|
||||
visible: true
|
||||
title: qsTr("My Tasks")
|
||||
|
||||
|
||||
// Theme properties
|
||||
property bool darkMode: false
|
||||
property color backgroundColor: darkMode ? "#1e1e1e" : "#f0f2f5"
|
||||
property color primaryColor: "#007aff"
|
||||
property color textColor: darkMode ? "#ffffff" : "#333333"
|
||||
property color cardColor: darkMode ? "#2d2d2d" : "#ffffff"
|
||||
property color completedColor: darkMode ? "#666666" : "#999999"
|
||||
|
||||
// Background
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.backgroundColor
|
||||
}
|
||||
|
||||
//The components of the ui
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 20
|
||||
spacing: 20
|
||||
|
||||
//Placeholder for header (we'll add this next)
|
||||
/*
|
||||
Rectangle{
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 80
|
||||
color: "transparent"
|
||||
border.color: root.textColor
|
||||
border.width: 1
|
||||
|
||||
Text{
|
||||
anchors.centerIn: parent
|
||||
text: "Header will go here"
|
||||
color: root.textColor
|
||||
}
|
||||
}
|
||||
*/
|
||||
//The actual AppHeader component to replace the place holder
|
||||
AppHeader {
|
||||
id: header
|
||||
Layout.fillWidth: true
|
||||
textColor: root.textColor
|
||||
textSecondary: root.completedColor
|
||||
darkMode: root.darkMode
|
||||
onToggleDarkMode: root.darkMode = !root.darkMode
|
||||
}
|
||||
|
||||
// Add task bar
|
||||
AddTaskBar {
|
||||
id: addTaskBar
|
||||
Layout.fillWidth: true
|
||||
backgroundColor: root.cardColor
|
||||
textColor: root.textColor
|
||||
primaryColor: root.primaryColor
|
||||
darkMode: root.darkMode
|
||||
|
||||
}
|
||||
|
||||
|
||||
//Add a spacer to push things up. Will remove later
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(TodoList VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Quick QuickControls2)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.8)
|
||||
|
||||
qt_add_executable(TodoList
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(TodoList
|
||||
URI TodoList
|
||||
VERSION 1.0
|
||||
QML_FILES
|
||||
# Main View
|
||||
src/views/MainView.qml
|
||||
|
||||
# Components
|
||||
src/components/AppHeader.qml
|
||||
src/components/AddTaskBar.qml
|
||||
src/components/TaskItem.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(TodoList PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.app01_todolist_starter
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(TodoList
|
||||
PRIVATE Qt6::Quick
|
||||
Qt6::QuickControls2
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS TodoList
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,106 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: 60
|
||||
|
||||
signal taskAdded(string taskText)
|
||||
|
||||
property color backgroundColor: "#ffffff"
|
||||
property color textColor: "#333333"
|
||||
property color primaryColor: "#007aff"
|
||||
property bool darkMode: false
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.backgroundColor
|
||||
radius: 12
|
||||
border.color: root.darkMode ? "#404040" : "#e0e0e0"
|
||||
border.width: 1
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
spacing: 12
|
||||
|
||||
// Add icon
|
||||
Rectangle {
|
||||
Layout.preferredWidth: 36
|
||||
Layout.preferredHeight: 36
|
||||
color: root.primaryColor
|
||||
radius: 18
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "+"
|
||||
color: "#ffffff"
|
||||
font.pixelSize: 20
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
|
||||
// Text input
|
||||
TextField {
|
||||
id: taskInput
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 36
|
||||
placeholderText: qsTr("Add a new task...")
|
||||
placeholderTextColor: root.darkMode ? "#888888" : "#999999"
|
||||
color: root.textColor
|
||||
font.pixelSize: 16
|
||||
selectByMouse: true
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
border.color: "transparent"
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: root.addTask()
|
||||
Keys.onEnterPressed: root.addTask()
|
||||
|
||||
}
|
||||
|
||||
// Add button
|
||||
Button {
|
||||
id: addButton
|
||||
Layout.preferredWidth: 80
|
||||
Layout.preferredHeight: 36
|
||||
text: qsTr("Add")
|
||||
enabled: taskInput.text.trim().length > 0
|
||||
|
||||
background: Rectangle {
|
||||
color: addButton.enabled ?
|
||||
(addButton.pressed ? Qt.darker(root.primaryColor, 1.2) : root.primaryColor) :
|
||||
(root.darkMode ? "#404040" : "#e0e0e0")
|
||||
radius: 8
|
||||
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: addButton.text
|
||||
color: addButton.enabled ? "#ffffff" : (root.darkMode ? "#888888" : "#cccccc")
|
||||
font.pixelSize: 14
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
}
|
||||
|
||||
onClicked: root.addTask()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addTask() {
|
||||
//TODO: Implement task addition logic
|
||||
console.log("Task added.")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: 80
|
||||
|
||||
signal toggleDarkMode()
|
||||
|
||||
// Properties that will be bound from parent
|
||||
property color textColor: "#333333"
|
||||
property color textSecondary: "#999999"
|
||||
property bool darkMode: false
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
RowLayout{
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 8
|
||||
anchors.rightMargin: 8
|
||||
spacing: 12
|
||||
|
||||
// App icon
|
||||
Text {
|
||||
text: "📝"
|
||||
font.pixelSize: 32
|
||||
}
|
||||
|
||||
// App title and subtitle
|
||||
Column {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: "My Tasks"
|
||||
font.pixelSize: 28
|
||||
font.weight: Font.Bold
|
||||
color: root.textColor
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Stay organized, stay productive")
|
||||
font.pixelSize: 12
|
||||
color: root.textSecondary
|
||||
opacity: 0.8
|
||||
}
|
||||
}
|
||||
|
||||
// Dark mode toggle
|
||||
Button {
|
||||
id: themeToggle
|
||||
Layout.preferredWidth: 50
|
||||
Layout.preferredHeight: 50
|
||||
|
||||
background: Rectangle {
|
||||
color: themeToggle.pressed ?
|
||||
(root.darkMode ? "#404040" : "#e0e0e0") :
|
||||
(root.darkMode ? "#2d2d2d" : "#f5f5f5")
|
||||
radius: 25
|
||||
border.color: root.darkMode ? "#555555" : "#d0d0d0"
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
contentItem: Text{
|
||||
text: root.darkMode ? "☀️" : "🌙"
|
||||
font.pixelSize: 20
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
// Emit the signal when the button is clicked
|
||||
onClicked: root.toggleDarkMode()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: 56
|
||||
|
||||
required property string taskTitle
|
||||
required property bool taskDone
|
||||
|
||||
signal toggleDone()
|
||||
signal deleteTask()
|
||||
|
||||
property color backgroundColor: "#ffffff"
|
||||
property color textColor: "#333333"
|
||||
property color completedColor: "#999999"
|
||||
property color primaryColor: "#007aff"
|
||||
property bool darkMode: false
|
||||
|
||||
// Constants for this component
|
||||
readonly property int itemHeight: 56
|
||||
readonly property int margins: 4
|
||||
readonly property int innerMargins: 12
|
||||
readonly property int checkboxSize: 24
|
||||
readonly property int deleteButtonSize: 32
|
||||
|
||||
Rectangle {
|
||||
id: taskItemBackground
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
id: itemBackground
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.margins
|
||||
color: root.backgroundColor
|
||||
radius: 8
|
||||
border.color: root.taskDone ? "transparent" : (root.darkMode ? "#404040" : "#f0f0f0")
|
||||
border.width: 1
|
||||
opacity: root.taskDone ? 0.7 : 1.0
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.innerMargins
|
||||
spacing: 12
|
||||
|
||||
// Checkbox
|
||||
Rectangle {
|
||||
id: checkbox
|
||||
Layout.preferredWidth: root.checkboxSize
|
||||
Layout.preferredHeight: root.checkboxSize
|
||||
color: root.taskDone ? root.primaryColor : "transparent"
|
||||
border.color: root.taskDone ? root.primaryColor : (root.darkMode ? "#666666" : "#cccccc")
|
||||
border.width: 2
|
||||
radius: 4
|
||||
|
||||
// Checkmark
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "✓"
|
||||
color: "#ffffff"
|
||||
font.pixelSize: 16
|
||||
font.weight: Font.Bold
|
||||
opacity: root.taskDone ? 1.0 : 0.0
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
root.toggleDone()
|
||||
}
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Task text
|
||||
Text {
|
||||
id: taskText
|
||||
Layout.fillWidth: true
|
||||
text: root.taskTitle
|
||||
color: root.taskDone ? root.completedColor : root.textColor
|
||||
font.pixelSize: 16
|
||||
font.strikeout: root.taskDone
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: root.toggleDone()
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
}
|
||||
|
||||
// Delete button
|
||||
Button {
|
||||
id: deleteButton
|
||||
Layout.preferredWidth: root.deleteButtonSize
|
||||
Layout.preferredHeight: root.deleteButtonSize
|
||||
opacity: itemBackground.hovered ? 1.0 : 0.3
|
||||
|
||||
background: Rectangle {
|
||||
color: deleteButton.pressed ? "#ff3b30" : "transparent"
|
||||
radius: 16
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: "🗑"
|
||||
font.pixelSize: 16
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
console.log("Delete task clicked")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hover effect
|
||||
property bool hovered: false
|
||||
|
||||
HoverHandler {
|
||||
onHoveredChanged: itemBackground.hovered = hovered
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
22
Qt6QMLBeginnersCode/10-TodoListApp/04_task_item/src/main.cpp
Normal file
22
Qt6QMLBeginnersCode/10-TodoListApp/04_task_item/src/main.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQuickStyle>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
// Set Qt Quick Controls style to Basic to enable customization
|
||||
QQuickStyle::setStyle("Basic");
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("TodoList", "MainView");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
ApplicationWindow {
|
||||
id: root
|
||||
width: 400
|
||||
height: 700
|
||||
visible: true
|
||||
title: qsTr("My Tasks")
|
||||
|
||||
|
||||
// Theme properties
|
||||
property bool darkMode: false
|
||||
property color backgroundColor: darkMode ? "#1e1e1e" : "#f0f2f5"
|
||||
property color primaryColor: "#007aff"
|
||||
property color textColor: darkMode ? "#ffffff" : "#333333"
|
||||
property color cardColor: darkMode ? "#2d2d2d" : "#ffffff"
|
||||
property color completedColor: darkMode ? "#666666" : "#999999"
|
||||
|
||||
// Background
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.backgroundColor
|
||||
}
|
||||
|
||||
//The components of the ui
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 20
|
||||
spacing: 20
|
||||
|
||||
//Placeholder for header (we'll add this next)
|
||||
/*
|
||||
Rectangle{
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 80
|
||||
color: "transparent"
|
||||
border.color: root.textColor
|
||||
border.width: 1
|
||||
|
||||
Text{
|
||||
anchors.centerIn: parent
|
||||
text: "Header will go here"
|
||||
color: root.textColor
|
||||
}
|
||||
}
|
||||
*/
|
||||
//The actual AppHeader component to replace the place holder
|
||||
AppHeader {
|
||||
id: header
|
||||
Layout.fillWidth: true
|
||||
textColor: root.textColor
|
||||
textSecondary: root.completedColor
|
||||
darkMode: root.darkMode
|
||||
onToggleDarkMode: root.darkMode = !root.darkMode
|
||||
}
|
||||
|
||||
// Add task bar
|
||||
AddTaskBar {
|
||||
id: addTaskBar
|
||||
Layout.fillWidth: true
|
||||
backgroundColor: root.cardColor
|
||||
textColor: root.textColor
|
||||
primaryColor: root.primaryColor
|
||||
darkMode: root.darkMode
|
||||
|
||||
}
|
||||
|
||||
// Test TaskItem
|
||||
TaskItem {
|
||||
id: testTaskItem
|
||||
Layout.fillWidth: true
|
||||
taskTitle: "Sample Task Item"
|
||||
taskDone: false
|
||||
backgroundColor: root.cardColor
|
||||
textColor: root.textColor
|
||||
completedColor: root.completedColor
|
||||
primaryColor: root.primaryColor
|
||||
darkMode: root.darkMode
|
||||
|
||||
onToggleDone: {
|
||||
testTaskItem.taskDone = !testTaskItem.taskDone
|
||||
}
|
||||
|
||||
onDeleteTask: {
|
||||
console.log("Delete task clicked")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Add a spacer to push things up. Will remove later
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) Daniel Gakwaya.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(10-PathView VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
qt_add_executable(app10-PathView
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app10-PathView
|
||||
URI 10-PathView
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
set_target_properties(app10-PathView PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app10-PathView
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
install(TARGETS app10-PathView
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,203 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
|
||||
Window {
|
||||
id: rootId
|
||||
width: 340
|
||||
height: 480
|
||||
visible: true
|
||||
title: qsTr("PathView")
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: "#EBEBEB"
|
||||
|
||||
|
||||
ListModel {
|
||||
id: modelId
|
||||
ListElement { our_color: "red" }
|
||||
ListElement { our_color: "green" }
|
||||
ListElement { our_color: "blue" }
|
||||
ListElement { our_color: "yellow" }
|
||||
ListElement { our_color: "black" }
|
||||
ListElement { our_color: "dodgerblue" }
|
||||
ListElement { our_color: "purple" }
|
||||
ListElement { our_color: "magenta" }
|
||||
ListElement { our_color: "yellowgreen" }
|
||||
ListElement { our_color: "skyblue" }
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: delegateId
|
||||
Column {
|
||||
//opacity: PathView.opacity
|
||||
scale: PathView.scale
|
||||
opacity: PathView.isCurrentItem ? 1 : 0.3
|
||||
readonly property bool is_current: PathView.isCurrentItem
|
||||
|
||||
|
||||
/*
|
||||
Rectangle{
|
||||
width: 5
|
||||
height: 5
|
||||
color: "black"
|
||||
radius: 5
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
Rectangle {
|
||||
anchors.horizontalCenter: textId.horizontalCenter
|
||||
width: 64
|
||||
height: 64
|
||||
radius: 20
|
||||
color: model.our_color
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
if(is_current){
|
||||
console.log("Clicked on "+ model.our_color)
|
||||
}else{
|
||||
console.log("Not current item")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Text {
|
||||
id: textId
|
||||
text: model.our_color; font.pixelSize: 24
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PathView {
|
||||
anchors.fill: parent
|
||||
model: modelId
|
||||
//model: 100
|
||||
delegate: delegateId
|
||||
focus: true
|
||||
|
||||
path: Path {
|
||||
|
||||
//Bottom : Starting Point
|
||||
startX: rootId.width/2
|
||||
startY: rootId.height - 50
|
||||
|
||||
PathAttribute{
|
||||
name: "scale"
|
||||
value: 1
|
||||
}
|
||||
/*
|
||||
PathAttribute{
|
||||
name: "opacity"
|
||||
value: 1
|
||||
}
|
||||
*/
|
||||
|
||||
// Towards Left
|
||||
PathCubic {
|
||||
x: 50
|
||||
y: rootId.height/2
|
||||
|
||||
control1X: rootId.width/2 - rootId.width/8
|
||||
control1Y: rootId.height
|
||||
control2X: 0
|
||||
control2Y: rootId.height/2 + rootId.height/8
|
||||
|
||||
}
|
||||
|
||||
PathAttribute{
|
||||
name: "scale"
|
||||
value: 0.5
|
||||
}
|
||||
/*
|
||||
PathAttribute{
|
||||
name: "opacity"
|
||||
value: 0.5
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//Towards Top: Q2
|
||||
PathCubic {
|
||||
x: rootId.width/2
|
||||
y: 50
|
||||
control1X: 0
|
||||
control1Y: (rootId.height/2 - rootId.height/8)
|
||||
control2X : (rootId.width/2 - rootId.width/8)
|
||||
control2Y: 0
|
||||
}
|
||||
|
||||
|
||||
PathAttribute{
|
||||
name: "scale"
|
||||
value: 0.3
|
||||
}
|
||||
|
||||
/*
|
||||
PathAttribute{
|
||||
name: "opacity"
|
||||
value: 0.5
|
||||
}
|
||||
*/
|
||||
|
||||
//Towards Right: Q3
|
||||
PathCubic {
|
||||
x: rootId.width - 50
|
||||
y: rootId.height/2
|
||||
control1X: rootId.width/2 + rootId.width/8
|
||||
control1Y: 0
|
||||
control2X: rootId.width
|
||||
control2Y: rootId.height/2 - rootId.height/8
|
||||
}
|
||||
|
||||
|
||||
PathAttribute{
|
||||
name: "scale"
|
||||
value: 0.5
|
||||
}
|
||||
|
||||
/*
|
||||
PathAttribute{
|
||||
name: "opacity"
|
||||
value: 0.5
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//Towards bottom: Q4
|
||||
PathCubic {
|
||||
x: rootId.width/2
|
||||
y: rootId.height - 50
|
||||
control1X: rootId.width
|
||||
control1Y: rootId.height/2 + rootId.height/8
|
||||
control2X: rootId.width/2 + rootId.width/8
|
||||
control2Y: rootId.height
|
||||
}
|
||||
|
||||
|
||||
PathAttribute{
|
||||
name: "scale";value: 1
|
||||
}
|
||||
|
||||
/*
|
||||
PathAttribute{
|
||||
name: "opacity";value: 0.5
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
Keys.onLeftPressed: decrementCurrentIndex()
|
||||
Keys.onRightPressed: incrementCurrentIndex()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
|
||||
&app, []() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("10-PathView", "Main");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) Daniel Gakwaya.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(11-TableView VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick QuickControls2)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
qt_add_executable(app11-TableView
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app11-TableView
|
||||
URI 11-TableView
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
set_target_properties(app11-TableView PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app11-TableView
|
||||
PRIVATE Qt6::Quick Qt6::QuickControls2
|
||||
)
|
||||
|
||||
install(TARGETS app11-TableView
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,128 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Qt.labs.qmlmodels
|
||||
|
||||
ApplicationWindow {
|
||||
width: 680
|
||||
height: 400
|
||||
visible: true
|
||||
|
||||
HorizontalHeaderView {
|
||||
id: horizontalHeader
|
||||
anchors.left: tableViewId.left
|
||||
anchors.top: parent.top
|
||||
syncView: tableViewId
|
||||
|
||||
}
|
||||
|
||||
VerticalHeaderView {
|
||||
id: verticalHeader
|
||||
anchors.top: tableViewId.top
|
||||
anchors.left: parent.left
|
||||
syncView: tableViewId
|
||||
}
|
||||
|
||||
|
||||
TableModel {
|
||||
id: tableModelId
|
||||
TableModelColumn { display: "checked" }
|
||||
TableModelColumn { display: "amount" }
|
||||
TableModelColumn { display: "fruitType" }
|
||||
TableModelColumn { display: "fruitName" }
|
||||
TableModelColumn { display: "fruitPrice" }
|
||||
|
||||
// Each row is one type of fruit that can be ordered
|
||||
rows: [
|
||||
{
|
||||
// Each property is one cell/column.
|
||||
checked: false,
|
||||
amount: 1,
|
||||
fruitType: "Apple",
|
||||
fruitName: "Granny Smith",
|
||||
fruitPrice: 1.50
|
||||
},
|
||||
{
|
||||
checked: true,
|
||||
amount: 4,
|
||||
fruitType: "Orange",
|
||||
fruitName: "Navel",
|
||||
fruitPrice: 2.50
|
||||
},
|
||||
{
|
||||
checked: false,
|
||||
amount: 1,
|
||||
fruitType: "Banana",
|
||||
fruitName: "Cavendish",
|
||||
fruitPrice: 3.50
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
TableView {
|
||||
id: tableViewId
|
||||
anchors.left: verticalHeader.right
|
||||
anchors.top: horizontalHeader.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
columnSpacing: 1
|
||||
rowSpacing: 1
|
||||
|
||||
model: tableModelId
|
||||
|
||||
/*
|
||||
delegate: TextInput {
|
||||
text: model.display
|
||||
padding: 12
|
||||
selectByMouse: true
|
||||
|
||||
onAccepted: model.display = text
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#efefef"
|
||||
z: -1
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
delegate: DelegateChooser {
|
||||
DelegateChoice {
|
||||
column: 0
|
||||
delegate: CheckBox {
|
||||
checked: model.display
|
||||
onToggled: model.display = checked
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
column: 1
|
||||
delegate: SpinBox {
|
||||
value: model.display
|
||||
onValueModified: model.display = value
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
delegate: TextField {
|
||||
text: model.display
|
||||
selectByMouse: true
|
||||
implicitWidth: 140
|
||||
onAccepted: model.display = text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Button{
|
||||
text: "See the data"
|
||||
anchors.bottom: parent.bottom
|
||||
onClicked: {
|
||||
console.log(tableModelId.data(tableModelId.index(0,0),"display"))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQuickStyle>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QQuickStyle::setStyle("Material");
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
|
||||
&app, []() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("11-TableView", "Main");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) Daniel Gakwaya.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(12-TableViewCppModel VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick QuickControls2)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
qt_add_executable(app12-TableViewCppModel
|
||||
main.cpp tablemodel.h tablemodel.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app12-TableViewCppModel
|
||||
URI 12-TableViewCppModel
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
set_target_properties(app12-TableViewCppModel PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app12-TableViewCppModel
|
||||
PRIVATE Qt6::Quick Qt6::QuickControls2
|
||||
)
|
||||
|
||||
install(TARGETS app12-TableViewCppModel
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import TableModel // Import the custom model from C++
|
||||
|
||||
ApplicationWindow {
|
||||
width: 680
|
||||
height: 400
|
||||
visible: true
|
||||
|
||||
HorizontalHeaderView {
|
||||
id: horizontalHeader
|
||||
anchors.left: tableViewId.left
|
||||
anchors.top: parent.top
|
||||
syncView: tableViewId
|
||||
clip: true
|
||||
|
||||
}
|
||||
|
||||
VerticalHeaderView {
|
||||
id: verticalHeader
|
||||
anchors.top: tableViewId.top
|
||||
anchors.left: parent.left
|
||||
syncView: tableViewId
|
||||
clip: true
|
||||
|
||||
}
|
||||
|
||||
TableModel{
|
||||
id: tableModelId
|
||||
}
|
||||
|
||||
TableView {
|
||||
id: tableViewId
|
||||
anchors.left: verticalHeader.right
|
||||
anchors.top: horizontalHeader.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
columnSpacing: 1
|
||||
rowSpacing: 1
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
model: tableModelId
|
||||
|
||||
delegate: Label {
|
||||
text: model.tabledata
|
||||
width: 100
|
||||
padding: 12
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#efefef"
|
||||
z: -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button{
|
||||
text: "See the data"
|
||||
anchors.bottom: parent.bottom
|
||||
onClicked: {
|
||||
console.log(tableModelId.get_display_data(tableModelId.index(0,1)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQuickStyle>
|
||||
#include "tablemodel.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
qmlRegisterType<TableModel>("TableModel", 0, 1, "TableModel");
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QQuickStyle::setStyle("Material");
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
|
||||
&app, []() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("12-TableViewCppModel", "Main");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "tablemodel.h"
|
||||
|
||||
TableModel::TableModel(QObject *parent) : QAbstractTableModel(parent)
|
||||
{
|
||||
table.append({"Mary","Jane","27","Teacher","Married","Verkso","Tukk"});
|
||||
table.append({"John","Doe","32","Farmer","Single","Gounduana","Mestkv"});
|
||||
table.append({"Mary","Jane","27","Teacher","Married","Verkso","Tukk"});
|
||||
table.append({"John","Doe","32","Farmer","Single","Gounduana","Mestkv"});
|
||||
table.append({"Mary","Jane","27","Teacher","Married","Verkso","Tukk"});
|
||||
table.append({"John","Doe","32","Farmer","Single","Gounduana","Mestkv"});
|
||||
table.append({"Mary","Jane","27","Teacher","Married","Verkso","Tukk"});
|
||||
table.append({"John","Doe","32","Farmer","Single","Gounduana","Mestkv"});
|
||||
table.append({"Mary","Jane","27","Teacher","Married","Verkso","Tukk"});
|
||||
table.append({"John","Doe","32","Farmer","Single","Gounduana","Mestkv"});
|
||||
table.append({"Mary","Jane","27","Teacher","Married","Verkso","Tukk"});
|
||||
table.append({"John","Doe","32","Farmer","Single","Gounduana","Mestkv"});
|
||||
table.append({"Mary","Jane","27","Teacher","Married","Verkso","Tukk"});
|
||||
table.append({"John","Doe","32","Farmer","Single","Gounduana","Mestkv"});
|
||||
table.append({"Mary","Jane","27","Teacher","Married","Verkso","Tukk"});
|
||||
table.append({"John","Doe","32","Farmer","Single","Gounduana","Mestkv"});
|
||||
table.append({"Mary","Jane","27","Teacher","Married","Verkso","Tukk"});
|
||||
table.append({"John","Doe","32","Farmer","Single","Gounduana","Mestkv"});
|
||||
table.append({"Mary","Jane","27","Teacher","Married","Verkso","Tukk"});
|
||||
|
||||
}
|
||||
|
||||
int TableModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return table.size();//Number of rows
|
||||
}
|
||||
|
||||
int TableModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return table.at(0).size();//Columns
|
||||
}
|
||||
|
||||
QVariant TableModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
switch (role) {
|
||||
case TableDataRole:
|
||||
{
|
||||
return table.at(index.row()).at(index.column());
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole) {
|
||||
return QVariant();
|
||||
}
|
||||
if (orientation == Qt::Horizontal && section == 0) {
|
||||
return "Name";
|
||||
} else if (orientation == Qt::Horizontal && section == 1) {
|
||||
return "Name";
|
||||
} else if (orientation == Qt::Horizontal && section == 2) {
|
||||
return "Age";
|
||||
} else if (orientation == Qt::Horizontal && section == 3) {
|
||||
return "Job";
|
||||
} else if (orientation == Qt::Horizontal && section == 4) {
|
||||
return "Status";
|
||||
} else if (orientation == Qt::Horizontal && section == 5) {
|
||||
return "Country";
|
||||
} else if (orientation == Qt::Horizontal && section == 6) {
|
||||
return "City";
|
||||
}
|
||||
|
||||
if(orientation == Qt::Vertical){
|
||||
return QVariant::fromValue(section + 1) ;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> TableModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles[TableDataRole] = "tabledata";
|
||||
return roles;
|
||||
}
|
||||
|
||||
QVariant TableModel::get_display_data(const QModelIndex &index){
|
||||
return data(index,TableDataRole );
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef TABLEMODEL_H
|
||||
#define TABLEMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
class TableModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
enum TableRoles{
|
||||
TableDataRole = Qt::UserRole + 1,
|
||||
};
|
||||
public:
|
||||
explicit TableModel(QObject *parent = nullptr);
|
||||
int rowCount(const QModelIndex & = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex & = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE
|
||||
QVariant get_display_data(const QModelIndex& index);
|
||||
|
||||
private:
|
||||
QVector<QVector<QString>> table;
|
||||
};
|
||||
|
||||
#endif // TABLEMODEL_H
|
||||
@@ -0,0 +1,5 @@
|
||||
[General]
|
||||
buildDir="D:/Sandbox/Qt6QMLBeginnersCode/11-ModelViewArchitecture/14-TodoListModelView/build"
|
||||
no-cmake-calls=false
|
||||
docDir=C:/Qt/Docs/Qt-6.9.0
|
||||
importPaths="C:/Qt/6.9.0/mingw_64/qml"
|
||||
@@ -0,0 +1,52 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(TodoList VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Quick QuickControls2)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.8)
|
||||
|
||||
qt_add_executable(TodoList
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(TodoList
|
||||
URI TodoList
|
||||
VERSION 1.0
|
||||
QML_FILES
|
||||
# Main View
|
||||
src/views/MainView.qml
|
||||
|
||||
# Components
|
||||
src/components/AppHeader.qml
|
||||
src/components/AddTaskBar.qml
|
||||
src/components/TaskItem.qml
|
||||
src/components/TaskStats.qml
|
||||
|
||||
# Models
|
||||
src/models/TaskListModel.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(TodoList PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.app01_todolist_starter
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(TodoList
|
||||
PRIVATE Qt6::Quick Qt6::QuickControls2
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS TodoList
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,110 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: 60
|
||||
|
||||
signal taskAdded(string taskText)
|
||||
|
||||
property color backgroundColor: "#ffffff"
|
||||
property color textColor: "#333333"
|
||||
property color primaryColor: "#007aff"
|
||||
property bool darkMode: false
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.backgroundColor
|
||||
radius: 12
|
||||
border.color: root.darkMode ? "#404040" : "#e0e0e0"
|
||||
border.width: 1
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
spacing: 12
|
||||
|
||||
// Add icon
|
||||
Rectangle {
|
||||
Layout.preferredWidth: 36
|
||||
Layout.preferredHeight: 36
|
||||
color: root.primaryColor
|
||||
radius: 18
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "+"
|
||||
color: "#ffffff"
|
||||
font.pixelSize: 20
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
|
||||
// Text input
|
||||
TextField {
|
||||
id: taskInput
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 36
|
||||
placeholderText: qsTr("Add a new task...")
|
||||
placeholderTextColor: root.darkMode ? "#888888" : "#999999"
|
||||
color: root.textColor
|
||||
font.pixelSize: 16
|
||||
selectByMouse: true
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
border.color: "transparent"
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: root.addTask()
|
||||
Keys.onEnterPressed: root.addTask()
|
||||
|
||||
}
|
||||
|
||||
// Add button
|
||||
Button {
|
||||
id: addButton
|
||||
Layout.preferredWidth: 80
|
||||
Layout.preferredHeight: 36
|
||||
text: qsTr("Add")
|
||||
enabled: taskInput.text.trim().length > 0
|
||||
|
||||
background: Rectangle {
|
||||
color: addButton.enabled ?
|
||||
(addButton.pressed ? Qt.darker(root.primaryColor, 1.2) : root.primaryColor) :
|
||||
(root.darkMode ? "#404040" : "#e0e0e0")
|
||||
radius: 8
|
||||
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: addButton.text
|
||||
color: addButton.enabled ? "#ffffff" : (root.darkMode ? "#888888" : "#cccccc")
|
||||
font.pixelSize: 14
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
}
|
||||
|
||||
onClicked: root.addTask()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addTask() {
|
||||
if (taskInput.text.trim().length > 0) {
|
||||
root.taskAdded(taskInput.text.trim())
|
||||
taskInput.text = ""
|
||||
taskInput.focus = false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: 80
|
||||
|
||||
signal toggleDarkMode()
|
||||
|
||||
// Properties that will be bound from parent
|
||||
property color textColor: "#333333"
|
||||
property color textSecondary: "#999999"
|
||||
property bool darkMode: false
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
RowLayout{
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 8
|
||||
anchors.rightMargin: 8
|
||||
spacing: 12
|
||||
|
||||
// App icon
|
||||
Text {
|
||||
text: "📝"
|
||||
font.pixelSize: 32
|
||||
}
|
||||
|
||||
// App title and subtitle
|
||||
Column {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: "My Tasks"
|
||||
font.pixelSize: 28
|
||||
font.weight: Font.Bold
|
||||
color: root.textColor
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Stay organized, stay productive")
|
||||
font.pixelSize: 12
|
||||
color: root.textSecondary
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Dark mode toggle
|
||||
Button {
|
||||
id: themeToggle
|
||||
Layout.preferredWidth: 50
|
||||
Layout.preferredHeight: 50
|
||||
|
||||
background: Rectangle {
|
||||
color: themeToggle.pressed ?
|
||||
(root.darkMode ? "#404040" : "#e0e0e0") :
|
||||
(root.darkMode ? "#2d2d2d" : "#f5f5f5")
|
||||
radius: 25
|
||||
border.color: root.darkMode ? "#555555" : "#d0d0d0"
|
||||
border.width: 1
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: 150 }
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Text{
|
||||
text: root.darkMode ? "☀️" : "🌙"
|
||||
font.pixelSize: 20
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
//Emit the signal when the button is clicked
|
||||
onClicked: root.toggleDarkMode()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: 56
|
||||
|
||||
required property string taskTitle
|
||||
required property bool taskDone
|
||||
|
||||
signal toggleDone()
|
||||
signal deleteTask()
|
||||
|
||||
property color backgroundColor: "#ffffff"
|
||||
property color textColor: "#333333"
|
||||
property color completedColor: "#999999"
|
||||
property color primaryColor: "#007aff"
|
||||
property bool darkMode: false
|
||||
|
||||
// Constants for this component
|
||||
readonly property int itemHeight: 56
|
||||
readonly property int margins: 4
|
||||
readonly property int innerMargins: 12
|
||||
readonly property int checkboxSize: 24
|
||||
readonly property int deleteButtonSize: 32
|
||||
|
||||
Rectangle {
|
||||
id: taskItemBackground
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
id: itemBackground
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.margins
|
||||
color: root.backgroundColor
|
||||
radius: 8
|
||||
border.color: root.taskDone ? "transparent" : (root.darkMode ? "#404040" : "#f0f0f0")
|
||||
border.width: 1
|
||||
opacity: root.taskDone ? 0.7 : 1.0
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.innerMargins
|
||||
spacing: 12
|
||||
|
||||
// Checkbox
|
||||
Rectangle {
|
||||
id: checkbox
|
||||
Layout.preferredWidth: root.checkboxSize
|
||||
Layout.preferredHeight: root.checkboxSize
|
||||
color: root.taskDone ? root.primaryColor : "transparent"
|
||||
border.color: root.taskDone ? root.primaryColor : (root.darkMode ? "#666666" : "#cccccc")
|
||||
border.width: 2
|
||||
radius: 4
|
||||
|
||||
// Checkmark
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "✓"
|
||||
color: "#ffffff"
|
||||
font.pixelSize: 16
|
||||
font.weight: Font.Bold
|
||||
opacity: root.taskDone ? 1.0 : 0.0
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
root.toggleDone()
|
||||
}
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Task text
|
||||
Text {
|
||||
id: taskText
|
||||
Layout.fillWidth: true
|
||||
text: root.taskTitle
|
||||
color: root.taskDone ? root.completedColor : root.textColor
|
||||
font.pixelSize: 16
|
||||
font.strikeout: root.taskDone
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: root.toggleDone()
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
}
|
||||
|
||||
// Delete button
|
||||
Button {
|
||||
id: deleteButton
|
||||
Layout.preferredWidth: root.deleteButtonSize
|
||||
Layout.preferredHeight: root.deleteButtonSize
|
||||
opacity: itemBackground.hovered ? 1.0 : 0.3
|
||||
|
||||
background: Rectangle {
|
||||
color: deleteButton.pressed ? "#ff3b30" : "transparent"
|
||||
radius: 16
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: "🗑"
|
||||
font.pixelSize: 16
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
root.deleteTask()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hover effect
|
||||
property bool hovered: false
|
||||
|
||||
HoverHandler {
|
||||
onHoveredChanged: itemBackground.hovered = hovered
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: visible ? 60 : 0
|
||||
visible: totalTasks > 0
|
||||
|
||||
property int totalTasks: 0
|
||||
property int completedTasks: 0
|
||||
property int remainingTasks: 0
|
||||
property bool hasCompleted: false
|
||||
|
||||
property color backgroundColor: "#ffffff"
|
||||
property color textColor: "#333333"
|
||||
property color secondaryTextColor: "#666666"
|
||||
property color primaryColor: "#007aff"
|
||||
property color dangerColor: "#ff3b30"
|
||||
property bool darkMode: false
|
||||
|
||||
signal clearCompleted()
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.backgroundColor
|
||||
radius: 12
|
||||
border.color: root.darkMode ? "#404040" : "#e0e0e0"
|
||||
border.width: 1
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 16
|
||||
spacing: 16
|
||||
|
||||
// Statistics text
|
||||
Column {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: root.totalTasks === 1 ?
|
||||
qsTr("%1 task").arg(root.totalTasks) :
|
||||
qsTr("%1 tasks").arg(root.totalTasks)
|
||||
color: root.textColor
|
||||
font.pixelSize: 16
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
Text {
|
||||
text: root.completedTasks > 0 ?
|
||||
qsTr("%1 completed, %2 remaining").arg(root.completedTasks).arg(root.remainingTasks) :
|
||||
qsTr("No tasks completed yet")
|
||||
color: root.secondaryTextColor
|
||||
font.pixelSize: 14
|
||||
visible: root.totalTasks > 0
|
||||
}
|
||||
}
|
||||
|
||||
// Clear completed button
|
||||
Button {
|
||||
id: clearButton
|
||||
Layout.preferredHeight: 36
|
||||
text: qsTr("Clear Completed")
|
||||
visible: root.hasCompleted
|
||||
enabled: root.hasCompleted
|
||||
|
||||
background: Rectangle {
|
||||
color: clearButton.pressed ?
|
||||
Qt.darker(root.dangerColor, 1.2) :
|
||||
(clearButton.hovered ? root.dangerColor : "transparent")
|
||||
border.color: root.dangerColor
|
||||
border.width: 1
|
||||
radius: 8
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: clearButton.text
|
||||
color: clearButton.hovered ? "#ffffff" : root.dangerColor
|
||||
font.pixelSize: 14
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
onClicked: root.clearCompleted()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQuickStyle>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
// Set Qt Quick Controls style to Basic to enable customization
|
||||
QQuickStyle::setStyle("Basic");
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("TodoList", "MainView");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import QtQuick
|
||||
|
||||
ListModel {
|
||||
id: root
|
||||
|
||||
// Add some sample tasks for testing
|
||||
Component.onCompleted: {
|
||||
addTask("Learn Qt QML")
|
||||
addTask("Build a todo app")
|
||||
addTask("Practice QML components")
|
||||
}
|
||||
|
||||
// Add a new task
|
||||
function addTask(title) {
|
||||
if (title && title.trim().length > 0) {
|
||||
append({
|
||||
"title": title.trim(),
|
||||
"completed": false,
|
||||
"id": generateId()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle task completion status
|
||||
function toggleTask(index) {
|
||||
if (index >= 0 && index < count) {
|
||||
setProperty(index, "completed", !get(index).completed)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete a task
|
||||
function deleteTask(index) {
|
||||
if (index >= 0 && index < count) {
|
||||
remove(index)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete task by ID
|
||||
function deleteTaskById(taskId) {
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (get(i).id === taskId) {
|
||||
remove(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all completed tasks
|
||||
function clearCompletedTasks() {
|
||||
for (let i = count - 1; i >= 0; i--) {
|
||||
if (get(i).completed) {
|
||||
remove(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get statistics
|
||||
function getStats() {
|
||||
let total = count
|
||||
let completed = 0
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (get(i).completed) {
|
||||
completed++
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
"total": total,
|
||||
"completed": completed,
|
||||
"remaining": total - completed
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there are any completed tasks
|
||||
function hasCompletedTasks() {
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (get(i).completed) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Generate a unique ID for tasks
|
||||
function generateId() {
|
||||
return Date.now() + Math.random().toString(36).substr(2, 9)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
ApplicationWindow {
|
||||
id: root
|
||||
width: 400
|
||||
height: 700
|
||||
visible: true
|
||||
title: qsTr("My Tasks")
|
||||
|
||||
// Theme properties
|
||||
property bool darkMode: false
|
||||
property color backgroundColor: darkMode ? "#1e1e1e" : "#f0f2f5"
|
||||
property color primaryColor: "#007aff"
|
||||
property color textColor: darkMode ? "#ffffff" : "#333333"
|
||||
property color cardColor: darkMode ? "#2d2d2d" : "#ffffff"
|
||||
property color completedColor: darkMode ? "#666666" : "#999999"
|
||||
|
||||
// Task model - Using the dedicated TaskListModel
|
||||
TaskListModel {
|
||||
id: taskModel
|
||||
}
|
||||
|
||||
// Background
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.backgroundColor
|
||||
}
|
||||
|
||||
//The components of the ui
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 20
|
||||
spacing: 20
|
||||
|
||||
// Header
|
||||
AppHeader {
|
||||
id: header
|
||||
Layout.fillWidth: true
|
||||
textColor: root.textColor
|
||||
textSecondary: root.completedColor
|
||||
darkMode: root.darkMode
|
||||
onToggleDarkMode: root.darkMode = !root.darkMode
|
||||
}
|
||||
|
||||
// Add task bar
|
||||
AddTaskBar {
|
||||
id: addTaskBar
|
||||
Layout.fillWidth: true
|
||||
backgroundColor: root.cardColor
|
||||
textColor: root.textColor
|
||||
primaryColor: root.primaryColor
|
||||
darkMode: root.darkMode
|
||||
|
||||
onTaskAdded: function(taskText) {
|
||||
taskModel.addTask(taskText)
|
||||
}
|
||||
}
|
||||
|
||||
// Tasks list
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
color: root.cardColor
|
||||
radius: 12
|
||||
border.width: 1
|
||||
border.color: root.darkMode ? "#404040" : "#e0e0e0"
|
||||
|
||||
ScrollView {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 1
|
||||
clip: true
|
||||
|
||||
ListView {
|
||||
id: taskListView
|
||||
model: taskModel
|
||||
spacing: 8
|
||||
anchors.margins: 12
|
||||
|
||||
delegate: TaskItem {
|
||||
required property int index
|
||||
required property string title
|
||||
required property bool completed
|
||||
|
||||
width: taskListView.width
|
||||
taskTitle: title
|
||||
taskDone: completed
|
||||
backgroundColor: root.cardColor
|
||||
textColor: root.textColor
|
||||
completedColor: root.completedColor
|
||||
primaryColor: root.primaryColor
|
||||
darkMode: root.darkMode
|
||||
|
||||
onToggleDone: {
|
||||
taskModel.toggleTask(index)
|
||||
}
|
||||
|
||||
onDeleteTask: {
|
||||
taskModel.deleteTask(index)
|
||||
}
|
||||
}
|
||||
|
||||
// Empty state
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - 40
|
||||
height: 120
|
||||
color: "transparent"
|
||||
visible: taskListView.count === 0
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: 16
|
||||
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: "📝"
|
||||
font.pixelSize: 48
|
||||
opacity: 0.3
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("No tasks yet")
|
||||
color: root.completedColor
|
||||
font.pixelSize: 18
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("Add a task above to get started")
|
||||
color: root.completedColor
|
||||
font.pixelSize: 14
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Task statistics at bottom
|
||||
TaskStats {
|
||||
id: taskStats
|
||||
Layout.fillWidth: true
|
||||
backgroundColor: root.cardColor
|
||||
textColor: root.textColor
|
||||
secondaryTextColor: root.completedColor
|
||||
primaryColor: root.primaryColor
|
||||
darkMode: root.darkMode
|
||||
totalTasks: taskModel.count
|
||||
completedTasks: taskModel.getStats().completed
|
||||
remainingTasks: taskModel.getStats().remaining
|
||||
hasCompleted: taskModel.hasCompletedTasks()
|
||||
|
||||
onClearCompleted: {
|
||||
taskModel.clearCompletedTasks()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) Daniel Gakwaya.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(2-ListViewListModel VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
qt_add_executable(app2-ListViewListModel
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app2-ListViewListModel
|
||||
URI ListViewListModel
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
set_target_properties(app2-ListViewListModel PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app2-ListViewListModel
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
install(TARGETS app2-ListViewListModel
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
|
||||
Window {
|
||||
visible: true
|
||||
width: 640
|
||||
height: 480
|
||||
title: qsTr("ListView and ListModel Demo")
|
||||
|
||||
ListView {
|
||||
id: mListViewId
|
||||
anchors.fill: parent
|
||||
model: mModelId
|
||||
//delegate: delegateId
|
||||
|
||||
|
||||
delegate: Rectangle {
|
||||
id: rectangleId
|
||||
width: parent.width
|
||||
height: 50
|
||||
color: "beige"
|
||||
border.color: "yellowgreen"
|
||||
radius: 10
|
||||
|
||||
Text {
|
||||
id: textId
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: 20
|
||||
text: country + " : " + capital
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
console.log("Clicked on: "+ capital + ", "+ country)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
ListModel {
|
||||
id: mModelId
|
||||
ListElement {
|
||||
country: "Rwanda"
|
||||
capital: "Kigali"
|
||||
}
|
||||
ListElement {
|
||||
country: "Germany"; capital: "Berlin"
|
||||
}
|
||||
ListElement {
|
||||
country: "Japan"; capital: "Tokyo"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
country :"Nigeria"; capital: "Lagos"
|
||||
}
|
||||
ListElement {
|
||||
country: "Ghana"; capital: "Accra"
|
||||
}
|
||||
ListElement {
|
||||
country: "Kenya"; capital: "Nairobi"
|
||||
}
|
||||
ListElement {
|
||||
country: "India"; capital: "New Delhi"
|
||||
}
|
||||
ListElement {
|
||||
country: "Uganda"; capital: "Kampala"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: delegateId
|
||||
Rectangle {
|
||||
id: rectangleId
|
||||
width: parent.width
|
||||
height: 50
|
||||
color: "dodgerblue"
|
||||
border.color: "black"
|
||||
radius: 15
|
||||
|
||||
Text {
|
||||
id: textId
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: 20
|
||||
text: country + ": " + capital
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
console.log("Clicked on: "+ capital + ", "+ country)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
|
||||
&app, []() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("ListViewListModel", "Main");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) Daniel Gakwaya.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(3-InlineModels VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
qt_add_executable(app3-InlineModels
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app3-InlineModels
|
||||
URI 3-InlineModels
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
set_target_properties(app3-InlineModels PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app3-InlineModels
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
install(TARGETS app3-InlineModels
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
|
||||
Window {
|
||||
id: rootId
|
||||
visible: true
|
||||
width: 640
|
||||
height: 480
|
||||
title: qsTr("Inline Model")
|
||||
|
||||
|
||||
ListView {
|
||||
id: mListViewId
|
||||
anchors.fill: parent
|
||||
//model : ["January", "February", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"]
|
||||
model: 100
|
||||
delegate: Rectangle {
|
||||
id: rectangleId
|
||||
width: rootId.width
|
||||
height: 50
|
||||
color: "beige"
|
||||
border.color: "yellowgreen"
|
||||
radius: 10
|
||||
|
||||
Text {
|
||||
id: textId
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: 20
|
||||
text: modelData
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
console.log("Clicked on: "+ modelData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
|
||||
&app, []() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("3-InlineModels", "Main");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) Daniel Gakwaya.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(4-HeaderFooterHighlight VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
qt_add_executable(app4-HeaderFooterHighlight
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app4-HeaderFooterHighlight
|
||||
URI 4-HeaderFooterHighlight
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
set_target_properties(app4-HeaderFooterHighlight PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app4-HeaderFooterHighlight
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
install(TARGETS app4-HeaderFooterHighlight
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
|
||||
Window {
|
||||
id: rootId
|
||||
visible: true
|
||||
width: 640
|
||||
height: 480
|
||||
title: qsTr("Header Footer and Highlight")
|
||||
|
||||
ListView {
|
||||
id: mListViewId
|
||||
anchors.fill: parent
|
||||
header: headerId
|
||||
footer: Rectangle{
|
||||
width: rootId.width
|
||||
height: 50
|
||||
color: "dodgerblue"
|
||||
}
|
||||
highlight: Rectangle{
|
||||
width: rootId.width
|
||||
color: "blue"
|
||||
radius: 14
|
||||
border.color: "yellowgreen"
|
||||
z: 3
|
||||
opacity: 0.1
|
||||
}
|
||||
|
||||
model: ["January", "February", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"]
|
||||
delegate: Rectangle {
|
||||
id: delegateId
|
||||
width: rootId.width
|
||||
height: 50
|
||||
color: "beige"
|
||||
border.color: "yellowgreen"
|
||||
radius: 10
|
||||
|
||||
Text {
|
||||
id: textId
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: 20
|
||||
text : modelData
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
console.log("Clicked on: "+ modelData)
|
||||
mListViewId.currentIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: headerId
|
||||
Rectangle {
|
||||
id: headerRectId
|
||||
width: rootId.width
|
||||
height: 50
|
||||
color: "yellowgreen"
|
||||
border {color: "#9EDDF2"; width: 2}
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Months"
|
||||
font.pointSize: 20
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
|
||||
&app, []() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("4-HeaderFooterHighlight", "Main");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) Daniel Gakwaya.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(5-DecorationSection VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
qt_add_executable(app5-DecorationSection
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app5-DecorationSection
|
||||
URI 5-DecorationSection
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
set_target_properties(app5-DecorationSection PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app5-DecorationSection
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
install(TARGETS app5-DecorationSection
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
|
||||
Window {
|
||||
visible: true
|
||||
width: 640
|
||||
height: 480
|
||||
title: qsTr("Section (Decoration)")
|
||||
|
||||
|
||||
ListModel {
|
||||
id: mListModel
|
||||
|
||||
ListElement {
|
||||
names: "Seth Moris"; company: "GOOGLE"
|
||||
}
|
||||
ListElement {
|
||||
names: "Miriam Katv"; company: "GOOGLE"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
names: "Eugene Fitzgerald"; company: "GOOGLE"
|
||||
}
|
||||
ListElement {
|
||||
names: "Kantkl Vikney"; company : "GOOGLE"
|
||||
}
|
||||
ListElement {
|
||||
names: "Mary Beige"; company: "TESLA"
|
||||
}
|
||||
ListElement {
|
||||
names: "Bamba Pikt"; company: "TESLA"
|
||||
}
|
||||
ListElement {
|
||||
names: "Jeffery Mor"; company: "SIEMENS"
|
||||
}
|
||||
ListElement {
|
||||
names: "Pick Mo"; company: "SIEMENS"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
ListView {
|
||||
id: mListViewId
|
||||
anchors.fill: parent
|
||||
model : mListModel
|
||||
delegate: delegateId
|
||||
section {
|
||||
property: "company"
|
||||
criteria: ViewSection.FullString
|
||||
delegate: Rectangle{
|
||||
id: sectionRectId
|
||||
width : parent.width
|
||||
height: 50
|
||||
color: "red"
|
||||
border.color: "yellowgreen"
|
||||
radius: 14
|
||||
|
||||
Text {
|
||||
id: sectionTextId
|
||||
text : section
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: 20
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
console.log("Clicked on: " + section)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: delegateId
|
||||
Rectangle {
|
||||
id: rectangleId
|
||||
width : parent.width // Remember to specify these sizes or you'll have problems
|
||||
height: 50
|
||||
color: "beige"
|
||||
border.color: "yellowgreen"
|
||||
radius: 14
|
||||
|
||||
Text {
|
||||
id: textId
|
||||
anchors.centerIn: parent
|
||||
text: names
|
||||
font.pointSize: 20
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
console.log("Clicked on: " + names)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
|
||||
&app, []() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("5-DecorationSection", "Main");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) Daniel Gakwaya.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(6-Repeater VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
qt_add_executable(app6-Repeater
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app6-Repeater
|
||||
URI 6-Repeater
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
set_target_properties(app6-Repeater PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app6-Repeater
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
install(TARGETS app6-Repeater
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
|
||||
Window {
|
||||
visible: true
|
||||
width: 640
|
||||
height: 480
|
||||
title: qsTr("Repeater")
|
||||
|
||||
Flickable {
|
||||
contentHeight: columnId.implicitHeight
|
||||
anchors.fill : parent
|
||||
|
||||
|
||||
Column {
|
||||
id: columnId
|
||||
anchors.fill: parent
|
||||
spacing: 2
|
||||
|
||||
Repeater {
|
||||
id: repeaterId
|
||||
|
||||
//model: 15
|
||||
model: ["Jan", "Feb", "March"]
|
||||
delegate: Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
color: "dodgerblue"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: modelData
|
||||
font.pointSize: 20
|
||||
}
|
||||
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
console.log("Clicked on: "+modelData)
|
||||
console.log("count: " + repeaterId.count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
|
||||
&app, []() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("6-Repeater", "Main");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) Daniel Gakwaya.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(7-DynamicModels VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick QuickControls2)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
qt_add_executable(app7-DynamicModels
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app7-DynamicModels
|
||||
URI 7-DynamicModels
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
set_target_properties(app7-DynamicModels PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app7-DynamicModels
|
||||
PRIVATE Qt6::Quick Qt6::QuickControls2
|
||||
)
|
||||
|
||||
install(TARGETS app7-DynamicModels
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,116 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Window {
|
||||
visible: true
|
||||
width: 640
|
||||
height: 480
|
||||
title: qsTr("Dynamic Models Demo")
|
||||
|
||||
ListModel {
|
||||
id: mListModel
|
||||
|
||||
ListElement {
|
||||
firstName: "John"; lastName: "Snow"
|
||||
}
|
||||
ListElement {
|
||||
firstName: "Nicholai"; lastName: "Itchenko"
|
||||
}
|
||||
ListElement {
|
||||
firstName: "Mitch"; lastName: "Mathson"
|
||||
}
|
||||
ListElement {
|
||||
firstName: "Ken"; lastName: "Kologorov"
|
||||
}
|
||||
ListElement {
|
||||
firstName: "Vince"; lastName: "Luvkyj"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
ListView{
|
||||
id: mListViewId
|
||||
model: mListModel
|
||||
delegate: delegateId
|
||||
Layout.fillWidth : true
|
||||
Layout.fillHeight: true
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Button {
|
||||
text: "Add Item"
|
||||
Layout.fillWidth : true
|
||||
onClicked: {
|
||||
mListModel.append({"firstName": "Daniel", "lastName": "Gakwaya"})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Button {
|
||||
text: "Clear"
|
||||
Layout.fillWidth : true
|
||||
onClicked: {
|
||||
mListModel.clear()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Delete Item at index 2"
|
||||
Layout.fillWidth: true
|
||||
onClicked: {
|
||||
if ( 2 < mListViewId.model.count){
|
||||
mListModel.remove(2,1)
|
||||
}else{
|
||||
console.log("index is invalid")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Set item at index 1"
|
||||
Layout.fillWidth: true
|
||||
onClicked: {
|
||||
mListModel.set(1,{"firstName": "John", "lastName": "Doe"})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: delegateId
|
||||
Rectangle {
|
||||
id: rectangleId
|
||||
width: mListViewId.width
|
||||
height: 50
|
||||
color: "beige"
|
||||
border.color: "yellowgreen"
|
||||
radius: 14
|
||||
|
||||
Text {
|
||||
id: textId
|
||||
anchors.centerIn: parent
|
||||
text : firstName + " " + lastName
|
||||
font.pointSize: 20
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
console.log("Clicked on: " + firstName + " " + lastName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQuickStyle>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QQuickStyle::setStyle("Material");
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
|
||||
&app, []() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("7-DynamicModels", "Main");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) Daniel Gakwaya.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(8-GridView VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
qt_add_executable(app8-GridView
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app8-GridView
|
||||
URI 8-GridView
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
set_target_properties(app8-GridView PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app8-GridView
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
install(TARGETS app8-GridView
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
|
||||
Window {
|
||||
visible: true
|
||||
width: 640
|
||||
height: 480
|
||||
title: qsTr("GridView")
|
||||
|
||||
|
||||
ListModel {
|
||||
id: modelId
|
||||
|
||||
ListElement {
|
||||
mNumber: 1
|
||||
mColor: "red"
|
||||
}
|
||||
ListElement {
|
||||
mNumber: 2
|
||||
mColor: "green"
|
||||
}
|
||||
ListElement {
|
||||
mNumber: 3
|
||||
mColor: "beige"
|
||||
}
|
||||
ListElement {
|
||||
mNumber: 4
|
||||
mColor: "yellowgreen"
|
||||
}
|
||||
ListElement {
|
||||
mNumber: 5
|
||||
mColor: "dodgerblue"
|
||||
}
|
||||
ListElement {
|
||||
mNumber: 6
|
||||
mColor: "lightyellow"
|
||||
}
|
||||
ListElement {
|
||||
mNumber: 7
|
||||
mColor: "pink"
|
||||
}
|
||||
ListElement {
|
||||
mNumber: 8
|
||||
mColor: "magenta"
|
||||
}
|
||||
ListElement {
|
||||
mNumber: 9
|
||||
mColor: "silver"
|
||||
}
|
||||
}
|
||||
|
||||
GridView{
|
||||
id: mGridViewId
|
||||
anchors.fill: parent
|
||||
flow : GridView.FlowTopToBottom
|
||||
layoutDirection: Qt.RightToLeft
|
||||
model: modelId
|
||||
delegate: Rectangle {
|
||||
width: 100
|
||||
height: width
|
||||
color: mColor
|
||||
Text {
|
||||
text: mNumber
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: 20
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
|
||||
&app, []() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("8-GridView", "Main");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
# Copyright (c) Daniel Gakwaya.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(9-XmlListModel VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
qt_add_executable(app9-XmlListModel
|
||||
main.cpp resource.qrc
|
||||
)
|
||||
|
||||
qt_add_qml_module(app9-XmlListModel
|
||||
URI 9-XmlListModel
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
set_target_properties(app9-XmlListModel PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app9-XmlListModel
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
install(TARGETS app9-XmlListModel
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
import QtQml.XmlListModel
|
||||
|
||||
|
||||
Window {
|
||||
visible: true
|
||||
width: 640
|
||||
height: 480
|
||||
title: qsTr("XmlListModel")
|
||||
|
||||
|
||||
XmlListModel {
|
||||
id: mXmlListModelId
|
||||
source: "qrc:/xml/employees.xml"
|
||||
query: "/courses/course"
|
||||
|
||||
XmlListModelRole {
|
||||
name: "instructor"
|
||||
elementName: "instructor"
|
||||
}
|
||||
XmlListModelRole {
|
||||
name: "year"
|
||||
elementName: "year"
|
||||
}
|
||||
XmlListModelRole {
|
||||
name: "coursename"
|
||||
elementName: "coursename"
|
||||
}
|
||||
XmlListModelRole { name: "hot"
|
||||
elementName: "coursename"
|
||||
attributeName: "hot"
|
||||
}
|
||||
}
|
||||
|
||||
ListView{
|
||||
id: mListViewId
|
||||
anchors.fill: parent
|
||||
model : mXmlListModelId
|
||||
delegate: Rectangle {
|
||||
width : parent.width
|
||||
height: 50
|
||||
color: "beige"
|
||||
Row {
|
||||
spacing: 30
|
||||
Text {
|
||||
text: instructor
|
||||
font.pointSize: 15
|
||||
}
|
||||
Text {
|
||||
text: coursename + " (" + year + ")"
|
||||
font.bold: hot === "true" ? true : false
|
||||
font.pointSize: 15
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
console.log("Clicked on: "+ hot)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Daniel Gakwaya.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
|
||||
&app, []() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("9-XmlListModel", "Main");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>xml/employees.xml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -0,0 +1,30 @@
|
||||
<!-- Copyright (c) Daniel Gakwaya. -->
|
||||
<!-- SPDX-License-Identifier: MIT -->
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<courses>
|
||||
<course>
|
||||
<instructor>Matt Kabwe</instructor>
|
||||
<year>2002</year>
|
||||
<coursename hot ="true">Operating Systems</coursename >
|
||||
</course>
|
||||
<course>
|
||||
<instructor>Daniel Gwo</instructor>
|
||||
<year>2010</year>
|
||||
<coursename hot = "false">Object Oriented Programming (Java)</coursename >
|
||||
</course>
|
||||
<course>
|
||||
<instructor>Nathan Mepp</instructor>
|
||||
<year>2011</year>
|
||||
<coursename hot = "false">Embedded Systems</coursename >
|
||||
</course>
|
||||
<course >
|
||||
<instructor>Lilian Gwiza</instructor>
|
||||
<year>2015</year>
|
||||
<coursename hot = "false">IT Project Management</coursename >
|
||||
</course>
|
||||
<course>
|
||||
<instructor>John Wiks</instructor>
|
||||
<year>2023</year>
|
||||
<coursename hot = "true">C is Still King</coursename >
|
||||
</course>
|
||||
</courses>
|
||||
@@ -0,0 +1,42 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(10-EasingCurves VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.4 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(app10-EasingCurves
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app10-EasingCurves
|
||||
URI 10-EasingCurves
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
QML_FILES MovingRectangle.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(app10-EasingCurves PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.app10-EasingCurves
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app10-EasingCurves
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS app10-EasingCurves
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,298 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
Window {
|
||||
id: rootId
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: qsTr("Easing Curves")
|
||||
|
||||
property int animDuration: 500
|
||||
property color startColor : "beige"
|
||||
property color endColor: "blue"
|
||||
|
||||
|
||||
Flickable{
|
||||
anchors.fill: parent
|
||||
contentHeight: columnId.implicitHeight
|
||||
ColumnLayout{
|
||||
id: columnId
|
||||
width: parent.width
|
||||
spacing: 2
|
||||
|
||||
//The container rectangle
|
||||
/*
|
||||
Rectangle{
|
||||
id: containerRectId
|
||||
width: parent.width
|
||||
height: 50
|
||||
color: "gray"
|
||||
|
||||
Text{
|
||||
text: "Easing.Linear"
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
id: containedRectId
|
||||
color: startColor
|
||||
width: 50
|
||||
height: 50
|
||||
border{
|
||||
width: 5
|
||||
color: "black"
|
||||
}
|
||||
radius: 10
|
||||
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
property bool toRight: false
|
||||
|
||||
onClicked: function(){
|
||||
if( toRight === false){
|
||||
//Move towards the right
|
||||
toRight = true
|
||||
//Animate x
|
||||
numberAnimationId.to = containerRectId.width - containedRectId.width
|
||||
numberAnimationId.start()
|
||||
|
||||
//Animate the color
|
||||
colorAnimationId.from = startColor
|
||||
colorAnimationId.to = endColor
|
||||
colorAnimationId.start()
|
||||
}else{
|
||||
//Move towards the left
|
||||
toRight = false
|
||||
//Animate x
|
||||
numberAnimationId.to = 0
|
||||
numberAnimationId.start()
|
||||
|
||||
//Animate the color
|
||||
colorAnimationId.from = endColor
|
||||
colorAnimationId.to = startColor
|
||||
colorAnimationId.start()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
NumberAnimation {
|
||||
id: numberAnimationId
|
||||
target: containedRectId
|
||||
property: "x"
|
||||
easing.type: Easing.Linear
|
||||
to: containerRectId.width - containedRectId.width
|
||||
duration: animDuration
|
||||
}
|
||||
|
||||
ColorAnimation{
|
||||
id: colorAnimationId
|
||||
target: containedRectId
|
||||
property: "color"
|
||||
from: startColor
|
||||
to: endoColor
|
||||
duration: animDuration
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
MovingRectangle {
|
||||
backgroundColor: "gray"
|
||||
startColor: "beige"
|
||||
endColor: "blue"
|
||||
animDuration: rootId.animDuration
|
||||
easingText: "Linear"
|
||||
easingType: Easing.Linear
|
||||
containerwidth: rootId.width
|
||||
}
|
||||
|
||||
MovingRectangle {
|
||||
backgroundColor: "gray"
|
||||
startColor: "beige"
|
||||
endColor: "green"
|
||||
animDuration: rootId.animDuration
|
||||
easingText: "InQuad"
|
||||
easingType: Easing.InQuad
|
||||
containerwidth: rootId.width
|
||||
}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "salmon";
|
||||
animDuration:rootId.animDuration ; easingText: "OutQuad"; easingType: Easing.OutQuad;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "tomato";
|
||||
animDuration:rootId.animDuration ; easingText: "InOutQuad"; easingType: Easing.InOutQuad;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "darkorange"
|
||||
animDuration:rootId.animDuration ; easingText: "OutInQuad"; easingType: Easing.OutInQuad;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
|
||||
//Cubic
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "gold"
|
||||
animDuration:rootId.animDuration ; easingText: "InCubic"; easingType: Easing.InCubic;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "yellow"
|
||||
animDuration:rootId.animDuration ; easingText: "OutCubic"; easingType: Easing.OutCubic;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "peachpuff"
|
||||
animDuration:rootId.animDuration ; easingText: "InOutCubic"; easingType: Easing.InOutCubic;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "thistle"
|
||||
animDuration:rootId.animDuration ; easingText: "OutInCubic"; easingType: Easing.OutInCubic;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
//Quart
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "orchid"
|
||||
animDuration: rootId.animDuration; easingText: "InQuart"; easingType: Easing.InQuart;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "purple"
|
||||
animDuration:rootId.animDuration ; easingText: "OutQuart"; easingType: Easing.OutQuart;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "slateblue"
|
||||
animDuration:rootId.animDuration ; easingText: "InOutQuart"; easingType: Easing.InOutQuart;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "chartreuse"
|
||||
animDuration:rootId.animDuration ; easingText: "OutInQuart"; easingType: Easing.OutInQuart;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
//Quint
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "limegreen"
|
||||
animDuration:rootId.animDuration ; easingText: "InQuint"; easingType: Easing.InQuint;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "seagreen"
|
||||
animDuration:rootId.animDuration ; easingText: "OutQuint"; easingType: Easing.OutQuint;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "darkgreen"
|
||||
animDuration:rootId.animDuration ; easingText: "InOutQuint"; easingType: Easing.InOutQuint;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "olive"
|
||||
animDuration:rootId.animDuration ; easingText: "OutInQuint"; easingType: Easing.OutInQuint;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
//Sine
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "darkseagreen"
|
||||
animDuration:rootId.animDuration ; easingText: "InSine"; easingType: Easing.InSine;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "teal"
|
||||
animDuration:rootId.animDuration ; easingText: "OutSine"; easingType: Easing.OutSine;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "turquoise"
|
||||
animDuration: rootId.animDuration; easingText: "InOutSine"; easingType: Easing.InOutSine;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "steelblue"
|
||||
animDuration:rootId.animDuration ; easingText: "OutInSine"; easingType: Easing.OutInSine;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
//Expo
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "skyblue"
|
||||
animDuration:rootId.animDuration ; easingText: "InExpo"; easingType: Easing.InExpo;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "royalblue"
|
||||
animDuration:rootId.animDuration ; easingText: "OutExpo"; easingType: Easing.OutExpo;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "mediumblue"
|
||||
animDuration:rootId.animDuration ; easingText: "InOutExpo"; easingType: Easing.InOutExpo;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "midnightblue"
|
||||
animDuration:rootId.animDuration ; easingText: "OutInExpo"; easingType: Easing.OutInExpo;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
//Circ
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "cornsilk"
|
||||
animDuration:rootId.animDuration ; easingText: "InCirc"; easingType: Easing.InCirc;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "bisque"
|
||||
animDuration:rootId.animDuration ; easingText: "OutCirc"; easingType: Easing.OutCirc;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "rosybrown"
|
||||
animDuration:rootId.animDuration ; easingText: "InOutCirc"; easingType: Easing.InOutCirc;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "sandybrown"
|
||||
animDuration:rootId.animDuration ; easingText: "OutInCirc"; easingType: Easing.OutInCirc;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
|
||||
//Elastic
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "cornsilk"
|
||||
animDuration:rootId.animDuration ; easingText: "InElastic"; easingType: Easing.InElastic;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "bisque"
|
||||
animDuration:rootId.animDuration ; easingText: "OutElastic"; easingType: Easing.OutElastic;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "rosybrown"
|
||||
animDuration:rootId.animDuration ; easingText: "InOutElastic"; easingType: Easing.InOutElastic;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "sandybrown"
|
||||
animDuration:rootId.animDuration ; easingText: "OutInElastic"; easingType: Easing.OutInElastic;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
|
||||
//Black
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "maroon"
|
||||
animDuration:rootId.animDuration ; easingText: "InBack"; easingType: Easing.InBack;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "lavenderblush"
|
||||
animDuration:rootId.animDuration ; easingText: "OutBack"; easingType: Easing.OutBack;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "mistyrose"
|
||||
animDuration:rootId.animDuration ; easingText: "InOutBack"; easingType: Easing.InOutBack;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "gainsboro"
|
||||
animDuration:rootId.animDuration ; easingText: "OutInBack"; easingType: Easing.OutInBack;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
|
||||
//Bounce
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "silver"
|
||||
animDuration:rootId.animDuration ; easingText: "InBounce"; easingType: Easing.InBounce;
|
||||
containerwidth: rootId.width }
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "dimgray"
|
||||
animDuration:rootId.animDuration ; easingText: "OutBounce"; easingType: Easing.OutBounce;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "slategray"
|
||||
animDuration:rootId.animDuration ; easingText: "InOutBounce"; easingType: Easing.InOutBounce;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "darkslategray"
|
||||
animDuration:rootId.animDuration ; easingText: "OutInBounce"; easingType: Easing.OutInBounce;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
//Bezier
|
||||
MovingRectangle {backgroundColor: "gray"; startColor: "beige"; endColor: "darkslategray"
|
||||
animDuration:rootId.animDuration ; easingText: "Bezier"; easingType: Easing.Bezier;
|
||||
containerwidth: rootId.width}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
|
||||
property var backgroundColor
|
||||
property var startColor
|
||||
property var endColor
|
||||
property string easingText
|
||||
property int animDuration
|
||||
property var easingType
|
||||
property int containerwidth
|
||||
|
||||
|
||||
width: containerRectId.width
|
||||
height: containerRectId.height
|
||||
|
||||
property int finalX: containerRectId.width - containedRectId.width
|
||||
|
||||
Rectangle {
|
||||
id : containerRectId
|
||||
width: containerwidth
|
||||
height: 50
|
||||
color: backgroundColor
|
||||
|
||||
Text {
|
||||
|
||||
text: easingText
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
id : containedRectId
|
||||
color: startColor
|
||||
width: 50
|
||||
height: 50
|
||||
border {width : 5 ; color : "black" }
|
||||
radius: 10
|
||||
|
||||
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
|
||||
property bool toRight : false
|
||||
onClicked: {
|
||||
|
||||
if ( toRight === false)
|
||||
{
|
||||
toRight = true
|
||||
//Animate X
|
||||
mNumberAnimationId.to = finalX
|
||||
mNumberAnimationId.start()
|
||||
|
||||
//Animate color
|
||||
mColorAnimationId.from = startColor
|
||||
mColorAnimationId.to = endColor
|
||||
mColorAnimationId.start()
|
||||
|
||||
//Move to right
|
||||
}else{
|
||||
//Move to left
|
||||
toRight = false
|
||||
//Animate X
|
||||
mNumberAnimationId.to = 0
|
||||
mNumberAnimationId.start()
|
||||
|
||||
//Animate color
|
||||
mColorAnimationId.from = endColor
|
||||
mColorAnimationId.to = startColor
|
||||
mColorAnimationId.start()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
NumberAnimation{
|
||||
id : mNumberAnimationId
|
||||
target: containedRectId
|
||||
property : "x"
|
||||
easing.type : easingType
|
||||
to : finalX
|
||||
duration: animDuration
|
||||
}
|
||||
|
||||
|
||||
ColorAnimation {
|
||||
id : mColorAnimationId
|
||||
target: containedRectId
|
||||
property : "color"
|
||||
from: startColor
|
||||
to: endColor
|
||||
duration: animDuration
|
||||
}
|
||||
Component.onCompleted: {
|
||||
//console.log("The width of the contained rect is :" + parent.width)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
const QUrl url(u"qrc:/10-EasingCurves/Main.qml"_qs);
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.load(url);
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(11-GroupedAnimations VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.4 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(app11-GroupedAnimations
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app11-GroupedAnimations
|
||||
URI 11-GroupedAnimations
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(app11-GroupedAnimations PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.app11-GroupedAnimations
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app11-GroupedAnimations
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS app11-GroupedAnimations
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,76 @@
|
||||
import QtQuick
|
||||
|
||||
Window {
|
||||
id: rootId
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: qsTr("Grouped Animations")
|
||||
readonly property int animationDuration: 500
|
||||
property bool going_down: false
|
||||
|
||||
function animateCircle(){
|
||||
|
||||
if (going_down === false){
|
||||
//Go down
|
||||
going_down = true
|
||||
xAnimationId.from = 0
|
||||
xAnimationId.to = rootId.width - circleId.width
|
||||
|
||||
yAnimationId.from = 0
|
||||
yAnimationId.to = rootId.height - circleId.height
|
||||
}else{
|
||||
//Go up
|
||||
going_down = false
|
||||
xAnimationId.from = rootId.width - circleId.width
|
||||
xAnimationId.to = 0
|
||||
|
||||
yAnimationId.from = rootId.height - circleId.height
|
||||
yAnimationId.to = 0
|
||||
}
|
||||
groupedAnimationId.start()
|
||||
}
|
||||
|
||||
|
||||
Rectangle{
|
||||
anchors.fill: parent
|
||||
color: "gray"
|
||||
|
||||
Rectangle{
|
||||
id: circleId
|
||||
width: 100
|
||||
height: 100
|
||||
radius: 70
|
||||
color: "yellowgreen"
|
||||
|
||||
|
||||
//SequentialAnimation{
|
||||
ParallelAnimation{
|
||||
id: groupedAnimationId
|
||||
|
||||
//Animate x
|
||||
NumberAnimation{
|
||||
id: xAnimationId
|
||||
target: circleId
|
||||
property: "x"
|
||||
duration: animationDuration
|
||||
}
|
||||
|
||||
//Animate y
|
||||
NumberAnimation{
|
||||
id: yAnimationId
|
||||
target: circleId
|
||||
property: "y"
|
||||
duration: animationDuration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: function(){
|
||||
animateCircle()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
const QUrl url(u"qrc:/11-GroupedAnimations/Main.qml"_qs);
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.load(url);
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(12-PendulumSwing VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.4 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(app12-PendulumSwing
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app12-PendulumSwing
|
||||
URI 12-PendulumSwing
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(app12-PendulumSwing PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.app12-PendulumSwing
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app12-PendulumSwing
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS app12-PendulumSwing
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,57 @@
|
||||
import QtQuick
|
||||
|
||||
Window {
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: qsTr("Pendulum Swing")
|
||||
|
||||
readonly property int pendulumAngle: 30
|
||||
readonly property int animDuration: 700
|
||||
|
||||
Rectangle{
|
||||
id: pendulumId
|
||||
width: 20
|
||||
height: 200
|
||||
color: "black"
|
||||
x: (parent.width - width)/2
|
||||
y: 50
|
||||
transformOrigin: Item.Top
|
||||
|
||||
Rectangle{
|
||||
id: bobId
|
||||
width: 50
|
||||
height: 50
|
||||
color: "red"
|
||||
radius: width/2
|
||||
x: (pendulumId.width - width)/2
|
||||
y: pendulumId.height
|
||||
transformOrigin: Item.Bottom
|
||||
rotation: pendulumId.rotation
|
||||
}
|
||||
|
||||
SequentialAnimation{
|
||||
loops: Animation.Infinite
|
||||
running: true
|
||||
NumberAnimation{
|
||||
id: rightToLeftAnimationId
|
||||
target: pendulumId
|
||||
property: "rotation"
|
||||
from: -pendulumAngle
|
||||
to: pendulumAngle
|
||||
duration: animDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
|
||||
NumberAnimation{
|
||||
id: leftToRightAnimationId
|
||||
target: pendulumId
|
||||
property: "rotation"
|
||||
from: pendulumAngle
|
||||
to: -pendulumAngle
|
||||
duration: animDuration
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
const QUrl url(u"qrc:/12-PendulumSwing/Main.qml"_qs);
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.load(url);
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(13-StatesTransitions VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.4 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(app13-StatesTransitions
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_resources(app13-StatesTransitions "images"
|
||||
PREFIX /
|
||||
FILES
|
||||
images/treespringsmall.png
|
||||
images/treesummersmall.png
|
||||
)
|
||||
|
||||
qt_add_qml_module(app13-StatesTransitions
|
||||
URI 13-StatesTransitions
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(app13-StatesTransitions PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.app13-StatesTransitions
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app13-StatesTransitions
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS app13-StatesTransitions
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,152 @@
|
||||
import QtQuick
|
||||
|
||||
Window {
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: qsTr("States and Transitions")
|
||||
|
||||
Rectangle{
|
||||
id: containerRectId
|
||||
anchors.fill: parent
|
||||
|
||||
//Sky
|
||||
Rectangle{
|
||||
id: skyId
|
||||
width: parent.width
|
||||
height: 200
|
||||
color: "blue"
|
||||
}
|
||||
|
||||
|
||||
Rectangle{
|
||||
id: groundId
|
||||
anchors.top: skyId.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
color: "lime"
|
||||
}
|
||||
|
||||
|
||||
Image{
|
||||
id: treeSummerId
|
||||
x: 50
|
||||
y: 100
|
||||
width: 200
|
||||
height: 300
|
||||
source: "qrc:/images/treesummersmall.png"
|
||||
}
|
||||
|
||||
Image{
|
||||
id: treeSpringId
|
||||
x: 50
|
||||
y: 100
|
||||
width: 200
|
||||
height: 300
|
||||
source: "qrc:/images/treespringsmall.png"
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
id: sunId
|
||||
x: parent.width - width - 100
|
||||
y: 50
|
||||
width: 100
|
||||
height: 100
|
||||
color: "yellow"
|
||||
radius: 600
|
||||
}
|
||||
|
||||
state: "spring"
|
||||
|
||||
states: [
|
||||
|
||||
//Spring
|
||||
State{
|
||||
name: "spring"
|
||||
PropertyChanges {
|
||||
target: skyId
|
||||
color: "deepskyblue"
|
||||
}
|
||||
PropertyChanges {
|
||||
target: treeSummerId
|
||||
opacity: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: treeSpringId
|
||||
opacity: 1
|
||||
}
|
||||
PropertyChanges {
|
||||
target: groundId
|
||||
color: "lime"
|
||||
}
|
||||
PropertyChanges {
|
||||
target: sunId
|
||||
color: "lightyellow"
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
//Summer
|
||||
State{
|
||||
name: "summer"
|
||||
PropertyChanges {
|
||||
target: skyId
|
||||
color: "lightblue"
|
||||
}
|
||||
PropertyChanges {
|
||||
target: treeSummerId
|
||||
opacity: 1
|
||||
}
|
||||
PropertyChanges {
|
||||
target: treeSpringId
|
||||
opacity: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: groundId
|
||||
color: "darkkhaki"
|
||||
}
|
||||
PropertyChanges {
|
||||
target: sunId
|
||||
color: "yellow"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
//Transitions
|
||||
transitions: [
|
||||
Transition{
|
||||
from: "summer"
|
||||
to: "spring"
|
||||
ColorAnimation{
|
||||
duration: 500
|
||||
}
|
||||
NumberAnimation{
|
||||
property: "opacity"
|
||||
duration: 500
|
||||
}
|
||||
},
|
||||
|
||||
Transition{
|
||||
from: "spring"
|
||||
to: "summer"
|
||||
ColorAnimation{
|
||||
duration: 500
|
||||
}
|
||||
NumberAnimation{
|
||||
property: "opacity"
|
||||
duration: 500
|
||||
}
|
||||
|
||||
}
|
||||
]
|
||||
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: function(){
|
||||
containerRectId.state = (containerRectId.state === "spring" ? "summer" : "spring")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 293 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 201 KiB |
@@ -0,0 +1,19 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
const QUrl url(u"qrc:/13-StatesTransitions/Main.qml"_qs);
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.load(url);
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(14-StatesWithGradients VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.4 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(app14-StatesWithGradients
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_resources(app14-StatesWithGradients "images"
|
||||
PREFIX /
|
||||
FILES
|
||||
images/treespringsmall.png
|
||||
images/treesummersmall.png
|
||||
)
|
||||
|
||||
qt_add_qml_module(app14-StatesWithGradients
|
||||
URI 14-StatesWithGradients
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(app14-StatesWithGradients PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.app14-StatesWithGradients
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app14-StatesWithGradients
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS app14-StatesWithGradients
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,234 @@
|
||||
import QtQuick
|
||||
|
||||
Window {
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: qsTr("States with Gradients")
|
||||
|
||||
Rectangle{
|
||||
id: containerRectId
|
||||
anchors.fill: parent
|
||||
|
||||
//Sky
|
||||
Rectangle{
|
||||
id: skyId
|
||||
width: parent.width
|
||||
height: 200
|
||||
//color: "blue"
|
||||
gradient: Gradient{
|
||||
GradientStop{
|
||||
id: skyStartColorId
|
||||
position: 0.0
|
||||
color: "blue"
|
||||
}
|
||||
GradientStop{
|
||||
id: skyEndColorId
|
||||
position: 1.0
|
||||
color: "#66CCFF"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle{
|
||||
id: groundId
|
||||
anchors.top: skyId.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
//color: "lime"
|
||||
gradient: Gradient{
|
||||
GradientStop{
|
||||
id: groundStartColorId
|
||||
position: 0.0
|
||||
color: "lime"
|
||||
}
|
||||
GradientStop{
|
||||
id: groundEndColorId
|
||||
position: 1.0
|
||||
color: "#66CCFF"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Image{
|
||||
id: treeSummerId
|
||||
x: 50
|
||||
y: 100
|
||||
width: 200
|
||||
height: 300
|
||||
source: "qrc:/images/treesummersmall.png"
|
||||
}
|
||||
|
||||
Image{
|
||||
id: treeSpringId
|
||||
x: 50
|
||||
y: 100
|
||||
width: 200
|
||||
height: 300
|
||||
source: "qrc:/images/treespringsmall.png"
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
id: sunId
|
||||
x: parent.width - width - 100
|
||||
y: 50
|
||||
width: 100
|
||||
height: 100
|
||||
color: "yellow"
|
||||
radius: 600
|
||||
}
|
||||
|
||||
state: "spring"
|
||||
|
||||
states: [
|
||||
|
||||
//Spring
|
||||
State{
|
||||
name: "spring"
|
||||
/*
|
||||
PropertyChanges {
|
||||
target: skyId
|
||||
color: "deepskyblue"
|
||||
}
|
||||
*/
|
||||
PropertyChanges {
|
||||
target: skyStartColorId
|
||||
color: "deepskyblue"
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: skyEndColorId
|
||||
color: "#AACCFF"
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: treeSummerId
|
||||
opacity: 0
|
||||
}
|
||||
PropertyChanges {
|
||||
target: treeSpringId
|
||||
opacity: 1
|
||||
}
|
||||
/*
|
||||
PropertyChanges {
|
||||
target: groundId
|
||||
color: "lime"
|
||||
}
|
||||
*/
|
||||
PropertyChanges {
|
||||
target: groundStartColorId
|
||||
color: "lime"
|
||||
}
|
||||
PropertyChanges {
|
||||
target: groundEndColorId
|
||||
color: "#66CCFF"
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: sunId
|
||||
color: "lightyellow"
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
//Summer
|
||||
State{
|
||||
name: "summer"
|
||||
/*
|
||||
PropertyChanges {
|
||||
target: skyId
|
||||
color: "lightblue"
|
||||
}
|
||||
*/
|
||||
PropertyChanges{
|
||||
target: skyStartColorId
|
||||
color: "lightblue"
|
||||
}
|
||||
PropertyChanges{
|
||||
target: skyEndColorId
|
||||
color: "#EECCFF"
|
||||
}
|
||||
PropertyChanges {
|
||||
target: treeSummerId
|
||||
opacity: 1
|
||||
}
|
||||
PropertyChanges {
|
||||
target: treeSpringId
|
||||
opacity: 0
|
||||
}
|
||||
/*
|
||||
PropertyChanges {
|
||||
target: groundId
|
||||
color: "darkkhaki"
|
||||
}
|
||||
*/
|
||||
PropertyChanges {
|
||||
target: groundStartColorId
|
||||
color: "lime"
|
||||
}
|
||||
PropertyChanges {
|
||||
target: groundEndColorId
|
||||
color: "darkkhaki"
|
||||
}
|
||||
PropertyChanges {
|
||||
target: sunId
|
||||
color: "yellow"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
//Transitions
|
||||
/*
|
||||
transitions: [
|
||||
Transition{
|
||||
from: "summer"
|
||||
to: "spring"
|
||||
ColorAnimation{
|
||||
duration: 500
|
||||
}
|
||||
NumberAnimation{
|
||||
property: "opacity"
|
||||
duration: 500
|
||||
}
|
||||
},
|
||||
|
||||
Transition{
|
||||
from: "spring"
|
||||
to: "summer"
|
||||
ColorAnimation{
|
||||
duration: 500
|
||||
}
|
||||
NumberAnimation{
|
||||
property: "opacity"
|
||||
duration: 500
|
||||
}
|
||||
|
||||
}
|
||||
]
|
||||
*/
|
||||
|
||||
transitions: Transition{
|
||||
from: "*"
|
||||
to: "*"
|
||||
ColorAnimation{
|
||||
duration: 500
|
||||
}
|
||||
NumberAnimation{
|
||||
property: "opacity"
|
||||
duration: 500
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: function(){
|
||||
containerRectId.state = (containerRectId.state === "spring" ? "summer" : "spring")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 293 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 201 KiB |
@@ -0,0 +1,19 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
const QUrl url(u"qrc:/14-StatesWithGradients/Main.qml"_qs);
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.load(url);
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
57
Qt6QMLBeginnersCode/12-TransformsTransitionsAnimations/15-TodoListAnimations/.gitignore
vendored
Normal file
57
Qt6QMLBeginnersCode/12-TransformsTransitionsAnimations/15-TodoListAnimations/.gitignore
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
# Qt QML Language Server configuration
|
||||
qmlls.ini
|
||||
|
||||
# Build directories
|
||||
build/
|
||||
Desktop_Qt_6_9_0_MinGW_64_bit-Debug/
|
||||
|
||||
# Qt Creator user settings
|
||||
CMakeLists.txt.user
|
||||
|
||||
# Compiled Object files
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Compiled Static libraries
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Qt-specific
|
||||
*.qm
|
||||
*.prl
|
||||
*.pro.user
|
||||
*.pro.user.*
|
||||
*.qbs.user
|
||||
*.qbs.user.*
|
||||
*.moc
|
||||
moc_*.cpp
|
||||
moc_*.h
|
||||
qrc_*.cpp
|
||||
ui_*.h
|
||||
Makefile*
|
||||
*build-*
|
||||
|
||||
# QML cache and compiled files
|
||||
*.qmlc
|
||||
*.jsc
|
||||
|
||||
# Qt temporary files
|
||||
*~
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
# Windows
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
@@ -0,0 +1,52 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(TodoList VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Quick QuickControls2)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.8)
|
||||
|
||||
qt_add_executable(TodoList
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(TodoList
|
||||
URI TodoList
|
||||
VERSION 1.0
|
||||
QML_FILES
|
||||
# Main View
|
||||
src/views/MainView.qml
|
||||
|
||||
# Components
|
||||
src/components/AppHeader.qml
|
||||
src/components/AddTaskBar.qml
|
||||
src/components/TaskItem.qml
|
||||
src/components/TaskStats.qml
|
||||
|
||||
# Models
|
||||
src/models/TaskListModel.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(TodoList PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.app01_todolist_starter
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(TodoList
|
||||
PRIVATE Qt6::Quick Qt6::QuickControls2
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS TodoList
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,110 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: 60
|
||||
|
||||
signal taskAdded(string taskText)
|
||||
|
||||
property color backgroundColor: "#ffffff"
|
||||
property color textColor: "#333333"
|
||||
property color primaryColor: "#007aff"
|
||||
property bool darkMode: false
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.backgroundColor
|
||||
radius: 12
|
||||
border.color: root.darkMode ? "#404040" : "#e0e0e0"
|
||||
border.width: 1
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
spacing: 12
|
||||
|
||||
// Add icon
|
||||
Rectangle {
|
||||
Layout.preferredWidth: 36
|
||||
Layout.preferredHeight: 36
|
||||
color: root.primaryColor
|
||||
radius: 18
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "+"
|
||||
color: "#ffffff"
|
||||
font.pixelSize: 20
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
|
||||
// Text input
|
||||
TextField {
|
||||
id: taskInput
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 36
|
||||
placeholderText: qsTr("Add a new task...")
|
||||
placeholderTextColor: root.darkMode ? "#888888" : "#999999"
|
||||
color: root.textColor
|
||||
font.pixelSize: 16
|
||||
selectByMouse: true
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
border.color: "transparent"
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: root.addTask()
|
||||
Keys.onEnterPressed: root.addTask()
|
||||
|
||||
}
|
||||
|
||||
// Add button
|
||||
Button {
|
||||
id: addButton
|
||||
Layout.preferredWidth: 80
|
||||
Layout.preferredHeight: 36
|
||||
text: qsTr("Add")
|
||||
enabled: taskInput.text.trim().length > 0
|
||||
|
||||
background: Rectangle {
|
||||
color: addButton.enabled ?
|
||||
(addButton.pressed ? Qt.darker(root.primaryColor, 1.2) : root.primaryColor) :
|
||||
(root.darkMode ? "#404040" : "#e0e0e0")
|
||||
radius: 8
|
||||
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: addButton.text
|
||||
color: addButton.enabled ? "#ffffff" : (root.darkMode ? "#888888" : "#cccccc")
|
||||
font.pixelSize: 14
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
}
|
||||
|
||||
onClicked: root.addTask()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addTask() {
|
||||
if (taskInput.text.trim().length > 0) {
|
||||
root.taskAdded(taskInput.text.trim())
|
||||
taskInput.text = ""
|
||||
taskInput.focus = false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: 80
|
||||
|
||||
signal toggleDarkMode()
|
||||
|
||||
// Properties that will be bound from parent
|
||||
property color textColor: "#333333"
|
||||
property color textSecondary: "#999999"
|
||||
property bool darkMode: false
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
RowLayout{
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 8
|
||||
anchors.rightMargin: 8
|
||||
spacing: 12
|
||||
|
||||
// App icon
|
||||
Text {
|
||||
text: "📝"
|
||||
font.pixelSize: 32
|
||||
}
|
||||
|
||||
// App title and subtitle
|
||||
Column {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: "My Tasks"
|
||||
font.pixelSize: 28
|
||||
font.weight: Font.Bold
|
||||
color: root.textColor
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Stay organized, stay productive")
|
||||
font.pixelSize: 12
|
||||
color: root.textSecondary
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Dark mode toggle
|
||||
Button {
|
||||
id: themeToggle
|
||||
Layout.preferredWidth: 50
|
||||
Layout.preferredHeight: 50
|
||||
|
||||
background: Rectangle {
|
||||
color: themeToggle.pressed ?
|
||||
(root.darkMode ? "#404040" : "#e0e0e0") :
|
||||
(root.darkMode ? "#2d2d2d" : "#f5f5f5")
|
||||
radius: 25
|
||||
border.color: root.darkMode ? "#555555" : "#d0d0d0"
|
||||
border.width: 1
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: 150 }
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Text{
|
||||
text: root.darkMode ? "☀️" : "🌙"
|
||||
font.pixelSize: 20
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
//Emit the signal when the button is clicked
|
||||
onClicked: root.toggleDarkMode()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: 56
|
||||
|
||||
required property string taskTitle
|
||||
required property bool taskDone
|
||||
|
||||
signal toggleDone()
|
||||
signal deleteTask()
|
||||
|
||||
property color backgroundColor: "#ffffff"
|
||||
property color textColor: "#333333"
|
||||
property color completedColor: "#999999"
|
||||
property color primaryColor: "#007aff"
|
||||
property bool darkMode: false
|
||||
|
||||
// Constants for this component
|
||||
readonly property int itemHeight: 56
|
||||
readonly property int margins: 4
|
||||
readonly property int innerMargins: 12
|
||||
readonly property int checkboxSize: 24
|
||||
readonly property int deleteButtonSize: 32
|
||||
|
||||
Rectangle {
|
||||
id: taskItemBackground
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
id: itemBackground
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.margins
|
||||
color: root.backgroundColor
|
||||
radius: 8
|
||||
border.color: root.taskDone ? "transparent" : (root.darkMode ? "#404040" : "#f0f0f0")
|
||||
border.width: 1
|
||||
opacity: root.taskDone ? 0.7 : 1.0
|
||||
|
||||
scale: itemBackground.hovered ? 1.02 : 1.0
|
||||
|
||||
// Smooth transitions for background properties
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 300 }
|
||||
}
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation { duration: 300 }
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: 150; easing.type: Easing.OutQuad }
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.innerMargins
|
||||
spacing: 12
|
||||
|
||||
// Checkbox
|
||||
Rectangle {
|
||||
id: checkbox
|
||||
Layout.preferredWidth: root.checkboxSize
|
||||
Layout.preferredHeight: root.checkboxSize
|
||||
color: root.taskDone ? root.primaryColor : "transparent"
|
||||
border.color: root.taskDone ? root.primaryColor : (root.darkMode ? "#666666" : "#cccccc")
|
||||
border.width: 2
|
||||
radius: 4
|
||||
|
||||
// Smooth transitions for checkbox state changes
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: 100; easing.type: Easing.OutBack }
|
||||
}
|
||||
|
||||
// Checkmark
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "✓"
|
||||
color: "#ffffff"
|
||||
font.pixelSize: 16
|
||||
font.weight: Font.Bold
|
||||
opacity: root.taskDone ? 1.0 : 0.0
|
||||
|
||||
scale: root.taskDone ? 1.0 : 0.3
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: 200; easing.type: Easing.OutBack }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
// Add click animation
|
||||
checkbox.scale = 0.9
|
||||
scaleResetTimer.restart()
|
||||
|
||||
//Toggle the task
|
||||
root.toggleDone()
|
||||
}
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
// Timer to reset scale after click
|
||||
Timer {
|
||||
id: scaleResetTimer
|
||||
interval: 100
|
||||
onTriggered: checkbox.scale = 1.0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Task text
|
||||
Text {
|
||||
id: taskText
|
||||
Layout.fillWidth: true
|
||||
text: root.taskTitle
|
||||
color: root.taskDone ? root.completedColor : root.textColor
|
||||
font.pixelSize: 16
|
||||
font.strikeout: root.taskDone
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
// Smooth color transition when task state changes
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: 300 }
|
||||
}
|
||||
|
||||
// Subtle scale animation on completion
|
||||
scale: root.taskDone ? 0.95 : 1.0
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: 200; easing.type: Easing.OutQuad }
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: root.toggleDone()
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
}
|
||||
|
||||
// Delete button
|
||||
Button {
|
||||
id: deleteButton
|
||||
Layout.preferredWidth: root.deleteButtonSize
|
||||
Layout.preferredHeight: root.deleteButtonSize
|
||||
opacity: itemBackground.hovered ? 1.0 : 0.3
|
||||
scale: deleteButton.pressed ? 0.9 : 1.0
|
||||
|
||||
// Smooth transitions
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: 100; easing.type: Easing.OutQuad }
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: deleteButton.pressed ? "#ff3b30" : "transparent"
|
||||
radius: 16
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: 150 }
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: "🗑"
|
||||
font.pixelSize: 16
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
rotation: deleteButton.pressed ? 15 : 0
|
||||
|
||||
Behavior on rotation {
|
||||
NumberAnimation { duration: 100 }
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
root.deleteTask()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hover effect
|
||||
property bool hovered: false
|
||||
|
||||
HoverHandler {
|
||||
onHoveredChanged: itemBackground.hovered = hovered
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: visible ? 60 : 0
|
||||
visible: totalTasks > 0
|
||||
|
||||
property int totalTasks: 0
|
||||
property int completedTasks: 0
|
||||
property int remainingTasks: 0
|
||||
property bool hasCompleted: false
|
||||
|
||||
property color backgroundColor: "#ffffff"
|
||||
property color textColor: "#333333"
|
||||
property color secondaryTextColor: "#666666"
|
||||
property color primaryColor: "#007aff"
|
||||
property color dangerColor: "#ff3b30"
|
||||
property bool darkMode: false
|
||||
|
||||
signal clearCompleted()
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.backgroundColor
|
||||
radius: 12
|
||||
border.color: root.darkMode ? "#404040" : "#e0e0e0"
|
||||
border.width: 1
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 16
|
||||
spacing: 16
|
||||
|
||||
// Statistics text
|
||||
Column {
|
||||
Layout.fillWidth: true
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: root.totalTasks === 1 ?
|
||||
qsTr("%1 task").arg(root.totalTasks) :
|
||||
qsTr("%1 tasks").arg(root.totalTasks)
|
||||
color: root.textColor
|
||||
font.pixelSize: 16
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
Text {
|
||||
text: root.completedTasks > 0 ?
|
||||
qsTr("%1 completed, %2 remaining").arg(root.completedTasks).arg(root.remainingTasks) :
|
||||
qsTr("No tasks completed yet")
|
||||
color: root.secondaryTextColor
|
||||
font.pixelSize: 14
|
||||
visible: root.totalTasks > 0
|
||||
}
|
||||
}
|
||||
|
||||
// Clear completed button
|
||||
Button {
|
||||
id: clearButton
|
||||
Layout.preferredHeight: 36
|
||||
text: qsTr("Clear Completed")
|
||||
visible: root.hasCompleted
|
||||
enabled: root.hasCompleted
|
||||
|
||||
background: Rectangle {
|
||||
color: clearButton.pressed ?
|
||||
Qt.darker(root.dangerColor, 1.2) :
|
||||
(clearButton.hovered ? root.dangerColor : "transparent")
|
||||
border.color: root.dangerColor
|
||||
border.width: 1
|
||||
radius: 8
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: clearButton.text
|
||||
color: clearButton.hovered ? "#ffffff" : root.dangerColor
|
||||
font.pixelSize: 14
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
onClicked: root.clearCompleted()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQuickStyle>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
// Set Qt Quick Controls style to Basic to enable customization
|
||||
QQuickStyle::setStyle("Basic");
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("TodoList", "MainView");
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import QtQuick
|
||||
|
||||
ListModel {
|
||||
id: root
|
||||
|
||||
// Add some sample tasks for testing
|
||||
Component.onCompleted: {
|
||||
addTask("Learn Qt QML")
|
||||
addTask("Build a todo app")
|
||||
addTask("Practice QML components")
|
||||
}
|
||||
|
||||
// Add a new task
|
||||
function addTask(title) {
|
||||
if (title && title.trim().length > 0) {
|
||||
append({
|
||||
"title": title.trim(),
|
||||
"completed": false,
|
||||
"id": generateId()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle task completion status
|
||||
function toggleTask(index) {
|
||||
if (index >= 0 && index < count) {
|
||||
setProperty(index, "completed", !get(index).completed)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete a task
|
||||
function deleteTask(index) {
|
||||
if (index >= 0 && index < count) {
|
||||
remove(index)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete task by ID
|
||||
function deleteTaskById(taskId) {
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (get(i).id === taskId) {
|
||||
remove(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all completed tasks
|
||||
function clearCompletedTasks() {
|
||||
for (let i = count - 1; i >= 0; i--) {
|
||||
if (get(i).completed) {
|
||||
remove(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get statistics
|
||||
function getStats() {
|
||||
let total = count
|
||||
let completed = 0
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (get(i).completed) {
|
||||
completed++
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
"total": total,
|
||||
"completed": completed,
|
||||
"remaining": total - completed
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there are any completed tasks
|
||||
function hasCompletedTasks() {
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (get(i).completed) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Generate a unique ID for tasks
|
||||
function generateId() {
|
||||
return Date.now() + Math.random().toString(36).substr(2, 9)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
ApplicationWindow {
|
||||
id: root
|
||||
width: 400
|
||||
height: 700
|
||||
visible: true
|
||||
title: qsTr("My Tasks")
|
||||
|
||||
// Theme properties
|
||||
property bool darkMode: false
|
||||
property color backgroundColor: darkMode ? "#1e1e1e" : "#f0f2f5"
|
||||
property color primaryColor: "#007aff"
|
||||
property color textColor: darkMode ? "#ffffff" : "#333333"
|
||||
property color cardColor: darkMode ? "#2d2d2d" : "#ffffff"
|
||||
property color completedColor: darkMode ? "#666666" : "#999999"
|
||||
|
||||
// Task model - Using the dedicated TaskListModel
|
||||
TaskListModel {
|
||||
id: taskModel
|
||||
}
|
||||
|
||||
// Background
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.backgroundColor
|
||||
}
|
||||
|
||||
//The components of the ui
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 20
|
||||
spacing: 20
|
||||
|
||||
// Header
|
||||
AppHeader {
|
||||
id: header
|
||||
Layout.fillWidth: true
|
||||
textColor: root.textColor
|
||||
textSecondary: root.completedColor
|
||||
darkMode: root.darkMode
|
||||
onToggleDarkMode: root.darkMode = !root.darkMode
|
||||
}
|
||||
|
||||
// Add task bar
|
||||
AddTaskBar {
|
||||
id: addTaskBar
|
||||
Layout.fillWidth: true
|
||||
backgroundColor: root.cardColor
|
||||
textColor: root.textColor
|
||||
primaryColor: root.primaryColor
|
||||
darkMode: root.darkMode
|
||||
|
||||
onTaskAdded: function(taskText) {
|
||||
taskModel.addTask(taskText)
|
||||
}
|
||||
}
|
||||
|
||||
// Tasks list
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
color: root.cardColor
|
||||
radius: 12
|
||||
border.width: 1
|
||||
border.color: root.darkMode ? "#404040" : "#e0e0e0"
|
||||
|
||||
ScrollView {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 1
|
||||
clip: true
|
||||
|
||||
ListView {
|
||||
id: taskListView
|
||||
model: taskModel
|
||||
spacing: 8
|
||||
anchors.margins: 12
|
||||
|
||||
|
||||
|
||||
// Add animation transitions
|
||||
add: Transition {
|
||||
NumberAnimation {
|
||||
properties: "x"
|
||||
from: 100; to: 0
|
||||
duration: 300
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 0; to: 1
|
||||
duration: 300
|
||||
}
|
||||
}
|
||||
|
||||
remove: Transition {
|
||||
NumberAnimation {
|
||||
properties: "x"
|
||||
to: 100
|
||||
duration: 250
|
||||
easing.type: Easing.InCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
to: 0
|
||||
duration: 250
|
||||
}
|
||||
}
|
||||
|
||||
displaced: Transition {
|
||||
NumberAnimation {
|
||||
properties: "x,y"
|
||||
duration: 200
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
delegate: TaskItem {
|
||||
required property int index
|
||||
required property string title
|
||||
required property bool completed
|
||||
|
||||
width: taskListView.width
|
||||
taskTitle: title
|
||||
taskDone: completed
|
||||
backgroundColor: root.cardColor
|
||||
textColor: root.textColor
|
||||
completedColor: root.completedColor
|
||||
primaryColor: root.primaryColor
|
||||
darkMode: root.darkMode
|
||||
|
||||
onToggleDone: {
|
||||
taskModel.toggleTask(index)
|
||||
}
|
||||
|
||||
onDeleteTask: {
|
||||
taskModel.deleteTask(index)
|
||||
}
|
||||
}
|
||||
|
||||
// Empty state
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - 40
|
||||
height: 120
|
||||
color: "transparent"
|
||||
visible: taskListView.count === 0
|
||||
opacity: taskListView.count === 0 ? 1.0 : 0.0
|
||||
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 400; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: 16
|
||||
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: "📝"
|
||||
font.pixelSize: 48
|
||||
opacity: 0.3
|
||||
|
||||
// Subtle floating animation
|
||||
SequentialAnimation on y {
|
||||
running: taskListView.count === 0
|
||||
loops: Animation.Infinite
|
||||
NumberAnimation { from: 0; to: -5; duration: 1000; easing.type: Easing.InOutSine }
|
||||
NumberAnimation { from: -5; to: 0; duration: 1000; easing.type: Easing.InOutSine }
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("No tasks yet")
|
||||
color: root.completedColor
|
||||
font.pixelSize: 18
|
||||
font.weight: Font.Medium
|
||||
|
||||
// Gentle opacity breathing animation
|
||||
SequentialAnimation on opacity {
|
||||
running: taskListView.count === 0
|
||||
loops: Animation.Infinite
|
||||
NumberAnimation { from: 0.7; to: 1.0; duration: 1500; easing.type: Easing.InOutSine }
|
||||
NumberAnimation { from: 1.0; to: 0.7; duration: 1500; easing.type: Easing.InOutSine }
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("Add a task above to get started")
|
||||
color: root.completedColor
|
||||
font.pixelSize: 14
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
// Gentle opacity breathing animation with slight delay
|
||||
SequentialAnimation on opacity {
|
||||
running: taskListView.count === 0
|
||||
loops: Animation.Infinite
|
||||
PauseAnimation { duration: 300 } // Small delay for staggered effect
|
||||
NumberAnimation { from: 0.6; to: 0.9; duration: 1500; easing.type: Easing.InOutSine }
|
||||
NumberAnimation { from: 0.9; to: 0.6; duration: 1500; easing.type: Easing.InOutSine }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Task statistics at bottom
|
||||
TaskStats {
|
||||
id: taskStats
|
||||
Layout.fillWidth: true
|
||||
backgroundColor: root.cardColor
|
||||
textColor: root.textColor
|
||||
secondaryTextColor: root.completedColor
|
||||
primaryColor: root.primaryColor
|
||||
darkMode: root.darkMode
|
||||
totalTasks: taskModel.count
|
||||
completedTasks: taskModel.getStats().completed
|
||||
remainingTasks: taskModel.getStats().remaining
|
||||
hasCompleted: taskModel.hasCompletedTasks()
|
||||
|
||||
onClearCompleted: {
|
||||
taskModel.clearCompletedTasks()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(2-Transforms VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.4 REQUIRED COMPONENTS Quick)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(app2-Transforms
|
||||
main.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(app2-Transforms
|
||||
URI 2-Transforms
|
||||
VERSION 1.0
|
||||
QML_FILES Main.qml
|
||||
QML_FILES ClickableRect.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(app2-Transforms PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.app2-Transforms
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(app2-Transforms
|
||||
PRIVATE Qt6::Quick
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS app2-Transforms
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
import QtQuick
|
||||
|
||||
Rectangle{
|
||||
id: rootId
|
||||
signal clicked
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: function(){
|
||||
rootId.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import QtQuick
|
||||
|
||||
Window {
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: qsTr("Transforms")
|
||||
|
||||
ClickableRect{
|
||||
id: rect1Id
|
||||
width: 100
|
||||
height: 100
|
||||
x: 50
|
||||
y: 100
|
||||
color: "red"
|
||||
onClicked: function(){
|
||||
//Translation on x
|
||||
x += 20
|
||||
}
|
||||
}
|
||||
ClickableRect{
|
||||
id: rect2Id
|
||||
width: 100
|
||||
height: 100
|
||||
transformOrigin: Item.TopRight
|
||||
x: 250
|
||||
y: 100
|
||||
color: "green"
|
||||
onClicked: function(){
|
||||
// Rotation
|
||||
rotation += 15
|
||||
}
|
||||
}
|
||||
ClickableRect{
|
||||
id: rect3Id
|
||||
width: 100
|
||||
height: 100
|
||||
transformOrigin: Item.BottomLeft
|
||||
x: 450
|
||||
y: 100
|
||||
color: "blue"
|
||||
onClicked: function(){
|
||||
//scaling
|
||||
scale += 0.05
|
||||
|
||||
//rotation
|
||||
rotation += 20
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
const QUrl url(u"qrc:/2-Transforms/Main.qml"_qs);
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.load(url);
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user