할 일 목록

모든 플랫폼에서 네이티브처럼 보이는 애플리케이션을 만드는 방법을 보여주는 할 일 목록 애플리케이션의 QML 구현입니다.

CustomStyleMaterialiOS

To Do List는 모든 플랫폼에서 네이티브처럼 보이는 할 일 목록 애플리케이션 샘플을 보여줍니다. 이 예제는 QtDesignStudio와 QtCreator 모두에서 실행하고 편집할 수 있습니다. 사용자 지정 스타일을 만들고 사용하는 방법과 설정을 사용하여 애플리케이션의 모양과 동작을 제어하는 방법을 보여줍니다. 또한 델리게이트에서 간단한 드래그 앤 드롭 동작을 구현하는 방법도 소개합니다. 이 애플리케이션은 로컬 저장소를 사용하여 디바이스에 항목을 저장하고 XMLHttpRequest 를 사용하여 공개 API(무작위 작업 기능)에서 데이터를 검색합니다. 보기는 StackView 컴포넌트에 의해 제어됩니다.

애플리케이션 스타일 선택하기

애플리케이션은 대상 플랫폼에 따라 다양한 스타일을 지원합니다. 사용자 지정 스타일, 기본, 자료 및 유니버설은 각 플랫폼(Windows, Android, iOS, macOS)에서 사용할 수 있습니다. Windows 스타일은 Windows에서만 사용할 수 있으며 iOS 스타일은 iOS에서만 사용할 수 있습니다. 사용 가능한 스타일 목록은 SettingsView 의 하위 페이지 중 하나인 스타일에 있습니다. 현재 사용 중인 스타일은 같은 위치에서 변경할 수 있습니다. 변경 사항을 적용하려면 다시 시작해야 합니다. 애플리케이션은 ToolTip 정보와 함께 사용자에게 이에 대해 알려줍니다.

테마 변경하기

각 스타일에는 어두운 테마 및 밝은 테마도 지원됩니다. 테마는 SettingsView 의 테마 하위 페이지에서 변경할 수 있습니다. 모든 스타일에서 사용자가 수동으로 테마를 변경할 수 있는 것은 아닙니다(예: iOS에서는 이 옵션을 사용할 수 없습니다). 이 경우 테마는 기본 시스템 설정에 따라 변경됩니다. 앱을 처음 실행하면 시스템 테마가 사용됩니다.

앱 설정에서 앱 동작 제어하기

애플리케이션의 동작 및 스타일은 SettingsView 에서 변경할 수 있습니다. 설정을 통해 사용자가 변경할 수 있습니다:

  • 스타일
  • 테마
  • 글꼴 크기
  • 최대 작업 수
  • 완료된 작업을 자동으로 제거해야 하는지 여부

작업 목록 구현

애플리케이션에는 세 가지 목록이 있습니다:

  • 오늘의 작업 목록 → 오늘 날짜가 마감일인 작업입니다.
  • 이번 주 작업 목록 → 앞으로 7일 이내에 마감일이 있는 작업입니다.
  • 이후 작업 → 위 목록에 포함되지 않는 작업입니다.

작업은 애플리케이션을 시작할 때 목록 모델 간에 분산됩니다. 물론 작업은 런타임에 목록 모델을 통해 마이그레이션할 수 있습니다(마감일이 변경될 때). 단일 목록의 정의는 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
        }
    }

목록 모델을 데이터로 채우는 작업은 Component.onCompletedTasksListsView.qml 에서 수행됩니다.

    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
    }

공개 API에서 데이터를 검색하기 위한 XMLHttpRequest 사용

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

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.