feat: comprehensive Wino Mail updates

- ReaderView: complete rewrite with CSS styling, headers, attachments, zoom, find, dark mode, image blocking
- Categories: DAO + UI tree widget with colors, nested categories, assignment
- Rules engine: DAO + evaluation + actions (move, mark read, flag, delete, category, forward)
- Templates: DAO + editor + manager with variables support
- Signatures: DAO + manager + auto-per-account + manual selector in compose
- ComposeView: signature combo, template selector, auto-signature on new email
- MainWindow: frameless with rounded corners, 1px border, resize from edges, no status bar
- Database: new tables (Category, MailCategory, Rule, Template, Signature) with indexes
This commit is contained in:
2026-08-23 14:49:58 +02:00
parent 5fcedfa129
commit 0bb8738607
7399 changed files with 44711 additions and 209 deletions
+52 -3
View File
@@ -9,6 +9,11 @@
#include <QProgressBar>
#include <QToolBar>
#include <QAction>
#include <QToolButton>
#include <QLabel>
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QWindowStateChangeEvent>
#include "ui/readerview.h"
#include "ui/maillistview.h"
@@ -18,6 +23,8 @@
#include "ui/calendarview.h"
#include "ui/models/FolderListModel.h"
#include "ui/models/EmailListModel.h"
#include "ui/categorytreewidget.h"
#include "ui/templatesmanagerdialog.h"
#include "services/accountservice.h"
#include "services/mailservice.h"
@@ -28,12 +35,22 @@ public:
explicit MainMainWindow(QWidget *parent = nullptr);
~MainMainWindow() override = default;
protected:
// Frameless window handling
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
void changeEvent(QEvent *event) override;
private slots:
void onNavChanged(int index);
void onFolderSelected(const QModelIndex &index);
void onEmailSelected(int mailId);
void onComposeRequested();
void onReaderReplyRequested(const MailItem *item);
void onReaderReplyRequested(int mailId);
void onReaderForwardRequested(int mailId);
void onReaderDeleteRequested(int mailId);
void onNewMessage();
void openMailInIndependentWindow(int mailId);
void onAddAccountRequested();
@@ -41,6 +58,20 @@ private slots:
void onAccountDeleteRequested(int accountId);
void onProgressChanged(int percent);
void onStatusMessage(const QString &msg);
void onSyncRequested();
void onSettingsRequested();
void updateMaximizeButtonIcon();
void onCategorySelected(const Category& cat);
void onCategoryDoubleClicked(const Category& cat);
void onAssignCategoryRequested(qint64 mailId, qint64 categoryId);
void onCategoryCreated(const Category& cat);
void onCategoryEdited(const Category& cat);
void onCategoryDeleted(qint64 categoryId);
void onRulesChanged();
void onRunRulesOnFolder();
void onRunRulesOnSelected();
void showRulesManager();
void showTemplatesManager();
// Slots for embedded compose view
void onEmbeddedSendRequested(const QString &to, const QString &cc, const QString &bcc,
@@ -55,8 +86,12 @@ private:
void setupSidebar();
void setupMailPage();
void connectModels();
void createToolBar();
void createTitleBar();
void switchToPage(int pageIndex);
QWidget *createTitleButton(const QString &iconName, const QString &tooltip, std::function<void()> slot);
QWidget *createWindowControlButton(const QString &iconName, const QString &tooltip, std::function<void()> slot);
void updateCategoryTreeForAccount(qint64 accountId);
void assignCategoryToSelectedMails(qint64 categoryId);
// Navigation
QListWidget *m_sidebar;
@@ -74,6 +109,7 @@ private:
QWidget *m_mailPage;
QSplitter *m_folderSplitter;
QTreeView *m_folderTree;
CategoryTreeWidget *m_categoryTree;
MailListView *m_mailListView;
ReaderView *m_emailViewer;
QStackedWidget *m_viewerStack;
@@ -92,7 +128,20 @@ private:
AccountService *m_accountService = nullptr;
MailService *m_mailService = nullptr;
QToolBar *m_toolBar;
// Frameless title bar
QWidget *m_titleBar;
QToolButton *m_maximizeButton;
QToolButton *m_closeButton;
QPoint m_dragPos;
bool m_dragging = false;
Qt::WindowStates m_lastWindowState;
// Resize handling (item 3)
QPoint m_resizeStartPos;
QRect m_resizeStartGeom;
bool m_resizing = false;
Qt::Edges m_resizeEdges = Qt::Edges();
int m_currentFolderId;
int m_currentMailId;