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",
"" ) );
176 m_list.append(
"exttool-"+t.
cmdname);
181 Kate::Document::unregisterCommand(
this);
182 Kate::Document::registerCommand(
this);
187 bool KateExternalToolsCommand::exec (Kate::View *view,
const TQString &cmd, TQString &) {
188 TQWidget *wv=
dynamic_cast<TQWidget*
>(view);
193 KateMDI::MainWindow *dmw=
dynamic_cast<KateMDI::MainWindow*
>(wv->topLevelWidget());
199 TQString actionName=m_map[cmd.stripWhiteSpace()];
200 if (actionName.isEmpty())
return false;
204 if (!a)
return false;
206 TDEAction *a1=a->actionCollection()->action(
static_cast<const char *
>(actionName.utf8()));
207 if (!a1)
return false;
213 bool KateExternalToolsCommand::help (Kate::View *,
const TQString &, TQString &) {
219 KateExternalToolAction::KateExternalToolAction( TQObject *parent,
221 : TDEAction( parent, name ),
225 if ( ! t->
icon.isEmpty() )
226 setIconSet( SmallIconSet( t->
icon ) );
228 connect(
this ,TQ_SIGNAL(activated()),
this, TQ_SLOT(slotRun()) );
231 bool KateExternalToolAction::expandMacro(
const TQString &str, TQStringList &ret )
233 KateMainWindow *mw = (KateMainWindow*)parent()->parent();
235 Kate::View *view = mw->viewManager()->activeView();
236 if ( ! view )
return false;
240 ret += mw->activeDocumentUrl().url();
241 else if ( str ==
"directory" )
242 ret += mw->activeDocumentUrl().directory();
243 else if ( str ==
"filename" )
244 ret += mw->activeDocumentUrl().fileName();
245 else if ( str ==
"line" )
246 ret += TQString::number( view->cursorLine() );
247 else if ( str ==
"col" )
248 ret += TQString::number( view->cursorColumn() );
249 else if ( str ==
"selection" )
250 ret += view->getDoc()->selection();
251 else if ( str ==
"text" )
252 ret += view->getDoc()->text();
253 else if ( str ==
"URLs" ) {
254 for( Kate::Document *doc = KateDocManager::self()->firstDocument(); doc; doc = KateDocManager::self()->nextDocument() )
255 if ( ! doc->url().isEmpty() )
256 ret += doc->url().url();
262 KateExternalToolAction::~KateExternalToolAction() {
266 void KateExternalToolAction::slotRun()
272 if ( ! expandMacrosShellQuote( cmd ) )
274 KMessageBox::sorry( (KateMainWindow*)parent()->parent(),
275 i18n(
"Failed to expand the command '%1'.").arg( cmd ),
276 i18n(
"Kate External Tools") );
279 kdDebug(13001)<<
"externaltools: Running command: "<<cmd<<endl;
282 KateMainWindow *mw = (KateMainWindow*)parent()->parent();
283 if ( tool->
save == 1 )
284 mw->viewManager()->activeView()->document()->save();
285 else if ( tool->
save == 2 )
286 mw->actionCollection()->action(
"file_save_all")->activate();
288 KRun::runCommand( cmd, tool->
tryexec, tool->
icon );
293 KateExternalToolsMenuAction::KateExternalToolsMenuAction(
const TQString &text,
297 : TDEActionMenu( text, parent, name ),
301 m_actionCollection =
new TDEActionCollection( mainwindow );
303 connect(KateDocManager::self(),TQ_SIGNAL(documentChanged()),
this,TQ_SLOT(slotDocumentChanged()));
310 m_actionCollection->clear ();
311 popupMenu()->clear();
314 TDEConfig *config =
new TDEConfig(
"externaltools",
false,
false,
"appdata" );
315 config->setGroup(
"Global" );
316 TQStringList tools = config->readListEntry(
"tools" );
320 config->setReadDefaults(
true );
321 TQStringList dtools = config->readListEntry(
"tools" );
322 int gver = config->readNumEntry(
"version", 1 );
323 config->setReadDefaults(
false );
325 int ver = config->readNumEntry(
"version" );
328 TQStringList removed = config->readListEntry(
"removed" );
329 bool sepadded =
false;
330 for (TQStringList::iterator itg = dtools.begin(); itg != dtools.end(); ++itg )
332 if ( ! tools.contains( *itg ) &&
333 ! removed.contains( *itg ) )
344 config->writeEntry(
"tools", tools );
346 config->writeEntry(
"version", gver );
349 for( TQStringList::Iterator it = tools.begin(); it != tools.end(); ++it )
353 popupMenu()->insertSeparator();
358 config->setGroup( *it );
361 config->readEntry(
"name",
"" ),
362 config->readEntry(
"command",
""),
363 config->readEntry(
"icon",
""),
364 config->readEntry(
"executable",
""),
365 config->readListEntry(
"mimetypes" ),
366 config->readEntry(
"acname",
"" ),
367 config->readEntry(
"cmdname",
"" ),
368 config->readNumEntry(
"save", 0 ) );
374 m_actionCollection->readShortcutSettings(
"Shortcuts", config );
375 slotDocumentChanged();
379 void KateExternalToolsMenuAction::slotDocumentChanged()
382 Kate::DocumentExt *de = documentExt( KateDocManager::self()->activeDocument() );
385 TQString mt = de->mimeType();
389 TDEActionPtrList actions = m_actionCollection->actions();
390 for (TDEActionPtrList::iterator it = actions.begin(); it != actions.end(); ++it )
396 b = ( ! l.count() || l.contains( mt ) );
397 action->setEnabled( b );
409 class ToolItem :
public TQListBoxPixmap
413 : TQListBoxPixmap( lb, icon, tool->name ),
424 KateExternalToolServiceEditor::KateExternalToolServiceEditor(
KateExternalTool *tool,
425 TQWidget *parent,
const char *name )
426 : KDialogBase( parent, name, true, i18n(
"Edit External Tool"), KDialogBase::Ok|KDialogBase::Cancel ),
431 TQWidget *w =
new TQWidget(
this );
433 TQGridLayout *lo =
new TQGridLayout( w );
434 lo->setSpacing( KDialogBase::spacingHint() );
438 leName =
new TQLineEdit( w );
439 lo->addWidget( leName, 1, 2 );
440 l =
new TQLabel( leName, i18n(
"&Label:"), w );
441 l->setAlignment( l->alignment()|TQt::AlignRight );
442 lo->addWidget( l, 1, 1 );
443 if ( tool ) leName->setText( tool->
name );
444 TQWhatsThis::add( leName, i18n(
445 "The name will be displayed in the 'Tools->External' menu") );
447 btnIcon =
new TDEIconButton( w );
448 btnIcon->setIconSize( TDEIcon::SizeSmall );
449 lo->addWidget( btnIcon, 1, 3 );
450 if ( tool && !tool->
icon.isEmpty() )
451 btnIcon->setIcon( tool->
icon );
453 teCommand =
new TQTextEdit( w );
454 lo->addMultiCellWidget( teCommand, 2, 2, 2, 3 );
455 l =
new TQLabel( teCommand, i18n(
"S&cript:"), w );
456 l->setAlignment( TQt::AlignTop|TQt::AlignRight );
457 lo->addWidget( l, 2, 1 );
458 if ( tool ) teCommand->setText( tool->
command );
459 TQWhatsThis::add( teCommand, i18n(
460 "<p>The script to execute to invoke the tool. The script is passed "
461 "to /bin/sh for execution. The following macros "
462 "will be expanded:</p>"
463 "<ul><li><code>%URL</code> - the URL of the current document."
464 "<li><code>%URLs</code> - a list of the URLs of all open documents."
465 "<li><code>%directory</code> - the URL of the directory containing "
466 "the current document."
467 "<li><code>%filename</code> - the filename of the current document."
468 "<li><code>%line</code> - the current line of the text cursor in the "
470 "<li><code>%column</code> - the column of the text cursor in the "
472 "<li><code>%selection</code> - the selected text in the current view."
473 "<li><code>%text</code> - the text of the current document.</ul>" ) );
476 leExecutable =
new TQLineEdit( w );
477 lo->addMultiCellWidget( leExecutable, 3, 3, 2, 3 );
478 l =
new TQLabel( leExecutable, i18n(
"&Executable:"), w );
479 l->setAlignment( l->alignment()|TQt::AlignRight );
480 lo->addWidget( l, 3, 1 );
481 if ( tool ) leExecutable->setText( tool->
tryexec );
482 TQWhatsThis::add( leExecutable, i18n(
483 "The executable used by the command. This is used to check if a tool "
484 "should be displayed; if not set, the first word of <em>command</em> "
487 leMimetypes =
new TQLineEdit( w );
488 lo->addWidget( leMimetypes, 4, 2 );
489 l =
new TQLabel( leMimetypes, i18n(
"&Mime types:"), w );
490 l->setAlignment( l->alignment()|TQt::AlignRight );
491 lo->addWidget( l, 4, 1 );
492 if ( tool ) leMimetypes->setText( tool->
mimetypes.join(
"; ") );
493 TQWhatsThis::add( leMimetypes, i18n(
494 "A semicolon-separated list of mime types for which this tool should "
495 "be available; if this is left empty, the tool is always available. "
496 "To choose from known mimetypes, press the button on the right.") );
498 TQToolButton *btnMTW =
new TQToolButton(w);
499 lo->addWidget( btnMTW, 4, 3 );
500 btnMTW->setIconSet(TQIconSet(SmallIcon(
"wizard")));
501 connect(btnMTW, TQ_SIGNAL(clicked()),
this, TQ_SLOT(showMTDlg()));
502 TQWhatsThis::add( btnMTW, i18n(
503 "Click for a dialog that can help you creating a list of mimetypes.") );
505 cmbSave =
new TQComboBox(w);
506 lo->addMultiCellWidget( cmbSave, 5, 5, 2, 3 );
507 l =
new TQLabel( cmbSave, i18n(
"&Save:"), w );
508 l->setAlignment( l->alignment()|TQt::AlignRight );
509 lo->addWidget( l, 5, 1 );
511 sl << i18n(
"None") << i18n(
"Current Document") << i18n(
"All Documents");
512 cmbSave->insertStringList( sl );
513 if ( tool ) cmbSave->setCurrentItem( tool->
save );
514 TQWhatsThis::add( cmbSave, i18n(
515 "You can elect to save the current or all [modified] documents prior to "
516 "running the command. This is helpful if you want to pass URLs to "
517 "an application like, for example, an FTP client.") );
520 leCmdLine =
new TQLineEdit( w );
521 lo->addMultiCellWidget( leCmdLine, 6, 6, 2, 3 );
522 l =
new TQLabel( leCmdLine, i18n(
"&Command line name:"), w );
523 l->setAlignment( l->alignment()|TQt::AlignRight );
524 lo->addWidget( l, 6, 1 );
525 if ( tool ) leCmdLine->setText( tool->
cmdname );
526 TQWhatsThis::add( leCmdLine, i18n(
527 "If you specify a name here, you can invoke the command from the view "
528 "command lines with exttool-the_name_you_specified_here. "
529 "Please do not use spaces or tabs in the name."));
533 void KateExternalToolServiceEditor::slotOk()
535 if ( leName->text().isEmpty() ||
536 teCommand->text().isEmpty() )
538 KMessageBox::information(
this, i18n(
"You must specify at least a name and a command") );
542 KDialogBase::slotOk();
545 void KateExternalToolServiceEditor::showMTDlg()
547 TQString text = i18n(
"Select the MimeTypes for which to enable this tool.");
548 TQStringList list = TQStringList::split( TQRegExp(
"\\s*;\\s*"), leMimetypes->text() );
549 KMimeTypeChooserDialog d( i18n(
"Select Mime Types"), text, list,
"text",
this );
550 if ( d.exec() == KDialogBase::Accepted ) {
551 leMimetypes->setText( d.chooser()->mimeTypes().join(
";") );
557 KateExternalToolsConfigWidget::KateExternalToolsConfigWidget( TQWidget *parent,
const char* name )
558 :
Kate::ConfigPage( parent, name ),
561 TQGridLayout *lo =
new TQGridLayout(
this, 5, 5, 0, KDialog::spacingHint() );
563 lbTools =
new TDEListBox(
this );
564 lo->addMultiCellWidget( lbTools, 1, 4, 0, 3 );
565 connect( lbTools, TQ_SIGNAL(selectionChanged()),
this, TQ_SLOT(slotSelectionChanged()) );
567 btnNew =
new TQPushButton( i18n(
"&New..."),
this );
568 lo->addWidget( btnNew, 5, 0 );
569 connect( btnNew, TQ_SIGNAL(clicked()),
this, TQ_SLOT(slotNew()) );
571 btnRemove =
new TQPushButton( i18n(
"&Remove"),
this );
572 lo->addWidget( btnRemove, 5, 2 );
573 connect( btnRemove, TQ_SIGNAL(clicked()),
this, TQ_SLOT(slotRemove()) );
575 btnEdit =
new TQPushButton( i18n(
"&Edit..."),
this );
576 lo->addWidget( btnEdit, 5, 1 );
577 connect( btnEdit, TQ_SIGNAL(clicked()),
this, TQ_SLOT(slotEdit()) );
579 TQPushButton *b =
new TQPushButton( i18n(
"Insert &Separator"),
this );
580 lo->addWidget( b, 5, 3 );
581 connect( b, TQ_SIGNAL(clicked()),
this, TQ_SLOT(slotInsertSeparator()) );
583 btnMoveUp =
new TQPushButton( SmallIconSet(
"go-up"),
"",
this );
584 lo->addWidget( btnMoveUp, 2, 4 );
585 connect( btnMoveUp, TQ_SIGNAL(clicked()),
this, TQ_SLOT(slotMoveUp()) );
587 btnMoveDwn =
new TQPushButton( SmallIconSet(
"go-down"),
"",
this );
588 lo->addWidget( btnMoveDwn, 3, 4 );
589 connect( btnMoveDwn, TQ_SIGNAL(clicked()),
this, TQ_SLOT(slotMoveDown()) );
591 connect( lbTools, TQ_SIGNAL( doubleClicked ( TQListBoxItem * ) ),
this, TQ_SLOT( slotEdit() ) );
593 lo->setRowStretch( 1, 1 );
594 lo->setRowStretch( 4, 1 );
595 lo->setColStretch( 0, 1 );
596 lo->setColStretch( 1, 1 );
597 lo->setColStretch( 2, 1 );
600 TQWhatsThis::add( lbTools, i18n(
601 "This list shows all the configured tools, represented by their menu text.") );
603 config =
new TDEConfig(
"externaltools",
false,
false,
"appdata");
605 slotSelectionChanged();
608 KateExternalToolsConfigWidget::~KateExternalToolsConfigWidget()
613 void KateExternalToolsConfigWidget::reload()
619 config->setGroup(
"Global" );
620 TQStringList tools = config->readListEntry(
"tools");
622 for( TQStringList::Iterator it = tools.begin(); it != tools.end(); ++it )
626 new TQListBoxText( lbTools,
"---" );
630 config->setGroup( *it );
633 config->readEntry(
"name",
"" ),
634 config->readEntry(
"command",
""),
635 config->readEntry(
"icon",
""),
636 config->readEntry(
"executable",
""),
637 config->readListEntry(
"mimetypes" ),
638 config->readEntry(
"acname" ),
639 config->readEntry(
"cmdname"),
640 config->readNumEntry(
"save", 0 ) );
643 new ToolItem( lbTools, t->
icon.isEmpty() ? blankIcon() : SmallIcon( t->
icon ), t );
649 TQPixmap KateExternalToolsConfigWidget::blankIcon()
651 TQPixmap pm( TDEIcon::SizeSmall, TDEIcon::SizeSmall );
653 pm.setMask( pm.createHeuristicMask() );
657 void KateExternalToolsConfigWidget::apply()
666 for ( uint i = 0; i < lbTools->count(); i++ )
668 if ( lbTools->text( i ) ==
"---" )
677 config->setGroup( t->
acname );
678 config->writeEntry(
"name", t->
name );
679 config->writeEntry(
"command", t->
command );
680 config->writeEntry(
"icon", t->
icon );
681 config->writeEntry(
"executable", t->
tryexec );
682 config->writeEntry(
"mimetypes", t->
mimetypes );
683 config->writeEntry(
"acname", t->
acname );
684 config->writeEntry(
"cmdname", t->
cmdname );
685 config->writeEntry(
"save", t->
save );
688 config->setGroup(
"Global");
689 config->writeEntry(
"tools", tools );
693 if ( m_removed.count() )
695 for ( TQStringList::iterator it = m_removed.begin(); it != m_removed.end(); ++it )
697 if ( config->hasGroup( *it ) )
698 config->deleteGroup( *it );
700 TQStringList removed = config->readListEntry(
"removed" );
701 removed += m_removed;
706 TQStringList::iterator it1 = removed.begin();
707 while( it1 != removed.end() )
709 if ( ! config->hasGroup( *it1 ) )
710 it1 = removed.remove( it1 );
714 config->writeEntry(
"removed", removed );
720 void KateExternalToolsConfigWidget::slotSelectionChanged()
723 bool hs = lbTools->selectedItem() != 0;
724 btnEdit->setEnabled( hs &&
dynamic_cast<ToolItem*
>(lbTools->selectedItem()) );
725 btnRemove->setEnabled( hs );
726 btnMoveUp->setEnabled( ( lbTools->currentItem() > 0 ) && hs );
727 btnMoveDwn->setEnabled( ( lbTools->currentItem() < (
int)lbTools->count()-1 )&&hs );
730 void KateExternalToolsConfigWidget::slotNew()
739 editor.leName->text(),
740 editor.teCommand->text(),
741 editor.btnIcon->icon(),
742 editor.leExecutable->text(),
743 TQStringList::split( TQRegExp(
"\\s*;\\s*"), editor.leMimetypes->text() ) );
747 t->
acname =
"externaltool_" + TQString(t->
name).replace( TQRegExp(
"\\W+"),
"" );
749 new ToolItem ( lbTools, t->
icon.isEmpty() ? blankIcon() : SmallIcon( t->
icon ), t );
756 void KateExternalToolsConfigWidget::slotRemove()
760 if ( lbTools->currentItem() > -1 ) {
761 ToolItem *i =
dynamic_cast<ToolItem*
>(lbTools->selectedItem());
763 m_removed << i->tool->acname;
765 lbTools->removeItem( lbTools->currentItem() );
771 void KateExternalToolsConfigWidget::slotEdit()
773 if( !
dynamic_cast<ToolItem*
>(lbTools->selectedItem()) )
return;
777 config->setGroup(
"Editor" );
778 editor.resize( config->readSizeEntry(
"Size" ) );
782 bool elementChanged = ( ( editor.btnIcon->icon() != t->
icon ) || (editor.leName->text() != t->
name ) ) ;
784 t->
name = editor.leName->text();
785 t->
cmdname = editor.leCmdLine->text();
786 t->
command = editor.teCommand->text();
787 t->
icon = editor.btnIcon->icon();
788 t->
tryexec = editor.leExecutable->text();
789 t->
mimetypes = TQStringList::split( TQRegExp(
"\\s*;\\s*"), editor.leMimetypes->text() );
790 t->
save = editor.cmbSave->currentItem();
793 if ( elementChanged )
795 int idx = lbTools->index( lbTools->selectedItem() );
796 lbTools->removeItem( idx );
797 lbTools->insertItem(
new ToolItem( 0, t->
icon.isEmpty() ? blankIcon() : SmallIcon( t->
icon ), t ), idx );
804 config->setGroup(
"Editor" );
805 config->writeEntry(
"Size", editor.size() );
809 void KateExternalToolsConfigWidget::slotInsertSeparator()
811 lbTools->insertItem(
"---", lbTools->currentItem()+1 );
816 void KateExternalToolsConfigWidget::slotMoveUp()
819 TQListBoxItem *item = lbTools->selectedItem();
820 if ( ! item )
return;
822 int idx = lbTools->index( item );
824 if ( idx < 1 )
return;
826 if (
dynamic_cast<ToolItem*
>(item) )
829 lbTools->removeItem( idx );
830 lbTools->insertItem(
new ToolItem( 0, tool->
icon.isEmpty() ? blankIcon() : SmallIcon( tool->icon ), tool ), idx-1 );
834 lbTools->removeItem( idx );
835 lbTools->insertItem(
new TQListBoxText( 0,
"---" ), idx-1 );
838 lbTools->setCurrentItem( idx - 1 );
839 slotSelectionChanged();
844 void KateExternalToolsConfigWidget::slotMoveDown()
847 TQListBoxItem *item = lbTools->selectedItem();
848 if ( ! item )
return;
850 uint idx = lbTools->index( item );
852 if ( idx > lbTools->count()-1 )
return;
854 if (
dynamic_cast<ToolItem*
>(item) )
857 lbTools->removeItem( idx );
858 lbTools->insertItem(
new ToolItem( 0, tool->
icon.isEmpty() ? blankIcon() : SmallIcon( tool->icon ), tool ), idx+1 );
862 lbTools->removeItem( idx );
863 lbTools->insertItem(
new TQListBoxText( 0,
"---" ), idx+1 );
866 lbTools->setCurrentItem( idx+1 );
867 slotSelectionChanged();
Namespace collecting as much of the internal Kate classes as we can manage.