add book
This commit is contained in:
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user