kde-playground/kdepim/messageviewer/adblock/adblockblockableitemswidget.cpp
2015-04-14 21:49:29 +00:00

315 lines
10 KiB
C++

/*
Copyright (c) 2013, 2014 Montel Laurent <montel@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License, version 2, as
published by the Free Software Foundation.
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "adblockblockableitemswidget.h"
#include "adblockcreatefilterdialog.h"
#include "settings/globalsettings.h"
#include "adblock/adblockmanager.h"
#include "pimcommon/widgets/customtreeview.h"
#include <KLocalizedString>
#include <KTreeWidgetSearchLine>
#include <KMenu>
#include <KConfigGroup>
#include <KStandardDirs>
#include <KRun>
#include <QHeaderView>
#include <QVBoxLayout>
#include <QWebFrame>
#include <QWebElement>
#include <QDebug>
#include <QPointer>
#include <QClipboard>
#include <QApplication>
#include <QFile>
#include <QPainter>
using namespace MessageViewer;
AdBlockBlockableItemsWidget::AdBlockBlockableItemsWidget(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *lay = new QVBoxLayout;
setLayout(lay);
mListItems = new PimCommon::CustomTreeView;
mListItems->setDefaultText(i18n("No blockable element found."));
mListItems->setContextMenuPolicy(Qt::CustomContextMenu);
mListItems->setAlternatingRowColors(true);
mListItems->setRootIsDecorated(false);
connect(mListItems, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(customContextMenuRequested(QPoint)));
QStringList lst;
lst << i18n("Filter") << i18n("Address") << i18n("Type");
mListItems->setHeaderLabels(lst);
KTreeWidgetSearchLine *searchLine = new KTreeWidgetSearchLine(this, mListItems);
searchLine->setPlaceholderText(i18n("Search..."));
lay->addWidget(searchLine);
lay->addWidget(mListItems);
KConfigGroup config( MessageViewer::GlobalSettings::self()->config(),"AdBlockHeaders");
mListItems->header()->restoreState(config.readEntry("HeaderState",QByteArray()));
}
AdBlockBlockableItemsWidget::~AdBlockBlockableItemsWidget()
{
KConfigGroup groupHeader( MessageViewer::GlobalSettings::self()->config(),"AdBlockHeaders" );
groupHeader.writeEntry( "HeaderState", mListItems->header()->saveState());
groupHeader.sync();
}
void AdBlockBlockableItemsWidget::setWebFrame(QWebFrame *frame)
{
mListItems->clear();
searchBlockableElement(frame);
}
QString AdBlockBlockableItemsWidget::elementTypeToI18n(AdBlockBlockableItemsWidget::TypeElement type)
{
QString result;
switch(type) {
case AdBlockBlockableItemsWidget::Image:
result = i18n("Image");
break;
case AdBlockBlockableItemsWidget::Script:
result = i18n("Script");
break;
case AdBlockBlockableItemsWidget::StyleSheet:
result = i18n("Stylesheet");
break;
case AdBlockBlockableItemsWidget::Font:
result = i18n("Font");
break;
case AdBlockBlockableItemsWidget::Frame:
result = i18n("Frame");
break;
case AdBlockBlockableItemsWidget::XmlRequest:
result = i18n("XML Request");
break;
case AdBlockBlockableItemsWidget::Object:
result = i18n("Object");
break;
case AdBlockBlockableItemsWidget::Media:
result = i18n("Audio/Video");
break;
case AdBlockBlockableItemsWidget::Popup:
result = i18n("Popup window");
break;
case AdBlockBlockableItemsWidget::None:
default:
result = i18n("Unknown");
}
return result;
}
QString AdBlockBlockableItemsWidget::elementType(AdBlockBlockableItemsWidget::TypeElement type)
{
QString result;
switch(type) {
case AdBlockBlockableItemsWidget::Image:
result = QLatin1String("image");
break;
case AdBlockBlockableItemsWidget::Script:
result = QLatin1String("script");
break;
case AdBlockBlockableItemsWidget::StyleSheet:
result = QLatin1String("stylesheet");
break;
case AdBlockBlockableItemsWidget::Font:
result = QLatin1String("font");
break;
case AdBlockBlockableItemsWidget::Frame:
result = QLatin1String("frame");
break;
case AdBlockBlockableItemsWidget::XmlRequest:
result = QLatin1String("xmlhttprequest");
break;
case AdBlockBlockableItemsWidget::Object:
result = QLatin1String("other");
break;
case AdBlockBlockableItemsWidget::Media:
result = QLatin1String("media");
break;
case AdBlockBlockableItemsWidget::Popup:
result = QLatin1String("popup");
break;
case AdBlockBlockableItemsWidget::None:
default:
qDebug()<<" unknown type "<<type;
}
return result;
}
void AdBlockBlockableItemsWidget::adaptSrc(QString &src,const QString &hostName)
{
if (src.startsWith(QLatin1String("http://")) || src.startsWith(QLatin1String("https://")) ) {
//Nothing
} else if (src.startsWith(QLatin1String("//"))) {
src = QLatin1String("https:") + src;
} else if (src.startsWith(QLatin1Char('/'))){
src = QLatin1String("https://") + hostName + src;
} else {
src = QString();
}
}
void AdBlockBlockableItemsWidget::searchBlockableElement(QWebFrame *frame)
{
const QUrl url = frame->requestedUrl();
const QString host = url.host();
const QWebElementCollection images = frame->findAllElements(QLatin1String("img"));
Q_FOREACH (const QWebElement &img, images) {
if (img.hasAttribute(QLatin1String("src"))) {
QString src = img.attribute(QLatin1String("src"));
if (src.isEmpty())
continue;
adaptSrc(src, host);
if (src.isEmpty())
continue;
QTreeWidgetItem *item = new QTreeWidgetItem(mListItems);
item->setText(Url, src);
item->setText(Type, elementTypeToI18n(AdBlockBlockableItemsWidget::Image));
item->setTextColor(FilterValue, Qt::red);
item->setData(Type, Element, Image);
}
}
const QWebElementCollection scripts = frame->findAllElements(QLatin1String("script"));
Q_FOREACH (const QWebElement &script, scripts) {
QString src = script.attribute(QLatin1String("src"));
if (src.isEmpty())
continue;
adaptSrc(src, host);
if (src.isEmpty())
continue;
QTreeWidgetItem *item = new QTreeWidgetItem(mListItems);
item->setText(Url, src);
item->setText(Type, elementTypeToI18n(AdBlockBlockableItemsWidget::Script));
item->setTextColor(FilterValue, Qt::red);
item->setData(Type, Element, Script);
}
foreach(QWebFrame *childFrame, frame->childFrames()) {
searchBlockableElement(childFrame);
}
}
void AdBlockBlockableItemsWidget::customContextMenuRequested(const QPoint &)
{
QTreeWidgetItem *item = mListItems->currentItem();
if (!item)
return;
KMenu menu;
menu.addAction(i18n("Copy url"),this,SLOT(slotCopyItem()));
if (!item->text(FilterValue).isEmpty())
menu.addAction(i18n("Copy filter"),this,SLOT(slotCopyFilterItem()));
menu.addAction(i18n("Block item..."),this,SLOT(slotBlockItem()));
menu.addSeparator();
menu.addAction(i18n("Open"), this, SLOT(slotOpenItem()));
if (!item->text(FilterValue).isEmpty()) {
menu.addSeparator();
menu.addAction(i18n("Remove filter"),this,SLOT(slotRemoveFilter()));
}
menu.exec(QCursor::pos());
}
void AdBlockBlockableItemsWidget::slotCopyFilterItem()
{
QTreeWidgetItem *item = mListItems->currentItem();
if (!item)
return;
QClipboard *cb = QApplication::clipboard();
cb->setText(item->text(FilterValue), QClipboard::Clipboard);
}
void AdBlockBlockableItemsWidget::slotOpenItem()
{
QTreeWidgetItem *item = mListItems->currentItem();
if (!item)
return;
const KUrl url(item->text(Url));
KRun *runner = new KRun( url, this ); // will delete itself
runner->setRunExecutables( false );
}
void AdBlockBlockableItemsWidget::slotBlockItem()
{
QTreeWidgetItem *item = mListItems->currentItem();
if (!item)
return;
QPointer<AdBlockCreateFilterDialog> dlg = new AdBlockCreateFilterDialog(this);
dlg->setPattern(static_cast<TypeElement>(item->data(Type, Element).toInt()), item->text(Url));
if (dlg->exec()) {
const QString filter = dlg->filter();
item->setText(FilterValue, filter);
}
delete dlg;
}
void AdBlockBlockableItemsWidget::slotCopyItem()
{
QTreeWidgetItem *item = mListItems->currentItem();
if (!item)
return;
QClipboard *cb = QApplication::clipboard();
cb->setText(item->text(Url), QClipboard::Clipboard);
}
void AdBlockBlockableItemsWidget::saveFilters()
{
const int numberOfElement(mListItems->topLevelItemCount());
QString filters;
for (int i = 0; i < numberOfElement; ++i) {
QTreeWidgetItem *item = mListItems->topLevelItem(i);
if (!item->text(FilterValue).isEmpty()) {
if (filters.isEmpty()) {
filters = item->text(FilterValue);
} else {
filters += QLatin1Char('\n') + item->text(FilterValue);
}
}
}
if (filters.isEmpty())
return;
const QString localRulesFilePath = KStandardDirs::locateLocal("appdata" , QLatin1String("adblockrules_local"));
QFile ruleFile(localRulesFilePath);
if (!ruleFile.open(QFile::WriteOnly | QFile::Text)) {
kDebug() << "Unable to open rule file" << localRulesFilePath;
return;
}
QTextStream out(&ruleFile);
out << filters;
AdBlockManager::self()->reloadConfig();
}
void AdBlockBlockableItemsWidget::slotRemoveFilter()
{
QTreeWidgetItem *item = mListItems->currentItem();
if (!item)
return;
item->setText(FilterValue, QString());
}