[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kdelibs/frameworks] /: Merge remote-tracking branch 'origin/master' into frameworks
From:       David Faure <faure+bluesystems () kde ! org>
Date:       2013-03-23 15:27:40
Message-ID: 20130323152740.D398BA604F () git ! kde ! org
[Download RAW message or body]

Git commit 465381c3e322ed15038e0d54f2cb0597ab9938df by David Faure.
Committed on 23/03/2013 at 16:13.
Pushed by dfaure into branch 'frameworks'.

Merge remote-tracking branch 'origin/master' into frameworks

Conflicts:
	kio/kio/accessmanagerreply_p.cpp [qDebug]
	knewstuff/knewstuff3/uploaddialog.cpp [QDialog, moved ported code...]
	solid/solid/backends/udisks2/udisksdevicebackend.cpp [moved by hand to tier1]
	solid/solid/backends/udisks2/udisksdevicebackend.h [moved by hand to tier1]
	tier1/solid/src/solid/CMakeLists.txt [hupnp detection, quite different...]

M  +14   -0    khtml/imload/decoders/gifloader.cpp
M  +1    -2    khtml/java/kjavaappletwidget.cpp
M  +4    -1    khtml/khtml_part.cpp
M  +2    -1    kimgio/eps.cpp
M  +2    -2    kio/kio/accessmanagerreply_p.cpp
M  +1    -1    kio/kio/kfileitemactions.cpp
M  +2    -1    kio/kssl/ksslcertificate.cpp
M  +42   -0    kio/tests/kdirlistertest.cpp
M  +1    -0    kio/tests/kdirlistertest.h
M  +11   -0    knewstuff/knewstuff3/upload/atticahelper.cpp
M  +53   -44   knewstuff/knewstuff3/uploaddialog.cpp
M  +1    -1    knewstuff/knewstuff3/uploaddialog_p.h
A  +8    -0    tier1/kcoreaddons/src/io/kdirwatch.cpp     [License: LGPL (v2)]
A  +24   -12   tier1/solid/src/solid/CMakeLists.txt
A  +5    -4    tier1/solid/src/solid/backends/udev/udevaudiointerface.cpp     \
[License: LGPL] A  +1    -3    tier1/solid/src/solid/backends/udev/udevmanager.cpp    \
[License: LGPL] A  +4    -8    tier1/solid/src/solid/backends/udisks/udisksdevice.cpp \
[License: LGPL] R  +2    -0    tier1/solid/src/solid/backends/udisks/udisksdevice.h
A  +239  -0    tier1/solid/src/solid/backends/udisks2/udisksdevicebackend.cpp     \
[License: LGPL] A  +84   -0    \
tier1/solid/src/solid/backends/udisks2/udisksdevicebackend.h     [License: LGPL] R  \
+25   -0    tier1/solid/src/solid/backends/udisks2/udisksmanager.cpp R  +1    -0    \
tier1/solid/src/solid/backends/udisks2/udisksmanager.h A  +11   -1    \
tier2/kconfig/autotests/kconfig_compiler/CMakeLists.txt R  +22   -0    \
tier2/kconfig/autotests/kconfig_compiler/test12.cpp.ref R  +35   -0    \
tier2/kconfig/autotests/kconfig_compiler/test12.h.ref R  +10   -0    \
tier2/kconfig/autotests/kconfig_compiler/test12.kcfg R  +1    -0    \
tier2/kconfig/autotests/kconfig_compiler/test12.kcfgc R  +30   -0    \
tier2/kconfig/autotests/kconfig_compiler/test12main.cpp A  +5    -1    \
tier2/kconfig/src/kconfig_compiler/kconfig_compiler.cpp     [License: GENERATED FILE] \
*

The files marked with a * at the end have a non valid license. Please read: \
http://techbase.kde.org/Policies/Licensing_Policy and use the headers which are \
listed at that page.


http://commits.kde.org/kdelibs/465381c3e322ed15038e0d54f2cb0597ab9938df

diff --cc kio/tests/kdirlistertest.cpp
index b0bb86f,a0b296d..946338d
--- a/kio/tests/kdirlistertest.cpp
+++ b/kio/tests/kdirlistertest.cpp
@@@ -1062,11 -1052,52 +1062,53 @@@ void KDirListerTest::testWatchingAfterC
      }
      QCOMPARE(m_items.count(), 1);
  
 -    newDir.unlink();
 -    QVERIFY(QTest::kWaitForSignal(&m_dirLister, SIGNAL(clear()), 1000));
 +    newDir.remove();
 +    QSignalSpy clearSpy(&m_dirLister, SIGNAL(clear()));
 +    QVERIFY(clearSpy.wait(1000));
  }
  
