/* * This file is part of smolbote. It's copyrighted by the contributors recorded * in the version control history of the file, available from its original * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote * * SPDX-License-Identifier: GPL-3.0 */ #include "urllineedit.h" #include #include #include #include #include "../addressbar.h" UrlLineEdit::UrlLineEdit(QWidget *parent) : QLineEdit(parent) , m_listView(new Completer(this)) { setObjectName("UrlBar"); setPlaceholderText(tr("Enter address")); m_listView->setVisible(false); connect(m_listView, &Completer::completionActivated, this, &UrlLineEdit::setText); addressbar = qobject_cast(parent); Q_CHECK_PTR(addressbar); auto *copyAction = new QAction(tr("Copy URL"), this); connect(copyAction, &QAction::triggered, this, [this]() { qApp->clipboard()->setText(this->text()); }); actions.append(copyAction); auto *pasteAction = new QAction(tr("Paste URL"), this); connect(pasteAction, &QAction::triggered, this, [this]() { this->setText(qApp->clipboard()->text()); this->setFocus(); }); actions.append(pasteAction); auto *loadAction = new QAction(tr("Paste and load"), this); connect(loadAction, &QAction::triggered, this, [this]() { emit addressbar->load(QUrl::fromUserInput(qApp->clipboard()->text())); clearFocus(); }); actions.append(loadAction); auto *searchAction = new QAction(tr("Paste and search"), this); connect(searchAction, &QAction::triggered, this, [this]() { emit addressbar->search(qApp->clipboard()->text()); clearFocus(); }); actions.append(searchAction); menuAction = addAction(style()->standardIcon(QStyle::SP_DriveNetIcon), QLineEdit::LeadingPosition); connect(menuAction, &QAction::triggered, this, [this]() { auto *menu = new QMenu(); menu->setAttribute(Qt::WA_DeleteOnClose, true); menu->setMinimumWidth(240); menu->addActions(actions); menu->exec(this->mapToGlobal(QPoint(0, height()))); }); auto *goAction = addAction(style()->standardIcon(QStyle::SP_DialogOkButton), QLineEdit::TrailingPosition); connect(goAction, &QAction::triggered, this, [this]() { emit returnPressed(); }); QTextCharFormat hostnameFormat; hostnameFormat.setFontWeight(QFont::Bold); m_hostFormat.format = hostnameFormat; } void UrlLineEdit::setUrl(const QUrl &url) { QString urlText = url.toString(); QString domain = url.host(); m_hostFormat.start = urlText.indexOf(domain); m_hostFormat.length = domain.length(); clear(); clearTextFormat(); setTextFormat(m_hostFormat); setText(urlText); } void UrlLineEdit::updateCompleter(const QStringList &l) { if(!m_listView->updateItems(l)) { m_listView->hide(); return; } // positioning m_listView->setFixedWidth(width()); m_listView->move(mapToGlobal(QPoint(0, height()))); m_listView->show(); } void UrlLineEdit::focusInEvent(QFocusEvent *event) { // a context menu event also causes a focusInEvent, so if text is selected // skip the formatting step if(event->reason() == Qt::PopupFocusReason) { QLineEdit::focusInEvent(event); return; } clearTextFormat(); QLineEdit::focusInEvent(event); } void UrlLineEdit::focusOutEvent(QFocusEvent *event) { // a context menu event causes a focusOutEvent, and setUrl will clear the // selection, and this would prevent the menu from working properly if(event->reason() == Qt::PopupFocusReason) { QLineEdit::focusOutEvent(event); return; } const QUrl url = QUrl::fromUserInput(text()); if(url.isValid()) setUrl(url); emit addressbar->giveFocus(); QLineEdit::focusOutEvent(event); } void UrlLineEdit::keyPressEvent(QKeyEvent *event) { if(m_listView->keyPressed(event)) { event->accept(); return; } else if(event->key() == Qt::Key::Key_Escape) { clearFocus(); event->accept(); return; } QLineEdit::keyPressEvent(event); } // formatting taken from: https://forum.qt.io/topic/60962/setting-qlineedit-text-bold void UrlLineEdit::setTextFormat(const QTextLayout::FormatRange &format) { QList attributes; attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, format.start, format.length, format.format)); QInputMethodEvent ev(QString(), attributes); event(&ev); } void UrlLineEdit::clearTextFormat() { setTextFormat(QTextLayout::FormatRange()); }