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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/*
* 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 "config.h"
#include <QFileInfo>
#include <QSettings>
#include <QStandardPaths>
QString Account::scopedQuery(const QString &query) const
{
const QString prefix = QStringLiteral("path:\"%1/**\"").arg(maildir);
if (query.trimmed().isEmpty())
return prefix;
return QStringLiteral("%1 and (%2)").arg(prefix, query);
}
QString Config::defaultPath()
{
const QString base =
QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
return base + QStringLiteral("/qtmaildir/qtmaildir.conf");
}
void Config::addProblem(const QString &message)
{
m_warnings.append(message);
m_problems.append(message);
}
void Config::addNotice(const QString &message)
{
m_warnings.append(message);
}
void Config::load(const QString &path)
{
QSettings settings(path, QSettings::IniFormat);
m_notmuchConfig =
settings.value(QStringLiteral("general/notmuch_config")).toString();
m_syncCommand = settings.value(QStringLiteral("sync/command")).toString();
if (m_syncCommand.isEmpty()) {
// Not a problem: sync is optional, and nothing the user asked for is
// being ignored. A modal here would fire on every launch.
addNotice(QStringLiteral(
"No sync command configured ([sync] command); syncing is disabled."));
} else if (!QFileInfo::exists(m_syncCommand.split(QLatin1Char(' ')).first())) {
addProblem(
QStringLiteral("Sync command '%1' does not exist; syncing is disabled.")
.arg(m_syncCommand));
m_syncCommand.clear();
}
// Account groups are written as [account.work], [account.personal], etc.
// A dot, not a slash, separates the "account" namespace from the key:
// QSettings' INI backend treats "/" as its own hierarchical group
// separator, so a literal "[account/work]" section header would be
// parsed as a *nested* group "work" inside a group "account" (and trips
// a QSettings::FormatError besides), not as a single flat group named
// "account/work". "." carries no such meaning to QSettings, so
// childGroups() here returns "account.work" and "account.personal" as
// plain top-level entries and status() stays NoError.
for (const QString &group : settings.childGroups()) {
if (!group.startsWith(QStringLiteral("account.")))
continue;
Account account;
account.key = group.mid(QStringLiteral("account.").size());
settings.beginGroup(group);
account.name = settings.value(QStringLiteral("name")).toString();
account.address = settings.value(QStringLiteral("address")).toString();
account.maildir = settings.value(QStringLiteral("maildir")).toString();
account.drafts = settings.value(QStringLiteral("drafts")).toString();
settings.endGroup();
if (!account.isValid()) {
addProblem(
QStringLiteral("Account '%1' has no maildir; ignoring it.")
.arg(account.key));
continue;
}
m_accounts.append(account);
}
settings.beginGroup(QStringLiteral("queries"));
// QSettings::childKeys() returns keys in alphabetical order, not file
// order, so the saved-query button order in the UI is alphabetical too.
// A hand-rolled parser would be needed to preserve file order; not
// needed in v1.
for (const QString &name : settings.childKeys())
m_savedQueries.append({ name, settings.value(name).toString() });
settings.endGroup();
}
Account Config::account(const QString &key) const
{
for (const Account &a : m_accounts) {
if (a.key == key)
return a;
}
return {};
}
|