/*************************************************************************** kshowmail.cpp - description ------------------- begin : Sat May 6 12:13:57 MEST 2000 copyright : (C) 2000-2002 by Eggert Ehmke email : eggert.ehmke@berlin.de 26 Sep 2002 - Allow for columns to be hidden. Allistar Melville ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kshowmail.h" using namespace TDEIO; TDEAboutData* KShowMailApp::m_pAbout; KShowMailApp::KShowMailApp() { //set up actions initActions(); // create GUI from ui resource file setXMLFile( "kshowmailui.rc", true ); createGUI(); //the main window settings will be saved automatically setAutoSaveSettings(); //initiate GUI parts initStatusBar(); initDocument(); initView(); //the application is idle at beginning m_state = idle; //the setup dialog will be created in slotSetup() at first use SetupDialog = NULL; m_pTimer = new TQTimer (this); m_pAlertDialog = NULL; m_pDockWindow = new KShowMailDock (this, m_actionRefresh); m_bForceClose = false; //read the setup m_ConfigList.refreshSetup( m_pView->m_pListAccounts ); //load stored mails m_ConfigList.readStoredMails(); //connect signals with slots connect (m_pDockWindow, SIGNAL (quitSelected ()), SLOT (slotForceClose ())); connect (m_pTimer, SIGNAL (timeout ()), SLOT (slotRefresh ())); connect (m_pView->m_pListAccounts, SIGNAL (currentChanged(TQListViewItem*)), SLOT(slotAccountActivated(TQListViewItem*))); connect (m_pView, SIGNAL (signalActiveChanged()), SLOT (slotRefreshView())); connect( &m_ConfigList, SIGNAL( sigDeleteReady() ), this, SLOT( slotDeletionReady() ) ); connect( &m_ConfigList, SIGNAL( sigShowBodiesReady() ), this, SLOT( slotShowMessageReady() ) ); connect( &m_ConfigList, SIGNAL( sigMessageWindowOpened() ), this, SLOT( slotNormalCursor() ) ); connect( &m_ConfigList, SIGNAL( sigAllMessageWindowsClosed() ), this, SLOT( slotWaitingCursor() ) ); connect( &m_ConfigList, SIGNAL( sigRefreshReady() ), this, SLOT( slotRefreshReady() ) ); //show welcome message KMessageBox::information( NULL, i18n( "Thank You for using KShowmail.\nPlease use the feedback dialog to tell us your experience with this program." ), i18n("Welcome"), "WelcomeMessage" ); // this starts the one-second-interval timer // this is a TQObject method startTimer (1000); //we are ready to take off! Lets initiate the first refresh (if desired) initFirstRefresh(); } KShowMailApp::~KShowMailApp() { kdDebug() << "cleaning up" << endl; delete m_pTimer; delete m_pDockWindow; kdDebug() << "cleanup finished" << endl; } /** * This is reimplemented from TQObject */ void KShowMailApp::timerEvent (TQTimerEvent *) { if (m_nSecondsToGo) { TQTime time; time = time.addSecs (m_nSecondsToGo--); TQCString msg (i18n("Autorefresh: %1").arg(time.toString()).utf8()); statusBar()->changeItem( msg, STATUSBAR_FIELD_NEXT_REFRESH ); } else statusBar()->changeItem( "", STATUSBAR_FIELD_NEXT_REFRESH ); // if busy, animate the traybar if ( m_state == refreshing || m_state == deleting ) { static int color = 0; color = (color+1)%2; switch (color) { case 0: m_pDockWindow->clear (); break; default: m_pDockWindow->drawText ("?", TQt::red); } } } void KShowMailApp::initActions () { // file menu KStdAction::quit( this, SLOT( slotFileQuit() ), actionCollection() ); // action menu m_actionRefresh = new TDEAction( i18n( "&Refresh messages" ), "reload", Key_F5, this, SLOT( slotRefresh() ), actionCollection(), "refresh" ); new TDEAction( i18n( "Show &header of highlighted messages" ), "letter-closed", Key_F2, this, SLOT( slotShowHeader() ), actionCollection(), "show_header" ); new TDEAction( i18n( "Show &complete highlighted messages" ), "letter-open", Key_F3, this, SLOT( slotShowMessage() ), actionCollection(), "show_complete" ); new TDEAction( i18n( "&Delete highlighted messages" ), "eraser", Key_Delete, this, SLOT( slotDelete() ), actionCollection(), "delete" ); new TDEAction( i18n( "S&top current transfer" ), "process-stop", 0, this, SLOT( slotStop() ), actionCollection(), "stop" ); new TDEAction( i18n( "Show Filter Log" ), "text-x-log", Key_F4, this, SLOT( slotShowFilterLog() ), actionCollection(), "show_filterlog" ); new TDEAction( i18n( "Add sender to whitelist" ), "add_user", 0, this, SLOT( slotAddToWhitelist() ), actionCollection(), "addWhitelist" ); new TDEAction( i18n( "Add sender to blacklist" ), "delete_user", 0, this, SLOT( slotAddToBlacklist() ), actionCollection(), "addBlacklist" ); // setup menu KStdAction::preferences( this, SLOT( slotSetup() ), actionCollection() ); KStdAction::configureToolbars( this, SLOT( slotEditToolbars() ), actionCollection() ); //create menu items for toggle tool and status bar setStandardToolBarMenuEnabled( true ); createStandardStatusBarAction(); //help menu new TDEAction( i18n( "Send &Feedback Mail" ), "email", 0, this, SLOT( slotSendFeedbackMail() ),actionCollection(), "sendFeedback" ); //for account context menu new TDEAction(i18n( "Setup &account" ), "tool", 0, this, SLOT( slotSetupAccount() ), actionCollection(), "setupAccount" ); } void KShowMailApp::initStatusBar() { statusBar()->insertItem( i18n( "Ready." ), STATUSBAR_FIELD_STATE ); statusBar()->insertItem( "", STATUSBAR_FIELD_FILTER, 1 ); statusBar()->setItemAlignment( STATUSBAR_FIELD_FILTER, AlignLeft | AlignVCenter ); statusBar()->insertItem( "", STATUSBAR_FIELD_NEXT_REFRESH ); statusBar()->insertItem( "", STATUSBAR_FIELD_LAST_REFRESH ); TQToolTip::add( statusBar(), i18n( "Shows the number of deleted, moved or ignored mails by the filter.\nThe positions denotes:\nby last refresh / since application start / listed by the log" ) ); refreshFilterStatusBar(); } void KShowMailApp::initDocument() { m_pDoc = new KshowmailDoc(this); m_pDoc->newDocument(); } void KShowMailApp::initView() { //////////////////////////////////////////////////////////////////// // create the main widget here that is managed by TDEMainWindow's view-region and // connect the widget to your document to display document contents. m_pView = new KshowmailView(this); m_pDoc->addView(m_pView); setCentralWidget(m_pView); } void KShowMailApp::slotSaveOptions() { TDEConfig* config = TDEGlobal::config(); //order application parts to save their setup m_pView->saveOptions( config ); m_ConfigList.saveOptions (); fLog.save(); //save config to file config->sync (); } bool KShowMailApp::queryClose() { bool result; kdDebug() << "KShowMailApp::queryClose()" << endl; if (m_bForceClose) { // We are forced to close app - so just do it kdDebug() << "forced exit" << endl; result = true; } else if( m_ConfigList.closeToTray() ) { // Don't close - close button must minimize the window result = false; kdDebug() << "ignoring close request and minimizing the window" << endl; TDEMainWindow* w = memberList->first(); w->hide(); } else { // Need to ask user first result = askCloseConfirmation(); } return result; } bool KShowMailApp::queryExit() { kdDebug() << "KShowMailApp::queryExit()" << endl; slotSaveOptions (); return true; } ///////////////////////////////////////////////////////////////////// // SLOT IMPLEMENTATION ///////////////////////////////////////////////////////////////////// void KShowMailApp::slotFileQuit() { kdDebug () << "KShowMailApp::slotFileQuit()" << endl; if(memberList && askCloseConfirmation()) { m_bForceClose = true; // Forcing the closing TDEMainWindow* w = memberList->first(); w->close(); } } void KShowMailApp::slotSetupAccount() { //just open the dialog, if the app is idle if (m_state != idle) { kapp->beep(); return; } //set application state m_state = configure; //stop the refresh timer stopRefreshTimer(); //get account to configure ConfigElem* pConfig = m_ConfigList.getSelectedAccount(); if( pConfig != NULL ) { //open dialog //the dialog sets the new options directly in the account ServerDialog dlg( this, pConfig ); if( dlg.exec() == TQDialog::Accepted ) { //if OK was clicked, refresh the account list view slotConfChanged(); } } //we are ready, set application state to idle and initiate next refresh m_state = idle; initNextRefresh(); } void KShowMailApp::slotAccountActivated (TQListViewItem* pItem) { TQPtrListIterator it(m_ConfigList); // this is = not == !!! while (ConfigElem* pConfig = it()) { if (pConfig->getListViewItem() == pItem) { setCaption (pConfig->getAccountName()); return; } } } void KShowMailApp::slotAlertDestroyed() { m_pAlertDialog = NULL; } void KShowMailApp::slotAlertOk () { //switch main window to normal view showNormal(); raise(); } void KShowMailApp::slotRefresh() { //return, if the app is not idle if ( m_state != idle ) { kapp->beep(); initNextRefresh(); return; } //stop the refresh timer stopRefreshTimer(); //set the state m_state = refreshing; //show status message slotStatusMsg( i18n( "Refreshing ..." ) ); //set waiting cursor TQApplication::setOverrideCursor( TQt::waitCursor ); //order the account list to refresh its mail lists m_ConfigList.refreshMailLists( &fLog ); return; } void KShowMailApp::slotStop () { if (m_state == idle) { kapp->beep (); return; } kdDebug() << "KShowMailApp::slotStop" << endl; //kill all running pop3 jobs m_ConfigList.killPOP3Jobs(); slotRefreshView (); // make sure the view is refreshed before the state gets idle again // bug #853651 //set state to idle m_state = idle; //set normal cursor //might be more than one override cursor ... while (TQApplication::overrideCursor()) TQApplication::restoreOverrideCursor (); //print status message slotStatusMsg(i18n("Job was stopped")); } void KShowMailApp::slotRefreshView () { //clear mail list view m_pView->clearMailListView(); //fill mail list view m_ConfigList.fillMailListView( m_pView ); //refresh account list m_ConfigList.refreshAccountList(); //get some informations int numberMails = m_ConfigList.getNumberMails(); bool hasNewMails = m_ConfigList.getNumberNewMails() > 0; //draw number of mails into dock if( hasNewMails ) //draw red number, because we have new mails m_pDockWindow->drawNumber( numberMails, TQt::red ); else //we haven't new mails, draw black m_pDockWindow->drawNumber( numberMails, TQt::black ); //show message in status bar long totalSize = m_ConfigList.getTotalSize(); slotStatusMsg( i18n( "%1 message(s) with a total of %2 bytes are waiting" ).arg( numberMails ).arg( totalSize ) ); //refresh filter view in the status bar refreshFilterStatusBar(); } void KShowMailApp::slotDelete() { //just delete, if no operation is running if( m_state != idle ) { kapp->beep(); return; } //return, if no mails are selected if( !m_ConfigList.hasSelectedMails() ) return; //confirm deletion if required if( m_ConfigList.confirmDeletion() ) { //get subjects off all selected mails TQStringList subjects = m_ConfigList.getSelectedSubjects(); //show question int answer = KMessageBox::questionYesNoList( this, i18n( "Do you want to delete these mails?"), subjects, i18n( "Delete?" ) ); if( answer == KMessageBox::No ) return; } //set the state m_state = deleting; //show status message slotStatusMsg( i18n( "Deleting Mail(s) ..." ) ); //set waiting cursor TQApplication::setOverrideCursor( TQt::waitCursor ); //order the account list to delete the selected mails //test! m_ConfigList.deleteSelectedMails(); } void KShowMailApp::slotShowHeader () { //only show headers, if the app is idle if( m_state != idle ) { kapp->beep (); return; } //show the headers m_ConfigList.showSelectedHeaders(); } void KShowMailApp::slotShowMessage () { //return, if application is not idle if( m_state != idle ) { kapp->beep (); return; } //return, if no mails are selected if( !m_ConfigList.hasSelectedMails() ) return; //set the state m_state = showing; //show status message slotStatusMsg( i18n( "Downloading ..." ) ); //set waiting cursor TQApplication::setOverrideCursor( TQt::waitCursor ); //order the account list to show the selected mails m_ConfigList.showSelectedMails(); } void KShowMailApp::slotStatusMsg(const TQString& text) { //get current time // added by Gustavo Zamorano to include time TQString sTime = TQTime::currentTime ().toString (); //clear status bar statusBar()->clear(); //set given text statusBar()->changeItem( text, STATUSBAR_FIELD_STATE ); //set current time statusBar()->changeItem( i18n( "Last Refresh: %1" ).arg( sTime ), STATUSBAR_FIELD_LAST_REFRESH ); } void KShowMailApp::slotStatusHelpMsg(const TQString &text) { statusBar()->message(text, 2000); } bool KShowMailApp::event(TQEvent *e) { // to hide the taskbar button; any better solution ?? if ((e->type() == TQEvent::Hide) && m_ConfigList.minimizesToTray() ) { hide (); } return(TDEMainWindow::event(e)); } void KShowMailApp::slotForceClose() { m_bForceClose = true; } bool KShowMailApp::askCloseConfirmation() { bool result; if( m_ConfigList.confirmClose() ) { // Need to ask user result = (KMessageBox::questionYesNo (this, i18n ("KShowmail will be closed.\n" "Are you sure?")) == KMessageBox::Yes); } else { // User doesn't want to be asked - just close it result = true; } return result; } void KShowMailApp::slotDeletionReady( ) { //set state to idle m_state = idle; //set normal cursor while( TQApplication::overrideCursor() ) TQApplication::restoreOverrideCursor(); //show status message slotStatusMsg( i18n( "Ready." ) ); //refresh mail list slotRefresh(); } void KShowMailApp::slotShowMessageReady( ) { //set state to idle m_state = idle; //set normal cursor while( TQApplication::overrideCursor() ) TQApplication::restoreOverrideCursor(); //show status message slotStatusMsg( i18n( "Ready." ) ); } void KShowMailApp::slotNormalCursor( ) { //set normal cursor while( TQApplication::overrideCursor() ) TQApplication::restoreOverrideCursor(); } void KShowMailApp::slotWaitingCursor( ) { //set waiting cursor TQApplication::setOverrideCursor( TQt::waitCursor ); } void KShowMailApp::slotRefreshReady( ) { //set state to idle m_state = idle; //set normal cursor while( TQApplication::overrideCursor() ) TQApplication::restoreOverrideCursor(); //refresh mail list view slotRefreshView(); //inform the user about new mails bool hasNewMails = m_ConfigList.getNumberNewMails() > 0; if ( hasNewMails ) { //show main window if desired if( m_ConfigList.showMainWindowForNewMails() ) { showNormal(); raise(); } //get out some sounds m_ConfigList.beep(); m_ConfigList.playSound(); //execute a command m_ConfigList.executeNewMailCommand(); //show alert message if desired if( m_ConfigList.showAlertMessageForNewMails() ) { //have we created one already? if( m_pAlertDialog != NULL ) { //yes, we have one m_pAlertDialog->show(); m_pAlertDialog->raise(); } else { //create a message dialog m_pAlertDialog = new AlertDialog( this ); connect( m_pAlertDialog, SIGNAL( destroyed() ), SLOT( slotAlertDestroyed() ) ); connect( m_pAlertDialog, SIGNAL( signalOk() ), SLOT( slotAlertOk() ) ); } } } else { //no new mails was received //perform configured actions //terminate app if desired if( m_ConfigList.quitNoNewMails() ) slotFileQuit(); else if( m_ConfigList.minimizeMainWindowNoNewMails() ) { showMinimized(); hide(); } } //show status message slotStatusMsg( i18n( "Ready." ) ); //prepare next refresh cycle initNextRefresh(); } void KShowMailApp::initFirstRefresh( ) { //is auto refresh on? if not, we do nothing if( m_ConfigList.AutoRefreshOn() ) { //is an initial time configured? if not, we refresh immediately if( m_ConfigList.hasInitTime() ) { //starts refresh timer with the configured initial time to first refresh m_pTimer->start( m_ConfigList.getInitTime() * 1000, true ); m_nSecondsToGo = m_ConfigList.getInitTime(); } else { //just to set a defined state m_pTimer->stop(); m_nSecondsToGo = 0; //start refresh cycle slotRefresh(); } } else { //set a defined state m_pTimer->stop(); m_nSecondsToGo = 0; } } void KShowMailApp::stopRefreshTimer( ) { m_pTimer->stop(); m_nSecondsToGo = 0; } void KShowMailApp::initNextRefresh( ) { if( m_ConfigList.AutoRefreshOn() ) { //auto refresh is activated //restart the refresh timer m_pTimer->start( m_ConfigList.getRefreshTimeInterval() * 60000, true ); m_nSecondsToGo = m_ConfigList.getRefreshTimeInterval() * 60; } else { //auto refresh is not activated //set a defined state of the refresh timer m_pTimer->stop(); m_nSecondsToGo = 0; } } void KShowMailApp::delayNextRefresh( ) { const unsigned long DELAY_TIME = 60; //delay only if the timer is active and the remaining time is less than one minute if( m_pTimer->isActive() ) { if( m_nSecondsToGo < DELAY_TIME ) { m_pTimer->start( DELAY_TIME * 1000, true ); m_nSecondsToGo = DELAY_TIME; } } } void KShowMailApp::slotEditToolbars() { //create the toolbar config dialog KEditToolbar *dlg = new KEditToolbar(guiFactory()); if( dlg->exec() ) { //if dialog closed by OK, create the GUI new //the dialog has changed the kshowmailui.rc file createGUI(); } //destruct dialog delete dlg; } void KShowMailApp::slotSetup( ) { //just open the dialog, if the app is idle if (m_state != idle) { kapp->beep(); return; } //set application state m_state = configure; //stop the refresh timer stopRefreshTimer(); if ( SetupDialog == NULL ) { //if no preferences dialog was created as yet, create one SetupDialog = new KCMultiDialog( KCMultiDialog::IconList, i18n( "Options" ), this, "SetupDialog" ); SetupDialog->addModule( "kshowmailconfigaccounts.desktop" ); SetupDialog->addModule( "kshowmailconfiggeneral.desktop" ); SetupDialog->addModule( "kshowmailconfigdisplay.desktop" ); SetupDialog->addModule( "kshowmailconfigactions.desktop" ); SetupDialog->addModule( "kshowmailconfigfilter.desktop" ); SetupDialog->addModule( "kshowmailconfigspamcheck.desktop" ); SetupDialog->addModule( "kshowmailconfiglog.desktop" ); //If the configuration was changed, it will call slotConfChanged connect( SetupDialog, SIGNAL( configCommitted() ), this, SLOT( slotConfChanged() ) ); } //execute preferences dialog SetupDialog->exec(); //we are ready, set application state to idle and initiate next refresh m_state = idle; initNextRefresh(); } void KShowMailApp::slotConfChanged( ) { //read the new setup m_ConfigList.refreshSetup( m_pView->m_pListAccounts ); m_pView->refreshSetup(); fLog.loadSetup(); } void KShowMailApp::slotShowFilterLog( ) { //open dialog FilterLogView view( this, &fLog ); view.exec(); refreshFilterStatusBar(); } void KShowMailApp::refreshFilterStatusBar( ) { int numberDeletedLastRefresh = m_ConfigList.numberDeletedMailsLastRefresh(); int numberDeletedSinceStart = m_ConfigList.numberDeletedMailsStart(); int numberDeletedLog = fLog.numberDeletedMails(); int numberMovedLastRefresh = m_ConfigList.numberMovedMailsLastRefresh(); int numberMovedSinceStart = m_ConfigList.numberMovedMailsStart(); int numberMovedLog = fLog.numberMovedMails(); int numberIgnored = m_ConfigList.numberIgnoredMails(); statusBar()->changeItem( i18n( "Filter: Deleted: %1/%2/%3; Moved: %4/%5/%6; Ignored: %7" ).arg( numberDeletedLastRefresh ).arg( numberDeletedSinceStart ).arg( numberDeletedLog ).arg( numberMovedLastRefresh ).arg( numberMovedSinceStart ).arg( numberMovedLog ).arg( numberIgnored ), STATUSBAR_FIELD_FILTER ); } void KShowMailApp::slotAddToWhitelist( ) { //get new entries TQStringList newEntries = m_ConfigList.getSelectedSenders(); //get previous whitelist from config TDEConfig* config = TDEApplication::kApplication()->config(); config->setGroup( CONFIG_GROUP_FILTER ); TQStringList whiteList = config->readListEntry( CONFIG_ENTRY_FILTER_WHITELIST ); //append new entries for( TQStringList::Iterator it = newEntries.begin(); it != newEntries.end(); ++it ) { if( whiteList.contains( *it ) == 0 ) { whiteList.append( *it ); } } //write extended whitelist back config->writeEntry( CONFIG_ENTRY_FILTER_WHITELIST, whiteList ); config->sync(); //load new config m_ConfigList.refreshFilterSetup(); } void KShowMailApp::slotAddToBlacklist( ) { //get new entries TQStringList newEntries = m_ConfigList.getSelectedSenders(); //get previous blacklist from config TDEConfig* config = TDEApplication::kApplication()->config(); config->setGroup( CONFIG_GROUP_FILTER ); TQStringList blackList = config->readListEntry( CONFIG_ENTRY_FILTER_BLACKLIST ); //append new entries for( TQStringList::Iterator it = newEntries.begin(); it != newEntries.end(); ++it ) { if( blackList.contains( *it ) == 0 ) { blackList.append( *it ); } } //write extended whitelist back config->writeEntry( CONFIG_ENTRY_FILTER_BLACKLIST, blackList ); config->sync(); //load new config m_ConfigList.refreshFilterSetup(); } #include "kshowmail.moc"