feat: IMAP sync incremental + Account Setup Wizard + robust FETCH parser
- ImapSynchronizer::syncFolder(): detecta eliminados (UIDs locales no en servidor), fetch nuevos (sinceUid), actualiza flags (FLAGS batch) - fetchAllUids(): SELECT + SEARCH ALL para lista completa UIDs servidor - parseAndUpdateFlags(): FETCH FLAGS en lotes 100, update DB si cambió read/flagged - AccountSetupDialog: integra ConnectionWizard para IMAP/POP3 con test de conexión real - IMAP FETCH parser robusto: logging respuesta servidor + fallback UID-by-UID - Fix: FETCH failed logging muestra first/last UID + respuesta truncada
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
qint64 AccountDao::insert(const Account& account)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"INSERT INTO Account (email, displayName, signature, type, accessToken, refreshToken, tokenExpires, "
|
||||
@@ -39,12 +39,13 @@ qint64 AccountDao::insert(const Account& account)
|
||||
|
||||
bool AccountDao::update(const Account& account)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"UPDATE Account SET "
|
||||
"email = :email, "
|
||||
"displayName = :displayName, "
|
||||
"signature = :signature, "
|
||||
"type = :type, "
|
||||
"accessToken = :accessToken, "
|
||||
"refreshToken = :refreshToken, "
|
||||
@@ -66,6 +67,7 @@ bool AccountDao::update(const Account& account)
|
||||
query.bindValue(":type", static_cast<int>(account.type()));
|
||||
query.bindValue(":accessToken", account.accessToken());
|
||||
query.bindValue(":refreshToken", account.refreshToken());
|
||||
query.bindValue(":tokenExpires", account.tokenExpires());
|
||||
const auto& settings = account.connectionSettings();
|
||||
query.bindValue(":incomingHost", settings.incomingHost);
|
||||
query.bindValue(":incomingPort", settings.incomingPort);
|
||||
@@ -86,7 +88,7 @@ bool AccountDao::update(const Account& account)
|
||||
|
||||
bool AccountDao::remove(int id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM Account WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
@@ -100,10 +102,10 @@ bool AccountDao::remove(int id)
|
||||
|
||||
Account* AccountDao::findById(int id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"SELECT id, email, displayName, type, accessToken, refreshToken, tokenExpires, "
|
||||
"SELECT id, email, displayName, signature, type, accessToken, refreshToken, tokenExpires, "
|
||||
"incomingHost, incomingPort, incomingSsl, outgoingHost, outgoingPort, outgoingSsl, "
|
||||
"connUsername, connPassword, authMethod "
|
||||
"FROM Account WHERE id = :id");
|
||||
@@ -144,10 +146,10 @@ Account* AccountDao::findById(int id)
|
||||
QVector<Account> AccountDao::findAll()
|
||||
{
|
||||
QVector<Account> accounts;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
if (!query.exec(
|
||||
"SELECT id, email, displayName, type, accessToken, refreshToken, tokenExpires, "
|
||||
"SELECT id, email, displayName, signature, type, accessToken, refreshToken, tokenExpires, "
|
||||
"incomingHost, incomingPort, incomingSsl, outgoingHost, outgoingPort, outgoingSsl, "
|
||||
"connUsername, connPassword, authMethod "
|
||||
"FROM Account")) {
|
||||
@@ -160,6 +162,7 @@ QVector<Account> AccountDao::findAll()
|
||||
acc.setId(query.value("id").toInt());
|
||||
acc.setEmail(query.value("email").toString());
|
||||
acc.setDisplayName(query.value("displayName").toString());
|
||||
acc.setSignature(query.value("signature").toString());
|
||||
acc.setType(static_cast<AccountType>(query.value("type").toInt()));
|
||||
acc.setAccessToken(query.value("accessToken").toString());
|
||||
acc.setRefreshToken(query.value("refreshToken").toString());
|
||||
@@ -182,10 +185,10 @@ QVector<Account> AccountDao::findAll()
|
||||
|
||||
Account* AccountDao::findByEmail(const QString& email)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"SELECT id, email, displayName, type, accessToken, refreshToken, tokenExpires, "
|
||||
"SELECT id, email, displayName, signature, type, accessToken, refreshToken, tokenExpires, "
|
||||
"incomingHost, incomingPort, incomingSsl, outgoingHost, outgoingPort, outgoingSsl, "
|
||||
"connUsername, connPassword, authMethod "
|
||||
"FROM Account WHERE email = :email");
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
#include "accountdao.h"
|
||||
|
||||
bool AccountDao::insert(const Account& account)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"INSERT INTO Account (email, displayName, type, accessToken, refreshToken, tokenExpires, "
|
||||
"incomingHost, incomingPort, incomingSsl, outgoingHost, outgoingPort, outgoingSsl, "
|
||||
"connUsername, connPassword, authMethod) "
|
||||
"VALUES (:email, :displayName, :type, :accessToken, :refreshToken, :tokenExpires, "
|
||||
":incomingHost, :incomingPort, :incomingSsl, :outgoingHost, :outgoingPort, :outgoingSsl, "
|
||||
":connUsername, :connPassword, :authMethod)");
|
||||
query.bindValue(":email", account.email());
|
||||
query.bindValue(":displayName", account.displayName());
|
||||
query.bindValue(":type", static_cast<int>(account.type()));
|
||||
query.bindValue(":accessToken", account.accessToken());
|
||||
query.bindValue(":refreshToken", account.refreshToken());
|
||||
query.bindValue(":tokenExpires", account.tokenExpires());
|
||||
const auto& settings = account.connectionSettings();
|
||||
query.bindValue(":incomingHost", settings.incomingHost);
|
||||
query.bindValue(":incomingPort", settings.incomingPort);
|
||||
query.bindValue(":incomingSsl", settings.incomingSsl ? 1 : 0);
|
||||
query.bindValue(":outgoingHost", settings.outgoingHost);
|
||||
query.bindValue(":outgoingPort", settings.outgoingPort);
|
||||
query.bindValue(":outgoingSsl", settings.outgoingSsl ? 1 : 0);
|
||||
query.bindValue(":connUsername", settings.username);
|
||||
query.bindValue(":connPassword", Account::encryptPassword(settings.password));
|
||||
query.bindValue(":authMethod", settings.authMethod);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to insert account:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AccountDao::update(const Account& account)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"UPDATE Account SET "
|
||||
"email = :email, "
|
||||
"displayName = :displayName, "
|
||||
"type = :type, "
|
||||
"accessToken = :accessToken, "
|
||||
"refreshToken = :refreshToken, "
|
||||
"tokenExpires = :tokenExpires, "
|
||||
"incomingHost = :incomingHost, "
|
||||
"incomingPort = :incomingPort, "
|
||||
"incomingSsl = :incomingSsl, "
|
||||
"outgoingHost = :outgoingHost, "
|
||||
"outgoingPort = :outgoingPort, "
|
||||
"outgoingSsl = :outgoingSsl, "
|
||||
"connUsername = :connUsername, "
|
||||
"connPassword = :connPassword, "
|
||||
"authMethod = :authMethod "
|
||||
"WHERE id = :id");
|
||||
query.bindValue(":id", account.id());
|
||||
query.bindValue(":email", account.email());
|
||||
query.bindValue(":displayName", account.displayName());
|
||||
query.bindValue(":type", static_cast<int>(account.type()));
|
||||
query.bindValue(":accessToken", account.accessToken());
|
||||
query.bindValue(":refreshToken", account.refreshToken());
|
||||
query.bindValue(":tokenExpires", account.tokenExpires());
|
||||
const auto& settings = account.connectionSettings();
|
||||
query.bindValue(":incomingHost", settings.incomingHost);
|
||||
query.bindValue(":incomingPort", settings.incomingPort);
|
||||
query.bindValue(":incomingSsl", settings.incomingSsl ? 1 : 0);
|
||||
query.bindValue(":outgoingHost", settings.outgoingHost);
|
||||
query.bindValue(":outgoingPort", settings.outgoingPort);
|
||||
query.bindValue(":outgoingSsl", settings.outgoingSsl ? 1 : 0);
|
||||
query.bindValue(":connUsername", settings.username);
|
||||
query.bindValue(":connPassword", Account::encryptPassword(settings.password));
|
||||
query.bindValue(":authMethod", settings.authMethod);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to update account:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AccountDao::remove(int id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM Account WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to delete account:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Account* AccountDao::findById(int id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"SELECT id, email, displayName, type, accessToken, refreshToken, tokenExpires, "
|
||||
"incomingHost, incomingPort, incomingSsl, outgoingHost, outgoingPort, outgoingSsl, "
|
||||
"connUsername, connPassword, authMethod "
|
||||
"FROM Account WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to find account by id:" << query.lastError().text();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
Account* account = new Account();
|
||||
account->setId(query.value("id").toInt());
|
||||
account->setEmail(query.value("email").toString());
|
||||
account->setDisplayName(query.value("displayName").toString());
|
||||
account->setType(static_cast<AccountType>(query.value("type").toInt()));
|
||||
account->setAccessToken(query.value("accessToken").toString());
|
||||
account->setRefreshToken(query.value("refreshToken").toString());
|
||||
account->setTokenExpires(query.value("tokenExpires").toDateTime());
|
||||
Account::ConnectionSettings settings;
|
||||
settings.incomingHost = query.value("incomingHost").toString();
|
||||
settings.incomingPort = query.value("incomingPort").toInt();
|
||||
settings.incomingSsl = query.value("incomingSsl").toBool();
|
||||
settings.outgoingHost = query.value("outgoingHost").toString();
|
||||
settings.outgoingPort = query.value("outgoingPort").toInt();
|
||||
settings.outgoingSsl = query.value("outgoingSsl").toBool();
|
||||
settings.username = query.value("connUsername").toString();
|
||||
settings.password = Account::decryptPassword(query.value("connPassword").toString());
|
||||
settings.authMethod = query.value("authMethod").toString();
|
||||
account->setConnectionSettings(settings);
|
||||
return account;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QVector<Account> AccountDao::findAll()
|
||||
{
|
||||
QVector<Account> accounts;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
if (!query.exec(
|
||||
"SELECT id, email, displayName, type, accessToken, refreshToken, tokenExpires, "
|
||||
"incomingHost, incomingPort, incomingSsl, outgoingHost, outgoingPort, outgoingSsl, "
|
||||
"connUsername, connPassword, authMethod "
|
||||
"FROM Account")) {
|
||||
qWarning() << "Failed to fetch all accounts:" << query.lastError().text();
|
||||
return accounts;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
Account acc;
|
||||
acc.setId(query.value("id").toInt());
|
||||
acc.setEmail(query.value("email").toString());
|
||||
acc.setDisplayName(query.value("displayName").toString());
|
||||
acc.setType(static_cast<AccountType>(query.value("type").toInt()));
|
||||
acc.setAccessToken(query.value("accessToken").toString());
|
||||
acc.setRefreshToken(query.value("refreshToken").toString());
|
||||
acc.setTokenExpires(query.value("tokenExpires").toDateTime());
|
||||
Account::ConnectionSettings settings;
|
||||
settings.incomingHost = query.value("incomingHost").toString();
|
||||
settings.incomingPort = query.value("incomingPort").toInt();
|
||||
settings.incomingSsl = query.value("incomingSsl").toBool();
|
||||
settings.outgoingHost = query.value("outgoingHost").toString();
|
||||
settings.outgoingPort = query.value("outgoingPort").toInt();
|
||||
settings.outgoingSsl = query.value("outgoingSsl").toBool();
|
||||
settings.username = query.value("connUsername").toString();
|
||||
settings.password = Account::decryptPassword(query.value("connPassword").toString());
|
||||
settings.authMethod = query.value("authMethod").toString();
|
||||
acc.setConnectionSettings(settings);
|
||||
accounts.append(acc);
|
||||
}
|
||||
return accounts;
|
||||
}
|
||||
|
||||
Account* AccountDao::findByEmail(const QString& email)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"SELECT id, email, displayName, type, accessToken, refreshToken, tokenExpires, "
|
||||
"incomingHost, incomingPort, incomingSsl, outgoingHost, outgoingPort, outgoingSsl, "
|
||||
"connUsername, connPassword, authMethod "
|
||||
"FROM Account WHERE email = :email");
|
||||
query.bindValue(":email", email);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to find account by email:" << query.lastError().text();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
Account* acc = new Account();
|
||||
acc->setId(query.value("id").toInt());
|
||||
acc->setEmail(query.value("email").toString());
|
||||
acc->setDisplayName(query.value("displayName").toString());
|
||||
acc->setType(static_cast<AccountType>(query.value("type").toInt()));
|
||||
acc->setAccessToken(query.value("accessToken").toString());
|
||||
acc->setRefreshToken(query.value("refreshToken").toString());
|
||||
acc->setTokenExpires(query.value("tokenExpires").toDateTime());
|
||||
Account::ConnectionSettings settings;
|
||||
settings.incomingHost = query.value("incomingHost").toString();
|
||||
settings.incomingPort = query.value("incomingPort").toInt();
|
||||
settings.incomingSsl = query.value("incomingSsl").toBool();
|
||||
settings.outgoingHost = query.value("outgoingHost").toString();
|
||||
settings.outgoingPort = query.value("outgoingPort").toInt();
|
||||
settings.outgoingSsl = query.value("outgoingSsl").toBool();
|
||||
settings.username = query.value("connUsername").toString();
|
||||
settings.password = Account::decryptPassword(query.value("connPassword").toString());
|
||||
settings.authMethod = query.value("authMethod").toString();
|
||||
acc->setConnectionSettings(settings);
|
||||
return acc;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
#include "accountdao.h"
|
||||
|
||||
qint64 AccountDao::insert(const Account& account)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"INSERT INTO Account (email, displayName, signature, type, accessToken, refreshToken, tokenExpires, "
|
||||
"incomingHost, incomingPort, incomingSsl, outgoingHost, outgoingPort, outgoingSsl, "
|
||||
"connUsername, connPassword, authMethod) "
|
||||
"VALUES (:email, :displayName, :signature, :type, :accessToken, :refreshToken, :tokenExpires, "
|
||||
":incomingHost, :incomingPort, :incomingSsl, :outgoingHost, :outgoingPort, :outgoingSsl, "
|
||||
":connUsername, :connPassword, :authMethod)");
|
||||
query.bindValue(":email", account.email());
|
||||
query.bindValue(":displayName", account.displayName());
|
||||
query.bindValue(":signature", account.signature());
|
||||
query.bindValue(":type", static_cast<int>(account.type()));
|
||||
query.bindValue(":accessToken", account.accessToken());
|
||||
query.bindValue(":refreshToken", account.refreshToken());
|
||||
query.bindValue(":tokenExpires", account.tokenExpires());
|
||||
const auto& settings = account.connectionSettings();
|
||||
query.bindValue(":incomingHost", settings.incomingHost);
|
||||
query.bindValue(":incomingPort", settings.incomingPort);
|
||||
query.bindValue(":incomingSsl", settings.incomingSsl ? 1 : 0);
|
||||
query.bindValue(":outgoingHost", settings.outgoingHost);
|
||||
query.bindValue(":outgoingPort", settings.outgoingPort);
|
||||
query.bindValue(":outgoingSsl", settings.outgoingSsl ? 1 : 0);
|
||||
query.bindValue(":connUsername", settings.username);
|
||||
query.bindValue(":connPassword", Account::encryptPassword(settings.password));
|
||||
query.bindValue(":authMethod", settings.authMethod);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to insert account:" << query.lastError().text();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return query.lastInsertId().toLongLong();
|
||||
}
|
||||
|
||||
bool AccountDao::update(const Account& account)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"UPDATE Account SET "
|
||||
"email = :email, "
|
||||
"displayName = :displayName, "
|
||||
"type = :type, "
|
||||
"accessToken = :accessToken, "
|
||||
"refreshToken = :refreshToken, "
|
||||
"tokenExpires = :tokenExpires, "
|
||||
"incomingHost = :incomingHost, "
|
||||
"incomingPort = :incomingPort, "
|
||||
"incomingSsl = :incomingSsl, "
|
||||
"outgoingHost = :outgoingHost, "
|
||||
"outgoingPort = :outgoingPort, "
|
||||
"outgoingSsl = :outgoingSsl, "
|
||||
"connUsername = :connUsername, "
|
||||
"connPassword = :connPassword, "
|
||||
"authMethod = :authMethod "
|
||||
"WHERE id = :id");
|
||||
query.bindValue(":id", account.id());
|
||||
query.bindValue(":email", account.email());
|
||||
query.bindValue(":displayName", account.displayName());
|
||||
query.bindValue(":signature", account.signature());
|
||||
query.bindValue(":type", static_cast<int>(account.type()));
|
||||
query.bindValue(":accessToken", account.accessToken());
|
||||
query.bindValue(":refreshToken", account.refreshToken());
|
||||
const auto& settings = account.connectionSettings();
|
||||
query.bindValue(":incomingHost", settings.incomingHost);
|
||||
query.bindValue(":incomingPort", settings.incomingPort);
|
||||
query.bindValue(":incomingSsl", settings.incomingSsl ? 1 : 0);
|
||||
query.bindValue(":outgoingHost", settings.outgoingHost);
|
||||
query.bindValue(":outgoingPort", settings.outgoingPort);
|
||||
query.bindValue(":outgoingSsl", settings.outgoingSsl ? 1 : 0);
|
||||
query.bindValue(":connUsername", settings.username);
|
||||
query.bindValue(":connPassword", Account::encryptPassword(settings.password));
|
||||
query.bindValue(":authMethod", settings.authMethod);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to update account:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AccountDao::remove(int id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM Account WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to delete account:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Account* AccountDao::findById(int id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"SELECT id, email, displayName, type, accessToken, refreshToken, tokenExpires, "
|
||||
"incomingHost, incomingPort, incomingSsl, outgoingHost, outgoingPort, outgoingSsl, "
|
||||
"connUsername, connPassword, authMethod "
|
||||
"FROM Account WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to find account by id:" << query.lastError().text();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
Account* account = new Account();
|
||||
account->setId(query.value("id").toInt());
|
||||
account->setEmail(query.value("email").toString());
|
||||
account->setDisplayName(query.value("displayName").toString());
|
||||
account->setSignature(query.value("signature").toString());
|
||||
account->setType(static_cast<AccountType>(query.value("type").toInt()));
|
||||
account->setAccessToken(query.value("accessToken").toString());
|
||||
account->setRefreshToken(query.value("refreshToken").toString());
|
||||
account->setTokenExpires(query.value("tokenExpires").toDateTime());
|
||||
Account::ConnectionSettings settings;
|
||||
settings.incomingHost = query.value("incomingHost").toString();
|
||||
settings.incomingPort = query.value("incomingPort").toInt();
|
||||
settings.incomingSsl = query.value("incomingSsl").toBool();
|
||||
settings.outgoingHost = query.value("outgoingHost").toString();
|
||||
settings.outgoingPort = query.value("outgoingPort").toInt();
|
||||
settings.outgoingSsl = query.value("outgoingSsl").toBool();
|
||||
settings.username = query.value("connUsername").toString();
|
||||
settings.password = Account::decryptPassword(query.value("connPassword").toString());
|
||||
settings.authMethod = query.value("authMethod").toString();
|
||||
account->setConnectionSettings(settings);
|
||||
return account;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QVector<Account> AccountDao::findAll()
|
||||
{
|
||||
QVector<Account> accounts;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
if (!query.exec(
|
||||
"SELECT id, email, displayName, type, accessToken, refreshToken, tokenExpires, "
|
||||
"incomingHost, incomingPort, incomingSsl, outgoingHost, outgoingPort, outgoingSsl, "
|
||||
"connUsername, connPassword, authMethod "
|
||||
"FROM Account")) {
|
||||
qWarning() << "Failed to fetch all accounts:" << query.lastError().text();
|
||||
return accounts;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
Account acc;
|
||||
acc.setId(query.value("id").toInt());
|
||||
acc.setEmail(query.value("email").toString());
|
||||
acc.setDisplayName(query.value("displayName").toString());
|
||||
acc.setType(static_cast<AccountType>(query.value("type").toInt()));
|
||||
acc.setAccessToken(query.value("accessToken").toString());
|
||||
acc.setRefreshToken(query.value("refreshToken").toString());
|
||||
acc.setTokenExpires(query.value("tokenExpires").toDateTime());
|
||||
Account::ConnectionSettings settings;
|
||||
settings.incomingHost = query.value("incomingHost").toString();
|
||||
settings.incomingPort = query.value("incomingPort").toInt();
|
||||
settings.incomingSsl = query.value("incomingSsl").toBool();
|
||||
settings.outgoingHost = query.value("outgoingHost").toString();
|
||||
settings.outgoingPort = query.value("outgoingPort").toInt();
|
||||
settings.outgoingSsl = query.value("outgoingSsl").toBool();
|
||||
settings.username = query.value("connUsername").toString();
|
||||
settings.password = Account::decryptPassword(query.value("connPassword").toString());
|
||||
settings.authMethod = query.value("authMethod").toString();
|
||||
acc.setConnectionSettings(settings);
|
||||
accounts.append(acc);
|
||||
}
|
||||
return accounts;
|
||||
}
|
||||
|
||||
Account* AccountDao::findByEmail(const QString& email)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"SELECT id, email, displayName, type, accessToken, refreshToken, tokenExpires, "
|
||||
"incomingHost, incomingPort, incomingSsl, outgoingHost, outgoingPort, outgoingSsl, "
|
||||
"connUsername, connPassword, authMethod "
|
||||
"FROM Account WHERE email = :email");
|
||||
query.bindValue(":email", email);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to find account by email:" << query.lastError().text();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
Account* acc = new Account();
|
||||
acc->setId(query.value("id").toInt());
|
||||
acc->setEmail(query.value("email").toString());
|
||||
acc->setDisplayName(query.value("displayName").toString());
|
||||
acc->setSignature(query.value("signature").toString());
|
||||
acc->setType(static_cast<AccountType>(query.value("type").toInt()));
|
||||
acc->setAccessToken(query.value("accessToken").toString());
|
||||
acc->setRefreshToken(query.value("refreshToken").toString());
|
||||
acc->setTokenExpires(query.value("tokenExpires").toDateTime());
|
||||
Account::ConnectionSettings settings;
|
||||
settings.incomingHost = query.value("incomingHost").toString();
|
||||
settings.incomingPort = query.value("incomingPort").toInt();
|
||||
settings.incomingSsl = query.value("incomingSsl").toBool();
|
||||
settings.outgoingHost = query.value("outgoingHost").toString();
|
||||
settings.outgoingPort = query.value("outgoingPort").toInt();
|
||||
settings.outgoingSsl = query.value("outgoingSsl").toBool();
|
||||
settings.username = query.value("connUsername").toString();
|
||||
settings.password = Account::decryptPassword(query.value("connPassword").toString());
|
||||
settings.authMethod = query.value("authMethod").toString();
|
||||
acc->setConnectionSettings(settings);
|
||||
return acc;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
+32
-32
@@ -4,34 +4,9 @@
|
||||
#include <QSqlError>
|
||||
#include <optional>
|
||||
|
||||
bool FolderDao::insert(const Folder& folder)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"INSERT INTO Folder (accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced) "
|
||||
"VALUES (:accountId, :name, :parentFolderId, :isInbox, :isSent, :isDrafts, :isTrash, :unreadCount, :lastSynced)"
|
||||
);
|
||||
query.bindValue(":accountId", folder.accountId());
|
||||
query.bindValue(":name", folder.name());
|
||||
query.bindValue(":parentFolderId", folder.parentFolderId());
|
||||
query.bindValue(":isInbox", folder.isInbox() ? 1 : 0);
|
||||
query.bindValue(":isSent", folder.isSent() ? 1 : 0);
|
||||
query.bindValue(":isDrafts", folder.isDrafts() ? 1 : 0);
|
||||
query.bindValue(":isTrash", folder.isTrash() ? 1 : 0);
|
||||
query.bindValue(":unreadCount", folder.unreadCount());
|
||||
query.bindValue(":lastSynced", folder.lastSynced());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to insert folder:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FolderDao::update(const Folder& folder)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"UPDATE Folder SET "
|
||||
@@ -66,7 +41,7 @@ bool FolderDao::update(const Folder& folder)
|
||||
|
||||
bool FolderDao::remove(int id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM Folder WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
@@ -80,7 +55,7 @@ bool FolderDao::remove(int id)
|
||||
|
||||
std::optional<Folder> FolderDao::findById(int id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced FROM Folder WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
@@ -110,7 +85,7 @@ std::optional<Folder> FolderDao::findById(int id)
|
||||
QVector<Folder> FolderDao::findAll()
|
||||
{
|
||||
QVector<Folder> folders;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
if (!query.exec("SELECT id, accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced FROM Folder")) {
|
||||
qWarning() << "Failed to fetch all folders:" << query.lastError().text();
|
||||
@@ -137,7 +112,7 @@ QVector<Folder> FolderDao::findAll()
|
||||
QVector<Folder> FolderDao::findByAccountId(int accountId)
|
||||
{
|
||||
QVector<Folder> folders;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced FROM Folder WHERE accountId = :accountId");
|
||||
query.bindValue(":accountId", accountId);
|
||||
@@ -166,7 +141,7 @@ QVector<Folder> FolderDao::findByAccountId(int accountId)
|
||||
|
||||
bool FolderDao::removeByAccountId(int accountId)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM Folder WHERE accountId = :accountId");
|
||||
query.bindValue(":accountId", accountId);
|
||||
@@ -176,4 +151,29 @@ bool FolderDao::removeByAccountId(int accountId)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
qint64 FolderDao::insert(const Folder& folder)
|
||||
{
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"INSERT INTO Folder (accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced) "
|
||||
"VALUES (:accountId, :name, :parentFolderId, :isInbox, :isSent, :isDrafts, :isTrash, :unreadCount, :lastSynced)"
|
||||
);
|
||||
query.bindValue(":accountId", folder.accountId());
|
||||
query.bindValue(":name", folder.name());
|
||||
query.bindValue(":parentFolderId", folder.parentFolderId());
|
||||
query.bindValue(":isInbox", folder.isInbox() ? 1 : 0);
|
||||
query.bindValue(":isSent", folder.isSent() ? 1 : 0);
|
||||
query.bindValue(":isDrafts", folder.isDrafts() ? 1 : 0);
|
||||
query.bindValue(":isTrash", folder.isTrash() ? 1 : 0);
|
||||
query.bindValue(":unreadCount", folder.unreadCount());
|
||||
query.bindValue(":lastSynced", folder.lastSynced());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to insert folder:" << query.lastError().text();
|
||||
return -1;
|
||||
}
|
||||
return query.lastInsertId().toLongLong();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
#include <QSqlQuery>
|
||||
#include "folderdao.h"
|
||||
#include <QSqlError>
|
||||
#include <QSqlError>
|
||||
#include <optional>
|
||||
|
||||
bool FolderDao::insert(const Folder& folder)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"INSERT INTO Folder (accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced) "
|
||||
"VALUES (:accountId, :name, :parentFolderId, :isInbox, :isSent, :isDrafts, :isTrash, :unreadCount, :lastSynced)"
|
||||
);
|
||||
query.bindValue(":accountId", folder.accountId());
|
||||
query.bindValue(":name", folder.name());
|
||||
query.bindValue(":parentFolderId", folder.parentFolderId());
|
||||
query.bindValue(":isInbox", folder.isInbox() ? 1 : 0);
|
||||
query.bindValue(":isSent", folder.isSent() ? 1 : 0);
|
||||
query.bindValue(":isDrafts", folder.isDrafts() ? 1 : 0);
|
||||
query.bindValue(":isTrash", folder.isTrash() ? 1 : 0);
|
||||
query.bindValue(":unreadCount", folder.unreadCount());
|
||||
query.bindValue(":lastSynced", folder.lastSynced());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to insert folder:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FolderDao::update(const Folder& folder)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"UPDATE Folder SET "
|
||||
"accountId = :accountId, "
|
||||
"name = :name, "
|
||||
"parentFolderId = :parentFolderId, "
|
||||
"isInbox = :isInbox, "
|
||||
"isSent = :isSent, "
|
||||
"isDrafts = :isDrafts, "
|
||||
"isTrash = :isTrash, "
|
||||
"unreadCount = :unreadCount, "
|
||||
"lastSynced = :lastSynced "
|
||||
"WHERE id = :id"
|
||||
);
|
||||
query.bindValue(":id", folder.id());
|
||||
query.bindValue(":accountId", folder.accountId());
|
||||
query.bindValue(":name", folder.name());
|
||||
query.bindValue(":parentFolderId", folder.parentFolderId());
|
||||
query.bindValue(":isInbox", folder.isInbox() ? 1 : 0);
|
||||
query.bindValue(":isSent", folder.isSent() ? 1 : 0);
|
||||
query.bindValue(":isDrafts", folder.isDrafts() ? 1 : 0);
|
||||
query.bindValue(":isTrash", folder.isTrash() ? 1 : 0);
|
||||
query.bindValue(":unreadCount", folder.unreadCount());
|
||||
query.bindValue(":lastSynced", folder.lastSynced());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to update folder:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FolderDao::remove(int id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM Folder WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to delete folder:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<Folder> FolderDao::findById(int id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced FROM Folder WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to find folder by id:" << query.lastError().text();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
Folder fld;
|
||||
fld.setId(query.value(0).toInt());
|
||||
fld.setAccountId(query.value(1).toInt());
|
||||
fld.setName(query.value(2).toString());
|
||||
fld.setParentFolderId(query.value(3).toString());
|
||||
fld.setInbox(query.value(4).toBool());
|
||||
fld.setSent(query.value(5).toBool());
|
||||
fld.setDrafts(query.value(6).toBool());
|
||||
fld.setTrash(query.value(7).toBool());
|
||||
fld.setUnreadCount(query.value(8).toInt());
|
||||
fld.setLastSynced(query.value(9).toDateTime());
|
||||
return fld;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QVector<Folder> FolderDao::findAll()
|
||||
{
|
||||
QVector<Folder> folders;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
if (!query.exec("SELECT id, accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced FROM Folder")) {
|
||||
qWarning() << "Failed to fetch all folders:" << query.lastError().text();
|
||||
return folders;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
Folder fld;
|
||||
fld.setId(query.value(0).toInt());
|
||||
fld.setAccountId(query.value(1).toInt());
|
||||
fld.setName(query.value(2).toString());
|
||||
fld.setParentFolderId(query.value(3).toString());
|
||||
fld.setInbox(query.value(4).toBool());
|
||||
fld.setSent(query.value(5).toBool());
|
||||
fld.setDrafts(query.value(6).toBool());
|
||||
fld.setTrash(query.value(7).toBool());
|
||||
fld.setUnreadCount(query.value(8).toInt());
|
||||
fld.setLastSynced(query.value(9).toDateTime());
|
||||
folders.push_back(fld);
|
||||
}
|
||||
return folders;
|
||||
}
|
||||
|
||||
QVector<Folder> FolderDao::findByAccountId(int accountId)
|
||||
{
|
||||
QVector<Folder> folders;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced FROM Folder WHERE accountId = :accountId");
|
||||
query.bindValue(":accountId", accountId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to fetch folders by account id:" << query.lastError().text();
|
||||
return folders;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
Folder fld;
|
||||
fld.setId(query.value(0).toInt());
|
||||
fld.setAccountId(query.value(1).toInt());
|
||||
fld.setName(query.value(2).toString());
|
||||
fld.setParentFolderId(query.value(3).toString());
|
||||
fld.setInbox(query.value(4).toBool());
|
||||
fld.setSent(query.value(5).toBool());
|
||||
fld.setDrafts(query.value(6).toBool());
|
||||
fld.setTrash(query.value(7).toBool());
|
||||
fld.setUnreadCount(query.value(8).toInt());
|
||||
fld.setLastSynced(query.value(9).toDateTime());
|
||||
folders.push_back(fld);
|
||||
}
|
||||
return folders;
|
||||
}
|
||||
|
||||
bool FolderDao::removeByAccountId(int accountId)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM Folder WHERE accountId = :accountId");
|
||||
query.bindValue(":accountId", accountId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to delete folders by account id:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
#include <QSqlQuery>
|
||||
#include "folderdao.h"
|
||||
#include <QSqlError>
|
||||
#include <QSqlError>
|
||||
#include <optional>
|
||||
|
||||
qint64 FolderDao::insert(Folder& folder)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"INSERT INTO Folder (accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced) "
|
||||
"VALUES (:accountId, :name, :parentFolderId, :isInbox, :isSent, :isDrafts, :isTrash, :unreadCount, :lastSynced)"
|
||||
);
|
||||
query.bindValue(":accountId", folder.accountId());
|
||||
query.bindValue(":name", folder.name());
|
||||
query.bindValue(":parentFolderId", folder.parentFolderId());
|
||||
query.bindValue(":isInbox", folder.isInbox() ? 1 : 0);
|
||||
query.bindValue(":isSent", folder.isSent() ? 1 : 0);
|
||||
query.bindValue(":isDrafts", folder.isDrafts() ? 1 : 0);
|
||||
query.bindValue(":isTrash", folder.isTrash() ? 1 : 0);
|
||||
query.bindValue(":unreadCount", folder.unreadCount());
|
||||
query.bindValue(":lastSynced", folder.lastSynced());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to insert folder:" << query.lastError().text();
|
||||
return -1;
|
||||
}
|
||||
folder.setId(query.lastInsertId().toLongLong());
|
||||
return folder.id();
|
||||
}
|
||||
|
||||
bool FolderDao::update(const Folder& folder)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"UPDATE Folder SET "
|
||||
"accountId = :accountId, "
|
||||
"name = :name, "
|
||||
"parentFolderId = :parentFolderId, "
|
||||
"isInbox = :isInbox, "
|
||||
"isSent = :isSent, "
|
||||
"isDrafts = :isDrafts, "
|
||||
"isTrash = :isTrash, "
|
||||
"unreadCount = :unreadCount, "
|
||||
"lastSynced = :lastSynced "
|
||||
"WHERE id = :id"
|
||||
);
|
||||
query.bindValue(":id", folder.id());
|
||||
query.bindValue(":accountId", folder.accountId());
|
||||
query.bindValue(":name", folder.name());
|
||||
query.bindValue(":parentFolderId", folder.parentFolderId());
|
||||
query.bindValue(":isInbox", folder.isInbox() ? 1 : 0);
|
||||
query.bindValue(":isSent", folder.isSent() ? 1 : 0);
|
||||
query.bindValue(":isDrafts", folder.isDrafts() ? 1 : 0);
|
||||
query.bindValue(":isTrash", folder.isTrash() ? 1 : 0);
|
||||
query.bindValue(":unreadCount", folder.unreadCount());
|
||||
query.bindValue(":lastSynced", folder.lastSynced());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to update folder:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FolderDao::remove(int id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM Folder WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to delete folder:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<Folder> FolderDao::findById(int id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced FROM Folder WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to find folder by id:" << query.lastError().text();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
Folder fld;
|
||||
fld.setId(query.value(0).toInt());
|
||||
fld.setAccountId(query.value(1).toInt());
|
||||
fld.setName(query.value(2).toString());
|
||||
fld.setParentFolderId(query.value(3).toString());
|
||||
fld.setInbox(query.value(4).toBool());
|
||||
fld.setSent(query.value(5).toBool());
|
||||
fld.setDrafts(query.value(6).toBool());
|
||||
fld.setTrash(query.value(7).toBool());
|
||||
fld.setUnreadCount(query.value(8).toInt());
|
||||
fld.setLastSynced(query.value(9).toDateTime());
|
||||
return fld;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QVector<Folder> FolderDao::findAll()
|
||||
{
|
||||
QVector<Folder> folders;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
if (!query.exec("SELECT id, accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced FROM Folder")) {
|
||||
qWarning() << "Failed to fetch all folders:" << query.lastError().text();
|
||||
return folders;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
Folder fld;
|
||||
fld.setId(query.value(0).toInt());
|
||||
fld.setAccountId(query.value(1).toInt());
|
||||
fld.setName(query.value(2).toString());
|
||||
fld.setParentFolderId(query.value(3).toString());
|
||||
fld.setInbox(query.value(4).toBool());
|
||||
fld.setSent(query.value(5).toBool());
|
||||
fld.setDrafts(query.value(6).toBool());
|
||||
fld.setTrash(query.value(7).toBool());
|
||||
fld.setUnreadCount(query.value(8).toInt());
|
||||
fld.setLastSynced(query.value(9).toDateTime());
|
||||
folders.push_back(fld);
|
||||
}
|
||||
return folders;
|
||||
}
|
||||
|
||||
QVector<Folder> FolderDao::findByAccountId(int accountId)
|
||||
{
|
||||
QVector<Folder> folders;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, accountId, name, parentFolderId, isInbox, isSent, isDrafts, isTrash, unreadCount, lastSynced FROM Folder WHERE accountId = :accountId");
|
||||
query.bindValue(":accountId", accountId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to fetch folders by account id:" << query.lastError().text();
|
||||
return folders;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
Folder fld;
|
||||
fld.setId(query.value(0).toInt());
|
||||
fld.setAccountId(query.value(1).toInt());
|
||||
fld.setName(query.value(2).toString());
|
||||
fld.setParentFolderId(query.value(3).toString());
|
||||
fld.setInbox(query.value(4).toBool());
|
||||
fld.setSent(query.value(5).toBool());
|
||||
fld.setDrafts(query.value(6).toBool());
|
||||
fld.setTrash(query.value(7).toBool());
|
||||
fld.setUnreadCount(query.value(8).toInt());
|
||||
fld.setLastSynced(query.value(9).toDateTime());
|
||||
folders.push_back(fld);
|
||||
}
|
||||
return folders;
|
||||
}
|
||||
|
||||
bool FolderDao::removeByAccountId(int accountId)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM Folder WHERE accountId = :accountId");
|
||||
query.bindValue(":accountId", accountId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to delete folders by account id:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
class FolderDao
|
||||
{
|
||||
public:
|
||||
static bool insert(const Folder& folder);
|
||||
static qint64 insert(const Folder& folder);
|
||||
static bool update(const Folder& folder);
|
||||
static bool remove(int id);
|
||||
static bool removeByAccountId(int accountId);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "../databasemanager.h"
|
||||
#include "../../core/models/folder.h"
|
||||
#include <QVector>
|
||||
#include <optional>
|
||||
|
||||
class FolderDao
|
||||
{
|
||||
public:
|
||||
static bool insert(const Folder& folder);
|
||||
static bool update(const Folder& folder);
|
||||
static bool remove(int id);
|
||||
static bool removeByAccountId(int accountId);
|
||||
static std::optional<Folder> findById(int id);
|
||||
static QVector<Folder> findAll();
|
||||
static QVector<Folder> findByAccountId(int accountId);
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "../databasemanager.h"
|
||||
#include "../../core/models/folder.h"
|
||||
#include <QVector>
|
||||
#include <optional>
|
||||
|
||||
class FolderDao
|
||||
{
|
||||
public:
|
||||
static qint64 insert(const Folder& folder);
|
||||
static bool update(const Folder& folder);
|
||||
static bool remove(int id);
|
||||
static bool removeByAccountId(int accountId);
|
||||
static std::optional<Folder> findById(int id);
|
||||
static QVector<Folder> findAll();
|
||||
static QVector<Folder> findByAccountId(int accountId);
|
||||
};
|
||||
+204
-20
@@ -1,18 +1,38 @@
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include "mailitemdao.h"
|
||||
#include <QDebug>
|
||||
#include <optional>
|
||||
|
||||
bool MailItemDao::insert(const MailItem& item)
|
||||
bool MailItemDao::insert(MailItem& item)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
|
||||
// IMAP UIDs and provider message IDs are stable across synchronizations.
|
||||
// Update the existing row instead of creating duplicates on every sync.
|
||||
if (!item.messageId().isEmpty() || item.uid() > 0) {
|
||||
QSqlQuery existing(db);
|
||||
if (!item.messageId().isEmpty()) {
|
||||
existing.prepare("SELECT id FROM MailCopy WHERE messageId = :messageId LIMIT 1");
|
||||
existing.bindValue(":messageId", item.messageId());
|
||||
} else {
|
||||
existing.prepare("SELECT id FROM MailCopy WHERE folderId = :folderId AND uid = :uid LIMIT 1");
|
||||
existing.bindValue(":folderId", item.folderId());
|
||||
existing.bindValue(":uid", item.uid());
|
||||
}
|
||||
if (existing.exec() && existing.next()) {
|
||||
item.setId(existing.value(0).toLongLong());
|
||||
return update(item);
|
||||
}
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"INSERT INTO MailCopy (folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid) "
|
||||
"VALUES (:folderId, :messageId, :subject, :sender, :recipient, :date, :read, :flagged, :hasAttachment, :size, :fileId, :uid)"
|
||||
"INSERT INTO MailCopy (folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr) "
|
||||
"VALUES (:folderId, :messageId, :subject, :sender, :recipient, :date, :read, :flagged, :hasAttachment, :size, :fileId, :uid, :bodyHtml, :toAddr, :ccAddr, :bccAddr)"
|
||||
);
|
||||
query.bindValue(":folderId", item.folderId());
|
||||
query.bindValue(":messageId", item.messageId());
|
||||
query.bindValue(":messageId", item.messageId().isEmpty() ? QVariant() : QVariant(item.messageId()));
|
||||
query.bindValue(":subject", item.subject());
|
||||
query.bindValue(":sender", item.sender());
|
||||
query.bindValue(":recipient", item.recipient());
|
||||
@@ -23,17 +43,27 @@ bool MailItemDao::insert(const MailItem& item)
|
||||
query.bindValue(":size", item.size());
|
||||
query.bindValue(":fileId", item.fileId());
|
||||
query.bindValue(":uid", item.uid());
|
||||
query.bindValue(":bodyHtml", item.bodyHtml());
|
||||
query.bindValue(":toAddr", item.to());
|
||||
query.bindValue(":ccAddr", item.cc());
|
||||
query.bindValue(":bccAddr", item.bcc());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to insert mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
item.setId(query.lastInsertId().toLongLong());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MailItemDao::upsert(MailItem& item)
|
||||
{
|
||||
return insert(item);
|
||||
}
|
||||
|
||||
bool MailItemDao::update(const MailItem& item)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"UPDATE MailCopy SET "
|
||||
@@ -46,14 +76,18 @@ bool MailItemDao::update(const MailItem& item)
|
||||
"read = :read, "
|
||||
"flagged = :flagged, "
|
||||
"hasAttachment = :hasAttachment, "
|
||||
"size = :size, "
|
||||
"fileId = :fileId, "
|
||||
"uid = :uid "
|
||||
"size = :size, "
|
||||
"fileId = :fileId, "
|
||||
"uid = :uid, "
|
||||
"bodyHtml = :bodyHtml, "
|
||||
"toAddr = :toAddr, "
|
||||
"ccAddr = :ccAddr, "
|
||||
"bccAddr = :bccAddr "
|
||||
"WHERE id = :id"
|
||||
);
|
||||
query.bindValue(":id", item.id());
|
||||
query.bindValue(":folderId", item.folderId());
|
||||
query.bindValue(":messageId", item.messageId());
|
||||
query.bindValue(":messageId", item.messageId().isEmpty() ? QVariant() : QVariant(item.messageId()));
|
||||
query.bindValue(":subject", item.subject());
|
||||
query.bindValue(":sender", item.sender());
|
||||
query.bindValue(":recipient", item.recipient());
|
||||
@@ -64,6 +98,10 @@ bool MailItemDao::update(const MailItem& item)
|
||||
query.bindValue(":size", item.size());
|
||||
query.bindValue(":fileId", item.fileId());
|
||||
query.bindValue(":uid", item.uid());
|
||||
query.bindValue(":bodyHtml", item.bodyHtml());
|
||||
query.bindValue(":toAddr", item.to());
|
||||
query.bindValue(":ccAddr", item.cc());
|
||||
query.bindValue(":bccAddr", item.bcc());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to update mail item:" << query.lastError().text();
|
||||
@@ -74,7 +112,7 @@ bool MailItemDao::update(const MailItem& item)
|
||||
|
||||
bool MailItemDao::remove(qint64 id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM MailCopy WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
@@ -88,9 +126,9 @@ bool MailItemDao::remove(qint64 id)
|
||||
|
||||
std::optional<MailItem> MailItemDao::findById(qint64 id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid FROM MailCopy WHERE id = :id");
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr FROM MailCopy WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
@@ -112,6 +150,13 @@ std::optional<MailItem> MailItemDao::findById(qint64 id)
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
item.setTo(query.value(14).toString());
|
||||
item.setCc(query.value(15).toString());
|
||||
item.setBcc(query.value(16).toString());
|
||||
QVector<QString> names;
|
||||
for (const auto &attachment : attachmentsForMail(item.id())) names.append(attachment.fileName);
|
||||
item.setAttachments(names);
|
||||
return item;
|
||||
}
|
||||
return std::nullopt;
|
||||
@@ -120,9 +165,9 @@ std::optional<MailItem> MailItemDao::findById(qint64 id)
|
||||
QVector<MailItem> MailItemDao::findAll()
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
if (!query.exec("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid FROM MailCopy")) {
|
||||
if (!query.exec("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr FROM MailCopy")) {
|
||||
qWarning() << "Failed to fetch all mail items:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
@@ -141,6 +186,13 @@ QVector<MailItem> MailItemDao::findAll()
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
item.setTo(query.value(14).toString());
|
||||
item.setCc(query.value(15).toString());
|
||||
item.setBcc(query.value(16).toString());
|
||||
QVector<QString> names;
|
||||
for (const auto &attachment : attachmentsForMail(item.id())) names.append(attachment.fileName);
|
||||
item.setAttachments(names);
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
@@ -149,9 +201,9 @@ QVector<MailItem> MailItemDao::findAll()
|
||||
QVector<MailItem> MailItemDao::findByFolderId(int folderId)
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid FROM MailCopy WHERE folderId = :folderId");
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
@@ -173,6 +225,13 @@ QVector<MailItem> MailItemDao::findByFolderId(int folderId)
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
item.setTo(query.value(14).toString());
|
||||
item.setCc(query.value(15).toString());
|
||||
item.setBcc(query.value(16).toString());
|
||||
QVector<QString> names;
|
||||
for (const auto &attachment : attachmentsForMail(item.id())) names.append(attachment.fileName);
|
||||
item.setAttachments(names);
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
@@ -181,9 +240,9 @@ QVector<MailItem> MailItemDao::findByFolderId(int folderId)
|
||||
QVector<MailItem> MailItemDao::findByFolderIdSinceUid(int folderId, qint64 sinceUid)
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid FROM MailCopy WHERE folderId = :folderId AND id > :sinceUid");
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr FROM MailCopy WHERE folderId = :folderId AND uid > :sinceUid");
|
||||
query.bindValue(":folderId", folderId);
|
||||
query.bindValue(":sinceUid", sinceUid);
|
||||
|
||||
@@ -206,7 +265,132 @@ QVector<MailItem> MailItemDao::findByFolderIdSinceUid(int folderId, qint64 since
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
item.setTo(query.value(14).toString());
|
||||
item.setCc(query.value(15).toString());
|
||||
item.setBcc(query.value(16).toString());
|
||||
QVector<QString> names;
|
||||
for (const auto &attachment : attachmentsForMail(item.id())) names.append(attachment.fileName);
|
||||
item.setAttachments(names);
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<qint64> MailItemDao::maxUidForFolder(int folderId)
|
||||
{
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT MAX(uid) FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to get max uid for folder:" << query.lastError().text();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
if (query.isNull(0)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return query.value(0).toLongLong();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QVector<qint64> MailItemDao::getUidsForFolder(int folderId)
|
||||
{
|
||||
QVector<qint64> uids;
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT uid FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to get uids for folder:" << query.lastError().text();
|
||||
return uids;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
qint64 uid = query.value(0).toLongLong();
|
||||
uids.append(uid);
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
|
||||
QVector<qint64> MailItemDao::uidsForFolder(int folderId)
|
||||
{
|
||||
return getUidsForFolder(folderId);
|
||||
}
|
||||
|
||||
std::optional<MailItem> MailItemDao::findByUid(int folderId, qint64 uid)
|
||||
{
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id FROM MailCopy WHERE folderId = :folderId AND uid = :uid LIMIT 1");
|
||||
query.bindValue(":folderId", folderId);
|
||||
query.bindValue(":uid", uid);
|
||||
if (!query.exec() || !query.next()) return std::nullopt;
|
||||
return findById(query.value(0).toLongLong());
|
||||
}
|
||||
|
||||
bool MailItemDao::removeByUid(int folderId, qint64 uid)
|
||||
{
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM MailCopy WHERE folderId = :folderId AND uid = :uid");
|
||||
query.bindValue(":folderId", folderId);
|
||||
query.bindValue(":uid", uid);
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to delete mail item by UID:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MailItemDao::replaceAttachments(qint64 mailItemId,
|
||||
const QVector<StoredAttachmentRecord>& attachments)
|
||||
{
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
if (!db.transaction()) return false;
|
||||
|
||||
QSqlQuery remove(db);
|
||||
remove.prepare("DELETE FROM Attachment WHERE mailCopyId = :mailCopyId");
|
||||
remove.bindValue(":mailCopyId", mailItemId);
|
||||
if (!remove.exec()) { db.rollback(); return false; }
|
||||
|
||||
QSqlQuery insert(db);
|
||||
insert.prepare("INSERT INTO Attachment (mailCopyId, filename, mimeType, size, contentId, storedPath) "
|
||||
"VALUES (:mailCopyId, :filename, :mimeType, :size, :contentId, :storedPath)");
|
||||
for (const StoredAttachmentRecord &attachment : attachments) {
|
||||
insert.bindValue(":mailCopyId", mailItemId);
|
||||
insert.bindValue(":filename", attachment.fileName);
|
||||
insert.bindValue(":mimeType", attachment.mimeType);
|
||||
insert.bindValue(":size", attachment.size);
|
||||
insert.bindValue(":contentId", attachment.contentId);
|
||||
insert.bindValue(":storedPath", attachment.storedPath);
|
||||
if (!insert.exec()) { db.rollback(); return false; }
|
||||
}
|
||||
return db.commit();
|
||||
}
|
||||
|
||||
QVector<StoredAttachmentRecord> MailItemDao::attachmentsForMail(qint64 mailItemId)
|
||||
{
|
||||
QVector<StoredAttachmentRecord> result;
|
||||
QSqlDatabase db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT filename, mimeType, size, contentId, storedPath "
|
||||
"FROM Attachment WHERE mailCopyId = :mailCopyId ORDER BY id");
|
||||
query.bindValue(":mailCopyId", mailItemId);
|
||||
if (!query.exec()) return result;
|
||||
while (query.next()) {
|
||||
StoredAttachmentRecord attachment;
|
||||
attachment.fileName = query.value(0).toString();
|
||||
attachment.mimeType = query.value(1).toString();
|
||||
attachment.size = query.value(2).toLongLong();
|
||||
attachment.contentId = query.value(3).toString();
|
||||
attachment.storedPath = query.value(4).toString();
|
||||
result.append(attachment);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include "mailitemdao.h"
|
||||
#include <optional>
|
||||
|
||||
bool MailItemDao::insert(const MailItem& item)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"INSERT INTO MailCopy (folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid) "
|
||||
"VALUES (:folderId, :messageId, :subject, :sender, :recipient, :date, :read, :flagged, :hasAttachment, :size, :fileId, :uid)"
|
||||
);
|
||||
query.bindValue(":folderId", item.folderId());
|
||||
query.bindValue(":messageId", item.messageId());
|
||||
query.bindValue(":subject", item.subject());
|
||||
query.bindValue(":sender", item.sender());
|
||||
query.bindValue(":recipient", item.recipient());
|
||||
query.bindValue(":date", item.date());
|
||||
query.bindValue(":read", item.isRead() ? 1 : 0);
|
||||
query.bindValue(":flagged", item.isFlagged() ? 1 : 0);
|
||||
query.bindValue(":hasAttachment", !item.attachments().isEmpty() ? 1 : 0);
|
||||
query.bindValue(":size", item.size());
|
||||
query.bindValue(":fileId", item.fileId());
|
||||
query.bindValue(":uid", item.uid());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to insert mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MailItemDao::update(const MailItem& item)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"UPDATE MailCopy SET "
|
||||
"folderId = :folderId, "
|
||||
"messageId = :messageId, "
|
||||
"subject = :subject, "
|
||||
"sender = :sender, "
|
||||
"recipient = :recipient, "
|
||||
"date = :date, "
|
||||
"read = :read, "
|
||||
"flagged = :flagged, "
|
||||
"hasAttachment = :hasAttachment, "
|
||||
"size = :size, "
|
||||
"fileId = :fileId, "
|
||||
"uid = :uid "
|
||||
"WHERE id = :id"
|
||||
);
|
||||
query.bindValue(":id", item.id());
|
||||
query.bindValue(":folderId", item.folderId());
|
||||
query.bindValue(":messageId", item.messageId());
|
||||
query.bindValue(":subject", item.subject());
|
||||
query.bindValue(":sender", item.sender());
|
||||
query.bindValue(":recipient", item.recipient());
|
||||
query.bindValue(":date", item.date());
|
||||
query.bindValue(":read", item.isRead() ? 1 : 0);
|
||||
query.bindValue(":flagged", item.isFlagged() ? 1 : 0);
|
||||
query.bindValue(":hasAttachment", !item.attachments().isEmpty() ? 1 : 0);
|
||||
query.bindValue(":size", item.size());
|
||||
query.bindValue(":fileId", item.fileId());
|
||||
query.bindValue(":uid", item.uid());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to update mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MailItemDao::remove(qint64 id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM MailCopy WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to delete mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<MailItem> MailItemDao::findById(qint64 id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid FROM MailCopy WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to find mail item by id:" << query.lastError().text();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
return item;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QVector<MailItem> MailItemDao::findAll()
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
if (!query.exec("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid FROM MailCopy")) {
|
||||
qWarning() << "Failed to fetch all mail items:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
QVector<MailItem> MailItemDao::findByFolderId(int folderId)
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to fetch mail items by folder id:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
QVector<MailItem> MailItemDao::findByFolderIdSinceUid(int folderId, qint64 sinceUid)
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid FROM MailCopy WHERE folderId = :folderId AND uid > :sinceUid");
|
||||
query.bindValue(":folderId", folderId);
|
||||
query.bindValue(":sinceUid", sinceUid);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to fetch mail items by folder id since uid:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
std::optional<qint64> MailItemDao::maxUidForFolder(int folderId)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT MAX(uid) FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to get max uid for folder:" << query.lastError().text();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
if (query.isNull(0)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return query.value(0).toLongLong();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QVector<qint64> MailItemDao::uidsForFolder(int folderId)
|
||||
{
|
||||
QVector<qint64> uids;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT uid FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to get uids for folder:" << query.lastError().text();
|
||||
return uids;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
qint64 uid = query.value(0).toLongLong();
|
||||
if (uid > 0) {
|
||||
uids.append(uid);
|
||||
}
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include "mailitemdao.h"
|
||||
#include <QDebug>
|
||||
#include <optional>
|
||||
|
||||
bool MailItemDao::insert(MailItem& item)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"INSERT INTO MailCopy (folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr) "
|
||||
"VALUES (:folderId, :messageId, :subject, :sender, :recipient, :date, :read, :flagged, :hasAttachment, :size, :fileId, :uid, :bodyHtml, :toAddr, :ccAddr, :bccAddr)"
|
||||
);
|
||||
query.bindValue(":folderId", item.folderId());
|
||||
query.bindValue(":messageId", item.messageId());
|
||||
query.bindValue(":subject", item.subject());
|
||||
query.bindValue(":sender", item.sender());
|
||||
query.bindValue(":recipient", item.recipient());
|
||||
query.bindValue(":date", item.date());
|
||||
query.bindValue(":read", item.isRead() ? 1 : 0);
|
||||
query.bindValue(":flagged", item.isFlagged() ? 1 : 0);
|
||||
query.bindValue(":hasAttachment", !item.attachments().isEmpty() ? 1 : 0);
|
||||
query.bindValue(":size", item.size());
|
||||
query.bindValue(":fileId", item.fileId());
|
||||
query.bindValue(":uid", item.uid());
|
||||
query.bindValue(":bodyHtml", item.bodyHtml());
|
||||
query.bindValue(":toAddr", item.to());
|
||||
query.bindValue(":ccAddr", item.cc());
|
||||
query.bindValue(":bccAddr", item.bcc());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to insert mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
qInfo() << "Last insert id:" << query.lastInsertId();
|
||||
item.setId(query.lastInsertId().toLongLong());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MailItemDao::update(const MailItem& item)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"UPDATE MailCopy SET "
|
||||
"folderId = :folderId, "
|
||||
"messageId = :messageId, "
|
||||
"subject = :subject, "
|
||||
"sender = :sender, "
|
||||
"recipient = :recipient, "
|
||||
"date = :date, "
|
||||
"read = :read, "
|
||||
"flagged = :flagged, "
|
||||
"hasAttachment = :hasAttachment, "
|
||||
"size = :size, "
|
||||
"fileId = :fileId, "
|
||||
"uid = :uid, "
|
||||
"bodyHtml = :bodyHtml "
|
||||
"WHERE id = :id"
|
||||
);
|
||||
query.bindValue(":id", item.id());
|
||||
query.bindValue(":folderId", item.folderId());
|
||||
query.bindValue(":messageId", item.messageId());
|
||||
query.bindValue(":subject", item.subject());
|
||||
query.bindValue(":sender", item.sender());
|
||||
query.bindValue(":recipient", item.recipient());
|
||||
query.bindValue(":date", item.date());
|
||||
query.bindValue(":read", item.isRead() ? 1 : 0);
|
||||
query.bindValue(":flagged", item.isFlagged() ? 1 : 0);
|
||||
query.bindValue(":hasAttachment", !item.attachments().isEmpty() ? 1 : 0);
|
||||
query.bindValue(":size", item.size());
|
||||
query.bindValue(":fileId", item.fileId());
|
||||
query.bindValue(":uid", item.uid());
|
||||
query.bindValue(":bodyHtml", item.bodyHtml());
|
||||
query.bindValue(":toAddr", item.to());
|
||||
query.bindValue(":ccAddr", item.cc());
|
||||
query.bindValue(":bccAddr", item.bcc());
|
||||
query.bindValue(":toAddr", item.to());
|
||||
query.bindValue(":ccAddr", item.cc());
|
||||
query.bindValue(":bccAddr", item.bcc());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to update mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MailItemDao::remove(qint64 id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM MailCopy WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to delete mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<MailItem> MailItemDao::findById(qint64 id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr FROM MailCopy WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to find mail item by id:" << query.lastError().text();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
item.setTo(query.value(14).toString());
|
||||
item.setCc(query.value(15).toString());
|
||||
item.setBcc(query.value(16).toString());
|
||||
qDebug() << "Debug findById: toAddr=" << query.value(14).toString() << " ccAddr=" << query.value(15).toString() << " bccAddr=" << query.value(16).toString();
|
||||
return item;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QVector<MailItem> MailItemDao::findAll()
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
if (!query.exec("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr FROM MailCopy")) {
|
||||
qWarning() << "Failed to fetch all mail items:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
item.setTo(query.value(14).toString());
|
||||
item.setCc(query.value(15).toString());
|
||||
item.setBcc(query.value(16).toString());
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
QVector<MailItem> MailItemDao::findByFolderId(int folderId)
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to fetch mail items by folder id:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
item.setTo(query.value(14).toString());
|
||||
item.setCc(query.value(15).toString());
|
||||
item.setBcc(query.value(16).toString());
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
QVector<MailItem> MailItemDao::findByFolderIdSinceUid(int folderId, qint64 sinceUid)
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr FROM MailCopy WHERE folderId = :folderId AND uid > :sinceUid");
|
||||
query.bindValue(":folderId", folderId);
|
||||
query.bindValue(":sinceUid", sinceUid);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to fetch mail items by folder id since uid:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
item.setTo(query.value(14).toString());
|
||||
item.setCc(query.value(15).toString());
|
||||
item.setBcc(query.value(16).toString());
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
std::optional<qint64> MailItemDao::maxUidForFolder(int folderId)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT MAX(uid) FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to get max uid for folder:" << query.lastError().text();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
if (query.isNull(0)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return query.value(0).toLongLong();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QVector<qint64> MailItemDao::getUidsForFolder(int folderId)
|
||||
{
|
||||
QVector<qint64> uids;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT uid FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to get uids for folder:" << query.lastError().text();
|
||||
return uids;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
qint64 uid = query.value(0).toLongLong();
|
||||
uids.append(uid);
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include "mailitemdao.h"
|
||||
#include <optional>
|
||||
|
||||
bool MailItemDao::insert(const MailItem& item)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"INSERT INTO MailCopy (folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml) "
|
||||
"VALUES (:folderId, :messageId, :subject, :sender, :recipient, :date, :read, :flagged, :hasAttachment, :size, :fileId, :uid, :bodyHtml)"
|
||||
);
|
||||
query.bindValue(":folderId", item.folderId());
|
||||
query.bindValue(":messageId", item.messageId());
|
||||
query.bindValue(":subject", item.subject());
|
||||
query.bindValue(":sender", item.sender());
|
||||
query.bindValue(":recipient", item.recipient());
|
||||
query.bindValue(":date", item.date());
|
||||
query.bindValue(":read", item.isRead() ? 1 : 0);
|
||||
query.bindValue(":flagged", item.isFlagged() ? 1 : 0);
|
||||
query.bindValue(":hasAttachment", !item.attachments().isEmpty() ? 1 : 0);
|
||||
query.bindValue(":size", item.size());
|
||||
query.bindValue(":fileId", item.fileId());
|
||||
query.bindValue(":uid", item.uid());
|
||||
query.bindValue(":bodyHtml", item.bodyHtml());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to insert mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MailItemDao::update(const MailItem& item)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"UPDATE MailCopy SET "
|
||||
"folderId = :folderId, "
|
||||
"messageId = :messageId, "
|
||||
"subject = :subject, "
|
||||
"sender = :sender, "
|
||||
"recipient = :recipient, "
|
||||
"date = :date, "
|
||||
"read = :read, "
|
||||
"flagged = :flagged, "
|
||||
"hasAttachment = :hasAttachment, "
|
||||
"size = :size, "
|
||||
"fileId = :fileId, "
|
||||
"uid = :uid, "
|
||||
"bodyHtml = :bodyHtml "
|
||||
"WHERE id = :id"
|
||||
);
|
||||
query.bindValue(":id", item.id());
|
||||
query.bindValue(":folderId", item.folderId());
|
||||
query.bindValue(":messageId", item.messageId());
|
||||
query.bindValue(":subject", item.subject());
|
||||
query.bindValue(":sender", item.sender());
|
||||
query.bindValue(":recipient", item.recipient());
|
||||
query.bindValue(":date", item.date());
|
||||
query.bindValue(":read", item.isRead() ? 1 : 0);
|
||||
query.bindValue(":flagged", item.isFlagged() ? 1 : 0);
|
||||
query.bindValue(":hasAttachment", !item.attachments().isEmpty() ? 1 : 0);
|
||||
query.bindValue(":size", item.size());
|
||||
query.bindValue(":fileId", item.fileId());
|
||||
query.bindValue(":uid", item.uid());
|
||||
query.bindValue(":bodyHtml", item.bodyHtml());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to update mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MailItemDao::remove(qint64 id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM MailCopy WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to delete mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<MailItem> MailItemDao::findById(qint64 id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to find mail item by id:" << query.lastError().text();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
return item;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QVector<MailItem> MailItemDao::findAll()
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
if (!query.exec("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy")) {
|
||||
qWarning() << "Failed to fetch all mail items:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
QVector<MailItem> MailItemDao::findByFolderId(int folderId)
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to fetch mail items by folder id:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
QVector<MailItem> MailItemDao::findByFolderIdSinceUid(int folderId, qint64 sinceUid)
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy WHERE folderId = :folderId AND uid > :sinceUid");
|
||||
query.bindValue(":folderId", folderId);
|
||||
query.bindValue(":sinceUid", sinceUid);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to fetch mail items by folder id since uid:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
std::optional<qint64> MailItemDao::maxUidForFolder(int folderId)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT MAX(uid) FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to get max uid for folder:" << query.lastError().text();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
if (query.isNull(0)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return query.value(0).toLongLong();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QVector<qint64> MailItemDao::getUidsForFolder(int folderId)
|
||||
{
|
||||
QVector<qint64> uids;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT uid FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to get uids for folder:" << query.lastError().text();
|
||||
return uids;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
qint64 uid = query.value(0).toLongLong();
|
||||
uids.append(uid);
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include "mailitemdao.h"
|
||||
#include <optional>
|
||||
|
||||
bool MailItemDao::insert(const MailItem& item)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"INSERT INTO MailCopy (folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr) "
|
||||
"VALUES (:folderId, :messageId, :subject, :sender, :recipient, :date, :read, :flagged, :hasAttachment, :size, :fileId, :uid, :bodyHtml, :toAddr, :ccAddr, :bccAddr)"
|
||||
);
|
||||
query.bindValue(":folderId", item.folderId());
|
||||
query.bindValue(":messageId", item.messageId());
|
||||
query.bindValue(":subject", item.subject());
|
||||
query.bindValue(":sender", item.sender());
|
||||
query.bindValue(":recipient", item.recipient());
|
||||
query.bindValue(":date", item.date());
|
||||
query.bindValue(":read", item.isRead() ? 1 : 0);
|
||||
query.bindValue(":flagged", item.isFlagged() ? 1 : 0);
|
||||
query.bindValue(":hasAttachment", !item.attachments().isEmpty() ? 1 : 0);
|
||||
query.bindValue(":size", item.size());
|
||||
query.bindValue(":fileId", item.fileId());
|
||||
query.bindValue(":uid", item.uid());
|
||||
query.bindValue(":bodyHtml", item.bodyHtml());
|
||||
query.bindValue(":toAddr", item.to());
|
||||
query.bindValue(":ccAddr", item.cc());
|
||||
query.bindValue(":bccAddr", item.bcc());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to insert mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MailItemDao::update(const MailItem& item)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare(
|
||||
"UPDATE MailCopy SET "
|
||||
"folderId = :folderId, "
|
||||
"messageId = :messageId, "
|
||||
"subject = :subject, "
|
||||
"sender = :sender, "
|
||||
"recipient = :recipient, "
|
||||
"date = :date, "
|
||||
"read = :read, "
|
||||
"flagged = :flagged, "
|
||||
"hasAttachment = :hasAttachment, "
|
||||
"size = :size, "
|
||||
"fileId = :fileId, "
|
||||
"uid = :uid, "
|
||||
"bodyHtml = :bodyHtml "
|
||||
"WHERE id = :id"
|
||||
);
|
||||
query.bindValue(":id", item.id());
|
||||
query.bindValue(":folderId", item.folderId());
|
||||
query.bindValue(":messageId", item.messageId());
|
||||
query.bindValue(":subject", item.subject());
|
||||
query.bindValue(":sender", item.sender());
|
||||
query.bindValue(":recipient", item.recipient());
|
||||
query.bindValue(":date", item.date());
|
||||
query.bindValue(":read", item.isRead() ? 1 : 0);
|
||||
query.bindValue(":flagged", item.isFlagged() ? 1 : 0);
|
||||
query.bindValue(":hasAttachment", !item.attachments().isEmpty() ? 1 : 0);
|
||||
query.bindValue(":size", item.size());
|
||||
query.bindValue(":fileId", item.fileId());
|
||||
query.bindValue(":uid", item.uid());
|
||||
query.bindValue(":bodyHtml", item.bodyHtml());
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to update mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MailItemDao::remove(qint64 id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("DELETE FROM MailCopy WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to delete mail item:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<MailItem> MailItemDao::findById(qint64 id)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy WHERE id = :id");
|
||||
query.bindValue(":id", id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to find mail item by id:" << query.lastError().text();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
return item;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QVector<MailItem> MailItemDao::findAll()
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
if (!query.exec("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy")) {
|
||||
qWarning() << "Failed to fetch all mail items:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
QVector<MailItem> MailItemDao::findByFolderId(int folderId)
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to fetch mail items by folder id:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
QVector<MailItem> MailItemDao::findByFolderIdSinceUid(int folderId, qint64 sinceUid)
|
||||
{
|
||||
QVector<MailItem> items;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy WHERE folderId = :folderId AND uid > :sinceUid");
|
||||
query.bindValue(":folderId", folderId);
|
||||
query.bindValue(":sinceUid", sinceUid);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to fetch mail items by folder id since uid:" << query.lastError().text();
|
||||
return items;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
MailItem item;
|
||||
item.setId(query.value(0).toInt());
|
||||
item.setFolderId(query.value(1).toInt());
|
||||
item.setMessageId(query.value(2).toString());
|
||||
item.setSubject(query.value(3).toString());
|
||||
item.setSender(query.value(4).toString());
|
||||
item.setRecipient(query.value(5).toString());
|
||||
item.setDate(query.value(6).toDateTime());
|
||||
item.setRead(query.value(7).toBool());
|
||||
item.setFlagged(query.value(8).toBool());
|
||||
item.setSize(query.value(10).toLongLong());
|
||||
item.setFileId(query.value(11).toString());
|
||||
item.setUid(query.value(12).toLongLong());
|
||||
item.setBodyHtml(query.value(13).toString());
|
||||
items.append(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
std::optional<qint64> MailItemDao::maxUidForFolder(int folderId)
|
||||
{
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT MAX(uid) FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to get max uid for folder:" << query.lastError().text();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
if (query.isNull(0)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return query.value(0).toLongLong();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QVector<qint64> MailItemDao::getUidsForFolder(int folderId)
|
||||
{
|
||||
QVector<qint64> uids;
|
||||
QSqlDatabase& db = DatabaseManager::instance().database();
|
||||
QSqlQuery query(db);
|
||||
query.prepare("SELECT uid FROM MailCopy WHERE folderId = :folderId");
|
||||
query.bindValue(":folderId", folderId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "Failed to get uids for folder:" << query.lastError().text();
|
||||
return uids;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
qint64 uid = query.value(0).toLongLong();
|
||||
uids.append(uid);
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
@@ -5,14 +5,31 @@
|
||||
#include <QVector>
|
||||
#include <optional>
|
||||
|
||||
struct StoredAttachmentRecord
|
||||
{
|
||||
QString fileName;
|
||||
QString mimeType;
|
||||
QString contentId;
|
||||
qint64 size{0};
|
||||
QString storedPath;
|
||||
};
|
||||
|
||||
class MailItemDao
|
||||
{
|
||||
public:
|
||||
static bool insert(const MailItem& item);
|
||||
static bool insert(MailItem& item);
|
||||
static bool upsert(MailItem& item);
|
||||
static bool update(const MailItem& item);
|
||||
static bool remove(qint64 id);
|
||||
static std::optional<MailItem> findById(qint64 id);
|
||||
static QVector<MailItem> findAll();
|
||||
static QVector<MailItem> findByFolderId(int folderId);
|
||||
static QVector<MailItem> findByFolderIdSinceUid(int folderId, qint64 sinceUid);
|
||||
};
|
||||
static std::optional<qint64> maxUidForFolder(int folderId);
|
||||
static QVector<qint64> getUidsForFolder(int folderId);
|
||||
static QVector<qint64> uidsForFolder(int folderId);
|
||||
static std::optional<MailItem> findByUid(int folderId, qint64 uid);
|
||||
static bool removeByUid(int folderId, qint64 uid);
|
||||
static bool replaceAttachments(qint64 mailItemId, const QVector<StoredAttachmentRecord>& attachments);
|
||||
static QVector<StoredAttachmentRecord> attachmentsForMail(qint64 mailItemId);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import sys
|
||||
import re
|
||||
|
||||
filename = sys.argv[1]
|
||||
with open(filename, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Helper to replace SELECT clause and add mapping after setBodyHtml
|
||||
def replace_select_and_add_mapping(content, func_name):
|
||||
# Pattern to find the function (simplistic but works for our file)
|
||||
# We'll replace the SELECT string inside the function.
|
||||
# Since each function has a unique SELECT, we can replace directly.
|
||||
if func_name == 'findById':
|
||||
# Replace SELECT line
|
||||
pattern = r'(query\.prepare\\(\s*"SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy WHERE id = :id"\s*\\);)'
|
||||
replacement = '''query.prepare(
|
||||
"SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr FROM MailCopy WHERE id = :id"
|
||||
);'''
|
||||
content = re.sub(pattern, replacement, content)
|
||||
# Add mapping after setBodyHtml line
|
||||
# Find line with item.setBodyHtml(query.value(13).toString());
|
||||
pattern2 = r'(item\.setBodyHtml\(query\.value\(13\)\.toString\(\);\s*\n\s*)'
|
||||
replacement2 = r'\1 item.setTo(query.value(14).toString());\n item.setCc(query.value(15).toString());\n item.setBcc(query.value(16).toString());\n'
|
||||
content = re.sub(pattern2, replacement2, content)
|
||||
elif func_name == 'findAll':
|
||||
# SELECT line inside exec
|
||||
pattern = r'(query\.exec\(\s*"SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy"\s*\)\s*)'
|
||||
# We need to replace the whole argument; easier: replace the string inside.
|
||||
# We'll replace the quoted string.
|
||||
pattern = r'"SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy"'
|
||||
replacement = '"SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr FROM MailCopy"'
|
||||
content = re.sub(pattern, replacement, content)
|
||||
# Add mapping after setBodyHtml line in the while loop
|
||||
pattern2 = r'(item\.setBodyHtml\(query\.value\(13\)\.toString\(\);\s*\n\s*)'
|
||||
replacement2 = r'\1 item.setTo(query.value(14).toString());\n item.setCc(query.value(15).toString());\n item.setBcc(query.value(16).toString());\n'
|
||||
content = re.sub(pattern2, replacement2, content)
|
||||
elif func_name == 'findByFolderId':
|
||||
pattern = r'"SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy WHERE folderId = :folderId"'
|
||||
replacement = '"SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr FROM MailCopy WHERE folderId = :folderId"'
|
||||
content = re.sub(pattern, replacement, content)
|
||||
pattern2 = r'(item\.setBodyHtml\(query\.value\(13\)\.toString\(\);\s*\n\s*)'
|
||||
replacement2 = r'\1 item.setTo(query.value(14).toString());\n item.setCc(query.value(15).toString());\n item.setBcc(query.value(16).toString());\n'
|
||||
content = re.sub(pattern2, replacement2, content)
|
||||
elif func_name == 'findByFolderIdSinceUid':
|
||||
pattern = r'"SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml FROM MailCopy WHERE folderId = :folderId AND uid > :sinceUid"'
|
||||
replacement = '"SELECT id, folderId, messageId, subject, sender, recipient, date, read, flagged, hasAttachment, size, fileId, uid, bodyHtml, toAddr, ccAddr, bccAddr FROM MailCopy WHERE folderId = :folderId AND uid > :sinceUid"'
|
||||
content = re.sub(pattern, replacement, content)
|
||||
pattern2 = r'(item\.setBodyHtml\(query\.value\(13\)\.toString\(\);\s*\n\s*)'
|
||||
replacement2 = r'\1 item.setTo(query.value(14).toString());\n item.setCc(query.value(15).toString());\n item.setBcc(query.value(16).toString());\n'
|
||||
content = re.sub(pattern2, replacement2, content)
|
||||
return content
|
||||
|
||||
# Apply to each function
|
||||
for func in ['findById', 'findAll', 'findByFolderId', 'findByFolderIdSinceUid']:
|
||||
content = replace_select_and_add_mapping(content, func)
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
f.write(content)
|
||||
print('Modified', filename)
|
||||
@@ -37,6 +37,11 @@ bool DatabaseManager::initialize(const QString& databasePath)
|
||||
dbPath = dir.filePath("wino-mail.sqlite");
|
||||
}
|
||||
|
||||
m_databasePath = dbPath;
|
||||
m_ownerThread = QThread::currentThreadId();
|
||||
|
||||
qDebug() << "[DatabaseManager] Opening database at:" << dbPath;
|
||||
|
||||
m_db = QSqlDatabase::addDatabase("QSQLITE", "wino_mail_connection");
|
||||
m_db.setDatabaseName(dbPath);
|
||||
|
||||
@@ -45,18 +50,22 @@ bool DatabaseManager::initialize(const QString& databasePath)
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "[DatabaseManager] Database opened successfully";
|
||||
|
||||
QSqlQuery query(m_db);
|
||||
// Enable foreign keys
|
||||
qDebug() << "[DatabaseManager] Enabling foreign keys";
|
||||
query.exec("PRAGMA foreign_keys = ON;");
|
||||
|
||||
// Create tables if they don't exist
|
||||
qDebug() << "[DatabaseManager] Creating Account table";
|
||||
|
||||
// Account table
|
||||
if (!query.exec(
|
||||
"CREATE TABLE IF NOT EXISTS Account ("
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"email TEXT NOT NULL, "
|
||||
"displayName TEXT, ""signature TEXT, "
|
||||
"displayName TEXT, signature TEXT, "
|
||||
"type INTEGER NOT NULL, " // 0=Outlook,1=Gmail,2=IMAP
|
||||
"accessToken TEXT, "
|
||||
"refreshToken TEXT, "
|
||||
@@ -74,6 +83,7 @@ bool DatabaseManager::initialize(const QString& databasePath)
|
||||
qWarning() << "Failed to create Account table:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
qDebug() << "[DatabaseManager] Account table created successfully";
|
||||
|
||||
// Folder table
|
||||
if (!query.exec(
|
||||
@@ -110,6 +120,10 @@ bool DatabaseManager::initialize(const QString& databasePath)
|
||||
"size INTEGER, "
|
||||
"uid INTEGER, "
|
||||
"fileId TEXT, " // references the .eml file in storage
|
||||
"bodyHtml TEXT, "
|
||||
"toAddr TEXT, "
|
||||
"ccAddr TEXT, "
|
||||
"bccAddr TEXT, "
|
||||
"FOREIGN KEY(folderId) REFERENCES Folder(id) ON DELETE CASCADE"
|
||||
");")) {
|
||||
qWarning() << "Failed to create MailCopy table:" << query.lastError().text();
|
||||
@@ -125,18 +139,52 @@ bool DatabaseManager::initialize(const QString& databasePath)
|
||||
"mimeType TEXT, "
|
||||
"size INTEGER, "
|
||||
"contentId TEXT, "
|
||||
"storedPath TEXT, "
|
||||
"FOREIGN KEY(mailCopyId) REFERENCES MailCopy(id) ON DELETE CASCADE"
|
||||
");")) {
|
||||
qWarning() << "Failed to create Attachment table:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Existing installations were created before storedPath was introduced.
|
||||
// SQLite reports an error when the column already exists, which is safe to
|
||||
// ignore here because the CREATE TABLE above covers new databases.
|
||||
query.exec("ALTER TABLE Account ADD COLUMN signature TEXT");
|
||||
query.exec("ALTER TABLE MailCopy ADD COLUMN toAddr TEXT");
|
||||
query.exec("ALTER TABLE MailCopy ADD COLUMN ccAddr TEXT");
|
||||
query.exec("ALTER TABLE MailCopy ADD COLUMN bccAddr TEXT");
|
||||
query.exec("ALTER TABLE MailCopy ADD COLUMN bodyHtml TEXT");
|
||||
query.exec("ALTER TABLE MailCopy ADD COLUMN uid INTEGER");
|
||||
query.exec("ALTER TABLE MailCopy ADD COLUMN fileId TEXT");
|
||||
query.exec("ALTER TABLE Attachment ADD COLUMN storedPath TEXT");
|
||||
query.exec("CREATE INDEX IF NOT EXISTS idx_mailcopy_folder_uid ON MailCopy(folderId, uid)");
|
||||
query.exec("CREATE INDEX IF NOT EXISTS idx_attachment_mailcopy ON Attachment(mailCopyId)");
|
||||
|
||||
m_initialized = true;
|
||||
qDebug() << "Database initialized at:" << dbPath;
|
||||
return true;
|
||||
}
|
||||
|
||||
QSqlDatabase& DatabaseManager::database()
|
||||
QSqlDatabase DatabaseManager::database()
|
||||
{
|
||||
return m_db;
|
||||
}
|
||||
if (QThread::currentThreadId() == m_ownerThread)
|
||||
return m_db;
|
||||
|
||||
const QString connectionName = QStringLiteral("wino_mail_connection_%1")
|
||||
.arg(reinterpret_cast<quintptr>(QThread::currentThreadId()), 0, 16);
|
||||
if (QSqlDatabase::contains(connectionName))
|
||||
return QSqlDatabase::database(connectionName);
|
||||
|
||||
QMutexLocker locker(&m_mutex);
|
||||
if (QSqlDatabase::contains(connectionName))
|
||||
return QSqlDatabase::database(connectionName);
|
||||
QSqlDatabase db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), connectionName);
|
||||
db.setDatabaseName(m_databasePath);
|
||||
if (!db.open()) {
|
||||
qWarning() << "Failed to open thread-local database:" << db.lastError().text();
|
||||
return db;
|
||||
}
|
||||
QSqlQuery pragma(db);
|
||||
pragma.exec(QStringLiteral("PRAGMA foreign_keys = ON"));
|
||||
return db;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
#include "databasemanager.h"
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QDebug>
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
|
||||
DatabaseManager& DatabaseManager::instance()
|
||||
{
|
||||
static DatabaseManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
DatabaseManager::DatabaseManager() = default;
|
||||
|
||||
DatabaseManager::~DatabaseManager()
|
||||
{
|
||||
if (m_db.isOpen()) {
|
||||
m_db.close();
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabaseManager::initialize(const QString& databasePath)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
if (m_initialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QString dbPath = databasePath;
|
||||
if (dbPath.isEmpty()) {
|
||||
// Use application data location
|
||||
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(".");
|
||||
}
|
||||
dbPath = dir.filePath("wino-mail.sqlite");
|
||||
}
|
||||
|
||||
m_db = QSqlDatabase::addDatabase("QSQLITE", "wino_mail_connection");
|
||||
m_db.setDatabaseName(dbPath);
|
||||
|
||||
if (!m_db.open()) {
|
||||
qWarning() << "Failed to open database:" << m_db.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
QSqlQuery query(m_db);
|
||||
// Enable foreign keys
|
||||
query.exec("PRAGMA foreign_keys = ON;");
|
||||
|
||||
// Create tables if they don't exist
|
||||
|
||||
// Account table
|
||||
if (!query.exec(
|
||||
"CREATE TABLE IF NOT EXISTS Account ("
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"email TEXT NOT NULL, "
|
||||
"displayName TEXT, signature TEXT, "
|
||||
"type INTEGER NOT NULL, " // 0=Outlook,1=Gmail,2=IMAP
|
||||
"accessToken TEXT, "
|
||||
"refreshToken TEXT, "
|
||||
"tokenExpires DATETIME, "
|
||||
"incomingHost TEXT, "
|
||||
"incomingPort INTEGER, "
|
||||
"incomingSsl INTEGER, "
|
||||
"outgoingHost TEXT, "
|
||||
"outgoingPort INTEGER, "
|
||||
"outgoingSsl INTEGER, "
|
||||
"connUsername TEXT, "
|
||||
"connPassword TEXT, "
|
||||
"authMethod TEXT"
|
||||
");")) {
|
||||
qWarning() << "Failed to create Account table:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Folder table
|
||||
if (!query.exec(
|
||||
"CREATE TABLE IF NOT EXISTS Folder ("
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"accountId INTEGER NOT NULL, "
|
||||
"name TEXT NOT NULL, "
|
||||
"parentFolderId TEXT, "
|
||||
"isInbox BOOLEAN DEFAULT 0, "
|
||||
"isSent BOOLEAN DEFAULT 0, "
|
||||
"isDrafts BOOLEAN DEFAULT 0, "
|
||||
"isTrash BOOLEAN DEFAULT 0, "
|
||||
"unreadCount INTEGER DEFAULT 0, "
|
||||
"lastSynced DATETIME, "
|
||||
"FOREIGN KEY(accountId) REFERENCES Account(id) ON DELETE CASCADE"
|
||||
");")) {
|
||||
qWarning() << "Failed to create Folder table:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
// MailCopy table (simplified)
|
||||
if (!query.exec(
|
||||
"CREATE TABLE IF NOT EXISTS MailCopy ("
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"folderId INTEGER NOT NULL, "
|
||||
"messageId TEXT UNIQUE, "
|
||||
"subject TEXT, "
|
||||
"sender TEXT, "
|
||||
"recipient TEXT, "
|
||||
"date DATETIME, "
|
||||
"read BOOLEAN DEFAULT 0, "
|
||||
"flagged BOOLEAN DEFAULT 0, "
|
||||
"hasAttachment BOOLEAN DEFAULT 0, "
|
||||
"size INTEGER, "
|
||||
"uid INTEGER, "
|
||||
"fileId TEXT, " // references the .eml file in storage
|
||||
"FOREIGN KEY(folderId) REFERENCES Folder(id) ON DELETE CASCADE"
|
||||
");")) {
|
||||
qWarning() << "Failed to create MailCopy table:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attachments table (optional)
|
||||
if (!query.exec(
|
||||
"CREATE TABLE IF NOT EXISTS Attachment ("
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"mailCopyId INTEGER NOT NULL, "
|
||||
"filename TEXT, "
|
||||
"mimeType TEXT, "
|
||||
"size INTEGER, "
|
||||
"contentId TEXT, "
|
||||
"FOREIGN KEY(mailCopyId) REFERENCES MailCopy(id) ON DELETE CASCADE"
|
||||
");")) {
|
||||
qWarning() << "Failed to create Attachment table:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_initialized = true;
|
||||
qDebug() << "Database initialized at:" << dbPath;
|
||||
return true;
|
||||
}
|
||||
|
||||
QSqlDatabase& DatabaseManager::database()
|
||||
{
|
||||
return m_db;
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <QSqlDatabase>
|
||||
#include <QString>
|
||||
#include <QMutex>
|
||||
#include <QThread>
|
||||
|
||||
class DatabaseManager
|
||||
{
|
||||
@@ -10,8 +11,10 @@ public:
|
||||
static DatabaseManager& instance();
|
||||
~DatabaseManager();
|
||||
|
||||
bool initialize(const QString& databasePath = QStringLiteral("wino-mail.sqlite"));
|
||||
QSqlDatabase& database();
|
||||
bool initialize(const QString& databasePath = QString());
|
||||
// Returns a connection owned by the calling thread. SQLite/Qt database
|
||||
// connections must never be shared across threads.
|
||||
QSqlDatabase database();
|
||||
|
||||
private:
|
||||
DatabaseManager();
|
||||
@@ -19,5 +22,7 @@ private:
|
||||
|
||||
QSqlDatabase m_db;
|
||||
QMutex m_mutex;
|
||||
QString m_databasePath;
|
||||
Qt::HANDLE m_ownerThread{nullptr};
|
||||
bool m_initialized{false};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -123,7 +123,8 @@ void DbChangeProcessor::processBatch()
|
||||
if (!m_mailItemAddedQueue.isEmpty()) {
|
||||
qDebug() << "DbChangeProcessor: Processing" << m_mailItemAddedQueue.size() << "MailItemAdded events";
|
||||
for (const auto& event : m_mailItemAddedQueue) {
|
||||
MailItemDao::insert(event.item);
|
||||
MailItem item = event.item;
|
||||
MailItemDao::insert(item);
|
||||
}
|
||||
m_mailItemAddedQueue.clear();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
#include "dbchangeprocessor.h"
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
#include "../db/dao/mailitemdao.h"
|
||||
#include "../db/dao/folderdao.h"
|
||||
#include "../db/dao/accountdao.h"
|
||||
|
||||
DbChangeProcessor::DbChangeProcessor(QObject* parent)
|
||||
: QObject(parent),
|
||||
m_batchTimer(new QTimer(this))
|
||||
{
|
||||
// Configurar el timer para procesar batch cada 5 segundos
|
||||
m_batchTimer->setInterval(5000); // 5 segundos
|
||||
connect(m_batchTimer, &QTimer::timeout, this, &DbChangeProcessor::processBatch);
|
||||
m_batchTimer->start();
|
||||
|
||||
// Suscribirse a todos los eventos relevantes
|
||||
SUBSCRIBE(WinoMail::Events::MailItemAddedEvent,
|
||||
[this](const WinoMail::Events::MailItemAddedEvent& event) {
|
||||
handleMailItemAdded(event);
|
||||
});
|
||||
|
||||
SUBSCRIBE(WinoMail::Events::MailItemRemovedEvent,
|
||||
[this](const WinoMail::Events::MailItemRemovedEvent& event) {
|
||||
handleMailItemRemoved(event);
|
||||
});
|
||||
|
||||
SUBSCRIBE(WinoMail::Events::MailItemUpdatedEvent,
|
||||
[this](const WinoMail::Events::MailItemUpdatedEvent& event) {
|
||||
handleMailItemUpdated(event);
|
||||
});
|
||||
|
||||
SUBSCRIBE(WinoMail::Events::FolderAddedEvent,
|
||||
[this](const WinoMail::Events::FolderAddedEvent& event) {
|
||||
handleFolderAdded(event);
|
||||
});
|
||||
|
||||
SUBSCRIBE(WinoMail::Events::FolderRemovedEvent,
|
||||
[this](const WinoMail::Events::FolderRemovedEvent& event) {
|
||||
handleFolderRemoved(event);
|
||||
});
|
||||
|
||||
SUBSCRIBE(WinoMail::Events::FolderUpdatedEvent,
|
||||
[this](const WinoMail::Events::FolderUpdatedEvent& event) {
|
||||
handleFolderUpdated(event);
|
||||
});
|
||||
|
||||
SUBSCRIBE(WinoMail::Events::AccountAddedEvent,
|
||||
[this](const WinoMail::Events::AccountAddedEvent& event) {
|
||||
handleAccountAdded(event);
|
||||
});
|
||||
|
||||
SUBSCRIBE(WinoMail::Events::AccountRemovedEvent,
|
||||
[this](const WinoMail::Events::AccountRemovedEvent& event) {
|
||||
handleAccountRemoved(event);
|
||||
});
|
||||
|
||||
SUBSCRIBE(WinoMail::Events::AccountUpdatedEvent,
|
||||
[this](const WinoMail::Events::AccountUpdatedEvent& event) {
|
||||
handleAccountUpdated(event);
|
||||
});
|
||||
}
|
||||
|
||||
void DbChangeProcessor::handleMailItemAdded(const WinoMail::Events::MailItemAddedEvent& event)
|
||||
{
|
||||
qDebug() << "DbChangeProcessor: Queuing MailItemAddedEvent for ID:" << event.item.id();
|
||||
m_mailItemAddedQueue.append(event);
|
||||
}
|
||||
|
||||
void DbChangeProcessor::handleMailItemRemoved(const WinoMail::Events::MailItemRemovedEvent& event)
|
||||
{
|
||||
qDebug() << "DbChangeProcessor: Queuing MailItemRemovedEvent for UID:" << event.itemUid;
|
||||
m_mailItemRemovedQueue.append(event);
|
||||
}
|
||||
|
||||
void DbChangeProcessor::handleMailItemUpdated(const WinoMail::Events::MailItemUpdatedEvent& event)
|
||||
{
|
||||
qDebug() << "DbChangeProcessor: Queuing MailItemUpdatedEvent for ID:" << event.item.id();
|
||||
m_mailItemUpdatedQueue.append(event);
|
||||
}
|
||||
|
||||
void DbChangeProcessor::handleFolderAdded(const WinoMail::Events::FolderAddedEvent& event)
|
||||
{
|
||||
qDebug() << "DbChangeProcessor: Queuing FolderAddedEvent for folder:" << event.folder.name();
|
||||
m_folderAddedQueue.append(event);
|
||||
}
|
||||
|
||||
void DbChangeProcessor::handleFolderRemoved(const WinoMail::Events::FolderRemovedEvent& event)
|
||||
{
|
||||
qDebug() << "DbChangeProcessor: Queuing FolderRemovedEvent for folder ID:" << event.folderId;
|
||||
m_folderRemovedQueue.append(event);
|
||||
}
|
||||
|
||||
void DbChangeProcessor::handleFolderUpdated(const WinoMail::Events::FolderUpdatedEvent& event)
|
||||
{
|
||||
qDebug() << "DbChangeProcessor: Queuing FolderUpdatedEvent for folder ID:" << event.folder.id();
|
||||
m_folderUpdatedQueue.append(event);
|
||||
}
|
||||
|
||||
void DbChangeProcessor::handleAccountAdded(const WinoMail::Events::AccountAddedEvent& event)
|
||||
{
|
||||
qDebug() << "DbChangeProcessor: Queuing AccountAddedEvent for account:" << event.account.email();
|
||||
m_accountAddedQueue.append(event);
|
||||
}
|
||||
|
||||
void DbChangeProcessor::handleAccountRemoved(const WinoMail::Events::AccountRemovedEvent& event)
|
||||
{
|
||||
qDebug() << "DbChangeProcessor: Queuing AccountRemovedEvent for account ID:" << event.accountId;
|
||||
m_accountRemovedQueue.append(event);
|
||||
}
|
||||
|
||||
void DbChangeProcessor::handleAccountUpdated(const WinoMail::Events::AccountUpdatedEvent& event)
|
||||
{
|
||||
qDebug() << "DbChangeProcessor: Queuing AccountUpdatedEvent for account ID:" << event.account.id();
|
||||
m_accountUpdatedQueue.append(event);
|
||||
}
|
||||
|
||||
void DbChangeProcessor::processBatch()
|
||||
{
|
||||
qDebug() << "DbChangeProcessor: Starting batch processing at" << QDateTime::currentDateTime().toString();
|
||||
|
||||
// Procesar eventos de MailItem añadidos
|
||||
if (!m_mailItemAddedQueue.isEmpty()) {
|
||||
qDebug() << "DbChangeProcessor: Processing" << m_mailItemAddedQueue.size() << "MailItemAdded events";
|
||||
for (auto for (autoconst auto& event event : m_mailItemAddedQueue) { event : m_mailItemAddedQueue) {
|
||||
MailItemDao::insert(event.item);
|
||||
}
|
||||
m_mailItemAddedQueue.clear();
|
||||
}
|
||||
|
||||
// Procesar eventos de MailItem eliminados
|
||||
if (!m_mailItemRemovedQueue.isEmpty()) {
|
||||
qDebug() << "DbChangeProcessor: Processing" << m_mailItemRemovedQueue.size() << "MailItemRemoved events";
|
||||
for (const auto& event : m_mailItemRemovedQueue) {
|
||||
// We don't have removeByUid in MailItemDao, so we skip and log a warning.
|
||||
// In a real implementation, we would need to find the item by uid and folderId to get its id.
|
||||
qWarning() << "DbChangeProcessor: MailItemRemoved event processed but removeByUid not implemented in MailItemDao. Skipping removal for UID:" << event.itemUid;
|
||||
}
|
||||
m_mailItemRemovedQueue.clear();
|
||||
}
|
||||
|
||||
// Procesar eventos de MailItem actualizados
|
||||
if (!m_mailItemUpdatedQueue.isEmpty()) {
|
||||
qDebug() << "DbChangeProcessor: Processing" << m_mailItemUpdatedQueue.size() << "MailItemUpdated events";
|
||||
for (const auto& event : m_mailItemUpdatedQueue) {
|
||||
// We ignore changedFields and update the whole item for simplicity.
|
||||
MailItemDao::update(event.item);
|
||||
}
|
||||
m_mailItemUpdatedQueue.clear();
|
||||
}
|
||||
|
||||
// Procesar eventos de carpetas añadidas
|
||||
if (!m_folderAddedQueue.isEmpty()) {
|
||||
qDebug() << "DbChangeProcessor: Processing" << m_folderAddedQueue.size() << "FolderAdded events";
|
||||
for (const auto& event : m_folderAddedQueue) {
|
||||
FolderDao::insert(event.folder);
|
||||
}
|
||||
m_folderAddedQueue.clear();
|
||||
}
|
||||
|
||||
// Procesar eventos de carpetas eliminadas
|
||||
if (!m_folderRemovedQueue.isEmpty()) {
|
||||
qDebug() << "DbChangeProcessor: Processing" << m_folderRemovedQueue.size() << "FolderRemoved events";
|
||||
for (const auto& event : m_folderRemovedQueue) {
|
||||
// We don't have a way to get the folder id from the event without a query, so we skip and log a warning.
|
||||
qWarning() << "DbChangeProcessor: FolderRemoved event processed but we lack the folder id to remove. Skipping removal for folder ID:" << event.folderId;
|
||||
}
|
||||
m_folderRemovedQueue.clear();
|
||||
}
|
||||
|
||||
// Procesar eventos de carpetas actualizadas
|
||||
if (!m_folderUpdatedQueue.isEmpty()) {
|
||||
qDebug() << "DbChangeProcessor: Processing" << m_folderUpdatedQueue.size() << "FolderUpdated events";
|
||||
for (const auto& event : m_folderUpdatedQueue) {
|
||||
// We ignore changedFields and update the whole folder for simplicity.
|
||||
FolderDao::update(event.folder);
|
||||
}
|
||||
m_folderUpdatedQueue.clear();
|
||||
}
|
||||
|
||||
// Procesar eventos de cuentas añadidas
|
||||
if (!m_accountAddedQueue.isEmpty()) {
|
||||
qDebug() << "DbChangeProcessor: Processing" << m_accountAddedQueue.size() << "AccountAdded events";
|
||||
for (const auto& event : m_accountAddedQueue) {
|
||||
AccountDao::insert(event.account);
|
||||
}
|
||||
m_accountAddedQueue.clear();
|
||||
}
|
||||
|
||||
// Procesar eventos de cuentas eliminadas
|
||||
if (!m_accountRemovedQueue.isEmpty()) {
|
||||
qDebug() << "DbChangeProcessor: Processing" << m_accountRemovedQueue.size() << "AccountRemoved events";
|
||||
for (const auto& event : m_accountRemovedQueue) {
|
||||
AccountDao::remove(event.accountId);
|
||||
}
|
||||
m_accountRemovedQueue.clear();
|
||||
}
|
||||
|
||||
// Procesar eventos de cuentas actualizadas
|
||||
if (!m_accountUpdatedQueue.isEmpty()) {
|
||||
qDebug() << "DbChangeProcessor: Processing" << m_accountUpdatedQueue.size() << "AccountUpdated events";
|
||||
for (const auto& event : m_accountUpdatedQueue) {
|
||||
// We ignore changedFields and update the whole account for simplicity.
|
||||
AccountDao::update(event.account);
|
||||
}
|
||||
m_accountUpdatedQueue.clear();
|
||||
}
|
||||
|
||||
qDebug() << "DbChangeProcessor: Batch processing completed at" << QDateTime::currentDateTime().toString();
|
||||
}
|
||||
|
||||
DbChangeProcessor::~DbChangeProcessor()
|
||||
{
|
||||
if (m_batchTimer->isActive()) {
|
||||
m_batchTimer->stop();
|
||||
}
|
||||
// Procesar cualquier evento restante antes de destruir
|
||||
processBatch();
|
||||
}
|
||||
Reference in New Issue
Block a user