Warning, /utilities/francis/src/ui/main.qml is written in an unsupported language. File is not indexed.
0001 // SPDX-FileCopyrightText: 2022 Felipe Kinoshita <kinofhek@gmail.com> 0002 // SPDX-License-Identifier: GPL-3.0-or-later 0003 0004 import QtQuick 2.15 0005 import QtQuick.Controls 2.15 as QQC2 0006 import QtQuick.Layouts 1.15 0007 import QtQuick.Shapes 1.14 0008 import QtQml 2.14 0009 0010 import org.kde.kirigami 2.19 as Kirigami 0011 import org.kde.notification 1.0 0012 0013 import org.kde.francis 1.0 0014 0015 Kirigami.ApplicationWindow { 0016 id: root 0017 0018 title: i18n("Francis") 0019 0020 width: Kirigami.Units.gridUnit * 25 0021 height: Kirigami.Units.gridUnit * 25 0022 minimumWidth: Kirigami.Units.gridUnit * 20 0023 minimumHeight: Kirigami.Units.gridUnit * 20 0024 0025 Timer { 0026 id: saveWindowGeometryTimer 0027 interval: 1000 0028 onTriggered: App.saveWindowGeometry(root) 0029 } 0030 0031 Connections { 0032 id: saveWindowGeometryConnections 0033 enabled: root.visible 0034 target: root 0035 0036 function onClosing() { App.saveWindowGeometry(root); } 0037 function onWidthChanged() { saveWindowGeometryTimer.restart(); } 0038 function onHeightChanged() { saveWindowGeometryTimer.restart(); } 0039 function onXChanged() { saveWindowGeometryTimer.restart(); } 0040 function onYChanged() { saveWindowGeometryTimer.restart(); } 0041 } 0042 0043 Connections { 0044 target: Controller 0045 0046 function onBreakChanged() { 0047 if (Controller.onBreak) { 0048 intervalEndedNotification.sendEvent() 0049 } else { 0050 breakEndedNotification.sendEvent() 0051 } 0052 } 0053 } 0054 0055 Loader { 0056 active: !Kirigami.Settings.isMobile 0057 sourceComponent: GlobalMenu {} 0058 } 0059 0060 Notification { 0061 id: intervalEndedNotification 0062 componentName: "plasma_workspace" 0063 eventId: "notification" 0064 urgency: Notification.LowUrgency 0065 title: i18n("Interval Ended") 0066 text: i18n("Enjoy your break, drink some water.") 0067 iconName: "appointment-reminder" 0068 } 0069 0070 Notification { 0071 id: breakEndedNotification 0072 componentName: "plasma_workspace" 0073 eventId: "notification" 0074 urgency: Notification.LowUrgency 0075 title: i18n("Break Ended") 0076 text: i18n("Get back to work.") 0077 iconName: "appointment-reminder" 0078 } 0079 0080 pageStack.initialPage: Kirigami.Page { 0081 id: page 0082 0083 padding: 0 0084 titleDelegate: PageHeader {} 0085 0086 TapHandler { 0087 onTapped: Controller.hasStarted ? Controller.toggle() : Controller.start() 0088 } 0089 0090 ColumnLayout { 0091 anchors.centerIn: parent 0092 0093 Item { 0094 implicitWidth: circleArc.radiusX * 2 + 10 0095 implicitHeight: implicitWidth 0096 0097 Shape { 0098 id: circle 0099 0100 layer { 0101 enabled: true 0102 samples: 8 0103 } 0104 anchors.fill: parent 0105 anchors.horizontalCenter: parent.horizontalCenter 0106 Kirigami.Theme.colorSet: Kirigami.Theme.Button 0107 0108 // base circle 0109 ShapePath { 0110 strokeColor: Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.disabledTextColor, "transparent", 0.6); 0111 fillColor: "transparent" 0112 strokeWidth: 3 0113 capStyle: ShapePath.FlatCap 0114 PathAngleArc { 0115 id: circleArc 0116 centerX: circle.width / 2; centerY: circle.height / 2; 0117 radiusX: Math.min(root.width * (Kirigami.Settings.isMobile ? 0.3 : 0.25), root.height * (Kirigami.Settings.isMobile ? 0.3 : 0.25)); radiusY: radiusX 0118 startAngle: -180 0119 sweepAngle: 360 0120 } 0121 } 0122 0123 // progress circle 0124 ShapePath { 0125 strokeColor: Controller.onBreak ? Kirigami.Theme.textColor : Kirigami.Theme.linkColor 0126 fillColor: "transparent" 0127 strokeWidth: 7 0128 capStyle: ShapePath.RoundCap 0129 PathAngleArc { 0130 id: arc 0131 centerX: circleArc.centerX; centerY: circleArc.centerY 0132 radiusX: circleArc.radiusX; radiusY: circleArc.radiusY 0133 startAngle: -90 + 360 * Controller.percentage / 100 0134 sweepAngle: 360 * (1 - Controller.percentage/100) 0135 Behavior on sweepAngle { 0136 NumberAnimation{ 0137 duration: 1000 0138 } 0139 } 0140 } 0141 } 0142 ShapePath { 0143 strokeColor: Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.backgroundColor, "transparent", 0.4); 0144 fillColor: "transparent" 0145 strokeWidth: 5 0146 capStyle: ShapePath.RoundCap 0147 PathAngleArc { 0148 centerX: circleArc.centerX; centerY: circleArc.centerY 0149 radiusX: circleArc.radiusX; radiusY: circleArc.radiusY 0150 startAngle: -90 + 360 * Controller.percentage / 100 0151 sweepAngle: 360 * (1 - Controller.percentage/100) 0152 0153 Behavior on sweepAngle { 0154 NumberAnimation{ 0155 0156 duration: 1000 0157 } 0158 } 0159 } 0160 } 0161 } 0162 0163 ColumnLayout { 0164 anchors.fill: parent 0165 0166 Item { 0167 Layout.fillHeight: true 0168 } 0169 0170 QQC2.Label { 0171 Layout.alignment: Qt.AlignCenter 0172 0173 text: { 0174 switch (Controller.pomodoros) { 0175 case 1: 0176 return i18n("Lap 2") 0177 case 2: 0178 return i18n("Lap 3") 0179 case 3: 0180 return i18n("Lap 4") 0181 default: 0182 return i18n("Lap 1") 0183 } 0184 } 0185 font.pointSize: Math.floor(Kirigami.Theme.defaultFont.pointSize * 1.5) 0186 color: Kirigami.Theme.disabledTextColor 0187 } 0188 0189 QQC2.Label { 0190 id: timeText 0191 0192 Layout.alignment: Qt.AlignCenter 0193 0194 text: Controller.text 0195 color: Controller.onBreak ? Kirigami.Theme.textColor : Kirigami.Theme.linkColor 0196 font.pointSize: Kirigami.Theme.defaultFont.pointSize * 4 0197 font.bold: true 0198 font.family: "monospace" 0199 } 0200 0201 Item { 0202 Layout.fillHeight: true 0203 } 0204 } 0205 } 0206 0207 QQC2.Label { 0208 visible: Controller.onBreak 0209 0210 Layout.fillWidth: true 0211 Layout.maximumWidth: root.width - (Kirigami.Units.gridUnit * 4) 0212 Layout.preferredHeight: goalText.implicitHeight 0213 Layout.alignment: Qt.AlignCenter 0214 0215 text: i18n("Taking a Break") 0216 wrapMode: Text.Wrap 0217 horizontalAlignment: Qt.AlignHCenter 0218 font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize * 1.5) 0219 } 0220 0221 QQC2.TextField { 0222 id: goalText 0223 0224 visible: !Controller.onBreak 0225 0226 Layout.fillWidth: true 0227 Layout.maximumWidth: root.width - (Kirigami.Units.gridUnit * 4) 0228 Layout.alignment: Qt.AlignCenter 0229 0230 wrapMode: Text.Wrap 0231 horizontalAlignment: Qt.AlignHCenter 0232 maximumLength: 78 0233 font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize * 1.5) 0234 0235 onEditingFinished: { 0236 text = text.trim() 0237 goalText.focus = false 0238 } 0239 0240 background: Item { 0241 QQC2.Label { 0242 enabled: false 0243 visible: !goalText.text && !goalText.activeFocus 0244 0245 anchors.centerIn: parent 0246 0247 Layout.alignment: Qt.AlignCenter 0248 0249 text: i18n("I need to focus on…") 0250 horizontalAlignment: Qt.AlignHCenter 0251 0252 color: Kirigami.Theme.disabledTextColor 0253 } 0254 } 0255 } 0256 0257 Item { 0258 Layout.fillHeight: true 0259 } 0260 } 0261 } 0262 }