待办事项列表

一个待办事项列表应用的 QML 实现,演示如何创建在任何平台上看起来原生的应用程序。

自定义样式材质iOS

待办事项列表 展示了一个示例待办事项列表应用,它在任何平台上看起来都是原生的。这个示例可以在 QtDesignStudio 和 QtCreator 中运行和编辑。它展示了如何创建和使用自定义样式,如何使用设置来控制应用程序的外观和行为。它还展示了如何在委托中实现简单的拖放行为。应用程序使用本地存储在设备上存储项目,并使用 XMLHttpRequest 从公开 API(随机任务功能)检索数据。视图由 StackView 组件控制。

选择应用程序样式

应用程序支持根据目标平台的不同风格。自定义样式、基本、材质和通用在每个平台上(Windows、Android、iOS、macOS)都可用。仅 Windows 上有 Windows 风格,iOS 上仅可用 iOS 风格。可用样式的列表位于 SettingsView 的子页之一中,称为样式。当前使用的样式也可以从中更改。更改后需要重启才能应用更改。应用程序会将此信息通知用户 ToolTip

更改主题

每个风格都支持深色和浅色主题。主题可以从 SettingsView 的主题子页中更改。并非每个样式都允许用户手动更改主题,例如在 iOS 上此选项不可用。在这种情况下,主题将根据默认系统设置更改。应用程序首次启动时将使用系统主题。

从应用程序设置控制应用程序行为

应用程序的行为和样式可以从 SettingsView 更改。这些设置允许用户更改

  • 样式
  • 主题
  • 字体大小
  • 最大任务数
  • 完成后的任务是否应自动删除

任务列表实现

应用程序有三个不同的列表

  • 今天的任务列表 → 以今天日期为截止日期的任务。
  • 本周的任务列表 → 在接下来的七天内到期的工作。
  • 稍后任务 → 不适合以上列表的任务。

任务在应用程序启动时分布在列表模型之间。当然,任务可以在运行时在不同的列表模型之间迁移(当它们的截止日期更改时)。单个列表的定义在 TasksList.qmlTasksListForm.ui.qml 中完成,实例在 TasksListsView.qml/TasksListsViewForm.ui.qml 中创建。

    ListModel {
        id: todayTasksListModel
    }

    ListModel {
        id: thisWeekTasksListModel
    }

    ListModel {
        id: laterTasksListModel
    }

    Column {
        id: column

        anchors.fill: parent
        spacing: 14

        TasksList {
            id: todayTasks

            width: column.width
            maxHeight: 180
            listModel: todayTasksListModel
            headerText: qsTr("Today")
            tasksCount: todayTasksListModel.count
        }

        TasksList {
            id: thisWeekTasks

            width: column.width
            maxHeight: column.height - y - 60
            listModel: thisWeekTasksListModel
            headerText: qsTr("This week")
            tasksCount: thisWeekTasksListModel.count
        }

        TasksList {
            id: laterTasks

            width: column.width
            maxHeight: column.height - y
            listModel: laterTasksListModel
            headerText: qsTr("Later")
            tasksCount: laterTasksListModel.count
        }
    }

TasksListsView.qml中的Component.onCompleted中完成填充列表模型。

    function createTasksLists() : void {
        var tasks = Database.getTasks()
        var currentDate = new Date()
        var format = Qt.locale().dateFormat(Locale.LongFormat)
        var dateStr = currentDate.toLocaleDateString(Qt.locale(),format)
        tasks.forEach( function(task){
            if (task.date === dateStr) {
                todayTasksModel.append(task)
            } else if (checkThisWeekDate(task.date)) {
                thisWeekTasksModel.append(task)
            } else {
                laterTasksModel.append(task)
            }
        })
    }

    Component.onCompleted: createTasksLists()

滑动、拖拽并放置行为

列表视图使用TasksListDelegate作为代理。代理是一个SwipeDelegate,允许用户滑动项目以突出显示它(项目移动到列表顶部)或移除它。它还允许用户标记任务已完成(项目移动到底部)或拖拽并放置项目以将项目移动到列表中的特定位置。这些行为的实现是在TasksListDelegate.qml中完成的。

本地存储的使用

使用本地存储将任务项读取和写入SQLite数据库。此及其它辅助函数的实现是在单例对象Database.qml中完成的。

    property var _db

    function _database() {
        if (_db) return _db

        try {
            let db = LocalStorage.openDatabaseSync("ToDoList", "1.0", "ToDoList app database")

            db.transaction(function (tx) {
                tx.executeSql('CREATE TABLE IF NOT EXISTS tasks (
                    task_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    task_name,
                    task_dueDate TEXT,
                    task_dueTime TEXT,
                    task_notes TEXT,
                    done INTEGER,
                    highlighted INTEGER
                )');
            })

            _db = db
        } catch (error) {
            console.log("Error opening databse: " + error)
        };
        return _db
    }

    function addTask(taskName, taskDueDate, taskDueTime, taskNotes, taskDone, taskHighlighted) {
        let results
        root._database().transaction(function(tx){
            tx.executeSql("INSERT INTO tasks (task_name, task_dueDate, task_dueTime,
                        task_notes, done, highlighted) VALUES(?,?,?,?,?,?);",
                        [taskName, taskDueDate, taskDueTime, taskNotes, taskDone, taskHighlighted])
            results = tx.executeSql("SELECT * FROM tasks ORDER BY task_id DESC LIMIT 1")
        })
        return results.rows.item(0).task_id
    }

使用XMLHttpRequest从公共API检索数据

使用XMLHttpRequest向某些公共API发送请求并获取响应数据。该应用程序使用boredapi,可以返回一个随机任务。然后将该任务添加到今天的任务列表中。

    function sendHttpRequest() : void {
        var http = new XMLHttpRequest()
        var url = "https://www.boredapi.com/api/activity";
        http.open("GET", url, true);

        http.setRequestHeader("Content-type", "application/json");
        http.setRequestHeader("Connection", "close");

        http.onreadystatechange = function() {
            if (http.readyState == 4) {
                if (http.status == 200) {
                    var object = JSON.parse(http.responseText.toString());
                    var currentDate = new Date()
                    var format = Qt.locale().dateFormat(Locale.LongFormat)
                    addTask(todayTasksModel, object.activity,
                            currentDate.toLocaleDateString(Qt.locale(), format), "","")
                } else {
                    console.log("error: " + http.status)
                }
            }
        }
        http.send();
    }

示例项目 @ code.qt.io

© 2024 Qt公司。包含在此处的文档贡献是各自所有者的版权。所提供的文档是根据自由软件开发基金会出版的<"text,tlink植"GNU自由文档许可第1.3版的条款发布的。Qt及其相应标志是芬兰及其它在世界范围内的Qt公司的商标。所有其他的商标均为其各自所有者的财产。