feat: email grouping by date + stability fixes
- EmailTreeModel: hierarchical model for grouped email view (QTreeView) - DateGroupProxyModel: proxy model for date-based grouping logic - MailListView: migrated from QTableView to QTreeView with grouping support - ReaderView: subject frame with shadow, avatar moved to header, body inside header - MainWindow: frameless with rounded corners, 1px border, edge resize, no status bar - Stability fixes for grouping mode switch: * Proper tree cleanup (no double-delete of root) * Bounds checking on all array accesses * Null pointer checks in index/parent/data methods * Date validity checks before grouping * Index validation before accessing m_emails
This commit is contained in:
@@ -97,6 +97,8 @@ set(SRC_FILES
|
||||
src/ui/accountsetupdialog.h
|
||||
src/ui/models/FolderListModel.cpp
|
||||
src/ui/models/EmailListModel.cpp
|
||||
src/ui/models/EmailTreeModel.cpp
|
||||
src/ui/models/DateGroupProxyModel.cpp
|
||||
src/ui/readerview.cpp
|
||||
src/ui/readerview.h
|
||||
src/ui/maillistview.cpp
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
# Plan de Acción: wino-mail-dtkqt
|
||||
|
||||
## Decisión Arquitectónica: Qt6 Widgets (no QML)
|
||||
|
||||
**Motivación**: El cliente de correo es una aplicación de escritorio orientada a PC.
|
||||
QML es excelente para dashboards animados y apps móviles, pero un cliente de correo
|
||||
con árboles de carpetas, tablas de correos, formularios complejos y paneles divididos
|
||||
se beneficia más de la madurez y eficiencia de Qt6 Widgets.
|
||||
|
||||
Beneficios clave del cambio:
|
||||
- Integración directa con DTK (Deepin Tool Kit) para el tema nativo
|
||||
- Menos dependencias: solo qt6-base-dev
|
||||
- Modelos C++ (QAbstractItemModel, QSqlQueryModel) funcionan nativamente con QTreeView/QTableView
|
||||
- Sin bridges QML → C++, todo es C++ puro
|
||||
- Más eficiente con listas grandes de correos (miles de items)
|
||||
|
||||
El plan contempla descartar el QML existente y reconstruir la UI con QWidgets
|
||||
reaprovechando toda la lógica C++ ya implementada (DAOs, servicios, sincronizadores,
|
||||
modelos, EventBus, etc.).
|
||||
|
||||
---
|
||||
|
||||
## Fase 0 — Arreglar Build (base C++)
|
||||
- [x] Arreglar includes relativos en synchronizers
|
||||
- [x] Migrar main.cpp: eliminar QQmlApplicationEngine, usar QApplication + MainWindow widget
|
||||
- [x] Verificar compilación completa del target wino-mail-qt
|
||||
- [x] Revisar que todos los .h existentes tengan guards y #include correctos
|
||||
|
||||
## Fase 1 — Backend Core (completar lo que falta del C# original)
|
||||
- [x] Implementar sistema de HTTP requests (request.cpp, concreterequests.cpp, requestprocessor.cpp)
|
||||
- [x] Implementar ChangeProcessor completo (changetype.cpp, changprocessor.cpp)
|
||||
- [x] Implementar EmailComposerBridge (preparar correos para envío)
|
||||
- [x] Implementar SynchronizerProvider (fábrica de sincronizadores por tipo de cuenta)
|
||||
- [x] Implementar AccountSetupDialogLauncher (lanzar diálogo de configuración inicial)
|
||||
|
||||
## Fase 2 — Autenticación y Servicios (port desde C#)
|
||||
- [x] Portar IAuthenticator → GmailAuthenticator, OutlookAuthenticator (OAuth2 con Qt Network)
|
||||
- [x] Portar AccountService: CRUD de cuentas de correo (IMAP, Gmail, Outlook)
|
||||
- [x] Portar MailService: envío (SMTP) y recepción real de correos
|
||||
- [x] Portar MimeStorageService: almacenamiento y gestión de adjuntos
|
||||
- [x] Portar MimeFileService: exportar/importar .eml y adjuntos
|
||||
- [x] Portar FolderService: gestión de carpetas (INBOX, Sent, Drafts, etc.)
|
||||
|
||||
## Fase 3 — UI con Qt6 Widgets (descartar QML)
|
||||
- [x] **Diseñar estructura de navegación**: QMainWindow + QSplitter (panel izquierdo: árbol de carpetas, panel derecho: lista de correos + lector)
|
||||
- [x] **Implementar MainWindow**: menú, toolbar, barra de estado, system tray
|
||||
- [x] **AccountSetupDialog**: QDialog con wizard para configurar cuenta IMAP/Gmail/Outlook (OAuth2 o credenciales)
|
||||
- [x] **FolderTreeView**: QTreeView con QStandardItemModel o modelo propio para mostrar jerarquía de carpetas
|
||||
- [x] **MailListView**: QTableView o QTreeView con delegados personalizados
|
||||
- [x] **ReaderPanel**: QTextBrowser o QWebEngineView para mostrar el cuerpo del correo
|
||||
- [x] **ComposeDialog**: QDialog para redactar correos (To, CC, BCC, asunto, cuerpo HTML/plain, adjuntos)
|
||||
- [x] **SearchBar**: QLineEdit con filtrado en tiempo real sobre el modelo de correos
|
||||
- [x] **Ventanas independientes**: Botón en toolbar y ReaderView + doble clic en lista para abrir correo en ventana independiente
|
||||
- [x] **AccountSetupDialog (Wizard)**: QDialog con wizard de 3 pasos para configurar cuenta Gmail/Outlook (OAuth2) o IMAP (credenciales manuales)
|
||||
|
||||
## Fase 4 — DTK Integration (tema Deepin)
|
||||
- [ ] Habilitar DTK en CMakeLists.txt (detectar dtkwidget)
|
||||
- [ ] Aplicar DMainWindow, DApplication, DTitlebar para el look nativo Deepin
|
||||
- [ ] Adaptar QSS/DStyle para mantener coherencia visual
|
||||
- [ ] Fallback a Qt widgets estándar si DTK no está disponible
|
||||
|
||||
## Fase 5 — Testing y QA
|
||||
- [ ] Re-activar y arreglar tests unitarios (DAO, Translator, EventBus)
|
||||
- [ ] Tests de integración (SyncScheduler con mock de sincronizadores)
|
||||
- [ ] Tests de UI (verificar navegación, apertura de correos, composición)
|
||||
- [ ] Benchmark con cargas grandes de correos (>10.000)
|
||||
+98
-71
@@ -1,7 +1,18 @@
|
||||
#include "ui/maillistview.h"
|
||||
#include <QDateTime>
|
||||
#include "ui/models/EmailListModel.h"
|
||||
#include "ui/models/EmailTreeModel.h"
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QCheckBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QComboBox>
|
||||
#include <QHeaderView>
|
||||
|
||||
MailListView::MailListView(QWidget *parent) : QWidget(parent) {
|
||||
MailListView::MailListView(QWidget *parent) : QWidget(parent), m_sourceModel(nullptr) {
|
||||
setupUI();
|
||||
}
|
||||
|
||||
@@ -10,29 +21,6 @@ void MailListView::setupUI() {
|
||||
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);
|
||||
|
||||
// Search bar
|
||||
QWidget *searchBar = new QWidget();
|
||||
searchBar->setFixedHeight(44);
|
||||
@@ -76,83 +64,122 @@ void MailListView::setupUI() {
|
||||
|
||||
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);
|
||||
// Group by combo
|
||||
m_groupByCombo = new QComboBox();
|
||||
m_groupByCombo->addItem("Sin agrupación");
|
||||
m_groupByCombo->addItem("Agrupar por fecha");
|
||||
m_groupByCombo->setFixedWidth(180);
|
||||
m_groupByCombo->setStyleSheet(
|
||||
"QComboBox { border: 1px solid #d1d1d6; border-radius: 4px; padding: 4px 8px; "
|
||||
"background: white; min-height: 20px; }"
|
||||
"QComboBox:hover { border-color: #bdbdbd; }"
|
||||
"QComboBox:focus { border-color: #1976D2; }"
|
||||
);
|
||||
connect(m_groupByCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &MailListView::onGroupByChanged);
|
||||
filterLayout->addWidget(m_groupByCombo);
|
||||
|
||||
layout->addWidget(filterBar);
|
||||
|
||||
// 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; }"
|
||||
// Tree View
|
||||
m_treeView = new QTreeView();
|
||||
m_treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_treeView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_treeView->setAlternatingRowColors(true);
|
||||
m_treeView->header()->setStretchLastSection(false);
|
||||
m_treeView->header()->setSectionsClickable(true);
|
||||
m_treeView->setSortingEnabled(false); // We handle sorting in the model
|
||||
m_treeView->setFrameShape(QFrame::NoFrame);
|
||||
m_treeView->setRootIsDecorated(true);
|
||||
m_treeView->setItemsExpandable(true);
|
||||
m_treeView->setUniformRowHeights(true);
|
||||
m_treeView->setStyleSheet(
|
||||
"QTreeView { background-color: #ffffff; alternate-background-color: #f9f9fb; border: none; }"
|
||||
"QTreeView::item { padding: 8px; border-bottom: 1px solid #e8e8ed; }"
|
||||
"QTreeView::item:selected { background-color: #e3f2fd; color: #1a1a2e; }"
|
||||
"QTreeView::branch { background: transparent; }"
|
||||
"QHeaderView::section { background-color: #f5f5f7; padding: 8px; border: none; border-bottom: 1px solid #d1d1d6; font-weight: 600; color: #555; }"
|
||||
);
|
||||
|
||||
// Tree model
|
||||
m_treeModel = new EmailTreeModel(this);
|
||||
m_proxyModel = new QSortFilterProxyModel(this);
|
||||
m_proxyModel->setSortRole(EmailListModel::DateRole);
|
||||
m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_proxyModel->setDynamicSortFilter(true);
|
||||
m_proxyModel->setSourceModel(m_treeModel);
|
||||
m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_proxyModel->setFilterKeyColumn(-1); // Search all columns
|
||||
|
||||
m_tableView->setModel(m_proxyModel);
|
||||
m_treeView->setModel(m_proxyModel);
|
||||
|
||||
connect(m_tableView, &QTableView::clicked, this, &MailListView::onRowSelected);
|
||||
connect(m_tableView, &QTableView::doubleClicked, this, [this](const QModelIndex &index) {
|
||||
// Column widths
|
||||
m_treeView->header()->setSectionResizeMode(EmailTreeModel::ColSubject, QHeaderView::Stretch);
|
||||
m_treeView->header()->setSectionResizeMode(EmailTreeModel::ColSender, QHeaderView::Stretch);
|
||||
m_treeView->header()->setSectionResizeMode(EmailTreeModel::ColDate, QHeaderView::ResizeToContents);
|
||||
|
||||
connect(m_treeView, &QTreeView::clicked, this, &MailListView::onRowSelected);
|
||||
connect(m_treeView, &QTreeView::doubleClicked, this, [this](const QModelIndex &index) {
|
||||
if (!index.isValid()) return;
|
||||
QModelIndex sourceIndex = m_proxyModel->mapToSource(index);
|
||||
int mailId = sourceIndex.data(EmailListModel::IdRole).toInt();
|
||||
QModelIndex proxyIdx = m_proxyModel->mapToSource(index);
|
||||
if (proxyIdx.isValid() && proxyIdx.data(EmailTreeModel::MailIdRole).isValid()) {
|
||||
int mailId = proxyIdx.data(EmailTreeModel::MailIdRole).toInt();
|
||||
emit emailOpenRequested(mailId);
|
||||
}
|
||||
});
|
||||
|
||||
layout->addWidget(m_tableView);
|
||||
// Expand all groups by default
|
||||
m_treeView->expandAll();
|
||||
|
||||
layout->addWidget(m_treeView);
|
||||
|
||||
// Connect filter checkboxes
|
||||
connect(m_unreadOnlyCheck, &QCheckBox::toggled, this, &MailListView::onFilterChanged);
|
||||
connect(m_flaggedOnlyCheck, &QCheckBox::toggled, this, &MailListView::onFilterChanged);
|
||||
connect(m_hasAttachmentsCheck, &QCheckBox::toggled, this, &MailListView::onFilterChanged);
|
||||
}
|
||||
|
||||
void MailListView::setModel(EmailListModel *model) {
|
||||
m_proxyModel->setSourceModel(model);
|
||||
m_sourceModel = model;
|
||||
|
||||
// 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
|
||||
// Connect to source model changes to refresh tree
|
||||
connect(m_sourceModel, &QAbstractItemModel::modelReset, this, &MailListView::refreshTreeModel);
|
||||
connect(m_sourceModel, &QAbstractItemModel::layoutChanged, this, &MailListView::refreshTreeModel);
|
||||
connect(m_sourceModel, &QAbstractItemModel::rowsInserted, this, &MailListView::refreshTreeModel);
|
||||
connect(m_sourceModel, &QAbstractItemModel::rowsRemoved, this, &MailListView::refreshTreeModel);
|
||||
|
||||
// Default sort by date descending (column 2)
|
||||
m_tableView->sortByColumn(EmailListModel::ColDate, Qt::DescendingOrder);
|
||||
// Initial population
|
||||
refreshTreeModel();
|
||||
}
|
||||
|
||||
// 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);
|
||||
void MailListView::refreshTreeModel() {
|
||||
if (!m_sourceModel) return;
|
||||
|
||||
const QVector<MailItem> &emails = m_sourceModel->emails();
|
||||
m_treeModel->setEmails(emails);
|
||||
m_treeView->expandAll();
|
||||
}
|
||||
|
||||
void MailListView::onRowSelected(const QModelIndex &index) {
|
||||
if (!index.isValid()) return;
|
||||
QModelIndex sourceIndex = m_proxyModel->mapToSource(index);
|
||||
int mailId = sourceIndex.data(EmailListModel::IdRole).toInt();
|
||||
QModelIndex proxyIdx = m_proxyModel->mapToSource(index);
|
||||
if (proxyIdx.isValid() && proxyIdx.data(EmailTreeModel::MailIdRole).isValid()) {
|
||||
int mailId = proxyIdx.data(EmailTreeModel::MailIdRole).toInt();
|
||||
emit emailSelected(mailId);
|
||||
}
|
||||
}
|
||||
|
||||
void MailListView::onSearchTextChanged(const QString &text) {
|
||||
if (auto *model = qobject_cast<EmailListModel*>(m_proxyModel->sourceModel())) {
|
||||
model->setSearchFilter(text);
|
||||
}
|
||||
m_proxyModel->setFilterFixedString(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());
|
||||
}
|
||||
if (!m_sourceModel) return;
|
||||
m_sourceModel->setShowUnreadOnly(m_unreadOnlyCheck->isChecked());
|
||||
m_sourceModel->setShowFlaggedOnly(m_flaggedOnlyCheck->isChecked());
|
||||
m_sourceModel->setShowHasAttachments(m_hasAttachmentsCheck->isChecked());
|
||||
// refreshTreeModel will be called automatically via modelReset signal
|
||||
}
|
||||
|
||||
void MailListView::onGroupByChanged(int index) {
|
||||
bool enabled = (index == 1); // 0 = Sin agrupación, 1 = Agrupar por fecha
|
||||
m_treeModel->setGroupMode(enabled ? EmailTreeModel::GroupByDate : EmailTreeModel::NoGrouping);
|
||||
m_treeView->expandAll();
|
||||
}
|
||||
+10
-3
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QTableView>
|
||||
#include <QTreeView>
|
||||
#include <QHeaderView>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QVBoxLayout>
|
||||
@@ -10,8 +10,10 @@
|
||||
#include <QLineEdit>
|
||||
#include <QCheckBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QComboBox>
|
||||
|
||||
#include "ui/models/EmailListModel.h"
|
||||
#include "ui/models/EmailTreeModel.h"
|
||||
|
||||
class MailListView : public QWidget {
|
||||
Q_OBJECT
|
||||
@@ -21,7 +23,7 @@ public:
|
||||
~MailListView() override = default;
|
||||
|
||||
void setModel(EmailListModel *model);
|
||||
QTableView* tableView() const { return m_tableView; }
|
||||
QTreeView* treeView() const { return m_treeView; }
|
||||
|
||||
signals:
|
||||
void emailSelected(int mailId);
|
||||
@@ -32,15 +34,20 @@ private slots:
|
||||
void onRowSelected(const QModelIndex &index);
|
||||
void onSearchTextChanged(const QString &text);
|
||||
void onFilterChanged();
|
||||
void onGroupByChanged(int index);
|
||||
|
||||
private:
|
||||
void setupUI();
|
||||
void refreshTreeModel();
|
||||
|
||||
QTableView *m_tableView;
|
||||
QTreeView *m_treeView;
|
||||
EmailTreeModel *m_treeModel;
|
||||
QSortFilterProxyModel *m_proxyModel;
|
||||
EmailListModel *m_sourceModel = nullptr;
|
||||
QPushButton *m_composeButton;
|
||||
QLineEdit *m_searchEdit;
|
||||
QCheckBox *m_unreadOnlyCheck;
|
||||
QCheckBox *m_flaggedOnlyCheck;
|
||||
QCheckBox *m_hasAttachmentsCheck;
|
||||
QComboBox *m_groupByCombo;
|
||||
};
|
||||
@@ -385,7 +385,7 @@ void MainMainWindow::onFolderSelected(const QModelIndex &index)
|
||||
m_emailModel->refresh();
|
||||
// Clear selection and show placeholder
|
||||
m_currentMailId = -1;
|
||||
m_mailListView->tableView()->clearSelection();
|
||||
m_mailListView->treeView()->clearSelection();
|
||||
m_viewerStack->setCurrentIndex(0); // placeholder
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "DateGroupProxyModel.h"
|
||||
#include <QDateTime>
|
||||
#include <QDate>
|
||||
#include <QDebug>
|
||||
#include "EmailListModel.h"
|
||||
|
||||
DateGroupProxyModel::DateGroupProxyModel(QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{
|
||||
setDynamicSortFilter(true);
|
||||
}
|
||||
|
||||
void DateGroupProxyModel::setGroupByDate(bool enabled)
|
||||
{
|
||||
if (m_groupByDate == enabled) return;
|
||||
m_groupByDate = enabled;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
bool DateGroupProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
if (!m_groupByDate) {
|
||||
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
|
||||
}
|
||||
|
||||
// When grouping, we don't filter rows, we just organize them
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DateGroupProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
// First sort by group, then by date within group (descending)
|
||||
if (m_groupByDate) {
|
||||
int leftGroup = groupForRow(left.row());
|
||||
int rightGroup = groupForRow(right.row());
|
||||
|
||||
if (leftGroup != rightGroup) {
|
||||
return leftGroup < rightGroup;
|
||||
}
|
||||
|
||||
// Same group - sort by date descending (newest first)
|
||||
QVariant leftDate = sourceModel()->data(left, EmailListModel::DateRole);
|
||||
QVariant rightDate = sourceModel()->data(right, EmailListModel::DateRole);
|
||||
|
||||
if (leftDate.isValid() && rightDate.isValid()) {
|
||||
return leftDate.toDateTime() > rightDate.toDateTime();
|
||||
}
|
||||
}
|
||||
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
||||
|
||||
QString DateGroupProxyModel::groupNameForDate(const QDateTime &date)
|
||||
{
|
||||
if (!date.isValid()) return "Sin fecha";
|
||||
|
||||
QDate emailDate = date.date();
|
||||
QDate today = QDate::currentDate();
|
||||
|
||||
int daysDiff = today.daysTo(emailDate);
|
||||
|
||||
if (daysDiff == 0) {
|
||||
return "Hoy";
|
||||
} else if (daysDiff == -1) {
|
||||
return "Ayer";
|
||||
} else if (daysDiff > -7 && daysDiff < 0) {
|
||||
// This week (Monday to Sunday)
|
||||
return emailDate.dayOfWeek() == 1 ? "Esta semana (Lunes)" : "Esta semana";
|
||||
} else if (daysDiff >= -13 && daysDiff <= -7) {
|
||||
return "Semana pasada";
|
||||
} else if (daysDiff >= -20 && daysDiff <= -14) {
|
||||
return "Hace dos semanas";
|
||||
} else if (emailDate.month() == today.month() && emailDate.year() == today.year()) {
|
||||
return "Este mes";
|
||||
} else if (emailDate.year() == today.year()) {
|
||||
// Month name
|
||||
static const QString months[] = {
|
||||
"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio",
|
||||
"Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"
|
||||
};
|
||||
return months[emailDate.month() - 1];
|
||||
} else {
|
||||
return QString("%1").arg(emailDate.year());
|
||||
}
|
||||
}
|
||||
|
||||
void DateGroupProxyModel::updateGroupCache() const
|
||||
{
|
||||
m_groupRowCounts.clear();
|
||||
m_groupStartRows.clear();
|
||||
|
||||
int rowCount = this->rowCount();
|
||||
if (rowCount == 0) return;
|
||||
|
||||
QString lastGroup = "";
|
||||
int currentGroup = -1;
|
||||
|
||||
for (int i = 0; i < rowCount; ++i) {
|
||||
QModelIndex idx = index(i, 0);
|
||||
QString group = idx.data(GroupRole).toString();
|
||||
|
||||
if (group != lastGroup) {
|
||||
currentGroup++;
|
||||
lastGroup = group;
|
||||
m_groupStartRows.append(i);
|
||||
m_groupRowCounts.append(1);
|
||||
} else {
|
||||
m_groupRowCounts[currentGroup]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int DateGroupProxyModel::groupForRow(int row) const
|
||||
{
|
||||
if (row < 0 || row >= rowCount()) return -1;
|
||||
|
||||
if (m_groupStartRows.isEmpty()) {
|
||||
updateGroupCache();
|
||||
}
|
||||
|
||||
// Binary search for group
|
||||
int group = 0;
|
||||
for (int i = m_groupStartRows.size() - 1; i >= 0; --i) {
|
||||
if (row >= m_groupStartRows[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString DateGroupProxyModel::groupNameForRow(int row) const
|
||||
{
|
||||
if (row < 0 || row >= rowCount()) return "";
|
||||
|
||||
QModelIndex idx = index(row, 0);
|
||||
return idx.data(GroupRole).toString();
|
||||
}
|
||||
|
||||
QVariant DateGroupProxyModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid()) return QVariant();
|
||||
|
||||
if (role == GroupRole) {
|
||||
// Return group name for this row
|
||||
QModelIndex sourceIdx = mapToSource(index);
|
||||
QVariant dateVar = sourceModel()->data(sourceIdx, EmailListModel::DateRole);
|
||||
if (dateVar.isValid()) {
|
||||
return groupNameForDate(dateVar.toDateTime());
|
||||
}
|
||||
return "Sin fecha";
|
||||
}
|
||||
|
||||
if (role == IsGroupHeaderRole) {
|
||||
// This would be used if we inserted header rows - not implemented yet
|
||||
return false;
|
||||
}
|
||||
|
||||
if (role == GroupSectionRole) {
|
||||
return groupForRow(index.row());
|
||||
}
|
||||
|
||||
return QSortFilterProxyModel::data(index, role);
|
||||
}
|
||||
|
||||
QVariant DateGroupProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role == GroupRole && orientation == Qt::Horizontal && m_groupByDate) {
|
||||
// For the date column, we might want to show group headers
|
||||
// This is for column headers, not row grouping
|
||||
}
|
||||
|
||||
return QSortFilterProxyModel::headerData(section, orientation, role);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QDateTime>
|
||||
#include <QVector>
|
||||
#include <QPair>
|
||||
|
||||
class DateGroupProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum GroupBy {
|
||||
GroupByDate = 0
|
||||
};
|
||||
|
||||
explicit DateGroupProxyModel(QObject *parent = nullptr);
|
||||
|
||||
// Grouping methods
|
||||
void setGroupByDate(bool enabled);
|
||||
bool isGroupByDateEnabled() const { return m_groupByDate; }
|
||||
|
||||
// Override to provide group headers
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// For grouping - we'll use a custom role for group identification
|
||||
static constexpr int GroupRole = Qt::UserRole + 100;
|
||||
static constexpr int IsGroupHeaderRole = Qt::UserRole + 101;
|
||||
static constexpr int GroupSectionRole = Qt::UserRole + 102;
|
||||
|
||||
// Helper to get group name for a date
|
||||
static QString groupNameForDate(const QDateTime &date);
|
||||
|
||||
protected:
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
|
||||
private:
|
||||
bool m_groupByDate = false;
|
||||
mutable QVector<int> m_groupRowCounts; // cached group sizes
|
||||
mutable QVector<int> m_groupStartRows; // cached start rows for each group
|
||||
|
||||
void updateGroupCache() const;
|
||||
int groupForRow(int row) const;
|
||||
QString groupNameForRow(int row) const;
|
||||
};
|
||||
@@ -53,6 +53,9 @@ public:
|
||||
void setShowFlaggedOnly(bool show);
|
||||
void setShowHasAttachments(bool show);
|
||||
|
||||
// Get all emails currently in the model (after filtering)
|
||||
const QVector<MailItem>& emails() const { return m_emails; }
|
||||
|
||||
private:
|
||||
QVector<MailItem> m_emails;
|
||||
int m_folderId{-1}; // -1 means all folders
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
#include "EmailTreeModel.h"
|
||||
#include <QDateTime>
|
||||
#include <QDate>
|
||||
#include <QDebug>
|
||||
#include <algorithm>
|
||||
|
||||
EmailTreeModel::EmailTreeModel(QObject *parent)
|
||||
: QAbstractItemModel(parent), m_rootItem(new TreeItem(TreeItem::Group))
|
||||
{
|
||||
m_rootItem->type = TreeItem::Group;
|
||||
m_rootItem->groupName = "Root";
|
||||
}
|
||||
|
||||
EmailTreeModel::~EmailTreeModel()
|
||||
{
|
||||
deleteTree(m_rootItem);
|
||||
}
|
||||
|
||||
void EmailTreeModel::deleteTree(TreeItem* item)
|
||||
{
|
||||
if (!item) return;
|
||||
qDeleteAll(item->children);
|
||||
delete item;
|
||||
}
|
||||
|
||||
QModelIndex EmailTreeModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem* parentItem;
|
||||
if (!parent.isValid())
|
||||
parentItem = m_rootItem;
|
||||
else
|
||||
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||
|
||||
// Verify parentItem is valid
|
||||
if (!parentItem)
|
||||
return QModelIndex();
|
||||
|
||||
if (row < 0 || row >= parentItem->children.size())
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem* childItem = parentItem->children[row];
|
||||
if (!childItem)
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(row, column, childItem);
|
||||
}
|
||||
|
||||
QModelIndex EmailTreeModel::parent(const QModelIndex &child) const
|
||||
{
|
||||
if (!child.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem* childItem = static_cast<TreeItem*>(child.internalPointer());
|
||||
if (!childItem)
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem* parentItem = childItem->parent;
|
||||
if (!parentItem || parentItem == m_rootItem)
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(parentItem->row, 0, parentItem);
|
||||
}
|
||||
|
||||
int EmailTreeModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
TreeItem* parentItem;
|
||||
if (!parent.isValid())
|
||||
parentItem = m_rootItem;
|
||||
else
|
||||
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||
|
||||
return parentItem->children.size();
|
||||
}
|
||||
|
||||
int EmailTreeModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return ColCount;
|
||||
}
|
||||
|
||||
QVariant EmailTreeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||
|
||||
if (role == MailIdRole) {
|
||||
if (item->type == TreeItem::Mail) {
|
||||
const MailItem& mail = m_emails[item->mailIndex];
|
||||
return mail.id();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (role == IsGroupRole) {
|
||||
return item->type == TreeItem::Group;
|
||||
}
|
||||
|
||||
if (role == GroupNameRole && item->type == TreeItem::Group) {
|
||||
return item->groupName;
|
||||
}
|
||||
|
||||
if (role == GroupIndexRole && item->type == TreeItem::Group) {
|
||||
return item->groupIndex;
|
||||
}
|
||||
|
||||
if (role == MailIndexRole && item->type == TreeItem::Mail) {
|
||||
return item->mailIndex;
|
||||
}
|
||||
|
||||
if (role != Qt::DisplayRole && role != Qt::ToolTipRole)
|
||||
return QVariant();
|
||||
|
||||
if (item->type == TreeItem::Group) {
|
||||
if (index.column() == ColSubject) {
|
||||
return QString("%1 (%2)").arg(item->groupName).arg(item->children.size());
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// Mail item
|
||||
if (item->type == TreeItem::Mail) {
|
||||
if (item->mailIndex < 0 || item->mailIndex >= m_emails.size()) {
|
||||
return QVariant();
|
||||
}
|
||||
const MailItem& mail = m_emails[item->mailIndex];
|
||||
|
||||
switch (index.column()) {
|
||||
case ColSubject:
|
||||
return mail.subject().isEmpty() ? "(Sin asunto)" : mail.subject();
|
||||
case ColSender:
|
||||
return mail.sender();
|
||||
case ColDate: {
|
||||
if (!mail.date().isValid()) return QVariant();
|
||||
QDateTime dt = mail.date();
|
||||
QDate today = QDate::currentDate();
|
||||
if (dt.date() == today) {
|
||||
return dt.toString("HH:mm");
|
||||
} else if (dt.date() == today.addDays(-1)) {
|
||||
return "Ayer " + dt.toString("HH:mm");
|
||||
} else if (dt.date().year() == today.year()) {
|
||||
return dt.toString("ddd dd/MM HH:mm");
|
||||
} else {
|
||||
return dt.toString("dd/MM/yyyy HH:mm");
|
||||
}
|
||||
}
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant EmailTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||
switch (section) {
|
||||
case ColSubject: return "Asunto";
|
||||
case ColSender: return "De";
|
||||
case ColDate: return "Fecha";
|
||||
default: return QVariant();
|
||||
}
|
||||
}
|
||||
return QAbstractItemModel::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
Qt::ItemFlags EmailTreeModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
|
||||
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||
|
||||
Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
if (item->type == TreeItem::Group) {
|
||||
// Groups don't need special flags for expand/collapse in Qt6
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
void EmailTreeModel::setEmails(const QVector<MailItem> &emails)
|
||||
{
|
||||
beginResetModel();
|
||||
m_emails = emails;
|
||||
// Clear tree properly without deleting root
|
||||
qDeleteAll(m_rootItem->children);
|
||||
m_rootItem->children.clear();
|
||||
setupModelData();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void EmailTreeModel::clear()
|
||||
{
|
||||
beginResetModel();
|
||||
m_emails.clear();
|
||||
deleteTree(m_rootItem);
|
||||
m_rootItem = new TreeItem(TreeItem::Group);
|
||||
m_rootItem->type = TreeItem::Group;
|
||||
m_rootItem->groupName = "Root";
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void EmailTreeModel::setGroupMode(GroupMode mode)
|
||||
{
|
||||
if (m_groupMode == mode) return;
|
||||
|
||||
// Clear existing tree first
|
||||
beginResetModel();
|
||||
m_groupMode = mode;
|
||||
qDeleteAll(m_rootItem->children);
|
||||
m_rootItem->children.clear();
|
||||
setupModelData();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void EmailTreeModel::setupModelData()
|
||||
{
|
||||
if (m_groupMode == NoGrouping) {
|
||||
// Flat list - all mails directly under root
|
||||
for (int i = 0; i < m_emails.size(); ++i) {
|
||||
if (i < 0 || i >= m_emails.size()) continue;
|
||||
TreeItem* mailItem = new TreeItem(TreeItem::Mail, m_rootItem);
|
||||
mailItem->mailIndex = i;
|
||||
mailItem->row = m_rootItem->children.size();
|
||||
m_rootItem->children.append(mailItem);
|
||||
}
|
||||
} else {
|
||||
// Grouped by date
|
||||
buildGroups();
|
||||
}
|
||||
}
|
||||
|
||||
void EmailTreeModel::buildGroups()
|
||||
{
|
||||
// Sort emails by date descending (newest first)
|
||||
QVector<int> indices(m_emails.size());
|
||||
std::iota(indices.begin(), indices.end(), 0);
|
||||
std::sort(indices.begin(), indices.end(), [this](int a, int b) {
|
||||
const QDateTime& dateA = m_emails[a].date();
|
||||
const QDateTime& dateB = m_emails[b].date();
|
||||
if (!dateA.isValid() && !dateB.isValid()) return false;
|
||||
if (!dateA.isValid()) return false;
|
||||
if (!dateB.isValid()) return true;
|
||||
return dateA > dateB;
|
||||
});
|
||||
|
||||
// Group by date
|
||||
QMap<QString, QVector<int>> groups; // groupName -> mail indices
|
||||
for (int idx : indices) {
|
||||
if (idx < 0 || idx >= m_emails.size()) continue;
|
||||
const QDateTime& dt = m_emails[idx].date();
|
||||
if (!dt.isValid()) continue;
|
||||
|
||||
QString groupName = groupNameForDate(dt);
|
||||
groups[groupName].append(idx);
|
||||
}
|
||||
|
||||
// Create tree items in group order
|
||||
int groupIdx = 0;
|
||||
for (auto it = groups.constBegin(); it != groups.constEnd(); ++it) {
|
||||
const QString& groupName = it.key();
|
||||
const QVector<int>& mailIndices = it.value();
|
||||
if (mailIndices.isEmpty()) continue;
|
||||
|
||||
TreeItem* groupItem = new TreeItem(TreeItem::Group, m_rootItem);
|
||||
groupItem->groupName = groupName;
|
||||
groupItem->groupIndex = groupIdx++;
|
||||
groupItem->row = m_rootItem->children.size();
|
||||
m_rootItem->children.append(groupItem);
|
||||
|
||||
for (int mailIdx : mailIndices) {
|
||||
if (mailIdx < 0 || mailIdx >= m_emails.size()) continue;
|
||||
TreeItem* mailItem = new TreeItem(TreeItem::Mail, groupItem);
|
||||
mailItem->mailIndex = mailIdx;
|
||||
mailItem->row = groupItem->children.size();
|
||||
groupItem->children.append(mailItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString EmailTreeModel::groupNameForDate(const QDateTime &date) const
|
||||
{
|
||||
if (!date.isValid()) return "Sin fecha";
|
||||
|
||||
QDate emailDate = date.date();
|
||||
QDate today = QDate::currentDate();
|
||||
|
||||
int daysDiff = today.daysTo(emailDate);
|
||||
|
||||
if (daysDiff == 0) {
|
||||
return "Hoy";
|
||||
} else if (daysDiff == -1) {
|
||||
return "Ayer";
|
||||
} else if (daysDiff > -7 && daysDiff < 0) {
|
||||
// This week
|
||||
return "Esta semana";
|
||||
} else if (daysDiff >= -13 && daysDiff <= -7) {
|
||||
return "Semana pasada";
|
||||
} else if (daysDiff >= -20 && daysDiff <= -14) {
|
||||
return "Hace dos semanas";
|
||||
} else if (emailDate.month() == today.month() && emailDate.year() == today.year()) {
|
||||
return "Este mes";
|
||||
} else if (emailDate.year() == today.year()) {
|
||||
static const QString months[] = {
|
||||
"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio",
|
||||
"Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"
|
||||
};
|
||||
return months[emailDate.month() - 1];
|
||||
} else {
|
||||
return QString("%1").arg(emailDate.year());
|
||||
}
|
||||
}
|
||||
|
||||
int EmailTreeModel::groupIndexForDate(const QDateTime &date) const
|
||||
{
|
||||
// Not used directly but kept for reference
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QModelIndex>
|
||||
#include <QVariant>
|
||||
#include <QVector>
|
||||
#include <QDateTime>
|
||||
#include <QDate>
|
||||
#include "core/mailitem.h"
|
||||
|
||||
class EmailTreeModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Columns {
|
||||
ColSubject = 0,
|
||||
ColSender = 1,
|
||||
ColDate = 2,
|
||||
ColCount = 3
|
||||
};
|
||||
|
||||
enum Roles {
|
||||
MailIdRole = Qt::UserRole + 1,
|
||||
IsGroupRole = Qt::UserRole + 2,
|
||||
GroupNameRole = Qt::UserRole + 3,
|
||||
GroupIndexRole = Qt::UserRole + 4,
|
||||
MailIndexRole = Qt::UserRole + 5
|
||||
};
|
||||
|
||||
explicit EmailTreeModel(QObject *parent = nullptr);
|
||||
~EmailTreeModel() override;
|
||||
|
||||
// Basic model interface
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
// Email data management
|
||||
void setEmails(const QVector<MailItem> &emails);
|
||||
void clear();
|
||||
|
||||
// Grouping
|
||||
enum GroupMode {
|
||||
NoGrouping = 0,
|
||||
GroupByDate = 1
|
||||
};
|
||||
void setGroupMode(GroupMode mode);
|
||||
GroupMode groupMode() const { return m_groupMode; }
|
||||
|
||||
private:
|
||||
struct TreeItem {
|
||||
enum Type { Group, Mail } type;
|
||||
QString groupName; // for Group type
|
||||
int groupIndex = -1; // for Group type
|
||||
int mailIndex = -1; // for Mail type (index in m_emails)
|
||||
QVector<TreeItem*> children;
|
||||
TreeItem* parent = nullptr;
|
||||
int row = -1;
|
||||
|
||||
TreeItem(Type t, TreeItem* p = nullptr) : type(t), parent(p) {}
|
||||
~TreeItem() { qDeleteAll(children); }
|
||||
};
|
||||
|
||||
GroupMode m_groupMode = NoGrouping;
|
||||
QVector<MailItem> m_emails;
|
||||
TreeItem* m_rootItem = nullptr;
|
||||
|
||||
void setupModelData();
|
||||
void buildGroups();
|
||||
QString groupNameForDate(const QDateTime &date) const;
|
||||
int groupIndexForDate(const QDateTime &date) const;
|
||||
void deleteTree(TreeItem* item);
|
||||
};
|
||||
+56
-23
@@ -20,6 +20,7 @@
|
||||
#include <QFileDialog>
|
||||
#include <QDir>
|
||||
#include <functional>
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
#include "db/dao/mailitemdao.h"
|
||||
|
||||
ReaderView::ReaderView(QWidget *parent) : QWidget(parent) {
|
||||
@@ -29,7 +30,7 @@ ReaderView::ReaderView(QWidget *parent) : QWidget(parent) {
|
||||
|
||||
void ReaderView::setupUI() {
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
mainLayout->setContentsMargins(12, 0, 12, 0);
|
||||
mainLayout->setSpacing(0);
|
||||
|
||||
// ===== Toolbar (zoom, find, images) =====
|
||||
@@ -182,23 +183,31 @@ void ReaderView::setupUI() {
|
||||
mainLayout->addWidget(m_toolbar);
|
||||
mainLayout->addWidget(m_findBar);
|
||||
|
||||
// ===== Header Section =====
|
||||
m_headerWidget = new QWidget();
|
||||
m_headerWidget->setStyleSheet("QWidget { background: white; border-bottom: 1px solid #e0e0e0; }");
|
||||
QVBoxLayout *headerLayout = new QVBoxLayout(m_headerWidget);
|
||||
headerLayout->setContentsMargins(16, 12, 16, 12);
|
||||
headerLayout->setSpacing(8);
|
||||
// ===== Subject Section (independent, with shadow) =====
|
||||
QFrame *subjectFrame = new QFrame();
|
||||
subjectFrame->setObjectName("SubjectFrame");
|
||||
subjectFrame->setStyleSheet(
|
||||
"QFrame#SubjectFrame {"
|
||||
" background: white;"
|
||||
" border: none;"
|
||||
" border: 1px solid #e0e0e0;"
|
||||
" border-radius: 10px;"
|
||||
"}"
|
||||
);
|
||||
// Add shadow effect
|
||||
QGraphicsDropShadowEffect *shadowEffect = new QGraphicsDropShadowEffect(this);
|
||||
shadowEffect->setBlurRadius(8);
|
||||
shadowEffect->setOffset(0, 3);
|
||||
shadowEffect->setColor(QColor(0, 0, 0, 40));
|
||||
subjectFrame->setGraphicsEffect(shadowEffect);
|
||||
|
||||
QVBoxLayout *subjectLayout = new QVBoxLayout(subjectFrame);
|
||||
subjectLayout->setContentsMargins(16, 16, 16, 16);
|
||||
subjectLayout->setSpacing(8);
|
||||
|
||||
// Subject row
|
||||
QHBoxLayout *subjectRow = new QHBoxLayout();
|
||||
subjectRow->setSpacing(12);
|
||||
|
||||
m_avatarLabel = new QLabel();
|
||||
m_avatarLabel->setFixedSize(40, 40);
|
||||
m_avatarLabel->setAlignment(Qt::AlignCenter);
|
||||
m_avatarLabel->setStyleSheet("QLabel { background: #1976D2; color: white; border-radius: 20px; font-weight: bold; font-size: 14px; }");
|
||||
subjectRow->addWidget(m_avatarLabel);
|
||||
|
||||
m_subjectLabel = new QLabel();
|
||||
m_subjectLabel->setText("(Sin asunto)");
|
||||
QFont subjectFont = m_subjectLabel->font();
|
||||
@@ -210,12 +219,33 @@ void ReaderView::setupUI() {
|
||||
m_subjectLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
subjectRow->addWidget(m_subjectLabel, 1);
|
||||
|
||||
headerLayout->addLayout(subjectRow);
|
||||
subjectLayout->addLayout(subjectRow);
|
||||
mainLayout->addWidget(subjectFrame);
|
||||
// Add spacing after subject frame so shadow is visible
|
||||
mainLayout->addSpacing(12);
|
||||
|
||||
// From / To / Date row
|
||||
// ===== Header Section =====
|
||||
m_headerWidget = new QWidget();
|
||||
m_headerWidget->setStyleSheet("QWidget { background: white; border-bottom: 1px solid #e0e0e0; }");
|
||||
QVBoxLayout *headerLayout = new QVBoxLayout(m_headerWidget);
|
||||
headerLayout->setContentsMargins(16, 12, 16, 12);
|
||||
headerLayout->setSpacing(8);
|
||||
|
||||
// Avatar + From / To / Date row
|
||||
QHBoxLayout *metaRow = new QHBoxLayout();
|
||||
metaRow->setSpacing(16);
|
||||
|
||||
// Avatar on the left
|
||||
m_avatarLabel = new QLabel();
|
||||
m_avatarLabel->setFixedSize(40, 40);
|
||||
m_avatarLabel->setAlignment(Qt::AlignCenter);
|
||||
m_avatarLabel->setStyleSheet("QLabel { background: #1976D2; color: white; border-radius: 20px; font-weight: bold; font-size: 14px; }");
|
||||
metaRow->addWidget(m_avatarLabel, 0, Qt::AlignTop);
|
||||
|
||||
// From / To / Date on the right of avatar
|
||||
QVBoxLayout *metaRightLayout = new QVBoxLayout();
|
||||
metaRightLayout->setSpacing(2);
|
||||
|
||||
m_fromLabel = new QLabel();
|
||||
m_fromLabel->setStyleSheet("color: #333; font-size: 13px;");
|
||||
m_fromLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
@@ -223,17 +253,19 @@ void ReaderView::setupUI() {
|
||||
connect(m_fromLabel, &QLabel::linkActivated, [this](const QString &link) {
|
||||
QDesktopServices::openUrl(QUrl(link));
|
||||
});
|
||||
metaRow->addWidget(m_fromLabel, 1);
|
||||
metaRightLayout->addWidget(m_fromLabel);
|
||||
|
||||
m_toLabel = new QLabel();
|
||||
m_toLabel->setStyleSheet("color: #666; font-size: 12px;");
|
||||
m_toLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
m_toLabel->setWordWrap(true);
|
||||
metaRow->addWidget(m_toLabel, 2);
|
||||
metaRightLayout->addWidget(m_toLabel);
|
||||
|
||||
m_dateLabel = new QLabel();
|
||||
m_dateLabel->setStyleSheet("color: #888; font-size: 12px;");
|
||||
metaRow->addWidget(m_dateLabel);
|
||||
metaRightLayout->addWidget(m_dateLabel);
|
||||
|
||||
metaRow->addLayout(metaRightLayout, 1);
|
||||
|
||||
headerLayout->addLayout(metaRow);
|
||||
|
||||
@@ -310,16 +342,17 @@ void ReaderView::setupUI() {
|
||||
actionsLayout->addWidget(m_moreButton);
|
||||
|
||||
headerLayout->addLayout(actionsLayout);
|
||||
|
||||
// ===== Body Viewer (inside header widget) =====
|
||||
setupBodyViewer();
|
||||
headerLayout->addWidget(m_scrollArea, 1);
|
||||
|
||||
mainLayout->addWidget(m_headerWidget);
|
||||
|
||||
// ===== Attachments Area =====
|
||||
setupAttachmentsArea();
|
||||
mainLayout->addWidget(m_attachmentsFrame);
|
||||
|
||||
// ===== Body Viewer =====
|
||||
setupBodyViewer();
|
||||
mainLayout->addWidget(m_scrollArea, 1);
|
||||
|
||||
// Shortcuts
|
||||
QShortcut *findShortcut = new QShortcut(QKeySequence(Qt::ControlModifier | Qt::Key_F), this);
|
||||
connect(findShortcut, &QShortcut::activated, [this]() {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
QMAKE_CXX.QT_COMPILER_STDCXX = 201703L
|
||||
QMAKE_CXX.QMAKE_GCC_MAJOR_VERSION = 15
|
||||
QMAKE_CXX.QMAKE_GCC_MINOR_VERSION = 2
|
||||
QMAKE_CXX.QMAKE_GCC_PATCH_VERSION = 0
|
||||
QMAKE_CXX.COMPILER_MACROS = \
|
||||
QT_COMPILER_STDCXX \
|
||||
QMAKE_GCC_MAJOR_VERSION \
|
||||
QMAKE_GCC_MINOR_VERSION \
|
||||
QMAKE_GCC_PATCH_VERSION
|
||||
QMAKE_CXX.INCDIRS = \
|
||||
/usr/include/c++/15 \
|
||||
/usr/include/x86_64-linux-gnu/c++/15 \
|
||||
/usr/include/c++/15/backward \
|
||||
/usr/lib/gcc/x86_64-linux-gnu/15/include \
|
||||
/usr/local/include \
|
||||
/usr/include/x86_64-linux-gnu \
|
||||
/usr/include
|
||||
QMAKE_CXX.LIBDIRS = \
|
||||
/usr/lib/gcc/x86_64-linux-gnu/15 \
|
||||
/usr/lib/x86_64-linux-gnu \
|
||||
/usr/lib \
|
||||
/lib/x86_64-linux-gnu \
|
||||
/lib
|
||||
@@ -0,0 +1,400 @@
|
||||
#############################################################################
|
||||
# Makefile for building: test_accountdao
|
||||
# Generated by qmake (3.1) (Qt 6.10.2)
|
||||
# Project: test_accountdao.pro
|
||||
# Template: app
|
||||
# Command: /usr/bin/qmake6 -o Makefile test_accountdao.pro
|
||||
#############################################################################
|
||||
|
||||
MAKEFILE = Makefile
|
||||
|
||||
EQ = =
|
||||
|
||||
####### Compiler, tools and options
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
DEFINES = -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_TESTLIB_LIB -DQT_SQL_LIB -DQT_CORE_LIB -DQT_TESTCASE_BUILDDIR='"/mnt/c/Users/javie/wino-mail-dtkqt/tests/unit"'
|
||||
CFLAGS = -pipe -O2 -Wall -Wextra -D_REENTRANT $(DEFINES)
|
||||
CXXFLAGS = -pipe -O2 -std=gnu++1z -Wall -Wextra -D_REENTRANT $(DEFINES)
|
||||
INCPATH = -I. -I../../src -I../../src/services -I../../src/db -I../../src/db/dao -I../../src/core -I../../src/core/models -I/usr/include/x86_64-linux-gnu/qt6 -I/usr/include/x86_64-linux-gnu/qt6/QtGui -I/usr/include/x86_64-linux-gnu/qt6/QtTest -I/usr/include/x86_64-linux-gnu/qt6/QtSql -I/usr/include/x86_64-linux-gnu/qt6/QtCore -I. -I/usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++
|
||||
QMAKE = /usr/bin/qmake6
|
||||
DEL_FILE = rm -f
|
||||
CHK_DIR_EXISTS= test -d
|
||||
MKDIR = mkdir -p
|
||||
COPY = cp -f
|
||||
COPY_FILE = cp -f
|
||||
COPY_DIR = cp -f -R
|
||||
INSTALL_FILE = install -m 644 -p
|
||||
INSTALL_PROGRAM = install -m 755 -p
|
||||
INSTALL_DIR = cp -f -R
|
||||
QINSTALL = /usr/bin/qmake6 -install qinstall
|
||||
QINSTALL_PROGRAM = /usr/bin/qmake6 -install qinstall -exe
|
||||
DEL_FILE = rm -f
|
||||
SYMLINK = ln -f -s
|
||||
DEL_DIR = rmdir
|
||||
MOVE = mv -f
|
||||
TAR = tar -cf
|
||||
COMPRESS = gzip -9f
|
||||
DISTNAME = test_accountdao1.0.0
|
||||
DISTDIR = /mnt/c/Users/javie/wino-mail-dtkqt/tests/unit/.tmp/test_accountdao1.0.0
|
||||
LINK = g++
|
||||
LFLAGS = -Wl,-O1 -Wl,-rpath-link,/usr/lib/x86_64-linux-gnu
|
||||
LIBS = $(SUBLIBS) /usr/lib/x86_64-linux-gnu/libQt6Gui.so /usr/lib/x86_64-linux-gnu/libGLX.so /usr/lib/x86_64-linux-gnu/libOpenGL.so /usr/lib/x86_64-linux-gnu/libQt6Test.so /usr/lib/x86_64-linux-gnu/libQt6Sql.so /usr/lib/x86_64-linux-gnu/libQt6Core.so -lpthread -lGLX -lOpenGL
|
||||
AR = ar cqs
|
||||
RANLIB =
|
||||
SED = sed
|
||||
STRIP = strip
|
||||
|
||||
####### Output directory
|
||||
|
||||
OBJECTS_DIR = ./
|
||||
|
||||
####### Files
|
||||
|
||||
SOURCES = ../../src/db/dao/accountdao.cpp \
|
||||
../../src/db/databasemanager.cpp \
|
||||
../../src/core/models/account.cpp \
|
||||
test_accountdao.cpp
|
||||
OBJECTS = accountdao.o \
|
||||
databasemanager.o \
|
||||
account.o \
|
||||
test_accountdao.o
|
||||
DIST = /usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/spec_pre.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/unix.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/linux.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/sanitize.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/gcc-base.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/gcc-base-unix.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/g++-base.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/g++-unix.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/qconfig.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_concurrent.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_core.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_core_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_dbus.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_dbus_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_devicediscovery_support_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_eglfs_kms_gbm_support_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_eglfs_kms_support_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_eglfsdeviceintegration_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_example_icons_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_examples_asset_downloader_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_fb_support_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_gui.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_gui_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_input_support_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_kms_support_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_network.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_network_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_opengl.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_opengl_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_openglwidgets.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_printsupport.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_printsupport_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_sql.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_sql_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_testinternals_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_testlib.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_testlib_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_waylandclient.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_waylandclient_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_waylandglobal_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_widgets.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_widgets_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_wl_shell_integration_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_xcb_qpa_lib_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_xml.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_xml_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/qt_functions.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/qt_config.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++/qmake.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/spec_post.prf \
|
||||
.qmake.stash \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/exclusive_builds.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/toolchain.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/default_pre.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/resolve_config.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/default_post.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/warn_on.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/permissions.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/qt.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/resources_functions.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/resources.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/moc.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/testlib_defines.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/unix/opengl.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/unix/thread.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/qmake_use.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/file_copies.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/testcase_targets.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/exceptions.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/yacc.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/lex.prf \
|
||||
test_accountdao.pro ../../src/db/dao/accountdao.cpp \
|
||||
../../src/db/databasemanager.cpp \
|
||||
../../src/core/models/account.cpp \
|
||||
test_accountdao.cpp
|
||||
QMAKE_TARGET = test_accountdao
|
||||
DESTDIR =
|
||||
TARGET = test_accountdao
|
||||
|
||||
|
||||
first: all
|
||||
####### Build rules
|
||||
|
||||
test_accountdao: $(OBJECTS)
|
||||
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
|
||||
|
||||
Makefile: test_accountdao.pro /usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++/qmake.conf /usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/spec_pre.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/unix.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/linux.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/sanitize.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/gcc-base.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/gcc-base-unix.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/g++-base.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/g++-unix.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/qconfig.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_concurrent.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_core.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_core_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_dbus.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_dbus_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_devicediscovery_support_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_eglfs_kms_gbm_support_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_eglfs_kms_support_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_eglfsdeviceintegration_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_example_icons_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_examples_asset_downloader_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_fb_support_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_gui.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_gui_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_input_support_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_kms_support_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_network.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_network_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_opengl.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_opengl_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_openglwidgets.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_printsupport.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_printsupport_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_sql.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_sql_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_testinternals_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_testlib.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_testlib_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_waylandclient.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_waylandclient_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_waylandglobal_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_widgets.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_widgets_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_wl_shell_integration_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_xcb_qpa_lib_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_xml.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_xml_private.pri \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/qt_functions.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/qt_config.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++/qmake.conf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/spec_post.prf \
|
||||
.qmake.stash \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/exclusive_builds.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/toolchain.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/default_pre.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/resolve_config.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/default_post.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/warn_on.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/permissions.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/qt.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/resources_functions.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/resources.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/moc.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/testlib_defines.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/unix/opengl.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/unix/thread.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/qmake_use.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/file_copies.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/testcase_targets.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/exceptions.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/yacc.prf \
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/lex.prf \
|
||||
test_accountdao.pro \
|
||||
/usr/lib/x86_64-linux-gnu/libQt6Gui.prl \
|
||||
/usr/lib/x86_64-linux-gnu/libQt6Test.prl \
|
||||
/usr/lib/x86_64-linux-gnu/libQt6Sql.prl \
|
||||
/usr/lib/x86_64-linux-gnu/libQt6Core.prl
|
||||
$(QMAKE) -o Makefile test_accountdao.pro
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/spec_pre.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/unix.conf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/linux.conf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/sanitize.conf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/gcc-base.conf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/gcc-base-unix.conf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/g++-base.conf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/common/g++-unix.conf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/qconfig.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_concurrent.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_core.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_core_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_dbus.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_dbus_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_devicediscovery_support_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_eglfs_kms_gbm_support_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_eglfs_kms_support_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_eglfsdeviceintegration_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_example_icons_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_examples_asset_downloader_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_fb_support_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_gui.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_gui_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_input_support_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_kms_support_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_network.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_network_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_opengl.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_opengl_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_openglwidgets.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_printsupport.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_printsupport_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_sql.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_sql_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_testinternals_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_testlib.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_testlib_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_waylandclient.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_waylandclient_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_waylandglobal_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_widgets.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_widgets_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_wl_shell_integration_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_xcb_qpa_lib_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_xml.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/modules/qt_lib_xml_private.pri:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/qt_functions.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/qt_config.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++/qmake.conf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/spec_post.prf:
|
||||
.qmake.stash:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/exclusive_builds.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/toolchain.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/default_pre.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/resolve_config.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/default_post.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/warn_on.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/permissions.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/qt.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/resources_functions.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/resources.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/moc.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/testlib_defines.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/unix/opengl.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/unix/thread.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/qmake_use.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/file_copies.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/testcase_targets.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/exceptions.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/yacc.prf:
|
||||
/usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/lex.prf:
|
||||
test_accountdao.pro:
|
||||
/usr/lib/x86_64-linux-gnu/libQt6Gui.prl:
|
||||
/usr/lib/x86_64-linux-gnu/libQt6Test.prl:
|
||||
/usr/lib/x86_64-linux-gnu/libQt6Sql.prl:
|
||||
/usr/lib/x86_64-linux-gnu/libQt6Core.prl:
|
||||
qmake: FORCE
|
||||
@$(QMAKE) -o Makefile test_accountdao.pro
|
||||
|
||||
qmake_all: FORCE
|
||||
|
||||
|
||||
all: Makefile test_accountdao
|
||||
|
||||
dist: distdir FORCE
|
||||
(cd `dirname $(DISTDIR)` && $(TAR) $(DISTNAME).tar $(DISTNAME) && $(COMPRESS) $(DISTNAME).tar) && $(MOVE) `dirname $(DISTDIR)`/$(DISTNAME).tar.gz . && $(DEL_FILE) -r $(DISTDIR)
|
||||
|
||||
distdir: FORCE
|
||||
@test -d $(DISTDIR) || mkdir -p $(DISTDIR)
|
||||
$(COPY_FILE) --parents $(DIST) $(DISTDIR)/
|
||||
$(COPY_FILE) --parents /usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/data/dummy.cpp $(DISTDIR)/
|
||||
$(COPY_FILE) --parents ../../src/db/dao/accountdao.cpp ../../src/db/databasemanager.cpp ../../src/core/models/account.cpp test_accountdao.cpp $(DISTDIR)/
|
||||
|
||||
|
||||
clean: compiler_clean
|
||||
-$(DEL_FILE) $(OBJECTS)
|
||||
-$(DEL_FILE) *~ core *.core
|
||||
|
||||
|
||||
distclean: clean
|
||||
-$(DEL_FILE) $(TARGET)
|
||||
-$(DEL_FILE) .qmake.stash
|
||||
-$(DEL_FILE) Makefile
|
||||
|
||||
|
||||
####### Sub-libraries
|
||||
|
||||
mocclean: compiler_moc_header_clean compiler_moc_objc_header_clean compiler_moc_source_clean
|
||||
|
||||
mocables: compiler_moc_header_make_all compiler_moc_objc_header_make_all compiler_moc_source_make_all
|
||||
|
||||
check: first
|
||||
|
||||
benchmark: first
|
||||
|
||||
compiler_rcc_make_all:
|
||||
compiler_rcc_clean:
|
||||
compiler_moc_predefs_make_all: moc_predefs.h
|
||||
compiler_moc_predefs_clean:
|
||||
-$(DEL_FILE) moc_predefs.h
|
||||
moc_predefs.h: /usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/data/dummy.cpp
|
||||
g++ -pipe -O2 -std=gnu++1z -Wall -Wextra -dM -E -o moc_predefs.h /usr/lib/x86_64-linux-gnu/qt6/mkspecs/features/data/dummy.cpp
|
||||
|
||||
compiler_moc_header_make_all:
|
||||
compiler_moc_header_clean:
|
||||
compiler_moc_objc_header_make_all:
|
||||
compiler_moc_objc_header_clean:
|
||||
compiler_moc_source_make_all: test_accountdao.moc
|
||||
compiler_moc_source_clean:
|
||||
-$(DEL_FILE) test_accountdao.moc
|
||||
test_accountdao.moc: test_accountdao.cpp \
|
||||
../../src/db/dao/accountdao.h \
|
||||
../../src/db/databasemanager.h \
|
||||
../../src/core/models/account.h \
|
||||
moc_predefs.h \
|
||||
/usr/lib/qt6/libexec/moc
|
||||
/usr/lib/qt6/libexec/moc $(DEFINES) --include /mnt/c/Users/javie/wino-mail-dtkqt/tests/unit/moc_predefs.h -I/usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++ -I/mnt/c/Users/javie/wino-mail-dtkqt/tests/unit -I/mnt/c/Users/javie/wino-mail-dtkqt/src -I/mnt/c/Users/javie/wino-mail-dtkqt/src/services -I/mnt/c/Users/javie/wino-mail-dtkqt/src/db -I/mnt/c/Users/javie/wino-mail-dtkqt/src/db/dao -I/mnt/c/Users/javie/wino-mail-dtkqt/src/core -I/mnt/c/Users/javie/wino-mail-dtkqt/src/core/models -I/usr/include/x86_64-linux-gnu/qt6 -I/usr/include/x86_64-linux-gnu/qt6/QtGui -I/usr/include/x86_64-linux-gnu/qt6/QtTest -I/usr/include/x86_64-linux-gnu/qt6/QtSql -I/usr/include/x86_64-linux-gnu/qt6/QtCore -I/usr/include/c++/15 -I/usr/include/x86_64-linux-gnu/c++/15 -I/usr/include/c++/15/backward -I/usr/lib/gcc/x86_64-linux-gnu/15/include -I/usr/local/include -I/usr/include/x86_64-linux-gnu -I/usr/include test_accountdao.cpp -o test_accountdao.moc
|
||||
|
||||
compiler_yacc_decl_make_all:
|
||||
compiler_yacc_decl_clean:
|
||||
compiler_yacc_impl_make_all:
|
||||
compiler_yacc_impl_clean:
|
||||
compiler_lex_make_all:
|
||||
compiler_lex_clean:
|
||||
compiler_clean: compiler_moc_predefs_clean compiler_moc_source_clean
|
||||
|
||||
####### Compile
|
||||
|
||||
accountdao.o: ../../src/db/dao/accountdao.cpp ../../src/db/dao/accountdao.h \
|
||||
../../src/db/databasemanager.h \
|
||||
../../src/core/models/account.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o accountdao.o ../../src/db/dao/accountdao.cpp
|
||||
|
||||
databasemanager.o: ../../src/db/databasemanager.cpp ../../src/db/databasemanager.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o databasemanager.o ../../src/db/databasemanager.cpp
|
||||
|
||||
account.o: ../../src/core/models/account.cpp ../../src/core/models/account.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o account.o ../../src/core/models/account.cpp
|
||||
|
||||
test_accountdao.o: test_accountdao.cpp ../../src/db/dao/accountdao.h \
|
||||
../../src/db/databasemanager.h \
|
||||
../../src/core/models/account.h \
|
||||
test_accountdao.moc
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o test_accountdao.o test_accountdao.cpp
|
||||
|
||||
####### Install
|
||||
|
||||
install: FORCE
|
||||
|
||||
uninstall: FORCE
|
||||
|
||||
FORCE:
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
@@ -0,0 +1,475 @@
|
||||
#define __DBL_MIN_EXP__ (-1021)
|
||||
#define __LDBL_MANT_DIG__ 64
|
||||
#define __cpp_nontype_template_parameter_auto 201606L
|
||||
#define __UINT_LEAST16_MAX__ 0xffff
|
||||
#define __FLT16_HAS_QUIET_NAN__ 1
|
||||
#define __ATOMIC_ACQUIRE 2
|
||||
#define __FLT128_MAX_10_EXP__ 4932
|
||||
#define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F
|
||||
#define __GCC_IEC_559_COMPLEX 2
|
||||
#define __cpp_aggregate_nsdmi 201304L
|
||||
#define __UINT_LEAST8_TYPE__ unsigned char
|
||||
#define __SIZEOF_FLOAT80__ 16
|
||||
#define __BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16
|
||||
#define __INTMAX_C(c) c ## L
|
||||
#define __CHAR_BIT__ 8
|
||||
#define __UINT8_MAX__ 0xff
|
||||
#define __SCHAR_WIDTH__ 8
|
||||
#define __WINT_MAX__ 0xffffffffU
|
||||
#define __FLT32_MIN_EXP__ (-125)
|
||||
#define __cpp_static_assert 201411L
|
||||
#define __BFLT16_MIN_10_EXP__ (-37)
|
||||
#define __cpp_inheriting_constructors 201511L
|
||||
#define __ORDER_LITTLE_ENDIAN__ 1234
|
||||
#define __WCHAR_MAX__ 0x7fffffff
|
||||
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
|
||||
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
|
||||
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
|
||||
#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
|
||||
#define __GCC_IEC_559 2
|
||||
#define __FLT32X_DECIMAL_DIG__ 17
|
||||
#define __FLT_EVAL_METHOD__ 0
|
||||
#define __cpp_binary_literals 201304L
|
||||
#define __FLT64_DECIMAL_DIG__ 17
|
||||
#define __CET__ 3
|
||||
#define __cpp_noexcept_function_type 201510L
|
||||
#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
|
||||
#define __cpp_variadic_templates 200704L
|
||||
#define __UINT_FAST64_MAX__ 0xffffffffffffffffUL
|
||||
#define __SIG_ATOMIC_TYPE__ int
|
||||
#define __DBL_MIN_10_EXP__ (-307)
|
||||
#define __FINITE_MATH_ONLY__ 0
|
||||
#define __cpp_variable_templates 201304L
|
||||
#define __FLT32X_MAX_EXP__ 1024
|
||||
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
|
||||
#define __FLT32_HAS_DENORM__ 1
|
||||
#define __UINT_FAST8_MAX__ 0xff
|
||||
#define __cpp_rvalue_reference 200610L
|
||||
#define __cpp_nested_namespace_definitions 201411L
|
||||
#define __DEC64_MAX_EXP__ 385
|
||||
#define __INT8_C(c) c
|
||||
#define __LDBL_HAS_INFINITY__ 1
|
||||
#define __INT_LEAST8_WIDTH__ 8
|
||||
#define __cpp_variadic_using 201611L
|
||||
#define __UINT_LEAST64_MAX__ 0xffffffffffffffffUL
|
||||
#define __INT_LEAST8_MAX__ 0x7f
|
||||
#define __cpp_attributes 200809L
|
||||
#define __cpp_capture_star_this 201603L
|
||||
#define __SHRT_MAX__ 0x7fff
|
||||
#define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L
|
||||
#define __FLT64X_MAX_10_EXP__ 4932
|
||||
#define __cpp_if_constexpr 201606L
|
||||
#define __BFLT16_MAX_10_EXP__ 38
|
||||
#define __BFLT16_MAX_EXP__ 128
|
||||
#define __LDBL_IS_IEC_60559__ 1
|
||||
#define __FLT64X_HAS_QUIET_NAN__ 1
|
||||
#define __UINT_LEAST8_MAX__ 0xff
|
||||
#define __GCC_ATOMIC_BOOL_LOCK_FREE 2
|
||||
#define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128
|
||||
#define __UINTMAX_TYPE__ long unsigned int
|
||||
#define __cpp_nsdmi 200809L
|
||||
#define __BFLT16_DECIMAL_DIG__ 4
|
||||
#define __linux 1
|
||||
#define __DEC32_EPSILON__ 1E-6DF
|
||||
#define __FLT_EVAL_METHOD_TS_18661_3__ 0
|
||||
#define __OPTIMIZE__ 1
|
||||
#define __UINT32_MAX__ 0xffffffffU
|
||||
#define __GXX_EXPERIMENTAL_CXX0X__ 1
|
||||
#define __DBL_DENORM_MIN__ double(4.94065645841246544176568792868221372e-324L)
|
||||
#define __FLT128_MIN_EXP__ (-16381)
|
||||
#define __DEC64X_MAX_EXP__ 6145
|
||||
#define __WINT_MIN__ 0U
|
||||
#define __FLT128_MIN_10_EXP__ (-4931)
|
||||
#define __FLT32X_IS_IEC_60559__ 1
|
||||
#define __INT_LEAST16_WIDTH__ 16
|
||||
#define __SCHAR_MAX__ 0x7f
|
||||
#define __FLT128_MANT_DIG__ 113
|
||||
#define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
|
||||
#define __INT64_C(c) c ## L
|
||||
#define __SSP_STRONG__ 3
|
||||
#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
|
||||
#define __ATOMIC_SEQ_CST 5
|
||||
#define _FORTIFY_SOURCE 3
|
||||
#define __unix 1
|
||||
#define __INT_LEAST64_MAX__ 0x7fffffffffffffffL
|
||||
#define __FLT32X_MANT_DIG__ 53
|
||||
#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
|
||||
#define __cpp_aligned_new 201606L
|
||||
#define __FLT32_MAX_10_EXP__ 38
|
||||
#define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x
|
||||
#define __STDC_HOSTED__ 1
|
||||
#define __DEC64_MIN_EXP__ (-382)
|
||||
#define __cpp_decltype_auto 201304L
|
||||
#define __DBL_DIG__ 15
|
||||
#define __STDC_EMBED_EMPTY__ 2
|
||||
#define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F
|
||||
#define __GXX_WEAK__ 1
|
||||
#define __SHRT_WIDTH__ 16
|
||||
#define __FLT32_IS_IEC_60559__ 1
|
||||
#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
|
||||
#define __DBL_IS_IEC_60559__ 1
|
||||
#define __DEC32_MAX__ 9.999999E96DF
|
||||
#define __cpp_threadsafe_static_init 200806L
|
||||
#define __cpp_enumerator_attributes 201411L
|
||||
#define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x
|
||||
#define __FLT32X_HAS_INFINITY__ 1
|
||||
#define __unix__ 1
|
||||
#define __INT_WIDTH__ 32
|
||||
#define __STDC_IEC_559__ 1
|
||||
#define __STDC_ISO_10646__ 201706L
|
||||
#define __DECIMAL_DIG__ 21
|
||||
#define __STDC_IEC_559_COMPLEX__ 1
|
||||
#define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64
|
||||
#define __gnu_linux__ 1
|
||||
#define __INT16_MAX__ 0x7fff
|
||||
#define __FLT64_MIN_EXP__ (-1021)
|
||||
#define __DEC64X_EPSILON__ 1E-33D64x
|
||||
#define __FLT64X_MIN_10_EXP__ (-4931)
|
||||
#define __LDBL_HAS_QUIET_NAN__ 1
|
||||
#define __FLT16_MIN_EXP__ (-13)
|
||||
#define __FLT64_MANT_DIG__ 53
|
||||
#define __FLT64X_MANT_DIG__ 64
|
||||
#define __BFLT16_DIG__ 2
|
||||
#define __GNUC__ 15
|
||||
#define __GXX_RTTI 1
|
||||
#define __pie__ 2
|
||||
#define __MMX__ 1
|
||||
#define __FLT_HAS_DENORM__ 1
|
||||
#define __SIZEOF_LONG_DOUBLE__ 16
|
||||
#define __BIGGEST_ALIGNMENT__ 16
|
||||
#define __STDC_UTF_16__ 1
|
||||
#define __FLT64_MAX_10_EXP__ 308
|
||||
#define __BFLT16_IS_IEC_60559__ 0
|
||||
#define __FLT16_MAX_10_EXP__ 4
|
||||
#define __cpp_delegating_constructors 200604L
|
||||
#define __DBL_MAX__ double(1.79769313486231570814527423731704357e+308L)
|
||||
#define __cpp_raw_strings 200710L
|
||||
#define __INT_FAST32_MAX__ 0x7fffffffffffffffL
|
||||
#define __DBL_HAS_INFINITY__ 1
|
||||
#define __INT64_MAX__ 0x7fffffffffffffffL
|
||||
#define __SIZEOF_FLOAT__ 4
|
||||
#define __HAVE_SPECULATION_SAFE_VALUE 1
|
||||
#define __cpp_fold_expressions 201603L
|
||||
#define __DEC32_MIN_EXP__ (-94)
|
||||
#define __INTPTR_WIDTH__ 64
|
||||
#define __UINT_LEAST32_MAX__ 0xffffffffU
|
||||
#define __FLT32X_HAS_DENORM__ 1
|
||||
#define __INT_FAST16_TYPE__ long int
|
||||
#define __MMX_WITH_SSE__ 1
|
||||
#define __LDBL_HAS_DENORM__ 1
|
||||
#define __SEG_GS 1
|
||||
#define __cplusplus 201703L
|
||||
#define __cpp_ref_qualifiers 200710L
|
||||
#define __DEC32_MIN__ 1E-95DF
|
||||
#define __DEPRECATED 1
|
||||
#define __cpp_rvalue_references 200610L
|
||||
#define __DBL_MAX_EXP__ 1024
|
||||
#define __WCHAR_WIDTH__ 32
|
||||
#define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32
|
||||
#define __DEC128_EPSILON__ 1E-33DL
|
||||
#define __FLT16_DECIMAL_DIG__ 5
|
||||
#define __SSE2_MATH__ 1
|
||||
#define __ATOMIC_HLE_RELEASE 131072
|
||||
#define __PTRDIFF_MAX__ 0x7fffffffffffffffL
|
||||
#define __amd64 1
|
||||
#define __DEC64X_MAX__ 9.999999999999999999999999999999999E6144D64x
|
||||
#define __ATOMIC_HLE_ACQUIRE 65536
|
||||
#define __GNUG__ 15
|
||||
#define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
|
||||
#define __SIZEOF_SIZE_T__ 8
|
||||
#define __BFLT16_HAS_INFINITY__ 1
|
||||
#define __FLT64X_MIN_EXP__ (-16381)
|
||||
#define __SIZEOF_WINT_T__ 4
|
||||
#define __FLT32X_DIG__ 15
|
||||
#define __LONG_LONG_WIDTH__ 64
|
||||
#define __cpp_initializer_lists 200806L
|
||||
#define __FLT32_MAX_EXP__ 128
|
||||
#define __cpp_hex_float 201603L
|
||||
#define __GXX_ABI_VERSION 1020
|
||||
#define __FLT_MIN_EXP__ (-125)
|
||||
#define __GCC_HAVE_DWARF2_CFI_ASM 1
|
||||
#define __x86_64 1
|
||||
#define __cpp_lambdas 200907L
|
||||
#define __INT_FAST64_TYPE__ long int
|
||||
#define __BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16
|
||||
#define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64
|
||||
#define __cpp_template_auto 201606L
|
||||
#define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16
|
||||
#define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128
|
||||
#define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x
|
||||
#define __SIZEOF_POINTER__ 8
|
||||
#define __SIZE_TYPE__ long unsigned int
|
||||
#define __LP64__ 1
|
||||
#define __DBL_HAS_QUIET_NAN__ 1
|
||||
#define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x
|
||||
#define __LDBL_MAX_EXP__ 16384
|
||||
#define __DECIMAL_BID_FORMAT__ 1
|
||||
#define __FLT64_MIN_10_EXP__ (-307)
|
||||
#define __FLT16_MIN_10_EXP__ (-4)
|
||||
#define __FLT64X_DECIMAL_DIG__ 21
|
||||
#define __DEC128_MIN__ 1E-6143DL
|
||||
#define __REGISTER_PREFIX__
|
||||
#define __UINT16_MAX__ 0xffff
|
||||
#define __FLT128_HAS_INFINITY__ 1
|
||||
#define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32
|
||||
#define __UINT8_TYPE__ unsigned char
|
||||
#define __FLT_DIG__ 6
|
||||
#define __DEC_EVAL_METHOD__ 2
|
||||
#define __FLT_MANT_DIG__ 24
|
||||
#define __LDBL_DECIMAL_DIG__ 21
|
||||
#define __VERSION__ "15.2.0"
|
||||
#define __UINT64_C(c) c ## UL
|
||||
#define __cpp_unicode_characters 201411L
|
||||
#define __DEC64X_MIN__ 1E-6143D64x
|
||||
#define _STDC_PREDEF_H 1
|
||||
#define __INT_LEAST32_MAX__ 0x7fffffff
|
||||
#define __GCC_ATOMIC_INT_LOCK_FREE 2
|
||||
#define __FLT128_MAX_EXP__ 16384
|
||||
#define __FLT32_MANT_DIG__ 24
|
||||
#define __cpp_decltype 200707L
|
||||
#define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
#define __FLT32X_MIN_EXP__ (-1021)
|
||||
#define __STDC_IEC_60559_COMPLEX__ 201404L
|
||||
#define __cpp_aggregate_bases 201603L
|
||||
#define __BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16
|
||||
#define __FLT128_HAS_DENORM__ 1
|
||||
#define __FLT32_DECIMAL_DIG__ 9
|
||||
#define __FLT128_DIG__ 33
|
||||
#define __INT32_C(c) c
|
||||
#define __DEC64_EPSILON__ 1E-15DD
|
||||
#define __ORDER_PDP_ENDIAN__ 3412
|
||||
#define __DEC128_MIN_EXP__ (-6142)
|
||||
#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
|
||||
#define __INT_FAST32_TYPE__ long int
|
||||
#define __UINT_LEAST16_TYPE__ short unsigned int
|
||||
#define __DEC64X_MANT_DIG__ 34
|
||||
#define __DEC128_MAX_EXP__ 6145
|
||||
#define unix 1
|
||||
#define __DBL_HAS_DENORM__ 1
|
||||
#define __cpp_rtti 199711L
|
||||
#define __UINT64_MAX__ 0xffffffffffffffffUL
|
||||
#define __FLT_IS_IEC_60559__ 1
|
||||
#define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE"
|
||||
#define __FLT64X_DIG__ 18
|
||||
#define __INT8_TYPE__ signed char
|
||||
#define __cpp_digit_separators 201309L
|
||||
#define __ELF__ 1
|
||||
#define __GCC_ASM_FLAG_OUTPUTS__ 1
|
||||
#define __UINT32_TYPE__ unsigned int
|
||||
#define __BFLT16_HAS_QUIET_NAN__ 1
|
||||
#define __FLT_RADIX__ 2
|
||||
#define __INT_LEAST16_TYPE__ short int
|
||||
#define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L
|
||||
#define __UINTMAX_C(c) c ## UL
|
||||
#define __FLT16_DIG__ 3
|
||||
#define __k8 1
|
||||
#define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x
|
||||
#define __SIG_ATOMIC_MAX__ 0x7fffffff
|
||||
#define __cpp_constexpr 201603L
|
||||
#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
|
||||
#define __USER_LABEL_PREFIX__
|
||||
#define __STDC_IEC_60559_BFP__ 201404L
|
||||
#define __SIZEOF_PTRDIFF_T__ 8
|
||||
#define __FLT64X_HAS_INFINITY__ 1
|
||||
#define __SIZEOF_LONG__ 8
|
||||
#define __LDBL_DIG__ 18
|
||||
#define __FLT64_IS_IEC_60559__ 1
|
||||
#define __x86_64__ 1
|
||||
#define __FLT16_IS_IEC_60559__ 1
|
||||
#define __FLT16_MAX_EXP__ 16
|
||||
#define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
|
||||
#define __STDC_EMBED_FOUND__ 1
|
||||
#define __INT_FAST16_MAX__ 0x7fffffffffffffffL
|
||||
#define __GCC_CONSTRUCTIVE_SIZE 64
|
||||
#define __FLT64_DIG__ 15
|
||||
#define __UINT_FAST32_MAX__ 0xffffffffffffffffUL
|
||||
#define __UINT_LEAST64_TYPE__ long unsigned int
|
||||
#define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16
|
||||
#define __FLT_HAS_QUIET_NAN__ 1
|
||||
#define __FLT_MAX_10_EXP__ 38
|
||||
#define __FLT64X_HAS_DENORM__ 1
|
||||
#define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
|
||||
#define __FLT_HAS_INFINITY__ 1
|
||||
#define __GNUC_EXECUTION_CHARSET_NAME "UTF-8"
|
||||
#define __cpp_unicode_literals 200710L
|
||||
#define __UINT_FAST16_TYPE__ long unsigned int
|
||||
#define __DEC64_MAX__ 9.999999999999999E384DD
|
||||
#define __STDC_EMBED_NOT_FOUND__ 0
|
||||
#define __INT_FAST32_WIDTH__ 64
|
||||
#define __CHAR16_TYPE__ short unsigned int
|
||||
#define __PRAGMA_REDEFINE_EXTNAME 1
|
||||
#define __DEC64X_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143D64x
|
||||
#define __SIZE_WIDTH__ 64
|
||||
#define __SEG_FS 1
|
||||
#define __INT_LEAST16_MAX__ 0x7fff
|
||||
#define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16
|
||||
#define __DEC64_MANT_DIG__ 16
|
||||
#define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32
|
||||
#define __SIG_ATOMIC_WIDTH__ 32
|
||||
#define __INT_LEAST64_TYPE__ long int
|
||||
#define __INT16_TYPE__ short int
|
||||
#define __INT_LEAST8_TYPE__ signed char
|
||||
#define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16
|
||||
#define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128
|
||||
#define __cpp_structured_bindings 201606L
|
||||
#define __SIZEOF_INT__ 4
|
||||
#define __DEC32_MAX_EXP__ 97
|
||||
#define __BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16
|
||||
#define __INT_FAST8_MAX__ 0x7f
|
||||
#define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128
|
||||
#define __INTPTR_MAX__ 0x7fffffffffffffffL
|
||||
#define __cpp_sized_deallocation 201309L
|
||||
#define __cpp_guaranteed_copy_elision 201606L
|
||||
#define linux 1
|
||||
#define __FLT64_HAS_QUIET_NAN__ 1
|
||||
#define __FLT32_MIN_10_EXP__ (-37)
|
||||
#define __EXCEPTIONS 1
|
||||
#define __UINT16_C(c) c
|
||||
#define __PTRDIFF_WIDTH__ 64
|
||||
#define __cpp_range_based_for 201603L
|
||||
#define __INT_FAST16_WIDTH__ 64
|
||||
#define __FLT64_HAS_INFINITY__ 1
|
||||
#define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x
|
||||
#define __FLT16_HAS_INFINITY__ 1
|
||||
#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16
|
||||
#define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
|
||||
#define __code_model_small__ 1
|
||||
#define __GCC_ATOMIC_LONG_LOCK_FREE 2
|
||||
#define __cpp_nontype_template_args 201411L
|
||||
#define __DEC32_MANT_DIG__ 7
|
||||
#define __k8__ 1
|
||||
#define __INTPTR_TYPE__ long int
|
||||
#define __UINT16_TYPE__ short unsigned int
|
||||
#define __WCHAR_TYPE__ int
|
||||
#define __pic__ 2
|
||||
#define __UINTPTR_MAX__ 0xffffffffffffffffUL
|
||||
#define __INT_FAST64_WIDTH__ 64
|
||||
#define __INT_FAST64_MAX__ 0x7fffffffffffffffL
|
||||
#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
|
||||
#define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F
|
||||
#define __FLT32_HAS_INFINITY__ 1
|
||||
#define __FLT64X_MAX_EXP__ 16384
|
||||
#define __UINT_FAST64_TYPE__ long unsigned int
|
||||
#define __cpp_inline_variables 201606L
|
||||
#define __BFLT16_MIN_EXP__ (-125)
|
||||
#define __INT_MAX__ 0x7fffffff
|
||||
#define __linux__ 1
|
||||
#define __INT64_TYPE__ long int
|
||||
#define __FLT_MAX_EXP__ 128
|
||||
#define __ORDER_BIG_ENDIAN__ 4321
|
||||
#define __DBL_MANT_DIG__ 53
|
||||
#define __SIZEOF_FLOAT128__ 16
|
||||
#define __BFLT16_MANT_DIG__ 8
|
||||
#define __DEC64_MIN__ 1E-383DD
|
||||
#define __WINT_TYPE__ unsigned int
|
||||
#define __UINT_LEAST32_TYPE__ unsigned int
|
||||
#define __SIZEOF_SHORT__ 2
|
||||
#define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32
|
||||
#define __SSE__ 1
|
||||
#define __LDBL_MIN_EXP__ (-16381)
|
||||
#define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64
|
||||
#define __DEC64X_MIN_EXP__ (-6142)
|
||||
#define __amd64__ 1
|
||||
#define __WINT_WIDTH__ 32
|
||||
#define __INT_LEAST64_WIDTH__ 64
|
||||
#define __FLT32X_MAX_10_EXP__ 308
|
||||
#define __cpp_namespace_attributes 201411L
|
||||
#define __SIZEOF_INT128__ 16
|
||||
#define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16
|
||||
#define __FLT64X_IS_IEC_60559__ 1
|
||||
#define __GXX_CONSTEXPR_ASM__ 1
|
||||
#define __LDBL_MAX_10_EXP__ 4932
|
||||
#define __ATOMIC_RELAXED 0
|
||||
#define __DBL_EPSILON__ double(2.22044604925031308084726333618164062e-16L)
|
||||
#define __INT_LEAST32_TYPE__ int
|
||||
#define _LP64 1
|
||||
#define __UINT8_C(c) c
|
||||
#define __FLT64_MAX_EXP__ 1024
|
||||
#define __cpp_return_type_deduction 201304L
|
||||
#define __SIZEOF_WCHAR_T__ 4
|
||||
#define __GNUC_PATCHLEVEL__ 0
|
||||
#define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128
|
||||
#define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64
|
||||
#define __FLT128_HAS_QUIET_NAN__ 1
|
||||
#define __INTMAX_MAX__ 0x7fffffffffffffffL
|
||||
#define __INT_FAST8_TYPE__ signed char
|
||||
#define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x
|
||||
#define __STDCPP_THREADS__ 1
|
||||
#define __BFLT16_HAS_DENORM__ 1
|
||||
#define __GNUC_STDC_INLINE__ 1
|
||||
#define __FLT64_HAS_DENORM__ 1
|
||||
#define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32
|
||||
#define __FLT16_HAS_DENORM__ 1
|
||||
#define __DBL_DECIMAL_DIG__ 17
|
||||
#define __STDC_UTF_32__ 1
|
||||
#define __INT_FAST8_WIDTH__ 8
|
||||
#define __FXSR__ 1
|
||||
#define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x
|
||||
#define __DBL_NORM_MAX__ double(1.79769313486231570814527423731704357e+308L)
|
||||
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
#define __GCC_DESTRUCTIVE_SIZE 64
|
||||
#define __INTMAX_WIDTH__ 64
|
||||
#define __cpp_runtime_arrays 198712L
|
||||
#define __FLT32_DIG__ 6
|
||||
#define __UINT64_TYPE__ long unsigned int
|
||||
#define __UINT32_C(c) c ## U
|
||||
#define __cpp_alias_templates 200704L
|
||||
#define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F
|
||||
#define __FLT128_IS_IEC_60559__ 1
|
||||
#define __INT8_MAX__ 0x7f
|
||||
#define __LONG_WIDTH__ 64
|
||||
#define __DBL_MIN__ double(2.22507385850720138309023271733240406e-308L)
|
||||
#define __PIC__ 2
|
||||
#define __INT32_MAX__ 0x7fffffff
|
||||
#define __UINT_FAST32_TYPE__ long unsigned int
|
||||
#define __FLT16_MANT_DIG__ 11
|
||||
#define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x
|
||||
#define __CHAR32_TYPE__ unsigned int
|
||||
#define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F
|
||||
#define __SSE2__ 1
|
||||
#define __cpp_deduction_guides 201703L
|
||||
#define __BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16
|
||||
#define __INT32_TYPE__ int
|
||||
#define __SIZEOF_DOUBLE__ 8
|
||||
#define __cpp_exceptions 199711L
|
||||
#define __FLT_MIN_10_EXP__ (-37)
|
||||
#define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64
|
||||
#define __INT_LEAST32_WIDTH__ 32
|
||||
#define __INTMAX_TYPE__ long int
|
||||
#define __GLIBCXX_BITSIZE_INT_N_0 128
|
||||
#define __FLT32X_HAS_QUIET_NAN__ 1
|
||||
#define __ATOMIC_CONSUME 1
|
||||
#define __GNUC_MINOR__ 2
|
||||
#define __GLIBCXX_TYPE_INT_N_0 __int128
|
||||
#define __UINTMAX_MAX__ 0xffffffffffffffffUL
|
||||
#define __PIE__ 2
|
||||
#define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x
|
||||
#define __cpp_template_template_args 201611L
|
||||
#define __DBL_MAX_10_EXP__ 308
|
||||
#define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L
|
||||
#define __INT16_C(c) c
|
||||
#define __STDC__ 1
|
||||
#define __PTRDIFF_TYPE__ long int
|
||||
#define __LONG_MAX__ 0x7fffffffffffffffL
|
||||
#define __FLT32X_MIN_10_EXP__ (-307)
|
||||
#define __UINTPTR_TYPE__ long unsigned int
|
||||
#define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
|
||||
#define __DEC128_MANT_DIG__ 34
|
||||
#define __LDBL_MIN_10_EXP__ (-4931)
|
||||
#define __cpp_generic_lambdas 201304L
|
||||
#define __SSE_MATH__ 1
|
||||
#define __SIZEOF_LONG_LONG__ 8
|
||||
#define __cpp_user_defined_literals 200809L
|
||||
#define __FLT128_DECIMAL_DIG__ 36
|
||||
#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
|
||||
#define __FLT32_HAS_QUIET_NAN__ 1
|
||||
#define __FLT_DECIMAL_DIG__ 9
|
||||
#define __UINT_FAST16_MAX__ 0xffffffffffffffffUL
|
||||
#define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L
|
||||
#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
|
||||
#define __SIZE_MAX__ 0xffffffffffffffffUL
|
||||
#define __UINT_FAST8_TYPE__ unsigned char
|
||||
#define _GNU_SOURCE 1
|
||||
#define __cpp_init_captures 201304L
|
||||
#define __ATOMIC_ACQ_REL 4
|
||||
#define __ATOMIC_RELEASE 3
|
||||
Binary file not shown.
+109
-52
@@ -2,6 +2,8 @@
|
||||
#include "../../src/db/dao/accountdao.h"
|
||||
#include "../../src/db/databasemanager.h"
|
||||
#include "../../src/core/models/account.h"
|
||||
#include <QtSql/QSqlDatabase>
|
||||
#include <QtSql/QSqlQuery>
|
||||
|
||||
class TestAccountDao : public QObject
|
||||
{
|
||||
@@ -16,90 +18,145 @@ private slots:
|
||||
|
||||
void TestAccountDao::initTestCase()
|
||||
{
|
||||
DatabaseManager::instance().openDatabase(":memory:");
|
||||
DatabaseManager::instance().createTables();
|
||||
// Use in-memory SQLite database
|
||||
// Ensure fresh connection by removing previous connection
|
||||
QSqlDatabase::removeDatabase(QStringLiteral("wino_mail_connection"));
|
||||
QVERIFY(DatabaseManager::instance().initialize(QStringLiteral(":memory:")));
|
||||
// Create tables (initialize will do it)
|
||||
}
|
||||
|
||||
void TestAccountDao::cleanupTestCase()
|
||||
{
|
||||
DatabaseManager::instance().closeDatabase();
|
||||
// Database will be closed automatically in destructor
|
||||
}
|
||||
|
||||
void TestAccountDao::testInsertAndFind()
|
||||
{
|
||||
Account account;
|
||||
account.setEmail("test@example.com");
|
||||
account.setProvider("IMAP");
|
||||
account.setHost("imap.example.com");
|
||||
account.setPort(993);
|
||||
account.setUsername("testuser");
|
||||
account.setPassword("testpass");
|
||||
account.setUseSsl(true);
|
||||
account.setEmail(QStringLiteral("test@example.com"));
|
||||
account.setDisplayName(QStringLiteral("Test User"));
|
||||
account.setSignature(QStringLiteral("Test sig"));
|
||||
account.setType(AccountType::IMAP);
|
||||
|
||||
bool inserted = AccountDao::insert(account);
|
||||
QVERIFY(inserted);
|
||||
QVERIFY(account.id() > 0);
|
||||
Account::ConnectionSettings settings;
|
||||
settings.type = QStringLiteral("imap");
|
||||
settings.incomingHost = QStringLiteral("imap.example.com");
|
||||
settings.incomingPort = 993;
|
||||
settings.incomingSsl = true;
|
||||
settings.outgoingHost = QStringLiteral("smtp.example.com");
|
||||
settings.outgoingPort = 465;
|
||||
settings.outgoingSsl = true;
|
||||
settings.username = QStringLiteral("testuser");
|
||||
settings.password = QStringLiteral("testpass");
|
||||
settings.authMethod = QStringLiteral("plain");
|
||||
account.setConnectionSettings(settings);
|
||||
|
||||
Account found = AccountDao::findById(account.id());
|
||||
QVERIFY(found.isValid());
|
||||
QCOMPARE(found.email(), QString("test@example.com"));
|
||||
QCOMPARE(found.provider(), QString("IMAP"));
|
||||
QCOMPARE(found.host(), QString("imap.example.com"));
|
||||
QCOMPARE(found.port(), 993);
|
||||
QCOMPARE(found.username(), QString("testuser"));
|
||||
QCOMPARE(found.password(), QString("testpass"));
|
||||
QVERIFY(found.useSsl());
|
||||
qint64 insertedId = AccountDao::insert(account);
|
||||
QVERIFY(insertedId != -1);
|
||||
// Optionally set id on account for later use (if needed)
|
||||
// account.setId(insertedId);
|
||||
|
||||
Account* foundPtr = AccountDao::findById(insertedId);
|
||||
QVERIFY(foundPtr != nullptr);
|
||||
Account found = *foundPtr;
|
||||
QCOMPARE(found.id(), insertedId);
|
||||
QCOMPARE(found.email(), QStringLiteral("test@example.com"));
|
||||
QCOMPARE(found.displayName(), QStringLiteral("Test User"));
|
||||
QCOMPARE(found.signature(), QStringLiteral("Test sig"));
|
||||
QCOMPARE(found.type(), AccountType::IMAP);
|
||||
QCOMPARE(found.connectionSettings().incomingHost, QStringLiteral("imap.example.com"));
|
||||
QCOMPARE(found.connectionSettings().incomingPort, 993);
|
||||
QVERIFY(found.connectionSettings().incomingSsl);
|
||||
QCOMPARE(found.connectionSettings().username, QStringLiteral("testuser"));
|
||||
QCOMPARE(found.connectionSettings().password, QStringLiteral("testpass"));
|
||||
QCOMPARE(found.connectionSettings().authMethod, QStringLiteral("plain"));
|
||||
}
|
||||
|
||||
void TestAccountDao::testUpdate()
|
||||
{
|
||||
Account account;
|
||||
account.setEmail("original@example.com");
|
||||
account.setProvider("IMAP");
|
||||
account.setHost("imap.example.com");
|
||||
account.setPort(993);
|
||||
account.setUsername("user");
|
||||
account.setPassword("pass");
|
||||
account.setUseSsl(true);
|
||||
account.setEmail(QStringLiteral("original@example.com"));
|
||||
account.setDisplayName(QStringLiteral("Original User"));
|
||||
account.setType(AccountType::IMAP);
|
||||
Account::ConnectionSettings settings;
|
||||
settings.type = QStringLiteral("imap");
|
||||
settings.incomingHost = QStringLiteral("imap.example.com");
|
||||
settings.incomingPort = 993;
|
||||
settings.incomingSsl = true;
|
||||
settings.outgoingHost = QStringLiteral("smtp.example.com");
|
||||
settings.outgoingPort = 465;
|
||||
settings.outgoingSsl = true;
|
||||
settings.username = QStringLiteral("user");
|
||||
settings.password = QStringLiteral("pass");
|
||||
settings.authMethod = QStringLiteral("plain");
|
||||
account.setConnectionSettings(settings);
|
||||
|
||||
bool inserted = AccountDao::insert(account);
|
||||
QVERIFY(inserted);
|
||||
qint64 id = account.id();
|
||||
qint64 insertedId = AccountDao::insert(account);
|
||||
QVERIFY(insertedId != -1);
|
||||
qint64 id = insertedId;
|
||||
|
||||
account.setEmail("updated@example.com");
|
||||
account.setProvider("Gmail");
|
||||
account.setUseSsl(false);
|
||||
// Modify
|
||||
account.setEmail(QStringLiteral("updated@example.com"));
|
||||
account.setDisplayName(QStringLiteral("Updated User"));
|
||||
account.setType(AccountType::Gmail);
|
||||
Account::ConnectionSettings newSettings;
|
||||
newSettings.type = QStringLiteral("imap");
|
||||
newSettings.incomingHost = QStringLiteral("imap.gmail.com");
|
||||
newSettings.incomingPort = 993;
|
||||
newSettings.incomingSsl = true;
|
||||
newSettings.outgoingHost = QStringLiteral("smtp.gmail.com");
|
||||
newSettings.outgoingPort = 465;
|
||||
newSettings.outgoingSsl = true;
|
||||
newSettings.username = QStringLiteral("user2");
|
||||
newSettings.password = QStringLiteral("newpass");
|
||||
newSettings.authMethod = QStringLiteral("plain");
|
||||
account.setConnectionSettings(newSettings);
|
||||
|
||||
bool updated = AccountDao::update(account);
|
||||
QVERIFY(updated);
|
||||
|
||||
Account found = AccountDao::findById(id);
|
||||
QVERIFY(found.isValid());
|
||||
QCOMPARE(found.email(), QString("updated@example.com"));
|
||||
QCOMPARE(found.provider(), QString("Gmail"));
|
||||
QVERIFY(!found.useSsl());
|
||||
Account* foundPtr = AccountDao::findById(id);
|
||||
QVERIFY(foundPtr != nullptr);
|
||||
Account found = *foundPtr;
|
||||
QCOMPARE(found.id(), id);
|
||||
QCOMPARE(found.email(), QStringLiteral("updated@example.com"));
|
||||
QCOMPARE(found.displayName(), QStringLiteral("Updated User"));
|
||||
QCOMPARE(found.type(), AccountType::Gmail);
|
||||
QCOMPARE(found.connectionSettings().incomingHost, QStringLiteral("imap.gmail.com"));
|
||||
QCOMPARE(found.connectionSettings().incomingPort, 993);
|
||||
QVERIFY(found.connectionSettings().incomingSsl);
|
||||
QCOMPARE(found.connectionSettings().username, QStringLiteral("user2"));
|
||||
QCOMPARE(found.connectionSettings().password, QStringLiteral("newpass"));
|
||||
QCOMPARE(found.connectionSettings().authMethod, QStringLiteral("plain"));
|
||||
}
|
||||
|
||||
void TestAccountDao::testRemove()
|
||||
{
|
||||
Account account;
|
||||
account.setEmail("todelete@example.com");
|
||||
account.setProvider("IMAP");
|
||||
account.setHost("imap.example.com");
|
||||
account.setPort(993);
|
||||
account.setUsername("user");
|
||||
account.setPassword("pass");
|
||||
account.setUseSsl(true);
|
||||
account.setEmail(QStringLiteral("todelete@example.com"));
|
||||
account.setType(AccountType::IMAP);
|
||||
Account::ConnectionSettings settings;
|
||||
settings.type = QStringLiteral("imap");
|
||||
settings.incomingHost = QStringLiteral("imap.example.com");
|
||||
settings.incomingPort = 993;
|
||||
settings.incomingSsl = true;
|
||||
settings.outgoingHost = QStringLiteral("smtp.example.com");
|
||||
settings.outgoingPort = 465;
|
||||
settings.outgoingSsl = true;
|
||||
settings.username = QStringLiteral("user");
|
||||
settings.password = QStringLiteral("pass");
|
||||
settings.authMethod = QStringLiteral("plain");
|
||||
account.setConnectionSettings(settings);
|
||||
|
||||
bool inserted = AccountDao::insert(account);
|
||||
QVERIFY(inserted);
|
||||
qint64 id = account.id();
|
||||
qint64 insertedId = AccountDao::insert(account);
|
||||
QVERIFY(insertedId != -1);
|
||||
qint64 id = insertedId;
|
||||
|
||||
bool removed = AccountDao::remove(id);
|
||||
QVERIFY(removed);
|
||||
|
||||
Account found = AccountDao::findById(id);
|
||||
QVERIFY(!found.isValid());
|
||||
Account* foundPtr = AccountDao::findById(id);
|
||||
QVERIFY(foundPtr == nullptr);
|
||||
}
|
||||
|
||||
QTEST_MAIN(TestAccountDao)
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/****************************************************************************
|
||||
** Meta object code from reading C++ file 'test_accountdao.cpp'
|
||||
**
|
||||
** Created by: The Qt Meta Object Compiler version 69 (Qt 6.10.2)
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
#include <QtCore/qmetatype.h>
|
||||
|
||||
#include <QtCore/qtmochelpers.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
#include <QtCore/qxptype_traits.h>
|
||||
#if !defined(Q_MOC_OUTPUT_REVISION)
|
||||
#error "The header file 'test_accountdao.cpp' doesn't include <QObject>."
|
||||
#elif Q_MOC_OUTPUT_REVISION != 69
|
||||
#error "This file was generated using the moc from 6.10.2. It"
|
||||
#error "cannot be used with the include files from this version of Qt."
|
||||
#error "(The moc has changed too much.)"
|
||||
#endif
|
||||
|
||||
#ifndef Q_CONSTINIT
|
||||
#define Q_CONSTINIT
|
||||
#endif
|
||||
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
QT_WARNING_DISABLE_GCC("-Wuseless-cast")
|
||||
namespace {
|
||||
struct qt_meta_tag_ZN14TestAccountDaoE_t {};
|
||||
} // unnamed namespace
|
||||
|
||||
template <> constexpr inline auto TestAccountDao::qt_create_metaobjectdata<qt_meta_tag_ZN14TestAccountDaoE_t>()
|
||||
{
|
||||
namespace QMC = QtMocConstants;
|
||||
QtMocHelpers::StringRefStorage qt_stringData {
|
||||
"TestAccountDao",
|
||||
"initTestCase",
|
||||
"",
|
||||
"cleanupTestCase",
|
||||
"testInsertAndFind",
|
||||
"testUpdate",
|
||||
"testRemove"
|
||||
};
|
||||
|
||||
QtMocHelpers::UintData qt_methods {
|
||||
// Slot 'initTestCase'
|
||||
QtMocHelpers::SlotData<void()>(1, 2, QMC::AccessPrivate, QMetaType::Void),
|
||||
// Slot 'cleanupTestCase'
|
||||
QtMocHelpers::SlotData<void()>(3, 2, QMC::AccessPrivate, QMetaType::Void),
|
||||
// Slot 'testInsertAndFind'
|
||||
QtMocHelpers::SlotData<void()>(4, 2, QMC::AccessPrivate, QMetaType::Void),
|
||||
// Slot 'testUpdate'
|
||||
QtMocHelpers::SlotData<void()>(5, 2, QMC::AccessPrivate, QMetaType::Void),
|
||||
// Slot 'testRemove'
|
||||
QtMocHelpers::SlotData<void()>(6, 2, QMC::AccessPrivate, QMetaType::Void),
|
||||
};
|
||||
QtMocHelpers::UintData qt_properties {
|
||||
};
|
||||
QtMocHelpers::UintData qt_enums {
|
||||
};
|
||||
return QtMocHelpers::metaObjectData<TestAccountDao, qt_meta_tag_ZN14TestAccountDaoE_t>(QMC::MetaObjectFlag{}, qt_stringData,
|
||||
qt_methods, qt_properties, qt_enums);
|
||||
}
|
||||
Q_CONSTINIT const QMetaObject TestAccountDao::staticMetaObject = { {
|
||||
QMetaObject::SuperData::link<QObject::staticMetaObject>(),
|
||||
qt_staticMetaObjectStaticContent<qt_meta_tag_ZN14TestAccountDaoE_t>.stringdata,
|
||||
qt_staticMetaObjectStaticContent<qt_meta_tag_ZN14TestAccountDaoE_t>.data,
|
||||
qt_static_metacall,
|
||||
nullptr,
|
||||
qt_staticMetaObjectRelocatingContent<qt_meta_tag_ZN14TestAccountDaoE_t>.metaTypes,
|
||||
nullptr
|
||||
} };
|
||||
|
||||
void TestAccountDao::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
auto *_t = static_cast<TestAccountDao *>(_o);
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
switch (_id) {
|
||||
case 0: _t->initTestCase(); break;
|
||||
case 1: _t->cleanupTestCase(); break;
|
||||
case 2: _t->testInsertAndFind(); break;
|
||||
case 3: _t->testUpdate(); break;
|
||||
case 4: _t->testRemove(); break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
(void)_a;
|
||||
}
|
||||
|
||||
const QMetaObject *TestAccountDao::metaObject() const
|
||||
{
|
||||
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
|
||||
}
|
||||
|
||||
void *TestAccountDao::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return nullptr;
|
||||
if (!strcmp(_clname, qt_staticMetaObjectStaticContent<qt_meta_tag_ZN14TestAccountDaoE_t>.strings))
|
||||
return static_cast<void*>(this);
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
||||
int TestAccountDao::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
_id = QObject::qt_metacall(_c, _id, _a);
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 5)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 5;
|
||||
}
|
||||
if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
|
||||
if (_id < 5)
|
||||
*reinterpret_cast<QMetaType *>(_a[0]) = QMetaType();
|
||||
_id -= 5;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
QT_WARNING_POP
|
||||
@@ -0,0 +1,7 @@
|
||||
QT += core testlib sql
|
||||
CONFIG += console c++17
|
||||
SOURCES += ../../src/db/dao/accountdao.cpp \
|
||||
../../src/db/databasemanager.cpp \
|
||||
../../src/core/models/account.cpp \
|
||||
test_accountdao.cpp
|
||||
INCLUDEPATH += ../../src ../../src/services ../../src/db ../../src/db/dao ../../src/core ../../src/core/models
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <QtTest/QtTest>
|
||||
#include <QFile>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include "services/mimestorage.h"
|
||||
|
||||
class TestMimeStorage : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void storesRawMessageAndDecodedAttachments();
|
||||
};
|
||||
|
||||
void TestMimeStorage::storesRawMessageAndDecodedAttachments()
|
||||
{
|
||||
QStandardPaths::setTestModeEnabled(true);
|
||||
const QByteArray rawMime =
|
||||
"Message-ID: <mime-test@example.com>\r\n"
|
||||
"From: =?UTF-8?B?Sm9zw6k=?= <sender@example.com>\r\n"
|
||||
"To: receiver@example.com\r\n"
|
||||
"Subject: =?UTF-8?Q?Informe_de_prueba?=\r\n"
|
||||
"Date: Tue, 11 Aug 2026 12:00:00 +0000\r\n"
|
||||
"MIME-Version: 1.0\r\n"
|
||||
"Content-Type: multipart/mixed; boundary=\"wino-boundary\"\r\n"
|
||||
"\r\n"
|
||||
"--wino-boundary\r\n"
|
||||
"Content-Type: text/html; charset=UTF-8\r\n"
|
||||
"Content-Transfer-Encoding: 8bit\r\n"
|
||||
"\r\n"
|
||||
"<p>Contenido completo</p>\r\n"
|
||||
"--wino-boundary\r\n"
|
||||
"Content-Type: application/octet-stream; name=\"datos.bin\"\r\n"
|
||||
"Content-Disposition: attachment; filename=\"datos.bin\"\r\n"
|
||||
"Content-Transfer-Encoding: base64\r\n"
|
||||
"\r\n"
|
||||
"AAECAwQF\r\n"
|
||||
"--wino-boundary--\r\n";
|
||||
|
||||
MimeStorageService storage;
|
||||
ParsedMimeMessage parsed;
|
||||
QVERIFY(storage.parseMessage(rawMime, parsed));
|
||||
QCOMPARE(parsed.subject, QStringLiteral("Informe de prueba"));
|
||||
QCOMPARE(parsed.attachments.size(), 1);
|
||||
QCOMPARE(parsed.attachments.first().fileName, QStringLiteral("datos.bin"));
|
||||
QCOMPARE(parsed.attachments.first().data, QByteArray::fromHex("000102030405"));
|
||||
|
||||
MailItem item;
|
||||
item.setMessageId(QStringLiteral("mime-test@example.com"));
|
||||
QVector<QString> attachmentPaths;
|
||||
QVERIFY(storage.storeMessage(QStringLiteral("account-test"), QStringLiteral("inbox"),
|
||||
item, rawMime, &attachmentPaths));
|
||||
QVERIFY(!item.fileId().isEmpty());
|
||||
QCOMPARE(storage.readEmlFile(item.fileId()), rawMime);
|
||||
QCOMPARE(item.attachments(), QVector<QString>{QStringLiteral("datos.bin")});
|
||||
QCOMPARE(attachmentPaths.size(), 1);
|
||||
|
||||
QFile attachment(attachmentPaths.first());
|
||||
QVERIFY(attachment.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(attachment.readAll(), QByteArray::fromHex("000102030405"));
|
||||
QVERIFY(storage.getEmlFilePath(item.fileId()).endsWith(QStringLiteral(".eml")));
|
||||
}
|
||||
|
||||
QTEST_MAIN(TestMimeStorage)
|
||||
#include "test_mimestorage.moc"
|
||||
Reference in New Issue
Block a user