Removed search functionality ( this is covered by qss now).
Dieser Commit ist enthalten in:
Ursprung
7a82cdd31b
Commit
3970019fac
1
BUGS
1
BUGS
@ -1,2 +1 @@
|
|||||||
SearchWorker: isPending etc. may need proper locking (with mutexes)
|
|
||||||
Memory leaks(ignored for now due to short-running nature of the application)
|
Memory leaks(ignored for now due to short-running nature of the application)
|
||||||
|
16
README.md
16
README.md
@ -1,9 +1,7 @@
|
|||||||
qsRunner
|
qsRunner
|
||||||
========
|
========
|
||||||
qsRunner is a launcher. It contains user defined entries for applications and also searches
|
qsRunner is a launcher. It contains user defined entries for applications and also searches
|
||||||
system-applications. Using libcalculate, it can also be used as a calculator. It
|
system-applications. Using libcalculate, it can also be used as a calculator.
|
||||||
can also search for files (and their contents) by querying a sqlite database, although it itself does
|
|
||||||
not index files.
|
|
||||||
|
|
||||||
If you run a desktop environment like KDE it is questionable whether you will
|
If you run a desktop environment like KDE it is questionable whether you will
|
||||||
find this useful, since they usually bring applications that are more or less
|
find this useful, since they usually bring applications that are more or less
|
||||||
@ -16,7 +14,6 @@ Dependencies
|
|||||||
It has been only tested for Qt 5.7.
|
It has been only tested for Qt 5.7.
|
||||||
|
|
||||||
For the calculation engine, libqalculate is needed.
|
For the calculation engine, libqalculate is needed.
|
||||||
For file search, easyindex is necessary.
|
|
||||||
|
|
||||||
Currently no conditional compile flags are supported...
|
Currently no conditional compile flags are supported...
|
||||||
|
|
||||||
@ -33,9 +30,6 @@ Config format
|
|||||||
Path: $HOME/.config/qsRunner/qsrunner.config
|
Path: $HOME/.config/qsRunner/qsrunner.config
|
||||||
|
|
||||||
```
|
```
|
||||||
[Search]
|
|
||||||
dbpath="/path/to/database.sqlite"
|
|
||||||
|
|
||||||
[General]
|
[General]
|
||||||
systemApplicationsPath="/usr/share/applications/"
|
systemApplicationsPath="/usr/share/applications/"
|
||||||
```
|
```
|
||||||
@ -80,11 +74,3 @@ terminal.
|
|||||||
Calculator
|
Calculator
|
||||||
----------
|
----------
|
||||||
Start by typing "=", followed by your expression, e. g: "=(2+3)^2"
|
Start by typing "=", followed by your expression, e. g: "=(2+3)^2"
|
||||||
|
|
||||||
File searches
|
|
||||||
-------------
|
|
||||||
It only queries a sqlite database. It does not index files, this is beyond the
|
|
||||||
scope a launcher. For the file searches functionality, easyindex is necessary.
|
|
||||||
See: git.quitesimple.org/easyindex.
|
|
||||||
|
|
||||||
|
|
||||||
|
3
main.cpp
3
main.cpp
@ -44,7 +44,6 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
QSettings settings(configDirectoryPath + "qsrun.config", QSettings::NativeFormat);
|
QSettings settings(configDirectoryPath + "qsrun.config", QSettings::NativeFormat);
|
||||||
QString dbpath = settings.value("Search/dbpath").toString();
|
|
||||||
QString systemApplicationsPath = settings.value("General/systemApplicationsPath", "/usr/share/applications/").toString();
|
QString systemApplicationsPath = settings.value("General/systemApplicationsPath", "/usr/share/applications/").toString();
|
||||||
|
|
||||||
QVector<EntryConfig> configs;
|
QVector<EntryConfig> configs;
|
||||||
@ -59,7 +58,7 @@ int main(int argc, char *argv[])
|
|||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
Window w(configs, dbpath);
|
Window w(configs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: Reconsider the need
|
* TODO: Reconsider the need
|
||||||
|
@ -9,12 +9,10 @@ INCLUDEPATH += .
|
|||||||
# Input
|
# Input
|
||||||
HEADERS += config.h window.h \
|
HEADERS += config.h window.h \
|
||||||
entrypushbutton.h \
|
entrypushbutton.h \
|
||||||
calculationengine.h \
|
calculationengine.h
|
||||||
searchworker.h
|
|
||||||
SOURCES += config.cpp main.cpp window.cpp \
|
SOURCES += config.cpp main.cpp window.cpp \
|
||||||
entrypushbutton.cpp \
|
entrypushbutton.cpp \
|
||||||
calculationengine.cpp \
|
calculationengine.cpp
|
||||||
searchworker.cpp
|
|
||||||
QT += widgets sql
|
QT += widgets sql
|
||||||
QT_CONFIG -= no-pkg-config
|
QT_CONFIG -= no-pkg-config
|
||||||
LIBS += -lcln
|
LIBS += -lcln
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
#include "searchworker.h"
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QSqlError>
|
|
||||||
//TODO: we have code duplication in the search functions currently.
|
|
||||||
SearchWorker::SearchWorker(const QString &dbpath)
|
|
||||||
{
|
|
||||||
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
|
|
||||||
db.setDatabaseName(dbpath);
|
|
||||||
if(!db.open())
|
|
||||||
{
|
|
||||||
qDebug() << "failed to open database";
|
|
||||||
}
|
|
||||||
queryContent = new QSqlQuery(db);
|
|
||||||
queryFile = new QSqlQuery(db);
|
|
||||||
queryFile->prepare("SELECT path FROM file WHERE path LIKE ? ORDER BY mtime DESC");
|
|
||||||
|
|
||||||
queryContent->prepare("SELECT DISTINCT file.path FROM file INNER JOIN content ON file.id = content.fileid INNER JOIN content_fts ON content.id = content_fts.ROWID WHERE content_fts.content MATCH ? ORDER By file.mtime DESC");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchWorker::searchForFile(const QString &query)
|
|
||||||
{
|
|
||||||
this->isPending = true;
|
|
||||||
this->cancelCurrent = false;
|
|
||||||
QVector<QString> results;
|
|
||||||
queryFile->addBindValue("%" + query + "%");
|
|
||||||
queryFile->exec();
|
|
||||||
while(queryFile->next())
|
|
||||||
{
|
|
||||||
if(cancelCurrent)
|
|
||||||
{
|
|
||||||
this->isPending = false;
|
|
||||||
emit searchCancelled();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QString result = queryFile->value(0).toString();
|
|
||||||
qDebug() << "result" << result;
|
|
||||||
results.append(queryFile->value(0).toString());
|
|
||||||
}
|
|
||||||
this->isPending = false;
|
|
||||||
emit searchResultsReady(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchWorker::requestCancellation()
|
|
||||||
{
|
|
||||||
this->cancelCurrent = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchWorker::searchForContent(const QString &query)
|
|
||||||
{
|
|
||||||
this->isPending = true;
|
|
||||||
this->cancelCurrent = false;
|
|
||||||
QVector<QString> results;
|
|
||||||
queryContent->addBindValue(query);
|
|
||||||
queryContent->exec();
|
|
||||||
while(queryContent->next())
|
|
||||||
{
|
|
||||||
if(cancelCurrent)
|
|
||||||
{
|
|
||||||
this->isPending = false;
|
|
||||||
emit searchCancelled();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QString result = queryContent->value(0).toString();
|
|
||||||
qDebug() << "result" << result;
|
|
||||||
results.append(queryContent->value(0).toString());
|
|
||||||
}
|
|
||||||
this->isPending = false;
|
|
||||||
emit searchResultsReady(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SearchWorker::isOperationPending()
|
|
||||||
{
|
|
||||||
return this->isPending;
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
#ifndef SEARCHWORKER_H
|
|
||||||
#define SEARCHWORKER_H
|
|
||||||
#include <QObject>
|
|
||||||
#include <QSqlDatabase>
|
|
||||||
#include <QSqlQuery>
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
class SearchWorker : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
QSqlQuery *queryFile;
|
|
||||||
QSqlQuery *queryContent;
|
|
||||||
bool isPending = false;
|
|
||||||
bool cancelCurrent = false;
|
|
||||||
public:
|
|
||||||
SearchWorker(const QString &dbpath);
|
|
||||||
bool isOperationPending();
|
|
||||||
void requestCancellation();
|
|
||||||
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void searchForFile(const QString &query);
|
|
||||||
void searchForContent(const QString &query);
|
|
||||||
signals:
|
|
||||||
void searchResultsReady(const QVector<QString> &results);
|
|
||||||
void searchCancelled();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SEARCHWORKER_H
|
|
124
window.cpp
124
window.cpp
@ -26,19 +26,11 @@
|
|||||||
#include <QFileIconProvider>
|
#include <QFileIconProvider>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
Window::Window(const QVector<EntryConfig> &configs, const QString &dbpath)
|
Window::Window(const QVector<EntryConfig> &configs)
|
||||||
{
|
{
|
||||||
this->userEntryButtons = generateEntryButtons(configs);
|
this->userEntryButtons = generateEntryButtons(configs);
|
||||||
createGui();
|
createGui();
|
||||||
populateGrid(this->userEntryButtons);
|
populateGrid(this->userEntryButtons);
|
||||||
searchWorker = new SearchWorker(dbpath);
|
|
||||||
searchWorker->moveToThread(&searchThread);
|
|
||||||
connect(this, &Window::beginFileSearch, searchWorker, &SearchWorker::searchForFile);
|
|
||||||
connect(this, &Window::beginContentSearch, searchWorker, &SearchWorker::searchForContent);
|
|
||||||
connect(searchWorker, &SearchWorker::searchResultsReady, this, &Window::handleSearchResults);
|
|
||||||
connect(searchWorker, &SearchWorker::searchCancelled, this, &Window::handleCancelledSearch);
|
|
||||||
searchThread.start();
|
|
||||||
initTreeWidgets();
|
|
||||||
this->lineEdit->installEventFilter(this);
|
this->lineEdit->installEventFilter(this);
|
||||||
QFont font;
|
QFont font;
|
||||||
font.setPointSize(48);
|
font.setPointSize(48);
|
||||||
@ -55,43 +47,14 @@ Window::Window(const QVector<EntryConfig> &configs, const QString &dbpath)
|
|||||||
|
|
||||||
Window::~Window()
|
Window::~Window()
|
||||||
{
|
{
|
||||||
searchThread.quit();
|
|
||||||
searchThread.wait();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::initTreeWidgets()
|
|
||||||
{
|
|
||||||
QStringList headers;
|
|
||||||
headers << "Filename";
|
|
||||||
headers << "Path";
|
|
||||||
headers << "Modification time";
|
|
||||||
treeFileSearchResults.setHeaderLabels(headers);
|
|
||||||
treeFileSearchResults.header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
|
||||||
connect(&treeFileSearchResults, &QTreeWidget::itemActivated, this, &Window::treeSearchItemActivated);
|
|
||||||
treeFileSearchResults.setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
|
|
||||||
connect(&treeFileSearchResults, &QTreeWidget::customContextMenuRequested, this, &Window::showSearchResultsContextMenu);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Window::showSearchResultsContextMenu(const QPoint &point)
|
|
||||||
{
|
|
||||||
QTreeWidgetItem *item = treeFileSearchResults.itemAt(point);
|
|
||||||
if(item == nullptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QMenu menu("SearchResult", this);
|
|
||||||
menu.addAction("Copy filename to clipboard", [&] { QGuiApplication::clipboard()->setText(item->text(0));});
|
|
||||||
menu.addAction("Copy full path to clipboard", [&] { QGuiApplication::clipboard()->setText(item->text(1)); });
|
|
||||||
menu.addAction("Open containing folder", [&] {
|
|
||||||
QFileInfo pathinfo(item->text(1));
|
|
||||||
QString dir = pathinfo.absolutePath();
|
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(dir));
|
|
||||||
|
|
||||||
});
|
|
||||||
menu.exec(QCursor::pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::showCalculationResultContextMenu(const QPoint &point)
|
void Window::showCalculationResultContextMenu(const QPoint &point)
|
||||||
{
|
{
|
||||||
@ -218,34 +181,6 @@ void Window::lineEditTextChanged(QString text)
|
|||||||
addCalcResult(input);
|
addCalcResult(input);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(text[0] == '/')
|
|
||||||
{
|
|
||||||
if(searchWorker->isOperationPending())
|
|
||||||
{
|
|
||||||
this->queuedFileSearch = input;
|
|
||||||
searchWorker->requestCancellation();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->queuedFileSearch = "";
|
|
||||||
emit beginFileSearch(input);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(text[0] == '|')
|
|
||||||
{
|
|
||||||
if(searchWorker->isOperationPending())
|
|
||||||
{
|
|
||||||
this->queuedContentSearch = input;
|
|
||||||
searchWorker->requestCancellation();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->queuedContentSearch = "";
|
|
||||||
emit beginContentSearch(input);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filterGridFor(text);
|
filterGridFor(text);
|
||||||
@ -384,10 +319,6 @@ void Window::lineEditReturnPressed()
|
|||||||
buttonClick(*buttonsInGrid[0]);
|
buttonClick(*buttonsInGrid[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(this->isSearchMode())
|
|
||||||
{
|
|
||||||
treeSearchItemActivated(treeFileSearchResults.topLevelItem(0), 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::setSystemConfig(const QVector<EntryConfig> &config)
|
void Window::setSystemConfig(const QVector<EntryConfig> &config)
|
||||||
@ -395,51 +326,7 @@ void Window::setSystemConfig(const QVector<EntryConfig> &config)
|
|||||||
this->systemEntryButtons = generateEntryButtons(config);
|
this->systemEntryButtons = generateEntryButtons(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::handleSearchResults(const QVector<QString> &results)
|
|
||||||
{
|
|
||||||
clearGrid();
|
|
||||||
treeFileSearchResults.clear();
|
|
||||||
QFileIconProvider provider;
|
|
||||||
for(const QString &path : results)
|
|
||||||
{
|
|
||||||
QFileInfo pathInfo(path);
|
|
||||||
QString fileName =pathInfo.fileName();
|
|
||||||
QString absPath = path;
|
|
||||||
QString datestr = pathInfo.lastModified().toString(Qt::ISODate);
|
|
||||||
QTreeWidgetItem *item = new QTreeWidgetItem(&treeFileSearchResults);
|
|
||||||
item->setText(0, fileName);
|
|
||||||
item->setIcon(0, provider.icon(pathInfo));
|
|
||||||
item->setText(1, absPath);
|
|
||||||
item->setText(2, datestr);
|
|
||||||
|
|
||||||
}
|
|
||||||
treeFileSearchResults.resizeColumnToContents(0);
|
|
||||||
treeFileSearchResults.resizeColumnToContents(2);
|
|
||||||
treeFileSearchResults.setVisible(true);
|
|
||||||
|
|
||||||
this->grid->addWidget(&treeFileSearchResults, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::handleCancelledSearch()
|
|
||||||
{
|
|
||||||
if(this->queuedFileSearch != "")
|
|
||||||
{
|
|
||||||
QString searchFor = this->queuedFileSearch;
|
|
||||||
this->queuedFileSearch = "";
|
|
||||||
emit beginFileSearch(searchFor);
|
|
||||||
}
|
|
||||||
if(this->queuedContentSearch != "")
|
|
||||||
{
|
|
||||||
QString searchFor = this->queuedContentSearch;
|
|
||||||
this->queuedContentSearch = "";
|
|
||||||
emit beginContentSearch(searchFor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::treeSearchItemActivated(QTreeWidgetItem *item, int i)
|
|
||||||
{
|
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(item->text(1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Window::eventFilter(QObject *obj, QEvent *event)
|
bool Window::eventFilter(QObject *obj, QEvent *event)
|
||||||
@ -468,8 +355,3 @@ bool Window::eventFilter(QObject *obj, QEvent *event)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::isSearchMode()
|
|
||||||
{
|
|
||||||
QChar c = this->lineEdit->text()[0];
|
|
||||||
return c == '/' || c == '|';
|
|
||||||
}
|
|
||||||
|
14
window.h
14
window.h
@ -33,20 +33,16 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "entrypushbutton.h"
|
#include "entrypushbutton.h"
|
||||||
#include "calculationengine.h"
|
#include "calculationengine.h"
|
||||||
#include "searchworker.h"
|
|
||||||
|
|
||||||
class Window : public QWidget
|
class Window : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
QThread searchThread;
|
|
||||||
SearchWorker *searchWorker;
|
|
||||||
CalculationEngine calcEngine;
|
CalculationEngine calcEngine;
|
||||||
QString calculationresult;
|
QString calculationresult;
|
||||||
QVector<EntryPushButton*> userEntryButtons;
|
QVector<EntryPushButton*> userEntryButtons;
|
||||||
QVector<EntryPushButton*> systemEntryButtons;
|
QVector<EntryPushButton*> systemEntryButtons;
|
||||||
QVector<EntryPushButton *> buttonsInGrid;
|
QVector<EntryPushButton *> buttonsInGrid;
|
||||||
QTreeWidget treeFileSearchResults;
|
|
||||||
QLabel calculationResultLabel;
|
QLabel calculationResultLabel;
|
||||||
QString currentCalculationResult;
|
QString currentCalculationResult;
|
||||||
QString queuedFileSearch;
|
QString queuedFileSearch;
|
||||||
@ -67,19 +63,11 @@ class Window : public QWidget
|
|||||||
void addCalcResult(const QString & expression);
|
void addCalcResult(const QString & expression);
|
||||||
void initTreeWidgets();
|
void initTreeWidgets();
|
||||||
QStringList generatePATHSuggestions(const QString &text);
|
QStringList generatePATHSuggestions(const QString &text);
|
||||||
bool isSearchMode();
|
|
||||||
private slots:
|
private slots:
|
||||||
void lineEditReturnPressed();
|
void lineEditReturnPressed();
|
||||||
void handleSearchResults(const QVector<QString> &results);
|
|
||||||
void handleCancelledSearch();
|
|
||||||
void treeSearchItemActivated(QTreeWidgetItem *item, int i);
|
|
||||||
void showSearchResultsContextMenu(const QPoint &point);
|
|
||||||
void showCalculationResultContextMenu(const QPoint &point);
|
void showCalculationResultContextMenu(const QPoint &point);
|
||||||
signals:
|
|
||||||
void beginFileSearch(const QString &query);
|
|
||||||
void beginContentSearch(const QString &query);
|
|
||||||
public:
|
public:
|
||||||
Window(const QVector<EntryConfig> &userEntryButtons, const QString &dbpath);
|
Window(const QVector<EntryConfig> &userEntryButtons);
|
||||||
void setSystemConfig(const QVector<EntryConfig> &config);
|
void setSystemConfig(const QVector<EntryConfig> &config);
|
||||||
bool eventFilter(QObject *obj, QEvent *event);
|
bool eventFilter(QObject *obj, QEvent *event);
|
||||||
~Window();
|
~Window();
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren