kmail

customtemplates.cpp

Go to the documentation of this file.
00001 /*   -*- mode: C++; c-file-style: "gnu" -*-
00002  *   kmail: KDE mail client
00003  *   This file: Copyright (C) 2006 Dmitry Morozhnikov
00004  *
00005  *   This program is free software; you can redistribute it and/or modify
00006  *   it under the terms of the GNU General Public License as published by
00007  *   the Free Software Foundation; either version 2 of the License, or
00008  *   (at your option) any later version.
00009  *
00010  *   This program is distributed in the hope that it will be useful,
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *   GNU General Public License for more details.
00014  *
00015  *   You should have received a copy of the GNU General Public License
00016  *   along with this program; if not, write to the Free Software
00017  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  */
00020 
00021 #include <config.h>
00022 
00023 #include <klocale.h>
00024 #include <kglobal.h>
00025 #include <qpopupmenu.h>
00026 #include <qpushbutton.h>
00027 #include <qtextedit.h>
00028 #include <qlineedit.h>
00029 #include <qtoolbox.h>
00030 #include <kdebug.h>
00031 #include <qfont.h>
00032 #include <kiconloader.h>
00033 #include <kpushbutton.h>
00034 #include <klistview.h>
00035 #include <klineedit.h>
00036 #include <qcombobox.h>
00037 #include <kshortcut.h>
00038 #include <kmessagebox.h>
00039 #include <kkeybutton.h>
00040 #include <kactivelabel.h>
00041 
00042 #include "customtemplates_base.h"
00043 #include "customtemplates_kfg.h"
00044 #include "globalsettings.h"
00045 #include "kmkernel.h"
00046 #include "kmmainwidget.h"
00047 
00048 #include "customtemplates.h"
00049 
00050 CustomTemplates::CustomTemplates( QWidget *parent, const char *name )
00051   :CustomTemplatesBase( parent, name ), mCurrentItem( 0 )
00052 {
00053   QFont f = KGlobalSettings::fixedFont();
00054   mEdit->setFont( f );
00055 
00056   mAdd->setIconSet( BarIconSet( "add", KIcon::SizeSmall ) );
00057   mRemove->setIconSet( BarIconSet( "remove", KIcon::SizeSmall ) );
00058 
00059   mList->setColumnWidth( 0, 50 );
00060   mList->setColumnWidth( 1, 100 );
00061 
00062   mEditFrame->setEnabled( false );
00063 
00064   connect( mEdit, SIGNAL( textChanged() ),
00065            this, SLOT( slotTextChanged( void ) ) );
00066 
00067   connect( mInsertCommand, SIGNAL( insertCommand(QString, int) ),
00068            this, SLOT( slotInsertCommand(QString, int) ) );
00069 
00070   connect( mAdd, SIGNAL( clicked() ),
00071            this, SLOT( slotAddClicked() ) );
00072   connect( mRemove, SIGNAL( clicked() ),
00073            this, SLOT( slotRemoveClicked() ) );
00074   connect( mList, SIGNAL( selectionChanged() ),
00075            this, SLOT( slotListSelectionChanged() ) );
00076   connect( mType, SIGNAL( activated( int ) ),
00077            this, SLOT( slotTypeActivated( int ) ) );
00078 
00079   connect( mKeyButton, SIGNAL( capturedShortcut( const KShortcut& ) ),
00080            this, SLOT( slotShortcutCaptured( const KShortcut& ) ) );
00081 
00082   mReplyPix = KIconLoader().loadIcon( "mail_reply", KIcon::Small );
00083   mReplyAllPix = KIconLoader().loadIcon( "mail_replyall", KIcon::Small );
00084   mForwardPix = KIconLoader().loadIcon( "mail_forward", KIcon::Small );
00085 
00086   mType->clear();
00087   mType->insertItem( QPixmap(), i18n( "Message->", "Universal" ), TUniversal );
00088   mType->insertItem( mReplyPix, i18n( "Message->", "Reply" ), TReply );
00089   mType->insertItem( mReplyAllPix, i18n( "Message->", "Reply to All" ), TReplyAll );
00090   mType->insertItem( mForwardPix, i18n( "Message->", "Forward" ), TForward );
00091 
00092   QString help =
00093       i18n( "<qt>"
00094             "<p>Here you can add, edit, and delete custom message "
00095             "templates to use when you compose a reply or forwarding message. "
00096             "Create the custom template by selecting it using the right mouse "
00097             " button menu or toolbar menu. Also, you can bind a keyboard "
00098             "combination to the template for faster operations.</p>"
00099             "<p>Message templates support substitution commands "
00100             "by simple typing them or selecting them from menu "
00101             "<i>Insert command</i>.</p>"
00102             "<p>There are four types of custom templates: used to "
00103             "<i>Reply</i>, <i>Reply to All</i>, <i>Forward</i>, and "
00104             "<i>Universal</i> which can be used for all kind of operations. "
00105             "You cannot bind keyboard shortcut to <i>Universal</i> templates.</p>"
00106             "</qt>" );
00107   mHelp->setText( i18n( "<a href=\"whatsthis:%1\">How does this work?</a>" ).arg( help ) );
00108 }
00109 
00110 CustomTemplates::~CustomTemplates()
00111 {
00112   QDictIterator<CustomTemplateItem> it(mItemList);
00113   for ( ; it.current() ; ++it ) {
00114     CustomTemplateItem *vitem = mItemList.take( it.currentKey() );
00115     if ( vitem ) {
00116       delete vitem;
00117     }
00118   }
00119 }
00120 
00121 QString CustomTemplates::indexToType( int index )
00122 {
00123   QString typeStr;
00124   switch ( index ) {
00125   case TUniversal:
00126     // typeStr = i18n( "Any" ); break;
00127     break;
00128 /*  case TNewMessage:
00129     typeStr = i18n( "New Message" ); break;*/
00130   case TReply:
00131     typeStr = i18n( "Message->", "Reply" ); break;
00132   case TReplyAll:
00133     typeStr = i18n( "Message->", "Reply to All" ); break;
00134   case TForward:
00135     typeStr = i18n( "Message->", "Forward" ); break;
00136   default:
00137     typeStr = i18n( "Message->", "Unknown" ); break;
00138   }
00139   return typeStr;
00140 }
00141 
00142 void CustomTemplates::slotTextChanged()
00143 {
00144   emit changed();
00145 }
00146 
00147 void CustomTemplates::load()
00148 {
00149   QStringList list = GlobalSettings::self()->customTemplates();
00150   for ( QStringList::iterator it = list.begin(); it != list.end(); ++it ) {
00151     CTemplates t(*it);
00152     // QString typeStr = indexToType( t.type() );
00153     QString typeStr;
00154     KShortcut shortcut( t.shortcut() );
00155     CustomTemplateItem *vitem =
00156       new CustomTemplateItem( *it, t.content(),
00157         shortcut,
00158         static_cast<Type>( t.type() ) );
00159     mItemList.insert( *it, vitem );
00160     QListViewItem *item = new QListViewItem( mList, typeStr, *it, t.content() );
00161     switch ( t.type() ) {
00162     case TReply:
00163       item->setPixmap( 0, mReplyPix );
00164       break;
00165     case TReplyAll:
00166       item->setPixmap( 0, mReplyAllPix );
00167       break;
00168     case TForward:
00169       item->setPixmap( 0, mForwardPix );
00170       break;
00171     default:
00172       item->setPixmap( 0, QPixmap() );
00173       item->setText( 0, indexToType( t.type() ) );
00174       break;
00175     };
00176   }
00177 }
00178 
00179 void CustomTemplates::save()
00180 {
00181   if ( mCurrentItem ) {
00182     CustomTemplateItem *vitem = mItemList[ mCurrentItem->text( 1 ) ];
00183     if ( vitem ) {
00184       vitem->mContent = mEdit->text();
00185       vitem->mShortcut = mKeyButton->shortcut();
00186     }
00187   }
00188   QStringList list;
00189   QListViewItemIterator lit( mList );
00190   while ( lit.current() ) {
00191     list.append( (*lit)->text( 1 ) );
00192     ++lit;
00193   }
00194   QDictIterator<CustomTemplateItem> it( mItemList );
00195   for ( ; it.current() ; ++it ) {
00196     // list.append( (*it)->mName );
00197     CTemplates t( (*it)->mName );
00198     QString &content = (*it)->mContent;
00199     if ( content.stripWhiteSpace().isEmpty() ) {
00200       content = "%BLANK";
00201     }
00202     t.setContent( content );
00203     t.setShortcut( (*it)->mShortcut.toString() );
00204     t.setType( (*it)->mType );
00205     t.writeConfig();
00206   }
00207   GlobalSettings::self()->setCustomTemplates( list );
00208   GlobalSettings::self()->writeConfig();
00209 
00210   // update kmail menus related to custom templates
00211   if ( kmkernel->getKMMainWidget() )
00212     kmkernel->getKMMainWidget()->updateCustomTemplateMenus();
00213 }
00214 
00215 void CustomTemplates::slotInsertCommand( QString cmd, int adjustCursor )
00216 {
00217   int para, index;
00218   mEdit->getCursorPosition( &para, &index );
00219   mEdit->insertAt( cmd, para, index );
00220 
00221   index += adjustCursor;
00222 
00223   mEdit->setCursorPosition( para, index + cmd.length() );
00224 }
00225 
00226 void CustomTemplates::slotAddClicked()
00227 {
00228   QString str = mName->text();
00229   if ( !str.isEmpty() ) {
00230     CustomTemplateItem *vitem = mItemList[ str ];
00231     if ( !vitem ) {
00232       vitem = new CustomTemplateItem( str, "", KShortcut::null(), TUniversal );
00233       mItemList.insert( str, vitem );
00234       QListViewItem *item =
00235         new QListViewItem( mList, indexToType( TUniversal ), str, "" );
00236       mList->setSelected( item, true );
00237       mKeyButton->setEnabled( false );
00238       emit changed();
00239     }
00240   }
00241 }
00242 
00243 void CustomTemplates::slotRemoveClicked()
00244 {
00245   if ( mCurrentItem ) {
00246     CustomTemplateItem *vitem = mItemList.take( mCurrentItem->text( 1 ) );
00247     if ( vitem ) {
00248       delete vitem;
00249     }
00250     delete mCurrentItem;
00251     mCurrentItem = 0;
00252     emit changed();
00253   }
00254 }
00255 
00256 void CustomTemplates::slotListSelectionChanged()
00257 {
00258   if ( mCurrentItem ) {
00259     CustomTemplateItem *vitem = mItemList[ mCurrentItem->text( 1 ) ];
00260     if ( vitem ) {
00261       vitem->mContent = mEdit->text();
00262       vitem->mShortcut = mKeyButton->shortcut();
00263     }
00264   }
00265   QListViewItem *item = mList->selectedItem();
00266   if ( item ) {
00267     mEditFrame->setEnabled( true );
00268     mCurrentItem = item;
00269     CustomTemplateItem *vitem = mItemList[ mCurrentItem->text( 1 ) ];
00270     if ( vitem ) {
00271       // avoid emit changed()
00272       disconnect( mEdit, SIGNAL( textChanged() ),
00273                   this, SLOT( slotTextChanged( void ) ) );
00274 
00275       mEdit->setText( vitem->mContent );
00276       mKeyButton->setShortcut( vitem->mShortcut, false );
00277       mType->setCurrentItem( vitem->mType );
00278 
00279       connect( mEdit, SIGNAL( textChanged() ),
00280               this, SLOT( slotTextChanged( void ) ) );
00281 
00282       if ( vitem->mType == TUniversal )
00283       {
00284         mKeyButton->setEnabled( false );
00285       } else {
00286         mKeyButton->setEnabled( true );
00287       }
00288     }
00289   } else {
00290     mEditFrame->setEnabled( false );
00291     mCurrentItem = 0;
00292     mEdit->clear();
00293     mKeyButton->setShortcut( KShortcut::null(), false );
00294     mType->setCurrentItem( 0 );
00295   }
00296 }
00297 
00298 void CustomTemplates::slotTypeActivated( int index )
00299 {
00300   if ( mCurrentItem ) {
00301     // mCurrentItem->setText( 0, indexToType( index ) );
00302     CustomTemplateItem *vitem = mItemList[ mCurrentItem->text( 1 ) ];
00303     if ( !vitem ) {
00304       return;
00305     }
00306     vitem->mType = static_cast<Type>(index);
00307     switch ( vitem->mType ) {
00308     case TReply:
00309       mCurrentItem->setPixmap( 0, mReplyPix );
00310       break;
00311     case TReplyAll:
00312       mCurrentItem->setPixmap( 0, mReplyAllPix );
00313       break;
00314     case TForward:
00315       mCurrentItem->setPixmap( 0, mForwardPix );
00316       break;
00317     default:
00318       mCurrentItem->setPixmap( 0, QPixmap() );
00319       break;
00320     };
00321     if ( index == TUniversal )
00322     {
00323       mKeyButton->setEnabled( false );
00324     } else {
00325       mKeyButton->setEnabled( true );
00326     }
00327     emit changed();
00328   }
00329 }
00330 
00331 void CustomTemplates::slotShortcutCaptured( const KShortcut &shortcut )
00332 {
00333   KShortcut sc( shortcut );
00334   if ( sc == mKeyButton->shortcut() )
00335     return;
00336   if ( sc.isNull() || sc.toString().isEmpty() )
00337     sc.clear();
00338   bool assign = true;
00339   bool customused = false;
00340   // check if shortcut is already used for custom templates
00341   QDictIterator<CustomTemplateItem> it(mItemList);
00342   for ( ; it.current() ; ++it ) {
00343     if ( !mCurrentItem || (*it)->mName != mCurrentItem->text( 1 ) )
00344     {
00345       if ( (*it)->mShortcut == sc )
00346       {
00347         QString title( I18N_NOOP("Key Conflict") );
00348         QString msg( I18N_NOOP("The selected shortcut is already used "
00349               "for another custom template, "
00350               "would you still like to continue with the assignment?" ) );
00351         assign = ( KMessageBox::warningYesNo( this, msg, title )
00352                     == KMessageBox::Yes );
00353         if ( assign )
00354         {
00355           (*it)->mShortcut = KShortcut::null();
00356         }
00357         customused = true;
00358       }
00359     }
00360   }
00361   // check if shortcut is used somewhere else
00362   if ( !customused && !sc.isNull() &&
00363        !( kmkernel->getKMMainWidget()->shortcutIsValid( sc ) ) ) {
00364     QString title( I18N_NOOP("Key Conflict") );
00365     QString msg( I18N_NOOP("The selected shortcut is already used, "
00366           "would you still like to continue with the assignment?" ) );
00367     assign = ( KMessageBox::warningYesNo( this, msg, title )
00368                 == KMessageBox::Yes );
00369   }
00370   if ( assign ) {
00371     mKeyButton->setShortcut( sc, false );
00372     emit changed();
00373   }
00374 }
00375 
00376 #include "customtemplates.moc"