kate Library API Documentation

kateexternaltools.cpp

00001 /* 00002 This file is part of the Kate text editor of the KDE project. 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License version 2 as published by the Free Software Foundation. 00007 00008 This library is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 Library General Public License for more details. 00012 00013 You should have received a copy of the GNU Library General Public License 00014 along with this library; see the file COPYING.LIB. If not, write to 00015 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00016 Boston, MA 02111-1307, USA. 00017 00018 --- 00019 Copyright (C) 2004, Anders Lund <anders@alweb.dk> 00020 */ 00021 // TODO 00022 // Icons 00023 // Direct shortcut setting 00024 00025 #include "kateexternaltools.h" 00026 #include "kateexternaltools.moc" 00027 #include "katedocmanager.h" 00028 00029 #include "katemainwindow.h" 00030 00031 #include <kate/view.h> 00032 #include <kate/document.h> 00033 00034 #include <klistbox.h> 00035 #include <klocale.h> 00036 #include <kiconloader.h> 00037 #include <kmessagebox.h> 00038 #include <kconfig.h> 00039 #include <krun.h> 00040 #include <kicondialog.h> 00041 00042 #include <qbitmap.h> 00043 #include <qfile.h> 00044 #include <qpushbutton.h> 00045 #include <qlineedit.h> 00046 #include <qlayout.h> 00047 #include <qlabel.h> 00048 #include <qlistbox.h> 00049 #include <qmap.h> 00050 #include <qregexp.h> 00051 #include <qwhatsthis.h> 00052 00053 #include <stdlib.h> 00054 #include <unistd.h> 00055 00056 #include <kdebug.h> 00057 00058 //BEGIN KateExternalTool 00059 KateExternalTool::KateExternalTool( const QString &name, 00060 const QString &command, 00061 const QString &icon, 00062 const QString &tryexec, 00063 const QStringList &mimetypes, 00064 const QString &acname ) 00065 : name ( name ), 00066 command ( command ), 00067 icon ( icon ), 00068 tryexec ( tryexec ), 00069 mimetypes ( mimetypes ), 00070 acname ( acname ) 00071 { 00072 //if ( ! tryexec.isEmpty() ) 00073 hasexec = checkExec(); 00074 } 00075 00076 bool KateExternalTool::checkExec() 00077 { 00078 // if tryexec is empty, it is the first word of command 00079 if ( tryexec.isEmpty() ) 00080 tryexec = command.section( " ", 0, 0, QString::SectionSkipEmpty ); 00081 00082 // NOTE this code is modified taken from kdesktopfile.cpp, from KDesktopFile::tryExec() 00083 if (!tryexec.isEmpty()) { 00084 if (tryexec[0] == '/') { 00085 if (::access(QFile::encodeName(tryexec), R_OK | X_OK)) 00086 return false; 00087 00088 m_exec = tryexec; 00089 } else { 00090 // !!! Sergey A. Sukiyazov <corwin@micom.don.ru> !!! 00091 // Environment PATH may contain filenames in 8bit locale cpecified 00092 // encoding (Like a filenames). 00093 QStringList dirs = QStringList::split(':', QFile::decodeName(::getenv("PATH"))); 00094 QStringList::Iterator it(dirs.begin()); 00095 bool match = false; 00096 for (; it != dirs.end(); ++it) 00097 { 00098 QString fName = *it + "/" + tryexec; 00099 if (::access(QFile::encodeName(fName), R_OK | X_OK) == 0) 00100 { 00101 match = true; 00102 m_exec = fName; 00103 break; 00104 } 00105 } 00106 // didn't match at all 00107 if (!match) 00108 return false; 00109 } 00110 return true; 00111 } 00112 return false; 00113 } 00114 00115 bool KateExternalTool::valid( QString mt ) const 00116 { 00117 return mimetypes.isEmpty() || mimetypes.contains( mt ); 00118 } 00119 //END KateExternalTool 00120 00121 //BEGIN KateExternalToolAction 00122 KateExternalToolAction::KateExternalToolAction( QObject *parent, 00123 const char *name, KateExternalTool *t) 00124 : KAction( parent, name ), 00125 tool ( t ) 00126 { 00127 setText( t->name ); 00128 if ( ! t->icon.isEmpty() ) 00129 setIconSet( SmallIconSet( t->icon ) ); 00130 00131 connect( this ,SIGNAL(activated()), this, SLOT(slotRun()) ); 00132 } 00133 00134 bool KateExternalToolAction::expandMacro( const QString &str, QStringList &ret ) 00135 { 00136 KateMainWindow *mw = ((KateExternalToolsMenuAction*)parent()->parent())->mainwindow; 00137 Kate::View *view = mw->viewManager()->activeView(); 00138 00139 if ( str == "URL" ) 00140 ret += mw->activeDocumentUrl().url(); 00141 else if ( str == "directory" ) // directory of current doc 00142 ret += mw->activeDocumentUrl().directory(); 00143 else if ( str == "filename" ) 00144 ret += mw->activeDocumentUrl().filename(); 00145 else if ( str == "line" ) // cursor line of current doc 00146 ret += QString::number( view->cursorLine() ); 00147 else if ( str == "col" ) // cursor col of current doc 00148 ret += QString::number( view->cursorColumn() ); 00149 else if ( str == "selection" ) // selection of current doc if any 00150 ret += view->getDoc()->selection(); 00151 else if ( str == "text" ) // text of current doc 00152 ret += view->getDoc()->text(); 00153 else if ( str == "URLs" ) { 00154 for( Kate::Document *doc = mw->m_docManager->firstDocument(); doc; doc = mw->m_docManager->nextDocument() ) 00155 if ( ! doc->url().isEmpty() ) 00156 ret += doc->url().url(); 00157 } else 00158 return false; 00159 return true; 00160 } 00161 00162 void KateExternalToolAction::slotRun() 00163 { 00164 // expand the macros in command if any, 00165 // and construct a command with an absolute path 00166 QString cmd = tool->command; 00167 00168 expandMacrosShellQuote( cmd ); 00169 00170 kdDebug()<<"=== Running command: "<<cmd<<endl; 00171 KRun::runCommand( cmd, tool->tryexec, tool->icon ); 00172 } 00173 //END KateExternalToolAction 00174 00175 //BEGIN KateExternalToolsMenuAction 00176 KateExternalToolsMenuAction::KateExternalToolsMenuAction( const QString &text, 00177 QObject *parent, 00178 const char* name, 00179 KateMainWindow *mw ) 00180 : KActionMenu( text, parent, name ), 00181 mainwindow( mw ) 00182 { 00183 00184 m_actionCollection = new KActionCollection( this ); 00185 00186 // connect(mw->m_docManager,SIGNAL(documentChanged()),this,SLOT(slotDocumentChanged())); 00187 00188 reload(); 00189 } 00190 00191 void KateExternalToolsMenuAction::reload() 00192 { 00193 m_actionCollection->clear(); 00194 00195 popupMenu()->clear(); 00196 00197 // load all the tools, and create a action for each of them 00198 KConfig *config = new KConfig("externaltools", false, false, "appdata"); 00199 config->setGroup("Global"); 00200 QStringList tools = config->readListEntry("tools"); 00201 00202 // QRegExp re_nw("\\W"); 00203 00204 for( QStringList::Iterator it = tools.begin(); it != tools.end(); ++it ) 00205 { 00206 if ( *it == "---" ) 00207 { 00208 popupMenu()->insertSeparator(); 00209 // a separator 00210 continue; 00211 } 00212 00213 config->setGroup( *it ); 00214 00215 KateExternalTool *t = new KateExternalTool( 00216 config->readEntry( "name", "" ), 00217 config->readEntry( "command", ""), 00218 config->readEntry( "icon", ""), 00219 config->readEntry( "executable", ""), 00220 config->readListEntry( "mimetypes" ), 00221 config->readEntry( "acname", "" ) ); 00222 00223 if ( t->hasexec ) 00224 insert( new KateExternalToolAction( m_actionCollection, t->acname.ascii(), t ) ); 00225 } 00226 00227 m_actionCollection->readShortcutSettings( "Shortcuts", config ); 00228 } 00229 00230 void KateExternalToolsMenuAction::slotDocumentChanged() 00231 { 00232 // // enable/disable to match current mime type 00233 // QString mt = mainwindow->m_docManager->activeDocument()->mimeType(); 00234 // 00235 // KActionPtrList actions = m_actionCollection->actions(); 00236 // for (KActionPtrList::iterator it = actions.begin(); it != actions.end(); ++it ) 00237 // { 00238 // if ( (KateExternalToolAction *a = dynamic_cast<KateExternalToolAction*>(*it)) ) 00239 // { 00240 // a->setEnabled a->tool->mimetypes.contain( mt ); 00241 // } 00242 // } 00243 } 00244 //END KateExternalToolsMenuAction 00245 00246 //BEGIN ToolItem 00251 class ToolItem : public QListBoxPixmap 00252 { 00253 public: 00254 ToolItem( QListBox *lb, const QPixmap &icon, KateExternalTool *tool ) 00255 : QListBoxPixmap( lb, icon, tool->name ), 00256 tool ( tool ) 00257 {;} 00258 00259 ~ToolItem() {}; 00260 00261 KateExternalTool *tool; 00262 }; 00263 //END ToolItem 00264 00265 //BEGIN KateExternalToolServiceEditor 00266 KateExternalToolServiceEditor::KateExternalToolServiceEditor( KateExternalTool *tool, 00267 QWidget *parent, const char *name ) 00268 : KDialogBase( parent, name, true, i18n("Edit External Tool"), KDialogBase::Ok|KDialogBase::Cancel ), 00269 tool( tool ) 00270 { 00271 // create a entry for each property 00272 // fill in the values from the service if available 00273 QWidget *w = new QWidget( this ); 00274 setMainWidget( w ); 00275 QGridLayout *lo = new QGridLayout( w ); 00276 lo->setSpacing( KDialogBase::spacingHint() ); 00277 00278 QLabel *l; 00279 00280 leName = new QLineEdit( w ); 00281 lo->addWidget( leName, 1, 2 ); 00282 l = new QLabel( leName, i18n("&Name:"), w ); 00283 l->setAlignment( l->alignment()|Qt::AlignRight ); 00284 lo->addWidget( l, 1, 1 ); 00285 if ( tool ) leName->setText( tool->name ); 00286 QWhatsThis::add( leName, i18n( 00287 "The name will be displayed in the 'Tools->External' menu") ); 00288 00289 leCommand = new QLineEdit( w ); 00290 lo->addWidget( leCommand, 2, 2 ); 00291 l = new QLabel( leCommand, i18n("Co&mmand:"), w ); 00292 l->setAlignment( l->alignment()|Qt::AlignRight ); 00293 lo->addWidget( l, 2, 1 ); 00294 if ( tool ) leCommand->setText( tool->command ); 00295 QWhatsThis::add( leCommand, i18n( 00296 "<p>The command to execute to invoke the tool. The following macros " 00297 "will be expanded:</p>" 00298 "<ul><li><code>%URL</code> - the URL of the current document." 00299 "<li><code>%URLs</code> - a list of the URLs of all open documents." 00300 "<li><code>%directory</code> - the URL of the directory containing " 00301 "the current document." 00302 "<li><code>filename</code> - the filename of the current document." 00303 "<li><code>%line</code> - the current line of the text cursor in the " 00304 "current view." 00305 "<li><code>%column</code> - the column of the text cursor in the " 00306 "current view." 00307 "<li><code>%selection</code> - the selected text in the current view." 00308 "<li><code>%text</code> - the text of the current document.</ul>" ) ); 00309 00310 btnIcon = new KIconButton( w ); 00311 btnIcon->setIconSize( KIcon::SizeMedium ); 00312 lo->addMultiCellWidget( btnIcon, 1, 2, 3, 3 ); 00313 if ( tool && !tool->icon.isEmpty() ) 00314 btnIcon->setIcon( tool->icon ); 00315 00316 00317 leExecutable = new QLineEdit( w ); 00318 lo->addWidget( leExecutable, 3, 2 ); 00319 l = new QLabel( leExecutable, i18n("&Executable:"), w ); 00320 l->setAlignment( l->alignment()|Qt::AlignRight ); 00321 lo->addWidget( l, 3, 1 ); 00322 if ( tool ) leExecutable->setText( tool->tryexec ); 00323 QWhatsThis::add( leExecutable, i18n( 00324 "The executable used by the command. This is used to check if a tool " 00325 "should be displayed; if not set, the first word of <em>command</em> " 00326 "will be used.") ); 00327 00328 leMimetypes = new QLineEdit( w ); 00329 lo->addWidget( leMimetypes, 4, 2 ); 00330 l = new QLabel( leMimetypes, i18n("&Mime types:"), w ); 00331 l->setAlignment( l->alignment()|Qt::AlignRight ); 00332 lo->addWidget( l, 4, 1 ); 00333 if ( tool ) leMimetypes->setText( tool->mimetypes.join("; ") ); 00334 QWhatsThis::add( leMimetypes, i18n( 00335 "A semicolon-separated list of mime types for which this tool should " 00336 "be available; if this is left empty, the tool is always available." 00337 "To choose from known mimetypes, press the button on the right.") ); 00338 } 00339 00340 void KateExternalToolServiceEditor::slotOk() 00341 { 00342 if ( leName->text().isEmpty() || 00343 leCommand->text().isEmpty() ) 00344 { 00345 KMessageBox::information( this, i18n("You must specify at least a name and a command") ); 00346 return; 00347 } 00348 00349 KDialogBase::slotOk(); 00350 } 00351 //END KateExternalToolServiceEditor 00352 00353 //BEGIN KateExternalToolsConfigWidget 00354 KateExternalToolsConfigWidget::KateExternalToolsConfigWidget( QWidget *parent, const char* name ) 00355 : Kate::ConfigPage( parent, name ) 00356 { 00357 QGridLayout *lo = new QGridLayout( this, 5, 5, 0, KDialog::spacingHint() ); 00358 00359 lbTools = new KListBox( this ); 00360 lo->addMultiCellWidget( lbTools, 1, 4, 0, 3 ); 00361 connect( lbTools, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()) ); 00362 00363 btnNew = new QPushButton( i18n("&New..."), this ); 00364 lo->addWidget( btnNew, 5, 0 ); 00365 connect( btnNew, SIGNAL(clicked()), this, SLOT(slotNew()) ); 00366 00367 btnRemove = new QPushButton( i18n("&Remove"), this ); 00368 lo->addWidget( btnRemove, 5, 2 ); 00369 connect( btnRemove, SIGNAL(clicked()), this, SLOT(slotRemove()) ); 00370 00371 btnEdit = new QPushButton( i18n("&Edit..."), this ); 00372 lo->addWidget( btnEdit, 5, 1 ); 00373 connect( btnEdit, SIGNAL(clicked()), this, SLOT(slotEdit()) ); 00374 00375 QPushButton *b = new QPushButton( i18n("Insert &Separator"), this ); 00376 lo->addWidget( b, 5, 3 ); 00377 connect( b, SIGNAL(clicked()), this, SLOT(slotInsertSeparator()) ); 00378 00379 btnMoveUp = new QPushButton( SmallIconSet("up"), "", this ); 00380 lo->addWidget( btnMoveUp, 2, 4 ); 00381 connect( btnMoveUp, SIGNAL(clicked()), this, SLOT(slotMoveUp()) ); 00382 00383 btnMoveDwn = new QPushButton( SmallIconSet("down"), "", this ); 00384 lo->addWidget( btnMoveDwn, 3, 4 ); 00385 connect( btnMoveDwn, SIGNAL(clicked()), this, SLOT(slotMoveDown()) ); 00386 00387 lo->setRowStretch( 1, 1 ); 00388 lo->setRowStretch( 4, 1 ); 00389 lo->setColStretch( 0, 1 ); 00390 lo->setColStretch( 1, 1 ); 00391 lo->setColStretch( 2, 1 ); 00392 00393 00394 QWhatsThis::add( lbTools, i18n( 00395 "This list shows all the configured tools, represented by their menu text.") ); 00396 00397 00398 00399 reload(); 00400 slotSelectionChanged(); 00401 } 00402 00403 void KateExternalToolsConfigWidget::reload() 00404 { 00405 //m_tools.clear(); 00406 lbTools->clear(); 00407 00408 // load the files from a KConfig 00409 KConfig *config = new KConfig("externaltools", false, false, "appdata"); 00410 config->setGroup( "Global" ); 00411 QStringList tools = config->readListEntry("tools"); 00412 00413 for( QStringList::Iterator it = tools.begin(); it != tools.end(); ++it ) 00414 { 00415 if ( *it == "---" ) 00416 { 00417 new QListBoxText( lbTools, "---" ); 00418 } 00419 else 00420 { 00421 config->setGroup( *it ); 00422 00423 KateExternalTool *t = new KateExternalTool( 00424 config->readEntry( "name", "" ), 00425 config->readEntry( "command", ""), 00426 config->readEntry( "icon", ""), 00427 config->readEntry( "executable", ""), 00428 config->readListEntry( "mimetypes" ), 00429 config->readEntry( "acname" ) ); 00430 00431 if ( t->hasexec ) // we only show tools that are also in the menu. 00432 new ToolItem( lbTools, t->icon.isEmpty() ? blankIcon() : SmallIcon( t->icon ), t ); 00433 } 00434 } 00435 00436 00437 } 00438 00439 QPixmap KateExternalToolsConfigWidget::blankIcon() 00440 { 00441 QPixmap pm( KIcon::SizeSmall, KIcon::SizeSmall ); 00442 pm.fill(); 00443 pm.setMask( pm.createHeuristicMask() ); 00444 return pm; 00445 } 00446 00447 void KateExternalToolsConfigWidget::apply() 00448 { 00449 KConfig *config = new KConfig("externaltools", false, false, "appdata"); 00450 // save a new list 00451 // save each item 00452 QStringList tools; 00453 for ( uint i = 0; i < lbTools->count(); i++ ) 00454 { 00455 if ( lbTools->text( i ) == "---" ) 00456 { 00457 tools << "---"; 00458 continue; 00459 } 00460 KateExternalTool *t = ((ToolItem*)lbTools->item( i ))->tool; 00461 kdDebug()<<"adding tool: "<<t->name<<endl; 00462 tools << t->acname; 00463 00464 config->setGroup( t->acname ); 00465 config->writeEntry( "name", t->name ); 00466 config->writeEntry( "command", t->command ); 00467 config->writeEntry( "icon", t->icon ); 00468 config->writeEntry( "executable", t->tryexec ); 00469 config->writeEntry( "mimetypes", t->mimetypes ); 00470 config->writeEntry( "acname", t->acname ); 00471 } 00472 00473 config->setGroup("Global"); 00474 config->writeEntry( "tools", tools ); 00475 00476 config->sync(); 00477 } 00478 00479 void KateExternalToolsConfigWidget::slotSelectionChanged() 00480 { 00481 // update button state 00482 bool hs = lbTools->selectedItem() != 0; 00483 btnEdit->setEnabled( hs && static_cast<ToolItem*>(lbTools->selectedItem()) ); 00484 btnRemove->setEnabled( hs ); 00485 btnMoveUp->setEnabled( lbTools->currentItem() > 0 ); 00486 btnMoveDwn->setEnabled( lbTools->currentItem() < (int)lbTools->count()-1 ); 00487 } 00488 00489 void KateExternalToolsConfigWidget::slotNew() 00490 { 00491 // display a editor, and if it is OK'd, create a new tool and 00492 // create a listbox item for it 00493 KateExternalToolServiceEditor editor( 0, this ); 00494 00495 if ( editor.exec() ) 00496 { 00497 KateExternalTool *t = new KateExternalTool( 00498 editor.leName->text(), 00499 editor.leCommand->text(), 00500 editor.btnIcon->icon(), 00501 editor.leExecutable->text(), 00502 QStringList::split( QRegExp("\\s*;\\s*"), editor.leMimetypes->text() ) ); 00503 00504 // This is sticky, it does not change again, so that shortcuts sticks 00505 // TODO check for dups 00506 t->acname = "externaltool_" + QString(t->name).replace( QRegExp("\\W+"), "" ); 00507 00508 new ToolItem ( lbTools, t->icon.isEmpty() ? blankIcon() : SmallIcon( t->icon ), t ); 00509 00510 slotChanged(); 00511 } 00512 } 00513 00514 void KateExternalToolsConfigWidget::slotRemove() 00515 { 00516 // just remove the current listbox item 00517 if ( lbTools->currentItem() > -1 ) { 00518 lbTools->removeItem( lbTools->currentItem() ); 00519 slotChanged(); 00520 } 00521 } 00522 00523 void KateExternalToolsConfigWidget::slotEdit() 00524 { 00525 // show the item in an editor 00526 KateExternalTool *t = ((ToolItem*)lbTools->selectedItem())->tool; 00527 KateExternalToolServiceEditor editor( t, this); 00528 if ( editor.exec() /*== KDialogBase::Ok*/ ) 00529 { 00530 00531 bool iconChanged = ( editor.btnIcon->icon() != t->icon ); 00532 00533 t->name = editor.leName->text(); 00534 t->command = editor.leCommand->text(); 00535 t->icon = editor.btnIcon->icon(); 00536 t->tryexec = editor.leExecutable->text(); 00537 t->mimetypes = QStringList::split( QRegExp("\\s*;\\s*"), editor.leMimetypes->text() ); 00538 00539 //if the icon has changed, I have to renew the listbox item :S 00540 if ( iconChanged ) 00541 { 00542 int idx = lbTools->index( lbTools->selectedItem() ); 00543 lbTools->removeItem( idx ); 00544 lbTools->insertItem( new ToolItem( 0, t->icon.isEmpty() ? blankIcon() : SmallIcon( t->icon ), t ), idx ); 00545 } 00546 00547 slotChanged(); 00548 } 00549 } 00550 00551 void KateExternalToolsConfigWidget::slotInsertSeparator() 00552 { 00553 lbTools->insertItem( "---", lbTools->currentItem()+1 ); 00554 } 00555 00556 void KateExternalToolsConfigWidget::slotMoveUp() 00557 { 00558 // move the current item in the listbox upwards if possible 00559 QListBoxItem *item = lbTools->selectedItem(); 00560 if ( ! item ) return; 00561 00562 int idx = lbTools->index( item ); 00563 00564 if ( idx < 1 ) return; 00565 00566 if ( dynamic_cast<ToolItem*>(item) ) 00567 { 00568 KateExternalTool *tool = ((ToolItem*)item)->tool; 00569 lbTools->removeItem( idx ); 00570 lbTools->insertItem( new ToolItem( 0, tool->icon.isEmpty() ? blankIcon() : SmallIcon( tool->icon ), tool ), idx-1 ); 00571 } 00572 else // a separator! 00573 { 00574 lbTools->removeItem( idx ); 00575 lbTools->insertItem( new QListBoxText( 0, "---" ), idx-1 ); 00576 } 00577 00578 lbTools->setCurrentItem( idx - 1 ); 00579 slotSelectionChanged(); 00580 } 00581 00582 void KateExternalToolsConfigWidget::slotMoveDown() 00583 { 00584 // move the current item in the listbox downwards if possible 00585 QListBoxItem *item = lbTools->selectedItem(); 00586 if ( ! item ) return; 00587 00588 uint idx = lbTools->index( item ); 00589 00590 if ( idx > lbTools->count()-1 ) return; 00591 00592 if ( dynamic_cast<ToolItem*>(item) ) 00593 { 00594 KateExternalTool *tool = ((ToolItem*)item)->tool; 00595 lbTools->removeItem( idx ); 00596 lbTools->insertItem( new ToolItem( 0, tool->icon.isEmpty() ? blankIcon() : SmallIcon( tool->icon ), tool ), idx+1 ); 00597 } 00598 else // a separator! 00599 { 00600 lbTools->removeItem( idx ); 00601 lbTools->insertItem( new QListBoxText( 0, "---" ), idx+1 ); 00602 } 00603 00604 lbTools->setCurrentItem( idx+1 ); 00605 slotSelectionChanged(); 00606 } 00607 //END KateExternalToolsConfigWidget
KDE Logo
This file is part of the documentation for kate Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 13 21:47:01 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003