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 }