diff options
Diffstat (limited to 'lib/util')
-rw-r--r-- | lib/util/Mainpage.dox | 10 | ||||
-rw-r--r-- | lib/util/Makefile.am | 21 | ||||
-rw-r--r-- | lib/util/blockingkprocess.cpp | 105 | ||||
-rw-r--r-- | lib/util/blockingkprocess.h | 92 | ||||
-rw-r--r-- | lib/util/configwidgetproxy.cpp | 105 | ||||
-rw-r--r-- | lib/util/configwidgetproxy.h | 129 | ||||
-rw-r--r-- | lib/util/domutil.cpp | 367 | ||||
-rw-r--r-- | lib/util/domutil.h | 226 | ||||
-rw-r--r-- | lib/util/execcommand.cpp | 101 | ||||
-rw-r--r-- | lib/util/execcommand.h | 70 | ||||
-rw-r--r-- | lib/util/filetemplate.cpp | 128 | ||||
-rw-r--r-- | lib/util/filetemplate.h | 88 | ||||
-rw-r--r-- | lib/util/kdeveditorutil.cpp | 89 | ||||
-rw-r--r-- | lib/util/kdeveditorutil.h | 67 | ||||
-rw-r--r-- | lib/util/kdevjobtimer.cpp | 39 | ||||
-rw-r--r-- | lib/util/kdevjobtimer.h | 39 | ||||
-rw-r--r-- | lib/util/kdevshellwidget.cpp | 125 | ||||
-rw-r--r-- | lib/util/kdevshellwidget.h | 100 | ||||
-rw-r--r-- | lib/util/kscriptactionmanager.cpp | 177 | ||||
-rw-r--r-- | lib/util/kscriptactionmanager.h | 139 | ||||
-rw-r--r-- | lib/util/rurl.cpp | 369 | ||||
-rw-r--r-- | lib/util/rurl.h | 182 | ||||
-rw-r--r-- | lib/util/settings.cpp | 63 | ||||
-rw-r--r-- | lib/util/settings.h | 26 | ||||
-rw-r--r-- | lib/util/urlutil.cpp | 319 | ||||
-rw-r--r-- | lib/util/urlutil.h | 190 |
26 files changed, 3366 insertions, 0 deletions
diff --git a/lib/util/Mainpage.dox b/lib/util/Mainpage.dox new file mode 100644 index 00000000..dad04de5 --- /dev/null +++ b/lib/util/Mainpage.dox @@ -0,0 +1,10 @@ +/** +@mainpage The KDevelop Utility Library + +This library contains utility classes for the KDevelop architecture. + +<b>Link with</b>: -lkdevelop + +<b>Include path</b>: -I\$(kde_includes)/kdevelop/util +*/ + diff --git a/lib/util/Makefile.am b/lib/util/Makefile.am new file mode 100644 index 00000000..c170787e --- /dev/null +++ b/lib/util/Makefile.am @@ -0,0 +1,21 @@ +INCLUDES = -I$(top_srcdir)/lib/compat -I$(top_srcdir)/lib/interfaces -I$(top_srcdir)/lib/sourceinfo $(all_includes) + +noinst_LTLIBRARIES = libkdevutil.la + +libkdevutil_la_SOURCES = blockingkprocess.cpp configwidgetproxy.cpp domutil.cpp \ + execcommand.cpp filetemplate.cpp kdeveditorutil.cpp kdevjobtimer.cpp \ + kdevshellwidget.cpp kscriptactionmanager.cpp rurl.cpp settings.cpp urlutil.cpp + +METASOURCES = AUTO + +kdevelopincludedir = $(includedir)/kdevelop/util +kdevelopinclude_HEADERS = domutil.h execcommand.h filetemplate.h urlutil.h \ + configwidgetproxy.h rurl.h kscriptactionmanager.h + +DOXYGEN_REFERENCES = dcop interfaces kdecore kdefx kdeui khtml kmdi kio kjs kparts kutils kdevextensions kdevinterfaces +DOXYGEN_PROJECTNAME = KDevelop Utility Library +DOXYGEN_DOCDIRPREFIX = kdev +include ../../Doxyfile.am + +noinst_HEADERS = blockingkprocess.h kdeveditorutil.h kdevjobtimer.h \ + kdevshellwidget.h settings.h diff --git a/lib/util/blockingkprocess.cpp b/lib/util/blockingkprocess.cpp new file mode 100644 index 00000000..f0d6e6c3 --- /dev/null +++ b/lib/util/blockingkprocess.cpp @@ -0,0 +1,105 @@ +/*************************************************************************** +* Copyright (C) 2006 by Andras Mantia * +* amantia@kde.org * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "blockingkprocess.h" + +#include <qapplication.h> +#include <qtimer.h> + +BlockingKProcess::BlockingKProcess(QObject *parent, const char *name) + : KProcess(parent, name) +{ + m_stdOut = ""; + m_stdErr = ""; + m_timeoutValue = 60; + m_timer = 0L; + + connect(this, SIGNAL(receivedStdout(KProcess *, char *, int)), + this, SLOT(slotReceivedStdOut(KProcess *, char *, int))); + connect(this, SIGNAL(receivedStderr(KProcess *, char *, int)), + this, SLOT(slotReceivedStdErr(KProcess *, char *, int))); + connect(this, SIGNAL(processExited(KProcess *)), + this, SLOT(slotProcessExited(KProcess *))); +} + +BlockingKProcess::BlockingKProcess() + : KProcess() +{ + m_stdOut = ""; + m_stdErr = ""; + m_timeoutValue = 60; + m_timer = 0L; + connect(this, SIGNAL(receivedStdout(KProcess *, char *, int)), + this, SLOT(slotReceivedStdOut(KProcess *, char *, int))); + connect(this, SIGNAL(receivedStderr(KProcess *, char *, int)), + this, SLOT(slotReceivedStdErr(KProcess *, char *, int))); + connect(this, SIGNAL(processExited(KProcess *)), + this, SLOT(slotProcessExited(KProcess *))); +} + + +BlockingKProcess::~BlockingKProcess() +{ +} +bool BlockingKProcess::start(RunMode runmode, Communication comm) +{ + if (KProcess::start(runmode, comm)) + { + m_timeout = false; + m_timer = new QTimer(); + connect(m_timer, SIGNAL(timeout()), this, SLOT(slotTimeOut())); + m_timer->start(m_timeoutValue*1000, true); + enter_loop(); + delete m_timer; + m_timer = 0L; + return !m_timeout; + } else + return false; +} + + +void BlockingKProcess::slotReceivedStdOut(KProcess *, char *buffer, int buflen) +{ + m_stdOut += QString::fromLatin1(buffer, buflen); +} + +void BlockingKProcess::slotReceivedStdErr(KProcess *, char *buffer, int buflen) +{ + m_stdErr += QString::fromLatin1(buffer, buflen); +} + +void BlockingKProcess::slotProcessExited(KProcess *) +{ + qApp->exit_loop(); +} + +void BlockingKProcess::slotTimeOut() +{ + m_timeout = true; + kill(); + qApp->exit_loop(); +} + + +void qt_enter_modal( QWidget *widget ); +void qt_leave_modal( QWidget *widget ); + +void BlockingKProcess::enter_loop() +{ + QWidget dummy(0,0,WType_Dialog | WShowModal); + dummy.setFocusPolicy( QWidget::NoFocus ); + qt_enter_modal(&dummy); + qApp->enter_loop(); + qt_leave_modal(&dummy); +} + + +#include "blockingkprocess.moc" diff --git a/lib/util/blockingkprocess.h b/lib/util/blockingkprocess.h new file mode 100644 index 00000000..c5c8f5d9 --- /dev/null +++ b/lib/util/blockingkprocess.h @@ -0,0 +1,92 @@ + +/*************************************************************************** +* Copyright (C) 2006 by Andras Mantia * +* amantia@kde.org * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + + +#ifndef BLOCKINGKPROCESS_H +#define BLOCKINGKPROCESS_H + +#include <kprocess.h> + +/** + * Blocking version of KProcess, which stores the stdout. + * Differences between start(KProcess::Block, KProcess::StdOut) and this + * class are: + * - the GUI update is not blocked why the external process is running + * - in case of problems there is a timeout (defaults to 60 seconds), after which the + * process is terminated. + * - the stdout is caught - it the caller request it - and can be read by the caller + * @author Andras Mantia <amantia@kde.org> +*/ + +class QTimer; +class BlockingKProcess : public KProcess +{ + Q_OBJECT + +public: + BlockingKProcess(QObject *parent, const char *name=0); + BlockingKProcess(); + + virtual ~BlockingKProcess(); + + /** + * Start the process. It waits until the process exits or the timeout is hit. + * @param runmode @see KProcess, use KProcess::NotifyOnExit to get proper behaviour, + * not KProcess::Block + * @param comm if Stdout is passed, it catches the output. For the rest @see KProcess + * @return true in case of success, false if there are problems to start the process + * or it was killed because of the timeout. + */ + virtual bool start(RunMode runmode=NotifyOnExit, Communication comm=NoCommunication); + + /** + * Get the output of the run process + * @return the output + */ + QString stdOut() { return m_stdOut;} + /** + * Clear the internal stdout buffer. Useful in case the class is reused. + */ + void clearStdOut() { m_stdOut = "";} + /** + * Get the error output of the run process + * @return the output + */ + QString stdErr() { return m_stdErr;} + /** + * Clear the internal stderr buffer. Useful in case the class is reused. + */ + void clearStdErr() { m_stdErr = "";} + + /** + * Sets the timeout + * @param timeout seconds after which the process is considered hung and killed. 0 disables the timeout. + */ + void setTimeOut(int timeout) { m_timeoutValue = timeout; } + +private slots: + void slotReceivedStdOut(KProcess *proc, char *buffer, int buflen); + void slotReceivedStdErr(KProcess *proc, char *buffer, int buflen); + void slotProcessExited(KProcess *proc); + void slotTimeOut(); + +private: + void enter_loop(); + + QString m_stdOut; + QString m_stdErr; + bool m_timeout; + int m_timeoutValue; + QTimer *m_timer; +}; + +#endif diff --git a/lib/util/configwidgetproxy.cpp b/lib/util/configwidgetproxy.cpp new file mode 100644 index 00000000..128fa2ad --- /dev/null +++ b/lib/util/configwidgetproxy.cpp @@ -0,0 +1,105 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Jens Dagerbo <jens.dagerbo@swipnet.se> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + + +#include <qstring.h> +#include <qvbox.h> + +#include <kdebug.h> +#include <kdialogbase.h> +#include <kiconloader.h> + +#include <kdevcore.h> + + +#include "configwidgetproxy.h" + + +ConfigWidgetProxy::ConfigWidgetProxy( KDevCore * core ) +{ + connect( core, SIGNAL(configWidget(KDialogBase*)), this, SLOT(slotConfigWidget( KDialogBase*)) ); + connect( core, SIGNAL(projectConfigWidget(KDialogBase*)), this, SLOT(slotProjectConfigWidget( KDialogBase*)) ); +} + +ConfigWidgetProxy::~ConfigWidgetProxy() +{} + +void ConfigWidgetProxy::createGlobalConfigPage( QString const & title, unsigned int pagenumber, QString const & icon ) +{ + _globalTitleMap.insert( pagenumber, qMakePair( title, icon ) ); +} + +void ConfigWidgetProxy::createProjectConfigPage( QString const & title, unsigned int pagenumber, QString const & icon ) +{ + _projectTitleMap.insert( pagenumber, qMakePair( title, icon ) ); +} + +void ConfigWidgetProxy::removeConfigPage( int pagenumber ) +{ + _globalTitleMap.remove( pagenumber ); + _projectTitleMap.remove( pagenumber ); +} + +void ConfigWidgetProxy::slotConfigWidget( KDialogBase * dlg ) +{ + TitleMap::Iterator it = _globalTitleMap.begin(); + while ( it != _globalTitleMap.end() ) + { + _pageMap.insert( dlg->addVBoxPage( it.data().first, it.data().first, BarIcon( it.data().second, KIcon::SizeMedium ) ), it.key() ); + ++it; + } + + connect( dlg, SIGNAL(aboutToShowPage(QWidget*)), this, SLOT( slotAboutToShowPage(QWidget*)) ); + connect( dlg, SIGNAL(destroyed()), this, SLOT(slotConfigWidgetDestroyed()) ); +} + +void ConfigWidgetProxy::slotProjectConfigWidget( KDialogBase * dlg ) +{ + TitleMap::Iterator it = _projectTitleMap.begin(); + while ( it != _projectTitleMap.end() ) + { + _pageMap.insert( dlg->addVBoxPage( it.data().first, it.data().first, BarIcon( it.data().second, KIcon::SizeMedium ) ), it.key() ); + ++it; + } + + connect( dlg, SIGNAL(aboutToShowPage(QWidget*)), this, SLOT( slotAboutToShowPage(QWidget*)) ); + connect( dlg, SIGNAL(destroyed()), this, SLOT(slotConfigWidgetDestroyed()) ); +} + +void ConfigWidgetProxy::slotConfigWidgetDestroyed( ) +{ + _pageMap.clear(); +} + +void ConfigWidgetProxy::slotAboutToShowPage( QWidget * page ) +{ + if ( !page ) return; + + PageMap::Iterator it = _pageMap.find( page ); + if ( it != _pageMap.end() ) + { + emit insertConfigWidget( static_cast<KDialogBase*>(const_cast<QObject*>(sender())), page, it.data() ); + _pageMap.remove( it ); + } +} + +#include "configwidgetproxy.moc" + +// kate: space-indent off; indent-width 4; replace-tabs off; tab-width 4; diff --git a/lib/util/configwidgetproxy.h b/lib/util/configwidgetproxy.h new file mode 100644 index 00000000..6380d002 --- /dev/null +++ b/lib/util/configwidgetproxy.h @@ -0,0 +1,129 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Jens Dagerbo <jens.dagerbo@swipnet.se> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _CONFIGWIDGETPROXY_H +#define _CONFIGWIDGETPROXY_H + +#include <qobject.h> +#include <qstring.h> +#include <qmap.h> + +class KDevCore; +class KDialogBase; + +/** +@file configwidgetproxy.h +Configuration widget proxy class. +*/ + +/** +This class can be used to implement demand-loading of config pages. +In order to avoid the potentially heavy and unneccessary creation +of a config page that might not be needed, this class can be used +to delay the config page creation until the user explicitly asks +for it. + +A typical case looks like this: +@code +#define GLOBALDOC_OPTIONS 1 +#define PROJECTDOC_OPTIONS 2 + +_configProxy = new ConfigWidgetProxy( core() ); +_configProxy->createGlobalConfigPage( i18n("My Part"), GLOBALDOC_OPTIONS, info()->icon() ); +_configProxy->createProjectConfigPage( i18n("My Part"), PROJECTDOC_OPTIONS, info()->icon() ); +connect( _configProxy, SIGNAL(insertConfigWidget(const QObject*, QWidget*, unsigned int )), + this, SLOT(insertConfigWidget(const QObject*, QWidget*, unsigned int )) ); + +... +... + +void MyPart::insertConfigWidget( QObject const * dlg, QWidget * page, unsigned int pagenumber ) +{ + if ( pagenumber == PROJECTDOC_OPTIONS ) { + MyPartGlobalSettings * w = new MyPartGlobalSettings( this, page ); + connect( dlg, SIGNAL(okClicked()), w, SLOT(slotAccept()) ); + } else if ( pagenumber == PROJECTDOC_OPTIONS ) { + MyPartProjectSettings * w = new MyPartProjectSettings( this, page ); + connect( dlg, SIGNAL(okClicked()), w, SLOT(slotAccept()) ); + } +} +@endcode + +Note that this replaces the functionality of typical KDevCore::configWidget() and +KDevCore::projectConfigWidget() slots. +*/ +class ConfigWidgetProxy : public QObject +{ +Q_OBJECT + +public: + /**Constructor. + @param core An instance of KDevelop Core.*/ + ConfigWidgetProxy( KDevCore * core ); + virtual ~ConfigWidgetProxy(); + + /** + * Tells the proxy you want a page in the Global Settings. + * @param title The title of the config page, shown in the settings dialog. + * @param pagenumber A per-proxy unique identifier, used when responding to insertConfigWidget() signal. + * @param icon The name of the icon to use. + */ + void createGlobalConfigPage( QString const & title, unsigned int pagenumber, QString const & icon = "kdevelop" ); + + /** + * Tells the proxy you want a page in the Project Settings. + * @param title The title of the config page, shown in the settings dialog. + * @param pagenumber A per-proxy unique identifier, used when responding to insertConfigWidget() signal. + * @param icon The name of the icon to use. + */ + void createProjectConfigPage( QString const & title, unsigned int pagenumber, QString const & icon = "kdevelop" ); + + /** + * Removes a config page from the proxy. Next time the settings dialog opens, this page will not be available. + * @param pagenumber The identifier set in createGlobalConfigPage() or createProjectConfigPage(). + */ + void removeConfigPage( int pagenumber ); + +signals: + /** + * The proxy emits this signal to notify the client that a specific config page has been requested. + * @param dlg The settings dialog. The client should connect to its okClicked() signal. + * @param page The setting page. The client should use this as parent to the config widget. + * @param pagenumber The identifier set in createGlobalConfigPage() or createProjectConfigPage(). Identifies the requested config page. + */ + void insertConfigWidget( const KDialogBase * dlg, QWidget * page, unsigned int pagenumber ); + +private slots: + void slotConfigWidget( KDialogBase * ); + void slotProjectConfigWidget( KDialogBase * ); + void slotConfigWidgetDestroyed(); + void slotAboutToShowPage( QWidget * page ); + +private: + typedef QMap<unsigned int, QPair<QString,QString> > TitleMap; + typedef QMap<QWidget*, int> PageMap; + + TitleMap _globalTitleMap; + TitleMap _projectTitleMap; + PageMap _pageMap; +}; + +#endif + +// kate: space-indent off; indent-width 4; replace-tabs off; tab-width 4; diff --git a/lib/util/domutil.cpp b/lib/util/domutil.cpp new file mode 100644 index 00000000..b183717f --- /dev/null +++ b/lib/util/domutil.cpp @@ -0,0 +1,367 @@ +/*************************************************************************** + * Copyright (C) 2001-2002 by Bernd Gehrmann * + * bernd@kdevelop.org * + * default support: Eray Ozkural (exa) * + * additions: John Firebaugh <jfirebaugh@kde.org> * + * Jakob Simon-Gaarde <jakob@simon-gaarde.dk> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "domutil.h" + +#include <kdebug.h> +#include <qstringlist.h> +#include <qfile.h> + + +void DomUtil::makeEmpty( QDomElement& e ) +{ + while( !e.firstChild().isNull() ) + e.removeChild( e.firstChild() ); +} + +QDomElement DomUtil::elementByPath(const QDomDocument &doc, const QString &path) +{ + QStringList l = QStringList::split('/', path); + + QDomElement el; + if(&doc) el = doc.documentElement(); + QStringList::ConstIterator it; + for (it = l.begin(); it != l.end(); ++it) { + el = el.namedItem(*it).toElement(); + } + + return el; +} + + +QString DomUtil::readEntry(const QDomDocument &doc, const QString &path, const QString &defaultEntry) +{ + QDomElement el = elementByPath(doc, path); + if (el.isNull()) + return defaultEntry; + else + return el.firstChild().toText().data(); +} + +/// @todo consider whether it's okay to accept empty string == default value +/// if not use the below type +///typedef pair<bool,QString> EltInfo; + +QString DomUtil::readEntryAux(const QDomDocument &doc, const QString &path) +{ + QDomElement el = elementByPath(doc, path); + if (el.isNull()) + return QString::null; + else + return el.firstChild().toText().data(); +} + +int DomUtil::readIntEntry(const QDomDocument &doc, const QString &path, int defaultEntry) +{ + QString entry = readEntryAux(doc, path); + if (entry.isNull()) + return defaultEntry; + else + return entry.toInt(); +} + + +bool DomUtil::readBoolEntry(const QDomDocument &doc, const QString &path, bool defaultEntry) +{ + QString entry = readEntryAux(doc, path); + if (entry.isNull()) + return defaultEntry; + else + return entry == "TRUE" || entry == "true"; +} + + +QStringList DomUtil::readListEntry(const QDomDocument &doc, const QString &path, const QString &tag) +{ + QStringList list; + + QDomElement el = elementByPath(doc, path); + QDomElement subEl = el.firstChild().toElement(); + while (!subEl.isNull()) { + if (subEl.tagName() == tag) + list << subEl.firstChild().toText().data(); + subEl = subEl.nextSibling().toElement(); + } + + return list; +} + + +DomUtil::PairList DomUtil::readPairListEntry(const QDomDocument &doc, const QString &path, const QString &tag, + const QString &firstAttr, const QString &secondAttr) +{ + PairList list; + + QDomElement el = elementByPath(doc, path); + QDomElement subEl = el.firstChild().toElement(); + while (!subEl.isNull()) { + if (subEl.tagName() == tag) { + QString first = subEl.attribute(firstAttr); + QString second = subEl.attribute(secondAttr); + list << Pair(first, second); + } + subEl = subEl.nextSibling().toElement(); + } + + return list; +} + +QMap<QString, QString> DomUtil::readMapEntry(const QDomDocument &doc, const QString& path) +{ + QMap<QString, QString> map; + + QDomElement el = elementByPath(doc, path); + QDomElement subEl = el.firstChild().toElement(); + while (!subEl.isNull()) { + map[subEl.tagName()] = subEl.firstChild().toText().data(); + subEl = subEl.nextSibling().toElement(); + } + + return map; +} + +QDomElement DomUtil::namedChildElement( QDomElement& el, const QString& name ) +{ + QDomElement child = el.namedItem( name ).toElement(); + if (child.isNull()) { + child = el.ownerDocument().createElement( name ); + el.appendChild(child); + } + return child; +} + + +QDomElement DomUtil::createElementByPath(QDomDocument &doc, const QString &path) +{ + QStringList l = QStringList::split('/', path); + + QDomElement el; + if(&doc) el = doc.documentElement(); + QStringList::ConstIterator it; + for (it = l.begin(); it != l.end(); ++it) + el = DomUtil::namedChildElement( el, *it ); + + while (!el.firstChild().isNull()) + el.removeChild(el.firstChild()); + + return el; +} + + +void DomUtil::writeEntry(QDomDocument &doc, const QString &path, const QString &value) +{ + QDomElement el = createElementByPath(doc, path); + el.appendChild(doc.createTextNode(value)); +} + +void DomUtil::writeMapEntry(QDomDocument &doc, const QString &path, const QMap<QString, QString> &map) +{ + QString basePath( path + "/" ); + QMap<QString,QString>::ConstIterator it; + for (it = map.begin(); it != map.end(); ++it) + { + kdDebug( 9010 ) << "writing " << basePath << ";" << it.key() << ";" << it.data() << endl; + if( ! it.key().isEmpty() ) + writeEntry(doc, basePath + it.key(), it.data() ); + } +} + +void DomUtil::writeIntEntry(QDomDocument &doc, const QString &path, int value) +{ + writeEntry(doc, path, QString::number(value)); +} + + +void DomUtil::writeBoolEntry(QDomDocument &doc, const QString &path, bool value) +{ + writeEntry(doc, path, value? "true" : "false"); +} + + +void DomUtil::writeListEntry(QDomDocument &doc, const QString &path, const QString &tag, + const QStringList &value) +{ + QDomElement el = createElementByPath(doc, path); + + QStringList::ConstIterator it; + for (it = value.begin(); it != value.end(); ++it) { + QDomElement subEl = doc.createElement(tag); + subEl.appendChild(doc.createTextNode(*it)); + el.appendChild(subEl); + } +} + + +void DomUtil::writePairListEntry(QDomDocument &doc, const QString &path, const QString &tag, + const QString &firstAttr, const QString &secondAttr, + const PairList &value) +{ + QDomElement el = createElementByPath(doc, path); + + PairList::ConstIterator it; + for (it = value.begin(); it != value.end(); ++it) { + QDomElement subEl = doc.createElement(tag); + subEl.setAttribute(firstAttr, (*it).first); + subEl.setAttribute(secondAttr, (*it).second); + el.appendChild(subEl); + } +} + +DomPath DomUtil::resolvPathStringExt(const QString pathstring) +{ + // parse path + unsigned int i; + QStringList pathParts = QStringList::split('/',pathstring); + DomPath dompath; + for (i=0; i<pathParts.count(); i++) + { + QStringList pathElemParts = QStringList::split('|',pathParts[i],TRUE); + DomPathElement dompathelem; + dompathelem.tagName = pathElemParts[0].simplifyWhiteSpace(); + if (pathElemParts.count()>1) + { + // handle attributes + QStringList attrParts = QStringList::split(';',pathElemParts[1]); + for (unsigned int j=0; j<attrParts.count(); j++) + { + QStringList attribSet = QStringList::split('=',attrParts[j]); + if (attribSet.count()<2) + continue; + DomAttribute domattribute; + domattribute.name = attribSet[0].simplifyWhiteSpace(); + domattribute.value = attribSet[1].simplifyWhiteSpace(); + dompathelem.attribute.append(domattribute); + } + } + if (pathElemParts.count()>2) + dompathelem.matchNumber = pathElemParts[2].toInt(); + else + dompathelem.matchNumber = 0; // or else the first + dompath.append(dompathelem); + } + return dompath; +} + + +#define rightchild !wrongchild + +QDomElement DomUtil::elementByPathExt(QDomDocument &doc, const QString &pathstring) +{ + DomPath dompath = resolvPathStringExt(pathstring); + QDomElement elem = doc.documentElement(); + QDomNodeList children; + QDomElement nextElem = elem; + for (unsigned int j=0; j<dompath.count(); j++) + { + children = nextElem.childNodes(); + DomPathElement dompathelement= dompath[j]; + bool wrongchild = false; + int matchCount = 0; + for (unsigned int i=0; i<children.count(); i++) + { + wrongchild = false; + QDomElement child = children.item(i).toElement(); + QString tag = child.tagName(); + tag = dompathelement.tagName; + if (child.tagName() == dompathelement.tagName) + { + for (unsigned int k=0; k<dompathelement.attribute.count(); k++) + { + DomAttribute domattribute = dompathelement.attribute[k]; + QDomAttr domattr = child.attributeNode(domattribute.name); + if (domattr.isNull() || + domattr.value() != domattribute.value) + { + wrongchild = true; + break; + } + } + } + else + wrongchild=true; + if (rightchild) + { + if (dompathelement.matchNumber == matchCount++) + { + nextElem = child; + break; + } + } + } + if (wrongchild) + { + QDomElement nullDummy; + nullDummy.clear(); + return nullDummy; + } + } + return nextElem; +} + + +bool DomUtil::openDOMFile(QDomDocument &doc, QString filename) +{ + QFile file( filename ); + if ( !file.open( IO_ReadOnly ) ) + return false; + if ( !doc.setContent( &file ) ) { + file.close(); + return false; + } + file.close(); + return true; +} + +bool DomUtil::saveDOMFile(QDomDocument &doc, QString filename) +{ + QFile file( filename ); + if ( !file.open( IO_ReadWrite | IO_Truncate ) ) + return false; + QTextStream t( &file ); + t << doc.toString(); + file.close(); + return true; +} + +bool DomUtil::removeTextNodes(QDomDocument doc,QString pathExt) +{ + QDomElement elem = elementByPathExt(doc,pathExt); + if (elem.isNull()) + return false; + QDomNodeList children = elem.childNodes(); + for (unsigned int i=0;i<children.count();i++) + if (children.item(i).isText()) + elem.removeChild(children.item(i)); + return true; +} + + +bool DomUtil::appendText(QDomDocument doc, QString pathExt, QString text) +{ + QDomElement elem = elementByPathExt(doc,pathExt); + if (elem.isNull()) + return false; + elem.appendChild(doc.createTextNode(text)); + return true; +} + + +bool DomUtil::replaceText(QDomDocument doc, QString pathExt, QString text) +{ + if (removeTextNodes(doc,pathExt) && + appendText(doc,pathExt,text)) + return true; + else + return false; +} diff --git a/lib/util/domutil.h b/lib/util/domutil.h new file mode 100644 index 00000000..a301ef00 --- /dev/null +++ b/lib/util/domutil.h @@ -0,0 +1,226 @@ +/*************************************************************************** + * Copyright (C) 2001 by Bernd Gehrmann * + * bernd@kdevelop.org * + * jakob@simon-gaarde.dk * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _DOMUTIL_H_ +#define _DOMUTIL_H_ + +#include <qdom.h> +#include <qpair.h> +#include <qstringlist.h> +#include <qvaluelist.h> +#include <qmap.h> + +/** +@file domutil.h +Utility functions to operate on %DOM. +*/ + +struct DomAttribute +{ + QString name; + QString value; +}; + +struct DomPathElement +{ + QString tagName; + QValueList<DomAttribute> attribute; + int matchNumber; // for use when more than one element matches the path +}; + +typedef QValueList<DomPathElement> DomPath; + +/** + * Utility class for conveniently accessing data in a %DOM tree. + */ +class DomUtil +{ +public: + typedef QPair<QString, QString> Pair; + typedef QValueList<Pair> PairList; + /** + * Remove all child elements from a given element. + */ + static void makeEmpty( QDomElement& ); + /** + * Reads a string entry. + */ + static QString readEntry(const QDomDocument &doc, const QString &path, const QString &defaultEntry = QString::null); + /** + * Reads a number entry. + */ + static int readIntEntry(const QDomDocument &doc, const QString &path, int defaultEntry = 0); + /** + * Reads a boolean entry. The strings "true" and "TRUE" are interpreted + * as true, all other as false. + */ + static bool readBoolEntry(const QDomDocument &doc, const QString &path, bool defaultEntry = false); + /** + * Reads a list entry. See writeListEntry(). + */ + static QStringList readListEntry(const QDomDocument &doc, const QString &path, const QString &tag); + /** + * Reads a list of string pairs. See writePairListEntry(). + */ + static PairList readPairListEntry(const QDomDocument &doc, const QString &path, const QString &tag, + const QString &firstAttr, const QString &secondAttr); + /** + * Reads a string to string map. See writeMapEntry() + */ + static QMap<QString, QString> readMapEntry(const QDomDocument &doc, const QString &path); + /** + * Retrieves an element by path, return null if any item along + * the path does not exist. + */ + static QDomElement elementByPath( const QDomDocument& doc, const QString& path ); + /** + * Retrieves an element by path, creating the necessary nodes. + */ + static QDomElement createElementByPath( QDomDocument& doc, const QString& path ); + /** + * Retrieves a child element, creating it if it does not exist. + * The return value is guaranteed to be non isNull() + */ + static QDomElement namedChildElement( QDomElement& el, const QString& name ); + /** + Writes a string entry. For example, + \verbatim + <code> + writeEntry(doc, "/general/special", "foo"); + </code> + \endverbatim creates the %DOM fragment: \verbatim + <code> + <general><special>foo</special></general> + </code> + \endverbatim + */ + static void writeEntry(QDomDocument &doc, const QString &path, const QString &value); + /** + * Writes a number entry. + */ + static void writeIntEntry(QDomDocument &doc, const QString &path, int value); + /** + * Writes a boolean entry. Booleans are stored as "true", "false" resp. + */ + static void writeBoolEntry(QDomDocument &doc, const QString &path, bool value); + /** + Writes a string list element. The list elements are separated by tag. For example, + \verbatim + <code> + QStringList l; l << "one" << "two"; + writeListEntry(doc, "/general/special", "el", l); + </code> + \endverbatim creates the %DOM fragment: \verbatim + <code> + <general><special><el>one</el><el>two</el></special></general> + </code> + \endverbatim + */ + static void writeListEntry(QDomDocument &doc, const QString &path, const QString &tag, + const QStringList &value); + /** + Writes a list of string pairs. The list elements are stored in the attributes + firstAttr and secondAttr of elements named tag. For example, + \verbatim + <code> + DomUtil::PairList l; + l << DomUtil::StringPair("one", "1"); + l << DomUtil::StringPair("two", "2"); + writePairListEntry(doc, "/general/special", "el", "first", "second", l); + </code> + \endverbatim creates the %DOM fragment: \verbatim + <code> + <general><special> + <el first="one" second="1"/> + <el first="two" second="2"/> + </special></general> + </code> + \endverbatim + */ + static void writePairListEntry(QDomDocument &doc, const QString &path, const QString &tag, + const QString &firstAttr, const QString &secondAttr, + const PairList &value); + /** + * Writes a string to string map. This map is stored in a way, that it can be read with + * readMapEntry() and readEntry() + */ + static void writeMapEntry(QDomDocument &doc, const QString& path, const QMap<QString,QString> &map); + + /** + * Resolves an extended path + * Extended path format: + * pathpart: tag[|attr1=value[;attr2=value;..][|matchNumber]] + * where matchNumber is zero-based + * path: pathpart[/pathpart/..] + */ + static DomPath resolvPathStringExt(const QString pathstring); + + /** + Retrieve an element specified with extended path + examples: + + - 1: "widget|class=QDialog/property|name=geometry" + or "widget|class=QDialog/property||1" + - 2: "widget/property|name=caption/string" + or "widget/property||2/string" + . + \verbatim + <widget class="QDialog"> + <property name="name"> + <cstring>KdevFormName</cstring> + </property> + <property name="geometry"> <-- 1. reaches this node + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>480</height> + </rect> + </property> + <property name="caption"> + <string>KdevFormCaption</string> <-- 2. reaches this node + </property> + </widget> + \endverbatim + */ + static QDomElement elementByPathExt(QDomDocument &doc, const QString &pathstring); + + /** + * Open file - filename - and set setContents of doc + */ + static bool openDOMFile(QDomDocument &doc, QString filename); + + /** + * Store contents of doc in file - filename. Existing file will be truncated! + */ + static bool saveDOMFile(QDomDocument &doc, QString filename); + + /** + * Remove all child text nodes of parent described in pathExt + */ + static bool removeTextNodes(QDomDocument doc,QString pathExt); + + /** + * Add child text node to parent described in pathExt + */ + static bool appendText(QDomDocument doc, QString pathExt, QString text); + + /** + * Replace all chilt text nodes of parent described in pathExt with one new. + */ + static bool replaceText(QDomDocument doc, QString pathExt, QString text); + +private: + static QString readEntryAux(const QDomDocument &doc, const QString &path); +}; + +#endif diff --git a/lib/util/execcommand.cpp b/lib/util/execcommand.cpp new file mode 100644 index 00000000..73fc9320 --- /dev/null +++ b/lib/util/execcommand.cpp @@ -0,0 +1,101 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Harald Fernengel <harry@kdevelop.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "execcommand.h" + +#include <kprocess.h> +#include <kprogress.h> +#include <klocale.h> +#include <kmessagebox.h> + +ExecCommand::ExecCommand( const QString& executable, const QStringList& args, + const QString& workingDir, const QStringList& env, + QObject* parent, const char* name ): + QObject( parent, name ), out( "" ) /* make sure out is not QString::null since that would mean "error" */ + +{ + progressDlg = 0; + + proc = new KProcess(); + proc->setWorkingDirectory( workingDir ); + for ( QStringList::ConstIterator it = env.begin(); it != env.end(); ++it ) + proc->setEnvironment( (*it).section( '=', 0, 0 ), (*it).section( '=', 1, 1 ) ); + *proc << executable; + *proc << args; + + connect( proc, SIGNAL(processExited(KProcess*)), + this, SLOT(processExited()) ); + connect( proc, SIGNAL(receivedStdout(KProcess*,char*,int)), + this, SLOT(receivedStdout(KProcess*,char*,int)) ); + connect( proc, SIGNAL(receivedStderr(KProcess*,char*,int)), + this, SLOT(receivedStderr(KProcess*,char*,int)) ); + + bool ok = proc->start( KProcess::NotifyOnExit, KProcess::AllOutput ); + + if ( !ok ) { + KMessageBox::error( 0, i18n("Could not invoke \"%1\". Please make sure it is installed correctly").arg( executable ), + i18n("Error Invoking Command") ); + + emit finished( QString::null, QString::null ); + deleteLater(); + + } else { + progressDlg = new KProgressDialog( 0, 0, i18n("Command running..."), + i18n("Please wait until the \"%1\" command finishes.").arg( executable ), false ); + connect( progressDlg, SIGNAL(cancelClicked()), + this, SLOT(cancelClicked()) ); + } +} + +void ExecCommand::receivedStdout (KProcess*, char *buffer, int buflen) +{ + out += QString::fromUtf8( buffer, buflen ); +} + +void ExecCommand::receivedStderr (KProcess*, char *buffer, int buflen) +{ + err += QString::fromUtf8( buffer, buflen ); +} + +void ExecCommand::processExited() +{ + delete progressDlg; + progressDlg = 0; + + emit finished( out, err ); + deleteLater(); +} + +void ExecCommand::cancelClicked() +{ + delete progressDlg; + progressDlg = 0; + proc->kill(); + + emit finished( QString::null, QString::null ); + deleteLater(); +} + +ExecCommand::~ExecCommand() +{ + delete proc; + delete progressDlg; +} + +#include "execcommand.moc" diff --git a/lib/util/execcommand.h b/lib/util/execcommand.h new file mode 100644 index 00000000..b5545e0d --- /dev/null +++ b/lib/util/execcommand.h @@ -0,0 +1,70 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Harald Fernengel <harry@kdevelop.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _EXECCOMMAND_H_ +#define _EXECCOMMAND_H_ + +#include <qobject.h> +#include <qstringlist.h> + +class KProcess; +class KProgressDialog; + +/** +@file execcommand.h +Command execution facilities. +*/ + +/** + * This class invokes a binary with the arguments passed in the constructor and + * emits the signal finished() with the output. It also displays + * a progress dialog with the possibility to cancel the command. + * + * If there was an error or the user pressed cancel, finished () + * will emit a QString::null, otherwise QStrings containing the stdout/stderr. + * + * The object will delete itself after the finished signal has been emitted. + * Additional environment can be set in the QStringList env via QStrings with the format "foo=blah" + */ +class ExecCommand : public QObject +{ + Q_OBJECT +public: + ExecCommand( const QString& executable, const QStringList& args, + const QString& workingDir = QString::null, + const QStringList& env = QStringList(), QObject* parent = 0, const char* name = 0 ); + ~ExecCommand(); + +signals: + void finished( const QString& output, const QString& errorOutput ); + +private slots: + void receivedStdout (KProcess *, char *buffer, int buflen); + void receivedStderr (KProcess *, char *buffer, int buflen); + void processExited(); + void cancelClicked(); + +private: + KProcess* proc; + KProgressDialog* progressDlg; + QString out; + QString err; +}; + +#endif diff --git a/lib/util/filetemplate.cpp b/lib/util/filetemplate.cpp new file mode 100644 index 00000000..82221891 --- /dev/null +++ b/lib/util/filetemplate.cpp @@ -0,0 +1,128 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Sandy Meier <smeier@kdevelop.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "filetemplate.h" + +#include <qdatetime.h> +#include <qfile.h> +#include <qfileinfo.h> +#include <qregexp.h> +#include <qtextstream.h> + +#include <kstandarddirs.h> + +#include "kdevplugin.h" +#include "kdevproject.h" +#include "domutil.h" + + +bool FileTemplate::exists(KDevPlugin *part, const QString &name, Policy p) +{ + //QString fileName = (p == Default) ? + // (part->project()->projectDirectory() + "/templates/" + name) : name; + + return QFile::exists( fullPathForName(part,name,p) ); +} + +QString FileTemplate::read(KDevPlugin *part, const QString &name, Policy p) +{ + + //KDevProject *project = part->project(); + //QString fileName = (p == Default) ? (project->projectDirectory() + +// "/templates/" + name) : name; + + return readFile(part, fullPathForName(part, name, p) ); +} + +QString FileTemplate::readFile(KDevPlugin *part, const QString &fileName) +{ + QDomDocument &dom = *part->projectDom(); + + QFile f(fileName); + if (!f.open(IO_ReadOnly)) + return QString::null; + QTextStream stream(&f); + QString str = stream.read(); + + return makeSubstitutions( dom, str ); +} + +QString FileTemplate::makeSubstitutions( QDomDocument & dom, const QString & text ) +{ + QString author = DomUtil::readEntry(dom, "/general/author"); + QString email = DomUtil::readEntry(dom, "/general/email"); + QString version = DomUtil::readEntry(dom, "/general/version"); + QString appname = DomUtil::readEntry(dom, "/general/projectname"); + QString date = QDate::currentDate().toString(); + QString year = QString::number(QDate::currentDate().year()); + + QString str = text; + str.replace(QRegExp("\\$EMAIL\\$"),email); + str.replace(QRegExp("\\$AUTHOR\\$"),author); + str.replace(QRegExp("\\$VERSION\\$"),version); + str.replace(QRegExp("\\$DATE\\$"),date); + str.replace(QRegExp("\\$YEAR\\$"),year); + str.replace(QRegExp("\\$APPNAME\\$"),appname); + str.replace(QRegExp("\\$APPNAME\\$"),appname); + str.replace(QRegExp("\\$APPNAMEUC\\$"),appname.upper()); + str.replace(QRegExp("\\$APPNAMELC\\$"),appname.lower()); + + return str; +} + + +bool FileTemplate::copy(KDevPlugin *part, const QString &name, + const QString &dest, Policy p) +{ + QString text = read(part, name, p); + + QFile f(dest); + if (!f.open(IO_WriteOnly)) + return false; + + QFileInfo fi(f); + QString module = fi.baseName(); + QString basefilename = fi.baseName(true); + text.replace(QRegExp("\\$MODULE\\$"),module); + text.replace(QRegExp("\\$FILENAME\\$"),basefilename); + + QTextStream stream(&f); + stream << text; + f.close(); + + return true; +} + +QString FileTemplate::fullPathForName(KDevPlugin *part, const QString &name, + Policy p) { + // if Policy is not default, full path is just the name + if (p!=Default) return name; + + QString fileName; + // first try project-specific + if (part->project()) + { + fileName = (part->project()->projectDirectory() + "/templates/" + name); + if (QFile::exists(fileName)) return fileName; + } + + // next try global + QString globalName = ::locate("data", "kdevfilecreate/file-templates/" + name); + return globalName.isNull() ? fileName : globalName; +} diff --git a/lib/util/filetemplate.h b/lib/util/filetemplate.h new file mode 100644 index 00000000..e126176d --- /dev/null +++ b/lib/util/filetemplate.h @@ -0,0 +1,88 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Bernd Gehrmann <bernd@kdevelop.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _FILETEMPLATE_H_ +#define _FILETEMPLATE_H_ + +#include <qstring.h> + +class KDevPlugin; +class QDomDocument; + +/** +@file filetemplate.h +FileTemplate class with utility methods to work with file templates. +*/ + +/** +Utilities to work with file templates in the current project. +*/ +class FileTemplate +{ +public: + + /**Policy of finding file templates.*/ + typedef enum { + Default /**<Checks for templates in project and also for global filecreate templates.*/, + Custom /**<Checks for templates in custom directories. This usually means that + full paths are given for FileTemplate methods.*/ + } Policy; + + /** + * @return Whether a template with the given name + * exists in the current project. File templates + * are stored in the "templates" subdirectory of a project or in application shared dirs. + */ + static bool exists(KDevPlugin *part, const QString &name, Policy p = Default); + + /** + * Reads a template with the given name (e.g. "cpp") + * and makes variable substitutions (like $AUTHOR$ etc.) + * in it. The resulting string is returned. + */ + static QString read(KDevPlugin *part, const QString &name, Policy p = Default); + + /** + * Reads a template with the given URL + * and makes variable substitutions (like $AUTHOR$ etc.) + * in it. The resulting string is returned. + */ + static QString readFile(KDevPlugin *part, const QString &fileName); + + /** + * Makes variable substitutions on a text, based on a specified QDomDocument + * describing a KDevelop project file. The resulting string is returned. + */ + static QString makeSubstitutions(QDomDocument &dom, const QString &text); + + /** + * Copies a file template with the given name to the + * file with the name dest and - while copying - + * performs variable substitutions. + */ + static bool copy(KDevPlugin *part, const QString &name, + const QString &dest, Policy p = Default); + /** + * Translates a template name into a full path, or suggests a full path + * for the template in the project directory if it doesn't exist. + */ + static QString fullPathForName(KDevPlugin *part, const QString &name, Policy p = Default); +}; + +#endif diff --git a/lib/util/kdeveditorutil.cpp b/lib/util/kdeveditorutil.cpp new file mode 100644 index 00000000..fdf044d5 --- /dev/null +++ b/lib/util/kdeveditorutil.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + * Copyright (C) 2007 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kdeveditorutil.h" + +#include <ktexteditor/document.h> +#include <ktexteditor/view.h> +#include <ktexteditor/viewcursorinterface.h> +#include <ktexteditor/editinterface.h> +#include <ktexteditor/selectioninterface.h> + +bool KDevEditorUtil::currentPositionReal( unsigned int * line, unsigned int * col, KTextEditor::Document * doc, KTextEditor::View * view ) +{ + if ( !line || !col ) return false; + + KTextEditor::EditInterface * editIface = dynamic_cast<KTextEditor::EditInterface*>( doc ); + if ( !editIface ) return false; + + view = view ? view : dynamic_cast<KTextEditor::View*>( doc->widget() ); + + KTextEditor::ViewCursorInterface * cursorIface = dynamic_cast<KTextEditor::ViewCursorInterface*>( view ); + if ( !cursorIface ) return false; + + cursorIface->cursorPositionReal( line, col ); + return true; +} + +QString KDevEditorUtil::currentLine( KTextEditor::Document * doc, KTextEditor::View * view ) +{ + KTextEditor::EditInterface * editIface = dynamic_cast<KTextEditor::EditInterface*>( doc ); + if ( !editIface ) return QString(); + + view = view ? view : dynamic_cast<KTextEditor::View*>( doc->widget() ); + + KTextEditor::ViewCursorInterface * cursorIface = dynamic_cast<KTextEditor::ViewCursorInterface*>( view ); + if ( !cursorIface ) return QString(); + + uint line = 0; + uint col = 0; + cursorIface->cursorPositionReal(&line, &col); + + return editIface->textLine(line); +} + +QString KDevEditorUtil::currentWord( KTextEditor::Document * doc, KTextEditor::View * view ) +{ + KTextEditor::EditInterface * editIface = dynamic_cast<KTextEditor::EditInterface*>( doc ); + if ( !editIface ) return QString(); + + view = view ? view : dynamic_cast<KTextEditor::View*>( doc->widget() ); + + KTextEditor::ViewCursorInterface * cursorIface = dynamic_cast<KTextEditor::ViewCursorInterface*>( view ); + if ( !cursorIface ) return QString(); + + uint line = 0; + uint col = 0; + cursorIface->cursorPositionReal(&line, &col); + + QString linestr = editIface->textLine(line); + + int startPos = QMAX( QMIN( (int)col, (int)linestr.length()-1 ), 0 ); + int endPos = startPos; + startPos--; + while (startPos >= 0 && ( linestr[startPos].isLetterOrNumber() || linestr[startPos] == '_' || linestr[startPos] == '~') ) + startPos--; + while (endPos < (int)linestr.length() && ( linestr[endPos].isLetterOrNumber() || linestr[endPos] == '_' ) ) + endPos++; + + return ( ( startPos == endPos ) ? QString::null : linestr.mid( startPos+1, endPos-startPos-1 ) ); +} + + +QString KDevEditorUtil::currentSelection( KTextEditor::Document * doc ) +{ + KTextEditor::SelectionInterface * selectIface = dynamic_cast<KTextEditor::SelectionInterface*>( doc ); + return selectIface ? selectIface->selection() : QString(); +} + + +// kate: space-indent off; indent-width 4; tab-width 4; show-tabs on; + diff --git a/lib/util/kdeveditorutil.h b/lib/util/kdeveditorutil.h new file mode 100644 index 00000000..7b788fc3 --- /dev/null +++ b/lib/util/kdeveditorutil.h @@ -0,0 +1,67 @@ +/*************************************************************************** + * Copyright (C) 2007 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KDEVEDITOR_H +#define KDEVEDITOR_H + +namespace KTextEditor +{ +class Document; +class View; +} + +#include <qstring.h> + +/** +Class with some common utility operations not currently supported by KTE + + @author Jens Dagerbo <jens.dagerbo@swipnet.se> +*/ +class KDevEditorUtil +{ + KDevEditorUtil() {} +public: + + /** + * + * @param line + * @param col + * @param doc + * @param view + * @return + */ + static bool currentPositionReal( unsigned int * line, unsigned int * col, KTextEditor::Document * doc, KTextEditor::View * view = 0 ); + + /** + * + * @param doc + * @param view + * @return + */ + static QString currentLine( KTextEditor::Document * doc, KTextEditor::View * view = 0 ); + + /** + * Call to get the text under the cursor of the currently active view. + * @return the text under the cursor of the currently active view + */ + static QString currentWord( KTextEditor::Document * doc, KTextEditor::View * view = 0 ); + + /** + * Call to get the selection in the currently active view + * @return the selection in the currently active view + */ + static QString currentSelection( KTextEditor::Document * doc ); +}; + +#endif + + +// kate: space-indent off; indent-width 4; tab-width 4; show-tabs on; diff --git a/lib/util/kdevjobtimer.cpp b/lib/util/kdevjobtimer.cpp new file mode 100644 index 00000000..b7f9e2ae --- /dev/null +++ b/lib/util/kdevjobtimer.cpp @@ -0,0 +1,39 @@ +/*************************************************************************** + * Copyright (C) 2006 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kdevjobtimer.h" + +KDevJobTimer::KDevJobTimer( void * payload, QObject *parent, const char *name) + : QTimer(parent, name) +{ + m_payload = payload; + connect( this, SIGNAL(timeout()), this, SLOT(slotTimeout()) ); +} + +KDevJobTimer::~KDevJobTimer() +{ +} + +void KDevJobTimer::singleShot(int msec, QObject * receiver, const char * member, void * payload) +{ + KDevJobTimer * p = new KDevJobTimer( payload ); + p->start( msec, true ); + connect( p, SIGNAL(timeout(void*)), receiver, member ); +} + +void KDevJobTimer::slotTimeout() +{ + emit timeout( m_payload ); + m_payload = 0; + deleteLater(); +} + +#include "kdevjobtimer.moc" diff --git a/lib/util/kdevjobtimer.h b/lib/util/kdevjobtimer.h new file mode 100644 index 00000000..972a654a --- /dev/null +++ b/lib/util/kdevjobtimer.h @@ -0,0 +1,39 @@ +/*************************************************************************** + * Copyright (C) 2006 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KDEVJOBTIMER_H +#define KDEVJOBTIMER_H + +#include <qtimer.h> + +class KDevJobTimer : public QTimer +{ +Q_OBJECT +public: + static void singleShot( int msec, QObject * receiver, const char * member, void * payload ); + +signals: + void timeout(void*); + +private: + KDevJobTimer( void * payload, QObject *parent = 0, const char *name = 0); + ~KDevJobTimer(); + +private slots: + void slotTimeout(); + +private: + void * m_payload; + +}; + + +#endif diff --git a/lib/util/kdevshellwidget.cpp b/lib/util/kdevshellwidget.cpp new file mode 100644 index 00000000..f9a61fea --- /dev/null +++ b/lib/util/kdevshellwidget.cpp @@ -0,0 +1,125 @@ +/*************************************************************************** + * Copyright (C) 2006 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <qtimer.h> +#include <qframe.h> + +#include <kdebug.h> +#include <kparts/part.h> +#include <klibloader.h> +#include <kde_terminal_interface.h> +#include <kprocess.h> + +#include "kdevshellwidget.h" + +KDevShellWidget::KDevShellWidget(QWidget *parent, const char *name) + : QVBox(parent, name), m_doAutoActivate( false ), m_isRunning( false ) +{ +} + + +KDevShellWidget::~KDevShellWidget() +{ +} + +void KDevShellWidget::setShell( const QString & shell, const QStrList & arguments ) +{ + m_shellName = shell; + m_shellArguments = arguments; +} + +void KDevShellWidget::activate( ) +{ + KLibFactory *factory = KLibLoader::self()->factory("libkonsolepart"); + if ( !factory ) return; + + m_konsolePart = (KParts::ReadOnlyPart *) factory->create( this, "libkonsolepart", "KParts::ReadOnlyPart" ); + if ( !m_konsolePart ) return; + + connect( m_konsolePart, SIGNAL( processExited(KProcess *) ), this, SLOT( processExited(KProcess *) ) ); + connect( m_konsolePart, SIGNAL( receivedData( const QString& ) ), this, SIGNAL( receivedData( const QString& ) ) ); + connect( m_konsolePart, SIGNAL(destroyed()), this, SLOT(partDestroyed()) ); + + m_konsolePart->widget()->setFocusPolicy( QWidget::WheelFocus ); + setFocusProxy( m_konsolePart->widget() ); + m_konsolePart->widget()->setFocus(); + + if ( m_konsolePart->widget()->inherits("QFrame") ) + ((QFrame*)m_konsolePart->widget())->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + + m_konsolePart->widget()->show(); + + TerminalInterface* ti = static_cast<TerminalInterface*>( m_konsolePart->qt_cast( "TerminalInterface" ) ); + if( !ti ) return; + + if ( !m_shellName.isEmpty() ) + ti->startProgram( m_shellName, m_shellArguments ); + + m_isRunning = true; + +} + +void KDevShellWidget::partDestroyed( ) +{ + if ( m_doAutoActivate ) + { + activate(); + } +} + +void KDevShellWidget::processExited( KProcess * proc ) +{ + m_isRunning = false; + + if ( !proc ) return; + + kdDebug(9000) << proc->args() << endl; + + if ( proc->normalExit() ) + emit shellExited( proc->exitStatus() ); + else if ( proc->signalled() ) + emit shellSignalled( proc->exitSignal() ); +} + +void KDevShellWidget::sendInput( const QString & text ) +{ + if ( !m_konsolePart ) return; + TerminalInterface* ti = static_cast<TerminalInterface*>( m_konsolePart->qt_cast( "TerminalInterface" ) ); + if( !ti ) return; + + ti->sendInput( text ); +} + +bool KDevShellWidget::isRunning( ) +{ + return m_isRunning; +} + +void KDevShellWidget::setAutoReactivateOnClose( bool doAutoActivate ) +{ + // to auto reactivate can be dangerous, do it like this to avoid + // reactivating with a non-working setting (the partDestroyed() + // slot will have ran before m_doAutoActivate is set) + if ( doAutoActivate ) + QTimer::singleShot( 3000, this, SLOT(setAutoReactivateOnCloseDelayed()) ); + else + m_doAutoActivate = false; +} + +void KDevShellWidget::setAutoReactivateOnCloseDelayed( ) +{ + m_doAutoActivate = true; +} + + +#include "kdevshellwidget.moc" + +// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off; diff --git a/lib/util/kdevshellwidget.h b/lib/util/kdevshellwidget.h new file mode 100644 index 00000000..3f1500aa --- /dev/null +++ b/lib/util/kdevshellwidget.h @@ -0,0 +1,100 @@ +/*************************************************************************** + * Copyright (C) 2006 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#ifndef KDEVSHELLWIDGET_H +#define KDEVSHELLWIDGET_H + +#include <qstrlist.h> +#include <qvbox.h> +#include <qguardedptr.h> + +class KProcess; +namespace KParts +{ + class ReadOnlyPart; +} + +class KDevShellWidget : public QVBox +{ + +Q_OBJECT + +public: + KDevShellWidget(QWidget *parent = 0, const char *name = 0); + virtual ~KDevShellWidget(); + + /** + * Stores the shell name and arguments, that will be used in @ref activate() + * @param shell The shell name, for example 'irb' or '/bin/bash' + * @param arguments Any optional arguments + */ + void setShell( const QString & shell, const QStrList & arguments = QStrList() ); + + /** + * Executes the previously set shell. If @ref setShell wasn't called before + * konsolepart will decide what to use. + */ + void activate(); + + /** + * Should we auto launch the shell again if it was terminated? + * @param doAutoActivate + */ + void setAutoReactivateOnClose( bool doAutoActivate ); + + /** + * Send text to the running shell + * @param text The text to send to the shell + */ + void sendInput( const QString & text ); + + /** + * Call to check if the shell is currently running + * @return true if the shell is currently running + */ + bool isRunning(); + +signals: + /** + * This signal will be emmitted when the started shell exits normally + * @param exitcode The return code of the process + */ + void shellExited( int exitcode ); + + /** + * This signal will be emitted when the started shell is terminated by a signal + * @param signalcode The signal the process was killed with + */ + void shellSignalled( int signalcode ); + + /** + * This signal will be emitted when the process receives data + * @param text received data + */ + void receivedData( const QString & ); + +private slots: + void partDestroyed(); + void processExited( KProcess * ); + void setAutoReactivateOnCloseDelayed( ); + +private: + QGuardedPtr<KParts::ReadOnlyPart> m_konsolePart; + QString m_shellName; + QStrList m_shellArguments; + bool m_doAutoActivate; + bool m_isRunning; +}; + +#endif + +// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off; diff --git a/lib/util/kscriptactionmanager.cpp b/lib/util/kscriptactionmanager.cpp new file mode 100644 index 00000000..cf73e949 --- /dev/null +++ b/lib/util/kscriptactionmanager.cpp @@ -0,0 +1,177 @@ +/*************************************************************************** +* Copyright (C) 2004 by ian geiser * +* geiseri@sourcextreme.com * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ +#include "kscriptactionmanager.h" +#include <kparts/part.h> +#include <kparts/componentfactory.h> +#include <kapplication.h> +#include <kdesktopfile.h> +#include <kstandarddirs.h> + +#include <klocale.h> +#include <kmessagebox.h> +#include <kdebug.h> +#include <scriptinterface.h> +#include <kaction.h> +#include <qfileinfo.h> +#include <qtimer.h> + +KScriptAction::KScriptAction( const QString &scriptDesktopFile, QObject *interface, KActionCollection *ac ) + : QObject(interface), KScriptClientInterface( ) +{ + m_interface = 0L; + m_action = 0L; + m_isValid = false; + m_refs = 0; + // Read the desktop file + if(KDesktopFile::isDesktopFile(scriptDesktopFile)) + { + KDesktopFile desktop(scriptDesktopFile, true); + QFileInfo scriptPath(scriptDesktopFile); + + m_scriptFile = scriptPath.dirPath(true) + "/" + desktop.readEntry("X-KDE-ScriptName", ""); + m_scriptName = desktop.readName(); + m_scriptType = desktop.readType(); + QString scriptTypeQuery = "([X-KDE-Script-Runner] == '" + m_scriptType + "')"; + KTrader::OfferList offers = KTrader::self()->query( "KScriptRunner/KScriptRunner", scriptTypeQuery ); + if ( !offers.isEmpty() ) + { + m_action = new KAction(m_scriptName, KShortcut(), this, SLOT(activate()), ac, "script"); + m_isValid = true; + m_timeout = new QTimer(this); + QString icon = desktop.readIcon(); + m_action->setStatusText(desktop.readComment()); + if( !icon.isEmpty() ) + m_action->setIcon(icon); + m_action->setShortcutConfigurable(true); + connect( m_timeout, SIGNAL(timeout()), SLOT(cleanup()) ); + } + } +} + +KScriptAction::~KScriptAction() +{ + if( m_interface ) delete m_interface; + if( m_action ) delete m_action; +} + + + +KAction * KScriptAction::action( ) +{ + return m_action; +} + +void KScriptAction::activate( ) +{ + if( m_interface == 0L) + { + QString scriptTypeQuery = "([X-KDE-Script-Runner] == '" + m_scriptType + "')"; + m_interface= KParts::ComponentFactory::createInstanceFromQuery<KScriptInterface>( "KScriptRunner/KScriptRunner", scriptTypeQuery, this ); + if ( m_interface != 0L) + { + m_interface->ScriptClientInterface= this; + if( m_scriptMethod.isEmpty() ) + m_interface->setScript(m_scriptFile); + else + m_interface->setScript(m_scriptFile, m_scriptMethod); + connect(this, SIGNAL(done(KScriptClientInterface::Result, const QVariant &)), this, SLOT(scriptFinished())); + } + else + { + KMessageBox::sorry(0, i18n("Unable to get KScript Runner for type \"%1\".").arg(m_scriptType), i18n("KScript Error")); + kdDebug() << "Query string: " << scriptTypeQuery << endl; + return; + } + } + m_interface->run(parent(), QVariant()); + m_timeout->start(60000,FALSE); // after 1 minute unload + m_refs++; +} + +void KScriptAction::cleanup() +{ + if( m_interface && m_refs == 0) + { + delete m_interface; + m_interface = 0L; + } +} + +void KScriptAction::scriptFinished() +{ + m_refs--; +} + +KScriptActionManager::KScriptActionManager( QObject *parent, KActionCollection * ac ) : QObject(parent), m_ac(ac) +{ + m_actions.setAutoDelete(true); +} + +KScriptActionManager::~ KScriptActionManager( ) +{ + m_actions.clear(); +} + +QPtrList< KAction > KScriptActionManager::scripts( QObject * interface , const QStringList &dirs) const +{ + m_actions.clear(); + QPtrList<KAction> actions; + QStringList scripts; + + scripts += KGlobal::dirs()->findAllResources("data", + QString(kapp->name())+"/scripts/*.desktop", false, true ); + + for( QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it) + { + scripts += KGlobal::dirs()->findAllResources("data", + (*it)+"/*.desktop", false, true ); + } + + for (QStringList::Iterator it = scripts.begin(); it != scripts.end(); ++it ) + { + kdDebug() << "Loading " << *it << endl; + KScriptAction *script = new KScriptAction(*it, interface, m_ac); + if( script->isValid()) + { + actions.append(script->action()); + m_actions.append(script); + connect(script, SIGNAL(error( const QString&)), this, + SIGNAL(scriptError( const QString&))); + connect(script, SIGNAL(warning( const QString&)), this, + SIGNAL(scriptWarning( const QString&))); + connect(script, SIGNAL(output( const QString&)), this, + SIGNAL(scriptOutput( const QString&))); + connect(script, SIGNAL(progress( int )), this, + SIGNAL(scriptProgress(int))); + connect(script, SIGNAL(done( KScriptClientInterface::Result, const QVariant &)),this, + SIGNAL(scriptDone( KScriptClientInterface::Result, const QVariant &))); + } + else + delete script; + } + return actions; +} + +bool KScriptAction::isValid( ) const +{ + return m_isValid; +} + +#include "kscriptactionmanager.moc" diff --git a/lib/util/kscriptactionmanager.h b/lib/util/kscriptactionmanager.h new file mode 100644 index 00000000..234e4a3c --- /dev/null +++ b/lib/util/kscriptactionmanager.h @@ -0,0 +1,139 @@ +/*************************************************************************** +* Copyright (C) 2004 by ian geiser * +* geiseri@sourcextreme.com * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ +#ifndef KScriptAction_H +#define KScriptAction_H + +#include <scriptclientinterface.h> +#include <qobject.h> +#include <qptrlist.h> + +class KAction; +class KActionCollection; +class KScriptInterface; +class KScriptActionManager; +class QTimer; + +/** +* Connects a KAction to a script runner. +* +* @author ian geiser geiseri@sourcextreme.com +*/ +class KScriptAction : public QObject, public KScriptClientInterface { + Q_OBJECT +public: + + KScriptAction( const QString &scriptDesktopFile, QObject *interface, KActionCollection *ac ); + + virtual ~KScriptAction(); + + /** + * KAction for the current script + */ + KAction *action(); + + /** + * Returns the validity of the current script. + */ + bool isValid() const; + +signals: + // Reimplemented from KScript + void error ( const QString &msg ); + void warning ( const QString &msg ); + void output ( const QString &msg ); + void progress ( int percent ); + void done ( KScriptClientInterface::Result result, const QVariant &returned ); + +signals: + void scriptError ( const QString &msg ); + void scriptWarning ( const QString &msg ); + void scriptOutput ( const QString &msg ); + void scriptProgress ( int percent ); + void scriptDone ( KScriptClientInterface::Result result, const QVariant &returned ); + +private slots: + void activate(); + void cleanup(); + void scriptFinished(); + +private: + KAction *m_action; + QString m_scriptName; + QString m_scriptType; + QString m_scriptFile; + QString m_scriptMethod; + KScriptInterface *m_interface; + bool m_isValid; + QTimer *m_timeout; + uint m_refs; +}; + +/** + * Provides an actionlist of scripts that are currently available. + * Scripts are not actually loaded until they are actually executed. + * @author ian geiser <geiseri@sourcextreme.com> + */ +class KScriptActionManager : public QObject { +Q_OBJECT + +public: + /** + * Create a script manager that is attached to an action collection. + */ + KScriptActionManager( QObject *parent, KActionCollection *ac ); + ~KScriptActionManager(); + + /** + * Return all currently loaded scripts in a direcotry and attaches them + * to a QObject interface. If the dirs are empty the current applications + * scripts directory is used. The dirs are actual directories to search + * in the $KDEPATH/data/ direcories. So if you add "coolapp/data" then + * the manager will search in $KDEPATH/data/coolapp/data for all desktop + * files that are scripts. + */ + QPtrList<KAction> scripts( QObject *interface, const QStringList &dirs = QStringList() ) const; + +signals: + /** + * Returns an error message from a script. + */ + void scriptError ( const QString &msg ); + /** + * Returns a warning message from a script. + */ + void scriptWarning ( const QString &msg ); + /** + * Returns a standard out message from a script. + */ + void scriptOutput ( const QString &msg ); + /** + * Returns the percentage complete of an operation in the script. + */ + void scriptProgress ( int percent ); + /** + * Notifies that the script has finished. + */ + void scriptDone( KScriptClientInterface::Result result, const QVariant &returned ); + +private: + mutable QPtrList<KScriptAction> m_actions; + KActionCollection *m_ac; +}; +#endif diff --git a/lib/util/rurl.cpp b/lib/util/rurl.cpp new file mode 100644 index 00000000..1ec23434 --- /dev/null +++ b/lib/util/rurl.cpp @@ -0,0 +1,369 @@ +#include <qstringlist.h> + +#include "rurl.h" + +namespace Relative{ + + +//class Name + +Name::Name( const QString & rurl, const Type type ) + :m_rurl(rurl), m_type(type) +{ + correct(); +} + +Name::Name( const char * rurl, const Type type ) + :m_rurl(rurl), m_type(type) +{ + correct(); +} + +void Name::correct() +{ + cleanRURL(); + if (m_rurl[0] == '/') + m_rurl = m_rurl.mid(1); + switch (m_type) + { + case File: + if (m_rurl.endsWith("/")) + m_rurl = m_rurl.mid(0, m_rurl.length()-1); + break; + case Directory: + if (!m_rurl.endsWith("/")) + m_rurl += "/"; + break; + case Auto: + if (m_rurl.endsWith("/")) + m_type = Directory; + else + m_type = File; + break; + } +} + +QString Name::correctName( const QString & rurl, const Type type ) +{ + QString temp = rurl; + temp = Name::cleanName(temp); + if (temp[0] == '/') + temp = temp.mid(1); + + switch (type) + { + case File: + if (temp.endsWith("/")) + temp = temp.mid(0, temp.length()-1); + break; + case Directory: + if (!temp.endsWith("/")) + temp += "/"; + break; + } + + return temp; +} + +void Name::setRURL( const QString & rurl, const Type type ) +{ + m_rurl = rurl; + m_type = type; + correct(); +} + +QString Name::rurl( ) const +{ + return m_rurl; +} + +void Name::addPath( const QString & addendum ) +{ + QString temp = correctName(addendum, Directory); + m_rurl = directory() + temp + fileName(); +} + +void Name::cleanRURL( ) +{ + m_rurl = cleanName(m_rurl); +} + +QString Name::cleanName( const QString & rurl ) +{ + QString temp; + bool wasSlash = false; + for (unsigned int i = 0; i < rurl.length(); ++i) + { + if (wasSlash && (rurl[i] == '/')) + continue; + + temp += rurl[i]; + if (rurl[i] == '/') + wasSlash = true; + else if (wasSlash) + wasSlash = false; + } + + return temp; +} + +QString Name::extension( bool complete ) const +{ + if (m_type == File) + { + QString temp = fileName(); + if (complete) + return temp.mid(temp.find('.')+1); + else + return temp.mid(temp.findRev('.')+1); + } + return QString::null; +} + +QString Name::fileName( ) const +{ + if (m_type == File) + return m_rurl.section('/', -1); + return QString::null; +} + +QString Name::directory( ) const +{ + if ( (m_type == File) && (m_rurl.findRev('/') == -1) ) + return QString::null; + + return m_rurl.mid(0, m_rurl.findRev('/')+1); +} + +bool Name::isFile( ) const +{ + return m_type == File; +} + +bool Name::isDirectory( ) const +{ + return m_type == Directory; +} + +bool Name::operator ==( const Name & rname ) +{ + return rname.rurl() == m_rurl; +} + +bool Name::operator !=( const Name & rname ) +{ + return rname.rurl() != m_rurl; +} + +bool Name::isValid( ) const +{ + if (m_rurl.startsWith("/")) + return false; + if (m_rurl.contains("//")) + return false; + if ( (m_rurl.endsWith("/")) && (m_type == File) ) + return false; + if ( (!m_rurl.endsWith("/")) && (m_type == Directory) ) + return false; + if (m_type == Auto) + return false; + + return true; +} + +Name::Type Name::type( ) const +{ + return m_type; +} + +void Name::setType( const Type type ) +{ + m_type = type; +} + +Name Name::relativeName( const QString &base, const QString &url ) +{ + QString dirUrl = base; + QString fileUrl = url; + + if (dirUrl.isEmpty() || (dirUrl == "/")) + return Name(fileUrl); + + QStringList dir = QStringList::split("/", dirUrl, false); + QStringList file = QStringList::split("/", fileUrl, false); + + QString resFileName = file.last(); + if (url.endsWith("/")) + resFileName += "/"; + file.remove(file.last()); + + uint i = 0; + while ( (i < dir.count()) && (i < (file.count())) && (dir[i] == file[i]) ) + i++; + + QString result_up; + QString result_down; + QString currDir; + QString currFile; + do + { + i >= dir.count() ? currDir = "" : currDir = dir[i]; + i >= file.count() ? currFile = "" : currFile = file[i]; +// qWarning("i = %d, currDir = %s, currFile = %s", i, currDir.latin1(), currFile.latin1()); + if (currDir.isEmpty() && currFile.isEmpty()) + break; + else if (currDir.isEmpty()) + result_down += file[i] + "/"; + else if (currFile.isEmpty()) + result_up += "../"; + else + { + result_down += file[i] + "/"; + result_up += "../"; + } + i++; + } + while ( (!currDir.isEmpty()) || (!currFile.isEmpty()) ); + + return result_up + result_down + resFileName; +} + + + +//class URL + +URL::URL( KURL base, KURL url, Type type ) + :Name(Name::relativeName(base.path(), url.path()).rurl(), type), m_base(base) +{ +} + +URL::URL( KURL base, QString url, bool isUrlRelative, Type type ) + :Name(isUrlRelative ? url : Name::relativeName(base.path(), url).rurl(), type), m_base(base) +{ +} + +void URL::setBase( const KURL & base ) +{ + m_base = base; +} + +void URL::setBase( const QString & base ) +{ + KURL url; + url.setPath(base); + m_base = url; +} + +KURL URL::base( ) const +{ + return m_base; +} + +QString URL::basePath( ) const +{ + return m_base.path(1); +} + +KURL URL::url( ) const +{ + KURL url = m_base; + url.addPath(rurl()); + url.cleanPath(); + return url; +} + +QString URL::urlPath( ) const +{ + KURL url = m_base; + url.addPath(rurl()); + int mod = 0; + if (type() == File) + mod = -1; + else if (type() == Directory) + mod = 1; + url.cleanPath(); + return url.path(mod); +} + +QString URL::urlDirectory( ) const +{ + KURL url = m_base; + url.addPath(rurl()); + url.cleanPath(); + return url.directory(false, false); +} + +URL URL::relativeTo( KURL base ) +{ + return URL(base, url(), type()); +} + +URL URL::relativeURL( KURL base, KURL url ) +{ + return URL(base, url); +} + +URL URL::relativeURL( KURL base, QString url, bool isUrlRelative ) +{ + return URL(base, url, isUrlRelative); +} + +bool Relative::URL::operator ==( const URL & url ) +{ + return (m_base == url.base()) && (rurl() == url.rurl()); +} + +bool Relative::URL::operator !=( const URL & url ) +{ + return (m_base != url.base()) || (rurl() != url.rurl()); +} + + + +// Directory class + +Directory::Directory( KURL base, KURL url ) + :URL(base, url, Name::Directory) +{ +} + +Directory::Directory( KURL base, QString url, bool isRelativeUrl ) + :URL(base, url, isRelativeUrl, Name::Directory) +{ +} + +void Directory::setRURL( QString rurl ) +{ + URL::setRURL(rurl, Name::Directory); +} + +void Directory::setRURL( QString rurl, Type type ) +{ + URL::setRURL(rurl, type); +} + + + +//File class + +File::File( KURL base, KURL url ) + :URL(base, url, Name::File) +{ +} + +File::File( KURL base, QString url, bool isRelativeUrl ) + :URL(base, url, isRelativeUrl, Name::File) +{ +} + +void File::setRURL( QString rurl, Type type ) +{ + URL::setRURL(rurl, type); +} + +void File::setRURL( QString rurl ) +{ + URL::setRURL(rurl, Name::File); +} + +} diff --git a/lib/util/rurl.h b/lib/util/rurl.h new file mode 100644 index 00000000..342b3e3d --- /dev/null +++ b/lib/util/rurl.h @@ -0,0 +1,182 @@ +#ifndef RURL_H_LIB +#define RURL_H_LIB + +#include <kurl.h> + +/** +@file rurl.h +Classes and functions to work with relative URLs. +*/ + +/**Classes and functions to work with relative URLs.*/ +namespace Relative +{ + +/**Relative name of a file or directory.*/ +class Name{ +public: + enum Type { File, Directory, Auto }; + + /**Constructor takes the relative name of a directory or file. + Leading slash in the name will be deleted. + If type is Auto names like: + name/name/ are directories + name/name are files. + Trailing slash will be deleted for files (type == File).*/ + Name(const QString &rurl, const Type type = Auto); + Name(const char *rurl, const Type type = Auto); + + /**Sets the relative name.*/ + void setRURL(const QString &rurl, const Type type); + /**Gets the relative name in form + dir/dir/ -> directory + or + dir/dir/file -> file.*/ + QString rurl() const; + + /**Adds addendum to the directory path. This honors file names so + if RName represents /dir1/dir2/fname.ext + addPath(dir3) will change RName to /dir1/dir2/dir3/fname.ext*/ + void addPath(const QString &addendum); + /**Removes "//" from the name.*/ + void cleanRURL(); + + /**Returns the extension of a file or QString::null for directories. + If complete is true then returns extensions like "tar.gz". + Else returns "gz".*/ + QString extension(bool complete = true) const; + /**Returns the name of the file without the path or QString::null + for directories.*/ + QString fileName() const; + /**Returns the name of the directory or QString::null if there are no dirs in path.*/ + QString directory() const; + + /**Returns true if the type of RName is file.*/ + bool isFile() const; + /**Returns true if the type of RName is directory.*/ + bool isDirectory() const; + /**Checks if RName is valid.*/ + bool isValid() const; + + /**Returns a type of the relative name - file or directory.*/ + Type type() const; + /**Sets a type of the relative name - file or directory. + If Auto is passed, nothing happens.*/ + void setType(const Type type); + + /**Creates and returns relative name between base and url. Base and url should be absolute. + Base is considered to be a directory.*/ + static Name relativeName(const QString &base, const QString &url); + /**Cleans rurl by removing extra slashes.*/ + static QString cleanName(const QString &rurl); + /**Corrects rurl according to the given type and returns corrected url. + Also cleans url (see @ref cleanRURL).*/ + static QString correctName(const QString &rurl, const Type type = Auto); + + bool operator == (const Name &rname); + bool operator != (const Name &rname); + +protected: + /**Corrects m_rurl and m_type according to the relative name storing policy, + i.e. removes leading slash, removes trailing slash for files, changes type + to be either File or Directory, but not Auto. Also cleans url (see @ref cleanRURL).*/ + void correct(); + +private: + QString m_rurl; + Type m_type; +}; + +/**Relative name of file or directory to some base location.*/ +class URL: public Name{ +public: + /**Evaluates the relative path between url and base and creates RURL object. + base should be an url to the directory or location, not a file. + The check is not performed. url should be the usual url. Only the + path of this url is taken into account when evaluating relative path.*/ + URL(KURL base, KURL url, Type type = Auto); + /**Creates RURL object with given base and relative or full url (according to + the isUrlRelative value).*/ + URL(KURL base, QString url, bool isUrlRelative, Type type = Auto); + + /**Sets a new base for a RURL.*/ + void setBase(const KURL &base); + /**Sets a new base for a RURL. Base is is considered to be a + directory and converted to KURL using KURL::setPath().*/ + void setBase(const QString &base); + /**Returns RURL base.*/ + KURL base() const; + /**Returns a path of a base KURL (using KURL::path()). Trailing slash is guaranteed.*/ + QString basePath() const; + + /**Returns a complete url to the RURL location. This is basically base + rurl. + This also resolves ".." components in path. + Directories always have trailing slash in KURL + (this means that if url() == "file:/test/dir/" then + url() != KURL("/test/dir") and + url() == KURL("/test/dir/").*/ + KURL url() const; + /**Returns a path of a complete url to the location. The url is basically base + rurl. + This method only returns a path part of the KURL (using KURL::path()). + Trailing slash is guaranteed for directories and no trailing slash - for files. + This also resolves ".." components in path.*/ + QString urlPath() const; + /**Returns a directory of a complete url to the location. The url is constructed as base + rurl. + Returns the same as urlPath() for directories. + This method uses KURL::directory to determine the directory. + Trailing slash is guaranteed. + This also resolves ".." components in path.*/ + QString urlDirectory() const; + + /**Returns a new URL that is relative to given base. Relative part is taken from + current URL object.*/ + URL relativeTo(KURL base); + + /**Returns a new relative URL constructed from base and given url.*/ + static URL relativeURL(KURL base, KURL url); + /**Returns a new relative URL constructed from base and given url. url parameter + is either relative or full (depends on isUrlRelative value).*/ + static URL relativeURL(KURL base, QString url, bool isUrlRelative); + + bool operator == (const URL &url); + bool operator != (const URL &url); + +private: + KURL m_base; +}; + +/**Relative directory name.*/ +class Directory: public URL{ +public: + /**Works as URL::URL(KURL, KURL), only implies Name::Directory mode.*/ + Directory(KURL base, KURL url); + /**Works as URL::URL(KURL, QString, bool), only implies Name::Directory mode.*/ + Directory(KURL base, QString url, bool isRelativeUrl); + + /**Works as URL::setRURL(QString), only implies Name::Directory mode.*/ + void setRURL(QString rurl); + +private: + void setRURL(QString rurl, Type type); + +}; + +/**Relative file name.*/ +class File: public URL{ +public: + /**Works as URL::URL(KURL, KURL), only implies Name::File mode.*/ + File(KURL base, KURL url); + /**Works as URL::URL(KURL, KURL), only implies Name::File mode.*/ + File(KURL base, QString url, bool isRelativeUrl); + + /**Works as URL::setRURL(QString), only implies Name::File mode.*/ + void setRURL(QString rurl); + +private: + void setRURL(QString rurl, Type type); + +}; + +} + +#endif diff --git a/lib/util/settings.cpp b/lib/util/settings.cpp new file mode 100644 index 00000000..4e246e5b --- /dev/null +++ b/lib/util/settings.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2005 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <kconfig.h> +#include <kglobal.h> +#include <kstandarddirs.h> + +#include "settings.h" + +QString Settings::terminalEmulatorName( KConfig & config ) +{ + config.setGroup("TerminalEmulator"); + bool useKDESetting = config.readBoolEntry( "UseKDESetting", true ); + QString terminal; + + if ( useKDESetting ) + { + KConfigGroup confGroup( KGlobal::config(), QString::fromLatin1("General") ); + terminal = confGroup.readEntry("TerminalApplication", QString::fromLatin1("konsole")); + } + else + { + terminal = config.readEntry( "TerminalApplication", QString::fromLatin1("konsole")); + } + return terminal; +} + +QString Settings::profileByAttributes(const QString &language, const QStringList &keywords) +{ + KConfig config(locate("data", "kdevelop/profiles/projectprofiles")); + config.setGroup(language); + + QStringList profileKeywords = QStringList::split("/", "Empty"); + if (config.hasKey("Keywords")) + profileKeywords = config.readListEntry("Keywords"); + + int idx = 0; + for (QStringList::const_iterator it = profileKeywords.constBegin(); + it != profileKeywords.constEnd(); ++it) + { + if (keywords.contains(*it)) + { + idx = profileKeywords.findIndex(*it); + break; + } + } + + QStringList profiles; + if (config.hasKey("Profiles")) + { + profiles = config.readListEntry("Profiles"); + return profiles[idx]; + } + return "KDevelop"; +} diff --git a/lib/util/settings.h b/lib/util/settings.h new file mode 100644 index 00000000..cd241cad --- /dev/null +++ b/lib/util/settings.h @@ -0,0 +1,26 @@ +/*************************************************************************** + * Copyright (C) 2005 by Jens Dagerbo * + * jens.dagerbo@swipnet.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef SETTINGS_H +#define SETTINGS_H + +class KConfig; + +/// Utility functions for settings +class Settings +{ +public: + static QString terminalEmulatorName( KConfig & config ); + static QString profileByAttributes(const QString &language, const QStringList &keywords); + +}; + +#endif diff --git a/lib/util/urlutil.cpp b/lib/util/urlutil.cpp new file mode 100644 index 00000000..942f1900 --- /dev/null +++ b/lib/util/urlutil.cpp @@ -0,0 +1,319 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Julian Rockey <linux@jrockey.com> + Copyright (C) 2003 Alexander Dymo <cloudtemple@mksat.net> + Copyright (C) 2003 Mario Scalas <mario.scalas@libero.it> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#include <qstringlist.h> + +#include <qdir.h> +#include <qfileinfo.h> +#include <kdebug.h> + +#include <unistd.h> +#include <limits.h> +#include <stdlib.h> + +#include "urlutil.h" + +#include <kdeversion.h> + +/////////////////////////////////////////////////////////////////////////////// +// Namespace URLUtil +/////////////////////////////////////////////////////////////////////////////// + +QString URLUtil::filename(const QString & name) { + int slashPos = name.findRev("/"); + return slashPos<0 ? name : name.mid(slashPos+1); +} + +/////////////////////////////////////////////////////////////////////////////// + +QString URLUtil::directory(const QString & name) { + int slashPos = name.findRev("/"); + return slashPos<0 ? QString("") : name.left(slashPos); +} + +/////////////////////////////////////////////////////////////////////////////// + +QString URLUtil::getRelativePath(const QString& basepath, const QString& destpath) +{ + QString relpath = "."; + if (!QFile::exists(basepath) || + !QFile::exists(destpath)) + return ""; + QStringList basedirs = QStringList::split(QString( QChar( QDir::separator() ) ),basepath); + QStringList destdirs = QStringList::split(QString( QChar( QDir::separator() ) ),destpath); + + int maxCompare=0; + if (basedirs.count()>=destdirs.count()) + maxCompare=destdirs.count(); + else + maxCompare=basedirs.count(); + int lastCommonDir=-1; + for (int i=0; i<maxCompare; i++) + { + if (basedirs[i] != destdirs[i]) + break; + lastCommonDir=i; + } + for (uint i=0;i<basedirs.count()-(lastCommonDir+1); i++) + relpath += QString( QChar( QDir::separator() ) )+QString(".."); + for (int i=0; i<lastCommonDir+1; i++) + destdirs.pop_front(); + if (destdirs.count()) + relpath += QString( QChar( QDir::separator() ) )+destdirs.join( QChar( QDir::separator() ) ); + return QDir::cleanDirPath(relpath); +} + +/////////////////////////////////////////////////////////////////////////////// + +QString URLUtil::relativePath(const KURL & parent, const KURL & child, uint slashPolicy) { + bool slashPrefix = slashPolicy & SLASH_PREFIX; + bool slashSuffix = slashPolicy & SLASH_SUFFIX; + if (parent.equals(child,true)) + return slashPrefix ? QString("/") : QString(""); + + if (!parent.isParentOf(child)) return QString(); + int a=slashPrefix ? -1 : 1; + int b=slashSuffix ? 1 : -1; + return child.path(b).mid(parent.path(a).length()); +} + +/////////////////////////////////////////////////////////////////////////////// + +QString URLUtil::relativePath(const QString & parent, const QString & child, uint slashPolicy) { + return relativePath(KURL(parent), KURL(child), slashPolicy); +} + +/////////////////////////////////////////////////////////////////////////////// + +QString URLUtil::upDir(const QString & path, bool slashSuffix) { + int slashPos = path.findRev("/"); + if (slashPos<1) return QString::null; + return path.mid(0,slashPos+ (slashSuffix ? 1 : 0) ); +} + +/////////////////////////////////////////////////////////////////////////////// + +KURL URLUtil::mergeURL(const KURL & source, const KURL & dest, const KURL & child) { + + // if already a child of source, then fine + if (source.isParentOf(child) || source.equals(child,true)) return child; + + // if not a child of dest, return blank URL (error) + if (!dest.isParentOf(child) && !dest.equals(child,true)) return KURL(); + + // if child is same as dest, return source + if (dest.equals(child,true)) return source; + + // calculate + QString childUrlStr = child.url(-1); + QString destStemStr = dest.url(1); + QString sourceStemStr = source.url(1); + return KURL(sourceStemStr.append( childUrlStr.mid( destStemStr.length() ) ) ); + +} + +/////////////////////////////////////////////////////////////////////////////// + +QString URLUtil::getExtension(const QString & path) { + int dotPos = path.findRev('.'); + if (dotPos<0) return QString(""); + return path.mid(dotPos+1); +} + +/////////////////////////////////////////////////////////////////////////////// + +QString URLUtil::extractPathNameRelative(const KURL &baseDirUrl, const KURL &url ) +{ + QString absBase = extractPathNameAbsolute( baseDirUrl ), + absRef = extractPathNameAbsolute( url ); + int i = absRef.find( absBase, 0, true ); + + if (i == -1) + return QString(); + + if (absRef == absBase) + return QString( "." ); + else + return absRef.replace( 0, absBase.length(), QString() ); +} + +/////////////////////////////////////////////////////////////////////////////// + +QString URLUtil::extractPathNameRelative(const QString &basePath, const KURL &url ) +{ + KURL baseDirUrl = KURL::fromPathOrURL( basePath ); + return extractPathNameRelative( baseDirUrl, url ); +} + +/////////////////////////////////////////////////////////////////////////////// + +QString URLUtil::extractPathNameRelative(const QString &basePath, const QString &absFilePath ) +{ + KURL baseDirUrl = KURL::fromPathOrURL( basePath ), + fileUrl = KURL::fromPathOrURL( absFilePath ); + return extractPathNameRelative( baseDirUrl, fileUrl ); +} + +/////////////////////////////////////////////////////////////////////////////// + +QString URLUtil::extractPathNameAbsolute( const KURL &url ) +{ + if (isDirectory( url )) + return url.path( +1 ); // with trailing "/" if none is present + else + { + // Ok, this is an over-tight pre-condition on "url" since I hope nobody will never + // stress this function with absurd cases ... but who knows? + /* + QString path = url.path(); + QFileInfo fi( path ); // Argh: QFileInfo is back ;)) + return ( fi.exists()? path : QString() ); + */ + return url.path(); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +bool URLUtil::isDirectory( const KURL &url ) +{ + return isDirectory( url.path() ); +} + +/////////////////////////////////////////////////////////////////////////////// + +bool URLUtil::isDirectory( const QString &absFilePath ) +{ + return QDir( absFilePath ).exists(); +} + +/////////////////////////////////////////////////////////////////////////////// + +void URLUtil::dump( const KURL::List &urls, const QString &aMessage ) +{ + if (!aMessage.isNull()) + { + kdDebug(9000) << aMessage << endl; + } + kdDebug(9000) << " List has " << urls.count() << " elements." << endl; + + for (size_t i = 0; i<urls.count(); ++i) + { + KURL url = urls[ i ]; +// kdDebug(9000) << " * Element = " << url.path() << endl; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +QStringList URLUtil::toRelativePaths( const QString &baseDir, const KURL::List &urls) +{ + QStringList paths; + + for (size_t i=0; i<urls.count(); ++i) + { + paths << extractPathNameRelative( baseDir, urls[i] ); + } + + return paths; +} + +/////////////////////////////////////////////////////////////////////////////// + +QString URLUtil::relativePathToFile( const QString & dirUrl, const QString & fileUrl ) +{ + if (dirUrl.isEmpty() || (dirUrl == "/")) + return fileUrl; + + QStringList dir = QStringList::split("/", dirUrl, false); + QStringList file = QStringList::split("/", fileUrl, false); + + QString resFileName = file.last(); + file.remove(file.last()); + + uint i = 0; + while ( (i < dir.count()) && (i < (file.count())) && (dir[i] == file[i]) ) + i++; + + QString result_up; + QString result_down; + QString currDir; + QString currFile; + do + { + i >= dir.count() ? currDir = "" : currDir = dir[i]; + i >= file.count() ? currFile = "" : currFile = file[i]; + //qWarning("i = %d, currDir = %s, currFile = %s", i, currDir.latin1(), currFile.latin1()); + if (currDir.isEmpty() && currFile.isEmpty()) + break; + else if (currDir.isEmpty()) + result_down += file[i] + "/"; + else if (currFile.isEmpty()) + result_up += "../"; + else + { + result_down += file[i] + "/"; + result_up += "../"; + } + i++; + } + while ( (!currDir.isEmpty()) || (!currFile.isEmpty()) ); + + return result_up + result_down + resFileName; +} + +/////////////////////////////////////////////////////////////////////////////// + +//TODO: remove for KDE4 +QString URLUtil::canonicalPath( const QString & path ) +{ + QDir dir(path); + return dir.canonicalPath(); +} + +/////////////////////////////////////////////////////////////////////////////// + +//written by "Dawit A." <adawit@kde.org> +//borrowed from his patch to KShell +QString URLUtil::envExpand ( const QString& str ) +{ + uint len = str.length(); + + if (len > 1 && str[0] == '$') + { + int pos = str.find ('/'); + + if (pos < 0) + pos = len; + + char* ret = getenv( QConstString(str.unicode()+1, pos-1).string().local8Bit().data() ); + + if (ret) + { + QString expandedStr ( QFile::decodeName( ret ) ); + if (pos < (int)len) + expandedStr += str.mid(pos); + return expandedStr; + } + } + + return str; +} + diff --git a/lib/util/urlutil.h b/lib/util/urlutil.h new file mode 100644 index 00000000..4f9ddbab --- /dev/null +++ b/lib/util/urlutil.h @@ -0,0 +1,190 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Julian Rockey <linux@jrockey.com> + Copyright (C) 2003 Mario Scalas <mario.scalas@libero.it> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _URLUTIL_H_ +#define _URLUTIL_H_ + +#include <qstring.h> +#include <qvaluelist.h> +#include <kurl.h> + +/** +@file urlutil.h +Utility functions to operate on URLs. +*/ + +/**Utility functions to operate on URLs.*/ +namespace URLUtil +{ + /**Position of a slash in the URL.*/ + enum SlashesPosition { + SLASH_PREFIX = 1 /**<URL has slash as a prefix.*/, + SLASH_SUFFIX = 2 /**<URL has slash as a suffix.*/ + }; + + /** + * @return The filename part of a pathname (i.e. everything past the last slash). + * @param pathName The absolute path to a file. + */ + QString filename(const QString & pathName); + /** + * @return The directory part of a path (i.e. everything up to but not including the last slash) + * @param pathName The absolute path to a directory. + */ + QString directory(const QString & pathName); + /** + * @return The relative path between a parent and child URL, or blank if the specified + * child is not a child of parent. + * @param parent The parent URL. + * @param child The child URL. + * @param slashPolicy If parent and child are equal then the function returns "/" if + * slashPolicy contains SLASH_PREFIX and otherwise "".\n"/" is appended to a result + * if slashPolicy contains SLASH_SUFFIX.\n"/" is prepended to a result if + * slashPolicy contains SLASH_PREFIX. + */ + QString relativePath(const KURL & parent, const KURL & child, uint slashPolicy = SLASH_PREFIX); + /** + * @return The relative path between a parent and child URL, or blank if the specified + * child is not a child of parent. + * @param parent The parent URL. + * @param child The child URL. + * @param slashPolicy If parent and child are equal then the function returns "/" if + * slashPolicy contains SLASH_PREFIX and otherwise "".\n"/" is appended to a result + * if slashPolicy contains SLASH_SUFFIX.\n"/" is prepended to a result if + * slashPolicy contains SLASH_PREFIX. + */ + QString relativePath(const QString & parent, const QString & child, uint slashPolicy = SLASH_PREFIX); + /** + * @return The relative path between a base path and destination path or. + * @param base The base Path. + * @param dest The destination path. + */ + QString getRelativePath( const QString& base, const QString& dest ); + /** + * @param dirUrl An URL of a directory. + * @param fileUrl An URL of a file. + * @return The relative path between a directory and file. Should never return empty path.\n + * <pre>Example: + * dirUrl: /home/test/src + * fileUrl: /home/test/lib/mylib.cpp + * returns: ../lib/mylib.cpp</pre> + */ + QString relativePathToFile( const QString & dirUrl, const QString & fileUrl ); + /** + *@param path A path (absolute or relative). + *@param slashSuffix if true then "/" is appended to a path. + *@returns The path 'up one level' - the opposite of what filename returns. + */ + QString upDir(const QString & path, bool slashSuffix = false); + /** + * 'Merges' URLs - changes a URL that starts with dest to start with source instead.\n + * <pre>Example: + * source is /home/me/ + * dest is /home/you/ + * child is /home/you/dir1/file1 + * returns /home/me/dir1/fil1</pre> + * @param source An URL of a source. + * @param dest An URL of a destination. + * @param child An URL to change. + * @return The result of merge. + */ + KURL mergeURL(const KURL & source, const KURL & dest, const KURL & child); + /** + * @return The file extension for a filename or path. + * @param path Absolute or relative path. + */ + QString getExtension(const QString & path); + + /** + * Given a base directory url in @p baseDirUrl and the url referring to the + * sub-directory or file, it will return the path relative to @p baseDirUrl. + * If baseDirUrl == url.path() then it will return ".". + * @code + * KURL baseUrl, dirUrl; + * baseUrl.setPath( "/home/mario/src/kdevelop/" ); + * dirUrl.setPath( "/home/mario/src/kdevelop/parts/cvs/" ); + * QString relPathName = extractDirPathRelative( baseUrl, url ); // == "parts/cvs/" + * QString absPathName = extractDirPathAbsolute( url ); // == "/home/mario/src/kdevelop/parts/cvs/" + * @endcode + * Note that if you pass a file name in @p url (instead of a directory) or the + * @p baseUrl is not contained in @p url then the function will return "" (void string). + * + * @param baseDirUrl Base directory URL. + * @param url Base directory URL. + * @return The relative path between @p url and @p baseDirUrl. + */ + QString extractPathNameRelative(const KURL &baseDirUrl, const KURL &url ); + /**Same as above. @p basePath is QString.*/ + QString extractPathNameRelative(const QString &basePath, const KURL &url ); + /**Same as above. Both @p basePath and @p absFilePath are QStrings.*/ + QString extractPathNameRelative(const QString &basePath, const QString &absFilePath ); + + /** + * @param url The url to extract the absolute path from. + * @return The absolute path name referred in @p url. + * Look at @ref extractPathNameRelative documentation for an example. + */ + QString extractPathNameAbsolute( const KURL &url ); + + /** + * @param baseDir Base directory for relative URLs. + * @param urls The list of urls to extract the relative paths from. + * @return A QStringList of relative (to @p baseDir) paths from a list of KURLs in @p urls. + */ + QStringList toRelativePaths( const QString &baseDir, const KURL::List &urls); + + /** + * @param url The absolute URL. + * @return true if @p url is a directory, false otherwise. + */ + bool isDirectory( const KURL &url ); + /** + * @param absFilePath The absolute path. + * @return true if @p url is a directory, false otherwise. + */ + bool isDirectory( const QString &absFilePath ); + + /** + * Dumps the list of KURL @p urls on standard output, eventually printing @p aMessage if it + * is not null. + * @param urls URLs to dump. + * @param aMessage Message to be written onto a stdout. + */ + void dump( const KURL::List &urls, const QString &aMessage = QString::null ); + + /** + * Same as QDir::canonicalPath in later versions of Qt. Earlier versions of Qt + * had this broken, so it's reproduced here. + * Deprecated, use QDir::canonicalPath instead. + */ + QString canonicalPath( const QString & path ); + + /** + * Performs environment variable expansion on @p variable. + * + * @param variable The string with the environment variable to expand. + * @return The expanded environment variable value. if the variable + * cannot be expanded, @p variable itself is returned. + */ + QString envExpand ( const QString &variable ); + +} + +#endif |