Hello community,

here is the log from the commit of package albert for openSUSE:Factory checked 
in at 2017-06-05 18:50:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/albert (Old)
 and      /work/SRC/openSUSE:Factory/.albert.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "albert"

Mon Jun  5 18:50:49 2017 rev:7 rq:501138 version:0.11.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/albert/albert.changes    2017-05-16 
14:44:27.241040755 +0200
+++ /work/SRC/openSUSE:Factory/.albert.new/albert.changes       2017-06-05 
18:51:19.284935520 +0200
@@ -1,0 +2,6 @@
+Mon Jun  5 11:10:39 UTC 2017 - sor.ale...@meowr.ru
+
+- Update to version 0.11.3:
+  * No changelog available.
+
+-------------------------------------------------------------------

Old:
----
  albert-0.11.1.tar.gz

New:
----
  albert-0.11.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ albert.spec ++++++
--- /var/tmp/diff_new_pack.q6Cnpq/_old  2017-06-05 18:51:19.736871815 +0200
+++ /var/tmp/diff_new_pack.q6Cnpq/_new  2017-06-05 18:51:19.736871815 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           albert
-Version:        0.11.1
+Version:        0.11.3
 Release:        0
 Summary:        Desktop agnostic launcher
 License:        GPL-3.0+

++++++ albert-0.11.1.tar.gz -> albert-0.11.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/.travis.yml 
new/albert-0.11.3/.travis.yml
--- old/albert-0.11.1/.travis.yml       2017-04-16 13:17:45.000000000 +0200
+++ new/albert-0.11.3/.travis.yml       2017-05-28 23:57:15.000000000 +0200
@@ -5,22 +5,20 @@
   - clang
   - gcc
 
-before_install:
-    - sudo apt-get install -qq cmake qtbase5-dev libqt5x11extras5-dev 
libqt5svg5-dev libmuparser-dev
- 
-before_script:
-  - mkdir build
-  - cd build
-  - cmake ..  -DCMAKE_BUILD_TYPE=Release 
-  
+install:
+  - sudo add-apt-repository ppa:beineri/opt-qt551-trusty -y  # Qt-5.5
+  - sudo apt-get update -qq
+  - sudo apt-get install -qq cmake qt55base qt55x11extras qt55svg 
libmuparser-dev
+
 script:
-    - make
-    # Test installation process
-    - make DESTDIR=/tmp/albertbuild install
-    
+  - source /opt/qt55/bin/qt55-env.sh
+  - cmake . -DCMAKE_BUILD_TYPE=Debug
+  - make
+  - sudo make install
+
 notifications:
   irc:
     channels:
       - "chat.freenode.net#albertlauncher"
-    on_success: never # default: always
+    on_success: always # default: always
     on_failure: always # default: always
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/CMakeLists.txt 
new/albert-0.11.3/CMakeLists.txt
--- old/albert-0.11.1/CMakeLists.txt    2017-04-16 13:17:45.000000000 +0200
+++ new/albert-0.11.3/CMakeLists.txt    2017-05-28 23:57:15.000000000 +0200
@@ -16,10 +16,6 @@
 # Color make output
 SET(CMAKE_COLOR_MAKEFILE ON)
 
-# Do not export symbols by default
-set(CMAKE_CXX_VISIBILITY_PRESET hidden)
-set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
-
 # Suppress gcc details
 if(CMAKE_BUILD_TYPE STREQUAL "Debug")
     SET(CMAKE_VERBOSE_MAKEFILE ON)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/ISSUE_TEMPLATE.md 
new/albert-0.11.3/ISSUE_TEMPLATE.md
--- old/albert-0.11.1/ISSUE_TEMPLATE.md 2017-04-16 13:17:45.000000000 +0200
+++ new/albert-0.11.3/ISSUE_TEMPLATE.md 2017-05-28 23:57:15.000000000 +0200
@@ -1,7 +1,9 @@
 <!-- 
+First check if the docs answer your question
+https://albertlauncher.github.io/docs/
+
 People are too lazy to read, so in a nutshell:
 * Check for existing issues.
-* Read the FAQ.
 * Dont ask for support here (there are chats for that).
 * Upate to the latest version. 
 * If not possible check if the issue has been fixed already.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/data/themes/Elementary.qss 
new/albert-0.11.3/data/themes/Elementary.qss
--- old/albert-0.11.1/data/themes/Elementary.qss        2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/data/themes/Elementary.qss        2017-05-28 
23:57:15.000000000 +0200
@@ -56,7 +56,7 @@
 /********** ListViews **********/
 
 QListView {
-    selection-color: #ccc;
+       selection-color: #331;
        background-color: #F5F5F5;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/lib/CMakeLists.txt 
new/albert-0.11.3/src/lib/CMakeLists.txt
--- old/albert-0.11.1/src/lib/CMakeLists.txt    2017-04-16 13:17:45.000000000 
+0200
+++ new/albert-0.11.3/src/lib/CMakeLists.txt    2017-05-28 23:57:15.000000000 
+0200
@@ -1,3 +1,7 @@
+# Do not export symbols by default
+set(CMAKE_CXX_VISIBILITY_PRESET hidden)
+set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
+
 add_subdirectory(albert)
 add_subdirectory(xdg)
 add_subdirectory(globalshortcut)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/lib/albert/src/albert/albert.cpp 
new/albert-0.11.3/src/lib/albert/src/albert/albert.cpp
--- old/albert-0.11.1/src/lib/albert/src/albert/albert.cpp      2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/lib/albert/src/albert/albert.cpp      2017-05-28 
23:57:15.000000000 +0200
@@ -29,6 +29,7 @@
 #include <QtNetwork/QLocalServer>
 #include <QtNetwork/QLocalSocket>
 #include <csignal>
+#include <functional>
 #include "albert.h"
 #include "extensionmanager.h"
 #include "hotkeymanager.h"
@@ -68,7 +69,7 @@
         app = new QApplication(argc, argv);
         app->setApplicationName("albert");
         app->setApplicationDisplayName("Albert");
-        app->setApplicationVersion("v0.11.1");
+        app->setApplicationVersion("v0.11.2");
         app->setQuitOnLastWindowClosed(false);
         QString icon = XdgIconLookup::iconPath("albert");
         if ( icon.isEmpty() ) icon = ":app_icon";
@@ -128,13 +129,10 @@
         // Make sure data, cache and config dir exists
         QString dataLocation = 
QStandardPaths::writableLocation(QStandardPaths::DataLocation);
         QString cacheLocation = 
QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
-        QDir dir;
-        dir.setPath(dataLocation);
-        if (!dir.mkpath("."))
-            qFatal("Could not create dir: %s",  
dataLocation.toUtf8().constData());
-        dir.setPath(cacheLocation);
-        if (!dir.mkpath("."))
-            qFatal("Could not create dir: %s",  
cacheLocation.toUtf8().constData());
+        QString configLocation = 
QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
+        for ( const QString &location : {dataLocation, cacheLocation, 
configLocation} )
+            if (!QDir(location).mkpath("."))
+                qFatal("Could not create dir: %s",  qPrintable(location));
 
         // Move old config for user convenience TODO drop somewhen
         QFileInfo 
oldcfg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + 
"/albert/albert.conf");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/albert-0.11.1/src/lib/albert/src/albert/extensionmanager.cpp 
new/albert-0.11.3/src/lib/albert/src/albert/extensionmanager.cpp
--- old/albert-0.11.1/src/lib/albert/src/albert/extensionmanager.cpp    
2017-04-16 13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/lib/albert/src/albert/extensionmanager.cpp    
2017-05-28 23:57:15.000000000 +0200
@@ -39,7 +39,7 @@
 public:
     vector<unique_ptr<ExtensionSpec>> extensionSpecs_; // TASK: Rename _
     set<QObject*> extensions_;
