aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.cpp15
-rw-r--r--tests/test_config.cpp56
-rw-r--r--translations/qtmaildir_it_IT.ts10
3 files changed, 67 insertions, 14 deletions
diff --git a/src/config.cpp b/src/config.cpp
index d56099a..8294e4b 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -473,6 +473,21 @@ void Config::load(const QString &path)
.arg(account.key));
continue;
}
+
+ // Mandatory, unlike sent: Delete moves a file into this folder, so an
+ // account without one cannot delete at all. Reported rather than
+ // silently disabled, so the user finds out from a warning rather than
+ // from a Delete that quietly does nothing. The account still loads;
+ // only Delete is unusable, which does not warrant losing the rest of
+ // the account's mail.
+ if (account.trash.isEmpty()) {
+ addProblem(
+ tr("Account '%1' has no trash folder configured; add a "
+ "'trash' key to its section. Delete will not work for "
+ "this account until it does.")
+ .arg(account.key));
+ }
+
m_accounts.append(account);
}
diff --git a/tests/test_config.cpp b/tests/test_config.cpp
index 98743f5..10dcf68 100644
--- a/tests/test_config.cpp
+++ b/tests/test_config.cpp
@@ -118,6 +118,7 @@ private slots:
void allDraftsQueryIsIndependentOfSent();
void anAccountCarriesItsTrashFolder();
void aBracketedTrashFolderIsQuoted();
+ void anAccountWithoutATrashFolderWarns();
};
static QString writeIni(const QTemporaryDir &dir, const QString &body)
@@ -430,7 +431,8 @@ void TestConfig::absentSyncCommandIsNoticeNotProblem()
QTemporaryDir dir;
const QString path = writeIni(dir, QStringLiteral(
"[account.work]\n"
- "maildir=work-mail\n"));
+ "maildir=work-mail\n"
+ "trash=Trash\n"));
Config config;
config.load(path);
@@ -450,7 +452,8 @@ void TestConfig::brokenSyncCommandIsAProblem()
"command=/nonexistent/qtmaildir-test/mailsync.sh\n"
"\n"
"[account.work]\n"
- "maildir=work-mail\n"));
+ "maildir=work-mail\n"
+ "trash=Trash\n"));
Config config;
config.load(path);
@@ -485,7 +488,8 @@ void TestConfig::validConfigHasNoProblems()
"\n"
"[account.work]\n"
"maildir=work-mail\n"
- "address=user@example.org\n"));
+ "address=user@example.org\n"
+ "trash=Trash\n"));
Config config;
config.load(path);
@@ -905,7 +909,8 @@ void TestConfig::sentQueryIsEmptyWithoutTheKey()
Config config;
config.load(writeIni(dir, QStringLiteral(
"[account.provider-c]\n"
- "maildir = provider-c\n")));
+ "maildir = provider-c\n"
+ "trash = Trash\n")));
QCOMPARE(config.accounts().size(), 1);
QVERIFY(config.accounts().at(0).sentQuery().isEmpty());
@@ -983,6 +988,27 @@ void TestConfig::aBracketedTrashFolderIsQuoted()
QStringLiteral("path:\"provider-a/[Provider]/Cestino/**\""));
}
+void TestConfig::anAccountWithoutATrashFolderWarns()
+{
+ QTemporaryDir dir;
+ Config config;
+ config.load(writeIni(dir, QStringLiteral(
+ "[account.work]\n"
+ "maildir=work\n")));
+
+ // The account still loads. A missing trash folder disables Delete, it does
+ // not invalidate the account: the user can still read mail.
+ QVERIFY(config.account(QStringLiteral("work")).isValid());
+
+ // Names the account and the key, so the warning is actionable. A warning
+ // the user cannot act on teaches them to ignore warnings, which item 83
+ // recorded the hard way.
+ QVERIFY(!config.problems().isEmpty());
+ const QString joined = config.warnings().join(QLatin1Char('\n'));
+ QVERIFY(joined.contains(QStringLiteral("work")));
+ QVERIFY(joined.contains(QStringLiteral("trash")));
+}
+
void TestConfig::sentQueryComposesWithScopedQuery()
{
// A Sent view under one account must not show another account's sent mail.
@@ -1103,9 +1129,11 @@ void TestConfig::theStartupAccountIsReadAndValidated()
"\n"
"[account.work]\n"
"maildir=work\n"
+ "trash=Trash\n"
"\n"
"[account.personal]\n"
- "maildir=personal\n")));
+ "maildir=personal\n"
+ "trash=Trash\n")));
QCOMPARE(config.startupAccount(), QStringLiteral("work"));
QVERIFY(config.problems().isEmpty());
@@ -1130,7 +1158,8 @@ void TestConfig::theStartupAccountIsReadAndValidated()
"startup_account=nosuchaccount\n"
"\n"
"[account.work]\n"
- "maildir=work\n")));
+ "maildir=work\n"
+ "trash=Trash\n")));
QVERIFY2(wrong.startupAccount().isEmpty(),
"an unknown startup account was passed through rather than "
"falling back to All accounts");
@@ -1155,7 +1184,8 @@ void TestConfig::theStartupAccountTakesTheKeyNotTheSyncChannel()
"\n"
"[account.provider-work.mailbox]\n"
"maildir=provider-work.mailbox\n"
- "channel=provider-workmailbox\n")));
+ "channel=provider-workmailbox\n"
+ "trash=Trash\n")));
QCOMPARE(config.accounts().size(), 1);
QCOMPARE(config.accounts().constFirst().key,
@@ -1177,7 +1207,8 @@ void TestConfig::theStartupAccountTakesTheKeyNotTheSyncChannel()
"\n"
"[account.provider-work.mailbox]\n"
"maildir=provider-work.mailbox\n"
- "channel=provider-workmailbox\n")));
+ "channel=provider-workmailbox\n"
+ "trash=Trash\n")));
QVERIFY2(byChannel.startupAccount().isEmpty(),
"the sync channel was accepted as an account key");
@@ -1261,7 +1292,8 @@ void TestConfig::theStartupQuerySurvivesATranslatedFilterName()
"\n"
"[account.work]\n"
"maildir=work\n"
- "sent=Sent\n")));
+ "sent=Sent\n"
+ "trash=Trash\n")));
QVERIFY2(!config.savedQueries().isEmpty(),
"queries.json did not load, so the warning path is unreachable");
@@ -1286,7 +1318,8 @@ void TestConfig::theStartupQuerySurvivesATranslatedFilterName()
"\n"
"[account.work]\n"
"maildir=work\n"
- "sent=Sent\n")));
+ "sent=Sent\n"
+ "trash=Trash\n")));
QVERIFY(!byLabel.savedQueries().isEmpty());
QCOMPARE(byLabel.startupSavedQuery().generated, QStringLiteral("inbox"));
QVERIFY(byLabel.problems().isEmpty());
@@ -1513,7 +1546,8 @@ void TestConfig::draftsQueryIsEmptyWithoutTheKey()
Config config;
config.load(writeIni(dir, QStringLiteral(
"[account.provider-c]\n"
- "maildir = provider-c\n")));
+ "maildir = provider-c\n"
+ "trash = Trash\n")));
QCOMPARE(config.accounts().size(), 1);
QVERIFY(config.accounts().at(0).draftsQuery().isEmpty());
diff --git a/translations/qtmaildir_it_IT.ts b/translations/qtmaildir_it_IT.ts
index 036ce4b..fd51547 100644
--- a/translations/qtmaildir_it_IT.ts
+++ b/translations/qtmaildir_it_IT.ts
@@ -44,6 +44,10 @@
<translation>[completion] extra_mimetypes: la voce &apos;%1&apos; non ha un mimetype; verrà ignorata.</translation>
</message>
<message>
+ <source>Account &apos;%1&apos; has no trash folder configured; add a &apos;trash&apos; key to its section. Delete will not work for this account until it does.</source>
+ <translation>L&apos;account &apos;%1&apos; non ha un cestino configurato; aggiungere una chiave &apos;trash&apos; alla sua sezione. L&apos;eliminazione non funzionerà per questo account finché non verrà fatto.</translation>
+ </message>
+ <message>
<source>Startup account &apos;%1&apos; is not a configured account; starting on all accounts.</source>
<translation>L&apos;account iniziale &apos;%1&apos; non è un account configurato; si parte da tutti gli account.</translation>
</message>
@@ -280,7 +284,7 @@
</message>
<message>
<source>Add or remove the important tag</source>
- <translation>Aggiunge o rimuove l'etichetta importante</translation>
+ <translation>Aggiunge o rimuove l&apos;etichetta importante</translation>
</message>
<message>
<source>Unmark important</source>
@@ -340,7 +344,7 @@
</message>
<message>
<source>Add or remove the deleted tag on whole threads</source>
- <translation>Aggiunge o rimuove l'etichetta eliminato su intere conversazioni</translation>
+ <translation>Aggiunge o rimuove l&apos;etichetta eliminato su intere conversazioni</translation>
</message>
<message>
<source>Undelete thread</source>
@@ -364,7 +368,7 @@
</message>
<message>
<source>Toggle the unread tag on whole threads</source>
- <translation>Inverte l'etichetta non letto su intere conversazioni</translation>
+ <translation>Inverte l&apos;etichetta non letto su intere conversazioni</translation>
</message>
<message>
<source>Mark thread read</source>