diff --git a/Mangonel.cpp b/Mangonel.cpp index fb39f7e..6775739 100644 --- a/Mangonel.cpp +++ b/Mangonel.cpp @@ -1,180 +1,295 @@ /* * Copyright 2010-2012 Bart Kroon * Copyright 2012, 2013 Martin Sandsmark * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "Mangonel.h" #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include "Config.h" //Include the providers. #include "providers/Applications.h" #include "providers/Paths.h" #include "providers/Shell.h" #include "providers/Calculator.h" #include "providers/Units.h" #include #include Mangonel::Mangonel() { // Setup our global shortcut. m_actionShow = new QAction(i18n("Show Mangonel"), this); m_actionShow->setObjectName(QString("show")); QList shortcuts({QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Space)}); KGlobalAccel::self()->setShortcut(m_actionShow, shortcuts); shortcuts = KGlobalAccel::self()->shortcut(m_actionShow); connect(m_actionShow, SIGNAL(triggered()), this, SIGNAL(triggered())); QString shortcutString; if (!shortcuts.isEmpty()) { shortcutString = shortcuts.first().toString(); } QString message = xi18nc("@info", "Press %1 to show Mangonel.", shortcutString); KNotification::event(QLatin1String("startup"), message); QSettings settings; m_history = settings.value("history").toStringList(); // Instantiate the providers. m_providers["applications"] = new Applications(this); m_providers["paths"] = new Paths(this); m_providers["shell"] = new Shell(this); m_providers["Calculator"] = new Calculator(this); m_providers["Units"] = new Units(this); + + settings.beginGroup("popularities"); + for (const QString &key : settings.childGroups()) { + settings.beginGroup(key); + Popularity pop; + pop.count = settings.value("launches").toLongLong(); + pop.lastUse = settings.value("lastUse").toLongLong(); + pop.matchStrings = settings.value("matchStrings").toStringList(); + m_popularities.insert(key, pop); + settings.endGroup(); + } +} + +void Mangonel::storePopularities() +{ + QSettings settings; + settings.beginGroup("popularities"); + for (const QString &key : m_popularities.keys()) { + settings.beginGroup(key); + settings.setValue("launches", m_popularities[key].count); + settings.setValue("lastUse", m_popularities[key].lastUse); + settings.setValue("matchString", m_popularities[key].matchStrings); + settings.endGroup(); + } } Mangonel::~Mangonel() { } Mangonel *Mangonel::instance() { static Mangonel s_instance; return &s_instance; } QList Mangonel::apps() { QList ret; - for (QPointer app : m_apps) { + for (QPointer app : m_apps) { ret.append(app.data()); } return ret; } -void Mangonel::getApp(QString query) +void Mangonel::setQuery(const QString &query) { - for (QPointer app : m_apps) { + for (QPointer app : m_apps) { if (!app) { continue; } app->deleteLater(); } + m_apps.clear(); if (query.length() > 0) { m_current = -1; for (Provider* provider : m_providers) { - QList list = provider->getResults(query); - for (Application *app : list) { + QList list = provider->getResults(query); + for (ProviderResult *app : list) { app->setParent(this); + + if (app->isCalculation) { + m_apps.append(app); + continue; + } + if (m_popularities.contains(app->program)) { + const Popularity &popularity = m_popularities[app->program]; + app->priority = QDateTime::currentSecsSinceEpoch() - popularity.lastUse; + app->priority -= (3600 * 360) * popularity.count; + + if (popularity.matchStrings.contains(query)) { + app->priority /= 2; + } + } + m_apps.append(app); } } - std::sort(m_apps.begin(), m_apps.end(), [](Application *a, Application *b) { + std::sort(m_apps.begin(), m_apps.end(), [&](ProviderResult *a, ProviderResult *b) { + if (a->isCalculation != b->isCalculation) { + if (a->isCalculation) { + return true; + } + if (b->isCalculation) { + return false; + } + } + + const bool aStartMatch = a->name.startsWith(query, Qt::CaseInsensitive); + const bool bStartMatch = b->name.startsWith(query, Qt::CaseInsensitive); + if (aStartMatch != bStartMatch) { + return aStartMatch && !bStartMatch; + } + + const bool aContains = a->name.contains(query, Qt::CaseInsensitive); + const bool bContains = b->name.contains(query, Qt::CaseInsensitive); + if (aContains != bContains) { + return aContains && !bContains; + } + if (m_popularities.contains(a->program)) { + if (!m_popularities.contains(b->program)) { + return true; + } + + const Popularity &aPopularity = m_popularities[a->program]; + const Popularity &bPopularity = m_popularities[b->program]; + if (aPopularity.count >= bPopularity.count) { + return aPopularity.count >= bPopularity.count; + } + + return aPopularity.lastUse > bPopularity.lastUse; + } + if (a->priority != b->priority) { return a->priority < b->priority; } else { return a->name > b->name; } }); } + m_currentQuery = query; emit appsChanged(); } +void Mangonel::launch(QObject *selectedObject) +{ + ProviderResult *selected = qobject_cast(selectedObject); + if (!selected) { + qWarning() << "Trying to launch null pointer"; + return; + } + + addToHistory(m_currentQuery); + selected->launch(); + + if (selected->isCalculation) { + return; + } + + Popularity pop; + const QString exec = selected->program; + + if (m_popularities.contains(exec)) { + pop = m_popularities[exec]; + pop.lastUse = QDateTime::currentSecsSinceEpoch(); + + // Cap it, so history doesn't haunt forever + pop.count = std::min(pop.count + 1, qint64(10)); + + if (pop.matchStrings.contains(m_currentQuery)) { + pop.matchStrings.removeAll(m_currentQuery); + } + } else { + pop.lastUse = QDateTime::currentSecsSinceEpoch(); + pop.count = 0; + } + pop.matchStrings.prepend(m_currentQuery); + + m_popularities[exec] = pop; + + storePopularities(); +} + void Mangonel::showConfig() { QList shortcuts(KGlobalAccel::self()->globalShortcut(qApp->applicationName(), "show")); ConfigDialog* dialog = new ConfigDialog; if (!shortcuts.isEmpty()) { dialog->setHotkey(shortcuts.first()); } connect(dialog, SIGNAL(hotkeyChanged(QKeySequence)), this, SLOT(setHotkey(QKeySequence))); installEventFilter(this); dialog->exec(); removeEventFilter(this); } void Mangonel::setHotkey(const QKeySequence& hotkey) { KGlobalAccel::self()->setShortcut(m_actionShow, QList() << hotkey, KGlobalAccel::NoAutoloading); } void Mangonel::configureNotifications() { KNotifyConfigWidget::configure(); } QString Mangonel::selectionClipboardContent() { return QGuiApplication::clipboard()->text(QClipboard::Selection); } void Mangonel::addToHistory(const QString &text) { m_history.prepend(text); emit historyChanged(); // Store history of session. QSettings settings; settings.setValue("history", m_history); settings.sync(); } // kate: indent-mode cstyle; space-indent on; indent-width 4; diff --git a/Mangonel.h b/Mangonel.h index 25dc127..a555bdb 100644 --- a/Mangonel.h +++ b/Mangonel.h @@ -1,77 +1,85 @@ /* * Copyright 2010-2012 Bart Kroon * Copyright 2012, 2013 Martin Sandsmark * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef Mangonel_H #define Mangonel_H #include "Provider.h" #include #include #include class Mangonel : public QObject { Q_OBJECT Q_PROPERTY(QList apps READ apps NOTIFY appsChanged) Q_PROPERTY(QStringList history READ history NOTIFY historyChanged) public: ~Mangonel(); static Mangonel *instance(); QList apps(); const QStringList &history() { return m_history; } public slots: - void getApp(QString query); + void setQuery(const QString &query); + void launch(QObject *selectedObject); void showConfig(); void configureNotifications(); QString selectionClipboardContent(); void addToHistory(const QString &text); signals: void appsChanged(); void triggered(); void historyChanged(); private slots: void setHotkey(const QKeySequence& hotkey); private: Mangonel(); - + void storePopularities(); + QAction* m_actionShow; bool m_processingKey; QStringList m_history; QHash m_providers; - QList> m_apps; + + // QPointer so it gets nulled when the object is deleted + QList> m_apps; + + QHash m_popularities; + int m_current; + QString m_currentQuery; }; #endif // Mangonel_H // kate: indent-mode cstyle; space-indent on; indent-width 4; diff --git a/Provider.cpp b/Provider.cpp index 6442e60..ba551da 100644 --- a/Provider.cpp +++ b/Provider.cpp @@ -1,35 +1,32 @@ /* * Copyright 2016 Martin Sandsmark * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "Provider.h" -Application::Application() -{} - Provider::Provider(QObject *parent) : QObject(parent) { } diff --git a/Provider.h b/Provider.h index 4d9165f..d2b9cb6 100644 --- a/Provider.h +++ b/Provider.h @@ -1,85 +1,85 @@ /* * Copyright 2010-2012 Bart Kroon * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef Provider_H #define Provider_H #include #include -struct popularity +struct Popularity { qint64 lastUse; qint64 count; + QStringList matchStrings; }; -struct Application; +struct ProviderResult; // Abstract base class of providers. class Provider : public QObject { Q_OBJECT public: explicit Provider (QObject *parent); Provider() = delete; virtual ~Provider() {} public slots: - virtual QList getResults(QString query) = 0; - virtual int launch(QVariant selected) = 0; + virtual QList getResults(QString query) = 0; + virtual int launch(const QString &exec) = 0; }; // Struct stored in AppList. -struct Application : public QObject +struct ProviderResult : public QObject { Q_OBJECT Q_PROPERTY(QString name MEMBER name CONSTANT) Q_PROPERTY(QString completion MEMBER completion CONSTANT) Q_PROPERTY(QString icon MEMBER icon CONSTANT) Q_PROPERTY(QString type MEMBER type CONSTANT) Q_PROPERTY(int priority MEMBER priority CONSTANT) public: - Application(); - + bool isCalculation = false; QString name; QString completion; QString icon; long priority = 0;//INT_MAX; - QVariant program; - Provider* object; //Pointer to the search provider that provided this result. + QString program; + Provider *object; //Pointer to the search provider that provided this result. QString type; public slots: void launch() { object->launch(program); } }; #endif // Provider_H // kate: indent-mode cstyle; space-indent on; indent-width 4; diff --git a/main.qml b/main.qml index a968e46..327e9d2 100644 --- a/main.qml +++ b/main.qml @@ -1,357 +1,361 @@ import QtQuick 2.2 import QtQuick.Window 2.2 import QtQuick.Controls 1.4 import org.kde 1.0 import QtGraphicalEffects 1.0 Window { id: window flags: Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.X11BypassWindowManagerHint color: "transparent" width: 1000 height: 650 visible: true y: -height onVisibleChanged:{ inputText.text = "" if (visible) { requestActivate() var desktopWidth = window.screen.width window.width = Math.max(desktopWidth / 1.5, 800) } inputText.preHistoryText = "" inputText.historyIndex = -1 } onActiveChanged: if (!active) visible = false Connections { target: Mangonel onTriggered: window.visible = true } Rectangle { id: background anchors { top: parent.top left: parent.left right: parent.right margins: shadow.radius } height: 400 + historyList.height Behavior on height { NumberAnimation { duration: 50 } } color: Qt.rgba(0, 0, 0, 0.5) radius: 10 visible: false Rectangle { id: bottomBackground anchors { bottom: background.bottom left: background.left right: background.right } color: "black" height: inputText.height + 20 } } DropShadow { id: shadow anchors.fill: background radius: 10 samples: 17 color: Qt.rgba(0, 0, 0, 0.75) source: background cached: true } MouseArea { id: mouseArea anchors.fill: background acceptedButtons: Qt.RightButton onClicked: { popupMenu.popup() } } ListView { id: resultList visible: false anchors { top: background.top // bottom: historyList.top left: background.left right: background.right } height: 350 clip: true model: Mangonel.apps orientation: Qt.Horizontal highlightMoveDuration: 50 preferredHighlightBegin: width/2 - itemWidth/2 preferredHighlightEnd: width/2 + itemWidth/2 highlightRangeMode: ListView.StrictlyEnforceRange property real itemWidth: height delegate: Item { width: resultList.itemWidth height: resultList.height function launch() { - modelData.launch(modelData.program) + if (!modelData) { + return + } + + Mangonel.launch(modelData) } property string type: modelData.type property string completion: modelData.completion opacity: ListView.view.currentIndex === index ? 1 : 0.2 Behavior on opacity { NumberAnimation { duration: 200 } } Image { id: icon anchors { top: parent.top topMargin: 10 horizontalCenter: parent.horizontalCenter } source: "image://icon/" + modelData.icon sourceSize.width: parent.width sourceSize.height: parent.height - nameText.height - 20 visible: false } Glow { id: iconGlow anchors.fill: icon source: icon radius: 16 samples: 32 } Text { id: nameText anchors { bottom: parent.bottom bottomMargin: 20 left: parent.left right: parent.right } property string name: modelData.name onNameChanged: { var index = name.toLowerCase().indexOf(inputText.text.toLowerCase()) if (index === -1) { text = name return } text = name.substring(0, index) text += "" text += name.substring(index, index + inputText.text.length) text += "" text += name.substring(index + inputText.text.length) } color: "white" font.pointSize: 20 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter text: modelData.name wrapMode: Text.WordWrap } } } LinearGradient { id: mask anchors.fill: resultList property real centerLeft: (width / 2 - resultList.itemWidth / 2) / width property real centerRight: (width / 2 + resultList.itemWidth / 2) / width gradient: Gradient { GradientStop { position: 0.1; color: Qt.rgba(1, 1, 1, 1) } GradientStop { position: mask.centerLeft; color: Qt.rgba(0, 0, 0, 0) } GradientStop { position: mask.centerRight; color: Qt.rgba(0, 0, 0, 0) } GradientStop { position: 0.9; color: Qt.rgba(1, 1, 1, 1) } } start: Qt.point(0, 0) end: Qt.point(resultList.width, 0) opacity: 0.5 visible: false } MaskedBlur { anchors.fill: resultList source: resultList maskSource: mask radius: 8 samples: 24 } Text { anchors { left: background.left leftMargin: 15 verticalCenter: inputText.verticalCenter } text: (resultList.count > 0 && resultList.currentItem !== null) ? resultList.currentItem.type : "" color: "white" } ListView { id: historyList anchors { bottom: inputText.top bottomMargin: 15 } x: inputText.x + inputText.cursorRectangle.x - inputText.width height: inputText.historyIndex >= 0 ? 190 : 0 interactive: false highlightFollowsCurrentItem: true currentIndex: inputText.historyIndex model: height ? Mangonel.history : 0 verticalLayoutDirection: ListView.BottomToTop delegate: Text { text: modelData; color: "white"; font.bold: index == inputText.historyIndex; opacity: font.bold ? 1 : 0.4 } } TextInput { id: inputText anchors { horizontalCenter: background.horizontalCenter bottom: background.bottom bottomMargin: 10 } property var history: Mangonel.history property int historyIndex: -1 property string preHistoryText: "" onHistoryIndexChanged: { if (historyIndex < 0) { text = preHistoryText return } if (historyIndex >= history.length ) return text = history[historyIndex] } Keys.onDownPressed: { if (historyIndex >= 0) { historyIndex-- } } Keys.onUpPressed: { if (historyIndex < 0) { // preserve what is written now preHistoryText = text } if (historyIndex <= history.length - 1) { historyIndex++ } } color: "white" focus: true font.pointSize: 15 font.bold: true - onTextChanged: Mangonel.getApp(text) + onTextChanged: Mangonel.setQuery(text) Keys.onEscapePressed: window.visible = false Keys.onLeftPressed: { if (resultList.currentIndex > 0) { resultList.currentIndex-- } event.accepted = true } Keys.onRightPressed: { if (resultList.currentIndex < resultList.count - 1) { resultList.currentIndex++ } event.accepted = true } Keys.onTabPressed: { event.accepted = true if (resultList.currentItem === null) { return } text = resultList.currentItem.completion } onAccepted: { if (resultList.currentItem === null) { return } - Mangonel.addToHistory(text) + resultList.currentItem.launch() window.visible = false } } MouseArea { anchors { left: background.left right: background.right bottom: background.bottom } acceptedButtons: "MiddleButton" onClicked: inputText.text += Mangonel.selectionClipboardContent() height: bottomBackground.height } Menu { id: popupMenu title: "Mangonel" MenuItem { text: qsTr("Configure &shortcuts") iconName: "configure-shortcuts" onTriggered: Mangonel.showConfig() shortcut: StandardKey.Preferences } MenuItem { text: qsTr("Configure ¬ifications") iconName: "preferences-desktop-notifications" onTriggered: Mangonel.configureNotifications() } MenuSeparator {} MenuItem { text: qsTr("&Quit") iconName: "application-exit" onTriggered: Qt.quit() shortcut: StandardKey.Quit } } // Ugly hack to work around being shown with garbage on initial showing with nvidia driver Component.onCompleted: uglyHackTimer.start() Timer { id: uglyHackTimer repeat: false interval: 100 onTriggered: { window.width = Math.max(window.screen.width / 1.5, 800) window.y = window.screen.height / 2 - height / 2 window.x = window.screen.width / 2 - width / 2 window.flags = Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint window.visible = false } } } diff --git a/providers/Applications.cpp b/providers/Applications.cpp index 9ed66a0..d1c5aaa 100644 --- a/providers/Applications.cpp +++ b/providers/Applications.cpp @@ -1,162 +1,114 @@ /* * Copyright 2010-2012 Bart Kroon * Copyright 2012, 2013 Martin Sandsmark * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "Applications.h" - - #include #include #include #include #include #include #include #include Applications::Applications(QObject *parent) : Provider(parent) { - QSettings settings; - settings.beginGroup("applications"); - for (const QString &key : settings.childGroups()) { - settings.beginGroup(key); - popularity pop; - pop.count = settings.value("launches").toLongLong(); - pop.lastUse = settings.value("lastUse").toLongLong(); - m_popularities.insert(key, pop); - settings.endGroup(); - } } Applications::~Applications() { - storePopularities(); } -Application *Applications::createApp(const KService::Ptr &service) +ProviderResult *Applications::createApp(const KService::Ptr &service) { - Application *app = new Application; + ProviderResult *app = new ProviderResult; app->name = service->name(); app->completion = app->name; app->icon = service->icon(); app->object = this; - app->program = service->exec(); + + QString exec = service->exec(); + exec.remove(QRegularExpression("\\%[fFuUdDnNickvm]")); + + app->program = exec; QFileInfo entryPathInfo(service->entryPath()); app->priority = QDateTime::currentSecsSinceEpoch(); if (entryPathInfo.exists()) { app->priority = app->priority - entryPathInfo.lastModified().toSecsSinceEpoch(); } else { // KService can't give us the path to anything... } if (service->isApplication()) { app->type = i18n("Run application"); } else { app->type = i18n("Open control module"); } return app; } -QList Applications::getResults(QString term) +QList Applications::getResults(QString term) { - QList list; + QList list; term = term.toHtmlEscaped(); - term.replace('\'', " "); - QString query = "exist Exec and ( (exist Keywords and '%1' ~subin Keywords) or (exist GenericName and '%1' ~~ GenericName) or (exist Name and '%1' ~~ Name) or ('%1' ~~ Exec) )"; - query = query.arg(term); - KService::List services = KServiceTypeTrader::self()->query("Application", query); - services.append(KServiceTypeTrader::self()->query("KCModule", query)); - foreach(const KService::Ptr &service, services) { - if (service->noDisplay()) + term.replace('\'', ' '); + + static const QString query = "exist Exec and ( (exist Keywords and '%1' ~subin Keywords) or (exist GenericName and '%1' ~~ GenericName) or (exist Name and '%1' ~~ Name) or ('%1' ~~ Exec) )"; + + KService::List services = KServiceTypeTrader::self()->query("Application", query.arg(term)); + services.append(KServiceTypeTrader::self()->query("KCModule", query.arg(term))); + + for (const KService::Ptr &service : services) { + if (service->noDisplay()) { continue; + } - Application *app = createApp(service); + ProviderResult *app = createApp(service); if (app->name.isEmpty()) { delete app; continue; } - - if (m_popularities.contains(service->exec())) { - app->priority = QDateTime::currentSecsSinceEpoch() - m_popularities[service->exec()].lastUse; - app->priority -= (3600 * 360) * m_popularities[service->exec()].count; - } else { - qreal modifier = 1; - if (service->isApplication()) modifier *= 1.1; - if (app->name.startsWith(term)) modifier *= 1.5; - if (app->name.startsWith(term, Qt::CaseInsensitive)) modifier *= 1.1; - if (app->name.contains(term)) modifier *= 1.05; - if (app->name.contains(term, Qt::CaseInsensitive)) modifier *= 1.01; - if (!app->name.contains(term, Qt::CaseInsensitive)) modifier /= 2; - - modifier += 1. / app->name.length(); - app->priority /= modifier; - } + if (service->isApplication()) app->priority *= 1.1; list.append(app); } return list; } -int Applications::launch(QVariant selected) +int Applications::launch(const QString &selected) { - QString exec = selected.toString(); - exec.remove(QRegularExpression("\\%[fFuUdDnNickvm]")); - popularity pop; - if (m_popularities.contains(exec)) { - pop = m_popularities[exec]; - pop.lastUse = QDateTime::currentSecsSinceEpoch(); - pop.count++; - } else { - pop.lastUse = QDateTime::currentSecsSinceEpoch(); - pop.count = 0; - } - m_popularities[selected.toString()] = pop; - - storePopularities(); - if (QProcess::startDetached(exec)) { + if (QProcess::startDetached(selected)) { return 0; } else { return 1; } } -void Applications::storePopularities() -{ - QSettings settings; - settings.beginGroup("applications"); - for (const QString &key : m_popularities.keys()) { - settings.beginGroup(key); - settings.setValue("launches", m_popularities[key].count); - settings.setValue("lastUse", m_popularities[key].lastUse); - settings.endGroup(); - } - -} - -// kate: indent-mode cstyle; space-indent on; indent-width 4; +// kate: indent-mode cstyle; space-indent on; indent-width 4; diff --git a/providers/Applications.h b/providers/Applications.h index b0196e7..4c31562 100644 --- a/providers/Applications.h +++ b/providers/Applications.h @@ -1,53 +1,51 @@ /* * Copyright 2010-2012 Bart Kroon * Copyright 2012, 2013 Martin Sandsmark * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef APPLICATIONS_H #define APPLICATIONS_H #include "Provider.h" #include class Applications : public Provider { Q_OBJECT public: Applications(QObject *parent); ~Applications(); public slots: - QList getResults(QString query) override; - int launch(QVariant selected) override; + QList getResults(QString query) override; + int launch(const QString &selected) override; private: - Application *createApp(const KService::Ptr &service); - void storePopularities(); - QHash m_popularities; + ProviderResult *createApp(const KService::Ptr &service); }; #endif // kate: indent-mode cstyle; space-indent on; indent-width 4; diff --git a/providers/Calculator.cpp b/providers/Calculator.cpp index 9d2eaae..10816eb 100644 --- a/providers/Calculator.cpp +++ b/providers/Calculator.cpp @@ -1,85 +1,86 @@ /* * Copyright 2010-2012 Bart Kroon * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "Calculator.h" #include #include #include #include #include #include #include #include #include "calculator/evaluator.h" #include "calculator/numberformatter.h" #include Calculator::Calculator(QObject *parent) : Provider(parent) { } Calculator::~Calculator() {} -QList Calculator::getResults(QString query) +QList Calculator::getResults(QString query) { - QList list; + QList list; Evaluator *ev = Evaluator::instance(); query = ev->autoFix(query); if (query.isEmpty()) { return list; } ev->setExpression(query); const Quantity quantity = ev->evalNoAssign(); if (!ev->error().isEmpty()) { return list; } - Application *app = new Application; + ProviderResult *app = new ProviderResult; app->icon = "accessories-calculator"; app->name = NumberFormatter::format(quantity); app->program = app->name; app->object = this; app->type = i18n("Calculation"); + app->isCalculation = true; list.append(app); return list; } -int Calculator::launch(QVariant selected) +int Calculator::launch(const QString &exec) { QClipboard* clipboard = QApplication::clipboard(); - clipboard->setText(selected.toString(), QClipboard::Selection); + clipboard->setText(exec, QClipboard::Selection); return 0; } // kate: indent-mode cstyle; space-indent on; indent-width 4; diff --git a/providers/Calculator.h b/providers/Calculator.h index 301dbd7..f5a4916 100644 --- a/providers/Calculator.h +++ b/providers/Calculator.h @@ -1,48 +1,48 @@ /* * Copyright 2010-2012 Bart Kroon * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef Calculator_H #define Calculator_H #include "Provider.h" typedef double (*calcFunct)(double val1, double val2); class Calculator : public Provider { Q_OBJECT public: explicit Calculator(QObject *parent); ~Calculator(); public slots: - QList getResults(QString query); - int launch(QVariant selected); + QList getResults(QString query); + int launch(const QString &exec); }; #endif // Calculator_H // kate: indent-mode cstyle; space-indent on; indent-width 4; diff --git a/providers/Paths.cpp b/providers/Paths.cpp index 1e3e73b..da4b278 100644 --- a/providers/Paths.cpp +++ b/providers/Paths.cpp @@ -1,110 +1,110 @@ /* * Copyright 2010-2012 Bart Kroon * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "Paths.h" #include #include #include #include #include static QString subUser(QString path) { QString homePath = QDir::homePath(); if (path.startsWith(homePath)) path = "~" + path.mid(homePath.length(), -1); return path; } Paths::Paths(QObject *parent) : Provider(parent) { } Paths::~Paths() {} -QList Paths::getResults(QString query) +QList Paths::getResults(QString query) { - QList list; + QList list; QDir dir; if (query.startsWith("/")) { dir = QDir::root(); query.remove(0, 1); } else { dir = QDir::home(); } QStringList walk = query.split("/", QString::SkipEmptyParts); if (walk.isEmpty() || query.endsWith('/')) { walk.append(""); } QString part = walk.takeFirst(); while (walk.length() > 0) { dir.cd(part); part = walk.takeFirst(); } QFileInfoList paths = dir.entryInfoList(QStringList(part + '*'), QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files, QDir::Time); if (paths.size() > 100) { paths = paths.mid(0, 100); } for(const QFileInfo &path : paths) { - Application *result = new Application(); + ProviderResult *result = new ProviderResult(); result->name = subUser(path.absoluteFilePath()); result->completion = result->name.left(result->name.lastIndexOf("/")) + "/" + path.fileName(); QFileInfo info(path.absoluteFilePath()); result->priority = info.lastModified().toSecsSinceEpoch(); if (path.isDir()) { result->completion += "/"; result->icon = "system-file-manager"; } else { result->icon = m_mimeDb.mimeTypeForFile(path.absoluteFilePath()).iconName(); } result->object = this; result->program = path.absoluteFilePath(); result->type = i18n("Open path"); list.append(result); } return list; } -int Paths::launch(QVariant selected) +int Paths::launch(const QString &exec) { - QDesktopServices::openUrl(QUrl::fromLocalFile(selected.toString())); + QDesktopServices::openUrl(QUrl::fromLocalFile(exec)); return 0; } // kate: indent-mode cstyle; space-indent on; indent-width 4; diff --git a/providers/Paths.h b/providers/Paths.h index f1e313c..be9cada 100644 --- a/providers/Paths.h +++ b/providers/Paths.h @@ -1,49 +1,49 @@ /* * Copyright 2010-2012 Bart Kroon * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef Paths_H #define Paths_H #include "Provider.h" #include class Paths : public Provider { Q_OBJECT public: Paths(QObject *parent); ~Paths(); public slots: - QList getResults(QString query) override; - int launch(QVariant selected) override; + QList getResults(QString query) override; + int launch(const QString &exec) override; private: QMimeDatabase m_mimeDb; }; #endif //Paths_H // kate: indent-mode cstyle; space-indent on; indent-width 4; diff --git a/providers/Shell.cpp b/providers/Shell.cpp index 503eb1b..47ef8e4 100644 --- a/providers/Shell.cpp +++ b/providers/Shell.cpp @@ -1,128 +1,127 @@ /* * Copyright 2010-2012 Bart Kroon * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "Shell.h" #include #include #include #include #include #include #include namespace { QMap walkDir(QString path) { QMap binList; QDir dir = QDir(path); QFileInfoList list = dir.entryInfoList(QStringList(), QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files); - foreach(QFileInfo file, list) - { - if (file.isDir()) - { - if (file.isSymLink() && file.canonicalFilePath() != path) + for (const QFileInfo &file : list) { + if (file.isDir()) { + if (file.isSymLink() && file.canonicalFilePath() != path) { binList.unite(walkDir(file.absoluteFilePath())); - } - else - { - if (file.isExecutable()) + } + } else { + if (file.isExecutable()) { binList.insert(file.fileName(), file.absoluteFilePath()); + } } } return binList; } QStringList getPathEnv() { QString pathEnv = getenv("PATH"); QStringList pathList = pathEnv.split(":", QString::SkipEmptyParts); pathList.append(QDir::homePath() + "/bin"); pathList.removeDuplicates(); return pathList; } } Shell::Shell(QObject *parent) : Provider(parent) { - this->index.clear(); - foreach(QString dir, getPathEnv()) - { - this->index.unite(walkDir(dir)); + index.clear(); + + for (const QString &dir : getPathEnv()) { + index.unite(walkDir(dir)); } } Shell::~Shell() {} -QList Shell::getResults(QString query) +QList Shell::getResults(QString query) { - QList list; + QList list; + return list; QMapIterator iterator(this->index); while (iterator.hasNext()) { iterator.next(); if (!iterator.key().startsWith(query.left(query.indexOf(" ")), Qt::CaseInsensitive)) { continue; } QString args = query.right(query.length() - query.indexOf(" ")); if (args == query) { args = ""; } - Application *app = new Application; + ProviderResult *app = new ProviderResult; app->name = iterator.value() + args; app->completion = iterator.key(); app->icon = "system-run"; app->object = this; app->program = iterator.value() + args; app->type = i18n("Shell command"); app->priority = QFileInfo(iterator.value()).lastModified().toSecsSinceEpoch(); list.append(app); } return list; } -int Shell::launch(QVariant selected) +int Shell::launch(const QString &exec) { - QStringList args = selected.toString().split(" "); + QStringList args = exec.split(" "); if (args.isEmpty()) { - qWarning() << "Asked to launch invalid program:" << selected; + qWarning() << "Asked to launch invalid program:" << exec; return 0; } QString program(args.takeFirst()); QProcess::startDetached(program, args); return 0; } // kate: indent-mode cstyle; space-indent on; indent-width 4; diff --git a/providers/Shell.h b/providers/Shell.h index 6404915..04f1a8f 100644 --- a/providers/Shell.h +++ b/providers/Shell.h @@ -1,50 +1,50 @@ /* * Copyright 2010-2012 Bart Kroon * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef Shell_H #define Shell_H #include "Provider.h" #include class Shell : public Provider { Q_OBJECT public: Shell(QObject *parent); ~Shell(); public slots: - QList getResults(QString query) override; - int launch(QVariant selected) override; + QList getResults(QString query) override; + int launch(const QString &exec) override; private: QMap index; }; #endif //Shell_H // kate: indent-mode cstyle; space-indent on; indent-width 4; diff --git a/providers/Units.cpp b/providers/Units.cpp index 024ce5b..316ac36 100644 --- a/providers/Units.cpp +++ b/providers/Units.cpp @@ -1,180 +1,181 @@ /* * Copyright 2010-2012 Bart Kroon * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "Units.h" #include #include #include #include #include #include #include Units::Units(QObject *parent) : Provider(parent) { } Units::~Units() {} -QList Units::getResults(QString query) +QList Units::getResults(QString query) { - QList list; + QList list; QRegExp pattern("(\\d+)\\s*(\\w+)\\s+(?:\\=|to|is|in)\\s+(\\w+)$", Qt::CaseInsensitive); if (!query.contains(pattern) || pattern.captureCount() != 3) { return list; } const KUnitConversion::Unit inputUnit = resolveUnitName(pattern.cap(2)); if (!inputUnit.isValid()) { return list; } const double inputNumber = pattern.cap(1).toDouble(); const KUnitConversion::Value inputValue(inputNumber, inputUnit); const KUnitConversion::Unit outputUnit = resolveUnitName(pattern.cap(3), inputUnit.category()); if (!outputUnit.isValid()) { return list; } const KUnitConversion::Value outputValue = m_converter.convert(inputValue, outputUnit); int precision = 2; qreal calculationResult = outputValue.number(); if (calculationResult < 100) { precision = 6; } double scaledResult = calculationResult * std::pow(10, precision); while (precision > 0 && std::floor(scaledResult) == std::ceil(scaledResult)) { precision--; scaledResult = calculationResult * std::pow(10, precision); } const QString inputString = QLocale::system().toString(inputValue.number(), 'f', precision + 1); const QString outputString = QLocale::system().toString(outputValue.number(), 'f', precision + 1); - Application *result = new Application; + ProviderResult *result = new ProviderResult; result->icon = "accessories-calculator"; result->object = this; result->name = i18nc("conversion from one unit to another", "%1 %2 is %3 %4", inputString, inputValue.unit().symbol(), outputString, outputValue.unit().symbol()); result->program = result->name; result->type = i18n("Unit conversion"); + result->isCalculation = true; list.append(result); return list; } -int Units::launch(QVariant selected) +int Units::launch(const QString &exec) { QClipboard* clipboard = QApplication::clipboard(); - clipboard->setText(selected.toString(), QClipboard::Selection); + clipboard->setText(exec, QClipboard::Selection); return 0; } KUnitConversion::Unit Units::resolveUnitName(const QString &name, const KUnitConversion::UnitCategory &category) { KUnitConversion::Unit unit; if (!category.isNull()) { unit = category.unit(name); } else { unit = m_converter.unit(name); } if (unit.isValid()) { return unit; } // Didn't match directly, try to match without case sensitivity if (!category.isNull()) { // try only common first unit = matchUnitCaseInsensitive(name, category, OnlyCommonUnits); if (unit.isValid()) { return unit; } // If not common, try something else unit = matchUnitCaseInsensitive(name, category, AllUnits); if (unit.isValid()) { return unit; } } else { for (const KUnitConversion::UnitCategory &candidateCategory : m_converter.categories()) { unit = matchUnitCaseInsensitive(name, candidateCategory, OnlyCommonUnits); if (unit.isValid()) { return unit; } } // Was not a common unit, try all units for (const KUnitConversion::UnitCategory &candidateCategory : m_converter.categories()) { unit = matchUnitCaseInsensitive(name, candidateCategory, AllUnits); if (unit.isValid()) { return unit; } } } return unit; } KUnitConversion::Unit Units::matchUnitCaseInsensitive(const QString &name, const KUnitConversion::UnitCategory &category, const UnitMatchingLevel level) { if (category.isNull()) { return KUnitConversion::Unit(); } QSet commonIds; if (level == OnlyCommonUnits) { for (const KUnitConversion::Unit &unit : category.mostCommonUnits()) { commonIds.insert(unit.id()); } } for (const QString &candidateName : category.allUnits()) { if (name.compare(candidateName, Qt::CaseInsensitive)) { continue; } KUnitConversion::Unit candidate = category.unit(candidateName); if (level == OnlyCommonUnits && !commonIds.contains(candidate.id())) { continue; } if (candidate.isValid()) { return candidate; } } return KUnitConversion::Unit(); } // kate: indent-mode cstyle; space-indent on; indent-width 4; diff --git a/providers/Units.h b/providers/Units.h index 47a04e6..e204a5d 100644 --- a/providers/Units.h +++ b/providers/Units.h @@ -1,57 +1,57 @@ /* * Copyright 2010-2012 Bart Kroon * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef Units_H #define Units_H #include "Provider.h" #include class Units : public Provider { Q_OBJECT public: Units(QObject *parent); ~Units(); public slots: - QList getResults(QString query) override; - int launch(QVariant selected) override; + QList getResults(QString query) override; + int launch(const QString &exec) override; private: enum UnitMatchingLevel { OnlyCommonUnits, AllUnits }; KUnitConversion::Unit resolveUnitName(const QString &name, const KUnitConversion::UnitCategory &category = KUnitConversion::UnitCategory()); KUnitConversion::Unit matchUnitCaseInsensitive(const QString &name, const KUnitConversion::UnitCategory &category, const UnitMatchingLevel level); KUnitConversion::Converter m_converter; }; #endif // Units_H // kate: indent-mode cstyle; space-indent on; indent-width 4;