store history using sqlite, add suggestion with open
This commit is contained in:
+58
-1
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "adblock.h"
|
||||
#include "commandline.h"
|
||||
#include "completionview.h"
|
||||
#include "hints.h"
|
||||
#include "statusbar.h"
|
||||
#include "urlutil.h"
|
||||
@@ -11,8 +12,10 @@
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QRegularExpression>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWebEnginePage>
|
||||
#include <QWebEngineProfile>
|
||||
#include <QWebEngineScript>
|
||||
#include <QWebEngineView>
|
||||
#include <QWidget>
|
||||
@@ -21,6 +24,14 @@ namespace {
|
||||
|
||||
constexpr int kScrollStep = 60;
|
||||
constexpr double kZoomStep = 0.1;
|
||||
constexpr int kCompletionLimit = 100;
|
||||
|
||||
// ":open <query>" or ":o <query>"; captures the prefix and the query.
|
||||
const QRegularExpression &openCommand()
|
||||
{
|
||||
static const QRegularExpression re(QStringLiteral("^(:(?:open|o) +)(.*)$"));
|
||||
return re;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -31,6 +42,7 @@ BrowserWindow::BrowserWindow(QWebEngineProfile *profile, AdBlocker *adBlocker,
|
||||
, m_view(new QWebEngineView(profile, this))
|
||||
, m_status(new StatusBar(this))
|
||||
, m_commandLine(new CommandLine(this))
|
||||
, m_completion(new CompletionView(this))
|
||||
{
|
||||
setupUi();
|
||||
connectView();
|
||||
@@ -42,6 +54,8 @@ BrowserWindow::BrowserWindow(QWebEngineProfile *profile, AdBlocker *adBlocker,
|
||||
connect(m_commandLine, &CommandLine::cancelled, this, [this] {
|
||||
setMode(Mode::Normal);
|
||||
});
|
||||
connect(m_commandLine, &QLineEdit::textEdited, this, &BrowserWindow::updateCompletion);
|
||||
connect(m_commandLine, &CommandLine::completionCycled, this, &BrowserWindow::cycleCompletion);
|
||||
connect(m_adBlocker, &AdBlocker::message, m_status, &StatusBar::showMessage);
|
||||
|
||||
qApp->installEventFilter(this);
|
||||
@@ -61,6 +75,7 @@ void BrowserWindow::setupUi()
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(m_view, 1);
|
||||
layout->addWidget(m_completion);
|
||||
layout->addWidget(m_status);
|
||||
layout->addWidget(m_commandLine);
|
||||
setCentralWidget(central);
|
||||
@@ -80,11 +95,17 @@ void BrowserWindow::connectView()
|
||||
connect(m_view, &QWebEngineView::titleChanged, this, [this](const QString &title) {
|
||||
setWindowTitle(title.isEmpty() ? QStringLiteral("att")
|
||||
: QStringLiteral("%1 - att").arg(title));
|
||||
m_history.updateTitle(m_view->url(), title);
|
||||
});
|
||||
connect(m_view, &QWebEngineView::loadFinished, this, [this](bool ok) {
|
||||
m_status->setProgress(100);
|
||||
if (!ok)
|
||||
if (!ok) {
|
||||
m_status->showMessage(QStringLiteral("Failed to load page"), true);
|
||||
return;
|
||||
}
|
||||
// Here rather than on urlChanged, which also fires for every redirect
|
||||
// hop and in-page #anchor jump.
|
||||
m_history.addVisit(m_view->url(), m_view->title());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -96,6 +117,9 @@ void BrowserWindow::setMode(Mode mode)
|
||||
m_mode = mode;
|
||||
m_pendingKeys.clear();
|
||||
|
||||
if (mode != Mode::Command)
|
||||
m_completion->setEntries({});
|
||||
|
||||
switch (mode) {
|
||||
case Mode::Normal:
|
||||
m_status->setMode(QString());
|
||||
@@ -109,6 +133,7 @@ void BrowserWindow::setMode(Mode mode)
|
||||
break;
|
||||
case Mode::Command:
|
||||
m_status->hide();
|
||||
updateCompletion();
|
||||
break;
|
||||
case Mode::Hint:
|
||||
m_status->setMode(QStringLiteral("hint"));
|
||||
@@ -363,6 +388,14 @@ void BrowserWindow::runCommand(const QString &command)
|
||||
m_view->forward();
|
||||
} else if (name == QLatin1String("stop")) {
|
||||
m_view->stop();
|
||||
} else if (name == QLatin1String("history-clear")) {
|
||||
if (m_history.clear()) {
|
||||
// Also forget Chromium's own record, which colours visited links.
|
||||
m_view->page()->profile()->clearAllVisitedLinks();
|
||||
m_status->showMessage(QStringLiteral("History cleared"));
|
||||
} else {
|
||||
m_status->showMessage(QStringLiteral("Could not clear history"), true);
|
||||
}
|
||||
} else if (name == QLatin1String("adblock-update")) {
|
||||
m_adBlocker->update();
|
||||
} else if (name == QLatin1String("adblock-toggle")) {
|
||||
@@ -374,6 +407,30 @@ void BrowserWindow::runCommand(const QString &command)
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserWindow::updateCompletion()
|
||||
{
|
||||
const QRegularExpressionMatch match = openCommand().match(m_commandLine->text());
|
||||
if (!match.hasMatch()) {
|
||||
m_completion->setEntries({});
|
||||
return;
|
||||
}
|
||||
const QStringList words = match.captured(2).split(QLatin1Char(' '), Qt::SkipEmptyParts);
|
||||
m_completion->setEntries(m_history.search(words, kCompletionLimit));
|
||||
}
|
||||
|
||||
void BrowserWindow::cycleCompletion(int step)
|
||||
{
|
||||
if (!m_completion->isVisible())
|
||||
return;
|
||||
const QString url = m_completion->cycle(step);
|
||||
if (url.isEmpty())
|
||||
return;
|
||||
// Keep whichever of ":o " / ":open " the user typed.
|
||||
const QRegularExpressionMatch match = openCommand().match(m_commandLine->text());
|
||||
const QString prefix = match.hasMatch() ? match.captured(1) : QStringLiteral(":open ");
|
||||
m_commandLine->setCommandText(prefix + url);
|
||||
}
|
||||
|
||||
void BrowserWindow::openUrl(const QString &input)
|
||||
{
|
||||
const QUrl url = urlutil::fromUserInput(input);
|
||||
|
||||
Reference in New Issue
Block a user