summaryrefslogtreecommitdiffstats
path: root/kio/bookmarks
diff options
context:
space:
mode:
Diffstat (limited to 'kio/bookmarks')
-rw-r--r--kio/bookmarks/Makefile.am40
-rw-r--r--kio/bookmarks/dptrtemplate.h57
-rw-r--r--kio/bookmarks/kbookmark.cc535
-rw-r--r--kio/bookmarks/kbookmark.h329
-rw-r--r--kio/bookmarks/kbookmarkbar.cc554
-rw-r--r--kio/bookmarks/kbookmarkbar.h130
-rw-r--r--kio/bookmarks/kbookmarkdombuilder.cc81
-rw-r--r--kio/bookmarks/kbookmarkdombuilder.h48
-rw-r--r--kio/bookmarks/kbookmarkdrag.cc169
-rw-r--r--kio/bookmarks/kbookmarkdrag.h57
-rw-r--r--kio/bookmarks/kbookmarkexporter.cc32
-rw-r--r--kio/bookmarks/kbookmarkexporter.h50
-rw-r--r--kio/bookmarks/kbookmarkimporter.cc101
-rw-r--r--kio/bookmarks/kbookmarkimporter.h106
-rw-r--r--kio/bookmarks/kbookmarkimporter_crash.cc215
-rw-r--r--kio/bookmarks/kbookmarkimporter_crash.h74
-rw-r--r--kio/bookmarks/kbookmarkimporter_ie.cc185
-rw-r--r--kio/bookmarks/kbookmarkimporter_ie.h90
-rw-r--r--kio/bookmarks/kbookmarkimporter_kde1.cc150
-rw-r--r--kio/bookmarks/kbookmarkimporter_kde1.h49
-rw-r--r--kio/bookmarks/kbookmarkimporter_ns.cc243
-rw-r--r--kio/bookmarks/kbookmarkimporter_ns.h132
-rw-r--r--kio/bookmarks/kbookmarkimporter_opera.cc170
-rw-r--r--kio/bookmarks/kbookmarkimporter_opera.h86
-rw-r--r--kio/bookmarks/kbookmarkmanager.cc727
-rw-r--r--kio/bookmarks/kbookmarkmanager.h367
-rw-r--r--kio/bookmarks/kbookmarkmenu.cc1187
-rw-r--r--kio/bookmarks/kbookmarkmenu.h265
-rw-r--r--kio/bookmarks/kbookmarkmenu_p.h224
-rw-r--r--kio/bookmarks/kbookmarknotifier.h45
30 files changed, 6498 insertions, 0 deletions
diff --git a/kio/bookmarks/Makefile.am b/kio/bookmarks/Makefile.am
new file mode 100644
index 000000000..2a41efd98
--- /dev/null
+++ b/kio/bookmarks/Makefile.am
@@ -0,0 +1,40 @@
+# This file is part of the KDE libraries
+# Copyright (C) 1997 Stephan Kulow (coolo@kde.org)
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+
+# This library 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
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this library; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+
+INCLUDES= -I$(srcdir)/../libltdl/ -I$(top_srcdir) -I$(top_srcdir)/kdefx -I$(top_builddir)/kio/kio $(all_includes)
+
+noinst_LTLIBRARIES = libkbookmarks.la
+
+METASOURCES = AUTO
+
+# convenience lib - no _LDFLAGS or _LIBADD !
+
+include_HEADERS = \
+ kbookmark.h kbookmarkbar.h kbookmarkdrag.h kbookmarkexporter.h \
+ kbookmarkimporter.h kbookmarkmanager.h kbookmarkmenu.h kbookmarknotifier.h \
+ kbookmarkimporter_crash.h kbookmarkimporter_opera.h kbookmarkimporter_ie.h \
+ kbookmarkimporter_ns.h kbookmarkimporter_kde1.h kbookmarkdombuilder.h
+libkbookmarks_la_SOURCES = \
+ kbookmark.cc kbookmarkbar.cc kbookmarkdrag.cc kbookmarkexporter.cc \
+ kbookmarkimporter.cc kbookmarkmanager.cc kbookmarkmenu.cc \
+ kbookmarkimporter_crash.cc kbookmarkimporter_opera.cc kbookmarkimporter_ie.cc \
+ kbookmarkimporter_ns.cc kbookmarkimporter_kde1.cc kbookmarkdombuilder.cc \
+ kbookmarkmanager.skel kbookmarknotifier.skel
+
+include $(top_srcdir)/admin/Doxyfile.am
diff --git a/kio/bookmarks/dptrtemplate.h b/kio/bookmarks/dptrtemplate.h
new file mode 100644
index 000000000..26fd0b3a9
--- /dev/null
+++ b/kio/bookmarks/dptrtemplate.h
@@ -0,0 +1,57 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE project
+ Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __dptrtemplate_h__
+#define __dptrtemplate_h__
+
+#include <qptrdict.h>
+
+template<class Instance, class PrivateData>
+class dPtrTemplate {
+public:
+ static PrivateData* d( const Instance* instance )
+ {
+ if ( !d_ptr ) {
+ cleanup_d_ptr();
+ d_ptr = new QPtrDict<PrivateData>;
+ qAddPostRoutine( cleanup_d_ptr );
+ }
+ PrivateData* ret = d_ptr->find( (void*) instance );
+ if ( ! ret ) {
+ ret = new PrivateData;
+ d_ptr->replace( (void*) instance, ret );
+ }
+ return ret;
+ }
+ static void delete_d( const Instance* instance )
+ {
+ if ( d_ptr )
+ d_ptr->remove( (void*) instance );
+ }
+private:
+ static void cleanup_d_ptr()
+ {
+ delete d_ptr;
+ }
+ static QPtrDict<PrivateData>* d_ptr;
+};
+
+#endif
diff --git a/kio/bookmarks/kbookmark.cc b/kio/bookmarks/kbookmark.cc
new file mode 100644
index 000000000..59cf10db3
--- /dev/null
+++ b/kio/bookmarks/kbookmark.cc
@@ -0,0 +1,535 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>
+ Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kbookmark.h"
+#include <qvaluestack.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+#include <kstringhandler.h>
+#include <kinputdialog.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <assert.h>
+#include <kapplication.h>
+#include <dcopclient.h>
+#include <kbookmarkmanager.h>
+
+KBookmarkGroup::KBookmarkGroup()
+ : KBookmark( QDomElement() )
+{
+}
+
+KBookmarkGroup::KBookmarkGroup( QDomElement elem )
+ : KBookmark(elem)
+{
+}
+
+QString KBookmarkGroup::groupAddress() const
+{
+ if (m_address.isEmpty())
+ m_address = address();
+ return m_address;
+}
+
+bool KBookmarkGroup::isOpen() const
+{
+ return element.attribute("folded") == "no"; // default is: folded
+}
+
+// Returns first element node equal to or after node n
+static QDomElement firstElement(QDomNode n)
+{
+ while(!n.isNull() && !n.isElement())
+ n = n.nextSibling();
+ return n.toElement();
+}
+
+// Returns first element node equal to or before node n
+static QDomElement lastElement(QDomNode n)
+{
+ while(!n.isNull() && !n.isElement())
+ n = n.previousSibling();
+ return n.toElement();
+}
+
+KBookmark KBookmarkGroup::first() const
+{
+ return KBookmark( nextKnownTag( firstElement(element.firstChild()), true ) );
+}
+
+KBookmark KBookmarkGroup::previous( const KBookmark & current ) const
+{
+ return KBookmark( nextKnownTag( lastElement(current.element.previousSibling()), false ) );
+}
+
+KBookmark KBookmarkGroup::next( const KBookmark & current ) const
+{
+ return KBookmark( nextKnownTag( firstElement(current.element.nextSibling()), true ) );
+}
+
+// KDE4: Change QDomElement to QDomNode so that we can get rid of
+// firstElement() and lastElement()
+QDomElement KBookmarkGroup::nextKnownTag( QDomElement start, bool goNext ) const
+{
+ static const QString & bookmark = KGlobal::staticQString("bookmark");
+ static const QString & folder = KGlobal::staticQString("folder");
+ static const QString & separator = KGlobal::staticQString("separator");
+
+ for( QDomNode n = start; !n.isNull(); )
+ {
+ QDomElement elem = n.toElement();
+ QString tag = elem.tagName();
+ if (tag == folder || tag == bookmark || tag == separator)
+ return elem;
+ if (goNext)
+ n = n.nextSibling();
+ else
+ n = n.previousSibling();
+ }
+ return QDomElement();
+}
+
+KBookmarkGroup KBookmarkGroup::createNewFolder( KBookmarkManager* mgr, const QString & text, bool emitSignal )
+{
+ QString txt( text );
+ if ( text.isEmpty() )
+ {
+ bool ok;
+ QString caption = parentGroup().fullText().isEmpty() ?
+ i18n( "Create New Bookmark Folder" ) :
+ i18n( "Create New Bookmark Folder in %1" )
+ .arg( parentGroup().text() );
+ txt = KInputDialog::getText( caption, i18n( "New folder:" ),
+ QString::null, &ok );
+ if ( !ok )
+ return KBookmarkGroup();
+ }
+
+ Q_ASSERT(!element.isNull());
+ QDomDocument doc = element.ownerDocument();
+ QDomElement groupElem = doc.createElement( "folder" );
+ element.appendChild( groupElem );
+ QDomElement textElem = doc.createElement( "title" );
+ groupElem.appendChild( textElem );
+ textElem.appendChild( doc.createTextNode( txt ) );
+
+ KBookmarkGroup grp(groupElem);
+
+ if (emitSignal)
+ emit mgr->notifier().createdNewFolder(
+ mgr->path(), grp.fullText(),
+ grp.address() );
+
+ return grp;
+
+}
+
+KBookmark KBookmarkGroup::createNewSeparator()
+{
+ Q_ASSERT(!element.isNull());
+ QDomDocument doc = element.ownerDocument();
+ Q_ASSERT(!doc.isNull());
+ QDomElement sepElem = doc.createElement( "separator" );
+ element.appendChild( sepElem );
+ return KBookmark(sepElem);
+}
+
+bool KBookmarkGroup::moveItem( const KBookmark & item, const KBookmark & after )
+{
+ QDomNode n;
+ if ( !after.isNull() )
+ n = element.insertAfter( item.element, after.element );
+ else // first child
+ {
+ if ( element.firstChild().isNull() ) // Empty element -> set as real first child
+ n = element.insertBefore( item.element, QDomElement() );
+
+ // we have to skip everything up to the first valid child
+ QDomElement firstChild = nextKnownTag(element.firstChild().toElement(), true);
+ if ( !firstChild.isNull() )
+ n = element.insertBefore( item.element, firstChild );
+ else
+ {
+ // No real first child -> append after the <title> etc.
+ n = element.appendChild( item.element );
+ }
+ }
+ return (!n.isNull());
+}
+
+KBookmark KBookmarkGroup::addBookmark( KBookmarkManager* mgr, const KBookmark &bm, bool emitSignal )
+{
+ element.appendChild( bm.internalElement() );
+
+ if (emitSignal) {
+ if ( bm.hasMetaData() ) {
+ mgr->notifyCompleteChange( "" );
+ } else {
+ emit mgr->notifier().addedBookmark(
+ mgr->path(), bm.url().url(),
+ bm.fullText(), bm.address(), bm.icon() );
+ }
+ }
+
+ return bm;
+}
+
+KBookmark KBookmarkGroup::addBookmark( KBookmarkManager* mgr, const QString & text, const KURL & url, const QString & icon, bool emitSignal )
+{
+ //kdDebug(7043) << "KBookmarkGroup::addBookmark " << text << " into " << m_address << endl;
+ QDomDocument doc = element.ownerDocument();
+ QDomElement elem = doc.createElement( "bookmark" );
+ elem.setAttribute( "href", url.url( 0, 106 ) ); // write utf8 URL (106 is mib enum for utf8)
+ QString _icon = icon;
+ if ( _icon.isEmpty() )
+ _icon = KMimeType::iconForURL( url );
+ elem.setAttribute( "icon", _icon );
+
+ QDomElement textElem = doc.createElement( "title" );
+ elem.appendChild( textElem );
+ textElem.appendChild( doc.createTextNode( text ) );
+
+ return addBookmark( mgr, KBookmark( elem ), emitSignal );
+}
+
+void KBookmarkGroup::deleteBookmark( KBookmark bk )
+{
+ element.removeChild( bk.element );
+}
+
+bool KBookmarkGroup::isToolbarGroup() const
+{
+ return ( element.attribute("toolbar") == "yes" );
+}
+
+QDomElement KBookmarkGroup::findToolbar() const
+{
+ if ( element.attribute("toolbar") == "yes" )
+ return element;
+ for (QDomNode n = element.firstChild(); !n.isNull() ; n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+ // Search among the "folder" children only
+ if ( e.tagName() == "folder" )
+ {
+ if ( e.attribute("toolbar") == "yes" )
+ return e;
+ else
+ {
+ QDomElement result = KBookmarkGroup(e).findToolbar();
+ if (!result.isNull())
+ return result;
+ }
+ }
+ }
+ return QDomElement();
+}
+
+QValueList<KURL> KBookmarkGroup::groupUrlList() const
+{
+ QValueList<KURL> urlList;
+ for ( KBookmark bm = first(); !bm.isNull(); bm = next(bm) )
+ {
+ if ( bm.isSeparator() || bm.isGroup() )
+ continue;
+ urlList << bm.url();
+ }
+ return urlList;
+}
+
+//////
+
+bool KBookmark::isGroup() const
+{
+ QString tag = element.tagName();
+ return ( tag == "folder"
+ || tag == "xbel" ); // don't forget the toplevel group
+}
+
+bool KBookmark::isSeparator() const
+{
+ return (element.tagName() == "separator");
+}
+
+bool KBookmark::hasParent() const
+{
+ QDomElement parent = element.parentNode().toElement();
+ return !parent.isNull();
+}
+
+QString KBookmark::text() const
+{
+ return KStringHandler::csqueeze( fullText() );
+}
+
+QString KBookmark::fullText() const
+{
+ if (isSeparator())
+ return i18n("--- separator ---");
+
+ return element.namedItem("title").toElement().text();
+}
+
+KURL KBookmark::url() const
+{
+ return KURL(element.attribute("href"), 106); // Decode it from utf8 (106 is mib enum for utf8)
+}
+
+QString KBookmark::icon() const
+{
+ QString icon = element.attribute("icon");
+ if ( icon.isEmpty() )
+ // Default icon depends on URL for bookmarks, and is default directory
+ // icon for groups.
+ if ( isGroup() )
+ icon = "bookmark_folder";
+ else
+ if ( isSeparator() )
+ icon = "eraser"; // whatever
+ else
+ icon = KMimeType::iconForURL( url() );
+ return icon;
+}
+
+KBookmarkGroup KBookmark::parentGroup() const
+{
+ return KBookmarkGroup( element.parentNode().toElement() );
+}
+
+KBookmarkGroup KBookmark::toGroup() const
+{
+ Q_ASSERT( isGroup() );
+ return KBookmarkGroup(element);
+}
+
+QString KBookmark::address() const
+{
+ if ( element.tagName() == "xbel" )
+ return ""; // not QString::null !
+ else
+ {
+ // Use keditbookmarks's DEBUG_ADDRESSES flag to debug this code :)
+ if (!hasParent())
+ {
+ Q_ASSERT(hasParent());
+ return "ERROR"; // Avoid an infinite loop
+ }
+ KBookmarkGroup group = parentGroup();
+ QString parentAddress = group.address();
+ uint counter = 0;
+ // Implementation note: we don't use QDomNode's childNode list because we
+ // would have to skip "TEXT", which KBookmarkGroup already does for us.
+ for ( KBookmark bk = group.first() ; !bk.isNull() ; bk = group.next(bk), ++counter )
+ {
+ if ( bk.element == element )
+ return parentAddress + "/" + QString::number(counter);
+ }
+ kdWarning() << "KBookmark::address : this can't happen! " << parentAddress << endl;
+ return "ERROR";
+ }
+}
+
+KBookmark KBookmark::standaloneBookmark( const QString & text, const KURL & url, const QString & icon )
+{
+ QDomDocument doc("xbel");
+ QDomElement elem = doc.createElement("xbel");
+ doc.appendChild( elem );
+ KBookmarkGroup grp( elem );
+ grp.addBookmark( 0L, text, url, icon, false );
+ return grp.first();
+}
+
+// For some strange reason QString("").left(0) returns QString::null;
+// That breaks commonParent()
+QString KBookmark::left(const QString & str, uint len)
+{
+ //kdDebug()<<"********"<<QString("").left(0).isNull()<<endl;
+ if(len == 0)
+ return QString("");
+ else
+ return str.left(len);
+}
+
+QString KBookmark::commonParent(QString A, QString B)
+{
+ QString error("ERROR");
+ if(A == error || B == error)
+ return error;
+
+ A += "/";
+ B += "/";
+
+ uint lastCommonSlash = 0;
+ uint lastPos = A.length() < B.length() ? A.length() : B.length();
+ for(uint i=0; i < lastPos; ++i)
+ {
+ if(A[i] != B[i])
+ return left(A, lastCommonSlash);
+ if(A[i] == '/')
+ lastCommonSlash = i;
+ }
+ return left(A, lastCommonSlash);
+}
+
+static QDomNode cd_or_create(QDomNode node, QString name)
+{
+ QDomNode subnode = node.namedItem(name);
+ if (subnode.isNull())
+ {
+ subnode = node.ownerDocument().createElement(name);
+ node.appendChild(subnode);
+ }
+ return subnode;
+}
+
+static QDomText get_or_create_text(QDomNode node)
+{
+ QDomNode subnode = node.firstChild();
+ if (subnode.isNull())
+ {
+ subnode = node.ownerDocument().createTextNode("");
+ node.appendChild(subnode);
+ }
+ return subnode.toText();
+}
+
+// Look for a metadata with owner="http://www.kde.org" or without any owner (for compatibility)
+static QDomNode findOrCreateMetadata( QDomNode& parent )
+{
+ static const char kdeOwner[] = "http://www.kde.org";
+ QDomElement metadataElement;
+ for ( QDomNode _node = parent.firstChild(); !_node.isNull(); _node = _node.nextSibling() ) {
+ QDomElement elem = _node.toElement();
+ if ( !elem.isNull() && elem.tagName() == "metadata" ) {
+ const QString owner = elem.attribute( "owner" );
+ if ( owner == kdeOwner )
+ return elem;
+ if ( owner.isEmpty() )
+ metadataElement = elem;
+ }
+ }
+ if ( metadataElement.isNull() ) {
+ metadataElement = parent.ownerDocument().createElement( "metadata" );
+ parent.appendChild(metadataElement);
+ }
+ metadataElement.setAttribute( "owner", kdeOwner );
+ return metadataElement;
+}
+
+bool KBookmark::hasMetaData() const
+{
+ // ### NOTE: this code creates <info> and <metadata>, despite its name and the const.
+ // It doesn't matter much in practice since it's only called for newly-created bookmarks,
+ // which will get metadata soon after anyway.
+ QDomNode n = cd_or_create( internalElement(), "info" );
+ return findOrCreateMetadata( n ).hasChildNodes();
+}
+
+void KBookmark::updateAccessMetadata()
+{
+ kdDebug(7043) << "KBookmark::updateAccessMetadata " << address() << " " << url().prettyURL() << endl;
+
+ const uint timet = QDateTime::currentDateTime().toTime_t();
+ setMetaDataItem( "time_added", QString::number( timet ), DontOverwriteMetaData );
+ setMetaDataItem( "time_visited", QString::number( timet ) );
+
+ QString countStr = metaDataItem( "visit_count" ); // TODO use spec'ed name
+ bool ok;
+ int currentCount = countStr.toInt(&ok);
+ if (!ok)
+ currentCount = 0;
+ currentCount++;
+ setMetaDataItem( "visit_count", QString::number( currentCount ) );
+
+ // TODO - for 4.0 - time_modified
+}
+
+QString KBookmark::metaDataItem( const QString &key ) const
+{
+ QDomNode infoNode = cd_or_create( internalElement(), "info" );
+ infoNode = findOrCreateMetadata( infoNode );
+ for ( QDomNode n = infoNode.firstChild(); !n.isNull(); n = n.nextSibling() ) {
+ if ( !n.isElement() ) {
+ continue;
+ }
+ const QDomElement e = n.toElement();
+ if ( e.tagName() == key ) {
+ return e.text();
+ }
+ }
+ return QString::null;
+}
+
+void KBookmark::setMetaDataItem( const QString &key, const QString &value, MetaDataOverwriteMode mode )
+{
+ QDomNode infoNode = cd_or_create( internalElement(), "info" );
+ infoNode = findOrCreateMetadata( infoNode );
+
+ QDomNode item = cd_or_create( infoNode, key );
+ QDomText text = get_or_create_text( item );
+ if ( mode == DontOverwriteMetaData && !text.data().isEmpty() ) {
+ return;
+ }
+
+ text.setData( value );
+}
+
+void KBookmarkGroupTraverser::traverse(const KBookmarkGroup &root)
+{
+ // non-recursive bookmark iterator
+ QValueStack<KBookmarkGroup> stack;
+ stack.push(root);
+ KBookmark bk = stack.top().first();
+ for (;;) {
+ if (bk.isNull())
+ {
+ if (stack.isEmpty())
+ return;
+ if (stack.count() > 1)
+ visitLeave(stack.top());
+ bk = stack.pop();
+ bk = stack.top().next(bk);
+ if (bk.isNull())
+ continue;
+ }
+
+ if (bk.isGroup())
+ {
+ KBookmarkGroup gp = bk.toGroup();
+ visitEnter(gp);
+ if (!gp.first().isNull())
+ {
+ stack.push(gp);
+ bk = gp.first();
+ continue;
+ }
+ // empty group
+ visitLeave(gp);
+ }
+ else
+ visit(bk);
+
+ bk = stack.top().next(bk);
+ }
+
+ // never reached
+}
+
diff --git a/kio/bookmarks/kbookmark.h b/kio/bookmarks/kbookmark.h
new file mode 100644
index 000000000..9cb9b1fdf
--- /dev/null
+++ b/kio/bookmarks/kbookmark.h
@@ -0,0 +1,329 @@
+// -*- c-basic-offset: 4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef __kbookmark_h
+#define __kbookmark_h
+
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <qdom.h>
+#include <kurl.h>
+
+class KBookmarkManager;
+class KBookmarkGroup;
+
+class KIO_EXPORT KBookmark
+{
+ friend class KBookmarkGroup;
+public:
+ enum MetaDataOverwriteMode {
+ OverwriteMetaData, DontOverwriteMetaData
+ };
+
+ KBookmark( ) {}
+ KBookmark( QDomElement elem ) : element(elem) {}
+
+ static KBookmark standaloneBookmark( const QString & text, const KURL & url, const QString & icon = QString::null );
+
+ /**
+ * Whether the bookmark is a group or a normal bookmark
+ */
+ bool isGroup() const;
+
+ /**
+ * Whether the bookmark is a separator
+ */
+ bool isSeparator() const;
+
+ /**
+ * @return true if this is a null bookmark. This will never
+ * be the case for a real bookmark (in a menu), but it's used
+ * for instance as the end condition for KBookmarkGroup::next()
+ */
+ bool isNull() const {return element.isNull();}
+
+ /**
+ * @return true if bookmark is contained by a QDomDocument,
+ * if not it is most likely that it has become separated and
+ * is thus invalid and/or has been deleted from the bookmarks.
+ * @since 3.2
+ */
+ bool hasParent() const;
+
+ /**
+ * Text shown for the bookmark
+ * If bigger than 40, the text is shortened by
+ * replacing middle characters with "..." (see KStringHandler::csqueeze)
+ */
+ QString text() const;
+ /**
+ * Text shown for the bookmark, not truncated.
+ * You should not use this - this is mainly for keditbookmarks.
+ */
+ QString fullText() const;
+ /**
+ * URL contained by the bookmark
+ */
+ KURL url() const;
+ /**
+ * @return the pixmap file for this bookmark
+ * (i.e. the name of the icon)
+ */
+ QString icon() const;
+
+ /**
+ * @return the group containing this bookmark
+ */
+ KBookmarkGroup parentGroup() const;
+
+ /**
+ * Convert this to a group - do this only if
+ * isGroup() returns true.
+ */
+ KBookmarkGroup toGroup() const;
+
+ /**
+ * Return the "address" of this bookmark in the whole tree.
+ * This is used when telling other processes about a change
+ * in a given bookmark. The encoding of the address is "/4/2", for
+ * instance, to design the 2nd child inside the 4th child of the root bk.
+ */
+ QString address() const;
+
+ // Hard to decide. Good design would imply that each bookmark
+ // knows about its manager, so that there can be several managers.
+ // But if we say there is only one manager (i.e. set of bookmarks)
+ // per application, then KBookmarkManager::self() is much easier.
+ //KBookmarkManager * manager() const { return m_manager; }
+
+ /**
+ * @internal for KEditBookmarks
+ */
+ QDomElement internalElement() const { return element; }
+
+ /**
+ * Updates the bookmarks access metadata
+ * Call when a user accesses the bookmark
+ * @since 3.2
+ */
+ void updateAccessMetadata();
+
+ // Utility functions (internal)
+
+ /**
+ * @return address of parent
+ */
+ static QString parentAddress( const QString & address )
+ { return address.left( address.findRev('/') ); }
+
+ /**
+ * @return position in parent (e.g. /4/5/2 -> 2)
+ */
+ static uint positionInParent( const QString & address )
+ { return address.mid( address.findRev('/') + 1 ).toInt(); }
+
+ /**
+ * @return address of previous sibling (e.g. /4/5/2 -> /4/5/1)
+ * Returns QString::null for a first child
+ */
+ static QString previousAddress( const QString & address )
+ {
+ uint pp = positionInParent(address);
+ return pp>0 ? parentAddress(address) + '/' + QString::number(pp-1) : QString::null;
+ }
+
+ /**
+ * @return address of next sibling (e.g. /4/5/2 -> /4/5/3)
+ * This doesn't check whether it actually exists
+ */
+ static QString nextAddress( const QString & address )
+ { return parentAddress(address) + '/' + QString::number(positionInParent(address)+1); }
+
+ /**
+ * @return the common parent of both addresses which
+ * has the greatest depth
+ * @since 3.5
+ */
+ static QString commonParent(QString A, QString B);
+
+ /**
+ * Get the value of a specific metadata item.
+ * @param key Name of the metadata item
+ * @return Value of the metadata item. QString::null is returned in case
+ * the specified key does not exist.
+ * @since 3.4
+ */
+ QString metaDataItem( const QString &key ) const;
+
+ /**
+ * Change the value of a specific metadata item, or create the given item
+ * if it doesn't exist already.
+ * @param key Name of the metadata item to change
+ * @param value Value to use for the specified metadata item
+ * @param mode Whether to overwrite the item's value if it exists already or not.
+ * @since 3.4
+ */
+ void setMetaDataItem( const QString &key, const QString &value, MetaDataOverwriteMode mode = OverwriteMetaData );
+
+protected:
+ QDomElement element;
+ // Note: you can't add new member variables here.
+ // The KBookmarks are created on the fly, as wrappers
+ // around internal QDomElements. Any additional information
+ // has to be implemented as an attribute of the QDomElement.
+
+private:
+ bool hasMetaData() const;
+ static QString left(const QString & str, uint len);
+};
+
+/**
+ * A group of bookmarks
+ */
+class KIO_EXPORT KBookmarkGroup : public KBookmark
+{
+public:
+ /**
+ * Create an invalid group. This is mostly for use in QValueList,
+ * and other places where we need a null group.
+ * Also used as a parent for a bookmark that doesn't have one
+ * (e.g. Netscape bookmarks)
+ */
+ KBookmarkGroup();
+
+ /**
+ * Create a bookmark group as specified by the given element
+ */
+ KBookmarkGroup( QDomElement elem );
+
+ /**
+ * Much like KBookmark::address, but caches the
+ * address into m_address.
+ */
+ QString groupAddress() const;
+
+ /**
+ * @return true if the bookmark folder is opened in the bookmark editor
+ */
+ bool isOpen() const;
+
+ /**
+ * Return the first child bookmark of this group
+ */
+ KBookmark first() const;
+ /**
+ * Return the prevous sibling of a child bookmark of this group
+ * @param current has to be one of our child bookmarks.
+ */
+ KBookmark previous( const KBookmark & current ) const;
+ /**
+ * Return the next sibling of a child bookmark of this group
+ * @param current has to be one of our child bookmarks.
+ */
+ KBookmark next( const KBookmark & current ) const;
+
+ /**
+ * Create a new bookmark folder, as the last child of this group
+ * @param mgr the manager of the bookmark
+ * @param text for the folder. If empty, the user will be queried for it.
+ * @param emitSignal if true emit KBookmarkNotifier signal
+ */
+ KBookmarkGroup createNewFolder( KBookmarkManager* mgr, const QString & text = QString::null, bool emitSignal = true );
+ /**
+ * Create a new bookmark separator
+ * Don't forget to use KBookmarkManager::self()->emitChanged( parentBookmark );
+ */
+ KBookmark createNewSeparator();
+
+ /**
+ * Create a new bookmark, as the last child of this group
+ * Don't forget to use KBookmarkManager::self()->emitChanged( parentBookmark );
+ * @param mgr the manager of the bookmark
+ * @param bm the bookmark to add
+ * @param emitSignal if true emit KBookmarkNotifier signal
+ * @since 3.4
+ */
+ KBookmark addBookmark( KBookmarkManager* mgr, const KBookmark &bm, bool emitSignal = true );
+
+ /**
+ * Create a new bookmark, as the last child of this group
+ * Don't forget to use KBookmarkManager::self()->emitChanged( parentBookmark );
+ * @param mgr the manager of the bookmark
+ * @param text for the bookmark
+ * @param url the URL that the bookmark points to
+ * @param icon the name of the icon to associate with the bookmark. A suitable default
+ * will be determined from the URL if not specified.
+ * @param emitSignal if true emit KBookmarkNotifier signal
+ */
+ KBookmark addBookmark( KBookmarkManager* mgr, const QString & text, const KURL & url, const QString & icon = QString::null, bool emitSignal = true );
+
+ /**
+ * Moves @p item after @p after (which should be a child of ours).
+ * If item is null, @p item is moved as the first child.
+ * Don't forget to use KBookmarkManager::self()->emitChanged( parentBookmark );
+ */
+ bool moveItem( const KBookmark & item, const KBookmark & after );
+
+ /**
+ * Delete a bookmark - it has to be one of our children !
+ * Don't forget to use KBookmarkManager::self()->emitChanged( parentBookmark );
+ */
+ void deleteBookmark( KBookmark bk );
+
+ /**
+ * @return true if this is the toolbar group
+ */
+ bool isToolbarGroup() const;
+ /**
+ * @internal
+ */
+ QDomElement findToolbar() const;
+
+ /**
+ * @return the list of urls of bookmarks at top level of the group
+ * @since 3.2
+ */
+ QValueList<KURL> groupUrlList() const;
+
+protected:
+ QDomElement nextKnownTag( QDomElement start, bool goNext ) const;
+
+private:
+ mutable QString m_address;
+ // Note: you can't add other member variables here, except for caching info.
+ // The KBookmarks are created on the fly, as wrappers
+ // around internal QDomElements. Any additional information
+ // has to be implemented as an attribute of the QDomElement.
+};
+
+/**
+ * @since 3.2
+ */
+class KIO_EXPORT KBookmarkGroupTraverser {
+protected:
+ virtual ~KBookmarkGroupTraverser() { ; }
+ void traverse(const KBookmarkGroup &);
+ virtual void visit(const KBookmark &) { ; }
+ virtual void visitEnter(const KBookmarkGroup &) { ; }
+ virtual void visitLeave(const KBookmarkGroup &) { ; }
+private:
+ class KBookmarkGroupTraverserPrivate *d;
+};
+
+#endif
diff --git a/kio/bookmarks/kbookmarkbar.cc b/kio/bookmarks/kbookmarkbar.cc
new file mode 100644
index 000000000..d71069014
--- /dev/null
+++ b/kio/bookmarks/kbookmarkbar.cc
@@ -0,0 +1,554 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE project
+ Copyright (C) 1999 Kurt Granroth <granroth@kde.org>
+ Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include <qregexp.h>
+#include <qfile.h>
+
+#include <kbookmarkbar.h>
+#include <kbookmarkdrag.h>
+
+#include <kbookmarkmenu.h>
+#include <kdebug.h>
+
+#include <ktoolbar.h>
+#include <ktoolbarbutton.h>
+
+#include <kconfig.h>
+#include <kpopupmenu.h>
+
+#include "kbookmarkdrag.h"
+#include "kbookmarkmenu_p.h"
+#include "kbookmarkdombuilder.h"
+
+#include "dptrtemplate.h"
+
+#include <qapplication.h>
+
+class KBookmarkBarPrivate : public dPtrTemplate<KBookmarkBar, KBookmarkBarPrivate>
+{
+public:
+ QPtrList<KAction> m_actions;
+ bool m_readOnly;
+ KBookmarkManager* m_filteredMgr;
+ KToolBar* m_sepToolBar;
+ int m_sepIndex;
+ bool m_atFirst;
+ QString m_dropAddress;
+ QString m_highlightedAddress;
+public:
+ KBookmarkBarPrivate() {
+ m_readOnly = false;
+ m_filteredMgr = 0;
+ m_sepToolBar = 0;
+ m_sepIndex = -1;
+ m_atFirst = false;
+ }
+};
+template<> QPtrDict<KBookmarkBarPrivate>* dPtrTemplate<KBookmarkBar, KBookmarkBarPrivate>::d_ptr = 0;
+
+KBookmarkBarPrivate* KBookmarkBar::dptr() const
+{
+ return KBookmarkBarPrivate::d( this );
+}
+
+// usage of KXBELBookmarkImporterImpl is just plain evil, but it reduces code dup. so...
+class ToolbarFilter : public KXBELBookmarkImporterImpl
+{
+public:
+ ToolbarFilter() : m_visible(false) { ; }
+ void filter( const KBookmarkGroup &grp ) { traverse(grp); }
+private:
+ virtual void visit( const KBookmark & );
+ virtual void visitEnter( const KBookmarkGroup & );
+ virtual void visitLeave( const KBookmarkGroup & );
+private:
+ bool m_visible;
+ KBookmarkGroup m_visibleStart;
+};
+
+KBookmarkBar::KBookmarkBar( KBookmarkManager* mgr,
+ KBookmarkOwner *_owner, KToolBar *_toolBar,
+ KActionCollection *coll,
+ QObject *parent, const char *name )
+ : QObject( parent, name ), m_pOwner(_owner), m_toolBar(_toolBar),
+ m_actionCollection( coll ), m_pManager(mgr)
+{
+ m_lstSubMenus.setAutoDelete( true );
+
+ m_toolBar->setAcceptDrops( true );
+ m_toolBar->installEventFilter( this ); // for drops
+
+ dptr()->m_actions.setAutoDelete( true );
+
+ connect( mgr, SIGNAL( changed(const QString &, const QString &) ),
+ SLOT( slotBookmarksChanged(const QString &) ) );
+
+ KBookmarkGroup toolbar = getToolbar();
+ fillBookmarkBar( toolbar );
+}
+
+QString KBookmarkBar::parentAddress()
+{
+ return dptr()->m_filteredMgr ? QString::null : m_pManager->toolbar().address();
+}
+
+#define CURRENT_TOOLBAR() ( \
+ dptr()->m_filteredMgr ? dptr()->m_filteredMgr->root() \
+ : m_pManager->toolbar() )
+
+#define CURRENT_MANAGER() ( \
+ dptr()->m_filteredMgr ? dptr()->m_filteredMgr \
+ : m_pManager )
+
+KBookmarkGroup KBookmarkBar::getToolbar()
+{
+ if ( KBookmarkSettings::self()->m_filteredtoolbar )
+ {
+ if ( !dptr()->m_filteredMgr ) {
+ dptr()->m_filteredMgr = KBookmarkManager::createTempManager();
+ } else {
+ KBookmarkGroup bkRoot = dptr()->m_filteredMgr->root();
+ QValueList<KBookmark> bks;
+ for (KBookmark bm = bkRoot.first(); !bm.isNull(); bm = bkRoot.next(bm))
+ bks << bm;
+ for ( QValueListConstIterator<KBookmark> it = bks.begin(); it != bks.end(); ++it )
+ bkRoot.deleteBookmark( (*it) );
+ }
+ ToolbarFilter filter;
+ KBookmarkDomBuilder builder( dptr()->m_filteredMgr->root(),
+ dptr()->m_filteredMgr );
+ builder.connectImporter( &filter );
+ filter.filter( m_pManager->root() );
+ }
+
+ return CURRENT_TOOLBAR();
+}
+
+KBookmarkBar::~KBookmarkBar()
+{
+ //clear();
+ KBookmarkBarPrivate::delete_d(this);
+}
+
+void KBookmarkBar::clear()
+{
+ QPtrListIterator<KAction> it( dptr()->m_actions );
+ m_toolBar->clear();
+ for (; it.current(); ++it ) {
+ (*it)->unplugAll();
+ }
+ dptr()->m_actions.clear();
+ m_lstSubMenus.clear();
+}
+
+void KBookmarkBar::slotBookmarksChanged( const QString & group )
+{
+ KBookmarkGroup tb = getToolbar(); // heavy for non cached toolbar version
+ kdDebug(7043) << "slotBookmarksChanged( " << group << " )" << endl;
+
+ if ( tb.isNull() )
+ return;
+
+ if ( KBookmark::commonParent(group, tb.address()) == group // Is group a parent of tb.address?
+ || KBookmarkSettings::self()->m_filteredtoolbar )
+ {
+ clear();
+ fillBookmarkBar( tb );
+ }
+ else
+ {
+ // Iterate recursively into child menus
+ QPtrListIterator<KBookmarkMenu> it( m_lstSubMenus );
+ for (; it.current(); ++it )
+ {
+ it.current()->slotBookmarksChanged( group );
+ }
+ }
+}
+
+void KBookmarkBar::fillBookmarkBar(KBookmarkGroup & parent)
+{
+ if (parent.isNull())
+ return;
+
+ for (KBookmark bm = parent.first(); !bm.isNull(); bm = parent.next(bm))
+ {
+ QString text = bm.text();
+ text.replace( '&', "&&" );
+ if (!bm.isGroup())
+ {
+ if ( bm.isSeparator() )
+ m_toolBar->insertLineSeparator();
+ else
+ {
+ KAction *action = new KBookmarkAction( text, bm.icon(), 0, m_actionCollection, 0 );
+ connect(action, SIGNAL( activated ( KAction::ActivationReason, Qt::ButtonState )),
+ this, SLOT( slotBookmarkSelected( KAction::ActivationReason, Qt::ButtonState ) ));
+
+ action->setProperty( "url", bm.url().url() );
+ action->setProperty( "address", bm.address() );
+
+ action->setToolTip( bm.url().pathOrURL() );
+
+ action->plug(m_toolBar);
+
+ dptr()->m_actions.append( action );
+ }
+ }
+ else
+ {
+ KActionMenu *action = new KBookmarkActionMenu( text, bm.icon(),
+ m_actionCollection,
+ "bookmarkbar-actionmenu");
+ action->setProperty( "address", bm.address() );
+ action->setProperty( "readOnly", dptr()->m_readOnly );
+ action->setDelayed( false );
+
+ // this flag doesn't have any UI yet
+ KGlobal::config()->setGroup( "Settings" );
+ bool addEntriesBookmarkBar = KGlobal::config()->readBoolEntry("AddEntriesBookmarkBar",true);
+
+ KBookmarkMenu *menu = new KBookmarkMenu(CURRENT_MANAGER(), m_pOwner, action->popupMenu(),
+ m_actionCollection, false, addEntriesBookmarkBar,
+ bm.address());
+ connect(menu, SIGNAL( aboutToShowContextMenu(const KBookmark &, QPopupMenu * ) ),
+ this, SIGNAL( aboutToShowContextMenu(const KBookmark &, QPopupMenu * ) ));
+ connect(menu, SIGNAL( openBookmark( const QString &, Qt::ButtonState) ),
+ this, SIGNAL( openBookmark( const QString &, Qt::ButtonState) ));
+ menu->fillBookmarkMenu();
+ action->plug(m_toolBar);
+ m_lstSubMenus.append( menu );
+
+ dptr()->m_actions.append( action );
+ }
+ }
+}
+
+void KBookmarkBar::setReadOnly(bool readOnly)
+{
+ dptr()->m_readOnly = readOnly;
+}
+
+bool KBookmarkBar::isReadOnly() const
+{
+ return dptr()->m_readOnly;
+}
+
+void KBookmarkBar::slotBookmarkSelected( KAction::ActivationReason /*reason*/, Qt::ButtonState state )
+{
+ if (!m_pOwner) return; // this view doesn't handle bookmarks...
+
+ const KAction* action = dynamic_cast<const KAction *>(sender());
+ if(action)
+ {
+ const QString & url = sender()->property("url").toString();
+ m_pOwner->openBookmarkURL(url);
+ emit openBookmark( url, state );
+ }
+}
+
+void KBookmarkBar::slotBookmarkSelected()
+{
+ slotBookmarkSelected(KAction::ToolBarActivation, Qt::NoButton);
+}
+
+static const int const_sepId = -9999; // FIXME this is ugly,
+ // surely there is another
+ // way of doing this...
+
+static void removeTempSep(KBookmarkBarPrivate* p)
+{
+ if (p->m_sepToolBar) {
+ p->m_sepToolBar->removeItem(const_sepId);
+ p->m_sepToolBar = 0; // needed?
+ }
+}
+
+static KAction* findPluggedAction(QPtrList<KAction> actions, KToolBar *tb, int id)
+{
+ QPtrListIterator<KAction> it( actions );
+ for (; (*it); ++it )
+ if ((*it)->isPlugged(tb, id))
+ return (*it);
+ return 0;
+}
+
+/**
+ * Handle a QDragMoveEvent event on a toolbar drop
+ * @return the address of the bookmark to be dropped after/before
+ * else a QString::null if event should be ignored
+ * @param pos the current QDragMoveEvent position
+ * @param the toolbar
+ * @param actions the list of actions plugged into the bar
+ * @param atFirst bool reference, when true the position before the
+ * returned action was dropped on
+ */
+static QString handleToolbarDragMoveEvent(
+ KBookmarkBarPrivate *p, KToolBar *tb, QPoint pos, QPtrList<KAction> actions,
+ bool &atFirst, KBookmarkManager *mgr
+) {
+ Q_UNUSED( mgr );
+ Q_ASSERT( actions.isEmpty() || (tb == dynamic_cast<KToolBar*>(actions.first()->container(0))) );
+ p->m_sepToolBar = tb;
+ p->m_sepToolBar->removeItemDelayed(const_sepId);
+
+ int index = 0;
+ KToolBarButton* b;
+
+ b = dynamic_cast<KToolBarButton*>(tb->childAt(pos));
+ KAction *a = 0;
+ QString address;
+ atFirst = false;
+
+ if (b)
+ {
+ index = tb->itemIndex(b->id());
+ QRect r = b->geometry();
+ if (pos.x() < ((r.left() + r.right())/2))
+ {
+ // if in first half of button then
+ // we jump to previous index
+ if ( index == 0 )
+ atFirst = true;
+ else {
+ index--;
+ b = tb->getButton(tb->idAt(index));
+ }
+ }
+ }
+ else if (actions.isEmpty())
+ {
+ atFirst = true;
+ index = 0;
+ // we skip the action related stuff
+ // and do what it should have...
+ // FIXME - here we want to get the
+ // parent address of the bookmark
+ // bar itself and return that + "/0"
+ p->m_sepIndex = 0;
+ goto skipact;
+ }
+ else // (!b)
+ {
+ index = actions.count() - 1;
+ b = tb->getButton(tb->idAt(index));
+ // if !b and not past last button, we didn't find button
+ if (pos.x() <= b->geometry().left())
+ goto skipact; // TODO - rename
+ }
+
+ if ( !b )
+ return QString::null; // TODO Make it works for that case
+
+ a = findPluggedAction(actions, tb, b->id());
+ Q_ASSERT(a);
+ address = a->property("address").toString();
+ p->m_sepIndex = index + (atFirst ? 0 : 1);
+
+#if 0
+ { // ugly workaround to fix the goto scoping problems...
+ KBookmark bk = mgr->findByAddress( address );
+ if (bk.isGroup()) // TODO - fix this ****!!!, manhatten distance should be used!!!
+ {
+ kdDebug() << "kbookmarkbar:: popping up " << bk.text() << endl;
+ KBookmarkActionMenu *menu = dynamic_cast<KBookmarkActionMenu*>(a);
+ Q_ASSERT(menu);
+ menu->popup(tb->mapToGlobal(b->geometry().center()));
+ }
+ }
+#endif
+
+skipact:
+ tb->insertLineSeparator(p->m_sepIndex, const_sepId);
+ return address;
+}
+
+// TODO - document!!!!
+static KAction* handleToolbarMouseButton(QPoint pos, QPtrList<KAction> actions,
+ KBookmarkManager * /*mgr*/, QPoint & pt)
+{
+ KAction *act = actions.first();
+ if (!act) {
+ return 0;
+ }
+
+ KToolBar *tb = dynamic_cast<KToolBar*>(act->container(0));
+ Q_ASSERT(tb);
+
+ KToolBarButton *b;
+ b = dynamic_cast<KToolBarButton*>(tb->childAt(pos));
+ if (!b)
+ return 0;
+
+ KAction *a = 0;
+ a = findPluggedAction(actions, tb, b->id());
+ Q_ASSERT(a);
+ pt = tb->mapToGlobal(pos);
+
+ return a;
+}
+
+// TODO *** drop improvements ***
+// open submenus on drop interactions
+
+// TODO *** generic rmb improvements ***
+// don't *ever* show the rmb on press, always relase, possible???
+
+class KBookmarkBarRMBAssoc : public dPtrTemplate<KBookmarkBar, RMB> { };
+template<> QPtrDict<RMB>* dPtrTemplate<KBookmarkBar, RMB>::d_ptr = 0;
+
+static RMB* rmbSelf(KBookmarkBar *m) { return KBookmarkBarRMBAssoc::d(m); }
+
+void RMB::begin_rmb_action(KBookmarkBar *self)
+{
+ RMB *s = rmbSelf(self);
+ s->recv = self;
+ s->m_parentAddress = self->parentAddress();
+ s->s_highlightedAddress = self->dptr()->m_highlightedAddress; // rename in RMB
+ s->m_pManager = self->m_pManager;
+ s->m_pOwner = self->m_pOwner;
+ s->m_parentMenu = 0;
+}
+
+void KBookmarkBar::slotRMBActionEditAt( int val )
+{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionEditAt( val ); }
+
+void KBookmarkBar::slotRMBActionProperties( int val )
+{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionProperties( val ); }
+
+void KBookmarkBar::slotRMBActionInsert( int val )
+{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionInsert( val ); }
+
+void KBookmarkBar::slotRMBActionRemove( int val )
+{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionRemove( val ); }
+
+void KBookmarkBar::slotRMBActionCopyLocation( int val )
+{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionCopyLocation( val ); }
+
+bool KBookmarkBar::eventFilter( QObject *o, QEvent *e )
+{
+ if (dptr()->m_readOnly || dptr()->m_filteredMgr) // note, we assume m_pManager in various places,
+ // this shouldn't really be the case
+ return false; // todo: make this limit the actions
+
+ if ( (e->type() == QEvent::MouseButtonRelease) || (e->type() == QEvent::MouseButtonPress) ) // FIXME, which one?
+ {
+ QMouseEvent *mev = (QMouseEvent*)e;
+
+ QPoint pt;
+ KAction *_a;
+
+ // FIXME, see how this holds up on an empty toolbar
+ _a = handleToolbarMouseButton( mev->pos(), dptr()->m_actions, m_pManager, pt );
+ if (_a && mev->button() == Qt::RightButton)
+ {
+ dptr()->m_highlightedAddress = _a->property("address").toString();
+ KBookmark bookmark = m_pManager->findByAddress( dptr()->m_highlightedAddress );
+ RMB::begin_rmb_action(this);
+ KPopupMenu *pm = new KPopupMenu;
+ rmbSelf(this)->fillContextMenu( pm, dptr()->m_highlightedAddress, 0 );
+ emit aboutToShowContextMenu( rmbSelf(this)->atAddress( dptr()->m_highlightedAddress ), pm );
+ rmbSelf(this)->fillContextMenu2( pm, dptr()->m_highlightedAddress, 0 );
+ pm->popup( pt );
+ mev->accept();
+ }
+
+ return !!_a; // ignore the event if we didn't find the button
+ }
+ else if ( e->type() == QEvent::DragLeave )
+ {
+ removeTempSep(dptr());
+ dptr()->m_dropAddress = QString::null;
+ }
+ else if ( e->type() == QEvent::Drop )
+ {
+ removeTempSep(dptr());
+ QDropEvent *dev = (QDropEvent*)e;
+ if ( !KBookmarkDrag::canDecode( dev ) )
+ return false;
+ QValueList<KBookmark> list = KBookmarkDrag::decode( dev );
+ if (list.count() > 1)
+ kdWarning(7043) << "Sorry, currently you can only drop one address "
+ "onto the bookmark bar!" << endl;
+ KBookmark toInsert = list.first();
+ KBookmark bookmark = m_pManager->findByAddress( dptr()->m_dropAddress );
+ Q_ASSERT(!bookmark.isNull());
+ kdDebug(7043) << "inserting "
+ << QString(dptr()->m_atFirst ? "before" : "after")
+ << " dptr()->m_dropAddress == " << dptr()->m_dropAddress << endl;
+ KBookmarkGroup parentBookmark = bookmark.parentGroup();
+ Q_ASSERT(!parentBookmark.isNull());
+ KBookmark newBookmark = parentBookmark.addBookmark(
+ m_pManager, toInsert.fullText(),
+ toInsert.url() );
+ parentBookmark.moveItem( newBookmark, dptr()->m_atFirst ? KBookmark() : bookmark );
+ m_pManager->emitChanged( parentBookmark );
+ return true;
+ }
+ else if ( e->type() == QEvent::DragMove )
+ {
+ QDragMoveEvent *dme = (QDragMoveEvent*)e;
+ if (!KBookmarkDrag::canDecode( dme ))
+ return false;
+ bool _atFirst;
+ QString dropAddress;
+ KToolBar *tb = (KToolBar*)o;
+ dropAddress = handleToolbarDragMoveEvent(dptr(), tb, dme->pos(), dptr()->m_actions, _atFirst, m_pManager);
+ if (!dropAddress.isNull())
+ {
+ dptr()->m_dropAddress = dropAddress;
+ dptr()->m_atFirst = _atFirst;
+ dme->accept();
+ }
+ }
+ return false;
+}
+
+static bool showInToolbar( const KBookmark &bk ) {
+ return (bk.internalElement().attributes().namedItem("showintoolbar").toAttr().value() == "yes");
+}
+
+void ToolbarFilter::visit( const KBookmark &bk ) {
+ //kdDebug() << "visit(" << bk.text() << ")" << endl;
+ if ( m_visible || showInToolbar(bk) )
+ KXBELBookmarkImporterImpl::visit(bk);
+}
+
+void ToolbarFilter::visitEnter( const KBookmarkGroup &grp ) {
+ //kdDebug() << "visitEnter(" << grp.text() << ")" << endl;
+ if ( !m_visible && showInToolbar(grp) )
+ {
+ m_visibleStart = grp;
+ m_visible = true;
+ }
+ if ( m_visible )
+ KXBELBookmarkImporterImpl::visitEnter(grp);
+}
+
+void ToolbarFilter::visitLeave( const KBookmarkGroup &grp ) {
+ //kdDebug() << "visitLeave()" << endl;
+ if ( m_visible )
+ KXBELBookmarkImporterImpl::visitLeave(grp);
+ if ( m_visible && grp.address() == m_visibleStart.address() )
+ m_visible = false;
+}
+
+#include "kbookmarkbar.moc"
diff --git a/kio/bookmarks/kbookmarkbar.h b/kio/bookmarks/kbookmarkbar.h
new file mode 100644
index 000000000..162d045bb
--- /dev/null
+++ b/kio/bookmarks/kbookmarkbar.h
@@ -0,0 +1,130 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE project
+ Copyright (C) 1999 Kurt Granroth <granroth@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KBOOKMARKBAR_H
+#define KBOOKMARKBAR_H
+
+#include <qobject.h>
+#include <qguardedptr.h>
+#include <qptrlist.h>
+#include <kbookmark.h>
+#include <kaction.h>
+
+class KToolBar;
+class KBookmarkMenu;
+class KBookmarkOwner;
+class KActionCollection;
+class KAction;
+class QPopupMenu;
+
+/**
+ * This class provides a bookmark toolbar. Using this class is nearly
+ * identical to using KBookmarkMenu so follow the directions
+ * there.
+ */
+class KIO_EXPORT KBookmarkBar : public QObject
+{
+ Q_OBJECT
+ friend class RMB;
+public:
+ /**
+ * Fills a bookmark toolbar
+ *
+ * @param manager the bookmark manager
+ * @param owner implementation of the KBookmarkOwner interface (callbacks)
+ * @param toolBar toolbar to fill
+ *
+ * The KActionCollection pointer argument is now obsolete.
+ *
+ * @param parent the parent widget for the bookmark toolbar
+ * @param name the internal name for the bookmark toolbar
+ */
+ KBookmarkBar( KBookmarkManager* manager,
+ KBookmarkOwner *owner, KToolBar *toolBar,
+ KActionCollection *,
+ QObject *parent = 0L, const char *name = 0L);
+
+ virtual ~KBookmarkBar();
+
+ /**
+ * @since 3.2
+ */
+ bool isReadOnly() const;
+
+ /**
+ * @since 3.2
+ */
+ void setReadOnly(bool);
+
+ /**
+ * @since 3.2
+ */
+ QString parentAddress();
+
+signals:
+ /**
+ * @since 3.2
+ */
+ void aboutToShowContextMenu( const KBookmark &, QPopupMenu * );
+ /**
+ * @since 3.4
+ */
+ void openBookmark( const QString& url, Qt::ButtonState state );
+
+public slots:
+ void clear();
+
+ void slotBookmarksChanged( const QString & );
+ void slotBookmarkSelected();
+
+ /**
+ * @since 3.4
+ */
+ void slotBookmarkSelected( KAction::ActivationReason reason, Qt::ButtonState state );
+
+ /// @since 3.2
+ void slotRMBActionRemove( int );
+ /// @since 3.2
+ void slotRMBActionInsert( int );
+ /// @since 3.2
+ void slotRMBActionCopyLocation( int );
+ /// @since 3.2
+ void slotRMBActionEditAt( int );
+ /// @since 3.2
+ void slotRMBActionProperties( int );
+
+protected:
+ void fillBookmarkBar( KBookmarkGroup & parent );
+ virtual bool eventFilter( QObject *o, QEvent *e );
+
+private:
+ KBookmarkGroup getToolbar();
+
+ KBookmarkOwner *m_pOwner;
+ QGuardedPtr<KToolBar> m_toolBar;
+ KActionCollection *m_actionCollection;
+ KBookmarkManager *m_pManager;
+ QPtrList<KBookmarkMenu> m_lstSubMenus;
+
+private:
+ class KBookmarkBarPrivate* dptr() const;
+};
+
+#endif // KBOOKMARKBAR_H
diff --git a/kio/bookmarks/kbookmarkdombuilder.cc b/kio/bookmarks/kbookmarkdombuilder.cc
new file mode 100644
index 000000000..7b6bad4e6
--- /dev/null
+++ b/kio/bookmarks/kbookmarkdombuilder.cc
@@ -0,0 +1,81 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 David Faure <faure@kde.org>
+ Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kbookmarkmanager.h>
+#include <kdebug.h>
+
+#include "kbookmarkdombuilder.h"
+
+KBookmarkDomBuilder::KBookmarkDomBuilder(
+ const KBookmarkGroup &bkGroup, KBookmarkManager *manager
+) {
+ m_manager = manager;
+ m_stack.push(bkGroup);
+}
+
+KBookmarkDomBuilder::~KBookmarkDomBuilder() {
+ m_list.clear();
+ m_stack.clear();
+}
+
+void KBookmarkDomBuilder::connectImporter(const QObject *importer) {
+ connect(importer, SIGNAL( newBookmark(const QString &, const QCString &, const QString &) ),
+ SLOT( newBookmark(const QString &, const QCString &, const QString &) ));
+ connect(importer, SIGNAL( newFolder(const QString &, bool, const QString &) ),
+ SLOT( newFolder(const QString &, bool, const QString &) ));
+ connect(importer, SIGNAL( newSeparator() ),
+ SLOT( newSeparator() ) );
+ connect(importer, SIGNAL( endFolder() ),
+ SLOT( endFolder() ) );
+}
+
+void KBookmarkDomBuilder::newBookmark(
+ const QString &text, const QCString &url, const QString &additionalInfo
+) {
+ KBookmark bk = m_stack.top().addBookmark(
+ m_manager, text,
+ KURL( QString::fromUtf8(url), 106 /*utf8*/ ),
+ QString::null, false);
+ // store additional info
+ bk.internalElement().setAttribute("netscapeinfo", additionalInfo);
+}
+
+void KBookmarkDomBuilder::newFolder(
+ const QString & text, bool open, const QString & additionalInfo
+) {
+ // we use a qvaluelist so that we keep pointers to valid objects in the stack
+ KBookmarkGroup gp = m_stack.top().createNewFolder(m_manager, text, false);
+ m_list.append(gp);
+ m_stack.push(m_list.last());
+ // store additional info
+ QDomElement element = m_list.last().internalElement();
+ element.setAttribute("netscapeinfo", additionalInfo);
+ element.setAttribute("folded", (open?"no":"yes"));
+}
+
+void KBookmarkDomBuilder::newSeparator() {
+ m_stack.top().createNewSeparator();
+}
+
+void KBookmarkDomBuilder::endFolder() {
+ m_stack.pop();
+}
+
+#include "kbookmarkdombuilder.moc"
diff --git a/kio/bookmarks/kbookmarkdombuilder.h b/kio/bookmarks/kbookmarkdombuilder.h
new file mode 100644
index 000000000..f570525f6
--- /dev/null
+++ b/kio/bookmarks/kbookmarkdombuilder.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kbookmarkdombuilder_h
+#define __kbookmarkdombuilder_h
+
+#include <qvaluestack.h>
+#include <qobject.h>
+#include <kbookmark.h>
+
+/**
+ * @since 3.2
+ */
+class KIO_EXPORT KBookmarkDomBuilder : public QObject {
+ Q_OBJECT
+public:
+ KBookmarkDomBuilder(const KBookmarkGroup &group, KBookmarkManager *);
+ virtual ~KBookmarkDomBuilder();
+ void connectImporter(const QObject *);
+protected slots:
+ void newBookmark(const QString &text, const QCString &url, const QString &additionalInfo);
+ void newFolder(const QString &text, bool open, const QString &additionalInfo);
+ void newSeparator();
+ void endFolder();
+private:
+ QValueStack<KBookmarkGroup> m_stack;
+ QValueList<KBookmarkGroup> m_list;
+ KBookmarkManager *m_manager;
+ class KBookmarkDomBuilderPrivate *p;
+};
+
+#endif
diff --git a/kio/bookmarks/kbookmarkdrag.cc b/kio/bookmarks/kbookmarkdrag.cc
new file mode 100644
index 000000000..3e1db9c15
--- /dev/null
+++ b/kio/bookmarks/kbookmarkdrag.cc
@@ -0,0 +1,169 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kbookmarkdrag.h"
+#include <kurldrag.h>
+#include <kdebug.h>
+
+KBookmarkDrag * KBookmarkDrag::newDrag( const QValueList<KBookmark> & bookmarks, QWidget * dragSource, const char * name )
+{
+ KURL::List urls;
+
+ for ( QValueListConstIterator<KBookmark> it = bookmarks.begin(); it != bookmarks.end(); ++it ) {
+ urls.append( (*it).url() );
+ }
+
+ // See KURLDrag::newDrag
+ QStrList uris;
+ KURL::List::ConstIterator uit = urls.begin();
+ KURL::List::ConstIterator uEnd = urls.end();
+ // Get each URL encoded in utf8 - and since we get it in escaped
+ // form on top of that, .latin1() is fine.
+ for ( ; uit != uEnd ; ++uit )
+ uris.append( KURLDrag::urlToString(*uit).latin1() );
+
+ return new KBookmarkDrag( bookmarks, uris, dragSource, name );
+}
+
+KBookmarkDrag * KBookmarkDrag::newDrag( const KBookmark & bookmark, QWidget * dragSource, const char * name )
+{
+ QValueList<KBookmark> bookmarks;
+ bookmarks.append( KBookmark(bookmark) );
+ return newDrag(bookmarks, dragSource, name);
+}
+
+KBookmarkDrag::KBookmarkDrag( const QValueList<KBookmark> & bookmarks, const QStrList & urls,
+ QWidget * dragSource, const char * name )
+ : QUriDrag( urls, dragSource, name ), m_bookmarks( bookmarks ), m_doc("xbel")
+{
+ // We need to create the XML for this drag right now and not
+ // in encodedData because when cutting a folder, the children
+ // wouldn't be part of the bookmarks anymore, when encodedData
+ // is requested.
+ QDomElement elem = m_doc.createElement("xbel");
+ m_doc.appendChild( elem );
+ for ( QValueListConstIterator<KBookmark> it = bookmarks.begin(); it != bookmarks.end(); ++it ) {
+ elem.appendChild( (*it).internalElement().cloneNode( true /* deep */ ) );
+ }
+ //kdDebug(7043) << "KBookmarkDrag::KBookmarkDrag " << m_doc.toString() << endl;
+}
+
+const char* KBookmarkDrag::format( int i ) const
+{
+ if ( i == 0 )
+ return "application/x-xbel";
+ else if ( i == 1 )
+ return "text/uri-list";
+ else if ( i == 2 )
+ return "text/plain";
+ else return 0;
+}
+
+QByteArray KBookmarkDrag::encodedData( const char* mime ) const
+{
+ QByteArray a;
+ QCString mimetype( mime );
+ if ( mimetype == "text/uri-list" )
+ return QUriDrag::encodedData( mime );
+ else if ( mimetype == "application/x-xbel" )
+ {
+ a = m_doc.toCString();
+ //kdDebug(7043) << "KBookmarkDrag::encodedData " << m_doc.toCString() << endl;
+ }
+ else if ( mimetype == "text/plain" )
+ {
+ KURL::List m_lstDragURLs;
+ if ( KURLDrag::decode( this, m_lstDragURLs ) )
+ {
+ QStringList uris;
+ KURL::List::ConstIterator uit = m_lstDragURLs.begin();
+ KURL::List::ConstIterator uEnd = m_lstDragURLs.end();
+ for ( ; uit != uEnd ; ++uit )
+ uris.append( (*uit).prettyURL() );
+
+ QCString s = uris.join( "\n" ).local8Bit();
+ a.resize( s.length() + 1 ); // trailing zero
+ memcpy( a.data(), s.data(), s.length() + 1 );
+ }
+ }
+ return a;
+}
+
+bool KBookmarkDrag::canDecode( const QMimeSource * e )
+{
+ return e->provides("text/uri-list") || e->provides("application/x-xbel") ||
+ e->provides("text/plain");
+}
+
+QValueList<KBookmark> KBookmarkDrag::decode( const QMimeSource * e )
+{
+ QValueList<KBookmark> bookmarks;
+ if ( e->provides("application/x-xbel") )
+ {
+ QByteArray s( e->encodedData("application/x-xbel") );
+ //kdDebug(7043) << "KBookmarkDrag::decode s=" << QCString(s) << endl;
+ QDomDocument doc;
+ doc.setContent( s );
+ QDomElement elem = doc.documentElement();
+ QDomNodeList children = elem.childNodes();
+ for ( uint childno = 0; childno < children.count(); childno++)
+ {
+ bookmarks.append( KBookmark( children.item(childno).cloneNode(true).toElement() ));
+ }
+ return bookmarks;
+ }
+ if ( e->provides("text/uri-list") )
+ {
+ KURL::List m_lstDragURLs;
+ //kdDebug(7043) << "KBookmarkDrag::decode uri-list" << endl;
+ if ( KURLDrag::decode( e, m_lstDragURLs ) )
+ {
+ KURL::List::ConstIterator uit = m_lstDragURLs.begin();
+ KURL::List::ConstIterator uEnd = m_lstDragURLs.end();
+ for ( ; uit != uEnd ; ++uit )
+ {
+ //kdDebug(7043) << "KBookmarkDrag::decode url=" << (*uit).url() << endl;
+ bookmarks.append( KBookmark::standaloneBookmark(
+ (*uit).prettyURL(), (*uit) ));
+ }
+ return bookmarks;
+ }
+ }
+ if( e->provides("text/plain") )
+ {
+ //kdDebug(7043) << "KBookmarkDrag::decode text/plain" << endl;
+ QString s;
+ if(QTextDrag::decode( e, s ))
+ {
+
+ QStringList listDragURLs = QStringList::split(QChar('\n'), s);
+ QStringList::ConstIterator it = listDragURLs.begin();
+ QStringList::ConstIterator end = listDragURLs.end();
+ for( ; it!=end; ++it)
+ {
+ //kdDebug(7043)<<"KBookmarkDrag::decode string"<<(*it)<<endl;
+ bookmarks.append( KBookmark::standaloneBookmark( KURL(*it).prettyURL(), KURL(*it)));
+ }
+ return bookmarks;
+ }
+ }
+ bookmarks.append( KBookmark() );
+ return bookmarks;
+}
diff --git a/kio/bookmarks/kbookmarkdrag.h b/kio/bookmarks/kbookmarkdrag.h
new file mode 100644
index 000000000..fdaaf23f3
--- /dev/null
+++ b/kio/bookmarks/kbookmarkdrag.h
@@ -0,0 +1,57 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kebdrag_h
+#define __kebdrag_h
+
+#include <qdragobject.h>
+#include <kbookmark.h>
+
+// Clipboard/dnd data : URLs + XML for bookmarks
+class KIO_EXPORT KBookmarkDrag : public QUriDrag
+{
+public:
+ static KBookmarkDrag * newDrag( const QValueList<KBookmark> & bookmarks,
+ QWidget * dragSource = 0,
+ const char * name = 0 );
+ static KBookmarkDrag * newDrag( const KBookmark & bookmark,
+ QWidget * dragSource = 0,
+ const char * name = 0 );
+protected:
+ KBookmarkDrag( const QValueList<KBookmark> & bookmarks,
+ const QStrList & urls,
+ QWidget * dragSource,
+ const char * name );
+public:
+ virtual ~KBookmarkDrag() {}
+
+ virtual const char* format( int i ) const;
+ virtual QByteArray encodedData( const char* mime ) const;
+
+ static bool canDecode( const QMimeSource * e );
+ static QValueList<KBookmark> decode( const QMimeSource * e );
+
+protected:
+ QValueList<KBookmark> m_bookmarks;
+ QDomDocument m_doc;
+ class KBookmarkDragPrivate;
+ KBookmarkDragPrivate * d;
+};
+#endif
diff --git a/kio/bookmarks/kbookmarkexporter.cc b/kio/bookmarks/kbookmarkexporter.cc
new file mode 100644
index 000000000..8ed394ad1
--- /dev/null
+++ b/kio/bookmarks/kbookmarkexporter.cc
@@ -0,0 +1,32 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include <stdio.h>
+
+#include <qfile.h>
+#include <qtextcodec.h>
+#include <qstylesheet.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "kbookmarkmanager.h"
+#include "kbookmarkexporter.h"
+
+// todo - put stuff in here :)
diff --git a/kio/bookmarks/kbookmarkexporter.h b/kio/bookmarks/kbookmarkexporter.h
new file mode 100644
index 000000000..19978b3dd
--- /dev/null
+++ b/kio/bookmarks/kbookmarkexporter.h
@@ -0,0 +1,50 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 1996-1998 Martin R. Jones <mjones@kde.org>
+ Copyright (C) 2000 David Faure <faure@kde.org>
+ Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kbookmarkexporter_h
+#define __kbookmarkexporter_h
+
+#include <qtextstream.h>
+#include <kbookmark.h>
+
+/**
+ * @since 3.2
+ */
+class KIO_EXPORT KBookmarkExporterBase
+{
+public:
+ KBookmarkExporterBase(KBookmarkManager* mgr, const QString & fileName)
+ : m_fileName(fileName), m_pManager(mgr)
+ { ; }
+ virtual ~KBookmarkExporterBase() {}
+ virtual void write(KBookmarkGroup) = 0;
+protected:
+ QString m_fileName;
+ KBookmarkManager* m_pManager;
+private:
+ class KBookmarkExporterBasePrivate *d;
+};
+
+// for SC
+#include "kbookmarkimporter_ns.h"
+
+#endif
diff --git a/kio/bookmarks/kbookmarkimporter.cc b/kio/bookmarks/kbookmarkimporter.cc
new file mode 100644
index 000000000..b646b0626
--- /dev/null
+++ b/kio/bookmarks/kbookmarkimporter.cc
@@ -0,0 +1,101 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kfiledialog.h>
+#include <kstringhandler.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kcharsets.h>
+#include <qtextcodec.h>
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <assert.h>
+
+#include "kbookmarkmanager.h"
+
+#include "kbookmarkimporter_ns.h"
+#include "kbookmarkimporter_opera.h"
+#include "kbookmarkimporter_ie.h"
+
+#include "kbookmarkimporter.h"
+
+void KXBELBookmarkImporterImpl::parse()
+{
+ //kdDebug() << "KXBELBookmarkImporterImpl::parse()" << endl;
+ KBookmarkManager *manager = KBookmarkManager::managerForFile(m_fileName);
+ KBookmarkGroup root = manager->root();
+ traverse(root);
+ // FIXME delete it!
+ // delete manager;
+}
+
+void KXBELBookmarkImporterImpl::visit(const KBookmark &bk)
+{
+ //kdDebug() << "KXBELBookmarkImporterImpl::visit" << endl;
+ if (bk.isSeparator())
+ emit newSeparator();
+ else
+ emit newBookmark(bk.fullText(), bk.url().url().utf8(), "");
+}
+
+void KXBELBookmarkImporterImpl::visitEnter(const KBookmarkGroup &grp)
+{
+ //kdDebug() << "KXBELBookmarkImporterImpl::visitEnter" << endl;
+ emit newFolder(grp.fullText(), false, "");
+}
+
+void KXBELBookmarkImporterImpl::visitLeave(const KBookmarkGroup &)
+{
+ //kdDebug() << "KXBELBookmarkImporterImpl::visitLeave" << endl;
+ emit endFolder();
+}
+
+void KBookmarkImporterBase::setupSignalForwards(QObject *src, QObject *dst)
+{
+ connect(src, SIGNAL( newBookmark( const QString &, const QCString &, const QString & ) ),
+ dst, SIGNAL( newBookmark( const QString &, const QCString &, const QString & ) ));
+ connect(src, SIGNAL( newFolder( const QString &, bool, const QString & ) ),
+ dst, SIGNAL( newFolder( const QString &, bool, const QString & ) ));
+ connect(src, SIGNAL( newSeparator() ),
+ dst, SIGNAL( newSeparator() ) );
+ connect(src, SIGNAL( endFolder() ),
+ dst, SIGNAL( endFolder() ) );
+}
+
+KBookmarkImporterBase* KBookmarkImporterBase::factory( const QString &type )
+{
+ if (type == "netscape")
+ return new KNSBookmarkImporterImpl;
+ else if (type == "mozilla")
+ return new KMozillaBookmarkImporterImpl;
+ else if (type == "xbel")
+ return new KXBELBookmarkImporterImpl;
+ else if (type == "ie")
+ return new KIEBookmarkImporterImpl;
+ else if (type == "opera")
+ return new KOperaBookmarkImporterImpl;
+ else
+ return 0;
+}
+
+#include <kbookmarkimporter.moc>
diff --git a/kio/bookmarks/kbookmarkimporter.h b/kio/bookmarks/kbookmarkimporter.h
new file mode 100644
index 000000000..f8f53ffa2
--- /dev/null
+++ b/kio/bookmarks/kbookmarkimporter.h
@@ -0,0 +1,106 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kbookmarkimporter_h
+#define __kbookmarkimporter_h
+
+#include <qdom.h>
+#include <qcstring.h>
+#include <qstringlist.h>
+#include <ksimpleconfig.h>
+
+#include "kbookmark.h"
+
+/**
+ * A class for importing NS bookmarks
+ * KEditBookmarks uses it to insert bookmarks into its DOM tree,
+ * and KActionMenu uses it to create actions directly.
+ * @since 3.2
+ */
+class KIO_EXPORT KBookmarkImporterBase : public QObject
+{
+ Q_OBJECT
+public:
+ KBookmarkImporterBase() {}
+ virtual ~KBookmarkImporterBase() {}
+
+ void setFilename(const QString &filename) { m_fileName = filename; }
+
+ virtual void parse() = 0;
+ virtual QString findDefaultLocation(bool forSaving = false) const = 0;
+
+ // TODO - make this static?
+ void setupSignalForwards(QObject *src, QObject *dst);
+ static KBookmarkImporterBase *factory(const QString &type);
+
+signals:
+ /**
+ * Notify about a new bookmark
+ * Use "html" for the icon
+ */
+ void newBookmark(const QString & text, const QCString & url, const QString & additionalInfo);
+
+ /**
+ * Notify about a new folder
+ * Use "bookmark_folder" for the icon
+ */
+ void newFolder(const QString & text, bool open, const QString & additionalInfo);
+
+ /**
+ * Notify about a new separator
+ */
+ void newSeparator();
+
+ /**
+ * Tell the outside world that we're going down
+ * one menu
+ */
+ void endFolder();
+
+protected:
+ QString m_fileName;
+
+private:
+ class KBookmarkImporterBasePrivate *d;
+};
+
+/**
+ * A class for importing XBEL files
+ */
+class KIO_EXPORT KXBELBookmarkImporterImpl : public KBookmarkImporterBase, protected KBookmarkGroupTraverser
+{
+ Q_OBJECT
+public:
+ KXBELBookmarkImporterImpl() {}
+ virtual void parse();
+ virtual QString findDefaultLocation(bool = false) const { return QString::null; }
+protected:
+ virtual void visit(const KBookmark &);
+ virtual void visitEnter(const KBookmarkGroup &);
+ virtual void visitLeave(const KBookmarkGroup &);
+private:
+ class KXBELBookmarkImporterImplPrivate *d;
+};
+
+// for SC
+#include "kbookmarkimporter_ns.h"
+#include "kbookmarkimporter_kde1.h"
+
+#endif
diff --git a/kio/bookmarks/kbookmarkimporter_crash.cc b/kio/bookmarks/kbookmarkimporter_crash.cc
new file mode 100644
index 000000000..b585df4c7
--- /dev/null
+++ b/kio/bookmarks/kbookmarkimporter_crash.cc
@@ -0,0 +1,215 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kbookmarkimporter_crash.h"
+
+#include <kfiledialog.h>
+#include <kstringhandler.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qstring.h>
+#include <qtextcodec.h>
+#include <dcopclient.h>
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+typedef QMap<QString, QString> ViewMap;
+
+// KDE 4.0: remove this BC keeping stub
+void KCrashBookmarkImporter::parseCrashLog( QString /*filename*/, bool /*del*/ )
+{
+ ;
+}
+
+ViewMap KCrashBookmarkImporterImpl::parseCrashLog_noemit( const QString & filename, bool del )
+{
+ static const int g_lineLimit = 16*1024;
+
+ QFile f( filename );
+ ViewMap views;
+
+ if ( !f.open( IO_ReadOnly ) )
+ return views;
+
+ QCString s( g_lineLimit );
+
+ QTextCodec * codec = QTextCodec::codecForName( "UTF-8" );
+ Q_ASSERT( codec );
+ if ( !codec )
+ return views;
+
+ while ( f.readLine( s.data(), g_lineLimit ) >=0 )
+ {
+ if ( s[s.length()-1] != '\n' )
+ {
+ kdWarning() << "Crash bookmarks contain a line longer than " << g_lineLimit << ". Skipping." << endl;
+ continue;
+ }
+ QString t = codec->toUnicode( s.stripWhiteSpace() );
+ QRegExp rx( "(.*)\\((.*)\\):(.*)$" );
+ rx.setMinimal( true );
+ if ( !rx.exactMatch( t ) )
+ continue;
+ if ( rx.cap(1) == "opened" )
+ views[rx.cap(2)] = rx.cap(3);
+ else if ( rx.cap(1) == "close" )
+ views.remove( rx.cap(2) );
+ }
+
+ f.close();
+
+ if ( del )
+ f.remove();
+
+ return views;
+}
+
+QStringList KCrashBookmarkImporter::getCrashLogs()
+{
+ return KCrashBookmarkImporterImpl::getCrashLogs();
+}
+
+QStringList KCrashBookmarkImporterImpl::getCrashLogs()
+{
+ QMap<QString, bool> activeLogs;
+
+ DCOPClient* dcop = kapp->dcopClient();
+
+ QCStringList apps = dcop->registeredApplications();
+ for ( QCStringList::Iterator it = apps.begin(); it != apps.end(); ++it )
+ {
+ QCString &clientId = *it;
+
+ if ( qstrncmp(clientId, "konqueror", 9) != 0 )
+ continue;
+
+ QByteArray data, replyData;
+ QCString replyType;
+ QDataStream arg( data, IO_WriteOnly );
+
+ if ( !dcop->call( clientId.data(), "KonquerorIface",
+ "crashLogFile()", data, replyType, replyData) )
+ {
+ kdWarning() << "can't find dcop function KonquerorIface::crashLogFile()" << endl;
+ continue;
+ }
+
+ if ( replyType != "QString" )
+ continue;
+
+ QDataStream reply( replyData, IO_ReadOnly );
+ QString ret;
+ reply >> ret;
+ activeLogs[ret] = true;
+ }
+
+ QDir d( KCrashBookmarkImporterImpl().findDefaultLocation() );
+ d.setSorting( QDir::Time );
+ d.setFilter( QDir::Files );
+ d.setNameFilter( "konqueror-crash-*.log" );
+
+ const QFileInfoList *list = d.entryInfoList();
+ QFileInfoListIterator it( *list );
+
+ QFileInfo *fi;
+ QStringList crashFiles;
+
+ int count = 0;
+ for ( ; (( fi = it.current() ) != 0) && (count < 20); ++it, ++count )
+ {
+ bool stillAlive = activeLogs.contains( fi->absFilePath() );
+ if ( !stillAlive )
+ crashFiles << fi->absFilePath();
+ }
+ // Delete remaining ones
+ for ( ; ( fi = it.current() ) != 0; ++it )
+ {
+ QFile::remove( fi->absFilePath() );
+ }
+
+ return crashFiles;
+}
+
+void KCrashBookmarkImporterImpl::parse()
+{
+ QDict<bool> signatureMap;
+ QStringList crashFiles = KCrashBookmarkImporterImpl::getCrashLogs();
+ int count = 1;
+ for ( QStringList::Iterator it = crashFiles.begin(); it != crashFiles.end(); ++it )
+ {
+ ViewMap views;
+ views = parseCrashLog_noemit( *it, m_shouldDelete );
+ QString signature;
+ for ( ViewMap::Iterator vit = views.begin(); vit != views.end(); ++vit )
+ signature += "|"+vit.data();
+ if (signatureMap[signature])
+ {
+ // Duplicate... throw away and skip
+ QFile::remove(*it);
+ continue;
+ }
+
+ signatureMap.insert(signature, (bool *) true); // hack
+
+ int outerFolder = ( crashFiles.count() > 1 ) && (views.count() > 0);
+ if ( outerFolder )
+ emit newFolder( QString("Konqueror Window %1").arg(count++), false, "" );
+ for ( ViewMap::Iterator vit = views.begin(); vit != views.end(); ++vit )
+ emit newBookmark( vit.data(), vit.data().latin1(), QString("") );
+ if ( outerFolder )
+ emit endFolder();
+ }
+}
+
+QString KCrashBookmarkImporter::crashBookmarksDir()
+{
+ static KCrashBookmarkImporterImpl *p = 0;
+ if (!p)
+ p = new KCrashBookmarkImporterImpl;
+ return p->findDefaultLocation();
+}
+
+void KCrashBookmarkImporterImpl::setShouldDelete( bool shouldDelete )
+{
+ m_shouldDelete = shouldDelete;
+}
+
+void KCrashBookmarkImporter::parseCrashBookmarks( bool del )
+{
+ KCrashBookmarkImporterImpl importer;
+ importer.setFilename( m_fileName );
+ importer.setShouldDelete( del );
+ importer.setupSignalForwards( &importer, this );
+ importer.parse();
+}
+
+QString KCrashBookmarkImporterImpl::findDefaultLocation( bool ) const
+{
+ return locateLocal( "tmp", "" );
+}
+
+#include "kbookmarkimporter_crash.moc"
diff --git a/kio/bookmarks/kbookmarkimporter_crash.h b/kio/bookmarks/kbookmarkimporter_crash.h
new file mode 100644
index 000000000..701387b4e
--- /dev/null
+++ b/kio/bookmarks/kbookmarkimporter_crash.h
@@ -0,0 +1,74 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2002 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kbookmarkimporter_crash_h
+#define __kbookmarkimporter_crash_h
+
+#include <qdom.h>
+#include <qcstring.h>
+#include <qstringlist.h>
+#include <qmap.h>
+#include <ksimpleconfig.h>
+#include <kdemacros.h>
+
+#include "kbookmarkimporter.h"
+
+/**
+ * A class for importing all crash sessions as bookmarks
+ * @deprecated
+ */
+class KIO_EXPORT_DEPRECATED KCrashBookmarkImporter : public QObject
+{
+ Q_OBJECT
+public:
+ KCrashBookmarkImporter( const QString & fileName ) : m_fileName(fileName) {}
+ ~KCrashBookmarkImporter() {}
+ void parseCrashBookmarks( bool del = true );
+ static QString crashBookmarksDir( );
+ static QStringList getCrashLogs(); // EMPTY!
+signals:
+ void newBookmark( const QString & text, const QCString & url, const QString & additionalInfo );
+ void newFolder( const QString & text, bool open, const QString & additionalInfo );
+ void newSeparator();
+ void endFolder();
+protected:
+ QString m_fileName;
+ void parseCrashLog( QString filename, bool del ); // EMPTY!
+};
+
+/**
+ * A class for importing all crash sessions as bookmarks
+ * @since 3.2
+ */
+class KIO_EXPORT KCrashBookmarkImporterImpl : public KBookmarkImporterBase
+{
+public:
+ KCrashBookmarkImporterImpl() : m_shouldDelete(false) { }
+ void setShouldDelete(bool);
+ virtual void parse();
+ virtual QString findDefaultLocation(bool forSaving = false) const;
+ static QStringList getCrashLogs();
+private:
+ bool m_shouldDelete;
+ QMap<QString, QString> parseCrashLog_noemit( const QString & filename, bool del );
+ class KCrashBookmarkImporterImplPrivate *d;
+};
+
+#endif
diff --git a/kio/bookmarks/kbookmarkimporter_ie.cc b/kio/bookmarks/kbookmarkimporter_ie.cc
new file mode 100644
index 000000000..a2e863518
--- /dev/null
+++ b/kio/bookmarks/kbookmarkimporter_ie.cc
@@ -0,0 +1,185 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kfiledialog.h>
+#include <kstringhandler.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <qtextcodec.h>
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include "kbookmarkimporter.h"
+#include "kbookmarkimporter_ie.h"
+
+/* antlarr: KDE 4: Make them const QString & */
+void KIEBookmarkImporter::parseIEBookmarks_url_file( QString filename, QString name ) {
+ static const int g_lineLimit = 16*1024;
+
+ QFile f(filename);
+
+ if(f.open(IO_ReadOnly)) {
+
+ QCString s(g_lineLimit);
+
+ while(f.readLine(s.data(), g_lineLimit)>=0) {
+ if ( s[s.length()-1] != '\n' ) // Gosh, this line is longer than g_lineLimit. Skipping.
+ {
+ kdWarning() << "IE bookmarks contain a line longer than " << g_lineLimit << ". Skipping." << endl;
+ continue;
+ }
+ QCString t = s.stripWhiteSpace();
+ QRegExp rx( "URL=(.*)" );
+ if (rx.exactMatch(t)) {
+ emit newBookmark( name, rx.cap(1).latin1(), QString("") );
+ }
+ }
+
+ f.close();
+ }
+}
+
+/* antlarr: KDE 4: Make them const QString & */
+void KIEBookmarkImporter::parseIEBookmarks_dir( QString dirname, QString foldername )
+{
+
+ QDir dir(dirname);
+ dir.setFilter( QDir::Files | QDir::Dirs );
+ dir.setSorting( QDir::Name | QDir::DirsFirst );
+ dir.setNameFilter("*.url"); // AK - possibly add ";index.ini" ?
+ dir.setMatchAllDirs(true);
+
+ const QFileInfoList *list = dir.entryInfoList();
+ if (!list) return;
+
+ if (dirname != m_fileName)
+ emit newFolder( foldername, false, "" );
+
+ QFileInfoListIterator it( *list );
+ QFileInfo *fi;
+
+ while ( (fi = it.current()) != 0 ) {
+ ++it;
+
+ if (fi->fileName() == "." || fi->fileName() == "..") continue;
+
+ if (fi->isDir()) {
+ parseIEBookmarks_dir(fi->absFilePath(), fi->fileName());
+
+ } else if (fi->isFile()) {
+ if (fi->fileName().endsWith(".url")) {
+ QString name = fi->fileName();
+ name.truncate(name.length() - 4); // .url
+ parseIEBookmarks_url_file(fi->absFilePath(), name);
+ }
+ // AK - add index.ini
+ }
+ }
+
+ if (dirname != m_fileName)
+ emit endFolder();
+}
+
+
+void KIEBookmarkImporter::parseIEBookmarks( )
+{
+ parseIEBookmarks_dir( m_fileName );
+}
+
+QString KIEBookmarkImporter::IEBookmarksDir()
+{
+ static KIEBookmarkImporterImpl* p = 0;
+ if (!p)
+ p = new KIEBookmarkImporterImpl;
+ return p->findDefaultLocation();
+}
+
+void KIEBookmarkImporterImpl::parse() {
+ KIEBookmarkImporter importer(m_fileName);
+ setupSignalForwards(&importer, this);
+ importer.parseIEBookmarks();
+}
+
+QString KIEBookmarkImporterImpl::findDefaultLocation(bool) const
+{
+ // notify user that they must give a new dir such
+ // as "Favourites" as otherwise it'll just place
+ // lots of .url files in the given dir and gui
+ // stuff in the exporter is ugly so that exclues
+ // the possibility of just writing to Favourites
+ // and checking if overwriting...
+ return KFileDialog::getExistingDirectory();
+}
+
+/////////////////////////////////////////////////
+
+class IEExporter : private KBookmarkGroupTraverser {
+public:
+ IEExporter( const QString & );
+ void write( const KBookmarkGroup &grp ) { traverse(grp); };
+private:
+ virtual void visit( const KBookmark & );
+ virtual void visitEnter( const KBookmarkGroup & );
+ virtual void visitLeave( const KBookmarkGroup & );
+private:
+ QDir m_currentDir;
+};
+
+static QString ieStyleQuote( const QString &str ) {
+ QString s(str);
+ s.replace(QRegExp("[/\\:*?\"<>|]"), "_");
+ return s;
+}
+
+IEExporter::IEExporter( const QString & dname ) {
+ m_currentDir.setPath( dname );
+}
+
+void IEExporter::visit( const KBookmark &bk ) {
+ QString fname = m_currentDir.path() + "/" + ieStyleQuote( bk.fullText() ) + ".url";
+ // kdDebug() << "visit(" << bk.text() << "), fname == " << fname << endl;
+ QFile file( fname );
+ file.open( IO_WriteOnly );
+ QTextStream ts( &file );
+ ts << "[InternetShortcut]\r\n";
+ ts << "URL=" << bk.url().url().utf8() << "\r\n";
+}
+
+void IEExporter::visitEnter( const KBookmarkGroup &grp ) {
+ QString dname = m_currentDir.path() + "/" + ieStyleQuote( grp.fullText() );
+ // kdDebug() << "visitEnter(" << grp.text() << "), dname == " << dname << endl;
+ m_currentDir.mkdir( dname );
+ m_currentDir.cd( dname );
+}
+
+void IEExporter::visitLeave( const KBookmarkGroup & ) {
+ // kdDebug() << "visitLeave()" << endl;
+ m_currentDir.cdUp();
+}
+
+void KIEBookmarkExporterImpl::write(KBookmarkGroup parent) {
+ IEExporter exporter( m_fileName );
+ exporter.write( parent );
+}
+
+#include "kbookmarkimporter_ie.moc"
diff --git a/kio/bookmarks/kbookmarkimporter_ie.h b/kio/bookmarks/kbookmarkimporter_ie.h
new file mode 100644
index 000000000..86f41a4f6
--- /dev/null
+++ b/kio/bookmarks/kbookmarkimporter_ie.h
@@ -0,0 +1,90 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2002 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kbookmarkimporter_ie_h
+#define __kbookmarkimporter_ie_h
+
+#include <qdom.h>
+#include <qcstring.h>
+#include <qstringlist.h>
+#include <ksimpleconfig.h>
+#include <kdemacros.h>
+
+#include <kbookmarkimporter.h>
+
+/**
+ * A class for importing IE bookmarks
+ * @deprecated
+ */
+class KIO_EXPORT_DEPRECATED KIEBookmarkImporter : public QObject
+{
+ Q_OBJECT
+public:
+ KIEBookmarkImporter( const QString & fileName ) : m_fileName(fileName) {}
+ ~KIEBookmarkImporter() {}
+
+ void parseIEBookmarks();
+
+ // Usual place for IE bookmarks
+ static QString IEBookmarksDir();
+
+signals:
+ void newBookmark( const QString & text, const QCString & url, const QString & additionalInfo );
+ void newFolder( const QString & text, bool open, const QString & additionalInfo );
+ void newSeparator();
+ void endFolder();
+
+protected:
+ void parseIEBookmarks_dir( QString dirname, QString name = QString::null );
+ void parseIEBookmarks_url_file( QString filename, QString name );
+
+ QString m_fileName;
+};
+
+/**
+ * A class for importing IE bookmarks
+ * @since 3.2
+ */
+class KIO_EXPORT KIEBookmarkImporterImpl : public KBookmarkImporterBase
+{
+public:
+ KIEBookmarkImporterImpl() { }
+ virtual void parse();
+ virtual QString findDefaultLocation(bool forSaving = false) const;
+private:
+ class KIEBookmarkImporterImplPrivate *d;
+};
+
+/*
+ * @since 3.2
+ */
+class KIO_EXPORT KIEBookmarkExporterImpl : public KBookmarkExporterBase
+{
+public:
+ KIEBookmarkExporterImpl(KBookmarkManager* mgr, const QString & path)
+ : KBookmarkExporterBase(mgr, path)
+ { ; }
+ virtual ~KIEBookmarkExporterImpl() {}
+ virtual void write(KBookmarkGroup);
+private:
+ class KIEBookmarkExporterImplPrivate *d;
+};
+
+#endif
diff --git a/kio/bookmarks/kbookmarkimporter_kde1.cc b/kio/bookmarks/kbookmarkimporter_kde1.cc
new file mode 100644
index 000000000..72fe8dbb3
--- /dev/null
+++ b/kio/bookmarks/kbookmarkimporter_kde1.cc
@@ -0,0 +1,150 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kbookmarkimporter_kde1.h"
+#include <kfiledialog.h>
+#include <kstringhandler.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kcharsets.h>
+#include <qtextcodec.h>
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <assert.h>
+
+////////////////////
+
+void KBookmarkImporter::import( const QString & path )
+{
+ QDomElement elem = m_pDoc->documentElement();
+ Q_ASSERT(!elem.isNull());
+ scanIntern( elem, path );
+}
+
+void KBookmarkImporter::scanIntern( QDomElement & parentElem, const QString & _path )
+{
+ kdDebug(7043) << "KBookmarkImporter::scanIntern " << _path << endl;
+ // Substitute all symbolic links in the path
+ QDir dir( _path );
+ QString canonical = dir.canonicalPath();
+
+ if ( m_lstParsedDirs.contains(canonical) )
+ {
+ kdWarning() << "Directory " << canonical << " already parsed" << endl;
+ return;
+ }
+
+ m_lstParsedDirs.append( canonical );
+
+ DIR *dp;
+ struct dirent *ep;
+ dp = opendir( QFile::encodeName(_path) );
+ if ( dp == 0L )
+ return;
+
+ // Loop thru all directory entries
+ while ( ( ep = readdir( dp ) ) != 0L )
+ {
+ if ( strcmp( ep->d_name, "." ) != 0 && strcmp( ep->d_name, ".." ) != 0 )
+ {
+ KURL file;
+ file.setPath( QString( _path ) + '/' + QFile::decodeName(ep->d_name) );
+
+ KMimeType::Ptr res = KMimeType::findByURL( file, 0, true );
+ //kdDebug(7043) << " - " << file.url() << " -> " << res->name() << endl;
+
+ if ( res->name() == "inode/directory" )
+ {
+ // We could use KBookmarkGroup::createNewFolder, but then it
+ // would notify about the change, so we'd need a flag, etc.
+ QDomElement groupElem = m_pDoc->createElement( "folder" );
+ parentElem.appendChild( groupElem );
+ QDomElement textElem = m_pDoc->createElement( "title" );
+ groupElem.appendChild( textElem );
+ textElem.appendChild( m_pDoc->createTextNode( KIO::decodeFileName( ep->d_name ) ) );
+ if ( KIO::decodeFileName( ep->d_name ) == "Toolbar" )
+ groupElem.setAttribute("toolbar","yes");
+ scanIntern( groupElem, file.path() );
+ }
+ else if ( res->name() == "application/x-desktop" )
+ {
+ KSimpleConfig cfg( file.path(), true );
+ cfg.setDesktopGroup();
+ QString type = cfg.readEntry( "Type" );
+ // Is it really a bookmark file ?
+ if ( type == "Link" )
+ parseBookmark( parentElem, ep->d_name, cfg, 0 /* desktop group */ );
+ else
+ kdWarning(7043) << " Not a link ? Type=" << type << endl;
+ }
+ else if ( res->name() == "text/plain")
+ {
+ // maybe its an IE Favourite..
+ KSimpleConfig cfg( file.path(), true );
+ QStringList grp = cfg.groupList().grep( "internetshortcut", false );
+ if ( grp.count() == 0 )
+ continue;
+ cfg.setGroup( *grp.begin() );
+
+ QString url = cfg.readPathEntry("URL");
+ if (!url.isEmpty() )
+ parseBookmark( parentElem, ep->d_name, cfg, *grp.begin() );
+ } else
+ kdWarning(7043) << "Invalid bookmark : found mimetype='" << res->name() << "' for file='" << file.path() << "'!" << endl;
+ }
+ }
+
+ closedir( dp );
+}
+
+void KBookmarkImporter::parseBookmark( QDomElement & parentElem, QCString _text,
+ KSimpleConfig& _cfg, const QString &_group )
+{
+ if ( !_group.isEmpty() )
+ _cfg.setGroup( _group );
+ else
+ _cfg.setDesktopGroup();
+
+ QString url = _cfg.readPathEntry( "URL" );
+ QString icon = _cfg.readEntry( "Icon" );
+ if (icon.right( 4 ) == ".xpm" ) // prevent warnings
+ icon.truncate( icon.length() - 4 );
+
+ QString text = KIO::decodeFileName( QString::fromLocal8Bit(_text) );
+ if ( text.length() > 8 && text.right( 8 ) == ".desktop" )
+ text.truncate( text.length() - 8 );
+ if ( text.length() > 7 && text.right( 7 ) == ".kdelnk" )
+ text.truncate( text.length() - 7 );
+
+ QDomElement elem = m_pDoc->createElement( "bookmark" );
+ parentElem.appendChild( elem );
+ elem.setAttribute( "href", url );
+ //if ( icon != "www" ) // No need to save the default
+ // Hmm, after all, it makes KBookmark::pixmapFile faster,
+ // and it shows a nice feature to those reading the file
+ elem.setAttribute( "icon", icon );
+ QDomElement textElem = m_pDoc->createElement( "title" );
+ elem.appendChild( textElem );
+ textElem.appendChild( m_pDoc->createTextNode( text ) );
+ kdDebug(7043) << "KBookmarkImporter::parseBookmark text=" << text << endl;
+}
diff --git a/kio/bookmarks/kbookmarkimporter_kde1.h b/kio/bookmarks/kbookmarkimporter_kde1.h
new file mode 100644
index 000000000..9811cce55
--- /dev/null
+++ b/kio/bookmarks/kbookmarkimporter_kde1.h
@@ -0,0 +1,49 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kbookmarkimporter_kde1_h
+#define __kbookmarkimporter_kde1_h
+
+#include <qdom.h>
+#include <qcstring.h>
+#include <qstringlist.h>
+#include <ksimpleconfig.h>
+
+/**
+ * A class for importing the previous bookmarks (desktop files)
+ * Separated from KBookmarkManager to save memory (we throw this one
+ * out once the import is done)
+ */
+class KIO_EXPORT KBookmarkImporter
+{
+public:
+ KBookmarkImporter( QDomDocument * doc ) : m_pDoc(doc) {}
+
+ void import( const QString & path );
+
+private:
+ void scanIntern( QDomElement & parentElem, const QString & _path );
+ void parseBookmark( QDomElement & parentElem, QCString _text,
+ KSimpleConfig& _cfg, const QString &_group );
+ QDomDocument * m_pDoc;
+ QStringList m_lstParsedDirs;
+};
+
+#endif
diff --git a/kio/bookmarks/kbookmarkimporter_ns.cc b/kio/bookmarks/kbookmarkimporter_ns.cc
new file mode 100644
index 000000000..23f37e4cb
--- /dev/null
+++ b/kio/bookmarks/kbookmarkimporter_ns.cc
@@ -0,0 +1,243 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 1996-1998 Martin R. Jones <mjones@kde.org>
+ Copyright (C) 2000 David Faure <faure@kde.org>
+ Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kbookmarkimporter.h"
+#include "kbookmarkexporter.h"
+#include "kbookmarkmanager.h"
+#include <kfiledialog.h>
+#include <kstringhandler.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kcharsets.h>
+#include <qtextcodec.h>
+#include <qstylesheet.h>
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <assert.h>
+
+void KNSBookmarkImporterImpl::parse()
+{
+ QFile f(m_fileName);
+ QTextCodec * codec = m_utf8 ? QTextCodec::codecForName("UTF-8") : QTextCodec::codecForLocale();
+ Q_ASSERT(codec);
+ if (!codec)
+ return;
+
+ if(f.open(IO_ReadOnly)) {
+
+ static const int g_lineLimit = 16*1024;
+ QCString s(g_lineLimit);
+ // skip header
+ while(f.readLine(s.data(), g_lineLimit) >= 0 && !s.contains("<DL>"));
+
+ while(f.readLine(s.data(), g_lineLimit)>=0) {
+ if ( s[s.length()-1] != '\n' ) // Gosh, this line is longer than g_lineLimit. Skipping.
+ {
+ kdWarning() << "Netscape bookmarks contain a line longer than " << g_lineLimit << ". Skipping." << endl;
+ continue;
+ }
+ QCString t = s.stripWhiteSpace();
+ if(t.left(12).upper() == "<DT><A HREF=" ||
+ t.left(16).upper() == "<DT><H3><A HREF=") {
+ int firstQuotes = t.find('"')+1;
+ int secondQuotes = t.find('"', firstQuotes);
+ if (firstQuotes != -1 && secondQuotes != -1)
+ {
+ QCString link = t.mid(firstQuotes, secondQuotes-firstQuotes);
+ int endTag = t.find('>', secondQuotes+1);
+ QCString name = t.mid(endTag+1);
+ name = name.left(name.findRev('<'));
+ if ( name.right(4) == "</A>" )
+ name = name.left( name.length() - 4 );
+ QString qname = KCharsets::resolveEntities( codec->toUnicode( name ) );
+ QCString additionalInfo = t.mid( secondQuotes+1, endTag-secondQuotes-1 );
+
+ emit newBookmark( qname,
+ link, codec->toUnicode(additionalInfo) );
+ }
+ }
+ else if(t.left(7).upper() == "<DT><H3") {
+ int endTag = t.find('>', 7);
+ QCString name = t.mid(endTag+1);
+ name = name.left(name.findRev('<'));
+ QString qname = KCharsets::resolveEntities( codec->toUnicode( name ) );
+ QCString additionalInfo = t.mid( 8, endTag-8 );
+ bool folded = (additionalInfo.left(6) == "FOLDED");
+ if (folded) additionalInfo.remove(0,7);
+
+ emit newFolder( qname,
+ !folded,
+ codec->toUnicode(additionalInfo) );
+ }
+ else if(t.left(4).upper() == "<HR>")
+ emit newSeparator();
+ else if(t.left(8).upper() == "</DL><P>")
+ emit endFolder();
+ }
+
+ f.close();
+ }
+}
+
+QString KNSBookmarkImporterImpl::findDefaultLocation(bool forSaving) const
+{
+ if (m_utf8)
+ {
+ if ( forSaving )
+ return KFileDialog::getSaveFileName( QDir::homeDirPath() + "/.mozilla",
+ i18n("*.html|HTML Files (*.html)") );
+ else
+ return KFileDialog::getOpenFileName( QDir::homeDirPath() + "/.mozilla",
+ i18n("*.html|HTML Files (*.html)") );
+ }
+ else
+ {
+ return QDir::homeDirPath() + "/.netscape/bookmarks.html";
+ }
+}
+
+////////////////////////////////////////////////////////////////
+
+
+void KNSBookmarkImporter::parseNSBookmarks( bool utf8 )
+{
+ KNSBookmarkImporterImpl importer;
+ importer.setFilename(m_fileName);
+ importer.setUtf8(utf8);
+ importer.setupSignalForwards(&importer, this);
+ importer.parse();
+}
+
+QString KNSBookmarkImporter::netscapeBookmarksFile( bool forSaving )
+{
+ static KNSBookmarkImporterImpl *p = 0;
+ if (!p)
+ {
+ p = new KNSBookmarkImporterImpl;
+ p->setUtf8(false);
+ }
+ return p->findDefaultLocation(forSaving);
+}
+
+QString KNSBookmarkImporter::mozillaBookmarksFile( bool forSaving )
+{
+ static KNSBookmarkImporterImpl *p = 0;
+ if (!p)
+ {
+ p = new KNSBookmarkImporterImpl;
+ p->setUtf8(true);
+ }
+ return p->findDefaultLocation(forSaving);
+}
+
+
+////////////////////////////////////////////////////////////////
+// compat only
+////////////////////////////////////////////////////////////////
+
+void KNSBookmarkExporter::write(bool utf8) {
+ KNSBookmarkExporterImpl exporter(m_pManager, m_fileName);
+ exporter.setUtf8(utf8);
+ exporter.write(m_pManager->root());
+}
+
+void KNSBookmarkExporter::writeFolder(QTextStream &/*stream*/, KBookmarkGroup /*gp*/) {
+ // TODO - requires a d pointer workaround hack?
+}
+
+////////////////////////////////////////////////////////////////
+
+void KNSBookmarkExporterImpl::setUtf8(bool utf8) {
+ m_utf8 = utf8;
+}
+
+void KNSBookmarkExporterImpl::write(KBookmarkGroup parent) {
+ if (QFile::exists(m_fileName)) {
+ ::rename(
+ QFile::encodeName(m_fileName),
+ QFile::encodeName(m_fileName + ".beforekde"));
+ }
+
+ QFile file(m_fileName);
+
+ if (!file.open(IO_WriteOnly)) {
+ kdError(7043) << "Can't write to file " << m_fileName << endl;
+ return;
+ }
+
+ QTextStream fstream(&file);
+ fstream.setEncoding(m_utf8 ? QTextStream::UnicodeUTF8 : QTextStream::Locale);
+
+ QString charset
+ = m_utf8 ? "UTF-8" : QString::fromLatin1(QTextCodec::codecForLocale()->name()).upper();
+
+ fstream << "<!DOCTYPE NETSCAPE-Bookmark-file-1>" << endl
+ << i18n("<!-- This file was generated by Konqueror -->") << endl
+ << "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset="
+ << charset << "\">" << endl
+ << "<TITLE>" << i18n("Bookmarks") << "</TITLE>" << endl
+ << "<H1>" << i18n("Bookmarks") << "</H1>" << endl
+ << "<DL><p>" << endl
+ << folderAsString(parent)
+ << "</DL><P>" << endl;
+}
+
+QString KNSBookmarkExporterImpl::folderAsString(KBookmarkGroup parent) const {
+ QString str;
+ QTextStream fstream(&str, IO_WriteOnly);
+
+ for (KBookmark bk = parent.first(); !bk.isNull(); bk = parent.next(bk)) {
+ if (bk.isSeparator()) {
+ fstream << "<HR>" << endl;
+ continue;
+ }
+
+ QString text = QStyleSheet::escape(bk.fullText());
+
+ if (bk.isGroup() ) {
+ fstream << "<DT><H3 "
+ << (!bk.toGroup().isOpen() ? "FOLDED " : "")
+ << bk.internalElement().attribute("netscapeinfo") << ">"
+ << text << "</H3>" << endl
+ << "<DL><P>" << endl
+ << folderAsString(bk.toGroup())
+ << "</DL><P>" << endl;
+ continue;
+
+ } else {
+ // note - netscape seems to use local8bit for url...
+ fstream << "<DT><A HREF=\"" << bk.url().url() << "\""
+ << bk.internalElement().attribute("netscapeinfo") << ">"
+ << text << "</A>" << endl;
+ continue;
+ }
+ }
+
+ return str;
+}
+
+////
+
+#include "kbookmarkimporter_ns.moc"
diff --git a/kio/bookmarks/kbookmarkimporter_ns.h b/kio/bookmarks/kbookmarkimporter_ns.h
new file mode 100644
index 000000000..48f6705aa
--- /dev/null
+++ b/kio/bookmarks/kbookmarkimporter_ns.h
@@ -0,0 +1,132 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kbookmarkimporter_ns_h
+#define __kbookmarkimporter_ns_h
+
+#include <qdom.h>
+#include <qcstring.h>
+#include <qstringlist.h>
+#include <ksimpleconfig.h>
+#include <kdemacros.h>
+
+#include "kbookmarkimporter.h"
+#include "kbookmarkexporter.h"
+
+/**
+ * A class for importing NS bookmarks
+ * @deprecated
+ */
+class KIO_EXPORT_DEPRECATED KNSBookmarkImporter : public QObject
+{
+ Q_OBJECT
+public:
+ KNSBookmarkImporter( const QString & fileName ) : m_fileName(fileName) {}
+ ~KNSBookmarkImporter() {}
+
+ // for compat reasons only
+ void parseNSBookmarks() { parseNSBookmarks(false); }
+ // go for it. Set utf8 to true for Mozilla, false for Netscape.
+ void parseNSBookmarks( bool utf8 );
+
+ static QString netscapeBookmarksFile( bool forSaving=false );
+ static QString mozillaBookmarksFile( bool forSaving=false );
+
+signals:
+ void newBookmark( const QString & text, const QCString & url, const QString & additionalInfo );
+ void newFolder( const QString & text, bool open, const QString & additionalInfo );
+ void newSeparator();
+ void endFolder();
+
+protected:
+ QString m_fileName;
+};
+
+/**
+ * A class for importing NS bookmarks
+ * utf8 defaults to off
+ * @since 3.2
+ */
+class KIO_EXPORT KNSBookmarkImporterImpl : public KBookmarkImporterBase
+{
+public:
+ KNSBookmarkImporterImpl() : m_utf8(false) { }
+ void setUtf8(bool utf8) { m_utf8 = utf8; }
+ virtual void parse();
+ virtual QString findDefaultLocation(bool forSaving = false) const;
+private:
+ bool m_utf8;
+ class KNSBookmarkImporterImplPrivate *d;
+};
+
+/**
+ * A class for importing Mozilla bookmarks
+ * utf8 defaults to on
+ * @since 3.2
+ */
+class KIO_EXPORT KMozillaBookmarkImporterImpl : public KNSBookmarkImporterImpl
+{
+public:
+ KMozillaBookmarkImporterImpl() { setUtf8(true); }
+private:
+ class KMozillaBookmarkImporterImplPrivate *d;
+};
+
+/**
+ * A class that exports all the current bookmarks to Netscape/Mozilla bookmarks
+ * Warning, it overwrites the existing bookmarks.html file !
+ * @deprecated
+ */
+class KIO_EXPORT_DEPRECATED KNSBookmarkExporter
+{
+public:
+ KNSBookmarkExporter(KBookmarkManager* mgr, const QString & fileName)
+ : m_fileName(fileName), m_pManager(mgr) { }
+ ~KNSBookmarkExporter() {}
+
+ void write() { write(false); } // deprecated
+ void write( bool utf8 );
+
+protected:
+ void writeFolder(QTextStream &stream, KBookmarkGroup parent);
+ QString m_fileName;
+ KBookmarkManager* m_pManager;
+};
+
+/**
+ * @since 3.2
+ */
+class KIO_EXPORT KNSBookmarkExporterImpl : public KBookmarkExporterBase
+{
+public:
+ KNSBookmarkExporterImpl(KBookmarkManager* mgr, const QString & fileName)
+ : KBookmarkExporterBase(mgr, fileName)
+ { ; }
+ virtual ~KNSBookmarkExporterImpl() {}
+ virtual void write(KBookmarkGroup);
+ void setUtf8(bool);
+protected:
+ QString folderAsString(KBookmarkGroup) const;
+private:
+ bool m_utf8;
+ class KNSBookmarkExporterImplPrivate *d;
+};
+
+#endif
diff --git a/kio/bookmarks/kbookmarkimporter_opera.cc b/kio/bookmarks/kbookmarkimporter_opera.cc
new file mode 100644
index 000000000..6e2a90570
--- /dev/null
+++ b/kio/bookmarks/kbookmarkimporter_opera.cc
@@ -0,0 +1,170 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kfiledialog.h>
+#include <kstringhandler.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <qtextcodec.h>
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include "kbookmarkimporter.h"
+#include "kbookmarkimporter_opera.h"
+
+void KOperaBookmarkImporter::parseOperaBookmarks( )
+{
+ QFile file(m_fileName);
+ if(!file.open(IO_ReadOnly)) {
+ return;
+ }
+
+ QTextCodec * codec = QTextCodec::codecForName("UTF-8");
+ Q_ASSERT(codec);
+ if (!codec)
+ return;
+
+ int lineno = 0;
+ QString url, name, type;
+ static const int g_lineLimit = 16*1024;
+ QCString line(g_lineLimit);
+
+ while ( file.readLine(line.data(), g_lineLimit) >=0 ) {
+ lineno++;
+
+ // skip lines that didn't fit in buffer and first two headers lines
+ if ( line[line.length()-1] != '\n' || lineno <= 2 )
+ continue;
+
+ QString currentLine = codec->toUnicode(line).stripWhiteSpace();
+
+ if (currentLine.isEmpty()) {
+ // end of data block
+ if (type.isNull())
+ continue;
+ else if ( type == "URL")
+ emit newBookmark( name, url.latin1(), "" );
+ else if (type == "FOLDER" )
+ emit newFolder( name, false, "" );
+
+ type = QString::null;
+ name = QString::null;
+ url = QString::null;
+
+ } else if (currentLine == "-") {
+ // end of folder
+ emit endFolder();
+
+ } else {
+ // data block line
+ QString tag;
+ if ( tag = "#", currentLine.startsWith( tag ) )
+ type = currentLine.remove( 0, tag.length() );
+ else if ( tag = "NAME=", currentLine.startsWith( tag ) )
+ name = currentLine.remove(0, tag.length());
+ else if ( tag = "URL=", currentLine.startsWith( tag ) )
+ url = currentLine.remove(0, tag.length());
+ }
+ }
+
+}
+
+QString KOperaBookmarkImporter::operaBookmarksFile()
+{
+ static KOperaBookmarkImporterImpl *p = 0;
+ if (!p)
+ p = new KOperaBookmarkImporterImpl;
+ return p->findDefaultLocation();
+}
+
+void KOperaBookmarkImporterImpl::parse() {
+ KOperaBookmarkImporter importer(m_fileName);
+ setupSignalForwards(&importer, this);
+ importer.parseOperaBookmarks();
+}
+
+QString KOperaBookmarkImporterImpl::findDefaultLocation(bool saving) const
+{
+ return saving ? KFileDialog::getSaveFileName(
+ QDir::homeDirPath() + "/.opera",
+ i18n("*.adr|Opera Bookmark Files (*.adr)") )
+ : KFileDialog::getOpenFileName(
+ QDir::homeDirPath() + "/.opera",
+ i18n("*.adr|Opera Bookmark Files (*.adr)") );
+}
+
+/////////////////////////////////////////////////
+
+class OperaExporter : private KBookmarkGroupTraverser {
+public:
+ OperaExporter();
+ QString generate( const KBookmarkGroup &grp ) { traverse(grp); return m_string; };
+private:
+ virtual void visit( const KBookmark & );
+ virtual void visitEnter( const KBookmarkGroup & );
+ virtual void visitLeave( const KBookmarkGroup & );
+private:
+ QString m_string;
+ QTextStream m_out;
+};
+
+OperaExporter::OperaExporter() : m_out(&m_string, IO_WriteOnly) {
+ m_out << "Opera Hotlist version 2.0" << endl;
+ m_out << "Options: encoding = utf8, version=3" << endl;
+}
+
+void OperaExporter::visit( const KBookmark &bk ) {
+ // kdDebug() << "visit(" << bk.text() << ")" << endl;
+ m_out << "#URL" << endl;
+ m_out << "\tNAME=" << bk.fullText() << endl;
+ m_out << "\tURL=" << bk.url().url().utf8() << endl;
+ m_out << endl;
+}
+
+void OperaExporter::visitEnter( const KBookmarkGroup &grp ) {
+ // kdDebug() << "visitEnter(" << grp.text() << ")" << endl;
+ m_out << "#FOLDER" << endl;
+ m_out << "\tNAME="<< grp.fullText() << endl;
+ m_out << endl;
+}
+
+void OperaExporter::visitLeave( const KBookmarkGroup & ) {
+ // kdDebug() << "visitLeave()" << endl;
+ m_out << "-" << endl;
+ m_out << endl;
+}
+
+void KOperaBookmarkExporterImpl::write(KBookmarkGroup parent) {
+ OperaExporter exporter;
+ QString content = exporter.generate( parent );
+ QFile file(m_fileName);
+ if (!file.open(IO_WriteOnly)) {
+ kdError(7043) << "Can't write to file " << m_fileName << endl;
+ return;
+ }
+ QTextStream fstream(&file);
+ fstream.setEncoding(QTextStream::UnicodeUTF8);
+ fstream << content;
+}
+
+#include "kbookmarkimporter_opera.moc"
diff --git a/kio/bookmarks/kbookmarkimporter_opera.h b/kio/bookmarks/kbookmarkimporter_opera.h
new file mode 100644
index 000000000..b179f2f93
--- /dev/null
+++ b/kio/bookmarks/kbookmarkimporter_opera.h
@@ -0,0 +1,86 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2002 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kbookmarkimporter_opera_h
+#define __kbookmarkimporter_opera_h
+
+#include <qdom.h>
+#include <qcstring.h>
+#include <qstringlist.h>
+#include <ksimpleconfig.h>
+
+#include <kbookmarkimporter.h>
+
+/**
+ * A class for importing Opera bookmarks
+ * @deprecated
+ */
+class KIO_EXPORT_DEPRECATED KOperaBookmarkImporter : public QObject
+{
+ Q_OBJECT
+public:
+ KOperaBookmarkImporter( const QString & fileName ) : m_fileName(fileName) {}
+ ~KOperaBookmarkImporter() {}
+
+ void parseOperaBookmarks();
+
+ // Usual place for Opera bookmarks
+ static QString operaBookmarksFile();
+
+signals:
+ void newBookmark( const QString & text, const QCString & url, const QString & additionalInfo );
+ void newFolder( const QString & text, bool open, const QString & additionalInfo );
+ void newSeparator();
+ void endFolder();
+
+protected:
+ QString m_fileName;
+};
+
+/**
+ * A class for importing Opera bookmarks
+ * @since 3.2
+ */
+class KIO_EXPORT KOperaBookmarkImporterImpl : public KBookmarkImporterBase
+{
+public:
+ KOperaBookmarkImporterImpl() { }
+ virtual void parse();
+ virtual QString findDefaultLocation(bool forSaving = false) const;
+private:
+ class KOperaBookmarkImporterImplPrivate *d;
+};
+
+/**
+ * @since 3.2
+ */
+class KIO_EXPORT KOperaBookmarkExporterImpl : public KBookmarkExporterBase
+{
+public:
+ KOperaBookmarkExporterImpl(KBookmarkManager* mgr, const QString & filename)
+ : KBookmarkExporterBase(mgr, filename)
+ { ; }
+ virtual ~KOperaBookmarkExporterImpl() {}
+ virtual void write(KBookmarkGroup);
+private:
+ class KOperaBookmarkExporterImplPrivate *d;
+};
+
+#endif
diff --git a/kio/bookmarks/kbookmarkmanager.cc b/kio/bookmarks/kbookmarkmanager.cc
new file mode 100644
index 000000000..d101c1f7f
--- /dev/null
+++ b/kio/bookmarks/kbookmarkmanager.cc
@@ -0,0 +1,727 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>
+ Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kbookmarkmanager.h"
+#include "kbookmarkmenu.h"
+#include "kbookmarkmenu_p.h"
+#include "kbookmarkimporter.h"
+#include <kdebug.h>
+#include <krun.h>
+#include <kstandarddirs.h>
+#include <ksavefile.h>
+#include <dcopref.h>
+#include <qregexp.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <dcopclient.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+#include <kstaticdeleter.h>
+#include <qptrstack.h>
+
+#include "dptrtemplate.h"
+
+class KBookmarkManagerPrivate : public dPtrTemplate<KBookmarkManager, KBookmarkManagerPrivate> {
+public:
+ KBookmarkManagerPrivate()
+ { m_browserEditor = true; }
+ QString m_editorCaption;
+ bool m_browserEditor;
+};
+template<> QPtrDict<KBookmarkManagerPrivate>* dPtrTemplate<KBookmarkManager, KBookmarkManagerPrivate>::d_ptr = 0;
+
+KBookmarkManagerPrivate* KBookmarkManager::dptr() const {
+ return KBookmarkManagerPrivate::d( this );
+}
+
+// TODO - clean this stuff up by just using the above dptrtemplate?
+QPtrList<KBookmarkManager>* KBookmarkManager::s_pSelf;
+static KStaticDeleter<QPtrList<KBookmarkManager> > sdbm;
+
+class KBookmarkMap : private KBookmarkGroupTraverser {
+public:
+ KBookmarkMap( KBookmarkManager * );
+ void update();
+ QValueList<KBookmark> find( const QString &url ) const
+ { return m_bk_map[url]; }
+private:
+ virtual void visit(const KBookmark &);
+ virtual void visitEnter(const KBookmarkGroup &) { ; }
+ virtual void visitLeave(const KBookmarkGroup &) { ; }
+private:
+ typedef QValueList<KBookmark> KBookmarkList;
+ QMap<QString, KBookmarkList> m_bk_map;
+ KBookmarkManager *m_manager;
+};
+
+static KBookmarkMap *s_bk_map = 0;
+
+KBookmarkMap::KBookmarkMap( KBookmarkManager *manager ) {
+ m_manager = manager;
+}
+
+void KBookmarkMap::update()
+{
+ m_bk_map.clear();
+ KBookmarkGroup root = m_manager->root();
+ traverse(root);
+}
+
+void KBookmarkMap::visit(const KBookmark &bk)
+{
+ if (!bk.isSeparator()) {
+ // add bookmark to url map
+ m_bk_map[bk.internalElement().attribute("href")].append(bk);
+ }
+}
+
+
+KBookmarkManager* KBookmarkManager::managerForFile( const QString& bookmarksFile, bool bImportDesktopFiles )
+{
+ if ( !s_pSelf ) {
+ sdbm.setObject( s_pSelf, new QPtrList<KBookmarkManager> );
+ s_pSelf->setAutoDelete( true );
+ }
+ QPtrListIterator<KBookmarkManager> it ( *s_pSelf );
+ for ( ; it.current() ; ++it )
+ if ( it.current()->path() == bookmarksFile )
+ return it.current();
+
+ KBookmarkManager* mgr = new KBookmarkManager( bookmarksFile, bImportDesktopFiles );
+ s_pSelf->append( mgr );
+ return mgr;
+}
+
+// principally used for filtered toolbars
+KBookmarkManager* KBookmarkManager::createTempManager()
+{
+ if ( !s_pSelf ) {
+ sdbm.setObject( s_pSelf, new QPtrList<KBookmarkManager> );
+ s_pSelf->setAutoDelete( true );
+ }
+ KBookmarkManager* mgr = new KBookmarkManager();
+ s_pSelf->append( mgr );
+ return mgr;
+}
+
+#define PI_DATA "version=\"1.0\" encoding=\"UTF-8\""
+
+KBookmarkManager::KBookmarkManager( const QString & bookmarksFile, bool bImportDesktopFiles )
+ : DCOPObject(QCString("KBookmarkManager-")+bookmarksFile.utf8()), m_doc("xbel"), m_docIsLoaded(false)
+{
+ m_toolbarDoc.clear();
+
+ m_update = true;
+ m_showNSBookmarks = true;
+
+ Q_ASSERT( !bookmarksFile.isEmpty() );
+ m_bookmarksFile = bookmarksFile;
+
+ if ( !QFile::exists(m_bookmarksFile) )
+ {
+ QDomElement topLevel = m_doc.createElement("xbel");
+ m_doc.appendChild( topLevel );
+ m_doc.insertBefore( m_doc.createProcessingInstruction( "xml", PI_DATA), topLevel );
+ if ( bImportDesktopFiles )
+ importDesktopFiles();
+ m_docIsLoaded = true;
+ }
+
+ connectDCOPSignal(0, objId(), "bookmarksChanged(QString)", "notifyChanged(QString)", false);
+ connectDCOPSignal(0, objId(), "bookmarkConfigChanged()", "notifyConfigChanged()", false);
+}
+
+KBookmarkManager::KBookmarkManager( )
+ : DCOPObject(QCString("KBookmarkManager-generated")), m_doc("xbel"), m_docIsLoaded(true)
+{
+ m_toolbarDoc.clear(); // strange ;-)
+
+ m_update = false; // TODO - make it read/write
+ m_showNSBookmarks = true;
+
+ m_bookmarksFile = QString::null; // AK - check all codepaths for this one
+
+ QDomElement topLevel = m_doc.createElement("xbel");
+ m_doc.appendChild( topLevel );
+ m_doc.insertBefore( m_doc.createProcessingInstruction( "xml", PI_DATA), topLevel );
+
+ // TODO - enable this via some sort of api and fix the above DCOPObject script somehow
+#if 0
+ connectDCOPSignal(0, objId(), "bookmarksChanged(QString)", "notifyChanged(QString)", false);
+ connectDCOPSignal(0, objId(), "bookmarkConfigChanged()", "notifyConfigChanged()", false);
+#endif
+}
+
+KBookmarkManager::~KBookmarkManager()
+{
+ if ( s_pSelf )
+ s_pSelf->removeRef( this );
+}
+
+void KBookmarkManager::setUpdate( bool update )
+{
+ m_update = update;
+}
+
+const QDomDocument &KBookmarkManager::internalDocument() const
+{
+ if(!m_docIsLoaded)
+ {
+ parse();
+ m_toolbarDoc.clear();
+ }
+ return m_doc;
+}
+
+
+void KBookmarkManager::parse() const
+{
+ m_docIsLoaded = true;
+ //kdDebug(7043) << "KBookmarkManager::parse " << m_bookmarksFile << endl;
+ QFile file( m_bookmarksFile );
+ if ( !file.open( IO_ReadOnly ) )
+ {
+ kdWarning() << "Can't open " << m_bookmarksFile << endl;
+ return;
+ }
+ m_doc = QDomDocument("xbel");
+ m_doc.setContent( &file );
+
+ QDomElement docElem = m_doc.documentElement();
+ if ( docElem.isNull() )
+ kdWarning() << "KBookmarkManager::parse : can't parse " << m_bookmarksFile << endl;
+ else
+ {
+ QString mainTag = docElem.tagName();
+ if ( mainTag == "BOOKMARKS" )
+ {
+ kdWarning() << "Old style bookmarks found. Calling convertToXBEL." << endl;
+ docElem.setTagName("xbel");
+ if ( docElem.hasAttribute( "HIDE_NSBK" ) && m_showNSBookmarks ) // non standard either, but we need it
+ {
+ docElem.setAttribute( "hide_nsbk", docElem.attribute( "HIDE_NSBK" ) == "1" ? "yes" : "no" );
+ docElem.removeAttribute( "HIDE_NSBK" );
+ }
+
+ convertToXBEL( docElem );
+ save();
+ }
+ else if ( mainTag != "xbel" )
+ kdWarning() << "KBookmarkManager::parse : unknown main tag " << mainTag << endl;
+
+ QDomNode n = m_doc.documentElement().previousSibling();
+ if ( n.isProcessingInstruction() )
+ {
+ QDomProcessingInstruction pi = n.toProcessingInstruction();
+ pi.parentNode().removeChild(pi);
+ }
+
+ QDomProcessingInstruction pi;
+ pi = m_doc.createProcessingInstruction( "xml", PI_DATA );
+ m_doc.insertBefore( pi, docElem );
+ }
+
+ file.close();
+ if ( !s_bk_map )
+ s_bk_map = new KBookmarkMap( const_cast<KBookmarkManager*>( this ) );
+ s_bk_map->update();
+}
+
+void KBookmarkManager::convertToXBEL( QDomElement & group )
+{
+ QDomNode n = group.firstChild();
+ while( !n.isNull() )
+ {
+ QDomElement e = n.toElement();
+ if ( !e.isNull() )
+ if ( e.tagName() == "TEXT" )
+ {
+ e.setTagName("title");
+ }
+ else if ( e.tagName() == "SEPARATOR" )
+ {
+ e.setTagName("separator"); // so close...
+ }
+ else if ( e.tagName() == "GROUP" )
+ {
+ e.setTagName("folder");
+ convertAttribute(e, "ICON","icon"); // non standard, but we need it
+ if ( e.hasAttribute( "TOOLBAR" ) ) // non standard either, but we need it
+ {
+ e.setAttribute( "toolbar", e.attribute( "TOOLBAR" ) == "1" ? "yes" : "no" );
+ e.removeAttribute( "TOOLBAR" );
+ }
+
+ convertAttribute(e, "NETSCAPEINFO","netscapeinfo"); // idem
+ bool open = (e.attribute("OPEN") == "1");
+ e.removeAttribute("OPEN");
+ e.setAttribute("folded", open ? "no" : "yes");
+ convertToXBEL( e );
+ }
+ else
+ if ( e.tagName() == "BOOKMARK" )
+ {
+ e.setTagName("bookmark"); // so much difference :-)
+ convertAttribute(e, "ICON","icon"); // non standard, but we need it
+ convertAttribute(e, "NETSCAPEINFO","netscapeinfo"); // idem
+ convertAttribute(e, "URL","href");
+ QString text = e.text();
+ while ( !e.firstChild().isNull() ) // clean up the old contained text
+ e.removeChild(e.firstChild());
+ QDomElement titleElem = e.ownerDocument().createElement("title");
+ e.appendChild( titleElem ); // should be the only child anyway
+ titleElem.appendChild( e.ownerDocument().createTextNode( text ) );
+ }
+ else
+ kdWarning(7043) << "Unknown tag " << e.tagName() << endl;
+ n = n.nextSibling();
+ }
+}
+
+void KBookmarkManager::convertAttribute( QDomElement elem, const QString & oldName, const QString & newName )
+{
+ if ( elem.hasAttribute( oldName ) )
+ {
+ elem.setAttribute( newName, elem.attribute( oldName ) );
+ elem.removeAttribute( oldName );
+ }
+}
+
+void KBookmarkManager::importDesktopFiles()
+{
+ KBookmarkImporter importer( const_cast<QDomDocument *>(&internalDocument()) );
+ QString path(KGlobal::dirs()->saveLocation("data", "kfm/bookmarks", true));
+ importer.import( path );
+ //kdDebug(7043) << internalDocument().toCString() << endl;
+
+ save();
+}
+
+bool KBookmarkManager::save( bool toolbarCache ) const
+{
+ return saveAs( m_bookmarksFile, toolbarCache );
+}
+
+bool KBookmarkManager::saveAs( const QString & filename, bool toolbarCache ) const
+{
+ kdDebug(7043) << "KBookmarkManager::save " << filename << endl;
+
+ // Save the bookmark toolbar folder for quick loading
+ // but only when it will actually make things quicker
+ const QString cacheFilename = filename + QString::fromLatin1(".tbcache");
+ if(toolbarCache && !root().isToolbarGroup())
+ {
+ KSaveFile cacheFile( cacheFilename );
+ if ( cacheFile.status() == 0 )
+ {
+ QString str;
+ QTextStream stream(&str, IO_WriteOnly);
+ stream << root().findToolbar();
+ QCString cstr = str.utf8();
+ cacheFile.file()->writeBlock( cstr.data(), cstr.length() );
+ cacheFile.close();
+ }
+ }
+ else // remove any (now) stale cache
+ {
+ QFile::remove( cacheFilename );
+ }
+
+ KSaveFile file( filename );
+ if ( file.status() == 0 )
+ {
+ file.backupFile( file.name(), QString::null, ".bak" );
+ QCString cstr;
+ cstr = internalDocument().toCString(); // is in UTF8
+ file.file()->writeBlock( cstr.data(), cstr.length() );
+ if ( file.close() )
+ return true;
+ }
+
+ static int hadSaveError = false;
+ file.abort();
+ if ( !hadSaveError ) {
+ QString error = i18n("Unable to save bookmarks in %1. Reported error was: %2. "
+ "This error message will only be shown once. The cause "
+ "of the error needs to be fixed as quickly as possible, "
+ "which is most likely a full hard drive.")
+ .arg(filename).arg(QString::fromLocal8Bit(strerror(file.status())));
+ if (qApp->type() != QApplication::Tty)
+ KMessageBox::error( 0L, error );
+ else
+ kdError() << error << endl;
+ }
+ hadSaveError = true;
+ return false;
+}
+
+KBookmarkGroup KBookmarkManager::root() const
+{
+ return KBookmarkGroup(internalDocument().documentElement());
+}
+
+KBookmarkGroup KBookmarkManager::toolbar()
+{
+ kdDebug(7043) << "KBookmarkManager::toolbar begin" << endl;
+ // Only try to read from a toolbar cache if the full document isn't loaded
+ if(!m_docIsLoaded)
+ {
+ kdDebug(7043) << "KBookmarkManager::toolbar trying cache" << endl;
+ const QString cacheFilename = m_bookmarksFile + QString::fromLatin1(".tbcache");
+ QFileInfo bmInfo(m_bookmarksFile);
+ QFileInfo cacheInfo(cacheFilename);
+ if (m_toolbarDoc.isNull() &&
+ QFile::exists(cacheFilename) &&
+ bmInfo.lastModified() < cacheInfo.lastModified())
+ {
+ kdDebug(7043) << "KBookmarkManager::toolbar reading file" << endl;
+ QFile file( cacheFilename );
+
+ if ( file.open( IO_ReadOnly ) )
+ {
+ m_toolbarDoc = QDomDocument("cache");
+ m_toolbarDoc.setContent( &file );
+ kdDebug(7043) << "KBookmarkManager::toolbar opened" << endl;
+ }
+ }
+ if (!m_toolbarDoc.isNull())
+ {
+ kdDebug(7043) << "KBookmarkManager::toolbar returning element" << endl;
+ QDomElement elem = m_toolbarDoc.firstChild().toElement();
+ return KBookmarkGroup(elem);
+ }
+ }
+
+ // Fallback to the normal way if there is no cache or if the bookmark file
+ // is already loaded
+ QDomElement elem = root().findToolbar();
+ if (elem.isNull())
+ return root(); // Root is the bookmark toolbar if none has been set.
+ else
+ return KBookmarkGroup(root().findToolbar());
+}
+
+KBookmark KBookmarkManager::findByAddress( const QString & address, bool tolerant )
+{
+ //kdDebug(7043) << "KBookmarkManager::findByAddress " << address << endl;
+ KBookmark result = root();
+ // The address is something like /5/10/2+
+ QStringList addresses = QStringList::split(QRegExp("[/+]"),address);
+ // kdWarning() << addresses.join(",") << endl;
+ for ( QStringList::Iterator it = addresses.begin() ; it != addresses.end() ; )
+ {
+ bool append = ((*it) == "+");
+ uint number = (*it).toUInt();
+ Q_ASSERT(result.isGroup());
+ KBookmarkGroup group = result.toGroup();
+ KBookmark bk = group.first(), lbk = bk; // last non-null bookmark
+ for ( uint i = 0 ; ( (i<number) || append ) && !bk.isNull() ; ++i ) {
+ lbk = bk;
+ bk = group.next(bk);
+ //kdWarning() << i << endl;
+ }
+ it++;
+ int shouldBeGroup = !bk.isGroup() && (it != addresses.end());
+ if ( tolerant && ( bk.isNull() || shouldBeGroup ) ) {
+ if (!lbk.isNull()) result = lbk;
+ //kdWarning() << "break" << endl;
+ break;
+ }
+ //kdWarning() << "found section" << endl;
+ result = bk;
+ }
+ if (result.isNull()) {
+ kdWarning() << "KBookmarkManager::findByAddress: couldn't find item " << address << endl;
+ Q_ASSERT(!tolerant);
+ }
+ //kdWarning() << "found " << result.address() << endl;
+ return result;
+ }
+
+static QString pickUnusedTitle( KBookmarkGroup parentBookmark,
+ const QString &title, const QString &url
+) {
+ // If this title is already used, we'll try to find something unused.
+ KBookmark ch = parentBookmark.first();
+ int count = 1;
+ QString uniqueTitle = title;
+ do
+ {
+ while ( !ch.isNull() )
+ {
+ if ( uniqueTitle == ch.text() )
+ {
+ // Title already used !
+ if ( url != ch.url().url() )
+ {
+ uniqueTitle = title + QString(" (%1)").arg(++count);
+ // New title -> restart search from the beginning
+ ch = parentBookmark.first();
+ break;
+ }
+ else
+ {
+ // this exact URL already exists
+ return QString::null;
+ }
+ }
+ ch = parentBookmark.next( ch );
+ }
+ } while ( !ch.isNull() );
+
+ return uniqueTitle;
+}
+
+KBookmarkGroup KBookmarkManager::addBookmarkDialog(
+ const QString & _url, const QString & _title,
+ const QString & _parentBookmarkAddress
+) {
+ QString url = _url;
+ QString title = _title;
+ QString parentBookmarkAddress = _parentBookmarkAddress;
+
+ if ( url.isEmpty() )
+ {
+ KMessageBox::error( 0L, i18n("Cannot add bookmark with empty URL."));
+ return KBookmarkGroup();
+ }
+
+ if ( title.isEmpty() )
+ title = url;
+
+ if ( KBookmarkSettings::self()->m_advancedaddbookmark)
+ {
+ KBookmarkEditDialog dlg( title, url, this, KBookmarkEditDialog::InsertionMode, parentBookmarkAddress );
+ if ( dlg.exec() != KDialogBase::Accepted )
+ return KBookmarkGroup();
+ title = dlg.finalTitle();
+ url = dlg.finalUrl();
+ parentBookmarkAddress = dlg.finalAddress();
+ }
+
+ KBookmarkGroup parentBookmark;
+ parentBookmark = findByAddress( parentBookmarkAddress ).toGroup();
+ Q_ASSERT( !parentBookmark.isNull() );
+
+ QString uniqueTitle = pickUnusedTitle( parentBookmark, title, url );
+ if ( !uniqueTitle.isNull() )
+ parentBookmark.addBookmark( this, uniqueTitle, KURL( url ));
+
+ return parentBookmark;
+}
+
+
+void KBookmarkManager::emitChanged( /*KDE4 const*/ KBookmarkGroup & group )
+{
+ save();
+
+ // Tell the other processes too
+ // kdDebug(7043) << "KBookmarkManager::emitChanged : broadcasting change " << group.address() << endl;
+
+ QByteArray data;
+ QDataStream ds( data, IO_WriteOnly );
+ ds << group.address();
+
+ emitDCOPSignal("bookmarksChanged(QString)", data);
+
+ // We do get our own broadcast, so no need for this anymore
+ //emit changed( group );
+}
+
+void KBookmarkManager::emitConfigChanged()
+{
+ emitDCOPSignal("bookmarkConfigChanged()", QByteArray());
+}
+
+void KBookmarkManager::notifyCompleteChange( QString caller ) // DCOP call
+{
+ if (!m_update) return;
+
+ //kdDebug(7043) << "KBookmarkManager::notifyCompleteChange" << endl;
+ // The bk editor tells us we should reload everything
+ // Reparse
+ parse();
+ // Tell our GUI
+ // (emit where group is "" to directly mark the root menu as dirty)
+ emit changed( "", caller );
+}
+
+void KBookmarkManager::notifyConfigChanged() // DCOP call
+{
+ kdDebug() << "reloaded bookmark config!" << endl;
+ KBookmarkSettings::self()->readSettings();
+ parse(); // reload, and thusly recreate the menus
+}
+
+void KBookmarkManager::notifyChanged( QString groupAddress ) // DCOP call
+{
+ if (!m_update) return;
+
+ // Reparse (the whole file, no other choice)
+ // if someone else notified us
+ if (callingDcopClient()->senderId() != DCOPClient::mainClient()->appId())
+ parse();
+
+ //kdDebug(7043) << "KBookmarkManager::notifyChanged " << groupAddress << endl;
+ //KBookmarkGroup group = findByAddress( groupAddress ).toGroup();
+ //Q_ASSERT(!group.isNull());
+ emit changed( groupAddress, QString::null );
+}
+
+bool KBookmarkManager::showNSBookmarks() const
+{
+ return KBookmarkMenu::showDynamicBookmarks("netscape").show;
+}
+
+void KBookmarkManager::setShowNSBookmarks( bool show )
+{
+ m_showNSBookmarks = show;
+ if (this->path() != userBookmarksFile())
+ return;
+ KBookmarkMenu::DynMenuInfo info
+ = KBookmarkMenu::showDynamicBookmarks("netscape");
+ info.show = show;
+ KBookmarkMenu::setDynamicBookmarks("netscape", info);
+}
+
+void KBookmarkManager::setEditorOptions( const QString& caption, bool browser )
+{
+ dptr()->m_editorCaption = caption;
+ dptr()->m_browserEditor = browser;
+}
+
+void KBookmarkManager::slotEditBookmarks()
+{
+ KProcess proc;
+ proc << QString::fromLatin1("keditbookmarks");
+ if (!dptr()->m_editorCaption.isNull())
+ proc << QString::fromLatin1("--customcaption") << dptr()->m_editorCaption;
+ if (!dptr()->m_browserEditor)
+ proc << QString::fromLatin1("--nobrowser");
+ proc << m_bookmarksFile;
+ proc.start(KProcess::DontCare);
+}
+
+void KBookmarkManager::slotEditBookmarksAtAddress( const QString& address )
+{
+ KProcess proc;
+ proc << QString::fromLatin1("keditbookmarks")
+ << QString::fromLatin1("--address") << address
+ << m_bookmarksFile;
+ proc.start(KProcess::DontCare);
+}
+
+///////
+
+void KBookmarkOwner::openBookmarkURL( const QString& url )
+{
+ (void) new KRun(KURL( url ));
+}
+
+void KBookmarkOwner::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+bool KBookmarkManager::updateAccessMetadata( const QString & url, bool emitSignal )
+{
+ if (!s_bk_map) {
+ s_bk_map = new KBookmarkMap(this);
+ s_bk_map->update();
+ }
+
+ QValueList<KBookmark> list = s_bk_map->find(url);
+ if ( list.count() == 0 )
+ return false;
+
+ for ( QValueList<KBookmark>::iterator it = list.begin();
+ it != list.end(); ++it )
+ (*it).updateAccessMetadata();
+
+ if (emitSignal)
+ emit notifier().updatedAccessMetadata( path(), url );
+
+ return true;
+}
+
+void KBookmarkManager::updateFavicon( const QString &url, const QString &faviconurl, bool emitSignal )
+{
+ Q_UNUSED(faviconurl);
+
+ if (!s_bk_map) {
+ s_bk_map = new KBookmarkMap(this);
+ s_bk_map->update();
+ }
+
+ QValueList<KBookmark> list = s_bk_map->find(url);
+ for ( QValueList<KBookmark>::iterator it = list.begin();
+ it != list.end(); ++it )
+ {
+ // TODO - update favicon data based on faviconurl
+ // but only when the previously used icon
+ // isn't a manually set one.
+ }
+
+ if (emitSignal)
+ {
+ // TODO
+ // emit notifier().updatedFavicon( path(), url, faviconurl );
+ }
+}
+
+QString KBookmarkManager::userBookmarksFile()
+{
+ return locateLocal("data", QString::fromLatin1("konqueror/bookmarks.xml"));
+}
+
+KBookmarkManager* KBookmarkManager::userBookmarksManager()
+{
+ return KBookmarkManager::managerForFile( userBookmarksFile() );
+}
+
+KBookmarkSettings* KBookmarkSettings::s_self = 0;
+
+void KBookmarkSettings::readSettings()
+{
+ KConfig config("kbookmarkrc", false, false);
+ config.setGroup("Bookmarks");
+
+ // add bookmark dialog usage - no reparse
+ s_self->m_advancedaddbookmark = config.readBoolEntry("AdvancedAddBookmarkDialog", false);
+
+ // these three alter the menu, therefore all need a reparse
+ s_self->m_contextmenu = config.readBoolEntry("ContextMenuActions", true);
+ s_self->m_quickactions = config.readBoolEntry("QuickActionSubmenu", false);
+ s_self->m_filteredtoolbar = config.readBoolEntry("FilteredToolbar", false);
+}
+
+KBookmarkSettings *KBookmarkSettings::self()
+{
+ if (!s_self)
+ {
+ s_self = new KBookmarkSettings;
+ readSettings();
+ }
+ return s_self;
+}
+
+#include "kbookmarkmanager.moc"
diff --git a/kio/bookmarks/kbookmarkmanager.h b/kio/bookmarks/kbookmarkmanager.h
new file mode 100644
index 000000000..03d0ac0c6
--- /dev/null
+++ b/kio/bookmarks/kbookmarkmanager.h
@@ -0,0 +1,367 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef __kbookmarkmanager_h
+#define __kbookmarkmanager_h
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qobject.h>
+#include <qdom.h>
+#include <dcopobject.h>
+#include "kbookmark.h"
+#include "kbookmarknotifier.h"
+
+/**
+ * This class implements the reading/writing of bookmarks in XML.
+ * The bookmarks file is read and written using the XBEL standard
+ * (http://pyxml.sourceforge.net/topics/xbel/)
+ *
+ * A sample file looks like this :
+ * \code
+ * <xbel>
+ * <bookmark href="http://developer.kde.org"><title>Developer Web Site</title></bookmark>
+ * <folder folded="no">
+ * <title>Title of this folder</title>
+ * <bookmark icon="kde" href="http://www.kde.org"><title>KDE Web Site</title></bookmark>
+ * <folder toolbar="yes">
+ * <title>My own bookmarks</title>
+ * <bookmark href="http://www.koffice.org"><title>KOffice Web Site</title></bookmark>
+ * <separator/>
+ * <bookmark href="http://www.kdevelop.org"><title>KDevelop Web Site</title></bookmark>
+ * </folder>
+ * </folder>
+ * </xbel>
+ * \endcode
+ */
+class KIO_EXPORT KBookmarkManager : public QObject, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+protected:
+ /**
+ * Creates a bookmark manager with a path to the bookmarks. By
+ * default, it will use the KDE standard dirs to find and create the
+ * correct location. If you are using your own app-specific
+ * bookmarks directory, you must instantiate this class with your
+ * own path <em>before</em> KBookmarkManager::managerForFile() is ever
+ * called.
+ *
+ * @param bookmarksFile full path to the bookmarks file,
+ * Use ~/.kde/share/apps/konqueror/bookmarks.xml for the konqueror bookmarks
+ *
+ * @param bImportDesktopFiles if true, and if the bookmarksFile
+ * doesn't already exist, import bookmarks from desktop files
+ */
+ KBookmarkManager( const QString & bookmarksFile, bool bImportDesktopFiles = true );
+
+ /**
+ * @since 3.2
+ */
+ KBookmarkManager();
+
+public:
+ /**
+ * Destructor
+ */
+ ~KBookmarkManager();
+
+ /**
+ * Set the update flag. Defaults to true. TODO - check
+ * @param update if true then KBookmarkManager will listen to DCOP update requests.
+ */
+ void setUpdate( bool update );
+
+ /**
+ * Save the bookmarks to the default konqueror XML file on disk.
+ * You should use emitChanged() instead of this function, it saves
+ * and notifies everyone that the file has changed.
+ * @param toolbarCache iff true save a cache of the toolbar folder, too
+ * @return true if saving was successful
+ */
+ bool save( bool toolbarCache = true ) const;
+
+ /**
+ * Save the bookmarks to the given XML file on disk.
+ * @param filename full path to the desired bookmarks file location
+ * @param toolbarCache iff true save a cache of the toolbar folder, too
+ * @return true if saving was successful
+ */
+ bool saveAs( const QString & filename, bool toolbarCache = true ) const;
+
+ /**
+ * Update access time stamps for a given url.
+ * @param url the viewed url
+ * @param emitSignal iff true emit KBookmarkNotifier signal
+ * @since 3.2
+ * @return true if any metadata was modified (bookmarks file is not saved automatically)
+ */
+ bool updateAccessMetadata( const QString &url, bool emitSignal = true );
+
+ /*
+ * NB. currently *unimplemented*
+ *
+ * Update favicon url for a given url.
+ * @param url the viewed url
+ * @param faviconurl the favicion url
+ * @emitSignal iff true emit KBookmarkNotifier signal
+ * @since 3.3
+ */
+ void updateFavicon( const QString &url, const QString &faviconurl, bool emitSignal = true );
+
+ /**
+ * This will return the path that this manager is using to read
+ * the bookmarks.
+ * @internal
+ * @return the path containing the bookmarks
+ */
+ QString path() { return m_bookmarksFile; }
+
+ /**
+ * This will return the root bookmark. It is used to iterate
+ * through the bookmarks manually. It is mostly used internally.
+ *
+ * @return the root (top-level) bookmark
+ */
+ KBookmarkGroup root() const;
+
+ /**
+ * This returns the root of the toolbar menu.
+ * In the XML, this is the group with the attribute TOOLBAR=1
+ *
+ * @return the toolbar group
+ */
+ KBookmarkGroup toolbar();
+
+ /**
+ * @return the bookmark designated by @p address
+ * @param address the address belonging to the bookmark you're looking for
+ * @param tolerate when true tries to find the most tolerable bookmark position
+ * @see KBookmark::address
+ */
+ KBookmark findByAddress( const QString & address, bool tolerate = false );
+
+ /**
+ * Saves the bookmark file and notifies everyone.
+ * @param group the parent of all changed bookmarks
+ */
+ void emitChanged( KBookmarkGroup & group );
+
+ void emitConfigChanged();
+
+ /**
+ * @return true if the NS bookmarks should be dynamically shown
+ * in the toplevel kactionmenu
+ * @deprecated
+ */
+ bool showNSBookmarks() const;
+
+ /**
+ * Shows an extra menu for NS bookmarks. Set this to false, if you don't
+ * want this.
+ */
+ void setShowNSBookmarks( bool show );
+
+ /**
+ * Set options with which slotEditBookmarks called keditbookmarks
+ * this can be used to change the appearance of the keditbookmarks
+ * in order to provide a slightly differing outer shell depending
+ * on the bookmarks file / app which calls it.
+ * @param caption the --caption string, for instance "Konsole"
+ * @param browser iff false display no browser specific
+ * menu items in keditbookmarks :: --nobrowser
+ * @since 3.2
+ */
+ void setEditorOptions( const QString& caption, bool browser );
+
+ /**
+ * This static function will return an instance of the
+ * KBookmarkManager, responsible for the given @p bookmarksFile.
+ * If you do not instantiate this class either
+ * natively or in a derived class, then it will return an object
+ * with the default behaviors. If you wish to use different
+ * behaviors, you <em>must</em> derive your own class and
+ * instantiate it before this method is ever called.
+ *
+ * @param bookmarksFile full path to the bookmarks file,
+ * Use ~/.kde/share/apps/konqueror/bookmarks.xml for the konqueror bookmarks
+ *
+ * @param bImportDesktopFiles if true, and if the bookmarksFile
+ * doesn't already exist, import bookmarks from desktop files
+ * @return a pointer to an instance of the KBookmarkManager.
+ */
+ static KBookmarkManager* managerForFile( const QString& bookmarksFile,
+ bool bImportDesktopFiles = true );
+
+
+ static KBookmarkManager* createTempManager();
+
+ /**
+ * Returns a pointer to the users main bookmark collection.
+ * @since 3.2
+ */
+ static KBookmarkManager* userBookmarksManager();
+
+ /**
+ * Returns the path to the user's main bookmark collection file.
+ * @since 3.5.5
+ */
+ static QString userBookmarksFile();
+
+ /**
+ * @internal
+ */
+ const QDomDocument & internalDocument() const;
+
+ /**
+ * Access to bookmark notifier, for emitting signals.
+ * We need this object to exist in one instance only, so we could
+ * connectDCOP to it by name.
+ */
+ KBookmarkNotifier& notifier() { return m_notifier; }
+
+ /**
+ * @since 3.2
+ */
+ KBookmarkGroup addBookmarkDialog( const QString & _url, const QString & _title,
+ const QString & _parentBookmarkAddress = QString::null );
+
+public slots:
+ void slotEditBookmarks();
+ void slotEditBookmarksAtAddress( const QString& address );
+
+public:
+k_dcop:
+ /**
+ * Reparse the whole bookmarks file and notify about the change
+ * (Called by the bookmark editor)
+ */
+ ASYNC notifyCompleteChange( QString caller );
+
+ /**
+ * Emit the changed signal for the group whose address is given
+ * @see KBookmark::address()
+ * Called by the instance of konqueror that saved the file after
+ * a small change (new bookmark or new folder).
+ */
+ ASYNC notifyChanged( QString groupAddress );
+
+ ASYNC notifyConfigChanged();
+
+signals:
+ /**
+ * Signals that the group (or any of its children) with the address
+ * @p groupAddress (e.g. "/4/5")
+ * has been modified by the caller @p caller.
+ */
+ void changed( const QString & groupAddress, const QString & caller );
+
+protected:
+ // consts added to avoid a copy-and-paste of internalDocument
+ void parse() const;
+ void importDesktopFiles();
+ static void convertToXBEL( QDomElement & group );
+ static void convertAttribute( QDomElement elem, const QString & oldName, const QString & newName );
+
+private:
+ KBookmarkNotifier m_notifier;
+ QString m_bookmarksFile;
+ mutable QDomDocument m_doc;
+ mutable QDomDocument m_toolbarDoc;
+ mutable bool m_docIsLoaded;
+ bool m_update;
+ static QPtrList<KBookmarkManager>* s_pSelf;
+ bool m_showNSBookmarks;
+
+private:
+ class KBookmarkManagerPrivate* dptr() const;
+};
+
+/**
+ * The KBookmarkMenu and KBookmarkBar classes gives the user
+ * the ability to either edit bookmarks or add their own. In the
+ * first case, the app may want to open the bookmark in a special way.
+ * In the second case, the app <em>must</em> supply the name and the
+ * URL for the bookmark.
+ *
+ * This class gives the app this callback-like ability.
+ *
+ * If your app does not give the user the ability to add bookmarks and
+ * you don't mind using the default bookmark editor to edit your
+ * bookmarks, then you don't need to overload this class at all.
+ * Rather, just use something like:
+ *
+ * <CODE>
+ * bookmarks = new KBookmarkMenu(new KBookmarkOwner(), ...)
+ * </CODE>
+ *
+ * If you wish to use your own editor or allow the user to add
+ * bookmarks, you must overload this class.
+ */
+class KIO_EXPORT KBookmarkOwner
+{
+public:
+ /**
+ * This function is called if the user selects a bookmark. It will
+ * open up the bookmark in a default fashion unless you override it.
+ */
+ virtual void openBookmarkURL(const QString& _url);
+
+ /**
+ * This function is called whenever the user wants to add the
+ * current page to the bookmarks list. The title will become the
+ * "name" of the bookmark. You must overload this function if you
+ * wish to give your users the ability to add bookmarks.
+ *
+ * @return the title of the current page.
+ */
+ virtual QString currentTitle() const { return QString::null; }
+
+ /**
+ * This function is called whenever the user wants to add the
+ * current page to the bookmarks list. The URL will become the URL
+ * of the bookmark. You must overload this function if you wish to
+ * give your users the ability to add bookmarks.
+ *
+ * @return the URL of the current page.
+ */
+ virtual QString currentURL() const { return QString::null; }
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+};
+
+/**
+ * @since 3.2
+ */
+class KIO_EXPORT KExtendedBookmarkOwner : public QObject, virtual public KBookmarkOwner
+{
+ Q_OBJECT
+public:
+ typedef QValueList<QPair<QString,QString> > QStringPairList;
+public slots:
+ void fillBookmarksList( KExtendedBookmarkOwner::QStringPairList & list ) { emit signalFillBookmarksList( list ); };
+signals:
+ void signalFillBookmarksList( KExtendedBookmarkOwner::QStringPairList & list );
+private:
+ class KExtendedBookmarkOwnerPrivate;
+ KExtendedBookmarkOwnerPrivate *d;
+};
+
+#endif
diff --git a/kio/bookmarks/kbookmarkmenu.cc b/kio/bookmarks/kbookmarkmenu.cc
new file mode 100644
index 000000000..0e1dfe35c
--- /dev/null
+++ b/kio/bookmarks/kbookmarkmenu.cc
@@ -0,0 +1,1187 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kbookmarkmenu.h"
+#include "kbookmarkmenu_p.h"
+#include "kbookmarkimporter.h"
+#include "kbookmarkimporter_opera.h"
+#include "kbookmarkimporter_ie.h"
+#include "kbookmarkdrag.h"
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdialogbase.h>
+#include <kiconloader.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <kstdaccel.h>
+#include <kstdaction.h>
+#include <kstringhandler.h>
+
+#include <qclipboard.h>
+#include <qfile.h>
+#include <qheader.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qlistview.h>
+#include <qpushbutton.h>
+
+#include <dptrtemplate.h>
+
+template class QPtrList<KBookmarkMenu>;
+
+static QString makeTextNodeMod(KBookmark bk, const QString &m_nodename, const QString &m_newText) {
+ QDomNode subnode = bk.internalElement().namedItem(m_nodename);
+ if (subnode.isNull()) {
+ subnode = bk.internalElement().ownerDocument().createElement(m_nodename);
+ bk.internalElement().appendChild(subnode);
+ }
+
+ if (subnode.firstChild().isNull()) {
+ QDomText domtext = subnode.ownerDocument().createTextNode("");
+ subnode.appendChild(domtext);
+ }
+
+ QDomText domtext = subnode.firstChild().toText();
+
+ QString m_oldText = domtext.data();
+ domtext.setData(m_newText);
+
+ return m_oldText;
+}
+
+/********************************************************************/
+/********************************************************************/
+/********************************************************************/
+
+KBookmarkMenu::KBookmarkMenu( KBookmarkManager* mgr,
+ KBookmarkOwner * _owner, KPopupMenu * _parentMenu,
+ KActionCollection *collec, bool _isRoot, bool _add,
+ const QString & parentAddress )
+ : QObject(),
+ m_bIsRoot(_isRoot), m_bAddBookmark(_add),
+ m_bAddShortcuts(true),
+ m_pManager(mgr), m_pOwner(_owner),
+ m_parentMenu( _parentMenu ),
+ m_actionCollection( collec ),
+ m_parentAddress( parentAddress )
+{
+ m_parentMenu->setKeyboardShortcutsEnabled( true );
+
+ m_lstSubMenus.setAutoDelete( true );
+ m_actions.setAutoDelete( true );
+
+ if (m_actionCollection)
+ {
+ m_actionCollection->setHighlightingEnabled(true);
+ disconnect( m_actionCollection, SIGNAL( actionHighlighted( KAction * ) ), 0, 0 );
+ connect( m_actionCollection, SIGNAL( actionHighlighted( KAction * ) ),
+ this, SLOT( slotActionHighlighted( KAction * ) ) );
+ }
+
+ m_bNSBookmark = m_parentAddress.isNull();
+ if ( !m_bNSBookmark ) // not for the netscape bookmark
+ {
+ //kdDebug(7043) << "KBookmarkMenu::KBookmarkMenu " << this << " address : " << m_parentAddress << endl;
+
+ connect( _parentMenu, SIGNAL( aboutToShow() ),
+ SLOT( slotAboutToShow() ) );
+
+ if ( KBookmarkSettings::self()->m_contextmenu )
+ {
+ (void) _parentMenu->contextMenu();
+ connect( _parentMenu, SIGNAL( aboutToShowContextMenu(KPopupMenu*, int, QPopupMenu*) ),
+ this, SLOT( slotAboutToShowContextMenu(KPopupMenu*, int, QPopupMenu*) ));
+ }
+
+ if ( m_bIsRoot )
+ {
+ connect( m_pManager, SIGNAL( changed(const QString &, const QString &) ),
+ SLOT( slotBookmarksChanged(const QString &) ) );
+ }
+ }
+
+ // add entries that possibly have a shortcut, so they are available _before_ first popup
+ if ( m_bIsRoot )
+ {
+ if ( m_bAddBookmark )
+ {
+ addAddBookmark();
+ if ( extOwner() )
+ addAddBookmarksList(); // FIXME
+ }
+
+ addEditBookmarks();
+ }
+
+ m_bDirty = true;
+}
+
+KBookmarkMenu::~KBookmarkMenu()
+{
+ //kdDebug(7043) << "KBookmarkMenu::~KBookmarkMenu() " << this << endl;
+ QPtrListIterator<KAction> it( m_actions );
+ for (; it.current(); ++it )
+ it.current()->unplugAll();
+
+ m_lstSubMenus.clear();
+ m_actions.clear();
+}
+
+void KBookmarkMenu::ensureUpToDate()
+{
+ slotAboutToShow();
+}
+
+void KBookmarkMenu::slotAboutToShow()
+{
+ // Did the bookmarks change since the last time we showed them ?
+ if ( m_bDirty )
+ {
+ m_bDirty = false;
+ refill();
+ }
+}
+
+QString KBookmarkMenu::s_highlightedAddress;
+QString KBookmarkMenu::s_highlightedImportType;
+QString KBookmarkMenu::s_highlightedImportLocation;
+
+void KBookmarkMenu::slotActionHighlighted( KAction* action )
+{
+ if (action->isA("KBookmarkActionMenu") || action->isA("KBookmarkAction"))
+ {
+ s_highlightedAddress = action->property("address").toString();
+ //kdDebug() << "KBookmarkMenu::slotActionHighlighted" << s_highlightedAddress << endl;
+ }
+ else if (action->isA("KImportedBookmarksActionMenu"))
+ {
+ s_highlightedImportType = action->property("type").toString();
+ s_highlightedImportLocation = action->property("location").toString();
+ }
+ else
+ {
+ s_highlightedAddress = QString::null;
+ s_highlightedImportType = QString::null;
+ s_highlightedImportLocation = QString::null;
+ }
+}
+
+/********************************************************************/
+/********************************************************************/
+/********************************************************************/
+
+class KBookmarkMenuRMBAssoc : public dPtrTemplate<KBookmarkMenu, RMB> { };
+template<> QPtrDict<RMB>* dPtrTemplate<KBookmarkMenu, RMB>::d_ptr = 0;
+
+static RMB* rmbSelf(KBookmarkMenu *m) { return KBookmarkMenuRMBAssoc::d(m); }
+
+// TODO check via dcop before making any changes to the bookmarks file???
+
+void RMB::begin_rmb_action(KBookmarkMenu *self)
+{
+ RMB *s = rmbSelf(self);
+ s->recv = self;
+ s->m_parentAddress = self->m_parentAddress;
+ s->s_highlightedAddress = KBookmarkMenu::s_highlightedAddress;
+ s->m_pManager = self->m_pManager;
+ s->m_pOwner = self->m_pOwner;
+ s->m_parentMenu = self->m_parentMenu;
+}
+
+bool RMB::invalid( int val )
+{
+ bool valid = true;
+
+ if (val == 1)
+ s_highlightedAddress = m_parentAddress;
+
+ if (s_highlightedAddress.isNull())
+ valid = false;
+
+ return !valid;
+}
+
+KBookmark RMB::atAddress(const QString & address)
+{
+ KBookmark bookmark = m_pManager->findByAddress( address );
+ Q_ASSERT(!bookmark.isNull());
+ return bookmark;
+}
+
+void KBookmarkMenu::slotAboutToShowContextMenu( KPopupMenu*, int, QPopupMenu* contextMenu )
+{
+ //kdDebug(7043) << "KBookmarkMenu::slotAboutToShowContextMenu" << s_highlightedAddress << endl;
+ if (s_highlightedAddress.isNull())
+ {
+ KPopupMenu::contextMenuFocus()->hideContextMenu();
+ return;
+ }
+ contextMenu->clear();
+ fillContextMenu( contextMenu, s_highlightedAddress, 0 );
+}
+
+void RMB::fillContextMenu( QPopupMenu* contextMenu, const QString & address, int val )
+{
+ KBookmark bookmark = atAddress(address);
+
+ int id;
+
+ // binner:
+ // "Add Bookmark Here" when pointing at a bookmark looks strange and if you
+ // call it you have to close and reopen the menu to see an entry was added?
+ //
+ // TODO rename these, but, message freeze... umm...
+
+// if (bookmark.isGroup()) {
+ id = contextMenu->insertItem( SmallIcon("bookmark_add"), i18n( "Add Bookmark Here" ), recv, SLOT(slotRMBActionInsert(int)) );
+ contextMenu->setItemParameter( id, val );
+/* }
+ else
+ {
+ id = contextMenu->insertItem( SmallIcon("bookmark_add"), i18n( "Add Bookmark Here" ), recv, SLOT(slotRMBActionInsert(int)) );
+ contextMenu->setItemParameter( id, val );
+ }*/
+}
+
+void RMB::fillContextMenu2( QPopupMenu* contextMenu, const QString & address, int val )
+{
+ KBookmark bookmark = atAddress(address);
+
+ int id;
+
+ if (bookmark.isGroup()) {
+ id = contextMenu->insertItem( i18n( "Open Folder in Bookmark Editor" ), recv, SLOT(slotRMBActionEditAt(int)) );
+ contextMenu->setItemParameter( id, val );
+ contextMenu->insertSeparator();
+ id = contextMenu->insertItem( SmallIcon("editdelete"), i18n( "Delete Folder" ), recv, SLOT(slotRMBActionRemove(int)) );
+ contextMenu->setItemParameter( id, val );
+ contextMenu->insertSeparator();
+ id = contextMenu->insertItem( i18n( "Properties" ), recv, SLOT(slotRMBActionProperties(int)) );
+ contextMenu->setItemParameter( id, val );
+ }
+ else
+ {
+ id = contextMenu->insertItem( i18n( "Copy Link Address" ), recv, SLOT(slotRMBActionCopyLocation(int)) );
+ contextMenu->setItemParameter( id, val );
+ contextMenu->insertSeparator();
+ id = contextMenu->insertItem( SmallIcon("editdelete"), i18n( "Delete Bookmark" ), recv, SLOT(slotRMBActionRemove(int)) );
+ contextMenu->setItemParameter( id, val );
+ contextMenu->insertSeparator();
+ id = contextMenu->insertItem( i18n( "Properties" ), recv, SLOT(slotRMBActionProperties(int)) );
+ contextMenu->setItemParameter( id, val );
+ }
+}
+
+void RMB::slotRMBActionEditAt( int val )
+{
+ kdDebug(7043) << "KBookmarkMenu::slotRMBActionEditAt" << s_highlightedAddress << endl;
+ if (invalid(val)) { hidePopup(); return; }
+
+ KBookmark bookmark = atAddress(s_highlightedAddress);
+
+ m_pManager->slotEditBookmarksAtAddress( s_highlightedAddress );
+}
+
+void RMB::slotRMBActionProperties( int val )
+{
+ kdDebug(7043) << "KBookmarkMenu::slotRMBActionProperties" << s_highlightedAddress << endl;
+ if (invalid(val)) { hidePopup(); return; }
+
+ KBookmark bookmark = atAddress(s_highlightedAddress);
+
+ QString folder = bookmark.isGroup() ? QString::null : bookmark.url().pathOrURL();
+ KBookmarkEditDialog dlg( bookmark.fullText(), folder,
+ m_pManager, KBookmarkEditDialog::ModifyMode, 0,
+ 0, 0, i18n("Bookmark Properties") );
+ if ( dlg.exec() != KDialogBase::Accepted )
+ return;
+
+ makeTextNodeMod(bookmark, "title", dlg.finalTitle());
+ if ( !dlg.finalUrl().isNull() )
+ {
+ KURL u = KURL::fromPathOrURL(dlg.finalUrl());
+ bookmark.internalElement().setAttribute("href", u.url(0, 106));
+ }
+
+ kdDebug(7043) << "Requested move to " << dlg.finalAddress() << "!" << endl;
+
+ KBookmarkGroup parentBookmark = atAddress(m_parentAddress).toGroup();
+ m_pManager->emitChanged( parentBookmark );
+}
+
+void RMB::slotRMBActionInsert( int val )
+{
+ kdDebug(7043) << "KBookmarkMenu::slotRMBActionInsert" << s_highlightedAddress << endl;
+ if (invalid(val)) { hidePopup(); return; }
+
+ QString url = m_pOwner->currentURL();
+ if (url.isEmpty())
+ {
+ KMessageBox::error( 0L, i18n("Cannot add bookmark with empty URL."));
+ return;
+ }
+ QString title = m_pOwner->currentTitle();
+ if (title.isEmpty())
+ title = url;
+
+ KBookmark bookmark = atAddress( s_highlightedAddress );
+
+ // TODO use unique title
+
+ if (bookmark.isGroup())
+ {
+ KBookmarkGroup parentBookmark = bookmark.toGroup();
+ Q_ASSERT(!parentBookmark.isNull());
+ parentBookmark.addBookmark( m_pManager, title, KURL( url ) );
+ m_pManager->emitChanged( parentBookmark );
+ }
+ else
+ {
+ KBookmarkGroup parentBookmark = bookmark.parentGroup();
+ Q_ASSERT(!parentBookmark.isNull());
+ KBookmark newBookmark = parentBookmark.addBookmark( m_pManager, title, KURL( url ) );
+ parentBookmark.moveItem( newBookmark, parentBookmark.previous(bookmark) );
+ m_pManager->emitChanged( parentBookmark );
+ }
+}
+
+void RMB::slotRMBActionRemove( int val )
+{
+ //kdDebug(7043) << "KBookmarkMenu::slotRMBActionRemove" << s_highlightedAddress << endl;
+ if (invalid(val)) { hidePopup(); return; }
+
+ KBookmark bookmark = atAddress( s_highlightedAddress );
+ bool folder = bookmark.isGroup();
+
+ if (KMessageBox::warningContinueCancel(
+ m_parentMenu,
+ folder ? i18n("Are you sure you wish to remove the bookmark folder\n\"%1\"?").arg(bookmark.text())
+ : i18n("Are you sure you wish to remove the bookmark\n\"%1\"?").arg(bookmark.text()),
+ folder ? i18n("Bookmark Folder Deletion")
+ : i18n("Bookmark Deletion"),
+ KStdGuiItem::del())
+ != KMessageBox::Continue
+ )
+ return;
+
+ KBookmarkGroup parentBookmark = atAddress( m_parentAddress ).toGroup();
+ parentBookmark.deleteBookmark( bookmark );
+ m_pManager->emitChanged( parentBookmark );
+ if (m_parentMenu)
+ m_parentMenu->hide();
+}
+
+void RMB::slotRMBActionCopyLocation( int val )
+{
+ //kdDebug(7043) << "KBookmarkMenu::slotRMBActionCopyLocation" << s_highlightedAddress << endl;
+ if (invalid(val)) { hidePopup(); return; }
+
+ KBookmark bookmark = atAddress( s_highlightedAddress );
+
+ if ( !bookmark.isGroup() )
+ {
+ kapp->clipboard()->setData( KBookmarkDrag::newDrag(bookmark, 0),
+ QClipboard::Selection );
+ kapp->clipboard()->setData( KBookmarkDrag::newDrag(bookmark, 0),
+ QClipboard::Clipboard );
+ }
+}
+
+void RMB::hidePopup() {
+ KPopupMenu::contextMenuFocus()->hideContextMenu();
+}
+
+/********************************************************************/
+/********************************************************************/
+/********************************************************************/
+
+void KBookmarkMenu::fillContextMenu( QPopupMenu* contextMenu, const QString & address, int val )
+{
+ RMB::begin_rmb_action(this);
+ rmbSelf(this)->fillContextMenu(contextMenu, address, val);
+ emit aboutToShowContextMenu( rmbSelf(this)->atAddress(address), contextMenu);
+ rmbSelf(this)->fillContextMenu2(contextMenu, address, val);
+}
+
+void KBookmarkMenu::slotRMBActionEditAt( int val )
+{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionEditAt( val ); }
+
+void KBookmarkMenu::slotRMBActionProperties( int val )
+{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionProperties( val ); }
+
+void KBookmarkMenu::slotRMBActionInsert( int val )
+{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionInsert( val ); }
+
+void KBookmarkMenu::slotRMBActionRemove( int val )
+{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionRemove( val ); }
+
+void KBookmarkMenu::slotRMBActionCopyLocation( int val )
+{ RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionCopyLocation( val ); }
+
+void KBookmarkMenu::slotBookmarksChanged( const QString & groupAddress )
+{
+ if (m_bNSBookmark)
+ return;
+
+ if ( groupAddress == m_parentAddress )
+ {
+ //kdDebug(7043) << "KBookmarkMenu::slotBookmarksChanged -> setting m_bDirty on " << groupAddress << endl;
+ m_bDirty = true;
+ }
+ else
+ {
+ // Iterate recursively into child menus
+ QPtrListIterator<KBookmarkMenu> it( m_lstSubMenus );
+ for (; it.current(); ++it )
+ {
+ it.current()->slotBookmarksChanged( groupAddress );
+ }
+ }
+}
+
+void KBookmarkMenu::refill()
+{
+ //kdDebug(7043) << "KBookmarkMenu::refill()" << endl;
+ m_lstSubMenus.clear();
+
+ QPtrListIterator<KAction> it( m_actions );
+ for (; it.current(); ++it )
+ it.current()->unplug( m_parentMenu );
+
+ m_parentMenu->clear();
+ m_actions.clear();
+
+ fillBookmarkMenu();
+ m_parentMenu->adjustSize();
+}
+
+void KBookmarkMenu::addAddBookmarksList()
+{
+ if (!kapp->authorizeKAction("bookmarks"))
+ return;
+
+ QString title = i18n( "Bookmark Tabs as Folder..." );
+
+ KAction * paAddBookmarksList = new KAction( title,
+ "bookmarks_list_add",
+ 0,
+ this,
+ SLOT( slotAddBookmarksList() ),
+ m_actionCollection, m_bIsRoot ? "add_bookmarks_list" : 0 );
+
+ paAddBookmarksList->setToolTip( i18n( "Add a folder of bookmarks for all open tabs." ) );
+
+ paAddBookmarksList->plug( m_parentMenu );
+ m_actions.append( paAddBookmarksList );
+}
+
+void KBookmarkMenu::addAddBookmark()
+{
+ if (!kapp->authorizeKAction("bookmarks"))
+ return;
+
+ QString title = i18n( "Add Bookmark" );
+
+ KAction * paAddBookmarks = new KAction( title,
+ "bookmark_add",
+ m_bIsRoot && m_bAddShortcuts ? KStdAccel::addBookmark() : KShortcut(),
+ this,
+ SLOT( slotAddBookmark() ),
+ m_actionCollection, m_bIsRoot ? "add_bookmark" : 0 );
+
+ paAddBookmarks->setToolTip( i18n( "Add a bookmark for the current document" ) );
+
+ paAddBookmarks->plug( m_parentMenu );
+ m_actions.append( paAddBookmarks );
+}
+
+void KBookmarkMenu::addEditBookmarks()
+{
+ if (!kapp->authorizeKAction("bookmarks"))
+ return;
+
+ KAction * m_paEditBookmarks = KStdAction::editBookmarks( m_pManager, SLOT( slotEditBookmarks() ),
+ m_actionCollection, "edit_bookmarks" );
+ m_paEditBookmarks->plug( m_parentMenu );
+ m_paEditBookmarks->setToolTip( i18n( "Edit your bookmark collection in a separate window" ) );
+ m_actions.append( m_paEditBookmarks );
+}
+
+void KBookmarkMenu::addNewFolder()
+{
+ if (!kapp->authorizeKAction("bookmarks"))
+ return;
+
+ QString title = i18n( "&New Bookmark Folder..." );
+ int p;
+ while ( ( p = title.find( '&' ) ) >= 0 )
+ title.remove( p, 1 );
+
+ KAction * paNewFolder = new KAction( title,
+ "folder_new", //"folder",
+ 0,
+ this,
+ SLOT( slotNewFolder() ),
+ m_actionCollection );
+
+ paNewFolder->setToolTip( i18n( "Create a new bookmark folder in this menu" ) );
+
+ paNewFolder->plug( m_parentMenu );
+ m_actions.append( paNewFolder );
+}
+
+void KBookmarkMenu::fillBookmarkMenu()
+{
+ if (!kapp->authorizeKAction("bookmarks"))
+ return;
+
+ if ( m_bIsRoot )
+ {
+ if ( m_bAddBookmark )
+ {
+ addAddBookmark();
+ if ( extOwner() )
+ addAddBookmarksList(); // FIXME
+ }
+
+ addEditBookmarks();
+
+ if ( m_bAddBookmark && !KBookmarkSettings::self()->m_advancedaddbookmark )
+ addNewFolder();
+ }
+
+ if ( m_bIsRoot
+ && KBookmarkManager::userBookmarksFile() == m_pManager->path() )
+ {
+ bool haveSep = false;
+
+ QValueList<QString> keys = KBookmarkMenu::dynamicBookmarksList();
+ QValueList<QString>::const_iterator it;
+ for ( it = keys.begin(); it != keys.end(); ++it )
+ {
+ DynMenuInfo info;
+ info = showDynamicBookmarks((*it));
+
+ if ( !info.show || !QFile::exists( info.location ) )
+ continue;
+
+ if (!haveSep)
+ {
+ m_parentMenu->insertSeparator();
+ haveSep = true;
+ }
+
+ KActionMenu * actionMenu;
+ actionMenu = new KImportedBookmarksActionMenu(
+ info.name, info.type,
+ m_actionCollection, "kbookmarkmenu" );
+
+ actionMenu->setProperty( "type", info.type );
+ actionMenu->setProperty( "location", info.location );
+
+ actionMenu->plug( m_parentMenu );
+ m_actions.append( actionMenu );
+
+ KBookmarkMenu *subMenu =
+ new KBookmarkMenu( m_pManager, m_pOwner, actionMenu->popupMenu(),
+ m_actionCollection, false,
+ m_bAddBookmark, QString::null );
+ connect( subMenu, SIGNAL( openBookmark( const QString &, Qt::ButtonState ) ),
+ this, SIGNAL( openBookmark( const QString &, Qt::ButtonState ) ));
+ m_lstSubMenus.append(subMenu);
+
+ connect(actionMenu->popupMenu(), SIGNAL(aboutToShow()), subMenu, SLOT(slotNSLoad()));
+ }
+ }
+
+ KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup();
+ Q_ASSERT(!parentBookmark.isNull());
+ bool separatorInserted = false;
+ for ( KBookmark bm = parentBookmark.first(); !bm.isNull(); bm = parentBookmark.next(bm) )
+ {
+ QString text = KStringHandler::csqueeze(bm.fullText(), 60);
+ text.replace( '&', "&&" );
+ if ( !separatorInserted && m_bIsRoot) {
+ // inserted before the first konq bookmark, to avoid the separator if no konq bookmark
+ m_parentMenu->insertSeparator();
+ separatorInserted = true;
+ }
+ if ( !bm.isGroup() )
+ {
+ if ( bm.isSeparator() )
+ {
+ m_parentMenu->insertSeparator();
+ }
+ else
+ {
+ //kdDebug(7043) << "Creating URL bookmark menu item for " << bm.text() << endl;
+ KAction * action = new KBookmarkAction( text, bm.icon(), 0, m_actionCollection, 0 );
+ connect(action, SIGNAL( activated ( KAction::ActivationReason, Qt::ButtonState )),
+ this, SLOT( slotBookmarkSelected( KAction::ActivationReason, Qt::ButtonState ) ));
+
+ action->setProperty( "url", bm.url().url() );
+ action->setProperty( "address", bm.address() );
+
+ action->setToolTip( bm.url().pathOrURL() );
+
+ action->plug( m_parentMenu );
+ m_actions.append( action );
+ }
+ }
+ else
+ {
+ //kdDebug(7043) << "Creating bookmark submenu named " << bm.text() << endl;
+ KActionMenu * actionMenu = new KBookmarkActionMenu( text, bm.icon(),
+ m_actionCollection,
+ "kbookmarkmenu" );
+ actionMenu->setProperty( "address", bm.address() );
+ actionMenu->plug( m_parentMenu );
+ m_actions.append( actionMenu );
+
+ KBookmarkMenu *subMenu = new KBookmarkMenu( m_pManager, m_pOwner, actionMenu->popupMenu(),
+ m_actionCollection, false,
+ m_bAddBookmark,
+ bm.address() );
+
+ connect(subMenu, SIGNAL( aboutToShowContextMenu( const KBookmark &, QPopupMenu * ) ),
+ this, SIGNAL( aboutToShowContextMenu( const KBookmark &, QPopupMenu * ) ));
+ connect(subMenu, SIGNAL( openBookmark( const QString &, Qt::ButtonState ) ),
+ this, SIGNAL( openBookmark( const QString &, Qt::ButtonState ) ));
+ m_lstSubMenus.append( subMenu );
+ }
+ }
+
+ if ( !m_bIsRoot && m_bAddBookmark )
+ {
+ if ( m_parentMenu->count() > 0 )
+ m_parentMenu->insertSeparator();
+
+ if ( KBookmarkSettings::self()->m_quickactions )
+ {
+ KActionMenu * actionMenu = new KActionMenu( i18n("Quick Actions"), m_actionCollection, 0L );
+ fillContextMenu( actionMenu->popupMenu(), m_parentAddress, 1 );
+ actionMenu->plug( m_parentMenu );
+ m_actions.append( actionMenu );
+ }
+ else
+ {
+ addAddBookmark();
+ if ( extOwner() )
+ addAddBookmarksList(); // FIXME
+ addNewFolder();
+ }
+ }
+}
+
+void KBookmarkMenu::slotAddBookmarksList()
+{
+ KExtendedBookmarkOwner *extOwner = dynamic_cast<KExtendedBookmarkOwner*>(m_pOwner);
+ if (!extOwner)
+ {
+ kdWarning() << "erm, sorry ;-)" << endl;
+ return;
+ }
+
+ KExtendedBookmarkOwner::QStringPairList list;
+ extOwner->fillBookmarksList( list );
+
+ KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup();
+ Q_ASSERT(!parentBookmark.isNull());
+ KBookmarkGroup group = parentBookmark.createNewFolder( m_pManager );
+ if ( group.isNull() )
+ return; // user canceled i guess
+
+ KExtendedBookmarkOwner::QStringPairList::const_iterator it;
+ for ( it = list.begin(); it != list.end(); ++it )
+ group.addBookmark( m_pManager, (*it).first, KURL((*it).second) );
+
+ m_pManager->emitChanged( parentBookmark );
+}
+
+
+void KBookmarkMenu::slotAddBookmark()
+{
+ KBookmarkGroup parentBookmark;
+ parentBookmark = m_pManager->addBookmarkDialog(m_pOwner->currentURL(), m_pOwner->currentTitle(), m_parentAddress);
+ if (!parentBookmark.isNull())
+ m_pManager->emitChanged( parentBookmark );
+}
+
+void KBookmarkMenu::slotNewFolder()
+{
+ if ( !m_pOwner ) return; // this view doesn't handle bookmarks...
+ KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup();
+ Q_ASSERT(!parentBookmark.isNull());
+ KBookmarkGroup group = parentBookmark.createNewFolder( m_pManager );
+ if ( !group.isNull() )
+ {
+ KBookmarkGroup parentGroup = group.parentGroup();
+ m_pManager->emitChanged( parentGroup );
+ }
+}
+
+void KBookmarkMenu::slotBookmarkSelected( KAction::ActivationReason /*reason*/, Qt::ButtonState state )
+{
+ kdDebug(7043) << "KBookmarkMenu::slotBookmarkSelected()" << endl;
+ if ( !m_pOwner ) return; // this view doesn't handle bookmarks...
+ const KAction* action = dynamic_cast<const KAction *>(sender());
+ if(action)
+ {
+ const QString& url = sender()->property("url").toString();
+ m_pOwner->openBookmarkURL( url );
+ emit openBookmark( url, state );
+ }
+}
+
+void KBookmarkMenu::slotBookmarkSelected()
+{
+ slotBookmarkSelected(KAction::PopupMenuActivation, Qt::NoButton);
+}
+
+KExtendedBookmarkOwner* KBookmarkMenu::extOwner()
+{
+ return dynamic_cast<KExtendedBookmarkOwner*>(m_pOwner);
+}
+
+void KBookmarkMenu::slotNSLoad()
+{
+ // only fill menu once
+ m_parentMenu->disconnect(SIGNAL(aboutToShow()));
+
+ // not NSImporter, but kept old name for BC reasons
+ KBookmarkMenuNSImporter importer( m_pManager, this, m_actionCollection );
+ importer.openBookmarks(s_highlightedImportLocation, s_highlightedImportType);
+}
+
+/********************************************************************/
+/********************************************************************/
+/********************************************************************/
+
+KBookmarkEditFields::KBookmarkEditFields(QWidget *main, QBoxLayout *vbox, FieldsSet fieldsSet)
+{
+ bool isF = (fieldsSet != FolderFieldsSet);
+
+ QGridLayout *grid = new QGridLayout( vbox, 2, isF ? 2 : 1 );
+
+ m_title = new KLineEdit( main );
+ grid->addWidget( m_title, 0, 1 );
+ grid->addWidget( new QLabel( m_title, i18n( "Name:" ), main ), 0, 0 );
+ m_title->setFocus();
+ if (isF)
+ {
+ m_url = new KLineEdit( main );
+ grid->addWidget( m_url, 1, 1 );
+ grid->addWidget( new QLabel( m_url, i18n( "Location:" ), main ), 1, 0 );
+ }
+ else
+ {
+ m_url = 0;
+ }
+
+ main->setMinimumSize( 300, 0 );
+}
+
+void KBookmarkEditFields::setName(const QString &str)
+{
+ m_title->setText(str);
+}
+
+void KBookmarkEditFields::setLocation(const QString &str)
+{
+ m_url->setText(str);
+}
+
+/********************************************************************/
+/********************************************************************/
+/********************************************************************/
+
+// TODO - make the dialog use Properties as a title when in Modify mode... (dirk noticed the bug...)
+KBookmarkEditDialog::KBookmarkEditDialog(const QString& title, const QString& url, KBookmarkManager * mgr, BookmarkEditType editType, const QString& address,
+ QWidget * parent, const char * name, const QString& caption )
+ : KDialogBase(parent, name, true, caption,
+ (editType == InsertionMode) ? (User1|Ok|Cancel) : (Ok|Cancel),
+ Ok, false, KGuiItem()),
+ m_folderTree(0), m_mgr(mgr), m_editType(editType), m_address(address)
+{
+ setButtonOK( (editType == InsertionMode) ? KGuiItem( i18n( "&Add" ), "bookmark_add") : i18n( "&Update" ) );
+ if (editType == InsertionMode) {
+ setButtonGuiItem( User1, KGuiItem( i18n( "&New Folder..." ), "folder_new") );
+ }
+
+ bool folder = url.isNull();
+
+ m_main = new QWidget( this );
+ setMainWidget( m_main );
+
+ QBoxLayout *vbox = new QVBoxLayout( m_main, 0, spacingHint() );
+ KBookmarkEditFields::FieldsSet fs =
+ folder ? KBookmarkEditFields::FolderFieldsSet
+ : KBookmarkEditFields::BookmarkFieldsSet;
+ m_fields = new KBookmarkEditFields(m_main, vbox, fs);
+ m_fields->setName(title);
+ if ( !folder )
+ m_fields->setLocation(url);
+
+ if ( editType == InsertionMode )
+ {
+ m_folderTree = KBookmarkFolderTree::createTree( m_mgr, m_main, name, m_address );
+ connect( m_folderTree, SIGNAL( doubleClicked(QListViewItem*) ),
+ this, SLOT( slotDoubleClicked(QListViewItem*) ) );
+ vbox->addWidget( m_folderTree );
+ connect( this, SIGNAL( user1Clicked() ), SLOT( slotUser1() ) );
+ }
+}
+
+void KBookmarkEditDialog::slotDoubleClicked( QListViewItem* item )
+{
+ Q_ASSERT( m_folderTree );
+ m_folderTree->setCurrentItem( item );
+ accept();
+}
+
+void KBookmarkEditDialog::slotOk()
+{
+ accept();
+}
+
+void KBookmarkEditDialog::slotCancel()
+{
+ reject();
+}
+
+QString KBookmarkEditDialog::finalAddress() const
+{
+ Q_ASSERT( m_folderTree );
+ return KBookmarkFolderTree::selectedAddress( m_folderTree );
+}
+
+QString KBookmarkEditDialog::finalUrl() const
+{
+ return m_fields->m_url ? m_fields->m_url->text() : QString::null;
+}
+
+QString KBookmarkEditDialog::finalTitle() const
+{
+ return m_fields->m_title ? m_fields->m_title->text() : QString::null;
+}
+
+void KBookmarkEditDialog::slotUser1()
+{
+ // kdDebug(7043) << "KBookmarkEditDialog::slotUser1" << endl;
+ Q_ASSERT( m_folderTree );
+
+ QString address = KBookmarkFolderTree::selectedAddress( m_folderTree );
+ if ( address.isNull() ) return;
+ KBookmarkGroup bm = m_mgr->findByAddress( address ).toGroup();
+ Q_ASSERT(!bm.isNull());
+ Q_ASSERT(m_editType == InsertionMode);
+
+ KBookmarkGroup group = bm.createNewFolder( m_mgr );
+ if ( !group.isNull() )
+ {
+ KBookmarkGroup parentGroup = group.parentGroup();
+ m_mgr->emitChanged( parentGroup );
+ }
+ KBookmarkFolderTree::fillTree( m_folderTree, m_mgr );
+}
+
+/********************************************************************/
+/********************************************************************/
+/********************************************************************/
+
+static void fillGroup( QListView* listview, KBookmarkFolderTreeItem * parentItem, KBookmarkGroup group, bool expandOpenGroups = true, const QString& address = QString::null )
+{
+ bool noSubGroups = true;
+ KBookmarkFolderTreeItem * lastItem = 0L;
+ KBookmarkFolderTreeItem * item = 0L;
+ for ( KBookmark bk = group.first() ; !bk.isNull() ; bk = group.next(bk) )
+ {
+ if ( bk.isGroup() )
+ {
+ KBookmarkGroup grp = bk.toGroup();
+ item = new KBookmarkFolderTreeItem( parentItem, lastItem, grp );
+ fillGroup( listview, item, grp, expandOpenGroups, address );
+ if ( expandOpenGroups && grp.isOpen() )
+ item->setOpen( true );
+ lastItem = item;
+ noSubGroups = false;
+ }
+ if (bk.address() == address) {
+ listview->setCurrentItem( lastItem );
+ listview->ensureItemVisible( item );
+ }
+ }
+ if ( noSubGroups ) {
+ parentItem->setOpen( true );
+ }
+}
+
+QListView* KBookmarkFolderTree::createTree( KBookmarkManager* mgr, QWidget* parent, const char* name, const QString& address )
+{
+ QListView *listview = new QListView( parent, name );
+
+ listview->setRootIsDecorated( false );
+ listview->header()->hide();
+ listview->addColumn( i18n("Bookmark"), 200 );
+ listview->setSorting( -1, false );
+ listview->setSelectionMode( QListView::Single );
+ listview->setAllColumnsShowFocus( true );
+ listview->setResizeMode( QListView::AllColumns );
+ listview->setMinimumSize( 60, 100 );
+
+ fillTree( listview, mgr, address );
+
+ return listview;
+}
+
+void KBookmarkFolderTree::fillTree( QListView *listview, KBookmarkManager* mgr, const QString& address )
+{
+ listview->clear();
+
+ KBookmarkGroup root = mgr->root();
+ KBookmarkFolderTreeItem * rootItem = new KBookmarkFolderTreeItem( listview, root );
+ listview->setCurrentItem( rootItem );
+ rootItem->setSelected( true );
+ fillGroup( listview, rootItem, root, (address == root.groupAddress() || address.isNull()) ? true : false, address );
+ rootItem->setOpen( true );
+}
+
+static KBookmarkFolderTreeItem* ft_cast( QListViewItem *i )
+{
+ return static_cast<KBookmarkFolderTreeItem*>( i );
+}
+
+QString KBookmarkFolderTree::selectedAddress( QListView *listview )
+{
+ if ( !listview)
+ return QString::null;
+ KBookmarkFolderTreeItem *item = ft_cast( listview->currentItem() );
+ return item ? item->m_bookmark.address() : QString::null;
+}
+
+void KBookmarkFolderTree::setAddress( QListView *listview, const QString & address )
+{
+ KBookmarkFolderTreeItem* it = ft_cast( listview->firstChild() );
+ while ( true ) {
+ kdDebug(7043) << it->m_bookmark.address() << endl;
+ it = ft_cast( it->itemBelow() );
+ if ( !it )
+ return;
+ if ( it->m_bookmark.address() == address )
+ break;
+ }
+ it->setSelected( true );
+ listview->setCurrentItem( it );
+}
+
+/********************************************************************/
+/********************************************************************/
+/********************************************************************/
+
+// toplevel item
+KBookmarkFolderTreeItem::KBookmarkFolderTreeItem( QListView *parent, const KBookmark & gp )
+ : QListViewItem(parent, i18n("Bookmarks")), m_bookmark(gp)
+{
+ setPixmap(0, SmallIcon("bookmark"));
+ setExpandable(true);
+}
+
+// group
+KBookmarkFolderTreeItem::KBookmarkFolderTreeItem( KBookmarkFolderTreeItem *parent, QListViewItem *after, const KBookmarkGroup & gp )
+ : QListViewItem(parent, after, gp.fullText()), m_bookmark(gp)
+{
+ setPixmap(0, SmallIcon( gp.icon() ) );
+ setExpandable(true);
+}
+
+/********************************************************************/
+/********************************************************************/
+/********************************************************************/
+
+// NOTE - KBookmarkMenuNSImporter is really === KBookmarkMenuImporter
+// i.e, it is _not_ ns specific. and in KDE4 it should be renamed.
+
+void KBookmarkMenuNSImporter::openNSBookmarks()
+{
+ openBookmarks( KNSBookmarkImporter::netscapeBookmarksFile(), "netscape" );
+}
+
+void KBookmarkMenuNSImporter::openBookmarks( const QString &location, const QString &type )
+{
+ mstack.push(m_menu);
+
+ KBookmarkImporterBase *importer = KBookmarkImporterBase::factory(type);
+ if (!importer)
+ return;
+ importer->setFilename(location);
+ connectToImporter(*importer);
+ importer->parse();
+
+ delete importer;
+}
+
+void KBookmarkMenuNSImporter::connectToImporter(const QObject &importer)
+{
+ connect( &importer, SIGNAL( newBookmark( const QString &, const QCString &, const QString & ) ),
+ SLOT( newBookmark( const QString &, const QCString &, const QString & ) ) );
+ connect( &importer, SIGNAL( newFolder( const QString &, bool, const QString & ) ),
+ SLOT( newFolder( const QString &, bool, const QString & ) ) );
+ connect( &importer, SIGNAL( newSeparator() ), SLOT( newSeparator() ) );
+ connect( &importer, SIGNAL( endFolder() ), SLOT( endFolder() ) );
+}
+
+void KBookmarkMenuNSImporter::newBookmark( const QString & text, const QCString & url, const QString & )
+{
+ QString _text = KStringHandler::csqueeze(text);
+ _text.replace( '&', "&&" );
+ KAction * action = new KBookmarkAction(_text, "html", 0, 0, "", m_actionCollection, 0);
+ connect(action, SIGNAL( activated ( KAction::ActivationReason, Qt::ButtonState )),
+ m_menu, SLOT( slotBookmarkSelected( KAction::ActivationReason, Qt::ButtonState ) ));
+ action->setProperty( "url", url );
+ action->setToolTip( url );
+ action->plug( mstack.top()->m_parentMenu );
+ mstack.top()->m_actions.append( action );
+}
+
+void KBookmarkMenuNSImporter::newFolder( const QString & text, bool, const QString & )
+{
+ QString _text = KStringHandler::csqueeze(text);
+ _text.replace( '&', "&&" );
+ KActionMenu * actionMenu = new KActionMenu( _text, "folder", m_actionCollection, 0L );
+ actionMenu->plug( mstack.top()->m_parentMenu );
+ mstack.top()->m_actions.append( actionMenu );
+ KBookmarkMenu *subMenu = new KBookmarkMenu( m_pManager, m_menu->m_pOwner, actionMenu->popupMenu(),
+ m_actionCollection, false,
+ m_menu->m_bAddBookmark, QString::null );
+ connect( subMenu, SIGNAL( openBookmark( const QString &, Qt::ButtonState ) ),
+ m_menu, SIGNAL( openBookmark( const QString &, Qt::ButtonState ) ));
+ mstack.top()->m_lstSubMenus.append( subMenu );
+
+ mstack.push(subMenu);
+}
+
+void KBookmarkMenuNSImporter::newSeparator()
+{
+ mstack.top()->m_parentMenu->insertSeparator();
+}
+
+void KBookmarkMenuNSImporter::endFolder()
+{
+ mstack.pop();
+}
+
+/********************************************************************/
+/********************************************************************/
+/********************************************************************/
+
+KBookmarkMenu::DynMenuInfo KBookmarkMenu::showDynamicBookmarks( const QString &id )
+{
+ KConfig config("kbookmarkrc", false, false);
+ config.setGroup("Bookmarks");
+
+ DynMenuInfo info;
+ info.show = false;
+
+ if (!config.hasKey("DynamicMenus")) {
+ // upgrade path
+ if (id == "netscape") {
+ KBookmarkManager *manager = KBookmarkManager::userBookmarksManager();
+ info.show = manager->root().internalElement().attribute("hide_nsbk") != "yes";
+ info.location = KNSBookmarkImporter::netscapeBookmarksFile();
+ info.type = "netscape";
+ info.name = i18n("Netscape Bookmarks");
+ } // else, no show
+
+ } else {
+ // have new version config
+ if (config.hasGroup("DynamicMenu-" + id)) {
+ config.setGroup("DynamicMenu-" + id);
+ info.show = config.readBoolEntry("Show");
+ info.location = config.readPathEntry("Location");
+ info.type = config.readEntry("Type");
+ info.name = config.readEntry("Name");
+ } // else, no show
+ }
+
+ return info;
+}
+
+QStringList KBookmarkMenu::dynamicBookmarksList()
+{
+ KConfig config("kbookmarkrc", false, false);
+ config.setGroup("Bookmarks");
+
+ QStringList mlist;
+ if (config.hasKey("DynamicMenus"))
+ mlist = config.readListEntry("DynamicMenus");
+ else
+ mlist << "netscape";
+
+ return mlist;
+}
+
+void KBookmarkMenu::setDynamicBookmarks(const QString &id, const DynMenuInfo &newMenu)
+{
+ KConfig config("kbookmarkrc", false, false);
+
+ // add group unconditionally
+ config.setGroup("DynamicMenu-" + id);
+ config.writeEntry("Show", newMenu.show);
+ config.writePathEntry("Location", newMenu.location);
+ config.writeEntry("Type", newMenu.type);
+ config.writeEntry("Name", newMenu.name);
+
+ QStringList elist;
+
+ config.setGroup("Bookmarks");
+ if (!config.hasKey("DynamicMenus")) {
+ if (newMenu.type != "netscape") {
+ // update from old xbel method to new rc method
+ // though only if not writing the netscape setting
+ config.setGroup("DynamicMenu-" "netscape");
+ DynMenuInfo xbelSetting;
+ xbelSetting = showDynamicBookmarks("netscape");
+ config.writeEntry("Show", xbelSetting.show);
+ config.writePathEntry("Location", xbelSetting.location);
+ config.writeEntry("Type", xbelSetting.type);
+ config.writeEntry("Name", xbelSetting.name);
+ }
+ } else {
+ elist = config.readListEntry("DynamicMenus");
+ }
+
+ // make sure list includes type
+ config.setGroup("Bookmarks");
+ if (elist.contains(id) < 1) {
+ elist << id;
+ config.writeEntry("DynamicMenus", elist);
+ }
+
+ config.sync();
+}
+
+#include "kbookmarkmenu.moc"
+#include "kbookmarkmenu_p.moc"
diff --git a/kio/bookmarks/kbookmarkmenu.h b/kio/bookmarks/kbookmarkmenu.h
new file mode 100644
index 000000000..0a1ca1f24
--- /dev/null
+++ b/kio/bookmarks/kbookmarkmenu.h
@@ -0,0 +1,265 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kbookmarkmenu_h__
+#define __kbookmarkmenu_h__
+
+#include <sys/types.h>
+
+#include <qptrlist.h>
+#include <qptrstack.h>
+#include <qobject.h>
+#include <qlistview.h>
+
+#include <kdialogbase.h>
+#include <klocale.h>
+#include <kaction.h>
+
+#include "kbookmark.h"
+#include "kbookmarkmanager.h"
+
+class QString;
+class QPopupMenu;
+class QPushButton;
+class QListView;
+class KLineEdit;
+class KBookmark;
+class KBookmarkGroup;
+class KAction;
+class KActionMenu;
+class KActionCollection;
+class KBookmarkOwner;
+class KBookmarkMenu;
+class KPopupMenu;
+
+namespace KIO { class Job; }
+
+/**
+ * This class provides a bookmark menu. It is typically used in
+ * cooperation with KActionMenu but doesn't have to be.
+ *
+ * If you use this class by itself, then it will use KDE defaults for
+ * everything -- the bookmark path, bookmark editor, bookmark launcher..
+ * everything. These defaults reside in the classes
+ * KBookmarkOwner (editing bookmarks) and KBookmarkManager
+ * (almost everything else). If you wish to change the defaults in
+ * any way, you must reimplement and instantiate those classes
+ * <em>before</em> this class is ever called.
+ *
+ * Using this class is very simple:
+ *
+ * 1) Create a popup menu (either KActionMenu or KPopupMenu will do)
+ * 2) Instantiate a new KBookmarkMenu object using the above popup
+ * menu as a parameter
+ * 3) Insert your (now full) popup menu wherever you wish
+ *
+ * Again, if you wish to modify any defaults, the procedure is:
+ *
+ * 1a) Reimplement your own KBookmarkOwner
+ * 1b) Reimplement and instantiate your own KBookmarkManager
+ */
+class KIO_EXPORT KBookmarkMenu : public QObject
+{
+ Q_OBJECT
+ friend class KBookmarkMenuNSImporter;
+ friend class RMB;
+public:
+ /**
+ * Fills a bookmark menu
+ * (one instance of KBookmarkMenu is created for the toplevel menu,
+ * but also one per submenu).
+ *
+ * @param mgr The bookmark manager to use (i.e. for reading and writing)
+ * @param owner implementation of the KBookmarkOwner callback interface.
+ * @param parentMenu menu to be filled
+ * @param collec parent collection for the KActions.
+ * Only used for other menus than the toplevel one.
+ * @param root true for the toplevel menu
+ * @param add true to show the "Add Bookmark" and "New Folder" entries
+ * @param parentAddress the address of the group containing the items
+ * that we want to show.
+ * @see KBookmark::address.
+ * Be careful :
+ * A _null_ parentAddress denotes a NS-bookmark menu.
+ * An _empty_ parentAddress denotes the toplevel bookmark menu
+ */
+ KBookmarkMenu( KBookmarkManager* mgr,
+ KBookmarkOwner * owner, KPopupMenu * parentMenu,
+ KActionCollection * collec, bool root, bool add = true,
+ const QString & parentAddress = "" );
+
+ ~KBookmarkMenu();
+
+ /**
+ * Even if you think you need to use this, you are probably wrong.
+ * It fills a bookmark menu starting a given KBookmark.
+ * This is public for KBookmarkBar.
+ */
+ void fillBookmarkMenu();
+
+ /**
+ * Call ensureUpToDate() if you need KBookmarkMenu to adjust to its
+ * final size before it is executed.
+ **/
+ void ensureUpToDate();
+
+ /**
+ * Structure used for storing information about
+ * the dynamic menu setting
+ * @since 3.2
+ */
+ // TODO - transform into class
+ struct DynMenuInfo {
+ bool show;
+ QString location;
+ QString type;
+ QString name;
+ class DynMenuInfoPrivate *d;
+ };
+
+ /**
+ * @return dynmenu info block for the given dynmenu name
+ * @since 3.2
+ */
+ static DynMenuInfo showDynamicBookmarks( const QString &id );
+
+ /**
+ * Shows an extra menu for the given bookmarks file and type.
+ * Upgrades from option inside XBEL to option in rc file
+ * on first call of this function.
+ * @param id the unique identification for the dynamic menu
+ * @param info a DynMenuInfo struct containing the to be added/modified data
+ * @since 3.2
+ */
+ static void setDynamicBookmarks( const QString &id, const DynMenuInfo &info );
+
+ /**
+ * @return list of dynamic menu ids
+ * @since 3.2
+ */
+ static QStringList dynamicBookmarksList();
+
+signals:
+ void aboutToShowContextMenu( const KBookmark &, QPopupMenu * );
+ /**
+ * @since 3.4
+ */
+ void openBookmark( const QString& url, Qt::ButtonState state );
+
+public slots: // public for bookmark bar
+ void slotBookmarksChanged( const QString & );
+
+protected slots:
+ void slotAboutToShow();
+ void slotAboutToShowContextMenu( KPopupMenu *, int, QPopupMenu * );
+ void slotActionHighlighted( KAction * );
+
+ void slotRMBActionRemove( int );
+ void slotRMBActionInsert( int );
+ void slotRMBActionCopyLocation( int );
+ void slotRMBActionEditAt( int );
+ void slotRMBActionProperties( int );
+
+ void slotBookmarkSelected();
+ /**
+ * @ since 3.4
+ */
+ void slotBookmarkSelected( KAction::ActivationReason reason, Qt::ButtonState state );
+ void slotAddBookmarksList();
+ void slotAddBookmark();
+ void slotNewFolder();
+
+ /**
+ * load Netscape's bookmarks
+ */
+ void slotNSLoad();
+
+protected:
+ KExtendedBookmarkOwner* extOwner();
+ void refill();
+ void addAddBookmark();
+ void addAddBookmarksList();
+ void addEditBookmarks();
+ void addNewFolder();
+
+ void fillContextMenu( QPopupMenu *, const QString &, int );
+
+ bool m_bIsRoot:1;
+ bool m_bAddBookmark:1;
+ bool m_bDirty:1;
+ bool m_bNSBookmark:1;
+ bool m_bAddShortcuts:1;
+
+ KBookmarkManager * m_pManager;
+ KBookmarkOwner *m_pOwner;
+ /**
+ * The menu in which we plug our actions.
+ * Supplied in the constructor.
+ */
+ KPopupMenu * m_parentMenu;
+ /**
+ * List of our sub menus
+ */
+ QPtrList<KBookmarkMenu> m_lstSubMenus;
+ KActionCollection * m_actionCollection;
+ /**
+ * List of our actions.
+ */
+ QPtrList<KAction> m_actions;
+ /**
+ * Parent bookmark for this menu.
+ */
+ QString m_parentAddress;
+
+ // TODO make non static!
+ static QString s_highlightedAddress;
+ static QString s_highlightedImportLocation;
+ static QString s_highlightedImportType;
+};
+
+/**
+ * A class connected to KNSBookmarkImporter, to fill KActionMenus.
+ */
+class KIO_EXPORT KBookmarkMenuNSImporter : public QObject
+{
+ Q_OBJECT
+public:
+ KBookmarkMenuNSImporter( KBookmarkManager* mgr, KBookmarkMenu * menu, KActionCollection * act ) :
+ m_menu(menu), m_actionCollection(act), m_pManager(mgr) {}
+
+ void openNSBookmarks();
+ void openBookmarks( const QString &location, const QString &type );
+ void connectToImporter( const QObject &importer );
+
+protected slots:
+ void newBookmark( const QString & text, const QCString & url, const QString & );
+ void newFolder( const QString & text, bool, const QString & );
+ void newSeparator();
+ void endFolder();
+
+protected:
+ QPtrStack<KBookmarkMenu> mstack;
+ KBookmarkMenu * m_menu;
+ KActionCollection * m_actionCollection;
+ KBookmarkManager* m_pManager;
+};
+
+#endif
diff --git a/kio/bookmarks/kbookmarkmenu_p.h b/kio/bookmarks/kbookmarkmenu_p.h
new file mode 100644
index 000000000..1c3f15ba8
--- /dev/null
+++ b/kio/bookmarks/kbookmarkmenu_p.h
@@ -0,0 +1,224 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE project
+ Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kbookmarkmenu_p_h__
+#define __kbookmarkmenu_p_h__
+
+#include <sys/types.h>
+
+#include <qptrlist.h>
+#include <qptrstack.h>
+#include <qobject.h>
+#include <qlistview.h>
+
+#include <kdialogbase.h>
+#include <klocale.h>
+#include <kaction.h>
+
+#include "kbookmark.h"
+#include "kbookmarkimporter.h"
+#include "kbookmarkmanager.h"
+
+class QString;
+class QPopupMenu;
+class QPushButton;
+class QListView;
+class KLineEdit;
+class KBookmark;
+class KBookmarkGroup;
+class KAction;
+class KActionMenu;
+class KActionCollection;
+class KBookmarkOwner;
+class KBookmarkMenu;
+class KBookmarkBar;
+class KPopupMenu;
+
+class KImportedBookmarksActionMenu : public KActionMenu {
+ Q_OBJECT
+ Q_PROPERTY( QString type READ type WRITE setType )
+ Q_PROPERTY( QString location READ location WRITE setLocation )
+public:
+ const QString type() const { return m_type; }
+ void setType(const QString &type) { m_type = type; }
+ const QString location() const { return m_location; }
+ void setLocation(const QString &location) { m_location = location; }
+private:
+ QString m_type;
+ QString m_location;
+public:
+ KImportedBookmarksActionMenu(
+ const QString &text, const QString& sIconName,
+ KActionCollection* parent, const char* name)
+ : KActionMenu(text, sIconName, parent, name) {
+ ;
+ }
+};
+
+class KBookmarkActionMenu : public KActionMenu {
+ Q_OBJECT
+ Q_PROPERTY( QString url READ url WRITE setUrl )
+ Q_PROPERTY( QString address READ address WRITE setAddress )
+ Q_PROPERTY( bool readOnly READ readOnly WRITE setReadOnly )
+public:
+ const QString url() const { return m_url; }
+ void setUrl(const QString &url) { m_url = url; }
+ const QString address() const { return m_address; }
+ void setAddress(const QString &address) { m_address = address; }
+ bool readOnly() const { return m_readOnly; }
+ void setReadOnly(bool readOnly) { m_readOnly = readOnly; }
+private:
+ QString m_url;
+ QString m_address;
+ bool m_readOnly;
+public:
+ KBookmarkActionMenu(
+ const QString &text, const QString& sIconName,
+ KActionCollection* parent, const char* name)
+ : KActionMenu(text, sIconName, parent, name) {
+ ;
+ }
+};
+
+class KBookmarkAction : public KAction {
+ Q_OBJECT
+ Q_PROPERTY( QString url READ url WRITE setUrl )
+ Q_PROPERTY( QString address READ address WRITE setAddress )
+public:
+ const QString url() const { return m_url; }
+ void setUrl(const QString &url) { m_url = url; }
+ const QString address() const { return m_address; }
+ void setAddress(const QString &address) { m_address = address; }
+private:
+ QString m_url;
+ QString m_address;
+public:
+ // KDE4: remove
+ KBookmarkAction(
+ const QString& text, const QString& sIconName, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ KActionCollection* parent, const char* name)
+ : KAction(text, sIconName, cut, receiver, slot, parent, name) {
+ }
+ KBookmarkAction(
+ const QString& text, const QString& sIconName, const KShortcut& cut,
+ KActionCollection* parent, const char* name)
+ : KAction(text, sIconName, cut, parent, name) {
+ }
+};
+
+class KBookmarkEditFields {
+public:
+ typedef enum { FolderFieldsSet, BookmarkFieldsSet } FieldsSet;
+ KLineEdit * m_url;
+ KLineEdit * m_title;
+ KBookmarkEditFields(QWidget *main, QBoxLayout *vbox, FieldsSet isFolder);
+ void setName(const QString &str);
+ void setLocation(const QString &str);
+};
+
+class KBookmarkEditDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ typedef enum { ModifyMode, InsertionMode } BookmarkEditType;
+
+ KBookmarkEditDialog( const QString& title, const QString& url, KBookmarkManager *, BookmarkEditType editType, const QString& address = QString::null,
+ QWidget * = 0, const char * = 0, const QString& caption = i18n( "Add Bookmark" ) );
+
+ QString finalUrl() const;
+ QString finalTitle() const;
+ QString finalAddress() const;
+
+protected slots:
+ void slotOk();
+ void slotCancel();
+ void slotUser1();
+ void slotDoubleClicked(QListViewItem* item);
+
+private:
+ QWidget * m_main;
+ KBookmarkEditFields * m_fields;
+ QListView * m_folderTree;
+ QPushButton * m_button;
+ KBookmarkManager * m_mgr;
+ BookmarkEditType m_editType;
+ QString m_address;
+};
+
+class KBookmarkFolderTreeItem : public QListViewItem
+{
+ // make this an accessor
+ friend class KBookmarkFolderTree;
+public:
+ KBookmarkFolderTreeItem( QListView *, const KBookmark & );
+ KBookmarkFolderTreeItem( KBookmarkFolderTreeItem *, QListViewItem *, const KBookmarkGroup & );
+private:
+ KBookmark m_bookmark;
+};
+
+class KBookmarkFolderTree
+{
+public:
+ static QListView* createTree( KBookmarkManager *, QWidget * = 0, const char * = 0, const QString& = QString::null );
+ static void fillTree( QListView*, KBookmarkManager *, const QString& = QString::null );
+ static QString selectedAddress( QListView* );
+ static void setAddress( QListView *, const QString & );
+};
+
+class KBookmarkSettings
+{
+public:
+ bool m_advancedaddbookmark;
+ bool m_contextmenu;
+ bool m_quickactions;
+ bool m_filteredtoolbar;
+ static KBookmarkSettings *s_self;
+ static void readSettings();
+ static KBookmarkSettings *self();
+};
+
+class RMB
+{
+public:
+ static void begin_rmb_action(KBookmarkMenu *);
+ static void begin_rmb_action(KBookmarkBar *);
+ bool invalid( int val );
+ KBookmark atAddress(const QString & address);
+ void fillContextMenu( QPopupMenu* contextMenu, const QString & address, int val );
+ void fillContextMenu2( QPopupMenu* contextMenu, const QString & address, int val );
+ void slotRMBActionEditAt( int val );
+ void slotRMBActionProperties( int val );
+ void slotRMBActionInsert( int val );
+ void slotRMBActionRemove( int val );
+ void slotRMBActionCopyLocation( int val );
+ void hidePopup();
+public:
+ QObject *recv;
+ KBookmarkManager *m_pManager;
+ QString s_highlightedAddress;
+ QString m_parentAddress;
+ KBookmarkOwner *m_pOwner;
+ QWidget *m_parentMenu;
+};
+
+#endif
diff --git a/kio/bookmarks/kbookmarknotifier.h b/kio/bookmarks/kbookmarknotifier.h
new file mode 100644
index 000000000..6a16fa052
--- /dev/null
+++ b/kio/bookmarks/kbookmarknotifier.h
@@ -0,0 +1,45 @@
+// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE libraries
+ Copyright (C) 2001, 2003 Alexander Kellett <lypanov@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kbookmarknotifier_h__
+#define __kbookmarknotifier_h__
+
+#include <dcopobject.h>
+
+/**
+ * DCOP interface for a bookmark notifier (an object which emits signals
+ * upon changes to the bookmarks)
+ */
+class KIO_EXPORT KBookmarkNotifier : virtual public DCOPObject
+{
+ K_DCOP
+
+public:
+ KBookmarkNotifier(QCString objId = "KBookmarkNotifier") : DCOPObject(objId) {}
+
+k_dcop_signals:
+ void addedBookmark( QString filename, QString url, QString text, QString address, QString icon );
+ void createdNewFolder( QString filename, QString text, QString address );
+ void updatedAccessMetadata( QString filename, QString url );
+};
+
+#endif
+