2026-05-24 00:02:19 +02:00
# include "notificationmanager.h"
# include <QGuiApplication>
# include <QDebug>
NotificationManager : : NotificationManager ( QObject * parent )
: QObject ( parent )
2026-05-24 21:01:05 +02:00
, m_trayIcon ( nullptr )
, m_trayMenu ( nullptr )
, m_showHideAction ( nullptr )
, m_quitAction ( nullptr )
, m_newMailSound ( nullptr )
2026-05-29 11:43:44 +02:00
, m_errorSound ( nullptr )
2026-05-24 00:02:19 +02:00
{
2026-05-24 21:01:05 +02:00
// Defer initialization to after QApplication is fully ready
// We'll initialize in a separate method called from main after the event loop starts?
// For now, we do nothing and log.
qDebug ( ) < < " NotificationManager: constructor (deferred initialization) " ;
}
NotificationManager : : ~ NotificationManager ( )
{
// Cleanup if we ever initialize
if ( m_trayMenu ) {
delete m_trayMenu ;
}
2026-05-29 11:43:44 +02:00
// Note: m_trayIcon, m_showHideAction, m_quitAction, m_newMailSound, m_errorSound are children of this or m_trayMenu?
// Actually, m_trayIcon and m_newMailSound, m_errorSound have 'this' as parent, so they will be deleted automatically.
2026-05-24 21:01:05 +02:00
// m_showHideAction and m_quitAction have m_trayMenu as parent, so they will be deleted when m_trayMenu is deleted.
}
void NotificationManager : : initialize ( )
{
// Initialize the tray icon and related objects
m_trayIcon = new QSystemTrayIcon ( this ) ;
2026-05-29 11:43:44 +02:00
m_trayMenu = new QMenu ( ) ; // parent to NotificationManager so it gets deleted with us
2026-05-24 21:01:05 +02:00
m_showHideAction = new QAction ( " Show/Hide " , m_trayMenu ) ;
m_quitAction = new QAction ( " Quit " , m_trayMenu ) ;
m_newMailSound = new QSoundEffect ( this ) ;
2026-05-29 11:43:44 +02:00
m_errorSound = new QSoundEffect ( this ) ;
2026-05-24 21:01:05 +02:00
2026-05-24 00:02:19 +02:00
setupTrayIcon ( ) ;
setupConnections ( ) ;
}
void NotificationManager : : setupTrayIcon ( )
{
// Set an icon (you may want to load from resources)
m_trayIcon - > setIcon ( QIcon : : fromTheme ( " mail-unread " ) ) ;
m_trayIcon - > setToolTip ( " Wino Mail " ) ;
m_trayMenu - > addAction ( m_showHideAction ) ;
m_trayMenu - > addSeparator ( ) ;
m_trayMenu - > addAction ( m_quitAction ) ;
m_trayIcon - > setContextMenu ( m_trayMenu ) ;
m_newMailSound - > setSource ( QUrl : : fromLocalFile ( " /usr/share/sounds/freedesktop/stereo/message-new-instant.oga " ) ) ;
m_newMailSound - > setVolume ( 0.5 ) ;
2026-05-29 11:43:44 +02:00
m_errorSound - > setSource ( QUrl : : fromLocalFile ( " /usr/share/sounds/freedesktop/stereo/dialog-error.oga " ) ) ;
m_errorSound - > setVolume ( 0.5 ) ;
2026-05-24 00:02:19 +02:00
}
void NotificationManager : : setupConnections ( )
{
// Connect tray icon signals
connect ( m_trayIcon , & QSystemTrayIcon : : activated , this , & NotificationManager : : onTrayIconActivated ) ;
connect ( m_showHideAction , & QAction : : triggered , this , & NotificationManager : : onShowHideRequested ) ;
connect ( m_quitAction , & QAction : : triggered , qApp , & QGuiApplication : : quit ) ;
2026-05-29 11:43:44 +02:00
// Subscribe to events
2026-05-24 00:02:19 +02:00
SUBSCRIBE ( WinoMail : : Events : : MailItemAddedEvent , [ this ] ( const WinoMail : : Events : : MailItemAddedEvent & event ) {
onMailItemAdded ( event ) ;
} ) ;
2026-05-29 11:43:44 +02:00
SUBSCRIBE ( WinoMail : : Events : : MailItemRemovedEvent , [ this ] ( const WinoMail : : Events : : MailItemRemovedEvent & event ) {
onMailItemRemoved ( event ) ;
} ) ;
SUBSCRIBE ( WinoMail : : Events : : MailItemUpdatedEvent , [ this ] ( const WinoMail : : Events : : MailItemUpdatedEvent & event ) {
onMailItemUpdated ( event ) ;
} ) ;
SUBSCRIBE ( WinoMail : : Events : : AccountConnectedEvent , [ this ] ( const WinoMail : : Events : : AccountConnectedEvent & event ) {
onAccountConnected ( event ) ;
} ) ;
SUBSCRIBE ( WinoMail : : Events : : AccountDisconnectedEvent , [ this ] ( const WinoMail : : Events : : AccountDisconnectedEvent & event ) {
onAccountDisconnected ( event ) ;
} ) ;
SUBSCRIBE ( WinoMail : : Events : : SyncStartedEvent , [ this ] ( const WinoMail : : Events : : SyncStartedEvent & event ) {
onSyncStarted ( event ) ;
} ) ;
SUBSCRIBE ( WinoMail : : Events : : SyncFinishedEvent , [ this ] ( const WinoMail : : Events : : SyncFinishedEvent & event ) {
onSyncFinished ( event ) ;
} ) ;
SUBSCRIBE ( WinoMail : : Events : : ErrorEvent , [ this ] ( const WinoMail : : Events : : ErrorEvent & event ) {
onErrorOccurred ( event ) ;
} ) ;
2026-05-24 00:02:19 +02:00
// Show tray icon
m_trayIcon - > show ( ) ;
}
void NotificationManager : : onMailItemAdded ( const WinoMail : : Events : : MailItemAddedEvent & event )
{
qDebug ( ) < < " NotificationManager: New mail arrived - " < < event . item . subject ( ) ;
// Show a system tray notification
m_trayIcon - > showMessage (
" Wino Mail - Nuevo correo " ,
event . item . subject ( ) ,
QSystemTrayIcon : : MessageIcon : : Information ,
5000 // 5 seconds
) ;
// Play sound
playNewMailSound ( ) ;
}
2026-05-29 11:43:44 +02:00
void NotificationManager : : onMailItemRemoved ( const WinoMail : : Events : : MailItemRemovedEvent & event )
{
qDebug ( ) < < " NotificationManager: Mail removed - UID: " < < event . itemUid ;
// Show a system tray notification
m_trayIcon - > showMessage (
" Wino Mail - Correo eliminado " ,
QString ( " Correo con UID %1 eliminado " ) . arg ( event . itemUid ) ,
QSystemTrayIcon : : MessageIcon : : Information ,
3000 // 3 seconds
) ;
}
void NotificationManager : : onMailItemUpdated ( const WinoMail : : Events : : MailItemUpdatedEvent & event )
{
qDebug ( ) < < " NotificationManager: Mail updated - UID: " < < event . item . id ( ) < < " Changed fields: " < < event . changedFields ;
// Show a system tray notification for significant changes (like read/unread)
if ( event . changedFields . contains ( " read " ) | | event . changedFields . contains ( " flagged " ) ) {
m_trayIcon - > showMessage (
" Wino Mail - Correo actualizado " ,
QString ( " Correo %1 actualizado " ) . arg ( event . item . subject ( ) ) ,
QSystemTrayIcon : : MessageIcon : : Information ,
3000 // 3 seconds
) ;
}
}
void NotificationManager : : onAccountConnected ( const WinoMail : : Events : : AccountConnectedEvent & event )
{
qDebug ( ) < < " NotificationManager: Account connected - ID: " < < event . accountId < < " Provider: " < < event . provider ;
// Show a system tray notification
m_trayIcon - > showMessage (
" Wino Mail - Cuenta conectada " ,
QString ( " Cuenta %1 conectada (%2) " ) . arg ( event . accountId ) . arg ( event . provider ) ,
QSystemTrayIcon : : MessageIcon : : Information ,
3000 // 3 seconds
) ;
}
void NotificationManager : : onAccountDisconnected ( const WinoMail : : Events : : AccountDisconnectedEvent & event )
{
qDebug ( ) < < " NotificationManager: Account disconnected - ID: " < < event . accountId < < " Provider: " < < event . provider < < " Reason: " < < event . reason ;
// Show a system tray notification
m_trayIcon - > showMessage (
" Wino Mail - Cuenta desconectada " ,
QString ( " Cuenta %1 desconectada (%2): %3 " ) . arg ( event . accountId ) . arg ( event . provider ) . arg ( event . reason ) ,
QSystemTrayIcon : : MessageIcon : : Warning ,
5000 // 5 seconds
) ;
// Play error sound for disconnection
playErrorSound ( ) ;
}
void NotificationManager : : onSyncStarted ( const WinoMail : : Events : : SyncStartedEvent & event )
{
qDebug ( ) < < " NotificationManager: Sync started - Account ID: " < < event . accountId < < " Folder ID: " < < event . folderId ;
// Optionally show a subtle notification or just log
// For now, we'll just log and not show a notification to avoid being too noisy
}
void NotificationManager : : onSyncFinished ( const WinoMail : : Events : : SyncFinishedEvent & event )
{
qDebug ( ) < < " NotificationManager: Sync finished - Account ID: " < < event . accountId < < " Folder ID: " < < event . folderId < < " Success: " < < event . success ;
if ( ! event . success ) {
// Show error notification and play sound
m_trayIcon - > showMessage (
" Wino Mail - Error de sincronización " ,
QString ( " Error al sincronizar cuenta %1, carpeta %2: %3 " ) . arg ( event . accountId ) . arg ( event . folderId ) . arg ( event . errorMessage ) ,
QSystemTrayIcon : : MessageIcon : : Critical ,
5000 // 5 seconds
) ;
playErrorSound ( ) ;
} else {
// Optionally show success notification
// m_trayIcon->showMessage("Wino Mail - Sincronización completada", QString("Sincronización completada para cuenta %1, carpeta %2").arg(event.accountId).arg(event.folderId), QSystemTrayIcon::MessageIcon::Information, 3000);
}
}
void NotificationManager : : onErrorOccurred ( const WinoMail : : Events : : ErrorEvent & event )
{
qDebug ( ) < < " NotificationManager: Error occurred - Source: " < < event . source < < " Message: " < < event . message < < " Critical: " < < event . isCritical ;
// Show a system tray notification for critical errors
if ( event . isCritical ) {
m_trayIcon - > showMessage (
" Wino Mail - Error crítico " ,
QString ( " Error en %1: %2 " ) . arg ( event . source ) . arg ( event . message ) ,
QSystemTrayIcon : : MessageIcon : : Critical ,
5000 // 5 seconds
) ;
playErrorSound ( ) ;
}
}
2026-05-24 00:02:19 +02:00
void NotificationManager : : onTrayIconActivated ( QSystemTrayIcon : : ActivationReason reason )
{
if ( reason = = QSystemTrayIcon : : Trigger | | reason = = QSystemTrayIcon : : DoubleClick ) {
onShowHideRequested ( ) ;
}
}
void NotificationManager : : onShowHideRequested ( )
{
2026-05-29 11:43:44 +02:00
// Emit signal to toggle main window visibility
Q_EMIT showHideRequested ( ) ;
2026-05-24 00:02:19 +02:00
}
void NotificationManager : : onQuitRequested ( )
{
// Already connected to quit
}
void NotificationManager : : playNewMailSound ( )
{
if ( m_newMailSound - > isLoaded ( ) ) {
m_newMailSound - > play ( ) ;
}
2026-05-29 11:43:44 +02:00
}
void NotificationManager : : playErrorSound ( )
{
if ( m_errorSound - > isLoaded ( ) ) {
m_errorSound - > play ( ) ;
}
}
void NotificationManager : : showNotification ( const QString & title , const QString & message , QSystemTrayIcon : : MessageIcon icon , int timeout )
{
m_trayIcon - > showMessage ( title , message , icon , timeout ) ;
2026-05-24 00:02:19 +02:00
}