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 @@ </head> <body> <p>Applications are looked up in the &quot;<span style=" font-style:italic;">applications/&quot;</span> 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: <span style=" font-weight:600; font-style:italic;">__XDG_DATA_DIRS__</span>. </p> -<p>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 <a href="https://specifications.freedesktop.org/desktop-entry-spec/latest/">desktop entry sprecificion</a>.</p></body></html></string> +<p>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 <a href="https://specifications.freedesktop.org/desktop-entry-spec/latest/">desktop entry specification</a>.</p></body></html></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; +}; + +}