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.
754 lines
23 KiB
754 lines
23 KiB
/*************************************************************************** |
|
* snippet feature from kdevelop/plugins/snippet/ * |
|
* * |
|
* Copyright (C) 2007 by Robert Gruber * |
|
* rgruber@users.sourceforge.net * |
|
* * |
|
* 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 "snippetwidget.h" |
|
#include "snippetitem.h" |
|
#include "snippetdlg.h" |
|
|
|
#include <kdebug.h> |
|
#include <klocale.h> |
|
#include <kpushbutton.h> |
|
#include <kmessagebox.h> |
|
#include <ktexteditor/editor.h> |
|
#include <ktexteditor/view.h> |
|
#include <ktexteditor/document.h> |
|
#include <kconfig.h> |
|
#include <kmenu.h> |
|
#include <kcombobox.h> |
|
#include <kiconloader.h> |
|
#include <kshortcut.h> |
|
#include <kaction.h> |
|
#include <kactioncollection.h> |
|
#include <kkeysequencewidget.h> |
|
|
|
#include <qlayout.h> |
|
#include <qheaderview.h> |
|
#include <qtooltip.h> |
|
#include <qregexp.h> |
|
#include <qlabel.h> |
|
#include <qcheckbox.h> |
|
#include <qwhatsthis.h> |
|
#include <qdrag.h> |
|
#include <QContextMenuEvent> |
|
#include <qtimer.h> |
|
|
|
#include <cassert> |
|
|
|
SnippetWidget::SnippetWidget(KMeditor* editor, KActionCollection* actionCollection, QWidget* parent) |
|
: QTreeWidget( parent ), |
|
mEditor( editor ), |
|
mActionCollection( actionCollection ), |
|
_cfg( 0 ) |
|
{ |
|
setObjectName("snippet widget"); |
|
// init the QTreeWidget |
|
//setSorting( -1 ); |
|
//setFullWidth(true); |
|
header()->hide(); |
|
setAcceptDrops(true); |
|
setDragEnabled(true); |
|
//setDropVisualizer(false); |
|
setRootIsDecorated(true); |
|
setAlternatingRowColors( true ); |
|
|
|
connect( this, SIGNAL( itemActivated (QTreeWidgetItem *, int) ), |
|
this, SLOT( slotEdit( QTreeWidgetItem *) ) ); |
|
|
|
//### in KDE 3 the enter key used to insert the snippet in the editor |
|
// (slotExecute()) but the enterPressed signal is gone. It is also a problem |
|
// that pressing enter on an item and double-clicking is supposed have the |
|
// exact same effect. |
|
|
|
connect( editor, SIGNAL( insertSnippet() ), this, SLOT( slotExecute() )); |
|
|
|
QTimer::singleShot(0, this, SLOT(readConfig())); |
|
} |
|
|
|
SnippetWidget::~SnippetWidget() |
|
{ |
|
writeConfig(); |
|
delete _cfg; |
|
|
|
/* We need to delete the child items before the parent items |
|
otherwise KMail would crash on exiting */ |
|
int itemsLeft = _list.count(); |
|
while (itemsLeft) { |
|
for (int i = 0; i < _list.count(); i++) { |
|
if (_list[i] && _list[i]->childCount() == 0) { |
|
delete _list[i]; |
|
_list[i] = 0; |
|
itemsLeft--; |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
/*! |
|
Opens the dialog to add a snippet |
|
*/ |
|
void SnippetWidget::slotAdd() |
|
{ |
|
//kDebug(5006) << "Ender slotAdd()"; |
|
SnippetDlg dlg( mActionCollection, this ); |
|
dlg.setObjectName( "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*/ |
|
foreach (SnippetItem *item, _list) { |
|
if (dynamic_cast<SnippetGroup*>(item)) { |
|
dlg.cbGroup->addItem(item->getName()); |
|
} |
|
} |
|
dlg.cbGroup->setCurrentIndex( dlg.cbGroup->findText( 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->toPlainText(), |
|
dlg.keyWidget->keySequence() ) ); |
|
} |
|
} |
|
|
|
SnippetItem* SnippetWidget::makeItem( SnippetItem *parent, const QString &name, |
|
const QString &text, const QKeySequence &keySeq ) |
|
{ |
|
SnippetItem *item = new SnippetItem( parent, name, text ); |
|
const QString actionName = i18n( "Snippet %1", name ); |
|
const QString normalizedName = QString( actionName ).replace( " ", "_" ); |
|
item->setToolTip( 0, text ); |
|
if ( !mActionCollection->action( normalizedName ) ) { |
|
KAction *action = mActionCollection->addAction( normalizedName, |
|
item, SLOT( slotExecute() ) ); |
|
action->setText( actionName ); |
|
action->setShortcut( keySeq ); |
|
item->setAction( action ); |
|
connect( item, SIGNAL( execute( QTreeWidgetItem* ) ), |
|
this, SLOT( slotExecuted( QTreeWidgetItem* ) ) ); |
|
} |
|
return item; |
|
} |
|
|
|
/*! |
|
Opens the dialog to add a snippet |
|
*/ |
|
void SnippetWidget::slotAddGroup() |
|
{ |
|
//kDebug(5006) << "Ender slotAddGroup()"; |
|
SnippetDlg dlg( mActionCollection, this ); |
|
dlg.setObjectName( "SnippetDlg" ); |
|
dlg.setGroupMode( true ); |
|
dlg.setWindowTitle( i18n("Add Group") ); |
|
|
|
if (dlg.exec() == QDialog::Accepted) { |
|
_list.append( new SnippetGroup(this, dlg.snippetName->text(), SnippetGroup::getMaxId() ) ); |
|
} |
|
} |
|
|
|
|
|
/*! |
|
Removes the selected snippet |
|
*/ |
|
void SnippetWidget::slotRemove() |
|
{ |
|
//get current data |
|
QTreeWidgetItem * 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(), KStandardGuiItem::del()) |
|
== KMessageBox::Cancel) |
|
return; |
|
|
|
for ( int i = 0; i < _list.size(); i++ ) { |
|
if (_list[i]->getParent() == group->getId()) { |
|
delete _list.takeAt( i-- ); |
|
} |
|
} |
|
} |
|
|
|
//kDebug(5006) << "remove " << snip->getName(); |
|
int snipIndex = _list.indexOf(snip); |
|
if (snipIndex > -1) |
|
delete _list.takeAt(snipIndex); |
|
} |
|
|
|
|
|
|
|
/*! |
|
Opens the dialog of editing the selected snippet |
|
*/ |
|
void SnippetWidget::slotEdit( QTreeWidgetItem* 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 ); |
|
dlg.setObjectName( "SnippetDlg" ); |
|
dlg.snippetName->setText(pSnippet->getName()); |
|
dlg.snippetText->setText(pSnippet->getText()); |
|
dlg.btnAdd->setText(i18n("&Apply")); |
|
if ( pSnippet->getAction() ) |
|
dlg.keyWidget->setKeySequence( pSnippet->getAction()->shortcut().primary() ); |
|
|
|
dlg.setWindowTitle(i18n("Edit Snippet")); |
|
/*fill the combobox with the names of all SnippetGroup entries*/ |
|
foreach (SnippetItem *item, _list) { |
|
if (dynamic_cast<SnippetGroup*>(item)) { |
|
dlg.cbGroup->addItem( item->getName() ); |
|
} |
|
} |
|
QString parentGroupText = |
|
SnippetItem::findGroupById( pSnippet->getParent(), _list )->getName(); |
|
dlg.cbGroup->setCurrentIndex( dlg.cbGroup->findText( parentGroupText ) ); |
|
|
|
if (dlg.exec() == QDialog::Accepted) { |
|
//update the QListView and the SnippetItem |
|
item->setText( 0, dlg.snippetName->text() ); |
|
pSnippet->setName( dlg.snippetName->text() ); |
|
pSnippet->setText( dlg.snippetText->toPlainText() ); |
|
pSnippet->setToolTip( 0, pSnippet->getText() ); |
|
if ( pSnippet->getAction() ) |
|
pSnippet->getAction()->setShortcut( dlg.keyWidget->keySequence()); |
|
|
|
/* 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()->removeChild(pSnippet); |
|
newGroup->addChild(pSnippet); |
|
pSnippet->resetParent(); |
|
} |
|
|
|
item->setSelected( true ); |
|
} |
|
} |
|
|
|
/*! |
|
Opens the dialog of editing the selected snippet-group |
|
*/ |
|
void SnippetWidget::slotEditGroup() |
|
{ |
|
//get current data |
|
QTreeWidgetItem * item = currentItem(); |
|
|
|
SnippetGroup *pGroup = dynamic_cast<SnippetGroup*>( item ); |
|
if (!pGroup) /*selected item MUST be a SnippetGroup*/ |
|
return; |
|
|
|
//init the dialog |
|
SnippetDlg dlg( mActionCollection, this ); |
|
dlg.setObjectName( "SnippetDlg" ); |
|
dlg.setGroupMode( true ); |
|
dlg.snippetName->setText(pGroup->getName()); |
|
dlg.btnAdd->setText(i18n("&Apply")); |
|
dlg.setWindowTitle(i18n("Edit Group")); |
|
|
|
if (dlg.exec() == QDialog::Accepted) { |
|
//update the QListView and the SnippetGroup |
|
item->setText( 0, dlg.snippetName->text() ); |
|
pGroup->setName( dlg.snippetName->text() ); |
|
|
|
item->setSelected( true ); |
|
} |
|
} |
|
|
|
void SnippetWidget::slotExecuted(QTreeWidgetItem * 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() ) ); |
|
} |
|
|
|
|
|
/*! |
|
Inserts the parameter text into the active view |
|
*/ |
|
void SnippetWidget::insertIntoActiveView( const QString &text ) |
|
{ |
|
mEditor->insertPlainText( text ); |
|
} |
|
|
|
|
|
/*! |
|
Write the config file |
|
*/ |
|
void SnippetWidget::writeConfig() |
|
{ |
|
if( !_cfg ) |
|
return; |
|
_cfg->deleteGroup("SnippetPart"); //this is necessary otherwise delete entries will stay in list until |
|
//they get overwritten by a more recent entry |
|
KConfigGroup kcg = _cfg->group("SnippetPart"); |
|
|
|
QString strKeyName=""; |
|
QString strKeyText=""; |
|
QString strKeyId=""; |
|
|
|
int iSnipCount = 0; |
|
int iGroupCount = 0; |
|
|
|
foreach ( SnippetItem *const item, _list ) { //write the snippet-list |
|
SnippetGroup * group = dynamic_cast<SnippetGroup*>(item); |
|
if (group) { |
|
strKeyName=QString("snippetGroupName_%1").arg(iGroupCount); |
|
strKeyId=QString("snippetGroupId_%1").arg(iGroupCount); |
|
|
|
kcg.writeEntry(strKeyName, group->getName()); |
|
kcg.writeEntry(strKeyId, group->getId()); |
|
|
|
iGroupCount++; |
|
} else if (dynamic_cast<SnippetItem*>(item)) { |
|
strKeyName=QString("snippetName_%1").arg(iSnipCount); |
|
strKeyText=QString("snippetText_%1").arg(iSnipCount); |
|
strKeyId=QString("snippetParent_%1").arg(iSnipCount); |
|
|
|
kcg.writeEntry(strKeyName, item->getName()); |
|
kcg.writeEntry(strKeyText, item->getText()); |
|
kcg.writeEntry(strKeyId, item->getParent()); |
|
|
|
KAction * action = item->getAction(); |
|
if ( action ) { |
|
const KShortcut& sc = action->shortcut(); |
|
if (!sc.isEmpty() ) { |
|
kcg.writeEntry( QString("snippetShortcut_%1").arg(iSnipCount), sc.toString() ); |
|
} |
|
} |
|
iSnipCount++; |
|
} else { |
|
} |
|
} |
|
kcg.writeEntry("snippetCount", iSnipCount); |
|
kcg.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.value().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); |
|
|
|
kcg.writeEntry(strKeyName, it.key()); |
|
kcg.writeEntry(strKeyText, it.value()); |
|
|
|
iCount++; |
|
} |
|
kcg.writeEntry("snippetSavedCount", iCount-1); |
|
kcg.sync(); |
|
} |
|
|
|
/*! |
|
Initial read the config file |
|
*/ |
|
void SnippetWidget::readConfig() |
|
{ |
|
if (!_cfg) |
|
_cfg = new KConfig("kmailsnippetrc", KConfig::NoGlobals); |
|
|
|
KConfigGroup kcg = _cfg->group("SnippetPart"); |
|
|
|
QString strKeyName; |
|
QString strKeyText; |
|
QString strKeyId; |
|
SnippetItem *item; |
|
SnippetGroup *group; |
|
|
|
//kDebug(5006); |
|
|
|
//if entry doesn't get found, this will return -1 which we will need a bit later |
|
int iCount = kcg.readEntry("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 = kcg.readEntry(strKeyName, ""); |
|
iIdVal = kcg.readEntry(strKeyId, -1); |
|
//kDebug(5006) << "Read group " << " " << iIdVal; |
|
|
|
if ( !strNameVal.isEmpty() && iIdVal != -1 ) { |
|
group = new SnippetGroup(this, strNameVal, iIdVal); |
|
//kDebug(5006) << "Created group " << group->getName() << " " << group->getId(); |
|
_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. |
|
Should only happen with an empty config file. |
|
*/ |
|
|
|
if (iCount != -1) { |
|
iCount = kcg.readEntry("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 = kcg.readEntry(strKeyName, ""); |
|
strTextVal = kcg.readEntry(strKeyText, ""); |
|
iParentVal = kcg.readEntry(strKeyId, -1); |
|
//kDebug(5006) << "Read item " << strNameVal << " " << iParentVal; |
|
|
|
if ( !strNameVal.isEmpty() && !strTextVal.isEmpty() && iParentVal != -1) { |
|
KShortcut shortcut( kcg.readEntry( QString("snippetShortcut_%1").arg(i), QString() ) ); |
|
item = makeItem( SnippetItem::findGroupById( iParentVal, _list ), strNameVal, strTextVal, shortcut.primary() ); |
|
//kDebug(5006) << "Created item " << item->getName() << " " << item->getParent(); |
|
_list.append(item); |
|
} |
|
} |
|
} else { |
|
} |
|
|
|
iCount = kcg.readEntry("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 = kcg.readEntry(strKeyName, ""); |
|
strTextVal = kcg.readEntry(strKeyText, ""); |
|
|
|
if (strNameVal != "" && strTextVal != "") { |
|
_mapSaved[strNameVal] = strTextVal; |
|
} |
|
} |
|
} |
|
|
|
|
|
/*! |
|
* Shows the Popup-Menu if there is an item where the event occurred |
|
*/ |
|
void SnippetWidget::contextMenuEvent( QContextMenuEvent *e ) |
|
{ |
|
KMenu popup; |
|
|
|
SnippetItem *item = static_cast<SnippetItem *>(itemAt(e->pos())); |
|
if ( item ) { |
|
popup.addTitle( item->getName() ); |
|
if (dynamic_cast<SnippetGroup*>(item)) { |
|
popup.addAction( i18n("Edit &group..."), this, SLOT( slotEditGroup() ) ); |
|
} else { |
|
popup.addAction( KIcon("edit-paste"), i18n("&Paste"), |
|
this, SLOT( slotExecuted() ) ); |
|
popup.addAction( KIcon("document-properties"), i18n("&Edit..."), |
|
this, SLOT( slotEdit() ) ); |
|
} |
|
popup.addAction( KIcon("edit-delete"), i18n("&Remove"), |
|
this, SLOT( slotRemove() ) ); |
|
popup.addSeparator(); |
|
} else { |
|
popup.addTitle(i18n("Text Snippets")); |
|
} |
|
popup.addAction( i18n("&Add Snippet..."), this, SLOT( slotAdd() ) ); |
|
popup.addAction( i18n("Add G&roup..."), this, SLOT( slotAddGroup() ) ); |
|
|
|
popup.exec(e->globalPos()); |
|
} |
|
|
|
/*! |
|
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( const QString &text ) |
|
{ |
|
QString str = text; |
|
QString strName; |
|
QString strNew; |
|
QString strMsg; |
|
int iFound = -1; |
|
int iEnd = -1; |
|
QMap<QString, QString> mapVar; |
|
|
|
do { |
|
iFound = text.indexOf(QRegExp("\\$[A-Za-z-_0-9\\s]*\\$"), iEnd+1); //find the next variable by this QRegExp |
|
if (iFound >= 0) { |
|
iEnd = text.indexOf('$', iFound+1)+1; |
|
strName = text.mid(iFound, iEnd-iFound); |
|
|
|
if ( strName != QString('$') + QString('$') ) { //if not doubel-delimiter |
|
if ( mapVar[strName].length() <= 0 ) { // and not already in map |
|
strMsg = i18n( "Please enter the value for <b>%1</b>:", strName ); |
|
strNew = showSingleVarDialog( strName, &_mapSaved ); |
|
if ( strNew.isEmpty() ) |
|
return QString(); //user clicked Cancel |
|
} else { |
|
continue; //we have already handled this variable |
|
} |
|
} |
|
else { |
|
strNew = '$'; //if double-delimiter -> replace by single character |
|
} |
|
|
|
str.replace(strName, strNew); |
|
mapVar[strName] = strNew; |
|
} |
|
} while ( iFound != -1 ); |
|
|
|
return str; |
|
} |
|
|
|
/*! |
|
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( const QString &var, QMap<QString, QString> *mapSave ) |
|
{ |
|
// --BEGIN-- building a dynamic dialog |
|
QDialog dlg(this); |
|
dlg.setWindowTitle(i18n("Enter Values for Variables")); |
|
|
|
QGridLayout * layout = new QGridLayout( &dlg ); |
|
QGridLayout * layoutTop = new QGridLayout(); |
|
QGridLayout * layoutVar = new QGridLayout(); |
|
QGridLayout * layoutBtn = new QGridLayout(); |
|
layout->setMargin( 11 ); |
|
layout->setSpacing( 6 ); |
|
layoutTop->setMargin( 0 ); |
|
layoutTop->setSpacing( 6 ); |
|
layoutVar->setMargin( 0 ); |
|
layoutVar->setSpacing( 6 ); |
|
layoutBtn->setMargin( 0 ); |
|
layoutBtn->setSpacing( 6 ); |
|
layout->setObjectName( "layout" ); |
|
layoutTop->setObjectName( "layoutTop" ); |
|
layoutVar->setObjectName( "layoutVar" ); |
|
layoutBtn->setObjectName( "layoutBtn" ); |
|
|
|
KTextEdit *te = NULL; |
|
QLabel * labTop = NULL; |
|
QCheckBox * cb = NULL; |
|
|
|
labTop = new QLabel( &dlg ); |
|
labTop->setObjectName( "label" ); |
|
layoutTop->addWidget(labTop, 0, 0); |
|
labTop->setText( i18n("Enter the replacement values for %1:", var) ); |
|
layout->addLayout( layoutTop, 0, 0, 1, 2 ); |
|
|
|
|
|
cb = new QCheckBox( &dlg ); |
|
cb->setObjectName( "cbVar" ); |
|
cb->setChecked( false ); |
|
cb->setText(i18n( "Make value &default" )); |
|
|
|
te = new KTextEdit( &dlg ); |
|
te->setObjectName( "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]); |
|
} |
|
|
|
cb->setToolTip( i18n("Enable this to save the value entered to the right as the default value for this variable") ); |
|
cb->setWhatsThis( 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->addLayout( layoutVar, 1, 0, 1, 2 ); |
|
|
|
KPushButton * btn1 = new KPushButton( KStandardGuiItem::cancel(), &dlg ); |
|
btn1->setObjectName( "pushButton1") ; |
|
layoutBtn->addWidget( btn1, 0, 0 ); |
|
|
|
KPushButton * btn2 = new KPushButton( KStandardGuiItem::apply(), &dlg ); |
|
btn2->setObjectName( "pushButton2") ; |
|
btn2->setDefault( true ); |
|
layoutBtn->addWidget( btn2, 0, 1 ); |
|
|
|
layout->addLayout( layoutBtn, 2, 0, 1, 2 ); |
|
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 ( dlg.exec() == QDialog::Accepted ) { |
|
if (cb->isChecked()) //if the checkbox is on; save the values for later |
|
(*mapSave)[var] = te->toPlainText(); |
|
else |
|
(*mapSave).remove(var); |
|
|
|
strReturn = te->toPlainText(); //copy the entered values back the the given map |
|
} |
|
|
|
//do some cleanup |
|
delete cb; |
|
delete te; |
|
delete labTop; |
|
delete btn1; |
|
delete btn2; |
|
delete layoutTop; |
|
delete layoutVar; |
|
delete layoutBtn; |
|
delete layout; |
|
|
|
return strReturn; |
|
} |
|
|
|
|
|
/*! |
|
Emulate Qt3's selectedItem() because it does exactly what we need here. |
|
*/ |
|
QTreeWidgetItem * SnippetWidget::selectedItem() const |
|
{ |
|
if ( selectedItems().isEmpty() ) |
|
return 0; |
|
return currentItem(); |
|
} |
|
|
|
|
|
/*! |
|
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. |
|
*/ |
|
void SnippetWidget::dragMoveEvent( QDragMoveEvent * event ) |
|
{ |
|
QTreeWidgetItem * item = itemAt(event->pos()); |
|
|
|
if (item && |
|
event->mimeData()->hasText() && |
|
static_cast<SnippetWidget *>(event->source()) != this) { |
|
event->setDropAction( Qt::CopyAction ); |
|
event->accept(); |
|
} else { |
|
event->ignore(); |
|
} |
|
} |
|
|
|
void SnippetWidget::dragEnterEvent( QDragEnterEvent * event ) |
|
{ |
|
if ( event->mimeData()->hasFormat("text/x-kmail-textsnippet") || |
|
event->mimeData()->hasText() ) { |
|
event->setDropAction( Qt::CopyAction ); |
|
event->accept(); |
|
} |
|
} |
|
|
|
void SnippetWidget::dropEvent( QDropEvent * event ) |
|
{ |
|
QTreeWidgetItem * item = itemAt( event->pos() ); |
|
if ( !item || !event->mimeData()->hasText() ) { |
|
event->ignore(); |
|
return; |
|
} |
|
else { |
|
event->setDropAction( Qt::CopyAction ); |
|
event->accept(); |
|
} |
|
|
|
SnippetItem *snippet = dynamic_cast<SnippetItem *>( item ); |
|
SnippetGroup *group = dynamic_cast<SnippetGroup *>( item ); |
|
SnippetGroup *parent = 0; |
|
if ( group ) |
|
parent = group; |
|
else { |
|
assert( dynamic_cast<SnippetGroup*>( snippet->parent() ) ); |
|
parent = static_cast<SnippetGroup*>( snippet->parent() ); |
|
} |
|
|
|
// fill the dialog with the given data |
|
SnippetDlg dlg( mActionCollection, this ); |
|
dlg.setObjectName( "SnippetDlg" ); |
|
dlg.snippetName->clear(); |
|
dlg.snippetText->setText( event->mimeData()->text() ); |
|
|
|
/*fill the combobox with the names of all SnippetGroup entries*/ |
|
foreach ( SnippetItem *const si, _list ) { |
|
if ( dynamic_cast<SnippetGroup*>( si ) ) { |
|
dlg.cbGroup->addItem( si->getName() ); |
|
} |
|
} |
|
dlg.cbGroup->setCurrentIndex( dlg.cbGroup->findText( parent->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->toPlainText(), dlg.keyWidget->keySequence() ) ); |
|
} |
|
} |
|
|
|
void SnippetWidget::startDrag( Qt::DropActions supportedActions ) |
|
{ |
|
Q_UNUSED( supportedActions ); |
|
|
|
// Don't allow to drag groups around |
|
if ( dynamic_cast<SnippetGroup*>( currentItem() ) ) |
|
return; |
|
|
|
QString text = dynamic_cast<SnippetItem*>( currentItem() )->getText(); |
|
QDrag *drag = new QDrag( this ); |
|
QMimeData *mimeData = new QMimeData(); |
|
mimeData->setData( "text/x-kmail-textsnippet", text.toUtf8() ); |
|
drag->setMimeData( mimeData ); |
|
drag->exec(); |
|
} |
|
|
|
void SnippetWidget::slotExecute() |
|
{ |
|
slotExecuted(currentItem()); |
|
} |
|
|
|
#include "snippetwidget.moc"
|
|
|