aboutsummaryrefslogtreecommitdiffstats
path: root/src/m_email/EMailViewLayout.cpp
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2026-09-29 19:51:52 +0200
committersaturneric <[email protected]>2026-09-29 19:51:52 +0200
commit391168fb8e5f353a318026278c890981c440ad5d (patch)
tree62edd8da294dceefd1f205990f83e70e309329db /src/m_email/EMailViewLayout.cpp
parentstyle(i18n): normalize instant messaging catalogs (diff)
downloadmodules-391168fb8e5f353a318026278c890981c440ad5d.tar.gz
modules-391168fb8e5f353a318026278c890981c440ad5d.zip
feat(email): redesign action and attachment bars
- centralize message commands as reusable actions with shared shortcuts - add compact attachment summaries, menus, and expandable lists - move secondary commands into More and show read-only status separately - centralize action, attachment, security, and surface layout decisions - enable compact Status Panel behavior for the email editor
Diffstat (limited to 'src/m_email/EMailViewLayout.cpp')
-rw-r--r--src/m_email/EMailViewLayout.cpp124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/m_email/EMailViewLayout.cpp b/src/m_email/EMailViewLayout.cpp
index 552d1d1..82c7b4c 100644
--- a/src/m_email/EMailViewLayout.cpp
+++ b/src/m_email/EMailViewLayout.cpp
@@ -28,8 +28,11 @@
#include "EMailViewLayout.h"
+#include <QCoreApplication>
#include <algorithm>
+#include "EMailModel.h"
+
auto EMailClampDetailsSize(int width, int height) -> std::pair<int, int> {
const auto wanted_width = width > 0 ? width : kEMailDetailsDefaultWidth;
const auto wanted_height = height > 0 ? height : kEMailDetailsDefaultHeight;
@@ -58,3 +61,124 @@ auto EMailNeedsSecurityRefresh(bool details_visible, bool security_current)
-> bool {
return details_visible && security_current;
}
+
+auto EMailAttachmentBar(const EMailAttachmentBarInput& in)
+ -> EMailAttachmentBarState {
+ EMailAttachmentBarState s;
+ const bool any = in.count > 0;
+
+ s.section_visible = any;
+ s.toggle_visible = any;
+ s.list_visible = any && in.expanded;
+
+ const auto targets = in.count == 1 ? 1 : (s.list_visible ? in.selected : 0);
+
+ s.show_open = any;
+ s.show_save = any;
+ s.show_save_all = any;
+ // Changing the parts is a mode, not a selection: a read-only message has
+ // no Attach or Remove to offer, not even greyed out.
+ s.show_attach = in.editable;
+ s.show_remove = in.editable && any;
+
+ s.can_open = targets == 1;
+ s.can_save = targets > 0;
+ s.can_save_all = any;
+ s.can_attach = in.editable;
+ s.can_remove = in.editable && targets > 0;
+ return s;
+}
+
+auto EMailActionBar(const EMailActionBarInput& in) -> EMailActionBarState {
+ EMailActionBarState s;
+ const bool received = in.is_message && !in.draft;
+ s.reply_visible = received;
+ s.send_visible = !received;
+ s.attach_visible = !received && in.editable;
+ s.attachments_menu_visible = in.attachments > 0;
+
+ s.more_details = true;
+ s.more_reply = in.is_message && in.draft;
+ s.more_send = received;
+ // Offered only where it changes something, and always while it is on so it
+ // can be turned off again.
+ s.more_read_only = received && (in.read_only_offered || in.read_only);
+ s.read_only_label = in.read_only;
+ return s;
+}
+
+auto EMailSecurityStatus(EMailBadgeState badge, bool encrypted)
+ -> EMailStatusLabel {
+ // Translated under the view's own context, spelled out at every call so
+ // lupdate sees each one: these are the view's strings, moved here only so
+ // they can be checked.
+ const auto warning = QStringLiteral(":/icons/warning.png");
+ const auto signature = QStringLiteral(":/icons/signature.png");
+
+ switch (badge) {
+ case EMailBadgeState::kENCRYPTED_ONLY:
+ return {QCoreApplication::translate("EMailPageView", "Encrypted"),
+ QStringLiteral(":/icons/lock.png")};
+ case EMailBadgeState::kSIGNED_UNVERIFIED:
+ // What is actually known at this point: the message CARRIES a
+ // signature. Whether it is any good is a separate question that has
+ // not been asked yet, and the wording must not answer it.
+ return {encrypted
+ ? QCoreApplication::translate(
+ "EMailPageView", "Encrypted, signature not checked")
+ : QCoreApplication::translate("EMailPageView",
+ "Signature not checked"),
+ signature};
+ case EMailBadgeState::kSIGNED_GOOD:
+ return {encrypted ? QCoreApplication::translate(
+ "EMailPageView", "Encrypted, signature verified")
+ : QCoreApplication::translate("EMailPageView",
+ "Signature verified"),
+ signature};
+ case EMailBadgeState::kSIGNED_MISMATCH:
+ return {QCoreApplication::translate("EMailPageView",
+ "Signed by a different address"),
+ warning};
+ case EMailBadgeState::kSIGNED_EXPIRED:
+ return {QCoreApplication::translate("EMailPageView",
+ "Signature or key expired"),
+ warning};
+ case EMailBadgeState::kSIGNED_UNKNOWN_KEY:
+ return {QCoreApplication::translate("EMailPageView",
+ "Signed by an unknown key"),
+ warning};
+ case EMailBadgeState::kSIGNED_BAD:
+ return {QCoreApplication::translate("EMailPageView", "Bad signature"),
+ warning};
+ case EMailBadgeState::kSIGNED_ERROR:
+ // Not the same claim as a bad signature, and not the same as one nobody
+ // has looked at. The check was made and could not produce an answer,
+ // which is the one outcome trying again might change.
+ return {QCoreApplication::translate("EMailPageView",
+ "Signature could not be checked"),
+ warning};
+ case EMailBadgeState::kMALFORMED:
+ return {QCoreApplication::translate("EMailPageView",
+ "Malformed OpenPGP structure"),
+ warning};
+ case EMailBadgeState::kNOT_PROTECTED:
+ // Stated plainly and quietly. An unprotected message is the ordinary
+ // case, not a fault, and painting it as a warning would train the user
+ // to ignore the one that matters.
+ break;
+ }
+ return {
+ QCoreApplication::translate("EMailPageView", "Not signed or encrypted"),
+ QStringLiteral(":/icons/email.png")};
+}
+
+auto EMailAttachmentTargets(int count, const QList<int>& selected_rows,
+ bool list_visible) -> QList<int> {
+ if (count == 1) return {0};
+ if (!list_visible) return {};
+ QList<int> rows;
+ for (const auto row : selected_rows) {
+ if (row >= 0 && row < count && !rows.contains(row)) rows.append(row);
+ }
+ return rows;
+}