diff --git a/applets/locationchooser/Engine.cpp b/applets/locationchooser/Engine.cpp index 7ceaf1c9..3c4715ac 100644 --- a/applets/locationchooser/Engine.cpp +++ b/applets/locationchooser/Engine.cpp @@ -1,233 +1,233 @@ /* * Copyright (C) 2012 Ivan Cukic * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, * or (at your option) any later version, as published by the Free * Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "Engine.h" #include #include #include #define LOCATION_MANAGER_DBUS_PATH "org.kde.LocationManager" #define LOCATION_MANAGER_DBUS_OBJECT "/LocationManager" class Engine::Private { public: org::kde::LocationManager * locationManager; Plasma::PopupApplet * parent; QSizeF regularSize; QStringList locations; qreal listItemHeight; QDBusServiceWatcher * watcher; }; Engine::Engine(Plasma::PopupApplet * parent) : QObject(parent), d(new Private()) { d->locationManager = NULL; d->parent = parent; } void Engine::init() { d->watcher = new QDBusServiceWatcher(QLatin1String(LOCATION_MANAGER_DBUS_PATH), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration, this); connect(d->watcher, SIGNAL(serviceRegistered(QString)), this, SLOT(onServiceRegistered())); connect(d->watcher, SIGNAL(serviceUnregistered(QString)), this, SLOT(onServiceUnregistered())); bool servicePresent = QDBusConnection::sessionBus().interface()->isServiceRegistered(LOCATION_MANAGER_DBUS_PATH); if (servicePresent) { onServiceRegistered(); } else { onServiceUnregistered(); } } void Engine::onServiceRegistered() { d->locationManager = new org::kde::LocationManager( LOCATION_MANAGER_DBUS_PATH, LOCATION_MANAGER_DBUS_OBJECT, QDBusConnection::sessionBus(), this); // This would be so much nicer as a .\ in C++11 // Heck, it would be nicer even with boost::bind class GetLocations: public QThread { public: GetLocations(Engine * parent_, Engine::Private * d_) : parent(parent_), d(d_) { } protected: void run() { foreach (const QString & id, d->locationManager->knownLocations().value()) { if (id.isEmpty()) continue; d->locations << d->locationManager->locationName(id); } QMetaObject::invokeMethod(parent, "knownLocationsChanged", Qt::QueuedConnection, Q_ARG(QStringList, d->locations)); deleteLater(); } private: Engine * const parent; Engine::Private * const d; }; - connect(d->locationManager, SIGNAL(currentLocationChanged(QString, QString)), - this, SLOT(onCurrentLocationChanged(QString, QString))); - - connect(d->locationManager, SIGNAL(locationAdded(QString, QString)), - this, SLOT(onLocationAdded(QString, QString))); - connect(d->locationManager, SIGNAL(locationRemoved(QString, QString)), - this, SLOT(onLocationRemoved(QString, QString))); - connect(d->locationManager, SIGNAL(locationNameChanged(QString, QString, QString)), - this, SLOT(onLocationNameChanged(QString, QString, QString))); + connect(d->locationManager, SIGNAL(currentLocationChanged(QString,QString)), + this, SLOT(onCurrentLocationChanged(QString,QString))); + + connect(d->locationManager, SIGNAL(locationAdded(QString,QString)), + this, SLOT(onLocationAdded(QString,QString))); + connect(d->locationManager, SIGNAL(locationRemoved(QString,QString)), + this, SLOT(onLocationRemoved(QString,QString))); + connect(d->locationManager, SIGNAL(locationNameChanged(QString,QString,QString)), + this, SLOT(onLocationNameChanged(QString,QString,QString))); // Starting the async getter (new GetLocations(this, d))->start(); emit locationManagerPresenceChanged(); setIcon("location"); } void Engine::onServiceUnregistered() { delete d->locationManager; d->locationManager = NULL; setState("Error"); emit locationManagerPresenceChanged(); d->parent->setPopupIcon("application-exit"); } void Engine::setIcon(const QString & icon) { if (d->locationManager) { d->parent->setPopupIcon("plasmaapplet-" + icon); } else { d->parent->setPopupIcon("application-exit"); } } QString Engine::currentLocationId() const { if (d->locationManager) return d->locationManager->currentLocationId(); else return i18n("The location manager is not running"); } QString Engine::currentLocationName() const { if (d->locationManager) return d->locationManager->currentLocationName(); else return i18n("The location manager is not running"); } void Engine::onCurrentLocationChanged(const QString & id, const QString & name) { emit currentLocationIdChanged(id); emit currentLocationNameChanged(name); } void Engine::setCurrentLocation(const QString & location) { if (d->locationManager) { d->locationManager->setCurrentLocation(location); } d->parent->hidePopup(); } void Engine::requestUiReset() { setIcon("location"); emit resetUiRequested(); } void Engine::setState(const QString & state) { if (state == "Showing" || state == "Error") { d->parent->graphicsWidget()->resize(d->regularSize); } else if (state == "Querying") { d->regularSize = d->parent->graphicsWidget()->size(); QSizeF bigSize(d->regularSize); qreal height = bigSize.height() + d->locations.size() * (4 + d->listItemHeight); if (height > 400) { height = 400; } bigSize.setHeight(height); d->parent->graphicsWidget()->resize(bigSize); } } void Engine::setListItemHeight(qreal height) { d->listItemHeight = height; } QStringList Engine::knownLocations() const { return d->locations; } void Engine::onLocationAdded(const QString & id, const QString & name) { Q_UNUSED(id) d->locations << name; emit knownLocationsChanged(d->locations); } void Engine::onLocationRemoved(const QString & id, const QString & name) { Q_UNUSED(id) d->locations.removeAll(name); emit knownLocationsChanged(d->locations); } void Engine::onLocationNameChanged(const QString & id, const QString & oldname, const QString & newname) { Q_UNUSED(id) d->locations.removeAll(oldname); d->locations << newname; emit knownLocationsChanged(d->locations); } bool Engine::locationManagerPresent() const { return (d->locationManager != NULL); } diff --git a/applets/locationchooser/LocationChooser.cpp b/applets/locationchooser/LocationChooser.cpp index ebe902e4..aa25c14f 100644 --- a/applets/locationchooser/LocationChooser.cpp +++ b/applets/locationchooser/LocationChooser.cpp @@ -1,93 +1,93 @@ /* * Copyright (C) 2009, 2010 Ivan Cukic * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, * or (at your option) any later version, as published by the Free * Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "LocationChooser.h" #include #include #include #include #include #include #include #include "Engine.h" class LocationChooser::Private { public: Plasma::DeclarativeWidget * root; KDesktopFile * desktop; Engine * engine; bool initialized : 1; }; LocationChooser::LocationChooser(QObject * parent, const QVariantList &args) : Plasma::PopupApplet(parent, args), d(new Private()) { kDebug() << "Location ###"; d->initialized = false; // init(); } LocationChooser::~LocationChooser() { delete d->desktop; delete d->root; delete d; } void LocationChooser::init() { if (d->initialized) return; setPopupIcon("plasmaapplet-location"); d->initialized = true; d->root = new Plasma::DeclarativeWidget(); d->desktop = new KDesktopFile(LOCATION_CHOOSER_PACKAGE_DIR + "metadata.desktop"); d->engine = new Engine(this); - // connect(d->engine, SIGNAL(currentLocationChanged(QString, QString)), - // this, SLOT(currentLocationChanged(QString, QString))); + // connect(d->engine, SIGNAL(currentLocationChanged(QString,QString)), + // this, SLOT(currentLocationChanged(QString,QString))); setGraphicsWidget(d->root); d->root->setInitializationDelayed(true); d->root->engine()->rootContext()->setContextProperty("locationManager", d->engine); d->root->setQmlPath(LOCATION_CHOOSER_PACKAGE_DIR + d->desktop->desktopGroup().readEntry("X-Plasma-MainScript")); d->engine->init(); } void LocationChooser::currentLocationChanged(const QString & id, const QString & name) { kDebug() << id << name; } void LocationChooser::popupEvent(bool show) { d->engine->requestUiReset(); Plasma::PopupApplet::popupEvent(show); } #include "LocationChooser.moc" diff --git a/applets/windowstrip/applet.cpp b/applets/windowstrip/applet.cpp index 0fa1c960..831a3c43 100644 --- a/applets/windowstrip/applet.cpp +++ b/applets/windowstrip/applet.cpp @@ -1,68 +1,68 @@ /*************************************************************************** * * * Copyright 2011 Sebastian Kügler * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "applet.h" #include "windowstrip.h" #include #include #include #include #include WindowStripApplet::WindowStripApplet(QObject *parent, const QVariantList &args) : Plasma::Containment(parent, args), m_widget(0) { kDebug() << "ctor......"; setDrawWallpaper(false); setContainmentType(Containment::CustomContainment); setHasConfigurationInterface(false); } WindowStripApplet::~WindowStripApplet() { kDebug() << "dtor......"; } void WindowStripApplet::init() { Plasma::Containment::init(); graphicsWidget(); } QGraphicsWidget* WindowStripApplet::graphicsWidget() { kDebug() << "gw......"; if (!m_widget) { setContentsMargins(0, 0, 0, 0); QGraphicsLinearLayout *l = new QGraphicsLinearLayout(this); l->setContentsMargins(0, 0, 0, 0); m_widget = new WindowStrip(this); l->addItem(m_widget); } return m_widget; } K_EXPORT_PLASMA_APPLET(windowstrip, WindowStripApplet) -#include "applet.moc" \ No newline at end of file +#include "applet.moc" diff --git a/applets/windowstrip/applet.h b/applets/windowstrip/applet.h index 36e791a5..574b6f95 100644 --- a/applets/windowstrip/applet.h +++ b/applets/windowstrip/applet.h @@ -1,45 +1,45 @@ /*************************************************************************** * * * Copyright 2011 Sebastian Kügler * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #ifndef WINDOWSTRIPAPPLET_H #define WINDOWSTRIPAPPLET_H #include #include #include #include class WindowStrip; class WindowStripApplet : public Plasma::Containment { Q_OBJECT public: // Basic Create/Destroy WindowStripApplet(QObject *parent, const QVariantList &args); ~WindowStripApplet(); void init(); QGraphicsWidget* graphicsWidget(); private: WindowStrip* m_widget; }; -#endif \ No newline at end of file +#endif diff --git a/applets/windowstrip/windowstrip.h b/applets/windowstrip/windowstrip.h index 68cedce4..b4e0f1ab 100644 --- a/applets/windowstrip/windowstrip.h +++ b/applets/windowstrip/windowstrip.h @@ -1,57 +1,57 @@ /*************************************************************************** * * * Copyright 2011 Sebastian Kügler * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #ifndef WINDOWSTRIP_H #define WINDOWSTRIP_H #include #include #include #include class QDeclarativeItem; class WindowStrip : public Plasma::DeclarativeWidget { Q_OBJECT public: WindowStrip(QGraphicsWidget* parent); ~WindowStrip(); void init(); private Q_SLOTS: void showThumbnails(); void hideThumbnails(); void scrollChanged(); void updateFrame(); void updateWindows(); private: QHash m_windows; QPoint m_windowsOffset; WId m_desktop; QTime m_time; // for profiling QTimer m_frameUpdater; // regularly updates the thumbnail rects during animations QTimer m_updateController; // stops the frameUpdater afte a timeout QDeclarativeItem *m_windowFlicker; }; -#endif \ No newline at end of file +#endif diff --git a/applications/imageviewer/src/dirmodel.cpp b/applications/imageviewer/src/dirmodel.cpp index 77c41b3b..7d237850 100644 --- a/applications/imageviewer/src/dirmodel.cpp +++ b/applications/imageviewer/src/dirmodel.cpp @@ -1,100 +1,100 @@ /* Copyright (C) 20111 Marco Martin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "dirmodel.h" #include #include DirModel::DirModel(QObject *parent) : KDirModel(parent) { KMimeType::List mimeList = KMimeType::allMimeTypes(); m_mimeTypes << "inode/directory"; foreach (KMimeType::Ptr mime, mimeList) { if (mime->name().startsWith("image/")) { m_mimeTypes << mime->name(); } } dirLister()->setMimeFilter(m_mimeTypes); QHashroleNames; roleNames[Qt::DisplayRole] = "display"; roleNames[Qt::DecorationRole] = "decoration"; roleNames[UrlRole] = "url"; roleNames[MimeTypeRole] = "mimeType"; setRoleNames(roleNames); - connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), + connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(countChanged())); - connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), + connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SIGNAL(countChanged())); connect(this, SIGNAL(modelReset()), this, SIGNAL(countChanged())); } DirModel::~DirModel() { } QString DirModel::url() const { return dirLister()->url().path(); } void DirModel::setUrl(const QString& url) { if (dirLister()->url().path() == url) { return; } dirLister()->openUrl(url); emit urlChanged(); } int DirModel::indexForUrl(const QString &url) const { QModelIndex index = KDirModel::indexForUrl(KUrl(url)); return index.row(); } QVariant DirModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } switch (role) { case UrlRole: { KFileItem item = itemForIndex(index); return item.url().prettyUrl(); } case MimeTypeRole: { KFileItem item = itemForIndex(index); return item.mimetype(); } default: return KDirModel::data(index, role); } } #include "dirmodel.moc" diff --git a/applications/settings/modules/time/timezonesmodel.cpp b/applications/settings/modules/time/timezonesmodel.cpp index 6b994d9c..6cfb16c6 100644 --- a/applications/settings/modules/time/timezonesmodel.cpp +++ b/applications/settings/modules/time/timezonesmodel.cpp @@ -1,46 +1,46 @@ /* * Copyright 2011 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "timezonesmodel.h" TimeZonesModel::TimeZonesModel(QObject *parent) : QStandardItemModel(parent) { QHash roleNames; roleNames[Qt::DisplayRole] = "display"; roleNames[Qt::UserRole+1] = "continent"; setRoleNames(roleNames); connect(this, SIGNAL(modelReset()), this, SIGNAL(countChanged())); - connect(this, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SIGNAL(countChanged())); - connect(this, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SIGNAL(countChanged())); + connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(countChanged())); + connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SIGNAL(countChanged())); } QVariantHash TimeZonesModel::get(int i) const { QModelIndex idx = index(i, 0); QVariantHash hash; hash["display"] = data(idx, Qt::DisplayRole); hash["continent"] = data(idx, Qt::UserRole+1); return hash; } #include "timezonesmodel.moc" diff --git a/applications/webbrowser/src/activebrowserwindow.cpp b/applications/webbrowser/src/activebrowserwindow.cpp index 08660b2d..a8536517 100644 --- a/applications/webbrowser/src/activebrowserwindow.cpp +++ b/applications/webbrowser/src/activebrowserwindow.cpp @@ -1,99 +1,99 @@ /*************************************************************************** * * * Copyright 2011 Sebastian Kügler * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "activebrowserwindow.h" #include #include #include #include #include #include #include "view.h" ActiveBrowserWindow::ActiveBrowserWindow(const QString &url, QWidget *parent) : QMainWindow(parent) { KConfigGroup cg(KSharedConfig::openConfig("plasmarc"), "Theme-plasma-mobile"); const QString themeName = cg.readEntry("name", "air-mobile"); Plasma::Theme::defaultTheme()->setUseGlobalSettings(false); Plasma::Theme::defaultTheme()->setThemeName(themeName); setAcceptDrops(true); addAction(KStandardAction::close(this, SLOT(close()), this)); addAction(KStandardAction::quit(this, SLOT(close()), this)); m_widget = new View(url, this); - connect(m_widget, SIGNAL(newWindow(const QString&)), SIGNAL(newWindow(const QString&))); + connect(m_widget, SIGNAL(newWindow(QString)), SIGNAL(newWindow(QString))); KConfigGroup config(KGlobal::config(), "Window"); const QByteArray geom = config.readEntry("Geometry", QByteArray()); if (geom.isEmpty()) { setGeometry(qApp->desktop()->screenGeometry()); } else { restoreGeometry(geom); } setCentralWidget(m_widget); connect(m_widget, SIGNAL(titleChanged(QString)), SLOT(setCaption(QString))); } ActiveBrowserWindow::~ActiveBrowserWindow() { } View* ActiveBrowserWindow::view() { return m_widget; } void ActiveBrowserWindow::closeEvent(QCloseEvent *) { KConfigGroup config(KGlobal::config(), "Window"); config.writeEntry("Geometry", saveGeometry()); } QString ActiveBrowserWindow::name() { return "Active Browser"; } QIcon ActiveBrowserWindow::icon() { return KIcon("internet-web-browser"); } void ActiveBrowserWindow::setUseGL(const bool on) { m_widget->setUseGL(on); } bool ActiveBrowserWindow::useGL() const { return m_widget->useGL(); } void ActiveBrowserWindow::setCaption(const QString &caption) { setWindowTitle(caption); } #include "activebrowserwindow.moc" diff --git a/applications/webbrowser/src/activewebbrowser.cpp b/applications/webbrowser/src/activewebbrowser.cpp index e4293213..9e017279 100644 --- a/applications/webbrowser/src/activewebbrowser.cpp +++ b/applications/webbrowser/src/activewebbrowser.cpp @@ -1,69 +1,69 @@ /*************************************************************************** * * * Copyright 2011 Sebastian Kügler * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "activewebbrowser.h" #include #include #include #include #include #include "activebrowserwindow.h" #include "kdeclarativewebview.h" #include "view.h" ActiveWebbrowser::ActiveWebbrowser(const KCmdLineArgs *args) : KApplication() { Q_UNUSED(args); qmlRegisterType(); qmlRegisterType("org.kde.kdewebkit", 0, 1, "WebView"); setStartDragDistance(20); } ActiveWebbrowser::~ActiveWebbrowser() { } void ActiveWebbrowser::newWindow(const QString& url) { ActiveBrowserWindow *browserWindow = new ActiveBrowserWindow(url); browserWindow->setUseGL(m_useGL); - connect(browserWindow, SIGNAL(newWindow(const QString&)), SLOT(newWindow(const QString&))); + connect(browserWindow, SIGNAL(newWindow(QString)), SLOT(newWindow(QString))); browserWindow->show(); } void ActiveWebbrowser::setUseGL(const bool on) { /* not switchable at runtime for now, if we want this, we can add * some housekeeping for the windows, let's keep it KISS for now. */ m_useGL = on; } bool ActiveWebbrowser::useGL() const { return m_useGL; } #include "activewebbrowser.moc" diff --git a/applications/webbrowser/src/adblock/adblockmanager.cpp b/applications/webbrowser/src/adblock/adblockmanager.cpp index 7d24265c..6f7e5a40 100644 --- a/applications/webbrowser/src/adblock/adblockmanager.cpp +++ b/applications/webbrowser/src/adblock/adblockmanager.cpp @@ -1,374 +1,374 @@ /* ============================================================ * * This file has been kindly borrowed and adapted from the rekonq project * * Copyright (C) 2010-2011 by Andrea Diamantini * Copyright 2011 Sebastian Kügler * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) 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 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * ============================================================ */ #define QL1S(x) QLatin1String(x) #define QL1C(x) QLatin1Char(x) // Self Includes #include "adblockmanager.h" // Local Includes #include "adblocknetworkreply.h" //#include "adblockwidget.h" //#include "webpage.h" // KDE Includes #include #include #include #include #include // Qt Includes #include #include #include #include QStringList defaultLocations() { return QStringList("https://easylist-downloads.adblockplus.org/easylist.txt"); } QStringList defaultTitles() { return QStringList("EasyList"); } AdBlockManager::AdBlockManager(QObject *parent) : QObject(parent) , _isAdblockEnabled(false) , _isHideAdsEnabled(false) , _index(0) { _dirWatch = new KDirWatch(this); QString configPath = KStandardDirs::locateLocal("config", "active-webbrowserrc"); _dirWatch->addFile(configPath); - connect(_dirWatch, SIGNAL(dirty(const QString&)), SLOT(loadSettings())); - connect(_dirWatch, SIGNAL(created(const QString&)), SLOT(loadSettings())); + connect(_dirWatch, SIGNAL(dirty(QString)), SLOT(loadSettings())); + connect(_dirWatch, SIGNAL(created(QString)), SLOT(loadSettings())); loadSettings(); } AdBlockManager::~AdBlockManager() { _whiteList.clear(); _blackList.clear(); _hideList.clear(); } void AdBlockManager::loadSettings(bool checkUpdateDate) { _index = 0; _buffer.clear(); _hostWhiteList.clear(); _hostBlackList.clear(); _whiteList.clear(); _blackList.clear(); _hideList.clear(); KSharedConfigPtr ptr = KSharedConfig::openConfig("active-webbrowserrc"); ptr->reparseConfiguration(); _config = KConfigGroup(ptr, "adblock"); _isAdblockEnabled = _config.readEntry("adBlockEnabled", true); kDebug() << "Adblock is now " << _isAdblockEnabled; // no need to load filters if adblock is not enabled :) if (!_isAdblockEnabled) return; // just to be sure.. _isHideAdsEnabled = _config.readEntry("hideAdsEnabled", true); // read settings KSharedConfig::Ptr config = KSharedConfig::openConfig("adblock", KConfig::SimpleConfig, "appdata"); KConfigGroup rulesGroup(config, "rules"); QStringList rules; rules = rulesGroup.readEntry("local-rules" , QStringList()); loadRules(rules); // Checking wether to update the adblock filters, and doin' it QDateTime today = QDateTime::currentDateTime(); QDateTime lastUpdate = _config.readEntry("lastUpdate", QDateTime(QDate(2001, 9, 11))); int days = _config.readEntry("updateInterval", 7); if (!checkUpdateDate || today > lastUpdate.addDays(days)) { _config.writeEntry("lastUpdate", QDateTime::currentDateTime()); updateNextSubscription(); return; } // else QStringList titles = _config.readEntry("adBlockEnabled", defaultTitles()); foreach(const QString & title, titles) { rules = rulesGroup.readEntry(title + "-rules" , QStringList()); loadRules(rules); } } void AdBlockManager::loadRules(const QStringList &rules) { foreach(const QString & stringRule, rules) { // ! rules are comments if (stringRule.startsWith('!')) continue; // [ rules are ABP info if (stringRule.startsWith('[')) continue; // empty rules are just dangerous.. // (an empty rule in whitelist allows all, in blacklist blocks all..) if (stringRule.isEmpty()) continue; // white rules if (stringRule.startsWith(QL1S("@@"))) { const QString filter = stringRule.mid(2); if (_hostWhiteList.tryAddFilter(filter)) continue; AdBlockRule rule(filter); _whiteList << rule; continue; } // hide (CSS) rules if (stringRule.startsWith(QL1S("##"))) { _hideList << stringRule.mid(2); continue; } // TODO implement domain-specific hiding if (stringRule.contains(QL1S("##"))) continue; if (_hostBlackList.tryAddFilter(stringRule)) continue; AdBlockRule rule(stringRule); _blackList << rule; } } QNetworkReply *AdBlockManager::block(const QNetworkRequest &request, QWebPage *page) { if (!_isAdblockEnabled) return 0; // we (ad)block just http traffic if (request.url().scheme() != QL1S("http")) return 0; QString urlString = request.url().toString(); // We compute a lowercase version of the URL so each rule does not // have to do it. const QString urlStringLowerCase = urlString.toLower(); const QString host = request.url().host(); // check white rules before :) if (_hostWhiteList.match(host)) { //kDebug() << " ****ADBLOCK: WHITE RULE (@@) Matched by host matcher: ***********"; //kDebug() << " UrlString: " << urlString; return 0; } foreach(const AdBlockRule & filter, _whiteList) { if (filter.match(request, urlString, urlStringLowerCase)) { //kDebug() << " ****ADBLOCK: WHITE RULE (@@) Matched: ***********"; //kDebug() << " UrlString: " << urlString; return 0; } } // then check the black ones :( if (_hostBlackList.match(host)) { //kDebug() << " ****ADBLOCK: BLACK RULE Matched by host matcher: ***********"; //kDebug() << " UrlString: " << urlString; AdBlockNetworkReply *reply = new AdBlockNetworkReply(request, urlString, this); return reply; } foreach(const AdBlockRule & filter, _blackList) { if (filter.match(request, urlString, urlStringLowerCase)) { //kDebug() << " ****ADBLOCK: BLACK RULE Matched: ***********"; //kDebug() << " UrlString: " << urlString; QWebElement document = page->mainFrame()->documentElement(); QWebElementCollection elements = document.findAll("*"); foreach(QWebElement el, elements) { const QString srcAttribute = el.attribute("src"); if (filter.match(request, srcAttribute, srcAttribute.toLower())) { //kDebug() << "MATCHES ATTRIBUTE!!!!!"; el.setStyleProperty(QL1S("visibility"), QL1S("hidden")); el.setStyleProperty(QL1S("width"), QL1S("0")); el.setStyleProperty(QL1S("height"), QL1S("0")); } } AdBlockNetworkReply *reply = new AdBlockNetworkReply(request, urlString, this); return reply; } } // no match return 0; } void AdBlockManager::applyHidingRules(QWebPage *page) { if (!page) return; if (!_isAdblockEnabled) return; if (!_isHideAdsEnabled) return; QWebElement document = page->mainFrame()->documentElement(); // HIDE RULES foreach(const QString & filter, _hideList) { QWebElementCollection elements = document.findAll(filter); foreach(QWebElement el, elements) { if (el.isNull()) continue; //kDebug() << "Hide element: " << el.localName(); el.setStyleProperty(QL1S("visibility"), QL1S("hidden")); el.removeFromDocument(); } } } void AdBlockManager::updateNextSubscription() { QStringList locations = _config.readEntry("subscriptionLocations", defaultLocations()); if (_index < locations.size()) { QString urlString = locations.at(_index); KUrl subUrl = KUrl(urlString); KIO::TransferJob* job = KIO::get(subUrl , KIO::Reload , KIO::HideProgressInfo); job->metaData().insert("ssl_no_client_cert", "TRUE"); job->metaData().insert("ssl_no_ui", "TRUE"); job->metaData().insert("UseCache", "false"); job->metaData().insert("cookies", "none"); job->metaData().insert("no-auth", "true"); - connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)), this, SLOT(subscriptionData(KIO::Job*, const QByteArray&))); + connect(job, SIGNAL(data(KIO::Job*,QByteArray)), this, SLOT(subscriptionData(KIO::Job*,QByteArray))); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotResult(KJob*))); - connect(job, SIGNAL(finished(KJob *job)), this, SLOT(slotFinished())); + connect(job, SIGNAL(finished(KJob*job)), this, SLOT(slotFinished())); return; } _index = 0; _buffer.clear(); } void AdBlockManager::slotResult(KJob *job) { if (job->error()) { kWarning() << "Fetching rules failed: " << job->errorString(); return; } QList list = _buffer.split('\n'); QStringList ruleList; foreach(const QByteArray & ba, list) { ruleList << QString(ba); } loadRules(ruleList); saveRules(ruleList); _index++; // last.. updateNextSubscription(); } void AdBlockManager::subscriptionData(KIO::Job* job, const QByteArray& data) { Q_UNUSED(job) if (data.isEmpty()) return; int oldSize = _buffer.size(); _buffer.resize(_buffer.size() + data.size()); memcpy(_buffer.data() + oldSize, data.data(), data.size()); } void AdBlockManager::saveRules(const QStringList &rules) { QStringList cleanedRules; foreach(const QString & r, rules) { if (!r.startsWith('!') && !r.startsWith('[') && !r.isEmpty()) cleanedRules << r; } QStringList titles = _config.readEntry("subscriptionTitles", defaultTitles()); QString title = titles.at(_index) + "-rules"; KSharedConfig::Ptr config = KSharedConfig::openConfig("adblock", KConfig::SimpleConfig, "appdata"); KConfigGroup cg(config , "rules"); cg.writeEntry(title, cleanedRules); } void AdBlockManager::addSubscription(const QString &title, const QString &location) { QStringList titles = _config.readEntry("subscriptionTitles", defaultTitles()); if (titles.contains(title)) return; QStringList locations = _config.readEntry("subscriptionLocations", defaultLocations()); if (locations.contains(location)) return; titles << title; locations << location; _config.writeEntry("subscriptionTitles", titles); _config.writeEntry("subscriptionLocations", locations); } #include "adblockmanager.moc" diff --git a/applications/webbrowser/src/history.cpp b/applications/webbrowser/src/history.cpp index 6519f3c6..30a37838 100644 --- a/applications/webbrowser/src/history.cpp +++ b/applications/webbrowser/src/history.cpp @@ -1,155 +1,155 @@ /*************************************************************************** * * * Copyright 2011 Sebastian Kügler * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "history.h" #include "completionitem.h" #include #include #include "kdebug.h" #include #include #include #include class HistoryPrivate { public: QList items; QImage icon; KConfigGroup config; KDirWatch* dirWatch; QTimer saveTimer; QString separator; CompletionItem* currentPage; QTimer addHistoryTimer; }; History::History(QObject *parent) : QObject(parent) { d = new HistoryPrivate; d->dirWatch = new KDirWatch(this); QString configPath = KStandardDirs::locateLocal("config", "active-webbrowserrc"); d->dirWatch->addFile(configPath); d->separator = "|X|"; d->currentPage = 0; // wait 30 sec before saving to history, // transient pages aren't interesting enough d->addHistoryTimer.setInterval(30000); connect(&d->addHistoryTimer, SIGNAL(timeout()), SLOT(recordHistory())); - connect(d->dirWatch, SIGNAL(dirty(const QString&)), SLOT(loadHistory())); - connect(d->dirWatch, SIGNAL(created(const QString&)), SLOT(loadHistory())); + connect(d->dirWatch, SIGNAL(dirty(QString)), SLOT(loadHistory())); + connect(d->dirWatch, SIGNAL(created(QString)), SLOT(loadHistory())); } History::~History() { delete d; } QList History::items() { return d->items; } void History::loadHistory() { KSharedConfigPtr ptr = KSharedConfig::openConfig("active-webbrowserrc"); KConfigGroup config = KConfigGroup(ptr, "history"); d->items.clear(); QStringList h = config.readEntry("history", QStringList()); foreach (const QString &hitem, h) { QStringList hs = hitem.split(d->separator); //kDebug() << "XXX history: " << hs; QString url = hs.at(0); QString title; if (url.isEmpty()) { continue; } if (hs.count() > 1) { title = hs.at(1); } CompletionItem* item = new CompletionItem(title, url, d->icon, this); item->setIconName("view-history"); d->items.append(item); } emit dataChanged(); } void History::addPage(const QString &url, const QString &title) { if (url.isEmpty() && title.isEmpty()) { return; } // Remove entry from earlier in the history: less clutter foreach (QObject* i, d->items) { CompletionItem* ci = qobject_cast(i); if (ci->url() == url) { d->items.removeAll(i); } } CompletionItem* item = new CompletionItem(title, url, d->icon, this); item->setIconName("view-history"); d->items.prepend(item); while (d->items.count() > 256) { d->items.takeLast(); } } void History::visitPage(const QString &url, const QString &title) { d->currentPage = new CompletionItem(title, url, d->icon, this); d->currentPage->setIconName("view-history"); d->addHistoryTimer.start(); } void History::recordHistory() { //kDebug() << "XXX Recording history!"; d->addHistoryTimer.stop(); if (d->items.count() == 0) { loadHistory(); } addPage(d->currentPage->url(), d->currentPage->name()); emit dataChanged(); saveHistory(); } void History::saveHistory() { QStringList l; foreach(QObject* it, d->items) { CompletionItem* ci = qobject_cast(it); if (ci) { l.append(ci->url() + d->separator + ci->name()); } } KSharedConfigPtr ptr = KSharedConfig::openConfig("active-webbrowserrc"); KConfigGroup config = KConfigGroup(ptr, "history"); config.writeEntry("history", l); config.sync(); //kDebug() << "XXX History saved to disk"; } #include "history.moc" diff --git a/applications/webbrowser/src/kdeclarativewebview.cpp b/applications/webbrowser/src/kdeclarativewebview.cpp index 3f751d5a..f9d4a98a 100644 --- a/applications/webbrowser/src/kdeclarativewebview.cpp +++ b/applications/webbrowser/src/kdeclarativewebview.cpp @@ -1,1338 +1,1338 @@ /* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) 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. */ #define QL1S(x) QLatin1String(x) #define QL1C(x) QLatin1Char(x) #include "kdeclarativewebview.h" #include "networkaccessmanager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class KDeclarativeWebViewPrivate { public: KDeclarativeWebViewPrivate(KDeclarativeWebView* qq) : q(qq) , preferredwidth(0) , preferredheight(0) , progress(1.0) , status(KDeclarativeWebView::Null) , wallet(0) , pending(PendingNone) , newWindowComponent(0) , newWindowParent(0) , rendering(true) { } KDeclarativeWebView* q; QUrl url; // page url might be different if it has not loaded yet GraphicsWebView* view; int preferredwidth, preferredheight; qreal progress; KDeclarativeWebView::Status status; KWebWallet *wallet; QString statusText; enum { PendingNone, PendingUrl, PendingHtml, PendingContent } pending; QUrl pendingUrl; QString pendingString; QByteArray pendingData; QStringList rssFeeds; mutable KDeclarativeWebSettings settings; QDeclarativeComponent* newWindowComponent; QDeclarativeItem* newWindowParent; static void windowObjectsAppend(QDeclarativeListProperty* prop, QObject* o) { static_cast(prop->data)->windowObjects.append(o); static_cast(prop->data)->updateWindowObjects(); } void updateWindowObjects(); QObjectList windowObjects; bool rendering; KDirWatch* dirWatch; }; GraphicsWebView::GraphicsWebView(KDeclarativeWebView* parent) : QGraphicsWebView(parent) , parent(parent) , pressTime(400) , flicking(true) { } void GraphicsWebView::mousePressEvent(QGraphicsSceneMouseEvent* event) { pressPoint = event->pos(); if (pressTime) { pressTimer.start(pressTime, this); parent->setKeepMouseGrab(false); } else { grabMouse(); parent->setKeepMouseGrab(true); } QGraphicsWebView::mousePressEvent(event); QWebHitTestResult hit = page()->mainFrame()->hitTestContent(pressPoint.toPoint()); if (hit.isContentEditable()) { parent->forceActiveFocus(); } // Comboboxes and flicking don't go together well, // disable flicking as long as the combo box is open setFlickingEnabled(hit.element().tagName() != "SELECT"); kDebug() << " - - > Hit element: " << hit.element().tagName() << hit.linkElement().geometry(); if (!hit.linkElement().geometry().isNull()) { kDebug() << "XXXXXXXXXX link pressed. .. "; emit linkPressed(hit.linkUrl(), hit.linkElement().geometry()); } //QMouseEvent* me = new QMouseEvent(QEvent::MouseButtonDblClick, (event->pos() / parent->contentsScale()).toPoint(), event->button(), event->buttons(), 0); emit click(event->pos().x(), event->pos().y()); setFocus(); } void GraphicsWebView::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { QGraphicsWebView::mouseReleaseEvent(event); pressTimer.stop(); parent->setKeepMouseGrab(false); ungrabMouse(); } void GraphicsWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) { QMouseEvent* me = new QMouseEvent(QEvent::MouseButtonDblClick, (event->pos() / parent->contentsScale()).toPoint(), event->button(), event->buttons(), 0); emit doubleClick(event->pos().x(), event->pos().y()); delete me; } void GraphicsWebView::handleLinkClicked(const QUrl &link) { QUrl u(link); if (pressTimer.isActive()) { kDebug() << "timer is running, loading URL" << link; page()->mainFrame()->load(u); } else { kDebug() << "timer is not running, not loading url" << link; } } void GraphicsWebView::timerEvent(QTimerEvent* event) { if (event->timerId() == pressTimer.timerId()) { pressTimer.stop(); grabMouse(); parent->setKeepMouseGrab(true); kDebug() << "handle pressAndHold"; QWebHitTestResult hit = page()->mainFrame()->hitTestContent(pressPoint.toPoint()); if (!hit.linkElement().geometry().isNull()) { kDebug() << "XXXXXXXXXX link pressed AND HOLD. .. "; emit linkPressAndHold(hit.linkUrl(), hit.linkElement().geometry()); } } } void GraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { if (pressTimer.isActive()) { if ((event->pos() - pressPoint).manhattanLength() > QApplication::startDragDistance()) pressTimer.stop(); } if (parent->keepMouseGrab()) QGraphicsWebView::mouseMoveEvent(event); } bool GraphicsWebView::sceneEvent(QEvent *event) { bool rv = QGraphicsWebView::sceneEvent(event); if (event->type() == QEvent::UngrabMouse) { pressTimer.stop(); parent->setKeepMouseGrab(false); } return rv; } bool GraphicsWebView::flickingEnabled() const { return flicking; } void GraphicsWebView::setFlickingEnabled(bool enabled) { if (flicking != enabled) { flicking = enabled; emit flickingEnabledChanged(); } } /*! \qmlclass WebView KDeclarativeWebView \ingroup qml-view-elements \since 4.7 \brief The WebView item allows you to add Web content to a canvas. \inherits Item A WebView renders Web content based on a URL. This type is made available by importing the \c QtWebKit module: \bold{import QtWebKit 1.0} The WebView item includes no scrolling, scaling, toolbars, or other common browser components. These must be implemented around WebView. See the \l{QML Web Browser} example for a demonstration of this. The page to be displayed by the item is specified using the \l url property, and this can be changed to fetch and display a new page. While the page loads, the \l progress property is updated to indicate how much of the page has been loaded. \section1 Appearance If the width and height of the item is not set, they will dynamically adjust to a size appropriate for the content. This width may be large for typical online web pages, typically greater than 800 by 600 pixels. If the \l{Item::}{width} or \l{Item::}{height} is explictly set, the rendered Web site will be clipped, not scaled, to fit into the set dimensions. If the preferredWidth property is set, the width will be this amount or larger, usually laying out the Web content to fit the preferredWidth. The appearance of the content can be controlled to a certain extent by changing the settings.standardFontFamily property and other settings related to fonts. The page can be zoomed by calling the heuristicZoom() method, which performs a series of tests to determine whether zoomed content will be displayed in an appropriate way in the space allocated to the item. \section1 User Interaction and Navigation By default, certain mouse and touch events are delivered to other items in preference to the Web content. For example, when a scrolling view is created by placing a WebView in a Flickable, move events are delivered to the Flickable so that the user can scroll the page. This prevents the user from accidentally selecting text in a Web page instead of scrolling. The pressGrabTime property defines the time the user must touch or press a mouse button over the WebView before the Web content will receive the move events it needs to select text and images. When this item has keyboard focus, all keyboard input will be sent directly to the Web page within. When the navigates by clicking on links, the item records the pages visited in its internal history Because this item is designed to be used as a component in a browser, it exposes \l{Action}{actions} for \l back, \l forward, \l reload and \l stop. These can be triggered to change the current page displayed by the item. \section1 Example Usage \beginfloatright \inlineimage webview.png \endfloat The following example displays a scaled down Web page at a fixed size. \snippet doc/src/snippets/declarative/webview/webview.qml document \clearfloat \sa {declarative/modelviews/webview}{WebView example}, {demos/declarative/webbrowser}{Web Browser demo} */ /*! \internal \class KDeclarativeWebView \brief The KDeclarativeWebView class allows you to add web content to a QDeclarativeView. A WebView renders web content base on a URL. \image webview.png The item includes no scrolling, scaling, toolbars, etc., those must be implemented around WebView. See the WebBrowser example for a demonstration of this. A KDeclarativeWebView object can be instantiated in Qml using the tag \l WebView. */ KDeclarativeWebView::KDeclarativeWebView(QDeclarativeItem *parent) : QDeclarativeItem(parent) { init(); } KDeclarativeWebView::~KDeclarativeWebView() { delete d; } void KDeclarativeWebView::init() { d = new KDeclarativeWebViewPrivate(this); if (QWebSettings::iconDatabasePath().isNull() && QWebSettings::globalSettings()->localStoragePath().isNull() && QWebSettings::offlineStoragePath().isNull() && QWebSettings::offlineWebApplicationCachePath().isNull()) QWebSettings::enablePersistentStorage(); setAcceptedMouseButtons(Qt::LeftButton); setFlag(QGraphicsItem::ItemHasNoContents, true); setClip(true); d->view = new GraphicsWebView(this); d->view->setResizesToContents(true); QWebPage* wp = new QDeclarativeWebPage(this); KWebPage* kwp = qobject_cast(wp); if (kwp) { WId wid = KWindowSystem::activeWindow(); d->wallet = new KWebWallet(this, wid); kwp->setWallet(d->wallet); // TODO: hook in some dialog wether the user wants to save the form data // happens unconditionally right now for every form filled in - connect(d->wallet, SIGNAL(saveFormDataRequested(const QString &, const QUrl &)), - d->wallet, SLOT(acceptSaveFormDataRequest(const QString &)), Qt::UniqueConnection); + connect(d->wallet, SIGNAL(saveFormDataRequested(QString,QUrl)), + d->wallet, SLOT(acceptSaveFormDataRequest(QString)), Qt::UniqueConnection); } wp->setForwardUnsupportedContent(true); setPage(wp); initSettings(); #ifndef NO_KIO KIO::AccessManager *access = new NetworkAccessManager(page()); wp->setNetworkAccessManager(access); #endif connect(d->view, SIGNAL(geometryChanged()), this, SLOT(updateDeclarativeWebViewSize())); connect(d->view, SIGNAL(flickingEnabledChanged()), this, SLOT(updateFlickingEnabled())); - connect(d->view, SIGNAL(click(int, int)), this, SIGNAL(click(int, int))); - connect(d->view, SIGNAL(doubleClick(int, int)), this, SIGNAL(doubleClick(int, int))); + connect(d->view, SIGNAL(click(int,int)), this, SIGNAL(click(int,int))); + connect(d->view, SIGNAL(doubleClick(int,int)), this, SIGNAL(doubleClick(int,int))); - //connect(d->view, SIGNAL(loadLink(const QUrl&, const QRect&)), SIGNAL(linkClicked(const QUrl&, const QRect&))); - connect(d->view, SIGNAL(linkPressed(const QUrl&, const QRect&)), - this, SIGNAL(linkPressed(const QUrl&, const QRect&))); - connect(d->view, SIGNAL(linkPressAndHold(const QUrl&, const QRect&)), - this, SIGNAL(linkPressAndHold(const QUrl&, const QRect&))); + //connect(d->view, SIGNAL(loadLink(QUrl,QRect)), SIGNAL(linkClicked(QUrl,QRect))); + connect(d->view, SIGNAL(linkPressed(QUrl,QRect)), + this, SIGNAL(linkPressed(QUrl,QRect))); + connect(d->view, SIGNAL(linkPressAndHold(QUrl,QRect)), + this, SIGNAL(linkPressAndHold(QUrl,QRect))); connect(d->view, SIGNAL(scaleChanged()), this, SIGNAL(contentsScaleChanged())); connect(access, SIGNAL(finished(QNetworkReply*)), page(), SLOT(handleNetworkErrors(QNetworkReply*))); wp->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); - connect(wp, SIGNAL(linkClicked(const QUrl&)), d->view, SLOT(handleLinkClicked(const QUrl&))); + connect(wp, SIGNAL(linkClicked(QUrl)), d->view, SLOT(handleLinkClicked(QUrl))); d->dirWatch = new KDirWatch(this); QString configPath = KStandardDirs::locateLocal("config", "active-webbrowserrc"); d->dirWatch->addFile(configPath); - connect(d->dirWatch, SIGNAL(dirty(const QString&)), SLOT(initSettings())); - connect(d->dirWatch, SIGNAL(created(const QString&)), SLOT(initSettings())); + connect(d->dirWatch, SIGNAL(dirty(QString)), SLOT(initSettings())); + connect(d->dirWatch, SIGNAL(created(QString)), SLOT(initSettings())); } void KDeclarativeWebView::initSettings() { //kDebug() << "Settings up fonts and reading settings: " << KGlobalSettings::generalFont().family() << KGlobalSettings::generalFont().pointSize(); settings()->setFontFamily(QWebSettings::StandardFont, KGlobalSettings::generalFont().family()); settings()->setFontFamily(QWebSettings::SerifFont, KGlobalSettings::generalFont().family()); settings()->setFontFamily(QWebSettings::FixedFont, KGlobalSettings::generalFont().family()); settings()->setFontFamily(QWebSettings::CursiveFont, KGlobalSettings::generalFont().family()); settings()->setFontFamily(QWebSettings::SansSerifFont, KGlobalSettings::generalFont().family()); settings()->setFontFamily(QWebSettings::FantasyFont, KGlobalSettings::generalFont().family()); settings()->setFontSize(QWebSettings::DefaultFontSize, KGlobalSettings::generalFont().pointSize()); //settings()->setFontSize(QWebSettings::FontSize, KGlobalSettings::generalFont().pointSize()); settings()->setFontSize(QWebSettings::DefaultFixedFontSize, KGlobalSettings::fixedFont().pointSize()); settings()->setFontSize(QWebSettings::MinimumFontSize, KGlobalSettings::smallestReadableFont().pointSize()); settings()->setFontSize(QWebSettings::MinimumLogicalFontSize, KGlobalSettings::smallestReadableFont().pointSize()); // From configuration KSharedConfigPtr ptr = KSharedConfig::openConfig("active-webbrowserrc"); ptr->reparseConfiguration(); KConfigGroup cg(ptr, "webbrowser"); bool pluginsEnabled = cg.readEntry("pluginsEnabled", false); //kDebug() << " C++ Plugins on? " << pluginsEnabled; settings()->setAttribute(QWebSettings::PluginsEnabled, pluginsEnabled); settingsObject()->setPluginsEnabled(pluginsEnabled); } void KDeclarativeWebView::componentComplete() { QDeclarativeItem::componentComplete(); #ifdef NO_KIO page()->setNetworkAccessManager(qmlEngine(this)->networkAccessManager()); #endif switch (d->pending) { case KDeclarativeWebViewPrivate::PendingUrl: setUrl(d->pendingUrl); break; case KDeclarativeWebViewPrivate::PendingHtml: setHtml(d->pendingString, d->pendingUrl); break; case KDeclarativeWebViewPrivate::PendingContent: setContent(d->pendingData, d->pendingString, d->pendingUrl); break; default: break; } d->pending = KDeclarativeWebViewPrivate::PendingNone; d->updateWindowObjects(); } KDeclarativeWebView::Status KDeclarativeWebView::status() const { return d->status; } /*! \qmlproperty real WebView::progress This property holds the progress of loading the current URL, from 0 to 1. If you just want to know when progress gets to 1, use WebView::onLoadFinished() or WebView::onLoadFailed() instead. */ qreal KDeclarativeWebView::progress() const { return d->progress; } void KDeclarativeWebView::doLoadStarted() { if (!d->url.isEmpty()) { d->status = Loading; emit statusChanged(d->status); } setRssFeeds(QStringList()); emit loadStarted(); } void KDeclarativeWebView::doLoadProgress(int p) { if (d->progress == p / 100.0) return; d->progress = p / 100.0; emit progressChanged(); } void KDeclarativeWebView::pageUrlChanged() { updateContentsSize(); if ((d->url.isEmpty() && page()->mainFrame()->url() != QUrl(QLatin1String("about:blank"))) || (d->url != page()->mainFrame()->url() && !page()->mainFrame()->url().isEmpty())) { d->url = page()->mainFrame()->url(); if (d->url == QUrl(QLatin1String("about:blank"))) d->url = QUrl(); emit urlChanged(); } } void KDeclarativeWebView::doLoadFinished(bool ok) { if (ok) { d->status = d->url.isEmpty() ? Null : Ready; emit loadFinished(); if (d->status == Ready) { if (d->wallet) { d->wallet->fillFormData(page()->mainFrame()); } foreach (const QWebElement &el, page()->mainFrame()->findAllElements("LINK")) { if (el.attribute("type").contains("application/rss+xml")) { d->rssFeeds << el.attribute("href"); } } if (!rssFeeds().isEmpty()) { emit rssFeedsChanged(); } } } else { d->status = Error; emit loadFailed(); } emit statusChanged(d->status); } /*! \qmlproperty url WebView::url This property holds the URL to the page displayed in this item. It can be set, but also can change spontaneously (eg. because of network redirection). If the url is empty, the page is blank. The url is always absolute (QML will resolve relative URL strings in the context of the containing QML document). */ QUrl KDeclarativeWebView::url() const { return d->url; } void KDeclarativeWebView::setUrl(const QUrl& url) { if (url == d->url) return; if (isComponentComplete()) { d->url = url; updateContentsSize(); QUrl seturl = url; if (seturl.isEmpty()) seturl = QUrl(QLatin1String("about:blank")); Q_ASSERT(!seturl.isRelative()); page()->mainFrame()->load(seturl); emit urlChanged(); } else { d->pending = d->PendingUrl; d->pendingUrl = url; } } QStringList KDeclarativeWebView::rssFeeds() const { return d->rssFeeds; } void KDeclarativeWebView::setRssFeeds(const QStringList &feeds) { if (d->rssFeeds != feeds) { d->rssFeeds = feeds; emit rssFeedsChanged(); }; } /*! \qmlproperty int WebView::preferredWidth This property holds the ideal width for displaying the current URL. */ int KDeclarativeWebView::preferredWidth() const { return d->preferredwidth; } void KDeclarativeWebView::setPreferredWidth(int width) { if (d->preferredwidth == width) return; d->preferredwidth = width; updateContentsSize(); emit preferredWidthChanged(); } /*! \qmlproperty int WebView::preferredHeight This property holds the ideal height for displaying the current URL. This only affects the area zoomed by heuristicZoom(). */ int KDeclarativeWebView::preferredHeight() const { return d->preferredheight; } void KDeclarativeWebView::setPreferredHeight(int height) { if (d->preferredheight == height) return; d->preferredheight = height; updateContentsSize(); emit preferredHeightChanged(); } /*! \qmlmethod bool WebView::evaluateJavaScript(string scriptSource) Evaluates the \a scriptSource JavaScript inside the context of the main web frame, and returns the result of the last executed statement. Note that this JavaScript does \e not have any access to QML objects except as made available as windowObjects. */ QVariant KDeclarativeWebView::evaluateJavaScript(const QString& scriptSource) { return this->page()->mainFrame()->evaluateJavaScript(scriptSource); } void KDeclarativeWebView::updateDeclarativeWebViewSize() { QSizeF size = d->view->geometry().size() * contentsScale(); setImplicitWidth(size.width()); setImplicitHeight(size.height()); } void KDeclarativeWebView::initialLayout() { // nothing useful to do at this point } void KDeclarativeWebView::updateContentsSize() { if (page()) { page()->setPreferredContentsSize(QSize( d->preferredwidth>0 ? d->preferredwidth : width(), d->preferredheight>0 ? d->preferredheight : height())); } } void KDeclarativeWebView::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) { QWebPage* webPage = page(); if (newGeometry.size() != oldGeometry.size() && webPage) { QSize contentSize = webPage->preferredContentsSize(); if (widthValid()) contentSize.setWidth(width()); if (heightValid()) contentSize.setHeight(height()); if (contentSize != webPage->preferredContentsSize()) webPage->setPreferredContentsSize(contentSize); } QDeclarativeItem::geometryChanged(newGeometry, oldGeometry); } /*! \qmlproperty list WebView::javaScriptWindowObjects A list of QML objects to expose to the web page. Each object will be added as a property of the web frame's window object. The property name is controlled by the value of \c WebView.windowObjectName attached property. Exposing QML objects to a web page allows JavaScript executing in the web page itself to communicate with QML, by reading and writing properties and by calling methods of the exposed QML objects. This example shows how to call into a QML method using a window object. \qml WebView { javaScriptWindowObjects: QtObject { WebView.windowObjectName: "qml" function qmlCall() { console.log("This call is in QML!"); } } html: "" } \endqml The output of the example will be: \code This is in WebKit! This call is in QML! \endcode If Javascript is not enabled for the page, then this property does nothing. */ QDeclarativeListProperty KDeclarativeWebView::javaScriptWindowObjects() { return QDeclarativeListProperty(this, d, &KDeclarativeWebViewPrivate::windowObjectsAppend); } KDeclarativeWebViewAttached* KDeclarativeWebView::qmlAttachedProperties(QObject* o) { return new KDeclarativeWebViewAttached(o); } void KDeclarativeWebViewPrivate::updateWindowObjects() { if (!q->isComponentCompletePublic() || !q->page()) return; for (int i = 0; i < windowObjects.count(); ++i) { QObject* object = windowObjects.at(i); KDeclarativeWebViewAttached* attached = static_cast(qmlAttachedPropertiesObject(object)); if (attached && !attached->windowObjectName().isEmpty()) q->page()->mainFrame()->addToJavaScriptWindowObject(attached->windowObjectName(), object); } } bool KDeclarativeWebView::renderingEnabled() const { return d->rendering; } void KDeclarativeWebView::setRenderingEnabled(bool enabled) { if (d->rendering == enabled) return; d->rendering = enabled; emit renderingEnabledChanged(); d->view->setTiledBackingStoreFrozen(!enabled); } /*! \qmlsignal WebView::onDoubleClick(int clickx, int clicky) The WebView does not pass double-click events to the web engine, but rather emits this signals. */ /*! \qmlmethod bool WebView::heuristicZoom(int clickX, int clickY, real maxzoom) Finds a zoom that: \list \i shows a whole item \i includes (\a clickX, \a clickY) \i fits into the preferredWidth and preferredHeight \i zooms by no more than \a maxZoom \i is more than 10% above the current zoom \endlist If such a zoom exists, emits zoomTo(zoom,centerX,centerY) and returns true; otherwise, no signal is emitted and returns false. */ bool KDeclarativeWebView::heuristicZoom(int clickX, int clickY, qreal maxZoom) { if (contentsScale() >= maxZoom / scale()) return false; qreal ozf = contentsScale(); QRect showArea = elementAreaAt(clickX, clickY, d->preferredwidth / maxZoom, d->preferredheight / maxZoom); qreal z = qMin(qreal(d->preferredwidth) / showArea.width(), qreal(d->preferredheight) / showArea.height()); if (z > maxZoom / scale()) z = maxZoom / scale(); if (z / ozf > 1.2) { QRectF r(showArea.left() * z, showArea.top() * z, showArea.width() * z, showArea.height() * z); emit zoomTo(z, r.x() + r.width() / 2, r.y() + r.height() / 2); return true; } return false; } /*! \qmlproperty int WebView::pressGrabTime The number of milliseconds the user must press before the WebView starts passing move events through to the Web engine (rather than letting other QML elements such as a Flickable take them). Defaults to 400ms. Set to 0 to always grab and pass move events to the Web engine. */ int KDeclarativeWebView::pressGrabTime() const { return d->view->pressTime; } void KDeclarativeWebView::setPressGrabTime(int millis) { if (d->view->pressTime == millis) return; d->view->pressTime = millis; emit pressGrabTimeChanged(); } bool KDeclarativeWebView::flickingEnabled() const { return d->view->flickingEnabled(); } void KDeclarativeWebView::setFlickingEnabled(bool enabled) { d->view->setFlickingEnabled(enabled); emit flickingEnabledChanged(); } void KDeclarativeWebView::updateFlickingEnabled() { setFlickingEnabled(d->view->flickingEnabled()); } #ifndef QT_NO_ACTION /*! \qmlproperty action WebView::back This property holds the action for causing the previous URL in the history to be displayed. */ QAction* KDeclarativeWebView::backAction() const { return page()->action(QWebPage::Back); } /*! \qmlproperty action WebView::forward This property holds the action for causing the next URL in the history to be displayed. */ QAction* KDeclarativeWebView::forwardAction() const { return page()->action(QWebPage::Forward); } /*! \qmlproperty action WebView::reload This property holds the action for reloading with the current URL */ QAction* KDeclarativeWebView::reloadAction() const { return page()->action(QWebPage::Reload); } /*! \qmlproperty action WebView::stop This property holds the action for stopping loading with the current URL */ QAction* KDeclarativeWebView::stopAction() const { return page()->action(QWebPage::Stop); } #endif // QT_NO_ACTION /*! \qmlproperty string WebView::title This property holds the title of the web page currently viewed By default, this property contains an empty string. */ QString KDeclarativeWebView::title() const { return page()->mainFrame()->title(); } /*! \qmlproperty pixmap WebView::icon This property holds the icon associated with the web page currently viewed */ QPixmap KDeclarativeWebView::icon() const { return page()->mainFrame()->icon().pixmap(QSize(256, 256)); } /*! \qmlproperty string WebView::statusText This property is the current status suggested by the current web page. In a web browser, such status is often shown in some kind of status bar. */ void KDeclarativeWebView::setStatusText(const QString& text) { d->statusText = text; emit statusTextChanged(); } void KDeclarativeWebView::windowObjectCleared() { d->updateWindowObjects(); } QString KDeclarativeWebView::statusText() const { return d->statusText; } QWebPage* KDeclarativeWebView::page() const { return d->view->page(); } // The QObject interface to settings(). /*! \qmlproperty string WebView::settings.standardFontFamily \qmlproperty string WebView::settings.fixedFontFamily \qmlproperty string WebView::settings.serifFontFamily \qmlproperty string WebView::settings.sansSerifFontFamily \qmlproperty string WebView::settings.cursiveFontFamily \qmlproperty string WebView::settings.fantasyFontFamily \qmlproperty int WebView::settings.minimumFontSize \qmlproperty int WebView::settings.minimumLogicalFontSize \qmlproperty int WebView::settings.defaultFontSize \qmlproperty int WebView::settings.defaultFixedFontSize \qmlproperty bool WebView::settings.autoLoadImages \qmlproperty bool WebView::settings.javascriptEnabled \qmlproperty bool WebView::settings.javaEnabled \qmlproperty bool WebView::settings.pluginsEnabled \qmlproperty bool WebView::settings.privateBrowsingEnabled \qmlproperty bool WebView::settings.javascriptCanOpenWindows \qmlproperty bool WebView::settings.javascriptCanAccessClipboard \qmlproperty bool WebView::settings.developerExtrasEnabled \qmlproperty bool WebView::settings.linksIncludedInFocusChain \qmlproperty bool WebView::settings.zoomTextOnly \qmlproperty bool WebView::settings.printElementBackgrounds \qmlproperty bool WebView::settings.offlineStorageDatabaseEnabled \qmlproperty bool WebView::settings.offlineWebApplicationCacheEnabled \qmlproperty bool WebView::settings.localStorageDatabaseEnabled \qmlproperty bool WebView::settings.localContentCanAccessRemoteUrls These properties give access to the settings controlling the web view. See QWebSettings for details of these properties. \qml WebView { settings.pluginsEnabled: true settings.standardFontFamily: "Arial" // ... } \endqml */ KDeclarativeWebSettings* KDeclarativeWebView::settingsObject() const { d->settings.s = page()->settings(); return &d->settings; } void KDeclarativeWebView::setPage(QWebPage* page) { if (d->view->page() == page) return; d->view->setPage(page); updateContentsSize(); page->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); page->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); connect(page->mainFrame(), SIGNAL(urlChanged(QUrl)), this, SLOT(pageUrlChanged())); connect(page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString))); connect(page->mainFrame(), SIGNAL(titleChanged(QString)), this, SIGNAL(iconChanged())); connect(page->mainFrame(), SIGNAL(iconChanged()), this, SIGNAL(iconChanged())); connect(page->mainFrame(), SIGNAL(initialLayoutCompleted()), this, SLOT(initialLayout())); connect(page->mainFrame(), SIGNAL(contentsSizeChanged(QSize)), this, SIGNAL(contentsSizeChanged(QSize))); connect(page, SIGNAL(loadStarted()), this, SLOT(doLoadStarted())); connect(page, SIGNAL(loadProgress(int)), this, SLOT(doLoadProgress(int))); connect(page, SIGNAL(loadFinished(bool)), this, SLOT(doLoadFinished(bool))); connect(page, SIGNAL(statusBarMessage(QString)), this, SLOT(setStatusText(QString))); connect(page->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(windowObjectCleared())); page->settings()->setAttribute(QWebSettings::TiledBackingStoreEnabled, true); } /*! \qmlsignal WebView::onLoadStarted() This handler is called when the web engine begins loading a page. Later, WebView::onLoadFinished() or WebView::onLoadFailed() will be emitted. */ /*! \qmlsignal WebView::onLoadFinished() This handler is called when the web engine \e successfully finishes loading a page, including any component content (WebView::onLoadFailed() will be emitted otherwise). \sa progress */ /*! \qmlsignal WebView::onLoadFailed() This handler is called when the web engine fails loading a page or any component content (WebView::onLoadFinished() will be emitted on success). */ void KDeclarativeWebView::load(const QNetworkRequest& request, QNetworkAccessManager::Operation operation, const QByteArray& body) { page()->mainFrame()->load(request, operation, body); } QString KDeclarativeWebView::html() const { return page()->mainFrame()->toHtml(); } /*! \qmlproperty string WebView::html This property holds HTML text set directly The html property can be set as a string. \qml WebView { html: "

