From kde-commits Fri Nov 30 23:58:08 2012 From: David Faure Date: Fri, 30 Nov 2012 23:58:08 +0000 To: kde-commits Subject: [kdelibs/frameworks] /: Merge remote-tracking branch 'origin/KDE/4.10' into frameworks Message-Id: <20121130235808.0D1E7A6091 () git ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=135431990419815 Git commit 71e5e17968c934f0e761adffddf489afd8dde44b by David Faure. Committed on 01/12/2012 at 00:57. Pushed by dfaure into branch 'frameworks'. Merge remote-tracking branch 'origin/KDE/4.10' into frameworks Conflicts: CMakeLists.txt [version] README [version] cmake/modules/CMakeLists.txt cmake/modules/FindKDE4Internal.cmake cmake/modules/FindNepomuk.cmake [git replaying an old conflict!] cmake/modules/KDE4Macros.cmake [automoc4 stuff, reverted] interfaces/ktexteditor/* [moved out] kdecore/services/kmimetype.cpp [hand-merged into kio/global.cpp] kdeui/util/kkeyserver.h kdeui/widgets/ktextedit.cpp kdewebkit/kwebwallet.cpp khtml/misc/enum.h [git got confused, me thinks] kio/kio/accessmanager.cpp kio/kio/hostinfo.cpp kio/kio/kprotocolmanager.cpp kio/kio/kprotocolmanager.h kioslave/http/http.cpp kioslave/http/http.h kioslave/http/tests/CMakeLists.txt kioslave/http/tests/httpheaderdispositiontest.cpp nepomuk/core/* [moved out] plasma/CMakeLists.txt plasma/applet.cpp plasma/applet.h plasma/dialog.cpp plasma/packagestructure.cpp plasma/popupapplet.cpp plasma/private/applethandle.cpp plasma/private/packages.cpp plasma/private/tooltip.cpp plasma/tooltipmanager.cpp plasma/widgets/videowidget.h staging/ki18n/src/klocalizedstring.cpp staging/kservice/autotests/kservicetest.cpp staging/kwidgets/src/utils/kglobalsettings.cpp tier1/solid/src/solid/backends/udisks2/udisksstorageaccess.cpp tier1/solid/src/solid/backends/upower/upoweracadapter.cpp tier1/solid/src/solid/backends/upower/upowerbattery.cpp M +1 -1 CMakeLists.txt M +7 -7 kdecore/localization/klocale.h M +1 -1 kdeui/tests/kmessagewidgettest.cpp M +1 -1 kdeui/util/kkeyserver.h M +22 -6 kdeui/widgets/kmessagewidget.cpp M +6 -1 kdeui/widgets/krichtextedit.cpp M +6 -6 kdeui/widgets/krichtextwidget.cpp M +11 -6 kdeui/widgets/ktextedit.cpp M +9 -0 kdeui/widgets/ktextedit.h M +2 -0 kdewebkit/CMakeLists.txt M +23 -10 kdewebkit/kwebwallet.cpp M +6 -0 kfile/kfileplacesitem.cpp M +2 -0 kfile/kfileplacesitem_p.h M +11 -2 kfile/kfileplacesmodel.cpp M +6 -2 kfile/kfilewidget.cpp M +7 -5 khtml/rendering/render_box.cpp M +1 -1 kimgio/xcf.cpp M +7 -1 kio/kio/kfileitem.cpp M +1 -1 kio/kio/kprotocolmanager.h M +5 -0 kio/kio/krun.cpp M +6 -0 kio/kio/krun.h M +3 -2 kio/kio/slaveinterface_p.h M +14 -0 kio/tests/jobtest.cpp M +2 -0 kioslave/ftp/ftp.cpp M +9 -3 kioslave/http/http.cpp M +4 -4 kioslave/http/http_cache_cleaner.cpp M +7 -7 kjsembed/kjsembed/qobject_binding.cpp M +5 -3 kparts/browserrun.cpp M +3 -3 kparts/browserrun.h M +1 -0 plasma/CMakeLists.txt A +26 -14 plasma/intoDeclarativeEngine/declarativewidget.cpp [Lice= nse: LGPL (v2+)] M +3 -1 plasma/plasma.h M +31 -0 plasma/runnercontext.cpp M +14 -2 plasma/runnercontext.h A +23 -0 staging/kio/src/core/global.cpp [License: LGPL (v2)] A +1 -1 staging/kservice/src/sycoca/ksycoca.cpp [License: LGPL (= v2)] A +1 -9 tier1/solid/src/solid/backends/udisks/udisksopticaldrive.cpp= [License: LGPL] R +3 -2 tier1/solid/src/solid/backends/udisks2/udisksblock.cpp R +1 -0 tier1/solid/src/solid/backends/udisks2/udisksblock.h R +19 -19 tier1/solid/src/solid/backends/udisks2/udisksdevice.cpp R +2 -0 tier1/solid/src/solid/backends/udisks2/udisksdevice.h R +5 -35 tier1/solid/src/solid/backends/udisks2/udisksmanager.cpp R +1 -0 tier1/solid/src/solid/backends/udisks2/udisksmanager.h R +1 -1 tier1/solid/src/solid/backends/udisks2/udisksopticaldrive.cpp A +53 -25 tier1/solid/src/solid/backends/udisks2/udisksstorageaccess.c= pp [License: LGPL] R +1 -1 tier1/solid/src/solid/backends/udisks2/udisksstorageaccess.h A +9 -7 tier1/solid/src/solid/backends/upower/upoweracadapter.cpp = [License: LGPL] A +37 -41 tier1/solid/src/solid/backends/upower/upowerbattery.cpp = [License: LGPL] R +2 -1 tier1/solid/src/solid/backends/upower/upowerdeviceinterface.h A +3 -3 tier1/solid/src/solid/backends/upower/upowergenericinterface= .cpp [License: LGPL] R +6 -7 tier1/solid/src/solid/networking.h R +2 -13 tier1/threadweaver/Mainpage.dox A +1 -1 tier1/threadweaver/src/Weaver/Job.h [License: LGPL (v2+)] A +3 -3 tier1/threadweaver/src/Weaver/WeaverInterface.h [License= : LGPL (v2+)] http://commits.kde.org/kdelibs/71e5e17968c934f0e761adffddf489afd8dde44b diff --cc CMakeLists.txt index 15ed359,893f00e..35310fe --- a/CMakeLists.txt +++ b/CMakeLists.txt @@@ -21,13 -9,10 +21,13 @@@ endif( ################# set KDE specific information ################# = set (KDE_VERSION_MAJOR 4) -set (KDE_VERSION_MINOR 9) -set (KDE_VERSION_RELEASE 80) +set (KDE_VERSION_MINOR 90) +set (KDE_VERSION_RELEASE 00) set (KDE_VERSION "${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}.${KDE_VERSION= _RELEASE}" ) -set (KDE_VERSION_STRING "${KDE_VERSION}") +# For git master, use this: - set (KDE_VERSION_STRING "${KDE_VERSION} (KDE Frameworks >=3D 20120113)") ++set (KDE_VERSION_STRING "${KDE_VERSION} (KDE Frameworks >=3D 20121130)") +# For a stable release, use this: +#set (KDE_VERSION_STRING "${KDE_VERSION}") = set (KDE_DISTRIBUTION_TEXT "compiled sources" CACHE STRING "Indicate the = distribution in bug reports" ) = diff --cc kdeui/widgets/ktextedit.cpp index 42a0303,dfaf5b8..71d2a9f --- a/kdeui/widgets/ktextedit.cpp +++ b/kdeui/widgets/ktextedit.cpp @@@ -1169,4 -1166,14 +1164,14 @@@ void KTextEdit::showAutoCorrectButton(b d->showAutoCorrectionButton =3D show; } = + void KTextEdit::mousePopupMenuImplementation(const QPoint& pos) + { + QMenu *popup =3D mousePopupMenu(); + if ( popup ) { + aboutToShowContextMenu(popup); + popup->exec( pos ); + delete popup; + } + } + = -#include "ktextedit.moc" +#include "moc_ktextedit.cpp" diff --cc kfile/kfileplacesmodel.cpp index 4160075,0192926..06cd069 --- a/kfile/kfileplacesmodel.cpp +++ b/kfile/kfileplacesmodel.cpp @@@ -56,8 -55,8 +57,9 @@@ #include #include #include + #include #include +#include = class KFilePlacesModel::Private { diff --cc kfile/kfilewidget.cpp index 55497d8,e755aae..c83df3a --- a/kfile/kfilewidget.cpp +++ b/kfile/kfilewidget.cpp @@@ -2611,8 -2593,12 +2611,12 @@@ QUrl KFileWidget::getStartUrl(const QUr } else // not special "kfiledialog" URL { - if (!startDir.isRelative()) // has directory, maybe with file= name - { + // We can use startDir as the starting directory if either: + // (a) it has a directory part, or + // (b) there is a scheme (protocol), and it is not just "file= ". - if (!startDir.directory().isEmpty() || ++ if (!QUrlPathInfo(startDir).directory().isEmpty() || + (!startDir.scheme().isEmpty() && !startDir.isLocalFile())) + { // can use start directory ret =3D startDir; // will be checked by stat later // If we won't be able to list it (e.g. http), then use d= efault if ( !KProtocolManager::supportsListing( ret ) ) { diff --cc kio/kio/kprotocolmanager.h index cf06c0e,d9dca11..274adab --- a/kio/kio/kprotocolmanager.h +++ b/kio/kio/kprotocolmanager.h @@@ -679,9 -678,9 +679,9 @@@ public /** * Returns the charset to use for the specified @ref url. * - * @since 5.0 + * @since 4.10 */ - static QString charsetFor(const KUrl& url); + static QString charsetFor(const QUrl& url); = private: friend class KIO::SlaveConfigPrivate; diff --cc kio/kio/slaveinterface_p.h index 30e9981,e31ec5e..3c289c6 --- a/kio/kio/slaveinterface_p.h +++ b/kio/kio/slaveinterface_p.h @@@ -20,8 -20,10 +20,10 @@@ #define KIO_SLAVEINTERFACEPRIVATE_H = #include "global.h" -#include "connection.h" +#include "connection_p.h" #include -#include ++#include + #include #include = static const unsigned int max_nums =3D 8; diff --cc kioslave/http/http.cpp index cbd6234,b7f8e8d..9d834da --- a/kioslave/http/http.cpp +++ b/kioslave/http/http.cpp @@@ -596,9 -592,9 +596,9 @@@ void HTTPProtocol::setHost( const QStri << "(" << m_request.encoded_hostname << ")"; } = -bool HTTPProtocol::maybeSetRequestUrl(const KUrl &u) +bool HTTPProtocol::maybeSetRequestUrl(const QUrl &u) { - kDebug (7113) << u; + kDebug(7113) << u; = m_request.url =3D u; m_request.url.setPort(u.port(defaultPort()) !=3D defaultPort() ? u.port= () : -1); diff --cc plasma/CMakeLists.txt index b2300fb,674550d..a95cb57 --- a/plasma/CMakeLists.txt +++ b/plasma/CMakeLists.txt @@@ -121,11 -129,20 +121,12 @@@ set(plasma_LIB_SRC private/associatedapplicationmanager.cpp private/componentinstaller.cpp private/datacontainer_p.cpp - private/dataenginebindings.cpp - private/dataengineconsumer.cpp + private/dataenginemanager.cpp private/dataengineservice.cpp - private/denyallauthorization.cpp + private/effects/halopainter.cpp + private/dialogshadows.cpp - private/effectwatcher.cpp - private/extenderapplet.cpp - private/extenderitemmimedata.cpp - private/focusindicator.cpp private/getsource.cpp - private/nativetabbar.cpp private/packages.cpp - private/pinpairingauthorization.cpp - private/pinpairingdialog.cpp private/plasmoidservice.cpp private/remotedataengine.cpp private/remoteservice.cpp diff --cc plasma/intoDeclarativeEngine/declarativewidget.cpp index 37f648e,0000000..c5fe651 mode 100644,000000..100644 --- a/plasma/intoDeclarativeEngine/declarativewidget.cpp +++ b/plasma/intoDeclarativeEngine/declarativewidget.cpp @@@ -1,326 -1,0 +1,338 @@@ +/* + * Copyright 2010 Marco Martin + * + * This program 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, 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 Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "declarativewidget.h" + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +#include "private/declarative/declarativenetworkaccessmanagerfactory_p.h" +#include "private/declarative/dataenginebindings_p.h" + +namespace Plasma +{ + +class DeclarativeWidgetPrivate +{ +public: + DeclarativeWidgetPrivate(DeclarativeWidget *parent) + : q(parent), + engine(0), + scriptEngine(0), + component(0), + root(0), + delay(false) + { + } + + ~DeclarativeWidgetPrivate() + { + } + + void errorPrint(); + void execute(const QString &fileName); + void finishExecute(); + void scheduleExecutionEnd(); + void minimumWidthChanged(); + void minimumHeightChanged(); + void maximumWidthChanged(); + void maximumHeightChanged(); + void preferredWidthChanged(); + void preferredHeightChanged(); + + + DeclarativeWidget *q; + + QString qmlPath; + QDeclarativeEngine* engine; + QScriptEngine *scriptEngine; + QDeclarativeComponent* component; + QObject *root; + bool delay : 1; +}; + +void DeclarativeWidgetPrivate::errorPrint() +{ + QString errorStr =3D "Error loading QML file.\n"; + if(component->isError()){ + QList errors =3D component->errors(); + foreach (const QDeclarativeError &error, errors) { + errorStr +=3D (error.line()>0?QString(QString::number(error.l= ine()) + QLatin1String(": ")):QLatin1String("")) + + error.description() + '\n'; + } + } + kWarning() << component->url().toString() + '\n' + errorStr; +} + +void DeclarativeWidgetPrivate::execute(const QString &fileName) +{ + if (fileName.isEmpty()) { +#ifndef NDEBUG + kDebug() << "File name empty!"; +#endif + return; + } + + KDeclarative kdeclarative; + kdeclarative.setDeclarativeEngine(engine); + kdeclarative.initialize(); + //binds things like kconfig and icons + kdeclarative.setupBindings(); + + component->loadUrl(QUrl::fromLocalFile(fileName)); + + scriptEngine =3D kdeclarative.scriptEngine(); + registerDataEngineMetaTypes(scriptEngine); + + if (delay) { + QTimer::singleShot(0, q, SLOT(scheduleExecutionEnd())); + } else { + scheduleExecutionEnd(); + } +} + +void DeclarativeWidgetPrivate::scheduleExecutionEnd() +{ + if (component->isReady() || component->isError()) { + finishExecute(); + } else { + QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComp= onent::Status)), q, SLOT(finishExecute())); + } +} + +void DeclarativeWidgetPrivate::finishExecute() +{ + if (component->isError()) { + errorPrint(); + } + + root =3D component->create(); + + if (!root) { + errorPrint(); + } + +#ifndef NDEBUG + kDebug() << "Execution of QML done!"; +#endif + QGraphicsWidget *widget =3D dynamic_cast(root); + QGraphicsObject *object =3D dynamic_cast(root); + + + if (object) { + static_cast(object)->setParentItem(q); + if (q->scene()) { + q->scene()->addItem(object); + } + } + + if (widget) { + q->setPreferredSize(-1,-1); + QGraphicsLinearLayout *lay =3D static_cast(q->layout()); + if (!lay) { + lay =3D new QGraphicsLinearLayout(q); + lay->setContentsMargins(0, 0, 0, 0); + } + lay->addItem(widget); + } else { + q->setLayout(0); + qreal minimumWidth =3D 0; + qreal minimumHeight =3D 0; + qreal maximumWidth =3D 0; + qreal maximumHeight =3D 0; + qreal preferredWidth =3D 0; + qreal preferredHeight =3D 0; + if (object) { + object->setProperty("width", q->size().width()); + object->setProperty("height", q->size().height()); + - minimumWidth =3D object->property("minimumWidth").toReal(); - minimumHeight =3D object->property("minimumHeight").toReal(); - QObject::connect(object, SIGNAL(minimumWidthChanged()), q, SL= OT(minimumWidthChanged())); - QObject::connect(object, SIGNAL(minimumHeightChanged()), q, S= LOT(minimumHeightChanged())); - = - maximumWidth =3D object->property("maximumWidth").toReal(); - maximumHeight =3D object->property("maximumHeight").toReal(); - QObject::connect(object, SIGNAL(maximumWidthChanged()), q, SL= OT(maximumWidthChanged())); - QObject::connect(object, SIGNAL(maximumHeightChanged()), q, S= LOT(maximumHeightChanged())); - = - preferredWidth =3D object->property("preferredWidth").toReal(= ); - preferredHeight =3D object->property("preferredHeight").toRea= l(); - QObject::connect(object, SIGNAL(preferredWidthChanged()), q, = SLOT(preferredWidthChanged())); - QObject::connect(object, SIGNAL(preferredHeightChanged()), q,= SLOT(preferredHeightChanged())); ++ if (object->metaObject()->indexOfProperty("minimumWidth")>=3D= 0) { ++ minimumWidth =3D object->property("minimumWidth").toReal(= ); ++ QObject::connect(object, SIGNAL(minimumWidthChanged()), q= , SLOT(minimumWidthChanged())); ++ } ++ if (object->metaObject()->indexOfProperty("minimumHeight")>= =3D0) { ++ minimumHeight =3D object->property("minimumHeight").toRea= l(); ++ QObject::connect(object, SIGNAL(minimumHeightChanged()), = q, SLOT(minimumHeightChanged())); ++ } ++ ++ if (object->metaObject()->indexOfProperty("maximumWidth")>=3D= 0) { ++ maximumWidth =3D object->property("maximumWidth").toReal(= ); ++ QObject::connect(object, SIGNAL(maximumWidthChanged()), q= , SLOT(maximumWidthChanged())); ++ } ++ if (object->metaObject()->indexOfProperty("maximumHeight")>= =3D0) { ++ maximumHeight =3D object->property("maximumHeight").toRea= l(); ++ QObject::connect(object, SIGNAL(maximumHeightChanged()), = q, SLOT(maximumHeightChanged())); ++ } ++ ++ if (object->metaObject()->indexOfProperty("preferredWidth")>= =3D0) { ++ preferredWidth =3D object->property("preferredWidth").toR= eal(); ++ QObject::connect(object, SIGNAL(preferredWidthChanged()),= q, SLOT(preferredWidthChanged())); ++ } ++ if (object->metaObject()->indexOfProperty("preferredHeight")>= =3D0) { ++ preferredHeight =3D object->property("preferredHeight").t= oReal(); ++ QObject::connect(object, SIGNAL(preferredHeightChanged())= , q, SLOT(preferredHeightChanged())); ++ } + } + + if (minimumWidth > 0 && minimumHeight > 0) { + q->setMinimumSize(minimumWidth, minimumHeight); + } else { + q->setMinimumSize(-1, -1); + } + + if (maximumWidth > 0 && maximumHeight > 0) { + q->setMaximumSize(maximumWidth, maximumHeight); + } else { + q->setMaximumSize(-1, -1); + } + + if (preferredWidth > 0 && preferredHeight > 0) { + q->setPreferredSize(preferredWidth, preferredHeight); + } else { + q->setPreferredSize(-1, -1); + } + } + emit q->finished(); +} + +void DeclarativeWidgetPrivate::minimumWidthChanged() +{ + qreal minimumWidth =3D root->property("minimumWidth").toReal(); + q->setMinimumWidth(minimumWidth); +} + +void DeclarativeWidgetPrivate::minimumHeightChanged() +{ + qreal minimumHeight =3D root->property("minimumHeight").toReal(); + q->setMinimumHeight(minimumHeight); +} + +void DeclarativeWidgetPrivate::maximumWidthChanged() +{ + qreal maximumWidth =3D root->property("maximumWidth").toReal(); + q->setMaximumWidth(maximumWidth); +} + +void DeclarativeWidgetPrivate::maximumHeightChanged() +{ + qreal maximumHeight =3D root->property("maximumHeight").toReal(); + q->setMaximumHeight(maximumHeight); +} + +void DeclarativeWidgetPrivate::preferredWidthChanged() +{ + qreal preferredWidth =3D root->property("preferredWidth").toReal(); + q->setPreferredWidth(preferredWidth); +} + +void DeclarativeWidgetPrivate::preferredHeightChanged() +{ + qreal preferredHeight =3D root->property("preferredHeight").toReal(); + q->setPreferredHeight(preferredHeight); +} + +DeclarativeWidget::DeclarativeWidget(QGraphicsWidget *parent) + : QGraphicsWidget(parent), + d(new DeclarativeWidgetPrivate(this)) +{ + setFlag(QGraphicsItem::ItemHasNoContents); + + d->engine =3D new QDeclarativeEngine(this); + d->engine->setNetworkAccessManagerFactory(new DeclarativeNetworkAcces= sManagerFactory); + + d->component =3D new QDeclarativeComponent(d->engine, this); +} + +DeclarativeWidget::~DeclarativeWidget() +{ + QDeclarativeNetworkAccessManagerFactory *factory =3D d->engine->netwo= rkAccessManagerFactory(); + d->engine->setNetworkAccessManagerFactory(0); + delete factory; + delete d; +} + +void DeclarativeWidget::setQmlPath(const QString &path) +{ + d->qmlPath =3D path; + d->execute(path); +} + +QString DeclarativeWidget::qmlPath() const +{ + return d->qmlPath; +} + +void DeclarativeWidget::setInitializationDelayed(const bool delay) +{ + d->delay =3D delay; +} + +bool DeclarativeWidget::isInitializationDelayed() const +{ + return d->delay; +} + +QDeclarativeEngine* DeclarativeWidget::engine() +{ + return d->engine; +} + +QScriptEngine *DeclarativeWidget::scriptEngine() const +{ + return d->scriptEngine; +} + +QObject *DeclarativeWidget::rootObject() const +{ + return d->root; +} + +QDeclarativeComponent *DeclarativeWidget::mainComponent() const +{ + return d->component; +} + +void DeclarativeWidget::resizeEvent(QGraphicsSceneResizeEvent *event) +{ + QGraphicsWidget::resizeEvent(event); + + if (d->root) { + d->root->setProperty("width", size().width()); + d->root->setProperty("height", size().height()); + } +} + + +} // namespace Plasma + + + + +#include "moc_declarativewidget.cpp" diff --cc staging/kio/src/core/global.cpp index 742102f,0000000..41bfb04 mode 100644,000000..100644 --- a/staging/kio/src/core/global.cpp +++ b/staging/kio/src/core/global.cpp @@@ -1,229 -1,0 +1,252 @@@ +/* This file is part of the KDE libraries + Copyright (C) 2000 David Faure + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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 Lice= nse + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "global.h" + +#include +#include +#include +#include +#include ++#include + +// If someone wants the SI-standard prefixes kB/MB/GB/TB, I would recomme= nd +// a hidden kconfig option and getting the code from #57240 into the same +// method, so that all KDE apps use the same unit, instead of letting eac= h app decide. + +KIOCORE_EXPORT QString KIO::convertSize( KIO::filesize_t size ) +{ + return KLocale::global()->formatByteSize(size); +} + +KIOCORE_EXPORT QString KIO::convertSizeFromKiB( KIO::filesize_t kibSize ) +{ + return KLocale::global()->formatByteSize(kibSize * 1024); +} + +KIOCORE_EXPORT QString KIO::number( KIO::filesize_t size ) +{ + char charbuf[256]; + sprintf(charbuf, "%lld", size); + return QLatin1String(charbuf); +} + +KIOCORE_EXPORT unsigned int KIO::calculateRemainingSeconds( KIO::filesize= _t totalSize, + KIO::filesize_t p= rocessedSize, KIO::filesize_t speed ) +{ + if ( (speed !=3D 0) && (totalSize !=3D 0) ) + return ( totalSize - processedSize ) / speed; + else + return 0; +} + +KIOCORE_EXPORT QString KIO::convertSeconds( unsigned int seconds ) +{ + unsigned int days =3D seconds / 86400; + unsigned int hours =3D (seconds - (days * 86400)) / 3600; + unsigned int mins =3D (seconds - (days * 86400) - (hours * 3600)) / 60; + seconds =3D (seconds - (days * 86400) - (hours * 3600) - (mi= ns * 60)); + + const QTime time(hours, mins, seconds); + const QString timeStr( KLocale::global()->formatTime(time, true /*with = seconds*/, true /*duration*/) ); + if ( days > 0 ) + return i18np("1 day %2", "%1 days %2", days, timeStr); + else + return timeStr; +} + +#ifndef KDE_NO_DEPRECATED +KIOCORE_EXPORT QTime KIO::calculateRemaining( KIO::filesize_t totalSize, = KIO::filesize_t processedSize, KIO::filesize_t speed ) +{ + QTime remainingTime; + + if ( speed !=3D 0 ) { + KIO::filesize_t secs; + if ( totalSize =3D=3D 0 ) { + secs =3D 0; + } else { + secs =3D ( totalSize - processedSize ) / speed; + } + if (secs >=3D (24*60*60)) // Limit to 23:59:59 + secs =3D (24*60*60)-1; + int hr =3D secs / ( 60 * 60 ); + int mn =3D ( secs - hr * 60 * 60 ) / 60; + int sc =3D ( secs - hr * 60 * 60 - mn * 60 ); + + remainingTime.setHMS( hr, mn, sc ); + } + + return remainingTime; +} +#endif + +KIOCORE_EXPORT QString KIO::itemsSummaryString(uint items, uint files, ui= nt dirs, KIO::filesize_t size, bool showSize) +{ + if ( files =3D=3D 0 && dirs =3D=3D 0 && items =3D=3D 0 ) { + return i18np( "%1 Item", "%1 Items", 0 ); + } + + QString summary; + const QString foldersText =3D i18np( "1 Folder", "%1 Folders", dirs ); + const QString filesText =3D i18np( "1 File", "%1 Files", files ); + if ( files > 0 && dirs > 0 ) { + summary =3D showSize ? + i18nc( "folders, files (size)", "%1, %2 (%3)", foldersT= ext, filesText, KIO::convertSize( size ) ) : + i18nc( "folders, files", "%1, %2", foldersText, filesTe= xt ); + } else if ( files > 0 ) { + summary =3D showSize ? i18nc( "files (size)", "%1 (%2)", filesTex= t, KIO::convertSize( size ) ) : filesText; + } else if ( dirs > 0 ) { + summary =3D foldersText; + } + + if ( items > dirs + files ) { + const QString itemsText =3D i18np( "%1 Item", "%1 Items", items ); + summary =3D summary.isEmpty() ? itemsText : i18nc( "items: folder= s, files (size)", "%1: %2", itemsText, summary ); + } + + return summary; +} + +KIOCORE_EXPORT QString KIO::encodeFileName( const QString & _str ) +{ + QString str( _str ); + str.replace('/', QChar(0x2044)); // "Fraction slash" + return str; +} + +KIOCORE_EXPORT QString KIO::decodeFileName( const QString & _str ) +{ + // Nothing to decode. "Fraction slash" is fine in filenames. + return _str; +} + +/*************************************************************** + * + * Utility functions + * + ***************************************************************/ + +KIO::CacheControl KIO::parseCacheControl(const QString &cacheControl) +{ + QString tmp =3D cacheControl.toLower(); + + if (tmp =3D=3D "cacheonly") + return KIO::CC_CacheOnly; + if (tmp =3D=3D "cache") + return KIO::CC_Cache; + if (tmp =3D=3D "verify") + return KIO::CC_Verify; + if (tmp =3D=3D "refresh") + return KIO::CC_Refresh; + if (tmp =3D=3D "reload") + return KIO::CC_Reload; + + qDebug() << "unrecognized Cache control option:"< iconNameCache; ++ static int autoClearCache =3D 0; ++ const QString notFound =3D QLatin1String("NOTFOUND"); ++ + if (url.isLocalFile() + || !url.scheme().startsWith(QLatin1String("http")) + || !useFavIcons()) + return QString(); + ++ QString iconNameFromCache =3D iconNameCache.value(url, notFound); ++ if (iconNameFromCache !=3D notFound) { ++ if ((++autoClearCache) < 5000) { ++ return iconNameFromCache; ++ } else { ++ iconNameCache.clear(); ++ autoClearCache =3D 0; ++ } ++ } ++ + QDBusInterface kded( QString::fromLatin1("org.kde.kded5"), + QString::fromLatin1("/modules/favicons"), + QString::fromLatin1("org.kde.FavIcon") ); + QDBusReply result =3D kded.call( QString::fromLatin1("iconFo= rUrl"), url.toString() ); ++ iconNameCache.insert(url, result.value()); + return result; // default is QString() +} + +QString KIO::iconNameForUrl(const QUrl& url) +{ + QMimeDatabase db; + const QMimeType mt =3D db.mimeTypeForUrl(url); + const QLatin1String unknown("unknown"); + const QString mimeTypeIcon =3D mt.iconName(); + QString i =3D mimeTypeIcon; + + // if we don't find an icon, maybe we can use the one for the protocol + if (i =3D=3D unknown || i.isEmpty() || mt.isDefault() + // and for the root of the protocol (e.g. trash:/) the protocol i= con has priority over the mimetype icon + || url.path().length() <=3D 1) + { + i =3D favIconForUrl(url); // maybe there is a favicon? + + if (i.isEmpty()) + i =3D KProtocolInfo::icon(url.scheme()); + + // root of protocol: if we found nothing, revert to mimeTypeIcon = (which is usually "folder") + if (url.path().length() <=3D 1 && (i =3D=3D unknown || i.isEmpty(= ))) + i =3D mimeTypeIcon; + } + return !i.isEmpty() ? i : unknown; +} diff --cc staging/kservice/src/sycoca/ksycoca.cpp index ea5df3f,0000000..b75e2ce mode 100644,000000..100644 --- a/staging/kservice/src/sycoca/ksycoca.cpp +++ b/staging/kservice/src/sycoca/ksycoca.cpp @@@ -1,626 -1,0 +1,626 @@@ +/* This file is part of the KDE libraries + * Copyright (C) 1999-2000 Waldo Bastian + * Copyright (C) 2005-2009 David Faure + * Copyright (C) 2008 Hamish Rodda + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation; + * + * 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 Lic= ense + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "ksycoca.h" +#include "ksycoca_p.h" +#include "ksycocatype.h" +#include "ksycocafactory.h" +#include "kmemfile_p.h" +#include "kconfiggroup.h" +#include "ksharedconfig.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ksycocadevices_p.h" + +// TODO: remove mmap() from kdewin32 and use QFile::mmap() when needed +#ifdef Q_OS_WIN +#undef HAVE_MMAP +#endif +/** + * Sycoca file version number. + * If the existing file is outdated, it will not get read + * but instead we'll ask kded to regenerate a new one... + */ - #define KSYCOCA_VERSION 209 ++#define KSYCOCA_VERSION 210 + +/** + * Sycoca file name, used internally (by kbuildsycoca) + */ +#define KSYCOCA_FILENAME "ksycoca5" + +#if HAVE_MADVISE || HAVE_MMAP +#include // This #include was checked when looking for posix= _madvise +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *) -1) +#endif + +static bool s_autoRebuild =3D true; + +// The following limitations are in place: +// Maximum length of a single string: 8192 bytes +// Maximum length of a string list: 1024 strings +// Maximum number of entries: 8192 +// +// The purpose of these limitations is to limit the impact +// of database corruption. + + +Q_DECLARE_OPERATORS_FOR_FLAGS(KSycocaPrivate::BehaviorsIfNotFound) + +KSycocaPrivate::KSycocaPrivate() + : databaseStatus( DatabaseNotOpen ), + readError( false ), + timeStamp( 0 ), + m_databasePath(), + updateSig( 0 ), + sycoca_size(0), + sycoca_mmap(0), + m_mmapFile(0), + m_device(0) +{ +#ifdef Q_OS_WIN + /* + on windows we use KMemFile (QSharedMemory) to avoid problems + with mmap (can't delete a mmap'd file) + */ + m_sycocaStrategy =3D StrategyMemFile; +#else + m_sycocaStrategy =3D StrategyMmap; +#endif + KConfigGroup config(KSharedConfig::openConfig(), "KSycoca"); + setStrategyFromString(config.readEntry("strategy")); +} + +void KSycocaPrivate::setStrategyFromString(const QString& strategy) { + if (strategy =3D=3D QLatin1String("mmap")) + m_sycocaStrategy =3D StrategyMmap; + else if (strategy =3D=3D QLatin1String("file")) + m_sycocaStrategy =3D StrategyFile; + else if (strategy =3D=3D QLatin1String("sharedmem")) + m_sycocaStrategy =3D StrategyMemFile; + else if (!strategy.isEmpty()) + qWarning() << "Unknown sycoca strategy:" << strategy; +} + +bool KSycocaPrivate::tryMmap() +{ +#if HAVE_MMAP + Q_ASSERT(!m_databasePath.isEmpty()); + m_mmapFile =3D new QFile(m_databasePath); + const bool canRead =3D m_mmapFile->open(QIODevice::ReadOnly); + Q_ASSERT(canRead); + if (!canRead) + return false; + fcntl(m_mmapFile->handle(), F_SETFD, FD_CLOEXEC); + sycoca_size =3D m_mmapFile->size(); + sycoca_mmap =3D (const char *) mmap(0, sycoca_size, + PROT_READ, MAP_SHARED, + m_mmapFile->handle(), 0); + /* POSIX mandates only MAP_FAILED, but we are paranoid so check for + null pointer too. */ + if (sycoca_mmap =3D=3D (const char*) MAP_FAILED || sycoca_mmap =3D=3D= 0) { + qDebug().nospace() << "mmap failed. (length =3D " << sycoca_size = << ")"; + sycoca_mmap =3D 0; + return false; + } else { +#if HAVE_MADVISE + (void) posix_madvise((void*)sycoca_mmap, sycoca_size, POSIX_MADV_= WILLNEED); +#endif // HAVE_MADVISE + return true; + } +#endif // HAVE_MMAP + return false; +} + +int KSycoca::version() +{ + return KSYCOCA_VERSION; +} + +class KSycocaSingleton +{ +public: + KSycocaSingleton() { } + ~KSycocaSingleton() { } + + bool hasSycoca() const { + return m_threadSycocas.hasLocalData(); + } + KSycoca* sycoca() { + if (!m_threadSycocas.hasLocalData()) + m_threadSycocas.setLocalData(new KSycoca); + return m_threadSycocas.localData(); + } + void setSycoca(KSycoca* s) { + m_threadSycocas.setLocalData(s); + } + +private: + QThreadStorage m_threadSycocas; +}; + +Q_GLOBAL_STATIC(KSycocaSingleton, ksycocaInstance) + +// Read-only constructor +KSycoca::KSycoca() + : d(new KSycocaPrivate) +{ + QDBusConnection::sessionBus().connect(QString(), QString(), + QString::fromLatin1("org.kde.KS= ycoca"), + QString::fromLatin1("notifyData= baseChanged"), + this, SLOT(notifyDatabaseChange= d(QStringList))); +} + +bool KSycocaPrivate::openDatabase(bool openDummyIfNotFound) +{ + Q_ASSERT(databaseStatus =3D=3D DatabaseNotOpen); + + delete m_device; m_device =3D 0; + QString path =3D KSycoca::absoluteFilePath(); + + bool canRead =3D QFileInfo(path).isReadable(); + qDebug() << "Trying to open ksycoca from" << path; + if (!canRead) { + path =3D KSycoca::absoluteFilePath(KSycoca::GlobalDatabase); + if (!path.isEmpty()) { + qDebug() << "Trying to open global ksycoca from " << path; + canRead =3D QFileInfo(path).isReadable(); + } + } + + bool result =3D true; + if (canRead) { + m_databasePath =3D path; + checkVersion(); + } else { // No database file + //qDebug() << "Could not open ksycoca"; + m_databasePath.clear(); + databaseStatus =3D NoDatabase; + if (openDummyIfNotFound) { + // We open a dummy database instead. + //qDebug() << "No database, opening a dummy one."; + + m_sycocaStrategy =3D StrategyDummyBuffer; + QDataStream* str =3D stream(); + *str << qint32(KSYCOCA_VERSION); + *str << qint32(0); + } else { + result =3D false; + } + } + return result; +} + +KSycocaAbstractDevice* KSycocaPrivate::device() +{ + if (m_device) + return m_device; + + Q_ASSERT(!m_databasePath.isEmpty()); + + KSycocaAbstractDevice* device =3D m_device; + if (m_sycocaStrategy =3D=3D StrategyDummyBuffer) { + device =3D new KSycocaBufferDevice; + device->device()->open(QIODevice::ReadOnly); // can't fail + } else { +#if HAVE_MMAP + if (m_sycocaStrategy =3D=3D StrategyMmap && tryMmap()) { + device =3D new KSycocaMmapDevice(sycoca_mmap, + sycoca_size); + if (!device->device()->open(QIODevice::ReadOnly)) { + delete device; device =3D 0; + } + } +#endif +#ifndef QT_NO_SHAREDMEMORY + if (!device && m_sycocaStrategy =3D=3D StrategyMemFile) { + device =3D new KSycocaMemFileDevice(m_databasePath); + if (!device->device()->open(QIODevice::ReadOnly)) { + delete device; device =3D 0; + } + } +#endif + if (!device) { + device =3D new KSycocaFileDevice(m_databasePath); + if (!device->device()->open(QIODevice::ReadOnly)) { + qWarning() << "Couldn't open" << m_databasePath << "even = though it is readable? Impossible."; + //delete device; device =3D 0; // this would crash in the= return statement... + } + } + } + if (device) { + m_device =3D device; + } + return m_device; +} + +QDataStream*& KSycocaPrivate::stream() +{ + if (!m_device) { + if (databaseStatus =3D=3D DatabaseNotOpen) { + checkDatabase(KSycocaPrivate::IfNotFoundRecreate | KSycocaPri= vate::IfNotFoundOpenDummy); + } + + device(); // create m_device + } + + return m_device->stream(); +} + +// Read-write constructor - only for KBuildSycoca +KSycoca::KSycoca( bool /* dummy */ ) + : d(new KSycocaPrivate) +{ + // This instance was not created by the singleton, but by a direct ca= ll to new! + ksycocaInstance()->setSycoca(this); +} + +KSycoca * KSycoca::self() +{ + KSycoca* s =3D ksycocaInstance()->sycoca(); + Q_ASSERT(s); + return s; +} + +KSycoca::~KSycoca() +{ + d->closeDatabase(); + delete d; + //if (ksycocaInstance.exists() + // && ksycocaInstance->self =3D=3D this) + // ksycocaInstance->self =3D 0; +} + +bool KSycoca::isAvailable() +{ + return self()->d->checkDatabase(KSycocaPrivate::IfNotFoundDoNothing/*= don't open dummy db if not found */); +} + +void KSycocaPrivate::closeDatabase() +{ + delete m_device; + m_device =3D 0; + + // It is very important to delete all factories here + // since they cache information about the database file + // But other threads might be using them, so this class is + // refcounted, and deleted when the last thread is done with them + qDeleteAll(m_factories); + m_factories.clear(); +#if HAVE_MMAP + if (sycoca_mmap) { + //QBuffer *buf =3D static_cast(device); + //buf->buffer().clear(); + // Solaris has munmap(char*, size_t) and everything else should + // be happy with a char* for munmap(void*, size_t) + munmap(const_cast(sycoca_mmap), sycoca_size); + sycoca_mmap =3D 0; + } + delete m_mmapFile; m_mmapFile =3D 0; +#endif + + databaseStatus =3D DatabaseNotOpen; + timeStamp =3D 0; +} + +void KSycoca::addFactory( KSycocaFactory *factory ) +{ + d->addFactory(factory); +} + +#ifndef KDE_NO_DEPRECATED +bool KSycoca::isChanged(const char *type) +{ + return self()->d->changeList.contains(QString::fromLatin1(type)); +} +#endif + +void KSycoca::notifyDatabaseChanged(const QStringList &changeList) +{ + d->changeList =3D changeList; + //qDebug() << QThread::currentThread() << "got a notifyDatabaseChange= d signal" << changeList; + // kbuildsycoca tells us the database file changed + // Close the database and forget all about what we knew + // The next call to any public method will recreate + // everything that's needed. + d->closeDatabase(); + + // Now notify applications +#ifndef KDE_NO_DEPRECATED + emit databaseChanged(); +#endif + emit databaseChanged(changeList); +} + +QDataStream * KSycoca::findEntry(int offset, KSycocaType &type) +{ + QDataStream* str =3D stream(); + Q_ASSERT(str); + //qDebug() << QString("KSycoca::_findEntry(offset=3D%1)").arg(offset,8= ,16); + str->device()->seek(offset); + qint32 aType; + *str >> aType; + type =3D KSycocaType(aType); + //qDebug() << QString("KSycoca::found type %1").arg(aType); + return str; +} + +KSycocaFactoryList* KSycoca::factories() +{ + return d->factories(); +} + +// Warning, checkVersion rewinds to the beginning of stream(). +bool KSycocaPrivate::checkVersion() +{ + QDataStream *m_str =3D device()->stream(); + Q_ASSERT(m_str); + m_str->device()->seek(0); + qint32 aVersion; + *m_str >> aVersion; + if ( aVersion < KSYCOCA_VERSION ) { + qDebug() << "Found version" << aVersion << ", expecting version" = << KSYCOCA_VERSION << "or higher."; + databaseStatus =3D BadVersion; + return false; + } else { + databaseStatus =3D DatabaseOK; + return true; + } +} + +// If it returns true, we have a valid database and the stream has rewind= ed to the beginning +// and past the version number. +bool KSycocaPrivate::checkDatabase(BehaviorsIfNotFound ifNotFound) +{ + if (databaseStatus =3D=3D DatabaseOK) { + if (checkVersion()) // we know the version is ok, but we must rew= ind the stream anyway + return true; + } + + closeDatabase(); // close the dummy one + + // We can only use the installed ksycoca file if kded is running, + // since kded is what keeps the file uptodate. + QDBusConnectionInterface* bus =3D QDBusConnection::sessionBus().inter= face(); + const bool kdedRunning =3D bus->isServiceRegistered(QString::fromLati= n1("org.kde.kded5")) || + qAppName() =3D=3D "kbuildsycoca5"; + + // Check if new database already available + if (kdedRunning && openDatabase(ifNotFound & IfNotFoundOpenDummy)) { + if (checkVersion()) { + // Database exists, and version is ok. + return true; + } + } + + if (ifNotFound & IfNotFoundRecreate) { + // Ask kded to rebuild ksycoca + // (so that it's not only built, but also kept up-to-date...) + bool justStarted =3D false; + if (!bus->isServiceRegistered(QLatin1String("org.kde.kded5"))) { + // kded isn't even running: start it + QDBusReply reply =3D bus->startService(QLatin1String("o= rg.kde.kded5")); + if (!reply.isValid()) { + qWarning() << "Couldn't start kded5 from org.kde.kded5.se= rvice:" << reply.error(); + } + //qDebug() << "kded5 registered"; + justStarted =3D true; + } else { + //qDebug() << "kded5 found"; + } + + QDBusInterface sycoca(QLatin1String("org.kde.kded5"), QLatin1Stri= ng("/kbuildsycoca")); +#if QT_VERSION >=3D QT_VERSION_CHECK(5, 0, 0) + if (QStandardPaths::isTestModeEnabled()) { + if (!justStarted) { + const QDBusReply testMode =3D sycoca.call(QLatin1St= ring("isTestModeEnabled")); + if (!testMode.value()) { + qWarning() << "This unit test uses ksycoca, it needs = to be run in a separate DBus session, so that kded can be started in 'test = mode'."; + qWarning() << "KSycoca updates will very likely fail = unless you do that."; + qWarning() << "`eval dbus-launch` ; make test"; + // Idea for the future: move kbuildsycoca stuff to it= s own kded module, and use + // the same module with a different name, for test mo= de. + // On the other hand, the use of other kded modules (= cookies, timezone, etc.) + // is also better separated from the user's kded anyw= ay. + } + } + sycoca.call(QLatin1String("enableTestMode")); + Q_ASSERT(QDBusReply(sycoca.call(QLatin1String("isTestMo= deEnabled"))).value()); + } +#else + Q_UNUSED(justStarted); +#endif + + //qDebug() << "We have no database.... asking kded to create it"; + sycoca.call(QLatin1String("recreate")); + + closeDatabase(); // close the dummy one + + // Ok, the new database should be here now, open it. + if (!openDatabase(ifNotFound & IfNotFoundOpenDummy)) { + qDebug() << "Still no database..."; + return false; // Still no database - uh oh + } + if (!checkVersion()) { + qDebug() << "Still outdated..."; + return false; // Still outdated - uh oh + } + return true; + } + + return false; +} + +QDataStream * KSycoca::findFactory(KSycocaFactoryId id) +{ + // Ensure we have a valid database (right version, and rewinded to be= ginning) + if (!d->checkDatabase(KSycocaPrivate::IfNotFoundRecreate)) { + return 0; + } + + QDataStream* str =3D stream(); + Q_ASSERT(str); + + qint32 aId; + qint32 aOffset; + while(true) { + *str >> aId; + if (aId =3D=3D 0) { + qWarning() << "Error, KSycocaFactory (id =3D" << int(id) << "= ) not found!"; + break; + } + *str >> aOffset; + if (aId =3D=3D id) { + //qDebug() << "KSycoca::findFactory(" << id << ") offset " <<= aOffset; + str->device()->seek(aOffset); + return str; + } + } + return 0; +} + +QString KSycoca::kfsstnd_prefixes() +{ + // do not try to launch kbuildsycoca from here; this code is also cal= led by kbuildsycoca. + if (!d->checkDatabase(KSycocaPrivate::IfNotFoundDoNothing)) + return QString(); + QDataStream* str =3D stream(); + Q_ASSERT(str); + qint32 aId; + qint32 aOffset; + // skip factories offsets + while(true) + { + *str >> aId; + if ( aId ) + *str >> aOffset; + else + break; // just read 0 + } + // We now point to the header + QString prefixes; + KSycocaEntry::read(*str, prefixes); + *str >> d->timeStamp; + KSycocaEntry::read(*str, d->language); + *str >> d->updateSig; + KSycocaEntry::read(*str, d->allResourceDirs); + return prefixes; +} + +quint32 KSycoca::timeStamp() +{ + if (!d->timeStamp) + (void) kfsstnd_prefixes(); + return d->timeStamp; +} + +quint32 KSycoca::updateSignature() +{ + if (!d->timeStamp) + (void) kfsstnd_prefixes(); + return d->updateSig; +} + +QString KSycoca::absoluteFilePath(DatabaseType type) +{ + if (type =3D=3D GlobalDatabase) { + QString path =3D QStandardPaths::locate(QStandardPaths::GenericDa= taLocation, QString::fromLatin1("kde5/services/" KSYCOCA_FILENAME)); + if (path.isEmpty()) + return QStandardPaths::writableLocation(QStandardPaths::Gener= icDataLocation) + QString::fromLatin1("/kde5/services/" KSYCOCA_FILENAME); + return path; + } + + const QByteArray ksycoca_env =3D qgetenv("KDESYCOCA"); + if (ksycoca_env.isEmpty()) { + return QStandardPaths::writableLocation(QStandardPaths::GenericCa= cheLocation) + QLatin1Char('/') + QString::fromLatin1(KSYCOCA_FILENAME); + } else { + return QFile::decodeName(ksycoca_env); + } +} + +QString KSycoca::language() +{ + if (d->language.isEmpty()) + (void) kfsstnd_prefixes(); + return d->language; +} + +QStringList KSycoca::allResourceDirs() +{ + if (!d->timeStamp) + (void) kfsstnd_prefixes(); + return d->allResourceDirs; +} + +void KSycoca::flagError() +{ + qWarning() << "ERROR: KSycoca database corruption!"; + KSycocaPrivate* d =3D ksycocaInstance()->sycoca()->d; + if (d->readError) + return; + d->readError =3D true; + if (s_autoRebuild) { + // Rebuild the damned thing. + if (QProcess::execute(QStandardPaths::findExecutable(QString::fro= mLatin1(KBUILDSYCOCA_EXENAME))) !=3D 0) + qWarning("ERROR: Running %s failed", KBUILDSYCOCA_EXENAME); + // Old comment, maybe not true anymore: + // Do not wait until the DBUS signal from kbuildsycoca here. + // It deletes m_str which is a problem when flagError is called d= uring the KSycocaFactory ctor... + } +} + +bool KSycoca::isBuilding() +{ + return false; +} + +void KSycoca::disableAutoRebuild() +{ + s_autoRebuild =3D false; +} + +QDataStream*& KSycoca::stream() +{ + return d->stream(); +} + +void KSycoca::clearCaches() +{ +#if QT_VERSION >=3D QT_VERSION_CHECK(5,1,0) + if (ksycocaInstance.exists() && ksycocaInstance()->hasSycoca()) +#else + if (ksycocaInstance() && ksycocaInstance()->hasSycoca()) +#endif + ksycocaInstance()->sycoca()->d->closeDatabase(); +} + +#include "ksycoca.moc" diff --cc tier1/solid/src/solid/backends/udisks/udisksopticaldrive.cpp index 1acaddd,0000000..d3e2f93 mode 100644,000000..100644 --- a/tier1/solid/src/solid/backends/udisks/udisksopticaldrive.cpp +++ b/tier1/solid/src/solid/backends/udisks/udisksopticaldrive.cpp @@@ -1,197 -1,0 +1,189 @@@ +/* + Copyright 2010 Michael Zanetti + Copyright 2010-2011 Lukas Tinkl + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "udisksopticaldrive.h" +#include "udisks.h" +#include "udisksdevice.h" + +using namespace Solid::Backends::UDisks; + +UDisksOpticalDrive::UDisksOpticalDrive(UDisksDevice *device) + : UDisksStorageDrive(device), m_ejectInProgress(false), m_readSpeed(0= ), m_writeSpeed(0), m_speedsInit(false) +{ + m_device->registerAction("eject", this, + SLOT(slotEjectRequested()), + SLOT(slotEjectDone(int,QString))); + + connect(m_device, SIGNAL(changed()), this, SLOT(slotChanged())); +} + +UDisksOpticalDrive::~UDisksOpticalDrive() +{ + +} + +bool UDisksOpticalDrive::eject() +{ + if (m_ejectInProgress) + return false; + m_ejectInProgress =3D true; + m_device->broadcastActionRequested("eject"); + + QDBusConnection c =3D QDBusConnection::systemBus(); + + QString path =3D m_device->udi(); + - // check if the device is mounted and call umount if needed - if (m_device->prop("DeviceIsMounted").toBool()) - { - QDBusMessage msg =3D QDBusMessage::createMethodCall(UD_DBUS_SERVI= CE, path, UD_DBUS_INTERFACE_DISKS_DEVICE, "FilesystemUnmount"); - msg << QStringList(); // options, unused now - c.call(msg, QDBus::NoBlock); - } - = + QDBusMessage msg =3D QDBusMessage::createMethodCall(UD_DBUS_SERVICE, = path, UD_DBUS_INTERFACE_DISKS_DEVICE, "DriveEject"); - msg << QStringList(); ++ msg << "unmount"; // unmount parameter + return c.callWithCallback(msg, this, SLOT(slotDBusReply(QDBusMessage)= ), SLOT(slotDBusError(QDBusError))); +} + +void UDisksOpticalDrive::slotDBusReply(const QDBusMessage &/*reply*/) +{ + m_ejectInProgress =3D false; + m_device->broadcastActionDone("eject"); +} + +void UDisksOpticalDrive::slotDBusError(const QDBusError &error) +{ + m_ejectInProgress =3D false; + m_device->broadcastActionDone("eject", m_device->errorToSolidError(er= ror.name()), + m_device->errorToString(error.name()) += ": " +error.message()); +} + +void UDisksOpticalDrive::slotEjectRequested() +{ + m_ejectInProgress =3D true; + Q_EMIT ejectRequested(m_device->udi()); +} + +void UDisksOpticalDrive::slotEjectDone(int error, const QString &errorStr= ing) +{ + m_ejectInProgress =3D false; + Q_EMIT ejectDone(static_cast(error), errorString, m= _device->udi()); +} + +void UDisksOpticalDrive::initReadWriteSpeeds() const +{ +#if 0 + int read_speed, write_speed; + char *write_speeds =3D 0; + QByteArray device_file =3D QFile::encodeName(m_device->property("Devi= ceFile").toString()); + + //qDebug("Doing open (\"%s\", O_RDONLY | O_NONBLOCK)", device_file.co= nstData()); + int fd =3D open(device_file, O_RDONLY | O_NONBLOCK); + if (fd < 0) { + qWarning("Cannot open %s: %s", device_file.constData(), strerror = (errno)); + return; + } + + if (get_read_write_speed(fd, &read_speed, &write_speed, &write_speeds= ) >=3D 0) { + m_readSpeed =3D read_speed; + m_writeSpeed =3D write_speed; + + QStringList list =3D QString::fromLatin1(write_speeds).split(',',= QString::SkipEmptyParts); + Q_FOREACH (const QString & speed, list) + m_writeSpeeds.append(speed.toInt()); + + free(write_speeds); + + m_speedsInit =3D true; + } + + close(fd); +#endif +} + +QList UDisksOpticalDrive::writeSpeeds() const +{ + if (!m_speedsInit) + initReadWriteSpeeds(); + //qDebug() << "solid write speeds:" << m_writeSpeeds; + return m_writeSpeeds; +} + +int UDisksOpticalDrive::writeSpeed() const +{ + if (!m_speedsInit) + initReadWriteSpeeds(); + return m_writeSpeed; +} + +int UDisksOpticalDrive::readSpeed() const +{ + if (!m_speedsInit) + initReadWriteSpeeds(); + return m_readSpeed; +} + +Solid::OpticalDrive::MediumTypes UDisksOpticalDrive::supportedMedia() con= st +{ + const QStringList mediaTypes =3D m_device->prop("DriveMediaCompatibil= ity").toStringList(); + Solid::OpticalDrive::MediumTypes supported; + + QMap map; + map[Solid::OpticalDrive::Cdr] =3D "optical_cd_r"; + map[Solid::OpticalDrive::Cdrw] =3D "optical_cd_rw"; + map[Solid::OpticalDrive::Dvd] =3D "optical_dvd"; + map[Solid::OpticalDrive::Dvdr] =3D "optical_dvd_r"; + map[Solid::OpticalDrive::Dvdrw] =3D"optical_dvd_rw"; + map[Solid::OpticalDrive::Dvdram] =3D"optical_dvd_ram"; + map[Solid::OpticalDrive::Dvdplusr] =3D"optical_dvd_plus_r"; + map[Solid::OpticalDrive::Dvdplusrw] =3D"optical_dvd_plus_rw"; + map[Solid::OpticalDrive::Dvdplusdl] =3D"optical_dvd_plus_r_dl"; + map[Solid::OpticalDrive::Dvdplusdlrw] =3D"optical_dvd_plus_rw_dl"; + map[Solid::OpticalDrive::Bd] =3D"optical_bd"; + map[Solid::OpticalDrive::Bdr] =3D"optical_bd_r"; + map[Solid::OpticalDrive::Bdre] =3D"optical_bd_re"; + map[Solid::OpticalDrive::HdDvd] =3D"optical_hddvd"; + map[Solid::OpticalDrive::HdDvdr] =3D"optical_hddvd_r"; + map[Solid::OpticalDrive::HdDvdrw] =3D"optical_hddvd_rw"; + // TODO add these to Solid + //map[Solid::OpticalDrive::Mo] =3D"optical_mo"; + //map[Solid::OpticalDrive::Mr] =3D"optical_mrw"; + //map[Solid::OpticalDrive::Mrw] =3D"optical_mrw_w"; + + Q_FOREACH ( const Solid::OpticalDrive::MediumType & type, map.keys() ) + { + if ( mediaTypes.contains( map[type] ) ) + { + supported |=3D type; + } + } + + return supported; +} + +void UDisksOpticalDrive::slotChanged() +{ + m_speedsInit =3D false; // reset the read/write speeds, changes eg. w= ith an inserted media +} diff --cc tier1/solid/src/solid/backends/udisks2/udisksstorageaccess.cpp index df63aa6,0000000..537c1a7 mode 100644,000000..100644 --- a/tier1/solid/src/solid/backends/udisks2/udisksstorageaccess.cpp +++ b/tier1/solid/src/solid/backends/udisks2/udisksstorageaccess.cpp @@@ -1,362 -1,0 +1,390 @@@ +/* + Copyright 2009 Pino Toscano + Copyright 2009-2012 Luk=C3=A1=C5=A1 Tinkl + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include "udisksstorageaccess.h" +#include "udisks2.h" + - #include ++#include +#include +#include +#include + +using namespace Solid::Backends::UDisks2; + +StorageAccess::StorageAccess(Device *device) + : DeviceInterface(device), m_setupInProgress(false), m_teardownInProg= ress(false), m_passphraseRequested(false) +{ + connect(device, SIGNAL(changed()), this, SLOT(checkAccessibility())); + updateCache(); + + // Delay connecting to DBus signals to avoid the related time penalty + // in hot paths such as predicate matching + QTimer::singleShot(0, this, SLOT(connectDBusSignals())); +} + +StorageAccess::~StorageAccess() +{ +} + +void StorageAccess::connectDBusSignals() +{ + m_device->registerAction("setup", this, + SLOT(slotSetupRequested()), + SLOT(slotSetupDone(int, const QString&))); + + m_device->registerAction("teardown", this, + SLOT(slotTeardownRequested()), + SLOT(slotTeardownDone(int, const QString&))); +} + +bool StorageAccess::isLuksDevice() const +{ + return m_device->isEncryptedContainer(); // encrypted device +} + +bool StorageAccess::isAccessible() const +{ + if (isLuksDevice()) { // check if the cleartext slave is mounted - if (m_clearTextPath.isEmpty() || m_clearTextPath =3D=3D "/") ++ const QString path =3D clearTextPath(); ++ //qDebug() << Q_FUNC_INFO << "CLEARTEXT device path: " << path; ++ if (path.isEmpty() || path =3D=3D "/") + return false; - Device holderDevice(m_clearTextPath); ++ Device holderDevice(path); + return holderDevice.isMounted(); + } + + return m_device->isMounted(); +} + +QString StorageAccess::filePath() const +{ - if (!isAccessible()) - return QString(); - = + QByteArrayList mntPoints; + + if (isLuksDevice()) { // encrypted (and unlocked) device - if (m_clearTextPath.isEmpty() || m_clearTextPath =3D=3D "/") ++ const QString path =3D clearTextPath(); ++ if (path.isEmpty() || path =3D=3D "/") + return QString(); - Device holderDevice(m_clearTextPath); ++ Device holderDevice(path); + mntPoints =3D qdbus_cast(holderDevice.prop("Mount= Points")); + if (!mntPoints.isEmpty()) + return QFile::decodeName(mntPoints.first()); // FIXME Solid d= oesn't support multiple mount points + else + return QString(); + } + + mntPoints =3D qdbus_cast(m_device->prop("MountPoints"= )); + + if (!mntPoints.isEmpty()) + return QFile::decodeName(mntPoints.first()); // FIXME Solid doesn= 't support multiple mount points + else + return QString(); +} + +bool StorageAccess::isIgnored() const +{ - return m_device->prop("HintIgnore").toBool(); // FIXME tune ++ return m_device->prop("HintIgnore").toBool(); +} + +bool StorageAccess::setup() +{ + if ( m_teardownInProgress || m_setupInProgress ) + return false; + m_setupInProgress =3D true; + m_device->broadcastActionRequested("setup"); + - if (m_device->isEncryptedContainer()) ++ if (m_device->isEncryptedContainer() && clearTextPath().isEmpty()) + return requestPassphrase(); + else + return mount(); +} + +bool StorageAccess::teardown() +{ + if ( m_teardownInProgress || m_setupInProgress ) + return false; + m_teardownInProgress =3D true; + m_device->broadcastActionRequested("teardown"); + + return unmount(); +} + +void StorageAccess::updateCache() +{ + m_isAccessible =3D isAccessible(); +} + +void StorageAccess::checkAccessibility() +{ + const bool old_isAccessible =3D m_isAccessible; + updateCache(); + + if (old_isAccessible !=3D m_isAccessible) { - Q_EMIT accessibilityChanged(m_isAccessible, isLuksDevice() ? m_cl= earTextPath : m_device->udi()); ++ Q_EMIT accessibilityChanged(m_isAccessible, m_device->udi()); + } +} + - void StorageAccess::slotDBusReply( const QDBusMessage & reply ) ++void StorageAccess::slotDBusReply( const QDBusMessage & /*reply*/ ) +{ ++ const QString ctPath =3D clearTextPath(); + if (m_setupInProgress) + { + if (isLuksDevice() && !isAccessible()) { // unlocked device, now = mount it - if (reply.type() =3D=3D QDBusMessage::ReplyMessage) // we've= got a response from Unlock - m_clearTextPath =3D reply.arguments().value(0).value().path(); + mount(); + } + else // Don't broadcast setupDone unless the setup is really done= . (Fix kde#271156) + { + m_setupInProgress =3D false; + m_device->broadcastActionDone("setup"); + + checkAccessibility(); + } + } + else if (m_teardownInProgress) // FIXME + { - if (isLuksDevice() && !m_clearTextPath.isEmpty() && m_clearTextPa= th !=3D "/") // unlocked device, lock it ++ if (isLuksDevice() && !ctPath.isEmpty() && ctPath !=3D "/") // un= locked device, lock it + { + callCryptoTeardown(); + } - else if (!m_clearTextPath.isEmpty() && m_clearTextPath !=3D "/") { ++ else if (!ctPath.isEmpty() && ctPath !=3D "/") { + callCryptoTeardown(true); // Lock crypted parent + } + else + { + // try to "eject" (aka safely remove) from the (parent) drive= , e.g. SD card from a reader - QString drivePath =3D m_device->prop("Drive").value().path(); ++ QString drivePath =3D m_device->drivePath(); + if (!drivePath.isEmpty() || drivePath !=3D "/") + { + Device drive(drivePath); + if (drive.prop("Ejectable").toBool() && + drive.prop("MediaAvailable").toBool() && + !m_device->isOpticalDisc()) // optical drives hav= e their Eject method + { + QDBusConnection c =3D QDBusConnection::systemBus(); + QDBusMessage msg =3D QDBusMessage::createMethodCall(U= D2_DBUS_SERVICE, drivePath, UD2_DBUS_INTERFACE_DRIVE, "Eject"); + msg << QVariantMap(); // options, unused now + c.call(msg, QDBus::NoBlock); + } + } + + m_teardownInProgress =3D false; + m_device->broadcastActionDone("teardown"); + + checkAccessibility(); + } + } +} + +void StorageAccess::slotDBusError( const QDBusError & error ) +{ ++ //qDebug() << Q_FUNC_INFO << "DBUS ERROR:" << error.name() << error.m= essage(); ++ + if (m_setupInProgress) + { + m_setupInProgress =3D false; + m_device->broadcastActionDone("setup", m_device->errorToSolidErro= r(error.name()), + m_device->errorToString(error.name(= )) + ": " +error.message()); + + checkAccessibility(); + } + else if (m_teardownInProgress) + { + m_teardownInProgress =3D false; - m_clearTextPath.clear(); + m_device->broadcastActionDone("teardown", m_device->errorToSolidE= rror(error.name()), + m_device->errorToString(error.name(= )) + ": " + error.message()); + checkAccessibility(); + } +} + +void StorageAccess::slotSetupRequested() +{ + m_setupInProgress =3D true; + //qDebug() << "SETUP REQUESTED:" << m_device->udi(); + Q_EMIT setupRequested(m_device->udi()); +} + +void StorageAccess::slotSetupDone(int error, const QString &errorString) +{ + m_setupInProgress =3D false; + //qDebug() << "SETUP DONE:" << m_device->udi(); + Q_EMIT setupDone(static_cast(error), errorString, m= _device->udi()); + + checkAccessibility(); +} + +void StorageAccess::slotTeardownRequested() +{ + m_teardownInProgress =3D true; + Q_EMIT teardownRequested(m_device->udi()); +} + +void StorageAccess::slotTeardownDone(int error, const QString &errorStrin= g) +{ + m_teardownInProgress =3D false; - m_clearTextPath.clear(); + Q_EMIT teardownDone(static_cast(error), errorString= , m_device->udi()); + + checkAccessibility(); +} + +bool StorageAccess::mount() +{ + QString path =3D m_device->udi(); ++ const QString ctPath =3D clearTextPath(); + - if (isLuksDevice()) { // mount options for the cleartext volume - path =3D m_clearTextPath; ++ if (isLuksDevice() && !ctPath.isEmpty()) { // mount options for the c= leartext volume ++ path =3D ctPath; + } + + QDBusConnection c =3D QDBusConnection::systemBus(); + QDBusMessage msg =3D QDBusMessage::createMethodCall(UD2_DBUS_SERVICE,= path, UD2_DBUS_INTERFACE_FILESYSTEM, "Mount"); + QVariantMap options; + + if (m_device->prop("IdType").toString() =3D=3D "vfat") + options.insert("options", "flush"); + + msg << options; + + return c.callWithCallback(msg, this, + SLOT(slotDBusReply(const QDBusMessage &)), + SLOT(slotDBusError(const QDBusError &))); +} + +bool StorageAccess::unmount() +{ + QString path =3D m_device->udi(); ++ const QString ctPath =3D clearTextPath(); + - if (isLuksDevice()) { // unmount options for the cleartext volume - path =3D m_clearTextPath; ++ if (isLuksDevice() && !ctPath.isEmpty()) { // unmount options for the= cleartext volume ++ path =3D ctPath; + } + + QDBusConnection c =3D QDBusConnection::systemBus(); + QDBusMessage msg =3D QDBusMessage::createMethodCall(UD2_DBUS_SERVICE,= path, UD2_DBUS_INTERFACE_FILESYSTEM, "Unmount"); + + msg << QVariantMap(); // options, unused now + + return c.callWithCallback(msg, this, + SLOT(slotDBusReply(const QDBusMessage &)), + SLOT(slotDBusError(const QDBusError &)), + s_unmountTimeout); +} + +QString StorageAccess::generateReturnObjectPath() +{ + static int number =3D 1; + + return "/org/kde/solid/UDisks2StorageAccess_"+QString::number(number+= +); +} + ++QString StorageAccess::clearTextPath() const ++{ ++ const QString prefix =3D "/org/freedesktop/UDisks2/block_devices"; ++ QDBusMessage call =3D QDBusMessage::createMethodCall(UD2_DBUS_SERVICE= , prefix, ++ DBUS_INTERFACE_INT= ROSPECT, "Introspect"); ++ QDBusPendingReply reply =3D QDBusConnection::systemBus().asy= ncCall(call); ++ reply.waitForFinished(); ++ ++ if (reply.isValid()) { ++ QDomDocument dom; ++ dom.setContent(reply.value()); ++ QDomNodeList nodeList =3D dom.documentElement().elementsByTagName= ("node"); ++ for (int i =3D 0; i < nodeList.count(); i++) { ++ QDomElement nodeElem =3D nodeList.item(i).toElement(); ++ if (!nodeElem.isNull() && nodeElem.hasAttribute("name")) { ++ const QString udi =3D prefix + "/" + nodeElem.attribute("= name"); ++ Device holderDevice(udi); ++ ++ if (m_device->udi() =3D=3D holderDevice.prop("CryptoBacki= ngDevice").value().path()) { ++ //qDebug() << Q_FUNC_INFO << "CLEARTEXT device path: = " << udi; ++ return udi; ++ } ++ } ++ } ++ } ++ ++ return QString(); ++} ++ +bool StorageAccess::requestPassphrase() +{ + QString udi =3D m_device->udi(); + QString returnService =3D QDBusConnection::sessionBus().baseService(); + m_lastReturnObject =3D generateReturnObjectPath(); + + QDBusConnection::sessionBus().registerObject(m_lastReturnObject, this= , QDBusConnection::ExportScriptableSlots); + + QWidget *activeWindow =3D QApplication::activeWindow(); + uint wId =3D 0; + if (activeWindow!=3D0) + wId =3D (uint)activeWindow->winId(); + + QString appId =3D QCoreApplication::applicationName(); + + QDBusInterface soliduiserver("org.kde.kded5", "/modules/soliduiserver= ", "org.kde.SolidUiServer"); + QDBusReply reply =3D soliduiserver.call("showPassphraseDialog",= udi, returnService, + m_lastReturnObject, wId, = appId); + m_passphraseRequested =3D reply.isValid(); + if (!m_passphraseRequested) + qWarning() << "Failed to call the SolidUiServer, D-Bus said:" << = reply.error(); + + return m_passphraseRequested; +} + +void StorageAccess::passphraseReply(const QString & passphrase) +{ + if (m_passphraseRequested) + { + QDBusConnection::sessionBus().unregisterObject(m_lastReturnObject= ); + m_passphraseRequested =3D false; + if (!passphrase.isEmpty()) + callCryptoSetup(passphrase); + else + { + m_setupInProgress =3D false; + m_device->broadcastActionDone("setup"); + } + } +} + +void StorageAccess::callCryptoSetup(const QString & passphrase) +{ + QDBusConnection c =3D QDBusConnection::systemBus(); + QDBusMessage msg =3D QDBusMessage::createMethodCall(UD2_DBUS_SERVICE,= m_device->udi(), UD2_DBUS_INTERFACE_ENCRYPTED, "Unlock"); + + msg << passphrase; + msg << QVariantMap(); // options, unused now + + c.callWithCallback(msg, this, + SLOT(slotDBusReply(const QDBusMessage &)), + SLOT(slotDBusError(const QDBusError &))); +} + +bool StorageAccess::callCryptoTeardown(bool actOnParent) +{ + QDBusConnection c =3D QDBusConnection::systemBus(); + QDBusMessage msg =3D QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, + actOnParent ? (m_de= vice->prop("CryptoBackingDevice").value().path()) : m_devi= ce->udi(), + UD2_DBUS_INTERFACE_= ENCRYPTED, "Lock"); + msg << QVariantMap(); // options, unused now + - m_clearTextPath.clear(); - = + return c.callWithCallback(msg, this, + SLOT(slotDBusReply(const QDBusMessage &)), + SLOT(slotDBusError(const QDBusError &))); +} diff --cc tier1/solid/src/solid/backends/upower/upoweracadapter.cpp index f21606e,0000000..19e8987 mode 100644,000000..100644 --- a/tier1/solid/src/solid/backends/upower/upoweracadapter.cpp +++ b/tier1/solid/src/solid/backends/upower/upoweracadapter.cpp @@@ -1,58 -1,0 +1,60 @@@ +/* + Copyright 2009 Pino Toscano + Copyright 2010 Lukas Tinkl + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include "upoweracadapter.h" + +using namespace Solid::Backends::UPower; + +AcAdapter::AcAdapter(UPowerDevice *device) + : DeviceInterface(device) +{ + connect(device, SIGNAL(changed()), this, SLOT(slotChanged())); + + updateCache(); +} + +AcAdapter::~AcAdapter() +{ +} + +bool AcAdapter::isPlugged() const +{ - return m_device->prop("Online").toBool(); ++ return m_device.data()->prop("Online").toBool(); +} + +void AcAdapter::slotChanged() +{ - const bool old_isPlugged =3D m_isPlugged; - updateCache(); - = - if (old_isPlugged !=3D m_isPlugged) - { - Q_EMIT plugStateChanged(m_isPlugged, m_device->udi()); ++ if (m_device) { ++ const bool old_isPlugged =3D m_isPlugged; ++ updateCache(); ++ ++ if (old_isPlugged !=3D m_isPlugged) ++ { ++ Q_EMIT plugStateChanged(m_isPlugged, m_device.data()->udi()); ++ } + } +} + +void AcAdapter::updateCache() +{ + m_isPlugged =3D isPlugged(); +} + diff --cc tier1/solid/src/solid/backends/upower/upowerbattery.cpp index 6e2ef6c,0000000..3d5819a mode 100644,000000..100644 --- a/tier1/solid/src/solid/backends/upower/upowerbattery.cpp +++ b/tier1/solid/src/solid/backends/upower/upowerbattery.cpp @@@ -1,198 -1,0 +1,194 @@@ +/* + Copyright 2009 Pino Toscano + Copyright 2010, 2012 Lukas Tinkl + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include "upowerbattery.h" + +using namespace Solid::Backends::UPower; + +Battery::Battery(UPowerDevice *device) + : DeviceInterface(device) +{ + connect(device, SIGNAL(changed()), this, SLOT(slotChanged())); + + updateCache(); +} + +Battery::~Battery() +{ +} + +bool Battery::isPlugged() const +{ - return m_device->prop("IsPresent").toBool(); ++ return m_device.data()->prop("IsPresent").toBool(); +} + +Solid::Battery::BatteryType Battery::type() const +{ + Solid::Battery::BatteryType result =3D Solid::Battery::UnknownBattery; - const uint t =3D m_device->prop("Type").toUInt(); ++ const uint t =3D m_device.data()->prop("Type").toUInt(); + switch (t) + { + case 1: // TODO "Line Power" + break; + case 2: + result =3D Solid::Battery::PrimaryBattery; + break; + case 3: + result =3D Solid::Battery::UpsBattery; + break; + case 4: + result =3D Solid::Battery::MonitorBattery; + break; + case 5: + result =3D Solid::Battery::MouseBattery; + break; + case 6: + result =3D Solid::Battery::KeyboardBattery; + break; + case 7: + result =3D Solid::Battery::PdaBattery; + break; + case 8: + result =3D Solid::Battery::PhoneBattery; + break; + } + return result; +} + +int Battery::chargePercent() const +{ - return qRound(m_device->prop("Percentage").toDouble()); ++ return qRound(m_device.data()->prop("Percentage").toDouble()); +} + +int Battery::capacity() const +{ - return qRound(m_device->prop("Capacity").toDouble()); ++ return qRound(m_device.data()->prop("Capacity").toDouble()); +} + +bool Battery::isRechargeable() const +{ - return m_device->prop("IsRechargeable").toBool(); ++ return m_device.data()->prop("IsRechargeable").toBool(); +} + +Solid::Battery::ChargeState Battery::chargeState() const +{ + Solid::Battery::ChargeState result =3D Solid::Battery::NoCharge; - const uint state =3D m_device->prop("State").toUInt(); ++ const uint state =3D m_device.data()->prop("State").toUInt(); + switch (state) + { + case 0: + result =3D Solid::Battery::NoCharge; // stable or unknown + break; + case 1: + result =3D Solid::Battery::Charging; + break; + case 2: + result =3D Solid::Battery::Discharging; + break; + case 3: // TODO "Empty" + break; + case 4: // TODO "Fully charged" + break; + case 5: // TODO "Pending charge" + break; + case 6: // TODO "Pending discharge" + break; + } + return result; +} + +Solid::Battery::Technology Battery::technology() const +{ - const uint tech =3D m_device->prop("Technology").toUInt(); ++ const uint tech =3D m_device.data()->prop("Technology").toUInt(); + switch (tech) + { + case 1: + return Solid::Battery::LithiumIon; + case 2: + return Solid::Battery::LithiumPolymer; + case 3: + return Solid::Battery::LithiumIronPhosphate; + case 4: + return Solid::Battery::LeadAcid; + case 5: + return Solid::Battery::NickelCadmium; + case 6: + return Solid::Battery::NickelMetalHydride; + default: + return Solid::Battery::UnknownTechnology; + } +} + +double Battery::energy() const +{ - return m_device->prop("Energy").toDouble(); ++ return m_device.data()->prop("Energy").toDouble(); +} + +double Battery::energyRate() const +{ - return m_device->prop("EnergyRate").toDouble(); ++ return m_device.data()->prop("EnergyRate").toDouble(); +} + +double Battery::voltage() const +{ - return m_device->prop("Voltage").toDouble(); ++ return m_device.data()->prop("Voltage").toDouble(); +} + +void Battery::slotChanged() +{ - if (!m_device) - return; - = - const bool old_isPlugged =3D m_isPlugged; - const int old_chargePercent =3D m_chargePercent; - const Solid::Battery::ChargeState old_chargeState =3D m_chargeState; - const double old_energy =3D m_energy; - const double old_energyRate =3D m_energyRate; - updateCache(); - = - if (old_chargePercent !=3D m_chargePercent) - { - Q_EMIT chargePercentChanged(m_chargePercent, m_device->udi()); - } - = - if (old_chargeState !=3D m_chargeState) - { - Q_EMIT chargeStateChanged(m_chargeState, m_device->udi()); - } - = - if (old_isPlugged !=3D m_isPlugged) - { - Q_EMIT plugStateChanged(m_isPlugged, m_device->udi()); - } - = - if (old_energy !=3D m_energy) { - Q_EMIT energyChanged(m_energy, m_device->udi()); - } - = - if (old_energyRate !=3D m_energyRate) { - Q_EMIT energyRateChanged(m_energyRate, m_device->udi()); ++ if (m_device) { ++ const bool old_isPlugged =3D m_isPlugged; ++ const int old_chargePercent =3D m_chargePercent; ++ const Solid::Battery::ChargeState old_chargeState =3D m_chargeSta= te; ++ const double old_energy =3D m_energy; ++ const double old_energyRate =3D m_energyRate; ++ updateCache(); ++ ++ if (old_chargePercent !=3D m_chargePercent) { ++ Q_EMIT chargePercentChanged(m_chargePercent, m_device.data()-= >udi()); ++ } ++ ++ if (old_chargeState !=3D m_chargeState) { ++ Q_EMIT chargeStateChanged(m_chargeState, m_device.data()->udi= ()); ++ } ++ ++ if (old_isPlugged !=3D m_isPlugged) { ++ Q_EMIT plugStateChanged(m_isPlugged, m_device.data()->udi()); ++ } ++ ++ if (old_energy !=3D m_energy) { ++ Q_EMIT energyChanged(m_energy, m_device.data()->udi()); ++ } ++ ++ if (old_energyRate !=3D m_energyRate) { ++ Q_EMIT energyRateChanged(m_energyRate, m_device.data()->udi()= ); ++ } + } +} + +void Battery::updateCache() +{ + m_isPlugged =3D isPlugged(); + m_chargePercent =3D chargePercent(); + m_chargeState =3D chargeState(); + m_energy =3D energy(); + m_energyRate =3D energyRate(); +} diff --cc tier1/solid/src/solid/backends/upower/upowergenericinterface.cpp index 3a2e944,0000000..97cd10b mode 100644,000000..100644 --- a/tier1/solid/src/solid/backends/upower/upowergenericinterface.cpp +++ b/tier1/solid/src/solid/backends/upower/upowergenericinterface.cpp @@@ -1,50 -1,0 +1,50 @@@ +/* + Copyright 2009 Pino Toscano + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include "upowergenericinterface.h" + +#include "upowerdevice.h" + +using namespace Solid::Backends::UPower; + +GenericInterface::GenericInterface(UPowerDevice *device) + : DeviceInterface(device) +{ +} + +GenericInterface::~GenericInterface() +{ +} + +QVariant GenericInterface::property(const QString &key) const +{ - return m_device->prop(key); ++ return m_device.data()->prop(key); +} + +QMap GenericInterface::allProperties() const +{ - return m_device->allProperties(); ++ return m_device.data()->allProperties(); +} + +bool GenericInterface::propertyExists(const QString &key) const +{ - return m_device->propertyExists(key); ++ return m_device.data()->propertyExists(key); +} + diff --cc tier1/threadweaver/src/Weaver/Job.h index 5729942,0000000..af78557 mode 100644,000000..100644 --- a/tier1/threadweaver/src/Weaver/Job.h +++ b/tier1/threadweaver/src/Weaver/Job.h @@@ -1,240 -1,0 +1,240 @@@ +/* -*- C++ -*- + +This file declares the Job class. + +$ Author: Mirko Boehm $ +$ Copyright: (C) 2004, 2005, 2006 Mirko Boehm $ +$ Contact: mirko@kde.org +http://www.kde.org +http://www.hackerbuero.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 Lice= nse + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +$Id: Job.h 32 2005-08-17 08:38:01Z mirko $ +*/ + +#ifndef THREADWEAVER_JOB_H +#define THREADWEAVER_JOB_H + +#include + +#include + +class QMutex; +class QWaitCondition; + +namespace ThreadWeaver { + + class Thread; + class QueuePolicy; + class JobRunHelper; + class WeaverInterface; + class QueuePolicyList; + + /** A Job is a simple abstraction of an action that is to be + executed in a thread context. + It is essential for the ThreadWeaver library that as a kind of + convention, the different creators of Job objects do not touch the + protected data members of the Job until somehow notified by the + Job. + + Also, please note that Jobs may not be executed twice. Create two + different objects to perform two consecutive or parallel runs. + + Jobs may declare dependencies. If Job B depends on Job A, B may not be + executed before A is finished. To learn about dependencies, see + DependencyPolicy. + + Job objects finish by emitting the done(Job*) signal. Once this has bee= n emitted, + ThreadWeaver is no longer using the Job which may then be deleted. + */ + + class THREADWEAVER_EXPORT Job : public QObject + { + Q_OBJECT + + public: + friend class JobRunHelper; + + /** Construct a Job. + + @param parent the parent QObject + */ + explicit Job ( QObject* parent =3D 0 ); + + /** Destructor. */ + virtual ~Job(); + + /** Perform the job. The thread in which this job is executed + is given as a parameter. + Do not overload this method to create your own Job + implementation, overload run(). */ + virtual void execute(Thread*); + + /** The queueing priority of the job. + Jobs will be sorted by their queueing priority when + enqueued. A higher queueing priority will place the job in + front of all lower-priority jobs in the queue. + + Note: A higher or lower priority does not influence queue + policies. For example, a high-priority job that has an + unresolved dependency will not be executed, which means an + available lower-priority job will take precedence. + + The default implementation returns zero. Only if this method + is overloaded for some job classes, priorities will + influence the execution order of jobs. + */ + virtual int priority() const; + + /** Return whether the Job finished successfully or not. + The default implementation simply returns true. Overload in + derived classes if the derived Job class can fail. + + If a job fails (success() returns false), it will *NOT* resol= ve + its dependencies when it finishes. This will make sure that J= obs + that depend on the failed job will not be started. + + There is an important gotcha: When a Job object is deleted, it + will always resolve its dependencies. If dependent jobs should + not be executed after a failure, it is important to dequeue t= hose + before deleting the failed Job. + + A JobSequence may be helpful for that purpose. + */ + virtual bool success () const; + + /** Abort the execution of the job. + Call this method to ask the Job to abort if it is currently e= xecuted. + Please note that the default implementation of the method does + nothing (!). This is due to the fact that there is no generic + method to abort a processing Job. Not even a default boolean = flag + makes sense, as Job could, for example, be in an event loop a= nd + will need to create an exit event. + You have to reimplement the method to actually initiate an ab= ort + action. + The method is not pure virtual because users are not supposed= to + be forced to always implement requestAbort(). - Also, this method is supposed to return immidiately, not afte= r the ++ Also, this method is supposed to return immediately, not afte= r the + abort has completed. It requests the abort, the Job has to ac= t on + the request. */ + // FIXME (Mirko) this should be private, I guess? + virtual void requestAbort () {} + + /** The job is about to be added to the weaver's job queue. + The job will be added right after this method finished. The + default implementation does nothing. + Use this method to, for example, queue sub-operations as jobs + before the job itself is queued. + + Note: When this method is called, the associated Weaver objec= t's + thread holds a lock on the weaver's queue. Therefore, it is s= ave + to assume that recursive queueing is atomic from the queues + perspective. + + @param weaver the Weaver object the job will be queued in + */ + virtual void aboutToBeQueued ( WeaverInterface *weaver ); + + /** This Job is about the be dequeued from the weaver's job queue. + The job will be removed from the queue right after this method + returns. + Use this method to dequeue, if necessary, sub-operations (jo= bs) that this job + has enqueued. + + Note: When this method is called, the associated Weaver objec= t's + thread does hold a lock on the weaver's queue. + + Note: The default implementation does nothing. + + @param weaver the Weaver object from which the job will be de= queued + */ + virtual void aboutToBeDequeued ( WeaverInterface *weaver ); + + /** canBeExecuted() returns true if all the jobs queue policies a= gree to it. + If it returns true, it expects that the job is executed right + after that. The done() methods of the queue policies will be + automatically called when the job is finished. + + If it returns false, all queue policy resources have been fre= ed, + and the method can be called again at a later time. + */ + virtual bool canBeExecuted(); + + /** Returns true if the jobs's execute method finished. */ + bool isFinished() const; + + /** Assign a queue policy. + Queue Policies customize the queueing (running) behaviour of = sets + of jobs. Examples for queue policies are dependencies and res= ource + restrictions. + Every queue policy object can only be assigned once to a job, + multiple assignments will be IGNORED. + */ + void assignQueuePolicy ( QueuePolicy* ); + + /** Remove a queue policy from this job. + */ + void removeQueuePolicy ( QueuePolicy* ); + + Q_SIGNALS: + /** This signal is emitted when this job is being processed by a + thread. */ + void started ( ThreadWeaver::Job* ); + /** = + * This signal is emitted when the job has been finished (no matter if i= t succeeded or not). + * After this signal has been emitted, ThreadWeaver no longer references= the Job internally + * and the Job can be deleted. + */ + void done ( ThreadWeaver::Job* ); + + /** This job has failed. + This signal is emitted when success() returns false after the= job + is executed. + */ + void failed( ThreadWeaver::Job* ); + + protected: + class Private; + Private* d; + + /** Free the queue policies acquired before this job has been + executed. */ + void freeQueuePolicyResources(); + + /** The method that actually performs the job. It is called from + execute(). This method is the one to overload it with the + job's task. */ + virtual void run () =3D 0; + /** Return the thread that executes this job. + Returns zero of the job is not currently executed. + + Do not confuse with QObject::thread() const ! + // @todo rename to executingThread() + */ + Thread *thread(); + + /** Call with status =3D true to mark this job as done. */ + void setFinished ( bool status ); + + /** The mutex used to protect this job. */ + // QMutex& mutex(); + + }; +} + +#endif // THREADWEAVER_JOB_H + diff --cc tier1/threadweaver/src/Weaver/WeaverInterface.h index d79f7f1,0000000..0ed66ac mode 100644,000000..100644 --- a/tier1/threadweaver/src/Weaver/WeaverInterface.h +++ b/tier1/threadweaver/src/Weaver/WeaverInterface.h @@@ -1,193 -1,0 +1,193 @@@ +/* -*- C++ -*- + + This file declares the WeaverInterface class. + + $ Author: Mirko Boehm $ + $ Copyright: (C) 2005, 2006 Mirko Boehm $ + $ Contact: mirko@kde.org + http://www.kde.org + http://www.hackerbuero.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 Lice= nse + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + $Id: WeaverImpl.h 29 2005-08-14 19:04:30Z mirko $ +*/ + +#ifndef WeaverInterface_H +#define WeaverInterface_H + +#include + +#include + +namespace ThreadWeaver { + + class Job; + class State; + class WeaverObserver; + + /** WeaverInterface provides a common interface for weaver implementa= tions. + + In most cases, it is sufficient for an application to hold exactl= y one + ThreadWeaver job queue. To execute jobs in a specific order, use = job + dependencies. To limit the number of jobs of a certain type that = can + be executed at the same time, use resource restrictions. To handle + special requirements of the application when it comes to the orde= r of + execution of jobs, implement a special queue policy and apply it = to + the jobs. + + Users of the ThreadWeaver API are encouraged to program to this + interface, instead of the implementation. This way, implementation + changes will not affect user programs. + + This interface can be used for example to implement adapters and + decorators. The member documentation is provided in the Weaver and + WeaverImpl classes. + */ + + class THREADWEAVER_EXPORT WeaverInterface : public QObject { + Q_OBJECT + + public: + /** A ThreadWeaver object manages a queue of Jobs. + It inherits QObject. + */ + explicit WeaverInterface ( QObject* parent =3D 0 ); + virtual ~WeaverInterface() {} + /** Return the state of the weaver object. */ + virtual const State& state() const =3D 0; + + /** Set the maximum number of threads this Weaver object may start.= */ + virtual void setMaximumNumberOfThreads( int cap ) =3D 0; + + /** Get the maximum number of threads this Weaver may start. */ + virtual int maximumNumberOfThreads() const =3D 0; + + /** Returns the current number of threads in the inventory. */ + virtual int currentNumberOfThreads () const =3D 0; + + /** Register an observer. + + Observers provides signals on different weaver events that are + otherwise only available through objects of different classes + (threads, jobs). Usually, access to the signals of those obje= cts + is not provided through the weaver API. Use an observer to re= veice + notice, for example, on thread activity. + + To unregister, simply delete the observer. + */ + virtual void registerObserver ( WeaverObserver* ) =3D 0; + /** Add a job to be executed. + + It depends on the state if execution of the job will be attem= pted - immidiately. In suspended state, jobs can be added to the que= ue, ++ immediately. In suspended state, jobs can be added to the que= ue, + but the threads remain suspended. In WorkongHard state, an id= le - thread may immidiately execute the job, or it might be queued= if ++ thread may immediately execute the job, or it might be queued= if + all threads are busy. + */ + virtual void enqueue ( Job* ) =3D 0; + /** Remove a job from the queue. + If the job was queued but not started so far, it is simply + removed from the queue. For now, it is unsupported to + dequeue a job once its execution has started. + For that case, you will have to provide a method to interrupt your + job's execution (and receive the done signal). + Returns true if the job has been dequeued, false if the + job has already been started or is not found in the + queue. */ + virtual bool dequeue ( Job* ) =3D 0; + /** Remove all queued jobs. + Please note that this will not kill the threads, therefore + all jobs that are being processed will be continued. */ + virtual void dequeue () =3D 0; + /** Finish all queued operations, then return. + + This method is used in imperative (not event driven) programs that + cannot react on events to have the controlling (main) thread wait + wait for the jobs to finish. The call will block the calling + thread and return when all queued jobs have been processed. + + Warning: This will suspend your thread! + Warning: If one of your jobs enters an infinite loop, this + will never return! */ + virtual void finish () =3D 0; + /** Suspend job execution. + When suspending, all threads are allowed to finish the + currently assigned job but will not receive a new + assignment. + When all threads are done processing the assigned job, the + signal suspended will() be emitted. + If you call suspend() and there are no jobs left to - be done, you will immidiately receive the suspended() ++ be done, you will immediately receive the suspended() + signal. */ + virtual void suspend () =3D 0; + /** Resume job queueing. + @see suspend + */ + virtual void resume () =3D 0; + /** Is the queue empty? + The queue is empty if no more jobs are queued. */ + virtual bool isEmpty () const =3D 0; + /** Is the weaver idle? + The weaver is idle if no jobs are queued and no jobs are processed + by the threads. */ + virtual bool isIdle () const =3D 0; + /** Returns the number of pending jobs. + This will return the number of queued jobs. Jobs that are + currently being executed are not part of the queue. All jobs in + the queue are waiting to be executed. + */ + virtual int queueLength () const =3D 0; + + /** Request aborts of the currently executed jobs. + It is important to understand that aborts are requested, but + cannot be guaranteed, as not all Job classes support it. It is up + to the application to decide if and how job aborts are + necessary. */ + virtual void requestAbort() =3D 0; + + Q_SIGNALS: + /** This signal is emitted when the Weaver has finished ALL currently + queued jobs. + If a number of jobs is enqueued sequentially, this signal might be + emitted a couple of times (what happens is that all already queued + jobs have been processed while you still add new ones). This is + not a bug, but the intended behaviour. */ + void finished (); + + /** Thread queueing has been suspended. + When suspend is called with state =3D true, all threads are + allowed to finish their job. When the last thread + finished, this signal is emitted. */ + void suspended (); + + /** This signal is emitted when a job is finished. In addition, + the Job itself emits a done() signal just before the jobDone() signal + is emitted. = + */ + + void jobDone ( ThreadWeaver::Job* ); + // FIXME (0.7) test if signal is emitted properly + // FIXME (0.7) provide jobStarted and jobFailed signals + // FIXME (0.7) or remove all these, and add them to WeaverObserver + + /** The Weaver's state has changed. */ + void stateChanged ( ThreadWeaver::State* ); + }; + +} + +#endif