00001 #include "tools_part.h"
00002
00003 #include <qfile.h>
00004 #include <qpopupmenu.h>
00005 #include <qregexp.h>
00006 #include <qtimer.h>
00007 #include <qvbox.h>
00008 #include <qwhatsthis.h>
00009
00010 #include <kaction.h>
00011 #include <kapplication.h>
00012 #include <kconfig.h>
00013 #include <kdebug.h>
00014 #include <kdesktopfile.h>
00015 #include <kdialogbase.h>
00016 #include <kiconloader.h>
00017 #include <klocale.h>
00018 #include <kparts/part.h>
00019 #include <kprocess.h>
00020 #include <ktexteditor/editinterface.h>
00021 #include <ktexteditor/viewcursorinterface.h>
00022 #include <ktexteditor/selectioninterface.h>
00023
00024 #include "kdevcore.h"
00025 #include "kdevproject.h"
00026 #include "kdevpartcontroller.h"
00027 #include "kdevappfrontend.h"
00028
00029 #include "toolsconfig.h"
00030 #include "toolsconfigwidget.h"
00031
00032
00033 static const KAboutData data("kdevtools", I18N_NOOP("External Tools"), "1.0");
00034 K_EXPORT_COMPONENT_FACTORY( libkdevtools, ToolsFactory( &data ) )
00035
00036 ToolsPart::ToolsPart(QObject *parent, const char *name, const QStringList &)
00037 : KDevPlugin( "Tools", "configure", parent, name ? name : "ToolsPart")
00038 {
00039 setInstance(ToolsFactory::instance());
00040
00041 setXMLFile("kdevpart_tools.rc");
00042
00043 connect(core(), SIGNAL(configWidget(KDialogBase*)), this, SLOT(configWidget(KDialogBase*)));
00044
00045 connect(core(), SIGNAL(coreInitialized()), this, SLOT(updateMenu()));
00046
00047 connect( core(), SIGNAL(contextMenu(QPopupMenu *, const Context *)),
00048 this, SLOT(contextMenu(QPopupMenu *, const Context *)) );
00049
00050
00051
00052 QTimer::singleShot(0, this, SLOT(updateToolsMenu()));
00053 }
00054
00055
00056 ToolsPart::~ToolsPart()
00057 {
00058 }
00059
00060
00061 void ToolsPart::configWidget(KDialogBase *dlg)
00062 {
00063 QVBox *vbox = dlg->addVBoxPage( i18n("Tools Menu"), i18n("Tools Menu"), BarIcon( icon(), KIcon::SizeMedium) );
00064 ToolsConfig *w = new ToolsConfig(vbox, "tools config widget");
00065 connect(dlg, SIGNAL(okClicked()), w, SLOT(accept()));
00066 connect(dlg, SIGNAL(destroyed()), this, SLOT(updateMenu()));
00067
00068 vbox = dlg->addVBoxPage(i18n("External Tools"), i18n("External Tools"), BarIcon( icon(), KIcon::SizeMedium) );
00069 ToolsConfigWidget *w2 = new ToolsConfigWidget(vbox, "tools config widget");
00070 connect(dlg, SIGNAL(okClicked()), w2, SLOT(accept()));
00071 connect(dlg, SIGNAL(destroyed()), this, SLOT(updateToolsMenu()));
00072 }
00073
00074
00075
00076 void ToolsPart::updateMenu()
00077 {
00078 QPtrList<KAction> actions;
00079
00080 unplugActionList("tools_list");
00081
00082 KConfig *config = ToolsFactory::instance()->config();
00083 config->setGroup("Tools");
00084
00085 QStringList list = config->readListEntry("Tools");
00086 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it)
00087 {
00088 QString name = *it;
00089
00090 KDesktopFile df(name, true);
00091 if (df.readName().isNull())
00092 continue;
00093
00094 KAction *action = new KAction(df.readName(), df.readIcon(), 0,
00095 this, SLOT(slotToolActivated()), (QObject*)0, name.latin1());
00096 actions.append(action);
00097 }
00098
00099 plugActionList("tools_list", actions);
00100 }
00101
00102
00103 void ToolsPart::slotToolActivated()
00104 {
00105 QString df = sender()->name();
00106 kapp->startServiceByDesktopPath(df);
00107 }
00108
00109
00110
00111
00112 static QString currentWord(KTextEditor::EditInterface *editiface,
00113 KTextEditor::ViewCursorInterface *cursoriface)
00114 {
00115 uint line, col;
00116 cursoriface->cursorPositionReal(&line, &col);
00117 QString str = editiface->textLine(line);
00118 int i;
00119 for (i = col-1; i >= 0; --i)
00120 if (!str[i].isLetter())
00121 break;
00122
00123 return str.mid(i+1, col-i-1);
00124 }
00125
00126
00127 void ToolsPart::startCommand(QString cmdline, bool captured, QString fileName)
00128 {
00129 KParts::Part *part = partController()->activePart();
00130 KParts::ReadWritePart *rwpart
00131 = dynamic_cast<KParts::ReadWritePart*>(part);
00132 KTextEditor::SelectionInterface *selectionIface
00133 = dynamic_cast<KTextEditor::SelectionInterface*>(part);
00134 KTextEditor::EditInterface *editIface
00135 = dynamic_cast<KTextEditor::EditInterface*>(part);
00136 KTextEditor::ViewCursorInterface *cursorIface
00137 = dynamic_cast<KTextEditor::ViewCursorInterface*>(part);
00138
00139 if (fileName.isNull() && rwpart)
00140 fileName = rwpart->url().path();
00141
00142 QString projectDirectory;
00143 if (project())
00144 projectDirectory = project()->projectDirectory();
00145
00146 QString selection;
00147 if (selectionIface)
00148 selection = KShellProcess::quote(selectionIface->selection());
00149
00150 QString word;
00151 if (editIface && cursorIface)
00152 word = KShellProcess::quote(currentWord(editIface, cursorIface));
00153
00154
00155 if (cmdline.contains("%D") && projectDirectory.isNull())
00156 return;
00157 cmdline.replace(QRegExp("%D"), projectDirectory);
00158
00159 if (cmdline.contains("%S") && fileName.isNull())
00160 return;
00161 cmdline.replace(QRegExp("%S"), fileName);
00162
00163 if (cmdline.contains("%T") && selection.isNull())
00164 return;
00165 cmdline.replace(QRegExp("%T"), selection);
00166
00167 if (cmdline.contains("%W") && word.isNull())
00168 return;
00169 cmdline.replace(QRegExp("%W"), word);
00170
00171 if (captured)
00172 appFrontend()->startAppCommand(QString::QString(), cmdline, false);
00173 else {
00174 KShellProcess proc;
00175 proc << cmdline;
00176 proc.start(KProcess::DontCare, KProcess::NoCommunication);
00177 }
00178 }
00179
00180
00181 void ToolsPart::updateToolsMenu()
00182 {
00183 KConfig *config = ToolsFactory::instance()->config();
00184 config->setGroup("External Tools");
00185 QStringList l = config->readListEntry("Tool Menu");
00186
00187 QPtrList<KAction> actions;
00188 QStringList::ConstIterator it;
00189 for (it = l.begin(); it != l.end(); ++it) {
00190 QString menutext = *it;
00191 KConfig *config = ToolsFactory::instance()->config();
00192 config->setGroup("Tool Menu " + menutext);
00193 bool isdesktopfile = config->readBoolEntry("DesktopFile");
00194 KAction *action = new KAction(*it, 0,
00195 this, SLOT(toolsMenuActivated()),
00196 (QObject*) 0, menutext.utf8());
00197 if (isdesktopfile) {
00198 KDesktopFile df(config->readPathEntry("CommandLine"));
00199 action->setIcon(df.readIcon());
00200 }
00201 actions.append(action);
00202 }
00203
00204 unplugActionList("tools2_list");
00205 plugActionList("tools2_list", actions);
00206 }
00207
00208
00209 void ToolsPart::contextMenu(QPopupMenu *popup, const Context *context)
00210 {
00211 if (!context->hasType( Context::FileContext ))
00212 return;
00213
00214 const FileContext *fcontext = static_cast<const FileContext*>(context);
00215 m_contextPopup = popup;
00216 m_contextFileName = fcontext->fileName();
00217
00218 KConfig *config = ToolsFactory::instance()->config();
00219 config->setGroup("External Tools");
00220 QStringList filecontextList = config->readListEntry("File Context");
00221
00222 if (fcontext->isDirectory()) {
00223 QStringList l = config->readListEntry("Dir Context");
00224 QStringList::ConstIterator it;
00225 for (it = l.begin(); it != l.end(); ++it)
00226 popup->insertItem( (*it), this, SLOT(dirContextActivated(int)) );
00227 } else {
00228 QStringList l = config->readListEntry("File Context");
00229 QStringList::ConstIterator it;
00230 for (it = l.begin(); it != l.end(); ++it)
00231 popup->insertItem( (*it), this, SLOT(fileContextActivated(int)) );
00232 }
00233 }
00234
00235
00236 void ToolsPart::toolsMenuActivated()
00237 {
00238 QString menutext = QString::fromUtf8(sender()->name());
00239 KConfig *config = ToolsFactory::instance()->config();
00240 config->setGroup("Tool Menu " + menutext);
00241 QString cmdline = config->readPathEntry("CommandLine");
00242 bool isdesktopfile = config->readBoolEntry("DesktopFile");
00243 bool captured = config->readBoolEntry("Captured");
00244 kdDebug() << "activating " << menutext
00245 << "with cmdline " << cmdline
00246 << "and desktopfile " << isdesktopfile << endl;
00247 if (isdesktopfile)
00248 kapp->startServiceByDesktopPath(cmdline);
00249 else
00250 startCommand(cmdline, captured, QString::null);
00251 }
00252
00253
00254 void ToolsPart::fileContextActivated(int id)
00255 {
00256 QString menutext = m_contextPopup->text(id);
00257
00258 KConfig *config = ToolsFactory::instance()->config();
00259 config->setGroup("File Context " + menutext);
00260 QString cmdline = config->readPathEntry("CommandLine");
00261 bool captured = config->readBoolEntry("Captured");
00262 kdDebug() << "activating " << menutext
00263 << "with cmdline " << cmdline
00264 << " on file " << m_contextFileName << endl;
00265 startCommand(cmdline, captured, m_contextFileName);
00266 }
00267
00268
00269 void ToolsPart::dirContextActivated(int id)
00270 {
00271 QString menutext = m_contextPopup->text(id);
00272
00273 KConfig *config = ToolsFactory::instance()->config();
00274 config->setGroup("Dir Context " + menutext);
00275 QString cmdline = config->readPathEntry("CommandLine");
00276 bool captured = config->readBoolEntry("Captured");
00277 kdDebug() << "activating " << menutext
00278 << "with cmdline " << cmdline
00279 << " on directory " << m_contextFileName << endl;
00280 startCommand(cmdline, captured, m_contextFileName);
00281 }
00282
00283 #include "tools_part.moc"