This is HTML." } \endqml */ void KDeclarativeWebView::setHtml(const QString& html, const QUrl& baseUrl) { updateContentsSize(); if (isComponentComplete()) page()->mainFrame()->setHtml(html, baseUrl); else { d->pending = d->PendingHtml; d->pendingUrl = baseUrl; d->pendingString = html; } emit htmlChanged(); } void KDeclarativeWebView::setContent(const QByteArray& data, const QString& mimeType, const QUrl& baseUrl) { updateContentsSize(); if (isComponentComplete()) page()->mainFrame()->setContent(data, mimeType, qmlContext(this)->resolvedUrl(baseUrl)); else { d->pending = d->PendingContent; d->pendingUrl = baseUrl; d->pendingString = mimeType; d->pendingData = data; } } QWebHistory* KDeclarativeWebView::history() const { return page()->history(); } QWebSettings* KDeclarativeWebView::settings() const { return page()->settings(); } KDeclarativeWebView* KDeclarativeWebView::createWindow(QWebPage::WebWindowType type) { switch (type) { case QWebPage::WebBrowserWindow: { if (!d->newWindowComponent && d->newWindowParent) qWarning("WebView::newWindowComponent not set - WebView::newWindowParent ignored"); else if (d->newWindowComponent && !d->newWindowParent) qWarning("WebView::newWindowParent not set - WebView::newWindowComponent ignored"); else if (d->newWindowComponent && d->newWindowParent) { KDeclarativeWebView* webview = 0; QDeclarativeContext* windowContext = new QDeclarativeContext(qmlContext(this)); QObject* newObject = d->newWindowComponent->create(windowContext); if (newObject) { windowContext->setParent(newObject); QDeclarativeItem* item = qobject_cast(newObject); if (!item) delete newObject; else { webview = item->findChild(); if (!webview) delete item; else { newObject->setParent(d->newWindowParent); static_cast(item)->setParentItem(d->newWindowParent); } } } else delete windowContext; return webview; } } break; case QWebPage::WebModalDialog: { // Not supported } } return 0; } /*! \qmlproperty component WebView::newWindowComponent This property holds the component to use for new windows. The component must have a WebView somewhere in its structure. When the web engine requests a new window, it will be an instance of this component. The parent of the new window is set by newWindowParent. It must be set. */ QDeclarativeComponent* KDeclarativeWebView::newWindowComponent() const { return d->newWindowComponent; } void KDeclarativeWebView::setNewWindowComponent(QDeclarativeComponent* newWindow) { if (newWindow == d->newWindowComponent) return; d->newWindowComponent = newWindow; emit newWindowComponentChanged(); } /*! \qmlproperty item WebView::newWindowParent The parent item for new windows. \sa newWindowComponent */ QDeclarativeItem* KDeclarativeWebView::newWindowParent() const { return d->newWindowParent; } void KDeclarativeWebView::setNewWindowParent(QDeclarativeItem* parent) { if (parent == d->newWindowParent) return; if (d->newWindowParent && parent) { QList children = d->newWindowParent->childItems(); for (int i = 0; i < children.count(); ++i) children.at(i)->setParentItem(parent); } d->newWindowParent = parent; emit newWindowParentChanged(); } QSize KDeclarativeWebView::contentsSize() const { return page()->mainFrame()->contentsSize() * contentsScale(); } qreal KDeclarativeWebView::contentsScale() const { return d->view->scale(); } void KDeclarativeWebView::setContentsScale(qreal scale) { if (scale == d->view->scale()) return; d->view->setScale(scale); updateDeclarativeWebViewSize(); emit contentsScaleChanged(); } /*! Returns the area of the largest element at position (\a x,\a y) that is no larger than \a maxWidth by \a maxHeight pixels. May return an area larger in the case when no smaller element is at the position. */ QRect KDeclarativeWebView::elementAreaAt(int x, int y, int maxWidth, int maxHeight) const { QWebHitTestResult hit = page()->mainFrame()->hitTestContent(QPoint(x, y)); QRect hitRect = hit.boundingRect(); QWebElement element = hit.enclosingBlockElement(); if (maxWidth <= 0) maxWidth = INT_MAX; if (maxHeight <= 0) maxHeight = INT_MAX; while (!element.parent().isNull() && element.geometry().width() <= maxWidth && element.geometry().height() <= maxHeight) { hitRect = element.geometry(); element = element.parent(); } return hitRect; } /*! \internal \class QDeclarativeWebPage \brief The QDeclarativeWebPage class is a QWebPage that can create QML plugins. \sa KDeclarativeWebView */ QDeclarativeWebPage::QDeclarativeWebPage(KDeclarativeWebView* parent) : KWebPage(parent, KWalletIntegration) { - connect(this, SIGNAL(unsupportedContent(QNetworkReply *)), this, SLOT(handleUnsupportedContent(QNetworkReply *))); + connect(this, SIGNAL(unsupportedContent(QNetworkReply*)), this, SLOT(handleUnsupportedContent(QNetworkReply*))); // //TODO: move this in the webbrowser implementation m_nepomukHelper = new NepomukHelper(this); } QDeclarativeWebPage::~QDeclarativeWebPage() { } QString QDeclarativeWebPage::chooseFile(QWebFrame* originatingFrame, const QString& oldFile) { Q_UNUSED(originatingFrame) Q_UNUSED(oldFile) return KFileDialog::getOpenFileName(); } /*! \qmlsignal WebView::onAlert(string message) The handler is called when the web engine sends a JavaScript alert. The \a message is the text to be displayed in the alert to the user. */ void QDeclarativeWebPage::javaScriptAlert(QWebFrame* originatingFrame, const QString& msg) { // FIXME: implement alert Q_UNUSED(originatingFrame) emit viewItem()->alert(msg); } bool QDeclarativeWebPage::javaScriptConfirm(QWebFrame* originatingFrame, const QString& msg) { // FIXME: Not supported (it's modal) Q_UNUSED(originatingFrame) Q_UNUSED(msg) return false; } bool QDeclarativeWebPage::javaScriptPrompt(QWebFrame* originatingFrame, const QString& msg, const QString& defaultValue, QString* result) { // FIXME: Not supported (it's modal) Q_UNUSED(originatingFrame) Q_UNUSED(msg) Q_UNUSED(defaultValue) Q_UNUSED(result) return false; } KDeclarativeWebView* QDeclarativeWebPage::viewItem() { return static_cast(parent()); } QWebPage* QDeclarativeWebPage::createWindow(WebWindowType type) { KDeclarativeWebView* newView = viewItem()->createWindow(type); if (newView) return newView->page(); return 0; } void QDeclarativeWebPage::handleUnsupportedContent(QNetworkReply *reply) { if (!reply) { return; } QUrl replyUrl = reply->url(); if (replyUrl.scheme() == QLatin1String("abp")) return; if (reply->error() == QNetworkReply::NoError && reply->header(QNetworkRequest::ContentTypeHeader).isValid()) { downloadUrl(replyUrl); } } bool QDeclarativeWebPage::downloadResource (const KUrl& srcUrl, const QString& suggestedName, QWidget* parent, const KIO::MetaData& metaData) { const QString fileName ((suggestedName.isEmpty() ? srcUrl.fileName() : suggestedName)); const KUrl &destUrl(QString("file://%1/%2").arg(QDir::homePath()).arg(fileName)); if (!destUrl.isValid()) { return false; } KIO::CopyJob *job = KIO::copy(srcUrl, destUrl); if (!metaData.isEmpty()) { job->setMetaData(metaData); } job->setAutoRename(true); job->addMetaData(QLatin1String("MaxCacheSize"), QLatin1String("0")); // Don't store in http cache. job->addMetaData(QLatin1String("cache"), QLatin1String("cache")); // Use entry from cache if available. job->ui()->setWindow((parent ? parent->window() : 0)); job->ui()->setAutoErrorHandlingEnabled(true); - connect(job, SIGNAL(result(KJob *)), this, SLOT(downloadFinished(KJob *))); + connect(job, SIGNAL(result(KJob*)), this, SLOT(downloadFinished(KJob*))); return true; } void QDeclarativeWebPage::downloadFinished(KJob *job) { KIO::CopyJob *cj = qobject_cast(job); if (cj && job->error() == KJob::NoError) { KUrl localUrl = cj->destUrl(); KUrl remoteUrl; foreach (const KUrl &_u, cj->srcUrls()) { remoteUrl = _u; } // add file to current activity, store remote url as metadata m_nepomukHelper->storeDownloadMetaData(remoteUrl, localUrl); } else { // TODO: handle download errors. kError() << "Error downloading file: " << job->errorString(); } } void QDeclarativeWebPage::downloadRequest(const QNetworkRequest &request) { downloadResource(request.url(), QString(), view(), request.attribute(static_cast(KIO::AccessManager::MetaData)).toMap()); } void QDeclarativeWebPage::downloadUrl(const KUrl &url) { downloadResource(url, QString(), view()); } #include "errorhandling.cpp" QT_END_NAMESPACE diff --git a/applications/webbrowser/src/view.cpp b/applications/webbrowser/src/view.cpp index 3a5f87e7..33d4ec98 100644 --- a/applications/webbrowser/src/view.cpp +++ b/applications/webbrowser/src/view.cpp @@ -1,227 +1,227 @@ /*************************************************************************** * * * Copyright 2011 Sebastian Kügler * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "view.h" #include "kdeclarativewebview.h" #include "completionmodel.h" #include "history.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Plasma/Package" #include View::View(const QString &url, QWidget *parent) : QDeclarativeView(parent), m_options(new WebsiteOptions), m_webBrowser(0), m_urlInput(0), m_useGL(false), m_completionModel(new CompletionModel(this)) { // avoid flicker on show setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_NoSystemBackground); viewport()->setAttribute(Qt::WA_OpaquePaintEvent); viewport()->setAttribute(Qt::WA_NoSystemBackground); setResizeMode(QDeclarativeView::SizeRootObjectToView); KDeclarative kdeclarative; kdeclarative.setDeclarativeEngine(engine()); kdeclarative.initialize(); //binds things like kconfig and icons kdeclarative.setupBindings(); // Filter the supplied argument through KUriFilter and then // make the resulting url known to the webbrowser component // as startupArguments property if (url.isEmpty()) { m_completionModel->populate(); } QVariant a = QVariant(QStringList(filterUrl(url))); rootContext()->setContextProperty("startupArguments", a); rootContext()->setContextProperty("bookmarksModel", QVariant::fromValue(m_completionModel->filteredBookmarks())); rootContext()->setContextProperty("historyModel", QVariant::fromValue(m_completionModel->filteredHistory())); // Locate the webbrowser QML component in the package // Note that this is a bit brittle, since it relies on the package name, // but it allows us to share the same code with the pure QML plasmoid // In a later stadium, we can install the QML stuff in a different path. QString qmlFile = KGlobal::dirs()->findResource("data", "plasma/plasmoids/qtwebbrowser/contents/code/webbrowser.qml"); Plasma::PackageStructure::Ptr structure = Plasma::PackageStructure::load("Plasma/Generic"); m_package = new Plasma::Package(QString(), "org.kde.active.webbrowser", structure); //kDebug() << "Loading QML File:" << qmlFile; setSource(QUrl(m_package->filePath("mainscript"))); //kDebug() << "Plugin pathes:" << engine()->pluginPathList(); show(); rootContext()->setContextProperty("filteredUrl", QVariant(QString())); onStatusChanged(status()); //connect(engine(), SIGNAL(signalHandlerException(QScriptValue)), this, SLOT(exception())); connect(this, SIGNAL(statusChanged(QDeclarativeView::Status)), this, SLOT(onStatusChanged(QDeclarativeView::Status))); connect(m_completionModel, SIGNAL(dataChanged()), SLOT(setBookmarks())); } View::~View() { m_completionModel->history()->saveHistory(); } void View::setUseGL(const bool on) { #ifndef QT_NO_OPENGL if (on) { QGLWidget *glWidget = new QGLWidget; glWidget->setAutoFillBackground(false); setViewport(glWidget); } #endif m_useGL = on; } bool View::useGL() const { return m_useGL; } void View::setBookmarks() { QDeclarativeItem* popup = rootObject()->findChild("completionPopup"); if (popup) { //QList items = ; rootContext()->setContextProperty("bookmarksModel", QVariant::fromValue(m_completionModel->filteredBookmarks())); rootContext()->setContextProperty("historyModel", QVariant::fromValue(m_completionModel->filteredHistory())); } } void View::onStatusChanged(QDeclarativeView::Status status) { if (status == QDeclarativeView::Ready) { if (!m_webBrowser && !m_urlInput) { // Note that "webView" is defined as objectName in the QML file m_webBrowser = rootObject()->findChild("webView"); if (m_webBrowser) { connect(m_webBrowser, SIGNAL(urlChanged()), this, SLOT(urlChanged())); connect(m_webBrowser, SIGNAL(titleChanged()), this, SLOT(onTitleChanged())); connect(m_webBrowser, SIGNAL(newWindowRequested(QString)), this, SIGNAL(newWindow(QString))); } else { kError() << "webView component not found. :("; } // Note that "urlInput" is defined as objectName in the QML file m_urlInput = rootObject()->findChild("urlInput"); if (m_urlInput) { - connect(m_urlInput, SIGNAL(urlEntered(const QString&)), - this, SLOT(onUrlEntered(const QString&))); + connect(m_urlInput, SIGNAL(urlEntered(QString)), + this, SLOT(onUrlEntered(QString))); connect(m_urlInput, SIGNAL(urlFilterChanged()), this, SLOT(urlFilterChanged())); } else { kError() << "urlInput component not found."; } } } else if (status == QDeclarativeView::Error) { foreach (const QDeclarativeError &e, errors()) { kWarning() << "error in QML: " << e.toString() << e.description(); } } else if (status == QDeclarativeView::Loading) { //kDebug() << "Loading."; } } void View::urlChanged() { QString newUrl = m_webBrowser->property("url").toString(); QString newTitle = m_webBrowser->property("title").toString(); m_options->url = newUrl; } void View::urlFilterChanged() { QString newFilter = m_urlInput->property("urlFilter").toString(); //kDebug() << "Filtering completion" << newFilter; m_completionModel->populate(); m_completionModel->setFilter(newFilter); } void View::onTitleChanged() { if (m_webBrowser) { if (m_options->title == m_webBrowser->property("title").toString()) { return; } //kDebug() << "XXX title changed" << m_webBrowser->property("title").toString(); m_options->title = m_webBrowser->property("title").toString(); QString u = m_webBrowser->property("url").toString(); m_completionModel->history()->visitPage(u, m_options->title); emit titleChanged(m_options->title); // sets window caption } } QString View::filterUrl(const QString &url) { QString filteredUrl(url); if (filteredUrl.indexOf('.') < 0) { //TODO: search engine config filteredUrl = "gg:"+filteredUrl; } filteredUrl = KUriFilter::self()->filteredUri(filteredUrl); return filteredUrl; } void View::onUrlEntered(const QString &newUrl) { QString filteredUrl = filterUrl(newUrl); QDeclarativeItem *b = rootObject()->findChild("urlInput"); if (b) { //kDebug() << "setting new property: filteredUrl : " << filteredUrl; b->setProperty("filteredUrl", QVariant(filteredUrl)); } } #include "view.moc" diff --git a/components/dirmodel/dirmodel.cpp b/components/dirmodel/dirmodel.cpp index 7c832dd3..c71dac48 100644 --- a/components/dirmodel/dirmodel.cpp +++ b/components/dirmodel/dirmodel.cpp @@ -1,179 +1,179 @@ /* Copyright (C) 20111 Marco Martin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "dirmodel.h" #include #include #include #include DirModel::DirModel(QObject *parent) : KDirModel(parent), m_screenshotSize(180, 120) { KMimeType::List mimeList = KMimeType::allMimeTypes(); m_mimeTypes << "inode/directory"; foreach (KMimeType::Ptr mime, mimeList) { if (mime->name().startsWith("image/")) { m_mimeTypes << mime->name(); } } //TODO: configurable mime filter //dirLister()->setMimeFilter(m_mimeTypes); QHashroleNames; roleNames[Qt::DisplayRole] = "display"; roleNames[Qt::DecorationRole] = "decoration"; roleNames[UrlRole] = "url"; roleNames[MimeTypeRole] = "mimeType"; roleNames[Thumbnail] = "thumbnail"; setRoleNames(roleNames); m_previewTimer = new QTimer(this); m_previewTimer->setSingleShot(true); connect(m_previewTimer, SIGNAL(timeout()), this, SLOT(delayedPreview())); //using the same cache of the engine, they index both by url m_imageCache = new KImageCache("plasma_engine_preview", 10485760); - connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), + connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(countChanged())); - connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), + connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SIGNAL(countChanged())); connect(this, SIGNAL(modelReset()), this, SIGNAL(countChanged())); } DirModel::~DirModel() { } QString DirModel::url() const { return dirLister()->url().path(); } void DirModel::setUrl(const QString& url) { if (url.isEmpty()) { return; } if (dirLister()->url().path() == url) { dirLister()->updateDirectory(url); return; } dirLister()->openUrl(url); emit urlChanged(); } int DirModel::indexForUrl(const QString &url) const { QModelIndex index = KDirModel::indexForUrl(KUrl(url)); return index.row(); } QVariant DirModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } switch (role) { case UrlRole: { KFileItem item = itemForIndex(index); return item.url().prettyUrl(); } case MimeTypeRole: { KFileItem item = itemForIndex(index); return item.mimetype(); } case Thumbnail: { KFileItem item = itemForIndex(index); QImage preview = QImage(m_screenshotSize, QImage::Format_ARGB32_Premultiplied); if (m_imageCache->findImage(item.url().prettyUrl(), &preview)) { return preview; } m_previewTimer->start(100); const_cast(this)->m_filesToPreview[item.url()] = QPersistentModelIndex(index); } default: return KDirModel::data(index, role); } } void DirModel::delayedPreview() { QHash::const_iterator i = m_filesToPreview.constBegin(); KFileItemList list; while (i != m_filesToPreview.constEnd()) { KUrl file = i.key(); QPersistentModelIndex index = i.value(); if (!m_previewJobs.contains(file) && file.isValid()) { list.append(KFileItem(file, QString(), 0)); m_previewJobs.insert(file, QPersistentModelIndex(index)); } ++i; } if (list.size() > 0) { KIO::PreviewJob* job = KIO::filePreview(list, m_screenshotSize); job->setIgnoreMaximumSize(true); kDebug() << "Created job" << job; - connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)), - this, SLOT(showPreview(const KFileItem&, const QPixmap&))); - connect(job, SIGNAL(failed(const KFileItem&)), - this, SLOT(previewFailed(const KFileItem&))); + connect(job, SIGNAL(gotPreview(KFileItem,QPixmap)), + this, SLOT(showPreview(KFileItem,QPixmap))); + connect(job, SIGNAL(failed(KFileItem)), + this, SLOT(previewFailed(KFileItem))); } m_filesToPreview.clear(); } void DirModel::showPreview(const KFileItem &item, const QPixmap &preview) { QPersistentModelIndex index = m_previewJobs.value(item.url()); m_previewJobs.remove(item.url()); if (!index.isValid()) { return; } m_imageCache->insertImage(item.url().prettyUrl(), preview.toImage()); //kDebug() << "preview size:" << preview.size(); emit dataChanged(index, index); } void DirModel::previewFailed(const KFileItem &item) { m_previewJobs.remove(item.url()); } #include "dirmodel.moc" diff --git a/components/metadatamodel/abstractmetadatamodel.cpp b/components/metadatamodel/abstractmetadatamodel.cpp index baba544f..1c6098fc 100644 --- a/components/metadatamodel/abstractmetadatamodel.cpp +++ b/components/metadatamodel/abstractmetadatamodel.cpp @@ -1,382 +1,382 @@ /* Copyright 2011 Marco Martin 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. */ #include "abstractmetadatamodel.h" #include #include #include #include #include #include AbstractMetadataModel::AbstractMetadataModel(QObject *parent) : QAbstractItemModel(parent), m_status(Idle), m_minimumRating(0), m_maximumRating(0) { // Add fallback icons here from generic to specific // The list of types is also sorted in this way, so // we're returning the most specific icon, even with // the hardcoded mapping. // Files //m_icons["FileDataObject"] = QString("audio-x-generic"); // Audio m_icons["Audio"] = QString("audio-x-generic"); m_icons["MusicPiece"] = QString("audio-x-generic"); // Images m_icons["Image"] = QString("image-x-generic"); m_icons["RasterImage"] = QString("image-x-generic"); m_icons["Email"] = QString("internet-mail"); m_icons["Document"] = QString("kword"); m_icons["PersonContact"] = QString("x-office-contact"); // Filesystem m_icons["Website"] = QString("text-html"); // ... add some more // Filesystem m_icons["Bookmark"] = QString("bookmarks"); m_icons["BookmarksFolder"] = QString("bookmarks-organize"); m_icons["FileDataObject"] = QString("unknown"); m_icons["TextDocument"] = QString("text-enriched"); - connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), + connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(countChanged())); - connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), + connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SIGNAL(countChanged())); connect(this, SIGNAL(modelReset()), this, SIGNAL(countChanged())); m_queryTimer = new QTimer(this); m_queryTimer->setSingleShot(true); if (Nepomuk::ResourceManager::instance()->initialized()) { connect(m_queryTimer, SIGNAL(timeout()), this, SLOT(doQuery())); } m_extraParameters = new QDeclarativePropertyMap; - connect (m_extraParameters, SIGNAL(valueChanged(QString, QVariant)), m_queryTimer, SLOT(start())); + connect (m_extraParameters, SIGNAL(valueChanged(QString,QVariant)), m_queryTimer, SLOT(start())); m_queryServiceWatcher = new QDBusServiceWatcher(QLatin1String("org.kde.nepomuk.services.nepomukqueryservice"), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration, this); connect(m_queryServiceWatcher, SIGNAL(serviceRegistered(QString)), this, SLOT(serviceRegistered(QString))); } AbstractMetadataModel::~AbstractMetadataModel() { delete m_extraParameters; } void AbstractMetadataModel::serviceRegistered(const QString &service) { if (service == QLatin1String("org.kde.nepomuk.services.nepomukqueryservice")) { disconnect(m_queryTimer, SIGNAL(timeout()), this, SLOT(doQuery())); connect(m_queryTimer, SIGNAL(timeout()), this, SLOT(doQuery())); doQuery(); } } void AbstractMetadataModel::setResourceType(const QString &type) { if (m_resourceType == type) { return; } m_resourceType = type; m_queryTimer->start(0); emit resourceTypeChanged(); } QString AbstractMetadataModel::resourceType() const { return m_resourceType; } void AbstractMetadataModel::setMimeType(const QString &type) { if (m_mimeType == type) { return; } m_mimeType = type; m_queryTimer->start(0); emit mimeTypeChanged(); } QString AbstractMetadataModel::mimeType() const { return m_mimeType; } void AbstractMetadataModel::setActivityId(const QString &activityId) { if (m_activityId == activityId) { return; } m_activityId = activityId; m_queryTimer->start(0); emit activityIdChanged(); } QString AbstractMetadataModel::activityId() const { return m_activityId; } void AbstractMetadataModel::setTags(const QVariantList &tags) { //FIXME: not exactly efficient QStringList stringList = variantToStringList(tags); if (m_tags == stringList) { return; } m_tags = stringList; m_queryTimer->start(0); emit tagsChanged(); } QVariantList AbstractMetadataModel::tags() const { return stringToVariantList(m_tags); } QStringList AbstractMetadataModel::tagStrings() const { return m_tags; } AbstractMetadataModel::Status AbstractMetadataModel::status() const { return m_status; } void AbstractMetadataModel::setStatus(AbstractMetadataModel::Status status) { if (status == m_status) { return; } m_status = status; emit statusChanged(); } void AbstractMetadataModel::askRefresh() { m_queryTimer->start(0); } void AbstractMetadataModel::setStartDateString(const QString &date) { QDate newDate = QDate::fromString(date, "yyyy-MM-dd"); if (m_startDate == newDate) { return; } m_startDate = newDate; m_queryTimer->start(0); emit startDateChanged(); } QString AbstractMetadataModel::startDateString() const { return m_startDate.toString("yyyy-MM-dd"); } void AbstractMetadataModel::setEndDateString(const QString &date) { QDate newDate = QDate::fromString(date, "yyyy-MM-dd"); if (m_endDate == newDate) { return; } m_endDate = newDate; m_queryTimer->start(0); emit endDateChanged(); } QString AbstractMetadataModel::endDateString() const { return m_endDate.toString("yyyy-MM-dd"); } void AbstractMetadataModel::setStartDate(const QDate &date) { if (m_startDate == date) { return; } m_startDate = date; m_queryTimer->start(0); emit startDateChanged(); } QDate AbstractMetadataModel::startDate() const { return m_startDate; } void AbstractMetadataModel::setEndDate(const QDate &date) { if (m_endDate == date) { return; } m_endDate = date; m_queryTimer->start(0); emit endDateChanged(); } QDate AbstractMetadataModel::endDate() const { return m_endDate; } void AbstractMetadataModel::setMinimumRating(int rating) { if (m_minimumRating == rating) { return; } m_minimumRating = rating; m_queryTimer->start(0); emit minimumRatingChanged(); } int AbstractMetadataModel::minimumRating() const { return m_minimumRating; } void AbstractMetadataModel::setMaximumRating(int rating) { if (m_maximumRating == rating) { return; } m_maximumRating = rating; m_queryTimer->start(0); emit maximumRatingChanged(); } int AbstractMetadataModel::maximumRating() const { return m_maximumRating; } QObject *AbstractMetadataModel::extraParameters() const { return m_extraParameters; } void AbstractMetadataModel::doQuery() { //Abstract, implement in subclasses } QVariant AbstractMetadataModel::headerData(int section, Qt::Orientation orientation, int role) const { Q_UNUSED(section) Q_UNUSED(orientation) Q_UNUSED(role) return QVariant(); } QModelIndex AbstractMetadataModel::index(int row, int column, const QModelIndex &parent) const { if (parent.isValid() || column != 0 || row < 0 || row >= rowCount()) { return QModelIndex(); } return createIndex(row, column, 0); } QModelIndex AbstractMetadataModel::parent(const QModelIndex &child) const { Q_UNUSED(child) return QModelIndex(); } int AbstractMetadataModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return count(); } int AbstractMetadataModel::columnCount(const QModelIndex &parent) const { //no trees if (parent.isValid()) { return 0; } return 1; } QString AbstractMetadataModel::retrieveIconName(const QStringList &types) const { // keep searching until the most specific icon is found QString _icon = "nepomuk"; foreach(const QString &t, types) { QString shortType = t.split('#').last(); if (shortType.isEmpty()) { shortType = t; } if (m_icons.keys().contains(shortType)) { _icon = m_icons[shortType]; //kDebug() << "found icon for type" << shortType << _icon; } } return _icon; } #include "abstractmetadatamodel.moc" diff --git a/components/metadatamodel/metadatacloudmodel.cpp b/components/metadatamodel/metadatacloudmodel.cpp index 56323523..ce0b7446 100644 --- a/components/metadatamodel/metadatacloudmodel.cpp +++ b/components/metadatamodel/metadatacloudmodel.cpp @@ -1,361 +1,361 @@ /* Copyright 2011 Marco Martin 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. */ #include "metadatacloudmodel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MetadataCloudModel::MetadataCloudModel(QObject *parent) : AbstractMetadataModel(parent), m_queryClient(0) { QHash roleNames; roleNames[Label] = "label"; roleNames[Count] = "count"; setRoleNames(roleNames); } MetadataCloudModel::~MetadataCloudModel() { } void MetadataCloudModel::setCloudCategory(QString category) { if (m_cloudCategory == category) { return; } m_cloudCategory = category; askRefresh(); emit cloudCategoryChanged(); } QString MetadataCloudModel::cloudCategory() const { return m_cloudCategory; } QVariantList MetadataCloudModel::categories() const { return m_categories; } void MetadataCloudModel::setAllowedCategories(const QVariantList &whitelist) { QSet set = variantToStringList(whitelist).toSet(); if (set == m_allowedCategories) { return; } m_allowedCategories = set; emit allowedCategoriesChanged(); } QVariantList MetadataCloudModel::allowedCategories() const { return stringToVariantList(m_allowedCategories.values()); } void MetadataCloudModel::doQuery() { QDeclarativePropertyMap *parameters = qobject_cast(extraParameters()); //check if really all properties to build the query are null if (m_cloudCategory.isEmpty()) { return; } setStatus(Waiting); QString query = "select distinct ?label count(*) as ?count where { "; if (m_cloudCategory == "kao:Activity") { query += " ?activity nao:isRelated ?r . ?activity rdf:type kao:Activity . ?activity kao:activityIdentifier ?label "; } else { query += " ?r " + m_cloudCategory + " ?label"; } if (!resourceType().isEmpty()) { QString type = resourceType(); bool negation = false; if (type.startsWith('!')) { type = type.remove(0, 1); negation = true; } if (negation) { query += " . FILTER(!bif:exists((select (1) where { ?r rdf:type " + type + " . }))) "; } else { query += " . ?r rdf:type " + type; } if (type != "nfo:Bookmark") { //FIXME: remove bookmarks if not explicitly asked for query += " . FILTER(!bif:exists((select (1) where { ?r a . }))) "; } } if (!mimeType().isEmpty()) { QString type = mimeType(); bool negation = false; if (type.startsWith('!')) { type = type.remove(0, 1); negation = true; } if (negation) { query += " . FILTER(!bif:exists((select (1) where { ?r nie:mimeType ?mimeType . FILTER(bif:contains(?mimeType, \"'" + type + "'\")) . }))) "; } else { query += " . ?r nie:mimeType ?mimeType . FILTER(bif:contains(?mimeType, \"'" + type + "'\")) "; } } if (parameters && parameters->size() > 0) { foreach (const QString &key, parameters->keys()) { QString parameter = parameters->value(key).toString(); bool negation = false; if (parameter.startsWith('!')) { parameter = parameter.remove(0, 1); negation = true; } if (negation) { query += " . FILTER(!bif:exists((select (1) where { ?r " + key + " ?mimeType . FILTER(bif:contains(?mimeType, \"'" + parameter + "'\")) . }))) "; } else { query += " . ?r " + key + " ?mimeType . FILTER(bif:contains(?mimeType, \"'" + parameter + "'\")) "; } } } if (!activityId().isEmpty()) { QString activity = activityId(); bool negation = false; if (activity.startsWith('!')) { activity = activity.remove(0, 1); negation = true; } Nepomuk::Resource acRes(activity, Nepomuk::Vocabulary::KAO::Activity()); if (negation) { query += ". FILTER(!bif:exists((select (1) where { <" + acRes.resourceUri().toString() + "> ?r . }))) "; } else { query += " . <" + acRes.resourceUri().toString() + "> nao:isRelated ?r "; } } //this is an AND set of tags.. should be allowed OR as well? foreach (const QString &tag, tagStrings()) { QString individualTag = tag; bool negation = false; if (individualTag.startsWith('!')) { individualTag = individualTag.remove(0, 1); negation = true; } if (negation) { query += ". FILTER(!bif:exists((select (1) where { ?r nao:hasTag ?tagSet \ . ?tagSet ?tagLabel ?tag \ . ?tagLabel \ . FILTER(bif:contains(?tag, \"'"+individualTag+"'\"))}))) "; } else { query += ". ?r nao:hasTag ?tagSet \ . ?tagSet ?tagLabel ?tag \ . ?tagLabel \ . FILTER(bif:contains(?tag, \"'"+individualTag+"'\")) "; } } if (startDate().isValid() || endDate().isValid()) { if (startDate().isValid()) { query += " . { \ ?r ?v2 . FILTER(?v2>\"" + startDate().toString(Qt::ISODate) + "\"^^) . \ } UNION {\ ?r ?v3 . FILTER(?v3>\"" + startDate().toString(Qt::ISODate) + "\"^^) . \ } UNION {\ ?v4 ?r .\ ?v4 ?v5 .\ FILTER(?v5>\"" + startDate().toString(Qt::ISODate) + "\"^^) . \ }"; } if (endDate().isValid()) { query += " . { \ ?r ?v2 . FILTER(?v2<\"" + endDate().toString(Qt::ISODate) + "\"^^) . \ } UNION {\ ?r ?v3 . FILTER(?v3<\"" + endDate().toString(Qt::ISODate) + "\"^^) . \ } UNION {\ ?v4 ?r .\ ?v4 ?v5 .\ FILTER(?v5<\"" + endDate().toString(Qt::ISODate) + "\"^^) . \ }"; } } if (minimumRating() > 0) { query += " . ?r nao:numericRating ?rating filter (?rating >=" + QString::number(minimumRating()) + ") "; } if (maximumRating() > 0) { query += " . ?r nao:numericRating ?rating filter (?rating <=" + QString::number(maximumRating()) + ") "; } //Exclude who doesn't have url query += " . FILTER(bif:exists((select (1) where { ?r nie:url ?h . }))) "; query += " . ?r ?v1 . FILTER(?v1>0) . } group by ?label order by ?label"; kDebug() << "Performing the Sparql query" << query; beginResetModel(); m_results.clear(); endResetModel(); emit countChanged(); delete m_queryClient; m_queryClient = new Nepomuk::Query::QueryServiceClient(this); - connect(m_queryClient, SIGNAL(newEntries(const QList &)), - this, SLOT(newEntries(const QList &))); - connect(m_queryClient, SIGNAL(entriesRemoved(const QList &)), - this, SLOT(entriesRemoved(const QList &))); + connect(m_queryClient, SIGNAL(newEntries(QList)), + this, SLOT(newEntries(QList))); + connect(m_queryClient, SIGNAL(entriesRemoved(QList)), + this, SLOT(entriesRemoved(QList))); connect(m_queryClient, SIGNAL(finishedListing()), this, SLOT(finishedListing())); m_queryClient->sparqlQuery(query); } void MetadataCloudModel::newEntries(const QList< Nepomuk::Query::Result > &entries) { setStatus(Running); QVector > results; QVariantList categories; foreach (const Nepomuk::Query::Result &res, entries) { QString label; int count = res.additionalBinding(QLatin1String("count")).variant().toInt(); QVariant rawLabel = res.additionalBinding(QLatin1String("label")).variant(); if (rawLabel.canConvert()) { label = rawLabel.value().className(); } else if (!rawLabel.value().scheme().isEmpty()) { const QUrl url = rawLabel.value(); if (url.scheme() == "nepomuk") { label = Nepomuk::Resource(url).genericLabel(); //TODO: it should convert from ontology url to short form nfo:Document } else { label = propertyShortName(url); } } else if (rawLabel.canConvert()) { label = rawLabel.toString(); } else if (rawLabel.canConvert()) { label = QString::number(rawLabel.toInt()); } else { continue; } if (label.isEmpty() || !(m_allowedCategories.isEmpty() || m_allowedCategories.contains(label))) { continue; } results << QPair(label, count); categories << label; } if (results.count() > 0) { beginInsertRows(QModelIndex(), m_results.count(), m_results.count()+results.count()-1); m_results << results; m_categories << categories; endInsertRows(); emit countChanged(); emit categoriesChanged(); } } void MetadataCloudModel::entriesRemoved(const QList &urls) { //FIXME: optimize kDebug()<= 0) { beginRemoveRows(QModelIndex(), index, index); m_results.remove(index); endRemoveRows(); } } emit countChanged(); } void MetadataCloudModel::finishedListing() { setStatus(Idle); } QVariant MetadataCloudModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.column() != 0 || index.row() < 0 || index.row() >= m_results.count()){ return QVariant(); } const QPair row = m_results[index.row()]; switch (role) { case Label: return row.first; case Count: return row.second; default: return QVariant(); } } #include "metadatacloudmodel.moc" diff --git a/components/metadatamodel/metadatamodel.cpp b/components/metadatamodel/metadatamodel.cpp index f04fded6..f8425752 100644 --- a/components/metadatamodel/metadatamodel.cpp +++ b/components/metadatamodel/metadatamodel.cpp @@ -1,910 +1,910 @@ /* Copyright 2011 Marco Martin 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. */ #include "metadatamodel.h" #include "resourcewatcher.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kao.h" using namespace Nepomuk::Vocabulary; using namespace Soprano::Vocabulary; MetadataModel::MetadataModel(QObject *parent) : AbstractMetadataModel(parent), m_runningClients(0), m_countQueryClient(0), m_limit(0), m_pageSize(30), m_scoreResources(false), m_thumbnailSize(180, 120), m_thumbnailerPlugins(new QStringList(KIO::PreviewJob::availablePlugins())) { m_newEntriesTimer = new QTimer(this); m_newEntriesTimer->setSingleShot(true); connect(m_newEntriesTimer, SIGNAL(timeout()), this, SLOT(newEntriesDelayed())); m_previewTimer = new QTimer(this); m_previewTimer->setSingleShot(true); connect(m_previewTimer, SIGNAL(timeout()), this, SLOT(delayedPreview())); //using the same cache of the engine, they index both by url m_imageCache = new KImageCache("plasma_engine_preview", 10485760); m_watcher = new Nepomuk::ResourceWatcher(this); m_watcher->addProperty(NAO::numericRating()); - connect(m_watcher, SIGNAL(propertyAdded(Nepomuk::Resource, Nepomuk::Types::Property, QVariant)), - this, SLOT(propertyChanged(Nepomuk::Resource, Nepomuk::Types::Property, QVariant))); + connect(m_watcher, SIGNAL(propertyAdded(Nepomuk::Resource,Nepomuk::Types::Property,QVariant)), + this, SLOT(propertyChanged(Nepomuk::Resource,Nepomuk::Types::Property,QVariant))); QHash roleNames; roleNames[Qt::DisplayRole] = "display"; roleNames[Qt::DecorationRole] = "decoration"; roleNames[Label] = "label"; roleNames[Description] = "description"; roleNames[Types] = "types"; roleNames[ClassName] = "className"; roleNames[GenericClassName] = "genericClassName"; roleNames[HasSymbol] = "hasSymbol"; roleNames[Icon] = "icon"; roleNames[Thumbnail] = "thumbnail"; roleNames[IsFile] = "isFile"; roleNames[Exists] = "exists"; roleNames[Rating] = "rating"; roleNames[NumericRating] = "numericRating"; roleNames[Symbols] = "symbols"; roleNames[ResourceUri] = "resourceUri"; roleNames[ResourceType] = "resourceType"; roleNames[MimeType] = "mimeType"; roleNames[Url] = "url"; roleNames[Topics] = "topics"; roleNames[TopicsNames] = "topicsNames"; roleNames[Tags] = "tags"; roleNames[TagsNames] = "tagsNames"; setRoleNames(roleNames); } MetadataModel::~MetadataModel() { delete m_imageCache; } void MetadataModel::setQuery(const Nepomuk::Query::Query &query) { m_query = query; if (Nepomuk::Query::QueryServiceClient::serviceAvailable()) { askRefresh(); } } Nepomuk::Query::Query MetadataModel::query() const { return m_query; } void MetadataModel::setQueryString(const QString &query) { if (query == m_queryString || query == "nepomuk") { return; } m_queryString = query; askRefresh(); emit queryStringChanged(); } QString MetadataModel::queryString() const { return m_queryString; } void MetadataModel::setLimit(int limit) { if (limit == m_limit) { return; } m_limit = limit; askRefresh(); emit limitChanged(); } int MetadataModel::limit() const { return m_limit; } void MetadataModel::setScoreResources(bool score) { if (m_scoreResources == score) { return; } m_scoreResources = score; askRefresh(); emit scoreResourcesChanged(); } bool MetadataModel::scoreResources() const { return m_scoreResources; } void MetadataModel::setLazyLoading(bool lazy) { //lazy loading depends from the page zise, that is not directly user controllable if (lazy == (m_pageSize > 0)) { return; } //TODO: a way to control this? maybe from the available memory? m_pageSize = lazy ? 30 : -1; askRefresh(); emit lazyLoadingChanged(); } bool MetadataModel::lazyLoading() const { return (m_pageSize > 0); } void MetadataModel::setSortBy(const QVariantList &sortBy) { QStringList stringList = variantToStringList(sortBy); if (m_sortBy == stringList) { return; } m_sortBy = stringList; askRefresh(); emit sortByChanged(); } QVariantList MetadataModel::sortBy() const { return stringToVariantList(m_sortBy); } void MetadataModel::setSortOrder(Qt::SortOrder sortOrder) { if (m_sortOrder == sortOrder) { return; } m_sortOrder = sortOrder; askRefresh(); emit sortOrderChanged(); } Qt::SortOrder MetadataModel::sortOrder() const { return m_sortOrder; } int MetadataModel::find(const QString &resourceUri) { int index = -1; int i = 0; Nepomuk::Resource resToFind = Nepomuk::Resource::fromResourceUri(resourceUri); foreach (const Nepomuk::Resource &res, m_resources) { if (res == resToFind) { index = i; break; } ++i; } return index; } void MetadataModel::doQuery() { QDeclarativePropertyMap *parameters = qobject_cast(extraParameters()); //check if really all properties to build the query are null if (m_queryString.isEmpty() && resourceType().isEmpty() && mimeType().isEmpty() && activityId().isEmpty() && tagStrings().size() == 0 && !startDate().isValid() && !endDate().isValid() && minimumRating() <= 0 && maximumRating() <= 0 && parameters->size() == 0) { return; } setStatus(Waiting); m_query = Nepomuk::Query::Query(); m_query.setQueryFlags(Nepomuk::Query::Query::WithoutFullTextExcerpt); Nepomuk::Query::AndTerm rootTerm; if (!m_queryString.isEmpty()) { rootTerm.addSubTerm(Nepomuk::Query::QueryParser::parseQuery(m_queryString).term()); } if (!resourceType().isEmpty()) { //FIXME: more elegant QString type = resourceType(); bool negation = false; if (type.startsWith('!')) { type = type.remove(0, 1); negation = true; } if (negation) { rootTerm.addSubTerm(Nepomuk::Query::NegationTerm::negateTerm(Nepomuk::Query::ResourceTypeTerm(propertyUrl(type)))); } else { rootTerm.addSubTerm(Nepomuk::Query::ResourceTypeTerm(propertyUrl(type))); if (type != "nfo:Bookmark") { //FIXME: remove bookmarks if not explicitly asked for rootTerm.addSubTerm(Nepomuk::Query::NegationTerm::negateTerm(Nepomuk::Query::ResourceTypeTerm(propertyUrl("nfo:Bookmark")))); } } } if (!mimeType().isEmpty()) { QString type = mimeType(); bool negation = false; if (type.startsWith('!')) { type = type.remove(0, 1); negation = true; } Nepomuk::Query::ComparisonTerm term(Nepomuk::Vocabulary::NIE::mimeType(), Nepomuk::Query::LiteralTerm(type)); if (negation) { rootTerm.addSubTerm(Nepomuk::Query::NegationTerm::negateTerm(term)); } else { rootTerm.addSubTerm(term); } } if (parameters && parameters->size() > 0) { foreach (const QString &key, parameters->keys()) { QString parameter = parameters->value(key).toString(); bool negation = false; if (parameter.startsWith('!')) { parameter = parameter.remove(0, 1); negation = true; } //FIXME: Contains should work, but doesn't match for file names Nepomuk::Query::ComparisonTerm term(propertyUrl(key), Nepomuk::Query::LiteralTerm(parameter)); if (negation) { rootTerm.addSubTerm(Nepomuk::Query::NegationTerm::negateTerm(term)); } else { rootTerm.addSubTerm(term); } } } if (!activityId().isEmpty()) { QString activity = activityId(); bool negation = false; if (activity.startsWith('!')) { activity = activity.remove(0, 1); negation = true; } kDebug() << "Asking for resources of activity" << activityId(); Nepomuk::Resource acRes(activity, Nepomuk::Vocabulary::KAO::Activity()); Nepomuk::Query::ComparisonTerm term(Soprano::Vocabulary::NAO::isRelated(), Nepomuk::Query::ResourceTerm(acRes)); term.setInverted(true); if (negation) { rootTerm.addSubTerm(Nepomuk::Query::NegationTerm::negateTerm(term)); } else { rootTerm.addSubTerm(term); } } foreach (const QString &tag, tagStrings()) { QString individualTag = tag; bool negation = false; if (individualTag.startsWith('!')) { individualTag = individualTag.remove(0, 1); negation = true; } Nepomuk::Query::ComparisonTerm term( Soprano::Vocabulary::NAO::hasTag(), Nepomuk::Query::ResourceTerm(Nepomuk::Tag(individualTag))); if (negation) { rootTerm.addSubTerm(Nepomuk::Query::NegationTerm::negateTerm(term)); } else { rootTerm.addSubTerm(term); } } if (startDate().isValid() || endDate().isValid()) { rootTerm.addSubTerm(Nepomuk::Query::dateRangeQuery(startDate(), endDate()).term()); } if (minimumRating() > 0) { const Nepomuk::Query::LiteralTerm ratingTerm(minimumRating()); Nepomuk::Query::ComparisonTerm term = Nepomuk::Types::Property(propertyUrl("nao:numericRating")) > ratingTerm; rootTerm.addSubTerm(term); } if (maximumRating() > 0) { const Nepomuk::Query::LiteralTerm ratingTerm(maximumRating()); Nepomuk::Query::ComparisonTerm term = Nepomuk::Types::Property(propertyUrl("nao:numericRating")) < ratingTerm; rootTerm.addSubTerm(term); } if (m_scoreResources) { QString activity = activityId(); if (activity.startsWith('!')) { activity = activity.remove(0, 1); } Nepomuk::Query::ComparisonTerm term = Nepomuk::Query::ComparisonTerm(propertyUrl("kao:targettedResource"), Nepomuk::Query::Term()); term.setVariableName("c"); term.setInverted(true); Nepomuk::Query::AndTerm andTerm = Nepomuk::Query::AndTerm(); Nepomuk::Query::ResourceTypeTerm typeTerm(KAO::ResourceScoreCache()); andTerm.addSubTerm(typeTerm); if (!activity.isEmpty()) { Nepomuk::Query::ComparisonTerm usedActivityTerm(propertyUrl("kao:usedActivity"), Nepomuk::Query::ResourceTerm(Nepomuk::Resource(activity, Nepomuk::Vocabulary::KAO::Activity())) ); andTerm.addSubTerm(usedActivityTerm); } Nepomuk::Query::ComparisonTerm cachedScoreTerm(propertyUrl("kao:cachedScore"), Nepomuk::Query::Term()); cachedScoreTerm.setVariableName("score"); cachedScoreTerm.setSortWeight(1, Qt::DescendingOrder); andTerm.addSubTerm(cachedScoreTerm); term.setSubTerm(andTerm); rootTerm.addSubTerm(term); } //bind directly some properties, to avoid calling hyper inefficient resource::property { m_query.addRequestProperty(Nepomuk::Query::Query::RequestProperty(NIE::url())); m_query.addRequestProperty(Nepomuk::Query::Query::RequestProperty(NAO::hasSymbol())); m_query.addRequestProperty(Nepomuk::Query::Query::RequestProperty(NIE::mimeType())); m_query.addRequestProperty(Nepomuk::Query::Query::RequestProperty(NAO::description())); m_query.addRequestProperty(Nepomuk::Query::Query::RequestProperty(Xesam::description())); m_query.addRequestProperty(Nepomuk::Query::Query::RequestProperty(RDFS::comment())); } int weight = m_sortBy.length() + 1; foreach (const QString &sortProperty, m_sortBy) { Nepomuk::Query::ComparisonTerm sortTerm(propertyUrl(sortProperty), Nepomuk::Query::Term()); sortTerm.setSortWeight(weight, m_sortOrder); rootTerm.addSubTerm(sortTerm); --weight; } m_query.setTerm(rootTerm); kDebug()<<"Sparql query:"< &)), - this, SLOT(countQueryResult(const QList &))); + connect(m_countQueryClient, SIGNAL(newEntries(QList)), + this, SLOT(countQueryResult(QList))); if (m_limit > 0) { m_query.setLimit(m_limit); } m_countQueryClient->sparqlQuery(m_query.toSparqlQuery(Nepomuk::Query::Query::CreateCountQuery)); //if page size is invalid, fetch all if (m_pageSize < 1) { fetchResultsPage(0); } } void MetadataModel::fetchResultsPage(int page) { Nepomuk::Query::QueryServiceClient *client = new Nepomuk::Query::QueryServiceClient(this); m_queryClients[page] = client; m_pagesForClient[client] = page; m_validIndexForPage[page] = 0; Nepomuk::Query::Query pageQuery(m_query); if (m_pageSize > 0) { pageQuery.setOffset(m_pageSize*page); pageQuery.setLimit(m_pageSize); } client->query(pageQuery); - connect(client, SIGNAL(newEntries(const QList &)), - this, SLOT(newEntries(const QList &))); - connect(client, SIGNAL(entriesRemoved(const QList &)), - this, SLOT(entriesRemoved(const QList &))); + connect(client, SIGNAL(newEntries(QList)), + this, SLOT(newEntries(QList))); + connect(client, SIGNAL(entriesRemoved(QList)), + this, SLOT(entriesRemoved(QList))); connect(client, SIGNAL(finishedListing()), this, SLOT(finishedListing())); m_queryClientsHistory << client; ++m_runningClients; } void MetadataModel::countQueryResult(const QList< Nepomuk::Query::Result > &entries) { setStatus(Running); //this should be always 1 foreach (const Nepomuk::Query::Result &res, entries) { int count = res.additionalBinding(QLatin1String("cnt")).variant().toInt(); if (count < m_resources.size()) { beginRemoveRows(QModelIndex(), count-1, m_resources.size()-1); m_resources.resize(count); endRemoveRows(); } else if (count > m_resources.size()) { beginInsertRows(QModelIndex(), m_resources.size(), count-1); m_resources.resize(count); endInsertRows(); } } } void MetadataModel::newEntries(const QList< Nepomuk::Query::Result > &entries) { setStatus(Running); const int page = m_pagesForClient.value(qobject_cast(sender())); foreach (const Nepomuk::Query::Result &res, entries) { //kDebug() << "Result!!!" << res.resource().genericLabel() << res.resource().type(); //kDebug() << "Result label:" << res.genericLabel(); Nepomuk::Resource resource = res.resource(); if (res.requestProperties().value(propertyUrl("nie:url")).toString().isEmpty()) { continue; } m_resourcesToInsert[page] << resource; //pre-popuplating of the cache to avoid accessing properties directly //label is a bit too complex to take from query m_cachedResources[resource][Label] = resource.genericLabel(); QString description = res.requestProperties().value(NAO::description()).toString(); if (description.isEmpty()) { description = res.requestProperties().value(Xesam::description()).toString(); } if (description.isEmpty()) { description = res.requestProperties().value(RDFS::comment()).toString(); } if (!description.isEmpty()) { m_cachedResources[resource][Description] = description; } m_cachedResources[resource][Url] = res.requestProperties().value(propertyUrl("nie:url")).toString(); QStringList types; foreach (const QUrl &u, resource.types()) { types << u.toString(); } m_cachedResources[resource][Types] = types; Soprano::Node symbol = res.requestProperties().value(NAO::hasSymbol()); if (!symbol.toString().isEmpty()) { m_cachedResources[resource][Icon] = symbol.toString(); } else { m_cachedResources[resource][Icon] = KMimeType::iconNameForUrl(m_cachedResources[resource][Url].toString()); } //those seems to not be possible avoiding to access the resource m_cachedResources[resource][ClassName] = resource.className(); m_cachedResources[resource][ResourceType] = resource.resourceType(); m_cachedResources[resource][IsFile] = resource.isFile(); m_cachedResources[resource][HasSymbol] = res.requestProperties().value(NAO::hasSymbol()).toString(); m_cachedResources[resource][MimeType] = res.requestProperties().value(NIE::mimeType()).toString(); //FIXME: The most complicated of all, this should really be simplified { //FIXME: a more elegant way is needed QString genericClassName = m_cachedResources.value(resource).value(ClassName).toString(); //FIXME: most bookmarks are Document too, so Bookmark wins if (m_cachedResources.value(resource).value(Label).value >().contains(NFO::Bookmark())) { m_cachedResources[resource][GenericClassName] = "Bookmark"; } else { Nepomuk::Types::Class resClass(resource.resourceType()); foreach (const Nepomuk::Types::Class &parentClass, resClass.parentClasses()) { const QString label = parentClass.label(); if (label == "Document" || label == "Audio" || label == "Video" || label == "Image" || label == "Contact") { genericClassName = label; break; //two cases where the class is 2 levels behind the level of generalization we want } else if (parentClass.label() == "RasterImage") { genericClassName = "Image"; } else if (parentClass.label() == "TextDocument") { genericClassName = "Document"; } } m_cachedResources[resource][GenericClassName] = genericClassName; } } } if (!m_newEntriesTimer->isActive() && !m_resourcesToInsert[page].isEmpty()) { m_newEntriesTimer->start(200); } } void MetadataModel::newEntriesDelayed() { if (m_resourcesToInsert.isEmpty()) { return; } m_elapsedTime.start(); QHash >::const_iterator i; for (i = m_resourcesToInsert.constBegin(); i != m_resourcesToInsert.constEnd(); ++i) { const QList resourcesToInsert = i.value(); m_watcher->stop(); int pageStart = 0; if (m_pageSize > 0) { pageStart = i.key() * m_pageSize; } int startOffset = m_validIndexForPage.value(i.key()); int offset = startOffset; //if new result arrive on an already running query, they may arrive before countQueryResult if (m_resources.size() < pageStart + startOffset + 1) { beginInsertRows(QModelIndex(), m_resources.size(), pageStart + startOffset); m_resources.resize(pageStart + startOffset + 1); endInsertRows(); } //this happens only when m_validIndexForPage has been invalidate by row removal if (!m_validIndexForPage.contains(i.key()) && m_resources[pageStart + startOffset].isValid()) { while (startOffset < m_resources.size() && m_resources[pageStart + startOffset].isValid()) { ++startOffset; ++offset; } } foreach (const Nepomuk::Resource &res, resourcesToInsert) { //kDebug() << "Result!!!" << res.genericLabel() << res.type(); //kDebug() << "Page:" << i.key() << "Index:"<< pageStart + offset; m_uriToResourceIndex[res.resourceUri()] = pageStart + offset; //there can be new results before the count query gets updated if (pageStart + offset < m_resources.size()) { m_resources[pageStart + offset] = res; m_watcher->addResource(res); ++offset; } else { beginInsertRows(QModelIndex(), m_resources.size(), pageStart + offset); m_resources.resize(pageStart + offset + 1); m_resources[pageStart + offset] = res; m_watcher->addResource(res); ++offset; endInsertRows(); } } m_validIndexForPage[i.key()] = offset; m_watcher->start(); emit dataChanged(createIndex(pageStart + startOffset, 0), createIndex(pageStart + startOffset + resourcesToInsert.count()-1, 0)); } kDebug() << "Elapsed time populating the model" << m_elapsedTime.elapsed(); m_resourcesToInsert.clear(); } void MetadataModel::propertyChanged(Nepomuk::Resource res, Nepomuk::Types::Property prop, QVariant val) { Q_UNUSED(prop) Q_UNUSED(val) const int index = m_uriToResourceIndex.value(res.resourceUri()); if (index >= 0) { emit dataChanged(createIndex(index, 0, 0), createIndex(index, 0, 0)); } } void MetadataModel::entriesRemoved(const QList &urls) { int prevIndex = -100; //pack all the stuff to remove in groups, to emit the least possible signals //this assumes urls are in the same order they arrived ion the results //it's a map because we want to remove values from the vector in inverted order to keep indexes valid trough the remove loop QMap toRemove; foreach (const QUrl &url, urls) { const int index = m_uriToResourceIndex.value(url); if (index == prevIndex + 1) { toRemove[prevIndex]++; } else { toRemove[index] = 1; } prevIndex = index; } //all the page indexes may be invalid now m_validIndexForPage.clear(); QMap::const_iterator i = toRemove.constEnd(); while (i != toRemove.constBegin()) { --i; beginRemoveRows(QModelIndex(), i.key(), i.key()+i.value()-1); m_resources.remove(i.key(), i.value()); endRemoveRows(); } //another loop, we don't depend to m_uriToResourceIndex in data(), but we take this doublesafety foreach (const QUrl &url, urls) { m_uriToResourceIndex.remove(url); } //FIXME: this loop makes all the optimizations useless, get rid either of it or the optimizations for (int i = 0; i < m_resources.count(); ++i) { m_uriToResourceIndex[m_resources[i].resourceUri()] = i; } emit countChanged(); } void MetadataModel::finishedListing() { --m_runningClients; if (m_runningClients <= 0) { setStatus(Idle); if (m_queryClientsHistory.count() > 10) { for (int i = 0; i < m_queryClientsHistory.count() - 10; ++i) { Nepomuk::Query::QueryServiceClient *client = m_queryClientsHistory.first(); m_queryClientsHistory.pop_front(); int page = m_pagesForClient.value(client); m_queryClients.remove(page); m_pagesForClient.remove(client); delete client; } } } } QVariant MetadataModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.column() != 0 || index.row() < 0 || index.row() >= m_resources.count()){ return QVariant(); } const Nepomuk::Resource &resource = m_resources[index.row()]; if (!resource.isValid() && m_pageSize > 0 && !m_queryClients.contains(floor(index.row()/m_pageSize))) { //HACK const_cast(this)->fetchResultsPage(floor(index.row()/m_pageSize)); return QVariant(); //m_pageSize <= 0, means fetch all } else if (!resource.isValid() && !m_queryClients.contains(0)) { //HACK const_cast(this)->fetchResultsPage(0); return QVariant(); } else if (!resource.isValid()) { return QVariant(); } //We're lucky: was cached if (m_cachedResources.value(resource).contains(role)) { return m_cachedResources.value(resource).value(role); } switch (role) { case Qt::DisplayRole: case Label: return m_cachedResources.value(resource).value(Label); case Qt::DecorationRole: return KIcon(m_cachedResources.value(resource).value(Icon).toString()); case HasSymbol: case Icon: return m_cachedResources.value(resource).value(Icon).toString(); case Thumbnail: { KUrl url(m_cachedResources.value(resource).value(Url).toString()); if (m_cachedResources.value(resource).value(IsFile).toBool() && url.isLocalFile()) { QImage preview = QImage(m_thumbnailSize, QImage::Format_ARGB32_Premultiplied); if (m_imageCache->findImage(url.prettyUrl(), &preview)) { return preview; } m_previewTimer->start(100); const_cast(this)->m_filesToPreview[url] = QPersistentModelIndex(index); } return QVariant(); } case Exists: return resource.exists(); case Rating: return resource.rating(); case NumericRating: return resource.property(NAO::numericRating()).toString(); case Symbols: return resource.symbols(); case ResourceUri: return resource.resourceUri(); case Topics: { QStringList topics; foreach (const Nepomuk::Resource &u, resource.topics()) { topics << u.resourceUri().toString(); } return topics; } case TopicsNames: { QStringList topicNames; foreach (const Nepomuk::Resource &u, resource.topics()) { topicNames << u.genericLabel(); } return topicNames; } case Tags: { QStringList tags; foreach (const Nepomuk::Tag &tag, resource.tags()) { tags << tag.resourceUri().toString(); } return tags; } case TagsNames: { QStringList tagNames; foreach (const Nepomuk::Tag &tag, resource.tags()) { tagNames << tag.genericLabel(); } return tagNames; } default: return QVariant(); } } void MetadataModel::delayedPreview() { QHash::const_iterator i = m_filesToPreview.constBegin(); KFileItemList list; while (i != m_filesToPreview.constEnd()) { KUrl file = i.key(); QPersistentModelIndex index = i.value(); if (!m_previewJobs.contains(file) && file.isValid()) { list.append(KFileItem(file, QString(), 0)); m_previewJobs.insert(file, QPersistentModelIndex(index)); } ++i; } if (list.size() > 0) { KIO::PreviewJob* job = KIO::filePreview(list, m_thumbnailSize, m_thumbnailerPlugins); //job->setIgnoreMaximumSize(true); kDebug() << "Created job" << job; - connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)), - this, SLOT(showPreview(const KFileItem&, const QPixmap&))); - connect(job, SIGNAL(failed(const KFileItem&)), - this, SLOT(previewFailed(const KFileItem&))); + connect(job, SIGNAL(gotPreview(KFileItem,QPixmap)), + this, SLOT(showPreview(KFileItem,QPixmap))); + connect(job, SIGNAL(failed(KFileItem)), + this, SLOT(previewFailed(KFileItem))); } m_filesToPreview.clear(); } void MetadataModel::showPreview(const KFileItem &item, const QPixmap &preview) { QPersistentModelIndex index = m_previewJobs.value(item.url()); m_previewJobs.remove(item.url()); if (!index.isValid()) { return; } m_imageCache->insertImage(item.url().prettyUrl(), preview.toImage()); //kDebug() << "preview size:" << preview.size(); emit dataChanged(index, index); } void MetadataModel::previewFailed(const KFileItem &item) { m_previewJobs.remove(item.url()); } // Just signal QSortFilterProxyModel to do the real sorting. void MetadataModel::sort(int column, Qt::SortOrder order) { Q_UNUSED(column); Q_UNUSED(order); beginResetModel(); endResetModel(); } void MetadataModel::setThumbnailSize(const QSize& size) { m_thumbnailSize = size; emit thumbnailSizeChanged(); } QSize MetadataModel::thumbnailSize() const { return m_thumbnailSize; } #include "metadatamodel.moc" diff --git a/components/metadatamodel/metadatatimelinemodel.cpp b/components/metadatamodel/metadatatimelinemodel.cpp index 643ae396..376482eb 100644 --- a/components/metadatamodel/metadatatimelinemodel.cpp +++ b/components/metadatamodel/metadatatimelinemodel.cpp @@ -1,340 +1,340 @@ /* Copyright 2011 Marco Martin 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. */ #include "metadatatimelinemodel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kao.h" MetadataTimelineModel::MetadataTimelineModel(QObject *parent) : AbstractMetadataModel(parent), m_queryClient(0), m_totalCount(0) { QHash roleNames; roleNames[LabelRole] = "label"; roleNames[YearRole] = "year"; roleNames[MonthRole] = "month"; roleNames[DayRole] = "day"; roleNames[CountRole] = "count"; setRoleNames(roleNames); askRefresh(); } MetadataTimelineModel::~MetadataTimelineModel() { } void MetadataTimelineModel::setLevel(MetadataTimelineModel::Level level) { if (m_level == level) { return; } m_level = level; askRefresh(); emit levelChanged(); } MetadataTimelineModel::Level MetadataTimelineModel::level() const { return m_level; } QString MetadataTimelineModel::description() const { if (m_results.isEmpty()) { return QString(); } //TODO: manage cases where start and enddate cover more than one year/month switch (m_level) { case Year: return i18n("All years"); case Month: return KGlobal::locale()->calendar()->yearString(startDate(), KCalendarSystem::LongFormat); case Day: default: return i18nc("Month and year, such as March 2007", "%1 %2", KGlobal::locale()->calendar()->monthName(startDate(), KCalendarSystem::LongName), KGlobal::locale()->calendar()->yearString(startDate(), KCalendarSystem::LongFormat)); } } void MetadataTimelineModel::doQuery() { QDeclarativePropertyMap *parameters = qobject_cast(extraParameters()); m_totalCount = 0; setStatus(Waiting); QString monthQuery; QString dayQuery; if (m_level >= Month) { monthQuery = "bif:month(?label)"; } else { monthQuery = '0'; } if (m_level >= Day) { dayQuery = "bif:dayofmonth(?label)"; } else { dayQuery = '0'; } QString query = QString("select distinct bif:year(?label) as ?year %1 as ?month %2 as ?day count(*) as ?count where { ?r nie:lastModified ?label ").arg(monthQuery).arg(dayQuery); if (!resourceType().isEmpty()) { QString type = resourceType(); bool negation = false; if (type.startsWith('!')) { type = type.remove(0, 1); negation = true; } if (negation) { query += " . FILTER(!bif:exists((select (1) where { ?r rdf:type " + type + " . }))) "; } else { query += " . ?r rdf:type " + type; } if (type != "nfo:Bookmark") { //FIXME: remove bookmarks if not explicitly asked for query += " . FILTER(!bif:exists((select (1) where { ?r a . }))) "; } } if (!mimeType().isEmpty()) { QString type = mimeType(); bool negation = false; if (type.startsWith('!')) { type = type.remove(0, 1); negation = true; } if (negation) { query += " . FILTER(!bif:exists((select (1) where { ?r nie:mimeType ?mimeType . FILTER(bif:contains(?mimeType, \"'" + type + "'\")) . }))) "; } else { query += " . ?r nie:mimeType ?mimeType . FILTER(bif:contains(?mimeType, \"'" + type + "'\")) "; } } if (parameters && parameters->size() > 0) { foreach (const QString &key, parameters->keys()) { QString parameter = parameters->value(key).toString(); bool negation = false; if (parameter.startsWith('!')) { parameter = parameter.remove(0, 1); negation = true; } if (negation) { query += " . FILTER(!bif:exists((select (1) where { ?r " + key + " ?mimeType . FILTER(bif:contains(?mimeType, \"'" + parameter + "'\")) . }))) "; } else { query += " . ?r " + key + " ?mimeType . FILTER(bif:contains(?mimeType, \"'" + parameter + "'\")) "; } } } if (!activityId().isEmpty()) { QString activity = activityId(); bool negation = false; if (activity.startsWith('!')) { activity = activity.remove(0, 1); negation = true; } Nepomuk::Resource acRes(activity, Nepomuk::Vocabulary::KAO::Activity()); if (negation) { query += ". FILTER(!bif:exists((select (1) where { <" + acRes.resourceUri().toString() + "> ?r . }))) "; } else { query += " . <" + acRes.resourceUri().toString() + "> nao:isRelated ?r "; } } //this is an AND set of tags.. should be allowed OR as well? foreach (const QString &tag, tagStrings()) { QString individualTag = tag; bool negation = false; if (individualTag.startsWith('!')) { individualTag = individualTag.remove(0, 1); negation = true; } if (negation) { query += ". FILTER(!bif:exists((select (1) where { ?r nao:hasTag ?tagSet \ . ?tagSet ?tagLabel ?tag \ . ?tagLabel \ . FILTER(bif:contains(?tag, \"'"+individualTag+"'\"))}))) "; } else { query += ". ?r nao:hasTag ?tagSet \ . ?tagSet ?tagLabel ?tag \ . ?tagLabel \ . FILTER(bif:contains(?tag, \"'"+individualTag+"'\")) "; } } if (startDate().isValid() || endDate().isValid()) { if (startDate().isValid()) { query += ". ?r ?v2 . FILTER(?v2>\"" + startDate().toString(Qt::ISODate) + "\"^^) "; } if (endDate().isValid()) { query += ". ?r ?v2 . FILTER(?v2<\"" + endDate().toString(Qt::ISODate) + "\"^^) "; } } if (minimumRating() > 0) { query += " . ?r nao:numericRating ?rating filter (?rating >=" + QString::number(minimumRating()) + ") "; } if (maximumRating() > 0) { query += " . ?r nao:numericRating ?rating filter (?rating <=" + QString::number(maximumRating()) + ") "; } query += " . ?r ?v1 . FILTER(?v1>0) . } "; //Group by construction query += " group by bif:year(?label) "; if (m_level >= Month) { query += " bif:month(?label) "; } if (m_level >= Day) { query += " bif:dayofmonth(?label) "; } query += " order by ?year ?month ?day "; kDebug() << "Performing the Sparql query" << query; beginResetModel(); m_results.clear(); endResetModel(); emit countChanged(); emit totalCountChanged(); emit descriptionChanged(); if (m_queryClient) { m_queryClient->close(); } delete m_queryClient; m_queryClient = new Nepomuk::Query::QueryServiceClient(this); - connect(m_queryClient, SIGNAL(newEntries(const QList &)), - this, SLOT(newEntries(const QList &))); - connect(m_queryClient, SIGNAL(entriesRemoved(const QList &)), - this, SLOT(entriesRemoved(const QList &))); + connect(m_queryClient, SIGNAL(newEntries(QList)), + this, SLOT(newEntries(QList))); + connect(m_queryClient, SIGNAL(entriesRemoved(QList)), + this, SLOT(entriesRemoved(QList))); connect(m_queryClient, SIGNAL(finishedListing()), this, SLOT(finishedListing())); m_queryClient->sparqlQuery(query); } void MetadataTimelineModel::newEntries(const QList< Nepomuk::Query::Result > &entries) { setStatus(Running); QVector > results; QVariantList categories; foreach (const Nepomuk::Query::Result &res, entries) { QString label; int count = res.additionalBinding(QLatin1String("count")).variant().toInt(); int year = res.additionalBinding(QLatin1String("year")).variant().toInt(); int month = res.additionalBinding(QLatin1String("month")).variant().toInt(); int day = res.additionalBinding(QLatin1String("day")).variant().toInt(); QHash resHash; resHash[YearRole] = year; resHash[MonthRole] = month; resHash[DayRole] = day; resHash[CountRole] = count; m_totalCount += count; results << resHash; } if (results.count() > 0) { beginInsertRows(QModelIndex(), m_results.count(), m_results.count()+results.count()); m_results << results; m_categories << categories; endInsertRows(); emit countChanged(); emit totalCountChanged(); emit descriptionChanged(); } } void MetadataTimelineModel::entriesRemoved(const QList &urls) { //FIXME: we don't have urls here return; emit countChanged(); emit totalCountChanged(); } void MetadataTimelineModel::finishedListing() { setStatus(Idle); } QVariant MetadataTimelineModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.column() != 0 || index.row() < 0 || index.row() >= m_results.count()){ return QVariant(); } const QHash row = m_results[index.row()]; if (role == LabelRole) { switch(m_level) { case Year: return row.value(YearRole); case Month: return KGlobal::locale()->calendar()->monthName(row.value(MonthRole), row.value(YearRole), KCalendarSystem::LongName); case Day: default: return row.value(DayRole); } } return row.value((Roles)role); } #include "metadatatimelinemodel.moc" diff --git a/components/metadatamodel/test/modeltest.cpp b/components/metadatamodel/test/modeltest.cpp index 0fd839c7..cc26f1ea 100644 --- a/components/metadatamodel/test/modeltest.cpp +++ b/components/metadatamodel/test/modeltest.cpp @@ -1,571 +1,571 @@ /**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "modeltest.h" #include //#undef Q_ASSERT //#define Q_ASSERT QVERIFY Q_DECLARE_METATYPE ( QModelIndex ) /*! Connect to all of the models signals. Whenever anything happens recheck everything. */ ModelTest::ModelTest ( MetadataModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false ) { Q_ASSERT ( model ); - connect ( model, SIGNAL ( columnsAboutToBeInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( columnsAboutToBeRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( columnsInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( columnsRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( dataChanged ( const QModelIndex &, const QModelIndex & ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( headerDataChanged ( Qt::Orientation, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( layoutAboutToBeChanged () ), this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( layoutChanged () ), this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( modelReset () ), this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL (columnsAboutToBeInserted(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (columnsAboutToBeRemoved(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (columnsInserted(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (columnsRemoved(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (dataChanged(QModelIndex,QModelIndex)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (headerDataChanged(Qt::Orientation,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (layoutAboutToBeChanged()), this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (layoutChanged()), this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (modelReset()), this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (rowsAboutToBeInserted(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (rowsAboutToBeRemoved(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (rowsInserted(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (rowsRemoved(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); // Special checks for inserting/removing - connect ( model, SIGNAL ( layoutAboutToBeChanged() ), - this, SLOT ( layoutAboutToBeChanged() ) ); - connect ( model, SIGNAL ( layoutChanged() ), - this, SLOT ( layoutChanged() ) ); - - connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ) ); - connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ) ); - connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsInserted ( const QModelIndex &, int, int ) ) ); - connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsRemoved ( const QModelIndex &, int, int ) ) ); + connect ( model, SIGNAL (layoutAboutToBeChanged()), + this, SLOT (layoutAboutToBeChanged()) ); + connect ( model, SIGNAL (layoutChanged()), + this, SLOT (layoutChanged()) ); + + connect ( model, SIGNAL (rowsAboutToBeInserted(QModelIndex,int,int)), + this, SLOT (rowsAboutToBeInserted(QModelIndex,int,int)) ); + connect ( model, SIGNAL (rowsAboutToBeRemoved(QModelIndex,int,int)), + this, SLOT (rowsAboutToBeRemoved(QModelIndex,int,int)) ); + connect ( model, SIGNAL (rowsInserted(QModelIndex,int,int)), + this, SLOT (rowsInserted(QModelIndex,int,int)) ); + connect ( model, SIGNAL (rowsRemoved(QModelIndex,int,int)), + this, SLOT (rowsRemoved(QModelIndex,int,int)) ); runAllTests(); } void ModelTest::setResourceType(const QString type) { model->setResourceType(type); } void ModelTest::runAllTests() { if ( fetchingMore ) return; nonDestructiveBasicTest(); rowCount(); columnCount(); hasIndex(); index(); parent(); data(); } /*! nonDestructiveBasicTest tries to call a number of the basic functions (not all) to make sure the model doesn't outright segfault, testing the functions that makes sense. */ void ModelTest::nonDestructiveBasicTest() { Q_ASSERT ( model->buddy ( QModelIndex() ) == QModelIndex() ); model->canFetchMore ( QModelIndex() ); Q_ASSERT ( model->columnCount ( QModelIndex() ) >= 0 ); Q_ASSERT ( model->data ( QModelIndex() ) == QVariant() ); fetchingMore = true; model->fetchMore ( QModelIndex() ); fetchingMore = false; Qt::ItemFlags flags = model->flags ( QModelIndex() ); Q_ASSERT ( flags == Qt::ItemIsDropEnabled || flags == 0 ); model->hasChildren ( QModelIndex() ); model->hasIndex ( 0, 0 ); model->headerData ( 0, Qt::Horizontal ); model->index ( 0, 0 ); model->itemData ( QModelIndex() ); QVariant cache; model->match ( QModelIndex(), -1, cache ); model->mimeTypes(); Q_ASSERT ( model->parent ( QModelIndex() ) == QModelIndex() ); Q_ASSERT ( model->rowCount() >= 0 ); QVariant variant; model->setData ( QModelIndex(), variant, -1 ); model->setHeaderData ( -1, Qt::Horizontal, QVariant() ); model->setHeaderData ( 999999, Qt::Horizontal, QVariant() ); QMap roles; model->sibling ( 0, 0, QModelIndex() ); model->span ( QModelIndex() ); model->supportedDropActions(); } /*! Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren() Models that are dynamically populated are not as fully tested here. */ void ModelTest::rowCount() { // qDebug() << "rc"; // check top row QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); int rows = model->rowCount ( topIndex ); Q_ASSERT ( rows >= 0 ); if ( rows > 0 ) Q_ASSERT ( model->hasChildren ( topIndex ) == true ); QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex ); if ( secondLevelIndex.isValid() ) { // not the top level // check a row count where parent is valid rows = model->rowCount ( secondLevelIndex ); Q_ASSERT ( rows >= 0 ); if ( rows > 0 ) Q_ASSERT ( model->hasChildren ( secondLevelIndex ) == true ); } // The models rowCount() is tested more extensively in checkChildren(), // but this catches the big mistakes } /*! Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren() */ void ModelTest::columnCount() { // check top row QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); Q_ASSERT ( model->columnCount ( topIndex ) >= 0 ); // check a column count where parent is valid QModelIndex childIndex = model->index ( 0, 0, topIndex ); if ( childIndex.isValid() ) Q_ASSERT ( model->columnCount ( childIndex ) >= 0 ); // columnCount() is tested more extensively in checkChildren(), // but this catches the big mistakes } /*! Tests model's implementation of QAbstractItemModel::hasIndex() */ void ModelTest::hasIndex() { // qDebug() << "hi"; // Make sure that invalid values returns an invalid index Q_ASSERT ( model->hasIndex ( -2, -2 ) == false ); Q_ASSERT ( model->hasIndex ( -2, 0 ) == false ); Q_ASSERT ( model->hasIndex ( 0, -2 ) == false ); int rows = model->rowCount(); int columns = model->columnCount(); // check out of bounds Q_ASSERT ( model->hasIndex ( rows, columns ) == false ); Q_ASSERT ( model->hasIndex ( rows + 1, columns + 1 ) == false ); if ( rows > 0 ) Q_ASSERT ( model->hasIndex ( 0, 0 ) == true ); // hasIndex() is tested more extensively in checkChildren(), // but this catches the big mistakes } /*! Tests model's implementation of QAbstractItemModel::index() */ void ModelTest::index() { // qDebug() << "i"; // Make sure that invalid values returns an invalid index Q_ASSERT ( model->index ( -2, -2 ) == QModelIndex() ); Q_ASSERT ( model->index ( -2, 0 ) == QModelIndex() ); Q_ASSERT ( model->index ( 0, -2 ) == QModelIndex() ); int rows = model->rowCount(); int columns = model->columnCount(); if ( rows == 0 ) return; // Catch off by one errors Q_ASSERT ( model->index ( rows, columns ) == QModelIndex() ); Q_ASSERT ( model->index ( 0, 0 ).isValid() == true ); // Make sure that the same index is *always* returned QModelIndex a = model->index ( 0, 0 ); QModelIndex b = model->index ( 0, 0 ); Q_ASSERT ( a == b ); // index() is tested more extensively in checkChildren(), // but this catches the big mistakes } /*! Tests model's implementation of QAbstractItemModel::parent() */ void ModelTest::parent() { // qDebug() << "p"; // Make sure the model wont crash and will return an invalid QModelIndex // when asked for the parent of an invalid index. Q_ASSERT ( model->parent ( QModelIndex() ) == QModelIndex() ); if ( model->rowCount() == 0 ) return; // Column 0 | Column 1 | // QModelIndex() | | // \- topIndex | topIndex1 | // \- childIndex | childIndex1 | // Common error test #1, make sure that a top level index has a parent // that is a invalid QModelIndex. QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); Q_ASSERT ( model->parent ( topIndex ) == QModelIndex() ); // Common error test #2, make sure that a second level index has a parent // that is the first level index. if ( model->rowCount ( topIndex ) > 0 ) { QModelIndex childIndex = model->index ( 0, 0, topIndex ); Q_ASSERT ( model->parent ( childIndex ) == topIndex ); } // Common error test #3, the second column should NOT have the same children // as the first column in a row. // Usually the second column shouldn't have children. QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() ); if ( model->rowCount ( topIndex1 ) > 0 ) { QModelIndex childIndex = model->index ( 0, 0, topIndex ); QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 ); Q_ASSERT ( childIndex != childIndex1 ); } // Full test, walk n levels deep through the model making sure that all // parent's children correctly specify their parent. checkChildren ( QModelIndex() ); } /*! Called from the parent() test. A model that returns an index of parent X should also return X when asking for the parent of the index. This recursive function does pretty extensive testing on the whole model in an effort to catch edge cases. This function assumes that rowCount(), columnCount() and index() already work. If they have a bug it will point it out, but the above tests should have already found the basic bugs because it is easier to figure out the problem in those tests then this one. */ void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth ) { // First just try walking back up the tree. QModelIndex p = parent; while ( p.isValid() ) p = p.parent(); // For models that are dynamically populated if ( model->canFetchMore ( parent ) ) { fetchingMore = true; model->fetchMore ( parent ); fetchingMore = false; } int rows = model->rowCount ( parent ); int columns = model->columnCount ( parent ); if ( rows > 0 ) Q_ASSERT ( model->hasChildren ( parent ) ); // Some further testing against rows(), columns(), and hasChildren() Q_ASSERT ( rows >= 0 ); Q_ASSERT ( columns >= 0 ); if ( rows > 0 ) Q_ASSERT ( model->hasChildren ( parent ) == true ); //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows // << "columns:" << columns << "parent column:" << parent.column(); Q_ASSERT ( model->hasIndex ( rows + 1, 0, parent ) == false ); for ( int r = 0; r < rows; ++r ) { if ( model->canFetchMore ( parent ) ) { fetchingMore = true; model->fetchMore ( parent ); fetchingMore = false; } Q_ASSERT ( model->hasIndex ( r, columns + 1, parent ) == false ); for ( int c = 0; c < columns; ++c ) { Q_ASSERT ( model->hasIndex ( r, c, parent ) == true ); QModelIndex index = model->index ( r, c, parent ); // rowCount() and columnCount() said that it existed... Q_ASSERT ( index.isValid() == true ); // index() should always return the same index when called twice in a row QModelIndex modifiedIndex = model->index ( r, c, parent ); Q_ASSERT ( index == modifiedIndex ); // Make sure we get the same index if we request it twice in a row QModelIndex a = model->index ( r, c, parent ); QModelIndex b = model->index ( r, c, parent ); Q_ASSERT ( a == b ); // Some basic checking on the index that is returned Q_ASSERT ( index.model() == model ); Q_ASSERT ( index.row() == r ); Q_ASSERT ( index.column() == c ); // While you can technically return a QVariant usually this is a sign // of an bug in data() Disable if this really is ok in your model. // Q_ASSERT ( model->data ( index, Qt::DisplayRole ).isValid() == true ); // If the next test fails here is some somewhat useful debug you play with. if (model->parent(index) != parent) { qDebug() << r << c << currentDepth << model->data(index).toString() << model->data(parent).toString(); qDebug() << index << parent << model->parent(index); // And a view that you can even use to show the model. // QTreeView view; // view.setModel(model); // view.show(); } // Check that we can get back our real parent. // qDebug() << model->parent ( index ) << parent ; Q_ASSERT ( model->parent ( index ) == parent ); // recursively go down the children if ( model->hasChildren ( index ) && currentDepth < 10 ) { //qDebug() << r << c << "has children" << model->rowCount(index); checkChildren ( index, ++currentDepth ); }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/ // make sure that after testing the children that the index doesn't change. QModelIndex newerIndex = model->index ( r, c, parent ); Q_ASSERT ( index == newerIndex ); } } } /*! Tests model's implementation of QAbstractItemModel::data() */ void ModelTest::data() { // Invalid index should return an invalid qvariant Q_ASSERT ( !model->data ( QModelIndex() ).isValid() ); if ( model->rowCount() == 0 ) return; // A valid index should have a valid QVariant data Q_ASSERT ( model->index ( 0, 0 ).isValid() ); // shouldn't be able to set data on an invalid index Q_ASSERT ( model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) == false ); // General Purpose roles that should return a QString QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole ); if ( variant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( variant ) ); } variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole ); if ( variant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( variant ) ); } variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole ); if ( variant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( variant ) ); } // General Purpose roles that should return a QSize variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole ); if ( variant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( variant ) ); } // General Purpose roles that should return a QFont QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole ); if ( fontVariant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( fontVariant ) ); } // Check that the alignment is one we know about QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole ); if ( textAlignmentVariant.isValid() ) { int alignment = textAlignmentVariant.toInt(); Q_ASSERT ( alignment == ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) ); } // General Purpose roles that should return a QColor QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole ); if ( colorVariant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( colorVariant ) ); } colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole ); if ( colorVariant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( colorVariant ) ); } // Check that the "check state" is one we know about. QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole ); if ( checkStateVariant.isValid() ) { int state = checkStateVariant.toInt(); Q_ASSERT ( state == Qt::Unchecked || state == Qt::PartiallyChecked || state == Qt::Checked ); } } /*! Store what is about to be inserted to make sure it actually happens \sa rowsInserted() */ void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int end ) { // Q_UNUSED(end); // qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString() // << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) ); // qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) ); Changing c; c.parent = parent; c.oldSize = model->rowCount ( parent ); c.last = model->data ( model->index ( start - 1, 0, parent ) ); c.next = model->data ( model->index ( start, 0, parent ) ); insert.push ( c ); } /*! Confirm that what was said was going to happen actually did \sa rowsAboutToBeInserted() */ void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end ) { Changing c = insert.pop(); Q_ASSERT ( c.parent == parent ); // qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize // << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent ); // for (int ii=start; ii <= end; ii++) // { // qDebug() << "itemWasInserted:" << ii << model->data ( model->index ( ii, 0, parent )); // } // qDebug(); Q_ASSERT ( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) ); Q_ASSERT ( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); if (c.next != model->data(model->index(end + 1, 0, c.parent))) { qDebug() << start << end; for (int i=0; i < model->rowCount(); ++i) qDebug() << model->index(i, 0).data().toString(); qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent)); } Q_ASSERT ( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) ); } void ModelTest::layoutAboutToBeChanged() { for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i ) changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) ); } void ModelTest::layoutChanged() { for ( int i = 0; i < changing.count(); ++i ) { QPersistentModelIndex p = changing[i]; Q_ASSERT ( p == model->index ( p.row(), p.column(), p.parent() ) ); } changing.clear(); } /*! Store what is about to be inserted to make sure it actually happens \sa rowsRemoved() */ void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end ) { qDebug() << "ratbr" << parent << start << end; Changing c; c.parent = parent; c.oldSize = model->rowCount ( parent ); c.last = model->data ( model->index ( start - 1, 0, parent ) ); c.next = model->data ( model->index ( end + 1, 0, parent ) ); remove.push ( c ); } /*! Confirm that what was said was going to happen actually did \sa rowsAboutToBeRemoved() */ void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end ) { qDebug() << "rr" << parent << start << end; Changing c = remove.pop(); Q_ASSERT ( c.parent == parent ); Q_ASSERT ( c.oldSize - ( end - start + 1 ) == model->rowCount ( parent ) ); Q_ASSERT ( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); Q_ASSERT ( c.next == model->data ( model->index ( start, 0, c.parent ) ) ); } diff --git a/components/mobilecomponents/categorizedproxymodel.cpp b/components/mobilecomponents/categorizedproxymodel.cpp index 65e6dd79..6a60ce77 100644 --- a/components/mobilecomponents/categorizedproxymodel.cpp +++ b/components/mobilecomponents/categorizedproxymodel.cpp @@ -1,238 +1,238 @@ /* Copyright 2011 Marco Martin 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. */ #include "categorizedproxymodel.h" #include #include CategorizedProxyModel::CategorizedProxyModel(QObject *parent) : QSortFilterProxyModel(parent), m_categoryRoleInt(Qt::UserRole) { m_fillCategoriesTimer = new QTimer(this); m_fillCategoriesTimer->setSingleShot(true); connect(m_fillCategoriesTimer, SIGNAL(timeout()), this, SLOT(fillCategories())); } CategorizedProxyModel::~CategorizedProxyModel() { } void CategorizedProxyModel::setCategoryRole(const QString &role) { if (role == m_categoryRoleString) { return; } m_categoryRoleString = role; m_fillCategoriesTimer->start(0); } QString CategorizedProxyModel::categoryRole() const { return m_categoryRoleString; } void CategorizedProxyModel::setCurrentCategory(const QString &category) { if (m_currentCategory == category) { return; } m_currentCategory = category; beginResetModel(); endResetModel(); } QString CategorizedProxyModel::currentCategory() const { return m_currentCategory; } QStringList CategorizedProxyModel::categories() const { return m_categories; } void CategorizedProxyModel::setModel(QObject *source) { QAbstractItemModel *model = qobject_cast(source); if (!model) { return; } m_fillCategoriesTimer->start(0); // TODO disconnect old model - connect(model, SIGNAL(rowsInserted(QModelIndex, int, int)), - SLOT(slotInsertRows(QModelIndex, int, int)), Qt::QueuedConnection); - connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), - SLOT(slotRemoveRows(QModelIndex, int, int))); + connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), + SLOT(slotInsertRows(QModelIndex,int,int)), Qt::QueuedConnection); + connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), + SLOT(slotRemoveRows(QModelIndex,int,int))); connect(model, SIGNAL(modelReset()), this, SLOT(fillCategories()), Qt::QueuedConnection); setRoleNames(model->roleNames()); setSourceModel(model); } QObject *CategorizedProxyModel::model() const { return sourceModel(); } int CategorizedProxyModel::rowCount(const QModelIndex &parent) const { //if it's a root it's a category if (parent.parent() != QModelIndex()) { return 0; } return m_categoryHash.value(m_currentCategory); } QVariant CategorizedProxyModel::data(const QModelIndex &index, int role) const { if (index.row() < 0) { return QVariant(); } int offset = 0; foreach (const QString &cat, m_categories) { if (cat == m_currentCategory) { break; } offset += m_categoryHash.value(cat); } return QSortFilterProxyModel::data(CategorizedProxyModel::index(index.row()+offset, index.column()), role); } void CategorizedProxyModel::fillCategories() { QAbstractItemModel *model = QSortFilterProxyModel::sourceModel(); if (!model) { return; } setRoleNames(model->roleNames()); QHash names = model->roleNames(); QHash::const_iterator i; for (i = names.constBegin(); i != names.constEnd(); ++i) { if (i.value() == m_categoryRoleString) { m_categoryRoleInt = i.key(); } } setSortRole(m_categoryRoleInt); sort(0); QHash categoryHash; QStringList categories; for (int i = 0; i <= model->rowCount(); i++) { QString category = model->data(model->index(i, 0), m_categoryRoleInt).toString(); if (category.isEmpty()) { continue; } if (categoryHash.contains(category)) { ++categoryHash[category]; } else { categoryHash[category] = 1; categories.append(category); qSort(categories.begin(), categories.end()); } } if (categoryHash != m_categoryHash) { beginResetModel(); m_categoryHash = categoryHash; m_categories = categories; endResetModel(); emit categoriesChanged(); } } void CategorizedProxyModel::slotInsertRows(const QModelIndex& sourceIndex, int begin, int end) { QAbstractItemModel *model = QSortFilterProxyModel::sourceModel(); if (!model) { return; } setRoleNames(model->roleNames()); sort(0); bool changed = false; for (int i = begin; i <= end; i++) { QString category = model->data(model->index(i, 0), m_categoryRoleInt).toString(); if (category.isEmpty()) { continue; } if (m_categoryHash.contains(category)) { ++m_categoryHash[category]; } else { m_categoryHash[category] = 1; m_categories.append(category); qSort(m_categories.begin(), m_categories.end()); changed = true; } } if (changed) { emit categoriesChanged(); } } void CategorizedProxyModel::slotRemoveRows(const QModelIndex& sourceIndex, int begin, int end) { QAbstractItemModel *model = QSortFilterProxyModel::sourceModel(); if (!model) { return; } bool changed = false; for (int i = begin; i <= end; i++) { QString category = model->data(model->index(i, 0), m_categoryRoleInt).toString(); if (m_categoryHash.contains(category)) { if (m_categoryHash.value(category) <= 1) { m_categoryHash.remove(category); m_categories.removeAll(category); changed = true; } else { --m_categoryHash[category]; } } } if (changed) { emit categoriesChanged(); } } #include "categorizedproxymodel.moc" diff --git a/components/mobilecomponents/pagedproxymodel.cpp b/components/mobilecomponents/pagedproxymodel.cpp index c3da0d55..72b01e81 100644 --- a/components/mobilecomponents/pagedproxymodel.cpp +++ b/components/mobilecomponents/pagedproxymodel.cpp @@ -1,294 +1,294 @@ /* Copyright 2010 Marco Martin 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. */ #include "pagedproxymodel.h" #include PagedProxyModel::PagedProxyModel(QObject *parent) : QAbstractProxyModel(parent), m_pageSize(16), m_currentPage(0) { } PagedProxyModel::~PagedProxyModel() { } int PagedProxyModel::totalPages() { if (!sourceModel()) { return 0; } return sourceModel()->rowCount() / m_pageSize; } void PagedProxyModel::setCurrentPage(const int page) { if (m_currentPage == page) { return; } beginResetModel(); m_currentPage = page; endResetModel(); } int PagedProxyModel::currentPage() const { return m_currentPage; } void PagedProxyModel::setPageSize(const int size) { if (m_pageSize == size) { return; } beginResetModel(); m_pageSize = size; endResetModel(); } int PagedProxyModel::pageSize() const { return m_pageSize; } void PagedProxyModel::setSourceModelObject(QObject *source) { QAbstractItemModel *model = qobject_cast(source); if (!model) { return; } if (sourceModel()) { disconnect(sourceModel(), 0, this, 0); } connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(sourceDataChanged(QModelIndex,QModelIndex))); - connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex, int,int)), + connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)) ); - connect(model, SIGNAL(rowsInserted(QModelIndex, int,int)), + connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(sourceRowsInserted(QModelIndex,int,int)) ); - connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int,int)), + connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)) ); - connect(model, SIGNAL(rowsRemoved(QModelIndex, int,int)), + connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(sourceRowsRemoved(QModelIndex,int,int)) ); - connect(model, SIGNAL(rowsMoved(QModelIndex, int, int, const QModelIndex, int)), - this, SLOT(sourceRowsMoved(QModelIndex, int, int, const QModelIndex, int))); + connect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), + this, SLOT(sourceRowsMoved(QModelIndex,int,int,QModelIndex,int))); connect(model, SIGNAL(modelAboutToBeReset()), this, SIGNAL(modelAboutToBeReset())); connect(model, SIGNAL(modelReset()), this, SIGNAL(modelReset())); setRoleNames(model->roleNames()); setSourceModel(model); } QObject *PagedProxyModel::sourceModelObject() const { return sourceModel(); } void PagedProxyModel::sourceDataChanged(const QModelIndex &from, const QModelIndex &to) { emit dataChanged(mapFromSource(from), mapFromSource(to)); } void PagedProxyModel::sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) { const int pageStart = (m_currentPage*m_pageSize); int newStart = qMin(m_pageSize, qMax(0, sourceStart - pageStart)); int newEnd = qMin(m_pageSize, newStart + (sourceEnd - sourceStart)); int newDestinationRow = qMin(m_pageSize, qMax(0, destinationRow - pageStart)); emit beginMoveRows(sourceParent, newStart, newEnd, destinationParent, newDestinationRow); endMoveRows(); } void PagedProxyModel::sourceRowsAboutToBeInserted( const QModelIndex & parentIdx, int start, int end ) { const int pageStart = (m_currentPage*m_pageSize); const int pageEnd = (m_currentPage*m_pageSize + m_pageSize); //insert in pages bigger than us, not interested if (start > pageEnd) { return; } //FIXME: proper indexes should be calculated beginResetModel(); return; int newStart = qMin(m_pageSize, qMax(0, start - pageStart)); int newEnd = qMin(m_pageSize, newStart + (end - start)); m_oldRowCount = rowCount(); //insert only the ones that are beyond the count if (newEnd > m_oldRowCount) { beginInsertRows(parentIdx, rowCount() - newEnd, newEnd ); } } void PagedProxyModel::sourceRowsInserted( const QModelIndex& parentIdx, int start, int end ) { Q_UNUSED( parentIdx ); const int pageStart = (m_currentPage*m_pageSize); const int pageEnd = (m_currentPage*m_pageSize + m_pageSize); if (start > pageEnd) { return; } //FIXME: proper mapped indexes should be calculated endResetModel(); return; if (rowCount() > m_oldRowCount) { endInsertRows(); } int newStart = qMin(m_pageSize, qMax(0, start - pageStart)); int newEnd = qMin(m_pageSize, newStart + (end - start)); if (newStart <= m_oldRowCount) { emit dataChanged(PagedProxyModel::index(newStart, 0), PagedProxyModel::index(qMin(newEnd, m_oldRowCount), 0)); } } void PagedProxyModel::sourceRowsAboutToBeRemoved( const QModelIndex & parentIdx, int start, int end ) { const int pageStart = (m_currentPage*m_pageSize); const int pageEnd = (m_currentPage*m_pageSize + m_pageSize); if (start > pageEnd) { return; } //FIXME: proper mapped indexes should be calculated beginResetModel(); return; int newStart = qMin(m_pageSize, qMax(0, start - pageStart)); int newEnd = qMin(m_pageSize, qMax(0, end - pageStart)); m_oldRowCount = rowCount(); //insert only the ones that are beyond the count if (newEnd < m_oldRowCount) { beginRemoveRows(parentIdx, newStart, newEnd ); } } void PagedProxyModel::sourceRowsRemoved( const QModelIndex& parentIdx, int start, int end ) { Q_UNUSED( parentIdx ); const int pageStart = (m_currentPage*m_pageSize); const int pageEnd = (m_currentPage*m_pageSize + m_pageSize); if (start > pageEnd) { return; } //FIXME: proper mapped indexes should be calculated endResetModel(); return; if (rowCount() < m_oldRowCount) { endRemoveRows(); } int newStart = qMin(m_pageSize, qMax(0, start - pageStart)); int newEnd = qMin(m_pageSize, newStart + (end - start)); if (sourceModel()->rowCount() - pageStart > rowCount()) { emit dataChanged(PagedProxyModel::index(newStart, 0), PagedProxyModel::index(qMin((sourceModel()->rowCount() - pageStart), qMin(newEnd, m_oldRowCount)), 0)); } } int PagedProxyModel::rowCount(const QModelIndex &parent) const { if (!sourceModel()) { return 0; } return qMin(m_pageSize, (sourceModel()->rowCount(parent)-m_currentPage*m_pageSize)); } QVariant PagedProxyModel::data(const QModelIndex &index, int role) const { if (!sourceModel()) { return QVariant(); } return sourceModel()->data(PagedProxyModel::index(index.row()+ (m_currentPage*m_pageSize), index.column(), QModelIndex()), role); } QModelIndex PagedProxyModel::index(int row, int column, const QModelIndex &parent) const { if (!sourceModel()) { return QModelIndex(); } return sourceModel()->index(row, column, parent); } QModelIndex PagedProxyModel::parent(const QModelIndex &index) const { Q_UNUSED(index) return QModelIndex(); } QModelIndex PagedProxyModel::mapFromSource(const QModelIndex &sourceIndex) const { if (!sourceModel()) { return QModelIndex(); } return sourceModel()->index(sourceIndex.row() - (m_currentPage*m_pageSize), sourceIndex.column(), QModelIndex()); } QModelIndex PagedProxyModel::mapToSource(const QModelIndex &proxyIndex) const { if (!sourceModel()) { return QModelIndex(); } return sourceModel()->index(proxyIndex.row() + (m_currentPage*m_pageSize), proxyIndex.column(), QModelIndex()); } int PagedProxyModel::columnCount(const QModelIndex &index) const { if (!sourceModel()) { return 0; } return sourceModel()->columnCount(index); } #include "pagedproxymodel.moc" diff --git a/components/runnermodel/test/modeltest.cpp b/components/runnermodel/test/modeltest.cpp index 8b298ec1..88677cc8 100644 --- a/components/runnermodel/test/modeltest.cpp +++ b/components/runnermodel/test/modeltest.cpp @@ -1,566 +1,566 @@ /**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "modeltest.h" #include //#undef Q_ASSERT //#define Q_ASSERT QVERIFY Q_DECLARE_METATYPE ( QModelIndex ) /*! Connect to all of the models signals. Whenever anything happens recheck everything. */ ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false ) { Q_ASSERT ( model ); - connect ( model, SIGNAL ( columnsAboutToBeInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( columnsAboutToBeRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( columnsInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( columnsRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( dataChanged ( const QModelIndex &, const QModelIndex & ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( headerDataChanged ( Qt::Orientation, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( layoutAboutToBeChanged () ), this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( layoutChanged () ), this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( modelReset () ), this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); + connect ( model, SIGNAL (columnsAboutToBeInserted(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (columnsAboutToBeRemoved(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (columnsInserted(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (columnsRemoved(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (dataChanged(QModelIndex,QModelIndex)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (headerDataChanged(Qt::Orientation,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (layoutAboutToBeChanged()), this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (layoutChanged()), this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (modelReset()), this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (rowsAboutToBeInserted(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (rowsAboutToBeRemoved(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (rowsInserted(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); + connect ( model, SIGNAL (rowsRemoved(QModelIndex,int,int)), + this, SLOT (runAllTests()) ); // Special checks for inserting/removing - connect ( model, SIGNAL ( layoutAboutToBeChanged() ), - this, SLOT ( layoutAboutToBeChanged() ) ); - connect ( model, SIGNAL ( layoutChanged() ), - this, SLOT ( layoutChanged() ) ); - - connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ) ); - connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ) ); - connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsInserted ( const QModelIndex &, int, int ) ) ); - connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsRemoved ( const QModelIndex &, int, int ) ) ); + connect ( model, SIGNAL (layoutAboutToBeChanged()), + this, SLOT (layoutAboutToBeChanged()) ); + connect ( model, SIGNAL (layoutChanged()), + this, SLOT (layoutChanged()) ); + + connect ( model, SIGNAL (rowsAboutToBeInserted(QModelIndex,int,int)), + this, SLOT (rowsAboutToBeInserted(QModelIndex,int,int)) ); + connect ( model, SIGNAL (rowsAboutToBeRemoved(QModelIndex,int,int)), + this, SLOT (rowsAboutToBeRemoved(QModelIndex,int,int)) ); + connect ( model, SIGNAL (rowsInserted(QModelIndex,int,int)), + this, SLOT (rowsInserted(QModelIndex,int,int)) ); + connect ( model, SIGNAL (rowsRemoved(QModelIndex,int,int)), + this, SLOT (rowsRemoved(QModelIndex,int,int)) ); runAllTests(); } void ModelTest::runAllTests() { if ( fetchingMore ) return; nonDestructiveBasicTest(); rowCount(); columnCount(); hasIndex(); index(); parent(); data(); } /*! nonDestructiveBasicTest tries to call a number of the basic functions (not all) to make sure the model doesn't outright segfault, testing the functions that makes sense. */ void ModelTest::nonDestructiveBasicTest() { Q_ASSERT ( model->buddy ( QModelIndex() ) == QModelIndex() ); model->canFetchMore ( QModelIndex() ); Q_ASSERT ( model->columnCount ( QModelIndex() ) >= 0 ); Q_ASSERT ( model->data ( QModelIndex() ) == QVariant() ); fetchingMore = true; model->fetchMore ( QModelIndex() ); fetchingMore = false; Qt::ItemFlags flags = model->flags ( QModelIndex() ); Q_ASSERT ( flags == Qt::ItemIsDropEnabled || flags == 0 ); model->hasChildren ( QModelIndex() ); model->hasIndex ( 0, 0 ); model->headerData ( 0, Qt::Horizontal ); model->index ( 0, 0 ); model->itemData ( QModelIndex() ); QVariant cache; model->match ( QModelIndex(), -1, cache ); model->mimeTypes(); Q_ASSERT ( model->parent ( QModelIndex() ) == QModelIndex() ); Q_ASSERT ( model->rowCount() >= 0 ); QVariant variant; model->setData ( QModelIndex(), variant, -1 ); model->setHeaderData ( -1, Qt::Horizontal, QVariant() ); model->setHeaderData ( 999999, Qt::Horizontal, QVariant() ); QMap roles; model->sibling ( 0, 0, QModelIndex() ); model->span ( QModelIndex() ); model->supportedDropActions(); } /*! Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren() Models that are dynamically populated are not as fully tested here. */ void ModelTest::rowCount() { // qDebug() << "rc"; // check top row QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); int rows = model->rowCount ( topIndex ); Q_ASSERT ( rows >= 0 ); if ( rows > 0 ) Q_ASSERT ( model->hasChildren ( topIndex ) == true ); QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex ); if ( secondLevelIndex.isValid() ) { // not the top level // check a row count where parent is valid rows = model->rowCount ( secondLevelIndex ); Q_ASSERT ( rows >= 0 ); if ( rows > 0 ) Q_ASSERT ( model->hasChildren ( secondLevelIndex ) == true ); } // The models rowCount() is tested more extensively in checkChildren(), // but this catches the big mistakes } /*! Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren() */ void ModelTest::columnCount() { // check top row QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); Q_ASSERT ( model->columnCount ( topIndex ) >= 0 ); // check a column count where parent is valid QModelIndex childIndex = model->index ( 0, 0, topIndex ); if ( childIndex.isValid() ) Q_ASSERT ( model->columnCount ( childIndex ) >= 0 ); // columnCount() is tested more extensively in checkChildren(), // but this catches the big mistakes } /*! Tests model's implementation of QAbstractItemModel::hasIndex() */ void ModelTest::hasIndex() { // qDebug() << "hi"; // Make sure that invalid values returns an invalid index Q_ASSERT ( model->hasIndex ( -2, -2 ) == false ); Q_ASSERT ( model->hasIndex ( -2, 0 ) == false ); Q_ASSERT ( model->hasIndex ( 0, -2 ) == false ); int rows = model->rowCount(); int columns = model->columnCount(); // check out of bounds Q_ASSERT ( model->hasIndex ( rows, columns ) == false ); Q_ASSERT ( model->hasIndex ( rows + 1, columns + 1 ) == false ); if ( rows > 0 ) Q_ASSERT ( model->hasIndex ( 0, 0 ) == true ); // hasIndex() is tested more extensively in checkChildren(), // but this catches the big mistakes } /*! Tests model's implementation of QAbstractItemModel::index() */ void ModelTest::index() { // qDebug() << "i"; // Make sure that invalid values returns an invalid index Q_ASSERT ( model->index ( -2, -2 ) == QModelIndex() ); Q_ASSERT ( model->index ( -2, 0 ) == QModelIndex() ); Q_ASSERT ( model->index ( 0, -2 ) == QModelIndex() ); int rows = model->rowCount(); int columns = model->columnCount(); if ( rows == 0 ) return; // Catch off by one errors Q_ASSERT ( model->index ( rows, columns ) == QModelIndex() ); Q_ASSERT ( model->index ( 0, 0 ).isValid() == true ); // Make sure that the same index is *always* returned QModelIndex a = model->index ( 0, 0 ); QModelIndex b = model->index ( 0, 0 ); Q_ASSERT ( a == b ); // index() is tested more extensively in checkChildren(), // but this catches the big mistakes } /*! Tests model's implementation of QAbstractItemModel::parent() */ void ModelTest::parent() { // qDebug() << "p"; // Make sure the model wont crash and will return an invalid QModelIndex // when asked for the parent of an invalid index. Q_ASSERT ( model->parent ( QModelIndex() ) == QModelIndex() ); if ( model->rowCount() == 0 ) return; // Column 0 | Column 1 | // QModelIndex() | | // \- topIndex | topIndex1 | // \- childIndex | childIndex1 | // Common error test #1, make sure that a top level index has a parent // that is a invalid QModelIndex. QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); Q_ASSERT ( model->parent ( topIndex ) == QModelIndex() ); // Common error test #2, make sure that a second level index has a parent // that is the first level index. if ( model->rowCount ( topIndex ) > 0 ) { QModelIndex childIndex = model->index ( 0, 0, topIndex ); Q_ASSERT ( model->parent ( childIndex ) == topIndex ); } // Common error test #3, the second column should NOT have the same children // as the first column in a row. // Usually the second column shouldn't have children. QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() ); if ( model->rowCount ( topIndex1 ) > 0 ) { QModelIndex childIndex = model->index ( 0, 0, topIndex ); QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 ); Q_ASSERT ( childIndex != childIndex1 ); } // Full test, walk n levels deep through the model making sure that all // parent's children correctly specify their parent. checkChildren ( QModelIndex() ); } /*! Called from the parent() test. A model that returns an index of parent X should also return X when asking for the parent of the index. This recursive function does pretty extensive testing on the whole model in an effort to catch edge cases. This function assumes that rowCount(), columnCount() and index() already work. If they have a bug it will point it out, but the above tests should have already found the basic bugs because it is easier to figure out the problem in those tests then this one. */ void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth ) { // First just try walking back up the tree. QModelIndex p = parent; while ( p.isValid() ) p = p.parent(); // For models that are dynamically populated if ( model->canFetchMore ( parent ) ) { fetchingMore = true; model->fetchMore ( parent ); fetchingMore = false; } int rows = model->rowCount ( parent ); int columns = model->columnCount ( parent ); if ( rows > 0 ) Q_ASSERT ( model->hasChildren ( parent ) ); // Some further testing against rows(), columns(), and hasChildren() Q_ASSERT ( rows >= 0 ); Q_ASSERT ( columns >= 0 ); if ( rows > 0 ) Q_ASSERT ( model->hasChildren ( parent ) == true ); //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows // << "columns:" << columns << "parent column:" << parent.column(); Q_ASSERT ( model->hasIndex ( rows + 1, 0, parent ) == false ); for ( int r = 0; r < rows; ++r ) { if ( model->canFetchMore ( parent ) ) { fetchingMore = true; model->fetchMore ( parent ); fetchingMore = false; } Q_ASSERT ( model->hasIndex ( r, columns + 1, parent ) == false ); for ( int c = 0; c < columns; ++c ) { Q_ASSERT ( model->hasIndex ( r, c, parent ) == true ); QModelIndex index = model->index ( r, c, parent ); // rowCount() and columnCount() said that it existed... Q_ASSERT ( index.isValid() == true ); // index() should always return the same index when called twice in a row QModelIndex modifiedIndex = model->index ( r, c, parent ); Q_ASSERT ( index == modifiedIndex ); // Make sure we get the same index if we request it twice in a row QModelIndex a = model->index ( r, c, parent ); QModelIndex b = model->index ( r, c, parent ); Q_ASSERT ( a == b ); // Some basic checking on the index that is returned Q_ASSERT ( index.model() == model ); Q_ASSERT ( index.row() == r ); Q_ASSERT ( index.column() == c ); // While you can technically return a QVariant usually this is a sign // of an bug in data() Disable if this really is ok in your model. // Q_ASSERT ( model->data ( index, Qt::DisplayRole ).isValid() == true ); // If the next test fails here is some somewhat useful debug you play with. if (model->parent(index) != parent) { qDebug() << r << c << currentDepth << model->data(index).toString() << model->data(parent).toString(); qDebug() << index << parent << model->parent(index); // And a view that you can even use to show the model. // QTreeView view; // view.setModel(model); // view.show(); } // Check that we can get back our real parent. // qDebug() << model->parent ( index ) << parent ; Q_ASSERT ( model->parent ( index ) == parent ); // recursively go down the children if ( model->hasChildren ( index ) && currentDepth < 10 ) { //qDebug() << r << c << "has children" << model->rowCount(index); checkChildren ( index, ++currentDepth ); }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/ // make sure that after testing the children that the index doesn't change. QModelIndex newerIndex = model->index ( r, c, parent ); Q_ASSERT ( index == newerIndex ); } } } /*! Tests model's implementation of QAbstractItemModel::data() */ void ModelTest::data() { // Invalid index should return an invalid qvariant Q_ASSERT ( !model->data ( QModelIndex() ).isValid() ); if ( model->rowCount() == 0 ) return; // A valid index should have a valid QVariant data Q_ASSERT ( model->index ( 0, 0 ).isValid() ); // shouldn't be able to set data on an invalid index Q_ASSERT ( model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) == false ); // General Purpose roles that should return a QString QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole ); if ( variant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( variant ) ); } variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole ); if ( variant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( variant ) ); } variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole ); if ( variant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( variant ) ); } // General Purpose roles that should return a QSize variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole ); if ( variant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( variant ) ); } // General Purpose roles that should return a QFont QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole ); if ( fontVariant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( fontVariant ) ); } // Check that the alignment is one we know about QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole ); if ( textAlignmentVariant.isValid() ) { int alignment = textAlignmentVariant.toInt(); Q_ASSERT ( alignment == ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) ); } // General Purpose roles that should return a QColor QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole ); if ( colorVariant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( colorVariant ) ); } colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole ); if ( colorVariant.isValid() ) { Q_ASSERT ( qVariantCanConvert ( colorVariant ) ); } // Check that the "check state" is one we know about. QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole ); if ( checkStateVariant.isValid() ) { int state = checkStateVariant.toInt(); Q_ASSERT ( state == Qt::Unchecked || state == Qt::PartiallyChecked || state == Qt::Checked ); } } /*! Store what is about to be inserted to make sure it actually happens \sa rowsInserted() */ void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int end ) { // Q_UNUSED(end); // qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString() // << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) ); // qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) ); Changing c; c.parent = parent; c.oldSize = model->rowCount ( parent ); c.last = model->data ( model->index ( start - 1, 0, parent ) ); c.next = model->data ( model->index ( start, 0, parent ) ); insert.push ( c ); } /*! Confirm that what was said was going to happen actually did \sa rowsAboutToBeInserted() */ void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end ) { Changing c = insert.pop(); Q_ASSERT ( c.parent == parent ); // qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize // << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent ); // for (int ii=start; ii <= end; ii++) // { // qDebug() << "itemWasInserted:" << ii << model->data ( model->index ( ii, 0, parent )); // } // qDebug(); Q_ASSERT ( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) ); Q_ASSERT ( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); if (c.next != model->data(model->index(end + 1, 0, c.parent))) { qDebug() << start << end; for (int i=0; i < model->rowCount(); ++i) qDebug() << model->index(i, 0).data().toString(); qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent)); } Q_ASSERT ( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) ); } void ModelTest::layoutAboutToBeChanged() { for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i ) changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) ); } void ModelTest::layoutChanged() { for ( int i = 0; i < changing.count(); ++i ) { QPersistentModelIndex p = changing[i]; Q_ASSERT ( p == model->index ( p.row(), p.column(), p.parent() ) ); } changing.clear(); } /*! Store what is about to be inserted to make sure it actually happens \sa rowsRemoved() */ void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end ) { qDebug() << "ratbr" << parent << start << end; Changing c; c.parent = parent; c.oldSize = model->rowCount ( parent ); c.last = model->data ( model->index ( start - 1, 0, parent ) ); c.next = model->data ( model->index ( end + 1, 0, parent ) ); remove.push ( c ); } /*! Confirm that what was said was going to happen actually did \sa rowsAboutToBeRemoved() */ void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end ) { qDebug() << "rr" << parent << start << end; Changing c = remove.pop(); Q_ASSERT ( c.parent == parent ); Q_ASSERT ( c.oldSize - ( end - start + 1 ) == model->rowCount ( parent ) ); Q_ASSERT ( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); Q_ASSERT ( c.next == model->data ( model->index ( start, 0, c.parent ) ) ); } diff --git a/components/settings/settingsmodule.cpp b/components/settings/settingsmodule.cpp index d1673272..7d01b276 100644 --- a/components/settings/settingsmodule.cpp +++ b/components/settings/settingsmodule.cpp @@ -1,105 +1,105 @@ /* * Copyright 2011 Sebastian Kügler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "settingsmodule.h" #include #include #include #include #include class SettingsModulePrivate { public: SettingsModulePrivate(SettingsModule *q): q(q) {} QString name; QString description; QString module; QString iconName; SettingsModule *q; }; SettingsModule::SettingsModule(QObject *parent, const QVariantList &v) : QObject(parent), d(new SettingsModulePrivate(this)) { d = new SettingsModulePrivate(this); Q_UNUSED(v); } SettingsModule::~SettingsModule() { delete d; } QString SettingsModule::name() { return d->name; } QString SettingsModule::description() { return d->description; } QString SettingsModule::module() { return d->module; } QString SettingsModule::iconName() { return d->iconName; } void SettingsModule::setName(const QString &name) { if (d->name != name) { d->name = name; emit nameChanged(); } } void SettingsModule::setDescription(const QString &description) { if (d->description != description) { d->description = description; emit descriptionChanged(); } } void SettingsModule::setIconName(const QString &iconName) { if (d->iconName != iconName) { d->iconName = iconName; emit iconNameChanged(); } } void SettingsModule::setModule(const QString &module) { if (d->module != module) { d->module = module; emit moduleChanged(); } } -#include "settingsmodule.moc" \ No newline at end of file +#include "settingsmodule.moc" diff --git a/dataengines/metadata/resourcecontainer.cpp b/dataengines/metadata/resourcecontainer.cpp index 00656167..1801fab4 100644 --- a/dataengines/metadata/resourcecontainer.cpp +++ b/dataengines/metadata/resourcecontainer.cpp @@ -1,263 +1,263 @@ /* Copyright 2011 Marco Martin Copyright 2011 Sebastian Kügler 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. */ #include "resourcecontainer.h" #include "resourcewatcher.h" #include #include #include #include #include #include ResourceContainer::ResourceContainer(QObject *parent) : Plasma::DataContainer(parent) { m_watcher = new Nepomuk::ResourceWatcher(this); m_watcher->addProperty(QUrl("http://www.semanticdesktop.org/ontologies/2007/08/15/nao#numericRating")); - connect(m_watcher, SIGNAL(propertyAdded(Nepomuk::Resource, Nepomuk::Types::Property, QVariant)), - this, SLOT(propertyChanged(Nepomuk::Resource, Nepomuk::Types::Property, QVariant))); + connect(m_watcher, SIGNAL(propertyAdded(Nepomuk::Resource,Nepomuk::Types::Property,QVariant)), + this, SLOT(propertyChanged(Nepomuk::Resource,Nepomuk::Types::Property,QVariant))); } ResourceContainer::~ResourceContainer() { } void ResourceContainer::propertyChanged(Nepomuk::Resource res, Nepomuk::Types::Property prop, QVariant val) { if (res != m_resource) { return; } setData(prop.name(), val); checkForUpdate(); } void ResourceContainer::setResource(Nepomuk::Resource resource) { if (m_resource == resource) { return; } m_resource = resource; //update the resource watcher { m_watcher->stop(); QList resources; resources << resource; m_watcher->setResources(resources); m_watcher->start(); } QString desc = resource.genericDescription(); if (desc.isEmpty()) { desc = resource.className(); } QString label = resource.genericLabel(); if (label.isEmpty()) { label = "Empty label."; } setData("label", label); setData("description", desc); // Types QStringList _types; foreach (const QUrl &u, resource.types()) { _types << u.toString(); } setData("types", _types); Nepomuk::Types::Class resClass(resource.resourceType()); //FIXME: a more elegant way is needed setData("genericClassName", resource.className()); foreach (const Nepomuk::Types::Class &parentClass, resClass.parentClasses()) { if (parentClass.label() == "Document" || parentClass.label() == "Audio" || parentClass.label() == "Video" || parentClass.label() == "Image" || parentClass.label() == "Contact") { setData("genericClassName", parentClass.label()); break; //two cases where the class is 2 levels behind the level of generalization we want } else if (parentClass.label() == "RasterImage") { setData("genericClassName", "Image"); } else if (parentClass.label() == "TextDocument") { setData("genericClassName", "Document"); } } QString _icon = resource.genericIcon(); if (_icon.isEmpty() && resource.isFile()) { KUrl url = resource.toFile().url(); if (!url.isEmpty()) { _icon = KMimeType::iconNameForUrl(url); } } if (_icon.isEmpty()) { // use resource types to find a suitable icon. //TODO _icon = icon(QStringList(resource.className())); //kDebug() << "symbol" << _icon; } if (_icon.split(',').count() > 1) { kDebug() << "More than one icon!" << _icon; _icon = _icon.split(',').last(); } setData("icon", _icon); setData("hasSymbol", _icon); setData("isFile", resource.isFile()); setData("exists", resource.exists()); setData("rating", resource.rating()); setData("symbols", resource.symbols()); setData("className", resource.className()); setData("resourceUri", resource.resourceUri()); setData("resourceType", resource.resourceType()); setData("query", objectName()); if (resource.isFile() && resource.toFile().url().isLocalFile()) { setData("url", resource.toFile().url().prettyUrl()); } // Topics QStringList _topics, _topicNames; foreach (const Nepomuk::Resource &u, resource.topics()) { _topics << u.resourceUri().toString(); _topicNames << u.genericLabel(); } setData("topics", _topics); setData("topicNames", _topicNames); // Tags QStringList _tags, _tagNames; foreach (const Nepomuk::Tag &tag, resource.tags()) { _tags << tag.resourceUri().toString(); _tagNames << tag.genericLabel(); } setData("tags", _tags); setData("tagNames", _tagNames); // Related QStringList _relateds; foreach (const Nepomuk::Resource &res, resource.isRelateds()) { _relateds << res.resourceUri().toString(); } setData("relateds", _relateds); // Dynamic properties QStringList _properties; QHash props = resource.properties(); foreach(const QUrl &propertyUrl, props.keys()) { QStringList _l = propertyUrl.toString().split('#'); if (_l.count() > 1) { QString key = _l[1]; _properties << key; //QString from = dynamic_cast(); if (resource.property(propertyUrl).variant().canConvert(QVariant::List)) { QVariantList tl = resource.property(propertyUrl).variant().toList(); foreach (const QVariant &vu, tl) { //kDebug() << vu.toString().startsWith("nepomuk:") << vu.toString().startsWith("akonadi:") << vu.toString(); if (vu.canConvert(QVariant::Url) && (vu.toString().startsWith("nepomuk:") || vu.toString().startsWith("akonadi:"))) { kDebug() << "HHH This is a list.!!!" << key << vu.toString(); } } } //kDebug() << " ... " << key << propertyUrl << resource.property(propertyUrl).variant(); if (key != "plainTextMessageContent" && !data().contains(key)) { setData(key, resource.property(propertyUrl).variant()); } // More properties } else { kWarning() << "Could not parse ontology URL, missing '#':" << propertyUrl.toString(); } } setData("properties", _properties); checkForUpdate(); } QString ResourceContainer::icon(const QStringList &types) { if (!m_icons.size()) { // Add fallback icons here from generic to specific // The list of types is also sorted in this way, so // we're returning the most specific icon, even with // the hardcoded mapping. // Files //m_icons["FileDataObject"] = QString("audio-x-generic"); // Audio m_icons["Audio"] = QString("audio-x-generic"); m_icons["MusicPiece"] = QString("audio-x-generic"); // Images m_icons["Image"] = QString("image-x-generic"); m_icons["RasterImage"] = QString("image-x-generic"); m_icons["Email"] = QString("internet-mail"); m_icons["Document"] = QString("kword"); m_icons["PersonContact"] = QString("x-office-contact"); // Filesystem m_icons["Website"] = QString("text-html"); // ... add some more // Filesystem m_icons["Bookmark"] = QString("bookmarks"); m_icons["BookmarksFolder"] = QString("bookmarks-organize"); m_icons["FileDataObject"] = QString("unknown"); m_icons["TextDocument"] = QString("text-enriched"); } // keep searching until the most specific icon is found QString _icon = "nepomuk"; foreach(const QString &t, types) { QString shortType = t.split('#').last(); if (shortType.isEmpty()) { shortType = t; } if (m_icons.keys().contains(shortType)) { _icon = m_icons[shortType]; //kDebug() << "found icon for type" << shortType << _icon; } } return _icon; } #include "resourcecontainer.moc" diff --git a/dataengines/preview/previewcontainer.cpp b/dataengines/preview/previewcontainer.cpp index f30580a6..787c3ef4 100644 --- a/dataengines/preview/previewcontainer.cpp +++ b/dataengines/preview/previewcontainer.cpp @@ -1,137 +1,137 @@ /* * Copyright 2011 Marco Martin * Copyright 2011 Sebastian Kügler * * This program 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 program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "previewcontainer.h" #include "previewengine.h" #include #include #include PreviewContainer::PreviewContainer(const QString &name, const QUrl &url, QObject *parent) : Plasma::DataContainer(parent), m_url(url) { setObjectName(name); m_previewSize = QSize(180, 120); } void PreviewContainer::init() { // Check if the image is in the cache, if so return it m_previewEngine = static_cast(parent()); QImage preview = QImage(m_previewSize, QImage::Format_ARGB32_Premultiplied); if (m_previewEngine->imageCache()->findImage(objectName(), &preview)) { // cache hit //kDebug() << "Cache hit: " << objectName(); setData("status", "done"); setData("url", m_url); setData("thumbnail", preview); checkForUpdate(); return; } kDebug() << "Cache miss: " << objectName(); // Set fallbackimage while loading m_fallbackImage = KIcon("image-loading").pixmap(QSize(64, 64)).toImage(); m_fallbackImage = m_fallbackImage.copy(QRect(QPoint(-120,0), m_previewSize)); setData("status", "loading"); setData("url", m_url); setData("thumbnail", m_fallbackImage); checkForUpdate(); // It may be a directory or a file, let's stat KIO::JobFlags flags = KIO::HideProgressInfo; m_mimeJob = KIO::mimetype(m_url, flags); - connect(m_mimeJob, SIGNAL(mimetype(KIO::Job *, const QString&)), - this, SLOT(mimetypeRetrieved(KIO::Job *, const QString&))); + connect(m_mimeJob, SIGNAL(mimetype(KIO::Job*,QString)), + this, SLOT(mimetypeRetrieved(KIO::Job*,QString))); } PreviewContainer::~PreviewContainer() { } void PreviewContainer::mimetypeRetrieved(KIO::Job* job, const QString &mimetype) { Q_UNUSED(job) if (mimetype.isEmpty() || m_mimeJob->error()) { setData("status", "failed"); //kDebug() << "mimejob failed" << m_mimeJob->url(); return; } else { // Make job reusable by keeping the connection open: // We want to retrieve the target next to create a preview m_mimeJob->putOnHold(); KIO::Scheduler::publishSlaveOnHold(); } // KIO::PreviewJob: http://api.kde.org/4.x-api/kdelibs-apidocs/kio/html/classKIO_1_1PreviewJob.html //kDebug() << "previewengine: starting previewjob for: " << m_url; KFileItem kfile = KFileItem(m_url, mimetype, KFileItem::Unknown); KFileItemList list; list << kfile; // Enable all plugins but the html thumbnailer, this ones covered by // the new web creator which also supports remote URLs QStringList _en = KIO::PreviewJob::availablePlugins(); _en.removeAll("htmlthumbnail"); QStringList *enabledPlugins = new QStringList(_en); m_job = new KIO::PreviewJob(list, m_previewSize, enabledPlugins); - connect(m_job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)), - SLOT(previewUpdated(const KFileItem&, const QPixmap&))); - connect(m_job, SIGNAL(failed(const KFileItem&)), - SLOT(previewJobFailed(const KFileItem&))); + connect(m_job, SIGNAL(gotPreview(KFileItem,QPixmap)), + SLOT(previewUpdated(KFileItem,QPixmap))); + connect(m_job, SIGNAL(failed(KFileItem)), + SLOT(previewJobFailed(KFileItem))); connect(m_job, SIGNAL(result(KJob*)), SLOT(previewResult(KJob*))); m_job->start(); } void PreviewContainer::previewJobFailed(const KFileItem &item) { Q_UNUSED(item) setData("status", "failed"); kWarning() << "preview failed for" << m_url; } void PreviewContainer::previewResult(KJob* job) { Q_UNUSED( job ); //kDebug() << "job result:" << job->errorText() << "success?" << (job->error() == 0); } void PreviewContainer::previewUpdated(const KFileItem &item, const QPixmap &preview) { Q_UNUSED(item) setData("status", "done"); setData("url", m_url); QImage p = preview.toImage(); setData("thumbnail", p); checkForUpdate(); kDebug() << "Cache insert: " << objectName(); m_previewEngine->imageCache()->insertImage(objectName(), p); } #include "previewcontainer.moc" diff --git a/handset/containments/mobiledesktop/mobiledesktop.cpp b/handset/containments/mobiledesktop/mobiledesktop.cpp index 2e28b26a..8fa31ee2 100644 --- a/handset/containments/mobiledesktop/mobiledesktop.cpp +++ b/handset/containments/mobiledesktop/mobiledesktop.cpp @@ -1,123 +1,123 @@ /*************************************************************************** * Copyright 2010 Alexis Menard * * Copyright 2010 Artur Duque de Souza * * Copyright 2010 Marco Martin * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ //own #include "mobiledesktop.h" #include "appletscontainer.h" #include "appletsview.h" //Qt #include #include //KDE #include #include #include #include using namespace Plasma; MobileDesktop::MobileDesktop(QObject *parent, const QVariantList &args) : Containment(parent, args) { setHasConfigurationInterface(false); kDebug() << "!!! loading mobile desktop"; setContainmentType(Containment::CustomContainment); } MobileDesktop::~MobileDesktop() { } void MobileDesktop::init() { Containment::init(); m_appletsView = new AppletsView(this); m_appletsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_appletsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(this); lay->setContentsMargins(0,0,0,0); setContentsMargins(0,0,0,0); m_container = new AppletsContainer(m_appletsView, this); m_appletsView->setAppletsContainer(m_container); lay->addItem(m_appletsView); - connect(this, SIGNAL(appletAdded(Plasma::Applet*, QPointF)), - m_container, SLOT(layoutApplet(Plasma::Applet*, QPointF))); + connect(this, SIGNAL(appletAdded(Plasma::Applet*,QPointF)), + m_container, SLOT(layoutApplet(Plasma::Applet*,QPointF))); connect(this, SIGNAL(appletRemoved(Plasma::Applet*)), m_container, SLOT(appletRemoved(Plasma::Applet*))); setAcceptsHoverEvents(false); setFlag(QGraphicsItem::ItemSendsGeometryChanges, false); setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false); configChanged(); } void MobileDesktop::configChanged() { KConfigGroup cg = config(); m_appletsView->setOrientation((Qt::Orientation)cg.readEntry("Orientation", (int)Qt::Horizontal)); } void MobileDesktop::constraintsEvent(Plasma::Constraints constraints) { if (constraints & Plasma::SizeConstraint) { if (m_appletsView->size().width() > m_appletsView->size().height()) { m_appletsView->setSnapSize(QSizeF(m_appletsView->size().width()/2, m_appletsView->size().height())); } else { m_appletsView->setSnapSize(QSizeF(m_appletsView->size().width(), m_appletsView->size().height()/2)); } } if (constraints & Plasma::StartupCompletedConstraint) { m_container->completeStartup(); } } //They all have to be reimplemented in order to accept them void MobileDesktop::dragEnterEvent(QGraphicsSceneDragDropEvent *event) { Containment::dragEnterEvent(event); } void MobileDesktop::dragLeaveEvent(QGraphicsSceneDragDropEvent *event) { Containment::dragLeaveEvent(event); } void MobileDesktop::dragMoveEvent(QGraphicsSceneDragDropEvent *event) { Containment::dragMoveEvent(event); event->accept(); } void MobileDesktop::dropEvent(QGraphicsSceneDragDropEvent *event) { Containment::dropEvent(event); event->accept(); } K_EXPORT_PLASMA_APPLET(mobiledesktop, MobileDesktop) #include "mobiledesktop.moc" diff --git a/shell/activity.cpp b/shell/activity.cpp index 20aa7300..a99a626b 100644 --- a/shell/activity.cpp +++ b/shell/activity.cpp @@ -1,436 +1,436 @@ /* * Copyright 2010 Chani Armitage * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "mobcorona.h" //#include "plasma-shell-desktop.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "plasmaapp.h" #include "activity.h" Activity::Activity(const QString &id, QObject *parent) : QObject(parent), m_id(id), m_plugin("default"), m_info(new KActivities::Info(id, this)), m_activityConsumer(new KActivities::Consumer(this)), m_current(false) { m_name = m_info->name(); m_icon = m_info->icon(); connect(m_info, SIGNAL(infoChanged()), this, SLOT(activityChanged())); connect(m_info, SIGNAL(stateChanged(KActivities::Info::State)), this, SLOT(activityStateChanged(KActivities::Info::State))); connect(m_info, SIGNAL(started()), this, SLOT(opened())); connect(m_info, SIGNAL(stopped()), this, SLOT(closed())); connect(m_info, SIGNAL(removed()), this, SLOT(removed())); connect(m_activityConsumer, SIGNAL(currentActivityChanged(QString)), this, SLOT(checkIfCurrent())); checkIfCurrent(); //find your containments foreach (Plasma::Containment *cont, PlasmaApp::self()->corona()->containments()) { if ((cont->containmentType() == Plasma::Containment::DesktopContainment || cont->containmentType() == Plasma::Containment::CustomContainment) && !PlasmaApp::self()->corona()->offscreenWidgets().contains(cont) && cont->context()->currentActivityId() == id) { insertContainment(cont); } } //kDebug() << m_containments.size(); } Activity::~Activity() { } void Activity::activityChanged() { setName(m_info->name()); setIcon(m_info->icon()); } void Activity::activityStateChanged(KActivities::Info::State state) { Q_UNUSED(state) emit stateChanged(); } QString Activity::id() { return m_id; } QString Activity::name() { return m_name; } QPixmap Activity::pixmap(const QSize &size) { if (m_info->isValid() && !m_info->icon().isEmpty()) { return KIcon(m_info->icon()).pixmap(size); } else { return QPixmap(); } } bool Activity::isCurrent() { return m_current; //TODO maybe plasmaapp should cache the current activity to reduce dbus calls? } void Activity::checkIfCurrent() { const bool current = m_id == m_activityConsumer->currentActivity(); if (current != m_current) { m_current = current; emit currentStatusChanged(); } } KActivities::Info::State Activity::state() { return m_info->state(); } void Activity::remove() { KActivities::Controller().removeActivity(m_id); } void Activity::removed() { if (! m_containments.isEmpty()) { //FIXME only PlasmaApp::self()->corona() has authority to remove properly kDebug() << "!!!!! if your widgets are locked you've hit a BUG now"; foreach (Plasma::Containment *c, m_containments) { c->destroy(false); } } const QString name = "activities/" + m_id; QFile::remove(KStandardDirs::locateLocal("appdata", name)); } Plasma::Containment* Activity::containmentForScreen(int screen, int desktop) { Plasma::Containment *containment = m_containments.value(QPair(screen, desktop)); if (!containment) { kDebug() << "adding containment for" << screen << desktop; // first look to see if there are any unnasigned containments that are candidates for // being sucked into this Activity foreach (Plasma::Containment *c, PlasmaApp::self()->corona()->containments()) { bool excludeFromActivities = c->config().readEntry("excludeFromActivities", false); if (!excludeFromActivities && (c->containmentType() == Plasma::Containment::DesktopContainment || c->containmentType() == Plasma::Containment::CustomContainment) && c->context()->currentActivityId().isEmpty() && !PlasmaApp::self()->corona()->offscreenWidgets().contains(c) && m_containments.key(c, QPair(-2,-2)) == QPair(-2,-2)) { containment = c; containment->setScreen(screen, desktop); break; } } if (!containment) { // we ask for the containment for the screen with a default plugin, because // this allows the corona to either grab one for us that already exists matching // screen and desktop, or create a new one. this also works regardless of immutability containment = PlasmaApp::self()->corona()->containmentForScreen(screen, desktop, m_plugin); if (!containment || !containment->context()->currentActivityId().isEmpty()) { // possibly a plugin failure, let's go for the default containment = PlasmaApp::self()->corona()->containmentForScreen(screen, desktop, "default"); } //we don't want to steal contaiments from other activities if (!containment) { // we failed to even get the default; we're screwed. Q_ASSERT(false); return 0; } if (!containment->context()->currentActivityId().isEmpty() && containment->context()->currentActivityId() != m_id) { // we got a containment, but it belongs to some other activity; let's unassign it // from a screen and grab a new one containment->setScreen(-1); containment = PlasmaApp::self()->corona()->containmentForScreen(screen, desktop, m_plugin); if (!containment) { // possibly a plugin failure, let's go for the default containment = PlasmaApp::self()->corona()->containmentForScreen(screen, desktop, "default"); } if (containment) { containment->setScreen(screen, desktop); } } } if (containment) { insertContainment(containment, screen, desktop); PlasmaApp::self()->corona()->requestConfigSync(); } } else if (containment->screen() != screen || containment->desktop() != desktop) { // ensure the containment _also_ knows which screen we think it is on; // can happen when swapping between activities without stopping them first containment->setScreen(screen, desktop); } return containment; } void Activity::activate() { KActivities::Controller().setCurrentActivity(m_id); } void Activity::ensureActive() { if (m_containments.isEmpty()) { opened(); } checkScreens(); } void Activity::checkScreens() { //ensure there's a containment for every screen & desktop. int numScreens = PlasmaApp::self()->corona()->numScreens(); int numDesktops = 0; for (int screen = 0; screen < numScreens; ++screen) { if (numDesktops > 0) { for (int desktop = 0; desktop < numDesktops; ++desktop) { containmentForScreen(screen, desktop); } } else { containmentForScreen(screen, -1); } } } void Activity::setName(const QString &name) { if (m_name == name) { return; } m_name = name; KActivities::Controller().setActivityName(m_id, name); emit infoChanged(); foreach (Plasma::Containment *c, m_containments) { c->context()->setCurrentActivity(name); } } void Activity::setIcon(const QString &icon) { if (m_icon == icon) { return; } m_icon = icon; KActivities::Controller().setActivityIcon(m_id, icon); emit infoChanged(); } void Activity::updateActivityName(Plasma::Context *context) { if (context->currentActivityId() != m_id) { kDebug() << "can't happen!"; return; } setName(context->currentActivity()); } void Activity::save(KConfig &external) { foreach (const QString &group, external.groupList()) { KConfigGroup cg(&external, group); cg.deleteGroup(); } //TODO: multi-screen saving/restoring, where each screen can be // independently restored: put each screen's containments into a // different group, e.g. [Screens][0][Containments], [Screens][1][Containments], etc KConfigGroup dest(&external, "Containments"); KConfigGroup dummy; foreach (Plasma::Containment *c, m_containments) { c->save(dummy); KConfigGroup group(&dest, QString::number(c->id())); c->config().copyTo(&group); } external.sync(); } void Activity::close() { KActivities::Controller().stopActivity(m_id); } void Activity::closed() { const QString name = "activities/" + m_id; KConfig external(name, KConfig::SimpleConfig, "appdata"); //passing an empty string for the group name turns a kconfig into a kconfiggroup KConfigGroup group = external.group(QString()); PlasmaApp::self()->corona()->exportLayout(group, m_containments.values()); //hrm, shouldn't the containments' deleted signals have done this for us? if (!m_containments.isEmpty()) { kDebug() << "isn't close supposed to *remove* containments??"; m_containments.clear(); } } void Activity::replaceContainment(Plasma::Containment* containment) { insertContainment(containment, true); } void Activity::insertContainment(Plasma::Containment* cont, bool force) { int screen = cont->lastScreen(); int desktop = cont->lastDesktop(); kDebug() << screen << desktop; if (screen == -1) { //the migration can't set lastScreen, so maybe we need to assign the containment here kDebug() << "found a lost one"; screen = 0; } if (!force && m_containments.contains(QPair(screen, desktop))) { //this almost certainly means someone has been meddling where they shouldn't //but we should protect them from harm anyways kDebug() << "@!@!@!@!@!@@@@rejecting containment!!!"; cont->context()->setCurrentActivityId(QString()); return; } insertContainment(cont, screen, desktop); } void Activity::insertContainment(Plasma::Containment* containment, int screen, int desktop) { //ensure it's hooked up Plasma::Context *context = containment->context(); context->setCurrentActivityId(m_id); context->setCurrentActivity(m_name); //hack to keep the name in sync while KActivities::* are in kdebase connect(context, SIGNAL(activityChanged(Plasma::Context*)), this, SLOT(updateActivityName(Plasma::Context*)), Qt::UniqueConnection); m_containments.insert(QPair(screen, desktop), containment); - connect(containment, SIGNAL(destroyed(QObject *)), this, SLOT(containmentDestroyed(QObject *))); + connect(containment, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed(QObject*))); } void Activity::containmentDestroyed(QObject *object) { //safe here because we are not accessing it Plasma::Containment *deletedCont = static_cast(object); QHash, Plasma::Containment*>::iterator i; for (i = m_containments.begin(); i != m_containments.end(); ++i) { Plasma::Containment *cont = i.value(); if (cont == deletedCont) { m_containments.remove(i.key()); break; } } } void Activity::open() { KActivities::Controller().startActivity(m_id); } void Activity::opened() { if (!m_containments.isEmpty()) { kDebug() << "already open!"; return; } QString fileName = "activities/"; fileName += m_id; KConfig external(fileName, KConfig::SimpleConfig, "appdata"); foreach (Plasma::Containment *newContainment, PlasmaApp::self()->corona()->importLayout(external.group(QByteArray()))) { insertContainment(newContainment); //ensure it's hooked up (if something odd happened we don't want orphan containments) Plasma::Context *context = newContainment->context(); context->setCurrentActivityId(m_id); connect(context, SIGNAL(activityChanged(Plasma::Context*)), this, SLOT(updateActivityName(Plasma::Context*)), Qt::UniqueConnection); } KConfigGroup configs(&external, "Containments"); configs.deleteGroup(); if (m_containments.isEmpty()) { //TODO check if we need more for screens/desktops kDebug() << "open failed (bad file?). creating new containment"; checkScreens(); } PlasmaApp::self()->corona()->requireConfigSync(); external.sync(); } void Activity::setDefaultPlugin(const QString &plugin) { m_plugin = plugin; //FIXME save&restore this setting } const KActivities::Info * Activity::info() const { return m_info; } #include "activity.moc" // vim: sw=4 sts=4 et tw=100 diff --git a/shell/activityconfiguration/backgroundlistmodel.cpp b/shell/activityconfiguration/backgroundlistmodel.cpp index 67dbc044..029047ee 100644 --- a/shell/activityconfiguration/backgroundlistmodel.cpp +++ b/shell/activityconfiguration/backgroundlistmodel.cpp @@ -1,424 +1,424 @@ #ifndef BACKGROUNDLISTMODEL_CPP #define BACKGROUNDLISTMODEL_CPP /* Copyright (c) 2007 Paolo Capriotti This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #include "backgroundlistmodel.h" #include #include #include #include #include #include #include #include #include #include #include #include ImageSizeFinder::ImageSizeFinder(const QString &path, QObject *parent) : QObject(parent), m_path(path) { } void ImageSizeFinder::run() { QImage image(m_path); emit sizeFound(m_path, image.size()); } BackgroundListModel::BackgroundListModel(Plasma::Wallpaper *listener, QObject *parent) : QAbstractListModel(parent), m_structureParent(listener), m_screenshotSize(320, 200) { connect(&m_dirwatch, SIGNAL(deleted(QString)), this, SLOT(removeBackground(QString))); m_previewUnavailablePix.fill(Qt::transparent); //m_previewUnavailablePix = KIcon("unknown").pixmap(m_previewUnavailablePix.size()); QHash roleNames; roleNames[Qt::DisplayRole] = "display"; roleNames[ScreenshotRole] = "screenshot"; roleNames[AuthorRole] = "author"; roleNames[ResolutionRole] = "resolution"; setRoleNames(roleNames); } BackgroundListModel::~BackgroundListModel() { qDeleteAll(m_packages); } void BackgroundListModel::removeBackground(const QString &path) { QModelIndex index; while ((index = indexOf(path)).isValid()) { beginRemoveRows(QModelIndex(), index.row(), index.row()); Plasma::Package *package = m_packages.at(index.row()); m_packages.removeAt(index.row()); delete package; endRemoveRows(); emit countChanged(); } } void BackgroundListModel::reload() { reload(QStringList()); } void BackgroundListModel::reload(const QStringList &selected) { if (!m_packages.isEmpty()) { beginRemoveRows(QModelIndex(), 0, m_packages.count() - 1); qDeleteAll(m_packages); m_packages.clear(); endRemoveRows(); emit countChanged(); } if (!selected.isEmpty()) { processPaths(selected); } const QStringList dirs = KGlobal::dirs()->findDirs("wallpaper", ""); kDebug() << "going looking in" << dirs; BackgroundFinder *finder = new BackgroundFinder(m_structureParent.data(), dirs); connect(finder, SIGNAL(backgroundsFound(QStringList,QString)), this, SLOT(backgroundsFound(QStringList,QString))); m_findToken = finder->token(); finder->start(); } void BackgroundListModel::backgroundsFound(const QStringList &paths, const QString &token) { if (token == m_findToken) { processPaths(paths); } } void BackgroundListModel::processPaths(const QStringList &paths) { QList newPackages; foreach (const QString &file, paths) { if (!contains(file) && QFile::exists(file)) { Plasma::PackageStructure::Ptr structure = Plasma::Wallpaper::packageStructure(m_structureParent.data()); Plasma::Package *package = new Plasma::Package(file, structure); if (package->isValid()) { newPackages << package; } else { delete package; } } } // add new files to dirwatch foreach (Plasma::Package *b, newPackages) { if (!m_dirwatch.contains(b->path())) { m_dirwatch.addFile(b->path()); } } if (!newPackages.isEmpty()) { const int start = rowCount(); beginInsertRows(QModelIndex(), start, start + newPackages.size()); m_packages.append(newPackages); endInsertRows(); emit countChanged(); } //kDebug() << t.elapsed(); } void BackgroundListModel::addBackground(const QString& path) { if (!contains(path)) { if (!m_dirwatch.contains(path)) { m_dirwatch.addFile(path); } beginInsertRows(QModelIndex(), 0, 0); Plasma::PackageStructure::Ptr structure = Plasma::Wallpaper::packageStructure(m_structureParent.data()); Plasma::Package *pkg = new Plasma::Package(path, structure); m_packages.prepend(pkg); endInsertRows(); emit countChanged(); } } QModelIndex BackgroundListModel::indexOf(const QString &path) const { for (int i = 0; i < m_packages.size(); i++) { // packages will end with a '/', but the path passed in may not QString package = m_packages[i]->path(); if (package.at(package.length() - 1) == '/') { package.truncate(package.length() - 1); } if (path.startsWith(package)) { // FIXME: ugly hack to make a difference between local files in the same dir // package->path does not contain the actual file name if ((!m_packages[i]->structure()->contentsPrefixPaths().isEmpty()) || (path == m_packages[i]->filePath("preferred"))) { return index(i, 0); } } } return QModelIndex(); } bool BackgroundListModel::contains(const QString &path) const { return indexOf(path).isValid(); } int BackgroundListModel::rowCount(const QModelIndex &) const { return m_packages.size(); } QSize BackgroundListModel::bestSize(Plasma::Package *package) const { if (m_sizeCache.contains(package)) { return m_sizeCache.value(package); } const QString image = package->filePath("preferred"); if (image.isEmpty()) { return QSize(); } KFileMetaInfo info(image, QString(), KFileMetaInfo::TechnicalInfo); QSize size(info.item("http://freedesktop.org/standards/xesam/1.0/core#width").value().toInt(), info.item("http://freedesktop.org/standards/xesam/1.0/core#height").value().toInt()); //backup solution if strigi does not work if (size.width() == 0 || size.height() == 0) { // kDebug() << "fall back to QImage, check your strigi"; ImageSizeFinder *finder = new ImageSizeFinder(image); connect(finder, SIGNAL(sizeFound(QString,QSize)), this, SLOT(sizeFound(QString,QSize))); QThreadPool::globalInstance()->start(finder); size = QSize(-1, -1); } const_cast(this)->m_sizeCache.insert(package, size); return size; } void BackgroundListModel::sizeFound(const QString &path, const QSize &s) { QModelIndex index = indexOf(path); if (index.isValid()) { Plasma::Package *package = m_packages.at(index.row()); m_sizeCache.insert(package, s); emit dataChanged(index, index); } } void BackgroundListModel::setScreenshotSize(const QSize &size) { if (m_screenshotSize == size) { return; } m_screenshotSize = size; //all screenshots have to be repainted emit dataChanged(index(0), index(rowCount())); } QSize BackgroundListModel::screenshotSize() const { return m_screenshotSize; } void BackgroundListModel::setTargetSizeHint(const QSize &size) { if (m_structureParent) { m_structureParent.data()->setTargetSizeHint(size); } } QVariant BackgroundListModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (index.row() >= m_packages.size()) { return QVariant(); } Plasma::Package *b = package(index.row()); if (!b) { return QVariant(); } switch (role) { case Qt::DisplayRole: { QString title = b->metadata().name(); if (title.isEmpty()) { return QFileInfo(b->filePath("preferred")).completeBaseName(); } return title; } break; case ScreenshotRole: { if (m_previews.contains(b)) { return m_previews.value(b); } KUrl file(b->filePath("preferred")); if (!m_previewJobs.contains(file) && file.isValid()) { KFileItemList list; list.append(KFileItem(file, QString(), 0)); KIO::PreviewJob* job = KIO::filePreview(list, m_screenshotSize); job->setIgnoreMaximumSize(true); - connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)), - this, SLOT(showPreview(const KFileItem&, const QPixmap&))); - connect(job, SIGNAL(failed(const KFileItem&)), - this, SLOT(previewFailed(const KFileItem&))); + connect(job, SIGNAL(gotPreview(KFileItem,QPixmap)), + this, SLOT(showPreview(KFileItem,QPixmap))); + connect(job, SIGNAL(failed(KFileItem)), + this, SLOT(previewFailed(KFileItem))); const_cast(this)->m_previewJobs.insert(file, QPersistentModelIndex(index)); } const_cast(this)->m_previews.insert(b, m_previewUnavailablePix); return m_previewUnavailablePix; } break; case AuthorRole: return b->metadata().author(); break; case ResolutionRole:{ QSize size = bestSize(b); if (size.isValid()) { return QString("%1x%2").arg(size.width()).arg(size.height()); } return QString(); } break; default: return QVariant(); break; } } void BackgroundListModel::showPreview(const KFileItem &item, const QPixmap &preview) { QPersistentModelIndex index = m_previewJobs.value(item.url()); m_previewJobs.remove(item.url()); if (!index.isValid()) { return; } Plasma::Package *b = package(index.row()); if (!b) { return; } m_previews.insert(b, preview); //kDebug() << "preview size:" << preview.size(); emit dataChanged(index, index); } void BackgroundListModel::previewFailed(const KFileItem &item) { m_previewJobs.remove(item.url()); } Plasma::Package* BackgroundListModel::package(int index) const { return m_packages.at(index); } BackgroundFinder::BackgroundFinder(Plasma::Wallpaper *structureParent, const QStringList &paths) : QThread(structureParent), m_structure(Plasma::Wallpaper::packageStructure(structureParent)), m_paths(paths), m_token(QUuid().toString()) { } BackgroundFinder::~BackgroundFinder() { wait(); } QString BackgroundFinder::token() const { return m_token; } void BackgroundFinder::run() { //QTime t; //t.start(); QSet suffixes; suffixes << "png" << "jpeg" << "jpg" << "svg" << "svgz"; QStringList papersFound; //kDebug() << "starting with" << m_paths; QDir dir; dir.setFilter(QDir::AllDirs | QDir::Files | QDir::Hidden | QDir::Readable); Plasma::Package pkg(QString(), m_structure); int i; for (i = 0; i < m_paths.count(); ++i) { const QString path = m_paths.at(i); //kDebug() << "doing" << path; dir.setPath(path); const QFileInfoList files = dir.entryInfoList(); foreach (const QFileInfo &wp, files) { if (wp.isDir()) { //kDebug() << "directory" << wp.fileName() << validPackages.contains(wp.fileName()); const QString name = wp.fileName(); if (name == "." || name == "..") { // do nothing continue; } const QString filePath = wp.filePath(); if (QFile::exists(filePath + "/metadata.desktop")) { pkg.setPath(filePath); if (pkg.isValid()) { papersFound << pkg.path(); continue; //kDebug() << "gots a" << wp.filePath(); } } // add this to the directories we should be looking at m_paths.append(filePath); } else if (suffixes.contains(wp.suffix().toLower())) { //kDebug() << " adding image file" << wp.filePath(); papersFound << wp.filePath(); } } } //kDebug() << "background found!" << papersFound.size() << "in" << i << "dirs, taking" << t.elapsed() << "ms"; emit backgroundsFound(papersFound, m_token); deleteLater(); } #include "backgroundlistmodel.moc" #endif // BACKGROUNDLISTMODEL_CPP diff --git a/shell/firstrun/app.cpp b/shell/firstrun/app.cpp index 75048b4c..ca113f6a 100644 --- a/shell/firstrun/app.cpp +++ b/shell/firstrun/app.cpp @@ -1,40 +1,40 @@ /* * Copyright 2011 Sebastian Kügler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "firstrun.h" #include "app.h" #include "kdebug.h" App::App(int argc, char **argv) : QApplication(argc, argv), m_firstRun(0) { m_firstRun = new FirstRun(this); kDebug() << "connecting..."; connect(m_firstRun, SIGNAL(done()), SLOT(quit())); //quit(); //exit(); } App::~App() { } -#include "app.moc" \ No newline at end of file +#include "app.moc" diff --git a/shell/mobcorona.cpp b/shell/mobcorona.cpp index 4c8eb545..4f06139c 100644 --- a/shell/mobcorona.cpp +++ b/shell/mobcorona.cpp @@ -1,454 +1,454 @@ /*************************************************************************** * Copyright 2006-2008 Aaron Seigo * * Copyright 2009 Marco Martin * * Copyright 2010 Alexis Menard * * Copyright 2010 Artur Duque de Souza * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "mobcorona.h" #include "mobdialogmanager.h" #include "activity.h" #include "kao.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "plasmaapp.h" #include "mobview.h" #include #include #include #include #include #include #include static const char *DEFAUL_CONTAINMENT = "org.kde.active.activityscreen"; MobCorona::MobCorona(QObject *parent) : Plasma::Corona(parent), m_activityController(new KActivities::Controller(this)), m_package(0) { init(); } MobCorona::~MobCorona() { KConfigGroup cg(config(), "SavedContainments"); //stop everything, in order to restore them just on demand at next boot const QString currentActivity = m_activityController->currentActivity(); QHash::const_iterator i = m_activities.constBegin(); while (i != m_activities.constEnd()) { QString file = "activities/"+i.key(); KConfig external(file, KConfig::SimpleConfig, "appdata"); //copy the old config to the new location i.value()->save(external); if (i.key() != currentActivity) { i.value()->close(); } ++i; } //get rid of containments and their config groups foreach (Plasma::Containment *cont, containments()) { if (cont->context()->currentActivityId() != currentActivity && cont->formFactor() == Plasma::Planar) { cont->config().deleteGroup(); cont->destroy(false); } } } void MobCorona::init() { QString homeScreenPath = KGlobal::mainComponent().componentName() + "-homescreen"; KConfigGroup globalConfig(KGlobal::config(), "General"); homeScreenPath = globalConfig.readEntry("HomeScreenPackage", "org.kde.active.contour-tablet-homescreen"); kDebug()<<"Searching for the home screen"<isValid()) { kWarning()<<"Invalid home screen package:"<filePath("config", "plasma-default-layoutrc"); //kDebug() << "============================================================================"; //kDebug() << "layout HSP:" << homeScreenPath; //kDebug() << "layout RC :" << layoutRc; //kDebug() << "layout CFG:" << defaultConfig; if (!defaultConfig.isEmpty()) { kDebug() << "attempting to load the default layout from:" << defaultConfig; return KConfigGroup(new KConfig(defaultConfig), QString()); } kWarning() << "Invalid layout, could not locate plasma-default-layoutrc"; return KConfigGroup(); } void MobCorona::loadDefaultLayout() { KConfigGroup cg = defaultConfig(); if (cg.isValid()) { importLayout(cg); return; } kWarning() << "Invalid layout, could not locate plasma-default-layoutrc"; // FIXME: need to load the Mobile-specific containment // passing in an empty string will get us whatever the default // containment type is! Plasma::Containment* c = addContainmentDelayed(QString()); if (!c) { return; } c->init(); KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); bool isDesktop = args->isSet("desktop"); if (isDesktop) { c->setScreen(0); } c->setWallpaper("image", "SingleImage"); c->setFormFactor(Plasma::Planar); c->updateConstraints(Plasma::StartupCompletedConstraint); c->flushPendingConstraintsEvents(); //cg is invalid here c->save(cg); // stacks all the containments at the same place c->setPos(0, 0); emit containmentAdded(c); requestConfigSync(); } void MobCorona::layoutContainments() { // we dont need any layout for this as we are going to bind the position // of the containments to QML items to animate them. As soon as we don't // need the containment anymore we can just let it stay wherever it is as // long as it's offscreen (the view is not 'looking' at it). // As this method is called from containments resize event and itemChange // if we let the default implementation work here we could have bad surprises // of containments appearing in the view when putting them in the default // grid-like layout. return; } Plasma::Applet *MobCorona::loadDefaultApplet(const QString &pluginName, Plasma::Containment *c) { QVariantList args; Plasma::Applet *applet = Plasma::Applet::load(pluginName, 0, args); if (applet) { c->addApplet(applet); } return applet; } Plasma::Containment *MobCorona::findFreeContainment() const { foreach (Plasma::Containment *cont, containments()) { if ((cont->containmentType() == Plasma::Containment::DesktopContainment || cont->containmentType() == Plasma::Containment::CustomContainment) && cont->screen() == -1 && !offscreenWidgets().contains(cont)) { return cont; } } return 0; } int MobCorona::numScreens() const { return QApplication::desktop()->screenCount(); } void MobCorona::setScreenGeometry(const QRect &geometry) { m_screenGeometry = geometry; } QRect MobCorona::screenGeometry(int id) const { Q_UNUSED(id) return m_screenGeometry; } void MobCorona::setAvailableScreenRegion(const QRegion &r) { m_availableScreenRegion = r; emit availableScreenRegionChanged(); } QRegion MobCorona::availableScreenRegion(int id) const { QRegion r(screenGeometry(id)); return m_availableScreenRegion; foreach (Plasma::Containment *cont, PlasmaApp::self()->panelContainments()) { if (cont->location() == Plasma::TopEdge || cont->location() == Plasma::BottomEdge || cont->location() == Plasma::LeftEdge || cont->location() == Plasma::RightEdge) { r = r.subtracted(cont->mapToScene(cont->boundingRect()).toPolygon()); } } return r; } void MobCorona::currentActivityChanged(const QString &newActivity) { if (newActivity.isEmpty()) { return; } kDebug() << newActivity; Activity *act =activity(newActivity); if (act) { act->ensureActive(); } } Activity* MobCorona::activity(const QString &id) { if (!m_activities.contains(id)) { //the add signal comes late sometimes activityAdded(id); } return m_activities.value(id); } void MobCorona::activityAdded(const QString &id) { //TODO more sanity checks if (m_activities.contains(id)) { kDebug() << "you're late." << id; return; } Activity *a = new Activity(id, this); if (a->isCurrent()) { a->ensureActive(); } m_activities.insert(id, a); } void MobCorona::activityRemoved(const QString &id) { Activity *a = m_activities.take(id); a->deleteLater(); } void MobCorona::activateNextActivity() { QStringList list = m_activityController->listActivities(KActivities::Info::Running); if (list.isEmpty()) { return; } //FIXME: if the current activity is in transition the "next" will be the first int start = list.indexOf(m_activityController->currentActivity()); int i = (start + 1) % list.size(); m_activityController->setCurrentActivity(list.at(i)); } void MobCorona::activatePreviousActivity() { QStringList list = m_activityController->listActivities(KActivities::Info::Running); if (list.isEmpty()) { return; } //FIXME: if the current activity is in transition the "previous" will be the last int start = list.indexOf(m_activityController->currentActivity()); //fun fact: in c++, (-1 % foo) == -1 int i = start - 1; if (i < 0) { i = list.size() - 1; } m_activityController->setCurrentActivity(list.at(i)); } void MobCorona::checkActivities() { kDebug() << "containments to start with" << containments().count(); KActivities::Consumer::ServiceStatus status = m_activityController->serviceStatus(); //kDebug() << "$%$%$#%$%$%Status:" << status; if (status == KActivities::Consumer::NotRunning) { //panic and give up - better than causing a mess kDebug() << "No ActivityManager? Help, I've fallen and I can't get up!"; return; } QStringList existingActivities = m_activityController->listActivities(); foreach (const QString &id, existingActivities) { //ensure the activity resource exists //FIXME: shouldn't be done here Nepomuk::Resource activityResource(id, Nepomuk::Vocabulary::KAO::Activity()); activityResource.setProperty(Nepomuk::Vocabulary::KAO::activityIdentifier(), id); activityAdded(id); } QStringList newActivities; QString newCurrentActivity; //migration checks: //-containments with an invalid id are deleted. //-containments that claim they were on a screen are kept together, and are preferred if we //need to initialize the current activity. //-containments that don't know where they were or who they were with just get made into their //own activity. foreach (Plasma::Containment *cont, containments()) { bool excludeFromActivities = cont->config().readEntry("excludeFromActivities", false); if (!excludeFromActivities && (cont->containmentType() == Plasma::Containment::DesktopContainment || cont->containmentType() == Plasma::Containment::CustomContainment) && !offscreenWidgets().contains(cont)) { Plasma::Context *context = cont->context(); QString oldId = context->currentActivityId(); if (!oldId.isEmpty()) { if (existingActivities.contains(oldId)) { continue; //it's already claimed } kDebug() << "invalid id" << oldId; //byebye cont->destroy(false); continue; } if (cont->screen() > -1) { //it belongs on the current activity if (!newCurrentActivity.isEmpty()) { context->setCurrentActivityId(newCurrentActivity); continue; } } //discourage blank names if (context->currentActivity().isEmpty()) { context->setCurrentActivity(i18nc("Default name for a new activity", "New Activity")); } //create a new activity for the containment QString id = m_activityController->addActivity(context->currentActivity()); context->setCurrentActivityId(id); newActivities << id; if (cont->screen() > -1) { newCurrentActivity = id; } kDebug() << "migrated" << context->currentActivityId() << context->currentActivity(); QString activityIcon = cont->config().readEntry("activityIcon", QString()); if (!activityIcon.isEmpty()) { m_activityController->setActivityIcon(id, activityIcon); } } } kDebug() << "migrated?" << !newActivities.isEmpty() << containments().count(); if (!newActivities.isEmpty()) { requestConfigSync(); } //init the newbies foreach (const QString &id, newActivities) { activityAdded(id); } //ensure the current activity is initialized if (m_activityController->currentActivity().isEmpty()) { kDebug() << "guessing at current activity"; if (existingActivities.isEmpty()) { if (newCurrentActivity.isEmpty()) { if (newActivities.isEmpty()) { kDebug() << "no activities!?! Bad activitymanager, no cookie!"; QString id = m_activityController->addActivity(i18nc("Default name for a new activity", "New Activity")); activityAdded(id); m_activityController->setCurrentActivity(id); kDebug() << "created emergency activity" << id; } else { m_activityController->setCurrentActivity(newActivities.first()); } } else { m_activityController->setCurrentActivity(newCurrentActivity); } } else { m_activityController->setCurrentActivity(existingActivities.first()); } } } Plasma::Package *MobCorona::homeScreenPackage() const { return m_package; } #include "mobcorona.moc" diff --git a/shell/mobileactivitythumbnails/mobileactivitythumbnails.cpp b/shell/mobileactivitythumbnails/mobileactivitythumbnails.cpp index 46dca2ed..5f280d91 100644 --- a/shell/mobileactivitythumbnails/mobileactivitythumbnails.cpp +++ b/shell/mobileactivitythumbnails/mobileactivitythumbnails.cpp @@ -1,128 +1,128 @@ /* * Copyright 2011 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "mobileactivitythumbnails.h" #include "imagescaler.h" #include #include #include #include #include #include #include #include #include #include #include #include MobileActivityThumbnails::MobileActivityThumbnails(QObject *parent, const QVariantList &args) : Plasma::DataEngine(parent, args) { m_consumer = new KActivities::Consumer(this); } bool MobileActivityThumbnails::sourceRequestEvent(const QString &source) { if (!m_consumer->listActivities().contains(source)) { return false; } QString path = KStandardDirs::locateLocal("data", QString("plasma/activities-screenshots/%1.png").arg(source)); if (QFile::exists(path)) { QImage image(path); DataEngine::Data data; data.insert("path", path); data.insert("image", image); setData(source, data); } else { setData(source, "path", QString()); } // as we successfully set up the source, return true return true; } void MobileActivityThumbnails::snapshotContainment(Plasma::Containment *containment) { if (!containment || !containment->wallpaper()) { return; } QImage activityImage = QImage(containment->size().toSize(), QImage::Format_ARGB32); KConfigGroup cg = containment->config(); cg = KConfigGroup(&cg, "Wallpaper"); cg = KConfigGroup(&cg, "image"); QString wallpaperPath = cg.readEntry("wallpaper"); if (QDir::isAbsolutePath(wallpaperPath)) { Plasma::Package b(wallpaperPath, containment->wallpaper()->packageStructure(containment->wallpaper())); wallpaperPath = b.filePath("preferred"); //kDebug() << img << wallpaperPath; if (wallpaperPath.isEmpty() && QFile::exists(wallpaperPath)) { wallpaperPath = wallpaperPath; } } else { //if it's not an absolute path, check if it's just a wallpaper name const QString path = KStandardDirs::locate("wallpaper", wallpaperPath + "/metadata.desktop"); if (!path.isEmpty()) { QDir dir(path); dir.cdUp(); Plasma::Package b(dir.path(), containment->wallpaper()->packageStructure(containment->wallpaper())); wallpaperPath = b.filePath("preferred"); } } const QString activity = containment->context()->currentActivityId(); ImageScaler *scaler = new ImageScaler(QImage(wallpaperPath), QSize(300, 200)); scaler->setActivity(activity); - connect(scaler, SIGNAL(scaled(QString, QImage)), this, SLOT(imageScaled(QString, QImage))); + connect(scaler, SIGNAL(scaled(QString,QImage)), this, SLOT(imageScaled(QString,QImage))); scaler->setAutoDelete(true); QThreadPool::globalInstance()->start(scaler); } void MobileActivityThumbnails::imageScaled(const QString &activity, const QImage &image) { const QString path = KStandardDirs::locateLocal("data", QString("plasma/activities-screenshots/%1.png").arg(activity)); Plasma::DataContainer *container = containerForSource(activity); //kDebug() << "setting the thumbnail for" << activity << path << container; if (container) { container->setData("path", path); container->setData("image", image); scheduleSourcesUpdated(); } } K_EXPORT_PLASMA_DATAENGINE(org.kde.mobileactivitythumbnails, MobileActivityThumbnails) #include "mobileactivitythumbnails.moc" diff --git a/shell/plasmaapp.cpp b/shell/plasmaapp.cpp index 117c134a..94b45686 100644 --- a/shell/plasmaapp.cpp +++ b/shell/plasmaapp.cpp @@ -1,633 +1,633 @@ /*************************************************************************** * Copyright 2006-2008 Aaron Seigo * * Copyright 2009 Marco Martin * * Copyright 2010 Alexis Menard * * Copyright 2010 Artur Duque de Souza * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "plasmaapp.h" #include "busywidget.h" #include "mobview.h" #include "mobcorona.h" #include "mobpluginloader.h" #include "mobileactivitythumbnails/mobileactivitythumbnails.h" #include "widgetsexplorer/mobilewidgetsexplorer.h" #include "activityconfiguration/activityconfiguration.h" #include "panelproxy.h" #include "panelshadows.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../components/runnermodel/runnermodel.h" #ifdef Q_WS_X11 #include #include #endif PlasmaApp* PlasmaApp::self() { if (!kapp) { return new PlasmaApp(); } return qobject_cast(kapp); } PlasmaApp::PlasmaApp() : KUniqueApplication(), m_corona(0), m_mainView(0), m_declarativeWidget(0), m_currentContainment(0), m_panelShadows(0), m_isDesktop(false) { KGlobal::locale()->insertCatalog("libplasma"); KGlobal::locale()->insertCatalog("plasma-device"); KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); Nepomuk::ResourceManager::instance()->init(); qmlRegisterType("org.kde.plasma.deviceshell", 0, 1, "DevicePanel"); qmlRegisterUncreatableType("org.kde.plasma.deviceshell", 0, 1, "ContainmentProperties", "ContainmentProperties is just a type holder"); //FIXME: why does not work? //qmlRegisterInterface("Wallpaper"); //qRegisterMetaType("Wallpaper"); bool useGL = args->isSet("opengl"); if (!useGL) { //use plasmarc to share this with plasma-windowed KConfigGroup cg(KSharedConfig::openConfig("plasmarc"), "General"); useGL = cg.readEntry("UseOpenGl", false); } m_mainView = new MobView(0, MobView::mainViewId(), 0); m_mainView->setWindowTitle(i18n("Home Screen")); m_mainView->setUseGL(useGL); bool isDesktop = args->isSet("desktop"); if (isDesktop) { notifyStartup(false); KCrash::setFlags(KCrash::AutoRestart); } int width = 800; int height = 480; if (isDesktop) { QRect rect = QApplication::desktop()->screenGeometry(m_mainView->screen()); width = rect.width(); height = rect.height(); } else { QAction *action = KStandardAction::quit(qApp, SLOT(quit()), m_mainView); m_mainView->addAction(action); QString geom = args->getOption("screen"); int x = geom.indexOf('x'); if (x > 0) { width = qMax(width, geom.left(x).toInt()); height = qMax(height, geom.right(geom.length() - x - 1).toInt()); } } bool isFullScreen = args->isSet("fullscreen"); if (isFullScreen) { m_mainView->showFullScreen(); } setIsDesktop(isDesktop); m_mainView->setFixedSize(width, height); m_mainView->move(0,0); KConfigGroup cg(KSharedConfig::openConfig("plasmarc"), "Theme-plasma-device"); const QString themeName = cg.readEntry("name", "air-mobile"); Plasma::Theme::defaultTheme()->setUseGlobalSettings(false); Plasma::Theme::defaultTheme()->setThemeName(themeName); cg = KConfigGroup(KGlobal::config(), "General"); Plasma::Theme::defaultTheme()->setFont(cg.readEntry("desktopFont", font())); m_pluginLoader = new MobPluginLoader; Plasma::PluginLoader::setPluginLoader(m_pluginLoader); Plasma::ToolTipManager::self()->setState(Plasma::ToolTipManager::Deactivated); // this line initializes the corona and setups the main qml homescreen corona(); connect(this, SIGNAL(aboutToQuit()), this, SLOT(cleanup())); if (isDesktop) { notifyStartup(true); } m_startupInfo = new KStartupInfo(KStartupInfo::CleanOnCantDetect, this ); connect(m_startupInfo, - SIGNAL(gotNewStartup(const KStartupInfoId&, const KStartupInfoData&)), - SLOT(gotStartup(const KStartupInfoId&, const KStartupInfoData&))); + SIGNAL(gotNewStartup(KStartupInfoId,KStartupInfoData)), + SLOT(gotStartup(KStartupInfoId,KStartupInfoData))); connect(m_startupInfo, - SIGNAL(gotStartupChange(const KStartupInfoId&, const KStartupInfoData&)), - SLOT(gotStartup(const KStartupInfoId&, const KStartupInfoData&))); + SIGNAL(gotStartupChange(KStartupInfoId,KStartupInfoData)), + SLOT(gotStartup(KStartupInfoId,KStartupInfoData))); connect(m_startupInfo, - SIGNAL(gotRemoveStartup(const KStartupInfoId&, const KStartupInfoData&)), - SLOT(killStartup(const KStartupInfoId&))); + SIGNAL(gotRemoveStartup(KStartupInfoId,KStartupInfoData)), + SLOT(killStartup(KStartupInfoId))); } PlasmaApp::~PlasmaApp() { } QList PlasmaApp::containments() const { return m_containments.values(); } QList PlasmaApp::panelContainments() const { return m_panelContainments.values(); } PanelShadows *PlasmaApp::panelShadows() { if (!m_panelShadows) { m_panelShadows = new PanelShadows(this); } return m_panelShadows; } void PlasmaApp::cleanup() { if (m_corona) { m_corona->saveLayout(); } delete m_mainView; m_mainView = 0; delete m_corona; m_corona = 0; //TODO: This manual sync() should not be necessary? syncConfig(); } void PlasmaApp::setIsDesktop(bool isDesktop) { m_isDesktop = isDesktop; if (isDesktop) { //FIXME: remove close button *and* window border: possible? KWindowSystem::setType(m_mainView->winId(), NET::Normal); m_mainView->setWindowFlags((m_mainView->windowFlags() | Qt::FramelessWindowHint /*| Qt::CustomizeWindowHint*/) /*& ~Qt::WindowCloseButtonHint*/); KWindowSystem::setOnAllDesktops(m_mainView->winId(), true); m_mainView->show(); } else { m_mainView->setWindowFlags(((m_mainView->windowFlags() | Qt::CustomizeWindowHint) & ~Qt::FramelessWindowHint) & ~Qt::WindowCloseButtonHint); KWindowSystem::setOnAllDesktops(m_mainView->winId(), false); KWindowSystem::setType(m_mainView->winId(), NET::Normal); } } void PlasmaApp::syncConfig() { KGlobal::config()->sync(); } void PlasmaApp::setupHomeScreen() { //The home screen can be set up a single time Q_ASSERT(!m_declarativeWidget); m_declarativeWidget = new Plasma::DeclarativeWidget(); m_corona->addItem(m_declarativeWidget); m_homeScreenPath = m_corona->homeScreenPackage()->filePath("mainscript"); if (m_homeScreenPath.isEmpty()) { kWarning() << "Could not find an home screen, exiting."; QTimer::singleShot(0, QCoreApplication::instance(), SLOT(quit())); return; } kDebug() << "Loading " << m_homeScreenPath; m_declarativeWidget->setQmlPath(m_homeScreenPath); if (!m_declarativeWidget->engine()) { kDebug() << "Invalid main declarative engine, exiting."; QTimer::singleShot(0, QCoreApplication::instance(), SLOT(quit())); return; } m_homeScreen = qobject_cast(m_declarativeWidget->rootObject()); if (!m_homeScreen) { kError() << "Error in creation of the homescreen object, exiting. " << m_homeScreenPath; QTimer::singleShot(0, QCoreApplication::instance(), SLOT(quit())); return; } mainViewGeometryChanged(); connect(m_mainView, SIGNAL(geometryChanged()), this, SLOT(mainViewGeometryChanged())); connect(m_mainView, SIGNAL(containmentActivated()), this, SLOT(mainContainmentActivated())); connect(m_homeScreen, SIGNAL(focusActivityView()), this, SLOT(focusMainView())); KAction *focusHomeAction = new KAction(this); focusHomeAction->setObjectName("Focus Homescreen"); focusHomeAction->setGlobalShortcut( KShortcut(QKeySequence(Qt::Key_Home)), KAction::ShortcutTypes(KAction::ActiveShortcut | KAction::DefaultShortcut), KAction::NoAutoloading); connect(focusHomeAction, SIGNAL(triggered()), this, SLOT(focusMainView())); connect(m_homeScreen, SIGNAL(newActivityRequested()), this, SLOT(showActivityCreation())); m_mainView->setSceneRect(m_homeScreen->x(), m_homeScreen->y(), m_homeScreen->width(), m_homeScreen->height()); } void PlasmaApp::changeContainment(Plasma::Containment *containment) { QDeclarativeProperty containmentProperty(m_homeScreen, "activeContainment"); containmentProperty.write(QVariant::fromValue(static_cast(containment))); m_oldContainment = m_currentContainment; m_currentContainment = containment; } Plasma::Corona* PlasmaApp::corona() { if (!m_corona) { m_corona = new MobCorona(this); m_corona->setItemIndexMethod(QGraphicsScene::NoIndex); m_corona->setScreenGeometry(QRect(QPoint(0,0), m_mainView->size())); //FIXME libplasma2: qml containments cannot set containmentType before this signal is emitted connect(m_corona, SIGNAL(containmentAdded(Plasma::Containment*)), this, SLOT(manageNewContainment(Plasma::Containment*)), Qt::QueuedConnection); connect(m_corona, SIGNAL(configSynced()), this, SLOT(syncConfig())); - connect(m_corona, SIGNAL(screenOwnerChanged(int, int, Plasma::Containment *)), this, SLOT(containmentScreenOwnerChanged(int,int,Plasma::Containment*))); + connect(m_corona, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment*)), this, SLOT(containmentScreenOwnerChanged(int,int,Plasma::Containment*))); // setup our QML home screen; setupHomeScreen(); m_corona->initializeLayout(); m_mainView->setScene(m_corona); m_corona->checkActivities(); m_mainView->show(); } return m_corona; } QSize PlasmaApp::defaultScreenSize() { return QSize(1366, 768); } void PlasmaApp::notifyStartup(bool completed) { org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus()); const QString startupID("mobile desktop"); if (completed) { ksmserver.resumeStartup(startupID); } else { ksmserver.suspendStartup(startupID); } } void PlasmaApp::mainContainmentActivated() { const WId id = m_mainView->effectiveWinId(); QWidget * activeWindow = QApplication::activeWindow(); KWindowSystem::raiseWindow(id); if (activeWindow) { KWindowSystem::raiseWindow(activeWindow->effectiveWinId()); m_mainView->activateWindow(); activeWindow->setFocus(); } else { m_mainView->activateWindow(); } } void PlasmaApp::manageNewContainment(Plasma::Containment *containment) { if (m_containments.contains(containment->id()) || m_panelContainments.contains(containment->id())) { return; } QAction *addAction = containment->action("add widgets"); if (addAction) { connect(addAction, SIGNAL(triggered()), this, SLOT(showWidgetsExplorer())); } connect(containment, SIGNAL(configureRequested(Plasma::Containment*)), this, SLOT(showActivityConfiguration(Plasma::Containment*))); //is it a panel? if (containment->location() == Plasma::LeftEdge || containment->location() == Plasma::TopEdge || containment->location() == Plasma::RightEdge || containment->location() == Plasma::BottomEdge) { m_panelContainments.insert(containment->id(), containment); //add the panel into the QML homescreen m_homeScreen->metaObject()->invokeMethod(m_homeScreen, "addPanel", Q_ARG(QVariant, QVariant::fromValue(containment)), Q_ARG(QVariant, containment->formFactor()), Q_ARG(QVariant, containment->location())); //done, don't need further management return; } // add the containment and it identifier to a hash to enable us // to retrieve it later. m_containments.insert(containment->id(), containment); - connect(containment, SIGNAL(destroyed(QObject *)), this, SLOT(containmentDestroyed(QObject *))); + connect(containment, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed(QObject*))); containment->resize(m_mainView->size()); //FIXME: avoidable all this disk access at startup? QString path = KStandardDirs::locateLocal("data", QString("plasma/activities-screenshots/%1.png").arg(containment->context()->currentActivityId())); if (!QFile::exists(path)) { m_pluginLoader->activityThumbnails()->snapshotContainment(containment); } // we need our homescreen to show something! if (containment->config().readEntry("excludeFromActivities", false)) { //Do nothing! //Don't remove this empty branch } else if (containment->screen() > -1) { changeContainment(containment); } else { containment->setPos(m_mainView->width(), m_mainView->height()); // containment->setVisible(false); } KConfigGroup cg = containment->config(); cg = KConfigGroup(&cg, "General"); } void PlasmaApp::focusMainView() { if (m_mainView) { KWindowSystem::forceActiveWindow(m_mainView->winId()); } } void PlasmaApp::mainViewGeometryChanged() { if (m_declarativeWidget) { //sometimes a geometry change arives very early in the ctor corona(); m_declarativeWidget->resize(m_mainView->size()); //m_declarativeWidget->setPos(m_mainView->mapToScene(QPoint(0,0))); m_declarativeWidget->setGeometry(m_mainView->mapToScene(QRect(QPoint(0,0), m_mainView->size())).boundingRect()); QRect availableScreenRect(QPoint(0,0), m_mainView->size()); QDeclarativeItem *availableScreenRectItem = m_homeScreen->property("availableScreenRect").value(); //is there an item that defines the screen geometry? if (availableScreenRectItem) { availableScreenRect = QRect((int)availableScreenRectItem->property("x").toReal(), (int)availableScreenRectItem->property("y").toReal(), (int)availableScreenRectItem->property("width").toReal(), (int)availableScreenRectItem->property("height").toReal()); const int left = availableScreenRectItem->property("leftReserved").toInt(); const int top = availableScreenRectItem->property("topReserved").toInt(); const int right = availableScreenRectItem->property("rightReserved").toInt(); const int bottom = availableScreenRectItem->property("bottomReserved").toInt(); reserveStruts(left, top, right, bottom); } m_corona->setScreenGeometry(QRect(QPoint(0, 0), m_mainView->size())); m_corona->setAvailableScreenRegion(availableScreenRect); if (m_currentContainment) { m_currentContainment->resize(m_mainView->size()); } if (m_widgetsExplorer) { m_widgetsExplorer.data()->setGeometry(m_declarativeWidget->geometry()); } } } void PlasmaApp::reserveStruts(const int left, const int top, const int right, const int bottom) { if (!m_mainView) { return; } if (!m_isDesktop) { KWindowSystem::setExtendedStrut(m_mainView->winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); return; } NETExtendedStrut strut; if (left) { strut.left_width = left; strut.left_start = m_mainView->y(); strut.left_end = m_mainView->y() + m_mainView->height() - 1; } if (right) { strut.right_width = right; strut.right_start = m_mainView->y(); strut.right_end = m_mainView->y() + m_mainView->height() - 1; } if (top) { strut.top_width = top; strut.top_start = m_mainView->x(); strut.top_end = m_mainView->x() + m_mainView->width() - 1; } if (bottom) { strut.bottom_width = bottom; strut.bottom_start = m_mainView->x(); strut.bottom_end = m_mainView->x() + m_mainView->width() - 1; } const QPoint oldPos = m_mainView->pos(); KWindowSystem::setExtendedStrut(m_mainView->winId(), strut.left_width, strut.left_start, strut.left_end, strut.right_width, strut.right_start, strut.right_end, strut.top_width, strut.top_start, strut.top_end, strut.bottom_width, strut.bottom_start, strut.bottom_end); //ensure the main view is at the proper position too m_mainView->move(oldPos); } void PlasmaApp::showWidgetsExplorer() { if (!m_widgetsExplorer) { m_widgetsExplorer = new MobileWidgetsExplorer(0); m_widgetsExplorer.data()->setZValue(1000); m_corona->addItem(m_widgetsExplorer.data()); } m_widgetsExplorer.data()->setContainment(m_currentContainment); if (m_declarativeWidget) { m_widgetsExplorer.data()->setGeometry(m_declarativeWidget->geometry()); } m_widgetsExplorer.data()->show(); } void PlasmaApp::showActivityCreation() { showActivityConfiguration(0); } void PlasmaApp::showActivityConfiguration(Plasma::Containment *containment) { if (!m_activityConfiguration) { m_activityConfiguration = new ActivityConfiguration(); connect(m_activityConfiguration.data(), SIGNAL(containmentWallpaperChanged(Plasma::Containment*)), this, SLOT(containmentWallpaperChanged(Plasma::Containment*))); m_activityConfiguration.data()->setZValue(1000); m_corona->addItem(m_activityConfiguration.data()); } m_activityConfiguration.data()->setContainment(containment); if (m_declarativeWidget) { m_activityConfiguration.data()->setGeometry(m_declarativeWidget->geometry()); } m_activityConfiguration.data()->show(); } void PlasmaApp::containmentWallpaperChanged(Plasma::Containment *containment) { if (m_pluginLoader->activityThumbnails()) { m_pluginLoader->activityThumbnails()->snapshotContainment(containment); } } void PlasmaApp::containmentDestroyed(QObject *object) { Plasma::Containment *cont = qobject_cast(object); if (cont) { m_containments.remove(cont->id()); } } void PlasmaApp::containmentScreenOwnerChanged(int wasScreen, int isScreen, Plasma::Containment *cont) { Q_UNUSED(wasScreen) bool excludeFromActivities = cont->config().readEntry("excludeFromActivities", false); if (!excludeFromActivities && isScreen >= 0 && (cont->location() == Plasma::Desktop || cont->location() == Plasma::Floating)) { changeContainment(cont); } } void PlasmaApp::gotStartup(const KStartupInfoId &id, const KStartupInfoData &data) { Q_UNUSED(id) Q_UNUSED(data) if (!m_busyWidget) { m_busyWidget = new BusyWidget(); } m_busyWidget.data()->setGeometry(m_mainView->geometry().center().x() - 128, m_mainView->geometry().bottom() - 78, 256, 78); KWindowSystem::setState(m_busyWidget.data()->winId(), NET::SkipTaskbar | NET::KeepAbove); Plasma::WindowEffects::slideWindow(m_busyWidget.data(), Plasma::BottomEdge); m_busyWidget.data()->show(); KWindowSystem::activateWindow(m_busyWidget.data()->winId(), 500); KWindowSystem::raiseWindow(m_busyWidget.data()->winId()); } void PlasmaApp::killStartup(const KStartupInfoId &id) { Q_UNUSED(id) if (!m_busyWidget) { return; } Plasma::WindowEffects::slideWindow(m_busyWidget.data(), Plasma::BottomEdge); m_busyWidget.data()->hide(); m_busyWidget.data()->deleteLater(); } #include "plasmaapp.moc" diff --git a/shell/widgetsexplorer/mobilewidgetsexplorer.cpp b/shell/widgetsexplorer/mobilewidgetsexplorer.cpp index d3508746..30d6897c 100644 --- a/shell/widgetsexplorer/mobilewidgetsexplorer.cpp +++ b/shell/widgetsexplorer/mobilewidgetsexplorer.cpp @@ -1,113 +1,113 @@ /*************************************************************************** * Copyright 2010 Alexis Menard * * Copyright 2010 Artur Duque de Souza * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ //own #include "mobilewidgetsexplorer.h" #include "plasmaappletitemmodel_p.h" //Qt #include #include #include #include #include #include #include #include //KDE #include #include //Plasma #include #include #include MobileWidgetsExplorer::MobileWidgetsExplorer(QGraphicsItem *parent) : QGraphicsWidget(parent), m_containment(0), m_mainWidget(0) { setContentsMargins(0, 0, 0, 0); m_declarativeWidget = new Plasma::DeclarativeWidget(this); QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(this); lay->setContentsMargins(0, 0, 0, 0); lay->addItem(m_declarativeWidget); m_appletsModel = new PlasmaAppletItemModel(this); m_appletsModel->setApplication(QString()); Plasma::PackageStructure::Ptr structure = Plasma::PackageStructure::load("Plasma/Generic"); m_package = new Plasma::Package(QString(), "org.kde.active.widgetexplorer", structure); m_declarativeWidget->setQmlPath(m_package->filePath("mainscript")); if (m_declarativeWidget->engine()) { QDeclarativeContext *ctxt = m_declarativeWidget->engine()->rootContext(); if (ctxt) { ctxt->setContextProperty("myModel", m_appletsModel); } m_mainWidget = qobject_cast(m_declarativeWidget->rootObject()); if (m_mainWidget) { - connect(m_mainWidget, SIGNAL(addAppletRequested(const QString &)), this, SLOT(addApplet(const QString &))); + connect(m_mainWidget, SIGNAL(addAppletRequested(QString)), this, SLOT(addApplet(QString))); connect(m_mainWidget, SIGNAL(closeRequested()), SLOT(doExit())); } } } MobileWidgetsExplorer::~MobileWidgetsExplorer() { } void MobileWidgetsExplorer::doExit() { QDBusMessage call = QDBusMessage::createMethodCall("org.kde.plasma-keyboardcontainer", "/MainApplication", "org.kde.plasma.VirtualKeyboard", "hide"); QDBusConnection::sessionBus().asyncCall(call); deleteLater(); } void MobileWidgetsExplorer::setContainment(Plasma::Containment *cont) { m_containment = cont; } Plasma::Containment *MobileWidgetsExplorer::containment() const { return m_containment; } void MobileWidgetsExplorer::addApplet(const QString &plugin) { if (m_mainWidget) { kWarning() << "Applet added" << plugin; if (m_containment) { m_containment->addApplet(plugin); } } } #include "mobilewidgetsexplorer.moc" diff --git a/virtualkeyboard/keyboardshell/keyboarddialog.cpp b/virtualkeyboard/keyboardshell/keyboarddialog.cpp index 3d8e4b4d..780b6233 100644 --- a/virtualkeyboard/keyboardshell/keyboarddialog.cpp +++ b/virtualkeyboard/keyboardshell/keyboarddialog.cpp @@ -1,374 +1,374 @@ /* * Copyright 2007-2008 Aaron Seigo * Copyright 2009 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "keyboarddialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include KeyboardDialog::KeyboardDialog(Plasma::Corona *corona, Plasma::Containment *containment, const QString &pluginName, int appletId, const QVariantList &appletArgs, QWidget *parent) : Plasma::Dialog(parent), m_applet(0), m_containment(0), m_corona(corona), m_location(Plasma::Floating), m_switchKeyboardLayoutScheduled(false) { setContainment(containment); m_closeButton = new Plasma::IconWidget(m_containment); m_closeButton->setSvg("widgets/configuration-icons", "close"); m_closeButton->setMaximumSize(QSize(KIconLoader::SizeMedium, KIconLoader::SizeMedium)); connect(m_closeButton, SIGNAL(clicked()), this, SLOT(hide())); m_keyboardLayoutButton = new Plasma::IconWidget(m_containment); m_keyboardLayoutButton->setMaximumSize(QSize(KIconLoader::SizeMedium, KIconLoader::SizeMedium)); connect(m_keyboardLayoutButton, SIGNAL(clicked()), this, SLOT(nextKeyboardLayout())); QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.connect("org.kde.keyboard", "/Layouts", "org.kde.KeyboardLayouts", "currentLayoutChanged", this, SLOT(currentKeyboardLayoutChanged())); dbus.connect("org.kde.keyboard", "/Layouts", "org.kde.KeyboardLayouts", "layoutListChanged", this, SLOT(refreshKeyboardLayoutInformation())); m_moveButton = new Plasma::IconWidget(m_containment); m_moveButton->setSvg("keyboardshell/arrows", "up-arrow"); m_moveButton->setMaximumWidth(KIconLoader::SizeMedium); connect(m_moveButton, SIGNAL(clicked()), this, SLOT(swapScreenEdge())); m_containment->setFormFactor(Plasma::Planar); m_containment->setLocation(Plasma::BottomEdge); KWindowSystem::setType(winId(), NET::Dock); setAttribute(Qt::WA_X11DoNotAcceptFocus); setWindowFlags(Qt::X11BypassWindowManagerHint); QFileInfo info(pluginName); if (!info.isAbsolute()) { info = QFileInfo(QDir::currentPath() + '/' + pluginName); } if (info.exists()) { m_applet = Plasma::Applet::loadPlasmoid(info.absoluteFilePath(), appletId, appletArgs); } if (!m_applet) { m_applet = Plasma::Applet::load(pluginName, appletId, appletArgs); } if (!m_applet) { #ifndef NDEBUG kWarning() << "Keyboard Plasmoid not found .. failing!"; #endif exit(1); } // ensure that the keyboard knows when to reset itself connect(this, SIGNAL(dialogVisible(bool)), m_applet, SLOT(dialogStatusChanged(bool))); m_containment->addApplet(m_applet, QPointF(-1, -1), false); QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(m_containment); lay->addItem(m_applet); m_controlButtonsLayouts = new QGraphicsLinearLayout(Qt::Vertical); lay->addItem(m_controlButtonsLayouts); m_controlButtonsLayouts->addItem(m_closeButton); m_controlButtonsLayouts->addItem(m_moveButton); m_controlButtonsLayouts->addItem(m_keyboardLayoutButton); setGraphicsWidget(m_containment); m_applet->setFlag(QGraphicsItem::ItemIsMovable, false); setWindowTitle(m_applet->name()); setWindowIcon(SmallIcon(m_applet->icon())); connect(this, SIGNAL(sceneRectAboutToChange()), this, SLOT(updateGeometry())); QDesktopWidget *desktop = QApplication::desktop(); - connect(desktop, SIGNAL(resized(int )), this, SLOT(updateGeometry())); + connect(desktop, SIGNAL(resized(int)), this, SLOT(updateGeometry())); setFixedHeight(static_cast(applet())->graphicsWidget()->effectiveSizeHint(Qt::PreferredSize).height()); QRect screenGeom = desktop->screenGeometry(desktop->screenNumber(this)); screenGeom.setWidth(screenGeom.width()-100); setFixedWidth(screenGeom.width()); hide(); setLocation(Plasma::BottomEdge); refreshKeyboardLayoutInformation(); } KeyboardDialog::~KeyboardDialog() { emit storeApplet(m_applet); } void KeyboardDialog::setContainment(Plasma::Containment *c) { if (m_containment) { disconnect(m_containment, 0, this, 0); } m_containment = c; m_containment->setScreen(0); updateGeometry(); } Plasma::Applet *KeyboardDialog::applet() { return m_applet; } Plasma::Location KeyboardDialog::location() const { return m_location; } Plasma::FormFactor KeyboardDialog::formFactor() const { return m_containment->formFactor(); } void KeyboardDialog::nextKeyboardLayout() { m_switchKeyboardLayoutScheduled = true; refreshKeyboardLayoutInformation(); } void KeyboardDialog::refreshKeyboardLayoutInformation() { QDBusInterface keyboards("org.kde.keyboard", "/Layouts"); QDBusPendingReply reply = keyboards.asyncCall("getLayoutsList"); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(layoutsReceived(QDBusPendingCallWatcher*))); } void KeyboardDialog::layoutsReceived(QDBusPendingCallWatcher *watcher) { QDBusReply reply(*watcher); QTimer::singleShot(0, watcher, SLOT(deleteLater())); if (!reply.isValid()) { return; } m_keyboardLayouts = reply.value(); if (m_keyboardLayouts.size() < 2) { m_keyboardLayoutButton->hide(); m_controlButtonsLayouts->removeItem(m_keyboardLayoutButton); } else { if (!m_keyboardLayoutButton->isVisible()) { m_keyboardLayoutButton->show(); m_controlButtonsLayouts->addItem(m_keyboardLayoutButton); } QDBusInterface keyboards("org.kde.keyboard", "/Layouts"); QDBusPendingReply reply = keyboards.asyncCall("getCurrentLayout"); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(currentLayoutReceived(QDBusPendingCallWatcher*))); } } void KeyboardDialog::currentLayoutReceived(QDBusPendingCallWatcher *watcher) { QDBusReply reply(*watcher); QTimer::singleShot(0, watcher, SLOT(deleteLater())); if (!reply.isValid()) { return; } const QString layout = reply.value(); int index = m_keyboardLayouts.indexOf(layout); if (index == -1) { refreshKeyboardLayoutInformation(); return; } if (m_switchKeyboardLayoutScheduled) { m_switchKeyboardLayoutScheduled = false; index = (index + 1) % m_keyboardLayouts.count(); QDBusInterface keyboards("org.kde.keyboard", "/Layouts"); keyboards.asyncCall("setLayout", m_keyboardLayouts.at(index)); return; } QIcon icon; if (m_iconMap.contains(layout)) { icon = m_iconMap[layout]; } else { QString file; if (layout == "epo") { file = KStandardDirs::locate("data", "kcmkeyboard/pics/epo.png"); } else { QString countryCode; if (countryCode == "nec_vndr/jp") { countryCode = "jp"; } else if (layout.length() < 3) { countryCode = layout; } file = KStandardDirs::locate("locale", QString("l10n/%1/flag.png").arg(countryCode)); } if (!file.isEmpty()) { icon.addFile(file); } } if (icon.isNull()) { m_keyboardLayoutButton->setIcon(QIcon()); m_keyboardLayoutButton->setText(layout); m_iconMap.insert(layout, QIcon()); } else { m_iconMap.insert(layout, icon); m_keyboardLayoutButton->setIcon(icon); m_keyboardLayoutButton->setText(QString()); } } void KeyboardDialog::currentKeyboardLayoutChanged() { refreshKeyboardLayoutInformation(); } void KeyboardDialog::swapScreenEdge() { switch (m_location) { case Plasma::TopEdge: setLocation(Plasma::BottomEdge); break; case Plasma::RightEdge: setLocation(Plasma::LeftEdge); break; case Plasma::LeftEdge: setLocation(Plasma::RightEdge); break; case Plasma::BottomEdge: setLocation(Plasma::TopEdge); break; default: break; } } void KeyboardDialog::setLocation(const Plasma::Location location) { if (location == m_location) { return; } const Plasma::Location oldLocation = m_location; m_location = location; QDesktopWidget *desktop = QApplication::desktop(); const QRect screenGeom = desktop->screenGeometry(desktop->screenNumber(this)); switch (location) { case Plasma::TopEdge: setFixedSize(screenGeom.width() - 100, static_cast(applet())->graphicsWidget()->effectiveSizeHint(Qt::PreferredSize).height()); move(screenGeom.left() + 50, screenGeom.top()); m_moveButton->setSvg("keyboardshell/arrows", "down-arrow"); break; case Plasma::RightEdge: setFixedSize(static_cast(applet())->graphicsWidget()->effectiveSizeHint(Qt::PreferredSize).width(), screenGeom.height() - 100); move(screenGeom.right() - width(), screenGeom.top() + 50); m_moveButton->setSvg("keyboardshell/arrows", "left-arrow"); break; case Plasma::LeftEdge: setFixedSize(static_cast(applet())->graphicsWidget()->effectiveSizeHint(Qt::PreferredSize).width(), screenGeom.height() - 100); move(screenGeom.left(), screenGeom.top() + 50); m_moveButton->setSvg("keyboardshell/arrows", "right-arrow"); break; case Plasma::BottomEdge: setFixedSize(screenGeom.width() - 100, static_cast(applet())->graphicsWidget()->effectiveSizeHint(Qt::PreferredSize).height()); move(screenGeom.left() + 50, screenGeom.height() - height()); m_moveButton->setSvg("keyboardshell/arrows", "up-arrow"); break; default: // we don't support this location, so just revert back m_location = oldLocation; break; } if (isVisible()) { Plasma::WindowEffects::slideWindow(this, m_location); } } void KeyboardDialog::showEvent(QShowEvent *event) { KWindowSystem::setType(winId(), NET::Dock); unsigned long state = NET::Sticky | NET::StaysOnTop | NET::KeepAbove; KWindowSystem::setState(winId(), state); KWindowSystem::raiseWindow(effectiveWinId()); Plasma::Dialog::showEvent(event); //FIXME: this is an hack for the applet disabing itself in panic when doesn't immediately find a view Plasma::PopupApplet *pa = qobject_cast(m_applet); if (pa) { pa->graphicsWidget()->setEnabled(true); } } void KeyboardDialog::resizeEvent(QResizeEvent *event) { if (event->oldSize() == event->size()) { return; } Plasma::Dialog::resizeEvent(event); QDesktopWidget *desktop = QApplication::desktop(); switch (m_location) { case Plasma::TopEdge: move((desktop->size().width() / 2) - (event->size().width() / 2), desktop->screenGeometry().y()); break; case Plasma::RightEdge: move(desktop->size().width() - event->size().width(), (desktop->size().height() / 2) - (event->size().height() / 2)); break; case Plasma::LeftEdge: move(desktop->screenGeometry().x(), (desktop->size().height() / 2) - (event->size().width() / 2)); break; case Plasma::BottomEdge: move((desktop->size().width() / 2) - (event->size().width() / 2), desktop->size().height() - event->size().height()); break; default: break; } } #include "keyboarddialog.moc" diff --git a/wallpapers/mobileimage/backgroundlistmodel.cpp b/wallpapers/mobileimage/backgroundlistmodel.cpp index 257b4d74..88982350 100644 --- a/wallpapers/mobileimage/backgroundlistmodel.cpp +++ b/wallpapers/mobileimage/backgroundlistmodel.cpp @@ -1,403 +1,403 @@ #ifndef BACKGROUNDLISTMODEL_CPP #define BACKGROUNDLISTMODEL_CPP /* Copyright (c) 2007 Paolo Capriotti This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #include "backgroundlistmodel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "mobileimage.h" ImageSizeFinder::ImageSizeFinder(const QString &path, QObject *parent) : QObject(parent), m_path(path) { } void ImageSizeFinder::run() { QImage image(m_path); emit sizeFound(m_path, image.size()); } BackgroundListModel::BackgroundListModel(Plasma::Wallpaper *listener, QObject *parent) : QAbstractListModel(parent), m_structureParent(listener), m_size(0,0), m_resizeMethod(Plasma::Wallpaper::ScaledResize) { connect(&m_dirwatch, SIGNAL(deleted(QString)), this, SLOT(removeBackground(QString))); m_previewUnavailablePix.fill(Qt::transparent); //m_previewUnavailablePix = KIcon("unknown").pixmap(m_previewUnavailablePix.size()); } BackgroundListModel::~BackgroundListModel() { qDeleteAll(m_packages); } void BackgroundListModel::removeBackground(const QString &path) { QModelIndex index; while ((index = indexOf(path)).isValid()) { beginRemoveRows(QModelIndex(), index.row(), index.row()); Plasma::Package *package = m_packages.at(index.row()); m_packages.removeAt(index.row()); delete package; endRemoveRows(); } } void BackgroundListModel::reload() { reload(QStringList()); } void BackgroundListModel::reload(const QStringList &selected) { if (!m_packages.isEmpty()) { beginRemoveRows(QModelIndex(), 0, m_packages.count() - 1); qDeleteAll(m_packages); m_packages.clear(); endRemoveRows(); } if (!selected.isEmpty()) { processPaths(selected); } const QStringList dirs = KGlobal::dirs()->findDirs("wallpaper", ""); kDebug() << "going looking in" << dirs; BackgroundFinder *finder = new BackgroundFinder(m_structureParent, dirs); connect(finder, SIGNAL(backgroundsFound(QStringList,QString)), this, SLOT(backgroundsFound(QStringList,QString))); m_findToken = finder->token(); finder->start(); } void BackgroundListModel::backgroundsFound(const QStringList &paths, const QString &token) { if (token == m_findToken) { processPaths(paths); } } void BackgroundListModel::processPaths(const QStringList &paths) { QList newPackages; foreach (const QString &file, paths) { if (!contains(file) && QFile::exists(file)) { Plasma::PackageStructure::Ptr structure = Plasma::Wallpaper::packageStructure(m_structureParent); Plasma::Package *package = new Plasma::Package(file, structure); if (package->isValid()) { newPackages << package; } else { delete package; } } } // add new files to dirwatch foreach (Plasma::Package *b, newPackages) { if (!m_dirwatch.contains(b->path())) { m_dirwatch.addFile(b->path()); } } if (!newPackages.isEmpty()) { const int start = rowCount(); beginInsertRows(QModelIndex(), start, start + newPackages.size()); m_packages.append(newPackages); endInsertRows(); } //kDebug() << t.elapsed(); } void BackgroundListModel::addBackground(const QString& path) { if (!contains(path)) { if (!m_dirwatch.contains(path)) { m_dirwatch.addFile(path); } beginInsertRows(QModelIndex(), 0, 0); Plasma::PackageStructure::Ptr structure = Plasma::Wallpaper::packageStructure(m_structureParent); Plasma::Package *pkg = new Plasma::Package(path, structure); m_packages.prepend(pkg); endInsertRows(); } } QModelIndex BackgroundListModel::indexOf(const QString &path) const { for (int i = 0; i < m_packages.size(); i++) { // packages will end with a '/', but the path passed in may not QString package = m_packages[i]->path(); if (package.at(package.length() - 1) == '/') { package.truncate(package.length() - 1); } if (path.startsWith(package)) { // FIXME: ugly hack to make a difference between local files in the same dir // package->path does not contain the actual file name if ((!m_packages[i]->structure()->contentsPrefixPaths().isEmpty()) || (path == m_packages[i]->filePath("preferred"))) { return index(i, 0); } } } return QModelIndex(); } bool BackgroundListModel::contains(const QString &path) const { return indexOf(path).isValid(); } int BackgroundListModel::rowCount(const QModelIndex &) const { return m_packages.size(); } QSize BackgroundListModel::bestSize(Plasma::Package *package) const { if (m_sizeCache.contains(package)) { return m_sizeCache.value(package); } const QString image = package->filePath("preferred"); if (image.isEmpty()) { return QSize(); } KFileMetaInfo info(image, QString(), KFileMetaInfo::TechnicalInfo); QSize size(info.item("http://freedesktop.org/standards/xesam/1.0/core#width").value().toInt(), info.item("http://freedesktop.org/standards/xesam/1.0/core#height").value().toInt()); //backup solution if strigi does not work if (size.width() == 0 || size.height() == 0) { // kDebug() << "fall back to QImage, check your strigi"; ImageSizeFinder *finder = new ImageSizeFinder(image); connect(finder, SIGNAL(sizeFound(QString,QSize)), this, SLOT(sizeFound(QString,QSize))); QThreadPool::globalInstance()->start(finder); size = QSize(-1, -1); } const_cast(this)->m_sizeCache.insert(package, size); return size; } void BackgroundListModel::sizeFound(const QString &path, const QSize &s) { QModelIndex index = indexOf(path); if (index.isValid()) { Plasma::Package *package = m_packages.at(index.row()); m_sizeCache.insert(package, s); } } QVariant BackgroundListModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (index.row() >= m_packages.size()) { return QVariant(); } Plasma::Package *b = package(index.row()); if (!b) { return QVariant(); } switch (role) { case Qt::DisplayRole: { QString title = b->metadata().name(); if (title.isEmpty()) { return QFileInfo(b->filePath("preferred")).completeBaseName(); } return title; } break; /* case BackgroundDelegate::ScreenshotRole: { if (m_previews.contains(b)) { return m_previews.value(b); } KUrl file(b->filePath("preferred")); if (!m_previewJobs.contains(file) && file.isValid()) { KFileItemList list; list.append(KFileItem(file, QString(), 0)); KIO::PreviewJob* job = KIO::filePreview(list, QSize(BackgroundDelegate::SCREENSHOT_SIZE, BackgroundDelegate::SCREENSHOT_SIZE/1.6)); job->setIgnoreMaximumSize(true); - connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)), - this, SLOT(showPreview(const KFileItem&, const QPixmap&))); - connect(job, SIGNAL(failed(const KFileItem&)), - this, SLOT(previewFailed(const KFileItem&))); + connect(job, SIGNAL(gotPreview(KFileItem,QPixmap)), + this, SLOT(showPreview(KFileItem,QPixmap))); + connect(job, SIGNAL(failed(KFileItem)), + this, SLOT(previewFailed(KFileItem))); const_cast(this)->m_previewJobs.insert(file, QPersistentModelIndex(index)); } const_cast(this)->m_previews.insert(b, m_previewUnavailablePix); return m_previewUnavailablePix; } break; case BackgroundDelegate::AuthorRole: return b->metadata().author(); break; case BackgroundDelegate::ResolutionRole:{ QSize size = bestSize(b); if (size.isValid()) { return QString("%1x%2").arg(size.width()).arg(size.height()); } return QString(); } break;*/ default: return QVariant(); break; } } void BackgroundListModel::showPreview(const KFileItem &item, const QPixmap &preview) { QPersistentModelIndex index = m_previewJobs.value(item.url()); m_previewJobs.remove(item.url()); if (!index.isValid()) { return; } Plasma::Package *b = package(index.row()); if (!b) { return; } m_previews.insert(b, preview); } void BackgroundListModel::previewFailed(const KFileItem &item) { m_previewJobs.remove(item.url()); } Plasma::Package* BackgroundListModel::package(int index) const { return m_packages.at(index); } void BackgroundListModel::setWallpaperSize(const QSize& size) { m_size = size; } void BackgroundListModel::setResizeMethod(Plasma::Wallpaper::ResizeMethod resizeMethod) { m_resizeMethod = resizeMethod; } BackgroundFinder::BackgroundFinder(Plasma::Wallpaper *structureParent, const QStringList &paths) : QThread(structureParent), m_structure(Plasma::Wallpaper::packageStructure(structureParent)), m_paths(paths), m_token(QUuid().toString()) { } BackgroundFinder::~BackgroundFinder() { wait(); } QString BackgroundFinder::token() const { return m_token; } void BackgroundFinder::run() { //QTime t; //t.start(); QSet suffixes; suffixes << "png" << "jpeg" << "jpg" << "svg" << "svgz"; QStringList papersFound; //kDebug() << "starting with" << m_paths; QDir dir; dir.setFilter(QDir::AllDirs | QDir::Files | QDir::Hidden | QDir::Readable); Plasma::Package pkg(QString(), m_structure); int i; for (i = 0; i < m_paths.count(); ++i) { const QString path = m_paths.at(i); //kDebug() << "doing" << path; dir.setPath(path); const QFileInfoList files = dir.entryInfoList(); foreach (const QFileInfo &wp, files) { if (wp.isDir()) { //kDebug() << "directory" << wp.fileName() << validPackages.contains(wp.fileName()); const QString name = wp.fileName(); if (name == "." || name == "..") { // do nothing continue; } const QString filePath = wp.filePath(); if (QFile::exists(filePath + "/metadata.desktop")) { pkg.setPath(filePath); if (pkg.isValid()) { papersFound << pkg.path(); continue; //kDebug() << "gots a" << wp.filePath(); } } // add this to the directories we should be looking at m_paths.append(filePath); } else if (suffixes.contains(wp.suffix().toLower())) { //kDebug() << " adding image file" << wp.filePath(); papersFound << wp.filePath(); } } } //kDebug() << "background found!" << papersFound.size() << "in" << i << "dirs, taking" << t.elapsed() << "ms"; emit backgroundsFound(papersFound, m_token); deleteLater(); } #include "backgroundlistmodel.moc" #endif // BACKGROUNDLISTMODEL_CPP