kmail

snippetwidget.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   snippet feature from kdevelop/plugins/snippet/                        *
00003  *                                                                         * 
00004  *   Copyright (C) 2007 by Robert Gruber                                   *
00005  *   rgruber@users.sourceforge.net                                         *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  ***************************************************************************/
00013 
00014 #include <kurl.h>
00015 #include <kdebug.h>
00016 #include <klocale.h>
00017 #include <qlayout.h>
00018 #include <kpushbutton.h>
00019 #include <klistview.h>
00020 #include <qheader.h>
00021 #include <klineedit.h>
00022 #include <ktextedit.h>
00023 #include <kmessagebox.h>
00024 #include <kconfig.h>
00025 #include <qtooltip.h>
00026 #include <kpopupmenu.h>
00027 #include <qregexp.h>
00028 #include <qinputdialog.h>
00029 #include <qlabel.h>
00030 #include <qcheckbox.h>
00031 #include <qwhatsthis.h>
00032 #include <qdragobject.h>
00033 #include <qtimer.h>
00034 #include <kcombobox.h>
00035 #include <kmedit.h>
00036 #include <kiconloader.h>
00037 #include <kshortcut.h>
00038 #include <kaction.h>
00039 #include <kkeybutton.h>
00040 
00041 #include "snippetdlg.h"
00042 #include "snippetitem.h"
00043 #include "snippetwidget.h"
00044 
00045 #include <cassert>
00046 
00047 SnippetWidget::SnippetWidget(KMEdit* editor, KActionCollection* actionCollection, QWidget* parent)
00048         : KListView(parent, "snippet widget"), QToolTip( viewport() ),
00049         mEditor( editor ), mActionCollection( actionCollection )
00050 {
00051     // init the QPtrList
00052     _list.setAutoDelete(TRUE);
00053 
00054     // init the KListView
00055     setSorting( -1 );
00056     addColumn( "" );
00057     setFullWidth(true);
00058     header()->hide();
00059     setAcceptDrops(true);
00060     setDragEnabled(true);
00061     setDropVisualizer(false);
00062     setRootIsDecorated(true);
00063 
00064     //connect the signals
00065     connect( this, SIGNAL( contextMenuRequested ( QListViewItem *, const QPoint & , int ) ),
00066              this, SLOT( showPopupMenu(QListViewItem *, const QPoint & , int ) ) );
00067 
00068     connect( this, SIGNAL( doubleClicked (QListViewItem *) ),
00069              this, SLOT( slotEdit( QListViewItem *) ) );
00070     connect( this, SIGNAL( returnPressed (QListViewItem *) ),
00071              this, SLOT( slotExecuted( QListViewItem *) ) );
00072 
00073     connect( this, SIGNAL( dropped(QDropEvent *, QListViewItem *) ),
00074              this, SLOT( slotDropped(QDropEvent *, QListViewItem *) ) );
00075 
00076     connect( editor, SIGNAL( insertSnippet() ), this, SLOT( slotExecute() ));
00077 
00078     _cfg = 0;
00079 
00080     QTimer::singleShot(0, this, SLOT(initConfig()));
00081 }
00082 
00083 SnippetWidget::~SnippetWidget()
00084 {
00085   writeConfig();
00086   delete _cfg;
00087 
00088   /* We need to delete the child items before the parent items
00089      otherwise KDevelop would crash on exiting */
00090   SnippetItem * item;
00091   while (_list.count() > 0) {
00092     for (item=_list.first(); item; item=_list.next()) {
00093       if (item->childCount() == 0)
00094           _list.remove(item);
00095     }
00096   }
00097 }
00098 
00099 
00104 void SnippetWidget::slotAdd()
00105 {
00106   //kdDebug(5006) << "Ender slotAdd()" << endl;
00107   SnippetDlg dlg( mActionCollection, this, "SnippetDlg");
00108 
00109   /*check if the user clicked a SnippetGroup
00110     If not, we set the group variable to the SnippetGroup
00111     which the selected item is a child of*/
00112   SnippetGroup * group = dynamic_cast<SnippetGroup*>(selectedItem());
00113   if ( !group && selectedItem() )
00114     group = dynamic_cast<SnippetGroup*>(selectedItem()->parent());
00115 
00116   /* still no group, let's make a default one */
00117   if (!group ) {
00118     if ( _list.isEmpty() ) {
00119       group = new SnippetGroup(this, i18n("General"), SnippetGroup::getMaxId() );
00120       _list.append( group );
00121     } else {
00122       group = dynamic_cast<SnippetGroup*>( _list.first() );
00123     }
00124   }
00125   assert( group );
00126 
00127   /*fill the combobox with the names of all SnippetGroup entries*/
00128   for (SnippetItem *it=_list.first(); it; it=_list.next()) {
00129     if (dynamic_cast<SnippetGroup*>(it)) {
00130       dlg.cbGroup->insertItem(it->getName());
00131     }
00132   }
00133   dlg.cbGroup->setCurrentText(group->getName());
00134 
00135   if (dlg.exec() == QDialog::Accepted) {
00136       group = dynamic_cast<SnippetGroup*>(SnippetItem::findItemByName(dlg.cbGroup->currentText(), _list));
00137       _list.append( makeItem( group, dlg.snippetName->text(), dlg.snippetText->text(), dlg.keyButton->shortcut() ) );
00138   }
00139 }
00140 
00145 SnippetItem* SnippetWidget::makeItem( SnippetItem* parent, const QString& name, const QString& text, const KShortcut& shortcut )
00146 {
00147     SnippetItem * item = new SnippetItem(parent, name, text);
00148     const QString actionName = i18n("Snippet %1").arg(name);
00149     const QString normalizedName = QString(actionName).replace(" ", "_");
00150     if ( !mActionCollection->action(normalizedName.utf8() ) ) {
00151         KAction * action = new KAction( actionName, shortcut, item,
00152                                         SLOT( slotExecute() ), mActionCollection,
00153                                         normalizedName.utf8() );
00154         item->setAction(action);
00155         connect( item, SIGNAL( execute( QListViewItem* ) ),
00156                  this, SLOT( slotExecuted( QListViewItem* ) ) );
00157     }
00158     return item;
00159 }
00160 
00165 void SnippetWidget::slotAddGroup()
00166 {
00167   //kdDebug(5006) << "Ender slotAddGroup()" << endl;
00168   SnippetDlg dlg( mActionCollection, this, "SnippetDlg");
00169   dlg.setShowShortcut( false );
00170   dlg.snippetText->setEnabled(false);
00171   dlg.snippetText->setText("GROUP");
00172   dlg.setCaption(i18n("Add Group"));
00173   dlg.cbGroup->insertItem(i18n("All"));
00174   dlg.cbGroup->setCurrentText(i18n("All"));
00175 
00176   if (dlg.exec() == QDialog::Accepted) {
00177     _list.append( new SnippetGroup(this, dlg.snippetName->text(), SnippetGroup::getMaxId() ) );
00178   }
00179 }
00180 
00181 
00186 void SnippetWidget::slotRemove()
00187 {
00188   //get current data
00189   QListViewItem * item = currentItem();
00190   SnippetItem *snip = dynamic_cast<SnippetItem*>( item );
00191   SnippetGroup *group = dynamic_cast<SnippetGroup*>( item );
00192   if (!snip)
00193     return;
00194 
00195   if (group) {
00196     if (group->childCount() > 0 &&
00197         KMessageBox::warningContinueCancel(this, i18n("Do you really want to remove this group and all its snippets?"),QString::null,KStdGuiItem::del())
00198         == KMessageBox::Cancel)
00199       return;
00200 
00201     SnippetItem *it=_list.first();
00202     while ( it ) {
00203       if (it->getParent() == group->getId()) {
00204         SnippetItem *doomed = it;
00205         it = _list.next();
00206         //kdDebug(5006) << "remove " << doomed->getName() << endl;
00207         _list.remove(doomed);
00208       } else {
00209         it = _list.next();
00210       }
00211     }
00212   }
00213 
00214   //kdDebug(5006) << "remove " << snip->getName() << endl;
00215   _list.remove(snip);
00216 }
00217 
00218 
00219 
00224 void SnippetWidget::slotEdit( QListViewItem* item )
00225 {
00226     if( item == 0 ) {
00227     item = currentItem();
00228     }
00229 
00230   SnippetGroup *pGroup = dynamic_cast<SnippetGroup*>(item);
00231   SnippetItem *pSnippet = dynamic_cast<SnippetItem*>( item );
00232   if (!pSnippet || pGroup) /*selected item must be a SnippetItem but MUST not be a SnippetGroup*/
00233     return;
00234 
00235   //init the dialog
00236   SnippetDlg dlg( mActionCollection, this, "SnippetDlg");
00237   dlg.snippetName->setText(pSnippet->getName());
00238   dlg.snippetText->setText(pSnippet->getText());
00239   dlg.keyButton->setShortcut( pSnippet->getAction()->shortcut(), false );
00240   dlg.btnAdd->setText(i18n("&Apply"));
00241 
00242   dlg.setCaption(i18n("Edit Snippet"));
00243   /*fill the combobox with the names of all SnippetGroup entries*/
00244   for (SnippetItem *it=_list.first(); it; it=_list.next()) {
00245     if (dynamic_cast<SnippetGroup*>(it)) {
00246       dlg.cbGroup->insertItem(it->getName());
00247     }
00248   }
00249   dlg.cbGroup->setCurrentText(SnippetItem::findGroupById(pSnippet->getParent(), _list)->getName());
00250 
00251   if (dlg.exec() == QDialog::Accepted) {
00252     //update the KListView and the SnippetItem
00253     item->setText( 0, dlg.snippetName->text() );
00254     pSnippet->setName( dlg.snippetName->text() );
00255     pSnippet->setText( dlg.snippetText->text() );
00256     pSnippet->getAction()->setShortcut( dlg.keyButton->shortcut());
00257 
00258     /* if the user changed the parent we need to move the snippet */
00259     if ( SnippetItem::findGroupById(pSnippet->getParent(), _list)->getName() != dlg.cbGroup->currentText() ) {
00260       SnippetGroup * newGroup = dynamic_cast<SnippetGroup*>(SnippetItem::findItemByName(dlg.cbGroup->currentText(), _list));
00261       pSnippet->parent()->takeItem(pSnippet);
00262       newGroup->insertItem(pSnippet);
00263       pSnippet->resetParent();
00264     }
00265 
00266     setSelected(item, TRUE);
00267   }
00268 }
00269 
00274 void SnippetWidget::slotEditGroup()
00275 {
00276   //get current data
00277   QListViewItem * item = currentItem();
00278 
00279   SnippetGroup *pGroup = dynamic_cast<SnippetGroup*>( item );
00280   if (!pGroup) /*selected item MUST be a SnippetGroup*/
00281     return;
00282 
00283   //init the dialog
00284   SnippetDlg dlg( mActionCollection, this, "SnippetDlg" );
00285   dlg.setShowShortcut( false );
00286   dlg.snippetName->setText(pGroup->getName());
00287   dlg.snippetText->setText(pGroup->getText());
00288   dlg.btnAdd->setText(i18n("&Apply"));
00289   dlg.snippetText->setEnabled(FALSE);
00290   dlg.setCaption(i18n("Edit Group"));
00291   dlg.cbGroup->insertItem(i18n("All"));
00292 
00293   if (dlg.exec() == QDialog::Accepted) {
00294     //update the KListView and the SnippetGroup
00295     item->setText( 0, dlg.snippetName->text() );
00296     pGroup->setName( dlg.snippetName->text() );
00297 
00298     setSelected(item, TRUE);
00299   }
00300 }
00301 
00302 void SnippetWidget::slotExecuted(QListViewItem * item)
00303 {
00304     if( item == 0 )
00305     {
00306     item = currentItem();
00307     }
00308 
00309   SnippetItem *pSnippet = dynamic_cast<SnippetItem*>( item );
00310   if (!pSnippet || dynamic_cast<SnippetGroup*>(item))
00311       return;
00312 
00313   //process variables if any, then insert into the active view
00314   insertIntoActiveView( parseText(pSnippet->getText(), _SnippetConfig.getDelimiter()) );
00315 }
00316 
00317 
00322 void SnippetWidget::insertIntoActiveView( const QString &text )
00323 {
00324     mEditor->insert( text );
00325 }
00326 
00327 
00332 void SnippetWidget::writeConfig()
00333 {
00334   if( !_cfg )
00335     return;
00336   _cfg->deleteGroup("SnippetPart");  //this is neccessary otherwise delete entries will stay in list until
00337                                      //they get overwritten by a more recent entry
00338   _cfg->setGroup("SnippetPart");
00339 
00340   QString strKeyName="";
00341   QString strKeyText="";
00342   QString strKeyId="";
00343 
00344   int iSnipCount = 0;
00345   int iGroupCount = 0;
00346 
00347   SnippetItem* item=_list.first();
00348   while ( item != 0) {
00349 
00350     //kdDebug(5006) << "-->ERROR " << item->getName() << endl;
00351     //kdDebug(5006) << "SnippetWidget::writeConfig() " << item->getName() << endl;
00352     SnippetGroup * group = dynamic_cast<SnippetGroup*>(item);
00353     if (group) {
00354       //kdDebug(5006) << "-->GROUP " << item->getName() << group->getId() << " " << iGroupCount<< endl;
00355       strKeyName=QString("snippetGroupName_%1").arg(iGroupCount);
00356       strKeyId=QString("snippetGroupId_%1").arg(iGroupCount);
00357 
00358       _cfg->writeEntry(strKeyName, group->getName());
00359       _cfg->writeEntry(strKeyId, group->getId());
00360 
00361       iGroupCount++;
00362     } else if (dynamic_cast<SnippetItem*>(item)) {
00363       //kdDebug(5006) << "-->ITEM " << item->getName() << item->getParent() << " " << iSnipCount << endl;
00364       strKeyName=QString("snippetName_%1").arg(iSnipCount);
00365       strKeyText=QString("snippetText_%1").arg(iSnipCount);
00366       strKeyId=QString("snippetParent_%1").arg(iSnipCount);
00367 
00368       _cfg->writeEntry(strKeyName, item->getName());
00369       _cfg->writeEntry(strKeyText, item->getText());
00370       _cfg->writeEntry(strKeyId, item->getParent());
00371 
00372       KAction * action = item->getAction();
00373       assert( action );
00374       const KShortcut& sc = action->shortcut();
00375       if (!sc.isNull() ) {
00376           _cfg->writeEntry( QString("snippetShortcut_%1").arg(iSnipCount), sc.toString() );
00377       }
00378       iSnipCount++;
00379     } else {
00380       //kdDebug(5006) << "-->ERROR " << item->getName() << endl;
00381     }
00382     item = _list.next();
00383   }
00384   _cfg->writeEntry("snippetCount", iSnipCount);
00385   _cfg->writeEntry("snippetGroupCount", iGroupCount);
00386 
00387   int iCount = 1;
00388   QMap<QString, QString>::Iterator it;
00389   for ( it = _mapSaved.begin(); it != _mapSaved.end(); ++it ) {  //write the saved variable values
00390     if (it.data().length()<=0) continue;  //is the saved value has no length -> no need to save it
00391 
00392     strKeyName=QString("snippetSavedName_%1").arg(iCount);
00393     strKeyText=QString("snippetSavedVal_%1").arg(iCount);
00394 
00395     _cfg->writeEntry(strKeyName, it.key());
00396     _cfg->writeEntry(strKeyText, it.data());
00397 
00398     iCount++;
00399   }
00400   _cfg->writeEntry("snippetSavedCount", iCount-1);
00401 
00402 
00403   _cfg->writeEntry( "snippetDelimiter", _SnippetConfig.getDelimiter() );
00404   _cfg->writeEntry( "snippetVarInput", _SnippetConfig.getInputMethod() );
00405   _cfg->writeEntry( "snippetToolTips", _SnippetConfig.useToolTips() );
00406   _cfg->writeEntry( "snippetGroupAutoOpen", _SnippetConfig.getAutoOpenGroups() );
00407 
00408   _cfg->writeEntry("snippetSingleRect", _SnippetConfig.getSingleRect() );
00409   _cfg->writeEntry("snippetMultiRect", _SnippetConfig.getMultiRect() );
00410 
00411   _cfg->sync();
00412 }
00413 
00418 void SnippetWidget::initConfig()
00419 {
00420   if (_cfg == NULL)
00421     _cfg = new KConfig("kmailsnippetrc", false, false);
00422 
00423   _cfg->setGroup("SnippetPart");
00424 
00425   QString strKeyName="";
00426   QString strKeyText="";
00427   QString strKeyId="";
00428   SnippetItem *item;
00429   SnippetGroup *group;
00430 
00431   //kdDebug(5006) << "SnippetWidget::initConfig() " << endl;
00432 
00433   //if entry doesn't get found, this will return -1 which we will need a bit later
00434   int iCount = _cfg->readNumEntry("snippetGroupCount", -1);
00435 
00436   for ( int i=0; i<iCount; i++) {  //read the group-list
00437     strKeyName=QString("snippetGroupName_%1").arg(i);
00438     strKeyId=QString("snippetGroupId_%1").arg(i);
00439 
00440     QString strNameVal="";
00441     int iIdVal=-1;
00442 
00443     strNameVal = _cfg->readEntry(strKeyName, "");
00444     iIdVal = _cfg->readNumEntry(strKeyId, -1);
00445     //kdDebug(5006) << "Read group "  << " " << iIdVal << endl;
00446 
00447     if (strNameVal != "" && iIdVal != -1) {
00448       group = new SnippetGroup(this, strNameVal, iIdVal);
00449       //kdDebug(5006) << "Created group " << group->getName() << " " << group->getId() << endl;
00450       _list.append(group);
00451     }
00452   }
00453 
00454   /* Check if the snippetGroupCount property has been found
00455      if iCount is -1 this means, that the user has his snippets
00456      stored without groups. Therefore we will call the
00457      initConfigOldVersion() function below */
00458   // should not happen since this function has been removed
00459 
00460   if (iCount != -1) {
00461     iCount = _cfg->readNumEntry("snippetCount", 0);
00462     for ( int i=0; i<iCount; i++) {  //read the snippet-list
00463         strKeyName=QString("snippetName_%1").arg(i);
00464         strKeyText=QString("snippetText_%1").arg(i);
00465         strKeyId=QString("snippetParent_%1").arg(i);
00466 
00467         QString strNameVal="";
00468         QString strTextVal="";
00469         int iParentVal = -1;
00470 
00471         strNameVal = _cfg->readEntry(strKeyName, "");
00472         strTextVal = _cfg->readEntry(strKeyText, "");
00473         iParentVal = _cfg->readNumEntry(strKeyId, -1);
00474         //kdDebug(5006) << "Read item " << strNameVal << " " << iParentVal << endl;
00475 
00476         if (strNameVal != "" && strTextVal != "" && iParentVal != -1) {
00477             KShortcut shortcut( _cfg->readEntry( QString("snippetShortcut_%1").arg(i), QString() ) );
00478             item = makeItem( SnippetItem::findGroupById(iParentVal, _list), strNameVal, strTextVal, shortcut );
00479             //kdDebug(5006) << "Created item " << item->getName() << " " << item->getParent() << endl;
00480             _list.append(item);
00481         }
00482     }
00483   } else {
00484       //kdDebug() << "iCount is not -1";
00485   }
00486 
00487   iCount = _cfg->readNumEntry("snippetSavedCount", 0);
00488 
00489   for ( int i=1; i<=iCount; i++) {  //read the saved-values and store in QMap
00490     strKeyName=QString("snippetSavedName_%1").arg(i);
00491     strKeyText=QString("snippetSavedVal_%1").arg(i);
00492 
00493     QString strNameVal="";
00494     QString strTextVal="";
00495 
00496     strNameVal = _cfg->readEntry(strKeyName, "");
00497     strTextVal = _cfg->readEntry(strKeyText, "");
00498 
00499     if (strNameVal != "" && strTextVal != "") {
00500       _mapSaved[strNameVal] = strTextVal;
00501     }
00502   }
00503 
00504 
00505   _SnippetConfig.setDelimiter( _cfg->readEntry("snippetDelimiter", "$") );
00506   _SnippetConfig.setInputMethod( _cfg->readNumEntry("snippetVarInput", 0) );
00507   _SnippetConfig.setToolTips( _cfg->readBoolEntry("snippetToolTips", true) );
00508   _SnippetConfig.setAutoOpenGroups( _cfg->readNumEntry("snippetGroupAutoOpen", 1) );
00509 
00510   _SnippetConfig.setSingleRect( _cfg->readRectEntry("snippetSingleRect", 0L) );
00511   _SnippetConfig.setMultiRect( _cfg->readRectEntry("snippetMultiRect", 0L) );
00512 }
00513 
00518 void SnippetWidget::maybeTip( const QPoint & p )
00519 {
00520     SnippetItem * item = dynamic_cast<SnippetItem*>( itemAt( p ) );
00521     if (!item)
00522       return;
00523 
00524     QRect r = itemRect( item );
00525 
00526     if (r.isValid() &&
00527         _SnippetConfig.useToolTips() )
00528     {
00529         tip( r, item->getText() );  //show the snippet's text
00530     }
00531 }
00532 
00537 void SnippetWidget::showPopupMenu( QListViewItem * item, const QPoint & p, int )
00538 {
00539     KPopupMenu popup;
00540 
00541     SnippetItem * selectedItem = static_cast<SnippetItem *>(item);
00542     if ( item ) {
00543         popup.insertTitle( selectedItem->getName() );
00544         if (dynamic_cast<SnippetGroup*>(item)) {
00545             popup.insertItem( i18n("Edit &group..."), this, SLOT( slotEditGroup() ) );
00546         } else {
00547             popup.insertItem( SmallIconSet("editpaste"), i18n("&Paste"), this, SLOT( slotExecuted() ) );
00548             popup.insertItem( SmallIconSet("edit"), i18n("&Edit..."), this, SLOT( slotEdit() ) );
00549         }
00550         popup.insertItem( SmallIconSet("editdelete"), i18n("&Remove"), this, SLOT( slotRemove() ) );
00551         popup.insertSeparator();
00552     } else {
00553         popup.insertTitle(i18n("Text Snippets"));
00554     }
00555     popup.insertItem( i18n("&Add Snippet..."), this, SLOT( slotAdd() ) );
00556     popup.insertItem( i18n("Add G&roup..."), this, SLOT( slotAddGroup() ) );
00557 
00558     popup.exec(p);
00559 }
00560 
00561 
00562 //  fn SnippetWidget::parseText(QString text, QString del)
00567 QString SnippetWidget::parseText(QString text, QString del)
00568 {
00569   QString str = text;
00570   QString strName = "";
00571   QString strNew = "";
00572   QString strMsg="";
00573   int iFound = -1;
00574   int iEnd = -1;
00575   QMap<QString, QString> mapVar;
00576   int iInMeth = _SnippetConfig.getInputMethod();
00577   QRect rSingle = _SnippetConfig.getSingleRect();
00578   QRect rMulti = _SnippetConfig.getMultiRect();
00579 
00580   do {
00581     iFound = text.find(QRegExp("\\"+del+"[A-Za-z-_0-9\\s]*\\"+del), iEnd+1);  //find the next variable by this QRegExp
00582     if (iFound >= 0) {
00583       iEnd = text.find(del, iFound+1)+1;
00584       strName = text.mid(iFound, iEnd-iFound);
00585 
00586       if ( strName != del+del  ) {  //if not doubel-delimiter
00587         if (iInMeth == 0) { //if input-method "single" is selected
00588           if ( mapVar[strName].length() <= 0 ) {  // and not already in map
00589             strMsg=i18n("Please enter the value for <b>%1</b>:").arg(strName);
00590             strNew = showSingleVarDialog( strName, &_mapSaved, rSingle );
00591             if (strNew=="")
00592               return ""; //user clicked Cancle
00593           } else {
00594             continue; //we have already handled this variable
00595           }
00596         } else {
00597           strNew = ""; //for inputmode "multi" just reset new valaue
00598         }
00599       } else {
00600         strNew = del; //if double-delimiter -> replace by single character
00601       }
00602 
00603       if (iInMeth == 0) {  //if input-method "single" is selected
00604         str.replace(strName, strNew);
00605       }
00606 
00607       mapVar[strName] = strNew;
00608     }
00609   } while (iFound != -1);
00610 
00611   if (iInMeth == 1) {  //check config, if input-method "multi" is selected
00612     int w, bh, oh;
00613     w = rMulti.width();
00614     bh = rMulti.height();
00615     oh = rMulti.top();
00616     if (showMultiVarDialog( &mapVar, &_mapSaved, w, bh, oh )) {  //generate and show the dialog
00617       QMap<QString, QString>::Iterator it;
00618       for ( it = mapVar.begin(); it != mapVar.end(); ++it ) {  //walk through the map and do the replacement
00619         str.replace(it.key(), it.data());
00620       }
00621     } else {
00622       return "";
00623     }
00624 
00625     rMulti.setWidth(w);   //this is a hack to save the dialog's dimensions in only one QRect
00626     rMulti.setHeight(bh);
00627     rMulti.setTop(oh);
00628     rMulti.setLeft(0);
00629      _SnippetConfig.setMultiRect(rMulti);
00630   }
00631 
00632   _SnippetConfig.setSingleRect(rSingle);
00633 
00634   return str;
00635 }
00636 
00637 
00638 //  fn SnippetWidget::showMultiVarDialog()
00644 bool SnippetWidget::showMultiVarDialog(QMap<QString, QString> * map, QMap<QString, QString> * mapSave,
00645                                        int & iWidth, int & iBasicHeight, int & iOneHeight)
00646 {
00647   //if no var -> no need to show
00648   if (map->count() == 0)
00649     return true;
00650 
00651   //if only var is the double-delimiter -> no need to show
00652   QMap<QString, QString>::Iterator it = map->begin();
00653   if ( map->count() == 1 && it.data()==_SnippetConfig.getDelimiter()+_SnippetConfig.getDelimiter() )
00654     return true;
00655 
00656   QMap<QString, KTextEdit *> mapVar2Te;  //this map will help keeping track which TEXTEDIT goes with which variable
00657   QMap<QString, QCheckBox *> mapVar2Cb;  //this map will help keeping track which CHECKBOX goes with which variable
00658 
00659   // --BEGIN-- building a dynamic dialog
00660   QDialog dlg(this);
00661   dlg.setCaption(i18n("Enter Values for Variables"));
00662 
00663   QGridLayout * layout = new QGridLayout( &dlg, 1, 1, 11, 6, "layout");
00664   QGridLayout * layoutTop = new QGridLayout( 0, 1, 1, 0, 6, "layoutTop");
00665   QGridLayout * layoutVar = new QGridLayout( 0, 1, 1, 0, 6, "layoutVar");
00666   QGridLayout * layoutBtn = new QGridLayout( 0, 1, 1, 0, 6, "layoutBtn");
00667 
00668   KTextEdit *te = NULL;
00669   QLabel * labTop = NULL;
00670   QCheckBox * cb = NULL;
00671 
00672   labTop = new QLabel( &dlg, "label" );
00673   labTop->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0,
00674                          labTop->sizePolicy().hasHeightForWidth() ) );
00675   labTop->setText(i18n("Enter the replacement values for these variables:"));
00676   layoutTop->addWidget(labTop, 0, 0);
00677   layout->addMultiCellLayout( layoutTop, 0, 0, 0, 1 );
00678 
00679 
00680   int i = 0;                                           //walk through the variable map and add
00681   for ( it = map->begin(); it != map->end(); ++it ) {  //a checkbox, a lable and a lineedit to the main layout
00682     if (it.key() == _SnippetConfig.getDelimiter() + _SnippetConfig.getDelimiter())
00683       continue;
00684 
00685     cb = new QCheckBox( &dlg, "cbVar" );
00686     cb->setChecked( FALSE );
00687     cb->setText(it.key());
00688     layoutVar->addWidget( cb, i ,0, Qt::AlignTop );
00689 
00690     te = new KTextEdit( &dlg, "teVar" );
00691     layoutVar->addWidget( te, i, 1, Qt::AlignTop );
00692 
00693     if ((*mapSave)[it.key()].length() > 0) {
00694       cb->setChecked( TRUE );
00695       te->setText((*mapSave)[it.key()]);
00696     }
00697 
00698     mapVar2Te[it.key()] = te;
00699     mapVar2Cb[it.key()] = cb;
00700 
00701     QToolTip::add( cb, i18n("Enable this to save the value entered to the right as the default value for this variable") );
00702     QWhatsThis::add( cb, i18n("If you enable this option, the value entered to the right will be saved. "
00703                               "If you use the same variable later, even in another snippet, the value entered to the right "
00704                   "will be the default value for that variable.") );
00705 
00706     i++;
00707   }
00708   layout->addMultiCellLayout( layoutVar, 1, 1, 0, 1 );
00709 
00710   KPushButton * btn1 = new KPushButton( KStdGuiItem::cancel(), &dlg, "pushButton1" );
00711   btn1->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0,
00712                          btn1->sizePolicy().hasHeightForWidth() ) );
00713   layoutBtn->addWidget( btn1, 0, 0 );
00714 
00715   KPushButton * btn2 = new KPushButton( KStdGuiItem::apply(), &dlg, "pushButton2" );
00716   btn2->setDefault( TRUE );
00717   btn2->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0,
00718                          btn2->sizePolicy().hasHeightForWidth() ) );
00719   layoutBtn->addWidget( btn2, 0, 1 );
00720 
00721   layout->addMultiCellLayout( layoutBtn, 2, 2, 0, 1 );
00722   // --END-- building a dynamic dialog
00723 
00724   //connect the buttons to the QDialog default slots
00725   connect(btn1, SIGNAL(clicked()), &dlg, SLOT(reject()) );
00726   connect(btn2, SIGNAL(clicked()), &dlg, SLOT(accept()) );
00727 
00728   //prepare to execute the dialog
00729   bool bReturn = false;
00730   //resize the textedits
00731   if (iWidth > 1) {
00732     QRect r = dlg.geometry();
00733     r.setHeight(iBasicHeight + iOneHeight*mapVar2Te.count());
00734     r.setWidth(iWidth);
00735     dlg.setGeometry(r);
00736   }
00737   if ( i > 0 && // only if there are any variables
00738     dlg.exec() == QDialog::Accepted ) {
00739 
00740     QMap<QString, KTextEdit *>::Iterator it2;
00741     for ( it2 = mapVar2Te.begin(); it2 != mapVar2Te.end(); ++it2 ) {
00742       if (it2.key() == _SnippetConfig.getDelimiter() + _SnippetConfig.getDelimiter())
00743         continue;
00744       (*map)[it2.key()] = it2.data()->text();    //copy the entered values back to the given map
00745 
00746       if (mapVar2Cb[it2.key()]->isChecked())     //if the checkbox is on; save the values for later
00747         (*mapSave)[it2.key()] = it2.data()->text();
00748       else
00749         (*mapSave).erase(it2.key());
00750     }
00751     bReturn = true;
00752 
00753     iBasicHeight = dlg.geometry().height() - layoutVar->geometry().height();
00754     iOneHeight = layoutVar->geometry().height() / mapVar2Te.count();
00755     iWidth = dlg.geometry().width();
00756   }
00757 
00758   //do some cleanup
00759   QMap<QString, KTextEdit *>::Iterator it1;
00760   for (it1 = mapVar2Te.begin(); it1 != mapVar2Te.end(); ++it1)
00761     delete it1.data();
00762   mapVar2Te.clear();
00763   QMap<QString, QCheckBox *>::Iterator it2;
00764   for (it2 = mapVar2Cb.begin(); it2 != mapVar2Cb.end(); ++it2)
00765     delete it2.data();
00766   mapVar2Cb.clear();
00767   delete layoutTop;
00768   delete layoutVar;
00769   delete layoutBtn;
00770   delete layout;
00771 
00772   if (i==0) //if nothing happened this means, that there are no variables to translate
00773     return true; //.. so just return OK
00774 
00775   return bReturn;
00776 //  return true;
00777 }
00778 
00779 
00780 //  fn SnippetWidget::showSingleVarDialog(QString var, QMap<QString, QString> * mapSave)
00785 QString SnippetWidget::showSingleVarDialog(QString var, QMap<QString, QString> * mapSave, QRect & dlgSize)
00786 {
00787   // --BEGIN-- building a dynamic dialog
00788   QDialog dlg(this);
00789   dlg.setCaption(i18n("Enter Values for Variables"));
00790 
00791   QGridLayout * layout = new QGridLayout( &dlg, 1, 1, 11, 6, "layout");
00792   QGridLayout * layoutTop = new QGridLayout( 0, 1, 1, 0, 6, "layoutTop");
00793   QGridLayout * layoutVar = new QGridLayout( 0, 1, 1, 0, 6, "layoutVar");
00794   QGridLayout * layoutBtn = new QGridLayout( 0, 2, 1, 0, 6, "layoutBtn");
00795 
00796   KTextEdit *te = NULL;
00797   QLabel * labTop = NULL;
00798   QCheckBox * cb = NULL;
00799 
00800   labTop = new QLabel( &dlg, "label" );
00801   layoutTop->addWidget(labTop, 0, 0);
00802   labTop->setText(i18n("Enter the replacement values for %1:").arg( var ));
00803   layout->addMultiCellLayout( layoutTop, 0, 0, 0, 1 );
00804 
00805 
00806   cb = new QCheckBox( &dlg, "cbVar" );
00807   cb->setChecked( FALSE );
00808   cb->setText(i18n( "Make value &default" ));
00809 
00810   te = new KTextEdit( &dlg, "teVar" );
00811   layoutVar->addWidget( te, 0, 1, Qt::AlignTop);
00812   layoutVar->addWidget( cb, 1, 1, Qt::AlignTop);
00813   if ((*mapSave)[var].length() > 0) {
00814     cb->setChecked( TRUE );
00815     te->setText((*mapSave)[var]);
00816   }
00817 
00818   QToolTip::add( cb, i18n("Enable this to save the value entered to the right as the default value for this variable") );
00819   QWhatsThis::add( cb, i18n("If you enable this option, the value entered to the right will be saved. "
00820                             "If you use the same variable later, even in another snippet, the value entered to the right "
00821                             "will be the default value for that variable.") );
00822 
00823   layout->addMultiCellLayout( layoutVar, 1, 1, 0, 1 );
00824 
00825   KPushButton * btn1 = new KPushButton( KStdGuiItem::cancel(), &dlg, "pushButton1" );
00826   layoutBtn->addWidget( btn1, 0, 0 );
00827 
00828   KPushButton * btn2 = new KPushButton( KStdGuiItem::apply(), &dlg, "pushButton2" );
00829   btn2->setDefault( TRUE );
00830   layoutBtn->addWidget( btn2, 0, 1 );
00831 
00832   layout->addMultiCellLayout( layoutBtn, 2, 2, 0, 1 );
00833   te->setFocus();
00834   // --END-- building a dynamic dialog
00835 
00836   //connect the buttons to the QDialog default slots
00837   connect(btn1, SIGNAL(clicked()), &dlg, SLOT(reject()) );
00838   connect(btn2, SIGNAL(clicked()), &dlg, SLOT(accept()) );
00839 
00840   //execute the dialog
00841   QString strReturn = "";
00842   if (dlgSize.isValid())
00843     dlg.setGeometry(dlgSize);
00844   if ( dlg.exec() == QDialog::Accepted ) {
00845     if (cb->isChecked())     //if the checkbox is on; save the values for later
00846       (*mapSave)[var] = te->text();
00847     else
00848       (*mapSave).erase(var);
00849 
00850     strReturn = te->text();    //copy the entered values back the the given map
00851 
00852     dlgSize = dlg.geometry();
00853   }
00854 
00855   //do some cleanup
00856   delete cb;
00857   delete te;
00858   delete labTop;
00859   delete btn1;
00860   delete btn2;
00861   delete layoutTop;
00862   delete layoutVar;
00863   delete layoutBtn;
00864   delete layout;
00865 
00866   return strReturn;
00867 }
00868 
00869 //  fn SnippetWidget::acceptDrag (QDropEvent *event) const
00876 bool SnippetWidget::acceptDrag (QDropEvent *event) const
00877 {
00878   //kdDebug(5006) << "Format: " << event->format() << "" << event->pos() << endl;
00879 
00880   QListViewItem * item = itemAt(event->pos());
00881 
00882   if (item &&
00883       QString(event->format()).startsWith("text/plain") &&
00884       static_cast<SnippetWidget *>(event->source()) != this) {
00886     return TRUE;
00887   } else if(item &&
00888       QString(event->format()).startsWith("x-kmailsnippet") &&
00889       static_cast<SnippetWidget *>(event->source()) != this)
00890   {
00891     //kdDebug(5006) << "returning TRUE " << endl;
00892     return TRUE;
00893   } else {
00894     //kdDebug(5006) << "returning FALSE" << endl;
00895     event->acceptAction(FALSE);
00896     return FALSE;
00897   }
00898 }
00899 
00900 //  fn SnippetWidget::slotDropped(QDropEvent *e, QListViewItem *after)
00906 void SnippetWidget::slotDropped(QDropEvent *e, QListViewItem *)
00907 {
00908   QListViewItem * item2 = itemAt(e->pos());
00909 
00910   SnippetGroup *group = dynamic_cast<SnippetGroup *>(item2);
00911   if (!group)
00912     group = dynamic_cast<SnippetGroup *>(item2->parent());
00913 
00914   QCString dropped;
00915   QByteArray data = e->encodedData("text/plain");
00916   if ( e->provides("text/plain") && data.size()>0 ) {
00917     //get the data from the event...
00918     QString encData(data.data());
00919     //kdDebug(5006) << "encData: " << encData << endl;
00920 
00921     //... then fill the dialog with the given data
00922     SnippetDlg dlg( mActionCollection, this, "SnippetDlg" );
00923     dlg.snippetName->clear();
00924     dlg.snippetText->setText(encData);
00925 
00926     /*fill the combobox with the names of all SnippetGroup entries*/
00927     for (SnippetItem *it=_list.first(); it; it=_list.next()) {
00928       if (dynamic_cast<SnippetGroup*>(it)) {
00929         dlg.cbGroup->insertItem(it->getName());
00930       }
00931     }
00932     dlg.cbGroup->setCurrentText(group->getName());
00933 
00934     if (dlg.exec() == QDialog::Accepted) {
00935       /* get the group that the user selected with the combobox */
00936       group = dynamic_cast<SnippetGroup*>(SnippetItem::findItemByName(dlg.cbGroup->currentText(), _list));
00937       _list.append( makeItem(group, dlg.snippetName->text(), dlg.snippetText->text(), dlg.keyButton->shortcut() ) );
00938     }
00939   }
00940 }
00941 
00942 void SnippetWidget::startDrag()
00943 {
00944     QString text = dynamic_cast<SnippetItem*>( currentItem() )->getText();
00945     QTextDrag *drag = new QTextDrag(text, this);
00946     drag->setSubtype("x-textsnippet");
00947     drag->drag();
00948 }
00949 
00950 void SnippetWidget::slotExecute()
00951 {
00952     slotExecuted(currentItem());
00953 }
00954 
00955 
00956 #include "snippetwidget.moc"
00957