diff --git a/CMakeLists.txt b/CMakeLists.txt index be32738..b1c220f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/PLAN.md b/PLAN.md deleted file mode 100644 index e131375..0000000 --- a/PLAN.md +++ /dev/null @@ -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) diff --git a/src/ui/maillistview.cpp b/src/ui/maillistview.cpp index 5ca0162..b494f49 100644 --- a/src/ui/maillistview.cpp +++ b/src/ui/maillistview.cpp @@ -1,7 +1,18 @@ #include "ui/maillistview.h" #include +#include "ui/models/EmailListModel.h" +#include "ui/models/EmailTreeModel.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -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::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(); - emit emailOpenRequested(mailId); + 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); - - // 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 + m_sourceModel = model; - // Default sort by date descending (column 2) - m_tableView->sortByColumn(EmailListModel::ColDate, Qt::DescendingOrder); + // 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); + + // 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 &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(); - emit emailSelected(mailId); + 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(m_proxyModel->sourceModel())) { - model->setSearchFilter(text); - } + m_proxyModel->setFilterFixedString(text); } void MailListView::onFilterChanged() { - if (auto *model = qobject_cast(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(); } \ No newline at end of file diff --git a/src/ui/maillistview.h b/src/ui/maillistview.h index 97e476c..b88779d 100644 --- a/src/ui/maillistview.h +++ b/src/ui/maillistview.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include @@ -10,8 +10,10 @@ #include #include #include +#include #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; }; \ No newline at end of file diff --git a/src/ui/mainmainwindow.cpp b/src/ui/mainmainwindow.cpp index 757b1c0..2bc97b3 100644 --- a/src/ui/mainmainwindow.cpp +++ b/src/ui/mainmainwindow.cpp @@ -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 } } diff --git a/src/ui/models/DateGroupProxyModel.cpp b/src/ui/models/DateGroupProxyModel.cpp new file mode 100644 index 0000000..e6628b3 --- /dev/null +++ b/src/ui/models/DateGroupProxyModel.cpp @@ -0,0 +1,173 @@ +#include "DateGroupProxyModel.h" +#include +#include +#include +#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); +} \ No newline at end of file diff --git a/src/ui/models/DateGroupProxyModel.h b/src/ui/models/DateGroupProxyModel.h new file mode 100644 index 0000000..92ba765 --- /dev/null +++ b/src/ui/models/DateGroupProxyModel.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include + +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 m_groupRowCounts; // cached group sizes + mutable QVector m_groupStartRows; // cached start rows for each group + + void updateGroupCache() const; + int groupForRow(int row) const; + QString groupNameForRow(int row) const; +}; \ No newline at end of file diff --git a/src/ui/models/EmailListModel.h b/src/ui/models/EmailListModel.h index 227285e..8441d7d 100644 --- a/src/ui/models/EmailListModel.h +++ b/src/ui/models/EmailListModel.h @@ -53,6 +53,9 @@ public: void setShowFlaggedOnly(bool show); void setShowHasAttachments(bool show); + // Get all emails currently in the model (after filtering) + const QVector& emails() const { return m_emails; } + private: QVector m_emails; int m_folderId{-1}; // -1 means all folders diff --git a/src/ui/models/EmailTreeModel.cpp b/src/ui/models/EmailTreeModel.cpp new file mode 100644 index 0000000..cbb4d52 --- /dev/null +++ b/src/ui/models/EmailTreeModel.cpp @@ -0,0 +1,325 @@ +#include "EmailTreeModel.h" +#include +#include +#include +#include + +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(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(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(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(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(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 &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 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> 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& 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; +} \ No newline at end of file diff --git a/src/ui/models/EmailTreeModel.h b/src/ui/models/EmailTreeModel.h new file mode 100644 index 0000000..7272871 --- /dev/null +++ b/src/ui/models/EmailTreeModel.h @@ -0,0 +1,78 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#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 &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 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 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); +}; \ No newline at end of file diff --git a/src/ui/readerview.cpp b/src/ui/readerview.cpp index eba5bc3..f5fea97 100644 --- a/src/ui/readerview.cpp +++ b/src/ui/readerview.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #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]() { diff --git a/tests/unit/.qmake.stash b/tests/unit/.qmake.stash new file mode 100644 index 0000000..42dcf68 --- /dev/null +++ b/tests/unit/.qmake.stash @@ -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 diff --git a/tests/unit/Makefile b/tests/unit/Makefile new file mode 100644 index 0000000..2158401 --- /dev/null +++ b/tests/unit/Makefile @@ -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: + diff --git a/tests/unit/moc_predefs.h b/tests/unit/moc_predefs.h new file mode 100644 index 0000000..9a7f989 --- /dev/null +++ b/tests/unit/moc_predefs.h @@ -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 diff --git a/tests/unit/test_accountdao b/tests/unit/test_accountdao new file mode 100644 index 0000000..c3a18a4 Binary files /dev/null and b/tests/unit/test_accountdao differ diff --git a/tests/unit/test_accountdao.cpp b/tests/unit/test_accountdao.cpp index 3f4d354..b6e78ba 100644 --- a/tests/unit/test_accountdao.cpp +++ b/tests/unit/test_accountdao.cpp @@ -2,6 +2,8 @@ #include "../../src/db/dao/accountdao.h" #include "../../src/db/databasemanager.h" #include "../../src/core/models/account.h" +#include +#include 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); + + 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); - bool inserted = AccountDao::insert(account); - QVERIFY(inserted); - QVERIFY(account.id() > 0); + qint64 insertedId = AccountDao::insert(account); + QVERIFY(insertedId != -1); + // Optionally set id on account for later use (if needed) + // account.setId(insertedId); - 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()); + 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) diff --git a/tests/unit/test_accountdao.moc b/tests/unit/test_accountdao.moc new file mode 100644 index 0000000..e5d3d3a --- /dev/null +++ b/tests/unit/test_accountdao.moc @@ -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 + +#include + +#include + + +#include +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'test_accountdao.cpp' doesn't include ." +#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() +{ + namespace QMC = QtMocConstants; + QtMocHelpers::StringRefStorage qt_stringData { + "TestAccountDao", + "initTestCase", + "", + "cleanupTestCase", + "testInsertAndFind", + "testUpdate", + "testRemove" + }; + + QtMocHelpers::UintData qt_methods { + // Slot 'initTestCase' + QtMocHelpers::SlotData(1, 2, QMC::AccessPrivate, QMetaType::Void), + // Slot 'cleanupTestCase' + QtMocHelpers::SlotData(3, 2, QMC::AccessPrivate, QMetaType::Void), + // Slot 'testInsertAndFind' + QtMocHelpers::SlotData(4, 2, QMC::AccessPrivate, QMetaType::Void), + // Slot 'testUpdate' + QtMocHelpers::SlotData(5, 2, QMC::AccessPrivate, QMetaType::Void), + // Slot 'testRemove' + QtMocHelpers::SlotData(6, 2, QMC::AccessPrivate, QMetaType::Void), + }; + QtMocHelpers::UintData qt_properties { + }; + QtMocHelpers::UintData qt_enums { + }; + return QtMocHelpers::metaObjectData(QMC::MetaObjectFlag{}, qt_stringData, + qt_methods, qt_properties, qt_enums); +} +Q_CONSTINIT const QMetaObject TestAccountDao::staticMetaObject = { { + QMetaObject::SuperData::link(), + qt_staticMetaObjectStaticContent.stringdata, + qt_staticMetaObjectStaticContent.data, + qt_static_metacall, + nullptr, + qt_staticMetaObjectRelocatingContent.metaTypes, + nullptr +} }; + +void TestAccountDao::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) +{ + auto *_t = static_cast(_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.strings)) + return static_cast(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(_a[0]) = QMetaType(); + _id -= 5; + } + return _id; +} +QT_WARNING_POP diff --git a/tests/unit/test_accountdao.pro b/tests/unit/test_accountdao.pro new file mode 100644 index 0000000..edba3d5 --- /dev/null +++ b/tests/unit/test_accountdao.pro @@ -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 \ No newline at end of file diff --git a/tests/unit/test_mimestorage.cpp b/tests/unit/test_mimestorage.cpp new file mode 100644 index 0000000..e1a0486 --- /dev/null +++ b/tests/unit/test_mimestorage.cpp @@ -0,0 +1,64 @@ +#include +#include +#include + +#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: \r\n" + "From: =?UTF-8?B?Sm9zw6k=?= \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" + "

Contenido completo

\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 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{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"