You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kshowmail/kshowmail/kshowmail.cpp

863 lines
22 KiB

/***************************************************************************
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()));
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<ConfigElem> 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"