summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--CMakeLists.txt19
-rw-r--r--README.md3
-rw-r--r--config.cpp91
-rw-r--r--config.h11
-rw-r--r--config.ui42
-rwxr-xr-xinstall.sh8
-rw-r--r--pass.cpp137
-rw-r--r--pass.h10
-rw-r--r--plasma-runner-pass.desktop2
-rw-r--r--postinst3
-rwxr-xr-xuninstall.sh9
12 files changed, 192 insertions, 145 deletions
diff --git a/.gitignore b/.gitignore
index 796b96d..f4774b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
/build
+/cmake-build-debug
+/.idea
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aa7050a..fb0e438 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,3 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12)
+
project(RunnerPass)
find_package(ECM 5.12.0 REQUIRED NO_MODULE)
@@ -12,6 +14,21 @@ include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDECompilerSettings NO_POLICY_SCOPE)
+# CPack configuration
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Copies a password from the password store (https://www.passwordstore.org/) to the clipboard")
+set(CPACK_PACKAGE_NAME krunner-pass)
+set(CPACK_PACKAGE_VERSION "1.1.0")
+set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
+set(CPACK_DEBIAN_PACKAGE_MAINTAINER "alex1701c")
+set(CPACK_RPM_PACKAGE_ARCHITECTURE "x86_64")
+set(CPACK_GENERATOR "DEB;RPM")
+set(CPACK_RPM_PACKAGE_ARCHITECTURE "x86_64")
+
+set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
+set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
+
+INCLUDE(CPack)
+
set(krunner_pass_SRCS
pass.cpp
)
@@ -42,6 +59,6 @@ target_link_libraries(krunner_pass KF5::Runner Qt5::Widgets
add_dependencies(krunner_pass kcm_krunner_pass)
-install(TARGETS krunner_pass kcm_krunner_pass DESTINATION ${PLUGIN_INSTALL_DIR})
+install(TARGETS krunner_pass kcm_krunner_pass DESTINATION ${KDE_INSTALL_QTPLUGINDIR})
install(FILES plasma-runner-pass.desktop plasma-runner-pass_config.desktop DESTINATION ${SERVICES_INSTALL_DIR})
install(FILES krunner_pass.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR})
diff --git a/README.md b/README.md
index b9f7159..3af8614 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,8 @@ apt-get install build-essential cmake extra-cmake-modules gettext \
libkf5service-dev \
libkf5runner-dev \
libkf5textwidgets-dev \
- libkf5notifications-dev
+ libkf5notifications-dev \
+ libkf5kcmutils-dev
mkdir -p build
cd build
diff --git a/config.cpp b/config.cpp
index e342161..6eff86f 100644
--- a/config.cpp
+++ b/config.cpp
@@ -20,14 +20,15 @@
#include <KPluginFactory>
#include <krunner/abstractrunner.h>
#include <QToolButton>
+#include <QtCore/QDir>
+#include "kcmutils_version.h"
#include "config.h"
K_PLUGIN_FACTORY(PassConfigFactory, registerPlugin<PassConfig>("kcm_krunner_pass");)
-
-
-PassConfigForm::PassConfigForm(QWidget *parent) : QWidget(parent)
+PassConfigForm::PassConfigForm(QWidget *parent)
+ : QWidget(parent)
{
setupUi(this);
this->listSavedActions->setDragEnabled(true);
@@ -46,32 +47,36 @@ PassConfigForm::PassConfigForm(QWidget *parent) : QWidget(parent)
connect(this->buttonAddAction, &QPushButton::clicked, [this]() {
this->addPassAction(this->lineName->text(), this->lineIcon->text(), this->lineRegEx->text());
});
+
+ // Disable add button if the necessary field are not filled out
+ connect(this->lineIcon, &QLineEdit::textChanged, this, &PassConfigForm::validateAddButton);
+ connect(this->lineName, &QLineEdit::textChanged, this, &PassConfigForm::validateAddButton);
+ connect(this->lineRegEx, &QLineEdit::textChanged, this, &PassConfigForm::validateAddButton);
+ validateAddButton();
}
-void PassConfigForm::addPassAction(const QString &name, const QString &icon, const QString &regex, bool isNew /* = true */)
+void
+PassConfigForm::addPassAction(const QString &name, const QString &icon, const QString &regex, bool isNew /* = true */)
{
// Checks
- for (auto act: this->passActions())
+ for (const auto &act: this->passActions())
if (act.name == name)
return;
- if (name.isEmpty() || icon.isEmpty() || regex.isEmpty())
- return;
-
// Widgets
auto *listWidget = new QWidget(this);
auto *layoutAction = new QHBoxLayout(listWidget);
auto *buttonRemoveAction = new QToolButton(listWidget);
- buttonRemoveAction->setIcon(QIcon::fromTheme("remove"));
+ buttonRemoveAction->setIcon(QIcon::fromTheme("delete"));
layoutAction->setMargin(0);
layoutAction->addStretch();
layoutAction->addWidget(buttonRemoveAction);
listWidget->setLayout(layoutAction);
// Item
- auto *item = new QListWidgetItem(name + (isNew ? "*":""), this->listSavedActions);
- item->setData(Qt::UserRole, QVariant::fromValue(PassAction {name, icon, regex}));
+ auto *item = new QListWidgetItem(name + (isNew ? "*" : ""), this->listSavedActions);
+ item->setData(Qt::UserRole, QVariant::fromValue(PassAction{name, icon, regex}));
this->listSavedActions->setItemWidget(item, listWidget);
this->clearInputs();
@@ -91,8 +96,8 @@ void PassConfigForm::addPassAction(const QString &name, const QString &icon, con
QVector<PassAction> PassConfigForm::passActions()
{
QVector<PassAction> passActions;
- for(int i = 0; i < this->listSavedActions->count(); ++i) {
- QListWidgetItem* item = this->listSavedActions->item(i);
+ for (int i = 0; i < listSavedActions->count(); ++i) {
+ QListWidgetItem *item = this->listSavedActions->item(i);
passActions << item->data(Qt::UserRole).value<PassAction>();
}
return passActions;
@@ -100,8 +105,8 @@ QVector<PassAction> PassConfigForm::passActions()
void PassConfigForm::clearPassActions()
{
- for(int i = 0; i < this->listSavedActions->count(); ++i) {
- QListWidgetItem* item = this->listSavedActions->item(i);
+ for (int i = 0; i < listSavedActions->count(); ++i) {
+ QListWidgetItem *item = this->listSavedActions->item(i);
delete this->listSavedActions->itemWidget(item);
}
@@ -115,21 +120,30 @@ void PassConfigForm::clearInputs()
this->lineRegEx->clear();
}
+void PassConfigForm::validateAddButton()
+{
+ this->buttonAddAction->setDisabled(this->lineIcon->text().isEmpty() ||
+ this->lineName->text().isEmpty() ||
+ this->lineRegEx->text().isEmpty());
+}
-PassConfig::PassConfig(QWidget *parent, const QVariantList &args) :
+PassConfig::PassConfig(QWidget *parent, const QVariantList &args)
+ :
KCModule(parent, args)
{
this->ui = new PassConfigForm(this);
- QGridLayout* layout = new QGridLayout(this);
+ QGridLayout *layout = new QGridLayout(this);
layout->addWidget(ui, 0, 0);
-
- load();
-
- connect(this->ui,SIGNAL(passActionAdded()),this,SLOT(changed()));
- connect(this->ui,SIGNAL(passActionRemoved()),this,SLOT(changed()));
- connect(this->ui->checkAdditionalActions,SIGNAL(stateChanged(int)),this,SLOT(changed()));
- connect(this->ui->checkShowFileContentAction,SIGNAL(stateChanged(int)),this,SLOT(changed()));
- connect(this->ui->listSavedActions,SIGNAL(itemSelectionChanged()), this, SLOT(changed()));
+#if KCMUTILS_VERSION >= QT_VERSION_CHECK(5, 64, 0)
+ const auto changedSlotPointer = &PassConfig::markAsChanged;
+#else
+ const auto changedSlotPointer = static_cast<void (PassConfig::*)()>(&PassConfig::changed);
+#endif
+ connect(this->ui, &PassConfigForm::passActionAdded, this, changedSlotPointer);
+ connect(this->ui, &PassConfigForm::passActionRemoved, this, changedSlotPointer);
+ connect(this->ui->checkAdditionalActions, &QCheckBox::stateChanged, this, changedSlotPointer);
+ connect(this->ui->checkShowFileContentAction, &QCheckBox::stateChanged, this, changedSlotPointer);
+ connect(this->ui->listSavedActions, &QListWidget::itemSelectionChanged, this, changedSlotPointer);
}
void PassConfig::load()
@@ -137,9 +151,7 @@ void PassConfig::load()
KCModule::load();
KSharedConfig::Ptr cfg = KSharedConfig::openConfig(QStringLiteral("krunnerrc"));
- KConfigGroup passCfg = cfg->group("Runners");
- passCfg = KConfigGroup(&passCfg, "Pass");
-
+ KConfigGroup passCfg = cfg->group("Runners").group("Pass");
bool showActions = passCfg.readEntry(Config::showActions, false);
bool showFileContentAction = passCfg.readEntry(Config::showFileContentAction, false);
@@ -150,16 +162,12 @@ void PassConfig::load()
// Load saved actions
this->ui->clearPassActions();
- auto actionGroup = passCfg.group(Config::Group::Actions);
- auto groups = actionGroup.groupList();
- Q_FOREACH (auto name, groups) {
+ const auto actionGroup = passCfg.group(Config::Group::Actions);
+ for (const auto &name: actionGroup.groupList()) {
auto group = actionGroup.group(name);
auto passAction = PassAction::fromConfig(group);
-
this->ui->addPassAction(passAction.name, passAction.icon, passAction.regex, false);
}
-
- emit changed(false);
}
void PassConfig::save()
@@ -167,28 +175,23 @@ void PassConfig::save()
KCModule::save();
KSharedConfig::Ptr cfg = KSharedConfig::openConfig(QStringLiteral("krunnerrc"));
- KConfigGroup passCfg = cfg->group("Runners");
- passCfg = KConfigGroup(&passCfg, "Pass");
-
+ KConfigGroup passCfg = cfg->group("Runners").group("Pass");
auto showActions = this->ui->checkAdditionalActions->isChecked();
- auto showFileContentAction = this->ui->checkShowFileContentAction->isChecked();
+ auto showFileContentAction = this->ui->checkShowFileContentAction->isChecked();
passCfg.writeEntry(Config::showActions, showActions);
passCfg.writeEntry(Config::showFileContentAction, showFileContentAction);
-
passCfg.deleteGroup(Config::Group::Actions);
if (showActions) {
int i = 0;
- for (PassAction act: this->ui->passActions()) {
+ for (PassAction &act: this->ui->passActions()) {
auto group = passCfg.group(Config::Group::Actions).group(QString::number(i++));
act.writeToConfig(group);
}
}
-
- emit changed(false);
}
void PassConfig::defaults()
@@ -200,7 +203,11 @@ void PassConfig::defaults()
ui->clearPassActions();
ui->clearInputs();
+#if KCMUTILS_VERSION >= QT_VERSION_CHECK(5, 64, 0)
+ markAsChanged();
+#else
emit changed(true);
+#endif
}
diff --git a/config.h b/config.h
index f11e293..474c7cd 100644
--- a/config.h
+++ b/config.h
@@ -76,6 +76,9 @@ public:
signals:
void passActionRemoved();
void passActionAdded();
+
+private slots:
+ void validateAddButton();
};
@@ -84,12 +87,12 @@ class PassConfig : public KCModule
Q_OBJECT
public:
- explicit PassConfig(QWidget* parent = 0, const QVariantList& args = QVariantList());
+ explicit PassConfig(QWidget* parent = nullptr, const QVariantList& args = QVariantList());
public Q_SLOTS:
- void save();
- void load();
- void defaults();
+ void save() override;
+ void load() override;
+ void defaults() override;
private:
PassConfigForm *ui;
diff --git a/config.ui b/config.ui
index f712d23..8a06b41 100644
--- a/config.ui
+++ b/config.ui
@@ -6,32 +6,37 @@
<rect>
<x>0</x>
<y>0</y>
- <width>314</width>
- <height>420</height>
+ <width>356</width>
+ <height>421</height>
</rect>
</property>
<property name="windowTitle">
<string>Pass Config</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="0">
- <widget class="QCheckBox" name="checkAdditionalActions">
- <property name="text">
- <string>Show additional actions</string>
+ <item row="4" column="0">
+ <widget class="QGroupBox" name="boxSavedActions">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="title">
+ <string>Saved Actions</string>
</property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <widget class="QListWidget" name="listSavedActions"/>
+ </item>
+ </layout>
</widget>
</item>
<item row="1" column="0">
- <widget class="QCheckBox" name="checkShowFileContentAction">
- <property name="enabled">
- <bool>false</bool>
- </property>
+ <widget class="QCheckBox" name="checkAdditionalActions">
<property name="text">
- <string>Show an action for displaying full file content</string>
+ <string>Show additional actions</string>
</property>
</widget>
</item>
- <item row="2" column="0">
+ <item row="3" column="0">
<widget class="QGroupBox" name="boxNewAction">
<property name="enabled">
<bool>false</bool>
@@ -93,19 +98,14 @@
</layout>
</widget>
</item>
- <item row="3" column="0">
- <widget class="QGroupBox" name="boxSavedActions">
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="checkShowFileContentAction">
<property name="enabled">
<bool>false</bool>
</property>
- <property name="title">
- <string>Saved Actions</string>
+ <property name="text">
+ <string>Show an action for displaying full file content</string>
</property>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="0" column="0">
- <widget class="QListWidget" name="listSavedActions"/>
- </item>
- </layout>
</widget>
</item>
</layout>
diff --git a/install.sh b/install.sh
index 7d6331c..73144ae 100755
--- a/install.sh
+++ b/install.sh
@@ -5,11 +5,11 @@ set -e
mkdir -p build
cd build
-cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DCMAKE_INSTALL_PREFIX=`kf5-config --prefix` -DQT_PLUGIN_INSTALL_DIR=`kf5-config --qt-plugins`
-make
+cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DCMAKE_INSTALL_PREFIX=`kf5-config --prefix` -DCMAKE_BUILD_TYPE=Release
+make -j$(nproc)
sudo make install
set +e
-kquitapp5 krunner 2> /dev/null
-kstart5 --windowclass krunner krunner > /dev/null 2>&1 &
+kquitapp5 krunner
+kstart5 --windowclass krunner krunner
diff --git a/pass.cpp b/pass.cpp
index c02f9d0..da6adb9 100644
--- a/pass.cpp
+++ b/pass.cpp
@@ -17,7 +17,7 @@
*****************************************************************************/
#include <KSharedConfig>
#include <KLocalizedString>
-#include <knotification.h>
+#include <KNotification>
#include <QAction>
#include <QDirIterator>
@@ -27,8 +27,9 @@
#include <QMessageBox>
#include <QClipboard>
#include <QDebug>
+#include <QApplication>
-#include <stdlib.h>
+#include <cstdlib>
#include "pass.h"
#include "config.h"
@@ -39,41 +40,40 @@ using namespace std;
Pass::Pass(QObject *parent, const QVariantList &args)
: Plasma::AbstractRunner(parent, args)
{
- Q_UNUSED(args);
-
// General runner configuration
- setObjectName(QString("Pass"));
+ setObjectName(QStringLiteral("Pass"));
setSpeed(AbstractRunner::NormalSpeed);
setPriority(HighestPriority);
- auto comment = i18n("Looks for a password matching :q:. Pressing ENTER copies the password to the clipboard.");
- setDefaultSyntax(Plasma::RunnerSyntax(QString(":q:"), comment));
}
-Pass::~Pass() {}
+Pass::~Pass() = default;
void Pass::reloadConfiguration()
{
- actions().clear();
+ clearActions();
orderedActions.clear();
KConfigGroup cfg = config();
+ cfg.config()->reparseConfiguration(); // Just to be sure
this->showActions = cfg.readEntry(Config::showActions, false);
if (showActions) {
- auto configActions = cfg.group(Config::Group::Actions);
+ const auto configActions = cfg.group(Config::Group::Actions);
// Create actions for every additional field
- auto groups = configActions.groupList();
- Q_FOREACH (auto name, groups) {
+ const auto configActionsList = configActions.groupList();
+ for (const auto &name: configActionsList) {
auto group = configActions.group(name);
auto passAction = PassAction::fromConfig(group);
auto icon = QIcon::fromTheme(passAction.icon, QIcon::fromTheme("object-unlocked"));
- QAction *act = addAction(passAction.name, icon , passAction.name);
+ QAction *act = addAction(passAction.name, icon, passAction.name);
act->setData(passAction.regex);
this->orderedActions << act;
}
+ } else {
+ this->orderedActions.clear();
}
if (cfg.readEntry(Config::showFileContentAction, false)) {
@@ -82,6 +82,12 @@ void Pass::reloadConfiguration()
act->setData(Config::showFileContentAction);
this->orderedActions << act;
}
+
+ setDefaultSyntax(Plasma::RunnerSyntax(QString(":q:"),
+ i18n("Looks for a password matching :q:. Pressing ENTER copies the password to the clipboard.")));
+
+ addSyntax(Plasma::RunnerSyntax(QString("pass :q:"),
+ i18n("Looks for a password matching :q:. This way you avoid results from other runners")));
}
void Pass::init()
@@ -89,42 +95,43 @@ void Pass::init()
reloadConfiguration();
this->baseDir = QDir(QDir::homePath() + "/.password-store");
- auto baseDir = getenv("PASSWORD_STORE_DIR");
- if (baseDir != nullptr) {
- this->baseDir = QDir(baseDir);
+ auto _baseDir = getenv("PASSWORD_STORE_DIR");
+ if (_baseDir != nullptr) {
+ this->baseDir = QDir(_baseDir);
}
this->timeout = 45;
- auto timeout = getenv("PASSWORD_STORE_CLIP_TIME");
- if (timeout != nullptr) {
- QString str(timeout);
+ auto _timeout = getenv("PASSWORD_STORE_CLIP_TIME");
+ if (_timeout != nullptr) {
+ QString str(_timeout);
bool ok;
- auto timeout = str.toInt(&ok);
+ auto _timeoutParsed = str.toInt(&ok);
if (ok) {
- this->timeout = timeout;
+ this->timeout = _timeoutParsed;
}
}
this->passOtpIdentifier = "totp::";
- auto passOtpIdentifier = getenv("PASSWORD_STORE_OTP_IDENTIFIER");
- if (passOtpIdentifier != nullptr) {
- this->passOtpIdentifier = passOtpIdentifier;
+ auto _passOtpIdentifier = getenv("PASSWORD_STORE_OTP_IDENTIFIER");
+ if (_passOtpIdentifier != nullptr) {
+ this->passOtpIdentifier = _passOtpIdentifier;
}
initPasswords();
- connect(&watcher, SIGNAL(directoryChanged(QString)), this, SLOT(reinitPasswords(QString)));
+ connect(&watcher, &QFileSystemWatcher::directoryChanged, this, &Pass::reinitPasswords);
}
-void Pass::initPasswords() {
+void Pass::initPasswords()
+{
passwords.clear();
watcher.addPath(this->baseDir.absolutePath());
QDirIterator it(this->baseDir, QDirIterator::Subdirectories);
while (it.hasNext()) {
it.next();
- auto fileInfo = it.fileInfo();
- if (fileInfo.isFile() && fileInfo.suffix() == "gpg") {
+ const auto fileInfo = it.fileInfo();
+ if (fileInfo.isFile() && fileInfo.suffix() == QLatin1String("gpg")) {
QString password = this->baseDir.relativeFilePath(fileInfo.absoluteFilePath());
// Remove suffix ".gpg"
password.chop(4);
@@ -135,8 +142,9 @@ void Pass::initPasswords() {
}
}
-void Pass::reinitPasswords(const QString &path) {
- Q_UNUSED(path);
+void Pass::reinitPasswords(const QString &path)
+{
+ Q_UNUSED(path)
lock.lockForWrite();
initPasswords();
@@ -145,22 +153,26 @@ void Pass::reinitPasswords(const QString &path) {
void Pass::match(Plasma::RunnerContext &context)
{
- if (!context.isValid()) return;
+ if (!context.isValid()) {
+ return;
+ }
auto input = context.query();
+ // If we use the prefix we want to remove it
+ if (input.contains(queryPrefix)) {
+ input = input.remove(QLatin1String("pass")).simplified();
+ } else if (input.count() < 3 && !context.singleRunnerQueryMode()) {
+ return;
+ }
QList<Plasma::QueryMatch> matches;
lock.lockForRead();
- Q_FOREACH (auto password, passwords) {
- QRegularExpression re(".*" + input + ".*", QRegularExpression::CaseInsensitiveOption);
- if (re.match(password).hasMatch()) {
+ for (const auto &password: qAsConst(passwords)) {
+ if (password.contains(input, Qt::CaseInsensitive)) {
Plasma::QueryMatch match(this);
- if (input.length() == password.length()) {
- match.setType(Plasma::QueryMatch::ExactMatch);
- } else {
- match.setType(Plasma::QueryMatch::CompletionMatch);
- }
+ match.setType(input.length() == password.length() ?
+ Plasma::QueryMatch::ExactMatch : Plasma::QueryMatch::CompletionMatch);
match.setIcon(QIcon::fromTheme("object-locked"));
match.setText(password);
matches.append(match);
@@ -176,42 +188,37 @@ void Pass::clip(const QString &msg)
QClipboard *cb = QApplication::clipboard();
cb->setText(msg);
QTimer::singleShot(timeout * 1000, cb, [cb]() {
- cb->clear();
- });
+ cb->setText(QString());
+ });
}
void Pass::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match)
{
Q_UNUSED(context);
- auto regexp = QRegularExpression("^" + QRegularExpression::escape(this->passOtpIdentifier) + ".*");
- auto isOtp = match.text().split('/').filter(regexp).size() > 0;
+ const auto regexp = QRegularExpression("^" + QRegularExpression::escape(this->passOtpIdentifier) + ".*");
+ const auto isOtp = !match.text().split('/').filter(regexp).isEmpty();
- QProcess *pass = new QProcess();
+ auto *pass = new QProcess();
QStringList args;
if (isOtp) {
- args << "otp" << "show" << match.text();
- } else {
- args << "show" << match.text();
+ args << "otp";
}
+ args << "show" << match.text();
pass->start("pass", args);
connect(pass, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
[=](int exitCode, QProcess::ExitStatus exitStatus) {
- Q_UNUSED(exitCode);
- Q_UNUSED(exitStatus);
+ Q_UNUSED(exitStatus)
if (exitCode == 0) {
-
const auto output = pass->readAllStandardOutput();
-
if (match.selectedAction() != nullptr) {
const auto data = match.selectedAction()->data().toString();
-
if (data == Config::showFileContentAction) {
QMessageBox::information(nullptr, match.text(), output);
} else {
QRegularExpression re(data, QRegularExpression::MultilineOption);
- auto matchre = re.match(output);
+ const auto matchre = re.match(output);
if (matchre.hasMatch()) {
clip(matchre.captured(1));
@@ -225,9 +232,9 @@ void Pass::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &m
}
}
} else {
- auto string = QString::fromUtf8(output.data());
- auto lines = string.split('\n', QString::SkipEmptyParts);
- if (lines.count() > 0) {
+ const auto string = QString::fromUtf8(output.data());
+ const auto lines = string.split('\n', QString::SkipEmptyParts);
+ if (!lines.isEmpty()) {
clip(lines[0]);
this->showNotification(match.text());
}
@@ -243,20 +250,16 @@ QList<QAction *> Pass::actionsForMatch(const Plasma::QueryMatch &match)
{
Q_UNUSED(match)
- if (showActions)
- return this->orderedActions;
-
- return QList<QAction *>();
+ return this->orderedActions;
}
-void Pass::showNotification(const QString &text, const QString &actionName /* = "" */)
+void Pass::showNotification(const QString &text, const QString &actionName)
{
- QString msgPrefix = actionName.isEmpty() ? "":actionName + i18n(" of ");
- QString msg = i18n("Password %1 copied to clipboard for %2 seconds", text, timeout);
- auto notification = KNotification::event("password-unlocked", "Pass", msgPrefix + msg,
- "object-unlocked", nullptr, KNotification::CloseOnTimeout,
- "krunner_pass");
- QTimer::singleShot(timeout * 1000, notification, SLOT(quit));
+ const QString msgPrefix = actionName.isEmpty() ? "" : actionName + i18n(" of ");
+ const QString msg = i18n("Password %1 copied to clipboard for %2 seconds", text, timeout);
+ KNotification::event("password-unlocked", "Pass", msgPrefix + msg,
+ "object-unlocked", nullptr, KNotification::CloseOnTimeout,
+ "krunner_pass");
}
K_EXPORT_PLASMA_RUNNER(pass, Pass)
diff --git a/pass.h b/pass.h
index 7b1da33..1218b87 100644
--- a/pass.h
+++ b/pass.h
@@ -23,6 +23,7 @@
#include <QDir>
#include <QReadWriteLock>
#include <QFileSystemWatcher>
+#include <QRegularExpression>
class Pass : public Plasma::AbstractRunner
{
@@ -30,7 +31,7 @@ class Pass : public Plasma::AbstractRunner
public:
Pass(QObject *parent, const QVariantList &args);
- ~Pass();
+ ~Pass() override;
void clip(const QString &msg);
void match(Plasma::RunnerContext &) override;
@@ -39,13 +40,13 @@ public:
void reloadConfiguration() override;
-public slots:
+public Q_SLOTS:
void reinitPasswords(const QString &path);
protected:
void init() override;
void initPasswords();
- void showNotification(const QString &, const QString & = "");
+ void showNotification(const QString &, const QString & = QString());
private:
QDir baseDir;
@@ -57,7 +58,8 @@ private:
bool showActions;
QList<QAction *> orderedActions;
-
+
+ const QRegularExpression queryPrefix = QRegularExpression("^pass( .+)?$");
};
#endif
diff --git a/plasma-runner-pass.desktop b/plasma-runner-pass.desktop
index fd4cb89..1606799 100644
--- a/plasma-runner-pass.desktop
+++ b/plasma-runner-pass.desktop
@@ -8,7 +8,7 @@ X-KDE-Library=krunner_pass
X-KDE-PluginInfo-Author=Lukas Fürmetz
X-KDE-PluginInfo-Email=fuermetz@mailbox.org
X-KDE-PluginInfo-Name=Pass
-X-KDE-PluginInfo-Version=1.0.3
+X-KDE-PluginInfo-Version=1.1.0
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true
X-Plasma-AdvertiseSingleRunnerQueryMode=true
diff --git a/postinst b/postinst
new file mode 100644
index 0000000..3100ccd
--- /dev/null
+++ b/postinst
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+killall krunner
diff --git a/uninstall.sh b/uninstall.sh
new file mode 100755
index 0000000..e3efe5b
--- /dev/null
+++ b/uninstall.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# Exit immediately if something fails
+set -e
+
+cd build
+sudo make uninstall
+kquitapp5 krunner
+kstart5 --windowclass krunner krunner