1 /* ============================================================
2 * Falkon - Qt web browser
3 * Copyright (C) 2010-2018 David Rosca <nowrep@gmail.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 * ============================================================ */
18 #include "adblockdialog.h"
19 #include "adblockmanager.h"
20 #include "adblocksubscription.h"
21 #include "adblocktreewidget.h"
22 #include "adblockaddsubscriptiondialog.h"
23 #include "mainapplication.h"
24 #include "qztools.h"
25 
26 #include <QMenu>
27 #include <QTimer>
28 #include <QMessageBox>
29 #include <QInputDialog>
30 
AdBlockDialog(QWidget * parent)31 AdBlockDialog::AdBlockDialog(QWidget* parent)
32     : QDialog(parent)
33     , m_manager(AdBlockManager::instance())
34     , m_currentTreeWidget(nullptr)
35     , m_currentSubscription(nullptr)
36     , m_loaded(false)
37 {
38     setAttribute(Qt::WA_DeleteOnClose);
39     setupUi(this);
40 
41     QzTools::centerWidgetOnScreen(this);
42 
43 #ifdef Q_OS_MACOS
44     tabWidget->setDocumentMode(false);
45 #endif
46     adblockCheckBox->setChecked(m_manager->isEnabled());
47 
48     QMenu* menu = new QMenu(buttonOptions);
49     m_actionAddRule = menu->addAction(tr("Add Rule"), this, &AdBlockDialog::addRule);
50     m_actionRemoveRule = menu->addAction(tr("Remove Rule"), this, &AdBlockDialog::removeRule);
51     menu->addSeparator();
52     m_actionAddSubscription = menu->addAction(tr("Add Subscription"), this, &AdBlockDialog::addSubscription);
53     m_actionRemoveSubscription = menu->addAction(tr("Remove Subscription"), this, &AdBlockDialog::removeSubscription);
54     menu->addAction(tr("Update Subscriptions"), m_manager, &AdBlockManager::updateAllSubscriptions);
55     menu->addSeparator();
56     menu->addAction(tr("Learn about writing rules..."), this, &AdBlockDialog::learnAboutRules);
57 
58     buttonOptions->setMenu(menu);
59     connect(menu, &QMenu::aboutToShow, this, &AdBlockDialog::aboutToShowMenu);
60 
61     connect(adblockCheckBox, &QAbstractButton::toggled, this, &AdBlockDialog::enableAdBlock);
62     connect(search, &QLineEdit::textChanged, this, &AdBlockDialog::filterString);
63     connect(tabWidget, &QTabWidget::currentChanged, this, &AdBlockDialog::currentChanged);
64     connect(buttonBox, &QDialogButtonBox::accepted, this, &QWidget::close);
65 
66     load();
67 
68     buttonBox->setFocus();
69 }
70 
showRule(const AdBlockRule * rule) const71 void AdBlockDialog::showRule(const AdBlockRule* rule) const
72 {
73     AdBlockSubscription* subscription = rule->subscription();
74     if (!subscription) {
75         return;
76     }
77 
78     for (int i = 0; i < tabWidget->count(); ++i) {
79         AdBlockTreeWidget* treeWidget = qobject_cast<AdBlockTreeWidget*>(tabWidget->widget(i));
80 
81         if (subscription == treeWidget->subscription()) {
82             treeWidget->showRule(rule);
83             tabWidget->setCurrentIndex(i);
84             break;
85         }
86     }
87 }
88 
addRule()89 void AdBlockDialog::addRule()
90 {
91     m_currentTreeWidget->addRule();
92 }
93 
removeRule()94 void AdBlockDialog::removeRule()
95 {
96     m_currentTreeWidget->removeRule();
97 }
98 
addSubscription()99 void AdBlockDialog::addSubscription()
100 {
101     AdBlockAddSubscriptionDialog dialog(this);
102     if (dialog.exec() != QDialog::Accepted) {
103         return;
104     }
105 
106     QString title = dialog.title();
107     QString url = dialog.url();
108 
109     if (AdBlockSubscription* subscription = m_manager->addSubscription(title, url)) {
110         AdBlockTreeWidget* tree = new AdBlockTreeWidget(subscription, tabWidget);
111         int index = tabWidget->insertTab(tabWidget->count() - 1, tree, subscription->title());
112 
113         tabWidget->setCurrentIndex(index);
114     }
115 }
116 
removeSubscription()117 void AdBlockDialog::removeSubscription()
118 {
119     if (m_manager->removeSubscription(m_currentSubscription)) {
120         delete m_currentTreeWidget;
121     }
122 }
123 
currentChanged(int index)124 void AdBlockDialog::currentChanged(int index)
125 {
126     if (index != -1) {
127         m_currentTreeWidget = qobject_cast<AdBlockTreeWidget*>(tabWidget->widget(index));
128         m_currentSubscription = m_currentTreeWidget->subscription();
129     }
130 }
131 
filterString(const QString & string)132 void AdBlockDialog::filterString(const QString &string)
133 {
134     if (m_currentTreeWidget && adblockCheckBox->isChecked()) {
135         m_currentTreeWidget->filterString(string);
136     }
137 }
138 
enableAdBlock(bool state)139 void AdBlockDialog::enableAdBlock(bool state)
140 {
141     m_manager->setEnabled(state);
142 
143     if (state) {
144         load();
145     }
146 }
147 
aboutToShowMenu()148 void AdBlockDialog::aboutToShowMenu()
149 {
150     bool subscriptionEditable = m_currentSubscription && m_currentSubscription->canEditRules();
151     bool subscriptionRemovable = m_currentSubscription && m_currentSubscription->canBeRemoved();
152 
153     m_actionAddRule->setEnabled(subscriptionEditable);
154     m_actionRemoveRule->setEnabled(subscriptionEditable);
155     m_actionRemoveSubscription->setEnabled(subscriptionRemovable);
156 }
157 
learnAboutRules()158 void AdBlockDialog::learnAboutRules()
159 {
160     mApp->addNewTab(QUrl(QSL("http://adblockplus.org/en/filters")));
161 }
162 
loadSubscriptions()163 void AdBlockDialog::loadSubscriptions()
164 {
165     for (int i = 0; i < tabWidget->count(); ++i) {
166         AdBlockTreeWidget* treeWidget = qobject_cast<AdBlockTreeWidget*>(tabWidget->widget(i));
167         treeWidget->refresh();
168     }
169 }
170 
load()171 void AdBlockDialog::load()
172 {
173     if (m_loaded || !adblockCheckBox->isChecked()) {
174         return;
175     }
176 
177     const auto subscriptions = m_manager->subscriptions();
178     for (AdBlockSubscription* subscription : subscriptions) {
179         AdBlockTreeWidget* tree = new AdBlockTreeWidget(subscription, tabWidget);
180         tabWidget->addTab(tree, subscription->title());
181     }
182 
183     m_loaded = true;
184 
185     QTimer::singleShot(50, this, &AdBlockDialog::loadSubscriptions);
186 }
187