MailJD nbsp;·nbsp; Test Dashboard nbsp;·nbsp; Coverage
LCOV - code coverage report
Current view: top level - ui - AccountFormWidget.cpp (source / functions) Coverage Total Hit
Test: MailJD Coverage (Unit + E2E) Lines: 92.2 % 295 272
Test Date: 2026-06-21 21:10:19 Functions: 96.0 % 25 24
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 44.4 % 736 327

             Branch data     Line data    Source code
       1                 :             : #include "AccountFormWidget.h"
       2                 :             : 
       3                 :             : #include <QAction>
       4                 :             : #include <QComboBox>
       5                 :             : #include <QEvent>
       6                 :             : #include <QFormLayout>
       7                 :             : #include <QGroupBox>
       8                 :             : #include <QHBoxLayout>
       9                 :             : #include <QLabel>
      10                 :             : #include <QLineEdit>
      11                 :             : #include <QLoggingCategory>
      12                 :             : #include <QPushButton>
      13                 :             : #include <QSpinBox>
      14                 :             : #include <QTimer>
      15                 :             : #include <QVBoxLayout>
      16                 :             : #include <QEvent>
      17                 :             : 
      18                 :             : #include "data/AccountConfig.h"
      19                 :             : #include "service/ImapService.h"
      20                 :             : #include "ui/ThemeManager.h"
      21                 :             : 
      22   [ #  #  #  #  :           0 : Q_LOGGING_CATEGORY(lcAccountForm, "mailjd.accountform")
             #  #  #  # ]
      23                 :             : 
      24         [ +  - ]:          97 : AccountFormWidget::AccountFormWidget(QWidget *parent) : QWidget(parent) {
      25         [ +  - ]:          97 :   setupUi();
      26         [ +  - ]:          97 :   setupTabOrder();
      27         [ +  - ]:          97 :   connectFieldSignals();
      28                 :          97 : }
      29                 :             : 
      30                 :         186 : AccountFormWidget::~AccountFormWidget() {
      31                 :             :   // Clean up test service if running
      32         [ -  + ]:          97 :   if (m_testService) {
      33                 :           0 :     m_testService->disconnect();
      34                 :           0 :     m_testService->deleteLater();
      35                 :           0 :     m_testService = nullptr;
      36                 :             :   }
      37                 :         186 : }
      38                 :             : 
      39                 :          97 : void AccountFormWidget::setupUi() {
      40   [ +  -  -  +  :          97 :   auto *mainLayout = new QVBoxLayout(this);
                   -  - ]
      41                 :          97 :   mainLayout->setContentsMargins(0, 0, 0, 0);
      42                 :             : 
      43                 :             :   // --- Account basics ---
      44   [ +  -  -  +  :          97 :   auto *basicsLayout = new QFormLayout();
                   -  - ]
      45   [ +  -  -  +  :          97 :   m_nameEdit = new QLineEdit(this);
                   -  - ]
      46   [ +  -  +  - ]:          97 :   m_nameEdit->setPlaceholderText(tr("e.g. Personal, Work"));
      47   [ +  -  -  +  :          97 :   m_emailEdit = new QLineEdit(this);
                   -  - ]
      48   [ +  -  +  - ]:          97 :   m_emailEdit->setPlaceholderText("user@example.com");
      49   [ +  -  +  -  :          97 :   m_nameLabel = new QLabel(tr("&Name:"), this);
             -  +  -  - ]
      50                 :          97 :   m_nameLabel->setBuddy(m_nameEdit);
      51                 :          97 :   basicsLayout->addRow(m_nameLabel, m_nameEdit);
      52   [ +  -  +  -  :          97 :   m_emailLabel = new QLabel(tr("&Email:"), this);
             -  +  -  - ]
      53                 :          97 :   m_emailLabel->setBuddy(m_emailEdit);
      54                 :          97 :   basicsLayout->addRow(m_emailLabel, m_emailEdit);
      55                 :          97 :   mainLayout->addLayout(basicsLayout);
      56                 :             : 
      57                 :             :   // --- IMAP group ---
      58   [ +  -  +  -  :          97 :   m_imapGroup = new QGroupBox(tr("IMAP Server (Incoming)"), this);
             -  +  -  - ]
      59   [ +  -  -  +  :          97 :   auto *imapLayout = new QFormLayout(m_imapGroup);
                   -  - ]
      60                 :             : 
      61   [ +  -  -  +  :          97 :   m_imapHost = new QLineEdit(this);
                   -  - ]
      62   [ +  -  +  - ]:          97 :   m_imapHost->setPlaceholderText("imap.example.com");
      63   [ +  -  -  +  :          97 :   m_imapPort = new QSpinBox(this);
                   -  - ]
      64                 :          97 :   m_imapPort->setRange(1, 65535);
      65                 :          97 :   m_imapPort->setValue(993);
      66   [ +  -  -  +  :          97 :   m_imapSecurity = new QComboBox(this);
                   -  - ]
      67   [ +  -  +  -  :          97 :   m_imapSecurity->addItem("SSL/TLS", "ssl");
                   +  - ]
      68   [ +  -  +  -  :          97 :   m_imapSecurity->addItem("STARTTLS", "starttls");
                   +  - ]
      69   [ +  -  -  +  :          97 :   m_imapUsername = new QLineEdit(this);
                   -  - ]
      70   [ +  -  +  - ]:          97 :   m_imapUsername->setPlaceholderText("user@example.com");
      71   [ +  -  -  +  :          97 :   m_imapPassword = new QLineEdit(this);
                   -  - ]
      72                 :          97 :   m_imapPassword->setEchoMode(QLineEdit::Password);
      73   [ +  -  +  - ]:          97 :   m_imapPassword->setPlaceholderText(tr("Password"));
      74                 :             :   // Password visibility toggle via action
      75         [ +  - ]:          97 :   m_imapToggleAction = m_imapPassword->addAction(
      76   [ +  -  +  - ]:         194 :       style()->standardIcon(QStyle::SP_FileDialogDetailedView),
      77                 :             :       QLineEdit::TrailingPosition);
      78   [ +  -  +  - ]:          97 :   m_imapToggleAction->setToolTip(tr("Show/hide password (Alt+P)"));
      79   [ +  -  +  -  :          97 :   m_imapToggleAction->setShortcut(QKeySequence("Alt+P"));
                   +  - ]
      80         [ +  - ]:          97 :   connect(m_imapToggleAction, &QAction::triggered, this, [this]() {
      81         [ #  # ]:           0 :     m_imapPassword->setEchoMode(m_imapPassword->echoMode() ==
      82                 :             :                                         QLineEdit::Password
      83                 :             :                                     ? QLineEdit::Normal
      84                 :             :                                     : QLineEdit::Password);
      85                 :           0 :   });
      86                 :             : 
      87   [ +  -  +  -  :          97 :   m_imapHostLabel = new QLabel(tr("&Host:"), m_imapGroup);
             -  +  -  - ]
      88                 :          97 :   m_imapHostLabel->setBuddy(m_imapHost);
      89                 :          97 :   imapLayout->addRow(m_imapHostLabel, m_imapHost);
      90   [ +  -  +  -  :          97 :   m_imapPortLabel = new QLabel(tr("P&ort:"), m_imapGroup);
             -  +  -  - ]
      91                 :          97 :   m_imapPortLabel->setBuddy(m_imapPort);
      92                 :          97 :   imapLayout->addRow(m_imapPortLabel, m_imapPort);
      93   [ +  -  +  -  :          97 :   m_imapSecurityLabel = new QLabel(tr("S&ecurity:"), m_imapGroup);
             -  +  -  - ]
      94                 :          97 :   m_imapSecurityLabel->setBuddy(m_imapSecurity);
      95                 :          97 :   imapLayout->addRow(m_imapSecurityLabel, m_imapSecurity);
      96   [ +  -  +  -  :          97 :   m_imapUsernameLabel = new QLabel(tr("&Username:"), m_imapGroup);
             -  +  -  - ]
      97                 :          97 :   m_imapUsernameLabel->setBuddy(m_imapUsername);
      98                 :          97 :   imapLayout->addRow(m_imapUsernameLabel, m_imapUsername);
      99   [ +  -  +  -  :          97 :   m_imapPasswordLabel = new QLabel(tr("&Password:"), m_imapGroup);
             -  +  -  - ]
     100                 :          97 :   m_imapPasswordLabel->setBuddy(m_imapPassword);
     101                 :          97 :   imapLayout->addRow(m_imapPasswordLabel, m_imapPassword);
     102                 :             : 
     103         [ +  - ]:          97 :   mainLayout->addWidget(m_imapGroup);
     104                 :             : 
     105                 :             :   // Auto-update port when security changes
     106         [ +  - ]:          97 :   connect(m_imapSecurity, &QComboBox::currentIndexChanged, this, [this](int) {
     107   [ +  -  +  - ]:           2 :     auto sec = m_imapSecurity->currentData().toString();
     108   [ +  +  +  -  :           2 :     if (sec == "ssl" && m_imapPort->value() == 143) {
             -  +  -  + ]
     109         [ #  # ]:           0 :       m_imapPort->setValue(993);
     110   [ +  +  +  -  :           2 :     } else if (sec == "starttls" && m_imapPort->value() == 993) {
             -  +  -  + ]
     111         [ #  # ]:           0 :       m_imapPort->setValue(143);
     112                 :             :     }
     113                 :           2 :   });
     114                 :             : 
     115                 :             :   // --- SMTP group ---
     116   [ +  -  +  -  :          97 :   m_smtpGroup = new QGroupBox(tr("SMTP Server (Outgoing)"), this);
             -  +  -  - ]
     117   [ +  -  -  +  :          97 :   auto *smtpLayout = new QFormLayout(m_smtpGroup);
                   -  - ]
     118                 :             : 
     119   [ +  -  -  +  :          97 :   m_smtpHost = new QLineEdit(this);
                   -  - ]
     120   [ +  -  +  - ]:          97 :   m_smtpHost->setPlaceholderText("smtp.example.com");
     121   [ +  -  -  +  :          97 :   m_smtpPort = new QSpinBox(this);
                   -  - ]
     122                 :          97 :   m_smtpPort->setRange(1, 65535);
     123                 :          97 :   m_smtpPort->setValue(587);
     124   [ +  -  -  +  :          97 :   m_smtpSecurity = new QComboBox(this);
                   -  - ]
     125   [ +  -  +  -  :          97 :   m_smtpSecurity->addItem("STARTTLS", "starttls");
                   +  - ]
     126   [ +  -  +  -  :          97 :   m_smtpSecurity->addItem("SSL/TLS", "ssl");
                   +  - ]
     127   [ +  -  -  +  :          97 :   m_smtpUsername = new QLineEdit(this);
                   -  - ]
     128   [ +  -  +  - ]:          97 :   m_smtpUsername->setPlaceholderText("user@example.com");
     129   [ +  -  -  +  :          97 :   m_smtpPassword = new QLineEdit(this);
                   -  - ]
     130                 :          97 :   m_smtpPassword->setEchoMode(QLineEdit::Password);
     131   [ +  -  +  - ]:          97 :   m_smtpPassword->setPlaceholderText(tr("Password"));
     132                 :             :   // SMTP password visibility toggle
     133         [ +  - ]:          97 :   m_smtpToggleAction = m_smtpPassword->addAction(
     134   [ +  -  +  - ]:         194 :       style()->standardIcon(QStyle::SP_FileDialogDetailedView),
     135                 :             :       QLineEdit::TrailingPosition);
     136   [ +  -  +  - ]:          97 :   m_smtpToggleAction->setToolTip(tr("Show/hide password"));
     137         [ +  - ]:          97 :   connect(m_smtpToggleAction, &QAction::triggered, this, [this]() {
     138         [ #  # ]:           0 :     m_smtpPassword->setEchoMode(m_smtpPassword->echoMode() ==
     139                 :             :                                         QLineEdit::Password
     140                 :             :                                     ? QLineEdit::Normal
     141                 :             :                                     : QLineEdit::Password);
     142                 :           0 :   });
     143                 :             : 
     144   [ +  -  +  -  :          97 :   m_smtpHostLabel = new QLabel(tr("H&ost:"), m_smtpGroup);
             -  +  -  - ]
     145                 :          97 :   m_smtpHostLabel->setBuddy(m_smtpHost);
     146                 :          97 :   smtpLayout->addRow(m_smtpHostLabel, m_smtpHost);
     147   [ +  -  +  -  :          97 :   m_smtpPortLabel = new QLabel(tr("Po&rt:"), m_smtpGroup);
             -  +  -  - ]
     148                 :          97 :   m_smtpPortLabel->setBuddy(m_smtpPort);
     149                 :          97 :   smtpLayout->addRow(m_smtpPortLabel, m_smtpPort);
     150   [ +  -  +  -  :          97 :   m_smtpSecurityLabel = new QLabel(tr("Se&curity:"), m_smtpGroup);
             -  +  -  - ]
     151                 :          97 :   m_smtpSecurityLabel->setBuddy(m_smtpSecurity);
     152                 :          97 :   smtpLayout->addRow(m_smtpSecurityLabel, m_smtpSecurity);
     153   [ +  -  +  -  :          97 :   m_smtpUsernameLabel = new QLabel(tr("User&name:"), m_smtpGroup);
             -  +  -  - ]
     154                 :          97 :   m_smtpUsernameLabel->setBuddy(m_smtpUsername);
     155                 :          97 :   smtpLayout->addRow(m_smtpUsernameLabel, m_smtpUsername);
     156   [ +  -  +  -  :          97 :   m_smtpPasswordLabel = new QLabel(tr("Pass&word:"), m_smtpGroup);
             -  +  -  - ]
     157                 :          97 :   m_smtpPasswordLabel->setBuddy(m_smtpPassword);
     158                 :          97 :   smtpLayout->addRow(m_smtpPasswordLabel, m_smtpPassword);
     159                 :             : 
     160                 :             :   // Auto-update SMTP port on security change
     161         [ +  - ]:          97 :   connect(m_smtpSecurity, &QComboBox::currentIndexChanged, this, [this](int) {
     162   [ +  -  +  - ]:          10 :     auto sec = m_smtpSecurity->currentData().toString();
     163   [ +  +  +  -  :          10 :     if (sec == "ssl" && m_smtpPort->value() == 587) {
             -  +  -  + ]
     164         [ #  # ]:           0 :       m_smtpPort->setValue(465);
     165   [ +  +  +  -  :          10 :     } else if (sec == "starttls" && m_smtpPort->value() == 465) {
             -  +  -  + ]
     166         [ #  # ]:           0 :       m_smtpPort->setValue(587);
     167                 :             :     }
     168                 :          10 :   });
     169                 :             : 
     170         [ +  - ]:          97 :   mainLayout->addWidget(m_smtpGroup);
     171                 :             : 
     172                 :             :   // --- Connection test ---
     173   [ +  -  -  +  :          97 :   auto *testLayout = new QHBoxLayout();
                   -  - ]
     174   [ +  -  +  -  :          97 :   m_testButton = new QPushButton(tr("Test Connection"), this);
             -  +  -  - ]
     175   [ +  -  -  +  :          97 :   m_testResultLabel = new QLabel(this);
                   -  - ]
     176                 :          97 :   m_testResultLabel->setWordWrap(true);
     177         [ +  - ]:          97 :   testLayout->addWidget(m_testButton);
     178         [ +  - ]:          97 :   testLayout->addWidget(m_testResultLabel, 1);
     179                 :          97 :   mainLayout->addLayout(testLayout);
     180                 :             : 
     181                 :          97 :   connect(m_testButton, &QPushButton::clicked, this,
     182         [ +  - ]:          97 :           &AccountFormWidget::testConnection);
     183                 :          97 : }
     184                 :             : 
     185                 :          97 : void AccountFormWidget::setupTabOrder() {
     186                 :          97 :   setTabOrder(m_nameEdit, m_emailEdit);
     187                 :          97 :   setTabOrder(m_emailEdit, m_imapHost);
     188                 :          97 :   setTabOrder(m_imapHost, m_imapPort);
     189                 :          97 :   setTabOrder(m_imapPort, m_imapSecurity);
     190                 :          97 :   setTabOrder(m_imapSecurity, m_imapUsername);
     191                 :          97 :   setTabOrder(m_imapUsername, m_imapPassword);
     192                 :          97 :   setTabOrder(m_imapPassword, m_smtpHost);
     193                 :          97 :   setTabOrder(m_smtpHost, m_smtpPort);
     194                 :          97 :   setTabOrder(m_smtpPort, m_smtpSecurity);
     195                 :          97 :   setTabOrder(m_smtpSecurity, m_smtpUsername);
     196                 :          97 :   setTabOrder(m_smtpUsername, m_smtpPassword);
     197                 :          97 :   setTabOrder(m_smtpPassword, m_testButton);
     198                 :          97 : }
     199                 :             : 
     200                 :          97 : void AccountFormWidget::connectFieldSignals() {
     201                 :             :   // Track modifications
     202                 :         521 :   auto markModified = [this]() {
     203                 :         521 :     m_modified = true;
     204                 :         521 :     emit formChanged();
     205                 :         618 :   };
     206                 :             : 
     207         [ +  - ]:          97 :   connect(m_nameEdit, &QLineEdit::textChanged, this, markModified);
     208         [ +  - ]:          97 :   connect(m_emailEdit, &QLineEdit::textChanged, this, markModified);
     209         [ +  - ]:          97 :   connect(m_imapHost, &QLineEdit::textChanged, this, markModified);
     210         [ +  - ]:          97 :   connect(m_imapPort, &QSpinBox::valueChanged, this, markModified);
     211         [ +  - ]:          97 :   connect(m_imapSecurity, &QComboBox::currentIndexChanged, this, markModified);
     212         [ +  - ]:          97 :   connect(m_imapUsername, &QLineEdit::textChanged, this, markModified);
     213         [ +  - ]:          97 :   connect(m_imapPassword, &QLineEdit::textChanged, this, markModified);
     214         [ +  - ]:          97 :   connect(m_smtpHost, &QLineEdit::textChanged, this, markModified);
     215         [ +  - ]:          97 :   connect(m_smtpPort, &QSpinBox::valueChanged, this, markModified);
     216         [ +  - ]:          97 :   connect(m_smtpSecurity, &QComboBox::currentIndexChanged, this, markModified);
     217         [ +  - ]:          97 :   connect(m_smtpUsername, &QLineEdit::textChanged, this, markModified);
     218         [ +  - ]:          97 :   connect(m_smtpPassword, &QLineEdit::textChanged, this, markModified);
     219                 :          97 : }
     220                 :             : 
     221                 :          56 : void AccountFormWidget::setConfig(const AccountConfig &config) {
     222                 :             :   // Block signals to avoid marking as modified during population
     223                 :          56 :   const QSignalBlocker blocker(this);
     224                 :             : 
     225         [ +  - ]:          56 :   m_nameEdit->setText(config.name);
     226         [ +  - ]:          56 :   m_emailEdit->setText(config.email);
     227                 :             : 
     228         [ +  - ]:          56 :   m_imapHost->setText(config.imap.host);
     229         [ +  - ]:          56 :   m_imapPort->setValue(config.imap.port);
     230   [ +  -  +  - ]:          56 :   m_imapSecurity->setCurrentIndex(
     231                 :         112 :       m_imapSecurity->findData(config.imap.security));
     232         [ +  - ]:          56 :   m_imapUsername->setText(config.imap.username);
     233   [ +  -  +  - ]:          56 :   m_imapPassword->setText(QString::fromUtf8(config.imap.password));
     234                 :             : 
     235         [ +  - ]:          56 :   m_smtpHost->setText(config.smtp.host);
     236         [ +  - ]:          56 :   m_smtpPort->setValue(config.smtp.port);
     237   [ +  -  +  - ]:          56 :   m_smtpSecurity->setCurrentIndex(
     238                 :         112 :       m_smtpSecurity->findData(config.smtp.security));
     239         [ +  - ]:          56 :   m_smtpUsername->setText(config.smtp.username);
     240   [ +  -  +  - ]:          56 :   m_smtpPassword->setText(QString::fromUtf8(config.smtp.password));
     241                 :             : 
     242                 :          56 :   m_modified = false;
     243         [ +  - ]:          56 :   m_testResultLabel->clear();
     244                 :          56 : }
     245                 :             : 
     246                 :          31 : AccountConfig AccountFormWidget::config() const {
     247                 :          31 :   AccountConfig cfg;
     248   [ +  -  +  - ]:          31 :   cfg.name = m_nameEdit->text().trimmed();
     249   [ +  -  +  - ]:          31 :   cfg.email = m_emailEdit->text().trimmed();
     250                 :             : 
     251   [ +  -  +  - ]:          31 :   cfg.imap.host = m_imapHost->text().trimmed();
     252         [ +  - ]:          31 :   cfg.imap.port = static_cast<quint16>(m_imapPort->value());
     253   [ +  -  +  - ]:          31 :   cfg.imap.security = m_imapSecurity->currentData().toString();
     254   [ +  -  +  - ]:          31 :   cfg.imap.username = m_imapUsername->text().trimmed();
     255   [ +  -  +  - ]:          31 :   cfg.imap.password = m_imapPassword->text().toUtf8();
     256                 :             : 
     257   [ +  -  +  - ]:          31 :   cfg.smtp.host = m_smtpHost->text().trimmed();
     258         [ +  - ]:          31 :   cfg.smtp.port = static_cast<quint16>(m_smtpPort->value());
     259   [ +  -  +  - ]:          31 :   cfg.smtp.security = m_smtpSecurity->currentData().toString();
     260   [ +  -  +  - ]:          31 :   cfg.smtp.username = m_smtpUsername->text().trimmed();
     261   [ +  -  +  - ]:          31 :   cfg.smtp.password = m_smtpPassword->text().toUtf8();
     262                 :             : 
     263                 :          31 :   return cfg;
     264                 :           0 : }
     265                 :             : 
     266                 :          11 : QStringList AccountFormWidget::validate() const {
     267   [ +  -  +  - ]:          11 :   return AccountConfigLoader::validate(config());
     268                 :             : }
     269                 :             : 
     270                 :           6 : bool AccountFormWidget::isModified() const { return m_modified; }
     271                 :             : 
     272                 :           6 : void AccountFormWidget::resetModified() { m_modified = false; }
     273                 :             : 
     274                 :          72 : void AccountFormWidget::clear() {
     275                 :          72 :   const QSignalBlocker blocker(this);
     276                 :             : 
     277         [ +  - ]:          72 :   m_nameEdit->clear();
     278         [ +  - ]:          72 :   m_emailEdit->clear();
     279         [ +  - ]:          72 :   m_imapHost->clear();
     280         [ +  - ]:          72 :   m_imapPort->setValue(993);
     281         [ +  - ]:          72 :   m_imapSecurity->setCurrentIndex(0); // SSL
     282         [ +  - ]:          72 :   m_imapUsername->clear();
     283         [ +  - ]:          72 :   m_imapPassword->clear();
     284         [ +  - ]:          72 :   m_smtpHost->clear();
     285         [ +  - ]:          72 :   m_smtpPort->setValue(587);
     286         [ +  - ]:          72 :   m_smtpSecurity->setCurrentIndex(0); // STARTTLS
     287         [ +  - ]:          72 :   m_smtpUsername->clear();
     288         [ +  - ]:          72 :   m_smtpPassword->clear();
     289         [ +  - ]:          72 :   m_testResultLabel->clear();
     290                 :             : 
     291                 :          72 :   m_modified = false;
     292                 :          72 : }
     293                 :             : 
     294                 :           4 : void AccountFormWidget::testConnection() {
     295                 :             :   // Validate first
     296         [ +  - ]:           4 :   auto errors = validate();
     297         [ +  + ]:           4 :   if (!errors.isEmpty()) {
     298   [ +  -  +  -  :           1 :     setTestResult("Formular unvollständig: " + errors.first(), false);
                   +  - ]
     299                 :           1 :     return;
     300                 :             :   }
     301                 :             : 
     302                 :             :   // Disable button and show "testing" state
     303         [ +  - ]:           3 :   m_testButton->setEnabled(false);
     304   [ +  -  +  - ]:           3 :   m_testButton->setText(tr("Testing..."));
     305   [ +  -  +  - ]:           3 :   m_testResultLabel->setText(tr("Testing connection..."));
     306   [ +  -  +  - ]:           3 :   m_testResultLabel->setStyleSheet("");
     307                 :             : 
     308                 :             :   // Clean up previous test service
     309         [ +  + ]:           3 :   if (m_testService) {
     310         [ +  - ]:           1 :     m_testService->disconnect();
     311         [ +  - ]:           1 :     m_testService->deleteLater();
     312                 :             :   }
     313                 :             : 
     314                 :             :   // Create a temporary ImapService for this test
     315   [ +  -  +  -  :           3 :   m_testService = new ImapService(this);
             -  +  -  - ]
     316                 :             : 
     317         [ +  - ]:           3 :   auto cfg = config();
     318                 :             : 
     319                 :             :   // On state change: look for Authenticated (success) or Error
     320                 :           3 :   connect(m_testService, &ImapService::stateChanged, this,
     321         [ +  - ]:           3 :           [this](ImapService::State state) {
     322         [ +  + ]:           6 :             if (state == ImapService::State::Authenticated) {
     323   [ +  -  +  - ]:           1 :               setTestResult("✅ Verbindung erfolgreich!", true);
     324                 :           1 :               m_testService->disconnect();
     325                 :           1 :               m_testService->deleteLater();
     326                 :           1 :               m_testService = nullptr;
     327                 :             :             }
     328                 :           6 :           });
     329                 :             : 
     330                 :           3 :   connect(m_testService, &ImapService::errorOccurred, this,
     331         [ +  - ]:           3 :           [this](const QString &error) {
     332   [ +  -  +  - ]:           1 :             setTestResult("❌ " + error, false);
     333                 :           1 :             m_testService->deleteLater();
     334                 :           1 :             m_testService = nullptr;
     335                 :           1 :           });
     336                 :             : 
     337                 :             :   // Timeout: 10s
     338         [ +  - ]:           3 :   QTimer::singleShot(10000, this, [this]() {
     339         [ #  # ]:           0 :     if (m_testService) {
     340   [ #  #  #  # ]:           0 :       setTestResult("❌ Zeitüberschreitung (10s)", false);
     341                 :           0 :       m_testService->disconnect();
     342                 :           0 :       m_testService->deleteLater();
     343                 :           0 :       m_testService = nullptr;
     344                 :             :     }
     345                 :           0 :   });
     346                 :             : 
     347         [ +  - ]:           3 :   m_testService->connectToServer(cfg.imap);
     348         [ +  + ]:           4 : }
     349                 :             : 
     350                 :           3 : void AccountFormWidget::setTestResult(const QString &message, bool success) {
     351         [ +  - ]:           3 :   m_testResultLabel->setText(message);
     352                 :             :   // Sprint 69: @success/@danger tokens instead of CSS named colors
     353                 :             :   // (so dark theme and the no_inline_colors gate work).
     354   [ +  -  +  +  :           6 :   const QString color = ThemeManager::instance().color(
                   +  - ]
     355         [ +  - ]:           3 :       success ? QLatin1String("@success") : QLatin1String("@danger"));
     356         [ +  - ]:           3 :   m_testResultLabel->setStyleSheet(
     357   [ +  +  +  -  :          12 :       success ? QStringLiteral("color: %1; font-weight: bold;").arg(color)
          +  -  +  +  -  
                -  -  - ]
     358   [ +  +  +  +  :           5 :               : QStringLiteral("color: %1;").arg(color));
          +  +  -  -  -  
                      - ]
     359                 :             : 
     360         [ +  - ]:           3 :   m_testButton->setEnabled(true);
     361   [ +  -  +  - ]:           3 :   m_testButton->setText(tr("Test Connection"));
     362                 :             : 
     363                 :             :   // Auto-clear success after 3 seconds
     364         [ +  + ]:           3 :   if (success) {
     365         [ +  - ]:           1 :     QTimer::singleShot(3000, this, [this]() {
     366   [ #  #  #  #  :           0 :       if (m_testResultLabel->text().startsWith("✅")) {
             #  #  #  # ]
     367                 :           0 :         m_testResultLabel->clear();
     368   [ #  #  #  # ]:           0 :         m_testResultLabel->setStyleSheet("");
     369                 :             :       }
     370                 :           0 :     });
     371                 :             :   }
     372                 :           3 : }
     373                 :             : 
     374                 :             : // T-76.B3: Runtime language switching
     375                 :         478 : void AccountFormWidget::changeEvent(QEvent *event) {
     376         [ +  + ]:         478 :   if (event->type() == QEvent::LanguageChange)
     377                 :           6 :     retranslateUi();
     378                 :         478 :   QWidget::changeEvent(event);
     379                 :         478 : }
     380                 :             : 
     381                 :           6 : void AccountFormWidget::retranslateUi() {
     382   [ +  -  +  - ]:           6 :   m_nameLabel->setText(tr("&Name:"));
     383   [ +  -  +  - ]:           6 :   m_emailLabel->setText(tr("&Email:"));
     384   [ +  -  +  - ]:           6 :   m_imapGroup->setTitle(tr("IMAP Server (Incoming)"));
     385   [ +  -  +  - ]:           6 :   m_imapHostLabel->setText(tr("&Host:"));
     386   [ +  -  +  - ]:           6 :   m_imapPortLabel->setText(tr("P&ort:"));
     387   [ +  -  +  - ]:           6 :   m_imapSecurityLabel->setText(tr("S&ecurity:"));
     388   [ +  -  +  - ]:           6 :   m_imapUsernameLabel->setText(tr("&Username:"));
     389   [ +  -  +  - ]:           6 :   m_imapPasswordLabel->setText(tr("&Password:"));
     390   [ +  -  +  - ]:           6 :   m_smtpGroup->setTitle(tr("SMTP Server (Outgoing)"));
     391   [ +  -  +  - ]:           6 :   m_smtpHostLabel->setText(tr("H&ost:"));
     392   [ +  -  +  - ]:           6 :   m_smtpPortLabel->setText(tr("Po&rt:"));
     393   [ +  -  +  - ]:           6 :   m_smtpSecurityLabel->setText(tr("Se&curity:"));
     394   [ +  -  +  - ]:           6 :   m_smtpUsernameLabel->setText(tr("User&name:"));
     395   [ +  -  +  - ]:           6 :   m_smtpPasswordLabel->setText(tr("Pass&word:"));
     396                 :             : 
     397   [ +  -  +  - ]:           6 :   m_nameEdit->setPlaceholderText(tr("e.g. Personal, Work"));
     398   [ +  -  +  - ]:           6 :   m_imapPassword->setPlaceholderText(tr("Password"));
     399   [ +  -  +  - ]:           6 :   m_smtpPassword->setPlaceholderText(tr("Password"));
     400   [ +  -  +  - ]:           6 :   m_imapToggleAction->setToolTip(tr("Show/hide password (Alt+P)"));
     401   [ +  -  +  - ]:           6 :   m_smtpToggleAction->setToolTip(tr("Show/hide password"));
     402                 :             : 
     403                 :             :   // Don't clobber the "Testing..." state of an in-flight connection test.
     404         [ +  - ]:           6 :   if (!m_testService)
     405   [ +  -  +  - ]:           6 :     m_testButton->setText(tr("Test Connection"));
     406                 :           6 : }
        

Generated by: LCOV version 2.0-1