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.
952 lines
31 KiB
952 lines
31 KiB
/* |
|
* File : snippet_widget.cpp |
|
* |
|
* Author: Robert Gruber <rgruber@users.sourceforge.net> |
|
* |
|
* Copyright: See COPYING file that comes with this distribution |
|
*/ |
|
|
|
#include <kurl.h> |
|
#include <kdebug.h> |
|
#include <klocale.h> |
|
#include <qlayout.h> |
|
#include <kpushbutton.h> |
|
#include <klistview.h> |
|
#include <qheader.h> |
|
#include <klineedit.h> |
|
#include <ktextedit.h> |
|
#include <kmessagebox.h> |
|
#include <kconfig.h> |
|
#include <qtooltip.h> |
|
#include <kpopupmenu.h> |
|
#include <qregexp.h> |
|
#include <qinputdialog.h> |
|
#include <qlabel.h> |
|
#include <qcheckbox.h> |
|
#include <qwhatsthis.h> |
|
#include <qdragobject.h> |
|
#include <qtimer.h> |
|
#include <kcombobox.h> |
|
#include <kmedit.h> |
|
#include <kiconloader.h> |
|
#include <kshortcut.h> |
|
#include <kaction.h> |
|
#include <kkeybutton.h> |
|
|
|
#include "snippetdlg.h" |
|
#include "snippetitem.h" |
|
#include "snippet_widget.h" |
|
|
|
#include <cassert> |
|
|
|
SnippetWidget::SnippetWidget(KMEdit* editor, KActionCollection* actionCollection, QWidget* parent) |
|
: KListView(parent, "snippet widget"), QToolTip( viewport() ), |
|
mEditor( editor ), mActionCollection( actionCollection ) |
|
{ |
|
// init the QPtrList |
|
_list.setAutoDelete(TRUE); |
|
|
|
// init the KListView |
|
setSorting( -1 ); |
|
addColumn( "" ); |
|
setFullWidth(true); |
|
header()->hide(); |
|
setAcceptDrops(true); |
|
setDragEnabled(true); |
|
setDropVisualizer(false); |
|
setRootIsDecorated(true); |
|
|
|
//connect the signals |
|
connect( this, SIGNAL( contextMenuRequested ( QListViewItem *, const QPoint & , int ) ), |
|
this, SLOT( showPopupMenu(QListViewItem *, const QPoint & , int ) ) ); |
|
|
|
connect( this, SIGNAL( doubleClicked (QListViewItem *) ), |
|
this, SLOT( slotEdit( QListViewItem *) ) ); |
|
connect( this, SIGNAL( returnPressed (QListViewItem *) ), |
|
this, SLOT( slotExecuted( QListViewItem *) ) ); |
|
|
|
connect( this, SIGNAL( dropped(QDropEvent *, QListViewItem *) ), |
|
this, SLOT( slotDropped(QDropEvent *, QListViewItem *) ) ); |
|
|
|
connect( editor, SIGNAL( insertSnippet() ), this, SLOT( slotExecute() )); |
|
|
|
_cfg = 0; |
|
|
|
QTimer::singleShot(0, this, SLOT(initConfig())); |
|
} |
|
|
|
SnippetWidget::~SnippetWidget() |
|
{ |
|
writeConfig(); |
|
delete _cfg; |
|
|
|
/* We need to delete the child items before the parent items |
|
otherwise KDevelop would crash on exiting */ |
|
SnippetItem * item; |
|
while (_list.count() > 0) { |
|
for (item=_list.first(); item; item=_list.next()) { |
|
if (item->childCount() == 0) |
|
_list.remove(item); |
|
} |
|
} |
|
} |
|
|
|
|
|
/*! |
|
\fn SnippetWidget::slotAdd() |
|
Opens the dialog to add a snippet |
|
*/ |
|
void SnippetWidget::slotAdd() |
|
{ |
|
//kdDebug(5006) << "Ender slotAdd()" << endl; |
|
SnippetDlg dlg( mActionCollection, this, "SnippetDlg"); |
|
|
|
/*check if the user clicked a SnippetGroup |
|
If not, we set the group variable to the SnippetGroup |
|
which the selected item is a child of*/ |
|
SnippetGroup * group = dynamic_cast<SnippetGroup*>(selectedItem()); |
|
if ( !group && selectedItem() ) |
|
group = dynamic_cast<SnippetGroup*>(selectedItem()->parent()); |
|
|
|
/* still no group, let's make a default one */ |
|
if (!group ) { |
|
if ( _list.isEmpty() ) { |
|
group = new SnippetGroup(this, i18n("General"), SnippetGroup::getMaxId() ); |
|
_list.append( group ); |
|
} else { |
|
group = dynamic_cast<SnippetGroup*>( _list.first() ); |
|
} |
|
} |
|
assert( group ); |
|
|
|
/*fill the combobox with the names of all SnippetGroup entries*/ |
|
for (SnippetItem *it=_list.first(); it; it=_list.next()) { |
|
if (dynamic_cast<SnippetGroup*>(it)) { |
|
dlg.cbGroup->insertItem(it->getName()); |
|
} |
|
} |
|
dlg.cbGroup->setCurrentText(group->getName()); |
|
|
|
if (dlg.exec() == QDialog::Accepted) { |
|
group = dynamic_cast<SnippetGroup*>(SnippetItem::findItemByName(dlg.cbGroup->currentText(), _list)); |
|
_list.append( makeItem( group, dlg.snippetName->text(), dlg.snippetText->text(), dlg.keyButton->shortcut() ) ); |
|
} |
|
} |
|
|
|
/*! |
|
\fn SnippetWidget::makeItem( SnippetItem* parent, const QString& name, const QString& text ) |
|
Helper factory method. |
|
*/ |
|
SnippetItem* SnippetWidget::makeItem( SnippetItem* parent, const QString& name, const QString& text, const KShortcut& shortcut ) |
|
{ |
|
SnippetItem * item = new SnippetItem(parent, name, text); |
|
const QString actionName = i18n("Snippet %1").arg(name); |
|
const QString normalizedName = QString(actionName).replace(" ", "_"); |
|
if ( !mActionCollection->action(normalizedName.utf8() ) ) { |
|
KAction * action = new KAction( actionName, shortcut, item, |
|
SLOT( slotExecute() ), mActionCollection, |
|
normalizedName.utf8() ); |
|
item->setAction(action); |
|
connect( item, SIGNAL( execute( QListViewItem* ) ), |
|
this, SLOT( slotExecuted( QListViewItem* ) ) ); |
|
} |
|
return item; |
|
} |
|
|
|
/*! |
|
\fn SnippetWidget::slotAddGroup() |
|
Opens the didalog to add a snippet |
|
*/ |
|
void SnippetWidget::slotAddGroup() |
|
{ |
|
//kdDebug(5006) << "Ender slotAddGroup()" << endl; |
|
SnippetDlg dlg( mActionCollection, this, "SnippetDlg"); |
|
dlg.setShowShortcut( false ); |
|
dlg.snippetText->setEnabled(false); |
|
dlg.snippetText->setText("GROUP"); |
|
dlg.setCaption(i18n("Add Group")); |
|
dlg.cbGroup->insertItem(i18n("All")); |
|
dlg.cbGroup->setCurrentText(i18n("All")); |
|
|
|
if (dlg.exec() == QDialog::Accepted) { |
|
_list.append( new SnippetGroup(this, dlg.snippetName->text(), SnippetGroup::getMaxId() ) ); |
|
} |
|
} |
|
|
|
|
|
/*! |
|
\fn SnippetWidget::slotRemove() |
|
Removes the selected snippet |
|
*/ |
|
void SnippetWidget::slotRemove() |
|
{ |
|
//get current data |
|
QListViewItem * item = currentItem(); |
|
SnippetItem *snip = dynamic_cast<SnippetItem*>( item ); |
|
SnippetGroup *group = dynamic_cast<SnippetGroup*>( item ); |
|
if (!snip) |
|
return; |
|
|
|
if (group) { |
|
if (group->childCount() > 0 && |
|
KMessageBox::warningContinueCancel(this, i18n("Do you really want to remove this group and all its snippets?"),QString::null,KStdGuiItem::del()) |
|
== KMessageBox::Cancel) |
|
return; |
|
|
|
SnippetItem *it=_list.first(); |
|
while ( it ) { |
|
if (it->getParent() == group->getId()) { |
|
SnippetItem *doomed = it; |
|
it = _list.next(); |
|
//kdDebug(5006) << "remove " << doomed->getName() << endl; |
|
_list.remove(doomed); |
|
} else { |
|
it = _list.next(); |
|
} |
|
} |
|
} |
|
|
|
//kdDebug(5006) << "remove " << snip->getName() << endl; |
|
_list.remove(snip); |
|
} |
|
|
|
|
|
|
|
/*! |
|
\fn SnippetWidget::slotEdit() |
|
Opens the dialog of editing the selected snippet |
|
*/ |
|
void SnippetWidget::slotEdit( QListViewItem* item ) |
|
{ |
|
if( item == 0 ) { |
|
item = currentItem(); |
|
} |
|
|
|
SnippetGroup *pGroup = dynamic_cast<SnippetGroup*>(item); |
|
SnippetItem *pSnippet = dynamic_cast<SnippetItem*>( item ); |
|
if (!pSnippet || pGroup) /*selected item must be a SnippetItem but MUST not be a SnippetGroup*/ |
|
return; |
|
|
|
//init the dialog |
|
SnippetDlg dlg( mActionCollection, this, "SnippetDlg"); |
|
dlg.snippetName->setText(pSnippet->getName()); |
|
dlg.snippetText->setText(pSnippet->getText()); |
|
dlg.keyButton->setShortcut( pSnippet->getAction()->shortcut(), false ); |
|
dlg.btnAdd->setText(i18n("&Apply")); |
|
|
|
dlg.setCaption(i18n("Edit Snippet")); |
|
/*fill the combobox with the names of all SnippetGroup entries*/ |
|
for (SnippetItem *it=_list.first(); it; it=_list.next()) { |
|
if (dynamic_cast<SnippetGroup*>(it)) { |
|
dlg.cbGroup->insertItem(it->getName()); |
|
} |
|
} |
|
dlg.cbGroup->setCurrentText(SnippetItem::findGroupById(pSnippet->getParent(), _list)->getName()); |
|
|
|
if (dlg.exec() == QDialog::Accepted) { |
|
//update the KListView and the SnippetItem |
|
item->setText( 0, dlg.snippetName->text() ); |
|
pSnippet->setName( dlg.snippetName->text() ); |
|
pSnippet->setText( dlg.snippetText->text() ); |
|
pSnippet->getAction()->setShortcut( dlg.keyButton->shortcut()); |
|
|
|
/* if the user changed the parent we need to move the snippet */ |
|
if ( SnippetItem::findGroupById(pSnippet->getParent(), _list)->getName() != dlg.cbGroup->currentText() ) { |
|
SnippetGroup * newGroup = dynamic_cast<SnippetGroup*>(SnippetItem::findItemByName(dlg.cbGroup->currentText(), _list)); |
|
pSnippet->parent()->takeItem(pSnippet); |
|
newGroup->insertItem(pSnippet); |
|
pSnippet->resetParent(); |
|
} |
|
|
|
setSelected(item, TRUE); |
|
} |
|
} |
|
|
|
/*! |
|
\fn SnippetWidget::slotEditGroup() |
|
Opens the dialog of editing the selected snippet-group |
|
*/ |
|
void SnippetWidget::slotEditGroup() |
|
{ |
|
//get current data |
|
QListViewItem * item = currentItem(); |
|
|
|
SnippetGroup *pGroup = dynamic_cast<SnippetGroup*>( item ); |
|
if (!pGroup) /*selected item MUST be a SnippetGroup*/ |
|
return; |
|
|
|
//init the dialog |
|
SnippetDlg dlg( mActionCollection, this, "SnippetDlg" ); |
|
dlg.setShowShortcut( false ); |
|
dlg.snippetName->setText(pGroup->getName()); |
|
dlg.snippetText->setText(pGroup->getText()); |
|
dlg.btnAdd->setText(i18n("&Apply")); |
|
dlg.snippetText->setEnabled(FALSE); |
|
dlg.setCaption(i18n("Edit Group")); |
|
dlg.cbGroup->insertItem(i18n("All")); |
|
|
|
if (dlg.exec() == QDialog::Accepted) { |
|
//update the KListView and the SnippetGroup |
|
item->setText( 0, dlg.snippetName->text() ); |
|
pGroup->setName( dlg.snippetName->text() ); |
|
|
|
setSelected(item, TRUE); |
|
} |
|
} |
|
|
|
void SnippetWidget::slotExecuted(QListViewItem * item) |
|
{ |
|
if( item == 0 ) |
|
{ |
|
item = currentItem(); |
|
} |
|
|
|
SnippetItem *pSnippet = dynamic_cast<SnippetItem*>( item ); |
|
if (!pSnippet || dynamic_cast<SnippetGroup*>(item)) |
|
return; |
|
|
|
//process variables if any, then insert into the active view |
|
insertIntoActiveView( parseText(pSnippet->getText(), _SnippetConfig.getDelimiter()) ); |
|
} |
|
|
|
|
|
/*! |
|
\fn SnippetWidget::insertIntoActiveView(QString text) |
|
Inserts the parameter text into the activ view |
|
*/ |
|
void SnippetWidget::insertIntoActiveView( const QString &text ) |
|
{ |
|
mEditor->insert( text ); |
|
} |
|
|
|
|
|
/*! |
|
\fn SnippetWidget::writeConfig() |
|
Write the cofig file |
|
*/ |
|
void SnippetWidget::writeConfig() |
|
{ |
|
if( !_cfg ) |
|
return; |
|
_cfg->deleteGroup("SnippetPart"); //this is neccessary otherwise delete entries will stay in list until |
|
//they get overwritten by a more recent entry |
|
_cfg->setGroup("SnippetPart"); |
|
|
|
QString strKeyName=""; |
|
QString strKeyText=""; |
|
QString strKeyId=""; |
|
|
|
int iSnipCount = 0; |
|
int iGroupCount = 0; |
|
|
|
SnippetItem* item=_list.first(); |
|
while ( item != 0) { |
|
|
|
//kdDebug(5006) << "-->ERROR " << item->getName() << endl; |
|
//kdDebug(5006) << "SnippetWidget::writeConfig() " << item->getName() << endl; |
|
SnippetGroup * group = dynamic_cast<SnippetGroup*>(item); |
|
if (group) { |
|
//kdDebug(5006) << "-->GROUP " << item->getName() << group->getId() << " " << iGroupCount<< endl; |
|
strKeyName=QString("snippetGroupName_%1").arg(iGroupCount); |
|
strKeyId=QString("snippetGroupId_%1").arg(iGroupCount); |
|
|
|
_cfg->writeEntry(strKeyName, group->getName()); |
|
_cfg->writeEntry(strKeyId, group->getId()); |
|
|
|
iGroupCount++; |
|
} else if (dynamic_cast<SnippetItem*>(item)) { |
|
//kdDebug(5006) << "-->ITEM " << item->getName() << item->getParent() << " " << iSnipCount << endl; |
|
strKeyName=QString("snippetName_%1").arg(iSnipCount); |
|
strKeyText=QString("snippetText_%1").arg(iSnipCount); |
|
strKeyId=QString("snippetParent_%1").arg(iSnipCount); |
|
|
|
_cfg->writeEntry(strKeyName, item->getName()); |
|
_cfg->writeEntry(strKeyText, item->getText()); |
|
_cfg->writeEntry(strKeyId, item->getParent()); |
|
|
|
KAction * action = item->getAction(); |
|
assert( action ); |
|
const KShortcut& sc = action->shortcut(); |
|
if (!sc.isNull() ) { |
|
_cfg->writeEntry( QString("snippetShortcut_%1").arg(iSnipCount), sc.toString() ); |
|
} |
|
iSnipCount++; |
|
} else { |
|
//kdDebug(5006) << "-->ERROR " << item->getName() << endl; |
|
} |
|
item = _list.next(); |
|
} |
|
_cfg->writeEntry("snippetCount", iSnipCount); |
|
_cfg->writeEntry("snippetGroupCount", iGroupCount); |
|
|
|
int iCount = 1; |
|
QMap<QString, QString>::Iterator it; |
|
for ( it = _mapSaved.begin(); it != _mapSaved.end(); ++it ) { //write the saved variable values |
|
if (it.data().length()<=0) continue; //is the saved value has no length -> no need to save it |
|
|
|
strKeyName=QString("snippetSavedName_%1").arg(iCount); |
|
strKeyText=QString("snippetSavedVal_%1").arg(iCount); |
|
|
|
_cfg->writeEntry(strKeyName, it.key()); |
|
_cfg->writeEntry(strKeyText, it.data()); |
|
|
|
iCount++; |
|
} |
|
_cfg->writeEntry("snippetSavedCount", iCount-1); |
|
|
|
|
|
_cfg->writeEntry( "snippetDelimiter", _SnippetConfig.getDelimiter() ); |
|
_cfg->writeEntry( "snippetVarInput", _SnippetConfig.getInputMethod() ); |
|
_cfg->writeEntry( "snippetToolTips", _SnippetConfig.useToolTips() ); |
|
_cfg->writeEntry( "snippetGroupAutoOpen", _SnippetConfig.getAutoOpenGroups() ); |
|
|
|
_cfg->writeEntry("snippetSingleRect", _SnippetConfig.getSingleRect() ); |
|
_cfg->writeEntry("snippetMultiRect", _SnippetConfig.getMultiRect() ); |
|
|
|
_cfg->sync(); |
|
} |
|
|
|
/*! |
|
\fn SnippetWidget::initConfig() |
|
Initial read the cofig file |
|
*/ |
|
void SnippetWidget::initConfig() |
|
{ |
|
if (_cfg == NULL) |
|
_cfg = new KConfig("kmailsnippetrc", false, false); |
|
|
|
_cfg->setGroup("SnippetPart"); |
|
|
|
QString strKeyName=""; |
|
QString strKeyText=""; |
|
QString strKeyId=""; |
|
SnippetItem *item; |
|
SnippetGroup *group; |
|
|
|
//kdDebug(5006) << "SnippetWidget::initConfig() " << endl; |
|
|
|
//if entry doesn't get found, this will return -1 which we will need a bit later |
|
int iCount = _cfg->readNumEntry("snippetGroupCount", -1); |
|
|
|
for ( int i=0; i<iCount; i++) { //read the group-list |
|
strKeyName=QString("snippetGroupName_%1").arg(i); |
|
strKeyId=QString("snippetGroupId_%1").arg(i); |
|
|
|
QString strNameVal=""; |
|
int iIdVal=-1; |
|
|
|
strNameVal = _cfg->readEntry(strKeyName, ""); |
|
iIdVal = _cfg->readNumEntry(strKeyId, -1); |
|
//kdDebug(5006) << "Read group " << " " << iIdVal << endl; |
|
|
|
if (strNameVal != "" && iIdVal != -1) { |
|
group = new SnippetGroup(this, strNameVal, iIdVal); |
|
//kdDebug(5006) << "Created group " << group->getName() << " " << group->getId() << endl; |
|
_list.append(group); |
|
} |
|
} |
|
|
|
/* Check if the snippetGroupCount property has been found |
|
if iCount is -1 this means, that the user has his snippets |
|
stored without groups. Therefore we will call the |
|
initConfigOldVersion() function below */ |
|
// should not happen since this function has been removed |
|
|
|
if (iCount != -1) { |
|
iCount = _cfg->readNumEntry("snippetCount", 0); |
|
for ( int i=0; i<iCount; i++) { //read the snippet-list |
|
strKeyName=QString("snippetName_%1").arg(i); |
|
strKeyText=QString("snippetText_%1").arg(i); |
|
strKeyId=QString("snippetParent_%1").arg(i); |
|
|
|
QString strNameVal=""; |
|
QString strTextVal=""; |
|
int iParentVal = -1; |
|
|
|
strNameVal = _cfg->readEntry(strKeyName, ""); |
|
strTextVal = _cfg->readEntry(strKeyText, ""); |
|
iParentVal = _cfg->readNumEntry(strKeyId, -1); |
|
//kdDebug(5006) << "Read item " << strNameVal << " " << iParentVal << endl; |
|
|
|
if (strNameVal != "" && strTextVal != "" && iParentVal != -1) { |
|
KShortcut shortcut( _cfg->readEntry( QString("snippetShortcut_%1").arg(i), QString() ) ); |
|
item = makeItem( SnippetItem::findGroupById(iParentVal, _list), strNameVal, strTextVal, shortcut ); |
|
//kdDebug(5006) << "Created item " << item->getName() << " " << item->getParent() << endl; |
|
_list.append(item); |
|
} |
|
} |
|
} else { |
|
//kdDebug() << "iCount is not -1"; |
|
} |
|
|
|
iCount = _cfg->readNumEntry("snippetSavedCount", 0); |
|
|
|
for ( int i=1; i<=iCount; i++) { //read the saved-values and store in QMap |
|
strKeyName=QString("snippetSavedName_%1").arg(i); |
|
strKeyText=QString("snippetSavedVal_%1").arg(i); |
|
|
|
QString strNameVal=""; |
|
QString strTextVal=""; |
|
|
|
strNameVal = _cfg->readEntry(strKeyName, ""); |
|
strTextVal = _cfg->readEntry(strKeyText, ""); |
|
|
|
if (strNameVal != "" && strTextVal != "") { |
|
_mapSaved[strNameVal] = strTextVal; |
|
} |
|
} |
|
|
|
|
|
_SnippetConfig.setDelimiter( _cfg->readEntry("snippetDelimiter", "$") ); |
|
_SnippetConfig.setInputMethod( _cfg->readNumEntry("snippetVarInput", 0) ); |
|
_SnippetConfig.setToolTips( _cfg->readBoolEntry("snippetToolTips", true) ); |
|
_SnippetConfig.setAutoOpenGroups( _cfg->readNumEntry("snippetGroupAutoOpen", 1) ); |
|
|
|
_SnippetConfig.setSingleRect( _cfg->readRectEntry("snippetSingleRect", 0L) ); |
|
_SnippetConfig.setMultiRect( _cfg->readRectEntry("snippetMultiRect", 0L) ); |
|
} |
|
|
|
/*! |
|
\fn SnippetWidget::maybeTip( const QPoint & p ) |
|
Shows the Snippet-Text as ToolTip |
|
*/ |
|
void SnippetWidget::maybeTip( const QPoint & p ) |
|
{ |
|
SnippetItem * item = dynamic_cast<SnippetItem*>( itemAt( p ) ); |
|
if (!item) |
|
return; |
|
|
|
QRect r = itemRect( item ); |
|
|
|
if (r.isValid() && |
|
_SnippetConfig.useToolTips() ) |
|
{ |
|
tip( r, item->getText() ); //show the snippet's text |
|
} |
|
} |
|
|
|
/*! |
|
\fn SnippetWidget::showPopupMenu( QListViewItem * item, const QPoint & p, int ) |
|
Shows the Popup-Menu depending item is a valid pointer |
|
*/ |
|
void SnippetWidget::showPopupMenu( QListViewItem * item, const QPoint & p, int ) |
|
{ |
|
KPopupMenu popup; |
|
|
|
SnippetItem * selectedItem = static_cast<SnippetItem *>(item); |
|
if ( item ) { |
|
popup.insertTitle( selectedItem->getName() ); |
|
if (dynamic_cast<SnippetGroup*>(item)) { |
|
popup.insertItem( i18n("Edit &group..."), this, SLOT( slotEditGroup() ) ); |
|
} else { |
|
popup.insertItem( SmallIconSet("editpaste"), i18n("&Paste"), this, SLOT( slotExecuted() ) ); |
|
popup.insertItem( SmallIconSet("edit"), i18n("&Edit..."), this, SLOT( slotEdit() ) ); |
|
} |
|
popup.insertItem( SmallIconSet("editdelete"), i18n("&Remove"), this, SLOT( slotRemove() ) ); |
|
popup.insertSeparator(); |
|
} else { |
|
popup.insertTitle(i18n("Text Snippets")); |
|
} |
|
popup.insertItem( i18n("&Add Snippet..."), this, SLOT( slotAdd() ) ); |
|
popup.insertItem( i18n("Add G&roup..."), this, SLOT( slotAddGroup() ) ); |
|
|
|
popup.exec(p); |
|
} |
|
|
|
|
|
// fn SnippetWidget::parseText(QString text, QString del) |
|
/*! |
|
This function is used to parse the given QString for variables. If found the user will be prompted |
|
for a replacement value. It returns the string text with all replacements made |
|
*/ |
|
QString SnippetWidget::parseText(QString text, QString del) |
|
{ |
|
QString str = text; |
|
QString strName = ""; |
|
QString strNew = ""; |
|
QString strMsg=""; |
|
int iFound = -1; |
|
int iEnd = -1; |
|
QMap<QString, QString> mapVar; |
|
int iInMeth = _SnippetConfig.getInputMethod(); |
|
QRect rSingle = _SnippetConfig.getSingleRect(); |
|
QRect rMulti = _SnippetConfig.getMultiRect(); |
|
|
|
do { |
|
iFound = text.find(QRegExp("\\"+del+"[A-Za-z-_0-9\\s]*\\"+del), iEnd+1); //find the next variable by this QRegExp |
|
if (iFound >= 0) { |
|
iEnd = text.find(del, iFound+1)+1; |
|
strName = text.mid(iFound, iEnd-iFound); |
|
|
|
if ( strName != del+del ) { //if not doubel-delimiter |
|
if (iInMeth == 0) { //if input-method "single" is selected |
|
if ( mapVar[strName].length() <= 0 ) { // and not already in map |
|
strMsg=i18n("Please enter the value for <b>%1</b>:").arg(strName); |
|
strNew = showSingleVarDialog( strName, &_mapSaved, rSingle ); |
|
if (strNew=="") |
|
return ""; //user clicked Cancle |
|
} else { |
|
continue; //we have already handled this variable |
|
} |
|
} else { |
|
strNew = ""; //for inputmode "multi" just reset new valaue |
|
} |
|
} else { |
|
strNew = del; //if double-delimiter -> replace by single character |
|
} |
|
|
|
if (iInMeth == 0) { //if input-method "single" is selected |
|
str.replace(strName, strNew); |
|
} |
|
|
|
mapVar[strName] = strNew; |
|
} |
|
} while (iFound != -1); |
|
|
|
if (iInMeth == 1) { //check config, if input-method "multi" is selected |
|
int w, bh, oh; |
|
w = rMulti.width(); |
|
bh = rMulti.height(); |
|
oh = rMulti.top(); |
|
if (showMultiVarDialog( &mapVar, &_mapSaved, w, bh, oh )) { //generate and show the dialog |
|
QMap<QString, QString>::Iterator it; |
|
for ( it = mapVar.begin(); it != mapVar.end(); ++it ) { //walk through the map and do the replacement |
|
str.replace(it.key(), it.data()); |
|
} |
|
} else { |
|
return ""; |
|
} |
|
|
|
rMulti.setWidth(w); //this is a hack to save the dialog's dimensions in only one QRect |
|
rMulti.setHeight(bh); |
|
rMulti.setTop(oh); |
|
rMulti.setLeft(0); |
|
_SnippetConfig.setMultiRect(rMulti); |
|
} |
|
|
|
_SnippetConfig.setSingleRect(rSingle); |
|
|
|
return str; |
|
} |
|
|
|
|
|
// fn SnippetWidget::showMultiVarDialog() |
|
/*! |
|
This function constructs a dialog which contains a label and a linedit for every |
|
variable that is stored in the given map except the double-delimiter entry |
|
It return true if everything was ok and false if the user hit cancel |
|
*/ |
|
bool SnippetWidget::showMultiVarDialog(QMap<QString, QString> * map, QMap<QString, QString> * mapSave, |
|
int & iWidth, int & iBasicHeight, int & iOneHeight) |
|
{ |
|
//if no var -> no need to show |
|
if (map->count() == 0) |
|
return true; |
|
|
|
//if only var is the double-delimiter -> no need to show |
|
QMap<QString, QString>::Iterator it = map->begin(); |
|
if ( map->count() == 1 && it.data()==_SnippetConfig.getDelimiter()+_SnippetConfig.getDelimiter() ) |
|
return true; |
|
|
|
QMap<QString, KTextEdit *> mapVar2Te; //this map will help keeping track which TEXTEDIT goes with which variable |
|
QMap<QString, QCheckBox *> mapVar2Cb; //this map will help keeping track which CHECKBOX goes with which variable |
|
|
|
// --BEGIN-- building a dynamic dialog |
|
QDialog dlg(this); |
|
dlg.setCaption(i18n("Enter Values for Variables")); |
|
|
|
QGridLayout * layout = new QGridLayout( &dlg, 1, 1, 11, 6, "layout"); |
|
QGridLayout * layoutTop = new QGridLayout( 0, 1, 1, 0, 6, "layoutTop"); |
|
QGridLayout * layoutVar = new QGridLayout( 0, 1, 1, 0, 6, "layoutVar"); |
|
QGridLayout * layoutBtn = new QGridLayout( 0, 1, 1, 0, 6, "layoutBtn"); |
|
|
|
KTextEdit *te = NULL; |
|
QLabel * labTop = NULL; |
|
QCheckBox * cb = NULL; |
|
|
|
labTop = new QLabel( &dlg, "label" ); |
|
labTop->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, |
|
labTop->sizePolicy().hasHeightForWidth() ) ); |
|
labTop->setText(i18n("Enter the replacement values for these variables:")); |
|
layoutTop->addWidget(labTop, 0, 0); |
|
layout->addMultiCellLayout( layoutTop, 0, 0, 0, 1 ); |
|
|
|
|
|
int i = 0; //walk through the variable map and add |
|
for ( it = map->begin(); it != map->end(); ++it ) { //a checkbox, a lable and a lineedit to the main layout |
|
if (it.key() == _SnippetConfig.getDelimiter() + _SnippetConfig.getDelimiter()) |
|
continue; |
|
|
|
cb = new QCheckBox( &dlg, "cbVar" ); |
|
cb->setChecked( FALSE ); |
|
cb->setText(it.key()); |
|
layoutVar->addWidget( cb, i ,0, Qt::AlignTop ); |
|
|
|
te = new KTextEdit( &dlg, "teVar" ); |
|
layoutVar->addWidget( te, i, 1, Qt::AlignTop ); |
|
|
|
if ((*mapSave)[it.key()].length() > 0) { |
|
cb->setChecked( TRUE ); |
|
te->setText((*mapSave)[it.key()]); |
|
} |
|
|
|
mapVar2Te[it.key()] = te; |
|
mapVar2Cb[it.key()] = cb; |
|
|
|
QToolTip::add( cb, i18n("Enable this to save the value entered to the right as the default value for this variable") ); |
|
QWhatsThis::add( cb, i18n("If you enable this option, the value entered to the right will be saved. " |
|
"If you use the same variable later, even in another snippet, the value entered to the right " |
|
"will be the default value for that variable.") ); |
|
|
|
i++; |
|
} |
|
layout->addMultiCellLayout( layoutVar, 1, 1, 0, 1 ); |
|
|
|
KPushButton * btn1 = new KPushButton( KStdGuiItem::cancel(), &dlg, "pushButton1" ); |
|
btn1->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, |
|
btn1->sizePolicy().hasHeightForWidth() ) ); |
|
layoutBtn->addWidget( btn1, 0, 0 ); |
|
|
|
KPushButton * btn2 = new KPushButton( KStdGuiItem::apply(), &dlg, "pushButton2" ); |
|
btn2->setDefault( TRUE ); |
|
btn2->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, |
|
btn2->sizePolicy().hasHeightForWidth() ) ); |
|
layoutBtn->addWidget( btn2, 0, 1 ); |
|
|
|
layout->addMultiCellLayout( layoutBtn, 2, 2, 0, 1 ); |
|
// --END-- building a dynamic dialog |
|
|
|
//connect the buttons to the QDialog default slots |
|
connect(btn1, SIGNAL(clicked()), &dlg, SLOT(reject()) ); |
|
connect(btn2, SIGNAL(clicked()), &dlg, SLOT(accept()) ); |
|
|
|
//prepare to execute the dialog |
|
bool bReturn = false; |
|
//resize the textedits |
|
if (iWidth > 1) { |
|
QRect r = dlg.geometry(); |
|
r.setHeight(iBasicHeight + iOneHeight*mapVar2Te.count()); |
|
r.setWidth(iWidth); |
|
dlg.setGeometry(r); |
|
} |
|
if ( i > 0 && // only if there are any variables |
|
dlg.exec() == QDialog::Accepted ) { |
|
|
|
QMap<QString, KTextEdit *>::Iterator it2; |
|
for ( it2 = mapVar2Te.begin(); it2 != mapVar2Te.end(); ++it2 ) { |
|
if (it2.key() == _SnippetConfig.getDelimiter() + _SnippetConfig.getDelimiter()) |
|
continue; |
|
(*map)[it2.key()] = it2.data()->text(); //copy the entered values back to the given map |
|
|
|
if (mapVar2Cb[it2.key()]->isChecked()) //if the checkbox is on; save the values for later |
|
(*mapSave)[it2.key()] = it2.data()->text(); |
|
else |
|
(*mapSave).erase(it2.key()); |
|
} |
|
bReturn = true; |
|
|
|
iBasicHeight = dlg.geometry().height() - layoutVar->geometry().height(); |
|
iOneHeight = layoutVar->geometry().height() / mapVar2Te.count(); |
|
iWidth = dlg.geometry().width(); |
|
} |
|
|
|
//do some cleanup |
|
QMap<QString, KTextEdit *>::Iterator it1; |
|
for (it1 = mapVar2Te.begin(); it1 != mapVar2Te.end(); ++it1) |
|
delete it1.data(); |
|
mapVar2Te.clear(); |
|
QMap<QString, QCheckBox *>::Iterator it2; |
|
for (it2 = mapVar2Cb.begin(); it2 != mapVar2Cb.end(); ++it2) |
|
delete it2.data(); |
|
mapVar2Cb.clear(); |
|
delete layoutTop; |
|
delete layoutVar; |
|
delete layoutBtn; |
|
delete layout; |
|
|
|
if (i==0) //if nothing happened this means, that there are no variables to translate |
|
return true; //.. so just return OK |
|
|
|
return bReturn; |
|
// return true; |
|
} |
|
|
|
|
|
// fn SnippetWidget::showSingleVarDialog(QString var, QMap<QString, QString> * mapSave) |
|
/*! |
|
This function constructs a dialog which contains a label and a linedit for the given variable |
|
It return either the entered value or an empty string if the user hit cancel |
|
*/ |
|
QString SnippetWidget::showSingleVarDialog(QString var, QMap<QString, QString> * mapSave, QRect & dlgSize) |
|
{ |
|
// --BEGIN-- building a dynamic dialog |
|
QDialog dlg(this); |
|
dlg.setCaption(i18n("Enter Values for Variables")); |
|
|
|
QGridLayout * layout = new QGridLayout( &dlg, 1, 1, 11, 6, "layout"); |
|
QGridLayout * layoutTop = new QGridLayout( 0, 1, 1, 0, 6, "layoutTop"); |
|
QGridLayout * layoutVar = new QGridLayout( 0, 1, 1, 0, 6, "layoutVar"); |
|
QGridLayout * layoutBtn = new QGridLayout( 0, 2, 1, 0, 6, "layoutBtn"); |
|
|
|
KTextEdit *te = NULL; |
|
QLabel * labTop = NULL; |
|
QCheckBox * cb = NULL; |
|
|
|
labTop = new QLabel( &dlg, "label" ); |
|
layoutTop->addWidget(labTop, 0, 0); |
|
labTop->setText(i18n("Enter the replacement values for %1:").arg( var )); |
|
layout->addMultiCellLayout( layoutTop, 0, 0, 0, 1 ); |
|
|
|
|
|
cb = new QCheckBox( &dlg, "cbVar" ); |
|
cb->setChecked( FALSE ); |
|
cb->setText(i18n( "Make value &default" )); |
|
|
|
te = new KTextEdit( &dlg, "teVar" ); |
|
layoutVar->addWidget( te, 0, 1, Qt::AlignTop); |
|
layoutVar->addWidget( cb, 1, 1, Qt::AlignTop); |
|
if ((*mapSave)[var].length() > 0) { |
|
cb->setChecked( TRUE ); |
|
te->setText((*mapSave)[var]); |
|
} |
|
|
|
QToolTip::add( cb, i18n("Enable this to save the value entered to the right as the default value for this variable") ); |
|
QWhatsThis::add( cb, i18n("If you enable this option, the value entered to the right will be saved. " |
|
"If you use the same variable later, even in another snippet, the value entered to the right " |
|
"will be the default value for that variable.") ); |
|
|
|
layout->addMultiCellLayout( layoutVar, 1, 1, 0, 1 ); |
|
|
|
KPushButton * btn1 = new KPushButton( KStdGuiItem::cancel(), &dlg, "pushButton1" ); |
|
layoutBtn->addWidget( btn1, 0, 0 ); |
|
|
|
KPushButton * btn2 = new KPushButton( KStdGuiItem::apply(), &dlg, "pushButton2" ); |
|
btn2->setDefault( TRUE ); |
|
layoutBtn->addWidget( btn2, 0, 1 ); |
|
|
|
layout->addMultiCellLayout( layoutBtn, 2, 2, 0, 1 ); |
|
te->setFocus(); |
|
// --END-- building a dynamic dialog |
|
|
|
//connect the buttons to the QDialog default slots |
|
connect(btn1, SIGNAL(clicked()), &dlg, SLOT(reject()) ); |
|
connect(btn2, SIGNAL(clicked()), &dlg, SLOT(accept()) ); |
|
|
|
//execute the dialog |
|
QString strReturn = ""; |
|
if (dlgSize.isValid()) |
|
dlg.setGeometry(dlgSize); |
|
if ( dlg.exec() == QDialog::Accepted ) { |
|
if (cb->isChecked()) //if the checkbox is on; save the values for later |
|
(*mapSave)[var] = te->text(); |
|
else |
|
(*mapSave).erase(var); |
|
|
|
strReturn = te->text(); //copy the entered values back the the given map |
|
|
|
dlgSize = dlg.geometry(); |
|
} |
|
|
|
//do some cleanup |
|
delete cb; |
|
delete te; |
|
delete labTop; |
|
delete btn1; |
|
delete btn2; |
|
delete layoutTop; |
|
delete layoutVar; |
|
delete layoutBtn; |
|
delete layout; |
|
|
|
return strReturn; |
|
} |
|
|
|
// fn SnippetWidget::acceptDrag (QDropEvent *event) const |
|
/*! |
|
Reimplementation from KListView. |
|
Check here if the data the user is about to drop fits our restrictions. |
|
We only accept dropps of plaintext, because from the dropped text |
|
we will create a snippet. |
|
*/ |
|
bool SnippetWidget::acceptDrag (QDropEvent *event) const |
|
{ |
|
//kdDebug(5006) << "Format: " << event->format() << "" << event->pos() << endl; |
|
|
|
QListViewItem * item = itemAt(event->pos()); |
|
|
|
if (item && |
|
QString(event->format()).startsWith("text/plain") && |
|
static_cast<SnippetWidget *>(event->source()) != this) { |
|
///kdDebug(5006) << "returning TRUE " << endl; |
|
return TRUE; |
|
} else if(item && |
|
QString(event->format()).startsWith("x-kmailsnippet") && |
|
static_cast<SnippetWidget *>(event->source()) != this) |
|
{ |
|
//kdDebug(5006) << "returning TRUE " << endl; |
|
return TRUE; |
|
} else { |
|
//kdDebug(5006) << "returning FALSE" << endl; |
|
event->acceptAction(FALSE); |
|
return FALSE; |
|
} |
|
} |
|
|
|
// fn SnippetWidget::slotDropped(QDropEvent *e, QListViewItem *after) |
|
/*! |
|
This slot is connected to the dropped signal. |
|
If it is emitted, we need to construct a new snippet entry with |
|
the data given |
|
*/ |
|
void SnippetWidget::slotDropped(QDropEvent *e, QListViewItem *) |
|
{ |
|
QListViewItem * item2 = itemAt(e->pos()); |
|
|
|
SnippetGroup *group = dynamic_cast<SnippetGroup *>(item2); |
|
if (!group) |
|
group = dynamic_cast<SnippetGroup *>(item2->parent()); |
|
|
|
QCString dropped; |
|
QByteArray data = e->encodedData("text/plain"); |
|
if ( e->provides("text/plain") && data.size()>0 ) { |
|
//get the data from the event... |
|
QString encData(data.data()); |
|
//kdDebug(5006) << "encData: " << encData << endl; |
|
|
|
//... then fill the dialog with the given data |
|
SnippetDlg dlg( mActionCollection, this, "SnippetDlg" ); |
|
dlg.snippetName->clear(); |
|
dlg.snippetText->setText(encData); |
|
|
|
/*fill the combobox with the names of all SnippetGroup entries*/ |
|
for (SnippetItem *it=_list.first(); it; it=_list.next()) { |
|
if (dynamic_cast<SnippetGroup*>(it)) { |
|
dlg.cbGroup->insertItem(it->getName()); |
|
} |
|
} |
|
dlg.cbGroup->setCurrentText(group->getName()); |
|
|
|
if (dlg.exec() == QDialog::Accepted) { |
|
/* get the group that the user selected with the combobox */ |
|
group = dynamic_cast<SnippetGroup*>(SnippetItem::findItemByName(dlg.cbGroup->currentText(), _list)); |
|
_list.append( makeItem(group, dlg.snippetName->text(), dlg.snippetText->text(), dlg.keyButton->shortcut() ) ); |
|
} |
|
} |
|
} |
|
|
|
void SnippetWidget::startDrag() |
|
{ |
|
QString text = dynamic_cast<SnippetItem*>( currentItem() )->getText(); |
|
QTextDrag *drag = new QTextDrag(text, this); |
|
drag->setSubtype("x-textsnippet"); |
|
drag->drag(); |
|
} |
|
|
|
void SnippetWidget::slotExecute() |
|
{ |
|
slotExecuted(currentItem()); |
|
} |
|
|
|
|
|
#include "snippet_widget.moc" |
|
|
|
|