/*************************************************************************** * Copyright 2009-2011 by Sebastian Kugler * * * * 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 2 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "webslice.h" #include #include // Qt #include #include #include #include #include // KDE #include #include #include #include // Plasma #include WebSlice::WebSlice(QObject *parent, const QVariantList &args) : Plasma::PopupApplet(parent, args), m_slice(0), m_url(0) { setPopupIcon("internet-web-browser"); setAspectRatioMode(Plasma::IgnoreAspectRatio ); setAcceptDrops(true); setAcceptsHoverEvents(true); setMinimumSize(64, 64); resize(800, 600); kDebug() << "0"; } void WebSlice::init() { const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(pluginName()); const KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint); foreach (const KService::Ptr &service, offers) { QStringList args = service->property("X-Plasma-Args").toStringList(); if (args.count() >= 1) { m_url = KUrl(args[0]); if (args.count() >= 2) { m_element = args[1]; if (args.count() >= 6) { m_sliceGeometry = QRectF(args[2].toInt(), args[3].toInt(), args[4].toInt(), args[5].toInt()); } } } } void graphicsWidget(); } WebSlice::~WebSlice () { } void WebSlice::configChanged() { kDebug(); KConfigGroup cg = config(); if (!m_url.isValid() || m_url.isEmpty()) { m_url = cg.readEntry("url", "http://dot.kde.org/"); m_element = cg.readEntry("element", "#block-views-planetkde-block_1"); // for testing geometry //m_url = cg.readEntry("url", "http://buienradar.nl/"); //m_sliceGeometry = cg.readEntry("size", QRectF(258, 102, 550, 511)); m_sliceGeometry = cg.readEntry("sliceGeometry", QRectF()); } setAssociatedApplicationUrls(KUrl::List(m_url)); if (m_slice) { m_slice->preview(); } loadSlice(m_url, m_element); } QGraphicsWidget* WebSlice::graphicsWidget() { if (!m_slice) { m_widget = new QGraphicsWidget(this); QGraphicsLinearLayout *l = new QGraphicsLinearLayout(m_widget); m_widget->setLayout(l); m_slice = new KGraphicsWebSlice(m_widget); m_slice->setMaximumSize(contentsRect().size()); //m_slice->show(); updateColors(); //connect(m_slice, SIGNAL(sizeChanged(QSizeF)), this, SLOT(sizeChanged(QSizeF))); connect(m_slice, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool))); connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(updateColors())); setBusy(true); m_slice->setLoadingText(i18nc("displayed in the widget while loading", "

Loading...

")); //m_slice->hide(); l->addItem(m_slice); kDebug() << "slice set up"; configChanged(); } return m_widget; } void WebSlice::createConfigurationInterface(KConfigDialog *parent) { //QLabel *info = new QLabel(parent); QLabel* info = new QLabel(parent); info->setWordWrap(true); info->setTextInteractionFlags(Qt::TextBrowserInteraction); info->setText(i18n("

The Webslice Widget allows you to display a part of a webpage on your desktop or in a panel. The webslice is fully interactive.

" "

" "Specify the URL of the webpage in the URL field." "In the Element to Show field, fill in a CSS identifier (for example #mybox for elements with the id \"mybox\"). This is the preferred method as it works best with layout changes on the webpage." "

" "

" "Alternatively, you can specify a rectangle on the webpage to use as slice. Use \"x,y,width,height\" in pixels, for example \"100,80,300,360\". This method is a fallback for webpages that do not provide enough semantic markup for the above mechanism." "

" "If both methods (element and geometry) are used, the element will take precedence.")); parent->addPage(info, i18nc("informational page", "Info"), "help-hint"); QWidget *widget = new QWidget(parent); ui.setupUi(widget); parent->addPage(widget, i18nc("general config page", "Webpage"), Applet::icon()); connect(ui.loadUrl, SIGNAL(clicked()), this, SLOT(loadUrl())); connect(ui.elementCombo, SIGNAL(destroyed()), SLOT(disconnectLoadFinished())); connect(ui.elementCombo, SIGNAL(activated(QString)), this, SLOT(preview(QString))); connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted())); connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted())); ui.urlEdit->setText(m_url.toString()); ui.loadUrl->setIcon(KIcon("view-refresh")); ui.geometryEdit->setText(sliceGeometryToString()); ui.elementCombo->setEditable(true); updateElements(); preview(m_element); connect(ui.urlEdit, SIGNAL(userTextChanged(QString)), parent, SLOT(settingsModified())); connect(ui.loadUrl, SIGNAL(toggled(bool)), parent, SLOT(settingsModified())); connect(ui.elementCombo, SIGNAL(editTextChanged(QString)), parent, SLOT(settingsModified())); connect(ui.geometryEdit, SIGNAL(userTextChanged(QString)), parent, SLOT(settingsModified())); connect(ui.elementCombo, SIGNAL(editTextChanged(QString)), this, SLOT(handleGeometryEdit())); connect(parent, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)), this, SLOT(handleGeometryEdit())); } void WebSlice::updateElements() { ui.elementCombo->clear(); ui.elementCombo->addItem(m_element, m_element); ui.elementCombo->addItem(QString("body"), QString("body")); foreach(const QWebElement el, m_slice->page()->mainFrame()->findAllElements("*")) { QString elSelector; QString elAttributeName; if (el.attributeNames().contains("id")) { elAttributeName = QString("id"); elSelector = QString("#%1").arg(el.attribute("id")); // according to CSS selector syntax } else { /* don't add all elements for now, this really only clutters the combo elSelector = el.localName(); if (!el.attribute("class").isEmpty()) { elSelector.append("." + el.attribute("class")); } */ } // Add Item? if (!elSelector.isEmpty() && !(el.geometry().size().isNull())) { ui.elementCombo->addItem(elSelector, elAttributeName); } } } void WebSlice::disconnectLoadFinished() { // we need to prevent the combo from being updated when it's gone disconnect(m_slice, SIGNAL(loadFinished(bool)), this, SLOT(updateElements())); m_slice->preview(); } void WebSlice::preview(const QString &selector) { ui.geometryEdit->setText(sliceGeometryToString(selector)); m_slice->preview(selector); } void WebSlice::loadUrl() { loadSlice(QUrl(ui.urlEdit->text())); connect(m_slice, SIGNAL(loadFinished(bool)), SLOT(updateElements())); } void WebSlice::loadSlice(const QUrl &url, const QString &selector) { if (m_slice) { m_slice->loadSlice(url, selector); setAssociatedApplicationUrls(KUrl::List(url)); } } void WebSlice::configAccepted() { if (m_url.toString() != ui.urlEdit->text() || m_element != ui.elementCombo->currentText() || ui.geometryEdit->text() != sliceGeometryToString()) { m_url = QUrl(ui.urlEdit->text()); m_element = ui.elementCombo->currentText(); QString geo = ui.geometryEdit->text(); QStringList gel = geo.split(','); qreal x, y, w, h; bool ok = true; if (gel.length() == 4) { x = (qreal)(gel[0].toDouble(&ok)); y = (qreal)(gel[1].toDouble(&ok)); w = (qreal)(gel[2].toDouble(&ok)); h = (qreal)(gel[3].toDouble(&ok)); if (!ok) { kWarning() << "a conversion error occurred." << gel; } else { m_sliceGeometry = QRectF(x, y, w, h); config().writeEntry("sliceGeometry", m_sliceGeometry); } } else { if (m_element.isEmpty()) { kWarning() << "format error, use x,y,w,h" << gel << gel.length(); } } KConfigGroup cg = config(); cg.writeEntry("url", m_url.toString()); cg.writeEntry("element", m_element); if (!m_element.isEmpty()) { m_sliceGeometry = QRectF(); } emit configNeedsSaving(); configChanged(); } } QString WebSlice::sliceGeometryToString(const QString &selector) { QString s = QString("%1,%2,%3,%4").arg(m_slice->sliceGeometry(selector).x()).arg(m_slice->sliceGeometry(selector).y()).arg(m_slice->sliceGeometry(selector).width()).arg(m_slice->sliceGeometry(selector).height()); return s; } void WebSlice::loadFinished(bool ok) { setBusy(false); if (!ok) { return; } } void WebSlice::updateColors() { m_slice->setPreviewMaskColor( Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor)); } void WebSlice::handleGeometryEdit() { if (ui.elementCombo->currentText().isEmpty()) { ui.geometryEdit->setEnabled(true); } else { ui.geometryEdit->setEnabled(false); } } #include "moc_webslice.cpp"