diff options
Diffstat (limited to 'src/config.cpp')
| -rw-r--r-- | src/config.cpp | 73 |
1 files changed, 63 insertions, 10 deletions
diff --git a/src/config.cpp b/src/config.cpp index 23c7364..d91259a 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -80,6 +80,18 @@ QString generatorTag(const QString &generator) return QString(); } +/// Whether a generator lists MESSAGES rather than threads. "sent" folds a +/// user's own message back into the conversation it answers, and "drafts" is +/// worse: a thread row stands for its first matched message, which for a draft +/// reply is the message being replied TO, so the draft itself is unreachable. +/// "trash" stays threaded, since a deleted message still belongs to its +/// conversation. Closed set, and the one place the three views are decided. +bool generatorIsFlat(const QString &generator) +{ + return generator == QStringLiteral("sent") + || generator == QStringLiteral("drafts"); +} + } // namespace QString Account::scopedQuery(const QString &query) const @@ -459,6 +471,17 @@ void Config::load(const QString &path) account.sent = settings.value(QStringLiteral("sent")).toString().trimmed(); + // Optional, and a STARTING value rather than a binding: the composer's + // switch keeps every signature reachable whichever account is + // selected. Left empty when absent, so the composer can tell "this + // account says nothing" from "this account says none" and fall through + // to [compose] signature itself; resolving that here would collapse + // the two. Trimmed for the same reason as sent, above: a trailing + // space would be carried into a filename lookup and match nothing, + // which is invisible in a config file. + account.signature = + settings.value(QStringLiteral("signature")).toString().trimmed(); + // Mandatory, unlike sent: Delete moves a file into this folder, so an // account without one cannot delete at all. Trimmed for the same // reason as sent, above. @@ -547,6 +570,31 @@ void Config::load(const QString &path) m_compose.sendHtml = settings.value(QStringLiteral("send_html"), true).toBool(); + // Trimmed for the same reason the account key is: it reaches a filename + // lookup, where a trailing space matches nothing invisibly. + m_compose.signature = + settings.value(QStringLiteral("signature")).toString().trimmed(); + + // The same shape as quote_position directly above: an absent key is + // silent and the struct default holds, but a PRESENT and malformed value + // is reported rather than silently accepted. value(key, default) alone + // would read "signature_position = abov" as above_quote. + const QString signaturePosition = + settings.value(QStringLiteral("signature_position"), + QStringLiteral("end")) + .toString().trimmed(); + if (signaturePosition.compare(QStringLiteral("above_quote"), + Qt::CaseInsensitive) == 0) { + m_compose.signaturePosition = Signatures::Position::AboveQuote; + } else if (signaturePosition.compare(QStringLiteral("end"), + Qt::CaseInsensitive) == 0) { + m_compose.signaturePosition = Signatures::Position::End; + } else { + addProblem(tr("[compose] signature_position '%1' is not recognised; " + "expected end or above_quote. Using end.") + .arg(signaturePosition)); + } + // Three numerics, all following the shape already established at // message_zoom, toolbar_icon_size, mark_read_delay_ms and // auto_sync_delay_ms elsewhere in this function: a QVariant, a checked @@ -802,14 +850,14 @@ void Config::loadSavedQueries(const QString &configPath, QSettings &settings) query.query = object.value(QStringLiteral("query")).toString(); query.account = object.value(QStringLiteral("account")).toString(); query.generated = object.value(QStringLiteral("generated")).toString(); - // A generator carries its own view mode, so "sent" is flat whether or - // not the file says so. Storing it as a plain field would let a + // A generator carries its own view mode, so a flat one is flat whether + // or not the file says so. Storing it as a plain field would let a // hand-edited or migrated-from-elsewhere row produce a THREADED sent // view, which folds every reply back into the conversation the user // sent one message into. The file may still set it for an ordinary // query. query.flat = object.value(QStringLiteral("flat")).toBool(false) - || query.generated == QStringLiteral("sent"); + || generatorIsFlat(query.generated); if (query.isGenerated() && !kQueryGenerators.contains(query.generated)) { @@ -869,7 +917,7 @@ bool Config::saveSavedQueries() const object.insert(QStringLiteral("account"), query.account); // Skipped when the generator already implies it, which loadSavedQueries // reapplies on the way back in. - if (query.flat && query.generated != QStringLiteral("sent")) + if (query.flat && !generatorIsFlat(query.generated)) object.insert(QStringLiteral("flat"), true); for (auto it = query.unknown.begin(); it != query.unknown.end(); ++it) object.insert(it.key(), it.value()); @@ -951,6 +999,9 @@ SavedQuery Config::builtinFilter(const QString &generator) SavedQuery filter; filter.generated = generator; + // One source for the view mode, shared with the saved-query round trip, so + // a branch below cannot disagree with what loadSavedQueries reapplies. + filter.flat = generatorIsFlat(generator); // Translated, because these are the labels on the buttons. The GENERATOR // name is not: it is stored in queries.json and matched against a closed @@ -969,16 +1020,18 @@ SavedQuery Config::builtinFilter(const QString &generator) filter.name = tr("Important"); } else if (generator == QStringLiteral("sent")) { filter.name = tr("Sent"); - // Messages rather than threads, and the only filter that sets this. A - // thread would fold the user's sent message back into the conversation - // it belongs to, which is item 63's finding. - filter.flat = true; + // Flat, per generatorIsFlat(): a thread would fold the user's sent + // message back into the conversation it belongs to, item 63's finding. } else if (generator == QStringLiteral("drafts")) { // The LABEL is translated; the generator stays `drafts`, which is what // queries.json stores and what a closed set is matched against. filter.name = tr("Drafts"); - // NOT flat, like Trash and unlike Sent: a draft reply belongs with the - // conversation it answers. + // Flat, per generatorIsFlat(). Item 138 chose threaded, reasoning that + // a draft reply belongs with the conversation it answers; item 159 + // reversed it on what that cost. A thread row stands for its first + // MATCHED message, which for a draft reply is the message being + // replied TO, so the draft itself had no row of its own and + // double-clicking the conversation opened nothing. } else if (generator == QStringLiteral("trash")) { filter.name = tr("Trash"); // NOT flat, unlike Sent. A deleted message still belongs to its |
