aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/SaveBar.qml
blob: 147d00bab78f750dd6a46fa12e16c38a5b072871 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

import QtQuick

// Save and Discard for a settings page that edits a draft: its fields change
// the draft, and nothing reaches the file until Save. Sits in the Page header
// through Page.actions, the one place every settings page commits from. note
// says what is wrong when Save is held back; the labels follow what the page
// does (Apply and Reset for a staged wallpaper or cursor, Save + Restart for
// a daemon that rereads only at start); busy shows while a save runs.
//
// The outcome of a save is reported here too, not at the foot of the page:
// notice is what a finished save says ("saved"), shown once the page is
// clean, in noticeColor; error is a save refused or failed, which leaves the
// draft dirty, so it is shown over "unsaved changes", in red.
Row {
    id: bar
    property bool dirty: false
    property bool valid: true
    property string note: ""
    property string notice: ""
    property color noticeColor: Theme.green
    property string error: ""
    property string saveText: "Save"
    property string discardText: "Discard"
    property bool busy: false
    signal save
    signal discard
    spacing: 8

    Text {
        anchors.verticalCenter: parent.verticalCenter
        visible: bar.error !== "" || bar.dirty || bar.notice !== ""
        // ponytail: a long message elides; the header has one line.
        width: Math.min(implicitWidth, 420)
        elide: Text.ElideRight
        text: bar.error !== "" ? bar.error
            : !bar.dirty ? bar.notice
            : !bar.valid ? (bar.note || "fix the fields marked red") : "unsaved changes"
        color: bar.error !== "" ? Theme.red
             : !bar.dirty ? bar.noticeColor
             : bar.valid ? Theme.yellow : Theme.red
        font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 }
    }
    Button {
        text: bar.discardText
        enabled: bar.dirty && !bar.busy
        onClicked: bar.discard()
    }
    Button {
        text: bar.busy ? bar.saveText + "…" : bar.saveText
        enabled: bar.dirty && bar.valid && !bar.busy
        onClicked: bar.save()
    }
}