diff --git a/src/lib/adblock/adblockicon.cpp b/src/lib/adblock/adblockicon.cpp index a693dfd0..89fbadaf 100644 --- a/src/lib/adblock/adblockicon.cpp +++ b/src/lib/adblock/adblockicon.cpp @@ -1,178 +1,181 @@ /* ============================================================ * Falkon - Qt web browser * Copyright (C) 2010-2018 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ #include "adblockicon.h" #include "adblockrule.h" #include "adblockmanager.h" #include "adblocksubscription.h" #include "mainapplication.h" #include "browserwindow.h" #include "webview.h" #include "tabbedwebview.h" #include "tabwidget.h" #include "desktopnotificationsfactory.h" #include "qztools.h" #include AdBlockIcon::AdBlockIcon(QObject *parent) : AbstractButtonInterface(parent) { setTitle(tr("AdBlock")); setIcon(QIcon(QSL(":adblock/data/adblock.png"))); updateState(); connect(this, &AbstractButtonInterface::clicked, this, &AdBlockIcon::clicked); connect(this, &AbstractButtonInterface::webViewChanged, this, &AdBlockIcon::webViewChanged); connect(AdBlockManager::instance(), &AdBlockManager::enabledChanged, this, &AdBlockIcon::updateState); connect(AdBlockManager::instance(), &AdBlockManager::blockedRequestsChanged, this, &AdBlockIcon::blockedRequestsChanged); } QString AdBlockIcon::id() const { return QSL("adblock-icon"); } QString AdBlockIcon::name() const { return tr("AdBlock Icon"); } void AdBlockIcon::toggleCustomFilter() { QAction* action = qobject_cast(sender()); if (!action) { return; } const QString filter = action->data().toString(); AdBlockManager* manager = AdBlockManager::instance(); AdBlockCustomList* customList = manager->customList(); if (customList->containsFilter(filter)) { customList->removeFilter(filter); } else { AdBlockRule* rule = new AdBlockRule(filter, customList); customList->addRule(rule); } } void AdBlockIcon::updateState() { WebView *view = webView(); if (!view) { setActive(false); setToolTip(name()); setBadgeText(QString()); return; } if (!AdBlockManager::instance()->isEnabled()) { setActive(false); setToolTip(tr("AdBlock is disabled")); setBadgeText(QString()); return; } if (!AdBlockManager::instance()->canRunOnScheme(view->url().scheme())) { setActive(false); setToolTip(tr("AdBlock is disabled on this site ")); setBadgeText(QString()); return; } setActive(true); setToolTip(tr("AdBlock is active")); updateBadgeText(); } void AdBlockIcon::updateBadgeText() { WebView *view = webView(); if (!view) { return; } const int count = AdBlockManager::instance()->blockedRequestsForUrl(view->url()).count(); if (count > 0) { setBadgeText(QString::number(count)); } else { setBadgeText(QString()); } } void AdBlockIcon::webViewChanged(WebView *view) { updateState(); if (m_view) { disconnect(m_view.data(), &WebView::urlChanged, this, &AdBlockIcon::updateState); } m_view = view; if (m_view) { connect(m_view.data(), &WebView::urlChanged, this, &AdBlockIcon::updateState); } } void AdBlockIcon::clicked(ClickController *controller) { WebView *view = webView(); if (!view) { return; } AdBlockManager* manager = AdBlockManager::instance(); AdBlockCustomList* customList = manager->customList(); const QUrl pageUrl = view->url(); - QMenu menu; - menu.addAction(tr("Show AdBlock &Settings"), manager, SLOT(showDialog())); - menu.addSeparator(); + QMenu *menu = new QMenu(); + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->addAction(tr("Show AdBlock &Settings"), manager, SLOT(showDialog())); + menu->addSeparator(); if (!pageUrl.host().isEmpty() && manager->isEnabled() && manager->canRunOnScheme(pageUrl.scheme())) { const QString host = view->url().host().contains(QLatin1String("www.")) ? pageUrl.host().mid(4) : pageUrl.host(); const QString hostFilter = QString("@@||%1^$document").arg(host); const QString pageFilter = QString("@@|%1|$document").arg(pageUrl.toString()); - QAction* act = menu.addAction(tr("Disable on %1").arg(host)); + QAction* act = menu->addAction(tr("Disable on %1").arg(host)); act->setCheckable(true); act->setChecked(customList->containsFilter(hostFilter)); act->setData(hostFilter); connect(act, SIGNAL(triggered()), this, SLOT(toggleCustomFilter())); - act = menu.addAction(tr("Disable only on this page")); + act = menu->addAction(tr("Disable only on this page")); act->setCheckable(true); act->setChecked(customList->containsFilter(pageFilter)); act->setData(pageFilter); connect(act, SIGNAL(triggered()), this, SLOT(toggleCustomFilter())); - - menu.addSeparator(); } - menu.exec(controller->popupPosition(menu.sizeHint())); + connect(menu, &QMenu::aboutToHide, this, [=]() { + controller->popupClosed(); + }); + + menu->popup(controller->popupPosition(menu->sizeHint())); } void AdBlockIcon::blockedRequestsChanged(const QUrl &url) { WebView *view = webView(); if (!view || url != view->url()) { return; } updateState(); } diff --git a/src/lib/navigation/navigationbartoolbutton.cpp b/src/lib/navigation/navigationbartoolbutton.cpp index c5457fe5..dfe3c625 100644 --- a/src/lib/navigation/navigationbartoolbutton.cpp +++ b/src/lib/navigation/navigationbartoolbutton.cpp @@ -1,85 +1,91 @@ /* ============================================================ * QupZilla - Qt web browser * Copyright (C) 2018 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ #include "navigationbartoolbutton.h" #include "abstractbuttoninterface.h" #include #include NavigationBarToolButton::NavigationBarToolButton(AbstractButtonInterface *button, QWidget *parent) : ToolButton(parent) , m_button(button) { setAutoRaise(true); setToolbarButtonLook(true); setFocusPolicy(Qt::NoFocus); m_badgeLabel = new QLabel(this); m_badgeLabel->setObjectName(QSL("navigation-toolbutton-badge")); QFont f = m_badgeLabel->font(); f.setPixelSize(m_badgeLabel->height() / 2.5); m_badgeLabel->setFont(f); m_badgeLabel->hide(); setToolTip(button->toolTip()); updateIcon(); updateBadge(); connect(button, &AbstractButtonInterface::iconChanged, this, &NavigationBarToolButton::updateIcon); connect(button, &AbstractButtonInterface::activeChanged, this, &NavigationBarToolButton::updateIcon); connect(button, &AbstractButtonInterface::toolTipChanged, this, &NavigationBarToolButton::setToolTip); connect(button, &AbstractButtonInterface::badgeTextChanged, this, &NavigationBarToolButton::updateBadge); connect(this, &ToolButton::clicked, this, &NavigationBarToolButton::clicked); } void NavigationBarToolButton::clicked() { - AbstractButtonInterface::ClickController c; - c.visualParent = this; - c.popupPosition = [this](const QSize &size) { + AbstractButtonInterface::ClickController *c = new AbstractButtonInterface::ClickController; + c->visualParent = this; + c->popupPosition = [=](const QSize &size) { QPoint pos = mapToGlobal(rect().bottomRight()); if (QApplication::isRightToLeft()) { pos.setX(pos.x() - rect().width()); } else { pos.setX(pos.x() - size.width()); } + c->popupOpened = true; return pos; }; - setDown(true); - emit m_button->clicked(&c); - setDown(false); + c->popupClosed = [=]() { + setDown(false); + delete c; + }; + emit m_button->clicked(c); + if (c->popupOpened) { + setDown(true); + } } void NavigationBarToolButton::updateIcon() { const QIcon::Mode mode = m_button->isActive() ? QIcon::Normal : QIcon::Disabled; const QImage img = m_button->icon().pixmap(iconSize(), mode).toImage(); setIcon(QPixmap::fromImage(img, Qt::MonoOnly)); } void NavigationBarToolButton::updateBadge() { if (m_button->badgeText().isEmpty()) { m_badgeLabel->hide(); } else { m_badgeLabel->setText(m_button->badgeText()); m_badgeLabel->resize(m_badgeLabel->sizeHint()); m_badgeLabel->move(width() - m_badgeLabel->width(), 0); m_badgeLabel->show(); } } diff --git a/src/lib/tools/abstractbuttoninterface.h b/src/lib/tools/abstractbuttoninterface.h index 9aeafd4b..107c8ef3 100644 --- a/src/lib/tools/abstractbuttoninterface.h +++ b/src/lib/tools/abstractbuttoninterface.h @@ -1,80 +1,82 @@ /* ============================================================ * QupZilla - Qt web browser * Copyright (C) 2018 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ #pragma once #include #include #include #include "qzcommon.h" class WebView; class QUPZILLA_EXPORT AbstractButtonInterface : public QObject { Q_OBJECT public: struct ClickController { QWidget *visualParent; std::function popupPosition; + bool popupOpened = false; + std::function popupClosed; }; explicit AbstractButtonInterface(QObject *parent = nullptr); virtual QString id() const = 0; virtual QString name() const = 0; bool isValid() const; bool isActive() const; void setActive(bool active); QString title() const; void setTitle(const QString &text); QString toolTip() const; void setToolTip(const QString &toolTip); QIcon icon() const; void setIcon(const QIcon &icon); QString badgeText() const; void setBadgeText(const QString &badgeText); WebView *webView() const; void setWebView(WebView *view); signals: void activeChanged(bool active); void titleChanged(const QString &title); void toolTipChanged(const QString &toolTip); void iconChanged(const QIcon &icon); void badgeTextChanged(const QString &badgeText); void webViewChanged(WebView *view); void clicked(ClickController *controller); private: bool m_active = true; QString m_title; QString m_toolTip; QIcon m_icon; QString m_badgeText; WebView *m_view = nullptr; };