+ void KDirListerTest::testRemoveWatchedDirectory()
+ {
+     m_items.clear();
+ 
+     KTempDir newDir;
+     const QString path = newDir.name();
+ 
+     // List and watch an empty dir
+     connect(&m_dirLister, SIGNAL(newItems(KFileItemList)), this, \
SLOT(slotNewItems(KFileItemList))); +     m_dirLister.openUrl(KUrl(path));
+     QVERIFY(QTest::kWaitForSignal(&m_dirLister, SIGNAL(completed()), 1000));
+     QVERIFY(m_dirLister.isFinished());
+     QVERIFY(m_items.isEmpty());
+ 
+     // Create a subfolder.
+     const QString subDirPath = path + "abc";
+     QVERIFY(QDir().mkdir(subDirPath));
+ 
+     QVERIFY(QTest::kWaitForSignal(&m_dirLister, SIGNAL(completed()), 1000));
+     QVERIFY(m_dirLister.isFinished());
+     QCOMPARE(m_items.count(), 1);
+     const KFileItem item = m_items.at(0);
+ 
+     // Watch the subfolder for changes, independently.
+     // This is what triggers the bug.
+     // (Technically, this could become a KDirWatch unittest, but if one day we use \
QFSW, good to have the tests here) +     KDirWatch watcher;
+     watcher.addDir(subDirPath);
+ 
+     // Remove the subfolder.
+     m_items.clear();
+     QVERIFY(QDir().rmdir(path + "abc"));
+ 
+     // This should trigger an update.
+     QVERIFY(QTest::kWaitForSignal(&m_dirLister, SIGNAL(completed()), 1000));
+     QVERIFY(m_dirLister.isFinished());
+     QCOMPARE(m_items.count(), 0);
+     QCOMPARE(m_dirLister.spyItemsDeleted.count(), 1);
+     const KFileItem deletedItem = \
m_dirLister.spyItemsDeleted.at(0).at(0).value<KFileItemList>().at(0); +     \
QCOMPARE(item, deletedItem); + }
+ 
  void KDirListerTest::enterLoop(int exitCount)
  {
      //qDebug("enterLoop");
diff --cc knewstuff/knewstuff3/uploaddialog.cpp
index 640e8d8,922469e..2e0989a
--- a/knewstuff/knewstuff3/uploaddialog.cpp
+++ b/knewstuff/knewstuff3/uploaddialog.cpp
@@@ -41,35 -40,58 +41,82 @@@
  
  using namespace KNS3;
  
- void UploadDialog::Private::init()
+ bool UploadDialog::Private::init(const QString& configfile)
  {
 +    QVBoxLayout *layout = new QVBoxLayout;
 +    q->setLayout(layout);
 +
      QWidget* _mainWidget = new QWidget(q);
 -    q->setMainWidget(_mainWidget);
      ui.setupUi(_mainWidget);
++
 +    layout->addWidget(_mainWidget);
 +
 +    backButton = new QPushButton;
 +    KGuiItem::assign(backButton, KStandardGuiItem::back(KStandardGuiItem::UseRTL));
 +
 +    nextButton = new QPushButton;
 +    nextButton->setText(i18nc("Opposite to Back", "Next"));
 +    nextButton->setIcon(KStandardGuiItem::forward(KStandardGuiItem::UseRTL).icon());
  +    nextButton->setDefault(true);
 +
 +    finishButton = new QPushButton;
 +    finishButton->setText(i18n("Finish"));
 +    finishButton->setIcon(QIcon::fromTheme("dialog-ok-apply"));
 +
 +    buttonBox = new QDialogButtonBox(q);
 +    buttonBox->addButton(backButton, QDialogButtonBox::ActionRole);
 +    buttonBox->addButton(nextButton, QDialogButtonBox::ActionRole);
 +    buttonBox->addButton(finishButton, QDialogButtonBox::AcceptRole);
 +    buttonBox->setStandardButtons(QDialogButtonBox::Cancel);
 +    layout->addWidget(buttonBox);
 +
      atticaHelper = new AtticaHelper(q);
+ 
+     bool success = true;
+     KConfig conf(configfile);
+     if (conf.accessMode() == KConfig::NoAccess) {
+         kError() << "No knsrc file named '" << configfile << "' was found." << \
endl; +         success = false;
+     }
+     // FIXME: accessMode() doesn't return NoAccess for non-existing files
+     // - bug in kdecore?
+     // - this needs to be looked at again until KConfig backend changes for KDE 4
+     //   the check below is a workaround
 -    if (KStandardDirs::locate("config", configfile).isEmpty()) {
++    if (QStandardPaths::locate(QStandardPaths::ConfigLocation, \
configfile).isEmpty()) { +         kError() << "No knsrc file named '" << configfile \
<< "' was found." << endl; +         success = false;
+     }
+ 
+     KConfigGroup group;
+     if (conf.hasGroup("KNewStuff3")) {
+         kDebug() << "Loading KNewStuff3 config: " << configfile;
+         group = conf.group("KNewStuff3");
+     } else {
+         kError() << "A knsrc file was found but it doesn't contain a KNewStuff3 \
section." << endl; +         success = false;
+     }
+ 
+     if ( success ) {
+         const QString providersFileUrl = group.readEntry("ProvidersUrl", \
QString()); + 
+         categoryNames = group.readEntry("UploadCategories", QStringList());
+         // fall back to download categories
+         if (categoryNames.isEmpty()) {
+             categoryNames = group.readEntry("Categories", QStringList());
+         }
+ 
+         atticaHelper->addProviderFile(QUrl(providersFileUrl));
+     }
+ 
+     ui.mCategoryCombo->addItems(categoryNames);
+ 
+     if (categoryNames.size() == 1) {
+         ui.mCategoryLabel->setVisible(false);
+         ui.mCategoryCombo->setVisible(false);
+     }
+ 
+     kDebug() << "Categories: " << categoryNames;
+ 
      q->connect(atticaHelper, SIGNAL(providersLoaded(QStringList)), q, \
                SLOT(_k_providersLoaded(QStringList)));
      q->connect(atticaHelper, SIGNAL(loginChecked(bool)), q, \
                SLOT(_k_checkCredentialsFinished(bool)));
      q->connect(atticaHelper, SIGNAL(licensesLoaded(Attica::License::List)), q, \
SLOT(_k_licensesLoaded(Attica::License::List))); @@@ -381,10 -401,18 +426,10 @@@ \
UploadDialog::~UploadDialog(  
  bool UploadDialog::init(const QString &configfile)
  {
-     d->init();
+     bool success = d->init(configfile);
  
 -    setCaption(i18n("Share Hot New Stuff"));
 +    setWindowTitle(i18n("Share Hot New Stuff"));
  
 -    setButtons(KDialog::Cancel | KDialog::User1 | KDialog::User2 | KDialog::User3 | \
                KDialog::Help);
 -    setButtonGuiItem( BackButton, KStandardGuiItem::back(KStandardGuiItem::UseRTL) \
                );
 -
 -    setButtonText( NextButton, i18nc("Opposite to Back", "Next") );
 -    setButtonIcon( NextButton, \
                KStandardGuiItem::forward(KStandardGuiItem::UseRTL).icon() );
 -    setButtonText(FinishButton, i18n("Finish"));
 -    setButtonIcon( FinishButton, KIcon("dialog-ok-apply") );
 -    setDefaultButton(NextButton);
      d->_k_updatePage();
  
      connect(d->ui.username, SIGNAL(textChanged(QString)), this, \
SLOT(_k_updatePage())); @@@ -396,63 -424,23 +441,27 @@@
  
      connect(d->ui.uploadButton, SIGNAL(clicked()), this, SLOT(_k_startUpload()));
  
 -    connect(this, SIGNAL(user3Clicked()), this, SLOT(_k_backPage()));
 -    connect(this, SIGNAL(user2Clicked()), this, SLOT(_k_nextPage()));
 -    connect(this, SIGNAL(user1Clicked()), this, SLOT(accept()));
 +    connect(d->backButton, SIGNAL(clicked()), this, SLOT(_k_backPage()));
 +    connect(d->nextButton, SIGNAL(clicked()), this, SLOT(_k_nextPage()));
 +    connect(d->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
 +    connect(d->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
  
 +    QString displayName = QGuiApplication::applicationDisplayName();
 +    if (displayName.isEmpty())
 +        displayName = QCoreApplication::applicationName();
      d->ui.mTitleWidget->setText(i18nc("Program name followed by 'Add On Uploader'",
                                   "%1 Add-On Uploader",
 -                                 \
                KGlobal::activeComponent().aboutData()->programName()));
 -    d->ui.mTitleWidget->setPixmap(KIcon(KGlobal::activeComponent().aboutData()->programIconName()));
  +                                 displayName));
 +    //d->ui.mTitleWidget->setPixmap(QIcon::fromTheme(KGlobal::activeComponent().aboutData()->programIconName()));
  
-     KConfig conf(configfile);
-     if (conf.accessMode() == KConfig::NoAccess) {
-         kError() << "No knsrc file named '" << configfile << "' was found." << \
                endl;
-         return false;
-     }
-     // FIXME: accessMode() doesn't return NoAccess for non-existing files
-     // - bug in kdecore?
-     // - this needs to be looked at again until KConfig backend changes for KDE 4
-     // the check below is a workaround
-     if (QStandardPaths::locate(QStandardPaths::ConfigLocation, \
                configfile).isEmpty()) {
-         kError() << "No knsrc file named '" << configfile << "' was found." << \
                endl;
-         return false;
+     if ( success ) {
+         d->_k_showPage(0);
      }
  
-     KConfigGroup group;
-     if (conf.hasGroup("KNewStuff3")) {
-         kDebug() << "Loading KNewStuff3 config: " << configfile;
-         group = conf.group("KNewStuff3");
-     } else {
-         kError() << "A knsrc file was found but it doesn't contain a KNewStuff3 \
                section." << endl;
-         return false;
-     }
- 
-     d->categoryNames = group.readEntry("UploadCategories", QStringList());
-     // fall back to download categories
-     if (d->categoryNames.isEmpty()) {
-         d->categoryNames = group.readEntry("Categories", QStringList());
-     }
- 
-     d->ui.mCategoryCombo->addItems(d->categoryNames);
- 
-     if (d->categoryNames.size() == 1) {
-         d->ui.mCategoryLabel->setVisible(false);
-         d->ui.mCategoryCombo->setVisible(false);
-     }
- 
-     kDebug() << "Categories: " << d->categoryNames;
- 
-     d->_k_showPage(0);
- 
-     return true;
+     return success;
  }
  
 -void UploadDialog::setUploadFile(const KUrl& payloadFile)
 +void UploadDialog::setUploadFile(const QUrl & payloadFile)
  {
      d->uploadFile = payloadFile;
  
diff --cc tier1/kcoreaddons/src/io/kdirwatch.cpp
index 8687808,0000000..ddbc8f5
mode 100644,000000..100644
--- a/tier1/kcoreaddons/src/io/kdirwatch.cpp
+++ b/tier1/kcoreaddons/src/io/kdirwatch.cpp
@@@ -1,1915 -1,0 +1,1923 @@@
 +/* This file is part of the KDE libraries
 +   Copyright (C) 1998 Sven Radej <sven@lisa.exp.univie.ac.at>
 +   Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
 +   Copyright (C) 2007 Flavio Castelli <flavio.castelli@gmail.com>
 +   Copyright (C) 2008 Rafal Rzepecki <divided.mind@gmail.com>
 +   Copyright (C) 2010 David Faure <faure@kde.org>
 +
 +   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 License
 +   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.
 +*/
 +
 +
 +// CHANGES:
 +// Jul 30, 2008 - Don't follow symlinks when recursing to avoid loops (Rafal)
 +// Aug 6,  2007 - KDirWatch::WatchModes support complete, flags work fine also
 +// when using FAMD (Flavio Castelli)
 +// Aug 3,  2007 - Handled KDirWatch::WatchModes flags when using inotify, now
 +// recursive and file monitoring modes are implemented (Flavio Castelli)
 +// Jul 30, 2007 - Substituted addEntry boolean params with KDirWatch::WatchModes
 +// flag (Flavio Castelli)
 +// Oct 4,  2005 - Inotify support (Dirk Mueller)
 +// Februar 2002 - Add file watching and remote mount check for STAT
 +// Mar 30, 2001 - Native support for Linux dir change notification.
 +// Jan 28, 2000 - Usage of FAM service on IRIX (Josef.Weidendorfer@in.tum.de)
 +// May 24. 1998 - List of times introduced, and some bugs are fixed. (sven)
 +// May 23. 1998 - Removed static pointer - you can have more instances.
 +// It was Needed for KRegistry. KDirWatch now emits signals and doesn't
 +// call (or need) KFM. No more URL's - just plain paths. (sven)
 +// Mar 29. 1998 - added docs, stop/restart for particular Dirs and
 +// deep copies for list of dirs. (sven)
 +// Mar 28. 1998 - Created.  (sven)
 +
 +#include "kdirwatch.h"
 +#include "kdirwatch_p.h"
 +#include "kfilesystemtype_p.h"
 +
 +#include <io/config-kdirwatch.h>
 +
 +#include <sys/stat.h>
 +#include <assert.h>
 +#include <errno.h>
 +#include <QtCore/QDebug>
 +#include <QtCore/QDir>
 +#include <QtCore/QFile>
 +#include <QtCore/QSocketNotifier>
 +#include <QtCore/QTimer>
 +#include <QtCore/QCoreApplication>
 +
 +#include <qplatformdefs.h> // QT_LSTAT, QT_STAT, QT_STATBUF
 +
 +#include <stdlib.h>
 +#include <string.h>
 +
 +// debug
 +#include <sys/ioctl.h>
 +
 +
 +#include <sys/utsname.h>
 +
 +// set this to true for much more verbose debug output
 +static const bool s_verboseDebug = false;
 +
 +// The KDirWatchPrivate instance is refcounted, and deleted by the last KDirWatch \
instance  +static KDirWatchPrivate* dwp_self = 0;
 +static KDirWatchPrivate* createPrivate() {
 +  if (!dwp_self)
 +    dwp_self = new KDirWatchPrivate;
 +  return dwp_self;
 +}
 +
 +// Convert a string into a watch Method
 +static KDirWatch::Method methodFromString(const QString& method) {
 +  if (method == QLatin1String("Fam")) {
 +    return KDirWatch::FAM;
 +  } else if (method == QLatin1String("Stat")) {
 +    return KDirWatch::Stat;
 +  } else if (method == QLatin1String("QFSWatch")) {
 +    return KDirWatch::QFSWatch;
 +  } else {
 +#ifdef Q_OS_LINUX
 +    // inotify supports delete+recreate+modify, which QFSWatch doesn't support
 +    return KDirWatch::INotify;
 +#else
 +    return KDirWatch::QFSWatch;
 +#endif
 +  }
 +}
 +
 +#ifndef NDEBUG
 +static const char* methodToString(KDirWatch::Method method)
 +{
 +    switch (method) {
 +    case KDirWatch::FAM:
 +        return "Fam";
 +    case KDirWatch::INotify:
 +        return "INotify";
 +    case KDirWatch::DNotify:
 +        return "DNotify";
 +    case KDirWatch::Stat:
 +        return "Stat";
 +    case KDirWatch::QFSWatch:
 +        return "QFSWatch";
 +    default:
 +        return "ERROR!";
 +    }
 +}
 +#endif
 +
 +//
 +// Class KDirWatchPrivate (singleton)
 +//
 +
 +/* All entries (files/directories) to be watched in the
 + * application (coming from multiple KDirWatch instances)
 + * are registered in a single KDirWatchPrivate instance.
 + *
 + * At the moment, the following methods for file watching
 + * are supported:
 + * - Polling: All files to be watched are polled regularly
 + *   using stat (more precise: QFileInfo.lastModified()).
 + *   The polling frequency is determined from global kconfig
 + *   settings, defaulting to 500 ms for local directories
 + *   and 5000 ms for remote mounts
 + * - FAM (File Alternation Monitor): first used on IRIX, SGI
 + *   has ported this method to LINUX. It uses a kernel part
 + *   (IMON, sending change events to /dev/imon) and a user
 + *   level damon (fam), to which applications connect for
 + *   notification of file changes. For NFS, the fam damon
 + *   on the NFS server machine is used; if IMON is not built
 + *   into the kernel, fam uses polling for local files.
 + * - INOTIFY: In LINUX 2.6.13, inode change notification was
 + *   introduced. You're now able to watch arbitrary inode's
 + *   for changes, and even get notification when they're
 + *   unmounted.
 + */
 +
 +KDirWatchPrivate::KDirWatchPrivate()
 +  : timer(),
 +    freq( 3600000 ), // 1 hour as upper bound
 +    statEntries( 0 ),
 +    m_ref( 0 ),
 +    delayRemove( false ),
 +    rescan_all( false ),
 +    rescan_timer()
 +{
 +  timer.setObjectName(QLatin1String("KDirWatchPrivate::timer"));
 +  connect (&timer, SIGNAL(timeout()), this, SLOT(slotRescan()));
 +
 +#pragma message("KDE5 TODO: Remove dependencies on Kconfig and KGlobal")
 +#if 0
 +  KConfigGroup config(KSharedConfig::openConfig(), "DirWatch");
 +  m_nfsPollInterval = config.readEntry("NFSPollInterval", 5000);
 +  m_PollInterval = config.readEntry("PollInterval", 500);
 +
 +  QString method = config.readEntry("PreferredMethod", "inotify");
 +  m_preferredMethod = methodFromString(method);
 +
 +  // The nfs method defaults to the normal (local) method
 +  m_nfsPreferredMethod = methodFromString(config.readEntry("nfsPreferredMethod", \
"Fam"));  +#endif
 +#pragma message("KDE5 FIXME: We use the default values until the todo above is \
fixed")  +  m_nfsPollInterval = 5000;
 +  m_PollInterval = 500;
 +  m_preferredMethod = methodFromString(QLatin1String("inotify"));
 +  m_nfsPreferredMethod = methodFromString(QLatin1String("Fam"));
 +
 +  QList<QByteArray> availableMethods;
 +
 +  availableMethods << "Stat";
 +
 +  // used for FAM and inotify
 +  rescan_timer.setObjectName(QString::fromLatin1("KDirWatchPrivate::rescan_timer"));
  +  rescan_timer.setSingleShot( true );
 +  connect(&rescan_timer, SIGNAL(timeout()), this, SLOT(slotRescan()));
 +
 +#if HAVE_FAM
 +  // It's possible that FAM server can't be started
 +  if (FAMOpen(&fc) ==0) {
 +    availableMethods << "FAM";
 +    use_fam=true;
 +    sn = new QSocketNotifier( FAMCONNECTION_GETFD(&fc),
 +			      QSocketNotifier::Read, this);
 +    connect( sn, SIGNAL(activated(int)),
 + 	     this, SLOT(famEventReceived()) );
 +  }
 +  else {
 +    qDebug() << "Can't use FAM (fam daemon not running?)";
 +    use_fam=false;
 +  }
 +#endif
 +
 +#if HAVE_SYS_INOTIFY_H
 +  supports_inotify = true;
 +
 +  m_inotify_fd = inotify_init();
 +
 +  if ( m_inotify_fd <= 0 ) {
 +    qDebug() << "Can't use Inotify, kernel doesn't support it";
 +    supports_inotify = false;
 +  }
 +
 +  {
 +    struct utsname uts;
 +    int major, minor, patch;
 +    if (uname(&uts) < 0) {
 +      supports_inotify = false;
 +      qDebug() << "Unable to get uname";
 +    } else if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
 +      supports_inotify = false;
 +      qDebug() << "The version is malformed: " << uts.release;
 +    } else if(major == 2 && minor == 6) { // If it is 2.6 check further...
 +      if (sscanf(uts.release, "%d.%d.%d", &major, &minor, &patch) != 3) {
 +        supports_inotify = false;
 +        qDebug() << "Detected 2.6 kernel but can't know more: " << uts.release;
 +      } else if (major * 1000000 + minor * 1000 + patch < 2006014 ){
 +        supports_inotify = false;
 +        qDebug() << "Can't use INotify, Linux kernel too old " << uts.release;
 +      }
 +    }
 +  }
 +
 +  //qDebug() << "INotify available: " << supports_inotify;
 +  if ( supports_inotify ) {
 +    availableMethods << "INotify";
 +    (void)fcntl(m_inotify_fd, F_SETFD, FD_CLOEXEC);
 +
 +    mSn = new QSocketNotifier( m_inotify_fd, QSocketNotifier::Read, this );
 +    connect( mSn, SIGNAL(activated(int)),
 +             this, SLOT(inotifyEventReceived()) );
 +  }
 +#endif
 +#if HAVE_QFILESYSTEMWATCHER
 +  availableMethods << "QFileSystemWatcher";
 +  fsWatcher = 0;
 +#endif
 +#ifndef NDEBUG
 +  qDebug() << "Available methods: " << availableMethods << "preferred=" << \
methodToString(m_preferredMethod);  +#endif
 +}
 +
 +// This is called on app exit (when K_GLOBAL_STATIC deletes KDirWatch::self)
 +KDirWatchPrivate::~KDirWatchPrivate()
 +{
 +  timer.stop();
 +
 +  /* remove all entries being watched */
 +  removeEntries(0);
 +
 +#if HAVE_FAM
 +  if (use_fam) {
 +    FAMClose(&fc);
 +  }
 +#endif
 +#if HAVE_SYS_INOTIFY_H
 +  if ( supports_inotify )
 +    ::close( m_inotify_fd );
 +#endif
 +#if HAVE_QFILESYSTEMWATCHER
 +  delete fsWatcher;
 +#endif
 +}
 +
 +void KDirWatchPrivate::inotifyEventReceived()
 +{
 +  //kDebug(7001);
 +#if HAVE_SYS_INOTIFY_H
 +  if ( !supports_inotify )
 +    return;
 +
 +  int pending = -1;
 +  int offsetStartRead = 0; // where we read into buffer
 +  char buf[8192];
 +  assert( m_inotify_fd > -1 );
 +  ioctl( m_inotify_fd, FIONREAD, &pending );
 +
 +  while ( pending > 0 ) {
 +
 +    const int bytesToRead = qMin( pending, (int)sizeof( buf ) - offsetStartRead );
 +
 +    int bytesAvailable = read( m_inotify_fd, &buf[offsetStartRead], bytesToRead );
 +    pending -= bytesAvailable;
 +    bytesAvailable += offsetStartRead;
 +    offsetStartRead = 0;
 +
 +    int offsetCurrent = 0;
 +    while ( bytesAvailable >= (int)sizeof( struct inotify_event ) ) {
 +      const struct inotify_event * const event = (struct inotify_event *) \
&buf[offsetCurrent];  +      const int eventSize = sizeof( struct inotify_event ) + \
event->len;  +      if ( bytesAvailable < eventSize ) {
 +          break;
 +      }
 +
 +      bytesAvailable -= eventSize;
 +      offsetCurrent += eventSize;
 +
 +      QString path;
 +      QByteArray cpath(event->name, event->len);
 +      if(event->len)
 +        path = QFile::decodeName ( cpath );
 +
 +      if ( path.length() && isNoisyFile( cpath.data() ) )
 +        continue;
 +
 +      // now we're in deep trouble of finding the
 +      // associated entries
 +      // for now, we suck and iterate
 +      for ( EntryMap::Iterator it = m_mapEntries.begin();
 +            it != m_mapEntries.end();  ) {
 +        Entry* e = &( *it );
 +        ++it;
 +        if ( e->wd == event->wd ) {
 +          e->dirty = true;
 +
 +          //if (s_verboseDebug) {
 +          //  kDebug(7001) << "got event" << "0x"+QString::number(event->mask, 16) \
<< "for" << e->path;  +          //}
 +
 +          if( event->mask & IN_DELETE_SELF) {
 +            if (s_verboseDebug) {
 +              qDebug() << "-->got deleteself signal for" << e->path;
 +            }
 +            e->m_status = NonExistent;
 +            e->wd = -1;
 +            e->m_ctime = invalid_ctime;
 +            emitEvent(e, Deleted, e->path);
++            // If the parent dir was already watched, tell it something changed
++            Entry* parentEntry = entry(e->parentDirectory());
++            if (parentEntry)
++                parentEntry->dirty = true;
 +            // Add entry to parent dir to notice if the entry gets recreated
 +            addEntry(0, e->parentDirectory(), e, true /*isDir*/);
 +          }
 +          if ( event->mask & IN_IGNORED ) {
 +            // Causes bug #207361 with kernels 2.6.31 and 2.6.32!
 +            //e->wd = -1;
 +          }
 +          if ( event->mask & (IN_CREATE|IN_MOVED_TO) ) {
 +            const QString tpath = e->path + QLatin1Char('/') + path;
 +            Entry* sub_entry = e->findSubEntry(tpath);
 +
 +            if (s_verboseDebug) {
 +              qDebug() << "-->got CREATE signal for" << (tpath) << "sub_entry=" << \
sub_entry;  +              qDebug() << *e;
 +            }
 +
 +            // The code below is very similar to the one in checkFAMEvent...
 +            if (sub_entry) {
 +              // We were waiting for this new file/dir to be created
 +              sub_entry->dirty = true;
 +              rescan_timer.start(0); // process this asap, to start watching that \
dir  +            } else if (e->isDir && !e->m_clients.empty()) {
 +              bool isDir = false;
 +              const QList<Client *> clients = e->clientsForFileOrDir(tpath, \
&isDir);  +              Q_FOREACH(Client *client, clients) {
 +                // See discussion in addEntry for why we don't addEntry for \
individual  +                // files in WatchFiles mode with inotify.
 +                if (isDir) {
 +                  addEntry(client->instance, tpath, 0, isDir,
 +                           isDir ? client->m_watchModes : KDirWatch::WatchDirOnly);
 +                }
 +              }
 +              if (!clients.isEmpty()) {
 +                emitEvent(e, Created, tpath);
 +                qDebug().nospace() << clients.count() << " instance(s) monitoring \
the new "  +                                       << (isDir ? "dir " : "file ") << \
tpath;  +              }
 +              e->m_pendingFileChanges.append(e->path);
 +              if (!rescan_timer.isActive())
 +                  rescan_timer.start(m_PollInterval); // singleshot
 +            }
 +          }
 +          if (event->mask & (IN_DELETE|IN_MOVED_FROM)) {
 +            const QString tpath = e->path + QLatin1Char('/') + path;
 +            if (s_verboseDebug) {
 +              qDebug() << "-->got DELETE signal for" << tpath;
 +            }
 +            if ((e->isDir) && (!e->m_clients.empty())) {
 +              Client* client = 0;
 +              // A file in this directory has been removed.  It wasn't an \
explicitly  +              // watched file as it would have its own watch descriptor, \
so  +              // no addEntry/ removeEntry bookkeeping should be required.  Emit
 +              // the event immediately if any clients are interested.
 +              QT_STATBUF stat_buf;
 +              // Unlike clientsForFileOrDir, the stat can fail here (item deleted),
 +              // so in that case we'll just take both kinds of clients and emit \
Deleted.  +              KDirWatch::WatchModes flag = KDirWatch::WatchSubDirs | \
KDirWatch::WatchFiles;  +              if \
(QT_STAT(QFile::encodeName(tpath).constData(), &stat_buf) == 0) {  +                \
bool isDir = S_ISDIR(stat_buf.st_mode);  +                flag = isDir ? \
KDirWatch::WatchSubDirs : KDirWatch::WatchFiles;  +              }
 +              int counter = 0;
 +              Q_FOREACH(client, e->m_clients) { // krazy:exclude=Q_FOREACH
 +                  if (client->m_watchModes & flag) {
 +                        counter++;
 +                  }
 +              }
 +              if (counter != 0) {
 +                  emitEvent(e, Deleted, tpath);
 +              }
 +            }
 +          }
 +          if (event->mask & (IN_MODIFY|IN_ATTRIB)) {
 +            if ((e->isDir) && (!e->m_clients.empty())) {
 +              const QString tpath = e->path + QLatin1Char('/') + path;
 +              if (s_verboseDebug) {
 +                qDebug() << "-->got MODIFY signal for" << (tpath);
 +              }
 +              // A file in this directory has been changed.  No
 +              // addEntry/ removeEntry bookkeeping should be required.
 +              // Add the path to the list of pending file changes if
 +              // there are any interested clients.
 +              //QT_STATBUF stat_buf;
 +              //QByteArray tpath = QFile::encodeName(e->path+'/'+path);
 +              //QT_STAT(tpath, &stat_buf);
 +              //bool isDir = S_ISDIR(stat_buf.st_mode);
 +
 +              // The API doc is somewhat vague as to whether we should emit
 +              // dirty() for implicitly watched files when WatchFiles has
 +              // not been specified - we'll assume they are always interested,
 +              // regardless.
 +              // Don't worry about duplicates for the time
 +              // being; this is handled in slotRescan.
 +              e->m_pendingFileChanges.append(tpath);
 +            }
 +          }
 +
 +          if (!rescan_timer.isActive())
 +            rescan_timer.start(m_PollInterval); // singleshot
 +
 +          break;
 +        }
 +      }
 +    }
 +    if (bytesAvailable > 0) {
 +        // copy partial event to beginning of buffer
 +        memmove(buf, &buf[offsetCurrent], bytesAvailable);
 +        offsetStartRead = bytesAvailable;
 +    }
 +  }
 +#endif
 +}
 +
 +/* In FAM mode, only entries which are marked dirty are scanned.
 + * We first need to mark all yet nonexistent, but possible created
 + * entries as dirty...
 + */
 +void KDirWatchPrivate::Entry::propagate_dirty()
 +{
 +  Q_FOREACH(Entry *sub_entry, m_entries)
 +  {
 +     if (!sub_entry->dirty)
 +     {
 +        sub_entry->dirty = true;
 +        sub_entry->propagate_dirty();
 +     }
 +  }
 +}
 +
 +
 +/* A KDirWatch instance is interested in getting events for
 + * this file/Dir entry.
 + */
 +void KDirWatchPrivate::Entry::addClient(KDirWatch* instance,
 +                                        KDirWatch::WatchModes watchModes)
 +{
 +  if (instance == 0)
 +    return;
 +
 +  Q_FOREACH(Client* client, m_clients) {
 +    if (client->instance == instance) {
 +      client->count++;
 +      client->m_watchModes = watchModes;
 +      return;
 +    }
 +  }
 +
 +  Client* client = new Client;
 +  client->instance = instance;
 +  client->count = 1;
 +  client->watchingStopped = instance->isStopped();
 +  client->pending = NoChange;
 +  client->m_watchModes = watchModes;
 +
 +  m_clients.append(client);
 +}
 +
 +void KDirWatchPrivate::Entry::removeClient(KDirWatch* instance)
 +{
 +  QList<Client *>::iterator it = m_clients.begin();
 +  const QList<Client *>::iterator end = m_clients.end();
 +  for ( ; it != end ; ++it ) {
 +    Client* client = *it;
 +    if (client->instance == instance) {
 +      client->count--;
 +      if (client->count == 0) {
 +        m_clients.erase(it);
 +        delete client;
 +      }
 +      return;
 +    }
 +  }
 +}
 +
 +/* get number of clients */
 +int KDirWatchPrivate::Entry::clientCount() const
 +{
 +  int clients = 0;
 +  Q_FOREACH(Client* client, m_clients)
 +    clients += client->count;
 +
 +  return clients;
 +}
 +
 +QString KDirWatchPrivate::Entry::parentDirectory() const
 +{
 +  return QDir::cleanPath(path + QLatin1String("/.."));
 +}
 +
 +QList<KDirWatchPrivate::Client *> \
KDirWatchPrivate::Entry::clientsForFileOrDir(const QString& tpath, bool* isDir) const \
+{  +  QList<Client *> ret;
 +  QFileInfo fi(tpath);
 +  if (fi.exists()) {
 +    *isDir = fi.isDir();
 +    const KDirWatch::WatchModes flag =
 +      *isDir ? KDirWatch::WatchSubDirs : KDirWatch::WatchFiles;
 +    Q_FOREACH(Client *client, this->m_clients) {
 +      if (client->m_watchModes & flag) {
 +        ret.append(client);
 +      }
 +    }
 +  } else {
 +    // Happens frequently, e.g. ERROR: couldn't stat "/home/dfaure/.viminfo.tmp"
 +    //kDebug(7001) << "ERROR: couldn't stat" << tpath;
 +    // In this case isDir is not set, but ret is empty anyway
 +    // so isDir won't be used.
 +  }
 +  return ret;
 +}
 +
 +QDebug operator<<(QDebug debug, const KDirWatchPrivate::Entry &entry)
 +{
 +  debug.nospace() << "[ Entry for " << entry.path << ", " << (entry.isDir ? "dir" : \
"file");  +  if (entry.m_status == KDirWatchPrivate::NonExistent)
 +    debug << ", non-existent";
 +  debug << ", using " << ((entry.m_mode == KDirWatchPrivate::FAMMode) ? "FAM" :
 +                       (entry.m_mode == KDirWatchPrivate::INotifyMode) ? "INotify" \
:  +                       (entry.m_mode == KDirWatchPrivate::DNotifyMode) ? \
"DNotify" :  +                       (entry.m_mode == KDirWatchPrivate::QFSWatchMode) \
? "QFSWatch" :  +                       (entry.m_mode == KDirWatchPrivate::StatMode) \
? "Stat" : "Unknown Method");  +#if HAVE_SYS_INOTIFY_H
 +  if (entry.m_mode == KDirWatchPrivate::INotifyMode)
 +    debug << " inotify_wd=" << entry.wd;
 +#endif
 +  debug << ", has " << entry.m_clients.count() << " clients";
 +  debug.space();
 +  if (!entry.m_entries.isEmpty()) {
 +    debug << ", nonexistent subentries:";
 +    Q_FOREACH(KDirWatchPrivate::Entry* subEntry, entry.m_entries)
 +      debug << subEntry << subEntry->path;
 +  }
 +  debug << ']';
 +  return debug;
 +}
 +
 +KDirWatchPrivate::Entry* KDirWatchPrivate::entry(const QString& _path)
 +{
 +// we only support absolute paths
 +  if (_path.isEmpty() || QDir::isRelativePath(_path)) {
 +    return 0;
 +  }
 +
 +  QString path (_path);
 +
 +  if ( path.length() > 1 && path.endsWith( QLatin1Char( '/' ) ) )
 +    path.truncate( path.length() - 1 );
 +
 +  EntryMap::Iterator it = m_mapEntries.find( path );
 +  if ( it == m_mapEntries.end() )
 +    return 0;
 +  else
 +    return &(*it);
 +}
 +
 +// set polling frequency for a entry and adjust global freq if needed
 +void KDirWatchPrivate::useFreq(Entry* e, int newFreq)
 +{
 +  e->freq = newFreq;
 +
 +  // a reasonable frequency for the global polling timer
 +  if (e->freq < freq) {
 +    freq = e->freq;
 +    if (timer.isActive()) timer.start(freq);
 +    qDebug() << "Global Poll Freq is now" << freq << "msec";
 +  }
 +}
 +
 +
 +#if HAVE_FAM
 +// setup FAM notification, returns false if not possible
 +bool KDirWatchPrivate::useFAM(Entry* e)
 +{
 +  if (!use_fam) return false;
 +
 +  // handle FAM events to avoid deadlock
 +  // (FAM sends back all files in a directory when monitoring)
 +  famEventReceived();
 +
 +  e->m_mode = FAMMode;
 +  e->dirty = false;
 +
 +  if (e->isDir) {
 +    if (e->m_status == NonExistent) {
 +      // If the directory does not exist we watch the parent directory
 +      addEntry(0, e->parentDirectory(), e, true);
 +    }
 +    else {
 +      int res =FAMMonitorDirectory(&fc, QFile::encodeName(e->path).data(),
 +				   &(e->fr), e);
 +      if (res<0) {
 +	e->m_mode = UnknownMode;
 +	use_fam=false;
 +        delete sn; sn = 0;
 +	return false;
 +      }
 +      qDebug().nospace() << " Setup FAM (Req " << FAMREQUEST_GETREQNUM(&(e->fr))
 +                   << ") for " << e->path;
 +    }
 +  }
 +  else {
 +    if (e->m_status == NonExistent) {
 +      // If the file does not exist we watch the directory
 +      addEntry(0, QFileInfo(e->path).absolutePath(), e, true);
 +    }
 +    else {
 +      int res = FAMMonitorFile(&fc, QFile::encodeName(e->path).data(),
 +			       &(e->fr), e);
 +      if (res<0) {
 +	e->m_mode = UnknownMode;
 +	use_fam=false;
 +        delete sn; sn = 0;
 +	return false;
 +      }
 +
 +      qDebug().nospace() << " Setup FAM (Req " << FAMREQUEST_GETREQNUM(&(e->fr))
 +                   << ") for " << e->path;
 +    }
 +  }
 +
 +  // handle FAM events to avoid deadlock
 +  // (FAM sends back all files in a directory when monitoring)
 +  famEventReceived();
 +
 +  return true;
 +}
 +#endif
 +
 +#if HAVE_SYS_INOTIFY_H
 +// setup INotify notification, returns false if not possible
 +bool KDirWatchPrivate::useINotify( Entry* e )
 +{
 +  //kDebug (7001) << "trying to use inotify for monitoring";
 +
 +  e->wd = -1;
 +  e->dirty = false;
 +
 +  if (!supports_inotify) return false;
 +
 +  e->m_mode = INotifyMode;
 +
 +  if ( e->m_status == NonExistent ) {
 +    addEntry(0, e->parentDirectory(), e, true);
 +    return true;
 +  }
 +
 +  // May as well register for almost everything - it's free!
 +  int mask = IN_DELETE|IN_DELETE_SELF|IN_CREATE|IN_MOVE|IN_MOVE_SELF|IN_DONT_FOLLOW|IN_MOVED_FROM|IN_MODIFY|IN_ATTRIB;
  +
 +  if ( ( e->wd = inotify_add_watch( m_inotify_fd,
 +                                    QFile::encodeName( e->path ).data(), mask) ) >= \
0)  +  {
 +    if (s_verboseDebug) {
 +      qDebug() << "inotify successfully used for monitoring" << e->path << "wd=" << \
e->wd;  +    }
 +    return true;
 +  }
 +
 +   qDebug() << "inotify failed for monitoring" << e->path << ":" << \
strerror(errno);  +  return false;
 +}
 +#endif
 +#if HAVE_QFILESYSTEMWATCHER
 +bool KDirWatchPrivate::useQFSWatch(Entry* e)
 +{
 +  e->m_mode = QFSWatchMode;
 +  e->dirty = false;
 +
 +  if ( e->m_status == NonExistent ) {
 +    addEntry(0, e->parentDirectory(), e, true /*isDir*/);
 +    return true;
 +  }
 +
 +  qDebug() << "fsWatcher->addPath" << e->path;
 +  if (!fsWatcher) {
 +      fsWatcher = new KFileSystemWatcher();
 +      connect(fsWatcher, SIGNAL(directoryChanged(QString)), this, \
SLOT(fswEventReceived(QString)));  +      connect(fsWatcher, \
SIGNAL(fileChanged(QString)),      this, SLOT(fswEventReceived(QString)));  +  }
 +  fsWatcher->addPath( e->path );
 +  return true;
 +}
 +#endif
 +
 +bool KDirWatchPrivate::useStat(Entry* e)
 +{
 +  if (KFileSystemType::fileSystemType(e->path) == KFileSystemType::Nfs) // TODO: or \
Smbfs?  +    useFreq(e, m_nfsPollInterval);
 +  else
 +    useFreq(e, m_PollInterval);
 +
 +  if (e->m_mode != StatMode) {
 +    e->m_mode = StatMode;
 +    statEntries++;
 +
 +    if ( statEntries == 1 ) {
 +      // if this was first STAT entry (=timer was stopped)
 +      timer.start(freq);      // then start the timer
 +      qDebug() << " Started Polling Timer, freq " << freq;
 +    }
 +  }
 +
 +  qDebug() << " Setup Stat (freq " << e->freq << ") for " << e->path;
 +
 +  return true;
 +}
 +
 +
 +/* If <instance> !=0, this KDirWatch instance wants to watch at <_path>,
 + * providing in <isDir> the type of the entry to be watched.
 + * Sometimes, entries are dependant on each other: if <sub_entry> !=0,
 + * this entry needs another entry to watch himself (when notExistent).
 + */
 +void KDirWatchPrivate::addEntry(KDirWatch* instance, const QString& _path,
 +                Entry* sub_entry, bool isDir, KDirWatch::WatchModes watchModes)
 +{
 +  QString path (_path);
 +  if (path.isEmpty()
 +#ifndef Q_OS_WIN
 +     || path == QLatin1String("/dev")
 +     || (path.startsWith(QLatin1String("/dev/")) && \
!path.startsWith(QLatin1String("/dev/.")))  +#endif
 +  )
 +    return; // Don't even go there.
 +
 +  if ( path.length() > 1 && path.endsWith( QLatin1Char( '/' ) ) )
 +    path.truncate( path.length() - 1 );
 +
 +  EntryMap::Iterator it = m_mapEntries.find( path );
 +  if ( it != m_mapEntries.end() )
 +  {
 +    if (sub_entry) {
 +       (*it).m_entries.append(sub_entry);
 +       if (s_verboseDebug) {
 +         qDebug() << "Added already watched Entry" << path
 +                      << "(for" << sub_entry->path << ")";
 +       }
 +#if HAVE_SYS_INOTIFY_H
 +       Entry* e = &(*it);
 +       if( (e->m_mode == INotifyMode) && (e->wd >= 0) ) {
 +         int mask = \
IN_DELETE|IN_DELETE_SELF|IN_CREATE|IN_MOVE|IN_MOVE_SELF|IN_DONT_FOLLOW;  +         \
if(!e->isDir)  +           mask |= IN_MODIFY|IN_ATTRIB;
 +         else
 +           mask |= IN_ONLYDIR;
 +
 +         inotify_rm_watch (m_inotify_fd, e->wd);
 +         e->wd = inotify_add_watch( m_inotify_fd, QFile::encodeName( e->path \
).data(),  +                                    mask);
 +         //Q_ASSERT(e->wd >= 0); // fails in KDirListerTest::testDeleteCurrentDir
 +       }
 +#endif
 +    }
 +    else {
 +       (*it).addClient(instance, watchModes);
 +       if (s_verboseDebug) {
 +         qDebug() << "Added already watched Entry" << path
 +                      << "(now" <<  (*it).clientCount() << "clients)"
 +                      << QString::fromLatin1("[%1]").arg(instance->objectName());
 +       }
 +    }
 +    return;
 +  }
 +
 +  // we have a new path to watch
 +
 +  QT_STATBUF stat_buf;
 +  bool exists = (QT_STAT(QFile::encodeName(path).constData(), &stat_buf) == 0);
 +
 +  EntryMap::iterator newIt = m_mapEntries.insert( path, Entry() );
 +  // the insert does a copy, so we have to use <e> now
 +  Entry* e = &(*newIt);
 +
 +  if (exists) {
 +    e->isDir = S_ISDIR(stat_buf.st_mode);
 +
 +    if (e->isDir && !isDir) {
 +      if (QT_LSTAT(QFile::encodeName(path).constData(), &stat_buf) == 0) {
 +        if (S_ISLNK(stat_buf.st_mode))
 +          // if it's a symlink, don't follow it
 +          e->isDir = false;
 +        else
 +          qWarning() << "KDirWatch:" << path << "is a directory. Use addDir!";
 +      }
 +    } else if (!e->isDir && isDir)
 +      qWarning("KDirWatch: %s is a file. Use addFile!", qPrintable(path));
 +
 +    if (!e->isDir && ( watchModes != KDirWatch::WatchDirOnly)) {
 +      qWarning() << "KDirWatch:" << path << "is a file. You can't use recursive or \
"  +                    "watchFiles options";
 +      watchModes = KDirWatch::WatchDirOnly;
 +    }
 +
 +#ifdef Q_OS_WIN
 +    // ctime is the 'creation time' on windows - use mtime instead
 +    e->m_ctime = stat_buf.st_mtime;
 +#else
 +    e->m_ctime = stat_buf.st_ctime;
 +#endif
 +    e->m_status = Normal;
 +    e->m_nlink = stat_buf.st_nlink;
 +    e->m_ino = stat_buf.st_ino;
 +  }
 +  else {
 +    e->isDir = isDir;
 +    e->m_ctime = invalid_ctime;
 +    e->m_status = NonExistent;
 +    e->m_nlink = 0;
 +    e->m_ino = 0;
 +  }
 +
 +  e->path = path;
 +  if (sub_entry)
 +    e->m_entries.append(sub_entry);
 +  else
 +    e->addClient(instance, watchModes);
 +
 +  qDebug().nospace() << "Added " << (e->isDir ? "Dir " : "File ") << path
 +    << (e->m_status == NonExistent ? " NotExisting" : "")
 +    << " for " << (sub_entry ? sub_entry->path : QString())
 +    << " [" << (instance ? instance->objectName() : QString()) << "]";
 +
 +  // now setup the notification method
 +  e->m_mode = UnknownMode;
 +  e->msecLeft = 0;
 +
 +  if ( isNoisyFile( QFile::encodeName( path ).data() ) )
 +    return;
 +
 +  if (exists && e->isDir && (watchModes != KDirWatch::WatchDirOnly)) {
 +    QFlags<QDir::Filter> filters = QDir::NoDotAndDotDot;
 +
 +    if ((watchModes & KDirWatch::WatchSubDirs) &&
 +        (watchModes & KDirWatch::WatchFiles)) {
 +      filters |= (QDir::Dirs|QDir::Files);
 +    } else if (watchModes & KDirWatch::WatchSubDirs) {
 +      filters |= QDir::Dirs;
 +    } else if (watchModes & KDirWatch::WatchFiles) {
 +      filters |= QDir::Files;
 +    }
 +
 +#if HAVE_SYS_INOTIFY_H
 +    if (e->m_mode == INotifyMode || (e->m_mode == UnknownMode && m_preferredMethod \
== KDirWatch::INotify)  )  +    {
 +        //kDebug(7001) << "Ignoring WatchFiles directive - this is implicit with \
inotify";  +        // Placing a watch on individual files is redundant with inotify
 +        // (inotify gives us WatchFiles functionality "for free") and indeed
 +        // actively harmful, so prevent it.  WatchSubDirs is necessary, though.
 +        filters &= ~QDir::Files;
 +    }
 +#endif
 +
 +    QDir basedir (e->path);
 +    const QFileInfoList contents = basedir.entryInfoList(filters);
 +    for (QFileInfoList::const_iterator iter = contents.constBegin();
 +         iter != contents.constEnd(); ++iter)
 +    {
 +      const QFileInfo &fileInfo = *iter;
 +      // treat symlinks as files--don't follow them.
 +      bool isDir = fileInfo.isDir() && !fileInfo.isSymLink();
 +
 +      addEntry (instance, fileInfo.absoluteFilePath(), 0, isDir,
 +                isDir ? watchModes : KDirWatch::WatchDirOnly);
 +    }
 +  }
 +
 +  addWatch(e);
 +}
 +
 +void KDirWatchPrivate::addWatch(Entry* e)
 +{
 +  // If the watch is on a network filesystem use the nfsPreferredMethod as the
 +  // default, otherwise use preferredMethod as the default, if the methods are
 +  // the same we can skip the mountpoint check
 +
 +  // This allows to configure a different method for NFS mounts, since inotify
 +  // cannot detect changes made by other machines. However as a default inotify
 +  // is fine, since the most common case is a NFS-mounted home, where all changes
 +  // are made locally. #177892.
 +  KDirWatch::Method preferredMethod = m_preferredMethod;
 +  if (m_nfsPreferredMethod != m_preferredMethod) {
 +    if (KFileSystemType::fileSystemType(e->path) == KFileSystemType::Nfs) {
 +      preferredMethod = m_nfsPreferredMethod;
 +    }
 +  }
 +
 +  // Try the appropriate preferred method from the config first
 +  bool entryAdded = false;
 +  switch (preferredMethod) {
 +#if HAVE_FAM
 +    case KDirWatch::FAM: entryAdded = useFAM(e); break;
 +#endif
 +#if HAVE_SYS_INOTIFY_H
 +    case KDirWatch::INotify: entryAdded = useINotify(e); break;
 +#endif
 +#if HAVE_QFILESYSTEMWATCHER
 +    case KDirWatch::QFSWatch: entryAdded = useQFSWatch(e); break;
 +#endif
 +    case KDirWatch::Stat: entryAdded = useStat(e); break;
 +    default: break;
 +  }
 +
 +  // Failing that try in order INotify, FAM, QFSWatch, Stat
 +  if (!entryAdded) {
 +#if HAVE_SYS_INOTIFY_H
 +    if (useINotify(e)) return;
 +#endif
 +#if HAVE_FAM
 +    if (useFAM(e)) return;
 +#endif
 +#if HAVE_QFILESYSTEMWATCHER
 +    if (useQFSWatch(e)) return;
 +#endif
 +    useStat(e);
 +  }
 +}
 +
 +void KDirWatchPrivate::removeWatch(Entry* e)
 +{
 +#if HAVE_FAM
 +    if (e->m_mode == FAMMode) {
 +        FAMCancelMonitor(&fc, &(e->fr) );
 +        qDebug().nospace()  << "Cancelled FAM (Req " << \
FAMREQUEST_GETREQNUM(&(e->fr))  +                                << ") for " << \
e->path;  +    }
 +#endif
 +#if HAVE_SYS_INOTIFY_H
 +    if (e->m_mode == INotifyMode) {
 +        (void) inotify_rm_watch( m_inotify_fd, e->wd );
 +        if (s_verboseDebug) {
 +            qDebug().nospace() << "Cancelled INotify (fd " << m_inotify_fd << ", "
 +                                   << e->wd << ") for " << e->path;
 +        }
 +    }
 +#endif
 +#if HAVE_QFILESYSTEMWATCHER
 +    if (e->m_mode == QFSWatchMode && fsWatcher) {
 +        if (s_verboseDebug)
 +            qDebug() << "fsWatcher->removePath" << e->path;
 +        fsWatcher->removePath(e->path);
 +    }
 +#endif
 +}
 +
 +void KDirWatchPrivate::removeEntry(KDirWatch* instance,
 +                                   const QString& _path,
 +                                   Entry* sub_entry)
 +{
 +  if (s_verboseDebug) {
 +    qDebug() << "path=" << _path << "sub_entry:" << sub_entry;
 +  }
 +  Entry* e = entry(_path);
 +  if (!e) {
 +    qWarning() << "doesn't know" << _path;
 +    return;
 +  }
 +
 +  removeEntry(instance, e, sub_entry);
 +}
 +
 +void KDirWatchPrivate::removeEntry(KDirWatch* instance,
 +                                   Entry* e,
 +                                   Entry* sub_entry)
 +{
 +  removeList.remove(e);
 +
 +  if (sub_entry)
 +    e->m_entries.removeAll(sub_entry);
 +  else
 +    e->removeClient(instance);
 +
 +  if (e->m_clients.count() || e->m_entries.count())
 +    return;
 +
 +  if (delayRemove) {
 +    removeList.insert(e);
 +    // now e->isValid() is false
 +    return;
 +  }
 +
 +    if ( e->m_status == Normal) {
 +        removeWatch(e);
 +    } else {
 +        // Removed a NonExistent entry - we just remove it from the parent
 +        if (e->isDir)
 +            removeEntry(0, e->parentDirectory(), e);
 +        else
 +            removeEntry(0, QFileInfo(e->path).absolutePath(), e);
 +    }
 +
 +  if (e->m_mode == StatMode) {
 +    statEntries--;
 +    if ( statEntries == 0 ) {
 +      timer.stop(); // stop timer if lists are empty
 +      qDebug() << " Stopped Polling Timer";
 +    }
 +  }
 +
 +  if (s_verboseDebug) {
 +    qDebug().nospace() << "Removed " << (e->isDir ? "Dir ":"File ") << e->path
 +                           << " for " << (sub_entry ? sub_entry->path : QString())
 +                           << " [" << (instance ? instance->objectName() : \
QString()) << "]";  +  }
 +  m_mapEntries.remove( e->path ); // <e> not valid any more
 +}
 +
 +
 +/* Called from KDirWatch destructor:
 + * remove <instance> as client from all entries
 + */
 +void KDirWatchPrivate::removeEntries( KDirWatch* instance )
 +{
 +  int minfreq = 3600000;
 +
 +  QStringList pathList;
 +  // put all entries where instance is a client in list
 +  EntryMap::Iterator it = m_mapEntries.begin();
 +  for( ; it != m_mapEntries.end(); ++it ) {
 +    Client* c = 0;
 +    Q_FOREACH(Client* client, (*it).m_clients) {
 +      if (client->instance == instance) {
 +        c = client;
 +        break;
 +      }
 +    }
 +    if (c) {
 +      c->count = 1; // forces deletion of instance as client
 +      pathList.append((*it).path);
 +    }
 +    else if ( (*it).m_mode == StatMode && (*it).freq < minfreq )
 +      minfreq = (*it).freq;
 +  }
 +
 +  Q_FOREACH(const QString &path, pathList)
 +    removeEntry(instance, path, 0);
 +
 +  if (minfreq > freq) {
 +    // we can decrease the global polling frequency
 +    freq = minfreq;
 +    if (timer.isActive()) timer.start(freq);
 +    qDebug() << "Poll Freq now" << freq << "msec";
 +  }
 +}
 +
 +// instance ==0: stop scanning for all instances
 +bool KDirWatchPrivate::stopEntryScan( KDirWatch* instance, Entry* e)
 +{
 +  int stillWatching = 0;
 +  Q_FOREACH(Client* client, e->m_clients) {
 +    if (!instance || instance == client->instance)
 +      client->watchingStopped = true;
 +    else if (!client->watchingStopped)
 +      stillWatching += client->count;
 +  }
 +
 +  qDebug()  << (instance ? instance->objectName() : QString::fromLatin1("all"))
 +                << "stopped scanning" << e->path << "(now"
 +                << stillWatching << "watchers)";
 +
 +  if (stillWatching == 0) {
 +    // if nobody is interested, we don't watch
 +    if ( e->m_mode != INotifyMode ) {
 +      e->m_ctime = invalid_ctime; // invalid
 +      e->m_status = NonExistent;
 +    }
 +    //    e->m_status = Normal;
 +  }
 +  return true;
 +}
 +
 +// instance ==0: start scanning for all instances
 +bool KDirWatchPrivate::restartEntryScan( KDirWatch* instance, Entry* e,
 +					 bool notify)
 +{
 +  int wasWatching = 0, newWatching = 0;
 +  Q_FOREACH(Client* client, e->m_clients) {
 +    if (!client->watchingStopped)
 +      wasWatching += client->count;
 +    else if (!instance || instance == client->instance) {
 +      client->watchingStopped = false;
 +      newWatching += client->count;
 +    }
 +  }
 +  if (newWatching == 0)
 +    return false;
 +
 +  qDebug()  << (instance ? instance->objectName() : QString::fromLatin1("all"))
 +                << "restarted scanning" << e->path
 +                << "(now" << wasWatching+newWatching << "watchers)";
 +
 +  // restart watching and emit pending events
 +
 +  int ev = NoChange;
 +  if (wasWatching == 0) {
 +    if (!notify) {
 +      QT_STATBUF stat_buf;
 +      bool exists = (QT_STAT(QFile::encodeName(e->path).constData(), &stat_buf) == \
0);  +      if (exists) {
 +#ifdef Q_OS_WIN
 +        // ctime is the 'creation time' on windows - use mtime instead
 +        e->m_ctime = stat_buf.st_mtime;
 +#else
 +        e->m_ctime = stat_buf.st_ctime;
 +#endif
 +        e->m_status = Normal;
 +        if (s_verboseDebug) {
 +          qDebug() << "Setting status to Normal for" << e << e->path;
 +        }
 +        e->m_nlink = stat_buf.st_nlink;
 +        e->m_ino = stat_buf.st_ino;
 +
 +        // Same as in scanEntry: ensure no subentry in parent dir
 +        removeEntry(0, e->parentDirectory(), e);
 +      }
 +      else {
 +        e->m_ctime = invalid_ctime;
 +        e->m_status = NonExistent;
 +        e->m_nlink = 0;
 +        if (s_verboseDebug) {
 +          qDebug() << "Setting status to NonExistent for" << e << e->path;
 +        }
 +      }
 +    }
 +    e->msecLeft = 0;
 +    ev = scanEntry(e);
 +  }
 +  emitEvent(e,ev);
 +
 +  return true;
 +}
 +
 +// instance ==0: stop scanning for all instances
 +void KDirWatchPrivate::stopScan(KDirWatch* instance)
 +{
 +  EntryMap::Iterator it = m_mapEntries.begin();
 +  for( ; it != m_mapEntries.end(); ++it )
 +    stopEntryScan(instance, &(*it));
 +}
 +
 +
 +void KDirWatchPrivate::startScan(KDirWatch* instance,
 +                                 bool notify, bool skippedToo )
 +{
 +  if (!notify)
 +    resetList(instance,skippedToo);
 +
 +  EntryMap::Iterator it = m_mapEntries.begin();
 +  for( ; it != m_mapEntries.end(); ++it )
 +    restartEntryScan(instance, &(*it), notify);
 +
 +  // timer should still be running when in polling mode
 +}
 +
 +
 +// clear all pending events, also from stopped
 +void KDirWatchPrivate::resetList( KDirWatch* /*instance*/, bool skippedToo )
 +{
 +  EntryMap::Iterator it = m_mapEntries.begin();
 +  for( ; it != m_mapEntries.end(); ++it ) {
 +
 +    Q_FOREACH(Client* client, (*it).m_clients) {
 +      if (!client->watchingStopped || skippedToo)
 +        client->pending = NoChange;
 +    }
 +  }
 +}
 +
 +// Return event happened on <e>
 +//
 +int KDirWatchPrivate::scanEntry(Entry* e)
 +{
 +  // Shouldn't happen: Ignore "unknown" notification method
 +  if (e->m_mode == UnknownMode) return NoChange;
 +
 +  if (e->m_mode == FAMMode || e->m_mode == INotifyMode) {
 +    // we know nothing has changed, no need to stat
 +    if(!e->dirty) return NoChange;
 +    e->dirty = false;
 +  }
 +
 +  if (e->m_mode == StatMode) {
 +    // only scan if timeout on entry timer happens;
 +    // e.g. when using 500msec global timer, a entry
 +    // with freq=5000 is only watched every 10th time
 +
 +    e->msecLeft -= freq;
 +    if (e->msecLeft>0) return NoChange;
 +    e->msecLeft += e->freq;
 +  }
 +
 +  QT_STATBUF stat_buf;
 +  const bool exists = (QT_STAT(QFile::encodeName(e->path).constData(), &stat_buf) \
== 0);  +  if (exists) {
 +
 +    if (e->m_status == NonExistent) {
 +      // ctime is the 'creation time' on windows, but with qMax
 +      // we get the latest change of any kind, on any platform.
 +      e->m_ctime = qMax(stat_buf.st_ctime, stat_buf.st_mtime);
 +      e->m_status = Normal;
 +      e->m_ino = stat_buf.st_ino;
 +      if (s_verboseDebug) {
 +        qDebug() << "Setting status to Normal for just created" << e << e->path;
 +      }
 +      // We need to make sure the entry isn't listed in its parent's subentries... \
(#222974, testMoveTo)  +      removeEntry(0, e->parentDirectory(), e);
 +
 +      return Created;
 +    }
 +
 +#if 1 // for debugging the if() below
 +    if (s_verboseDebug) {
 +      struct tm* tmp = localtime(&e->m_ctime);
 +      char outstr[200];
 +      strftime(outstr, sizeof(outstr), "%T", tmp);
 +      qDebug() << "e->m_ctime=" << e->m_ctime << outstr
 +                   << "stat_buf.st_ctime=" << stat_buf.st_ctime
 +                   << "e->m_nlink=" << e->m_nlink
 +                   << "stat_buf.st_nlink=" << stat_buf.st_nlink
 +                   << "e->m_ino=" << e->m_ino
 +                   << "stat_buf.st_ino=" << stat_buf.st_ino;
 +    }
 +#endif
 +
 +    if ( ((e->m_ctime != invalid_ctime) &&
 +          (qMax(stat_buf.st_ctime, stat_buf.st_mtime) != e->m_ctime ||
 +           stat_buf.st_ino != e->m_ino ||
 +           stat_buf.st_nlink != nlink_t(e->m_nlink)))
 +#ifdef Q_OS_WIN
 +          // we trust QFSW to get it right, the ctime comparisons above
 +          // fail for example when adding files to directories on Windows
 +          // which doesn't change the mtime of the directory
 +        || e->m_mode == QFSWatchMode
 +#endif
 +    ) {
 +      e->m_ctime = qMax(stat_buf.st_ctime, stat_buf.st_mtime);
 +      e->m_nlink = stat_buf.st_nlink;
 +      if (e->m_ino != stat_buf.st_ino) {
 +          // The file got deleted and recreated. We need to watch it again.
 +          removeWatch(e);
 +          addWatch(e);
 +      }
 +      e->m_ino = stat_buf.st_ino;
 +      return Changed;
 +    }
 +
 +    return NoChange;
 +  }
 +
 +  // dir/file doesn't exist
 +
 +  e->m_nlink = 0;
 +  e->m_ino = 0;
 +  e->m_status = NonExistent;
 +
 +  if (e->m_ctime == invalid_ctime) {
 +    return NoChange;
 +  }
 +
 +  e->m_ctime = invalid_ctime;
 +  return Deleted;
 +}
 +
 +/* Notify all interested KDirWatch instances about a given event on an entry
 + * and stored pending events. When watching is stopped, the event is
 + * added to the pending events.
 + */
 +void KDirWatchPrivate::emitEvent(const Entry* e, int event, const QString \
&fileName)  +{
 +  QString path (e->path);
 +  if (!fileName.isEmpty()) {
 +    if (!QDir::isRelativePath(fileName))
 +      path = fileName;
 +    else {
 +#ifdef Q_OS_UNIX
 +      path += QLatin1Char('/') + fileName;
 +#elif defined(Q_OS_WIN)
 +      //current drive is passed instead of /
 +      path += QDir::currentPath().left(2) + QLatin1Char('/') + fileName;
 +#endif
 +    }
 +  }
 +
 +  if (s_verboseDebug) {
 +    qDebug() << event << path << e->m_clients.count() << "clients";
 +  }
 +
 +  Q_FOREACH(Client* c, e->m_clients)
 +  {
 +    if (c->instance==0 || c->count==0) continue;
 +
 +    if (c->watchingStopped) {
 +      // add event to pending...
 +      if (event == Changed)
 +        c->pending |= event;
 +      else if (event == Created || event == Deleted)
 +        c->pending = event;
 +      continue;
 +    }
 +    // not stopped
 +    if (event == NoChange || event == Changed)
 +      event |= c->pending;
 +    c->pending = NoChange;
 +    if (event == NoChange) continue;
 +
 +    // Emit the signals delayed, to avoid unexpected re-entrancy from the slots \
(#220153)  +
 +    if (event & Deleted) {
 +      QMetaObject::invokeMethod(c->instance, "setDeleted", Qt::QueuedConnection, \
Q_ARG(QString, path));  +      // emit only Deleted event...
 +      continue;
 +    }
 +
 +    if (event & Created) {
 +      QMetaObject::invokeMethod(c->instance, "setCreated", Qt::QueuedConnection, \
Q_ARG(QString, path));  +      // possible emit Change event after creation
 +    }
 +
 +    if (event & Changed) {
 +      QMetaObject::invokeMethod(c->instance, "setDirty", Qt::QueuedConnection, \
Q_ARG(QString, path));  +    }
 +  }
 +}
 +
 +// Remove entries which were marked to be removed
 +void KDirWatchPrivate::slotRemoveDelayed()
 +{
 +  delayRemove = false;
 +  // Removing an entry could also take care of removing its parent
 +  // (e.g. in FAM or inotify mode), which would remove other entries in removeList,
 +  // so don't use Q_FOREACH or iterators here...
 +  while (!removeList.isEmpty()) {
 +    Entry* entry = *removeList.begin();
 +    removeEntry(0, entry, 0); // this will remove entry from removeList
 +  }
 +}
 +
 +/* Scan all entries to be watched for changes. This is done regularly
 + * when polling. FAM and inotify use a single-shot timer to call this slot delayed.
 + */
 +void KDirWatchPrivate::slotRescan()
 +{
 +  if (s_verboseDebug)
 +    qDebug();
 +
 +  EntryMap::Iterator it;
 +
 +  // People can do very long things in the slot connected to dirty(),
 +  // like showing a message box. We don't want to keep polling during
 +  // that time, otherwise the value of 'delayRemove' will be reset.
 +  // ### TODO: now the emitEvent delays emission, this can be cleaned up
 +  bool timerRunning = timer.isActive();
 +  if ( timerRunning )
 +    timer.stop();
 +
 +  // We delay deletions of entries this way.
 +  // removeDir(), when called in slotDirty(), can cause a crash otherwise
 +  // ### TODO: now the emitEvent delays emission, this can be cleaned up
 +  delayRemove = true;
 +
 +  if (rescan_all)
 +  {
 +    // mark all as dirty
 +    it = m_mapEntries.begin();
 +    for( ; it != m_mapEntries.end(); ++it )
 +      (*it).dirty = true;
 +    rescan_all = false;
 +  }
 +  else
 +  {
 +    // progate dirty flag to dependant entries (e.g. file watches)
 +    it = m_mapEntries.begin();
 +    for( ; it != m_mapEntries.end(); ++it )
 +      if (((*it).m_mode == INotifyMode || (*it).m_mode == QFSWatchMode) && \
(*it).dirty )  +        (*it).propagate_dirty();
 +  }
 +
 +#if HAVE_SYS_INOTIFY_H
 +  QList<Entry*> cList;
 +#endif
 +
 +  it = m_mapEntries.begin();
 +  for( ; it != m_mapEntries.end(); ++it ) {
 +    // we don't check invalid entries (i.e. remove delayed)
 +    Entry* entry = &(*it);
 +    if (!entry->isValid()) continue;
 +
 +    const int ev = scanEntry(entry);
 +    if (s_verboseDebug)
 +      qDebug() << "scanEntry for" << entry->path << "says" << ev;
 +
 +    switch(entry->m_mode) {
 +#if HAVE_SYS_INOTIFY_H
 +    case INotifyMode:
 +      if ( ev == Deleted ) {
 +        if (s_verboseDebug)
 +          qDebug() << "scanEntry says" << entry->path << "was deleted";
 +        addEntry(0, entry->parentDirectory(), entry, true);
 +      } else if (ev == Created) {
 +        if (s_verboseDebug)
 +          qDebug() << "scanEntry says" << entry->path << "was created. wd=" << \
entry->wd;  +        if (entry->wd < 0) {
 +          cList.append(entry);
 +          addWatch(entry);
 +        }
 +      }
 +      break;
 +#endif
 +    case FAMMode:
 +    case QFSWatchMode:
 +      if (ev == Created) {
 +        addWatch(entry);
 +      }
 +      break;
 +    default:
 +      // dunno about StatMode...
 +      break;
 +    }
 +
 +#if HAVE_SYS_INOTIFY_H
 +    if (entry->isDir) {
 +      // Report and clear the the list of files that have changed in this \
directory.  +      // Remove duplicates by changing to set and back again:
 +      // we don't really care about preserving the order of the
 +      // original changes.
 +      QStringList pendingFileChanges = entry->m_pendingFileChanges;
 +      pendingFileChanges.removeDuplicates();
 +      Q_FOREACH(const QString &changedFilename, pendingFileChanges) {
 +        if (s_verboseDebug) {
 +          qDebug() << "processing pending file change for" << changedFilename;
 +        }
 +        emitEvent(entry, Changed, changedFilename);
 +      }
 +      entry->m_pendingFileChanges.clear();
 +    }
 +#endif
 +
 +    if ( ev != NoChange ) {
 +      emitEvent(entry, ev);
 +    }
 +  }
 +
 +  if ( timerRunning )
 +    timer.start(freq);
 +
 +#if HAVE_SYS_INOTIFY_H
 +  // Remove watch of parent of new created directories
 +  Q_FOREACH(Entry* e, cList)
 +    removeEntry(0, e->parentDirectory(), e);
 +#endif
 +
 +  QTimer::singleShot(0, this, SLOT(slotRemoveDelayed()));
 +}
 +
 +bool KDirWatchPrivate::isNoisyFile( const char * filename )
 +{
 +  // $HOME/.X.err grows with debug output, so don't notify change
 +  if ( *filename == '.') {
 +    if (strncmp(filename, ".X.err", 6) == 0) return true;
 +    if (strncmp(filename, ".xsession-errors", 16) == 0) return true;
 +    // fontconfig updates the cache on every KDE app start
 +    // (inclusive kio_thumbnail slaves)
 +    if (strncmp(filename, ".fonts.cache", 12) == 0) return true;
 +  }
 +
 +  return false;
 +}
 +
 +#if HAVE_FAM
 +void KDirWatchPrivate::famEventReceived()
 +{
 +  static FAMEvent fe;
 +
 +  delayRemove = true;
 +
 +  //kDebug(7001) << "Fam event received";
 +
 +  while(use_fam && FAMPending(&fc)) {
 +    if (FAMNextEvent(&fc, &fe) == -1) {
 +      qWarning() << "FAM connection problem, switching to polling.";
 +      use_fam = false;
 +      delete sn; sn = 0;
 +
 +      // Replace all FAMMode entries with INotify/Stat
 +      EntryMap::Iterator it = m_mapEntries.begin();
 +      for( ; it != m_mapEntries.end(); ++it )
 +        if ((*it).m_mode == FAMMode && (*it).m_clients.count()>0) {
 +            Entry* e = &(*it);
 +            addWatch(e);
 +        }
 +    }
 +    else
 +      checkFAMEvent(&fe);
 +  }
 +
 +  QTimer::singleShot(0, this, SLOT(slotRemoveDelayed()));
 +}
 +
 +void KDirWatchPrivate::checkFAMEvent(FAMEvent* fe)
 +{
 +  //kDebug(7001);
 +
 +  // Don't be too verbose ;-)
 +  if ((fe->code == FAMExists) ||
 +      (fe->code == FAMEndExist) ||
 +      (fe->code == FAMAcknowledge)) return;
 +
 +  if ( isNoisyFile( fe->filename ) )
 +    return;
 +
 +  Entry* e = 0;
 +  EntryMap::Iterator it = m_mapEntries.begin();
 +  for( ; it != m_mapEntries.end(); ++it )
 +    if (FAMREQUEST_GETREQNUM(&( (*it).fr )) ==
 +       FAMREQUEST_GETREQNUM(&(fe->fr)) ) {
 +      e = &(*it);
 +      break;
 +    }
 +
 +  // Entry* e = static_cast<Entry*>(fe->userdata);
 +
 +  if (s_verboseDebug) { // don't enable this except when debugging, see #88538
 +    qDebug()  << "Processing FAM event ("
 +                << ((fe->code == FAMChanged) ? "FAMChanged" :
 +                    (fe->code == FAMDeleted) ? "FAMDeleted" :
 +                    (fe->code == FAMStartExecuting) ? "FAMStartExecuting" :
 +                    (fe->code == FAMStopExecuting) ? "FAMStopExecuting" :
 +                    (fe->code == FAMCreated) ? "FAMCreated" :
 +                    (fe->code == FAMMoved) ? "FAMMoved" :
 +                    (fe->code == FAMAcknowledge) ? "FAMAcknowledge" :
 +                    (fe->code == FAMExists) ? "FAMExists" :
 +                    (fe->code == FAMEndExist) ? "FAMEndExist" : "Unknown Code")
 +                  << ", " << fe->filename
 +                  << ", Req " << FAMREQUEST_GETREQNUM(&(fe->fr)) << ") e=" << e;
 +  }
 +
 +  if (!e) {
 +    // this happens e.g. for FAMAcknowledge after deleting a dir...
 +    //    kDebug(7001) << "No entry for FAM event ?!";
 +    return;
 +  }
 +
 +  if (e->m_status == NonExistent) {
 +    qDebug() << "FAM event for nonExistent entry " << e->path;
 +    return;
 +  }
 +
 +  // Delayed handling. This rechecks changes with own stat calls.
 +  e->dirty = true;
 +  if (!rescan_timer.isActive())
 +    rescan_timer.start(m_PollInterval); // singleshot
 +
 +    // needed FAM control actions on FAM events
 +    switch (fe->code) {
 +    case FAMDeleted:
 +        // fe->filename is an absolute path when a watched file-or-dir is deleted
 +        if (!QDir::isRelativePath(QFile::decodeName(fe->filename))) {
 +          FAMCancelMonitor(&fc, &(e->fr) ); // needed ?
 +          qDebug()  << "Cancelled FAMReq"
 +                        << FAMREQUEST_GETREQNUM(&(e->fr))
 +                        << "for" << e->path;
 +          e->m_status = NonExistent;
 +          e->m_ctime = invalid_ctime;
 +          emitEvent(e, Deleted, e->path);
++          // If the parent dir was already watched, tell it something changed
++          Entry* parentEntry = entry(e->parentDirectory());
++          if (parentEntry)
++              parentEntry->dirty = true;
 +          // Add entry to parent dir to notice if the entry gets recreated
 +          addEntry(0, e->parentDirectory(), e, true /*isDir*/);
 +        } else {
 +            // A file in this directory has been removed, and wasn't explicitly \
watched.  +            // We could still inform clients, like inotify does? But stat \
can't.  +            // For now we just marked e dirty and slotRescan will emit the \
dir as dirty.  +            //kDebug(7001) << "Got FAMDeleted for" << \
QFile::decodeName(fe->filename) << "in" << e->path << ". Absolute path -> NOOP!";  +  \
}  +        break;
 +
 +      case FAMCreated: {
 +          // check for creation of a directory we have to watch
 +        QString tpath(e->path + QLatin1Char('/') + \
QFile::decodeName(fe->filename));  +
 +        // This code is very similar to the one in inotifyEventReceived...
 +        Entry* sub_entry = e->findSubEntry(tpath);
 +        if (sub_entry /*&& sub_entry->isDir*/) {
 +          // We were waiting for this new file/dir to be created
 +          emitEvent(sub_entry, Created);
 +          sub_entry->dirty = true;
 +          rescan_timer.start(0); // process this asap, to start watching that dir
 +        } else if (e->isDir && !e->m_clients.empty()) {
 +          bool isDir = false;
 +          const QList<Client *> clients = e->clientsForFileOrDir(tpath, &isDir);
 +          Q_FOREACH(Client *client, clients) {
 +            addEntry (client->instance, tpath, 0, isDir,
 +                      isDir ? client->m_watchModes : KDirWatch::WatchDirOnly);
 +          }
 +
 +          if (!clients.isEmpty()) {
 +            emitEvent(e, Created, tpath);
 +
 +            qDebug().nospace() << clients.count() << " instance(s) monitoring the \
new "  +                                   << (isDir ? "dir " : "file ") << tpath;
 +          }
 +        }
 +      }
 +        break;
 +      default:
 +        break;
 +    }
 +}
 +#else
 +void KDirWatchPrivate::famEventReceived()
 +{
 +    qWarning () << "Fam event received but FAM is not supported";
 +}
 +#endif
 +
 +
 +void KDirWatchPrivate::statistics()
 +{
 +  EntryMap::Iterator it;
 +
 +  qDebug() << "Entries watched:";
 +  if (m_mapEntries.count()==0) {
 +    qDebug() << "  None.";
 +  }
 +  else {
 +    it = m_mapEntries.begin();
 +    for( ; it != m_mapEntries.end(); ++it ) {
 +      Entry* e = &(*it);
 +      qDebug() << "  " << *e;
 +
 +      Q_FOREACH(Client* c, e->m_clients) {
 +        QByteArray pending;
 +        if (c->watchingStopped) {
 +          if (c->pending & Deleted) pending += "deleted ";
 +          if (c->pending & Created) pending += "created ";
 +          if (c->pending & Changed) pending += "changed ";
 +          if (!pending.isEmpty()) pending = " (pending: " + pending + ')';
 +          pending = ", stopped" + pending;
 +        }
 +        qDebug()  << "    by " << c->instance->objectName()
 +                  << " (" << c->count << " times)" << pending;
 +      }
 +      if (e->m_entries.count()>0) {
 +        qDebug() << "    dependent entries:";
 +        Q_FOREACH(Entry *d, e->m_entries) {
 +          qDebug() << "      " << d << d->path << (d->m_status == NonExistent ? \
"NonExistent" : "EXISTS!!! ERROR!");  +          if (s_verboseDebug) {
 +            Q_ASSERT(d->m_status == NonExistent); // it doesn't belong here \
otherwise  +          }
 +        }
 +      }
 +    }
 +  }
 +}
 +
 +#if HAVE_QFILESYSTEMWATCHER
 +// Slot for QFileSystemWatcher
 +void KDirWatchPrivate::fswEventReceived(const QString &path)
 +{
 +  if (s_verboseDebug)
 +    qDebug() << path;
 +  EntryMap::Iterator it = m_mapEntries.find(path);
 +  if(it != m_mapEntries.end()) {
 +    Entry* e = &(*it);
 +    e->dirty = true;
 +    const int ev = scanEntry(e);
 +    if (s_verboseDebug)
 +      qDebug() << "scanEntry for" << e->path << "says" << ev;
 +    if (ev != NoChange)
 +      emitEvent(e, ev);
 +    if(ev == Deleted) {
 +      if (e->isDir)
 +        addEntry(0, e->parentDirectory(), e, true);
 +      else
 +        addEntry(0, QFileInfo(e->path).absolutePath(), e, true);
 +    } else if (ev == Created) {
 +      // We were waiting for it to appear; now watch it
 +      addWatch(e);
 +    } else if (e->isDir) {
 +      // Check if any file or dir was created under this directory, that we were \
waiting for  +      Q_FOREACH(Entry* sub_entry, e->m_entries) {
 +          fswEventReceived(sub_entry->path); // recurse, to call scanEntry and see \
if something changed  +      }
 +    }
 +  }
 +}
 +#else
 +void KDirWatchPrivate::fswEventReceived(const QString &path)
 +{
 +    Q_UNUSED(path);
 +    qWarning () << "QFileSystemWatcher event received but QFileSystemWatcher is not \
supported";  +}
 +#endif    // HAVE_QFILESYSTEMWATCHER
 +
 +//
 +// Class KDirWatch
 +//
 +
 +Q_GLOBAL_STATIC(KDirWatch, s_pKDirWatchSelf)
 +KDirWatch* KDirWatch::self()
 +{
 +  return s_pKDirWatchSelf();
 +}
 +
 +// <steve> is this used anywhere?
 +// <dfaure> yes, see kio/kdirlister_p.h:328
 +bool KDirWatch::exists()
 +{
 +#pragma message("Qt5 TODO: use new Q_GLOBAL_STATIC isDestroyed")
 +//  return s_pKDirWatchSelf.exists();
 +    return true;
 +}
 +
 +static void cleanupQFSWatcher()
 +{
 +  s_pKDirWatchSelf()->deleteQFSWatcher();
 +}
 +
 +KDirWatch::KDirWatch (QObject* parent)
 +  : QObject(parent), d(createPrivate())
 +{
 +  static int nameCounter = 0;
 +
 +  nameCounter++;
 +  setObjectName(QString::fromLatin1("KDirWatch-%1").arg(nameCounter) );
 +
 +  d->ref();
 +
 +  d->_isStopped = false;
 +
 +    static bool cleanupRegistered = false;
 +    if (!cleanupRegistered) {
 +        cleanupRegistered = true;
 +        // Must delete QFileSystemWatcher before qApp is gone - bug 261541
 +        qAddPostRoutine(cleanupQFSWatcher);
 +    }
 +}
 +
 +KDirWatch::~KDirWatch()
 +{
 +  d->removeEntries(this);
 +  if ( d->deref() )
 +  {
 +    // delete it if it's the last one
 +    delete d;
 +    dwp_self = 0;
 +  }
 +}
 +
 +void KDirWatch::addDir( const QString& _path, WatchModes watchModes)
 +{
 +  if (d) d->addEntry(this, _path, 0, true, watchModes);
 +}
 +
 +void KDirWatch::addFile( const QString& _path )
 +{
 +  if ( !d )
 +	return;
 +
 +  d->addEntry(this, _path, 0, false);
 +}
 +
 +QDateTime KDirWatch::ctime( const QString &_path ) const
 +{
 +  KDirWatchPrivate::Entry* e = d->entry(_path);
 +
 +  if (!e)
 +    return QDateTime();
 +
 +  return QDateTime::fromTime_t(e->m_ctime);
 +}
 +
 +void KDirWatch::removeDir( const QString& _path )
 +{
 +  if (d) d->removeEntry(this, _path, 0);
 +}
 +
 +void KDirWatch::removeFile( const QString& _path )
 +{
 +  if (d) d->removeEntry(this, _path, 0);
 +}
 +
 +bool KDirWatch::stopDirScan( const QString& _path )
 +{
 +  if (d) {
 +    KDirWatchPrivate::Entry *e = d->entry(_path);
 +    if (e && e->isDir) return d->stopEntryScan(this, e);
 +  }
 +  return false;
 +}
 +
 +bool KDirWatch::restartDirScan( const QString& _path )
 +{
 +  if (d) {
 +    KDirWatchPrivate::Entry *e = d->entry(_path);
 +    if (e && e->isDir)
 +      // restart without notifying pending events
 +      return d->restartEntryScan(this, e, false);
 +  }
 +  return false;
 +}
 +
 +void KDirWatch::stopScan()
 +{
 +  if (d) {
 +    d->stopScan(this);
 +    d->_isStopped = true;
 +  }
 +}
 +
 +bool KDirWatch::isStopped()
 +{
 +  return d->_isStopped;
 +}
 +
 +void KDirWatch::startScan( bool notify, bool skippedToo )
 +{
 +  if (d) {
 +    d->_isStopped = false;
 +    d->startScan(this, notify, skippedToo);
 +  }
 +}
 +
 +
 +bool KDirWatch::contains( const QString& _path ) const
 +{
 +  KDirWatchPrivate::Entry* e = d->entry(_path);
 +  if (!e)
 +     return false;
 +
 +  Q_FOREACH(KDirWatchPrivate::Client* client, e->m_clients) {
 +    if (client->instance == this)
 +      return true;
 +  }
 +
 +  return false;
 +}
 +
 +void KDirWatch::deleteQFSWatcher()
 +{
 +  delete d->fsWatcher;
 +  d->fsWatcher = 0;
 +}
 +
 +void KDirWatch::statistics()
 +{
 +  if (!dwp_self) {
 +    qDebug() << "KDirWatch not used";
 +    return;
 +  }
 +  dwp_self->statistics();
 +}
 +
 +
 +void KDirWatch::setCreated( const QString & _file )
 +{
 +  qDebug() << objectName() << "emitting created" << _file;
 +  Q_EMIT created( _file );
 +}
 +
 +void KDirWatch::setDirty( const QString & _file )
 +{
 +  //kDebug(7001) << objectName() << "emitting dirty" << _file;
 +  Q_EMIT dirty( _file );
 +}
 +
 +void KDirWatch::setDeleted( const QString & _file )
 +{
 +  qDebug() << objectName() << "emitting deleted" << _file;
 +  Q_EMIT deleted( _file );
 +}
 +
 +KDirWatch::Method KDirWatch::internalMethod() const
 +{
 +  return d->m_preferredMethod;
 +}
 +
 +
 +#include "moc_kdirwatch.cpp"
 +#include "moc_kdirwatch_p.cpp"
 +
 +//sven
diff --cc tier1/solid/src/solid/CMakeLists.txt
index 323ba1f,0000000..9b225e4
mode 100644,000000..100644
--- a/tier1/solid/src/solid/CMakeLists.txt
+++ b/tier1/solid/src/solid/CMakeLists.txt
@@@ -1,466 -1,0 +1,478 @@@
 +include (CheckCXXSourceCompiles)
 +
 +if(MSVC)
 +    check_cxx_source_compiles("int main() { __asm { pxor mm0, mm0 }; }" \
HAVE_X86_MMX)  +    check_cxx_source_compiles("int main() { __asm { xorps xmm0, xmm0 \
}; }" HAVE_X86_SSE)  +    check_cxx_source_compiles("int main() { __asm { xorpd xmm0, \
xmm0 }; }" HAVE_X86_SSE2)  +    check_cxx_source_compiles("int main() { __asm { femms \
}; }" HAVE_X86_3DNOW)  +else(MSVC)
 +    check_cxx_source_compiles("	    #ifdef __SUNPRO_CC
 +                                            #define __asm__ asm
 +                                    #endif
 +                    int main() { __asm__(\"pxor %mm0, %mm0\") ; }" HAVE_X86_MMX)
 +    check_cxx_source_compiles("     #ifdef __SUNPRO_CC
 +                                            #define __asm__ asm
 +                                    #endif
 +                    int main() { __asm__(\"xorps %xmm0, %xmm0\"); }" HAVE_X86_SSE)
 +    check_cxx_source_compiles("     #ifdef __SUNPRO_CC
 +                                            #define __asm__ asm
 +                                    #endif
 +                    int main() { __asm__(\"xorpd %xmm0, %xmm0\"); }" HAVE_X86_SSE2)
 +    check_cxx_source_compiles("     #ifdef __SUNPRO_CC
 +                                            #define __asm__ asm
 +                                    #endif
 +                    int main() { __asm__(\"femms\"); }" HAVE_X86_3DNOW)
 +endif(MSVC)
 +check_cxx_source_compiles("     #ifdef __SUNPRO_CC
 +                                        #define __asm__ asm
 +                                #endif
 +				int main() { __asm__(\"mtspr 256, %0; vand %%v0, %%v0, %%v0\" : : \"r\"(-1) ); \
}" HAVE_PPC_ALTIVEC)  +
 +configure_file(config-processor.h.cmake \
${CMAKE_CURRENT_BINARY_DIR}/config-processor.h )  +
 +
 +
 +########### next target ###############
 +
 +file(MAKE_DIRECTORY
 +   ${CMAKE_CURRENT_BINARY_DIR}/backends/fakehw
 +   ${CMAKE_CURRENT_BINARY_DIR}/backends/hal
 +   ${CMAKE_CURRENT_BINARY_DIR}/backends/udev
 +   ${CMAKE_CURRENT_BINARY_DIR}/backends/wmi
 +)
 +
 +if(WIN32)
 +    add_definitions(-DYY_NO_UNISTD_H)
 +endif(WIN32)
 +
 +set(solid_LIB_SRCS
 +   solidnamespace.cpp
 +   managerbase.cpp
 +   device.cpp
 +   devicemanager.cpp
 +   deviceinterface.cpp
 +   genericinterface.cpp
 +   processor.cpp
 +   block.cpp
 +   storagedrive.cpp
 +   opticaldrive.cpp
 +   storagevolume.cpp
 +   opticaldisc.cpp
 +   storageaccess.cpp
 +   camera.cpp
 +   portablemediaplayer.cpp
 +   networkinterface.cpp
 +   networkshare.cpp
 +   serialinterface.cpp
 +   acadapter.cpp
 +   battery.cpp
 +   button.cpp
 +   audiointerface.cpp
 +   dvbinterface.cpp
 +   predicate.cpp
 +   predicateparse.cpp
 +   predicate_lexer.c
 +   predicate_parser.c
 +   powermanagement.cpp
 +   networking.cpp
 +   video.cpp
 +   smartcardreader.cpp
 +   internetgateway.cpp
 +
 +   ifaces/acadapter.cpp
 +   ifaces/audiointerface.cpp
 +   ifaces/battery.cpp
 +   ifaces/block.cpp
 +   ifaces/button.cpp
 +   ifaces/camera.cpp
 +   ifaces/opticaldrive.cpp
 +   ifaces/device.cpp
 +   ifaces/deviceinterface.cpp
 +   ifaces/devicemanager.cpp
 +   ifaces/dvbinterface.cpp
 +   ifaces/genericinterface.cpp
 +   ifaces/networkinterface.cpp
 +   ifaces/networkshare.cpp
 +   ifaces/serialinterface.cpp
 +   ifaces/opticaldisc.cpp
 +   ifaces/portablemediaplayer.cpp
 +   ifaces/processor.cpp
 +   ifaces/storagedrive.cpp
 +   ifaces/storagevolume.cpp
 +   ifaces/storageaccess.cpp
 +   ifaces/video.cpp
 +   ifaces/smartcardreader.cpp
 +   ifaces/internetgateway.cpp
 +
 +   backends/fakehw/fakeacadapter.cpp
 +   backends/fakehw/fakeaudiointerface.cpp
 +   backends/fakehw/fakebattery.cpp
 +   backends/fakehw/fakeblock.cpp
 +   backends/fakehw/fakebutton.cpp
 +   backends/fakehw/fakecamera.cpp
 +   backends/fakehw/fakecdrom.cpp
 +   backends/fakehw/fakedevice.cpp
 +   backends/fakehw/fakedeviceinterface.cpp
 +   backends/fakehw/fakedvbinterface.cpp
 +   backends/fakehw/fakegenericinterface.cpp
 +   backends/fakehw/fakemanager.cpp
 +   backends/fakehw/fakenetworkshare.cpp
 +   backends/fakehw/fakenetworkinterface.cpp
 +   backends/fakehw/fakeopticaldisc.cpp
 +   backends/fakehw/fakeportablemediaplayer.cpp
 +   backends/fakehw/fakeprocessor.cpp
 +   backends/fakehw/fakestorage.cpp
 +   backends/fakehw/fakestorageaccess.cpp
 +   backends/fakehw/fakevideo.cpp
 +   backends/fakehw/fakevolume.cpp
 +   backends/fakehw/fakesmartcardreader.cpp
 +
 +   backends/shared/rootdevice.cpp
 +   backends/shared/cpufeatures.cpp
 +)
 +
- if ( HUPNP_FOUND )
-   include_directories( ${HUPNP_INCLUDE_DIR} )
-   message(STATUS "Building Solid UPnP backend." )
-   set(solid_LIB_SRCS ${solid_LIB_SRCS}
-       backends/upnp/upnpdevice.cpp
-       backends/upnp/upnpdevicemanager.cpp
-       backends/upnp/upnpdeviceinterface.cpp
-       backends/upnp/upnpmediaserver.cpp
-       backends/upnp/upnpinternetgateway.cpp
-       backends/upnp/upnpcontrolpoint.cpp
-   )
- endif ()
++if(NOT APPLE)
++  set(HUPNP_ENABLED FALSE CACHE BOOL "explicitly enable the compilation of the \
hupnp backend") ++  if (HUPNP_ENABLED AND HUPNP_FOUND AND ((HUPNP_VERSION_MAJOR EQUAL \
0 AND HUPNP_VERSION_MINOR EQUAL 9) OR (HUPNP_VERSION_MAJOR EQUAL 1))) ++    \
include_directories( ${HUPNP_INCLUDE_DIR} ) ++    message(STATUS "Building Solid UPnP \
backend." ) ++    set(solid_LIB_SRCS ${solid_LIB_SRCS}
++       backends/upnp/upnpdevice.cpp
++       backends/upnp/upnpdevicemanager.cpp
++       backends/upnp/upnpdeviceinterface.cpp
++       backends/upnp/upnpmediaserver.cpp
++       backends/upnp/upnpinternetgateway.cpp
++       backends/upnp/upnpcontrolpoint.cpp
++    )
++  else ()
++    if(NOT HUPNP_ENABLED)
++        message(STATUS "To have UPnP support, explicitly enable HUPNP_ENABLED in \
the cmake cache") ++    endif(NOT HUPNP_ENABLED)
++    set(HUPNP_FOUND false)
++  endif ()
++endif(NOT APPLE)
 +
 +if(NOT WIN32 AND NOT APPLE)
 +#   message(STATUS "Building Solid KUPnP backend." )
 +#   set(solid_LIB_SRCS ${solid_LIB_SRCS}
 +
 +#   backends/kupnp/cagibidbuscodec.cpp
 +#   backends/kupnp/cagibidevice.cpp
 +#   backends/kupnp/kupnpstorageaccess.cpp
 +#   backends/kupnp/kupnpdeviceinterface.cpp
 +#   backends/kupnp/mediaserver1.cpp
 +#   backends/kupnp/mediaserver2.cpp
 +#   backends/kupnp/mediaserver3.cpp
 +#   backends/kupnp/internetgatewaydevice1.cpp
 +#   backends/kupnp/kupnpdevice.cpp
 +#   backends/kupnp/kupnprootdevice.cpp
 +#   backends/kupnp/kupnpmanager.cpp
 +
 +#   )
 +
 +   if ( UDEV_FOUND )
 +      message(STATUS "Building Solid UDev backend." )
 +      set(solid_LIB_SRCS ${solid_LIB_SRCS}
 +      backends/udev/udevdevice.cpp
 +      backends/udev/udevmanager.cpp
 +      backends/udev/udevdeviceinterface.cpp
 +      backends/udev/udevgenericinterface.cpp
 +      backends/udev/cpuinfo.cpp
 +      backends/udev/udevprocessor.cpp
 +      backends/udev/udevcamera.cpp
 +      backends/udev/udevvideo.cpp
 +      backends/udev/udevaudiointerface.cpp
 +      backends/udev/udevnetworkinterface.cpp
 +      backends/udev/udevserialinterface.cpp
 +      backends/udev/udevaudiointerface_p.cpp
 +      backends/udev/udevportablemediaplayer.cpp
 +      backends/udev/udevdvbinterface.cpp
 +      backends/udev/udevblock.cpp
 +      backends/shared/udevqtclient.cpp
 +      backends/shared/udevqtdevice.cpp
 +      )
++      set(UDEV_DETAILED_OUTPUT OFF CACHE BOOL "provide extended output regarding \
udev events") ++      if(UDEV_DETAILED_OUTPUT)
++         add_definitions(-DUDEV_DETAILED_OUTPUT)
++      endif(UDEV_DETAILED_OUTPUT)
 +
 +      # check for media-player-info (runtime-only optional dependency)
 +      find_package(MediaPlayerInfo)
 +      set_package_properties(MediaPlayerInfo PROPERTIES
 +         DESCRIPTION "Enables identification and querying of portable media \
players"  +         PURPOSE "Runtime-only dependency of the udev solid backend. \
Support for m-p-i is included even if not found during build"  +         URL \
"http://www.freedesktop.org/wiki/Software/media-player-info"  +         TYPE RUNTIME
 +      )
 +   endif( UDEV_FOUND )
 +
 +
 +   message(STATUS "Building Solid HAL backend." )
 +   set(solid_LIB_SRCS ${solid_LIB_SRCS}
 +      backends/hal/halacadapter.cpp
 +      backends/hal/halaudiointerface.cpp
 +      backends/hal/halbattery.cpp
 +      backends/hal/halblock.cpp
 +      backends/hal/halbutton.cpp
 +      backends/hal/halcamera.cpp
 +      backends/hal/halcdrom.cpp
 +      backends/hal/haldeviceinterface.cpp
 +      backends/hal/haldvbinterface.cpp
 +      backends/hal/halfstabhandling.cpp
 +      backends/hal/halgenericinterface.cpp
 +      backends/hal/haldevice.cpp
 +      backends/hal/halmanager.cpp
 +      backends/hal/halnetworkinterface.cpp
 +      backends/hal/halserialinterface.cpp
 +      backends/hal/halopticaldisc.cpp
 +      backends/hal/halportablemediaplayer.cpp
 +      backends/hal/halprocessor.cpp
 +      backends/hal/halstorageaccess.cpp
 +      backends/hal/halstorage.cpp
 +      backends/hal/halvideo.cpp
 +      backends/hal/halvolume.cpp
 +      backends/hal/halsmartcardreader.cpp
 +   )
 +
 +   message(STATUS "Building Solid UPower backend." )
 +   set(solid_LIB_SRCS ${solid_LIB_SRCS}
 +      backends/upower/upowermanager.cpp
 +      backends/upower/upowerdevice.cpp
 +      backends/upower/upowerbattery.cpp
 +      backends/upower/upoweracadapter.cpp
 +      backends/upower/upowerdeviceinterface.cpp
 +      backends/upower/upowergenericinterface.cpp
 +   )
 +
 +   # FIXME: this should work on more Unix systems
 +   if (CMAKE_SYSTEM_NAME MATCHES Linux)
 +       if ( WITH_SOLID_UDISKS2 )
 +           message(STATUS "Building Solid UDisks2 backend." )
 +           add_definitions(-DWITH_SOLID_UDISKS2)
 +           set(solid_LIB_SRCS ${solid_LIB_SRCS}
 +           backends/udisks2/udisksmanager.cpp
 +           backends/udisks2/udisksdevice.cpp
 +           backends/udisks2/udisksdevicebackend.cpp
 +           backends/udisks2/udisksblock.cpp
 +           backends/udisks2/udisksstoragevolume.cpp
 +           backends/udisks2/udisksdeviceinterface.cpp
 +           backends/udisks2/udisksopticaldisc.cpp
 +           backends/udisks2/udisksopticaldrive.cpp
 +           backends/udisks2/udisksstoragedrive.cpp
 +           backends/udisks2/udisksstorageaccess.cpp
 +           backends/udisks2/udisksgenericinterface.cpp
 +           backends/udisks2/dbus/manager.cpp
 +           )
 +       else ( WITH_SOLID_UDISKS2 )
 +           message(STATUS "Building Solid UDisks backend." )
 +           set(solid_LIB_SRCS ${solid_LIB_SRCS}
 +           backends/udisks/udisksmanager.cpp
 +           backends/udisks/udisksdevice.cpp
 +           backends/udisks/udisksblock.cpp
 +           backends/udisks/udisksstoragevolume.cpp
 +           backends/udisks/udisksdeviceinterface.cpp
 +           backends/udisks/udisksopticaldisc.cpp
 +           backends/udisks/udisksopticaldrive.cpp
 +           backends/udisks/udisksstoragedrive.cpp
 +           backends/udisks/udisksstorageaccess.cpp
 +           backends/udisks/udisksgenericinterface.cpp
 +          )
 +       endif ( WITH_SOLID_UDISKS2 )
 +   endif (CMAKE_SYSTEM_NAME MATCHES Linux)
 +
 +   message(STATUS "Building Solid fstab backend." )
 +   set(solid_LIB_SRCS ${solid_LIB_SRCS}
 +      backends/fstab/fstabmanager.cpp
 +      backends/fstab/fstabdevice.cpp
 +      backends/fstab/fstabnetworkshare.cpp
 +      backends/fstab/fstabstorageaccess.cpp
 +      backends/fstab/fstabhandling.cpp
 +      backends/fstab/fstabwatcher.cpp
 +   )
 +
 +endif(NOT WIN32 AND NOT APPLE)
 +
 +include(CheckIncludeFiles)
 +include(CheckFunctionExists)
 +include(CheckCXXSourceCompiles)
 +
 +check_include_files(mntent.h      HAVE_MNTENT_H)
 +check_include_files(sys/types.h   HAVE_SYS_TYPES_H)
 +check_include_files(sys/param.h   HAVE_SYS_PARAM_H)
 +check_include_files("stdio.h;sys/mnttab.h"  HAVE_SYS_MNTTAB_H)
 +check_include_files("sys/param.h;sys/mount.h"  HAVE_SYS_MOUNT_H)
 +
 +check_function_exists(getmntinfo HAVE_GETMNTINFO)
 +
 +check_function_exists(setmntent  HAVE_SETMNTENT)
 +
 +check_cxx_source_compiles("
 +  #include <sys/types.h>
 +  #include <sys/statvfs.h>
 +  int main(){
 +    struct statvfs *mntbufp;
 +    int flags;
 +    return getmntinfo(&mntbufp, flags);
 +  }
 +" GETMNTINFO_USES_STATVFS )
 +
 +configure_file( config-solid.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-solid.h )
 +
 +if(APPLE)
 +   find_package(IOKit REQUIRED)
 +
 +   message(STATUS "-- Building Solid IOKit backend." )
 +   set(solid_LIB_SRCS ${solid_LIB_SRCS}
 +      backends/iokit/iokitmanager.cpp
 +      backends/iokit/iokitdevice.cpp
 +      backends/iokit/cfhelper.cpp
 +      backends/iokit/iokitdeviceinterface.cpp
 +      backends/iokit/iokitgenericinterface.cpp
 +      backends/iokit/iokitprocessor.cpp
 +      backends/iokit/iokitnetworkinterface.cpp
 +      backends/iokit/iokitserialinterface.cpp
 +      backends/iokit/iokitbattery.cpp
 +   )
 +endif(APPLE)
 +
 +if(WIN32)
 +
 +   if(WBEM_FOUND)
 +       set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_WBEM")
 +       message(STATUS "-- Building Solid WMI backend." )
 +
 +       set(solid_LIB_SRCS ${solid_LIB_SRCS}
 +          backends/wmi/wmiacadapter.cpp
 +          backends/wmi/wmiaudiointerface.cpp
 +          backends/wmi/wmibattery.cpp
 +          backends/wmi/wmiblock.cpp
 +          backends/wmi/wmibutton.cpp
 +          backends/wmi/wmicamera.cpp
 +          backends/wmi/wmicdrom.cpp
 +          backends/wmi/wmideviceinterface.cpp
 +          backends/wmi/wmidvbinterface.cpp
 +          backends/wmi/wmigenericinterface.cpp
 +          backends/wmi/wmidevice.cpp
 +          backends/wmi/wmimanager.cpp
 +          backends/wmi/wminetworkinterface.cpp
 +          backends/wmi/wmiopticaldisc.cpp
 +          backends/wmi/wmiportablemediaplayer.cpp
 +          backends/wmi/wmiprocessor.cpp
 +          backends/wmi/wmiquery.cpp
 +          backends/wmi/wmistorageaccess.cpp
 +          backends/wmi/wmistorage.cpp
 +          backends/wmi/wmivideo.cpp
 +          backends/wmi/wmivolume.cpp
 +       )
 +    endif()
 +endif(WIN32)
 +
 +set_source_files_properties( org.freedesktop.PowerManagement.xml
 +                             org.freedesktop.PowerManagement.Inhibit.xml
 +                             org.kde.Solid.PowerManagement.PolicyAgent.xml
 +                             PROPERTIES NO_NAMESPACE TRUE)
 +
 +qt4_add_dbus_interfaces(solid_LIB_SRCS org.freedesktop.PowerManagement.xml
 +                        org.freedesktop.PowerManagement.Inhibit.xml
 +                        org.kde.Solid.PowerManagement.PolicyAgent.xml)
 +
 +qt4_add_dbus_interface(solid_LIB_SRCS org.kde.Solid.Networking.Client.xml
 +                       org_kde_solid_networking_client)
 +
 +set(solid_OPTIONAL_LIBS)
 +
 +if(WIN32)
 +   if(WBEM_FOUND)
 +      set(solid_OPTIONAL_LIBS ${solid_OPTIONAL_LIBS} ${WBEM_LIBRARIES})
 +   endif()
 +endif()
 +
 +if(APPLE)
 +   set(solid_OPTIONAL_LIBS ${IOKIT_LIBRARY})
 +endif()
 +
 +if ( HUPNP_FOUND )
 +   set(solid_OPTIONAL_LIBS ${solid_OPTIONAL_LIBS} ${HUPNP_LIBS})
 +endif()
 +
 +if ( UDEV_FOUND )
 +   set(solid_OPTIONAL_LIBS ${solid_OPTIONAL_LIBS} ${UDEV_LIBS})
 +endif ()
 +
 +add_library(Solid  ${solid_LIB_SRCS})
 +target_include_directories(Solid PUBLIC \
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..;${CMAKE_CURRENT_BINARY_DIR}/..>")  \
+generate_export_header(Solid)  +
 +target_link_libraries(Solid LINK_PUBLIC ${QT_QTCORE_LIBRARY}
 +                            LINK_PRIVATE ${QT_QTDBUS_LIBRARY}
 +                                         ${QT_QTXML_LIBRARY}
 +                                         Qt5::Widgets
 +                                         ${solid_OPTIONAL_LIBS}
 + )
 +
 +set_target_properties(Solid PROPERTIES  VERSION ${SOLID_VERSION_STRING}
 +                                        SOVERSION ${SOLID_SOVERSION} )
 +
 +install(TARGETS Solid EXPORT SolidTargets ${INSTALL_TARGETS_DEFAULT_ARGS})
 +
 +install(FILES org.kde.Solid.Networking.Client.xml
 +              org.kde.Solid.PowerManagement.PolicyAgent.xml
 +              org.freedesktop.PowerManagement.xml
 +              org.freedesktop.PowerManagement.Inhibit.xml
 +        DESTINATION ${DBUS_INTERFACES_INSTALL_DIR})
 +
 +########### static lib for tests  ###############
 +
 +add_library(Solid_static STATIC ${solid_LIB_SRCS})
 +set_target_properties(Solid_static PROPERTIES COMPILE_FLAGS \
-DSOLID_STATIC_DEFINE=1)  +
 +target_link_libraries(Solid_static LINK_PUBLIC ${QT_QTCORE_LIBRARY})
 +target_link_libraries(Solid_static ${QT_QTDBUS_LIBRARY} ${QT_QTXML_LIBRARY} \
Qt5::Widgets ${solid_OPTIONAL_LIBS})  +target_include_directories(Solid_static PUBLIC \
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..;${CMAKE_CURRENT_BINARY_DIR}/..>")  \
+  +########### install files ###############
 +
 +install( FILES ${CMAKE_CURRENT_BINARY_DIR}/solid_export.h solidnamespace.h device.h
 +               devicenotifier.h deviceinterface.h genericinterface.h processor.h \
block.h  +               storageaccess.h storagedrive.h opticaldrive.h \
storagevolume.h opticaldisc.h  +               camera.h portablemediaplayer.h \
networkinterface.h acadapter.h battery.h  +               button.h audiointerface.h \
dvbinterface.h predicate.h powermanagement.h  +               networking.h video.h \
serialinterface.h smartcardreader.h internetgateway.h  +               networkshare.h
 +         DESTINATION ${INCLUDE_INSTALL_DIR}/solid COMPONENT Devel)
 +
 +########### parser build ###############
 +
 +set(lexer_FILE predicate_lexer)
 +set(parser_FILE predicate_parser)
 +
 +find_package(FLEX)
 +set_package_properties(FLEX PROPERTIES DESCRIPTION "Allows the Solid predicate \
parser to be updated"  +                       URL "http://flex.sourceforge.net"
 +                       TYPE OPTIONAL
 +                       PURPOSE "Required by the UpdateSolidPredicateParser target \
(mainly useful for developers)"  +                      )
 +
 +find_package(BISON)
 +set_package_properties(BISON PROPERTIES
 +    URL "http://www.gnu.org/software/bison"
 +    DESCRIPTION "Allows the Solid predicate parser to be updated"
 +    TYPE OPTIONAL
 +    PURPOSE "Required by the UpdateSolidPredicateParser target (mainly useful for \
developers)"  +  )
 +
 +if (FLEX_FOUND AND BISON_FOUND)
 +
 +   add_custom_target(UpdateSolidPredicateParser
 +                     COMMAND ${FLEX_EXECUTABLE} -P Solid -o${lexer_FILE}.c \
${lexer_FILE}.l  +                     COMMAND ${BISON_EXECUTABLE} -p Solid -d -b \
${parser_FILE} ${parser_FILE}.y  +                     COMMAND ${CMAKE_COMMAND} -E \
copy ${parser_FILE}.tab.c ${CMAKE_CURRENT_SOURCE_DIR}/${parser_FILE}.c  +             \
COMMAND ${CMAKE_COMMAND} -E copy ${parser_FILE}.tab.h \
${CMAKE_CURRENT_SOURCE_DIR}/${parser_FILE}.h  +                     COMMAND \
${CMAKE_COMMAND} -E remove ${parser_FILE}.tab.c ${parser_FILE}.tab.h  +               \
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})  +
 +else ()
 +   add_custom_target(UpdateSolidPredicateParser
 +                     COMMAND echo "flex and/or bison not found, so target \
UpdateSolidPredicateParser inactive")  +endif ()
 +
diff --cc tier1/solid/src/solid/backends/udev/udevaudiointerface.cpp
index 4f53f2e,0000000..c7e6eaf
mode 100644,000000..100644
--- a/tier1/solid/src/solid/backends/udev/udevaudiointerface.cpp
+++ b/tier1/solid/src/solid/backends/udev/udevaudiointerface.cpp
@@@ -1,86 -1,0 +1,87 @@@
 +/*
 +    Copyright 2010 Alex Fiestas <alex@eyeos.org>
 +    Copyright 2010 UFO Coders <info@ufocoders.com>
 +
 +    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 <http://www.gnu.org/licenses/>.
 +*/
 +
 +#include "udevaudiointerface.h"
 +
 +#include "udevaudiointerface_p.h"
 +#include "udevdevice.h"
 +
 +#include <QFile>
++#include <QDebug>
 +
 +using namespace Solid::Backends::UDev;
 +
 +AudioInterface::AudioInterface(UDevDevice *device)
 +    : DeviceInterface(device),
 +    d(new UdevAudioInterfacePrivate(device))
 +{
 +}
 +
 +AudioInterface::~AudioInterface()
 +{
 +
 +}
 +
 +Solid::AudioInterface::AudioDriver AudioInterface::driver() const
 +{
 +    return d->m_driver;
 +}
 +
 +QVariant AudioInterface::driverHandle() const
 +{
 +    if (d->m_driver == Solid::AudioInterface::Alsa)
 +    {
 +        QList<QVariant> list;
 +        if (d->m_cardnum != -1) {
-             list << QVariant(d->m_cardnum);
-             if (d->m_devicenum != -1) {
-                 list << QVariant(d->m_devicenum);
-             }
++            QVariant card_id = d->m_cardnum;
++            QVariant dev_id = d->m_devicenum != -1 ? d->m_devicenum : QVariant();
++            QVariant subdev_id;
++            list << card_id << dev_id << subdev_id;
 +        } else if(!d->m_deviceFile.isEmpty()) {
 +            list << QVariant(d->m_deviceFile);
 +        }
 +        return list;
 +    }
 +    else if (d->m_driver == Solid::AudioInterface::OpenSoundSystem)
 +    {
 +        if (!d->m_deviceFile.isEmpty()) {
 +            return QVariant(d->m_deviceFile);
 +        }
 +    }
 +
 +    return QVariant();
 +}
 +
 +QString AudioInterface::name() const
 +{
 +    return d->m_name;
 +}
 +
 +Solid::AudioInterface::AudioInterfaceTypes AudioInterface::deviceType() const
 +{
 +        return d->m_type;
 +}
 +
 +Solid::AudioInterface::SoundcardType AudioInterface::soundcardType() const
 +{
 +    return d->soundcardType();
 +}
 +
diff --cc tier1/solid/src/solid/backends/udev/udevmanager.cpp
index 0faf9b3,0000000..1446868
mode 100644,000000..100644
--- a/tier1/solid/src/solid/backends/udev/udevmanager.cpp
+++ b/tier1/solid/src/solid/backends/udev/udevmanager.cpp
@@@ -1,211 -1,0 +1,209 @@@
 +/*
 +    Copyright 2010 Rafael Fernández López <ereslibre@kde.org>
 +
 +    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 <http://www.gnu.org/licenses/>.
 +*/
 +
 +#include "udevmanager.h"
 +
 +#include "udev.h"
 +#include "udevdevice.h"
 +#include "../shared/rootdevice.h"
 +
 +#include <QtCore/QCoreApplication>
 +#include <QtCore/QSet>
 +#include <QtCore/QFile>
 +#include <QtCore/QDebug>
 +
- #define DETAILED_OUTPUT 0
- 
 +using namespace Solid::Backends::UDev;
 +using namespace Solid::Backends::Shared;
 +
 +class UDevManager::Private
 +{
 +public:
 +    Private();
 +    ~Private();
 +
 +    bool isOfInterest(const UdevQt::Device &device);
 +
 +    UdevQt::Client *m_client;
 +    QSet<Solid::DeviceInterface::Type> m_supportedInterfaces;
 +};
 +
 +UDevManager::Private::Private()
 +{
 +    QStringList subsystems;
 +    subsystems << "processor";
 +    subsystems << "sound";
 +    subsystems << "tty";
 +    subsystems << "dvb";
 +    subsystems << "video4linux";
 +    subsystems << "net";
 +    subsystems << "usb";
 +    m_client = new UdevQt::Client(subsystems);
 +}
 +
 +UDevManager::Private::~Private()
 +{
 +    delete m_client;
 +}
 +
 +bool UDevManager::Private::isOfInterest(const UdevQt::Device &device)
 +{
- #if DETAILED_OUTPUT
++#ifdef UDEV_DETAILED_OUTPUT
 +    qDebug() << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<";
 +    qDebug() << "Path:" << device.sysfsPath();
 +    qDebug() << "Properties:" << device.deviceProperties();
 +    Q_FOREACH (const QString &key, device.deviceProperties()) {
 +        qDebug() << "\t" << key << ":" << device.deviceProperty(key).toString();
 +    }
 +    qDebug() << "Driver:" << device.driver();
 +    qDebug() << "Subsystem:" << device.subsystem();
 +    qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
 +#endif
 +    if (device.driver() == QLatin1String("processor")) {
 +        // Linux ACPI reports processor slots, rather than processors.
 +        // Empty slots will not have a system device associated with them.
 +        return QFile::exists(device.sysfsPath() + "/sysdev");
 +    }
 +    if (device.subsystem() == QLatin1String("sound") &&
 +            device.deviceProperty("SOUND_FORM_FACTOR").toString() != "internal") {
 +        return true;
 +    }
 +
 +    if (device.subsystem() == QLatin1String("tty")) {
 +        QString path = device.deviceProperty("DEVPATH").toString();
 +
 +        int lastSlash = path.length() - path.lastIndexOf(QLatin1String("/")) -1;
 +        QByteArray lastElement = path.right(lastSlash).toLatin1();
 +
 +        if (lastElement.startsWith("tty") && !path.startsWith("/devices/virtual")) \
{  +            return true;
 +        }
 +    }
 +    return device.subsystem() == QLatin1String("dvb") ||
 +           device.subsystem() == QLatin1String("video4linux") ||
 +           device.subsystem() == QLatin1String("net") ||
 +           device.deviceProperty("ID_MEDIA_PLAYER").toString().isEmpty() == false \
|| // media-player-info recognized devices  +           \
device.deviceProperty("ID_GPHOTO2").toInt() == 1; // GPhoto2 cameras  +}
 +
 +UDevManager::UDevManager(QObject *parent)
 +    : Solid::Ifaces::DeviceManager(parent),
 +      d(new Private)
 +{
 +    connect(d->m_client, SIGNAL(deviceAdded(UdevQt::Device)), this, \
SLOT(slotDeviceAdded(UdevQt::Device)));  +    connect(d->m_client, \
SIGNAL(deviceRemoved(UdevQt::Device)), this, \
SLOT(slotDeviceRemoved(UdevQt::Device)));  +
 +    d->m_supportedInterfaces << Solid::DeviceInterface::GenericInterface
 +                             << Solid::DeviceInterface::Processor
 +                             << Solid::DeviceInterface::AudioInterface
 +                             << Solid::DeviceInterface::NetworkInterface
 +                             << Solid::DeviceInterface::SerialInterface
 +                             << Solid::DeviceInterface::Camera
 +                             << Solid::DeviceInterface::PortableMediaPlayer
 +                             << Solid::DeviceInterface::DvbInterface
 +                             << Solid::DeviceInterface::Block
 +                             << Solid::DeviceInterface::Video;
 +}
 +
 +UDevManager::~UDevManager()
 +{
 +    delete d;
 +}
 +
 +QString UDevManager::udiPrefix() const
 +{
 +    return QString::fromLatin1(UDEV_UDI_PREFIX);
 +}
 +
 +QSet<Solid::DeviceInterface::Type> UDevManager::supportedInterfaces() const
 +{
 +    return d->m_supportedInterfaces;
 +}
 +
 +QStringList UDevManager::allDevices()
 +{
 +    QStringList res;
 +    const UdevQt::DeviceList deviceList = d->m_client->allDevices();
 +    Q_FOREACH (const UdevQt::Device &device, deviceList) {
 +        if (d->isOfInterest(device)) {
 +            res << udiPrefix() + device.sysfsPath();
 +        }
 +    }
 +    return res;
 +}
 +
 +QStringList UDevManager::devicesFromQuery(const QString &parentUdi,
 +                                          Solid::DeviceInterface::Type type)
 +{
 +    QStringList allDev = allDevices();
 +    QStringList result;
 +
 +    if (!parentUdi.isEmpty()) {
 +        Q_FOREACH (const QString &udi, allDev) {
 +            UDevDevice device(d->m_client->deviceBySysfsPath(udi.right(udi.size() - \
udiPrefix().size())));  +            if (device.queryDeviceInterface(type) && \
device.parentUdi() == parentUdi) {  +                result << udi;
 +            }
 +        }
 +
 +        return result;
 +    } else if (type != Solid::DeviceInterface::Unknown) {
 +        Q_FOREACH (const QString &udi, allDev) {
 +            UDevDevice device(d->m_client->deviceBySysfsPath(udi.right(udi.size() - \
udiPrefix().size())));  +            if (device.queryDeviceInterface(type)) {
 +                result << udi;
 +            }
 +        }
 +
 +        return result;
 +    } else {
 +        return allDev;
 +    }
 +}
 +
 +QObject *UDevManager::createDevice(const QString &udi_)
 +{
 +    if (udi_ == udiPrefix()) {
 +        RootDevice *const device = new RootDevice(UDEV_UDI_PREFIX);
 +        device->setProduct(QCoreApplication::translate("", "Devices"));
 +        device->setDescription(QCoreApplication::translate("", "Devices declared in \
your system"));  +        device->setIcon("computer");
 +        return device;
 +    }
 +    const QString udi = udi_.right(udi_.size() - udiPrefix().size());
 +    UdevQt::Device device = d->m_client->deviceBySysfsPath(udi);
 +    if (d->isOfInterest(device) || QFile::exists(udi)) {
 +        return new UDevDevice(device);
 +    }
 +    return 0;
 +}
 +
 +void UDevManager::slotDeviceAdded(const UdevQt::Device &device)
 +{
 +    if (d->isOfInterest(device)) {
 +        Q_EMIT deviceAdded(udiPrefix() + device.sysfsPath());
 +    }
 +}
 +
 +void UDevManager::slotDeviceRemoved(const UdevQt::Device &device)
 +{
 +    if (d->isOfInterest(device)) {
 +        Q_EMIT deviceRemoved(udiPrefix() + device.sysfsPath());
 +    }
 +}
diff --cc tier1/solid/src/solid/backends/udisks/udisksdevice.cpp
index 2c30ecd,0000000..e1c47af
mode 100644,000000..100644
--- a/tier1/solid/src/solid/backends/udisks/udisksdevice.cpp
+++ b/tier1/solid/src/solid/backends/udisks/udisksdevice.cpp
@@@ -1,778 -1,0 +1,774 @@@
 +/*
 +    Copyright 2010 Michael Zanetti <mzanetti@kde.org>
 +    Copyright 2010-2011 Lukas Tinkl <ltinkl@redhat.com>
 +
 +    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 <http://www.gnu.org/licenses/>.
 +*/
 +
 +#include "udisks.h"
 +#include "udisksdevice.h"
 +#include "udisksdeviceinterface.h"
 +#include "udisksstoragevolume.h"
 +#include "udisksopticaldisc.h"
 +#include "udisksopticaldrive.h"
 +#include "udisksstorageaccess.h"
 +#include "udisksgenericinterface.h"
 +
 +#include <solid/genericinterface.h>
 +#include <solid/deviceinterface.h>
 +#include <solid/device.h>
 +
 +#include <QtCore/QCoreApplication>
 +#include <QtCore/QStringList>
 +#include <QtCore/QDebug>
 +
 +#include <QtDBus/QDBusMessage>
 +#include <QtDBus/QDBusMetaType>
 +#include <QtDBus/QDBusPendingReply>
 +
 +using namespace Solid::Backends::UDisks;
 +
 +// Adapted from KLocale as Solid needs to be Qt-only
 +static QString formatByteSize(double size)
 +{
 +    // Per IEC 60027-2
 +
 +    // Binary prefixes
 +    //Tebi-byte             TiB             2^40    1,099,511,627,776 bytes
 +    //Gibi-byte             GiB             2^30    1,073,741,824 bytes
 +    //Mebi-byte             MiB             2^20    1,048,576 bytes
 +    //Kibi-byte             KiB             2^10    1,024 bytes
 +
 +    QString s;
 +    // Gibi-byte
 +    if ( size >= 1073741824.0 )
 +    {
 +        size /= 1073741824.0;
 +        if ( size > 1024 ) // Tebi-byte
 +            s = QCoreApplication::translate("", "%1 \
TiB").arg(QLocale().toString(size / 1024.0, 'f', 1));  +        else
 +            s = QCoreApplication::translate("", "%1 \
GiB").arg(QLocale().toString(size, 'f', 1));  +    }
 +    // Mebi-byte
 +    else if ( size >= 1048576.0 )
 +    {
 +        size /= 1048576.0;
 +        s = QCoreApplication::translate("", "%1 MiB").arg(QLocale().toString(size, \
'f', 1));  +    }
 +    // Kibi-byte
 +    else if ( size >= 1024.0 )
 +    {
 +        size /= 1024.0;
 +        s = QCoreApplication::translate("", "%1 KiB").arg(QLocale().toString(size, \
'f', 1));  +    }
 +    // Just byte
 +    else if ( size > 0 )
 +    {
 +        s = QCoreApplication::translate("", "%1 B").arg(QLocale().toString(size, \
'f', 1));  +    }
 +    // Nothing
 +    else
 +    {
 +        s = QCoreApplication::translate("", "0 B");
 +    }
 +    return s;
 +}
 +
 +UDisksDevice::UDisksDevice(const QString &udi)
 +    : Solid::Ifaces::Device()
 +    , m_udi(udi)
 +{
 +    QString realUdi = m_udi;
 +    if (realUdi.endsWith(":media")) {
 +        realUdi.chop(6);
 +    }
 +    m_device = new QDBusInterface(UD_DBUS_SERVICE, realUdi,
 +                                  UD_DBUS_INTERFACE_DISKS_DEVICE,
 +                                  QDBusConnection::systemBus());
 +
 +    if (m_device->isValid())
 +        connect(m_device, SIGNAL(Changed()), this, SLOT(slotChanged()));
 +}
 +
 +UDisksDevice::~UDisksDevice()
 +{
 +    delete m_device;
 +}
 +
 +QObject* UDisksDevice::createDeviceInterface(const Solid::DeviceInterface::Type& \
type)  +{
 +    if (!queryDeviceInterface(type)) {
 +        return 0;
 +    }
 +
 +    DeviceInterface *iface = 0;
 +    switch (type)
 +    {
 +    case Solid::DeviceInterface::GenericInterface:
 +        iface = new GenericInterface(this);
 +        break;
 +    case Solid::DeviceInterface::Block:
 +        iface = new Block(this);
 +        break;
 +    case Solid::DeviceInterface::StorageAccess:
 +        iface = new UDisksStorageAccess(this);
 +        break;
 +    case Solid::DeviceInterface::StorageDrive:
 +        iface = new UDisksStorageDrive(this);
 +        break;
 +    case Solid::DeviceInterface::OpticalDrive:
 +        iface = new UDisksOpticalDrive(this);
 +        break;
 +    case Solid::DeviceInterface::StorageVolume:
 +        iface = new UDisksStorageVolume(this);
 +        break;
 +    case Solid::DeviceInterface::OpticalDisc:
 +        iface = new OpticalDisc(this);
 +        break;
 +    default:
 +        break;
 +    }
 +    return iface;
 +}
 +
 +bool UDisksDevice::queryDeviceInterface(const Solid::DeviceInterface::Type& type) \
const  +{
 +    switch (type) {
 +        case Solid::DeviceInterface::GenericInterface:
 +            return true;
 +        case Solid::DeviceInterface::Block:
 +            return prop("DeviceMajor").toInt() != -1;
 +        case Solid::DeviceInterface::StorageVolume:
 +            if (prop("DeviceIsOpticalDisc").toBool()) {
 +                return m_udi.endsWith(":media");
 +            } else {
 +                return prop("DeviceIsPartition").toBool()
 +                        || prop("IdUsage").toString()=="filesystem"
 +                        || prop("IdUsage").toString()=="crypto";
 +            }
 +
 +        case Solid::DeviceInterface::StorageAccess:
 +            if (prop("DeviceIsOpticalDisc").toBool()) {
 +                return prop("IdUsage").toString()=="filesystem"
 +                        && m_udi.endsWith(":media");
 +
 +            } else {
 +                return prop("IdUsage").toString()=="filesystem"
 +                        || prop("IdUsage").toString()=="crypto";
 +            }
 +
 +        case Solid::DeviceInterface::StorageDrive:
 +            return !m_udi.endsWith(":media") && prop("DeviceIsDrive").toBool();
 +        case Solid::DeviceInterface::OpticalDrive:
 +            return !m_udi.endsWith(":media")
 +                    && prop( "DeviceIsDrive" ).toBool()
 +                    && !prop( "DriveMediaCompatibility" ).toStringList().filter( \
"optical_" ).isEmpty();  +        case Solid::DeviceInterface::OpticalDisc:
 +            return m_udi.endsWith(":media") && \
prop("DeviceIsOpticalDisc").toBool();  +        default:
 +            return false;
 +    }
 +}
 +
 +QStringList UDisksDevice::emblems() const
 +{
 +    QStringList res;
 +
 +    if (queryDeviceInterface(Solid::DeviceInterface::StorageAccess))
 +    {
 +
 +        bool isEncrypted = false;
 +        if (queryDeviceInterface(Solid::DeviceInterface::StorageVolume))
 +        {
 +            const UDisks::UDisksStorageVolume volIface(const_cast<UDisksDevice \
*>(this));  +            isEncrypted = (volIface.usage() == \
Solid::StorageVolume::Encrypted);  +        }
 +
 +        const UDisks::UDisksStorageAccess accessIface(const_cast<UDisksDevice \
*>(this));  +        if (accessIface.isAccessible())
 +        {
 +            if (isEncrypted)
 +                res << "emblem-encrypted-unlocked";
 +            else
 +                res << "emblem-mounted";
 +        }
 +        else
 +        {
 +            if (isEncrypted)
 +                res << "emblem-encrypted-locked";
 +            else
 +                res << "emblem-unmounted";
 +        }
 +    }
 +
 +    return res;
 +}
 +
 +QString UDisksDevice::description() const
 +{
 +    if (queryDeviceInterface(Solid::DeviceInterface::StorageDrive))
 +        return storageDescription();
 +    else if (queryDeviceInterface(Solid::DeviceInterface::StorageVolume))
 +        return volumeDescription();
 +    else
 +        return product();
 +}
 +
 +QString UDisksDevice::storageDescription() const
 +{
 +    QString description;
 +    const UDisks::UDisksStorageDrive storageDrive(const_cast<UDisksDevice*>(this));
 +    Solid::StorageDrive::DriveType drive_type = storageDrive.driveType();
 +    bool drive_is_hotpluggable = storageDrive.isHotpluggable();
 +    const UDisks::UDisksStorageVolume \
storageVolume(const_cast<UDisksDevice*>(this));  +
 +    if (drive_type == Solid::StorageDrive::CdromDrive)
 +    {
 +        const UDisks::UDisksOpticalDrive \
opticalDrive(const_cast<UDisksDevice*>(this));  +        \
Solid::OpticalDrive::MediumTypes mediumTypes = opticalDrive.supportedMedia();  +      \
QString first;  +        QString second;
 +
 +        first = QCoreApplication::translate("", "CD-ROM", "First item of %1%2 Drive \
sentence");  +        if (mediumTypes & Solid::OpticalDrive::Cdr)
 +            first = QCoreApplication::translate("", "CD-R", "First item of %1%2 \
Drive sentence");  +        if (mediumTypes & Solid::OpticalDrive::Cdrw)
 +            first = QCoreApplication::translate("", "CD-RW", "First item of %1%2 \
Drive sentence");  +
 +        if (mediumTypes & Solid::OpticalDrive::Dvd)
 +            second = QCoreApplication::translate("", "/DVD-ROM", "Second item of \
%1%2 Drive sentence");  +        if (mediumTypes & Solid::OpticalDrive::Dvdplusr)
 +            second = QCoreApplication::translate("", "/DVD+R", "Second item of %1%2 \
Drive sentence");  +        if (mediumTypes & Solid::OpticalDrive::Dvdplusrw)
 +            second = QCoreApplication::translate("", "/DVD+RW", "Second item of \
%1%2 Drive sentence");  +        if (mediumTypes & Solid::OpticalDrive::Dvdr)
 +            second = QCoreApplication::translate("", "/DVD-R", "Second item of %1%2 \
Drive sentence");  +        if (mediumTypes & Solid::OpticalDrive::Dvdrw)
 +            second = QCoreApplication::translate("", "/DVD-RW", "Second item of \
%1%2 Drive sentence");  +        if (mediumTypes & Solid::OpticalDrive::Dvdram)
 +            second = QCoreApplication::translate("", "/DVD-RAM", "Second item of \
%1%2 Drive sentence");  +        if ((mediumTypes & Solid::OpticalDrive::Dvdr) && \
(mediumTypes & Solid::OpticalDrive::Dvdplusr))  +        {
 +            if(mediumTypes & Solid::OpticalDrive::Dvdplusdl)
 +                second = QObject::trUtf8("/DVD ±R DL", "Second item of %1%2 Drive \
sentence");  +            else
 +                second = QObject::trUtf8("/DVD ±R", "Second item of %1%2 Drive \
sentence");  +        }
 +        if ((mediumTypes & Solid::OpticalDrive::Dvdrw) && (mediumTypes & \
Solid::OpticalDrive::Dvdplusrw))  +        {
 +            if((mediumTypes & Solid::OpticalDrive::Dvdplusdl) || (mediumTypes & \
Solid::OpticalDrive::Dvdplusdlrw))  +                second = QObject::trUtf8("/DVD \
±RW DL", "Second item of %1%2 Drive sentence");  +            else
 +                second = QObject::trUtf8("/DVD ±RW", "Second item of %1%2 Drive \
sentence");  +        }
 +        if (mediumTypes & Solid::OpticalDrive::Bd)
 +            second = QCoreApplication::translate("", "/BD-ROM", "Second item of \
%1%2 Drive sentence");  +        if (mediumTypes & Solid::OpticalDrive::Bdr)
 +            second = QCoreApplication::translate("", "/BD-R", "Second item of %1%2 \
Drive sentence");  +        if (mediumTypes & Solid::OpticalDrive::Bdre)
 +            second = QCoreApplication::translate("", "/BD-RE", "Second item of %1%2 \
Drive sentence");  +        if (mediumTypes & Solid::OpticalDrive::HdDvd)
 +            second = QCoreApplication::translate("", "/HD DVD-ROM", "Second item of \
%1%2 Drive sentence");  +        if (mediumTypes & Solid::OpticalDrive::HdDvdr)
 +            second = QCoreApplication::translate("", "/HD DVD-R", "Second item of \
%1%2 Drive sentence");  +        if (mediumTypes & Solid::OpticalDrive::HdDvdrw)
 +            second = QCoreApplication::translate("", "/HD DVD-RW", "Second item of \
%1%2 Drive sentence");  +
 +        if (drive_is_hotpluggable)
 +            description = QCoreApplication::translate("", "External %1%2 Drive", \
"%1 is CD-ROM/CD-R/etc; %2 is '/DVD-ROM'/'/DVD-R'/etc (with leading \
slash)").arg(first).arg(second);  +        else
 +            description = QCoreApplication::translate("", "%1%2 Drive", "%1 is \
CD-ROM/CD-R/etc; %2 is '/DVD-ROM'/'/DVD-R'/etc (with leading \
slash)").arg(first).arg(second);  +
 +        return description;
 +    }
 +
 +    if (drive_type == Solid::StorageDrive::Floppy)
 +    {
 +        if (drive_is_hotpluggable)
 +            description = QCoreApplication::translate("", "External Floppy Drive");
 +        else
 +            description = QCoreApplication::translate("", "Floppy Drive");
 +
 +        return description;
 +    }
 +
 +    bool drive_is_removable = storageDrive.isRemovable();
 +
 +    if (drive_type == Solid::StorageDrive::HardDisk && !drive_is_removable)
 +    {
 +        QString size_str = formatByteSize(storageVolume.size());
 +        if (!size_str.isEmpty())
 +        {
 +            if (drive_is_hotpluggable)
 +                description = QCoreApplication::translate("", "%1 External Hard \
Drive", "%1 is the size").arg(size_str);  +            else
 +                description = QCoreApplication::translate("", "%1 Hard Drive", "%1 \
is the size").arg(size_str);  +        } else {
 +            if (drive_is_hotpluggable)
 +                description = QCoreApplication::translate("", "External Hard \
Drive");  +            else
 +                description = QCoreApplication::translate("", "Hard Drive");
 +        }
 +
 +        return description;
 +    }
 +
 +    QString vendormodel_str;
 +    QString model = product();
 +    QString vendor_str = vendor();
 +
 +    if (vendor_str.isEmpty())
 +    {
 +        if (!model.isEmpty())
 +            vendormodel_str = model;
 +    }
 +    else
 +    {
 +        if (model.isEmpty())
 +            vendormodel_str = vendor_str;
 +        else
 +        {
 +            if (model.startsWith(vendor_str))
 +            {
 +                // e.g. vendor is "Nokia" and model is "Nokia N950" we do not want \
"Nokia Nokia N950" as description  +                vendormodel_str = model;
 +            }
 +            else
 +            {
 +                vendormodel_str = QCoreApplication::translate("", "%1 %2", "%1 is \
the vendor, %2 is the model of the device").arg(vendor_str).arg(model);  +            \
}  +        }
 +    }
 +
 +    if (vendormodel_str.isEmpty())
 +        description = QCoreApplication::translate("", "Drive");
 +    else
 +        description = vendormodel_str;
 +
 +    return description;
 +}
 +
 +QString UDisksDevice::volumeDescription() const
 +{
 +    QString description;
 +    const UDisks::UDisksStorageVolume \
storageVolume(const_cast<UDisksDevice*>(this));  +    QString volume_label = \
prop("IdLabel").toString();  +    if (volume_label.isEmpty())
 +        volume_label = prop("PartitionLabel").toString();
 +    if (!volume_label.isEmpty())
 +        return volume_label;
 +
 +    const UDisks::UDisksStorageDrive storageDrive(const_cast<UDisksDevice*>(this));
 +    Solid::StorageDrive::DriveType drive_type = storageDrive.driveType();
 +
 +    // Handle media in optical drives
 +    if (drive_type == Solid::StorageDrive::CdromDrive)
 +    {
 +        const UDisks::OpticalDisc disc(const_cast<UDisksDevice*>(this));
 +        switch (disc.discType())
 +        {
 +            case Solid::OpticalDisc::UnknownDiscType:
 +            case Solid::OpticalDisc::CdRom:
 +                description = QCoreApplication::translate("", "CD-ROM");
 +                break;
 +
 +            case Solid::OpticalDisc::CdRecordable:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank CD-R");
 +                else
 +                    description = QCoreApplication::translate("", "CD-R");
 +                break;
 +
 +            case Solid::OpticalDisc::CdRewritable:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank CD-RW");
 +                else
 +                    description = QCoreApplication::translate("", "CD-RW");
 +                break;
 +
 +            case Solid::OpticalDisc::DvdRom:
 +                description = QCoreApplication::translate("", "DVD-ROM");
 +                break;
 +
 +            case Solid::OpticalDisc::DvdRam:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank DVD-RAM");
 +                else
 +                    description = QCoreApplication::translate("", "DVD-RAM");
 +                break;
 +
 +            case Solid::OpticalDisc::DvdRecordable:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank DVD-R");
 +                else
 +                    description = QCoreApplication::translate("", "DVD-R");
 +                break;
 +
 +            case Solid::OpticalDisc::DvdPlusRecordableDuallayer:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank DVD+R \
Dual-Layer");  +                else
 +                    description = QCoreApplication::translate("", "DVD+R \
Dual-Layer");  +                break;
 +
 +            case Solid::OpticalDisc::DvdRewritable:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank DVD-RW");
 +                else
 +                    description = QCoreApplication::translate("", "DVD-RW");
 +                break;
 +
 +            case Solid::OpticalDisc::DvdPlusRecordable:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank DVD+R");
 +                else
 +                    description = QCoreApplication::translate("", "DVD+R");
 +                break;
 +
 +            case Solid::OpticalDisc::DvdPlusRewritable:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank DVD+RW");
 +                else
 +                    description = QCoreApplication::translate("", "DVD+RW");
 +                break;
 +
 +            case Solid::OpticalDisc::DvdPlusRewritableDuallayer:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank DVD+RW \
Dual-Layer");  +                else
 +                    description = QCoreApplication::translate("", "DVD+RW \
Dual-Layer");  +                break;
 +
 +            case Solid::OpticalDisc::BluRayRom:
 +                description = QCoreApplication::translate("", "BD-ROM");
 +                break;
 +
 +            case Solid::OpticalDisc::BluRayRecordable:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank BD-R");
 +                else
 +                    description = QCoreApplication::translate("", "BD-R");
 +                break;
 +
 +            case Solid::OpticalDisc::BluRayRewritable:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank BD-RE");
 +                else
 +                    description = QCoreApplication::translate("", "BD-RE");
 +                break;
 +
 +            case Solid::OpticalDisc::HdDvdRom:
 +                description = QCoreApplication::translate("", "HD DVD-ROM");
 +                break;
 +
 +            case Solid::OpticalDisc::HdDvdRecordable:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank HD \
DVD-R");  +                else
 +                    description = QCoreApplication::translate("", "HD DVD-R");
 +                break;
 +
 +            case Solid::OpticalDisc::HdDvdRewritable:
 +                if (disc.isBlank())
 +                    description = QCoreApplication::translate("", "Blank HD \
DVD-RW");  +                else
 +                    description = QCoreApplication::translate("", "HD DVD-RW");
 +                break;
 +            }
 +
 +        // Special case for pure audio disc
 +        if (disc.availableContent() == Solid::OpticalDisc::Audio)
 +            description = QCoreApplication::translate("", "Audio CD");
 +
 +        return description;
 +    }
 +
 +    bool drive_is_removable = storageDrive.isRemovable();
 +    bool drive_is_hotpluggable = storageDrive.isHotpluggable();
 +    bool drive_is_encrypted_container = (storageVolume.usage() == \
Solid::StorageVolume::Encrypted);  +
 +    QString size_str = formatByteSize(storageVolume.size());
 +    if (drive_is_encrypted_container)
 +    {
 +        if (!size_str.isEmpty())
 +            description = QCoreApplication::translate("", "%1 Encrypted Container", \
"%1 is the size").arg(size_str);  +        else
 +            description = QCoreApplication::translate("", "Encrypted Container");
 +    }
 +    else if (drive_type == Solid::StorageDrive::HardDisk && !drive_is_removable)
 +    {
 +        if (!size_str.isEmpty())
 +        {
 +            if (drive_is_hotpluggable)
 +                description = QCoreApplication::translate("", "%1 External Hard \
Drive", "%1 is the size").arg(size_str);  +            else
 +                description = QCoreApplication::translate("", "%1 Hard Drive", "%1 \
is the size").arg(size_str);  +        }
 +        else
 +        {
 +            if (drive_is_hotpluggable)
 +                description = QCoreApplication::translate("", "External Hard \
Drive");  +            else
 +                description = QCoreApplication::translate("", "Hard Drive");
 +        }
 +    }
 +    else
 +    {
 +        if (drive_is_removable)
 +            description = QCoreApplication::translate("", "%1 Removable Media", "%1 \
is the size").arg(size_str);  +        else
 +            description = QCoreApplication::translate("", "%1 Media", "%1 is the \
size").arg(size_str);  +    }
 +
 +    return description;
 +}
 +
 +QString UDisksDevice::icon() const
 +{
 +    QString iconName = prop( "DevicePresentationIconName" ).toString();
 +
 +    if ( !iconName.isEmpty() )
 +    {
 +        return iconName;
 +    }
 +    else
 +    {
 +        bool isPartition = prop( "DeviceIsPartition" ).toBool();
 +        if ( isPartition )      // this is a slave device, we need to return its \
parent's icon  +        {
-             UDisksDevice* parent = 0;
-             if ( !parentUdi().isEmpty() )
-                 parent = new UDisksDevice( parentUdi() );
++            if ( !m_parentDevice && !parentUdi().isEmpty() )
++                m_parentDevice = new UDisksDevice( parentUdi() );
 +
-             if ( parent )
-             {
-                 iconName = parent->icon();
-                 delete parent;
-             }
++            if ( m_parentDevice )
++                iconName = m_parentDevice->icon();
 +
 +            if ( !iconName.isEmpty() )
 +                return iconName;
 +        }
 +
 +        // handle mounted ISOs
 +        bool isLoop = prop( "DeviceIsLinuxLoop" ).toBool();
 +        QString fstype = prop("IdType").toString();
 +
 +        if( isLoop && ( fstype == "iso9660" || fstype == "udf" ) )
 +        {
 +            return "media-optical";
 +        }
 +
 +        // handle media
 +        const QString media = prop( "DriveMedia" ).toString();
 +        bool isOptical = prop( "DeviceIsOpticalDisc" ).toBool();
 +
 +        if ( !media.isEmpty() )
 +        {
 +            if ( isOptical )    // optical stuff
 +            {
 +                bool isWritable = prop( "OpticalDiscIsBlank" ).toBool() || \
prop("OpticalDiscIsAppendable").toBool();  +
 +                const UDisks::OpticalDisc disc(const_cast<UDisksDevice*>(this));
 +                Solid::OpticalDisc::ContentTypes availContent = \
disc.availableContent();  +
 +                if (availContent & Solid::OpticalDisc::VideoDvd) // Video DVD
 +                    return "media-optical-dvd-video";
 +                else if ((availContent & Solid::OpticalDisc::VideoCd) || \
(availContent & Solid::OpticalDisc::SuperVideoCd)) // Video CD  +                    \
return "media-optical-video";  +                else if ((availContent & \
Solid::OpticalDisc::Data) && (availContent & Solid::OpticalDisc::Audio)) // Mixed CD  \
+                    return "media-optical-mixed-cd";  +                else if \
(availContent & Solid::OpticalDisc::Audio) // Audio CD  +                    return \
"media-optical-audio";  +                else if (availContent & \
Solid::OpticalDisc::Data) // Data CD  +                    return \
"media-optical-data";  +                else if ( isWritable )
 +                    return "media-optical-recordable";
 +                else
 +                {
 +                    if ( media.startsWith( "optical_dvd" ) || media.startsWith( \
"optical_hddvd" ) ) // DVD  +                        return "media-optical-dvd";
 +                    else if ( media.startsWith( "optical_bd" ) ) // BluRay
 +                        return "media-optical-blu-ray";
 +                }
 +
 +                // fallback for every other optical disc
 +                return "media-optical";
 +            }
 +
 +            if ( media == "flash_ms" ) // Flash & Co.
 +                return "media-flash-memory-stick";
 +            else if ( media == "flash_sd" || media == "flash_sdhc" || media == \
"flash_mmc" )  +                return "media-flash-sd-mmc";
 +            else if ( media == "flash_sm" )
 +                return "media-flash-smart-media";
 +            else if ( media.startsWith( "flash" ) )
 +                return "media-flash";
 +            else if ( media == "floppy" ) // the good ol' floppy
 +                return "media-floppy";
 +
 +        }
 +
 +        // handle drives
 +        bool isRemovable = prop( "DeviceIsRemovable" ).toBool();
 +        const QString conn = prop( "DriveConnectionInterface" ).toString();
 +
 +        if ( queryDeviceInterface(Solid::DeviceInterface::OpticalDrive) )
 +            return "drive-optical";
 +        else if ( isRemovable && !isOptical )
 +        {
 +            if ( conn == "usb" )
 +                return "drive-removable-media-usb";
 +            else
 +                return "drive-removable-media";
 +        }
 +    }
 +
 +    return "drive-harddisk";    // general fallback
 +}
 +
 +QString UDisksDevice::product() const
 +{
 +    QString product = prop("DriveModel").toString();
 +    const bool isDrive = prop( "DeviceIsDrive" ).toBool() && \
!m_udi.endsWith(":media");  +
 +    if (!isDrive) {
 +        QString label = prop("IdLabel").toString();
 +        if (!label.isEmpty()) {
 +            product = label;
 +        }
 +    }
 +
 +    return product;
 +}
 +
 +QString UDisksDevice::vendor() const
 +{
 +    return prop("DriveVendor").toString();
 +}
 +
 +QString UDisksDevice::udi() const
 +{
 +    return m_udi;
 +}
 +
 +QString UDisksDevice::parentUdi() const
 +{
 +    if (m_udi.endsWith(QLatin1String(":media"))) {
 +        QString result = m_udi;
 +        return result.remove(":media");
 +    }
 +    else if ( prop( "DeviceIsLuksCleartext" ).toBool() )
 +        return prop( "LuksCleartextSlave" ).value<QDBusObjectPath>().path();
 +    else {
 +        QString parent = prop("PartitionSlave").value<QDBusObjectPath>().path();
 +        if (parent.isEmpty() || parent=="/") {
 +            parent = UD_UDI_DISKS_PREFIX;
 +        }
 +        return parent;
 +    }
 +}
 +
 +void UDisksDevice::checkCache(const QString &key) const
 +{
 +    if (m_cache.isEmpty()) // recreate the cache
 +        allProperties();
 +
 +    if (m_cache.contains(key))
 +        return;
 +
 +    QVariant reply = m_device->property(key.toUtf8());
 +
 +    if (reply.isValid()) {
 +        m_cache[key] = reply;
 +    } else {
 +        m_cache[key] = QVariant();
 +    }
 +}
 +
 +QVariant UDisksDevice::prop(const QString &key) const
 +{
 +    checkCache(key);
 +    return m_cache.value(key);
 +}
 +
 +bool UDisksDevice::propertyExists(const QString &key) const
 +{
 +    checkCache(key);
 +    return m_cache.contains(key);
 +}
 +
 +QMap<QString, QVariant> UDisksDevice::allProperties() const
 +{
 +    QDBusMessage call = QDBusMessage::createMethodCall(m_device->service(), \
m_device->path(),  +                                                       \
"org.freedesktop.DBus.Properties", "GetAll");  +    call << m_device->interface();
 +    QDBusPendingReply< QVariantMap > reply = \
QDBusConnection::systemBus().asyncCall(call);  +    reply.waitForFinished();
 +
 +    if (reply.isValid())
 +        m_cache = reply.value();
 +    else
 +        m_cache.clear();
 +
 +    return m_cache;
 +}
 +
 +void UDisksDevice::slotChanged()
 +{
 +    // given we cannot know which property/ies changed, clear the cache
 +    m_cache.clear();
 +    Q_EMIT changed();
 +}
 +
 +bool UDisksDevice::isDeviceBlacklisted() const
 +{
 +    return prop("DevicePresentationHide").toBool() ||
 +            prop("DeviceMountPaths").toStringList().contains("/boot") ||
 +            prop("IdLabel").toString() == "System Reserved" ||
 +            ( prop("IdUsage").toString().isEmpty() && \
!(prop("OpticalDiscIsBlank").toBool() || (prop("OpticalDiscNumAudioTracks").toInt() > \
0) ));  +}
 +
 +QString UDisksDevice::errorToString(const QString & error) const
 +{
 +    if (error == UD_ERROR_UNAUTHORIZED)
 +        return QCoreApplication::translate("", "You are not authorized to perform \
this operation.");  +    else if (error == UD_ERROR_BUSY)
 +        return QCoreApplication::translate("", "The device is currently busy.");
 +    else if (error == UD_ERROR_FAILED)
 +        return QCoreApplication::translate("", "The requested operation has \
failed.");  +    else if (error == UD_ERROR_CANCELED)
 +        return QCoreApplication::translate("", "The requested operation has been \
canceled.");  +    else if (error == UD_ERROR_INVALID_OPTION)
 +        return QCoreApplication::translate("", "An invalid or malformed option has \
been given.");  +    else if (error == UD_ERROR_MISSING_DRIVER)
 +        return QCoreApplication::translate("", "The kernel driver for this \
filesystem type is not available.");  +    else
 +        return QCoreApplication::translate("", "An unspecified error has \
occurred.");  +}
 +
 +Solid::ErrorType UDisksDevice::errorToSolidError(const QString & error) const
 +{
 +    if (error == UD_ERROR_BUSY)
 +        return Solid::DeviceBusy;
 +    else if (error == UD_ERROR_FAILED)
 +        return Solid::OperationFailed;
 +    else if (error == UD_ERROR_CANCELED)
 +        return Solid::UserCanceled;
 +    else if (error == UD_ERROR_INVALID_OPTION)
 +        return Solid::InvalidOption;
 +    else if (error == UD_ERROR_MISSING_DRIVER)
 +        return Solid::MissingDriver;
 +    else
 +        return Solid::UnauthorizedOperation;
 +}
diff --cc tier1/solid/src/solid/backends/udisks2/udisksdevicebackend.cpp
index 0000000,0000000..2a01b86
new file mode 100644
--- /dev/null
+++ b/tier1/solid/src/solid/backends/udisks2/udisksdevicebackend.cpp
@@@ -1,0 -1,0 +1,239 @@@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti@kde.org>
++    Copyright 2010-2012 Lukáš Tinkl <ltinkl@redhat.com>
++    Copyright 2012 Dan Vrátil <dvratil@redhat.com>
++
++    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 <http://www.gnu.org/licenses/>.
++*/
++
++#include "udisksdevicebackend.h"
++
++#include <QtDBus/QDBusConnection>
++#include <QtDBus/QDBusInterface>
++#include <QtXml/QDomDocument>
++
++#include "solid/deviceinterface.h"
++#include "solid/genericinterface.h"
++
++using namespace Solid::Backends::UDisks2;
++
++/* Static cache for DeviceBackends for all UDIs */
++QMap<QString /* UDI */, DeviceBackend*> DeviceBackend::s_backends;
++
++DeviceBackend* DeviceBackend::backendForUDI(const QString& udi)
++{
++    DeviceBackend *backend = 0;
++    if (udi.isEmpty()) {
++        return backend;
++    }
++
++    if (s_backends.contains(udi)) {
++        backend = s_backends.value(udi);
++    } else {
++        backend = new DeviceBackend(udi);
++        s_backends.insert(udi, backend);
++    }
++
++    return backend;
++}
++
++void DeviceBackend::destroyBackend(const QString& udi)
++{
++    if (s_backends.contains(udi)) {
++        DeviceBackend *backend = s_backends.value(udi);
++        s_backends.remove(udi);
++        delete backend;
++    }
++}
++
++DeviceBackend::DeviceBackend(const QString& udi)
++    : m_udi(udi)
++{
++    //qDebug() << "Creating backend for device" << m_udi;
++    m_device = new QDBusInterface(UD2_DBUS_SERVICE, m_udi,
++                                  QString(), // no interface, we aggregate them
++                                  QDBusConnection::systemBus(), this);
++
++    if (m_device->isValid()) {
++        QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, m_udi, \
DBUS_INTERFACE_PROPS, "PropertiesChanged", this, ++                                   \
SLOT(slotPropertiesChanged(QString,QVariantMap,QStringList))); ++        \
QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, UD2_DBUS_PATH, \
DBUS_INTERFACE_MANAGER, "InterfacesAdded", ++                                         \
this, SLOT(slotInterfacesAdded(QDBusObjectPath,QVariantMapMap))); ++        \
QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, UD2_DBUS_PATH, \
DBUS_INTERFACE_MANAGER, "InterfacesRemoved", ++                                       \
this, SLOT(slotInterfacesRemoved(QDBusObjectPath,QStringList))); ++
++        initInterfaces();
++    }
++}
++
++DeviceBackend::~DeviceBackend()
++{
++    //qDebug() << "Destroying backend for device" << m_udi;
++}
++
++void DeviceBackend::initInterfaces()
++{
++    m_interfaces.clear();
++
++    const QString xmlData = introspect();
++    if (xmlData.isEmpty()) {
++        qDebug() << m_udi << "has no interfaces!";
++        return;
++    }
++
++    QDomDocument dom;
++    dom.setContent(xmlData);
++
++    QDomNodeList ifaceNodeList = dom.elementsByTagName("interface");
++    for (int i = 0; i < ifaceNodeList.count(); i++) {
++        QDomElement ifaceElem = ifaceNodeList.item(i).toElement();
++        /* Accept only org.freedesktop.UDisks2.* interfaces so that when the device \
is unplugged, ++         * m_interfaces goes empty and we can easily verify that the \
device is gone. */ ++        if (!ifaceElem.isNull() && \
ifaceElem.attribute("name").startsWith(UD2_DBUS_SERVICE)) { ++            \
m_interfaces.append(ifaceElem.attribute("name")); ++        }
++    }
++
++    //qDebug() << m_udi << "has interfaces:" << m_interfaces;
++}
++
++QStringList DeviceBackend::interfaces() const
++{
++    return m_interfaces;
++}
++
++const QString& DeviceBackend::udi() const
++{
++    return m_udi;
++}
++
++QVariant DeviceBackend::prop(const QString& key) const
++{
++    checkCache(key);
++    return m_propertyCache.value(key);
++}
++
++bool DeviceBackend::propertyExists(const QString& key) const
++{
++    checkCache(key);
++    /* checkCache() will put an invalid QVariant in cache when the property
++     * does not exist, so check for validity, not for an actual presence. */
++    return m_propertyCache.value(key).isValid();
++}
++
++QVariantMap DeviceBackend::allProperties() const
++{
++    QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_udi, \
DBUS_INTERFACE_PROPS, "GetAll"); ++
++    Q_FOREACH (const QString & iface, m_interfaces) {
++        call.setArguments(QVariantList() << iface);
++        QDBusPendingReply<QVariantMap> reply = \
QDBusConnection::systemBus().call(call); ++
++        if (reply.isValid()) {
++            m_propertyCache.unite(reply.value());
++        } else {
++            qWarning() << "Error getting props:" << reply.error().name() << \
reply.error().message(); ++        }
++        //qDebug() << "After iface" << iface << ", cache now contains" << \
m_cache.size() << "items"; ++    }
++
++    return m_propertyCache;
++}
++
++QString DeviceBackend::introspect() const
++{
++    QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_udi,
++                                                    DBUS_INTERFACE_INTROSPECT, \
"Introspect"); ++    QDBusPendingReply<QString> reply = \
QDBusConnection::systemBus().call(call); ++
++    if (reply.isValid())
++        return reply.value();
++    else {
++        return QString();
++    }
++}
++
++void DeviceBackend::checkCache(const QString& key) const
++{
++    if (m_propertyCache.isEmpty()) { // recreate the cache
++        allProperties();
++    }
++
++    if (m_propertyCache.contains(key)) {
++        return;
++    }
++
++    QVariant reply = m_device->property(key.toUtf8());
++    m_propertyCache.insert(key, reply);
++
++    if (!reply.isValid()) {
++        /* Store the item in the cache anyway so next time we don't have to
++         * do the DBus call to find out it does not exist but just check whether
++         * prop(key).isValid() */
++        qDebug() << m_udi << ": property" << key << "does not exist";
++    }
++}
++
++void DeviceBackend::slotPropertiesChanged(const QString& ifaceName, const \
QVariantMap& changedProps, const QStringList& invalidatedProps) ++{
++    //qDebug() << m_udi << "'s interface" << ifaceName << "changed props:";
++
++    QMap<QString, int> changeMap;
++
++    Q_FOREACH(const QString & key, invalidatedProps) {
++        m_propertyCache.remove(key);
++        changeMap.insert(key, Solid::GenericInterface::PropertyRemoved);
++        //qDebug() << "\t invalidated:" << key;
++    }
++
++    QMapIterator<QString, QVariant> i(changedProps);
++    while (i.hasNext()) {
++        i.next();
++        const QString key = i.key();
++        m_propertyCache.insert(key, i.value());  // replace the value
++        changeMap.insert(key, Solid::GenericInterface::PropertyModified);
++        //qDebug() << "\t modified:" << key << ":" << m_propertyCache.value(key);
++    }
++
++    Q_EMIT propertyChanged(changeMap);
++    Q_EMIT changed();
++}
++
++void DeviceBackend::slotInterfacesAdded(const QDBusObjectPath& object_path, const \
QVariantMapMap& interfaces_and_properties) ++{
++    if (object_path.path() != m_udi) {
++        return;
++    }
++
++    Q_FOREACH(const QString & iface, interfaces_and_properties.keys()) {
++        /* Don't store generic DBus interfaces */
++        if (iface.startsWith(UD2_DBUS_SERVICE)) {
++            m_interfaces.append(interfaces_and_properties.keys());
++        }
++    }
++}
++
++void DeviceBackend::slotInterfacesRemoved(const QDBusObjectPath& object_path, const \
QStringList& interfaces) ++{
++    if (object_path.path() != m_udi) {
++        return;
++    }
++
++    Q_FOREACH(const QString & iface, interfaces) {
++        m_interfaces.removeAll(iface);
++    }
++}
diff --cc tier1/solid/src/solid/backends/udisks2/udisksdevicebackend.h
index 0000000,0000000..829fa41
new file mode 100644
--- /dev/null
+++ b/tier1/solid/src/solid/backends/udisks2/udisksdevicebackend.h
@@@ -1,0 -1,0 +1,84 @@@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti@kde.org>
++    Copyright 2010-2012 Lukáš Tinkl <ltinkl@redhat.com>
++    Copyright 2012 Dan Vrátil <dvratil@redhat.com>
++
++    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 <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef UDISKSDEVICEBACKEND_H
++#define UDISKSDEVICEBACKEND_H
++
++#include <QObject>
++#include <QtDBus/QDBusConnection>
++#include <QtDBus/QDBusObjectPath>
++#include <QtDBus/QDBusInterface>
++#include <QStringList>
++
++#include "udisks2.h"
++
++namespace Solid {
++namespace Backends {
++namespace UDisks2 {
++
++class DeviceBackend: public QObject {
++
++    Q_OBJECT
++
++  public:
++    static DeviceBackend* backendForUDI(const QString &udi);
++    static void destroyBackend(const QString &udi);
++
++    DeviceBackend(const QString &udi);
++    ~DeviceBackend();
++
++    QVariant prop(const QString &key) const;
++    bool propertyExists(const QString &key) const;
++    QVariantMap allProperties() const;
++
++    QStringList interfaces() const;
++    const QString & udi() const;
++
++  Q_SIGNALS:
++    void propertyChanged(const QMap<QString, int> &changeMap);
++    void changed();
++
++  private Q_SLOTS:
++    void slotInterfacesAdded(const QDBusObjectPath &object_path, const \
QVariantMapMap &interfaces_and_properties); ++    void slotInterfacesRemoved(const \
QDBusObjectPath &object_path, const QStringList &interfaces); ++    void \
slotPropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, \
const QStringList &invalidatedProps); ++
++  private:
++    void initInterfaces();
++    QString introspect() const;
++    void checkCache(const QString &key) const;
++
++    QDBusInterface *m_device;
++
++    mutable QVariantMap m_propertyCache;
++    QStringList m_interfaces;
++    QString m_udi;
++
++    static QMap<QString, DeviceBackend*> s_backends;
++
++};
++
++} /* namespace UDisks2 */
++} /* namespace Backends */
++} /* namespace Solid */
++
++#endif /* UDISKSDEVICEBACKEND_H */
diff --cc tier2/kconfig/autotests/kconfig_compiler/CMakeLists.txt
index 054c117,0000000..36265de
mode 100644,000000..100644
--- a/tier2/kconfig/autotests/kconfig_compiler/CMakeLists.txt
+++ b/tier2/kconfig/autotests/kconfig_compiler/CMakeLists.txt
@@@ -1,198 -1,0 +1,208 @@@
 +
 +#test5.cpp test5.h: $(srcdir)/test5.kcfg ../kconfig_compiler $(srcdir)/test5.kcfgc
 +#	../kconfig_compiler $(srcdir)/test5.kcfg $(srcdir)/test5.kcfgc
 +
 +macro(GEN_KCFG_TEST_SOURCE _testName _srcs)
 +   add_custom_command(
 +      OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_testName}.cpp \
${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h  +      COMMAND \
${KConfig_KCFGC_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfg \
${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfgc  +      DEPENDS \
${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfg \
${CMAKE_CURRENT_SOURCE_DIR}/${_testName}.kcfgc kconfig_compiler)  +
 +#   set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h \
PROPERTIES GENERATED TRUE)  +   \
qt4_generate_moc(${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h \
${CMAKE_CURRENT_BINARY_DIR}/${_testName}.moc )  +# do not run automoc on the \
generated file  +   set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${_testName}.cpp \
PROPERTIES SKIP_AUTOMOC TRUE)  +   set( ${_srcs} ${${_srcs}} \
${CMAKE_CURRENT_BINARY_DIR}/${_testName}.cpp \
${CMAKE_CURRENT_BINARY_DIR}/${_testName}.h )  +
 +   macro_add_file_dependencies(${CMAKE_CURRENT_BINARY_DIR}/${_testName}.cpp \
${CMAKE_CURRENT_BINARY_DIR}/${_testName}.moc )  +endmacro(GEN_KCFG_TEST_SOURCE)
 +
 +########### next target ###############
 +
 +set(test1_SRCS test1main.cpp )
 +
 +
 +gen_kcfg_test_source(test1 test1_SRCS)
 +
 +add_executable(test1 ${test1_SRCS})
 +
 +target_link_libraries(test1 Qt5::Widgets KConfigCore KConfigGui)
 +
 +
 +########### next target ###############
 +
 +set(test2_SRCS test2main.cpp )
 +
 +
 +gen_kcfg_test_source(test2 test2_SRCS)
 +
 +add_executable(test2 ${test2_SRCS})
 +
 +target_link_libraries(test2 Qt5::Widgets KConfigCore KConfigGui)
 +
 +
 +########### next target ###############
 +
 +set(test3_SRCS test3main.cpp )
 +
 +
 +gen_kcfg_test_source(test3 test3_SRCS)
 +
 +add_executable(test3 ${test3_SRCS})
 +
 +target_link_libraries(test3 Qt5::Widgets KConfigCore KConfigGui)
 +
 +
 +########### next target ###############
 +
 +set(test3a_SRCS test3amain.cpp )
 +
 +
 +gen_kcfg_test_source(test3a test3a_SRCS)
 +
 +add_executable(test3a ${test3a_SRCS})
 +
 +target_link_libraries(test3a Qt5::Widgets KConfigCore KConfigGui)
 +
 +
 +########### next target ###############
 +
 +set(test4_SRCS test4main.cpp )
 +
 +
 +gen_kcfg_test_source(test4 test4_SRCS)
 +
 +add_executable(test4 ${test4_SRCS})
 +
 +target_link_libraries(test4 Qt5::Widgets KConfigCore KConfigGui)
 +
 +
 +########### next target ###############
 +
 +set(test5_SRCS test5main.cpp )
 +
 +
 +gen_kcfg_test_source(test5 test5_SRCS)
 +
 +add_executable(test5 ${test5_SRCS})
 +
 +target_link_libraries(test5 Qt5::Widgets KConfigCore KConfigGui)
 +
 +
 +########### next target ###############
 +
 +set(test6_SRCS test6main.cpp )
 +
 +
 +gen_kcfg_test_source(test6 test6_SRCS)
 +
 +add_executable(test6 ${test6_SRCS})
 +
 +target_link_libraries(test6 Qt5::Widgets KConfigCore KConfigGui)
 +
 +
 +########### next target ###############
 +
 +set(test7_SRCS test7main.cpp )
 +
 +
 +gen_kcfg_test_source(test7 test7_SRCS)
 +
 +add_executable(test7 ${test7_SRCS})
 +
 +target_link_libraries(test7 Qt5::Widgets KConfigCore KConfigGui)
 +
 +
 +########### next target ###############
 +
 +set(test8_SRCS test8main.cpp )
 +
 +
 +gen_kcfg_test_source(test8a test8_SRCS)
 +gen_kcfg_test_source(test8b test8_SRCS)
 +
 +add_executable(test8 ${test8_SRCS})
 +
 +target_link_libraries(test8 Qt5::Widgets KConfigCore KConfigGui)
 +
 +
 +########### next target ###############
 +
 +set(test9_SRCS test9main.cpp )
 +
 +
 +gen_kcfg_test_source(test9 test9_SRCS)
 +
 +add_executable(test9 ${test9_SRCS})
 +
 +target_link_libraries(test9 Qt5::Widgets KConfigCore KConfigGui)
 +
 +
 +########### next target ###############
 +
 +set(test10_SRCS test10main.cpp )
 +
 +
 +gen_kcfg_test_source(test10 test10_SRCS)
 +
 +add_executable(test10 ${test10_SRCS})
 +
 +target_link_libraries(test10 Qt5::Widgets KConfigCore KConfigGui \
${KCoreAddons_LIBRARIES} )  +
 +
 +########### next target ###############
 +
 +set(test11_SRCS test11main.cpp )
 +
 +
 +gen_kcfg_test_source(test11 test11_SRCS)
 +gen_kcfg_test_source(test11a test11_SRCS)
 +
 +add_executable(test11 ${test11_SRCS})
 +
 +target_link_libraries(test11 Qt5::Widgets KConfigCore KConfigGui)
 +
 +
 +########### next target ###############
 +
- set(test_dpointer_SRCS test_dpointer_main.cpp )
++set(test12_SRCS test12main.cpp )
++
++gen_kcfg_test_source(test12 test12_SRCS)
++
++add_executable(test12 ${test11_SRCS})
++
++target_link_libraries(test12  ${KDE4_KDEUI_LIBS} )
 +
 +
++########### next target ###############
++
++set(test_dpointer_SRCS test_dpointer_main.cpp )
++
 +gen_kcfg_test_source(test_dpointer test_dpointer_SRCS)
 +
 +add_executable(test_dpointer ${test_dpointer_SRCS})
 +
 +target_link_libraries(test_dpointer Qt5::Widgets KConfigCore KConfigGui)
 +
 +
 +########### next target ###############
 +
 +set(test_signal_SRCS test_signal_main.cpp )
 +gen_kcfg_test_source(test_signal test_signal_SRCS)
 +add_executable(test_signal ${test_signal_SRCS})
 +target_link_libraries(test_signal Qt5::Widgets KConfigCore KConfigGui)
 +
 +########### next target ###############
 +
 +set(kconfigcompiler_test_SRCS kconfigcompiler_test.cpp )
 +add_executable(kconfigcompiler_test ${kconfigcompiler_test_SRCS})
 +add_test(kconfig-kconfigcompiler kconfigcompiler_test)
 +
 +target_link_libraries(kconfigcompiler_test ${QT_QTCORE_LIBS} ${QT_QTTEST_LIBRARY} \
${KCoreAddons_LIBRARIES})  +
 +########### install files ###############
 +
 +
 +
 +
 +
diff --cc tier2/kconfig/autotests/kconfig_compiler/test12.cpp.ref
index 0000000,f3bec18..f3bec18
mode 000000,100644..100644
--- a/tier2/kconfig/autotests/kconfig_compiler/test12.cpp.ref
+++ b/tier2/kconfig/autotests/kconfig_compiler/test12.cpp.ref
diff --cc tier2/kconfig/autotests/kconfig_compiler/test12.h.ref
index 0000000,9cec995..9cec995
mode 000000,100644..100644
--- a/tier2/kconfig/autotests/kconfig_compiler/test12.h.ref
+++ b/tier2/kconfig/autotests/kconfig_compiler/test12.h.ref
diff --cc tier2/kconfig/autotests/kconfig_compiler/test12.kcfg
index 0000000,57663ab..57663ab
mode 000000,100644..100644
--- a/tier2/kconfig/autotests/kconfig_compiler/test12.kcfg
+++ b/tier2/kconfig/autotests/kconfig_compiler/test12.kcfg
diff --cc tier2/kconfig/autotests/kconfig_compiler/test12.kcfgc
index 0000000,1ed82e7..1ed82e7
mode 000000,100644..100644
--- a/tier2/kconfig/autotests/kconfig_compiler/test12.kcfgc
+++ b/tier2/kconfig/autotests/kconfig_compiler/test12.kcfgc
diff --cc tier2/kconfig/autotests/kconfig_compiler/test12main.cpp
index 0000000,d39a70f..d39a70f
mode 000000,100644..100644
--- a/tier2/kconfig/autotests/kconfig_compiler/test12main.cpp
+++ b/tier2/kconfig/autotests/kconfig_compiler/test12main.cpp
diff --cc tier2/kconfig/src/kconfig_compiler/kconfig_compiler.cpp
index de2ca3b,0000000..2253a2b
mode 100644,000000..100644
--- a/tier2/kconfig/src/kconfig_compiler/kconfig_compiler.cpp
+++ b/tier2/kconfig/src/kconfig_compiler/kconfig_compiler.cpp
@@@ -1,2330 -1,0 +1,2334 @@@
 +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 +/*
 +    This file is part of KDE.
 +
 +    Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
 +    Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
 +    Copyright (c) 2003 Zack Rusin <zack@kde.org>
 +    Copyright (c) 2006 Michaël Larouche <michael.larouche@kdemail.net>
 +    Copyright (c) 2008 Allen Winter <winter@kde.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., 51 Franklin Street, Fifth Floor,
 +    Boston, MA 02110-1301, USA.
 +*/
 +
 +// Compiling this file with this flag is just crazy
 +#undef QT_NO_CAST_FROM_ASCII
 +
 +#include <QtCore/QCoreApplication>
 +#include <QtCore/QFile>
 +#include <QtCore/QFileInfo>
 +#include <QtCore/QSettings>
 +#include <QtCore/QTextStream>
 +#include <QtXml/QDomAttr>
 +#include <QtCore/QRegExp>
 +#include <QtCore/QStringList>
 +
 +#include <ostream>
 +#include <iostream>
 +#include <stdlib.h>
 +
 +namespace
 +{
 +  QTextStream cout(stdout);
 +  QTextStream cerr(stderr);
 +}
 +
 +static void parseArgs(const QStringList &args, QString &directory, QString &file1, \
QString &file2)  +{
 +    int fileCount = 0;
 +    directory = QChar::fromLatin1('.');
 +
 +    for (int i = 1; i < args.count(); ++i) {
 +        if (args.at(i) == QLatin1String("-d") ||  args.at(i) == \
QLatin1String("--directory")) {  +            if (i + 1 > args.count()) {
 +                cerr << args.at(i) << " needs an argument" << endl;
 +                exit(1);
 +            }
 +            directory = args.at(++i);
 +        } else if (args.at(i).startsWith(QLatin1String("-d"))) {
 +            directory = args.at(i).mid(2);
 +        } else if (args.at(i) == QLatin1String("--help") || args.at(i) == \
QLatin1String("-h")) {  +            cout << "Options:" << endl;
 +            cout << "  -L --license              Display software license" << endl;
 +            cout << "  -d, --directory <dir>     Directory to generate files in \
[.]" << endl;  +            cout << "  -h, --help                Display this help" \
<< endl;  +            cout << endl;
 +            cout << "Arguments:" << endl;
 +            cout << "      file.kcfg                 Input kcfg XML file" << endl;
 +            cout << "      file.kcfgc                Code generation options file" \
<< endl;  +            exit(0);
 +        } else if (args.at(i) == QLatin1String("--license") || args.at(i) == \
QLatin1String("-L")) {  +            cout << "Copyright 2003 Cornelius Schumacher, \
Waldo Bastian, Zack Rusin," << endl;  +            cout << "    Reinhold Kainhofer, \
Duncan Mac-Vicar P., Harald Fernengel" << endl;  +            cout << "This program \
comes with ABSOLUTELY NO WARRANTY." << endl;  +            cout << "You may \
redistribute copies of this program" << endl;  +            cout << "under the terms \
of the GNU Library Public License." << endl;  +            cout << "For more \
information about these matters, see the file named COPYING." << endl;  +            \
exit(0);  +        } else if (args.at(i).startsWith(QLatin1Char('-'))) {
 +            cerr << "Unknown option: " << args.at(i) << endl;
 +            exit(1);
 +        } else if (fileCount == 0) {
 +            file1 = args.at(i);
 +            ++fileCount;
 +        } else if (fileCount == 1) {
 +            file2 = args.at(i);
 +            ++fileCount;
 +        } else {
 +            cerr << "Too many arguments" << endl;
 +            exit(1);
 +        }
 +    }
 +    if (fileCount < 2) {
 +        cerr << "Too few arguments" << endl;
 +        exit(1);
 +    }
 +}
 +
 +QStringList allNames;
 +QRegExp *validNameRegexp;
 +QString This;
 +QString Const;
 +
 +/**
 +   Configuration Compiler Configuration
 +*/
 +class CfgConfig
 +{
 +public:
 +  CfgConfig( const QString &codegenFilename )
 +  {
 +    // Configure the compiler with some settings
 +    QSettings codegenConfig(codegenFilename, QSettings::IniFormat);
 +
 +    nameSpace = codegenConfig.value("NameSpace").toString();
 +    className = codegenConfig.value("ClassName").toString();
 +    if ( className.isEmpty() ) {
 +      cerr << "Class name missing" << endl;
 +      exit(1);
 +    }
 +    inherits = codegenConfig.value("Inherits").toString();
 +    if ( inherits.isEmpty() ) inherits = "KConfigSkeleton";
 +    visibility = codegenConfig.value("Visibility").toString();
 +    if ( !visibility.isEmpty() ) visibility += ' ';
 +    forceStringFilename = codegenConfig.value("ForceStringFilename", \
false).toBool();  +    singleton = codegenConfig.value("Singleton", false).toBool();
 +    staticAccessors = singleton;
 +    customAddons = codegenConfig.value("CustomAdditions", false).toBool();
 +    memberVariables = codegenConfig.value("MemberVariables").toString();
 +    dpointer = (memberVariables == "dpointer");
 +    headerIncludes = codegenConfig.value("IncludeFiles", \
QStringList()).toStringList();  +    sourceIncludes = \
codegenConfig.value("SourceIncludeFiles", QStringList()).toStringList();  +    \
mutators = codegenConfig.value("Mutators", QStringList()).toStringList();  +    \
allMutators = ((mutators.count() == 1) && (mutators.at(0).toLower() == "true"));  +   \
itemAccessors = codegenConfig.value("ItemAccessors", false).toBool();  +    \
setUserTexts = codegenConfig.value("SetUserTexts", false).toBool();  +    \
defaultGetters = codegenConfig.value("DefaultValueGetters", \
QStringList()).toStringList();  +    allDefaultGetters = (defaultGetters.count() == \
1) && (defaultGetters.at(0).toLower() == "true");  +    globalEnums = \
codegenConfig.value("GlobalEnums", false).toBool();  +    useEnumTypes = \
codegenConfig.value("UseEnumTypes", false).toBool();  +
 +    const QString trString = \
codegenConfig.value("TranslationSystem").toString().toLower();  +    if ( trString == \
"kde" ) {  +        translationSystem = KdeTranslation;
 +    } else {
 +        if ( !trString.isEmpty() && trString != "qt" ) {
 +            cerr << "Unknown translation system, falling back to Qt tr()" << endl;
 +        }
 +        translationSystem = QtTranslation;
 +    }
 +  }
 +
 +public:
 +  enum TranslationSystem {
 +      QtTranslation,
 +      KdeTranslation
 +  };
 +
 +  // These are read from the .kcfgc configuration file
 +  QString nameSpace;     // The namespace for the class to be generated
 +  QString className;     // The class name to be generated
 +  QString inherits;      // The class the generated class inherits (if empty, from \
KConfigSkeleton)  +  QString visibility;
 +  bool forceStringFilename;
 +  bool singleton;        // The class will be a singleton
 +  bool staticAccessors;  // provide or not static accessors
 +  bool customAddons;
 +  QString memberVariables;
 +  QStringList headerIncludes;
 +  QStringList sourceIncludes;
 +  QStringList mutators;
 +  QStringList defaultGetters;
 +  bool allMutators;
 +  bool setUserTexts;
 +  bool allDefaultGetters;
 +  bool dpointer;
 +  bool globalEnums;
 +  bool useEnumTypes;
 +  bool itemAccessors;
 +  TranslationSystem translationSystem;
 +};
 +
 +
 +struct SignalArguments
 +{
 +      QString type;
 +      QString variableName;
 +};
 +
 +class Signal {
 +public:
 +  QString name;
 +  QString label;
 +  QList<SignalArguments> arguments;
 +};
 +
 +
 +
 +
 +class CfgEntry
 +{
 +  public:
 +    struct Choice
 +    {
 +      QString name;
 +      QString context;
 +      QString label;
 +      QString toolTip;
 +      QString whatsThis;
 +    };
 +    class Choices
 +    {
 +      public:
 +        Choices() {}
 +        Choices( const QList<Choice> &d, const QString &n, const QString &p )
 +             : prefix(p), choices(d), mName(n)
 +        {
 +          int i = n.indexOf(QLatin1String("::"));
 +          if (i >= 0)
 +            mExternalQual = n.left(i + 2);
 +        }
 +        QString prefix;
 +        QList<Choice> choices;
 +        const QString& name() const  { return mName; }
 +        const QString& externalQualifier() const  { return mExternalQual; }
 +        bool external() const  { return !mExternalQual.isEmpty(); }
 +      private:
 +        QString mName;
 +        QString mExternalQual;
 +    };
 +
 +    CfgEntry( const QString &group, const QString &type, const QString &key,
 +              const QString &name, const QString &labelContext, const QString \
&label,  +              const QString &toolTipContext, const QString &toolTip, const \
QString &whatsThisContext, const QString &whatsThis, const QString &code,  +          \
const QString &defaultValue, const Choices &choices, const QList<Signal> signalList,  \
+              bool hidden )  +      : mGroup( group ), mType( type ), mKey( key ), \
mName( name ),  +        mLabelContext( labelContext ), mLabel( label ), \
mToolTipContext( toolTipContext ), mToolTip( toolTip ),  +        mWhatsThisContext( \
whatsThisContext ), mWhatsThis( whatsThis ),  +        mCode( code ), mDefaultValue( \
defaultValue ), mChoices( choices ),  +        mSignalList(signalList), mHidden( \
hidden )  +    {
 +    }
 +
 +    void setGroup( const QString &group ) { mGroup = group; }
 +    QString group() const { return mGroup; }
 +
 +    void setType( const QString &type ) { mType = type; }
 +    QString type() const { return mType; }
 +
 +    void setKey( const QString &key ) { mKey = key; }
 +    QString key() const { return mKey; }
 +
 +    void setName( const QString &name ) { mName = name; }
 +    QString name() const { return mName; }
 +
 +    void setLabelContext( const QString &labelContext ) { mLabelContext = \
labelContext; }  +    QString labelContext() const { return mLabelContext; }
 +
 +    void setLabel( const QString &label ) { mLabel = label; }
 +    QString label() const { return mLabel; }
 +
 +    void setToolTipContext( const QString &toolTipContext ) { mToolTipContext = \
toolTipContext; }  +    QString toolTipContext() const { return mToolTipContext; }
 +
 +    void setToolTip( const QString &toolTip ) { mToolTip = toolTip; }
 +    QString toolTip() const { return mToolTip; }
 +
 +    void setWhatsThisContext( const QString &whatsThisContext ) { mWhatsThisContext \
= whatsThisContext; }  +    QString whatsThisContext() const { return \
mWhatsThisContext; }  +
 +    void setWhatsThis( const QString &whatsThis ) { mWhatsThis = whatsThis; }
 +    QString whatsThis() const { return mWhatsThis; }
 +
 +    void setDefaultValue( const QString &d ) { mDefaultValue = d; }
 +    QString defaultValue() const { return mDefaultValue; }
 +
 +    void setCode( const QString &d ) { mCode = d; }
 +    QString code() const { return mCode; }
 +
 +    void setMinValue( const QString &d ) { mMin = d; }
 +    QString minValue() const { return mMin; }
 +
 +    void setMaxValue( const QString &d ) { mMax = d; }
 +    QString maxValue() const { return mMax; }
 +
 +    void setParam( const QString &d ) { mParam = d; }
 +    QString param() const { return mParam; }
 +
 +    void setParamName( const QString &d ) { mParamName = d; }
 +    QString paramName() const { return mParamName; }
 +
 +    void setParamType( const QString &d ) { mParamType = d; }
 +    QString paramType() const { return mParamType; }
 +
 +    void setChoices( const QList<Choice> &d, const QString &n, const QString &p ) { \
mChoices = Choices( d, n, p ); }  +    Choices choices() const { return mChoices; }
 +
 +    void setParamValues( const QStringList &d ) { mParamValues = d; }
 +    QStringList paramValues() const { return mParamValues; }
 +
 +    void setParamDefaultValues( const QStringList &d ) { mParamDefaultValues = d; }
 +    QString paramDefaultValue(int i) const { return mParamDefaultValues[i]; }
 +
 +    void setParamMax( int d ) { mParamMax = d; }
 +    int paramMax() const { return mParamMax; }
 +
 +    void setSignalList( const QList<Signal> &value ) { mSignalList = value; }
 +    QList<Signal> signalList() const { return mSignalList; }
 +
 +    bool hidden() const { return mHidden; }
 +
 +    void dump() const
 +    {
 +      cerr << "<entry>" << endl;
 +      cerr << "  group: " << mGroup << endl;
 +      cerr << "  type: " << mType << endl;
 +      cerr << "  key: " << mKey << endl;
 +      cerr << "  name: " << mName << endl;
 +      cerr << "  label context: " << mLabelContext << endl;
 +      cerr << "  label: " << mLabel << endl;
 +// whatsthis
 +      cerr << "  code: " << mCode << endl;
 +//      cerr << "  values: " << mValues.join(":") << endl;
 +
 +      if (!param().isEmpty())
 +      {
 +        cerr << "  param name: "<< mParamName << endl;
 +        cerr << "  param type: "<< mParamType << endl;
 +        cerr << "  paramvalues: " << mParamValues.join(QChar::fromLatin1(':')) << \
endl;  +      }
 +      cerr << "  default: " << mDefaultValue << endl;
 +      cerr << "  hidden: " << mHidden << endl;
 +      cerr << "  min: " << mMin << endl;
 +      cerr << "  max: " << mMax << endl;
 +      cerr << "</entry>" << endl;
 +    }
 +
 +  private:
 +    QString mGroup;
 +    QString mType;
 +    QString mKey;
 +    QString mName;
 +    QString mLabelContext;
 +    QString mLabel;
 +    QString mToolTipContext;
 +    QString mToolTip;
 +    QString mWhatsThisContext;
 +    QString mWhatsThis;
 +    QString mCode;
 +    QString mDefaultValue;
 +    QString mParam;
 +    QString mParamName;
 +    QString mParamType;
 +    Choices mChoices;
 +    QList<Signal> mSignalList;
 +    QStringList mParamValues;
 +    QStringList mParamDefaultValues;
 +    int mParamMax;
 +    bool mHidden;
 +    QString mMin;
 +    QString mMax;
 +};
 +
 +class Param {
 +public:
 +  QString name;
 +  QString type;
 +};
 +
 +// returns the name of an member variable
 +// use itemPath to know the full path
 +// like using d-> in case of dpointer
 +static QString varName(const QString &n, const CfgConfig &cfg)
 +{
 +  QString result;
 +  if ( !cfg.dpointer ) {
 +    result = QChar::fromLatin1('m') + n;
 +    result[1] = result[1].toUpper();
 +  }
 +  else {
 +    result = n;
 +    result[0] = result[0].toLower();
 +  }
 +  return result;
 +}
 +
 +static QString varPath(const QString &n, const CfgConfig &cfg)
 +{
 +  QString result;
 +  if ( cfg.dpointer ) {
 +    result = "d->"+varName(n, cfg);
 +  }
 +  else {
 +    result = varName(n, cfg);
 +  }
 +  return result;
 +}
 +
 +static QString enumName(const QString &n)
 +{
 +  QString result = QString::fromLatin1("Enum") + n;
 +  result[4] = result[4].toUpper();
 +  return result;
 +}
 +
 +static QString enumName(const QString &n, const CfgEntry::Choices &c)
 +{
 +  QString result = c.name();
 +  if ( result.isEmpty() )
 +  {
 +    result = QString::fromLatin1("Enum") + n;
 +    result[4] = result[4].toUpper();
 +  }
 +  return result;
 +}
 +
 +static QString enumType(const CfgEntry *e, bool globalEnums)
 +{
 +  QString result = e->choices().name();
 +  if ( result.isEmpty() )
 +  {
 +    result = QString::fromLatin1("Enum") + e->name();
 +    if( !globalEnums )
 +        result += QString::fromLatin1("::type");
 +    result[4] = result[4].toUpper();
 +  }
 +  return result;
 +}
 +
 +static QString enumTypeQualifier(const QString &n, const CfgEntry::Choices &c)
 +{
 +  QString result = c.name();
 +  if ( result.isEmpty() )
 +  {
 +    result = QString::fromLatin1("Enum") + n + QString::fromLatin1("::");
 +    result[4] = result[4].toUpper();
 +  }
 +  else if ( c.external() )
 +    result = c.externalQualifier();
 +  else
 +    result.clear();
 +  return result;
 +}
 +
 +static QString setFunction(const QString &n, const QString &className = QString())
 +{
 +  QString result = QString::fromLatin1("set") + n;
 +  result[3] = result[3].toUpper();
 +
 +  if ( !className.isEmpty() )
 +    result = className + QString::fromLatin1("::") + result;
 +  return result;
 +}
 +
 +static QString getDefaultFunction(const QString &n, const QString &className = \
QString())  +{
 +  QString result = QString::fromLatin1("default") +  n + \
QString::fromLatin1("Value");  +  result[7] = result[7].toUpper();
 +
 +  if ( !className.isEmpty() )
 +    result = className + QString::fromLatin1("::") + result;
 +  return result;
 +}
 +
 +static QString getFunction(const QString &n, const QString &className = QString())
 +{
 +  QString result = n;
 +  result[0] = result[0].toLower();
 +
 +  if ( !className.isEmpty() )
 +    result = className + QString::fromLatin1("::") + result;
 +  return result;
 +}
 +
 +
 +static void addQuotes( QString &s )
 +{
 +  if ( !s.startsWith( QLatin1Char('"') ) )
 +    s.prepend( QLatin1Char('"') );
 +  if ( !s.endsWith( QLatin1Char('"') ) )
 +    s.append( QLatin1Char('"') );
 +}
 +
 +static QString quoteString( const QString &s )
 +{
 +  QString r = s;
 +  r.replace( QLatin1Char('\\'), QLatin1String("\\\\") );
 +  r.replace( QLatin1Char('\"'), QLatin1String("\\\"") );
 +  r.remove( QLatin1Char('\r') );
 +  r.replace( QLatin1Char('\n'), QLatin1String("\\n\"\n\"") );
 +  return QLatin1Char('\"') + r + QLatin1Char('\"');
 +}
 +
 +static QString literalString( const QString &s )
 +{
 +  bool isAscii = true;
 +  for(int i = s.length(); i--;)
 +     if (s[i].unicode() > 127) isAscii = false;
 +
 +  if (isAscii)
 +     return QString::fromLatin1("QLatin1String( ") + quoteString(s) + \
QString::fromLatin1(" )");  +  else
 +     return QString::fromLatin1("QString::fromUtf8( ") + quoteString(s) + \
QString::fromLatin1(" )");  +}
 +
 +static QString dumpNode(const QDomNode &node)
 +{
 +  QString msg;
 +  QTextStream s(&msg, QIODevice::WriteOnly );
 +  node.save(s, 0);
 +
 +  msg = msg.simplified();
 +  if (msg.length() > 40)
 +    return msg.left(37) + QString::fromLatin1("...");
 +  return msg;
 +}
 +
 +static QString filenameOnly(const QString& path)
 +{
 +   int i = path.lastIndexOf(QRegExp(QLatin1String("[/\\]")));
 +   if (i >= 0)
 +      return path.mid(i+1);
 +   return path;
 +}
 +
 +static QString signalEnumName(const QString &signalName)
 +{
 +  QString result;
 +  result = QString::fromLatin1("signal") + signalName;
 +  result[6] = result[6].toUpper();
 +
 +  return result;
 +}
 +
 +static void preProcessDefault( QString &defaultValue, const QString &name,
 +                               const QString &type,
 +                               const CfgEntry::Choices &choices,
 +                               QString &code, const CfgConfig &cfg )
 +{
 +    if ( type == QLatin1String("String") && !defaultValue.isEmpty() ) {
 +      defaultValue = literalString(defaultValue);
 +
 +    } else if ( type == QLatin1String("Path") && !defaultValue.isEmpty() ) {
 +      defaultValue = literalString( defaultValue );
 +    } else if ( type == QLatin1String("Url") && !defaultValue.isEmpty() ) {
 +      // Use fromUserInput in order to support absolute paths and absolute urls, \
like KDE4's KUrl(QString) did.  +      defaultValue = \
QString::fromLatin1("QUrl::fromUserInput( ") + literalString(defaultValue) + \
QLatin1Char(')');  +    } else if ( ( type == QLatin1String("UrlList") || type == \
QLatin1String("StringList") || type == QLatin1String("PathList")) && \
!defaultValue.isEmpty() ) {  +      QTextStream cpp( &code, QIODevice::WriteOnly | \
QIODevice::Append );  +      if (!code.isEmpty())
 +         cpp << endl;
 +
-       cpp << "  QStringList default" << name << ";" << endl;
++      if( type == "UrlList" ) {
++        cpp << "  KUrl::List default" << name << ";" << endl;
++      } else {
++        cpp << "  QStringList default" << name << ";" << endl;
++      }
 +      const QStringList defaults = defaultValue.split(QLatin1Char(','));
 +      QStringList::ConstIterator it;
 +      for( it = defaults.constBegin(); it != defaults.constEnd(); ++it ) {
 +        cpp << "  default" << name << ".append( ";
 +        if( type == QLatin1String("UrlList") ) {
 +          cpp << "QUrl::fromUserInput(";
 +        }
 +        cpp << "QString::fromUtf8( \"" << *it << "\" ) ";
 +        if( type == QLatin1String("UrlList") ) {
 +          cpp << ") ";
 +        }
 +        cpp << ");" << endl;
 +      }
 +      defaultValue = QString::fromLatin1("default") + name;
 +
 +    } else if ( type == QLatin1String("Color") && !defaultValue.isEmpty() ) {
 +      QRegExp colorRe(QLatin1String("\\d+,\\s*\\d+,\\s*\\d+(,\\s*\\d+)?"));
 +      if (colorRe.exactMatch(defaultValue))
 +      {
 +        defaultValue = QLatin1String("QColor( ") + defaultValue + QLatin1String(" \
)");  +      }
 +      else
 +      {
 +        defaultValue = QLatin1String("QColor( \"") + defaultValue + \
QLatin1String("\" )");  +      }
 +
 +    } else if ( type == QLatin1String("Enum") ) {
 +      QList<CfgEntry::Choice>::ConstIterator it;
 +      for( it = choices.choices.constBegin(); it != choices.choices.constEnd(); \
++it ) {  +        if ( (*it).name == defaultValue ) {
 +          if ( cfg.globalEnums && choices.name().isEmpty() )
 +            defaultValue.prepend( choices.prefix );
 +          else
 +            defaultValue.prepend( enumTypeQualifier(name, choices) + choices.prefix \
);  +          break;
 +        }
 +      }
 +
 +    } else if ( type == QLatin1String("IntList") ) {
 +      QTextStream cpp( &code, QIODevice::WriteOnly | QIODevice::Append );
 +      if (!code.isEmpty())
 +         cpp << endl;
 +
 +      cpp << "  QList<int> default" << name << ";" << endl;
 +      if (!defaultValue.isEmpty())
 +      {
 +        const QStringList defaults = defaultValue.split( QLatin1Char(',') );
 +        QStringList::ConstIterator it;
 +        for( it = defaults.constBegin(); it != defaults.constEnd(); ++it ) {
 +          cpp << "  default" << name << ".append( " << *it << " );"
 +              << endl;
 +        }
 +      }
 +      defaultValue = QString::fromLatin1("default") + name;
 +    }
 +}
 +
 +
 +CfgEntry *parseEntry( const QString &group, const QDomElement &element, const \
CfgConfig &cfg )  +{
 +  bool defaultCode = false;
 +  QString type = element.attribute( "type" );
 +  QString name = element.attribute( "name" );
 +  QString key = element.attribute( "key" );
 +  QString hidden = element.attribute( "hidden" );
 +  QString labelContext;
 +  QString label;
 +  QString toolTipContext;
 +  QString toolTip;
 +  QString whatsThisContext;
 +  QString whatsThis;
 +  QString defaultValue;
 +  QString code;
 +  QString param;
 +  QString paramName;
 +  QString paramType;
 +  CfgEntry::Choices choices;
 +  QList<Signal> signalList;
 +  QStringList paramValues;
 +  QStringList paramDefaultValues;
 +  QString minValue;
 +  QString maxValue;
 +  int paramMax = 0;
 +
 +  for ( QDomElement e = element.firstChildElement(); !e.isNull(); e = \
e.nextSiblingElement() ) {  +    QString tag = e.tagName();
 +    if ( tag == "label" ) {
 +      label = e.text();
 +      labelContext = e.attribute( "context" );
 +    }
 +    else if ( tag == "tooltip" ) {
 +      toolTip = e.text();
 +      toolTipContext = e.attribute( "context" );
 +    }
 +    else if ( tag == "whatsthis" ) {
 +      whatsThis = e.text();
 +      whatsThisContext = e.attribute( "context" );
 +    }
 +    else if ( tag == "min" ) minValue = e.text();
 +    else if ( tag == "max" ) maxValue = e.text();
 +    else if ( tag == "code" ) code = e.text();
 +    else if ( tag == "parameter" )
 +    {
 +      param = e.attribute( "name" );
 +      paramType = e.attribute( "type" );
 +      if ( param.isEmpty() ) {
 +        cerr << "Parameter must have a name: " << dumpNode(e) << endl;
 +        return 0;
 +      }
 +      if ( paramType.isEmpty() ) {
 +        cerr << "Parameter must have a type: " << dumpNode(e) << endl;
 +        return 0;
 +      }
 +      if ((paramType == "Int") || (paramType == "UInt"))
 +      {
 +         bool ok;
 +         paramMax = e.attribute("max").toInt(&ok);
 +         if (!ok)
 +         {
 +           cerr << "Integer parameter must have a maximum (e.g. max=\"0\"): "
 +                       << dumpNode(e) << endl;
 +           return 0;
 +         }
 +      }
 +      else if (paramType == "Enum")
 +      {
 +         for ( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = \
e2.nextSiblingElement() ) {  +           if (e2.tagName() == "values")
 +           {
 +             for ( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = \
e3.nextSiblingElement() ) {  +               if (e3.tagName() == "value")
 +               {
 +                  paramValues.append( e3.text() );
 +               }
 +             }
 +             break;
 +           }
 +         }
 +         if (paramValues.isEmpty())
 +         {
 +           cerr << "No values specified for parameter '" << param
 +                       << "'." << endl;
 +           return 0;
 +         }
 +         paramMax = paramValues.count()-1;
 +      }
 +      else
 +      {
 +        cerr << "Parameter '" << param << "' has type " << paramType
 +                    << " but must be of type int, uint or Enum." << endl;
 +        return 0;
 +      }
 +    }
 +    else if ( tag == "default" )
 +    {
 +      if (e.attribute("param").isEmpty())
 +      {
 +        defaultValue = e.text();
 +        if (e.attribute( "code" ) == "true")
 +          defaultCode = true;
 +      }
 +    }
 +    else if ( tag == "choices" ) {
 +      QString name = e.attribute( "name" );
 +      QString prefix = e.attribute( "prefix" );
 +      QList<CfgEntry::Choice> chlist;
 +      for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = \
e2.nextSiblingElement() ) {  +        if ( e2.tagName() == "choice" ) {
 +          CfgEntry::Choice choice;
 +          choice.name = e2.attribute( "name" );
 +          if ( choice.name.isEmpty() ) {
 +            cerr << "Tag <choice> requires attribute 'name'." << endl;
 +          }
 +          for( QDomElement e3 = e2.firstChildElement(); !e3.isNull(); e3 = \
e3.nextSiblingElement() ) {  +            if ( e3.tagName() == "label" ) {
 +              choice.label = e3.text();
 +              choice.context = e3.attribute( "context" );
 +            }
 +            if ( e3.tagName() == "tooltip" ) {
 +              choice.toolTip = e3.text();
 +              choice.context = e3.attribute( "context" );
 +            }
 +            if ( e3.tagName() == "whatsthis" ) {
 +              choice.whatsThis = e3.text();
 +              choice.context = e3.attribute( "context" );
 +            }
 +          }
 +          chlist.append( choice );
 +        }
 +      }
 +      choices = CfgEntry::Choices( chlist, name, prefix );
 +    }
 +   else if ( tag == "emit" ) {
 +    QDomNode signalNode;
 +    Signal signal;
 +    signal.name = e.attribute( "signal" );
 +    signalList.append( signal);
 +   }
 +  }
 +
 +
 +  bool nameIsEmpty = name.isEmpty();
 +  if ( nameIsEmpty && key.isEmpty() ) {
 +    cerr << "Entry must have a name or a key: " << dumpNode(element) << endl;
 +    return 0;
 +  }
 +
 +  if ( key.isEmpty() ) {
 +    key = name;
 +  }
 +
 +  if ( nameIsEmpty ) {
 +    name = key;
 +    name.remove( ' ' );
 +  } else if ( name.contains( ' ' ) ) {
 +    cout<<"Entry '"<<name<<"' contains spaces! <name> elements can not contain \
spaces!"<<endl;  +    name.remove( ' ' );
 +  }
 +
 +  if (name.contains("$("))
 +  {
 +    if (param.isEmpty())
 +    {
 +      cerr << "Name may not be parameterized: " << name << endl;
 +      return 0;
 +    }
 +  }
 +  else
 +  {
 +    if (!param.isEmpty())
 +    {
 +      cerr << "Name must contain '$(" << param << ")': " << name << endl;
 +      return 0;
 +    }
 +  }
 +
 +  if ( label.isEmpty() ) {
 +    label = key;
 +  }
 +
 +  if ( type.isEmpty() ) type = "String"; // XXX : implicit type might be bad
 +
 +  if (!param.isEmpty())
 +  {
 +    // Adjust name
 +    paramName = name;
 +    name.remove("$("+param+')');
 +    // Lookup defaults for indexed entries
 +    for(int i = 0; i <= paramMax; i++)
 +    {
 +      paramDefaultValues.append(QString());
 +    }
 +
 +    for ( QDomElement e = element.firstChildElement(); !e.isNull(); e = \
e.nextSiblingElement() ) {  +      QString tag = e.tagName();
 +      if ( tag == "default" )
 +      {
 +        QString index = e.attribute("param");
 +        if (index.isEmpty())
 +           continue;
 +
 +        bool ok;
 +        int i = index.toInt(&ok);
 +        if (!ok)
 +        {
 +          i = paramValues.indexOf(index);
 +          if (i == -1)
 +          {
 +            cerr << "Index '" << index << "' for default value is unknown." << \
endl;  +            return 0;
 +          }
 +        }
 +
 +        if ((i < 0) || (i > paramMax))
 +        {
 +          cerr << "Index '" << i << "' for default value is out of range [0, "<< \
paramMax<<"]." << endl;  +          return 0;
 +        }
 +
 +        QString tmpDefaultValue = e.text();
 +
 +        if (e.attribute( "code" ) != "true")
 +           preProcessDefault(tmpDefaultValue, name, type, choices, code, cfg);
 +
 +        paramDefaultValues[i] = tmpDefaultValue;
 +      }
 +    }
 +  }
 +
 +  if (!validNameRegexp->exactMatch(name))
 +  {
 +    if (nameIsEmpty)
 +      cerr << "The key '" << key << "' can not be used as name for the entry \
because "  +                   "it is not a valid name. You need to specify a valid \
name for this entry." << endl;  +    else
 +      cerr << "The name '" << name << "' is not a valid name for an entry." << \
endl;  +    return 0;
 +  }
 +
 +  if (allNames.contains(name))
 +  {
 +    if (nameIsEmpty)
 +      cerr << "The key '" << key << "' can not be used as name for the entry \
because "  +                   "it does not result in a unique name. You need to \
specify a unique name for this entry." << endl;  +    else
 +      cerr << "The name '" << name << "' is not unique." << endl;
 +    return 0;
 +  }
 +  allNames.append(name);
 +
 +  if (!defaultCode)
 +  {
 +    preProcessDefault(defaultValue, name, type, choices, code, cfg);
 +  }
 +
 +  CfgEntry *result = new CfgEntry( group, type, key, name, labelContext, label, \
toolTipContext, toolTip, whatsThisContext, whatsThis,  +                              \
code, defaultValue, choices, signalList,  +                                   hidden \
== "true" );  +  if (!param.isEmpty())
 +  {
 +    result->setParam(param);
 +    result->setParamName(paramName);
 +    result->setParamType(paramType);
 +    result->setParamValues(paramValues);
 +    result->setParamDefaultValues(paramDefaultValues);
 +    result->setParamMax(paramMax);
 +  }
 +  result->setMinValue(minValue);
 +  result->setMaxValue(maxValue);
 +
 +  return result;
 +}
 +
 +static bool isUnsigned(const QString& type)
 +{
 +    if ( type == "UInt" )        return true;
 +    if ( type == "ULongLong" )   return true;
 +    return false;
 +}
 +
 +/**
 +  Return parameter declaration for given type.
 +*/
 +QString param( const QString &t )
 +{
 +    const QString type = t.toLower();
 +    if ( type == "string" )           return "const QString &";
 +    else if ( type == "stringlist" )  return "const QStringList &";
 +    else if ( type == "font" )        return "const QFont &";
 +    else if ( type == "rect" )        return "const QRect &";
 +    else if ( type == "size" )        return "const QSize &";
 +    else if ( type == "color" )       return "const QColor &";
 +    else if ( type == "point" )       return "const QPoint &";
 +    else if ( type == "int" )         return "int";
 +    else if ( type == "uint" )        return "uint";
 +    else if ( type == "bool" )        return "bool";
 +    else if ( type == "double" )      return "double";
 +    else if ( type == "datetime" )    return "const QDateTime &";
 +    else if ( type == "longlong" )    return "qint64";
 +    else if ( type == "ulonglong" )   return "quint64";
 +    else if ( type == "intlist" )     return "const QList<int> &";
 +    else if ( type == "enum" )        return "int";
 +    else if ( type == "path" )        return "const QString &";
 +    else if ( type == "pathlist" )    return "const QStringList &";
 +    else if ( type == "password" )    return "const QString &";
 +    else if ( type == "url" )         return "const QUrl &";
 +    else if ( type == "urllist" )     return "const QList<QUrl> &";
 +    else {
 +        cerr <<"kconfig_compiler does not support type \""<< type <<"\""<<endl;
 +        return "QString"; //For now, but an assert would be better
 +    }
 +}
 +
 +/**
 +  Actual C++ storage type for given type.
 +*/
 +QString cppType( const QString &t )
 +{
 +    const QString type = t.toLower();
 +    if ( type == "string" )           return "QString";
 +    else if ( type == "stringlist" )  return "QStringList";
 +    else if ( type == "font" )        return "QFont";
 +    else if ( type == "rect" )        return "QRect";
 +    else if ( type == "size" )        return "QSize";
 +    else if ( type == "color" )       return "QColor";
 +    else if ( type == "point" )       return "QPoint";
 +    else if ( type == "int" )         return "int";
 +    else if ( type == "uint" )        return "uint";
 +    else if ( type == "bool" )        return "bool";
 +    else if ( type == "double" )      return "double";
 +    else if ( type == "datetime" )    return "QDateTime";
 +    else if ( type == "longlong" )    return "qint64";
 +    else if ( type == "ulonglong" )   return "quint64";
 +    else if ( type == "intlist" )     return "QList<int>";
 +    else if ( type == "enum" )        return "int";
 +    else if ( type == "path" )        return "QString";
 +    else if ( type == "pathlist" )    return "QStringList";
 +    else if ( type == "password" )    return "QString";
 +    else if ( type == "url" )         return "QUrl";
 +    else if ( type == "urllist" )     return "QList<QUrl>";
 +    else {
 +        cerr<<"kconfig_compiler does not support type \""<< type <<"\""<<endl;
 +        return "QString"; //For now, but an assert would be better
 +    }
 +}
 +
 +QString defaultValue( const QString &t )
 +{
 +    const QString type = t.toLower();
 +    if ( type == "string" )           return "\"\""; // Use empty string, not null \
string!  +    else if ( type == "stringlist" )  return "QStringList()";
 +    else if ( type == "font" )        return "QFont()";
 +    else if ( type == "rect" )        return "QRect()";
 +    else if ( type == "size" )        return "QSize()";
 +    else if ( type == "color" )       return "QColor(128, 128, 128)";
 +    else if ( type == "point" )       return "QPoint()";
 +    else if ( type == "int" )         return "0";
 +    else if ( type == "uint" )        return "0";
 +    else if ( type == "bool" )        return "false";
 +    else if ( type == "double" )      return "0.0";
 +    else if ( type == "datedime" )    return "QDateTime()";
 +    else if ( type == "longlong" )    return "0";
 +    else if ( type == "ulonglong" )   return "0";
 +    else if ( type == "intlist" )     return "QList<int>()";
 +    else if ( type == "enum" )        return "0";
 +    else if ( type == "path" )        return "\"\""; // Use empty string, not null \
string!  +    else if ( type == "pathlist" )    return "QStringList()";
 +    else if ( type == "password" )    return "\"\""; // Use empty string, not null \
string!  +    else if ( type == "url" )         return "QUrl()";
 +    else if ( type == "urllist" )     return "QList<QUrl>()";
 +    else {
 +        cerr<<"Error, kconfig_compiler does not support the \""<< type <<"\" \
type!"<<endl;  +        return "QString"; //For now, but an assert would be better
 +    }
 +}
 +
 +QString itemType( const QString &type )
 +{
 +  QString t;
 +
 +  t = type;
 +  t.replace( 0, 1, t.left( 1 ).toUpper() );
 +
 +  return t;
 +}
 +
 +static QString itemDeclaration(const CfgEntry *e, const CfgConfig &cfg)
 +{
 +  if (cfg.itemAccessors)
 +     return QString();
 +
 +  QString fCap = e->name();
 +  fCap[0] = fCap[0].toUpper();
 +  return "  "+cfg.inherits+"::Item"+itemType( e->type() ) +
 +         "  *item" + fCap +
 +         ( (!e->param().isEmpty())?(QString("[%1]").arg(e->paramMax()+1)) : \
QString()) +  +         ";\n";
 +}
 +
 +// returns the name of an item variable
 +// use itemPath to know the full path
 +// like using d-> in case of dpointer
 +static QString itemVar(const CfgEntry *e, const CfgConfig &cfg)
 +{
 +  QString result;
 +  if (cfg.itemAccessors)
 +  {
 +    if ( !cfg.dpointer )
 +    {
 +      result = 'm' + e->name() + "Item";
 +      result[1] = result[1].toUpper();
 +    }
 +    else
 +    {
 +      result = e->name() + "Item";
 +      result[0] = result[0].toLower();
 +    }
 +  }
 +  else
 +  {
 +    result = "item" + e->name();
 +    result[4] = result[4].toUpper();
 +  }
 +  return result;
 +}
 +
 +static QString itemPath(const CfgEntry *e, const CfgConfig &cfg)
 +{
 +  QString result;
 +  if ( cfg.dpointer ) {
 +    result = "d->"+itemVar(e, cfg);
 +  }
 +  else {
 +    result = itemVar(e, cfg);
 +  }
 +  return result;
 +}
 +
 +QString newItem( const QString &type, const QString &name, const QString &key,
 +                 const QString &defaultValue, const CfgConfig &cfg, const QString \
&param = QString())  +{
 +  QString t = "new "+cfg.inherits+"::Item" + itemType( type ) +
 +              "( currentGroup(), " + key + ", " + varPath( name, cfg ) + param;
 +  if ( type == "Enum" ) t += ", values" + name;
 +  if ( !defaultValue.isEmpty() ) {
 +    t += ", ";
 +    if ( type == "String" ) t += defaultValue;
 +    else t+= defaultValue;
 +  }
 +  t += " );";
 +
 +  return t;
 +}
 +
 +QString paramString(const QString &s, const CfgEntry *e, int i)
 +{
 +  QString result = s;
 +  QString needle = "$("+e->param()+')';
 +  if (result.contains(needle))
 +  {
 +    QString tmp;
 +    if (e->paramType() == "Enum")
 +    {
 +      tmp = e->paramValues()[i];
 +    }
 +    else
 +    {
 +      tmp = QString::number(i);
 +    }
 +
 +    result.replace(needle, tmp);
 +  }
 +  return result;
 +}
 +
 +QString paramString(const QString &group, const QList<Param> &parameters)
 +{
 +  QString paramString = group;
 +  QString arguments;
 +  int i = 1;
 +  for (QList<Param>::ConstIterator it = parameters.constBegin();
 +       it != parameters.constEnd(); ++it)
 +  {
 +     if (paramString.contains("$("+(*it).name+')'))
 +     {
 +       QString tmp;
 +       tmp.sprintf("%%%d", i++);
 +       paramString.replace("$("+(*it).name+')', tmp);
 +       arguments += ".arg( mParam"+(*it).name+" )";
 +     }
 +  }
 +  if (arguments.isEmpty())
 +    return "QLatin1String( \""+group+"\" )";
 +
 +  return "QString( QLatin1String( \""+paramString+"\" ) )"+arguments;
 +}
 +
 +QString translatedString(const CfgConfig &cfg, const QString &string, const QString \
&context = QString(), const QString &param = QString(), const QString &paramValue = \
QString())  +{
 +    QString result;
 +
 +    switch (cfg.translationSystem) {
 +    case CfgConfig::QtTranslation:
 +        if (!context.isEmpty()) {
 +            result+= "/*: " + context + " */ QObject::tr(";
 +        } else {
 +            result+= "QObject::tr(";
 +        }
 +        break;
 +
 +    case CfgConfig::KdeTranslation:
 +        if (!context.isEmpty()) {
 +            result+= "i18nc(" + quoteString(context) + ", ";
 +        } else {
 +            result+= "i18n(";
 +        }
 +        break;
 +    }
 +
 +    if (!param.isEmpty()) {
 +        QString resolvedString = string;
 +        resolvedString.replace("$("+param+')', paramValue);
 +        result+= quoteString(resolvedString);
 +    } else {
 +        result+= quoteString(string);
 +    }
 +
 +    result+= ')';
 +
 +    return result;
 +}
 +
 +/* int i is the value of the parameter */
 +QString userTextsFunctions( CfgEntry *e, const CfgConfig &cfg, QString \
itemVarStr=QString(), QString i=QString() )  +{
 +  QString txt;
 +  if (itemVarStr.isNull()) itemVarStr=itemPath(e, cfg);
 +  if ( !e->label().isEmpty() ) {
 +    txt += "  " + itemVarStr + "->setLabel( ";
 +    txt += translatedString(cfg, e->label(), e->labelContext(), e->param(), i);
 +    txt += " );\n";
 +  }
 +  if ( !e->toolTip().isEmpty() ) {
 +    txt += "  " + itemVarStr + "->setToolTip( ";
 +    txt += translatedString(cfg, e->toolTip(), e->toolTipContext(), e->param(), i);
 +    txt += " );\n";
 +  }
 +  if ( !e->whatsThis().isEmpty() ) {
 +    txt += "  " + itemVarStr + "->setWhatsThis( ";
 +    txt += translatedString(cfg, e->whatsThis(), e->whatsThisContext(), e->param(), \
i);  +    txt += " );\n";
 +  }
 +  return txt;
 +}
 +
 +// returns the member accesor implementation
 +// which should go in the h file if inline
 +// or the cpp file if not inline
 +QString memberAccessorBody( CfgEntry *e, bool globalEnums, const CfgConfig &cfg )
 +{
 +    QString result;
 +    QTextStream out(&result, QIODevice::WriteOnly);
 +    QString n = e->name();
 +    QString t = e->type();
 +    bool useEnumType = cfg.useEnumTypes && t == "Enum";
 +
 +    out << "return ";
 +    if (useEnumType)
 +      out << "static_cast<" << enumType(e, globalEnums) << ">(";
 +    out << This << varPath(n, cfg);
 +    if (!e->param().isEmpty())
 +      out << "[i]";
 +    if (useEnumType)
 +      out << ")";
 +    out << ";" << endl;
 +
 +    return result;
 +}
 +
 +// returns the member mutator implementation
 +// which should go in the h file if inline
 +// or the cpp file if not inline
 +QString memberMutatorBody( CfgEntry *e, const CfgConfig &cfg )
 +{
 +  QString result;
 +  QTextStream out(&result, QIODevice::WriteOnly);
 +  QString n = e->name();
 +  QString t = e->type();
 +
 +  if (!e->minValue().isEmpty())
 +  {
 +    if (e->minValue() != "0" || !isUnsigned(t)) { // skip writing "if uint<0" \
(#187579)  +      out << "if (v < " << e->minValue() << ")" << endl;
 +      out << "{" << endl;
 +      out << "  qDebug() << \"" << setFunction(n);
 +      out << ": value \" << v << \" is less than the minimum value of ";
 +      out << e->minValue()<< "\";" << endl;
 +      out << "  v = " << e->minValue() << ";" << endl;
 +      out << "}" << endl;
 +    }
 +  }
 +
 +  if (!e->maxValue().isEmpty())
 +  {
 +    out << endl << "if (v > " << e->maxValue() << ")" << endl;
 +    out << "{" << endl;
 +    out << "  qDebug() << \"" << setFunction(n);
 +    out << ": value \" << v << \" is greater than the maximum value of ";
 +    out << e->maxValue()<< "\";" << endl;
 +    out << "  v = " << e->maxValue() << ";" << endl;
 +    out << "}" << endl << endl;
 +  }
 +
 +  out << "if (!" << This << "isImmutable( QString::fromLatin1( \"";
 +  if (!e->param().isEmpty())
 +  {
 +    out << e->paramName().replace("$("+e->param()+")", "%1") << "\" ).arg( ";
 +    if ( e->paramType() == "Enum" ) {
 +      out << "QLatin1String( ";
 +
 +      if (cfg.globalEnums)
 +        out << enumName(e->param()) << "ToString[i]";
 +      else
 +        out << enumName(e->param()) << "::enumToString[i]";
 +
 +        out << " )";
 +    }
 +    else
 +    {
 +      out << "i";
 +    }
 +    out << " )";
 +  }
 +  else
 +  {
 +    out << n << "\" )";
 +  }
 +  out << " ))" << (!e->signalList().empty() ? " {" : "") << endl;
 +  out << "  " << This << varPath(n, cfg);
 +  if (!e->param().isEmpty())
 +    out << "[i]";
 +  out << " = v;" << endl;
 +
 +  if ( !e->signalList().empty() ) {
 +    foreach(const Signal &signal, e->signalList()) {
 +      out << "  " << This << varPath("settingsChanged", cfg) << " |= " << \
signalEnumName(signal.name) << ";" << endl;  +    }
 +    out << "}" << endl;
 +  }
 +
 +  return result;
 +}
 +
 +// returns the member get default implementation
 +// which should go in the h file if inline
 +// or the cpp file if not inline
 +QString memberGetDefaultBody( CfgEntry *e )
 +{
 +  QString result = e->code();
 +  QTextStream out(&result, QIODevice::WriteOnly);
 +  out << endl;
 +
 +  if (!e->param().isEmpty()) {
 +    out << "  switch (i) {" << endl;
 +    for (int i = 0; i <= e->paramMax(); ++i) {
 +      if (!e->paramDefaultValue(i).isEmpty()) {
 +        out << "  case " << i << ": return " << e->paramDefaultValue(i) << ';' << \
endl;  +      }
 +    }
 +    out << "  default:" << endl;
 +    out << "    return " << e->defaultValue().replace("$("+e->param()+')', "i") << \
';' << endl;  +    out << "  }" << endl;
 +  } else {
 +    out << "  return " << e->defaultValue() << ';';
 +  }
 +
 +  return result;
 +}
 +
 +// returns the item accesor implementation
 +// which should go in the h file if inline
 +// or the cpp file if not inline
 +QString itemAccessorBody( CfgEntry *e, const CfgConfig &cfg )
 +{
 +    QString result;
 +    QTextStream out(&result, QIODevice::WriteOnly);
 +
 +    out << "return " << itemPath(e, cfg);
 +    if (!e->param().isEmpty()) out << "[i]";
 +    out << ";" << endl;
 +
 +    return result;
 +}
 +
 +//indents text adding X spaces per line
 +QString indent(QString text, int spaces)
 +{
 +    QString result;
 +    QTextStream out(&result, QIODevice::WriteOnly);
 +    QTextStream in(&text, QIODevice::ReadOnly);
 +    QString currLine;
 +    while ( !in.atEnd() )
 +    {
 +      currLine = in.readLine();
 +      if (!currLine.isEmpty())
 +        for (int i=0; i < spaces; i++)
 +          out << " ";
 +      out << currLine << endl;
 +    }
 +    return result;
 +}
 +
 +// adds as many 'namespace foo {' lines to p_out as
 +// there are namespaces in p_ns
 +void beginNamespaces(const QString &p_ns, QTextStream &p_out)
 +{
 +  if ( !p_ns.isEmpty() ) {
 +    const QStringList nameSpaces = p_ns.split( "::" );
 +    foreach (const QString &ns, nameSpaces )
 +      p_out << "namespace " << ns << " {" << endl;
 +    p_out << endl;
 +  }
 +}
 +
 +// adds as many '}' lines to p_out as
 +// there are namespaces in p_ns
 +void endNamespaces(const QString &p_ns, QTextStream &p_out)
 +{
 +  if ( !p_ns.isEmpty() ) {
 +    const int namespaceCount = p_ns.count( "::" ) + 1;
 +    for ( int i = 0; i < namespaceCount; ++i )
 +      p_out << "}" << endl;
 +    p_out << endl;
 +  }
 +}
 +
 +
 +int main( int argc, char **argv )
 +{
 +  QCoreApplication app(argc, argv);
 +
 +  validNameRegexp = new QRegExp("[a-zA-Z_][a-zA-Z0-9_]*");
 +
 +  QString directoryName, inputFilename, codegenFilename;
 +  parseArgs(app.arguments(), directoryName, inputFilename, codegenFilename);
 +
 +  QString baseDir = directoryName;
 +#ifdef Q_OS_WIN
 +  if (!baseDir.endsWith('/') && !baseDir.endsWith('\\'))
 +#else
 +  if (!baseDir.endsWith('/'))
 +#endif
 +    baseDir.append("/");
 +
 +  if (!codegenFilename.endsWith(QLatin1String(".kcfgc")))
 +  {
 +    cerr << "Codegen options file must have extension .kcfgc" << endl;
 +    return 1;
 +  }
 +  QString baseName = QFileInfo(codegenFilename).fileName();
 +  baseName = baseName.left(baseName.length() - 6);
 +
 +  CfgConfig cfg = CfgConfig( codegenFilename );
 +
 +  QFile input( inputFilename );
 +
 +  QDomDocument doc;
 +  QString errorMsg;
 +  int errorRow;
 +  int errorCol;
 +  if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) {
 +    cerr << "Unable to load document." << endl;
 +    cerr << "Parse error in " << inputFilename << ", line " << errorRow << ", col " \
<< errorCol << ": " << errorMsg << endl;  +    return 1;
 +  }
 +
 +  QDomElement cfgElement = doc.documentElement();
 +
 +  if ( cfgElement.isNull() ) {
 +    cerr << "No document in kcfg file" << endl;
 +    return 1;
 +  }
 +
 +  QString cfgFileName;
 +  bool cfgFileNameArg = false;
 +  QList<Param> parameters;
 +  QList<Signal> signalList;
 +  QStringList includes;
 +  bool hasSignals = false;
 +
 +  QList<CfgEntry*> entries;
 +
 +  for ( QDomElement e = cfgElement.firstChildElement(); !e.isNull(); e = \
e.nextSiblingElement() ) {  +    QString tag = e.tagName();
 +
 +    if ( tag == "include" ) {
 +      QString includeFile = e.text();
 +      if (!includeFile.isEmpty())
 +        includes.append(includeFile);
 +
 +    } else if ( tag == "kcfgfile" ) {
 +      cfgFileName = e.attribute( "name" );
 +      cfgFileNameArg = e.attribute( "arg" ).toLower() == "true";
 +      for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = \
e2.nextSiblingElement() ) {  +        if ( e2.tagName() == "parameter" ) {
 +          Param p;
 +          p.name = e2.attribute( "name" );
 +          p.type = e2.attribute( "type" );
 +          if (p.type.isEmpty())
 +             p.type = "String";
 +          parameters.append( p );
 +        }
 +      }
 +
 +    } else if ( tag == "group" ) {
 +      QString group = e.attribute( "name" );
 +      if ( group.isEmpty() ) {
 +        cerr << "Group without name" << endl;
 +        return 1;
 +      }
 +      for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = \
e2.nextSiblingElement() ) {  +        if ( e2.tagName() != "entry" ) continue;
 +        CfgEntry *entry = parseEntry( group, e2, cfg );
 +        if ( entry ) entries.append( entry );
 +        else {
 +          cerr << "Can not parse entry." << endl;
 +          return 1;
 +        }
 +      }
 +    }
 +    else if ( tag == "signal" ) {
 +      QString signalName = e.attribute( "name" );
 +      if ( signalName.isEmpty() ) {
 +        cerr << "Signal without name." << endl;
 +        return 1;
 +      }
 +      Signal theSignal;
 +      theSignal.name = signalName;
 +
 +      for( QDomElement e2 = e.firstChildElement(); !e2.isNull(); e2 = \
e2.nextSiblingElement() ) {  +        if ( e2.tagName() == "argument") {
 +          SignalArguments argument;
 +          argument.type = e2.attribute("type");
 +          if ( argument.type.isEmpty() ) {
 +            cerr << "Signal argument without type." << endl;
 +            return 1;
 +          }
 +          argument.variableName = e2.text();
 +          theSignal.arguments.append(argument);
 +        }
 +        else if( e2.tagName() == "label") {
 +          theSignal.label = e2.text();
 +        }
 +      }
 +      signalList.append(theSignal);
 +    }
 +  }
 +
 +  if ( cfg.className.isEmpty() ) {
 +    cerr << "Class name missing" << endl;
 +    return 1;
 +  }
 +
 +  if ( cfg.singleton && !parameters.isEmpty() ) {
 +    cerr << "Singleton class can not have parameters" << endl;
 +    return 1;
 +  }
 +
 +  if ( !cfgFileName.isEmpty() && cfgFileNameArg)
 +  {
 +    cerr << "Having both a fixed filename and a filename as argument is not \
possible." << endl;  +    return 1;
 +  }
 +
 +  if ( entries.isEmpty() ) {
 +    cerr << "No entries." << endl;
 +  }
 +
 +#if 0
 +  CfgEntry *cfg;
 +  for( cfg = entries.first(); cfg; cfg = entries.next() ) {
 +    cfg->dump();
 +  }
 +#endif
 +
 +  hasSignals = !signalList.empty();
 +  QString headerFileName = baseName + ".h";
 +  QString implementationFileName = baseName + ".cpp";
 +  QString mocFileName = baseName + ".moc";
 +  QString cppPreamble; // code to be inserted at the beginnin of the cpp file, e.g. \
initialization of static values  +
 +  QFile header( baseDir + headerFileName );
 +  if ( !header.open( QIODevice::WriteOnly ) ) {
 +    cerr << "Can not open '" << baseDir  << headerFileName << "for writing." << \
endl;  +    return 1;
 +  }
 +
 +  QTextStream h( &header );
 +
 +  h << "// This file is generated by kconfig_compiler from " << \
QFileInfo(inputFilename).fileName() << "." << endl;  +  h << "// All changes you do \
to this file will be lost." << endl;  +
 +  h << "#ifndef " << ( !cfg.nameSpace.isEmpty() ? QString \
(QString(cfg.nameSpace).replace( "::", "_" ).toUpper() + '_') : "" )  +    << \
cfg.className.toUpper() << "_H" << endl;  +  h << "#define " << ( \
!cfg.nameSpace.isEmpty() ? QString (QString(cfg.nameSpace).replace( "::", "_" \
).toUpper() + '_') : "" )  +    << cfg.className.toUpper() << "_H" << endl << endl;
 +
 +  // Includes
 +  QStringList::ConstIterator it;
 +  for( it = cfg.headerIncludes.constBegin(); it != cfg.headerIncludes.constEnd(); \
++it ) {  +    if ( (*it).startsWith('"') )
 +      h << "#include " << *it << endl;
 +    else
 +      h << "#include <" << *it << ">" << endl;
 +  }
 +
 +  if ( cfg.headerIncludes.count() > 0 ) h << endl;
 +
 +  if ( !cfg.singleton && parameters.isEmpty() )
 +    h << "#include <qglobal.h>" << endl;
 +
 +  if ( cfg.inherits=="KCoreConfigSkeleton" ) {
 +    h << "#include <kcoreconfigskeleton.h>" << endl;
 +  } else {
 +    h << "#include <kconfigskeleton.h>" << endl;
 +  }
 +
 +  h << "#include <QDebug>" << endl << endl;
 +
 +  // Includes
 +  for( it = includes.constBegin(); it != includes.constEnd(); ++it ) {
 +    if ( (*it).startsWith('"') )
 +      h << "#include " << *it << endl;
 +    else
 +      h << "#include <" << *it << ">" << endl;
 +  }
 +
 +  beginNamespaces(cfg.nameSpace, h);
 +
 +  // Private class declaration
 +  if ( cfg.dpointer )
 +    h << "class " << cfg.className << "Private;" << endl << endl;
 +
 +  // Class declaration header
 +  h << "class " << cfg.visibility << cfg.className << " : public " << cfg.inherits \
<< endl;  +
 +  h << "{" << endl;
 +  // Add Q_OBJECT macro if the config need signals.
 +  if( hasSignals )
 +   h << "  Q_OBJECT" << endl;
 +  h << "  public:" << endl;
 +
 +  // enums
 +  QList<CfgEntry*>::ConstIterator itEntry;
 +  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
 +    const CfgEntry::Choices &choices = (*itEntry)->choices();
 +    const QList<CfgEntry::Choice> chlist = choices.choices;
 +    if ( !chlist.isEmpty() ) {
 +      QStringList values;
 +      QList<CfgEntry::Choice>::ConstIterator itChoice;
 +      for( itChoice = chlist.constBegin(); itChoice != chlist.constEnd(); \
++itChoice ) {  +        values.append( choices.prefix + (*itChoice).name );
 +      }
 +      if ( choices.name().isEmpty() ) {
 +        if ( cfg.globalEnums ) {
 +          h << "    enum " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) \
<< " { " << values.join( ", " ) << " };" << endl;  +        } else {
 +          // Create an automatically named enum
 +          h << "    class " << enumName( (*itEntry)->name(), (*itEntry)->choices() \
) << endl;  +          h << "    {" << endl;
 +          h << "      public:" << endl;
 +          h << "      enum type { " << values.join( ", " ) << ", COUNT };" << endl;
 +          h << "    };" << endl;
 +        }
 +      } else if ( !choices.external() ) {
 +        // Create a named enum
 +        h << "    enum " << enumName( (*itEntry)->name(), (*itEntry)->choices() ) \
<< " { " << values.join( ", " ) << " };" << endl;  +      }
 +    }
 +    const QStringList values = (*itEntry)->paramValues();
 +    if ( !values.isEmpty() ) {
 +      if ( cfg.globalEnums ) {
 +        // ### FIXME!!
 +        // make the following string table an index-based string search!
 +        // ###
 +        h << "    enum " << enumName( (*itEntry)->param() ) << " { " << \
values.join( ", " ) << " };" << endl;  +        h << "    static const char* const " \
<< enumName( (*itEntry)->param() ) << "ToString[];" << endl;  +        cppPreamble += \
"const char* const " + cfg.className + "::" + enumName( (*itEntry)->param() ) +  +    \
"ToString[] = { \"" + values.join( "\", \"" ) + "\" };\n";  +      } else {
 +        h << "    class " << enumName( (*itEntry)->param() ) << endl;
 +        h << "    {" << endl;
 +        h << "      public:" << endl;
 +        h << "      enum type { " << values.join( ", " ) << ", COUNT };" << endl;
 +        h << "      static const char* const enumToString[];" << endl;
 +        h << "    };" << endl;
 +        cppPreamble += "const char* const " + cfg.className + "::" + enumName( \
(*itEntry)->param() ) +  +           "::enumToString[] = { \"" + values.join( "\", \
\"" ) + "\" };\n";  +      }
 +    }
 +  }
 +  if ( hasSignals ) {
 +   h << "\n    enum {" << endl;
 +   unsigned val = 1;
 +   QList<Signal>::ConstIterator it, itEnd = signalList.constEnd();
 +   for ( it = signalList.constBegin(); it != itEnd; val <<= 1) {
 +     if ( !val ) {
 +       cerr << "Too many signals to create unique bit masks" << endl;
 +       exit(1);
 +     }
 +     Signal signal = *it;
 +     h << "      " << signalEnumName(signal.name) << " = 0x" << hex << val;
 +     if ( ++it != itEnd )
 +      h << ",";
 +     h << endl;
 +   }
 +   h << " };" << dec << endl;
 +  }
 +  h << endl;
 +  // Constructor or singleton accessor
 +  if ( !cfg.singleton ) {
 +    h << "    " << cfg.className << "(";
 +    if (cfgFileNameArg)
 +    {
 +        if(cfg.forceStringFilename)
 +            h << " const QString &cfgfilename"
 +                << (parameters.isEmpty() ? " = QString()" : ", ");
 +        else
 +            h << " KSharedConfig::Ptr config"
 +                << (parameters.isEmpty() ? " = KSharedConfig::openConfig()" : ", \
");  +    }
 +    for (QList<Param>::ConstIterator it = parameters.constBegin();
 +         it != parameters.constEnd(); ++it)
 +    {
 +       if (it != parameters.constBegin())
 +         h << ",";
 +       h << " " << param((*it).type) << " " << (*it).name;
 +    }
 +    h << " );" << endl;
 +  } else {
 +    h << "    static " << cfg.className << " *self();" << endl;
 +    if (cfgFileNameArg)
 +    {
 +      h << "    static void instance(const QString& cfgfilename);" << endl;
 +    }
 +  }
 +
 +  // Destructor
 +  h << "    ~" << cfg.className << "();" << endl << endl;
 +
 +  // global variables
 +  if (cfg.staticAccessors)
 +    This = "self()->";
 +  else
 +    Const = " const";
 +
 +  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
 +    QString n = (*itEntry)->name();
 +    QString t = (*itEntry)->type();
 +
 +    // Manipulator
 +    if (cfg.allMutators || cfg.mutators.contains(n))
 +    {
 +      h << "    /**" << endl;
 +      h << "      Set " << (*itEntry)->label() << endl;
 +      h << "    */" << endl;
 +      if (cfg.staticAccessors)
 +        h << "    static" << endl;
 +      h << "    void " << setFunction(n) << "( ";
 +      if (!(*itEntry)->param().isEmpty())
 +        h << cppType((*itEntry)->paramType()) << " i, ";
 +      if (cfg.useEnumTypes && t == "Enum")
 +        h << enumType(*itEntry, cfg.globalEnums);
 +      else
 +        h << param( t );
 +      h << " v )";
 +      // function body inline only if not using dpointer
 +      // for BC mode
 +      if ( !cfg.dpointer )
 +      {
 +        h << endl << "    {" << endl;
 +        h << indent(memberMutatorBody(*itEntry, cfg), 6 );
 +        h << "    }" << endl;
 +      }
 +      else
 +      {
 +        h << ";" << endl;
 +      }
 +    }
 +    h << endl;
 +    // Accessor
 +    h << "    /**" << endl;
 +    h << "      Get " << (*itEntry)->label() << endl;
 +    h << "    */" << endl;
 +    if (cfg.staticAccessors)
 +      h << "    static" << endl;
 +    h << "    ";
 +    if (cfg.useEnumTypes && t == "Enum")
 +      h << enumType(*itEntry, cfg.globalEnums);
 +    else
 +      h << cppType(t);
 +    h << " " << getFunction(n) << "(";
 +    if (!(*itEntry)->param().isEmpty())
 +      h << " " << cppType((*itEntry)->paramType()) <<" i ";
 +    h << ")" << Const;
 +    // function body inline only if not using dpointer
 +    // for BC mode
 +    if ( !cfg.dpointer )
 +    {
 +       h << endl << "    {" << endl;
 +      h << indent(memberAccessorBody(*itEntry, cfg.globalEnums, cfg), 6 );
 +       h << "    }" << endl;
 +    }
 +    else
 +    {
 +      h << ";" << endl;
 +    }
 +
 +    // Default value Accessor
 +    if ((cfg.allDefaultGetters || cfg.defaultGetters.contains(n)) && \
!(*itEntry)->defaultValue().isEmpty()) {  +      h << endl;
 +      h << "    /**" << endl;
 +      h << "      Get " << (*itEntry)->label() << " default value" << endl;
 +      h << "    */" << endl;
 +      if (cfg.staticAccessors)
 +        h << "    static" << endl;
 +      h << "    ";
 +      if (cfg.useEnumTypes && t == "Enum")
 +        h << enumType(*itEntry, cfg.globalEnums);
 +      else
 +        h << cppType(t);
 +      h << " " << getDefaultFunction(n) << "(";
 +      if ( !(*itEntry)->param().isEmpty() )
 +          h << " " << cppType( (*itEntry)->paramType() ) <<" i ";
 +      h << ")" << Const << endl;
 +      h << "    {" << endl;
 +      h << "        return ";
 +      if (cfg.useEnumTypes && t == "Enum")
 +        h << "static_cast<" << enumType(*itEntry, cfg.globalEnums) << ">(";
 +      h << getDefaultFunction(n) << "_helper(";
 +      if ( !(*itEntry)->param().isEmpty() )
 +          h << " i ";
 +      h << ")";
 +      if (cfg.useEnumTypes && t == "Enum")
 +        h << ")";
 +      h << ";" << endl;
 +      h << "    }" << endl;
 +    }
 +
 +    // Item accessor
 +    if ( cfg.itemAccessors ) {
 +      h << endl;
 +      h << "    /**" << endl;
 +      h << "      Get Item object corresponding to " << n << "()"
 +        << endl;
 +      h << "    */" << endl;
 +      h << "    Item" << itemType( (*itEntry)->type() ) << " *"
 +        << getFunction( n ) << "Item(";
 +      if (!(*itEntry)->param().isEmpty()) {
 +        h << " " << cppType((*itEntry)->paramType()) << " i ";
 +      }
 +      h << ")";
 +      if ( !cfg.dpointer )
 +      {
 +        h << endl << "    {" << endl;
 +        h << indent( itemAccessorBody((*itEntry), cfg), 6);
 +        h << "    }" << endl;
 +      }
 +      else
 +      {
 +        h << ";" << endl;
 +      }
 +    }
 +
 +    h << endl;
 +  }
 +
 +
 +  // Signal definition.
 +  if( hasSignals ) {
 +    h << endl;
 +    h << "  Q_SIGNALS:";
 +    foreach(const Signal &signal, signalList) {
 +      h << endl;
 +      if ( !signal.label.isEmpty() ) {
 +        h << "    /**" << endl;
 +        h << "      " << signal.label << endl;
 +        h << "    */" << endl;
 +      }
 +      h << "    void " << signal.name << "(";
 +      QList<SignalArguments>::ConstIterator it, itEnd = \
signal.arguments.constEnd();  +      for ( it = signal.arguments.constBegin(); it != \
itEnd; ) {  +        SignalArguments argument = *it;
 +        QString type = param(argument.type);
 +        if ( cfg.useEnumTypes && argument.type == "Enum" ) {
 +          for ( int i = 0, end = entries.count(); i < end; ++i ) {
 +            if ( entries[i]->name() == argument.variableName ) {
 +              type = enumType(entries[i], cfg.globalEnums);
 +              break;
 +            }
 +          }
 +        }
 +        h << type << " " << argument.variableName;
 +        if ( ++it != itEnd ) {
 +         h << ", ";
 +        }
 +      }
 +      h << ");" << endl;
 +    }
 +    h << endl;
 +  }
 +
 +  h << "  protected:" << endl;
 +
 +  // Private constructor for singleton
 +  if ( cfg.singleton ) {
 +    h << "    " << cfg.className << "(";
 +    if ( cfgFileNameArg )
 +      h << "const QString& arg";
 +    h << ");" << endl;
 +    h << "    friend class " << cfg.className << "Helper;" << endl << endl;
 +  }
 +
 +  if ( hasSignals ) {
 +    h << "    virtual void usrWriteConfig();" << endl;
 +  }
 +
 +  // Member variables
 +  if ( !cfg.memberVariables.isEmpty() && cfg.memberVariables != "private" && \
cfg.memberVariables != "dpointer") {  +    h << "  " << cfg.memberVariables << ":" << \
endl;  +  }
 +
 +  // Class Parameters
 +  for (QList<Param>::ConstIterator it = parameters.constBegin();
 +       it != parameters.constEnd(); ++it)
 +  {
 +     h << "    " << cppType((*it).type) << " mParam" << (*it).name << ";" << endl;
 +  }
 +
 +  if ( cfg.memberVariables != "dpointer" )
 +  {
 +    QString group;
 +    for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) \
{  +      if ( (*itEntry)->group() != group ) {
 +        group = (*itEntry)->group();
 +        h << endl;
 +        h << "    // " << group << endl;
 +      }
 +      h << "    " << cppType( (*itEntry)->type() ) << " " << varName( \
(*itEntry)->name(), cfg );  +      if ( !(*itEntry)->param().isEmpty() )
 +      {
 +        h << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
 +      }
 +      h << ";" << endl;
 +
 +      if ( cfg.allDefaultGetters || cfg.defaultGetters.contains((*itEntry)->name()) \
)  +      {
 +        h << "    ";
 +        if (cfg.staticAccessors)
 +          h << "static ";
 +        h << cppType((*itEntry)->type()) << " " << \
getDefaultFunction((*itEntry)->name()) << "_helper(";  +        if ( \
!(*itEntry)->param().isEmpty() )  +            h << " " << cppType( \
(*itEntry)->paramType() ) <<" i ";  +        h << ")" << Const << ";" << endl;
 +      }
 +    }
 +
 +    h << endl << "  private:" << endl;
 +    if ( cfg.itemAccessors ) {
 +       for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); \
++itEntry ) {  +        h << "    Item" << itemType( (*itEntry)->type() ) << " *" << \
itemVar( *itEntry, cfg );  +        if ( !(*itEntry)->param().isEmpty() ) h << \
QString("[%1]").arg( (*itEntry)->paramMax()+1 );  +        h << ";" << endl;
 +      }
 +    }
 +    if ( hasSignals )
 +     h << "    uint " << varName("settingsChanged", cfg) << ";" << endl;
 +
 +  }
 +  else
 +  {
 +    // use a private class for both member variables and items
 +    h << "  private:" << endl;
 +    for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) \
{  +      if ( cfg.allDefaultGetters || \
cfg.defaultGetters.contains((*itEntry)->name()) ) {  +        h << "    ";
 +        if (cfg.staticAccessors)
 +          h << "static ";
 +        h << cppType((*itEntry)->type()) << " " << \
getDefaultFunction((*itEntry)->name()) << "_helper(";  +        if ( \
!(*itEntry)->param().isEmpty() )  +            h << " " << cppType( \
(*itEntry)->paramType() ) <<" i ";  +        h << ")" << Const << ";" << endl;
 +      }
 +    }
 +    h << "    " + cfg.className + "Private *d;" << endl;
 +  }
 +
 +  if (cfg.customAddons)
 +  {
 +     h << "    // Include custom additions" << endl;
 +     h << "    #include \"" << filenameOnly(baseName) << "_addons.h\"" <<endl;
 +  }
 +
 +  h << "};" << endl << endl;
 +
 +  endNamespaces(cfg.nameSpace, h);
 +
 +  h << "#endif" << endl << endl;
 +
 +
 +  header.close();
 +
 +  QFile implementation( baseDir + implementationFileName );
 +  if ( !implementation.open( QIODevice::WriteOnly ) ) {
 +    cerr << "Can not open '" << implementationFileName << "for writing."
 +              << endl;
 +    return 1;
 +  }
 +
 +  QTextStream cpp( &implementation );
 +
 +
 +  cpp << "// This file is generated by kconfig_compiler from " << \
QFileInfo(inputFilename).fileName() << "." << endl;  +  cpp << "// All changes you do \
to this file will be lost." << endl << endl;  +
 +  cpp << "#include \"" << headerFileName << "\"" << endl << endl;
 +
 +  for( it = cfg.sourceIncludes.constBegin(); it != cfg.sourceIncludes.constEnd(); \
++it ) {  +    if ( (*it).startsWith('"') )
 +      cpp << "#include " << *it << endl;
 +    else
 +      cpp << "#include <" << *it << ">" << endl;
 +  }
 +
 +  if ( cfg.sourceIncludes.count() > 0 ) cpp << endl;
 +
 +  if ( cfg.setUserTexts && cfg.translationSystem==CfgConfig::KdeTranslation)
 +    cpp << "#include <klocalizedstring.h>" << endl << endl;
 +
 +  // Header required by singleton implementation
 +  if ( cfg.singleton )
 +    cpp << "#include <qglobal.h>" << endl << "#include <QtCore/QFile>" << endl << \
endl;  +  if ( cfg.singleton && cfgFileNameArg )
 +    cpp << "#include <QDebug>" << endl << endl;
 +
 +  if ( !cfg.nameSpace.isEmpty() )
 +    cpp << "using namespace " << cfg.nameSpace << ";" << endl << endl;
 +
 +  QString group;
 +
 +  // private class implementation
 +  if ( cfg.dpointer )
 +  {
 +    beginNamespaces(cfg.nameSpace, cpp);
 +    cpp << "class " << cfg.className << "Private" << endl;
 +    cpp << "{" << endl;
 +    cpp << "  public:" << endl;
 +    for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) \
{  +      if ( (*itEntry)->group() != group ) {
 +        group = (*itEntry)->group();
 +        cpp << endl;
 +        cpp << "    // " << group << endl;
 +      }
 +      cpp << "    " << cppType( (*itEntry)->type() ) << " " << varName( \
(*itEntry)->name(), cfg );  +      if ( !(*itEntry)->param().isEmpty() )
 +      {
 +        cpp << QString("[%1]").arg( (*itEntry)->paramMax()+1 );
 +      }
 +      cpp << ";" << endl;
 +    }
 +    cpp << endl << "    // items" << endl;
 +    for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) \
{  +      cpp << "    "+cfg.inherits+"::Item" << itemType( (*itEntry)->type() ) << " \
*" << itemVar( *itEntry, cfg );  +      if ( !(*itEntry)->param().isEmpty() ) cpp << \
QString("[%1]").arg( (*itEntry)->paramMax()+1 );  +        cpp << ";" << endl;
 +    }
 +    if ( hasSignals ) {
 +      cpp << "    uint " << varName("settingsChanged", cfg) << ";" << endl;
 +    }
 +
 +    cpp << "};" << endl << endl;
 +    endNamespaces(cfg.nameSpace, cpp);
 +  }
 +
 +  // Singleton implementation
 +  if ( cfg.singleton ) {
 +    beginNamespaces(cfg.nameSpace, cpp);
 +    cpp << "class " << cfg.className << "Helper" << endl;
 +    cpp << '{' << endl;
 +    cpp << "  public:" << endl;
 +    cpp << "    " << cfg.className << "Helper() : q(0) {}" << endl;
 +    cpp << "    ~" << cfg.className << "Helper() { delete q; }" << endl;
 +    cpp << "    " << cfg.className << " *q;" << endl;
 +    cpp << "};" << endl;
 +    endNamespaces(cfg.nameSpace, cpp);
 +    cpp << "Q_GLOBAL_STATIC(" << cfg.className << "Helper, s_global" << \
cfg.className << ")" << endl;  +
 +    cpp << cfg.className << " *" << cfg.className << "::self()" << endl;
 +    cpp << "{" << endl;
 +    if ( cfgFileNameArg ) {
 +      cpp << "  if (!s_global" << cfg.className << "()->q)" << endl;
 +      cpp << "     qFatal(\"you need to call " << cfg.className << "::instance \
before using\");" << endl;  +    } else {
 +      cpp << "  if (!s_global" << cfg.className << "()->q) {" << endl;
 +      cpp << "    new " << cfg.className << ';' << endl;
 +      cpp << "    s_global" << cfg.className << "()->q->readConfig();" << endl;
 +      cpp << "  }" << endl << endl;
 +    }
 +    cpp << "  return s_global" << cfg.className << "()->q;" << endl;
 +    cpp << "}" << endl << endl;
 +
 +    if ( cfgFileNameArg ) {
 +      cpp << "void " << cfg.className << "::instance(const QString& cfgfilename)" \
<< endl;  +      cpp << "{" << endl;
 +      cpp << "  if (s_global" << cfg.className << "()->q) {" << endl;
 +      cpp << "     qDebug() << \"" << cfg.className << "::instance called after the \
first use - ignoring\";" << endl;  +      cpp << "     return;" << endl;
 +      cpp << "  }" << endl;
 +      cpp << "  new " << cfg.className << "(cfgfilename);" << endl;
 +      cpp << "  s_global" << cfg.className << "()->q->readConfig();" << endl;
 +      cpp << "}" << endl << endl;
 +    }
 +  }
 +
 +  if ( !cppPreamble.isEmpty() )
 +    cpp << cppPreamble << endl;
 +
 +  // Constructor
 +  cpp << cfg.className << "::" << cfg.className << "( ";
 +  if ( cfgFileNameArg ) {
 +    if ( !cfg.singleton && ! cfg.forceStringFilename)
 +      cpp << " KSharedConfig::Ptr config";
 +    else
 +      cpp << " const QString& config";
 +    cpp << (parameters.isEmpty() ? " " : ", ");
 +  }
 +
 +  for (QList<Param>::ConstIterator it = parameters.constBegin();
 +       it != parameters.constEnd(); ++it)
 +  {
 +     if (it != parameters.constBegin())
 +       cpp << ",";
 +     cpp << " " << param((*it).type) << " " << (*it).name;
 +  }
 +  cpp << " )" << endl;
 +
 +  cpp << "  : " << cfg.inherits << "(";
 +  if ( !cfgFileName.isEmpty() ) cpp << " QLatin1String( \"" << cfgFileName << "\" \
";  +  if ( cfgFileNameArg ) cpp << " config ";
 +  if ( !cfgFileName.isEmpty() ) cpp << ") ";
 +  cpp << ")" << endl;
 +
 +  // Store parameters
 +  for (QList<Param>::ConstIterator it = parameters.constBegin();
 +       it != parameters.constEnd(); ++it)
 +  {
 +     cpp << "  , mParam" << (*it).name << "(" << (*it).name << ")" << endl;
 +  }
 +
 +  if ( hasSignals && !cfg.dpointer )
 +    cpp << "  , " << varName("settingsChanged", cfg) << "(0)" << endl;
 +
 +  cpp << "{" << endl;
 +
 +  if (cfg.dpointer)
 +  {
 +    cpp << "  d = new " + cfg.className + "Private;" << endl;
 +    if (hasSignals)
 +      cpp << "  " << varPath("settingsChanged", cfg) << " = 0;" << endl;
 +  }
 +  // Needed in case the singleton class is used as baseclass for
 +  // another singleton.
 +  if (cfg.singleton) {
 +    cpp << "  Q_ASSERT(!s_global" << cfg.className << "()->q);" << endl;
 +    cpp << "  s_global" << cfg.className << "()->q = this;" << endl;
 +  }
 +
 +  group.clear();
 +
 +  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
 +    if ( (*itEntry)->group() != group ) {
 +      if ( !group.isEmpty() ) cpp << endl;
 +      group = (*itEntry)->group();
 +      cpp << "  setCurrentGroup( " << paramString(group, parameters) << " );" << \
endl << endl;  +    }
 +
 +    QString key = paramString( (*itEntry)->key(), parameters );
 +    if ( !(*itEntry)->code().isEmpty() ) {
 +      cpp << (*itEntry)->code() << endl;
 +    }
 +    if ( (*itEntry)->type() == "Enum" ) {
 +      cpp << "  QList<"+cfg.inherits+"::ItemEnum::Choice> values"
 +          << (*itEntry)->name() << ";" << endl;
 +      const QList<CfgEntry::Choice> choices = (*itEntry)->choices().choices;
 +      QList<CfgEntry::Choice>::ConstIterator it;
 +      for( it = choices.constBegin(); it != choices.constEnd(); ++it ) {
 +        cpp << "  {" << endl;
 +        cpp << "    "+cfg.inherits+"::ItemEnum::Choice choice;" << endl;
 +        cpp << "    choice.name = QLatin1String(\"" << (*it).name << "\");" << \
endl;  +        if ( cfg.setUserTexts ) {
 +          if ( !(*it).label.isEmpty() ) {
 +            cpp << "    choice.label = "
 +                << translatedString(cfg, (*it).label, (*it).context)
 +                << ";" << endl;
 +          }
 +          if ( !(*it).toolTip.isEmpty() ) {
 +            cpp << "    choice.toolTip = "
 +                << translatedString(cfg, (*it).toolTip, (*it).context)
 +                << ";" << endl;
 +          }
 +          if ( !(*it).whatsThis.isEmpty() ) {
 +            cpp << "    choice.whatsThis = "
 +                << translatedString(cfg, (*it).whatsThis, (*it).context)
 +                << ";" << endl;
 +          }
 +        }
 +        cpp << "    values" << (*itEntry)->name() << ".append( choice );" << endl;
 +        cpp << "  }" << endl;
 +      }
 +    }
 +
 +    if (!cfg.dpointer)
 +      cpp << itemDeclaration( *itEntry, cfg );
 +
 +    if ( (*itEntry)->param().isEmpty() )
 +    {
 +      // Normal case
 +      cpp << "  " << itemPath( *itEntry, cfg ) << " = "
 +          << newItem( (*itEntry)->type(), (*itEntry)->name(), key, \
(*itEntry)->defaultValue(), cfg ) << endl;  +
 +      if ( !(*itEntry)->minValue().isEmpty() )
 +        cpp << "  " << itemPath( *itEntry, cfg ) << "->setMinValue(" << \
(*itEntry)->minValue() << ");" << endl;  +      if ( \
!(*itEntry)->maxValue().isEmpty() )  +        cpp << "  " << itemPath( *itEntry, cfg \
) << "->setMaxValue(" << (*itEntry)->maxValue() << ");" << endl;  +
 +      if ( cfg.setUserTexts )
 +        cpp << userTextsFunctions( (*itEntry), cfg );
 +
 +      cpp << "  addItem( " << itemPath( *itEntry, cfg );
 +      QString quotedName = (*itEntry)->name();
 +      addQuotes( quotedName );
 +      if ( quotedName != key ) cpp << ", QLatin1String( \"" << (*itEntry)->name() \
<< "\" )";  +      cpp << " );" << endl;
 +    }
 +    else
 +    {
 +      // Indexed
 +      for(int i = 0; i <= (*itEntry)->paramMax(); i++)
 +      {
 +        QString defaultStr;
 +        QString itemVarStr(itemPath( *itEntry, cfg )+QString("[%1]").arg(i));
 +
 +        if ( !(*itEntry)->paramDefaultValue(i).isEmpty() )
 +          defaultStr = (*itEntry)->paramDefaultValue(i);
 +        else if ( !(*itEntry)->defaultValue().isEmpty() )
 +          defaultStr = paramString( (*itEntry)->defaultValue(), (*itEntry), i );
 +        else
 +          defaultStr = defaultValue( (*itEntry)->type() );
 +
 +        cpp << "  " << itemVarStr << " = "
 +            << newItem( (*itEntry)->type(), (*itEntry)->name(), paramString(key, \
*itEntry, i), defaultStr,cfg,  QString("[%1]").arg(i) )  +            << endl;
 +
 +        if ( cfg.setUserTexts )
 +          cpp << userTextsFunctions( *itEntry, cfg, itemVarStr, \
(*itEntry)->paramName() );  +
 +        // Make mutators for enum parameters work by adding them with $(..) \
replaced by the  +        // param name. The check for isImmutable in the set* \
functions doesn't have the param  +        // name available, just the corresponding \
enum value (int), so we need to store the  +        // param names in a separate \
static list!.  +        cpp << "  addItem( " << itemVarStr << ", QLatin1String( \"";
 +        if ( (*itEntry)->paramType()=="Enum" )
 +          cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', \
"%1").arg((*itEntry)->paramValues()[i] );  +        else
 +          cpp << (*itEntry)->paramName().replace( "$("+(*itEntry)->param()+')', \
"%1").arg(i);  +        cpp << "\" ) );" << endl;
 +      }
 +    }
 +  }
 +
 +  cpp << "}" << endl << endl;
 +
 +  if (cfg.dpointer)
 +  {
 +    // setters and getters go in Cpp if in dpointer mode
 +    for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) \
{  +      QString n = (*itEntry)->name();
 +      QString t = (*itEntry)->type();
 +
 +      // Manipulator
 +      if (cfg.allMutators || cfg.mutators.contains(n))
 +      {
 +        cpp << "void " << setFunction(n, cfg.className) << "( ";
 +        if ( !(*itEntry)->param().isEmpty() )
 +          cpp << cppType( (*itEntry)->paramType() ) << " i, ";
 +        if (cfg.useEnumTypes && t == "Enum")
 +          cpp << enumType(*itEntry, cfg.globalEnums);
 +        else
 +          cpp << param( t );
 +        cpp << " v )" << endl;
 +        // function body inline only if not using dpointer
 +        // for BC mode
 +        cpp << "{" << endl;
 +        cpp << indent(memberMutatorBody( *itEntry, cfg ), 6);
 +        cpp << "}" << endl << endl;
 +      }
 +
 +      // Accessor
 +      if (cfg.useEnumTypes && t == "Enum")
 +        cpp << enumType(*itEntry, cfg.globalEnums);
 +      else
 +        cpp << cppType(t);
 +      cpp << " " << getFunction(n, cfg.className) << "(";
 +      if ( !(*itEntry)->param().isEmpty() )
 +        cpp << " " << cppType( (*itEntry)->paramType() ) <<" i ";
 +      cpp << ")" << Const << endl;
 +      // function body inline only if not using dpointer
 +      // for BC mode
 +      cpp << "{" << endl;
 +      cpp << indent(memberAccessorBody( *itEntry, cfg.globalEnums, cfg ), 2);
 +      cpp << "}" << endl << endl;
 +
 +      // Default value Accessor -- written by the loop below
 +
 +      // Item accessor
 +      if ( cfg.itemAccessors )
 +      {
 +        cpp << endl;
 +        cpp << cfg.inherits+"::Item" << itemType( (*itEntry)->type() ) << " *"
 +          << getFunction( n, cfg.className ) << "Item(";
 +        if ( !(*itEntry)->param().isEmpty() ) {
 +          cpp << " " << cppType( (*itEntry)->paramType() ) << " i ";
 +        }
 +        cpp << ")" << endl;
 +        cpp << "{" << endl;
 +        cpp << indent(itemAccessorBody( *itEntry, cfg ), 2);
 +        cpp << "}" << endl;
 +      }
 +
 +      cpp << endl;
 +    }
 +  }
 +
 +  // default value getters always go in Cpp
 +  for( itEntry = entries.constBegin(); itEntry != entries.constEnd(); ++itEntry ) {
 +    QString n = (*itEntry)->name();
 +    QString t = (*itEntry)->type();
 +
 +    // Default value Accessor, as "helper" function
 +    if (( cfg.allDefaultGetters || cfg.defaultGetters.contains(n) ) && \
!(*itEntry)->defaultValue().isEmpty() ) {  +      cpp << cppType(t) << " " << \
getDefaultFunction(n, cfg.className) << "_helper(";  +      if ( \
!(*itEntry)->param().isEmpty() )  +        cpp << " " << cppType( \
(*itEntry)->paramType() ) <<" i ";  +      cpp << ")" << Const << endl;
 +      cpp << "{" << endl;
 +      cpp << memberGetDefaultBody(*itEntry) << endl;
 +      cpp << "}" << endl << endl;
 +    }
 +  }
 +
 +  // Destructor
 +  cpp << cfg.className << "::~" << cfg.className << "()" << endl;
 +  cpp << "{" << endl;
 +  if ( cfg.singleton ) {
 +    if ( cfg.dpointer )
 +      cpp << "  delete d;" << endl;
 +    cpp << "  s_global" << cfg.className << "()->q = 0;" << endl;
 +  }
 +  cpp << "}" << endl << endl;
 +
 +  if ( hasSignals ) {
 +    cpp << "void " << cfg.className << "::" << "usrWriteConfig()" << endl;
 +    cpp << "{" << endl;
 +    cpp << "  " << cfg.inherits << "::usrWriteConfig();" << endl << endl;
 +    foreach(const Signal &signal, signalList) {
 +      cpp << "  if ( " << varPath("settingsChanged", cfg) << " & " << \
signalEnumName(signal.name) << " ) " << endl;  +      cpp << "    emit " << \
signal.name << "(";  +      QList<SignalArguments>::ConstIterator it, itEnd = \
signal.arguments.constEnd();  +      for ( it = signal.arguments.constBegin(); it != \
itEnd; ) {  +        SignalArguments argument = *it;
 +        bool cast = false;
 +        if ( cfg.useEnumTypes && argument.type == "Enum" ) {
 +          for ( int i = 0, end = entries.count(); i < end; ++i ) {
 +            if ( entries[i]->name() == argument.variableName ) {
 +              cpp << "static_cast<" << enumType(entries[i], cfg.globalEnums) << \
">(";  +              cast = true;
 +              break;
 +            }
 +          }
 +        }
 +        cpp << varPath(argument.variableName, cfg);
 +        if ( cast )
 +          cpp << ")";
 +        if ( ++it != itEnd )
 +          cpp << ", ";
 +      }
 +      cpp << ");" << endl << endl;
 +    }
 +    cpp << "  " << varPath("settingsChanged", cfg) << " = 0;" << endl;
 +    cpp << "}" << endl;
 +  }
 +
 +  // Add includemoc if they are signals defined.
 +  if( hasSignals ) {
 +    cpp << endl;
 +    cpp << "#include \"" << mocFileName << "\"" << endl;
 +    cpp << endl;
 +  }
 +
 +  // clear entries list
 +  qDeleteAll( entries );
 +
 +  implementation.close();
 +}


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic