Compare commits

...

6 Commits

Author SHA1 Message Date
52b296ff01 gui: mainwindow: Set default query limit to 1000 2022-06-05 14:39:57 +02:00
e5e43c8bfb shared: SqliteSearch: Append LIMIT statement if need be 2022-06-05 14:39:57 +02:00
862168418b gui: mainwindow: Reword warning for inaccessible files 2022-06-05 14:39:57 +02:00
a6ddcef0c0 shared: LooqsQuery: Fix logic of implicit AND booleans. Add 'limit:' support
Add implicit AND booleans at the end.

This fixes a number of issues in LooqsQuery:

(1) A query like a b c p:(something) would fail, because
a b c get merged into one word. This happens at the end.

lonewords are special and do not become a token immediatly. So previous
logic to add implicit ANDs does not apply.

(2) Negations were also broken with lonewords.

(3) The TokenType enum fields were too narrow to be useful for the bitmask

Independent of that, add support for 'limit:'
2022-06-05 14:39:57 +02:00
821bed6706 shared: LooqsQuery: Add 'p', 'pb', 'pe' aliases
Because this way the user has to type significantly less
2022-06-05 14:39:57 +02:00
8f69be229b gui: mainwindow: Exclude HTML files from previews until we can do it properly 2022-06-05 14:39:57 +02:00
5 changed files with 69 additions and 32 deletions

View File

@ -411,10 +411,20 @@ void MainWindow::lineEditReturnPressed()
if(addPathSearch)
{
LooqsQuery filesQuery = LooqsQuery::build(q, TokenType::FILTER_PATH_CONTAINS, false);
if(filesQuery.getLimit() == -1)
{
filesQuery.setLimit(1000);
}
results.append(searcher.search(filesQuery));
}
if(addContentSearch)
{
if(this->contentSearchQuery.getLimit() == -1)
{
this->contentSearchQuery.setLimit(1000);
}
results.append(searcher.search(this->contentSearchQuery));
}
return results;
@ -444,9 +454,12 @@ void MainWindow::handleSearchResults(const QVector<SearchResult> &results)
bool exists = pathInfo.exists();
if(exists)
{
if(PreviewGenerator::get(pathInfo) != nullptr)
if(!pathInfo.suffix().contains("htm")) // hack until we can preview them properly...
{
this->previewableSearchResults.append(result);
if(PreviewGenerator::get(pathInfo) != nullptr)
{
this->previewableSearchResults.append(result);
}
}
}
else
@ -469,7 +482,7 @@ void MainWindow::handleSearchResults(const QVector<SearchResult> &results)
QString statusText = "Results: " + QString::number(results.size()) + " files";
if(hasDeleted)
{
statusText += " WARNING: Some files don't exist anymore. No preview available for those. Index out of sync";
statusText += " WARNING: Some files are inaccessible. No preview available for those. Index may be out of sync";
}
ui->lblSearchResults->setText(statusText);
}

View File

@ -220,19 +220,8 @@ LooqsQuery LooqsQuery::build(QString expression, TokenType loneWordsTokenType, b
{
throw LooqsGeneralException("Can't have two negations following each other");
}
if(!previousWasBool())
{
result.addToken(Token(BOOL_AND)); // Implicit and, our default operation
}
result.addToken(Token(NEGATION));
}
if(!result.tokens.isEmpty() && !previousWasBool() && !previousWas(NEGATION) && !previousWas(BRACKET_OPEN) &&
bracket != ")")
{
// the current token isn't a negation, isn't a boolean. Thus, implicit AND is required
result.addToken(Token(BOOL_AND));
}
if(bracket != "")
{
if(bracket == "(")
@ -259,7 +248,7 @@ LooqsQuery LooqsQuery::build(QString expression, TokenType loneWordsTokenType, b
if(filtername != "")
{
TokenType tokenType;
TokenType tokenType = WORD;
QString value = m.captured("innerargs");
if(value == "")
{
@ -270,15 +259,15 @@ LooqsQuery LooqsQuery::build(QString expression, TokenType loneWordsTokenType, b
throw LooqsGeneralException("value cannot be empty for filters");
}
if(filtername == "path.contains")
if(filtername == "p" || filtername == "path.contains")
{
tokenType = FILTER_PATH_CONTAINS;
}
else if(filtername == "path.starts")
else if(filtername == "pb" || filtername == "path.starts")
{
tokenType = FILTER_PATH_STARTS;
}
else if(filtername == "path.ends")
else if(filtername == "pe" || filtername == "path.ends")
{
tokenType = FILTER_PATH_ENDS;
}
@ -294,21 +283,21 @@ LooqsQuery LooqsQuery::build(QString expression, TokenType loneWordsTokenType, b
{
tokenType = FILTER_CONTENT_PAGE;
}
else if(filtername ==
"sort") // TODO: given this is not really a "filter", this feels slightly misplaced here
// TODO: given this is not really a "filter", this feels slightly misplaced here
else if(filtername == "sort")
{
if(!result.sortConditions.empty())
{
throw LooqsGeneralException("Two sort statements are illegal");
}
// TODO: hack, since we are not a "filter", we must remove a preceeding (implicit) boolean
if((result.tokens.last().type & BOOL) == BOOL)
{
result.tokens.pop_back();
}
result.sortConditions = createSortConditions(value);
continue;
}
else if(filtername == "limit")
{
result.limit = value.toInt();
continue;
}
else
{
throw LooqsGeneralException("Unknown filter provided!");
@ -326,6 +315,26 @@ LooqsQuery LooqsQuery::build(QString expression, TokenType loneWordsTokenType, b
}
}
/* Add our default implicit AND boolean condition where appropriate */
QVector<Token> newTokens;
TokenType prevType = BOOL_AND;
int needsBoolean = FILTER_CONTENT | FILTER_PATH | NEGATION;
for(Token &t : result.tokens)
{
if(t.type == BRACKET_OPEN || t.type & needsBoolean)
{
if(!((prevType & BOOL) == BOOL) && !((prevType & NEGATION) == NEGATION) &&
!((prevType & BRACKET_OPEN) == BRACKET_OPEN))
{
newTokens.append(Token(BOOL_AND));
}
}
prevType = t.type;
newTokens.append(t);
}
result.tokens = newTokens;
bool contentsearch = result.hasContentSearch();
bool sortsForContent = std::any_of(result.sortConditions.begin(), result.sortConditions.end(),
[](SortCondition c) { return c.field == CONTENT_TEXT; });

View File

@ -40,6 +40,7 @@ class LooqsQuery
/* Helper field to determine quertype as well as to quickly check what kind of filters etc.
* are being used in this query*/
int tokensMask = 0;
int limit = -1;
QVector<Token> tokens;
QVector<SortCondition> sortConditions;
void addToken(Token t);
@ -52,6 +53,14 @@ class LooqsQuery
{
return tokensMask;
}
int getLimit() const
{
return limit;
}
void setLimit(int limit)
{
this->limit = limit;
}
bool hasContentSearch();
bool hasPathSearch();

View File

@ -183,6 +183,11 @@ QSqlQuery SqliteSearch::makeSqlQuery(const LooqsQuery &query)
whereSql + " " + sortSql;
}
if(query.getLimit() > 0)
{
prepSql += " LIMIT " + QString::number(query.getLimit());
}
QSqlQuery dbquery(*db);
dbquery.prepare(prepSql);
for(const QString &value : bindValues)

View File

@ -4,24 +4,25 @@
enum TokenType
{
WORD,
NEGATION = 2,
BOOL = 4,
WORD = 8,
NEGATION = 16,
BOOL = 32,
BOOL_AND,
BOOL_OR,
GROUP = 8,
GROUP = 64,
BRACKET_OPEN,
BRACKET_CLOSE,
SORT = 16,
FILTER_PATH = 32,
SORT = 128,
FILTER_PATH = 256,
FILTER_PATH_MTIME,
FILTER_PATH_CONTAINS,
FILTER_PATH_SIZE,
FILTER_PATH_ENDS,
FILTER_PATH_STARTS,
FILTER_CONTENT = 64,
FILTER_CONTENT = 512,
FILTER_CONTENT_CONTAINS,
FILTER_CONTENT_PAGE,
LIMIT = 1024
};
class Token