forked from Shinonome/dots-hyprland
todo widget: add ability to add items
This commit is contained in:
@@ -120,9 +120,11 @@ Singleton {
|
|||||||
property color colLayer2Active: mix(colLayer2, colOnLayer2, 0.80);
|
property color colLayer2Active: mix(colLayer2, colOnLayer2, 0.80);
|
||||||
property color colLayer3Hover: mix(colLayer3, colOnLayer3, 0.90);
|
property color colLayer3Hover: mix(colLayer3, colOnLayer3, 0.90);
|
||||||
property color colLayer3Active: mix(colLayer3, colOnLayer3, 0.80);
|
property color colLayer3Active: mix(colLayer3, colOnLayer3, 0.80);
|
||||||
property color colPrimaryHover: mix(m3colors.m3primary, colLayer1Hover, 0.7)
|
property color colPrimaryHover: mix(m3colors.m3primary, colLayer1Hover, 0.85)
|
||||||
property color colPrimaryActive: mix(m3colors.m3primary, colLayer1Active, 0.4)
|
property color colPrimaryActive: mix(m3colors.m3primary, colLayer1Active, 0.7)
|
||||||
property color colSecondaryHover: mix(m3colors.m3secondary, colLayer1Hover, 0.7)
|
property color colPrimaryContainerHover: mix(m3colors.m3primaryContainer, colLayer1Hover, 0.7)
|
||||||
|
property color colPrimaryContainerActive: mix(m3colors.m3primaryContainer, colLayer1Active, 0.6)
|
||||||
|
property color colSecondaryHover: mix(m3colors.m3secondary, colLayer1Hover, 0.85)
|
||||||
property color colSecondaryActive: mix(m3colors.m3secondary, colLayer1Active, 0.4)
|
property color colSecondaryActive: mix(m3colors.m3secondary, colLayer1Active, 0.4)
|
||||||
property color colSecondaryContainerHover: mix(m3colors.m3secondaryContainer, colLayer1Hover, 0.8)
|
property color colSecondaryContainerHover: mix(m3colors.m3secondaryContainer, colLayer1Hover, 0.8)
|
||||||
property color colSecondaryContainerActive: mix(m3colors.m3secondaryContainer, colLayer1Active, 0.6)
|
property color colSecondaryContainerActive: mix(m3colors.m3secondaryContainer, colLayer1Active, 0.6)
|
||||||
@@ -144,7 +146,7 @@ Singleton {
|
|||||||
property QtObject family: QtObject {
|
property QtObject family: QtObject {
|
||||||
property string main: "Rubik"
|
property string main: "Rubik"
|
||||||
property string title: "Rubik"
|
property string title: "Rubik"
|
||||||
property string iconMaterial: "Material Symbols Rounded"
|
property string iconMaterial: "Material Symbols Outlined"
|
||||||
property string iconNerd: "SpaceMono NF"
|
property string iconNerd: "SpaceMono NF"
|
||||||
property string monospace: "JetBrains Mono NF"
|
property string monospace: "JetBrains Mono NF"
|
||||||
property string reading: "Readex Pro"
|
property string reading: "Readex Pro"
|
||||||
@@ -189,6 +191,8 @@ Singleton {
|
|||||||
property int sidebarWidth: 450
|
property int sidebarWidth: 450
|
||||||
property int hyprlandGapsOut: 5
|
property int hyprlandGapsOut: 5
|
||||||
property int elevationMargin: 7
|
property int elevationMargin: 7
|
||||||
|
property int fabShadowRadius: 5
|
||||||
|
property int fabHoveredShadowRadius: 7
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import "root:/modules/common"
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: button
|
||||||
|
|
||||||
|
property string buttonText
|
||||||
|
implicitHeight: 30
|
||||||
|
implicitWidth: buttonTextWidget.implicitWidth + 15 * 2
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Appearance.rounding.full
|
||||||
|
color: (button.down && button.enabled) ? Appearance.colors.colLayer1Active : ((button.hovered && button.enabled) ? Appearance.colors.colLayer1Hover : Appearance.transparentize(Appearance.m3colors.m3surfaceContainerHigh, 1))
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Appearance.animation.elementDecel.duration
|
||||||
|
easing.type: Appearance.animation.elementDecel.type
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: StyledText {
|
||||||
|
id: buttonTextWidget
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: 15
|
||||||
|
anchors.rightMargin: 15
|
||||||
|
text: buttonText
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.normal
|
||||||
|
color: button.enabled ? Appearance.m3colors.m3primary : Appearance.m3colors.m3outline
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Appearance.animation.elementDecel.duration
|
||||||
|
easing.type: Appearance.animation.elementDecel.type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,21 +21,16 @@ Rectangle {
|
|||||||
{"type": "calendar", "name": "Calendar", "icon": "calendar_month", "widget": calendarWidget},
|
{"type": "calendar", "name": "Calendar", "icon": "calendar_month", "widget": calendarWidget},
|
||||||
{"type": "todo", "name": "To Do", "icon": "done_outline", "widget": todoWidget}
|
{"type": "todo", "name": "To Do", "icon": "done_outline", "widget": todoWidget}
|
||||||
]
|
]
|
||||||
// Calendar
|
|
||||||
Component {
|
|
||||||
id: calendarWidget
|
|
||||||
|
|
||||||
CalendarWidget {
|
Keys.onPressed: (event) => {
|
||||||
anchors.centerIn: parent
|
if ((event.key === Qt.Key_PageDown || event.key === Qt.Key_PageUp)
|
||||||
}
|
&& event.modifiers === Qt.ControlModifier) {
|
||||||
}
|
if (event.key === Qt.Key_PageDown) {
|
||||||
|
root.selectedTab = Math.min(root.selectedTab + 1, root.tabs.length - 1)
|
||||||
// To Do
|
} else if (event.key === Qt.Key_PageUp) {
|
||||||
Component {
|
root.selectedTab = Math.max(root.selectedTab - 1, 0)
|
||||||
id: todoWidget
|
}
|
||||||
TodoWidget {
|
event.accepted = true;
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 5
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +67,7 @@ Rectangle {
|
|||||||
height: tabStack.children[0]?.tabLoader?.implicitHeight // TODO: make this less stupid
|
height: tabStack.children[0]?.tabLoader?.implicitHeight // TODO: make this less stupid
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
property int realIndex: 0
|
property int realIndex: 0
|
||||||
property int animationDuration: Appearance.animation.elementDecel.duration * 1.5
|
property int animationDuration: Appearance.animation.elementDecelFast.duration * 1.5
|
||||||
|
|
||||||
// Switch the tab on halfway of the anim duration
|
// Switch the tab on halfway of the anim duration
|
||||||
Connections {
|
Connections {
|
||||||
@@ -109,9 +104,28 @@ Rectangle {
|
|||||||
id: tabLoader
|
id: tabLoader
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
sourceComponent: modelData.widget
|
sourceComponent: modelData.widget
|
||||||
|
focus: root.selectedTab === tabItem.tabIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calendar component
|
||||||
|
Component {
|
||||||
|
id: calendarWidget
|
||||||
|
|
||||||
|
CalendarWidget {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// To Do component
|
||||||
|
Component {
|
||||||
|
id: todoWidget
|
||||||
|
TodoWidget {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 5
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ Scope {
|
|||||||
radius: Appearance.rounding.screenRounding - Appearance.sizes.elevationMargin + 1
|
radius: Appearance.rounding.screenRounding - Appearance.sizes.elevationMargin + 1
|
||||||
|
|
||||||
focus: true
|
focus: true
|
||||||
Keys.onPressed: {
|
Keys.onPressed: (event) => {
|
||||||
if (event.key === Qt.Key_Escape) {
|
if (event.key === Qt.Key_Escape) {
|
||||||
sidebarRoot.visible = false;
|
sidebarRoot.visible = false;
|
||||||
event.accepted = true; // Prevent further propagation of the event
|
event.accepted = true; // Prevent further propagation of the event
|
||||||
|
|||||||
@@ -14,9 +14,20 @@ Item {
|
|||||||
width: calendarColumn.width
|
width: calendarColumn.width
|
||||||
implicitHeight: calendarColumn.height + 10 * 2
|
implicitHeight: calendarColumn.height + 10 * 2
|
||||||
|
|
||||||
|
Keys.onPressed: (event) => {
|
||||||
|
if ((event.key === Qt.Key_PageDown || event.key === Qt.Key_PageUp)
|
||||||
|
&& event.modifiers === Qt.NoModifier) {
|
||||||
|
if (event.key === Qt.Key_PageDown) {
|
||||||
|
monthShift++;
|
||||||
|
} else if (event.key === Qt.Key_PageUp) {
|
||||||
|
monthShift--;
|
||||||
|
}
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onWheel: {
|
onWheel: (event) => {
|
||||||
if (wheel.angleDelta.y > 0) {
|
if (wheel.angleDelta.y > 0) {
|
||||||
monthShift--;
|
monthShift--;
|
||||||
} else if (wheel.angleDelta.y < 0) {
|
} else if (wheel.angleDelta.y < 0) {
|
||||||
@@ -24,6 +35,7 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: calendarColumn
|
id: calendarColumn
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|||||||
@@ -8,10 +8,14 @@ import QtQuick.Layouts
|
|||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
required property var taskList;
|
required property var taskList;
|
||||||
|
property string emptyPlaceholderIcon
|
||||||
|
property string emptyPlaceholderText
|
||||||
property int todoListItemSpacing: 5
|
property int todoListItemSpacing: 5
|
||||||
property int todoListItemPadding: 8
|
property int todoListItemPadding: 8
|
||||||
|
property int listBottomPadding: 80
|
||||||
|
|
||||||
Flickable { // Scrolled window
|
Flickable { // Scrolled window
|
||||||
|
id: flickable
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
contentHeight: columnLayout.height
|
contentHeight: columnLayout.height
|
||||||
clip: true
|
clip: true
|
||||||
@@ -123,6 +127,35 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// Bottom padding
|
||||||
|
Item {
|
||||||
|
implicitHeight: listBottomPadding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Placeholder when list is empty
|
||||||
|
Item {
|
||||||
|
visible: taskList.length === 0
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: 5
|
||||||
|
|
||||||
|
MaterialSymbol {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: emptyPlaceholderIcon
|
||||||
|
font.pixelSize: 55
|
||||||
|
color: Appearance.m3colors.m3outline
|
||||||
|
}
|
||||||
|
StyledText {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: emptyPlaceholderText
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.normal
|
||||||
|
color: Appearance.m3colors.m3outline
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,37 @@ import "root:/services"
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import Qt5Compat.GraphicalEffects
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
id: root
|
||||||
property int currentTab: 0
|
property int currentTab: 0
|
||||||
|
property var tabButtonList: [{"icon": "checklist", "name": "Unfinished"}, {"name": "Done", "icon": "check_circle"}]
|
||||||
|
property bool showAddDialog: false
|
||||||
|
property int dialogMargins: 25
|
||||||
|
property int fabSize: 48
|
||||||
|
property int fabMargins: 14
|
||||||
|
|
||||||
|
Keys.onPressed: (event) => {
|
||||||
|
if ((event.key === Qt.Key_PageDown || event.key === Qt.Key_PageUp) && event.modifiers === Qt.NoModifier) {
|
||||||
|
if (event.key === Qt.Key_PageDown) {
|
||||||
|
currentTab = Math.min(currentTab + 1, root.tabButtonList.length - 1)
|
||||||
|
} else if (event.key === Qt.Key_PageUp) {
|
||||||
|
currentTab = Math.max(currentTab - 1, 0)
|
||||||
|
}
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
// Open add dialog on "N" (any modifiers)
|
||||||
|
else if (event.key === Qt.Key_N) {
|
||||||
|
root.showAddDialog = true
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
// Close dialog on Esc if open
|
||||||
|
else if (event.key === Qt.Key_Escape && root.showAddDialog) {
|
||||||
|
root.showAddDialog = false
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -14,7 +42,6 @@ Item {
|
|||||||
|
|
||||||
TabBar {
|
TabBar {
|
||||||
id: tabBar
|
id: tabBar
|
||||||
property var tabButtonList: [{"icon": "checklist", "name": "Unfinished"}, {"name": "Done", "icon": "check_circle"}]
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
currentIndex: currentTab
|
currentIndex: currentTab
|
||||||
onCurrentIndexChanged: currentTab = currentIndex
|
onCurrentIndexChanged: currentTab = currentIndex
|
||||||
@@ -23,7 +50,7 @@ Item {
|
|||||||
WheelHandler {
|
WheelHandler {
|
||||||
onWheel: (event) => {
|
onWheel: (event) => {
|
||||||
if (event.angleDelta.y < 0)
|
if (event.angleDelta.y < 0)
|
||||||
currentTab = Math.min(currentTab + 1, tabBar.tabButtonList.length - 1)
|
currentTab = Math.min(currentTab + 1, root.tabButtonList.length - 1)
|
||||||
else if (event.angleDelta.y > 0)
|
else if (event.angleDelta.y > 0)
|
||||||
currentTab = Math.max(currentTab - 1, 0)
|
currentTab = Math.max(currentTab - 1, 0)
|
||||||
}
|
}
|
||||||
@@ -32,7 +59,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: tabBar.tabButtonList
|
model: root.tabButtonList
|
||||||
delegate: StyledTabButton {
|
delegate: StyledTabButton {
|
||||||
selected: (index == currentTab)
|
selected: (index == currentTab)
|
||||||
buttonText: modelData.name
|
buttonText: modelData.name
|
||||||
@@ -50,8 +77,8 @@ Item {
|
|||||||
height: 3
|
height: 3
|
||||||
radius: Appearance.rounding.full
|
radius: Appearance.rounding.full
|
||||||
|
|
||||||
width: tabBar.width / tabBar.tabButtonList.length - indicatorPadding * 2
|
width: tabBar.width / root.tabButtonList.length - indicatorPadding * 2
|
||||||
x: indicatorPadding + tabBar.width / tabBar.tabButtonList.length * currentTab
|
x: indicatorPadding + tabBar.width / root.tabButtonList.length * currentTab
|
||||||
z: 2
|
z: 2
|
||||||
Behavior on x { SmoothedAnimation {
|
Behavior on x { SmoothedAnimation {
|
||||||
velocity: Appearance.animation.positionShift.velocity
|
velocity: Appearance.animation.positionShift.velocity
|
||||||
@@ -71,11 +98,17 @@ Item {
|
|||||||
|
|
||||||
// To Do tab
|
// To Do tab
|
||||||
TaskList {
|
TaskList {
|
||||||
|
listBottomPadding: root.fabSize + root.fabMargins * 2
|
||||||
|
emptyPlaceholderIcon: "check_circle"
|
||||||
|
emptyPlaceholderText: "Nothing here!"
|
||||||
taskList: Todo.list
|
taskList: Todo.list
|
||||||
.map(function(item, i) { return Object.assign({}, item, {originalIndex: i}); })
|
.map(function(item, i) { return Object.assign({}, item, {originalIndex: i}); })
|
||||||
.filter(function(item) { return !item.done; })
|
.filter(function(item) { return !item.done; })
|
||||||
}
|
}
|
||||||
TaskList {
|
TaskList {
|
||||||
|
listBottomPadding: root.fabSize + root.fabMargins * 2
|
||||||
|
emptyPlaceholderIcon: "checklist"
|
||||||
|
emptyPlaceholderText: "Finished tasks will go here"
|
||||||
taskList: Todo.list
|
taskList: Todo.list
|
||||||
.map(function(item, i) { return Object.assign({}, item, {originalIndex: i}); })
|
.map(function(item, i) { return Object.assign({}, item, {originalIndex: i}); })
|
||||||
.filter(function(item) { return item.done; })
|
.filter(function(item) { return item.done; })
|
||||||
@@ -83,4 +116,164 @@ Item {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// + FAB
|
||||||
|
Button {
|
||||||
|
id: fabButton
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.rightMargin: root.fabMargins
|
||||||
|
anchors.bottomMargin: root.fabMargins
|
||||||
|
|
||||||
|
width: root.fabSize
|
||||||
|
height: root.fabSize
|
||||||
|
|
||||||
|
onClicked: root.showAddDialog = true
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
id: fabBackground
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Appearance.rounding.small
|
||||||
|
color: (fabButton.down) ? Appearance.colors.colPrimaryContainerActive : (fabButton.hovered ? Appearance.colors.colPrimaryContainerHover : Appearance.m3colors.m3primaryContainer)
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Appearance.animation.elementDecel.duration
|
||||||
|
easing.type: Appearance.animation.elementDecel.type
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DropShadow {
|
||||||
|
id: fabShadow
|
||||||
|
anchors.fill: fabBackground
|
||||||
|
source: fabBackground
|
||||||
|
horizontalOffset: 0
|
||||||
|
verticalOffset: fabButton.hovered ? 4 : 2
|
||||||
|
radius: fabButton.hovered ? Appearance.sizes.fabHoveredShadowRadius : Appearance.sizes.fabShadowRadius
|
||||||
|
samples: fabShadow.radius * 2 + 1
|
||||||
|
color: Appearance.transparentize(Appearance.m3colors.m3shadow, 0.55)
|
||||||
|
z: fabBackground.z - 1
|
||||||
|
|
||||||
|
Behavior on verticalOffset {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Appearance.animation.elementDecelFast.duration
|
||||||
|
easing.type: Appearance.animation.elementDecelFast.type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: MaterialSymbol {
|
||||||
|
text: "add"
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.huge
|
||||||
|
color: Appearance.m3colors.m3onPrimaryContainer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
visible: root.showAddDialog
|
||||||
|
z: 1000
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (!visible) {
|
||||||
|
todoInput.text = ""
|
||||||
|
fabButton.focus = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle { // Scrim
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Appearance.rounding.small
|
||||||
|
color: "#80000000"
|
||||||
|
MouseArea {
|
||||||
|
hoverEnabled: true
|
||||||
|
anchors.fill: parent
|
||||||
|
preventStealing: true
|
||||||
|
propagateComposedEvents: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle { // The dialog
|
||||||
|
id: dialog
|
||||||
|
implicitWidth: parent.width - dialogMargins * 2
|
||||||
|
implicitHeight: dialogColumnLayout.implicitHeight
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: Appearance.m3colors.m3surfaceContainerHigh
|
||||||
|
radius: Appearance.rounding.normal
|
||||||
|
|
||||||
|
function addTask() {
|
||||||
|
if (todoInput.text.length > 0) {
|
||||||
|
Todo.addTask(todoInput.text)
|
||||||
|
todoInput.text = ""
|
||||||
|
root.showAddDialog = false
|
||||||
|
root.currentTab = 0 // Show unfinished tasks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
id: dialogColumnLayout
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
Layout.topMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.alignment: Qt.AlignLeft
|
||||||
|
color: Appearance.m3colors.m3onSurface
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.larger
|
||||||
|
text: "Add task"
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: todoInput
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
padding: 10
|
||||||
|
color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant
|
||||||
|
selectedTextColor: Appearance.m3colors.m3onSurface
|
||||||
|
placeholderText: "Task description"
|
||||||
|
focus: root.showAddDialog
|
||||||
|
onAccepted: dialog.addTask()
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: 8
|
||||||
|
border.width: 2
|
||||||
|
border.color: todoInput.activeFocus ? Appearance.m3colors.m3primary : Appearance.m3colors.m3outline
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
|
|
||||||
|
cursorDelegate: Rectangle {
|
||||||
|
width: 1
|
||||||
|
color: todoInput.activeFocus ? Appearance.m3colors.m3primary : "transparent"
|
||||||
|
radius: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.bottomMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
spacing: 5
|
||||||
|
|
||||||
|
DialogButton {
|
||||||
|
buttonText: "Cancel"
|
||||||
|
onClicked: root.showAddDialog = false
|
||||||
|
}
|
||||||
|
DialogButton {
|
||||||
|
buttonText: "Add"
|
||||||
|
enabled: todoInput.text.length > 0
|
||||||
|
onClicked: dialog.addTask()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,9 +13,19 @@ Singleton {
|
|||||||
|
|
||||||
function addItem(item) {
|
function addItem(item) {
|
||||||
list.push(item)
|
list.push(item)
|
||||||
|
// Reassign to trigger onListChanged
|
||||||
|
root.list = list.slice(0)
|
||||||
todoFileView.setText(JSON.stringify(root.list))
|
todoFileView.setText(JSON.stringify(root.list))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addTask(desc) {
|
||||||
|
const item = {
|
||||||
|
"content": desc,
|
||||||
|
"done": false,
|
||||||
|
}
|
||||||
|
addItem(item)
|
||||||
|
}
|
||||||
|
|
||||||
function markDone(index) {
|
function markDone(index) {
|
||||||
if (index >= 0 && index < list.length) {
|
if (index >= 0 && index < list.length) {
|
||||||
list[index].done = true
|
list[index].done = true
|
||||||
|
|||||||
Reference in New Issue
Block a user