feat: email grouping by date + stability fixes
- EmailTreeModel: hierarchical model for grouped email view (QTreeView) - DateGroupProxyModel: proxy model for date-based grouping logic - MailListView: migrated from QTableView to QTreeView with grouping support - ReaderView: subject frame with shadow, avatar moved to header, body inside header - MainWindow: frameless with rounded corners, 1px border, edge resize, no status bar - Stability fixes for grouping mode switch: * Proper tree cleanup (no double-delete of root) * Bounds checking on all array accesses * Null pointer checks in index/parent/data methods * Date validity checks before grouping * Index validation before accessing m_emails
This commit is contained in:
+109
-52
@@ -2,6 +2,8 @@
|
||||
#include "../../src/db/dao/accountdao.h"
|
||||
#include "../../src/db/databasemanager.h"
|
||||
#include "../../src/core/models/account.h"
|
||||
#include <QtSql/QSqlDatabase>
|
||||
#include <QtSql/QSqlQuery>
|
||||
|
||||
class TestAccountDao : public QObject
|
||||
{
|
||||
@@ -16,90 +18,145 @@ private slots:
|
||||
|
||||
void TestAccountDao::initTestCase()
|
||||
{
|
||||
DatabaseManager::instance().openDatabase(":memory:");
|
||||
DatabaseManager::instance().createTables();
|
||||
// Use in-memory SQLite database
|
||||
// Ensure fresh connection by removing previous connection
|
||||
QSqlDatabase::removeDatabase(QStringLiteral("wino_mail_connection"));
|
||||
QVERIFY(DatabaseManager::instance().initialize(QStringLiteral(":memory:")));
|
||||
// Create tables (initialize will do it)
|
||||
}
|
||||
|
||||
void TestAccountDao::cleanupTestCase()
|
||||
{
|
||||
DatabaseManager::instance().closeDatabase();
|
||||
// Database will be closed automatically in destructor
|
||||
}
|
||||
|
||||
void TestAccountDao::testInsertAndFind()
|
||||
{
|
||||
Account account;
|
||||
account.setEmail("test@example.com");
|
||||
account.setProvider("IMAP");
|
||||
account.setHost("imap.example.com");
|
||||
account.setPort(993);
|
||||
account.setUsername("testuser");
|
||||
account.setPassword("testpass");
|
||||
account.setUseSsl(true);
|
||||
account.setEmail(QStringLiteral("test@example.com"));
|
||||
account.setDisplayName(QStringLiteral("Test User"));
|
||||
account.setSignature(QStringLiteral("Test sig"));
|
||||
account.setType(AccountType::IMAP);
|
||||
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user