25 #include "kateexternaltools.h"
26 #include "kateexternaltools.moc"
27 #include "katedocmanager.h"
28 #include "kateviewmanager.h"
31 #include "katemainwindow.h"
33 #include <kate/view.h>
34 #include <kate/document.h>
36 #include <tdelistbox.h>
37 #include <tdelocale.h>
38 #include <kiconloader.h>
39 #include <tdemessagebox.h>
40 #include <kmimetypechooser.h>
41 #include <tdeconfig.h>
43 #include <kicondialog.h>
44 #include <tdepopupmenu.h>
48 #include <tqcombobox.h>
50 #include <tqpushbutton.h>
51 #include <tqlineedit.h>
54 #include <tqlistbox.h>
57 #include <tqtextedit.h>
58 #include <tqtoolbutton.h>
59 #include <tqwhatsthis.h>
68 KateExternalTool::KateExternalTool(
const TQString &name,
69 const TQString &command,
71 const TQString &tryexec,
72 const TQStringList &mimetypes,
73 const TQString &acname,
74 const TQString &cmdname,
80 mimetypes ( mimetypes ),
86 hasexec = checkExec();
93 tryexec =
command.section(
" ", 0, 0, TQString::SectionSkipEmpty );
98 if (::access(TQFile::encodeName(
tryexec), R_OK | X_OK))
106 TQStringList dirs = TQStringList::split(
':', TQFile::decodeName(::getenv(
"PATH")));
107 TQStringList::Iterator it(dirs.begin());
109 for (; it != dirs.end(); ++it)
111 TQString fName = *it +
"/" +
tryexec;
112 if (::access(TQFile::encodeName(fName), R_OK | X_OK) == 0)
135 KateExternalToolsCommand::KateExternalToolsCommand() : Kate::Command() {
140 TQStringList KateExternalToolsCommand::cmds () {
145 if (s_self)
return s_self;
150 void KateExternalToolsCommand::reload () {
154 TDEConfig config(
"externaltools",
false,
false,
"appdata");
155 config.setGroup(
"Global");
156 TQStringList tools = config.readListEntry(
"tools");
159 for( TQStringList::Iterator it = tools.begin(); it != tools.end(); ++it )
165 config.setGroup( *it );
168 config.readEntry(
"name",
"" ),
169 config.readEntry(
"command",
""),
170 config.readEntry(
"icon",
""),
171 config.readEntry(
"executable",
""),
172 config.readListEntry(
"mimetypes" ),
173 config.readEntry(
"acname",
"" ),
174 config.readEntry(
"cmdname",
"" ) );
177 m_list.append(
"exttool-"+t.
cmdname);
182 Kate::Document::unregisterCommand(
this);
183 Kate::Document::registerCommand(
this);
188 bool KateExternalToolsCommand::exec (Kate::View *view,
const TQString &cmd, TQString &) {
189 TQWidget *wv=tqt_dynamic_cast<TQWidget*>(view);
194 KateMDI::MainWindow *dmw=tqt_dynamic_cast<KateMDI::MainWindow*>(wv->topLevelWidget());
200 TQString actionName=m_map[cmd.stripWhiteSpace()];
201 if (actionName.isEmpty())
return false;
205 if (!a)
return false;
207 TDEAction *a1=a->actionCollection()->action(static_cast<const char *>(actionName.utf8()));
208 if (!a1)
return false;
214 bool KateExternalToolsCommand::help (Kate::View *,
const TQString &, TQString &) {
220 KateExternalToolAction::KateExternalToolAction( TQObject *parent,
222 : TDEAction( parent, name ),
226 if ( ! t->
icon.isEmpty() )
227 setIconSet( SmallIconSet( t->
icon ) );
229 connect(
this ,TQT_SIGNAL(activated()),
this, TQT_SLOT(slotRun()) );
232 bool KateExternalToolAction::expandMacro(
const TQString &str, TQStringList &ret )
234 KateMainWindow *mw = (KateMainWindow*)parent()->parent();
236 Kate::View *view = mw->viewManager()->activeView();
237 if ( ! view )
return false;
241 ret += mw->activeDocumentUrl().url();
242 else if ( str ==
"directory" )
243 ret += mw->activeDocumentUrl().directory();
244 else if ( str ==
"filename" )
245 ret += mw->activeDocumentUrl().fileName();
246 else if ( str ==
"line" )
247 ret += TQString::number( view->cursorLine() );
248 else if ( str ==
"col" )
249 ret += TQString::number( view->cursorColumn() );
250 else if ( str ==
"selection" )
251 ret += view->getDoc()->selection();
252 else if ( str ==
"text" )
253 ret += view->getDoc()->text();
254 else if ( str ==
"URLs" ) {
255 for( Kate::Document *doc = KateDocManager::self()->firstDocument(); doc; doc = KateDocManager::self()->nextDocument() )
256 if ( ! doc->url().isEmpty() )
257 ret += doc->url().url();
263 KateExternalToolAction::~KateExternalToolAction() {
267 void KateExternalToolAction::slotRun()
273 if ( ! expandMacrosShellQuote( cmd ) )
275 KMessageBox::sorry( (KateMainWindow*)parent()->parent(),
276 i18n(
"Failed to expand the command '%1'.").arg( cmd ),
277 i18n(
"Kate External Tools") );
280 kdDebug(13001)<<
"externaltools: Running command: "<<cmd<<endl;
283 KateMainWindow *mw = (KateMainWindow*)parent()->parent();
284 if ( tool->
save == 1 )
285 mw->viewManager()->activeView()->document()->save();
286 else if ( tool->
save == 2 )
287 mw->actionCollection()->action(
"file_save_all")->activate();
289 KRun::runCommand( cmd, tool->
tryexec, tool->
icon );
294 KateExternalToolsMenuAction::KateExternalToolsMenuAction(
const TQString &text,
298 : TDEActionMenu( text, parent, name ),
302 m_actionCollection =
new TDEActionCollection( mainwindow );
304 connect(KateDocManager::self(),TQT_SIGNAL(documentChanged()),
this,TQT_SLOT(slotDocumentChanged()));
311 m_actionCollection->clear ();
312 popupMenu()->clear();
315 TDEConfig *config =
new TDEConfig(
"externaltools",
false,
false,
"appdata" );
316 config->setGroup(
"Global" );
317 TQStringList tools = config->readListEntry(
"tools" );
321 config->setReadDefaults(
true );
322 TQStringList dtools = config->readListEntry(
"tools" );
323 int gver = config->readNumEntry(
"version", 1 );
324 config->setReadDefaults(
false );
326 int ver = config->readNumEntry(
"version" );
329 TQStringList removed = config->readListEntry(
"removed" );
330 bool sepadded =
false;
331 for (TQStringList::iterator itg = dtools.begin(); itg != dtools.end(); ++itg )
333 if ( ! tools.contains( *itg ) &&
334 ! removed.contains( *itg ) )
345 config->writeEntry(
"tools", tools );
347 config->writeEntry(
"version", gver );
350 for( TQStringList::Iterator it = tools.begin(); it != tools.end(); ++it )
354 popupMenu()->insertSeparator();
359 config->setGroup( *it );
362 config->readEntry(
"name",
"" ),
363 config->readEntry(
"command",
""),
364 config->readEntry(
"icon",
""),
365 config->readEntry(
"executable",
""),
366 config->readListEntry(
"mimetypes" ),
367 config->readEntry(
"acname",
"" ),
368 config->readEntry(
"cmdname",
"" ),
369 config->readNumEntry(
"save", 0 ) );
375 m_actionCollection->readShortcutSettings(
"Shortcuts", config );
376 slotDocumentChanged();
380 void KateExternalToolsMenuAction::slotDocumentChanged()
383 Kate::DocumentExt *de = documentExt( KateDocManager::self()->activeDocument() );
386 TQString mt = de->mimeType();
390 TDEActionPtrList actions = m_actionCollection->actions();
391 for (TDEActionPtrList::iterator it = actions.begin(); it != actions.end(); ++it )
397 b = ( ! l.count() || l.contains( mt ) );
398 action->setEnabled( b );
410 class ToolItem :
public TQListBoxPixmap
414 : TQListBoxPixmap( lb, icon, tool->name ),
425 KateExternalToolServiceEditor::KateExternalToolServiceEditor(
KateExternalTool *tool,
426 TQWidget *parent,
const char *name )
427 : KDialogBase( parent, name, true, i18n(
"Edit External Tool"), KDialogBase::Ok|KDialogBase::Cancel ),
432 TQWidget *w =
new TQWidget(
this );
434 TQGridLayout *lo =
new TQGridLayout( w );
435 lo->setSpacing( KDialogBase::spacingHint() );
439 leName =
new TQLineEdit( w );
440 lo->addWidget( leName, 1, 2 );
441 l =
new TQLabel( leName, i18n(
"&Label:"), w );
442 l->setAlignment( l->alignment()|Qt::AlignRight );
443 lo->addWidget( l, 1, 1 );
444 if ( tool ) leName->setText( tool->
name );
445 TQWhatsThis::add( leName, i18n(
446 "The name will be displayed in the 'Tools->External' menu") );
448 btnIcon =
new TDEIconButton( w );
449 btnIcon->setIconSize( TDEIcon::SizeSmall );
450 lo->addWidget( btnIcon, 1, 3 );
451 if ( tool && !tool->
icon.isEmpty() )
452 btnIcon->setIcon( tool->
icon );
454 teCommand =
new TQTextEdit( w );
455 lo->addMultiCellWidget( teCommand, 2, 2, 2, 3 );
456 l =
new TQLabel( teCommand, i18n(
"S&cript:"), w );
457 l->setAlignment( Qt::AlignTop|Qt::AlignRight );
458 lo->addWidget( l, 2, 1 );
459 if ( tool ) teCommand->setText( tool->
command );
460 TQWhatsThis::add( teCommand, i18n(
461 "<p>The script to execute to invoke the tool. The script is passed "
462 "to /bin/sh for execution. The following macros "
463 "will be expanded:</p>"
464 "<ul><li><code>%URL</code> - the URL of the current document."
465 "<li><code>%URLs</code> - a list of the URLs of all open documents."
466 "<li><code>%directory</code> - the URL of the directory containing "
467 "the current document."
468 "<li><code>%filename</code> - the filename of the current document."
469 "<li><code>%line</code> - the current line of the text cursor in the "
471 "<li><code>%column</code> - the column of the text cursor in the "
473 "<li><code>%selection</code> - the selected text in the current view."
474 "<li><code>%text</code> - the text of the current document.</ul>" ) );
477 leExecutable =
new TQLineEdit( w );
478 lo->addMultiCellWidget( leExecutable, 3, 3, 2, 3 );
479 l =
new TQLabel( leExecutable, i18n(
"&Executable:"), w );
480 l->setAlignment( l->alignment()|Qt::AlignRight );
481 lo->addWidget( l, 3, 1 );
482 if ( tool ) leExecutable->setText( tool->
tryexec );
483 TQWhatsThis::add( leExecutable, i18n(
484 "The executable used by the command. This is used to check if a tool "
485 "should be displayed; if not set, the first word of <em>command</em> "
488 leMimetypes =
new TQLineEdit( w );
489 lo->addWidget( leMimetypes, 4, 2 );
490 l =
new TQLabel( leMimetypes, i18n(
"&Mime types:"), w );
491 l->setAlignment( l->alignment()|Qt::AlignRight );
492 lo->addWidget( l, 4, 1 );
493 if ( tool ) leMimetypes->setText( tool->
mimetypes.join(
"; ") );
494 TQWhatsThis::add( leMimetypes, i18n(
495 "A semicolon-separated list of mime types for which this tool should "
496 "be available; if this is left empty, the tool is always available. "
497 "To choose from known mimetypes, press the button on the right.") );
499 TQToolButton *btnMTW =
new TQToolButton(w);
500 lo->addWidget( btnMTW, 4, 3 );
501 btnMTW->setIconSet(TQIconSet(SmallIcon(
"wizard")));
502 connect(btnMTW, TQT_SIGNAL(clicked()),
this, TQT_SLOT(showMTDlg()));
503 TQWhatsThis::add( btnMTW, i18n(
504 "Click for a dialog that can help you creating a list of mimetypes.") );
506 cmbSave =
new TQComboBox(w);
507 lo->addMultiCellWidget( cmbSave, 5, 5, 2, 3 );
508 l =
new TQLabel( cmbSave, i18n(
"&Save:"), w );
509 l->setAlignment( l->alignment()|Qt::AlignRight );
510 lo->addWidget( l, 5, 1 );
512 sl << i18n(
"None") << i18n(
"Current Document") << i18n(
"All Documents");
513 cmbSave->insertStringList( sl );
514 if ( tool ) cmbSave->setCurrentItem( tool->
save );
515 TQWhatsThis::add( cmbSave, i18n(
516 "You can elect to save the current or all [modified] documents prior to "
517 "running the command. This is helpful if you want to pass URLs to "
518 "an application like, for example, an FTP client.") );
521 leCmdLine =
new TQLineEdit( w );
522 lo->addMultiCellWidget( leCmdLine, 6, 6, 2, 3 );
523 l =
new TQLabel( leCmdLine, i18n(
"&Command line name:"), w );
524 l->setAlignment( l->alignment()|Qt::AlignRight );
525 lo->addWidget( l, 6, 1 );
526 if ( tool ) leCmdLine->setText( tool->
cmdname );
527 TQWhatsThis::add( leCmdLine, i18n(
528 "If you specify a name here, you can invoke the command from the view "
529 "command lines with exttool-the_name_you_specified_here. "
530 "Please do not use spaces or tabs in the name."));
534 void KateExternalToolServiceEditor::slotOk()
536 if ( leName->text().isEmpty() ||
537 teCommand->text().isEmpty() )
539 KMessageBox::information(
this, i18n(
"You must specify at least a name and a command") );
543 KDialogBase::slotOk();
546 void KateExternalToolServiceEditor::showMTDlg()
548 TQString text = i18n(
"Select the MimeTypes for which to enable this tool.");
549 TQStringList list = TQStringList::split( TQRegExp(
"\\s*;\\s*"), leMimetypes->text() );
550 KMimeTypeChooserDialog d( i18n(
"Select Mime Types"), text, list,
"text",
this );
551 if ( d.exec() == KDialogBase::Accepted ) {
552 leMimetypes->setText( d.chooser()->mimeTypes().join(
";") );
558 KateExternalToolsConfigWidget::KateExternalToolsConfigWidget( TQWidget *parent,
const char* name )
559 : Kate::ConfigPage( parent, name ),
562 TQGridLayout *lo =
new TQGridLayout(
this, 5, 5, 0, KDialog::spacingHint() );
564 lbTools =
new TDEListBox(
this );
565 lo->addMultiCellWidget( lbTools, 1, 4, 0, 3 );
566 connect( lbTools, TQT_SIGNAL(selectionChanged()),
this, TQT_SLOT(slotSelectionChanged()) );
568 btnNew =
new TQPushButton( i18n(
"&New..."),
this );
569 lo->addWidget( btnNew, 5, 0 );
570 connect( btnNew, TQT_SIGNAL(clicked()),
this, TQT_SLOT(slotNew()) );
572 btnRemove =
new TQPushButton( i18n(
"&Remove"),
this );
573 lo->addWidget( btnRemove, 5, 2 );
574 connect( btnRemove, TQT_SIGNAL(clicked()),
this, TQT_SLOT(slotRemove()) );
576 btnEdit =
new TQPushButton( i18n(
"&Edit..."),
this );
577 lo->addWidget( btnEdit, 5, 1 );
578 connect( btnEdit, TQT_SIGNAL(clicked()),
this, TQT_SLOT(slotEdit()) );
580 TQPushButton *b =
new TQPushButton( i18n(
"Insert &Separator"),
this );
581 lo->addWidget( b, 5, 3 );
582 connect( b, TQT_SIGNAL(clicked()),
this, TQT_SLOT(slotInsertSeparator()) );
584 btnMoveUp =
new TQPushButton( SmallIconSet(
"go-up"),
"",
this );
585 lo->addWidget( btnMoveUp, 2, 4 );
586 connect( btnMoveUp, TQT_SIGNAL(clicked()),
this, TQT_SLOT(slotMoveUp()) );
588 btnMoveDwn =
new TQPushButton( SmallIconSet(
"go-down"),
"",
this );
589 lo->addWidget( btnMoveDwn, 3, 4 );
590 connect( btnMoveDwn, TQT_SIGNAL(clicked()),
this, TQT_SLOT(slotMoveDown()) );
592 connect( lbTools, TQT_SIGNAL( doubleClicked ( TQListBoxItem * ) ),
this, TQT_SLOT( slotEdit() ) );
594 lo->setRowStretch( 1, 1 );
595 lo->setRowStretch( 4, 1 );
596 lo->setColStretch( 0, 1 );
597 lo->setColStretch( 1, 1 );
598 lo->setColStretch( 2, 1 );
601 TQWhatsThis::add( lbTools, i18n(
602 "This list shows all the configured tools, represented by their menu text.") );
604 config =
new TDEConfig(
"externaltools",
false,
false,
"appdata");
606 slotSelectionChanged();
609 KateExternalToolsConfigWidget::~KateExternalToolsConfigWidget()
614 void KateExternalToolsConfigWidget::reload()
620 config->setGroup(
"Global" );
621 TQStringList tools = config->readListEntry(
"tools");
623 for( TQStringList::Iterator it = tools.begin(); it != tools.end(); ++it )
627 new TQListBoxText( lbTools,
"---" );
631 config->setGroup( *it );
634 config->readEntry(
"name",
"" ),
635 config->readEntry(
"command",
""),
636 config->readEntry(
"icon",
""),
637 config->readEntry(
"executable",
""),
638 config->readListEntry(
"mimetypes" ),
639 config->readEntry(
"acname" ),
640 config->readEntry(
"cmdname"),
641 config->readNumEntry(
"save", 0 ) );
644 new ToolItem( lbTools, t->
icon.isEmpty() ? blankIcon() : SmallIcon( t->icon ), t );
650 TQPixmap KateExternalToolsConfigWidget::blankIcon()
652 TQPixmap pm( TDEIcon::SizeSmall, TDEIcon::SizeSmall );
654 pm.setMask( pm.createHeuristicMask() );
658 void KateExternalToolsConfigWidget::apply()
667 for ( uint i = 0; i < lbTools->count(); i++ )
669 if ( lbTools->text( i ) ==
"---" )
678 config->setGroup( t->
acname );
679 config->writeEntry(
"name", t->
name );
680 config->writeEntry(
"command", t->
command );
681 config->writeEntry(
"icon", t->
icon );
682 config->writeEntry(
"executable", t->
tryexec );
683 config->writeEntry(
"mimetypes", t->
mimetypes );
684 config->writeEntry(
"acname", t->
acname );
685 config->writeEntry(
"cmdname", t->
cmdname );
686 config->writeEntry(
"save", t->
save );
689 config->setGroup(
"Global");
690 config->writeEntry(
"tools", tools );
694 if ( m_removed.count() )
696 for ( TQStringList::iterator it = m_removed.begin(); it != m_removed.end(); ++it )
698 if ( config->hasGroup( *it ) )
699 config->deleteGroup( *it );
701 TQStringList removed = config->readListEntry(
"removed" );
702 removed += m_removed;
707 TQStringList::iterator it1 = removed.begin();
708 while( it1 != removed.end() )
710 if ( ! config->hasGroup( *it1 ) )
711 it1 = removed.remove( it1 );
715 config->writeEntry(
"removed", removed );
721 void KateExternalToolsConfigWidget::slotSelectionChanged()
724 bool hs = lbTools->selectedItem() != 0;
725 btnEdit->setEnabled( hs && dynamic_cast<ToolItem*>(lbTools->selectedItem()) );
726 btnRemove->setEnabled( hs );
727 btnMoveUp->setEnabled( ( lbTools->currentItem() > 0 ) && hs );
728 btnMoveDwn->setEnabled( ( lbTools->currentItem() < (int)lbTools->count()-1 )&&hs );
731 void KateExternalToolsConfigWidget::slotNew()
740 editor.leName->text(),
741 editor.teCommand->text(),
742 editor.btnIcon->icon(),
743 editor.leExecutable->text(),
744 TQStringList::split( TQRegExp(
"\\s*;\\s*"), editor.leMimetypes->text() ) );
748 t->
acname =
"externaltool_" + TQString(t->
name).replace( TQRegExp(
"\\W+"),
"" );
750 new ToolItem ( lbTools, t->
icon.isEmpty() ? blankIcon() : SmallIcon( t->icon ), t );
757 void KateExternalToolsConfigWidget::slotRemove()
761 if ( lbTools->currentItem() > -1 ) {
762 ToolItem *i =
dynamic_cast<ToolItem*
>(lbTools->selectedItem());
764 m_removed << i->tool->acname;
766 lbTools->removeItem( lbTools->currentItem() );
772 void KateExternalToolsConfigWidget::slotEdit()
774 if( !dynamic_cast<ToolItem*>(lbTools->selectedItem()) )
return;
778 config->setGroup(
"Editor" );
779 editor.resize( config->readSizeEntry(
"Size" ) );
783 bool elementChanged = ( ( editor.btnIcon->icon() != t->
icon ) || (editor.leName->text() != t->
name ) ) ;
785 t->
name = editor.leName->text();
786 t->
cmdname = editor.leCmdLine->text();
787 t->
command = editor.teCommand->text();
788 t->
icon = editor.btnIcon->icon();
789 t->
tryexec = editor.leExecutable->text();
790 t->
mimetypes = TQStringList::split( TQRegExp(
"\\s*;\\s*"), editor.leMimetypes->text() );
791 t->
save = editor.cmbSave->currentItem();
794 if ( elementChanged )
796 int idx = lbTools->index( lbTools->selectedItem() );
797 lbTools->removeItem( idx );
798 lbTools->insertItem(
new ToolItem( 0, t->
icon.isEmpty() ? blankIcon() : SmallIcon( t->icon ), t ), idx );
805 config->setGroup(
"Editor" );
806 config->writeEntry(
"Size", editor.size() );
810 void KateExternalToolsConfigWidget::slotInsertSeparator()
812 lbTools->insertItem(
"---", lbTools->currentItem()+1 );
817 void KateExternalToolsConfigWidget::slotMoveUp()
820 TQListBoxItem *item = lbTools->selectedItem();
821 if ( ! item )
return;
823 int idx = lbTools->index( item );
825 if ( idx < 1 )
return;
827 if ( dynamic_cast<ToolItem*>(item) )
830 lbTools->removeItem( idx );
831 lbTools->insertItem(
new ToolItem( 0, tool->
icon.isEmpty() ? blankIcon() : SmallIcon( tool->icon ), tool ), idx-1 );
835 lbTools->removeItem( idx );
836 lbTools->insertItem(
new TQListBoxText( 0,
"---" ), idx-1 );
839 lbTools->setCurrentItem( idx - 1 );
840 slotSelectionChanged();
845 void KateExternalToolsConfigWidget::slotMoveDown()
848 TQListBoxItem *item = lbTools->selectedItem();
849 if ( ! item )
return;
851 uint idx = lbTools->index( item );
853 if ( idx > lbTools->count()-1 )
return;
855 if ( dynamic_cast<ToolItem*>(item) )
858 lbTools->removeItem( idx );
859 lbTools->insertItem(
new ToolItem( 0, tool->
icon.isEmpty() ? blankIcon() : SmallIcon( tool->icon ), tool ), idx+1 );
863 lbTools->removeItem( idx );
864 lbTools->insertItem(
new TQListBoxText( 0,
"---" ), idx+1 );
867 lbTools->setCurrentItem( idx+1 );
868 slotSelectionChanged();