summaryrefslogtreecommitdiffstats
path: root/src/composewindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/composewindow.cpp')
-rw-r--r--src/composewindow.cpp136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/composewindow.cpp b/src/composewindow.cpp
index a64736f..8236d79 100644
--- a/src/composewindow.cpp
+++ b/src/composewindow.cpp
@@ -25,6 +25,7 @@
#include "mimeparser.h"
#include "messagesender.h"
#include "senddialog.h"
+#include "signatures.h"
#include <QAction>
#include <QCheckBox>
@@ -40,9 +41,11 @@
#include <QLabel>
#include <QLineEdit>
#include <QListWidget>
+#include <QMenu>
#include <QMessageBox>
#include <QPlainTextEdit>
#include <QPushButton>
+#include <QStandardPaths>
#include <QTextCursor>
#include <QTimer>
#include <QToolBar>
@@ -128,6 +131,7 @@ ComposeWindow::ComposeWindow(const ComposeContext &context,
buildFormatToolbar();
seedFields();
seedBody();
+ seedSignature();
// AFTER buildUi(), which creates m_banner, and BEFORE
// refreshAttachmentList(), which renders m_attachments: extraction appends
@@ -536,6 +540,29 @@ void ComposeWindow::buildFormatToolbar()
m_sendHtml->setIcon(htmlIcon);
m_formatToolbar->addWidget(m_sendHtml);
+ // The signature switch rides at the right end with Attach and the HTML
+ // toggle: item 142 put the controls OF THE EDITOR on this side, as against
+ // the formatting buttons on the left, and choosing a signature is one of
+ // those.
+ //
+ // A QToolButton with a menu rather than a QComboBox, matching the bar's
+ // other controls; a combo would read as a different class of thing. Not
+ // registered in KeyMap: it is parented to this window, exactly as the
+ // formatting actions are, so its scope is the composer and item 132's
+ // reachability rule does not apply.
+ m_signatureSwitch = new QToolButton(m_formatToolbar);
+ m_signatureSwitch->setObjectName(QStringLiteral("signatureSwitch"));
+ m_signatureSwitch->setText(tr("Signature"));
+ m_signatureSwitch->setToolTip(
+ tr("Chooses the signature added to this message."));
+ m_signatureSwitch->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ m_signatureSwitch->setPopupMode(QToolButton::InstantPopup);
+ const QIcon signatureIcon = QIcon::fromTheme(QStringLiteral("insert-text"));
+ if (!signatureIcon.isNull())
+ m_signatureSwitch->setIcon(signatureIcon);
+ m_signatureSwitch->setMenu(new QMenu(m_signatureSwitch));
+ m_formatToolbar->addWidget(m_signatureSwitch);
+
// Send is NOT on this row: it is the terminal action, and it lives on the
// button beside the headers. The QAction survives because it carries the
// shortcut and is what the button triggers.
@@ -664,6 +691,114 @@ void ComposeWindow::seedBody()
m_body->document()->clearUndoRedoStacks();
}
+void ComposeWindow::setSignatureDir(const QString &dir)
+{
+ m_signatureDir = dir;
+}
+
+QStringList ComposeWindow::knownSignatures() const
+{
+ QStringList known;
+ const QStringList names = Signatures::names(m_signatureDir);
+ known.reserve(names.size());
+ for (const QString &name : names)
+ known.append(Signatures::text(m_signatureDir, name));
+ return known;
+}
+
+QString ComposeWindow::seededSignatureName() const
+{
+ // The account SEEDS, it does not bind: this is a starting value, and the
+ // switch keeps every signature reachable whichever account is selected.
+ const Account account = m_config.account(m_context.accountKey);
+ if (!account.signature.isEmpty())
+ return account.signature;
+ return m_config.compose().signature;
+}
+
+void ComposeWindow::applySignature(const QString &name)
+{
+ const QString text =
+ name.isEmpty() ? QString() : Signatures::text(m_signatureDir, name);
+
+ // A QTextCursor replacement rather than setPlainText(), for the reason
+ // recorded at applyEdit(): setPlainText() destroys the document's undo
+ // stack, so a switch would make everything typed before it unrecoverable.
+ const QString replaced = Signatures::replace(
+ m_body->toPlainText(), text, knownSignatures(),
+ m_config.compose().signaturePosition);
+
+ QTextCursor cursor(m_body->document());
+ cursor.select(QTextCursor::Document);
+ cursor.insertText(replaced);
+
+ m_signatureName = name;
+
+ for (QAction *action : m_signatureSwitch->menu()->actions())
+ action->setChecked(action->data().toString() == name);
+}
+
+void ComposeWindow::seedSignature()
+{
+ if (m_signatureDir.isEmpty()) {
+ const QString base =
+ QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
+ m_signatureDir = base + QStringLiteral("/qtmaildir/signatures");
+ }
+
+ QMenu *menu = m_signatureSwitch->menu();
+ menu->clear();
+
+ auto *none = menu->addAction(tr("None"));
+ none->setCheckable(true);
+ none->setData(QString());
+ connect(none, &QAction::triggered, this, [this]() {
+ m_signatureChosen = true;
+ applySignature(QString());
+ markDirty();
+ });
+
+ const QStringList names = Signatures::names(m_signatureDir);
+ for (const QString &name : names) {
+ auto *action = menu->addAction(name);
+ action->setCheckable(true);
+ action->setData(name);
+ connect(action, &QAction::triggered, this, [this, name]() {
+ m_signatureChosen = true;
+ applySignature(name);
+ markDirty();
+ });
+ }
+
+ // A resumed draft is the message ITSELF and already carries whatever
+ // signature it was saved with, exactly as seedBody() takes its body
+ // verbatim. Seeding again would append a second one.
+ if (m_context.kind == ComposeContext::Kind::Draft) {
+ none->setChecked(true);
+ return;
+ }
+
+ const QString seeded = seededSignatureName();
+ if (seeded.isEmpty()) {
+ none->setChecked(true);
+ return;
+ }
+ if (!names.contains(seeded)) {
+ // Reported by Config as a problem; the composer still opens, with no
+ // signature, and the switch still works.
+ none->setChecked(true);
+ return;
+ }
+
+ applySignature(seeded);
+
+ // The seeded signature is not an edit the user made, so it must not
+ // survive as an undo step: one Ctrl+Z on a fresh composer would otherwise
+ // wipe content they never typed. Same reason seedBody() clears after the
+ // quote.
+ m_body->document()->clearUndoRedoStacks();
+}
+
void ComposeWindow::refreshAttachmentList()
{
m_attachmentList->clear();
@@ -897,6 +1032,7 @@ void ComposeWindow::setInputsEnabled(bool enabled)
m_from->setEnabled(enabled);
m_body->setReadOnly(!enabled);
m_sendHtml->setEnabled(enabled);
+ m_signatureSwitch->setEnabled(enabled);
m_attachmentList->setEnabled(enabled);
m_formatToolbar->setEnabled(enabled);