|
|
|
/*
|
|
|
|
Copyright (C) 2004 Teemu Rytilahti <tpr@d5k.net>
|
|
|
|
Copyright (C) 2005 George Staikos <staikos@kde.org>
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
As a special exception, permission is given to link this program
|
|
|
|
with any edition of TQt, and distribute the resulting executable,
|
|
|
|
without including the source code for TQt in the source distribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "konqmficon.h"
|
|
|
|
|
|
|
|
#include <dcopref.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kgenericfactory.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <tdeparts/statusbarextension.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <kstatusbar.h>
|
|
|
|
#include <kurllabel.h>
|
|
|
|
|
|
|
|
#include <tqcursor.h>
|
|
|
|
#include <tqstylesheet.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
|
|
|
|
typedef KGenericFactory<KonqMFIcon> KonqMFIconFactory;
|
|
|
|
K_EXPORT_COMPONENT_FACTORY(libmfkonqmficon,
|
|
|
|
KonqMFIconFactory("mfkonqmficon"))
|
|
|
|
|
|
|
|
KonqMFIcon::KonqMFIcon(TQObject *parent, const char *name, const TQStringList &)
|
|
|
|
: KParts::Plugin(parent, name), PluginBase(), m_part(0), m_mfIcon(0), m_statusBarEx(0), m_menu(0) {
|
|
|
|
TDEGlobal::locale()->insertCatalogue("mf_konqplugin");
|
|
|
|
|
|
|
|
m_part = dynamic_cast<TDEHTMLPart*>(parent);
|
|
|
|
if (!m_part) {
|
|
|
|
kdDebug() << "couldn't get part" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
TQTimer::singleShot(0, this, TQ_SLOT(waitPartToLoad()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KonqMFIcon::waitPartToLoad() {
|
|
|
|
connect(m_part, TQ_SIGNAL(completed()), this, TQ_SLOT(addMFIcon()));
|
|
|
|
connect(m_part, TQ_SIGNAL(completed(bool)), this, TQ_SLOT(addMFIcon())); // to make pages with metarefresh to work
|
|
|
|
connect(m_part, TQ_SIGNAL(started(TDEIO::Job *)), this, TQ_SLOT(removeMFIcon()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
KonqMFIcon::~KonqMFIcon() {
|
|
|
|
TDEGlobal::locale()->removeCatalogue("mf_konqplugin");
|
|
|
|
delete m_menu;
|
|
|
|
m_menu = 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static TQString textForNode(DOM::Node node) {
|
|
|
|
TQString rc;
|
|
|
|
DOM::NodeList nl = node.childNodes();
|
|
|
|
for (unsigned int i = 0; i < nl.length(); ++i) {
|
|
|
|
DOM::Node n = nl.item(i);
|
|
|
|
if (n.nodeType() == DOM::Node::TEXT_NODE) {
|
|
|
|
rc += n.nodeValue().string();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// FIXME: entries need to be escaped for vcard/vevent
|
|
|
|
return rc.stripWhiteSpace();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static TQString extractAddress(DOM::Node node) {
|
|
|
|
TQString rc = ";;";
|
|
|
|
TQMap<TQString,TQString> entry;
|
|
|
|
DOM::NodeList nodes = node.childNodes();
|
|
|
|
unsigned int n = nodes.length();
|
|
|
|
for (unsigned int i = 0; i < n; ++i) {
|
|
|
|
DOM::Node node = nodes.item(i);
|
|
|
|
DOM::NamedNodeMap map = node.attributes();
|
|
|
|
for (unsigned int j = 0; j < map.length(); ++j) {
|
|
|
|
if (map.item(j).nodeName().string() != "class") {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TQString a = map.item(j).nodeValue().string();
|
|
|
|
if (a == "street-address") {
|
|
|
|
entry["street-address"] = textForNode(node);
|
|
|
|
} else if (a == "locality") {
|
|
|
|
entry["locality"] = textForNode(node);
|
|
|
|
} else if (a == "region") {
|
|
|
|
entry["region"] = textForNode(node);
|
|
|
|
} else if (a == "postal-code") {
|
|
|
|
entry["postal-code"] = textForNode(node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rc += entry["street-address"] + ";" + entry["locality"] + ";" + entry["region"] + ";" + entry["postal-code"] + ";" + entry["country"];
|
|
|
|
return rc.stripWhiteSpace();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KonqMFIcon::extractCard(DOM::Node node) {
|
|
|
|
TQString name, value;
|
|
|
|
DOM::NodeList nodes = node.childNodes();
|
|
|
|
unsigned int n = nodes.length();
|
|
|
|
value += "BEGIN:VCARD\nVERSION:3.0\n";
|
|
|
|
for (unsigned int i = 0; i < n; ++i) {
|
|
|
|
DOM::Node node = nodes.item(i);
|
|
|
|
DOM::NamedNodeMap map = node.attributes();
|
|
|
|
for (unsigned int j = 0; j < map.length(); ++j) {
|
|
|
|
if (map.item(j).nodeName().string() != "class") {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TQStringList l = TQStringList::split(' ', map.item(j).nodeValue().string());
|
|
|
|
for (TQStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
|
|
|
|
if (*it == "photo") {
|
|
|
|
} else if (*it == "adr") {
|
|
|
|
value += "ADR:" + extractAddress(node) + "\n";
|
|
|
|
} else if (*it == "tel") {
|
|
|
|
value += "TEL;TYPE=VOICE:" + textForNode(node) + "\n";
|
|
|
|
} else if (*it == "fn") {
|
|
|
|
name = textForNode(node);
|
|
|
|
value += "FN:" + name + "\n";
|
|
|
|
} else if (*it == "url") {
|
|
|
|
DOM::Node at = node.attributes().getNamedItem("href");
|
|
|
|
if (!at.isNull()) {
|
|
|
|
value += "URL:" + at.nodeValue().string().stripWhiteSpace() + "\n";
|
|
|
|
}
|
|
|
|
} else if (*it == "email") {
|
|
|
|
DOM::Node at = node.attributes().getNamedItem("href");
|
|
|
|
if (!at.isNull()) {
|
|
|
|
TQString v = at.nodeValue().string();
|
|
|
|
if (v.startsWith("mailto:")) {
|
|
|
|
v = v.mid(7);
|
|
|
|
}
|
|
|
|
value += "EMAIL:" + v.stripWhiteSpace() + "\n";
|
|
|
|
}
|
|
|
|
} else if (*it == "org") {
|
|
|
|
value += "ORG:" + textForNode(node) + "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!name.isEmpty()) {
|
|
|
|
value += "END:VCARD\n";
|
|
|
|
_cards.append(qMakePair(name, value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KonqMFIcon::extractEvent(DOM::Node node) {
|
|
|
|
TQString name, value = "BEGIN:VCALENDAR\nPRODID:-//Konqueror//EN\nVERSION:2.0\nBEGIN:VEVENT\n";
|
|
|
|
DOM::NodeList nodes = node.childNodes();
|
|
|
|
unsigned int n = nodes.length();
|
|
|
|
for (unsigned int i = 0; i < n; ++i) {
|
|
|
|
DOM::Node node = nodes.item(i);
|
|
|
|
DOM::NamedNodeMap map = node.attributes();
|
|
|
|
for (unsigned int j = 0; j < map.length(); ++j) {
|
|
|
|
if (map.item(j).nodeName().string() != "class") {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TQStringList l = TQStringList::split(' ', map.item(j).nodeValue().string());
|
|
|
|
for (TQStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
|
|
|
|
if (*it == "url") {
|
|
|
|
DOM::Node at = node.attributes().getNamedItem("href");
|
|
|
|
if (!at.isNull()) {
|
|
|
|
value += "URL:" + at.nodeValue().string().stripWhiteSpace() + "\n";
|
|
|
|
}
|
|
|
|
} else if (*it == "dtstart") {
|
|
|
|
DOM::Node at = node.attributes().getNamedItem("title");
|
|
|
|
if (!at.isNull()) {
|
|
|
|
value += "DTSTART:" + at.nodeValue().string().stripWhiteSpace() + "\n";
|
|
|
|
}
|
|
|
|
} else if (*it == "dtend") {
|
|
|
|
DOM::Node at = node.attributes().getNamedItem("title");
|
|
|
|
if (!at.isNull()) {
|
|
|
|
value += "DTEND:" + at.nodeValue().string().stripWhiteSpace() + "\n";
|
|
|
|
}
|
|
|
|
} else if (*it == "summary") {
|
|
|
|
name = textForNode(node);
|
|
|
|
value += "SUMMARY:" + name + "\n";
|
|
|
|
} else if (*it == "location") {
|
|
|
|
value += "LOCATION:" + textForNode(node) + "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!name.isEmpty()) {
|
|
|
|
value += "END:VEVENT\nEND:VCALENDAR\n";
|
|
|
|
_events.append(qMakePair(name, value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool KonqMFIcon::hasMicroFormat(DOM::NodeList nodes) {
|
|
|
|
bool ok = false;
|
|
|
|
unsigned int n = nodes.length();
|
|
|
|
for (unsigned int i = 0; i < n; ++i) {
|
|
|
|
DOM::Node node = nodes.item(i);
|
|
|
|
DOM::NamedNodeMap map = node.attributes();
|
|
|
|
for (unsigned int j = 0; j < map.length(); ++j) {
|
|
|
|
if (map.item(j).nodeName().string() != "class") {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (map.item(j).nodeValue().string() == "vevent") {
|
|
|
|
ok = true;
|
|
|
|
extractEvent(node);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (map.item(j).nodeValue().string() == "vcard") {
|
|
|
|
ok = true;
|
|
|
|
extractCard(node);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (hasMicroFormat(node.childNodes())) {
|
|
|
|
ok = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool KonqMFIcon::mfFound() {
|
|
|
|
_events.clear();
|
|
|
|
_cards.clear();
|
|
|
|
return hasMicroFormat(m_part->document().childNodes());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KonqMFIcon::contextMenu() {
|
|
|
|
delete m_menu;
|
|
|
|
m_menu = new TDEPopupMenu(m_part->widget());
|
|
|
|
m_menu->insertTitle(i18n("Microformats"));
|
|
|
|
connect(m_menu, TQ_SIGNAL(activated(int)), this, TQ_SLOT(addMF(int)));
|
|
|
|
int id = 0;
|
|
|
|
for (TQValueList<TQPair<TQString, TQString> >::ConstIterator it = _events.begin(); it != _events.end(); ++it) {
|
|
|
|
m_menu->insertItem(SmallIcon("bookmark_add"), (*it).first, id);
|
|
|
|
id++;
|
|
|
|
}
|
|
|
|
for (TQValueList<TQPair<TQString, TQString> >::ConstIterator it = _cards.begin(); it != _cards.end(); ++it) {
|
|
|
|
m_menu->insertItem(SmallIcon("bookmark_add"), (*it).first, id);
|
|
|
|
id++;
|
|
|
|
}
|
|
|
|
m_menu->insertSeparator();
|
|
|
|
m_menu->insertItem(SmallIcon("bookmark_add"), i18n("Import All Microformats"), this, TQ_SLOT(addMFs()), 0, 50000 );
|
|
|
|
m_menu->popup(TQCursor::pos());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KonqMFIcon::addMFIcon() {
|
|
|
|
if (!mfFound() || m_mfIcon) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_statusBarEx = KParts::StatusBarExtension::childObject(m_part);
|
|
|
|
if (!m_statusBarEx) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_mfIcon = new KURLLabel(m_statusBarEx->statusBar());
|
|
|
|
m_mfIcon->setFixedHeight(instance()->iconLoader()->currentSize(TDEIcon::Small));
|
|
|
|
m_mfIcon->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
|
|
|
|
m_mfIcon->setUseCursor(false);
|
|
|
|
//FIXME hackish
|
|
|
|
m_mfIcon->setPixmap(TQPixmap(locate("data", "microformat/pics/microformat.png")));
|
|
|
|
|
|
|
|
TQToolTip::remove(m_mfIcon);
|
|
|
|
TQToolTip::add(m_mfIcon, i18n("This site has a microformat entry", "This site has %n microformat entries", _events.count() + _cards.count()));
|
|
|
|
|
|
|
|
m_statusBarEx->addStatusBarItem(m_mfIcon, 0, true);
|
|
|
|
|
|
|
|
connect(m_mfIcon, TQ_SIGNAL(leftClickedURL()), this, TQ_SLOT(contextMenu()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KonqMFIcon::removeMFIcon() {
|
|
|
|
_events.clear();
|
|
|
|
_cards.clear();
|
|
|
|
if (m_mfIcon) {
|
|
|
|
m_statusBarEx->removeStatusBarItem(m_mfIcon);
|
|
|
|
delete m_mfIcon;
|
|
|
|
m_mfIcon = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close the popup if it's open, otherwise we crash
|
|
|
|
delete m_menu;
|
|
|
|
m_menu = 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KonqMFIcon::addMF(int id) {
|
|
|
|
if (id < int(_events.count())) {
|
|
|
|
} else if (id < int(_cards.count())) {
|
|
|
|
id -= _cards.count() - 1;
|
|
|
|
addVCardViaDCOP(_cards[id].second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KonqMFIcon::addMFs() {
|
|
|
|
int n = _events.count() + _cards.count();
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
addMF(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "konqmficon.moc"
|