Changeset View
Changeset View
Standalone View
Standalone View
addons/externaltools/kateexternaltools.cpp
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | This file is part of the Kate text editor of the KDE project. | ||||
3 | | ||||
4 | This library is free software; you can redistribute it and/or | ||||
5 | modify it under the terms of the GNU Library General Public | ||||
6 | License version 2 as published by the Free Software Foundation. | ||||
7 | | ||||
8 | This library is distributed in the hope that it will be useful, | ||||
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
11 | Library General Public License for more details. | ||||
12 | | ||||
13 | You should have received a copy of the GNU Library General Public License | ||||
14 | along with this library; see the file COPYING.LIB. If not, write to | ||||
15 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||||
16 | Boston, MA 02110-1301, USA. | ||||
17 | | ||||
18 | --- | ||||
19 | Copyright (C) 2004, Anders Lund <anders@alweb.dk> | ||||
20 | */ | ||||
21 | // TODO | ||||
22 | // Icons | ||||
23 | // Direct shortcut setting | ||||
24 | //BEGIN Includes | ||||
25 | #include "kateexternaltoolsplugin.h" | ||||
26 | #include "kateexternaltools.h" | ||||
27 | #include "kateexternaltools.moc" | ||||
28 | #include <KTextEditor/View> | ||||
29 | #include <KTextEditor/Document> | ||||
30 | #include <KTextEditor/Editor> | ||||
31 | | ||||
32 | #include <KActionCollection> | ||||
33 | #include <KListWidget> | ||||
34 | #include <KLocale> | ||||
35 | #include <KIconLoader> | ||||
36 | #include <KMessageBox> | ||||
37 | #include <KMimeTypeChooser> | ||||
38 | #include <KXmlGuiWindow> | ||||
39 | #include <KStandardDirs> | ||||
40 | #include <KConfig> | ||||
41 | #include <KConfigGroup> | ||||
42 | #include <KComboBox> | ||||
43 | #include <KLineEdit> | ||||
44 | #include <KRun> | ||||
45 | #include <KIconDialog> | ||||
46 | #include <KMenu> | ||||
47 | #include <KSharedConfig> | ||||
48 | #include <kdebug.h> | ||||
49 | #include <kde_file.h> | ||||
50 | | ||||
51 | #include <QBitmap> | ||||
52 | #include <QFile> | ||||
53 | #include <QLabel> | ||||
54 | #include <QPushButton> | ||||
55 | #include <QRegExp> | ||||
56 | #include <QToolButton> | ||||
57 | #include <QGridLayout> | ||||
58 | #include <QObject> | ||||
59 | #include <QTextEdit> | ||||
60 | | ||||
61 | #include <unistd.h> | ||||
62 | //END Includes | ||||
63 | | ||||
64 | | ||||
65 | //BEGIN KateExternalTool | ||||
66 | KateExternalTool::KateExternalTool( const QString &name, | ||||
67 | const QString &command, | ||||
68 | const QString &icon, | ||||
69 | const QString &tryexec, | ||||
70 | const QStringList &mimetypes, | ||||
71 | const QString &acname, | ||||
72 | const QString &cmdname, | ||||
73 | int save ) | ||||
74 | : name ( name ), | ||||
75 | command ( command ), | ||||
76 | icon ( icon ), | ||||
77 | tryexec ( tryexec ), | ||||
78 | mimetypes ( mimetypes ), | ||||
79 | acname ( acname ), | ||||
80 | cmdname ( cmdname ), | ||||
81 | save ( save ) | ||||
82 | { | ||||
83 | //if ( ! tryexec.isEmpty() ) | ||||
84 | hasexec = checkExec(); | ||||
85 | } | ||||
86 | | ||||
87 | bool KateExternalTool::checkExec() | ||||
88 | { | ||||
89 | // if tryexec is empty, it is the first word of command | ||||
90 | if ( tryexec.isEmpty() ) | ||||
91 | tryexec = command.section( ' ', 0, 0, QString::SectionSkipEmpty ); | ||||
92 | | ||||
93 | // NOTE this code is modified taken from kdesktopfile.cpp, from KDesktopFile::tryExec() | ||||
94 | if (!tryexec.isEmpty()) | ||||
95 | { | ||||
96 | m_exec = KStandardDirs::findExe(tryexec); | ||||
97 | return !m_exec.isEmpty(); | ||||
98 | } | ||||
99 | return false; | ||||
100 | } | ||||
101 | | ||||
102 | bool KateExternalTool::valid( const QString &mt ) const | ||||
103 | { | ||||
104 | return mimetypes.isEmpty() || mimetypes.contains( mt ); | ||||
105 | } | ||||
106 | //END KateExternalTool | ||||
107 | | ||||
108 | //BEGIN KateExternalToolsCommand | ||||
109 | KateExternalToolsCommand::KateExternalToolsCommand(KateExternalToolsPlugin *plugin) : KTextEditor::Command(),m_plugin(plugin) | ||||
110 | { | ||||
111 | m_inited = false; | ||||
112 | reload(); | ||||
113 | } | ||||
114 | | ||||
115 | const QStringList &KateExternalToolsCommand::cmds () | ||||
116 | { | ||||
117 | return m_list; | ||||
118 | } | ||||
119 | | ||||
120 | | ||||
121 | void KateExternalToolsCommand::reload () | ||||
122 | { | ||||
123 | m_list.clear(); | ||||
124 | m_map.clear(); | ||||
125 | m_name.clear(); | ||||
126 | | ||||
127 | KConfig _config( "externaltools", KConfig::NoGlobals, "appdata" ); | ||||
128 | KConfigGroup config(&_config, "Global"); | ||||
129 | const QStringList tools = config.readEntry("tools", QStringList()); | ||||
130 | | ||||
131 | | ||||
132 | for( QStringList::const_iterator it = tools.begin(); it != tools.end(); ++it ) | ||||
133 | { | ||||
134 | if ( *it == "---" ) | ||||
135 | continue; | ||||
136 | | ||||
137 | | ||||
138 | config= KConfigGroup(&_config, *it ); | ||||
139 | | ||||
140 | KateExternalTool t = KateExternalTool( | ||||
141 | config.readEntry( "name", "" ), | ||||
142 | config.readEntry( "command", ""), | ||||
143 | config.readEntry( "icon", ""), | ||||
144 | config.readEntry( "executable", ""), | ||||
145 | config.readEntry( "mimetypes", QStringList() ), | ||||
146 | config.readEntry( "acname", "" ), | ||||
147 | config.readEntry( "cmdname", "" ) ); | ||||
148 | // FIXME test for a command name first! | ||||
149 | if ( t.hasexec && (!t.cmdname.isEmpty())) | ||||
150 | { | ||||
151 | m_list.append("exttool-" + t.cmdname); | ||||
152 | m_map.insert("exttool-" + t.cmdname, t.acname); | ||||
153 | m_name.insert("exttool-" + t.cmdname, t.name); | ||||
154 | } | ||||
155 | } | ||||
156 | if (m_inited) | ||||
157 | { | ||||
158 | KTextEditor::CommandInterface* cmdIface = | ||||
159 | qobject_cast<KTextEditor::CommandInterface*>( Kate::application()->editor() ); | ||||
160 | if( cmdIface ) | ||||
161 | { | ||||
162 | // reregister commands, in case of something has changed | ||||
163 | cmdIface->unregisterCommand( this ); | ||||
164 | cmdIface->registerCommand( this ); | ||||
165 | } | ||||
166 | } | ||||
167 | else m_inited = true; | ||||
168 | } | ||||
169 | | ||||
170 | bool KateExternalToolsCommand::exec (KTextEditor::View *view, const QString &cmd, QString &) | ||||
171 | { | ||||
172 | QWidget *wv = dynamic_cast<QWidget*>(view); | ||||
173 | if (!wv) | ||||
174 | { | ||||
175 | // kDebug(13001)<<"KateExternalToolsCommand::exec: Could not get view widget"; | ||||
176 | return false; | ||||
177 | } | ||||
178 | | ||||
179 | | ||||
180 | // kDebug(13001)<<"cmd="<<cmd.trimmed(); | ||||
181 | QString actionName = m_map[cmd.trimmed()]; | ||||
182 | if (actionName.isEmpty()) return false; | ||||
183 | // kDebug(13001)<<"actionName is not empty:"<<actionName; | ||||
184 | /* KateExternalToolsMenuAction *a = | ||||
185 | dynamic_cast<KateExternalToolsMenuAction*>(dmw->action("tools_external")); | ||||
186 | if (!a) return false;*/ | ||||
187 | KateExternalToolsPluginView *extview=m_plugin->extView(wv->window()); | ||||
188 | if (!extview) return false; | ||||
189 | if (!extview->externalTools) return false; | ||||
190 | // kDebug(13001)<<"trying to find action"; | ||||
191 | QAction *a1 = extview->externalTools->actionCollection()->action(actionName.toUtf8().constData ()); | ||||
192 | if (!a1) return false; | ||||
193 | // kDebug(13001)<<"activating action"; | ||||
194 | a1->trigger(); | ||||
195 | return true; | ||||
196 | } | ||||
197 | | ||||
198 | bool KateExternalToolsCommand::help (KTextEditor::View *, const QString &, QString &) | ||||
199 | { | ||||
200 | return false; | ||||
201 | } | ||||
202 | //END KateExternalToolsCommand | ||||
203 | | ||||
204 | //BEGIN KateExternalToolAction | ||||
205 | KateExternalToolAction::KateExternalToolAction( QObject *parent, KateExternalTool *t) | ||||
206 | : KAction( KIcon(t->icon), t->name, parent ), | ||||
207 | tool ( t ) | ||||
208 | { | ||||
209 | //setText( t->name ); | ||||
210 | //if ( ! t->icon.isEmpty() ) | ||||
211 | // setIcon( KIcon( t->icon ) ); | ||||
212 | | ||||
213 | connect( this, SIGNAL(triggered(bool)), SLOT(slotRun()) ); | ||||
214 | } | ||||
215 | | ||||
216 | bool KateExternalToolAction::expandMacro( const QString &str, QStringList &ret ) | ||||
217 | { | ||||
218 | Kate::MainWindow *mw = qobject_cast<Kate::MainWindow*>(parent()->parent()); | ||||
219 | Q_ASSERT(mw); | ||||
220 | | ||||
221 | KTextEditor::View *view = mw->activeView(); | ||||
222 | if ( ! view ) return false; | ||||
223 | | ||||
224 | KTextEditor::Document *doc = view->document(); | ||||
225 | KUrl url = doc->url(); | ||||
226 | | ||||
227 | if ( str == "URL" ) | ||||
228 | ret += url.url(); | ||||
229 | else if ( str == "directory" ) // directory of current doc | ||||
230 | ret += url.directory(); | ||||
231 | else if ( str == "filename" ) | ||||
232 | ret += url.fileName(); | ||||
233 | else if ( str == "line" ) // cursor line of current doc | ||||
234 | ret += QString::number( view->cursorPosition().line() ); | ||||
235 | else if ( str == "col" ) // cursor col of current doc | ||||
236 | ret += QString::number( view->cursorPosition().column() ); | ||||
237 | else if ( str == "selection" ) // selection of current doc if any | ||||
238 | ret += view->selectionText(); | ||||
239 | else if ( str == "text" ) // text of current doc | ||||
240 | ret += doc->text(); | ||||
241 | else if ( str == "URLs" ) | ||||
242 | { | ||||
243 | foreach( KTextEditor::Document *it, Kate::documentManager()->documents()) | ||||
244 | if ( ! it->url().isEmpty() ) | ||||
245 | ret += it->url().url(); | ||||
246 | } | ||||
247 | else | ||||
248 | return false; | ||||
249 | | ||||
250 | return true; | ||||
251 | } | ||||
252 | | ||||
253 | KateExternalToolAction::~KateExternalToolAction() | ||||
254 | { | ||||
255 | delete(tool); | ||||
256 | } | ||||
257 | | ||||
258 | void KateExternalToolAction::slotRun() | ||||
259 | { | ||||
260 | // expand the macros in command if any, | ||||
261 | // and construct a command with an absolute path | ||||
262 | QString cmd = tool->command; | ||||
263 | | ||||
264 | Kate::MainWindow *mw = qobject_cast<Kate::MainWindow*>(parent()->parent()); | ||||
265 | if ( ! expandMacrosShellQuote( cmd ) ) | ||||
266 | { | ||||
267 | KMessageBox::sorry( mw->window(), | ||||
268 | i18n("Failed to expand the command '%1'.", cmd ), | ||||
269 | i18n( "Kate External Tools") ); | ||||
270 | return; | ||||
271 | } | ||||
272 | kDebug(13001) << "externaltools: Running command: " << cmd; | ||||
273 | | ||||
274 | // save documents if requested | ||||
275 | if ( tool->save == 1 ) | ||||
276 | mw->activeView()->document()->save(); | ||||
277 | else if ( tool->save == 2 ) | ||||
278 | { | ||||
279 | foreach (KXMLGUIClient *client, mw->guiFactory()->clients()) | ||||
280 | { | ||||
281 | if (QAction *a = client->actionCollection()->action("file_save_all")) | ||||
282 | { | ||||
283 | a->trigger(); | ||||
284 | break; | ||||
285 | } | ||||
286 | } | ||||
287 | } | ||||
288 | | ||||
289 | KRun::runCommand( cmd, tool->tryexec, tool->icon, mw->window() ); | ||||
290 | } | ||||
291 | //END KateExternalToolAction | ||||
292 | | ||||
293 | //BEGIN KateExternalToolsMenuAction | ||||
294 | KateExternalToolsMenuAction::KateExternalToolsMenuAction( const QString &text, | ||||
295 | KActionCollection *collection, | ||||
296 | QObject *parent, | ||||
297 | Kate::MainWindow *mw ) | ||||
298 | : KActionMenu( text, parent ), | ||||
299 | mainwindow( mw ) | ||||
300 | { | ||||
301 | | ||||
302 | m_actionCollection = collection; | ||||
303 | | ||||
304 | // connect to view changed... | ||||
305 | connect(mw, SIGNAL(viewChanged()), this, SLOT(slotDocumentChanged())); | ||||
306 | | ||||
307 | reload(); | ||||
308 | } | ||||
309 | | ||||
310 | KateExternalToolsMenuAction::~KateExternalToolsMenuAction() | ||||
311 | { | ||||
312 | //kDebug() << "deleted KateExternalToolsMenuAction"; | ||||
313 | } | ||||
314 | | ||||
315 | void KateExternalToolsMenuAction::reload() | ||||
316 | { | ||||
317 | bool needs_readd=(m_actionCollection->takeAction(this)!=0); | ||||
318 | m_actionCollection->clear (); | ||||
319 | if (needs_readd) m_actionCollection->addAction("tools_external",this); | ||||
320 | menu()->clear(); | ||||
321 | | ||||
322 | // load all the tools, and create a action for each of them | ||||
323 | KSharedConfig::Ptr pConfig = KSharedConfig::openConfig( "externaltools", KConfig::NoGlobals, "appdata" ); | ||||
324 | KConfigGroup config(pConfig, "Global" ); | ||||
325 | QStringList tools = config.readEntry( "tools", QStringList() ); | ||||
326 | | ||||
327 | // if there are tools that are present but not explicitly removed, | ||||
328 | // add them to the end of the list | ||||
329 | pConfig->setReadDefaults( true ); | ||||
330 | QStringList dtools = config.readEntry( "tools", QStringList() ); | ||||
331 | int gver = config.readEntry( "version", 1 ); | ||||
332 | pConfig->setReadDefaults( false ); | ||||
333 | | ||||
334 | int ver = config.readEntry( "version", 0 ); | ||||
335 | if ( ver <= gver ) | ||||
336 | { | ||||
337 | QStringList removed = config.readEntry( "removed", QStringList() ); | ||||
338 | bool sepadded = false; | ||||
339 | for (QStringList::iterator itg = dtools.begin(); itg != dtools.end(); ++itg ) | ||||
340 | { | ||||
341 | if ( ! tools.contains( *itg ) && | ||||
342 | ! removed.contains( *itg ) ) | ||||
343 | { | ||||
344 | if ( ! sepadded ) | ||||
345 | { | ||||
346 | tools << "---"; | ||||
347 | sepadded = true; | ||||
348 | } | ||||
349 | tools << *itg; | ||||
350 | } | ||||
351 | } | ||||
352 | | ||||
353 | config.writeEntry( "tools", tools ); | ||||
354 | config.sync(); | ||||
355 | config.writeEntry( "version", gver ); | ||||
356 | } | ||||
357 | | ||||
358 | for( QStringList::const_iterator it = tools.constBegin(); it != tools.constEnd(); ++it ) | ||||
359 | { | ||||
360 | if ( *it == "---" ) | ||||
361 | { | ||||
362 | menu()->addSeparator(); | ||||
363 | // a separator | ||||
364 | continue; | ||||
365 | } | ||||
366 | | ||||
367 | config=KConfigGroup(pConfig, *it ); | ||||
368 | | ||||
369 | KateExternalTool *t = new KateExternalTool( | ||||
370 | config.readEntry( "name", "" ), | ||||
371 | config.readEntry( "command", ""), | ||||
372 | config.readEntry( "icon", ""), | ||||
373 | config.readEntry( "executable", ""), | ||||
374 | config.readEntry( "mimetypes", QStringList() ), | ||||
375 | config.readEntry( "acname", "" ), | ||||
376 | config.readEntry( "cmdname", "" ), | ||||
377 | config.readEntry( "save", 0 ) ); | ||||
378 | | ||||
379 | if ( t->hasexec ) | ||||
380 | { | ||||
381 | KAction *a = new KateExternalToolAction( this, t ); | ||||
382 | m_actionCollection->addAction( t->acname.toAscii(), a ); | ||||
383 | addAction( a ); | ||||
384 | } | ||||
385 | else | ||||
386 | delete t; | ||||
387 | } | ||||
388 | | ||||
389 | config=KConfigGroup(pConfig, "Shortcuts"); | ||||
390 | m_actionCollection->readSettings( &config ); | ||||
391 | slotDocumentChanged(); | ||||
392 | } | ||||
393 | | ||||
394 | void KateExternalToolsMenuAction::slotDocumentChanged() | ||||
395 | { | ||||
396 | // try to enable/disable to match current mime type | ||||
397 | KTextEditor::View *v = mainwindow->activeView(); | ||||
398 | | ||||
399 | // no active view, oh oh | ||||
400 | if (!v) | ||||
401 | return; | ||||
402 | | ||||
403 | KTextEditor::Document *de = v->document(); | ||||
404 | if ( de ) | ||||
405 | { | ||||
406 | QString mt = de->mimeType(); | ||||
407 | QStringList l; | ||||
408 | bool b; | ||||
409 | | ||||
410 | foreach (QAction* kaction, m_actionCollection->actions()) | ||||
411 | { | ||||
412 | KateExternalToolAction *action = dynamic_cast<KateExternalToolAction*>(kaction); | ||||
413 | if ( action ) | ||||
414 | { | ||||
415 | l = action->tool->mimetypes; | ||||
416 | b = ( ! l.count() || l.contains( mt ) ); | ||||
417 | action->setEnabled( b ); | ||||
418 | } | ||||
419 | } | ||||
420 | } | ||||
421 | } | ||||
422 | //END KateExternalToolsMenuAction | ||||
423 | | ||||
424 | //BEGIN ToolItem | ||||
425 | /** | ||||
426 | * This is a QListBoxItem, that has a KateExternalTool. The text is the Name | ||||
427 | * of the tool. | ||||
428 | */ | ||||
429 | class ToolItem : public QListWidgetItem | ||||
430 | { | ||||
431 | public: | ||||
432 | ToolItem( QListWidget *lb, const QPixmap &icon, KateExternalTool *tool ) | ||||
433 | : QListWidgetItem( icon , tool->name , lb ), | ||||
434 | tool ( tool ) | ||||
435 | { | ||||
436 | } | ||||
437 | | ||||
438 | ~ToolItem() | ||||
439 | {} | ||||
440 | | ||||
441 | KateExternalTool *tool; | ||||
442 | }; | ||||
443 | //END ToolItem | ||||
444 | | ||||
445 | //BEGIN KateExternalToolServiceEditor | ||||
446 | KateExternalToolServiceEditor::KateExternalToolServiceEditor( KateExternalTool *tool, | ||||
447 | QWidget *parent, const char *name ) | ||||
448 | : KDialog( parent ), | ||||
449 | tool( tool ) | ||||
450 | { | ||||
451 | setCaption( i18n("Edit External Tool") ); | ||||
452 | setButtons( Ok | Cancel ); | ||||
453 | setObjectName( name ); | ||||
454 | setModal( true ); | ||||
455 | | ||||
456 | // create a entry for each property | ||||
457 | // fill in the values from the service if available | ||||
458 | QWidget *w = new QWidget( this ); | ||||
459 | setMainWidget( w ); | ||||
460 | QGridLayout *lo = new QGridLayout( w ); | ||||
461 | lo->setSpacing( KDialog::spacingHint() ); | ||||
462 | | ||||
463 | QLabel *l; | ||||
464 | | ||||
465 | leName = new KLineEdit( w ); | ||||
466 | lo->addWidget( leName, 1, 2 ); | ||||
467 | l = new QLabel( w ); | ||||
468 | l->setBuddy( leName ); | ||||
469 | l->setText( i18n("&Label:") ); | ||||
470 | l->setAlignment( l->alignment() | Qt::AlignRight ); | ||||
471 | lo->addWidget( l, 1, 1 ); | ||||
472 | if ( tool ) leName->setText( tool->name ); | ||||
473 | leName->setWhatsThis(i18n( | ||||
474 | "The name will be displayed in the 'Tools->External' menu") ); | ||||
475 | | ||||
476 | btnIcon = new KIconButton( w ); | ||||
477 | btnIcon->setIconSize( KIconLoader::SizeSmall ); | ||||
478 | lo->addWidget( btnIcon, 1, 3 ); | ||||
479 | if ( tool && !tool->icon.isEmpty() ) | ||||
480 | btnIcon->setIcon( tool->icon ); | ||||
481 | | ||||
482 | teCommand = new QTextEdit( w ); | ||||
483 | lo->addWidget( teCommand, 2, 2, 1, 2 ); | ||||
484 | l = new QLabel( w ); | ||||
485 | l->setBuddy( teCommand ); | ||||
486 | l->setText( i18n("S&cript:") ); | ||||
487 | l->setAlignment( Qt::AlignTop | Qt::AlignRight ); | ||||
488 | lo->addWidget( l, 2, 1 ); | ||||
489 | if ( tool ) teCommand->setText( tool->command ); | ||||
490 | teCommand->setWhatsThis(i18n( | ||||
491 | "<p>The script to execute to invoke the tool. The script is passed " | ||||
492 | "to /bin/sh for execution. The following macros " | ||||
493 | "will be expanded:</p>" | ||||
494 | "<ul><li><code>%URL</code> - the URL of the current document.</li>" | ||||
495 | "<li><code>%URLs</code> - a list of the URLs of all open documents.</li>" | ||||
496 | "<li><code>%directory</code> - the URL of the directory containing " | ||||
497 | "the current document.</li>" | ||||
498 | "<li><code>%filename</code> - the filename of the current document.</li>" | ||||
499 | "<li><code>%line</code> - the current line of the text cursor in the " | ||||
500 | "current view.</li>" | ||||
501 | "<li><code>%column</code> - the column of the text cursor in the " | ||||
502 | "current view.</li>" | ||||
503 | "<li><code>%selection</code> - the selected text in the current view.</li>" | ||||
504 | "<li><code>%text</code> - the text of the current document.</li></ul>" ) ); | ||||
505 | | ||||
506 | | ||||
507 | leExecutable = new KLineEdit( w ); | ||||
508 | lo->addWidget( leExecutable, 3, 2, 1, 2 ); | ||||
509 | l = new QLabel( w ); | ||||
510 | l->setBuddy( leExecutable ); | ||||
511 | l->setText( i18n("&Executable:") ); | ||||
512 | l->setAlignment( l->alignment() | Qt::AlignRight ); | ||||
513 | lo->addWidget( l, 3, 1 ); | ||||
514 | if ( tool ) leExecutable->setText( tool->tryexec ); | ||||
515 | leExecutable->setWhatsThis(i18n( | ||||
516 | "The executable used by the command. This is used to check if a tool " | ||||
517 | "should be displayed; if not set, the first word of <em>command</em> " | ||||
518 | "will be used.") ); | ||||
519 | | ||||
520 | leMimetypes = new KLineEdit( w ); | ||||
521 | lo->addWidget( leMimetypes, 4, 2 ); | ||||
522 | l = new QLabel( w ); | ||||
523 | l->setBuddy( leMimetypes ); | ||||
524 | l->setText( i18n("&Mime types:") ); | ||||
525 | l->setAlignment( l->alignment() | Qt::AlignRight ); | ||||
526 | lo->addWidget( l, 4, 1 ); | ||||
527 | if ( tool ) leMimetypes->setText( tool->mimetypes.join("; ") ); | ||||
528 | leMimetypes->setWhatsThis(i18n( | ||||
529 | "A semicolon-separated list of mime types for which this tool should " | ||||
530 | "be available; if this is left empty, the tool is always available. " | ||||
531 | "To choose from known mimetypes, press the button on the right.") ); | ||||
532 | | ||||
533 | QToolButton *btnMTW = new QToolButton(w); | ||||
534 | lo->addWidget( btnMTW, 4, 3 ); | ||||
535 | btnMTW->setIcon(QIcon(SmallIcon("wizard"))); | ||||
536 | connect(btnMTW, SIGNAL(clicked()), this, SLOT(showMTDlg())); | ||||
537 | btnMTW->setWhatsThis(i18n( | ||||
538 | "Click for a dialog that can help you create a list of mimetypes.") ); | ||||
539 | | ||||
540 | cmbSave = new KComboBox(w); | ||||
541 | lo->addWidget( cmbSave, 5, 2, 1, 2 ); | ||||
542 | l = new QLabel( w ); | ||||
543 | l->setBuddy( cmbSave ); | ||||
544 | l->setText( i18n("&Save:") ); | ||||
545 | l->setAlignment( l->alignment() | Qt::AlignRight ); | ||||
546 | lo->addWidget( l, 5, 1 ); | ||||
547 | QStringList sl; | ||||
548 | sl << i18n("None") << i18n("Current Document") << i18n("All Documents"); | ||||
549 | cmbSave->addItems( sl ); | ||||
550 | if ( tool ) cmbSave->setCurrentIndex( tool->save ); | ||||
551 | cmbSave->setWhatsThis(i18n( | ||||
552 | "You can choose to save the current or all [modified] documents prior to " | ||||
553 | "running the command. This is helpful if you want to pass URLs to " | ||||
554 | "an application like, for example, an FTP client.") ); | ||||
555 | | ||||
556 | | ||||
557 | leCmdLine = new KLineEdit( w ); | ||||
558 | lo->addWidget( leCmdLine, 6, 2, 1, 2 ); | ||||
559 | l = new QLabel( i18n("&Command line name:"), w ); | ||||
560 | l->setBuddy( leCmdLine ); | ||||
561 | l->setAlignment( l->alignment() | Qt::AlignRight ); | ||||
562 | lo->addWidget( l, 6, 1 ); | ||||
563 | if ( tool ) leCmdLine->setText( tool->cmdname ); | ||||
564 | leCmdLine->setWhatsThis(i18n( | ||||
565 | "If you specify a name here, you can invoke the command from the view " | ||||
566 | "command line with exttool-the_name_you_specified_here. " | ||||
567 | "Please do not use spaces or tabs in the name.")); | ||||
568 | } | ||||
569 | | ||||
570 | void KateExternalToolServiceEditor::slotButtonClicked(int button) | ||||
571 | { | ||||
572 | switch( button ) { | ||||
573 | case Ok: | ||||
574 | if ( leName->text().isEmpty() || teCommand->document()->isEmpty() ) | ||||
575 | { | ||||
576 | KMessageBox::information( this, i18n("You must specify at least a name and a command") ); | ||||
577 | return; | ||||
578 | } | ||||
579 | accept(); | ||||
580 | break; | ||||
581 | case Cancel: | ||||
582 | reject(); | ||||
583 | break; | ||||
584 | } | ||||
585 | | ||||
586 | } | ||||
587 | | ||||
588 | void KateExternalToolServiceEditor::showMTDlg() | ||||
589 | { | ||||
590 | QString text = i18n("Select the MimeTypes for which to enable this tool."); | ||||
591 | QStringList list = leMimetypes->text().split( QRegExp("\\s*;\\s*"), QString::SkipEmptyParts ); | ||||
592 | KMimeTypeChooserDialog d( i18n("Select Mime Types"), text, list, "text", this ); | ||||
593 | if ( d.exec() == KDialog::Accepted ) | ||||
594 | { | ||||
595 | leMimetypes->setText( d.chooser()->mimeTypes().join(";") ); | ||||
596 | } | ||||
597 | } | ||||
598 | //END KateExternalToolServiceEditor | ||||
599 | | ||||
600 | //BEGIN KateExternalToolsConfigWidget | ||||
601 | KateExternalToolsConfigWidget::KateExternalToolsConfigWidget( QWidget *parent, KateExternalToolsPlugin *plugin, const char* name) | ||||
602 | : Kate::PluginConfigPage( parent, name ) | ||||
603 | , m_changed( false ) | ||||
604 | , m_plugin(plugin) | ||||
605 | { | ||||
606 | setupUi(this); | ||||
607 | | ||||
608 | btnMoveUp->setIcon(KIcon("go-up")); | ||||
609 | btnMoveDown->setIcon(KIcon("go-down")); | ||||
610 | | ||||
611 | connect( lbTools, SIGNAL(itemSelectionChanged()), this, SLOT(slotSelectionChanged()) ); | ||||
612 | connect( lbTools, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(slotEdit()) ); | ||||
613 | connect( btnNew, SIGNAL(clicked()), this, SLOT(slotNew()) ); | ||||
614 | connect( btnRemove, SIGNAL(clicked()), this, SLOT(slotRemove()) ); | ||||
615 | connect( btnEdit, SIGNAL(clicked()), this, SLOT(slotEdit()) ); | ||||
616 | connect( btnSeparator, SIGNAL(clicked()), this, SLOT(slotInsertSeparator()) ); | ||||
617 | connect( btnMoveUp, SIGNAL(clicked()), this, SLOT(slotMoveUp()) ); | ||||
618 | connect( btnMoveDown, SIGNAL(clicked()), this, SLOT(slotMoveDown()) ); | ||||
619 | | ||||
620 | config = new KConfig( "externaltools", KConfig::NoGlobals, "appdata" ); | ||||
621 | reset(); | ||||
622 | slotSelectionChanged(); | ||||
623 | } | ||||
624 | | ||||
625 | KateExternalToolsConfigWidget::~KateExternalToolsConfigWidget() | ||||
626 | { | ||||
627 | delete config; | ||||
628 | } | ||||
629 | | ||||
630 | void KateExternalToolsConfigWidget::reset() | ||||
631 | { | ||||
632 | //m_tools.clear(); | ||||
633 | lbTools->clear(); | ||||
634 | | ||||
635 | // load the files from a KConfig | ||||
636 | const QStringList tools = config->group("Global").readEntry("tools", QStringList()); | ||||
637 | | ||||
638 | for( QStringList::const_iterator it = tools.begin(); it != tools.end(); ++it ) | ||||
639 | { | ||||
640 | if ( *it == "---" ) | ||||
641 | { | ||||
642 | new QListWidgetItem( "---" , lbTools); | ||||
643 | } | ||||
644 | else | ||||
645 | { | ||||
646 | KConfigGroup cg( config, *it ); | ||||
647 | | ||||
648 | KateExternalTool *t = new KateExternalTool( | ||||
649 | cg.readEntry( "name", "" ), | ||||
650 | cg.readEntry( "command", ""), | ||||
651 | cg.readEntry( "icon", ""), | ||||
652 | cg.readEntry( "executable", ""), | ||||
653 | cg.readEntry( "mimetypes", QStringList() ), | ||||
654 | cg.readEntry( "acname" ), | ||||
655 | cg.readEntry( "cmdname"), | ||||
656 | cg.readEntry( "save", 0 ) ); | ||||
657 | | ||||
658 | if ( t->hasexec ) // we only show tools that are also in the menu. | ||||
659 | new ToolItem( lbTools, t->icon.isEmpty() ? blankIcon() : SmallIcon( t->icon ), t ); | ||||
660 | else | ||||
661 | delete t; | ||||
662 | } | ||||
663 | } | ||||
664 | m_changed = false; | ||||
665 | } | ||||
666 | | ||||
667 | QPixmap KateExternalToolsConfigWidget::blankIcon() | ||||
668 | { | ||||
669 | QPixmap pm( KIconLoader::SizeSmall, KIconLoader::SizeSmall ); | ||||
670 | pm.fill(); | ||||
671 | pm.setMask( pm.createHeuristicMask() ); | ||||
672 | return pm; | ||||
673 | } | ||||
674 | | ||||
675 | void KateExternalToolsConfigWidget::apply() | ||||
676 | { | ||||
677 | if ( ! m_changed ) | ||||
678 | return; | ||||
679 | m_changed = false; | ||||
680 | | ||||
681 | // save a new list | ||||
682 | // save each item | ||||
683 | QStringList tools; | ||||
684 | for ( int i = 0; i < lbTools->count(); i++ ) | ||||
685 | { | ||||
686 | if ( lbTools->item(i)->text() == "---" ) | ||||
687 | { | ||||
688 | tools << "---"; | ||||
689 | continue; | ||||
690 | } | ||||
691 | KateExternalTool *t = static_cast<ToolItem*>(lbTools->item( i ))->tool; | ||||
692 | // kDebug(13001)<<"adding tool: "<<t->name; | ||||
693 | tools << t->acname; | ||||
694 | | ||||
695 | KConfigGroup cg( config, t->acname ); | ||||
696 | | ||||
697 | cg.writeEntry( "name", t->name ); | ||||
698 | cg.writeEntry( "command", t->command ); | ||||
699 | cg.writeEntry( "icon", t->icon ); | ||||
700 | cg.writeEntry( "executable", t->tryexec ); | ||||
701 | cg.writeEntry( "mimetypes", t->mimetypes ); | ||||
702 | cg.writeEntry( "acname", t->acname ); | ||||
703 | cg.writeEntry( "cmdname", t->cmdname ); | ||||
704 | cg.writeEntry( "save", t->save ); | ||||
705 | } | ||||
706 | | ||||
707 | config->group("Global").writeEntry( "tools", tools ); | ||||
708 | | ||||
709 | // if any tools was removed, try to delete their groups, and | ||||
710 | // add the group names to the list of removed items. | ||||
711 | if ( m_removed.count() ) | ||||
712 | { | ||||
713 | for ( QStringList::iterator it = m_removed.begin(); it != m_removed.end(); ++it ) | ||||
714 | { | ||||
715 | if ( config->hasGroup( *it ) ) | ||||
716 | config->deleteGroup( *it ); | ||||
717 | } | ||||
718 | QStringList removed = config->group("Global").readEntry( "removed", QStringList() ); | ||||
719 | removed += m_removed; | ||||
720 | | ||||
721 | // clean up the list of removed items, so that it does not contain | ||||
722 | // non-existing groups (we can't remove groups from a non-owned global file). | ||||
723 | config->sync(); | ||||
724 | QStringList::iterator it1 = removed.begin(); | ||||
725 | while ( it1 != removed.end() ) | ||||
726 | { | ||||
727 | if ( ! config->hasGroup( *it1 ) ) | ||||
728 | it1 = removed.erase( it1 ); | ||||
729 | else | ||||
730 | ++it1; | ||||
731 | } | ||||
732 | config->group("Global").writeEntry( "removed", removed ); | ||||
733 | } | ||||
734 | | ||||
735 | config->sync(); | ||||
736 | m_plugin->reload(); | ||||
737 | } | ||||
738 | | ||||
739 | void KateExternalToolsConfigWidget::slotSelectionChanged() | ||||
740 | { | ||||
741 | // update button state | ||||
742 | bool hs = lbTools->currentItem() != 0; | ||||
743 | btnEdit->setEnabled( hs && dynamic_cast<ToolItem*>(lbTools->currentItem()) ); | ||||
744 | btnRemove->setEnabled( hs ); | ||||
745 | btnMoveUp->setEnabled( ( lbTools->currentRow() > 0 ) && hs ); | ||||
746 | btnMoveDown->setEnabled( ( lbTools->currentRow() < (int)lbTools->count() - 1 ) && hs ); | ||||
747 | } | ||||
748 | | ||||
749 | void KateExternalToolsConfigWidget::slotNew() | ||||
750 | { | ||||
751 | // display a editor, and if it is OK'd, create a new tool and | ||||
752 | // create a listbox item for it | ||||
753 | KateExternalToolServiceEditor editor( 0, this ); | ||||
754 | | ||||
755 | if ( editor.exec() ) | ||||
756 | { | ||||
757 | KateExternalTool *t = new KateExternalTool( | ||||
758 | editor.leName->text(), | ||||
759 | editor.teCommand->toPlainText(), | ||||
760 | editor.btnIcon->icon(), | ||||
761 | editor.leExecutable->text(), | ||||
762 | editor.leMimetypes->text().split( QRegExp("\\s*;\\s*"), QString::SkipEmptyParts ) ); | ||||
763 | | ||||
764 | // This is sticky, it does not change again, so that shortcuts sticks | ||||
765 | // TODO check for dups | ||||
766 | t->acname = "externaltool_" + QString(t->name).remove( QRegExp("\\W+") ); | ||||
767 | | ||||
768 | new ToolItem ( lbTools, t->icon.isEmpty() ? blankIcon() : SmallIcon( t->icon ), t ); | ||||
769 | | ||||
770 | emit changed(); | ||||
771 | m_changed = true; | ||||
772 | } | ||||
773 | } | ||||
774 | | ||||
775 | void KateExternalToolsConfigWidget::slotRemove() | ||||
776 | { | ||||
777 | // add the tool action name to a list of removed items, | ||||
778 | // remove the current listbox item | ||||
779 | if ( lbTools->currentRow() > -1 ) | ||||
780 | { | ||||
781 | ToolItem *i = dynamic_cast<ToolItem*>(lbTools->currentItem()); | ||||
782 | if ( i ) | ||||
783 | m_removed << i->tool->acname; | ||||
784 | | ||||
785 | delete lbTools->takeItem( lbTools->currentRow() ); | ||||
786 | emit changed(); | ||||
787 | m_changed = true; | ||||
788 | } | ||||
789 | } | ||||
790 | | ||||
791 | void KateExternalToolsConfigWidget::slotEdit() | ||||
792 | { | ||||
793 | if( !dynamic_cast<ToolItem*>(lbTools->currentItem()) ) return; | ||||
794 | // show the item in an editor | ||||
795 | KateExternalTool *t = static_cast<ToolItem*>(lbTools->currentItem())->tool; | ||||
796 | KateExternalToolServiceEditor editor( t, this); | ||||
797 | editor.resize( config->group("Editor").readEntry( "Size", QSize() ) ); | ||||
798 | if ( editor.exec() /*== KDialog::Ok*/ ) | ||||
799 | { | ||||
800 | | ||||
801 | bool elementChanged = ( ( editor.btnIcon->icon() != t->icon ) || (editor.leName->text() != t->name ) ) ; | ||||
802 | | ||||
803 | t->name = editor.leName->text(); | ||||
804 | t->cmdname = editor.leCmdLine->text(); | ||||
805 | t->command = editor.teCommand->toPlainText(); | ||||
806 | t->icon = editor.btnIcon->icon(); | ||||
807 | t->tryexec = editor.leExecutable->text(); | ||||
808 | t->mimetypes = editor.leMimetypes->text().split( QRegExp("\\s*;\\s*"), QString::SkipEmptyParts ); | ||||
809 | t->save = editor.cmbSave->currentIndex(); | ||||
810 | | ||||
811 | //if the icon has changed or name changed, I have to renew the listbox item :S | ||||
812 | if ( elementChanged ) | ||||
813 | { | ||||
814 | int idx = lbTools->row( lbTools->currentItem() ); | ||||
815 | delete lbTools->takeItem( idx ); | ||||
816 | lbTools->insertItem( idx , new ToolItem( 0, t->icon.isEmpty() ? blankIcon() : SmallIcon( t->icon ), t )); | ||||
817 | } | ||||
818 | | ||||
819 | emit changed(); | ||||
820 | m_changed = true; | ||||
821 | } | ||||
822 | | ||||
823 | config->group("Editor").writeEntry( "Size", editor.size() ); | ||||
824 | config->sync(); | ||||
825 | } | ||||
826 | | ||||
827 | void KateExternalToolsConfigWidget::slotInsertSeparator() | ||||
828 | { | ||||
829 | lbTools->insertItem( lbTools->currentRow() + 1 , "---" ); | ||||
830 | emit changed(); | ||||
831 | m_changed = true; | ||||
832 | } | ||||
833 | | ||||
834 | void KateExternalToolsConfigWidget::slotMoveUp() | ||||
835 | { | ||||
836 | // move the current item in the listbox upwards if possible | ||||
837 | QListWidgetItem *item = lbTools->currentItem(); | ||||
838 | if ( ! item ) return; | ||||
839 | | ||||
840 | int idx = lbTools->row( item ); | ||||
841 | | ||||
842 | if ( idx < 1 ) return; | ||||
843 | | ||||
844 | if ( dynamic_cast<ToolItem*>(item) ) | ||||
845 | { | ||||
846 | KateExternalTool *tool = static_cast<ToolItem*>(item)->tool; | ||||
847 | delete lbTools->takeItem( idx ); | ||||
848 | lbTools->insertItem( idx - 1 , new ToolItem( 0, tool->icon.isEmpty() ? blankIcon() : SmallIcon( tool->icon ), tool ) ); | ||||
849 | } | ||||
850 | else // a separator! | ||||
851 | { | ||||
852 | delete lbTools->takeItem( idx ); | ||||
853 | lbTools->insertItem( idx - 1 , new QListWidgetItem( "---" )); | ||||
854 | } | ||||
855 | | ||||
856 | lbTools->setCurrentRow( idx - 1 ); | ||||
857 | slotSelectionChanged(); | ||||
858 | emit changed(); | ||||
859 | m_changed = true; | ||||
860 | } | ||||
861 | | ||||
862 | void KateExternalToolsConfigWidget::slotMoveDown() | ||||
863 | { | ||||
864 | // move the current item in the listbox downwards if possible | ||||
865 | QListWidgetItem *item = lbTools->currentItem(); | ||||
866 | if ( ! item ) return; | ||||
867 | | ||||
868 | int idx = lbTools->row( item ); | ||||
869 | | ||||
870 | if ( idx > lbTools->count() - 1 ) return; | ||||
871 | | ||||
872 | if ( dynamic_cast<ToolItem*>(item) ) | ||||
873 | { | ||||
874 | KateExternalTool *tool = static_cast<ToolItem*>(item)->tool; | ||||
875 | delete lbTools->takeItem( idx ); | ||||
876 | lbTools->insertItem( idx + 1 , new ToolItem( 0, tool->icon.isEmpty() ? blankIcon() : SmallIcon( tool->icon ), tool ) ); | ||||
877 | } | ||||
878 | else // a separator! | ||||
879 | { | ||||
880 | delete lbTools->takeItem( idx ); | ||||
881 | lbTools->insertItem( idx + 1 , new QListWidgetItem( "---" ) ); | ||||
882 | } | ||||
883 | | ||||
884 | lbTools->setCurrentRow( idx + 1 ); | ||||
885 | slotSelectionChanged(); | ||||
886 | emit changed(); | ||||
887 | m_changed = true; | ||||
888 | } | ||||
889 | //END KateExternalToolsConfigWidget | ||||
890 | // kate: space-indent on; indent-width 2; replace-tabs on; |