feat: Complete Preferences system implementation
- PreferencesService: QSettings-based persistence for all app settings - StartupBehaviorService: Windows registry auto-start management with policy detection - TranslationService: Language management with QTranslator, 9 built-in languages - AiActionOptionsService: 30+ AI translation language options - SettingsView: New 'Preferences' tab with full UI: * Search Mode (Local/Online) * Default App Mode (Mail/Calendar/Contacts/Settings) * Language selector (9 built-in + .qm files) * Email Sync Interval (1-1440 minutes) * Startup Behavior (auto-start, minimize to tray, notifications) * AI Translation (default language, summarize language, summary save path) - MainMainWindow: Service wiring (PreferencesService, StartupBehaviorService, TranslationService, AiActionOptionsService) - CMake: Added all new service files All services integrated and wired to SettingsView.
This commit is contained in:
@@ -9,6 +9,10 @@
|
||||
#include "ui/rulesmanagerdialog.h"
|
||||
#include "ui/accountsetupdialog.h"
|
||||
#include "ui/delegates/FolderTreeDelegate.h"
|
||||
#include "services/preferencesservice.h"
|
||||
#include "services/startupbehaviorservice.h"
|
||||
#include "services/translationservice.h"
|
||||
#include "services/aiactionoptionsservice.h"
|
||||
#include <optional>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
@@ -333,11 +337,25 @@ void MainMainWindow::connectModels()
|
||||
qDebug() << "[MainMainWindow::connectModels] Start";
|
||||
m_accountService = new AccountService(this);
|
||||
qDebug() << "[MainMainWindow::connectModels] AccountService created";
|
||||
|
||||
// Initialize preferences and related services
|
||||
m_preferencesService = new PreferencesService(this);
|
||||
m_startupBehaviorService = new StartupBehaviorService(this);
|
||||
m_translationService = new TranslationService(this);
|
||||
m_aiActionOptionsService = new AiActionOptionsService(this);
|
||||
|
||||
m_mailService = new MailService(m_accountService, this);
|
||||
qDebug() << "[MainMainWindow::connectModels] MailService created";
|
||||
m_composeView->setAccountService(m_accountService);
|
||||
m_embeddedComposeView->setAccountService(m_accountService);
|
||||
|
||||
// Pass services to settings view
|
||||
m_settingsView->setAccountService(m_accountService);
|
||||
m_settingsView->setPreferencesService(m_preferencesService);
|
||||
m_settingsView->setStartupBehaviorService(m_startupBehaviorService);
|
||||
m_settingsView->setTranslationService(m_translationService);
|
||||
m_settingsView->setAiActionOptionsService(m_aiActionOptionsService);
|
||||
|
||||
m_folderModel = new FolderListModel(m_accountService, this);
|
||||
qDebug() << "[MainMainWindow::connectModels] FolderListModel created";
|
||||
m_emailModel = new EmailListModel(this);
|
||||
|
||||
@@ -139,6 +139,10 @@ private:
|
||||
EmailListModel *m_emailModel;
|
||||
AccountService *m_accountService = nullptr;
|
||||
MailService *m_mailService = nullptr;
|
||||
PreferencesService *m_preferencesService = nullptr;
|
||||
StartupBehaviorService *m_startupBehaviorService = nullptr;
|
||||
TranslationService *m_translationService = nullptr;
|
||||
AiActionOptionsService *m_aiActionOptionsService = nullptr;
|
||||
|
||||
// Frameless title bar
|
||||
QWidget *m_titleBar;
|
||||
|
||||
+203
-3
@@ -1,6 +1,8 @@
|
||||
#include "settingsview.h"
|
||||
#include "services/accountservice.h"
|
||||
#include "core/models/account.h"
|
||||
#include "services/preferencesservice.h"
|
||||
#include "services/startupbehaviorservice.h"
|
||||
#include "services/translationservice.h"
|
||||
#include "services/aiactionoptionsservice.h"
|
||||
#include "db/dao/common_structs.h"
|
||||
#include "db/dao/categorydao.h"
|
||||
#include "db/dao/ruledao.h"
|
||||
@@ -34,6 +36,8 @@
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlDatabase>
|
||||
#include <QHeaderView>
|
||||
#include <QSpinBox>
|
||||
#include <QFileDialog>
|
||||
|
||||
SettingsView::SettingsView(QWidget *parent) : QWidget(parent) {
|
||||
setupUI();
|
||||
@@ -45,6 +49,7 @@ void SettingsView::setupUI() {
|
||||
|
||||
m_tabWidget = new QTabWidget();
|
||||
m_tabWidget->addTab(createAccountsTab(), tr("Accounts"));
|
||||
m_tabWidget->addTab(createPreferencesTab(), tr("Preferences"));
|
||||
m_tabWidget->addTab(createCategoriesTab(), tr("Categories"));
|
||||
m_tabWidget->addTab(createRulesTab(), tr("Rules"));
|
||||
m_tabWidget->addTab(createTemplatesTab(), tr("Templates"));
|
||||
@@ -452,7 +457,202 @@ QWidget* SettingsView::createAppearanceTab() {
|
||||
return widget;
|
||||
}
|
||||
|
||||
// ========== Slots for Accounts ==========
|
||||
QWidget* SettingsView::createPreferencesTab() {
|
||||
QWidget *widget = new QWidget();
|
||||
QVBoxLayout *layout = new QVBoxLayout(widget);
|
||||
layout->setContentsMargins(20, 20, 20, 20);
|
||||
layout->setSpacing(16);
|
||||
|
||||
QLabel *title = new QLabel(tr("Preferences"));
|
||||
QFont titleFont = title->font();
|
||||
titleFont.setPointSize(16);
|
||||
titleFont.setBold(true);
|
||||
title->setFont(titleFont);
|
||||
layout->addWidget(title);
|
||||
|
||||
// Search Mode
|
||||
QGroupBox *searchGroup = new QGroupBox(tr("Search"));
|
||||
QFormLayout *searchLayout = new QFormLayout(searchGroup);
|
||||
|
||||
m_searchModeCombo = new QComboBox();
|
||||
m_searchModeCombo->addItem(tr("Local"), QVariant(static_cast<int>(SearchMode::Local)));
|
||||
m_searchModeCombo->addItem(tr("Online"), QVariant(static_cast<int>(SearchMode::Online)));
|
||||
if (m_preferencesService) {
|
||||
m_searchModeCombo->setCurrentIndex(static_cast<int>(m_preferencesService->defaultSearchMode()));
|
||||
}
|
||||
connect(m_searchModeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) {
|
||||
if (m_preferencesService) {
|
||||
m_preferencesService->setDefaultSearchMode(static_cast<SearchMode>(m_searchModeCombo->itemData(index).toInt()));
|
||||
}
|
||||
});
|
||||
searchLayout->addRow(tr("Default search mode:"), m_searchModeCombo);
|
||||
layout->addWidget(searchGroup);
|
||||
|
||||
// Default App Mode
|
||||
QGroupBox *appModeGroup = new QGroupBox(tr("Default Application Mode"));
|
||||
QFormLayout *appModeLayout = new QFormLayout(appModeGroup);
|
||||
|
||||
m_defaultAppModeCombo = new QComboBox();
|
||||
m_defaultAppModeCombo->addItem(tr("Mail"), QVariant(static_cast<int>(WinoApplicationMode::Mail)));
|
||||
m_defaultAppModeCombo->addItem(tr("Calendar"), QVariant(static_cast<int>(WinoApplicationMode::Calendar)));
|
||||
m_defaultAppModeCombo->addItem(tr("Contacts"), QVariant(static_cast<int>(WinoApplicationMode::Contacts)));
|
||||
m_defaultAppModeCombo->addItem(tr("Settings"), QVariant(static_cast<int>(WinoApplicationMode::Settings)));
|
||||
if (m_preferencesService) {
|
||||
m_defaultAppModeCombo->setCurrentIndex(static_cast<int>(m_preferencesService->defaultApplicationMode()));
|
||||
}
|
||||
connect(m_defaultAppModeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) {
|
||||
if (m_preferencesService) {
|
||||
m_preferencesService->setDefaultApplicationMode(static_cast<WinoApplicationMode>(m_defaultAppModeCombo->itemData(index).toInt()));
|
||||
}
|
||||
});
|
||||
appModeLayout->addRow(tr("Default mode on startup:"), m_defaultAppModeCombo);
|
||||
layout->addWidget(appModeGroup);
|
||||
|
||||
// Language
|
||||
QGroupBox *languageGroup = new QGroupBox(tr("Language"));
|
||||
QFormLayout *languageLayout = new QFormLayout(languageGroup);
|
||||
|
||||
m_languageCombo = new QComboBox();
|
||||
if (m_translationService) {
|
||||
QVector<AppLanguageModel> languages = m_translationService->getAvailableLanguages();
|
||||
for (const AppLanguageModel &lang : languages) {
|
||||
m_languageCombo->addItem(lang.displayName, lang.language);
|
||||
}
|
||||
int idx = m_languageCombo->findData(m_translationService->currentLanguage());
|
||||
if (idx >= 0) m_languageCombo->setCurrentIndex(idx);
|
||||
}
|
||||
connect(m_languageCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) {
|
||||
if (m_translationService) {
|
||||
m_translationService->setLanguage(m_languageCombo->itemData(index).toString());
|
||||
}
|
||||
});
|
||||
languageLayout->addRow(tr("Interface language:"), m_languageCombo);
|
||||
layout->addWidget(languageGroup);
|
||||
|
||||
// Email Sync Interval
|
||||
QGroupBox *syncGroup = new QGroupBox(tr("Email Synchronization"));
|
||||
QFormLayout *syncLayout = new QFormLayout(syncGroup);
|
||||
|
||||
m_syncIntervalSpin = new QSpinBox();
|
||||
m_syncIntervalSpin->setRange(1, 1440); // 1 minute to 24 hours
|
||||
m_syncIntervalSpin->setSuffix(tr(" minutes"));
|
||||
if (m_preferencesService) {
|
||||
m_syncIntervalSpin->setValue(m_preferencesService->emailSyncIntervalMinutes());
|
||||
}
|
||||
connect(m_syncIntervalSpin, QOverload<int>::of(&QSpinBox::valueChanged), this, [this](int value) {
|
||||
if (m_preferencesService) {
|
||||
m_preferencesService->setEmailSyncIntervalMinutes(value);
|
||||
}
|
||||
});
|
||||
syncLayout->addRow(tr("Sync interval:"), m_syncIntervalSpin);
|
||||
layout->addWidget(syncGroup);
|
||||
|
||||
// Startup Behavior
|
||||
QGroupBox *startupGroup = new QGroupBox(tr("Startup"));
|
||||
QFormLayout *startupLayout = new QFormLayout(startupGroup);
|
||||
|
||||
m_startOnLoginCheck = new QCheckBox(tr("Start application on login"));
|
||||
if (m_preferencesService) {
|
||||
m_startOnLoginCheck->setChecked(m_preferencesService->startOnLogin());
|
||||
}
|
||||
connect(m_startOnLoginCheck, &QCheckBox::toggled, this, [this](bool checked) {
|
||||
if (m_preferencesService) {
|
||||
m_preferencesService->setStartOnLogin(checked);
|
||||
}
|
||||
if (m_startupBehaviorService) {
|
||||
m_startupBehaviorService->toggleStartupBehavior(checked);
|
||||
}
|
||||
});
|
||||
startupLayout->addRow(m_startOnLoginCheck);
|
||||
|
||||
m_minimizeToTrayCheck = new QCheckBox(tr("Minimize to tray on close"));
|
||||
if (m_preferencesService) {
|
||||
m_minimizeToTrayCheck->setChecked(m_preferencesService->minimizeToTray());
|
||||
}
|
||||
connect(m_minimizeToTrayCheck, &QCheckBox::toggled, this, [this](bool checked) {
|
||||
if (m_preferencesService) {
|
||||
m_preferencesService->setMinimizeToTray(checked);
|
||||
}
|
||||
});
|
||||
startupLayout->addRow(m_minimizeToTrayCheck);
|
||||
|
||||
m_enableNotificationsCheck = new QCheckBox(tr("Enable notifications"));
|
||||
if (m_preferencesService) {
|
||||
m_enableNotificationsCheck->setChecked(m_preferencesService->enableNotifications());
|
||||
}
|
||||
connect(m_enableNotificationsCheck, &QCheckBox::toggled, this, [this](bool checked) {
|
||||
if (m_preferencesService) {
|
||||
m_preferencesService->setEnableNotifications(checked);
|
||||
}
|
||||
});
|
||||
startupLayout->addRow(m_enableNotificationsCheck);
|
||||
layout->addWidget(startupGroup);
|
||||
|
||||
// AI Translation
|
||||
QGroupBox *aiGroup = new QGroupBox(tr("AI Translation"));
|
||||
QFormLayout *aiLayout = new QFormLayout(aiGroup);
|
||||
|
||||
m_translateLanguageCombo = new QComboBox();
|
||||
if (m_aiActionOptionsService) {
|
||||
QVector<AiTranslateLanguageOption> options = m_aiActionOptionsService->getTranslateLanguageOptions();
|
||||
for (const AiTranslateLanguageOption &opt : options) {
|
||||
m_translateLanguageCombo->addItem(opt.displayName, opt.code);
|
||||
}
|
||||
if (m_preferencesService) {
|
||||
int idx = m_translateLanguageCombo->findData(m_preferencesService->aiDefaultTranslationLanguageCode());
|
||||
if (idx >= 0) m_translateLanguageCombo->setCurrentIndex(idx);
|
||||
}
|
||||
}
|
||||
connect(m_translateLanguageCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) {
|
||||
if (m_preferencesService) {
|
||||
m_preferencesService->setAiDefaultTranslationLanguageCode(m_translateLanguageCombo->itemData(index).toString());
|
||||
}
|
||||
});
|
||||
aiLayout->addRow(tr("Default translation language:"), m_translateLanguageCombo);
|
||||
|
||||
m_summarizeLanguageCombo = new QComboBox();
|
||||
if (m_aiActionOptionsService) {
|
||||
QVector<AiTranslateLanguageOption> options = m_aiActionOptionsService->getTranslateLanguageOptions();
|
||||
for (const AiTranslateLanguageOption &opt : options) {
|
||||
m_summarizeLanguageCombo->addItem(opt.displayName, opt.code);
|
||||
}
|
||||
if (m_preferencesService) {
|
||||
int idx = m_summarizeLanguageCombo->findData(m_preferencesService->aiSummarizeLanguageCode());
|
||||
if (idx >= 0) m_summarizeLanguageCombo->setCurrentIndex(idx);
|
||||
}
|
||||
}
|
||||
connect(m_summarizeLanguageCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) {
|
||||
if (m_preferencesService) {
|
||||
m_preferencesService->setAiSummarizeLanguageCode(m_summarizeLanguageCombo->itemData(index).toString());
|
||||
}
|
||||
});
|
||||
aiLayout->addRow(tr("Summarize language:"), m_summarizeLanguageCombo);
|
||||
|
||||
m_summarySavePathEdit = new QLineEdit();
|
||||
m_summarySavePathEdit->setPlaceholderText(tr("Select folder for AI summaries..."));
|
||||
if (m_preferencesService) {
|
||||
m_summarySavePathEdit->setText(m_preferencesService->aiSummarySavePath());
|
||||
}
|
||||
m_summarySavePathBtn = new QPushButton(tr("Browse..."));
|
||||
connect(m_summarySavePathBtn, &QPushButton::clicked, this, [this]() {
|
||||
QString path = QFileDialog::getExistingDirectory(this, tr("Select Summary Save Folder"),
|
||||
m_summarySavePathEdit->text());
|
||||
if (!path.isEmpty()) {
|
||||
m_summarySavePathEdit->setText(path);
|
||||
if (m_preferencesService) {
|
||||
m_preferencesService->setAiSummarySavePath(path);
|
||||
}
|
||||
}
|
||||
});
|
||||
QHBoxLayout *pathLayout = new QHBoxLayout();
|
||||
pathLayout->addWidget(m_summarySavePathEdit);
|
||||
pathLayout->addWidget(m_summarySavePathBtn);
|
||||
aiLayout->addRow(tr("Summary save path:"), pathLayout);
|
||||
layout->addWidget(aiGroup);
|
||||
|
||||
layout->addStretch();
|
||||
return widget;
|
||||
}
|
||||
void SettingsView::setAccountService(AccountService *service) {
|
||||
m_accountService = service;
|
||||
if (m_accountService) {
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
#include <QDialog>
|
||||
#include <QColorDialog>
|
||||
#include "services/accountservice.h"
|
||||
#include "services/preferencesservice.h"
|
||||
#include "services/startupbehaviorservice.h"
|
||||
#include "services/translationservice.h"
|
||||
#include "services/aiactionoptionsservice.h"
|
||||
#include "db/dao/common_structs.h"
|
||||
|
||||
class SettingsView : public QWidget {
|
||||
@@ -27,6 +31,10 @@ public:
|
||||
~SettingsView() override = default;
|
||||
|
||||
void setAccountService(AccountService *service);
|
||||
void setPreferencesService(PreferencesService *service);
|
||||
void setStartupBehaviorService(StartupBehaviorService *service);
|
||||
void setTranslationService(TranslationService *service);
|
||||
void setAiActionOptionsService(AiActionOptionsService *service);
|
||||
|
||||
signals:
|
||||
void accountAddRequested();
|
||||
@@ -92,6 +100,7 @@ private:
|
||||
QWidget* createAccountsTab();
|
||||
QWidget* createGeneralTab();
|
||||
QWidget* createAppearanceTab();
|
||||
QWidget* createPreferencesTab(); // New: Preferences tab
|
||||
QWidget* createCategoriesTab();
|
||||
QWidget* createRulesTab();
|
||||
QWidget* createTemplatesTab();
|
||||
@@ -149,4 +158,26 @@ private:
|
||||
QPushButton *m_signatureAddBtn;
|
||||
QPushButton *m_signatureEditBtn;
|
||||
QPushButton *m_signatureDeleteBtn;
|
||||
|
||||
// Services
|
||||
AccountService *m_accountService = nullptr;
|
||||
PreferencesService *m_preferencesService = nullptr;
|
||||
StartupBehaviorService *m_startupBehaviorService = nullptr;
|
||||
TranslationService *m_translationService = nullptr;
|
||||
AiActionOptionsService *m_aiActionOptionsService = nullptr;
|
||||
|
||||
// Preferences tab controls
|
||||
QComboBox *m_searchModeCombo = nullptr;
|
||||
QComboBox *m_defaultAppModeCombo = nullptr;
|
||||
QComboBox *m_languageCombo = nullptr;
|
||||
QSpinBox *m_syncIntervalSpin = nullptr;
|
||||
QCheckBox *m_startOnLoginCheck = nullptr;
|
||||
QCheckBox *m_minimizeToTrayCheck = nullptr;
|
||||
QCheckBox *m_enableNotificationsCheck = nullptr;
|
||||
QComboBox *m_translateLanguageCombo = nullptr;
|
||||
QComboBox *m_summarizeLanguageCombo = nullptr;
|
||||
QLineEdit *m_summarySavePathEdit = nullptr;
|
||||
QPushButton *m_summarySavePathBtn = nullptr;
|
||||
|
||||
int m_selectedAccountId = -1;
|
||||
};
|
||||
Reference in New Issue
Block a user