/* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2010-2012 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 "adblocktreewidget.h" #include "adblocksubscription.h" #include #include #include #include AdBlockTreeWidget::AdBlockTreeWidget(AdBlockSubscription* subscription, QWidget* parent) : TreeWidget(parent) , m_subscription(subscription) , m_topItem(0) , m_itemChangingBlock(false) { setContextMenuPolicy(Qt::CustomContextMenu); setDefaultItemShowMode(TreeWidget::ItemsExpanded); setHeaderHidden(true); setAlternatingRowColors(true); connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequested(QPoint))); connect(this, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(itemChanged(QTreeWidgetItem*))); connect(m_subscription, SIGNAL(subscriptionUpdated()), this, SLOT(subscriptionUpdated())); QTimer::singleShot(100, this, SLOT(refresh())); } AdBlockSubscription* AdBlockTreeWidget::subscription() const { return m_subscription; } void AdBlockTreeWidget::showRule(const AdBlockRule* rule) { if (!m_topItem && rule) { m_ruleToBeSelected = rule->filter(); } else if (!m_ruleToBeSelected.isEmpty()) { QList items = findItems(m_ruleToBeSelected, Qt::MatchRecursive); if (!items.isEmpty()) { QTreeWidgetItem* item = items.at(0); setCurrentItem(item); scrollToItem(item, QAbstractItemView::PositionAtCenter); } m_ruleToBeSelected.clear(); } } void AdBlockTreeWidget::contextMenuRequested(const QPoint &pos) { if (!m_subscription->canEditRules()) { return; } QTreeWidgetItem* item = itemAt(pos); if (!item) { return; } QMenu menu; menu.addAction(tr("Add Rule"), this, SLOT(addRule())); menu.addSeparator(); QAction* deleteAction = menu.addAction(tr("Remove Rule"), this, SLOT(removeRule())); if (!item->parent()) { deleteAction->setDisabled(true); } menu.exec(viewport()->mapToGlobal(pos)); } void AdBlockTreeWidget::itemChanged(QTreeWidgetItem* item) { if (!item || m_itemChangingBlock) { return; } m_itemChangingBlock = true; if (item->checkState(0) == Qt::Unchecked && !item->text(0).startsWith("!")) { // Disable rule int offset = item->data(0, Qt::UserRole + 10).toInt(); item->setText(0, item->text(0).prepend("!")); const AdBlockRule* rule = m_subscription->disableRule(offset); adjustItemColor(item, *rule); } else if (item->checkState(0) == Qt::Checked && item->text(0).startsWith("!")) { // Enable rule int offset = item->data(0, Qt::UserRole + 10).toInt(); item->setText(0, item->text(0).mid(1)); const AdBlockRule* rule = m_subscription->enableRule(offset); adjustItemColor(item, *rule); } else if (m_subscription->canEditRules()) { // Custom rule has been changed int offset = item->data(0, Qt::UserRole + 10).toInt(); const AdBlockRule* rule = m_subscription->replaceRule(AdBlockRule(item->text(0)), offset); adjustItemColor(item, *rule); } m_itemChangingBlock = false; } void AdBlockTreeWidget::addRule() { if (!m_subscription->canEditRules()) { return; } QString newRule = QInputDialog::getText(this, tr("Add Custom Rule"), tr("Please write your rule here:")); if (newRule.isEmpty()) { return; } AdBlockRule rule(newRule, m_subscription); int offset = m_subscription->addRule(rule); QTreeWidgetItem* item = new QTreeWidgetItem(); item->setText(0, newRule); item->setData(0, Qt::UserRole + 10, offset); item->setFlags(item->flags() | Qt::ItemIsEditable); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setCheckState(0, Qt::Checked); m_itemChangingBlock = true; m_topItem->addChild(item); m_itemChangingBlock = false; adjustItemColor(item, rule); } void AdBlockTreeWidget::removeRule() { QTreeWidgetItem* item = currentItem(); if (!item || !m_subscription->canEditRules() || item == m_topItem) { return; } int offset = item->data(0, Qt::UserRole + 10).toInt(); m_subscription->removeRule(offset); deleteItem(item); } void AdBlockTreeWidget::subscriptionUpdated() { refresh(); m_itemChangingBlock = true; m_topItem->setText(0, tr("%1 (recently updated)").arg(m_subscription->title())); m_itemChangingBlock = false; } void AdBlockTreeWidget::adjustItemColor(QTreeWidgetItem* item, const AdBlockRule &rule) { if (!rule.isEnabled()) { QFont font; font.setItalic(true); item->setForeground(0, QColor(Qt::gray)); item->setFont(0, font); } else if (rule.isCssRule()) { item->setForeground(0, QColor(Qt::darkBlue)); item->setFont(0, QFont()); } else if (rule.isException()) { item->setForeground(0, QColor(Qt::darkGreen)); item->setFont(0, QFont()); } else { item->setForeground(0, QColor()); item->setFont(0, QFont()); } } void AdBlockTreeWidget::keyPressEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Delete) { removeRule(); } TreeWidget::keyPressEvent(event); } void AdBlockTreeWidget::refresh() { m_itemChangingBlock = true; clear(); QFont boldFont; boldFont.setBold(true); m_topItem = new QTreeWidgetItem(this); m_topItem->setText(0, m_subscription->title()); m_topItem->setFont(0, boldFont); addTopLevelItem(m_topItem); const QList &allRules = m_subscription->allRules(); int index = 0; foreach(const AdBlockRule & rule, allRules) { QTreeWidgetItem* item = new QTreeWidgetItem(m_topItem); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setCheckState(0, (rule.isEnabled()) ? Qt::Checked : Qt::Unchecked); item->setText(0, rule.filter()); item->setData(0, Qt::UserRole + 10, index); if (m_subscription->canEditRules()) { item->setFlags(item->flags() | Qt::ItemIsEditable); } adjustItemColor(item, rule); ++index; } expandAll(); showRule(0); m_itemChangingBlock = false; }