summaryrefslogtreecommitdiffstats
path: root/src/calendarsync.cpp
blob: 38d0c07ec4f9bba50af71597eba674ede86725e3 (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
65
66
67
68
69
70
71
72
73
74
75
/*
 * qtmaildir - a Qt6 mail client for notmuch-indexed Maildirs
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "calendarsync.h"

CalendarSync::CalendarSync(const QString &command, int delayMs, QObject *parent)
    : QObject(parent), m_command(command)
{
    m_timer.setSingleShot(true);
    m_timer.setInterval(delayMs);
    connect(&m_timer, &QTimer::timeout, this, &CalendarSync::run);
    m_process.setProcessChannelMode(QProcess::MergedChannels);
    connect(&m_process, &QProcess::readyRead, this,
            [this]() { m_output += m_process.readAll(); });
    connect(&m_process, &QProcess::finished, this,
            [this](int code, QProcess::ExitStatus status) {
        emit finished(status == QProcess::NormalExit && code == 0,
                      QString::fromLocal8Bit(m_output));
        if (m_again) {
            m_again = false;
            m_timer.start();
        }
    });
    connect(&m_process, &QProcess::errorOccurred, this,
            [this](QProcess::ProcessError error) {
        if (error == QProcess::FailedToStart) {
            // finished() never fires for a failed start, so the queued-run flag
            // would otherwise leak into the next successful run.
            m_again = false;
            emit finished(false, m_process.errorString());
        }
    });
}

void CalendarSync::schedule()
{
    if (m_command.isEmpty())
        return;
    if (isRunning())
        m_again = true;
    else
        m_timer.start();  // restarting is the debounce
}

bool CalendarSync::isRunning() const
{
    return m_process.state() != QProcess::NotRunning;
}

void CalendarSync::run()
{
    // splitCommand, not a shell: quoting works and nothing is interpreted.
    QStringList parts = QProcess::splitCommand(m_command);
    if (parts.isEmpty())
        return;
    const QString program = parts.takeFirst();
    m_output.clear();
    emit started();
    m_process.start(program, parts);
}