2026-06-17 22:44:27 +02:00
|
|
|
#include "ui/maillistview.h"
|
|
|
|
|
#include <QDateTime>
|
|
|
|
|
|
|
|
|
|
MailListView::MailListView(QWidget *parent) : QWidget(parent) {
|
|
|
|
|
setupUI();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MailListView::setupUI() {
|
|
|
|
|
QVBoxLayout *layout = new QVBoxLayout(this);
|
|
|
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
layout->setSpacing(0);
|
|
|
|
|
|
|
|
|
|
// Header bar
|
|
|
|
|
QWidget *headerBar = new QWidget();
|
|
|
|
|
headerBar->setFixedHeight(48);
|
|
|
|
|
headerBar->setStyleSheet("background-color: #1976D2;");
|
|
|
|
|
QHBoxLayout *headerLayout = new QHBoxLayout(headerBar);
|
|
|
|
|
headerLayout->setContentsMargins(16, 0, 10, 0);
|
|
|
|
|
|
|
|
|
|
QLabel *title = new QLabel("Wino Mail");
|
|
|
|
|
title->setStyleSheet("color: white; font-size: 18px; font-weight: bold;");
|
|
|
|
|
headerLayout->addWidget(title);
|
|
|
|
|
headerLayout->addStretch();
|
|
|
|
|
|
|
|
|
|
m_composeButton = new QPushButton("✎");
|
|
|
|
|
m_composeButton->setFixedSize(36, 36);
|
|
|
|
|
m_composeButton->setStyleSheet(
|
|
|
|
|
"QPushButton { background-color: #e0e0e0; border-radius: 4px; font-size: 18px; color: #333; }"
|
|
|
|
|
"QPushButton:hover { background-color: #d0d0d0; }"
|
|
|
|
|
);
|
|
|
|
|
headerLayout->addWidget(m_composeButton);
|
|
|
|
|
connect(m_composeButton, &QPushButton::clicked, this, &MailListView::composeRequested);
|
|
|
|
|
|
|
|
|
|
layout->addWidget(headerBar);
|
|
|
|
|
|
2026-08-23 14:49:58 +02:00
|
|
|
// Search bar
|
|
|
|
|
QWidget *searchBar = new QWidget();
|
|
|
|
|
searchBar->setFixedHeight(44);
|
|
|
|
|
searchBar->setStyleSheet("background-color: #f5f5f7; border-bottom: 1px solid #d1d1d6;");
|
|
|
|
|
QHBoxLayout *searchLayout = new QHBoxLayout(searchBar);
|
|
|
|
|
searchLayout->setContentsMargins(12, 4, 12, 4);
|
|
|
|
|
searchLayout->setSpacing(8);
|
|
|
|
|
|
|
|
|
|
m_searchEdit = new QLineEdit();
|
|
|
|
|
m_searchEdit->setPlaceholderText("Buscar correos…");
|
|
|
|
|
m_searchEdit->setClearButtonEnabled(true);
|
|
|
|
|
m_searchEdit->setStyleSheet(
|
|
|
|
|
"QLineEdit { background: white; border: 1px solid #d1d1d6; border-radius: 6px; "
|
|
|
|
|
"padding: 6px 12px; font-size: 13px; color: #1d1d1f; }"
|
|
|
|
|
"QLineEdit:focus { border: 2px solid #0071e3; }"
|
|
|
|
|
);
|
|
|
|
|
searchLayout->addWidget(m_searchEdit);
|
|
|
|
|
connect(m_searchEdit, &QLineEdit::textChanged, this, &MailListView::onSearchTextChanged);
|
|
|
|
|
|
|
|
|
|
layout->addWidget(searchBar);
|
|
|
|
|
|
|
|
|
|
// Filter bar
|
|
|
|
|
QWidget *filterBar = new QWidget();
|
|
|
|
|
filterBar->setFixedHeight(36);
|
|
|
|
|
filterBar->setStyleSheet("background-color: #f5f5f7; border-bottom: 1px solid #d1d1d6;");
|
|
|
|
|
QHBoxLayout *filterLayout = new QHBoxLayout(filterBar);
|
|
|
|
|
filterLayout->setContentsMargins(12, 2, 12, 2);
|
|
|
|
|
filterLayout->setSpacing(12);
|
|
|
|
|
|
|
|
|
|
m_unreadOnlyCheck = new QCheckBox("No leídos");
|
|
|
|
|
m_unreadOnlyCheck->setStyleSheet("QCheckBox { font-size: 12px; color: #333; }");
|
|
|
|
|
filterLayout->addWidget(m_unreadOnlyCheck);
|
|
|
|
|
|
|
|
|
|
m_flaggedOnlyCheck = new QCheckBox("Marcados");
|
|
|
|
|
m_flaggedOnlyCheck->setStyleSheet("QCheckBox { font-size: 12px; color: #333; }");
|
|
|
|
|
filterLayout->addWidget(m_flaggedOnlyCheck);
|
|
|
|
|
|
|
|
|
|
m_hasAttachmentsCheck = new QCheckBox("Con adjuntos");
|
|
|
|
|
m_hasAttachmentsCheck->setStyleSheet("QCheckBox { font-size: 12px; color: #333; }");
|
|
|
|
|
filterLayout->addWidget(m_hasAttachmentsCheck);
|
|
|
|
|
|
|
|
|
|
filterLayout->addStretch();
|
|
|
|
|
|
|
|
|
|
connect(m_unreadOnlyCheck, &QCheckBox::toggled, this, &MailListView::onFilterChanged);
|
|
|
|
|
connect(m_flaggedOnlyCheck, &QCheckBox::toggled, this, &MailListView::onFilterChanged);
|
|
|
|
|
connect(m_hasAttachmentsCheck, &QCheckBox::toggled, this, &MailListView::onFilterChanged);
|
|
|
|
|
|
|
|
|
|
layout->addWidget(filterBar);
|
|
|
|
|
|
2026-06-17 22:44:27 +02:00
|
|
|
// Table
|
|
|
|
|
m_tableView = new QTableView();
|
|
|
|
|
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
|
|
|
m_tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
|
|
|
m_tableView->setShowGrid(false);
|
|
|
|
|
m_tableView->setAlternatingRowColors(true);
|
|
|
|
|
m_tableView->verticalHeader()->hide();
|
|
|
|
|
m_tableView->horizontalHeader()->setStretchLastSection(true);
|
|
|
|
|
m_tableView->horizontalHeader()->setSectionsClickable(true);
|
|
|
|
|
m_tableView->setSortingEnabled(true);
|
|
|
|
|
m_tableView->setFrameShape(QFrame::NoFrame);
|
|
|
|
|
m_tableView->setStyleSheet(
|
|
|
|
|
"QTableView { background-color: #ffffff; alternate-background-color: #f9f9fb; border: none; }"
|
|
|
|
|
"QTableView::item { padding: 8px; border-bottom: 1px solid #e8e8ed; }"
|
|
|
|
|
"QTableView::item:selected { background-color: #e3f2fd; color: #1a1a2e; }"
|
|
|
|
|
"QHeaderView::section { background-color: #f5f5f7; padding: 8px; border: none; border-bottom: 1px solid #d1d1d6; font-weight: 600; color: #555; }"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
m_proxyModel = new QSortFilterProxyModel(this);
|
|
|
|
|
m_proxyModel->setSortRole(EmailListModel::DateRole);
|
|
|
|
|
m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
|
|
|
|
m_proxyModel->setDynamicSortFilter(true);
|
2026-08-23 14:49:58 +02:00
|
|
|
m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
|
|
|
|
m_proxyModel->setFilterKeyColumn(-1); // Search all columns
|
2026-06-17 22:44:27 +02:00
|
|
|
|
|
|
|
|
m_tableView->setModel(m_proxyModel);
|
|
|
|
|
|
|
|
|
|
connect(m_tableView, &QTableView::clicked, this, &MailListView::onRowSelected);
|
2026-06-18 18:58:27 +02:00
|
|
|
connect(m_tableView, &QTableView::doubleClicked, this, [this](const QModelIndex &index) {
|
|
|
|
|
if (!index.isValid()) return;
|
|
|
|
|
QModelIndex sourceIndex = m_proxyModel->mapToSource(index);
|
|
|
|
|
int mailId = sourceIndex.data(EmailListModel::IdRole).toInt();
|
|
|
|
|
emit emailOpenRequested(mailId);
|
|
|
|
|
});
|
2026-06-17 22:44:27 +02:00
|
|
|
|
|
|
|
|
layout->addWidget(m_tableView);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MailListView::setModel(EmailListModel *model) {
|
|
|
|
|
m_proxyModel->setSourceModel(model);
|
|
|
|
|
|
2026-08-19 09:43:03 +02:00
|
|
|
// Hide columns we don't want to show (by index now, not by role)
|
|
|
|
|
// Columns: 0=Subject, 1=Sender, 2=Date
|
|
|
|
|
// All visible for now - we can hide via header data
|
|
|
|
|
|
|
|
|
|
// Default sort by date descending (column 2)
|
|
|
|
|
m_tableView->sortByColumn(EmailListModel::ColDate, Qt::DescendingOrder);
|
2026-06-17 22:44:27 +02:00
|
|
|
|
2026-08-19 09:43:03 +02:00
|
|
|
// Set column resize modes
|
|
|
|
|
m_tableView->horizontalHeader()->setSectionResizeMode(EmailListModel::ColSubject, QHeaderView::Stretch);
|
|
|
|
|
m_tableView->horizontalHeader()->setSectionResizeMode(EmailListModel::ColSender, QHeaderView::Stretch);
|
|
|
|
|
m_tableView->horizontalHeader()->setSectionResizeMode(EmailListModel::ColDate, QHeaderView::ResizeToContents);
|
2026-06-17 22:44:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MailListView::onRowSelected(const QModelIndex &index) {
|
|
|
|
|
if (!index.isValid()) return;
|
|
|
|
|
QModelIndex sourceIndex = m_proxyModel->mapToSource(index);
|
|
|
|
|
int mailId = sourceIndex.data(EmailListModel::IdRole).toInt();
|
|
|
|
|
emit emailSelected(mailId);
|
2026-08-23 14:49:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MailListView::onSearchTextChanged(const QString &text) {
|
|
|
|
|
if (auto *model = qobject_cast<EmailListModel*>(m_proxyModel->sourceModel())) {
|
|
|
|
|
model->setSearchFilter(text);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MailListView::onFilterChanged() {
|
|
|
|
|
if (auto *model = qobject_cast<EmailListModel*>(m_proxyModel->sourceModel())) {
|
|
|
|
|
model->setShowUnreadOnly(m_unreadOnlyCheck->isChecked());
|
|
|
|
|
model->setShowFlaggedOnly(m_flaggedOnlyCheck->isChecked());
|
|
|
|
|
model->setShowHasAttachments(m_hasAttachmentsCheck->isChecked());
|
|
|
|
|
}
|
2026-06-17 22:44:27 +02:00
|
|
|
}
|