00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <kparts/part.h>
00010 #include <klibloader.h>
00011 #include <kurl.h>
00012 #include <kdebug.h>
00013 #include <klocale.h>
00014 #include <qlayout.h>
00015 #include <kpushbutton.h>
00016 #include <klistview.h>
00017 #include <qheader.h>
00018 #include <klineedit.h>
00019 #include <ktextedit.h>
00020 #include <kmessagebox.h>
00021 #include <qsplitter.h>
00022 #include <ktexteditor/editinterface.h>
00023 #include <ktexteditor/editor.h>
00024 #include <ktexteditor/viewcursorinterface.h>
00025 #include <ktexteditor/document.h>
00026 #include <kconfig.h>
00027 #include <qtooltip.h>
00028 #include <kpopupmenu.h>
00029 #include <qregexp.h>
00030 #include <qinputdialog.h>
00031 #include <qlayout.h>
00032 #include <qlabel.h>
00033 #include <qcheckbox.h>
00034 #include <qwhatsthis.h>
00035 #include <kdebug.h>
00036 #include <qdragobject.h>
00037
00038 #include <kdevcore.h>
00039 #include "kdevcore.h"
00040 #include <kdevproject.h>
00041 #include <kdevpartcontroller.h>
00042
00043 #include <snippetdlg.h>
00044 #include <snippetitem.h>
00045
00046 #include "snippet_part.h"
00047 #include "snippet_widget.h"
00048
00049 SnippetWidget::SnippetWidget(SnippetPart *part)
00050 : KListView(0, "snippet widget"), QToolTip( viewport() ),
00051 m_part( part )
00052 {
00053
00054 m_dialog = new SnippetDlg(this, "SnippetDlg", true);
00055
00056
00057 _list.setAutoDelete(TRUE);
00058
00059
00060 setSorting( -1 );
00061 addColumn( "" );
00062 setFullWidth(true);
00063 header()->hide();
00064 setAcceptDrops(true);
00065 setDragEnabled(false);
00066 setDropVisualizer(false);
00067
00068
00069 connect( this, SIGNAL( contextMenuRequested ( QListViewItem *, const QPoint & , int ) ),
00070 this, SLOT( showPopupMenu(QListViewItem *, const QPoint & , int ) ) );
00071 connect( this, SIGNAL( doubleClicked (QListViewItem *, const QPoint &, int) ),
00072 this, SLOT( slotListDblClicked( QListViewItem *, const QPoint &, int) ) );
00073 connect( this, SIGNAL( dropped(QDropEvent *, QListViewItem *) ),
00074 this, SLOT( slotDropped(QDropEvent *, QListViewItem *) ) );
00075
00076 _cfg = NULL;
00077 initConfig();
00078 }
00079
00080 SnippetWidget::~SnippetWidget()
00081 {
00082 writeConfig();
00083
00084 _list.clear();
00085 }
00086
00087
00092 void SnippetWidget::slotAdd()
00093 {
00094 kdDebug(26) << "Ender slotAdd()" << endl;
00095 m_dialog->snippetName->clear();
00096 m_dialog->snippetText->clear();
00097
00098 if (m_dialog->exec() == QDialog::Accepted) {
00099 _list.append( new SnippetItem(this, m_dialog->snippetName->text(), m_dialog->snippetText->text()) );
00100 }
00101 }
00102
00103
00108 void SnippetWidget::slotRemove()
00109 {
00110
00111 QListViewItem * item = currentItem();
00112 SnippetItem *pSnippet = dynamic_cast<SnippetItem*>( item );
00113 if (!pSnippet)
00114 return;
00115
00116 removeItem(item);
00117 _list.remove(pSnippet);
00118 }
00119
00120
00121
00126 void SnippetWidget::slotEdit()
00127 {
00128
00129 QListViewItem * item = currentItem();
00130
00131 SnippetItem *pSnippet = dynamic_cast<SnippetItem*>( item );
00132 if (!pSnippet)
00133 return;
00134
00135
00136 m_dialog->snippetName->setText(pSnippet->getName());
00137 m_dialog->snippetText->setText(pSnippet->getText());
00138 m_dialog->btnAdd->setText(i18n("&Apply"));
00139
00140 if (m_dialog->exec() == QDialog::Accepted) {
00141
00142 item->setText( 0, m_dialog->snippetName->text() );
00143 pSnippet->setName( m_dialog->snippetName->text() );
00144 pSnippet->setText( m_dialog->snippetText->text() );
00145
00146 setSelected(item, TRUE);
00147 }
00148
00149 m_dialog->btnAdd->setText(i18n("Add"));
00150 }
00151
00152
00153
00158 void SnippetWidget::slotListDblClicked(QListViewItem * item, const QPoint &, int)
00159 {
00160 SnippetItem *pSnippet = dynamic_cast<SnippetItem*>( item );
00161 if (!pSnippet)
00162 return;
00163
00164
00165 insertIntoActiveView( parseText(pSnippet->getText(), _SnippetConfig.getDelimiter()) );
00166 }
00167
00168
00173 void SnippetWidget::insertIntoActiveView(QString text)
00174 {
00175
00176 KTextEditor::ViewCursorInterface *cursorIface
00177 = dynamic_cast<KTextEditor::ViewCursorInterface*>(m_part->partController()->activeWidget());
00178
00179 if (!cursorIface)
00180 return;
00181
00182 KTextEditor::EditInterface* editIface
00183 = dynamic_cast<KTextEditor::EditInterface*>( m_part->partController()->activePart() );
00184
00185 if (!editIface)
00186 return;
00187
00188 uint line, col;
00189 cursorIface->cursorPositionReal(&line, &col);
00190
00191 editIface->insertText( line, col , text );
00192 }
00193
00194
00199 void SnippetWidget::writeConfig()
00200 {
00201 _cfg->deleteGroup("SnippetPart");
00202
00203 _cfg->setGroup("SnippetPart");
00204
00205 _cfg->writeEntry("snippetCount", _list.count());
00206 SnippetItem *item;
00207 QString strKeyName="";
00208 QString strKeyText="";
00209 int iCount = 1;
00210 for ( item = _list.first(); item; item = _list.next() ) {
00211 strKeyName=QString("snippetName_%1").arg(iCount);
00212 strKeyText=QString("snippetText_%1").arg(iCount);
00213
00214 _cfg->writeEntry(strKeyName, item->getName());
00215 _cfg->writeEntry(strKeyText, item->getText());
00216
00217 iCount++;
00218 }
00219
00220 iCount = 1;
00221 QMap<QString, QString>::Iterator it;
00222 for ( it = _mapSaved.begin(); it != _mapSaved.end(); ++it ) {
00223 if (it.data().length()<=0) continue;
00224
00225 strKeyName=QString("snippetSavedName_%1").arg(iCount);
00226 strKeyText=QString("snippetSavedVal_%1").arg(iCount);
00227
00228 _cfg->writeEntry(strKeyName, it.key());
00229 _cfg->writeEntry(strKeyText, it.data());
00230
00231 iCount++;
00232 }
00233 _cfg->writeEntry("snippetSavedCount", iCount-1);
00234
00235
00236 _cfg->writeEntry( "snippetDelimiter", _SnippetConfig.getDelimiter() );
00237 _cfg->writeEntry( "snippetVarInput", _SnippetConfig.getInputMethod() );
00238 _cfg->writeEntry( "snippetToolTips", _SnippetConfig.useToolTips() );
00239
00240 _cfg->writeEntry("snippetSingleRect", _SnippetConfig.getSingleRect() );
00241 _cfg->writeEntry("snippetMultiRect", _SnippetConfig.getMultiRect() );
00242
00243 _cfg->sync();
00244 }
00245
00246
00251 void SnippetWidget::initConfig()
00252 {
00253 if (_cfg == NULL)
00254 _cfg = new KConfig("kdevsnippetrc", false, false);
00255
00256 _cfg->setGroup("SnippetPart");
00257
00258 int iCount = _cfg->readNumEntry("snippetCount", 0);
00259 QString strKeyName="";
00260 QString strKeyText="";
00261 SnippetItem *item;
00262
00263 for ( int i=1; i<=iCount; i++) {
00264 strKeyName=QString("snippetName_%1").arg(i);
00265 strKeyText=QString("snippetText_%1").arg(i);
00266
00267 QString strNameVal="";
00268 QString strTextVal="";
00269
00270 strNameVal = _cfg->readEntry(strKeyName, "");
00271 strTextVal = _cfg->readEntry(strKeyText, "");
00272
00273 if (strNameVal != "" && strTextVal != "") {
00274 item = new SnippetItem(this, strNameVal, strTextVal);
00275 _list.append(item);
00276 }
00277 }
00278
00279
00280 iCount = _cfg->readNumEntry("snippetSavedCount", 0);
00281
00282 for ( int i=1; i<=iCount; i++) {
00283 strKeyName=QString("snippetSavedName_%1").arg(i);
00284 strKeyText=QString("snippetSavedVal_%1").arg(i);
00285
00286 QString strNameVal="";
00287 QString strTextVal="";
00288
00289 strNameVal = _cfg->readEntry(strKeyName, "");
00290 strTextVal = _cfg->readEntry(strKeyText, "");
00291
00292 if (strNameVal != "" && strTextVal != "") {
00293 _mapSaved[strNameVal] = strTextVal;
00294 }
00295 }
00296
00297
00298 _SnippetConfig.setDelimiter( _cfg->readEntry("snippetDelimiter", "$") );
00299 _SnippetConfig.setInputMethod( _cfg->readNumEntry("snippetVarInput", 0) );
00300 _SnippetConfig.setToolTips( _cfg->readBoolEntry("snippetToolTips", true) );
00301
00302 _SnippetConfig.setSingleRect( _cfg->readRectEntry("snippetSingleRect", 0L) );
00303 _SnippetConfig.setMultiRect( _cfg->readRectEntry("snippetMultiRect", 0L) );
00304 }
00305
00310 void SnippetWidget::maybeTip( const QPoint & p )
00311 {
00312 SnippetItem * item = dynamic_cast<SnippetItem*>( itemAt( p ) );
00313 if (!item)
00314 return;
00315
00316 QRect r = itemRect( item );
00317
00318 if ( item && r.isValid() && _SnippetConfig.useToolTips() )
00319 {
00320 tip( r, item->getText() );
00321 }
00322 }
00323
00328 void SnippetWidget::showPopupMenu( QListViewItem * item, const QPoint & p, int )
00329 {
00330 KPopupMenu popup;
00331
00332 if ( item ) {
00333 SnippetItem * selectedItem = static_cast<SnippetItem *>(item);
00334
00335 popup.insertTitle( i18n("Snippet: ") + selectedItem->getName() );
00336
00337 popup.insertItem( i18n("Add..."), this, SLOT( slotAdd() ) );
00338 popup.insertItem( i18n("Edit..."), this, SLOT( slotEdit() ) );
00339 popup.insertItem( i18n("Remove"), this, SLOT( slotRemove() ) );
00340
00341 } else {
00342 popup.insertTitle(i18n("Code Snippets"));
00343
00344 popup.insertItem( i18n("Add..."), this, SLOT( slotAdd() ) );
00345 }
00346
00347 popup.exec(p);
00348 }
00349
00350
00351
00356 QString SnippetWidget::parseText(QString text, QString del)
00357 {
00358 QString str = text;
00359 QString strName = "";
00360 QString strNew = "";
00361 QString strMsg="";
00362 int iFound = -1;
00363 int iEnd = -1;
00364 QMap<QString, QString> mapVar;
00365 int iInMeth = _SnippetConfig.getInputMethod();
00366 QRect rSingle = _SnippetConfig.getSingleRect();
00367 QRect rMulti = _SnippetConfig.getMultiRect();
00368
00369 do {
00370 iFound = text.find(QRegExp("\\"+del+"[A-Z,a-z,\\s]*\\"+del), iEnd+1);
00371 if (iFound >= 0) {
00372 iEnd = text.find(del, iFound+1)+1;
00373 strName = text.mid(iFound, iEnd-iFound);
00374
00375 if ( strName != del+del && mapVar[strName].length() <= 0 ) {
00376 if (iInMeth == 0) {
00377 strMsg=QString(i18n("Please enter the value for <b>%1</b>:")).arg(strName);
00378 strNew = showSingleVarDialog( strName, &_mapSaved, rSingle );
00379 if (strNew=="")
00380 return "";
00381 }
00382 } else {
00383 strNew = del;
00384 }
00385
00386 if (iInMeth == 0 || strName == del+del) {
00387 str.replace(strName, strNew);
00388 } else {
00389 strNew = strName;
00390 }
00391
00392 mapVar[strName] = strNew;
00393 }
00394 } while (iFound != -1);
00395
00396 if (iInMeth == 1) {
00397 int w, bh, oh;
00398 w = rMulti.width();
00399 bh = rMulti.height();
00400 oh = rMulti.top();
00401 if (showMultiVarDialog( &mapVar, &_mapSaved, w, bh, oh )) {
00402 QMap<QString, QString>::Iterator it;
00403 for ( it = mapVar.begin(); it != mapVar.end(); ++it ) {
00404 str.replace(it.key(), it.data());
00405 }
00406 } else {
00407 return "";
00408 }
00409
00410 rMulti.setWidth(w);
00411 rMulti.setHeight(bh);
00412 rMulti.setTop(oh);
00413 rMulti.setLeft(0);
00414 _SnippetConfig.setMultiRect(rMulti);
00415 }
00416
00417 _SnippetConfig.setSingleRect(rSingle);
00418
00419 return str;
00420 }
00421
00422
00423
00429 bool SnippetWidget::showMultiVarDialog(QMap<QString, QString> * map, QMap<QString, QString> * mapSave,
00430 int & iWidth, int & iBasicHeight, int & iOneHeight)
00431 {
00432
00433 if (map->count() == 0)
00434 return true;
00435
00436
00437 QMap<QString, QString>::Iterator it = map->begin();
00438 if ( map->count() == 1 && it.data()==_SnippetConfig.getDelimiter()+_SnippetConfig.getDelimiter() )
00439 return true;
00440
00441 QMap<QString, KTextEdit *> mapVar2Te;
00442 QMap<QString, QCheckBox *> mapVar2Cb;
00443
00444
00445 QDialog dlg(this);
00446 dlg.setCaption(i18n("Enter Values for Variables"));
00447
00448 QGridLayout * layout = new QGridLayout( &dlg, 1, 1, 11, 6, "layout");
00449 QGridLayout * layoutTop = new QGridLayout( 0, 1, 1, 0, 6, "layoutTop");
00450 QGridLayout * layoutVar = new QGridLayout( 0, 1, 1, 0, 6, "layoutVar");
00451 QGridLayout * layoutBtn = new QGridLayout( 0, 1, 1, 0, 6, "layoutBtn");
00452
00453 KTextEdit *te = NULL;
00454 QLabel * labTop = NULL;
00455 QCheckBox * cb = NULL;
00456
00457 labTop = new QLabel( &dlg, "label" );
00458 labTop->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0,
00459 labTop->sizePolicy().hasHeightForWidth() ) );
00460 labTop->setText(i18n("Enter the replacement values for these variables:"));
00461 layoutTop->addWidget(labTop, 0, 0);
00462 layout->addMultiCellLayout( layoutTop, 0, 0, 0, 1 );
00463
00464
00465 int i = 0;
00466 for ( it = map->begin(); it != map->end(); ++it ) {
00467 if (it.key() == _SnippetConfig.getDelimiter() + _SnippetConfig.getDelimiter())
00468 continue;
00469
00470 cb = new QCheckBox( &dlg, "cbVar" );
00471 cb->setChecked( FALSE );
00472 cb->setText(it.key());
00473 layoutVar->addWidget( cb, i ,0, Qt::AlignTop );
00474
00475 te = new KTextEdit( &dlg, "teVar" );
00476 layoutVar->addWidget( te, i, 1, Qt::AlignTop );
00477
00478 if ((*mapSave)[it.key()].length() > 0) {
00479 cb->setChecked( TRUE );
00480 te->setText((*mapSave)[it.key()]);
00481 }
00482
00483 mapVar2Te[it.key()] = te;
00484 mapVar2Cb[it.key()] = cb;
00485
00486 QToolTip::add( cb, i18n("Enable this to save the value entered to the right as the default value for this variable") );
00487 QWhatsThis::add( cb, i18n("If you enable this option, the value entered to the right will be saved. "
00488 "If you use the same variable later, even in another snippet, the value entered to the right "
00489 "will be the default value for that variable.") );
00490
00491 i++;
00492 }
00493 layout->addMultiCellLayout( layoutVar, 1, 1, 0, 1 );
00494
00495 KPushButton * btn1 = new KPushButton( &dlg, "pushButton1" );
00496 btn1->setText(i18n("&Cancel"));
00497 btn1->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0,
00498 btn1->sizePolicy().hasHeightForWidth() ) );
00499 layoutBtn->addWidget( btn1, 0, 0 );
00500
00501 KPushButton * btn2 = new KPushButton( &dlg, "pushButton2" );
00502 btn2->setText(i18n("&Apply"));
00503 btn2->setDefault( TRUE );
00504 btn2->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0,
00505 btn2->sizePolicy().hasHeightForWidth() ) );
00506 layoutBtn->addWidget( btn2, 0, 1 );
00507
00508 layout->addMultiCellLayout( layoutBtn, 2, 2, 0, 1 );
00509
00510
00511
00512 connect(btn1, SIGNAL(clicked()), &dlg, SLOT(reject()) );
00513 connect(btn2, SIGNAL(clicked()), &dlg, SLOT(accept()) );
00514
00515
00516 bool bReturn = false;
00517
00518 if (iWidth > 1) {
00519 QRect r = dlg.geometry();
00520 r.setHeight(iBasicHeight + iOneHeight*mapVar2Te.count());
00521 r.setWidth(iWidth);
00522 dlg.setGeometry(r);
00523 }
00524 if ( dlg.exec() == QDialog::Accepted ) {
00525 QMap<QString, KTextEdit *>::Iterator it2;
00526 for ( it2 = mapVar2Te.begin(); it2 != mapVar2Te.end(); ++it2 ) {
00527 if (it2.key() == _SnippetConfig.getDelimiter() + _SnippetConfig.getDelimiter())
00528 continue;
00529 (*map)[it2.key()] = it2.data()->text();
00530
00531 if (mapVar2Cb[it2.key()]->isChecked())
00532 (*mapSave)[it2.key()] = it2.data()->text();
00533 else
00534 (*mapSave).erase(it2.key());
00535 }
00536 bReturn = true;
00537
00538 iBasicHeight = dlg.geometry().height() - layoutVar->geometry().height();
00539 iOneHeight = layoutVar->geometry().height() / mapVar2Te.count();
00540 iWidth = dlg.geometry().width();
00541 }
00542
00543
00544 QMap<QString, KTextEdit *>::Iterator it1;
00545 for (it1 = mapVar2Te.begin(); it1 != mapVar2Te.end(); ++it1)
00546 delete it1.data();
00547 mapVar2Te.clear();
00548 QMap<QString, QCheckBox *>::Iterator it2;
00549 for (it2 = mapVar2Cb.begin(); it2 != mapVar2Cb.end(); ++it2)
00550 delete it2.data();
00551 mapVar2Cb.clear();
00552 delete layoutTop;
00553 delete layoutVar;
00554 delete layoutBtn;
00555 delete layout;
00556
00557 return bReturn;
00558 }
00559
00560
00561
00566 QString SnippetWidget::showSingleVarDialog(QString var, QMap<QString, QString> * mapSave, QRect & dlgSize)
00567 {
00568
00569 QDialog dlg(this);
00570 dlg.setCaption(i18n("Enter Values for Variables"));
00571
00572 QGridLayout * layout = new QGridLayout( &dlg, 1, 1, 11, 6, "layout");
00573 QGridLayout * layoutTop = new QGridLayout( 0, 1, 1, 0, 6, "layoutTop");
00574 QGridLayout * layoutVar = new QGridLayout( 0, 1, 1, 0, 6, "layoutVar");
00575 QGridLayout * layoutBtn = new QGridLayout( 0, 2, 1, 0, 6, "layoutBtn");
00576
00577 KTextEdit *te = NULL;
00578 QLabel * labTop = NULL;
00579 QCheckBox * cb = NULL;
00580
00581 labTop = new QLabel( &dlg, "label" );
00582 layoutTop->addWidget(labTop, 0, 0);
00583 labTop->setText((QString(i18n("Enter the replacement values for ")) + var + ":"));
00584 layout->addMultiCellLayout( layoutTop, 0, 0, 0, 1 );
00585
00586
00587 cb = new QCheckBox( &dlg, "cbVar" );
00588 cb->setChecked( FALSE );
00589 cb->setText("make value &default");
00590
00591 te = new KTextEdit( &dlg, "teVar" );
00592 layoutVar->addWidget( te, 0, 1, Qt::AlignTop);
00593 layoutVar->addWidget( cb, 1, 1, Qt::AlignTop);
00594 if ((*mapSave)[var].length() > 0) {
00595 cb->setChecked( TRUE );
00596 te->setText((*mapSave)[var]);
00597 }
00598
00599 QToolTip::add( cb, i18n("Enable this to save the value entered to the right as the default value for this variable") );
00600 QWhatsThis::add( cb, i18n("If you enable this option, the value entered to the right will be saved. "
00601 "If you use the same variable later, even in another snippet, the value entered to the right "
00602 "will be the default value for that variable.") );
00603
00604 layout->addMultiCellLayout( layoutVar, 1, 1, 0, 1 );
00605
00606 KPushButton * btn1 = new KPushButton( &dlg, "pushButton1" );
00607 btn1->setText(i18n("&Cancel"));
00608 layoutBtn->addWidget( btn1, 0, 0 );
00609
00610 KPushButton * btn2 = new KPushButton( &dlg, "pushButton2" );
00611 btn2->setText(i18n("&Apply"));
00612 btn2->setDefault( TRUE );
00613 layoutBtn->addWidget( btn2, 0, 1 );
00614
00615 layout->addMultiCellLayout( layoutBtn, 2, 2, 0, 1 );
00616 te->setFocus();
00617
00618
00619
00620 connect(btn1, SIGNAL(clicked()), &dlg, SLOT(reject()) );
00621 connect(btn2, SIGNAL(clicked()), &dlg, SLOT(accept()) );
00622
00623
00624 QString strReturn = "";
00625 if (dlgSize.isValid())
00626 dlg.setGeometry(dlgSize);
00627 if ( dlg.exec() == QDialog::Accepted ) {
00628 if (cb->isChecked())
00629 (*mapSave)[var] = te->text();
00630 else
00631 (*mapSave).erase(var);
00632
00633 strReturn = te->text();
00634
00635 dlgSize = dlg.geometry();
00636 }
00637
00638
00639 delete cb;
00640 delete te;
00641 delete labTop;
00642 delete btn1;
00643 delete btn2;
00644 delete layoutTop;
00645 delete layoutVar;
00646 delete layoutBtn;
00647 delete layout;
00648
00649 return strReturn;
00650 }
00651
00652
00659 bool SnippetWidget::acceptDrag (QDropEvent *event) const
00660 {
00661 kdDebug(9035) << "Format: " << event->format() << endl;
00662
00663 if (QString(event->format()).startsWith("text/plain") &&
00664 static_cast<SnippetWidget *>(event->source()) != this)
00665 return true;
00666 else
00667 return false;
00668 }
00669
00670
00676 void SnippetWidget::slotDropped(QDropEvent *e, QListViewItem *)
00677 {
00678 QCString dropped;
00679 QByteArray data = e->encodedData("text/plain");
00680 if ( e->provides("text/plain") && data.size()>0 ) {
00681
00682 QString encData(data.data());
00683 kdDebug(9035) << "encData: " << encData << endl;
00684
00685
00686 m_dialog->snippetName->clear();
00687 m_dialog->snippetText->setText(encData);
00688
00689 if (m_dialog->exec() == QDialog::Accepted) {
00690 _list.append( new SnippetItem(this, m_dialog->snippetName->text(), m_dialog->snippetText->text()) );
00691 }
00692 }
00693 }
00694
00695
00696 #include "snippet_widget.moc"