-    QStringList pluginDirs;
+    set<QString> pluginDirs;
 };
 
 
@@ -59,7 +59,7 @@
     for ( const QString& dir : dirs ) {
         QFileInfo fileInfo = QFileInfo(QDir(dir).filePath("albert/plugins"));
         if ( fileInfo.isDir() )
-            d->pluginDirs << fileInfo.absoluteFilePath();
+            d->pluginDirs.insert(fileInfo.canonicalFilePath());
     }
 
 #elif defined __APPLE__
@@ -80,7 +80,7 @@
 
 /** 
***************************************************************************/
 void Core::ExtensionManager::setPluginDirs(const QStringList &dirs) {
-    d->pluginDirs = dirs;
+    d->pluginDirs.insert(dirs.begin(), dirs.end());
 }
 
 
@@ -102,26 +102,36 @@
             QString path = dirIterator.fileInfo().canonicalFilePath();
 
             // Check if this path is a lib
-            if (QLibrary::isLibrary(path)) {
+            if ( !QLibrary::isLibrary(path) ) {
+                qWarning() << "File is not a library:" << path;
+                continue;
+            }
 
-                QPluginLoader loader(path);
+            QPluginLoader loader(path);
 
-                // Check for a sane interface ID  (IID)
-                QString iid = loader.metaData()["IID"].toString();
-                if (iid != ALBERT_EXTENSION_IID)
-                    continue;
-
-                // Check for duplicates
-                QString id = 
loader.metaData()["MetaData"].toObject()["id"].toString();
-                if (std::find_if (d->extensionSpecs_.begin(), 
d->extensionSpecs_.end(),
-                                  [&id](const unique_ptr<ExtensionSpec> & 
extensionSpec){
-                                      return id == extensionSpec->id();
-                                  }) != d->extensionSpecs_.end())
-                    continue;
+            if ( loader.metaData().empty() ) {
+                qWarning() << qPrintable(QString("Metadata empty. Is this a 
QPlugin? (%1)").arg(path));
+                continue;
+            }
 
-                // Put it to the results
-                d->extensionSpecs_.emplace_back(new ExtensionSpec(path));
+            // Check for a sane interface ID  (IID)
+            QString iid = loader.metaData()["IID"].toString();
+            if (iid != ALBERT_EXTENSION_IID) {
+                qWarning() << qPrintable(QString("Extension IDs do not match. 
App:'%1'. Ext: '%2' (%3)")
+                              .arg(ALBERT_EXTENSION_IID, iid, path));
+                continue;
             }
+
+            // Check for duplicates
+            QString id = 
loader.metaData()["MetaData"].toObject()["id"].toString();
+            if (std::any_of(d->extensionSpecs_.begin(), 
d->extensionSpecs_.end(),
+                            [&id](const unique_ptr<ExtensionSpec> & spec){ 
return id == spec->id(); })) {
+                qWarning() << qPrintable(QString("Extension IDs already 
exists. Skipping. (%1)").arg(path));
+                continue;
+            }
+
+            // Put it to the results
+            d->extensionSpecs_.emplace_back(new ExtensionSpec(path));
         }
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/albert-0.11.1/src/lib/albert/src/albert/mainwindow/proposallist.cpp 
new/albert-0.11.3/src/lib/albert/src/albert/mainwindow/proposallist.cpp
--- old/albert-0.11.1/src/lib/albert/src/albert/mainwindow/proposallist.cpp     
2017-04-16 13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/lib/albert/src/albert/mainwindow/proposallist.cpp     
2017-05-28 23:57:15.000000000 +0200
@@ -83,6 +83,16 @@
             update();
             return false;
 
+
+        // Expose the navigation hidden by the lineedit with the control 
modifier
+        case Qt::Key_Home:
+        case Qt::Key_End:
+            if ( keyEvent->modifiers() == Qt::ControlModifier ) {
+                keyPressEvent(keyEvent);
+                return true;
+            }
+            return false;
+
         // Navigation
         case Qt::Key_Up:
         case Qt::Key_Down:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/lib/albert/src/albert/query.cpp 
new/albert-0.11.3/src/lib/albert/src/albert/query.cpp
--- old/albert-0.11.1/src/lib/albert/src/albert/query.cpp       2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/lib/albert/src/albert/query.cpp       2017-05-28 
23:57:15.000000000 +0200
@@ -26,8 +26,8 @@
 #include <QVariant>
 #include <algorithm>
 #include <chrono>
-#include <map>
 #include <functional>
+#include <map>
 #include "action.h"
 #include "extension.h"
 #include "item.h"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/albert-0.11.1/src/plugins/applications/configwidget.ui 
new/albert-0.11.3/src/plugins/applications/configwidget.ui
--- old/albert-0.11.1/src/plugins/applications/configwidget.ui  2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/applications/configwidget.ui  2017-05-28 
23:57:15.000000000 +0200
@@ -22,7 +22,7 @@
 &lt;/head&gt;
 &lt;body&gt;
 &lt;p&gt;Applications are looked up in the &amp;quot;&lt;span style=&quot; 
font-style:italic;&quot;&gt;applications/&amp;quot;&lt;/span&gt; directories in 
the $XDG_DATA_HOME and $XDG_DATA_DIRS, which are set in the environment 
variables. Your current environment configuration results in the following 
applications directories: &lt;span style=&quot; font-weight:600; 
font-style:italic;&quot;&gt;__XDG_DATA_DIRS__&lt;/span&gt;. &lt;/p&gt;
-&lt;p&gt;Every application is represented by a desktop file which has an ID. 
The desktop file ID is built using the path of the desktop file relative to the 
applications directory and turning '/' into '-'. If multiple files have the 
same desktop file ID, the first one in the precedence order given above is 
used. For mor details check the &lt;a 
href=&quot;https://specifications.freedesktop.org/desktop-entry-spec/latest/&quot;&gt;desktop
 entry sprecificion&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;p&gt;Every application is represented by a desktop file which has an ID. 
The desktop file ID is built using the path of the desktop file relative to the 
applications directory and turning '/' into '-'. If multiple files have the 
same desktop file ID, the first one in the precedence order given above is 
used. For more details check the &lt;a 
href=&quot;https://specifications.freedesktop.org/desktop-entry-spec/latest/&quot;&gt;desktop
 entry specification&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
        </property>
        <property name="wordWrap">
         <bool>true</bool>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/plugins/applications/src/main.cpp 
new/albert-0.11.3/src/plugins/applications/src/main.cpp
--- old/albert-0.11.1/src/plugins/applications/src/main.cpp     2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/applications/src/main.cpp     2017-05-28 
23:57:15.000000000 +0200
@@ -30,6 +30,7 @@
 #include <QTimer>
 #include <QThread>
 #include <algorithm>
+#include <functional>
 #include <map>
 #include <memory>
 #include <vector>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/plugins/debug/src/main.cpp 
new/albert-0.11.3/src/plugins/debug/src/main.cpp
--- old/albert-0.11.1/src/plugins/debug/src/main.cpp    2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/debug/src/main.cpp    2017-05-28 
23:57:15.000000000 +0200
@@ -47,10 +47,10 @@
       d(new DebugPrivate) {
     QSettings s(qApp->applicationName());
     s.beginGroup(Core::QueryHandler::id);
-    setDelay(s.value("delay", 50).toInt());
-    setCount(s.value("count", 100).toInt());
-    setAsync(s.value("async", true).toBool());
-    setTrigger(s.value("trigger", "dbg").toString());
+    d->delay = s.value("delay", 50).toInt();
+    d->count = s.value("count", 100).toInt();
+    d->async = s.value("async", true).toBool();
+    d->trigger = s.value("trigger", "dbg").toString();
     s.endGroup();
 }
 
@@ -110,6 +110,13 @@
 }
 
 
+
+/** 
***************************************************************************/
+bool Debug::Extension::isLongRunning() const {
+    return d->async;
+}
+
+
 
 /** 
***************************************************************************/
 int Debug::Extension::count() const{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/plugins/debug/src/main.h 
new/albert-0.11.3/src/plugins/debug/src/main.h
--- old/albert-0.11.1/src/plugins/debug/src/main.h      2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/debug/src/main.h      2017-05-28 
23:57:15.000000000 +0200
@@ -46,7 +46,7 @@
     QWidget *widget(QWidget *parent = nullptr) override;
     QStringList triggers() const override;
     void handleQuery(Core::Query * query) override;
-    bool isLongRunning() const override { return true; }
+    bool isLongRunning() const override;
 
     /*
      * Extension specific members
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/albert-0.11.1/src/plugins/externalextensions/src/externalextension.cpp 
new/albert-0.11.3/src/plugins/externalextensions/src/externalextension.cpp
--- old/albert-0.11.1/src/plugins/externalextensions/src/externalextension.cpp  
2017-04-16 13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/externalextensions/src/externalextension.cpp  
2017-05-28 23:57:15.000000000 +0200
@@ -23,6 +23,7 @@
 #include <QLabel>
 #include <QProcess>
 #include <QVBoxLayout>
+#include <functional>
 #include <vector>
 #include "externalextension.h"
 #include "standardaction.h"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/plugins/files/src/main.cpp 
new/albert-0.11.3/src/plugins/files/src/main.cpp
--- old/albert-0.11.1/src/plugins/files/src/main.cpp    2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/files/src/main.cpp    2017-05-28 
23:57:15.000000000 +0200
@@ -28,6 +28,7 @@
 #include <QThreadPool>
 #include <QTimer>
 #include <memory>
+#include <functional>
 #include <vector>
 #include "configwidget.h"
 #include "file.h"
@@ -240,7 +241,7 @@
     }
 
     // Serialize data
-    QFile 
file(QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)).
+    QFile 
file(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)).
                    filePath(QString("%1.txt").arg(q->Core::Extension::id)));
     if (file.open(QIODevice::WriteOnly|QIODevice::Text)) {
         qDebug() << qPrintable(QString("Serializing files to 
'%1'").arg(file.fileName()));
@@ -277,7 +278,7 @@
     s.endGroup();
 
     // Deserialize data
-    QFile 
file(QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)).
+    QFile 
file(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)).
                    filePath(QString("%1.txt").arg(Core::Extension::id)));
     if (file.exists()) {
         if (file.open(QIODevice::ReadOnly| QIODevice::Text)) {
@@ -358,10 +359,6 @@
     }
     else
     {
-        // Skip  short terms since they pollute the output
-        if ( query->searchTerm().size() < 3)
-            return;
-
         if ( QString("albert scan files").startsWith(query->searchTerm()) ) {
             shared_ptr<StandardItem> standardItem = 
std::make_shared<StandardItem>("org.albert.extension.files.action.index");
             standardItem->setText("albert scan files");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/plugins/mpris/src/main.cpp 
new/albert-0.11.3/src/plugins/mpris/src/main.cpp
--- old/albert-0.11.1/src/plugins/mpris/src/main.cpp    2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/mpris/src/main.cpp    2017-05-28 
23:57:15.000000000 +0200
@@ -21,33 +21,29 @@
 #include "query.h"
 #include "xdgiconlookup.h"
 #include "command.h"
+#include "private.h"
 
 #define themeOr(name, fallbk)   XdgIconLookup::iconPath(name).isEmpty() ? 
fallbk : XdgIconLookup::iconPath(name)
 
 
+QDBusMessage MPRIS::MPRISPrivate::findPlayerMsg = 
QDBusMessage::createMethodCall("org.freedesktop.DBus", "/", 
"org.freedesktop.DBus", "ListNames");
 
-/** 
***************************************************************************/
-class MPRIS::MPRISPrivate {
-public:
-    ~MPRISPrivate() {
-        // If there are still media player objects, delete them
-        qDeleteAll(mediaPlayers);
-        // Don't need to destruct the command objects.
-        // This is done by the destructor of QMap
-    }
 
 
-    const char* name = "MPRIS Control";
-    static QDBusMessage findPlayerMsg;
-    QPointer<MPRIS::ConfigWidget> widget;
-    QList<MPRIS::Player*> mediaPlayers;
-    QStringList commands;
-    QMap<QString, MPRIS::Command> commandObjects;
-};
+/** 
***************************************************************************/
+MPRIS::MPRISPrivate::~MPRISPrivate() {
+    // If there are still media player objects, delete them
+    qDeleteAll(mediaPlayers);
+    // Don't need to destruct the command objects.
+    // This is done by the destructor of QMap
+}
 
 
 
-QDBusMessage MPRIS::MPRISPrivate::findPlayerMsg = 
QDBusMessage::createMethodCall("org.freedesktop.DBus", "/", 
"org.freedesktop.DBus", "ListNames");
+/** 
***************************************************************************/
+QDBusMessage MPRIS::MPRISPrivate::call(QDBusMessage &toDispatch) {
+    return QDBusConnection::sessionBus().call(toDispatch, QDBus::Block, 
DBUS_TIMEOUT);
+}
 
 
 
@@ -66,7 +62,7 @@
     icon = themeOr("media-playback-start", ":play");
     Command* nextToAdd = new Command(
                 "play", // Label
-                "Start playing", // Title
+                "Play", // Title
                 "Start playing on %1", // Subtext
                 "Play", // DBus Method
                 icon
@@ -90,7 +86,7 @@
     icon = themeOr("media-playback-stop", ":stop");
     nextToAdd = new Command(
                 "stop",
-                "Stop playing",
+                "Stop",
                 "Stop %1",
                 "Stop",
                 icon
@@ -101,7 +97,7 @@
 
     icon = themeOr("media-skip-forward", ":next");
     nextToAdd = new Command(
-                "next",
+                "next track",
                 "Next track",
                 "Play next track on %1",
                 "Next",
@@ -109,20 +105,20 @@
                 );
     nextToAdd->applicableWhen("/org/mpris/MediaPlayer2", 
"org.mpris.MediaPlayer2.Player.CanGoNext", true, true);
     //.fireCallback([](){qDebug("NEXT");})
-    d->commands.append("next");
-    d->commandObjects.insert("next", *nextToAdd);
+    d->commands.append("next track");
+    d->commandObjects.insert("next track", *nextToAdd);
 
     icon = themeOr("media-skip-backward", ":prev");
     nextToAdd = new Command(
-                "previous",
+                "previous track",
                 "Previous track",
                 "Play previous track on %1",
                 "Previous",
                 icon
                 );
     nextToAdd->applicableWhen("/org/mpris/MediaPlayer2", 
"org.mpris.MediaPlayer2.Player.CanGoPrevious", true, true);
-    d->commands.append("previous");
-    d->commandObjects.insert("previous", *nextToAdd);
+    d->commands.append("previous track");
+    d->commandObjects.insert("previous track", *nextToAdd);
 
     qDebug("[%s] Extension initialized", d->name);
 }
@@ -158,7 +154,7 @@
         return;
 
     // Querying the DBus to list all available services
-    QDBusMessage response = 
QDBusConnection::sessionBus().call(MPRISPrivate::findPlayerMsg);
+    QDBusMessage response = d->call(MPRISPrivate::findPlayerMsg);
 
     // Do some error checking
     if (response.type() == QDBusMessage::ReplyMessage) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/plugins/mpris/src/main.h 
new/albert-0.11.3/src/plugins/mpris/src/main.h
--- old/albert-0.11.1/src/plugins/mpris/src/main.h      2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/mpris/src/main.h      2017-05-28 
23:57:15.000000000 +0200
@@ -29,7 +29,6 @@
 namespace MPRIS {
 
 class MPRISPrivate;
-class ConfigWidget;
 
 class Extension final :
         public QObject,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/plugins/mpris/src/player.cpp 
new/albert-0.11.3/src/plugins/mpris/src/player.cpp
--- old/albert-0.11.1/src/plugins/mpris/src/player.cpp  2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/mpris/src/player.cpp  2017-05-28 
23:57:15.000000000 +0200
@@ -17,11 +17,13 @@
 #include "player.h"
 #include <QtDBus/QDBusConnection>
 #include <QtDBus/QDBusInterface>
+#include "private.h"
 
 /** 
***************************************************************************/
 MPRIS::Player::Player(QString &busid) : busid_(busid), name_(busid) {
     // Query the name of the media player of which we have the bus id.
     QDBusInterface iface(busid, "/org/mpris/MediaPlayer2", 
"org.mpris.MediaPlayer2");
+    iface.setTimeout(MPRIS::MPRISPrivate::DBUS_TIMEOUT);
 
     QVariant prop = iface.property("Identity");
     if (prop.isValid() && !prop.isNull() && prop.canConvert(QVariant::String)) 
{
@@ -34,6 +36,7 @@
     if (prop.isValid() && !prop.isNull() && prop.canConvert(QVariant::Bool)) {
         canRaise_ = prop.toBool();
     } else {
+        canRaise_ = false;
         qWarning("DBus: CanRaise is either invalid, null or not instanceof 
bool");
     }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/plugins/mpris/src/private.h 
new/albert-0.11.3/src/plugins/mpris/src/private.h
--- old/albert-0.11.1/src/plugins/mpris/src/private.h   1970-01-01 
01:00:00.000000000 +0100
+++ new/albert-0.11.3/src/plugins/mpris/src/private.h   2017-05-28 
23:57:15.000000000 +0200
@@ -0,0 +1,49 @@
+// albert extension mpris - a mpris interface plugin for albert
+// Copyright (C) 2017 Martin Buergmann
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+
+#include <QDBusConnection>
+#include <QDBusInterface>
+#include <QDBusMessage>
+#include <QStringList>
+#include <QMap>
+#include <QPointer>
+
+
+namespace MPRIS {
+
+class ConfigWidget;
+class Player;
+class Command;
+
+class MPRISPrivate {
+public:
+    ~MPRISPrivate();
+
+
+    const char* name = "MPRIS Control";
+    static QDBusMessage findPlayerMsg;
+    QPointer<MPRIS::ConfigWidget> widget;
+    QList<MPRIS::Player*> mediaPlayers;
+    QStringList commands;
+    QMap<QString, MPRIS::Command> commandObjects;
+
+    static const int DBUS_TIMEOUT = 25 /* ms */;
+
+    QDBusMessage call(QDBusMessage &toDispatch);
+
+};
+
+} // namespace MPRIS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/plugins/virtualbox/src/main.cpp 
new/albert-0.11.3/src/plugins/virtualbox/src/main.cpp
--- old/albert-0.11.1/src/plugins/virtualbox/src/main.cpp       2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/virtualbox/src/main.cpp       2017-05-28 
23:57:15.000000000 +0200
@@ -25,6 +25,7 @@
 #include <QRegularExpression>
 #include <QStandardPaths>
 #include <QString>
+#include <functional>
 #include "main.h"
 #include "vm.h"
 #include "query.h"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/albert-0.11.1/src/plugins/websearch/src/configwidget.cpp 
new/albert-0.11.3/src/plugins/websearch/src/configwidget.cpp
--- old/albert-0.11.1/src/plugins/websearch/src/configwidget.cpp        
2017-04-16 13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/websearch/src/configwidget.cpp        
2017-05-28 23:57:15.000000000 +0200
@@ -14,14 +14,22 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-#include "configwidget.h"
 #include <QFileDialog>
-#include <QStandardPaths>
 #include <QMessageBox>
+#include <QStandardPaths>
+#include "configwidget.h"
+#include "enginesmodel.h"
+#include "main.h"
 
 /** 
***************************************************************************/
-Websearch::ConfigWidget::ConfigWidget(QWidget *parent) : QWidget(parent) {
+Websearch::ConfigWidget::ConfigWidget(Extension *extension, QWidget *parent)
+    : QWidget(parent), extension_(extension) {
+
     ui.setupUi(this);
+
+    enginesModel_ = new EnginesModel(extension, ui.tableView_searches);
+    ui.tableView_searches->setModel(enginesModel_);
+
     
ui.tableView_searches->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
     
ui.tableView_searches->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
 
@@ -49,17 +57,20 @@
 
 /** 
***************************************************************************/
 Websearch::ConfigWidget::~ConfigWidget() {
-
 }
 
 
 
 /** 
***************************************************************************/
 void Websearch::ConfigWidget::onButton_new() {
-    if (ui.tableView_searches->currentIndex().isValid())
-        
ui.tableView_searches->model()->insertRow(ui.tableView_searches->currentIndex().row());
-    else
-        
ui.tableView_searches->model()->insertRow(ui.tableView_searches->model()->rowCount());
+    int row = (ui.tableView_searches->currentIndex().isValid())
+            ? ui.tableView_searches->currentIndex().row()
+            : ui.tableView_searches->model()->rowCount();
+    ui.tableView_searches->model()->insertRow(row);
+
+    QModelIndex index = ui.tableView_searches->model()->index(row, 0, 
QModelIndex());
+    ui.tableView_searches->setCurrentIndex(index);
+    ui.tableView_searches->edit(index);
 }
 
 
@@ -85,10 +96,9 @@
 /** 
***************************************************************************/
 void Websearch::ConfigWidget::onButton_moveUp() {
     ui.tableView_searches->model()->moveRows(
-                QModelIndex(), ui.tableView_searches->currentIndex().row(), 1,
-                QModelIndex(), ui.tableView_searches->currentIndex().row()-1);
-    //          v before this (-1)
-    //|..|..|..|..|XX|..|..|
+                QModelIndex(), ui.tableView_searches->currentIndex().row(),
+                1,
+                QModelIndex(), ui.tableView_searches->currentIndex().row() - 
1);
 }
 
 
@@ -96,10 +106,9 @@
 /** 
***************************************************************************/
 void Websearch::ConfigWidget::onButton_moveDown() {
     ui.tableView_searches->model()->moveRows(
-                QModelIndex(), ui.tableView_searches->currentIndex().row(), 1,
-                QModelIndex(), ui.tableView_searches->currentIndex().row()+2);
-    //             v before this (+2)
-    //|..|..|XX|..|..|..|..|
+                QModelIndex(), ui.tableView_searches->currentIndex().row(),
+                1,
+                QModelIndex(), ui.tableView_searches->currentIndex().row() + 
2);
 }
 
 
@@ -132,5 +141,5 @@
                                   QMessageBox::Yes|QMessageBox::No);
     // Remove if sure
     if (reply == QMessageBox::Yes)
-        emit restoreDefaults();
+        enginesModel_->restoreDefaults();
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/albert-0.11.1/src/plugins/websearch/src/configwidget.h 
new/albert-0.11.3/src/plugins/websearch/src/configwidget.h
--- old/albert-0.11.1/src/plugins/websearch/src/configwidget.h  2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/websearch/src/configwidget.h  2017-05-28 
23:57:15.000000000 +0200
@@ -20,15 +20,21 @@
 
 namespace Websearch {
 
+class Extension;
+class EnginesModel;
+
 class ConfigWidget final : public QWidget
 {
     Q_OBJECT
+
 public:
-    explicit ConfigWidget(QWidget *parent = 0);
+
+    explicit ConfigWidget(Extension *extension, QWidget *parent = 0);
     ~ConfigWidget();
     Ui::ConfigWidget ui;
 
 private:
+
     void onButton_new();
     void onButton_remove();
     void onButton_moveUp();
@@ -36,9 +42,8 @@
     void onButton_setIcon();
     void onButton_restoreDefaults();
 
-signals:
-
-    void restoreDefaults();
+    Extension *extension_;
+    EnginesModel *enginesModel_;
 };
 
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/albert-0.11.1/src/plugins/websearch/src/enginesmodel.cpp 
new/albert-0.11.3/src/plugins/websearch/src/enginesmodel.cpp
--- old/albert-0.11.1/src/plugins/websearch/src/enginesmodel.cpp        
2017-04-16 13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/websearch/src/enginesmodel.cpp        
2017-05-28 23:57:15.000000000 +0200
@@ -15,15 +15,19 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
-#include "enginesmodel.h"
 #include <QDir>
+#include <QDebug>
 #include <QFileInfo>
 #include <QIcon>
 #include <QStandardPaths>
+#include "enginesmodel.h"
+#include "main.h"
+#include "searchengine.h"
 
 namespace {
 
-enum class Section{ Enabled, Name, Trigger, URL, Count };
+enum class Section{ Name, Trigger, URL} ;
+const int sectionCount = 3;
 
 std::map<QString,QIcon> iconCache;
 
@@ -31,21 +35,21 @@
 
 
 /** 
***************************************************************************/
-Websearch::EnginesModel::EnginesModel(std::vector<SearchEngine>& se, QObject 
*parent)
-    : QAbstractTableModel(parent), searchEngines_(se) {
+Websearch::EnginesModel::EnginesModel(Extension *extension, QObject *parent)
+    : QAbstractTableModel(parent), extension_(extension) {
 }
 
 
 /** 
***************************************************************************/
 int Websearch::EnginesModel::rowCount(const QModelIndex &) const {
-    return static_cast<int>(searchEngines_.size());
+    return static_cast<int>(extension_->engines().size());
 }
 
 
 
 /** 
***************************************************************************/
 int Websearch::EnginesModel::columnCount(const QModelIndex &) const {
-    return static_cast<int>(Section::Count);
+    return sectionCount;
 }
 
 
@@ -53,18 +57,12 @@
 /** 
***************************************************************************/
 QVariant Websearch::EnginesModel::headerData(int section, Qt::Orientation 
orientation, int role) const {
     // No sanity check necessary since
-    if ( section<0 || static_cast<int>(Section::Count)<=section )
+    if ( section < 0 || sectionCount <= section )
         return QVariant();
 
 
     if (orientation == Qt::Horizontal){
         switch (static_cast<Section>(section)) {
-        case Section::Enabled:{
-            switch (role) {
-            case Qt::ToolTipRole: return "Enables the searchengine as 
fallback.";
-            default: return QVariant();
-            }
-        }
         case Section::Name:{
             switch (role) {
             case Qt::DisplayRole: return "Name";
@@ -89,8 +87,6 @@
             }
 
         }
-        case Section::Count:
-            return QVariant();
         }
     }
     return QVariant();
@@ -100,26 +96,21 @@
 
 /** 
***************************************************************************/
 QVariant Websearch::EnginesModel::data(const QModelIndex &index, int role) 
const {
-    if (!index.isValid()
-            || index.row() >= static_cast<int>(searchEngines_.size())
-            || index.column() >= 
static_cast<int>(static_cast<int>(Section::Count)))
+    if ( !index.isValid() ||
+         index.row() >= static_cast<int>(extension_->engines().size()) ||
+         index.column() >= sectionCount )
         return QVariant();
 
     switch (role) {
-    case Qt::DisplayRole: {
-        switch (static_cast<Section>(index.column())) {
-        case Section::Name:  return searchEngines_[index.row()].name;
-        case Section::Trigger:  return searchEngines_[index.row()].trigger;
-        case Section::URL:  return searchEngines_[index.row()].url;
-        default: return QVariant();
-        }
-    }
+    case Qt::DisplayRole:
     case Qt::EditRole: {
         switch (static_cast<Section>(index.column())) {
-        case Section::Name:  return searchEngines_[index.row()].name;
-        case Section::Trigger:  return searchEngines_[index.row()].trigger;
-        case Section::URL:  return searchEngines_[index.row()].url;
-        default: return QVariant();
+        case Section::Name:
+            return extension_->engines()[static_cast<ulong>(index.row())].name;
+        case Section::Trigger:
+            return 
extension_->engines()[static_cast<ulong>(index.row())].trigger;
+        case Section::URL:
+            return extension_->engines()[static_cast<ulong>(index.row())].url;
         }
     }
     case Qt::DecorationRole: {
@@ -127,26 +118,19 @@
         case Section::Name:{
             // Resizing request thounsands of repaints. Creating an icon for
             // ever paint event is to expensive. Therefor maintain an icon 
cache
-            QString &iconPath = searchEngines_[index.row()].iconPath;
-            decltype(iconCache)::iterator it = iconCache.find(iconPath);
+            const QString &iconPath = 
extension_->engines()[static_cast<ulong>(index.row())].iconPath;
+            std::map<QString,QIcon>::iterator it = iconCache.find(iconPath);
             if ( it != iconCache.end() )
                 return it->second;
-            return iconCache.emplace(iconPath, QIcon(iconPath)).second;
+            return iconCache.insert(std::make_pair(iconPath, 
QIcon(iconPath))).second;
         }
-        default: return QVariant();
+        case Section::URL:
+        case Section::Trigger:
+            return QVariant();
         }
     }
     case Qt::ToolTipRole: {
-        switch (static_cast<Section>(index.column())) {
-        case Section::Enabled:  return "Check to use as fallback";
-        default: return "Double click to edit";
-        }
-    }
-    case Qt::CheckStateRole: {
-        switch (static_cast<Section>(index.column())) {
-        case Section::Enabled:  return 
(searchEngines_[index.row()].enabled)?Qt::Checked:Qt::Unchecked;
-        default: return QVariant();
-        }
+        return "Double click to edit";
     }
     default:
         return QVariant();
@@ -157,9 +141,9 @@
 
 /** 
***************************************************************************/
 bool Websearch::EnginesModel::setData(const QModelIndex &index, const QVariant 
&value, int role) {
-    if (!index.isValid()
-            || index.row() >= static_cast<int>(searchEngines_.size())
-            || index.column() >= 
static_cast<int>(static_cast<int>(Section::Count)))
+    if ( !index.isValid() ||
+         index.row() >= static_cast<int>(extension_->engines().size()) ||
+         index.column() >= sectionCount)
         return false;
 
     switch (role) {
@@ -168,90 +152,87 @@
             return false;
         QString s = value.toString();
         switch (static_cast<Section>(index.column())) {
-        case Section::Enabled:
-            return false;
-        case Section::Name:
-            searchEngines_[index.row()].name = s;
+        case Section::Name: {
+            std::vector<SearchEngine> newEngines = extension_->engines();
+            newEngines[static_cast<ulong>(index.row())].name = s;
+            extension_->setEngines(newEngines);
             dataChanged(index, index, QVector<int>({Qt::DisplayRole}));
             return true;
-        case Section::Trigger:
-            searchEngines_[index.row()].trigger = s;
+        }
+        case Section::Trigger: {
+            std::vector<SearchEngine> newEngines = extension_->engines();
+            newEngines[static_cast<ulong>(index.row())].trigger = s;
+            extension_->setEngines(newEngines);
             dataChanged(index, index, QVector<int>({Qt::DisplayRole}));
             return true;
-        case Section::URL:
-            searchEngines_[index.row()].url = s;
+        }
+        case Section::URL: {
+            std::vector<SearchEngine> newEngines = extension_->engines();
+            newEngines[static_cast<ulong>(index.row())].url = s;
+            extension_->setEngines(newEngines);
             dataChanged(index, index, QVector<int>({Qt::DisplayRole}));
             return true;
-        default:
-            return false;
         }
-    }
-    case Qt::CheckStateRole: {
-        switch (static_cast<Section>(index.column())) {
-        case Section::Enabled:
-            searchEngines_[index.row()].enabled = value.toBool();
-            dataChanged(index, index, QVector<int>({Qt::CheckStateRole}));
-            return true;
-        default:
-            return false;
         }
     }
     case Qt::DecorationRole: {
         QFileInfo fileInfo(value.toString());
         QString newFilePath;
         uint i = 0;
+
+        // Remove icon from cache
+        
iconCache.erase(extension_->engines()[static_cast<ulong>(index.row())].iconPath);
+
+        // Build the new generic path and copy the file into cache dir
         do {
-        // Build the new path in cache dir
-        newFilePath = 
QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
-                .filePath(QString("%1-%2.%3")
-                            .arg(searchEngines_[index.row()].name)
-                            .arg(i++)
-                            .arg(fileInfo.suffix()));
-        // Copy the file into cache dir
+            newFilePath = 
QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
+                            .filePath(QString("%1-%2.%3")
+                                        
.arg(extension_->engines()[static_cast<ulong>(index.row())].name)
+                                        .arg(i++)
+                                        .arg(fileInfo.suffix()));
         } while (!QFile::copy(fileInfo.filePath(), newFilePath));
+
         // Set the copied file as icon
-        searchEngines_[index.row()].iconPath = newFilePath;
-        dataChanged(index, index, QVector<int>({Qt::DecorationRole}));
-        iconCache.clear();
+        std::vector<SearchEngine> newEngines = extension_->engines();
+        newEngines[static_cast<ulong>(index.row())].iconPath = newFilePath;
+        extension_->setEngines(newEngines);
+
+        // Update the icon in the first section of the row
+        QModelIndex firstSectionIndex = index.model()->index(index.row(), 0);
+        dataChanged(firstSectionIndex, firstSectionIndex, 
QVector<int>({Qt::DecorationRole}));
+
         return true;
     }
     default:
         return false;
     }
-    return false;
 }
 
 
 
 /** 
***************************************************************************/
 Qt::ItemFlags Websearch::EnginesModel::flags(const QModelIndex &index) const {
-    if (!index.isValid())
+    if (index.isValid())
+        return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
+    else
         return Qt::NoItemFlags;
-
-    switch (static_cast<Section>(index.column())) {
-    case Section::Enabled:
-        return Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsUserCheckable;
-    default:
-        return Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable;
-    }
 }
 
 
 
 /** 
***************************************************************************/
 bool Websearch::EnginesModel::insertRows(int position, int rows, const 
QModelIndex &) {
-    if (position<0 || rows<1 || 
static_cast<int>(searchEngines_.size())<position)
+    if ( position < 0 || rows < 1 ||
+         static_cast<int>(extension_->engines().size()) < position)
         return false;
 
     beginInsertRows(QModelIndex(), position, position + rows - 1);
-    for (int row = position; row < position + rows; ++row){
-        searchEngines_.insert(searchEngines_.begin() + row,
-                              SearchEngine({false,
-                                            "<name>",
-                                            "<trigger>",
-                                            ":default",
-                                            
"<http://url/containing/the/?query=%s>"}));
-    }
+    std::vector<SearchEngine> newEngines = extension_->engines();
+    for ( int row = position; row < position + rows; ++row )
+        newEngines.insert(newEngines.begin() + row,
+                          SearchEngine({"<name>", "<trigger>", ":default",
+                                        
"<http://url/containing/the/?query=%s>"}));
+    extension_->setEngines(newEngines);
     endInsertRows();
     return true;
 }
@@ -260,11 +241,15 @@
 
 /** 
***************************************************************************/
 bool Websearch::EnginesModel::removeRows(int position, int rows, const 
QModelIndex &) {
-    if (position<0 || rows<1 || 
static_cast<int>(searchEngines_.size())<position+rows)
+    if ( position < 0 || rows < 1 ||
+         static_cast<int>(extension_->engines().size()) < position + rows)
         return false;
 
-    beginRemoveRows(QModelIndex(), position, position + rows-1);
-    
searchEngines_.erase(searchEngines_.begin()+position,searchEngines_.begin()+(position+rows));
+    beginRemoveRows(QModelIndex(), position, position + rows - 1);
+    std::vector<SearchEngine> newEngines = extension_->engines();
+    newEngines.erase(newEngines.begin() + position,
+                     newEngines.begin() + position + rows);
+    extension_->setEngines(newEngines);
     endRemoveRows();
     return true;
 }
@@ -273,19 +258,34 @@
 
 /** 
***************************************************************************/
 bool Websearch::EnginesModel::moveRows(const QModelIndex &src, int srcRow, int 
cnt, const QModelIndex &dst, int dstRow) {
-    if (srcRow<0 || cnt<1 || dstRow<0
-            || static_cast<int>(searchEngines_.size())<srcRow+cnt-1
-            || static_cast<int>(searchEngines_.size())<dstRow
-            || ( srcRow<=dstRow && dstRow<srcRow+cnt) ) // If its inside the 
source do nothing
+    if ( srcRow < 0 || cnt < 1 || dstRow < 0 ||
+         static_cast<int>(extension_->engines().size()) < srcRow + cnt - 1 ||
+         static_cast<int>(extension_->engines().size()) < dstRow ||
+         ( srcRow <= dstRow && dstRow < srcRow + cnt) ) // If its inside the 
source do nothing
         return false;
 
-    std::vector<SearchEngine> tmp;
-    beginMoveRows(src, srcRow, srcRow+cnt-1, dst, dstRow);
-    tmp.insert(tmp.end(), make_move_iterator(searchEngines_.begin()+srcRow), 
make_move_iterator(searchEngines_.begin() + srcRow+cnt));
-    searchEngines_.erase(searchEngines_.begin()+srcRow, searchEngines_.begin() 
+ srcRow+cnt);
-    const size_t finalDst = dstRow > srcRow ? dstRow - cnt : dstRow;
-    searchEngines_.insert(searchEngines_.begin()+finalDst , 
make_move_iterator(tmp.begin()), make_move_iterator(tmp.end()));
+    std::vector<SearchEngine> newEngines = extension_->engines();
+    beginMoveRows(src, srcRow, srcRow + cnt - 1, dst, dstRow);
+    newEngines.insert(newEngines.begin() + dstRow,
+                      extension_->engines().begin() + srcRow,
+                      extension_->engines().begin() + srcRow + cnt);
+    if ( srcRow < dstRow )
+        newEngines.erase(newEngines.begin() + srcRow,
+                         newEngines.begin() + srcRow + cnt);
+    else
+        newEngines.erase(newEngines.begin() + srcRow + cnt,
+                         newEngines.begin() + srcRow + cnt * 2);
+    extension_->setEngines(newEngines);
     endMoveRows();
     return true;
 }
 
+
+
+/** 
***************************************************************************/
+void Websearch::EnginesModel::restoreDefaults() {
+    beginResetModel();
+    extension_->restoreDefaultEngines();
+    endResetModel();
+}
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/albert-0.11.1/src/plugins/websearch/src/enginesmodel.h 
new/albert-0.11.3/src/plugins/websearch/src/enginesmodel.h
--- old/albert-0.11.1/src/plugins/websearch/src/enginesmodel.h  2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/websearch/src/enginesmodel.h  2017-05-28 
23:57:15.000000000 +0200
@@ -19,13 +19,7 @@
 
 namespace Websearch {
 
-struct SearchEngine {
-    bool    enabled;
-    QString name;
-    QString trigger;
-    QString iconPath;
-    QString url;
-};
+class Extension;
 
 class EnginesModel final : public QAbstractTableModel
 {
@@ -33,7 +27,7 @@
 
 public:
 
-    EnginesModel(std::vector<SearchEngine>&, QObject *parent = Q_NULLPTR);
+    EnginesModel(Extension *extension, QObject *parent = Q_NULLPTR);
 
     int rowCount(const QModelIndex & parent = QModelIndex()) const override;
     int columnCount(const QModelIndex & parent = QModelIndex()) const override;
@@ -45,9 +39,11 @@
     bool removeRows (int position, int rows, const QModelIndex & parent = 
QModelIndex()) override;
     bool moveRows(const QModelIndex &sourceRow, int srcRow, int cnt, const 
QModelIndex & dst, int destinationChild) override;
 
+    void restoreDefaults();
+
 private:
 
-    std::vector<SearchEngine> &searchEngines_;
+    Extension *extension_;
 
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/plugins/websearch/src/main.cpp 
new/albert-0.11.3/src/plugins/websearch/src/main.cpp
--- old/albert-0.11.1/src/plugins/websearch/src/main.cpp        2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/websearch/src/main.cpp        2017-05-28 
23:57:15.000000000 +0200
@@ -247,13 +247,13 @@
 };
 
 std::vector<Websearch::SearchEngine> defaultSearchEngines = {
-    {true, "Google",        "gg ",  ":google",    
"https://www.google.com/search?q=%s"},
-    {true, "Youtube",       "yt ",  ":youtube",   
"https://www.youtube.com/results?search_query=%s"},
-    {true, "Amazon",        "ama ", ":amazon",    
"http://www.amazon.com/s/?field-keywords=%s"},
-    {true, "Ebay",          "eb ",  ":ebay",      
"http://www.ebay.com/sch/i.html?_nkw=%s"},
-    {true, "GitHub",        "gh ",  ":github",    
"https://github.com/search?utf8=✓&q=%s"},
-    {true, "Wikipedia",     "wp ",  ":wikipedia", 
"https://wikipedia.org/w/index.php?search=%s"},
-    {true, "Wolfram Alpha", "=",    ":wolfram",   
"https://www.wolframalpha.com/input/?i=%s"}
+    {"Google",        "gg ",  ":google",    
"https://www.google.com/search?q=%s"},
+    {"Youtube",       "yt ",  ":youtube",   
"https://www.youtube.com/results?search_query=%s"},
+    {"Amazon",        "ama ", ":amazon",    
"http://www.amazon.com/s/?field-keywords=%s"},
+    {"Ebay",          "eb ",  ":ebay",      
"http://www.ebay.com/sch/i.html?_nkw=%s"},
+    {"GitHub",        "gh ",  ":github",    
"https://github.com/search?utf8=✓&q=%s"},
+    {"Wikipedia",     "wp ",  ":wikipedia", 
"https://wikipedia.org/w/index.php?search=%s"},
+    {"Wolfram Alpha", "=",    ":wolfram",   
"https://www.wolframalpha.com/input/?i=%s"}
 };
 
 shared_ptr<Core::Item> buildWebsearchItem(const Websearch::SearchEngine &se, 
const QString &searchterm) {
@@ -270,6 +270,7 @@
     item->setText(se.name);
     item->setSubtext(desc);
     item->setIconPath(se.iconPath);
+    item->setCompletionString(QString("%1%2").arg(se.trigger, searchterm));
 
     item->setActions({action});
 
@@ -302,39 +303,32 @@
 
     std::sort(validTlds.begin(), validTlds.end());
 
-    QString writableLocation =  
QStandardPaths::writableLocation(QStandardPaths::DataLocation);
-    QFile 
dataFile(QDir(writableLocation).filePath(QString("%1.dat").arg(Core::Extension::id)));
-    QFile 
jsonFile(QDir(writableLocation).filePath(QString("%1.json").arg(Core::Extension::id)));
-
-    // If there is an old file
-    if (dataFile.exists()) {
-
-        // Deserialize binary data
-        if (dataFile.open(QIODevice::ReadOnly| QIODevice::Text)) {
-            qDebug() << "Porting websearches from old format";
-            QDataStream in(&dataFile);
-            quint64 size;
-            in >> size;
-            SearchEngine se;
-            for (quint64 i = 0; i < size; ++i) {
-                in >> se.enabled >> se.url >> se.name >> se.trigger >> 
se.iconPath;
-                d->searchEngines.push_back(se);
-            }
-            dataFile.close();
-        } else
-            qWarning() << qPrintable(QString("Could not open file 
'%1'").arg(dataFile.fileName()));
-
-        // Whatever remove it
-        if ( !dataFile.remove() )
-            qWarning() << qPrintable(QString("Could not remove file 
'%1'").arg(dataFile.fileName()));
-
-        // Hmm what to do?
-
-        // Serialize in json format
-        serialize();
-
-    } else if (!deserialize())
-        restoreDefaults();
+    // Move config file from old location to new. (data -> config) TODO: 
REMOVE in 1.0
+    QString dataLocFilePath = 
QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))
+            .filePath(QString("%1.json").arg(Core::Extension::id));
+    QString confLocFilePath = 
QDir(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation))
+            .filePath(QString("%1.json").arg(Core::Extension::id));
+
+    if ( QFile::exists(dataLocFilePath) )
+        QFile::rename(dataLocFilePath, confLocFilePath);
+
+    // Deserialize engines
+    QFile file(confLocFilePath);
+    if (file.open(QIODevice::ReadOnly)) {
+        QJsonArray array = QJsonDocument::fromJson(file.readAll()).array();
+        SearchEngine searchEngine;
+        for ( const QJsonValue& value : array) {
+            QJsonObject object = value.toObject();
+            searchEngine.name     = object["name"].toString();
+            searchEngine.trigger  = object["trigger"].toString();
+            searchEngine.iconPath = object["iconPath"].toString();
+            searchEngine.url      = object["url"].toString();
+            d->searchEngines.push_back(searchEngine);
+        }
+    } else {
+        qWarning() << qPrintable(QString("Could not load from file: 
'%1'.").arg(confLocFilePath));
+        setEngines(defaultSearchEngines);
+    }
 }
 
 
@@ -348,27 +342,8 @@
 
 /** 
***************************************************************************/
 QWidget *Websearch::Extension::widget(QWidget *parent) {
-    if (d->widget.isNull()){
-
-        d->widget = new ConfigWidget(parent);
-        EnginesModel *enginesModel = new EnginesModel(d->searchEngines,
-                                                     
d->widget->ui.tableView_searches);
-        d->widget->ui.tableView_searches->setModel(enginesModel);
-
-        // Serialize engines if anything changed
-        connect(enginesModel, &EnginesModel::dataChanged,
-                this, &Extension::serialize);
-        connect(enginesModel, &EnginesModel::rowsInserted,
-                this, &Extension::serialize);
-        connect(enginesModel, &EnginesModel::rowsRemoved,
-                this, &Extension::serialize);
-        connect(enginesModel, &EnginesModel::rowsMoved,
-                this, &Extension::serialize);
-
-        // TODO Fix all data() if least supported Qt supports its omittance
-        connect(d->widget.data(), &ConfigWidget::restoreDefaults,
-                this, &Extension::restoreDefaults);
-    }
+    if (d->widget.isNull())
+        d->widget = new ConfigWidget(this, parent);
     return d->widget;
 }
 
@@ -397,10 +372,12 @@
         QUrl url = QUrl::fromUserInput(query->searchTerm());
 
         // Check syntax and TLD validity
-        if ( url.isValid() && // Check syntax
-             QRegularExpression(R"R(\S+\.\S+$)R").match(url.host()).hasMatch() 
&&  // Check if not an emty tld
-             std::binary_search(validTlds.begin(), validTlds.end(), // Check 
tld validiy
-                                
url.topLevelDomain().mid(1).toUpper().toLocal8Bit().constData()) ) {
+        if ( url.isValid() && ( // Check syntax
+             query->searchTerm().trimmed().startsWith("http://";) ||
+             query->searchTerm().trimmed().startsWith("https://";) ||
+             
(QRegularExpression(R"R(\S+\.\S+$)R").match(url.host()).hasMatch() &&  // Check 
if not an emty tld
+              std::binary_search(validTlds.begin(), validTlds.end(), // Check 
tld validiy
+                                 
url.topLevelDomain().mid(1).toUpper().toLocal8Bit().constData()) ))) {
 
             shared_ptr<StandardAction> action = 
std::make_shared<StandardAction>();
             action->setText("Open URL");
@@ -433,78 +410,46 @@
 vector<shared_ptr<Core::Item>> Websearch::Extension::fallbacks(const QString & 
searchterm) {
     vector<shared_ptr<Core::Item>> res;
     for (const SearchEngine &se : d->searchEngines)
-        if (se.enabled)
-            res.push_back(buildWebsearchItem(se, searchterm));
+        res.push_back(buildWebsearchItem(se, searchterm));
     return res;
 }
 
 
 
 /** 
***************************************************************************/
-bool Websearch::Extension::deserialize() {
-
-    QFile 
file(QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))
-               .filePath(QString("%1.json").arg(Core::Extension::id)));
-
-    if (!file.open(QIODevice::ReadOnly)) {
-        qWarning() << qPrintable(QString("Could not open file: 
'%1'.").arg(file.fileName()));
-        return false;
-    }
-
-    QJsonArray array = QJsonDocument::fromJson(file.readAll()).array();
-
-    SearchEngine searchEngine;
-    for ( const QJsonValue& value : array) {
-        QJsonObject object = value.toObject();
-        searchEngine.enabled  = object["enabled"].toBool();
-        searchEngine.name     = object["name"].toString();
-        searchEngine.trigger  = object["trigger"].toString();
-        searchEngine.iconPath = object["iconPath"].toString();
-        searchEngine.url      = object["url"].toString();
-        d->searchEngines.push_back(searchEngine);
-    }
-
-    return true;
+const std::vector<Websearch::SearchEngine> &Websearch::Extension::engines() 
const {
+    return d->searchEngines;
 }
 
 
 
 /** 
***************************************************************************/
-bool Websearch::Extension::serialize() {
+void Websearch::Extension::setEngines(const 
std::vector<Websearch::SearchEngine> &engines) {
+    d->searchEngines = engines;
+    emit enginesChanged(d->searchEngines);
 
-    QFile 
file(QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))
+    // Serialize the engines
+    QFile 
file(QDir(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation))
                .filePath(QString("%1.json").arg(Core::Extension::id)));
 
-    if (!file.open(QIODevice::WriteOnly)) {
-        qWarning() << qPrintable(QString("Could not open file: 
'%1'.").arg(file.fileName()));
-        return false;
-    }
-
-    QJsonArray array;
-
-    for ( const SearchEngine& searchEngine : d->searchEngines ) {
-        QJsonObject object;
-        object["name"]     = searchEngine.name;
-        object["url"]      = searchEngine.url;
-        object["trigger"]  = searchEngine.trigger;
-        object["iconPath"] = searchEngine.iconPath;
-        object["enabled"]  = searchEngine.enabled;
-        array.append(object);
-    }
-
-    file.write(QJsonDocument(array).toJson());
-
-    return true;
+    if (file.open(QIODevice::WriteOnly)) {
+        QJsonArray array;
+        for ( const SearchEngine& searchEngine : d->searchEngines ) {
+            QJsonObject object;
+            object["name"]     = searchEngine.name;
+            object["url"]      = searchEngine.url;
+            object["trigger"]  = searchEngine.trigger;
+            object["iconPath"] = searchEngine.iconPath;
+            array.append(object);
+        }
+        file.write(QJsonDocument(array).toJson());
+    } else
+        qCritical() << qPrintable(QString("Could not write to file: 
'%1'.").arg(file.fileName()));
 }
 
 
 
 /** 
***************************************************************************/
-void Websearch::Extension::restoreDefaults() {
-    /* Init std searches */
-    d->searchEngines = defaultSearchEngines;
-    serialize();
-
-    if (!d->widget.isNull())
-        d->widget->ui.tableView_searches->reset();
+void Websearch::Extension::restoreDefaultEngines() {
+    setEngines(defaultSearchEngines);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/albert-0.11.1/src/plugins/websearch/src/main.h 
new/albert-0.11.3/src/plugins/websearch/src/main.h
--- old/albert-0.11.1/src/plugins/websearch/src/main.h  2017-04-16 
13:17:45.000000000 +0200
+++ new/albert-0.11.3/src/plugins/websearch/src/main.h  2017-05-28 
23:57:15.000000000 +0200
@@ -19,6 +19,7 @@
 #include "extension.h"
 #include "queryhandler.h"
 #include "fallbackprovider.h"
+#include "searchengine.h"
 
 namespace Websearch {
 
@@ -45,14 +46,19 @@
     void handleQuery(Core::Query * query) override;
     std::vector<std::shared_ptr<Core::Item>> fallbacks(const QString &) 
override;
 
-private:
+    const std::vector<SearchEngine>& engines() const;
+    void setEngines(const std::vector<SearchEngine> &engines);
+
+    void restoreDefaultEngines();
 
-    bool deserialize();
-    bool serialize();
-    void restoreDefaults();
+private:
 
     std::unique_ptr<Internal> d;
 
+signals:
+
+    void enginesChanged(const std::vector<SearchEngine> &engines);
+
 };
 
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/albert-0.11.1/src/plugins/websearch/src/searchengine.h 
new/albert-0.11.3/src/plugins/websearch/src/searchengine.h
--- old/albert-0.11.1/src/plugins/websearch/src/searchengine.h  1970-01-01 
01:00:00.000000000 +0100
+++ new/albert-0.11.3/src/plugins/websearch/src/searchengine.h  2017-05-28 
23:57:15.000000000 +0200
@@ -0,0 +1,29 @@
+// albert - a simple application launcher for linux
+// Copyright (C) 2014-2017 Manuel Schneider
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+
+#pragma once
+#include <QString>
+
+namespace Websearch {
+
+struct SearchEngine {
+    QString name;
+    QString trigger;
+    QString iconPath;
+    QString url;
+};
+
+}


Reply via email to