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., 51 Franklin Street, Fifth Floor, 00016 Boston, MA 02110-1301, USA. 00017 00018 --- 00019 Copyright (C) 2004, Anders Lund <anders@alweb.dk> 00020 */ 00021 // TODO 00022 // Icons 00023 // Direct shortcut setting 00024 //BEGIN Includes 00025 #include "kateexternaltools.h" 00026 #include "kateexternaltools.moc" 00027 #include "katedocmanager.h" 00028 #include "kateviewmanager.h" 00029 #include "kateapp.h" 00030 00031 #include "katemainwindow.h" 00032 00033 #include <kate/view.h> 00034 #include <kate/document.h> 00035 00036 #include <tdelistbox.h> 00037 #include <tdelocale.h> 00038 #include <kiconloader.h> 00039 #include <tdemessagebox.h> 00040 #include <kmimetypechooser.h> 00041 #include <tdeconfig.h> 00042 #include <krun.h> 00043 #include <kicondialog.h> 00044 #include <tdepopupmenu.h> 00045 #include <kdebug.h> 00046 00047 #include <tqbitmap.h> 00048 #include <tqcombobox.h> 00049 #include <tqfile.h> 00050 #include <tqpushbutton.h> 00051 #include <tqlineedit.h> 00052 #include <tqlayout.h> 00053 #include <tqlabel.h> 00054 #include <tqlistbox.h> 00055 #include <tqmap.h> 00056 #include <tqregexp.h> 00057 #include <tqtextedit.h> 00058 #include <tqtoolbutton.h> 00059 #include <tqwhatsthis.h> 00060 00061 #include <stdlib.h> 00062 #include <unistd.h> 00063 //END Includes 00064 00065 KateExternalToolsCommand *KateExternalToolsCommand::s_self=0; 00066 00067 //BEGIN KateExternalTool 00068 KateExternalTool::KateExternalTool( const TQString &name, 00069 const TQString &command, 00070 const TQString &icon, 00071 const TQString &tryexec, 00072 const TQStringList &mimetypes, 00073 const TQString &acname, 00074 const TQString &cmdname, 00075 int save ) 00076 : name ( name ), 00077 command ( command ), 00078 icon ( icon ), 00079 tryexec ( tryexec ), 00080 mimetypes ( mimetypes ), 00081 acname ( acname ), 00082 cmdname ( cmdname ), 00083 save ( save ) 00084 { 00085 //if ( ! tryexec.isEmpty() ) 00086 hasexec = checkExec(); 00087 } 00088 00089 bool KateExternalTool::checkExec() 00090 { 00091 // if tryexec is empty, it is the first word of command 00092 if ( tryexec.isEmpty() ) 00093 tryexec = command.section( " ", 0, 0, TQString::SectionSkipEmpty ); 00094 00095 // NOTE this code is modified taken from kdesktopfile.cpp, from KDesktopFile::tryExec() 00096 if (!tryexec.isEmpty()) { 00097 if (tryexec[0] == '/') { 00098 if (::access(TQFile::encodeName(tryexec), R_OK | X_OK)) 00099 return false; 00100 00101 m_exec = tryexec; 00102 } else { 00103 // !!! Sergey A. Sukiyazov <corwin@micom.don.ru> !!! 00104 // Environment PATH may contain filenames in 8bit locale cpecified 00105 // encoding (Like a filenames). 00106 TQStringList dirs = TQStringList::split(':', TQFile::decodeName(::getenv("PATH"))); 00107 TQStringList::Iterator it(dirs.begin()); 00108 bool match = false; 00109 for (; it != dirs.end(); ++it) 00110 { 00111 TQString fName = *it + "/" + tryexec; 00112 if (::access(TQFile::encodeName(fName), R_OK | X_OK) == 0) 00113 { 00114 match = true; 00115 m_exec = fName; 00116 break; 00117 } 00118 } 00119 // didn't match at all 00120 if (!match) 00121 return false; 00122 } 00123 return true; 00124 } 00125 return false; 00126 } 00127 00128 bool KateExternalTool::valid( const TQString &mt ) const 00129 { 00130 return mimetypes.isEmpty() || mimetypes.contains( mt ); 00131 } 00132 //END KateExternalTool 00133 00134 //BEGIN KateExternalToolsCommand 00135 KateExternalToolsCommand::KateExternalToolsCommand() : Kate::Command() { 00136 m_inited=false; 00137 reload(); 00138 } 00139 00140 TQStringList KateExternalToolsCommand::cmds () { 00141 return m_list; 00142 } 00143 00144 KateExternalToolsCommand *KateExternalToolsCommand::self () { 00145 if (s_self) return s_self; 00146 s_self=new KateExternalToolsCommand; 00147 return s_self; 00148 } 00149 00150 void KateExternalToolsCommand::reload () { 00151 m_list.clear(); 00152 m_map.clear(); 00153 00154 TDEConfig config("externaltools", false, false, "appdata"); 00155 config.setGroup("Global"); 00156 TQStringList tools = config.readListEntry("tools"); 00157 00158 00159 for( TQStringList::Iterator it = tools.begin(); it != tools.end(); ++it ) 00160 { 00161 if ( *it == "---" ) 00162 continue; 00163 00164 00165 config.setGroup( *it ); 00166 00167 KateExternalTool t = KateExternalTool( 00168 config.readEntry( "name", "" ), 00169 config.readEntry( "command", ""), 00170 config.readEntry( "icon", ""), 00171 config.readEntry( "executable", ""), 00172 config.readListEntry( "mimetypes" ), 00173 config.readEntry( "acname", "" ), 00174 config.readEntry( "cmdname", "" ) ); 00175 // FIXME test for a command name first! 00176 if ( t.hasexec && (!t.cmdname.isEmpty())) { 00177 m_list.append("exttool-"+t.cmdname); 00178 m_map.insert("exttool-"+t.cmdname,t.acname); 00179 } 00180 } 00181 if (m_inited) { 00182 Kate::Document::unregisterCommand(this); 00183 Kate::Document::registerCommand(this); 00184 } 00185 else m_inited=true; 00186 } 00187 00188 bool KateExternalToolsCommand::exec (Kate::View *view, const TQString &cmd, TQString &) { 00189 TQWidget *wv=tqt_dynamic_cast<TQWidget*>(view); 00190 if (!wv) { 00191 // kdDebug(13001)<<"KateExternalToolsCommand::exec: Could not get view widget"<<endl; 00192 return false; 00193 } 00194 KateMDI::MainWindow *dmw=tqt_dynamic_cast<KateMDI::MainWindow*>(wv->topLevelWidget()); 00195 if (!dmw) { 00196 // kdDebug(13001)<<"KateExternalToolsCommand::exec: Could not get main window"<<endl; 00197 return false; 00198 } 00199 // kdDebug(13001)<<"cmd="<<cmd.stripWhiteSpace()<<endl; 00200 TQString actionName=m_map[cmd.stripWhiteSpace()]; 00201 if (actionName.isEmpty()) return false; 00202 // kdDebug(13001)<<"actionName is not empty:"<<actionName<<endl; 00203 KateExternalToolsMenuAction *a= 00204 tqt_dynamic_cast<KateExternalToolsMenuAction*>(dmw->action("tools_external")); 00205 if (!a) return false; 00206 // kdDebug(13001)<<"trying to find action"<<endl; 00207 TDEAction *a1=a->actionCollection()->action(static_cast<const char *>(actionName.utf8())); 00208 if (!a1) return false; 00209 // kdDebug(13001)<<"activating action"<<endl; 00210 a1->activate(); 00211 return true; 00212 } 00213 00214 bool KateExternalToolsCommand::help (Kate::View *, const TQString &, TQString &) { 00215 return false; 00216 } 00217 //END KateExternalToolsCommand 00218 00219 //BEGIN KateExternalToolAction 00220 KateExternalToolAction::KateExternalToolAction( TQObject *parent, 00221 const char *name, KateExternalTool *t) 00222 : TDEAction( parent, name ), 00223 tool ( t ) 00224 { 00225 setText( t->name ); 00226 if ( ! t->icon.isEmpty() ) 00227 setIconSet( SmallIconSet( t->icon ) ); 00228 00229 connect( this ,TQT_SIGNAL(activated()), this, TQT_SLOT(slotRun()) ); 00230 } 00231 00232 bool KateExternalToolAction::expandMacro( const TQString &str, TQStringList &ret ) 00233 { 00234 KateMainWindow *mw = (KateMainWindow*)parent()->parent(); 00235 00236 Kate::View *view = mw->viewManager()->activeView(); 00237 if ( ! view ) return false; 00238 00239 00240 if ( str == "URL" ) 00241 ret += mw->activeDocumentUrl().url(); 00242 else if ( str == "directory" ) // directory of current doc 00243 ret += mw->activeDocumentUrl().directory(); 00244 else if ( str == "filename" ) 00245 ret += mw->activeDocumentUrl().fileName(); 00246 else if ( str == "line" ) // cursor line of current doc 00247 ret += TQString::number( view->cursorLine() ); 00248 else if ( str == "col" ) // cursor col of current doc 00249 ret += TQString::number( view->cursorColumn() ); 00250 else if ( str == "selection" ) // selection of current doc if any 00251 ret += view->getDoc()->selection(); 00252 else if ( str == "text" ) // text of current doc 00253 ret += view->getDoc()->text(); 00254 else if ( str == "URLs" ) { 00255 for( Kate::Document *doc = KateDocManager::self()->firstDocument(); doc; doc = KateDocManager::self()->nextDocument() ) 00256 if ( ! doc->url().isEmpty() ) 00257 ret += doc->url().url(); 00258 } else 00259 return false; 00260 return true; 00261 } 00262 00263 KateExternalToolAction::~KateExternalToolAction() { 00264 delete(tool); 00265 } 00266 00267 void KateExternalToolAction::slotRun() 00268 { 00269 // expand the macros in command if any, 00270 // and construct a command with an absolute path 00271 TQString cmd = tool->command; 00272 00273 if ( ! expandMacrosShellQuote( cmd ) ) 00274 { 00275 KMessageBox::sorry( (KateMainWindow*)parent()->parent(), 00276 i18n("Failed to expand the command '%1'.").arg( cmd ), 00277 i18n( "Kate External Tools") ); 00278 return; 00279 } 00280 kdDebug(13001)<<"externaltools: Running command: "<<cmd<<endl; 00281 00282 // save documents if requested 00283 KateMainWindow *mw = (KateMainWindow*)parent()->parent(); 00284 if ( tool->save == 1 ) 00285 mw->viewManager()->activeView()->document()->save(); 00286 else if ( tool->save == 2 ) 00287 mw->actionCollection()->action("file_save_all")->activate(); 00288 00289 KRun::runCommand( cmd, tool->tryexec, tool->icon ); 00290 } 00291 //END KateExternalToolAction 00292 00293 //BEGIN KateExternalToolsMenuAction 00294 KateExternalToolsMenuAction::KateExternalToolsMenuAction( const TQString &text, 00295 TQObject *parent, 00296 const char* name, 00297 KateMainWindow *mw ) 00298 : TDEActionMenu( text, parent, name ), 00299 mainwindow( mw ) 00300 { 00301 00302 m_actionCollection = new TDEActionCollection( mainwindow ); 00303 00304 connect(KateDocManager::self(),TQT_SIGNAL(documentChanged()),this,TQT_SLOT(slotDocumentChanged())); 00305 00306 reload(); 00307 } 00308 00309 void KateExternalToolsMenuAction::reload() 00310 { 00311 m_actionCollection->clear (); 00312 popupMenu()->clear(); 00313 00314 // load all the tools, and create a action for each of them 00315 TDEConfig *config = new TDEConfig( "externaltools", false, false, "appdata" ); 00316 config->setGroup( "Global" ); 00317 TQStringList tools = config->readListEntry( "tools" ); 00318 00319 // if there are tools that are present but not explicitly removed, 00320 // add them to the end of the list 00321 config->setReadDefaults( true ); 00322 TQStringList dtools = config->readListEntry( "tools" ); 00323 int gver = config->readNumEntry( "version", 1 ); 00324 config->setReadDefaults( false ); 00325 00326 int ver = config->readNumEntry( "version" ); 00327 if ( ver <= gver ) 00328 { 00329 TQStringList removed = config->readListEntry( "removed" ); 00330 bool sepadded = false; 00331 for (TQStringList::iterator itg = dtools.begin(); itg != dtools.end(); ++itg ) 00332 { 00333 if ( ! tools.contains( *itg ) && 00334 ! removed.contains( *itg ) ) 00335 { 00336 if ( ! sepadded ) 00337 { 00338 tools << "---"; 00339 sepadded = true; 00340 } 00341 tools << *itg; 00342 } 00343 } 00344 00345 config->writeEntry( "tools", tools ); 00346 config->sync(); 00347 config->writeEntry( "version", gver ); 00348 } 00349 00350 for( TQStringList::Iterator it = tools.begin(); it != tools.end(); ++it ) 00351 { 00352 if ( *it == "---" ) 00353 { 00354 popupMenu()->insertSeparator(); 00355 // a separator 00356 continue; 00357 } 00358 00359 config->setGroup( *it ); 00360 00361 KateExternalTool *t = new KateExternalTool( 00362 config->readEntry( "name", "" ), 00363 config->readEntry( "command", ""), 00364 config->readEntry( "icon", ""), 00365 config->readEntry( "executable", ""), 00366 config->readListEntry( "mimetypes" ), 00367 config->readEntry( "acname", "" ), 00368 config->readEntry( "cmdname", "" ), 00369 config->readNumEntry( "save", 0 ) ); 00370 00371 if ( t->hasexec ) 00372 insert( new KateExternalToolAction( m_actionCollection, t->acname.ascii(), t ) ); 00373 } 00374 00375 m_actionCollection->readShortcutSettings( "Shortcuts", config ); 00376 slotDocumentChanged(); 00377 delete config; 00378 } 00379 00380 void KateExternalToolsMenuAction::slotDocumentChanged() 00381 { 00382 // try to enable/disable to match current mime type 00383 Kate::DocumentExt *de = documentExt( KateDocManager::self()->activeDocument() ); 00384 if ( de ) 00385 { 00386 TQString mt = de->mimeType(); 00387 TQStringList l; 00388 bool b; 00389 00390 TDEActionPtrList actions = m_actionCollection->actions(); 00391 for (TDEActionPtrList::iterator it = actions.begin(); it != actions.end(); ++it ) 00392 { 00393 KateExternalToolAction *action = tqt_dynamic_cast<KateExternalToolAction*>(*it); 00394 if ( action ) 00395 { 00396 l = action->tool->mimetypes; 00397 b = ( ! l.count() || l.contains( mt ) ); 00398 action->setEnabled( b ); 00399 } 00400 } 00401 } 00402 } 00403 //END KateExternalToolsMenuAction 00404 00405 //BEGIN ToolItem 00410 class ToolItem : public TQListBoxPixmap 00411 { 00412 public: 00413 ToolItem( TQListBox *lb, const TQPixmap &icon, KateExternalTool *tool ) 00414 : TQListBoxPixmap( lb, icon, tool->name ), 00415 tool ( tool ) 00416 {;} 00417 00418 ~ToolItem() {}; 00419 00420 KateExternalTool *tool; 00421 }; 00422 //END ToolItem 00423 00424 //BEGIN KateExternalToolServiceEditor 00425 KateExternalToolServiceEditor::KateExternalToolServiceEditor( KateExternalTool *tool, 00426 TQWidget *parent, const char *name ) 00427 : KDialogBase( parent, name, true, i18n("Edit External Tool"), KDialogBase::Ok|KDialogBase::Cancel ), 00428 tool( tool ) 00429 { 00430 // create a entry for each property 00431 // fill in the values from the service if available 00432 TQWidget *w = new TQWidget( this ); 00433 setMainWidget( w ); 00434 TQGridLayout *lo = new TQGridLayout( w ); 00435 lo->setSpacing( KDialogBase::spacingHint() ); 00436 00437 TQLabel *l; 00438 00439 leName = new TQLineEdit( w ); 00440 lo->addWidget( leName, 1, 2 ); 00441 l = new TQLabel( leName, i18n("&Label:"), w ); 00442 l->setAlignment( l->alignment()|Qt::AlignRight ); 00443 lo->addWidget( l, 1, 1 ); 00444 if ( tool ) leName->setText( tool->name ); 00445 TQWhatsThis::add( leName, i18n( 00446 "The name will be displayed in the 'Tools->External' menu") ); 00447 00448 btnIcon = new TDEIconButton( w ); 00449 btnIcon->setIconSize( TDEIcon::SizeSmall ); 00450 lo->addWidget( btnIcon, 1, 3 ); 00451 if ( tool && !tool->icon.isEmpty() ) 00452 btnIcon->setIcon( tool->icon ); 00453 00454 teCommand = new TQTextEdit( w ); 00455 lo->addMultiCellWidget( teCommand, 2, 2, 2, 3 ); 00456 l = new TQLabel( teCommand, i18n("S&cript:"), w ); 00457 l->setAlignment( Qt::AlignTop|Qt::AlignRight ); 00458 lo->addWidget( l, 2, 1 ); 00459 if ( tool ) teCommand->setText( tool->command ); 00460 TQWhatsThis::add( teCommand, i18n( 00461 "<p>The script to execute to invoke the tool. The script is passed " 00462 "to /bin/sh for execution. The following macros " 00463 "will be expanded:</p>" 00464 "<ul><li><code>%URL</code> - the URL of the current document." 00465 "<li><code>%URLs</code> - a list of the URLs of all open documents." 00466 "<li><code>%directory</code> - the URL of the directory containing " 00467 "the current document." 00468 "<li><code>%filename</code> - the filename of the current document." 00469 "<li><code>%line</code> - the current line of the text cursor in the " 00470 "current view." 00471 "<li><code>%column</code> - the column of the text cursor in the " 00472 "current view." 00473 "<li><code>%selection</code> - the selected text in the current view." 00474 "<li><code>%text</code> - the text of the current document.</ul>" ) ); 00475 00476 00477 leExecutable = new TQLineEdit( w ); 00478 lo->addMultiCellWidget( leExecutable, 3, 3, 2, 3 ); 00479 l = new TQLabel( leExecutable, i18n("&Executable:"), w ); 00480 l->setAlignment( l->alignment()|Qt::AlignRight ); 00481 lo->addWidget( l, 3, 1 ); 00482 if ( tool ) leExecutable->setText( tool->tryexec ); 00483 TQWhatsThis::add( leExecutable, i18n( 00484 "The executable used by the command. This is used to check if a tool " 00485 "should be displayed; if not set, the first word of <em>command</em> " 00486 "will be used.") ); 00487 00488 leMimetypes = new TQLineEdit( w ); 00489 lo->addWidget( leMimetypes, 4, 2 ); 00490 l = new TQLabel( leMimetypes, i18n("&Mime types:"), w ); 00491 l->setAlignment( l->alignment()|Qt::AlignRight ); 00492 lo->addWidget( l, 4, 1 ); 00493 if ( tool ) leMimetypes->setText( tool->mimetypes.join("; ") ); 00494 TQWhatsThis::add( leMimetypes, i18n( 00495 "A semicolon-separated list of mime types for which this tool should " 00496 "be available; if this is left empty, the tool is always available. " 00497 "To choose from known mimetypes, press the button on the right.") ); 00498 00499 TQToolButton *btnMTW = new TQToolButton(w); 00500 lo->addWidget( btnMTW, 4, 3 ); 00501 btnMTW->setIconSet(TQIconSet(SmallIcon("wizard"))); 00502 connect(btnMTW, TQT_SIGNAL(clicked()), this, TQT_SLOT(showMTDlg())); 00503 TQWhatsThis::add( btnMTW, i18n( 00504 "Click for a dialog that can help you creating a list of mimetypes.") ); 00505 00506 cmbSave = new TQComboBox(w); 00507 lo->addMultiCellWidget( cmbSave, 5, 5, 2, 3 ); 00508 l = new TQLabel( cmbSave, i18n("&Save:"), w ); 00509 l->setAlignment( l->alignment()|Qt::AlignRight ); 00510 lo->addWidget( l, 5, 1 ); 00511 TQStringList sl; 00512 sl << i18n("None") << i18n("Current Document") << i18n("All Documents"); 00513 cmbSave->insertStringList( sl ); 00514 if ( tool ) cmbSave->setCurrentItem( tool->save ); 00515 TQWhatsThis::add( cmbSave, i18n( 00516 "You can elect to save the current or all [modified] documents prior to " 00517 "running the command. This is helpful if you want to pass URLs to " 00518 "an application like, for example, an FTP client.") ); 00519 00520 00521 leCmdLine = new TQLineEdit( w ); 00522 lo->addMultiCellWidget( leCmdLine, 6, 6, 2, 3 ); 00523 l = new TQLabel( leCmdLine, i18n("&Command line name:"), w ); 00524 l->setAlignment( l->alignment()|Qt::AlignRight ); 00525 lo->addWidget( l, 6, 1 ); 00526 if ( tool ) leCmdLine->setText( tool->cmdname ); 00527 TQWhatsThis::add( leCmdLine, i18n( 00528 "If you specify a name here, you can invoke the command from the view " 00529 "command lines with exttool-the_name_you_specified_here. " 00530 "Please do not use spaces or tabs in the name.")); 00531 00532 } 00533 00534 void KateExternalToolServiceEditor::slotOk() 00535 { 00536 if ( leName->text().isEmpty() || 00537 teCommand->text().isEmpty() ) 00538 { 00539 KMessageBox::information( this, i18n("You must specify at least a name and a command") ); 00540 return; 00541 } 00542 00543 KDialogBase::slotOk(); 00544 } 00545 00546 void KateExternalToolServiceEditor::showMTDlg() 00547 { 00548 TQString text = i18n("Select the MimeTypes for which to enable this tool."); 00549 TQStringList list = TQStringList::split( TQRegExp("\\s*;\\s*"), leMimetypes->text() ); 00550 KMimeTypeChooserDialog d( i18n("Select Mime Types"), text, list, "text", this ); 00551 if ( d.exec() == KDialogBase::Accepted ) { 00552 leMimetypes->setText( d.chooser()->mimeTypes().join(";") ); 00553 } 00554 } 00555 //END KateExternalToolServiceEditor 00556 00557 //BEGIN KateExternalToolsConfigWidget 00558 KateExternalToolsConfigWidget::KateExternalToolsConfigWidget( TQWidget *parent, const char* name ) 00559 : Kate::ConfigPage( parent, name ), 00560 m_changed( false ) 00561 { 00562 TQGridLayout *lo = new TQGridLayout( this, 5, 5, 0, KDialog::spacingHint() ); 00563 00564 lbTools = new TDEListBox( this ); 00565 lo->addMultiCellWidget( lbTools, 1, 4, 0, 3 ); 00566 connect( lbTools, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(slotSelectionChanged()) ); 00567 00568 btnNew = new TQPushButton( i18n("&New..."), this ); 00569 lo->addWidget( btnNew, 5, 0 ); 00570 connect( btnNew, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotNew()) ); 00571 00572 btnRemove = new TQPushButton( i18n("&Remove"), this ); 00573 lo->addWidget( btnRemove, 5, 2 ); 00574 connect( btnRemove, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotRemove()) ); 00575 00576 btnEdit = new TQPushButton( i18n("&Edit..."), this ); 00577 lo->addWidget( btnEdit, 5, 1 ); 00578 connect( btnEdit, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotEdit()) ); 00579 00580 TQPushButton *b = new TQPushButton( i18n("Insert &Separator"), this ); 00581 lo->addWidget( b, 5, 3 ); 00582 connect( b, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotInsertSeparator()) ); 00583 00584 btnMoveUp = new TQPushButton( SmallIconSet("go-up"), "", this ); 00585 lo->addWidget( btnMoveUp, 2, 4 ); 00586 connect( btnMoveUp, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotMoveUp()) ); 00587 00588 btnMoveDwn = new TQPushButton( SmallIconSet("go-down"), "", this ); 00589 lo->addWidget( btnMoveDwn, 3, 4 ); 00590 connect( btnMoveDwn, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotMoveDown()) ); 00591 00592 connect( lbTools, TQT_SIGNAL( doubleClicked ( TQListBoxItem * ) ), this, TQT_SLOT( slotEdit() ) ); 00593 00594 lo->setRowStretch( 1, 1 ); 00595 lo->setRowStretch( 4, 1 ); 00596 lo->setColStretch( 0, 1 ); 00597 lo->setColStretch( 1, 1 ); 00598 lo->setColStretch( 2, 1 ); 00599 00600 00601 TQWhatsThis::add( lbTools, i18n( 00602 "This list shows all the configured tools, represented by their menu text.") ); 00603 00604 config = new TDEConfig("externaltools", false, false, "appdata"); 00605 reload(); 00606 slotSelectionChanged(); 00607 } 00608 00609 KateExternalToolsConfigWidget::~KateExternalToolsConfigWidget() 00610 { 00611 delete config; 00612 } 00613 00614 void KateExternalToolsConfigWidget::reload() 00615 { 00616 //m_tools.clear(); 00617 lbTools->clear(); 00618 00619 // load the files from a TDEConfig 00620 config->setGroup( "Global" ); 00621 TQStringList tools = config->readListEntry("tools"); 00622 00623 for( TQStringList::Iterator it = tools.begin(); it != tools.end(); ++it ) 00624 { 00625 if ( *it == "---" ) 00626 { 00627 new TQListBoxText( lbTools, "---" ); 00628 } 00629 else 00630 { 00631 config->setGroup( *it ); 00632 00633 KateExternalTool *t = new KateExternalTool( 00634 config->readEntry( "name", "" ), 00635 config->readEntry( "command", ""), 00636 config->readEntry( "icon", ""), 00637 config->readEntry( "executable", ""), 00638 config->readListEntry( "mimetypes" ), 00639 config->readEntry( "acname" ), 00640 config->readEntry( "cmdname"), 00641 config->readNumEntry( "save", 0 ) ); 00642 00643 if ( t->hasexec ) // we only show tools that are also in the menu. 00644 new ToolItem( lbTools, t->icon.isEmpty() ? blankIcon() : SmallIcon( t->icon ), t ); 00645 } 00646 } 00647 m_changed = false; 00648 } 00649 00650 TQPixmap KateExternalToolsConfigWidget::blankIcon() 00651 { 00652 TQPixmap pm( TDEIcon::SizeSmall, TDEIcon::SizeSmall ); 00653 pm.fill(); 00654 pm.setMask( pm.createHeuristicMask() ); 00655 return pm; 00656 } 00657 00658 void KateExternalToolsConfigWidget::apply() 00659 { 00660 if ( ! m_changed ) 00661 return; 00662 m_changed = false; 00663 00664 // save a new list 00665 // save each item 00666 TQStringList tools; 00667 for ( uint i = 0; i < lbTools->count(); i++ ) 00668 { 00669 if ( lbTools->text( i ) == "---" ) 00670 { 00671 tools << "---"; 00672 continue; 00673 } 00674 KateExternalTool *t = ((ToolItem*)lbTools->item( i ))->tool; 00675 // kdDebug(13001)<<"adding tool: "<<t->name<<endl; 00676 tools << t->acname; 00677 00678 config->setGroup( t->acname ); 00679 config->writeEntry( "name", t->name ); 00680 config->writeEntry( "command", t->command ); 00681 config->writeEntry( "icon", t->icon ); 00682 config->writeEntry( "executable", t->tryexec ); 00683 config->writeEntry( "mimetypes", t->mimetypes ); 00684 config->writeEntry( "acname", t->acname ); 00685 config->writeEntry( "cmdname", t->cmdname ); 00686 config->writeEntry( "save", t->save ); 00687 } 00688 00689 config->setGroup("Global"); 00690 config->writeEntry( "tools", tools ); 00691 00692 // if any tools was removed, try to delete their groups, and 00693 // add the group names to the list of removed items. 00694 if ( m_removed.count() ) 00695 { 00696 for ( TQStringList::iterator it = m_removed.begin(); it != m_removed.end(); ++it ) 00697 { 00698 if ( config->hasGroup( *it ) ) 00699 config->deleteGroup( *it ); 00700 } 00701 TQStringList removed = config->readListEntry( "removed" ); 00702 removed += m_removed; 00703 00704 // clean up the list of removed items, so that it does not contain 00705 // non-existing groups (we can't remove groups from a non-owned global file). 00706 config->sync(); 00707 TQStringList::iterator it1 = removed.begin(); 00708 while( it1 != removed.end() ) 00709 { 00710 if ( ! config->hasGroup( *it1 ) ) 00711 it1 = removed.remove( it1 ); 00712 else 00713 ++it1; 00714 } 00715 config->writeEntry( "removed", removed ); 00716 } 00717 00718 config->sync(); 00719 } 00720 00721 void KateExternalToolsConfigWidget::slotSelectionChanged() 00722 { 00723 // update button state 00724 bool hs = lbTools->selectedItem() != 0; 00725 btnEdit->setEnabled( hs && dynamic_cast<ToolItem*>(lbTools->selectedItem()) ); 00726 btnRemove->setEnabled( hs ); 00727 btnMoveUp->setEnabled( ( lbTools->currentItem() > 0 ) && hs ); 00728 btnMoveDwn->setEnabled( ( lbTools->currentItem() < (int)lbTools->count()-1 )&&hs ); 00729 } 00730 00731 void KateExternalToolsConfigWidget::slotNew() 00732 { 00733 // display a editor, and if it is OK'd, create a new tool and 00734 // create a listbox item for it 00735 KateExternalToolServiceEditor editor( 0, this ); 00736 00737 if ( editor.exec() ) 00738 { 00739 KateExternalTool *t = new KateExternalTool( 00740 editor.leName->text(), 00741 editor.teCommand->text(), 00742 editor.btnIcon->icon(), 00743 editor.leExecutable->text(), 00744 TQStringList::split( TQRegExp("\\s*;\\s*"), editor.leMimetypes->text() ) ); 00745 00746 // This is sticky, it does not change again, so that shortcuts sticks 00747 // TODO check for dups 00748 t->acname = "externaltool_" + TQString(t->name).replace( TQRegExp("\\W+"), "" ); 00749 00750 new ToolItem ( lbTools, t->icon.isEmpty() ? blankIcon() : SmallIcon( t->icon ), t ); 00751 00752 slotChanged(); 00753 m_changed = true; 00754 } 00755 } 00756 00757 void KateExternalToolsConfigWidget::slotRemove() 00758 { 00759 // add the tool action name to a list of removed items, 00760 // remove the current listbox item 00761 if ( lbTools->currentItem() > -1 ) { 00762 ToolItem *i = dynamic_cast<ToolItem*>(lbTools->selectedItem()); 00763 if ( i ) 00764 m_removed << i->tool->acname; 00765 00766 lbTools->removeItem( lbTools->currentItem() ); 00767 slotChanged(); 00768 m_changed = true; 00769 } 00770 } 00771 00772 void KateExternalToolsConfigWidget::slotEdit() 00773 { 00774 if( !dynamic_cast<ToolItem*>(lbTools->selectedItem()) ) return; 00775 // show the item in an editor 00776 KateExternalTool *t = ((ToolItem*)lbTools->selectedItem())->tool; 00777 KateExternalToolServiceEditor editor( t, this); 00778 config->setGroup( "Editor" ); 00779 editor.resize( config->readSizeEntry( "Size" ) ); 00780 if ( editor.exec() /*== KDialogBase::Ok*/ ) 00781 { 00782 00783 bool elementChanged = ( ( editor.btnIcon->icon() != t->icon ) || (editor.leName->text() != t->name ) ) ; 00784 00785 t->name = editor.leName->text(); 00786 t->cmdname = editor.leCmdLine->text(); 00787 t->command = editor.teCommand->text(); 00788 t->icon = editor.btnIcon->icon(); 00789 t->tryexec = editor.leExecutable->text(); 00790 t->mimetypes = TQStringList::split( TQRegExp("\\s*;\\s*"), editor.leMimetypes->text() ); 00791 t->save = editor.cmbSave->currentItem(); 00792 00793 //if the icon has changed or name changed, I have to renew the listbox item :S 00794 if ( elementChanged ) 00795 { 00796 int idx = lbTools->index( lbTools->selectedItem() ); 00797 lbTools->removeItem( idx ); 00798 lbTools->insertItem( new ToolItem( 0, t->icon.isEmpty() ? blankIcon() : SmallIcon( t->icon ), t ), idx ); 00799 } 00800 00801 slotChanged(); 00802 m_changed = true; 00803 } 00804 00805 config->setGroup( "Editor" ); 00806 config->writeEntry( "Size", editor.size() ); 00807 config->sync(); 00808 } 00809 00810 void KateExternalToolsConfigWidget::slotInsertSeparator() 00811 { 00812 lbTools->insertItem( "---", lbTools->currentItem()+1 ); 00813 slotChanged(); 00814 m_changed = true; 00815 } 00816 00817 void KateExternalToolsConfigWidget::slotMoveUp() 00818 { 00819 // move the current item in the listbox upwards if possible 00820 TQListBoxItem *item = lbTools->selectedItem(); 00821 if ( ! item ) return; 00822 00823 int idx = lbTools->index( item ); 00824 00825 if ( idx < 1 ) return; 00826 00827 if ( dynamic_cast<ToolItem*>(item) ) 00828 { 00829 KateExternalTool *tool = ((ToolItem*)item)->tool; 00830 lbTools->removeItem( idx ); 00831 lbTools->insertItem( new ToolItem( 0, tool->icon.isEmpty() ? blankIcon() : SmallIcon( tool->icon ), tool ), idx-1 ); 00832 } 00833 else // a separator! 00834 { 00835 lbTools->removeItem( idx ); 00836 lbTools->insertItem( new TQListBoxText( 0, "---" ), idx-1 ); 00837 } 00838 00839 lbTools->setCurrentItem( idx - 1 ); 00840 slotSelectionChanged(); 00841 slotChanged(); 00842 m_changed = true; 00843 } 00844 00845 void KateExternalToolsConfigWidget::slotMoveDown() 00846 { 00847 // move the current item in the listbox downwards if possible 00848 TQListBoxItem *item = lbTools->selectedItem(); 00849 if ( ! item ) return; 00850 00851 uint idx = lbTools->index( item ); 00852 00853 if ( idx > lbTools->count()-1 ) return; 00854 00855 if ( dynamic_cast<ToolItem*>(item) ) 00856 { 00857 KateExternalTool *tool = ((ToolItem*)item)->tool; 00858 lbTools->removeItem( idx ); 00859 lbTools->insertItem( new ToolItem( 0, tool->icon.isEmpty() ? blankIcon() : SmallIcon( tool->icon ), tool ), idx+1 ); 00860 } 00861 else // a separator! 00862 { 00863 lbTools->removeItem( idx ); 00864 lbTools->insertItem( new TQListBoxText( 0, "---" ), idx+1 ); 00865 } 00866 00867 lbTools->setCurrentItem( idx+1 ); 00868 slotSelectionChanged(); 00869 slotChanged(); 00870 m_changed = true; 00871 } 00872 //END KateExternalToolsConfigWidget 00873 // kate: space-indent on; indent-width 2; replace-tabs on;