diff options
Diffstat (limited to 'src/widgets')
| -rw-r--r-- | src/widgets/BrowserManager.cpp | 124 | ||||
| -rw-r--r-- | src/widgets/CommandInput.cpp | 50 | ||||
| -rw-r--r-- | src/widgets/MainWindow.cpp | 76 |
3 files changed, 250 insertions, 0 deletions
diff --git a/src/widgets/BrowserManager.cpp b/src/widgets/BrowserManager.cpp new file mode 100644 index 0000000..a2390fc --- /dev/null +++ b/src/widgets/BrowserManager.cpp @@ -0,0 +1,124 @@ +#include <QStackedLayout> +#include <QWebEngineNewWindowRequest> +#include <QWebEngineView> + +#include "widgets/BrowserManager.hpp" + +BrowserManager::BrowserManager(QWebEngineProfile *profile) : QWidget() { + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + layout = new QStackedLayout(this); + layout->setStackingMode(QStackedLayout::StackAll); + layout->setContentsMargins(0, 0, 0, 0); + + this->profile = profile; + + createNewWebView(BrowserManager::NewtabURL, true); +} + +QWebEngineView *BrowserManager::createNewWebView(QUrl url, bool focus) { + auto webview = new QWebEngineView(profile); + webview->setUrl(url); + layout->addWidget(webview); + webViewList.append(webview); + + connect(webview->page(), &QWebEnginePage::newWindowRequested, this, + &BrowserManager::onNewWebViewRequest); + + if (focus) + focusWebView(webViewList.length() - 1); + + return webview; +} + +void BrowserManager::onNewWebViewRequest(QWebEngineNewWindowRequest &request) { + switch (request.destination()) { + case QWebEngineNewWindowRequest::InNewTab: + createNewWebView(request.requestedUrl(), true); + break; + case QWebEngineNewWindowRequest::InNewBackgroundTab: + createNewWebView(request.requestedUrl(), false); + break; + case QWebEngineNewWindowRequest::InNewWindow: + // TODO: Impl + createNewWebView(request.requestedUrl(), true); + break; + case QWebEngineNewWindowRequest::InNewDialog: + // TODO: Impl + createNewWebView(request.requestedUrl(), true); + break; + } +} + +void BrowserManager::nextWebView() { + if (webViewList.isEmpty()) + return; + auto index = currentWebViewIndex() + 1; + auto total = webViewList.length(); + index = index >= total ? index % total : index; + focusWebView(index); +} + +void BrowserManager::previousWebView() { + if (webViewList.isEmpty()) + return; + auto index = currentWebViewIndex() - 1; + auto total = webViewList.length(); + index = index < 0 ? total + index : index; + focusWebView(index); +} + +void BrowserManager::closeCurrentWebView() { + closeWebView(currentWebViewIndex()); +} + +void BrowserManager::closeWebView(long index) { + if (index < 0 || index >= webViewList.length()) + return; + + auto webview = webViewList.at(index); + layout->removeWidget(webview); + webViewList.removeAt(index); + disconnect(webview->page()); + webview->deleteLater(); + + focusWebView(currentWebViewIndex()); + + if (webViewList.isEmpty()) { + createNewWebView(BrowserManager::NewtabURL, true); + } +} + +std::vector<QUrl> BrowserManager::webViewUrls() { + std::vector<QUrl> urls; + for (auto &view : webViewList) + urls.push_back(view->url()); + return urls; +} + +u_int32_t BrowserManager::currentWebViewIndex() { + return layout->currentIndex(); +} +u_int32_t BrowserManager::webViewCount() { return webViewList.length(); } + +void BrowserManager::focusWebView(long index) { + if (webViewList.isEmpty()) + return; + + index = std::max((long)0, std::min(index, (long)webViewList.length() - 1)); + layout->setCurrentIndex(index); +} + +QUrl BrowserManager::currentUrl() { + if (currentWebViewIndex() >= webViewList.length()) + return QUrl("about:newtab"); + + return webViewList.at(currentWebViewIndex())->url(); +} + +void BrowserManager::setCurrentUrl(QUrl url) { + if (currentWebViewIndex() >= webViewList.length()) + return; + + webViewList.at(currentWebViewIndex())->setUrl(url); +} diff --git a/src/widgets/CommandInput.cpp b/src/widgets/CommandInput.cpp new file mode 100644 index 0000000..464065a --- /dev/null +++ b/src/widgets/CommandInput.cpp @@ -0,0 +1,50 @@ +#include <QHBoxLayout> +#include <QKeyEvent> +#include <QLineEdit> +#include <QVBoxLayout> +#include <QWidget> +#include <QWindow> + +#include "widgets/CommandInput.hpp" + +CommandInput::CommandInput(QString defaultInput, QWidget *parentNode) + : QWidget(parentNode) { + setContentsMargins(0, 0, 0, 0); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + setStyleSheet("background-color: #000; color: #fff; border-radius: 0;"); + + auto layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + input = new QLineEdit(defaultInput, this); + input->setFocusPolicy(Qt::StrongFocus); + layout->addWidget(input); + setFixedHeight(input->sizeHint().height()); +} + +void CommandInput::emitSubmit() { emit submitted(getInputCommand()); } + +void CommandInput::keyPressEvent(QKeyEvent *event) { + auto combo = event->keyCombination(); + auto ctrlL = combo.key() == Qt::Key_L && + combo.keyboardModifiers().testFlag(Qt::ControlModifier); + auto esc = combo.key() == Qt::Key_Escape; + auto enter = combo.key() == Qt::Key_Return || combo.key() == Qt::Key_Enter; + + if (esc || ctrlL) + emit cancelled(); + else if (enter) + emitSubmit(); +} + +void CommandInput::setInputText(QString text) { input->setText(text); } + +bool CommandInput::isInputFocussed() { return input->hasFocus(); } + +void CommandInput::setInputFocus(bool focussed) { + if (focussed) + input->setFocus(Qt::PopupFocusReason); + else + input->clearFocus(); +} + +QString CommandInput::getInputCommand() { return input->text(); } diff --git a/src/widgets/MainWindow.cpp b/src/widgets/MainWindow.cpp new file mode 100644 index 0000000..e660e52 --- /dev/null +++ b/src/widgets/MainWindow.cpp @@ -0,0 +1,76 @@ +#include <QKeyEvent> +#include <QStackedLayout> +#include <QVBoxLayout> +#include <QWebEngineView> + +#include "widgets/BrowserManager.hpp" +#include "widgets/CommandInput.hpp" +#include "widgets/MainWindow.hpp" + +MainWindow::MainWindow() { + setStyleSheet("background-color: #000; color: #fff;"); + setCentralWidget(new QWidget()); + + // Root stacked layout + auto layout = new QStackedLayout(); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + layout->setStackingMode(QStackedLayout::StackAll); + centralWidget()->setLayout(layout); + + // Web engine + browserManager = new BrowserManager(new QWebEngineProfile("web-browser")); + layout->addWidget(browserManager); + + // Command input + commandInput = new CommandInput(browserManager->currentUrl().toString()); + hideURLInput(); + commandInput->move(0, 0); + connect(commandInput, &CommandInput::submitted, this, + &MainWindow::evaluateCommand); + connect(commandInput, &CommandInput::cancelled, this, + &MainWindow::hideURLInput); + layout->addWidget(commandInput); +} + +void MainWindow::hideURLInput() { + commandInput->setInputFocus(false); + commandInput->setHidden(true); +} + +void MainWindow::showURLInput() { + commandInput->setInputText(browserManager->currentUrl().toString()); + commandInput->raise(); + commandInput->setHidden(false); + commandInput->setInputFocus(true); +} + +void MainWindow::evaluateCommand(QString command) { + if (!command.isEmpty()) + browserManager->setCurrentUrl(command); + hideURLInput(); +} + +void MainWindow::keyPressEvent(QKeyEvent *event) { + auto combo = event->keyCombination(); + if (combo.key() == Qt::Key_L && + combo.keyboardModifiers().testFlag(Qt::ControlModifier)) { + toggleURLInput(); + } else if (combo.key() == Qt::Key_T && + combo.keyboardModifiers().testFlag(Qt::ControlModifier)) { + browserManager->createNewWebView(QUrl("https://duckduckgo.com"), true); + } else if (combo.key() == Qt::Key_J && + combo.keyboardModifiers().testFlag(Qt::ControlModifier)) { + browserManager->nextWebView(); + } else if (combo.key() == Qt::Key_K && + combo.keyboardModifiers().testFlag(Qt::ControlModifier)) { + browserManager->previousWebView(); + } else if (combo.key() == Qt::Key_W && + combo.keyboardModifiers().testFlag(Qt::ControlModifier)) { + browserManager->closeCurrentWebView(); + } +} + +void MainWindow::toggleURLInput() { + commandInput->isHidden() ? showURLInput() : hideURLInput(); +} |
