summaryrefslogtreecommitdiffstats
path: root/konqueror/keditbookmarks
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit4aed2c8219774f5d797760606b8489a92ddc5163 (patch)
tree3f8c130f7d269626bf6a9447407ef6c35954426a /konqueror/keditbookmarks
downloadtdebase-4aed2c8219774f5d797760606b8489a92ddc5163.tar.gz
tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'konqueror/keditbookmarks')
-rw-r--r--konqueror/keditbookmarks/DESIGN20
-rw-r--r--konqueror/keditbookmarks/Makefile.am34
-rw-r--r--konqueror/keditbookmarks/TODO120
-rw-r--r--konqueror/keditbookmarks/actionsimpl.cpp638
-rw-r--r--konqueror/keditbookmarks/actionsimpl.h83
-rw-r--r--konqueror/keditbookmarks/bookmarkinfo.cpp293
-rw-r--r--konqueror/keditbookmarks/bookmarkinfo.h111
-rw-r--r--konqueror/keditbookmarks/bookmarkiterator.cpp105
-rw-r--r--konqueror/keditbookmarks/bookmarkiterator.h74
-rw-r--r--konqueror/keditbookmarks/commands.cpp745
-rw-r--r--konqueror/keditbookmarks/commands.h256
-rw-r--r--konqueror/keditbookmarks/cr16-app-keditbookmarks.pngbin0 -> 916 bytes
-rw-r--r--konqueror/keditbookmarks/cr32-app-keditbookmarks.pngbin0 -> 1636 bytes
-rw-r--r--konqueror/keditbookmarks/cr48-app-keditbookmarks.pngbin0 -> 2663 bytes
-rw-r--r--konqueror/keditbookmarks/cr64-app-keditbookmarks.pngbin0 -> 5042 bytes
-rw-r--r--konqueror/keditbookmarks/dcop.cpp67
-rw-r--r--konqueror/keditbookmarks/dcop.h36
-rw-r--r--konqueror/keditbookmarks/exporters.cpp90
-rw-r--r--konqueror/keditbookmarks/exporters.h39
-rw-r--r--konqueror/keditbookmarks/favicons.cpp100
-rw-r--r--konqueror/keditbookmarks/favicons.h69
-rw-r--r--konqueror/keditbookmarks/importers.cpp293
-rw-r--r--konqueror/keditbookmarks/importers.h192
-rw-r--r--konqueror/keditbookmarks/kbookmarkmerger.cpp138
-rw-r--r--konqueror/keditbookmarks/kebsearchline.cpp82
-rw-r--r--konqueror/keditbookmarks/kebsearchline.h52
-rw-r--r--konqueror/keditbookmarks/keditbookmarks-genui.rc146
-rw-r--r--konqueror/keditbookmarks/keditbookmarks.kcfg42
-rw-r--r--konqueror/keditbookmarks/keditbookmarksui.rc218
-rw-r--r--konqueror/keditbookmarks/kinsertionsort.h59
-rw-r--r--konqueror/keditbookmarks/listview.cpp968
-rw-r--r--konqueror/keditbookmarks/listview.h217
-rw-r--r--konqueror/keditbookmarks/main.cpp199
-rw-r--r--konqueror/keditbookmarks/settings.kcfgc4
-rw-r--r--konqueror/keditbookmarks/testlink.cpp395
-rw-r--r--konqueror/keditbookmarks/testlink.h75
-rw-r--r--konqueror/keditbookmarks/toplevel.cpp356
-rw-r--r--konqueror/keditbookmarks/toplevel.h175
-rw-r--r--konqueror/keditbookmarks/uninstall.desktop2
-rw-r--r--konqueror/keditbookmarks/updater.cpp180
-rw-r--r--konqueror/keditbookmarks/updater.h91
41 files changed, 6764 insertions, 0 deletions
diff --git a/konqueror/keditbookmarks/DESIGN b/konqueror/keditbookmarks/DESIGN
new file mode 100644
index 000000000..9ef300f81
--- /dev/null
+++ b/konqueror/keditbookmarks/DESIGN
@@ -0,0 +1,20 @@
+four main layers:
+ toplevel : startup, initialisation
+ listview : listview, selection, action forwarding
+ commands : bookmark undo/redo mechanism implementation
+ actionsimpl : the actual slots, almost all of 'em
+
+various other thingies:
+ search : incremental search implementation
+ favicons : iterating action implementation using bookmarkiterator
+ importers : forwarders to kio/bookmarks code
+ exporters : forwarders to kio/bookmarks code, and html export code
+ dcop : dcop handling, internal interface
+ bookmarkiterator : is a baseclass for iterating actions, of sorts...
+ updater : favicon updating base stuff - kio/khtml crap
+ testlink : link testing stuff
+
+3 different selection styles:
+ bookmark iterators (ITR_ACTION)
+ single bookmark (ITEM_ACTION)
+ normal selection (SELC_ACTION)
diff --git a/konqueror/keditbookmarks/Makefile.am b/konqueror/keditbookmarks/Makefile.am
new file mode 100644
index 000000000..3987d5944
--- /dev/null
+++ b/konqueror/keditbookmarks/Makefile.am
@@ -0,0 +1,34 @@
+INCLUDES= -I$(top_srcdir)/libkonq $(all_includes)
+
+METASOURCES = AUTO
+
+bin_PROGRAMS = kbookmarkmerger
+lib_LTLIBRARIES =
+kdeinit_LTLIBRARIES = keditbookmarks.la
+
+kbookmarkmerger_SOURCES = kbookmarkmerger.cpp
+kbookmarkmerger_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+kbookmarkmerger_LDADD = $(LIB_KIO)
+
+dcop_DCOPIDLNG = true
+keditbookmarks_la_SOURCES = main.cpp listview.cpp toplevel.cpp actionsimpl.cpp commands.cpp importers.cpp dcop.skel dcop.cpp bookmarkiterator.cpp \
+ testlink.cpp favicons.cpp updater.cpp exporters.cpp kbookmarknotifier.stub bookmarkinfo.cpp kebsearchline.cpp settings.kcfgc
+kbookmarknotifier_DIR = $(includedir)
+keditbookmarks_la_LIBADD = $(top_builddir)/libkonq/libkonq.la
+keditbookmarks_la_LDFLAGS = $(all_libraries) -module -avoid-version
+
+rcdir = $(kde_datadir)/keditbookmarks
+rc_DATA = keditbookmarksui.rc keditbookmarks-genui.rc
+
+install-data-local: uninstall.desktop
+ $(mkinstalldirs) $(DESTDIR)$(kde_appsdir)/Internet
+ $(INSTALL_DATA) $(srcdir)/uninstall.desktop $(DESTDIR)$(kde_appsdir)/Internet/keditbookmarks.desktop
+
+KDE_ICON = AUTO
+
+kde_kcfg_DATA = keditbookmarks.kcfg
+
+####### Build rules
+listview.lo: settings.h
+settings.lo: settings.h
+toplevel.lo: settings.h
diff --git a/konqueror/keditbookmarks/TODO b/konqueror/keditbookmarks/TODO
new file mode 100644
index 000000000..875dea715
--- /dev/null
+++ b/konqueror/keditbookmarks/TODO
@@ -0,0 +1,120 @@
+toolbar is not updating on save in editor
+editor does not have undo after save
+deleting folders from the quick actions menu is b0rked
+
+(#1)
+68161 : Favicons are lost on upgrade
+ - nothing to do with bookmarks, but, no idea where to put it,
+ so, whatever, i'll handle it anyways...
+
+ - problem: .kde/share/cache/favicons moved to .kde/`hostname`-cache/favicons
+
+ - fix: either 1) a symlink, 2) upgrade path
+
+67635 : Bookmarks toolbar edits don't take effect until restart
+ - completely unable to confirm, and can't recall fixing this in the past.. umm..
+
+67614 : abort bookmark's context menu causes bookmark to load
+ - can't reproduce... maybe a new / old qt bug...
+
+67686 : bookmark bar first displayed empty
+ - can't reproduce, maybe need to check from an empty .kde, thus no previous
+
+67958 : bookmark toolbar intermittenly disappears
+ - maybe just another dup of tokoe's bug
+
+67685 : crash often kills bookmarks AND backup
+ - how the heck does a crash wipe the bookmarks.xml in the first place?
+ well, whatever. i admit this can be improved, but only through new i18n's
+ so thats not going to happen until i get permission for 3.2.1...
+
+somehow multi selected deletes are broken again:
+ no longer crashes, but doesn't select current well
+ TODO note added to program, quite a difficult problem...
+a selected folder only takes one click to get a rename???
+tbcache: don't create a tbcache file when its gonna be empty in any case!!!
+historymgr: get dirtyness working for the kbookmarkmap
+proper readonly support - rmb should work but things should be disabled? no addbookmark, etc.
+general xbel bug: http://bugzilla.gnome.org/show_bug.cgi?id=69702
+
+possible qt bug:
+ multi selection deletion then shift down selects roots
+ valgrind doesn't show anything either
+ logging all the setSelected calls i can see doesn't help
+
+STUFF FROM BEINERI:
+
+ And the "Cancel" entries in the "Bookmark" menus looks strange too. How about
+ a KMail-like progress bar (in a status bar?) with an "X" button to stop them?
+ And "Advanced Add Bookmark" doesn't work for "Add Bookmark" in context menu?
+
+---
+
+ Btw, I think when you have no tab and call "Bookmarks Tabs as Folder..."
+ it should not only create a folder but bookmark the current page within
+ the folder unconditional if it's a tab or not. :-)
+
+CHECKS
+------
+
+valgrind report:
+
+on startup:
+ ==31246== Conditional jump or move depends on uninitialised value(s)
+ ==31246== at 0x4026A4DF: KEBListViewItem::paintCell(QPainter*, QColorGroup const&, int, int, int) (listview.cpp:786)
+ ==31246== by 0x40FD9CA7: QListView::drawContentsOffset(QPainter*, int, int, int, int, int, int) (qlistview.cpp:2905)
+ ==31246== by 0x41013A5D: QScrollView::viewportPaintEvent(QPaintEvent*) (qscrollview.cpp:1702)
+ ==31246== by 0x407E7051: KListView::viewportPaintEvent(QPaintEvent*) (klistview.cpp:1872)
+ ==31246==
+ ==31246== Conditional jump or move depends on uninitialised value(s)
+ ==31246== at 0x4026A4E4: KEBListViewItem::paintCell(QPainter*, QColorGroup const&, int, int, int) (listview.cpp:786)
+ ==31246== by 0x40FD9CA7: QListView::drawContentsOffset(QPainter*, int, int, int, int, int, int) (qlistview.cpp:2905)
+ ==31246== by 0x41013A5D: QScrollView::viewportPaintEvent(QPaintEvent*) (qscrollview.cpp:1702)
+ ==31246== by 0x407E7051: KListView::viewportPaintEvent(QPaintEvent*) (klistview.cpp:1872)
+ ==31246==
+ ==31246== Conditional jump or move depends on uninitialised value(s)
+ ==31246== at 0x4026A4E8: KEBListViewItem::paintCell(QPainter*, QColorGroup const&, int, int, int) (listview.cpp:786)
+ ==31246== by 0x40FD9CA7: QListView::drawContentsOffset(QPainter*, int, int, int, int, int, int) (qlistview.cpp:2905)
+ ==31246== by 0x41013A5D: QScrollView::viewportPaintEvent(QPaintEvent*) (qscrollview.cpp:1702)
+ ==31246== by 0x407E7051: KListView::viewportPaintEvent(QPaintEvent*) (klistview.cpp:1872)
+ ==31246==
+
+lots of crap when using file->open
+
+with memcheck
+ ==20415== 420 bytes in 14 blocks are definitely lost in loss record 107 of 146
+ ==20415== at 0x40029B01: __builtin_new (in /usr/lib/valgrind/vgskin_memcheck.so)
+ ==20415== by 0x40029B6C: operator new(unsigned) (in /usr/lib/valgrind/vgskin_memcheck.so)
+ ==20415== by 0x402669AA: KEBListView::itemList() (listview.cpp:682)
+ ==20415== by 0x402634EA: ListView::selectedItems() const (qptrlist.h:157)
+
+
+DONE TESTING:
+------------
+
+ favicon and status check updates:
+ removal of items while checks are happening
+ program exit with checks and updates are still going on
+ random deletion of all items - TODO
+
+THINGS FOR 3.3+
+------------------
+
+tools:
+ recursive 404 finder
+ duplicate finder
+
+basic gui:
+ split view stuff - including filtered views
+ need to get keyboard shortcut changes working somehow (wheels)
+ have to get dynamic filtering (e.g sorting, pruning),
+
+main bookmark config:
+ make the keditbookmarks prefs persistant
+ and make a simple include selector using
+ for example kautoconfig, including a
+ simple dynamic menu config gui
+
+bookmarklets: add some examples!
+
+tips dialog - fixes bugs - shortcuts for keyboard selection are wierd
diff --git a/konqueror/keditbookmarks/actionsimpl.cpp b/konqueror/keditbookmarks/actionsimpl.cpp
new file mode 100644
index 000000000..f0e8426d9
--- /dev/null
+++ b/konqueror/keditbookmarks/actionsimpl.cpp
@@ -0,0 +1,638 @@
+// -*- indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "actionsimpl.h"
+
+#include "toplevel.h"
+#include "commands.h"
+#include "importers.h"
+#include "favicons.h"
+#include "testlink.h"
+#include "listview.h"
+#include "exporters.h"
+#include "bookmarkinfo.h"
+
+#include <stdlib.h>
+
+#include <qclipboard.h>
+#include <qpopupmenu.h>
+#include <qpainter.h>
+
+#include <klocale.h>
+#include <dcopclient.h>
+#include <dcopref.h>
+#include <kdebug.h>
+#include <kapplication.h>
+
+#include <kaction.h>
+#include <kstdaction.h>
+#include <kedittoolbar.h>
+#include <kfiledialog.h>
+#include <kkeydialog.h>
+#include <kmessagebox.h>
+#include <kinputdialog.h>
+#include <krun.h>
+
+#include <kdatastream.h>
+#include <ktempfile.h>
+#include <kstandarddirs.h>
+
+#include <kparts/part.h>
+#include <kparts/componentfactory.h>
+
+#include <kicondialog.h>
+#include <kiconloader.h>
+
+#include <kbookmarkdrag.h>
+#include <kbookmarkmanager.h>
+#include <kbookmarkimporter.h>
+
+#include <kbookmarkimporter_ie.h>
+#include <kbookmarkimporter_opera.h>
+#include <kbookmarkexporter.h>
+
+ActionsImpl* ActionsImpl::s_self = 0;
+
+// decoupled from resetActions in toplevel.cpp
+// as resetActions simply uses the action groups
+// specified in the ui.rc file
+void KEBApp::createActions() {
+
+ ActionsImpl *actn = ActionsImpl::self();
+
+ // save and quit should probably not be in the toplevel???
+ (void) KStdAction::quit(
+ this, SLOT( close() ), actionCollection());
+ KStdAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), actionCollection());
+ (void) KStdAction::configureToolbars(
+ this, SLOT( slotConfigureToolbars() ), actionCollection());
+
+ if (m_browser) {
+ (void) KStdAction::open(
+ actn, SLOT( slotLoad() ), actionCollection());
+ (void) KStdAction::saveAs(
+ actn, SLOT( slotSaveAs() ), actionCollection());
+ }
+
+ (void) KStdAction::cut(actn, SLOT( slotCut() ), actionCollection());
+ (void) KStdAction::copy(actn, SLOT( slotCopy() ), actionCollection());
+ (void) KStdAction::paste(actn, SLOT( slotPaste() ), actionCollection());
+ (void) KStdAction::print(actn, SLOT( slotPrint() ), actionCollection());
+
+ // settings menu
+ (void) new KToggleAction(
+ i18n("&Show Netscape Bookmarks in Konqueror"), 0,
+ actn, SLOT( slotShowNS() ), actionCollection(),
+ "settings_showNS");
+
+ // actions
+ (void) new KAction(
+ i18n("&Delete"), "editdelete", Key_Delete,
+ actn, SLOT( slotDelete() ), actionCollection(), "delete");
+ (void) new KAction(
+ i18n("Rename"), "text", Key_F2,
+ actn, SLOT( slotRename() ), actionCollection(), "rename");
+ (void) new KAction(
+ i18n("C&hange URL"), "text", Key_F3,
+ actn, SLOT( slotChangeURL() ), actionCollection(), "changeurl");
+ (void) new KAction(
+ i18n("C&hange Comment"), "text", Key_F4,
+ actn, SLOT( slotChangeComment() ), actionCollection(), "changecomment");
+ (void) new KAction(
+ i18n("Chan&ge Icon..."), "icons", 0,
+ actn, SLOT( slotChangeIcon() ), actionCollection(), "changeicon");
+ (void) new KAction(
+ i18n("Update Favicon"), 0,
+ actn, SLOT( slotUpdateFavIcon() ), actionCollection(), "updatefavicon");
+ (void) new KAction(
+ i18n("Recursive Sort"), 0,
+ actn, SLOT( slotRecursiveSort() ), actionCollection(), "recursivesort");
+ (void) new KAction(
+ i18n("&New Folder..."), "folder_new", CTRL+Key_N,
+ actn, SLOT( slotNewFolder() ), actionCollection(), "newfolder");
+ (void) new KAction(
+ i18n("&New Bookmark"), "www", 0,
+ actn, SLOT( slotNewBookmark() ), actionCollection(), "newbookmark");
+ (void) new KAction(
+ i18n("&Insert Separator"), CTRL+Key_I,
+ actn, SLOT( slotInsertSeparator() ), actionCollection(),
+ "insertseparator");
+ (void) new KAction(
+ i18n("&Sort Alphabetically"), 0,
+ actn, SLOT( slotSort() ), actionCollection(), "sort");
+ (void) new KAction(
+ i18n("Set as T&oolbar Folder"), "bookmark_toolbar", 0,
+ actn, SLOT( slotSetAsToolbar() ), actionCollection(), "setastoolbar");
+ (void) new KAction(
+ i18n("Show in T&oolbar"), "bookmark_toolbar", 0,
+ actn, SLOT( slotShowInToolbar() ), actionCollection(), "showintoolbar");
+ (void) new KAction(
+ i18n("Hide in T&oolbar"), "bookmark_toolbar", 0,
+ actn, SLOT( slotHideInToolbar() ), actionCollection(), "hideintoolbar");
+ (void) new KAction(
+ i18n("&Expand All Folders"), 0,
+ actn, SLOT( slotExpandAll() ), actionCollection(), "expandall");
+ (void) new KAction(
+ i18n("Collapse &All Folders"), 0,
+ actn, SLOT( slotCollapseAll() ), actionCollection(), "collapseall" );
+ (void) new KAction(
+ i18n("&Open in Konqueror"), "fileopen", 0,
+ actn, SLOT( slotOpenLink() ), actionCollection(), "openlink" );
+ (void) new KAction(
+ i18n("Check &Status"), "bookmark", 0,
+ actn, SLOT( slotTestSelection() ), actionCollection(), "testlink" );
+
+ (void) new KAction(
+ i18n("Check Status: &All"), 0,
+ actn, SLOT( slotTestAll() ), actionCollection(), "testall" );
+ (void) new KAction(
+ i18n("Update All &Favicons"), 0,
+ actn, SLOT( slotUpdateAllFavIcons() ), actionCollection(),
+ "updateallfavicons" );
+ (void) new KAction(
+ i18n("Cancel &Checks"), 0,
+ actn, SLOT( slotCancelAllTests() ), actionCollection(), "canceltests" );
+ (void) new KAction(
+ i18n("Cancel &Favicon Updates"), 0,
+ actn, SLOT( slotCancelFavIconUpdates() ), actionCollection(),
+ "cancelfaviconupdates" );
+ (void) new KAction(
+ i18n("Import &Netscape Bookmarks..."), "netscape", 0,
+ actn, SLOT( slotImport() ), actionCollection(), "importNS");
+ (void) new KAction(
+ i18n("Import &Opera Bookmarks..."), "opera", 0,
+ actn, SLOT( slotImport() ), actionCollection(), "importOpera");
+ (void) new KAction(
+ i18n("Import All &Crash Sessions as Bookmarks..."), 0,
+ actn, SLOT( slotImport() ), actionCollection(), "importCrashes");
+ (void) new KAction(
+ i18n("Import &Galeon Bookmarks..."), 0,
+ actn, SLOT( slotImport() ), actionCollection(), "importGaleon");
+ (void) new KAction(
+ i18n("Import &KDE2/KDE3 Bookmarks..."), 0,
+ actn, SLOT( slotImport() ), actionCollection(), "importKDE2");
+ (void) new KAction(
+ i18n("Import &IE Bookmarks..."), 0,
+ actn, SLOT( slotImport() ), actionCollection(), "importIE");
+ (void) new KAction(
+ i18n("Import &Mozilla Bookmarks..."), "mozilla", 0,
+ actn, SLOT( slotImport() ), actionCollection(), "importMoz");
+ (void) new KAction(
+ i18n("Export to &Netscape Bookmarks"), "netscape", 0,
+ actn, SLOT( slotExportNS() ), actionCollection(), "exportNS");
+ (void) new KAction(
+ i18n("Export to &Opera Bookmarks..."), "opera", 0,
+ actn, SLOT( slotExportOpera() ), actionCollection(), "exportOpera");
+ (void) new KAction(
+ i18n("Export to &HTML Bookmarks..."), "html", 0,
+ actn, SLOT( slotExportHTML() ), actionCollection(), "exportHTML");
+ (void) new KAction(
+ i18n("Export to &IE Bookmarks..."), 0,
+ actn, SLOT( slotExportIE() ), actionCollection(), "exportIE");
+ (void) new KAction(
+ i18n("Export to &Mozilla Bookmarks..."), "mozilla", 0,
+ actn, SLOT( slotExportMoz() ), actionCollection(), "exportMoz");
+}
+
+void ActionsImpl::slotLoad() {
+ QString bookmarksFile
+ = KFileDialog::getOpenFileName(QString::null, "*.xml", KEBApp::self());
+ if (bookmarksFile.isNull())
+ return;
+ KEBApp::self()->m_caption = QString::null;
+ KEBApp::self()->m_bookmarksFilename = bookmarksFile;
+ KEBApp::self()->construct();
+}
+
+void ActionsImpl::slotSaveAs() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ QString saveFilename
+ = KFileDialog::getSaveFileName(QString::null, "*.xml", KEBApp::self());
+ if (!saveFilename.isEmpty())
+ CurrentMgr::self()->saveAs(saveFilename);
+}
+
+void CurrentMgr::doExport(ExportType type, const QString & _path) {
+ if(KEBApp::self())
+ KEBApp::self()->bkInfo()->commitChanges();
+ QString path(_path);
+ // TODO - add a factory and make all this use the base class
+ if (type == OperaExport) {
+ if (path.isNull())
+ path = KOperaBookmarkImporterImpl().findDefaultLocation(true);
+ KOperaBookmarkExporterImpl exporter(mgr(), path);
+ exporter.write(mgr()->root());
+ return;
+
+ } else if (type == HTMLExport) {
+ if (path.isNull())
+ path = KFileDialog::getSaveFileName(
+ QDir::homeDirPath(),
+ i18n("*.html|HTML Bookmark Listing") );
+ HTMLExporter exporter;
+ exporter.write(mgr()->root(), path);
+ return;
+
+ } else if (type == IEExport) {
+ if (path.isNull())
+ path = KIEBookmarkImporterImpl().findDefaultLocation(true);
+ KIEBookmarkExporterImpl exporter(mgr(), path);
+ exporter.write(mgr()->root());
+ return;
+ }
+
+ bool moz = (type == MozillaExport);
+
+ if (path.isNull())
+ path = (moz) ? KNSBookmarkImporter::mozillaBookmarksFile(true)
+ : KNSBookmarkImporter::netscapeBookmarksFile(true);
+
+ if (!path.isEmpty()) {
+ KNSBookmarkExporter exporter(mgr(), path);
+ exporter.write(moz);
+ }
+}
+
+void KEBApp::setActionsEnabled(SelcAbilities sa) {
+ KActionCollection * coll = actionCollection();
+
+ QStringList toEnable;
+
+ if (sa.multiSelect || (sa.singleSelect && !sa.root))
+ toEnable << "edit_copy";
+
+ if (sa.multiSelect || (sa.singleSelect && !sa.root && !sa.urlIsEmpty && !sa.group && !sa.separator))
+ toEnable << "openlink";
+
+ if (!m_readOnly) {
+ if (sa.notEmpty)
+ toEnable << "testall" << "updateallfavicons";
+
+ if ( sa.multiSelect || (sa.singleSelect && !sa.root) )
+ toEnable << "delete" << "edit_cut";
+
+ if( sa.singleSelect)
+ if (m_canPaste)
+ toEnable << "edit_paste";
+
+ if( sa.multiSelect || (sa.singleSelect && !sa.root && (sa.group || !sa.urlIsEmpty) && !sa.separator))
+ toEnable << "testlink" << "updatefavicon";
+
+ if(sa.multiSelect)
+ toEnable << "showintoolbar" << "hideintoolbar";
+ else if(sa.itemSelected)
+ toEnable << (sa.tbShowState ? "hideintoolbar" : "showintoolbar");
+
+ if (sa.singleSelect && !sa.root && !sa.separator) {
+ toEnable << "rename" << "changeicon" << "changecomment";
+ if (!sa.group)
+ toEnable << "changeurl";
+ }
+
+ if (sa.singleSelect) {
+ toEnable << "newfolder" << "newbookmark" << "insertseparator";
+ if (sa.group)
+ toEnable << "sort" << "recursivesort" << "setastoolbar";
+ }
+ }
+
+ for ( QStringList::Iterator it = toEnable.begin();
+ it != toEnable.end(); ++it )
+ {
+ coll->action((*it).ascii())->setEnabled(true);
+ // kdDebug() << (*it) << endl;
+ }
+}
+
+void KEBApp::setCancelFavIconUpdatesEnabled(bool enabled) {
+ actionCollection()->action("cancelfaviconupdates")->setEnabled(enabled);
+}
+
+void KEBApp::setCancelTestsEnabled(bool enabled) {
+ actionCollection()->action("canceltests")->setEnabled(enabled);
+}
+
+void ActionsImpl::slotCut() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ slotCopy();
+ DeleteManyCommand *mcmd = new DeleteManyCommand( i18n("Cut Items"), ListView::self()->selectedAddresses() );
+ CmdHistory::self()->addCommand(mcmd);
+
+}
+
+void ActionsImpl::slotCopy() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ // this is not a command, because it can't be undone
+ Q_ASSERT(ListView::self()->selectedItemsMap().count() != 0);
+ QValueList<KBookmark> bookmarks
+ = ListView::self()->itemsToBookmarks(ListView::self()->selectedItemsMap());
+ KBookmarkDrag* data = KBookmarkDrag::newDrag(bookmarks, 0 /* not this ! */);
+ kapp->clipboard()->setData(data, QClipboard::Clipboard);
+}
+
+void ActionsImpl::slotPaste() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ KEBMacroCommand *mcmd =
+ CmdGen::insertMimeSource(
+ i18n("Paste"),
+ kapp->clipboard()->data(QClipboard::Clipboard),
+ ListView::self()->userAddress());
+ CmdHistory::self()->didCommand(mcmd);
+}
+
+/* -------------------------------------- */
+
+void ActionsImpl::slotNewFolder() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ bool ok;
+ QString str = KInputDialog::getText( i18n( "Create New Bookmark Folder" ),
+ i18n( "New folder:" ), QString::null, &ok );
+ if (!ok)
+ return;
+
+ CreateCommand *cmd = new CreateCommand(
+ ListView::self()->userAddress(),
+ str, "bookmark_folder", /*open*/ true);
+ CmdHistory::self()->addCommand(cmd);
+}
+
+void ActionsImpl::slotNewBookmark() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ // TODO - make a setCurrentItem(Command *) which uses finaladdress interface
+ CreateCommand * cmd = new CreateCommand(
+ ListView::self()->userAddress(),
+ QString::null, "www", KURL("http://"));
+ CmdHistory::self()->addCommand(cmd);
+}
+
+void ActionsImpl::slotInsertSeparator() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ CreateCommand * cmd = new CreateCommand(ListView::self()->userAddress());
+ CmdHistory::self()->addCommand(cmd);
+}
+
+void ActionsImpl::slotImport() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ // kdDebug() << "ActionsImpl::slotImport() where sender()->name() == "
+ // << sender()->name() << endl;
+ ImportCommand* import
+ = ImportCommand::performImport(sender()->name()+6, KEBApp::self());
+ if (!import)
+ return;
+ CmdHistory::self()->addCommand(import);
+ ListView::self()->setCurrent( ListView::self()->getItemAtAddress(import->groupAddress()), true);
+}
+
+// TODO - this is getting ugly and repetitive. cleanup!
+
+void ActionsImpl::slotExportOpera() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ CurrentMgr::self()->doExport(CurrentMgr::OperaExport); }
+void ActionsImpl::slotExportHTML() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ CurrentMgr::self()->doExport(CurrentMgr::HTMLExport); }
+void ActionsImpl::slotExportIE() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ CurrentMgr::self()->doExport(CurrentMgr::IEExport); }
+void ActionsImpl::slotExportNS() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ CurrentMgr::self()->doExport(CurrentMgr::NetscapeExport); }
+void ActionsImpl::slotExportMoz() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ CurrentMgr::self()->doExport(CurrentMgr::MozillaExport); }
+
+/* -------------------------------------- */
+
+static QCString s_appId, s_objId;
+static KParts::ReadOnlyPart *s_part;
+
+void ActionsImpl::slotPrint() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ s_part = KParts::ComponentFactory
+ ::createPartInstanceFromQuery<KParts::ReadOnlyPart>(
+ "text/html", QString::null);
+ s_part->setProperty("pluginsEnabled", QVariant(false, 1));
+ s_part->setProperty("javaScriptEnabled", QVariant(false, 1));
+ s_part->setProperty("javaEnabled", QVariant(false, 1));
+
+ // doc->openStream( "text/html", KURL() );
+ // doc->writeStream( QCString( "<HTML><BODY>FOO</BODY></HTML>" ) );
+ // doc->closeStream();
+
+ HTMLExporter exporter;
+ KTempFile tmpf(locateLocal("tmp", "print_bookmarks"), ".html");
+ QTextStream *tstream = tmpf.textStream();
+ tstream->setEncoding(QTextStream::Unicode);
+ (*tstream) << exporter.toString(CurrentMgr::self()->mgr()->root(), true);
+ tmpf.close();
+
+ s_appId = kapp->dcopClient()->appId();
+ s_objId = s_part->property("dcopObjectId").toString().latin1();
+ connect(s_part, SIGNAL(completed()), this, SLOT(slotDelayedPrint()));
+
+ s_part->openURL(KURL( tmpf.name() ));
+}
+
+void ActionsImpl::slotDelayedPrint() {
+ Q_ASSERT(s_part);
+ DCOPRef(s_appId, s_objId).send("print", false);
+ delete s_part;
+ s_part = 0;
+}
+
+/* -------------------------------------- */
+
+void ActionsImpl::slotShowNS() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ bool shown = KEBApp::self()->nsShown();
+ CurrentMgr::self()->mgr()->setShowNSBookmarks(shown);
+ // TODO - need to force a save here
+ CurrentMgr::self()->reloadConfig();
+}
+
+void ActionsImpl::slotCancelFavIconUpdates() {
+ FavIconsItrHolder::self()->cancelAllItrs();
+}
+
+void ActionsImpl::slotCancelAllTests() {
+ TestLinkItrHolder::self()->cancelAllItrs();
+}
+
+void ActionsImpl::slotTestAll() {
+ TestLinkItrHolder::self()->insertItr(
+ new TestLinkItr(ListView::self()->allBookmarks()));
+}
+
+void ActionsImpl::slotUpdateAllFavIcons() {
+ FavIconsItrHolder::self()->insertItr(
+ new FavIconsItr(ListView::self()->allBookmarks()));
+}
+
+ActionsImpl::~ActionsImpl() {
+ delete FavIconsItrHolder::self();
+ delete TestLinkItrHolder::self();
+}
+
+/* -------------------------------------- */
+
+void ActionsImpl::slotTestSelection() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ TestLinkItrHolder::self()->insertItr(new TestLinkItr(ListView::self()->selectedBookmarksExpanded()));
+}
+
+void ActionsImpl::slotUpdateFavIcon() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ FavIconsItrHolder::self()->insertItr(new FavIconsItr(ListView::self()->selectedBookmarksExpanded()));
+}
+
+/* -------------------------------------- */
+
+class KBookmarkGroupList : private KBookmarkGroupTraverser {
+public:
+ KBookmarkGroupList(KBookmarkManager *);
+ QValueList<KBookmark> getList(const KBookmarkGroup &);
+private:
+ virtual void visit(const KBookmark &) { ; }
+ virtual void visitEnter(const KBookmarkGroup &);
+ virtual void visitLeave(const KBookmarkGroup &) { ; }
+private:
+ KBookmarkManager *m_manager;
+ QValueList<KBookmark> m_list;
+};
+
+KBookmarkGroupList::KBookmarkGroupList( KBookmarkManager *manager ) {
+ m_manager = manager;
+}
+
+QValueList<KBookmark> KBookmarkGroupList::getList( const KBookmarkGroup &grp ) {
+ traverse(grp);
+ return m_list;
+}
+
+void KBookmarkGroupList::visitEnter(const KBookmarkGroup &grp) {
+ m_list << grp;
+}
+
+void ActionsImpl::slotRecursiveSort() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ KBookmark bk = ListView::self()->firstSelected()->bookmark();
+ Q_ASSERT(bk.isGroup());
+ KEBMacroCommand *mcmd = new KEBMacroCommand(i18n("Recursive Sort"));
+ KBookmarkGroupList lister(CurrentMgr::self()->mgr());
+ QValueList<KBookmark> bookmarks = lister.getList(bk.toGroup());
+ bookmarks << bk.toGroup();
+ for (QValueListConstIterator<KBookmark> it = bookmarks.begin(); it != bookmarks.end(); ++it) {
+ SortCommand *cmd = new SortCommand("", (*it).address());
+ cmd->execute();
+ mcmd->addCommand(cmd);
+ }
+ CmdHistory::self()->didCommand(mcmd);
+}
+
+void ActionsImpl::slotSort() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ KBookmark bk = ListView::self()->firstSelected()->bookmark();
+ Q_ASSERT(bk.isGroup());
+ SortCommand *cmd = new SortCommand(i18n("Sort Alphabetically"), bk.address());
+ CmdHistory::self()->addCommand(cmd);
+}
+
+/* -------------------------------------- */
+
+void ActionsImpl::slotDelete() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ DeleteManyCommand *mcmd = new DeleteManyCommand(i18n("Delete Items"), ListView::self()->selectedAddresses());
+ CmdHistory::self()->addCommand(mcmd);
+}
+
+void ActionsImpl::slotOpenLink() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ QValueList<KBookmark> bks = ListView::self()->itemsToBookmarks(ListView::self()->selectedItemsMap());
+ QValueListIterator<KBookmark> it;
+ for (it = bks.begin(); it != bks.end(); ++it) {
+ if ((*it).isGroup() || (*it).isSeparator())
+ continue;
+ (void)new KRun((*it).url());
+ }
+}
+
+/* -------------------------------------- */
+
+void ActionsImpl::slotRename() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ ListView::self()->rename(KEBListView::NameColumn);
+}
+
+void ActionsImpl::slotChangeURL() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ ListView::self()->rename(KEBListView::UrlColumn);
+}
+
+void ActionsImpl::slotChangeComment() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ ListView::self()->rename(KEBListView::CommentColumn);
+}
+
+void ActionsImpl::slotSetAsToolbar() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ KBookmark bk = ListView::self()->firstSelected()->bookmark();
+ Q_ASSERT(bk.isGroup());
+ KEBMacroCommand *mcmd = CmdGen::setAsToolbar(bk);
+ CmdHistory::self()->addCommand(mcmd);
+}
+
+void ActionsImpl::slotShowInToolbar() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ QValueList<KBookmark> bks = ListView::self()->itemsToBookmarks(ListView::self()->selectedItemsMap());
+ KEBMacroCommand *mcmd = CmdGen::setShownInToolbar(bks, true);
+ CmdHistory::self()->addCommand(mcmd);
+}
+
+void ActionsImpl::slotHideInToolbar() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ QValueList<KBookmark> bks = ListView::self()->itemsToBookmarks(ListView::self()->selectedItemsMap());
+ KEBMacroCommand *mcmd = CmdGen::setShownInToolbar(bks, false);
+ CmdHistory::self()->addCommand(mcmd);
+}
+
+void ActionsImpl::slotChangeIcon() {
+ KEBApp::self()->bkInfo()->commitChanges();
+ KBookmark bk = ListView::self()->firstSelected()->bookmark();
+ KIconDialog dlg(KEBApp::self());
+ QString newIcon = dlg.selectIcon(KIcon::Small, KIcon::FileSystem);
+ if (newIcon.isEmpty())
+ return;
+ EditCommand *cmd = new EditCommand(
+ bk.address(),
+ EditCommand::Edition("icon", newIcon),
+ i18n("Icon"));
+ CmdHistory::self()->addCommand(cmd);
+}
+
+void ActionsImpl::slotExpandAll() {
+ ListView::self()->setOpen(true);
+}
+
+void ActionsImpl::slotCollapseAll() {
+ ListView::self()->setOpen(false);
+}
+
+#include "actionsimpl.moc"
diff --git a/konqueror/keditbookmarks/actionsimpl.h b/konqueror/keditbookmarks/actionsimpl.h
new file mode 100644
index 000000000..c10b8e12c
--- /dev/null
+++ b/konqueror/keditbookmarks/actionsimpl.h
@@ -0,0 +1,83 @@
+// -*- mode:cperl; cperl-indent-level:4; cperl-continued-statement-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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __actionsimpl_h
+#define __actionsimpl_h
+
+#include <qobject.h>
+
+class ActionsImpl : public QObject
+{
+ Q_OBJECT
+
+public:
+ bool save();
+
+public slots:
+ void slotLoad();
+ void slotSaveAs();
+ void slotCut();
+ void slotCopy();
+ void slotPaste();
+ void slotRename();
+ void slotPrint();
+ void slotChangeURL();
+ void slotChangeComment();
+ void slotChangeIcon();
+ void slotDelete();
+ void slotNewFolder();
+ void slotNewBookmark();
+ void slotInsertSeparator();
+ void slotSort();
+ void slotSetAsToolbar();
+ void slotShowInToolbar();
+ void slotHideInToolbar();
+ void slotOpenLink();
+ void slotShowNS();
+ void slotTestSelection();
+ void slotTestAll();
+ void slotCancelAllTests();
+ void slotUpdateFavIcon();
+ void slotRecursiveSort();
+ void slotUpdateAllFavIcons();
+ void slotCancelFavIconUpdates();
+ void slotExpandAll();
+ void slotCollapseAll();
+ void slotImport();
+ void slotExportOpera();
+ void slotExportHTML();
+ void slotExportIE();
+ void slotExportNS();
+ void slotExportMoz();
+
+ // ugly hack really...
+ void slotDelayedPrint();
+
+ static ActionsImpl* self() { if (!s_self) { s_self = new ActionsImpl(); }; return s_self; }
+
+public:
+ ~ActionsImpl();
+
+private:
+ ActionsImpl() { }
+ static ActionsImpl *s_self;
+};
+
+#endif
diff --git a/konqueror/keditbookmarks/bookmarkinfo.cpp b/konqueror/keditbookmarks/bookmarkinfo.cpp
new file mode 100644
index 000000000..9d2d23f28
--- /dev/null
+++ b/konqueror/keditbookmarks/bookmarkinfo.cpp
@@ -0,0 +1,293 @@
+// 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "bookmarkinfo.h"
+#include "commands.h"
+#include "toplevel.h"
+
+#include <stdlib.h>
+
+#include <qtimer.h>
+#include <qclipboard.h>
+#include <qsplitter.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <kapplication.h>
+#include <kstdaction.h>
+#include <kaction.h>
+#include <dcopclient.h>
+#include <dcopref.h>
+
+#include <kkeydialog.h>
+#include <kedittoolbar.h>
+#include <kmessagebox.h>
+#include <klineedit.h>
+#include <kfiledialog.h>
+
+#include <kbookmarkdrag.h>
+#include <kbookmarkmanager.h>
+
+// SHUFFLE all these functions around, the order is just plain stupid
+
+BookmarkLineEdit::BookmarkLineEdit( QWidget *parent )
+ : KLineEdit( parent )
+{
+}
+
+void BookmarkLineEdit::cut()
+{
+ QString select( selectedText() );
+ int pos( selectionStart() );
+ QString newText( text().remove( pos, select.length() ) );
+ KLineEdit::cut();
+ setEdited( true ); //KDE 4 setModified( true );
+ emit textChanged( newText );
+ setText( newText );
+}
+
+
+void BookmarkInfoWidget::showBookmark(const KBookmark &bk) {
+ commitChanges();
+ m_bk = bk;
+
+ if (m_bk.isNull()) {
+ // all read only and blank
+
+ m_title_le->setReadOnly(true);
+ m_title_le->setText(QString::null);
+
+ m_url_le->setReadOnly(true);
+ m_url_le->setText(QString::null);
+
+ m_comment_le->setReadOnly(true);
+ m_comment_le->setText(QString::null);
+
+ m_visitdate_le->setReadOnly(true);
+ m_visitdate_le->setText(QString::null);
+
+ m_credate_le->setReadOnly(true);
+ m_credate_le->setText(QString::null);
+
+ m_visitcount_le->setReadOnly(true);
+ m_visitcount_le->setText(QString::null);
+
+ return;
+ }
+
+ // read/write fields
+ m_title_le->setReadOnly( (bk.isSeparator()|| !bk.hasParent() )? true : false);
+ m_title_le->setText(bk.fullText());
+
+ m_url_le->setReadOnly(bk.isGroup() || bk.isSeparator());
+ m_url_le->setText(bk.isGroup() ? QString::null : bk.url().pathOrURL());
+
+ m_comment_le->setReadOnly((bk.isSeparator()|| !bk.hasParent()) ? true : false );
+ m_comment_le->setText(
+ NodeEditCommand::getNodeText(bk, QStringList() << "desc"));
+
+ // readonly fields
+ updateStatus();
+
+}
+
+void BookmarkInfoWidget::updateStatus()
+{
+ QString visitDate =
+ CurrentMgr::makeTimeStr( NodeEditCommand::getNodeText(m_bk, QStringList() << "info" << "metadata"
+ << "time_visited" ));
+ m_visitdate_le->setReadOnly(true);
+ m_visitdate_le->setText(visitDate);
+
+ QString creationDate =
+ CurrentMgr::makeTimeStr( NodeEditCommand::getNodeText(m_bk, QStringList() << "info" << "metadata"
+ << "time_added" ));
+ m_credate_le->setReadOnly(true);
+ m_credate_le->setText(creationDate);
+
+ // TODO - get the actual field name from the spec if it exists, else copy galeon
+ m_visitcount_le->setReadOnly(true);
+ m_visitcount_le->setText(
+ NodeEditCommand::getNodeText(m_bk, QStringList() << "info" << "metadata"
+ << "visit_count" ));
+}
+
+void BookmarkInfoWidget::commitChanges()
+{
+ commitTitle();
+ commitURL();
+ commitComment();
+}
+
+void BookmarkInfoWidget::commitTitle()
+{
+ if(titlecmd)
+ {
+ emit updateListViewItem();
+ CurrentMgr::self()->notifyManagers(CurrentMgr::bookmarkAt(titlecmd->affectedBookmarks()).toGroup());
+ titlecmd = 0;
+ }
+}
+
+void BookmarkInfoWidget::slotTextChangedTitle(const QString &str)
+{
+ if (m_bk.isNull() || !m_title_le->isModified())
+ return;
+
+ timer->start(1000, true);
+
+ if(titlecmd)
+ {
+ NodeEditCommand::setNodeText(m_bk, QStringList() << "title", str);
+ titlecmd->modify(str);
+ }
+ else
+ {
+ titlecmd = new NodeEditCommand(m_bk.address(), str, "title");
+ titlecmd->execute();
+ CmdHistory::self()->addInFlightCommand(titlecmd);
+ }
+}
+
+void BookmarkInfoWidget::commitURL()
+{
+ if(urlcmd)
+ {
+ emit updateListViewItem();
+ CurrentMgr::self()->notifyManagers(CurrentMgr::bookmarkAt(urlcmd->affectedBookmarks()).toGroup());
+ urlcmd = 0;
+ }
+}
+
+void BookmarkInfoWidget::slotTextChangedURL(const QString &str) {
+ if (m_bk.isNull() || !m_url_le->isModified())
+ return;
+
+ timer->start(1000, true);
+
+ if(urlcmd)
+ {
+ KURL u = KURL::fromPathOrURL(str);
+ m_bk.internalElement().setAttribute("href", u.url(0, 106));
+ urlcmd->modify("href", u.url(0, 106));
+ }
+ else
+ {
+ KURL u = KURL::fromPathOrURL(str);
+ urlcmd = new EditCommand(m_bk.address(), EditCommand::Edition("href", u.url(0, 106)), i18n("URL"));
+ urlcmd->execute();
+ CmdHistory::self()->addInFlightCommand(urlcmd);
+ }
+}
+
+void BookmarkInfoWidget::commitComment()
+{
+ if(commentcmd)
+ {
+ emit updateListViewItem();
+ CurrentMgr::self()->notifyManagers( CurrentMgr::bookmarkAt( commentcmd->affectedBookmarks() ).toGroup());
+ commentcmd = 0;
+ }
+}
+
+void BookmarkInfoWidget::slotTextChangedComment(const QString &str) {
+ if (m_bk.isNull() || !m_comment_le->isModified())
+ return;
+
+ timer->start(1000, true);
+
+ if(commentcmd)
+ {
+ NodeEditCommand::setNodeText(m_bk, QStringList() << "desc", str);
+ commentcmd->modify(str);
+ }
+ else
+ {
+ commentcmd = new NodeEditCommand(m_bk.address(), str, "desc");
+ commentcmd->execute();
+ CmdHistory::self()->addInFlightCommand(commentcmd);
+ }
+}
+
+BookmarkInfoWidget::BookmarkInfoWidget(QWidget *parent, const char *name)
+ : QWidget(parent, name), m_connected(false) {
+
+ timer = new QTimer(this);
+ connect(timer, SIGNAL( timeout() ), SLOT( commitChanges()));
+
+ titlecmd = 0;
+ urlcmd = 0;
+ commentcmd = 0;
+
+ QBoxLayout *vbox = new QVBoxLayout(this);
+ QGridLayout *grid = new QGridLayout(vbox, 3, 4, 4);
+
+ m_title_le = new BookmarkLineEdit(this);
+ grid->addWidget(m_title_le, 0, 1);
+ grid->addWidget(
+ new QLabel(m_title_le, i18n("Name:"), this),
+ 0, 0);
+
+ connect(m_title_le, SIGNAL( textChanged(const QString &) ),
+ SLOT( slotTextChangedTitle(const QString &) ));
+ connect(m_title_le, SIGNAL( lostFocus() ), SLOT( commitTitle() ));
+
+ m_url_le = new BookmarkLineEdit(this);
+ grid->addWidget(m_url_le, 1, 1);
+ grid->addWidget(
+ new QLabel(m_url_le, i18n("Location:"), this),
+ 1, 0);
+
+ connect(m_url_le, SIGNAL( textChanged(const QString &) ),
+ SLOT( slotTextChangedURL(const QString &) ));
+ connect(m_url_le, SIGNAL( lostFocus() ), SLOT( commitURL() ));
+
+ m_comment_le = new BookmarkLineEdit(this);
+ grid->addWidget(m_comment_le, 2, 1);
+ grid->addWidget(
+ new QLabel(m_comment_le, i18n("Comment:"), this),
+ 2, 0);
+ connect(m_comment_le, SIGNAL( textChanged(const QString &) ),
+ SLOT( slotTextChangedComment(const QString &) ));
+ connect(m_comment_le, SIGNAL( lostFocus() ), SLOT( commitComment() ));
+
+ m_credate_le = new KLineEdit(this);
+ grid->addWidget(m_credate_le, 0, 3);
+ grid->addWidget(
+ new QLabel(m_credate_le, i18n("First viewed:"), this),
+ 0, 2);
+
+ m_visitdate_le = new KLineEdit(this);
+ grid->addWidget(m_visitdate_le, 1, 3);
+ grid->addWidget(
+ new QLabel(m_visitdate_le, i18n("Viewed last:"), this),
+ 1, 2 );
+
+ m_visitcount_le = new KLineEdit(this);
+ grid->addWidget(m_visitcount_le, 2, 3);
+ grid->addWidget(
+ new QLabel(m_visitcount_le, i18n("Times visited:"), this),
+ 2, 2);
+}
+
+#include "bookmarkinfo.moc"
+
diff --git a/konqueror/keditbookmarks/bookmarkinfo.h b/konqueror/keditbookmarks/bookmarkinfo.h
new file mode 100644
index 000000000..51661959a
--- /dev/null
+++ b/konqueror/keditbookmarks/bookmarkinfo.h
@@ -0,0 +1,111 @@
+// vim: set ts=4 sts=4 sw=4 et:
+/* 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __bookmarkinfo_h
+#define __bookmarkinfo_h
+
+#include "commands.h"
+
+#include <kbookmark.h>
+#include <qwidget.h>
+#include <klineedit.h>
+
+class QTimer;
+
+class BookmarkLineEdit : public KLineEdit {
+ Q_OBJECT
+public:
+ BookmarkLineEdit( QWidget * );
+public slots:
+ virtual void cut ();
+};
+
+
+class BookmarkInfoWidget : public QWidget {
+ Q_OBJECT
+public:
+ BookmarkInfoWidget(QWidget * = 0, const char * = 0);
+ void showBookmark(const KBookmark &bk);
+ void saveBookmark(const KBookmark &bk);
+ KBookmark bookmark() { return m_bk; }
+ bool connected() { return m_connected; };
+ void setConnected(bool b) { m_connected = b; };
+ void updateStatus();
+
+public slots:
+ void slotTextChangedURL(const QString &);
+ void slotTextChangedTitle(const QString &);
+ void slotTextChangedComment(const QString &);
+
+ // _The deal with all those commitChanges() calls_
+ // First a short example how all the components
+ // normally fit together:
+ // Note: not all details are included
+ // For example: The user clicks on "New Bookmark"
+ // This constructs a cmd = new CreateCommand( .. )
+ // CmdHistory::self()->addCommand( cmd ) is called
+ // CmdHistory executes the command
+ // and enables the undo button
+ // and emits slotCommandExecuted
+ // We catch the signal and call
+ // CurrentMgr::self()->notifyManagers( .. );
+
+ // The bookmarkinfo widget is special, because
+ // we don't want to send a notification
+ // for every change, but want to enable the undo
+ // button and need to send the notification
+ // if the user has stopped typing
+
+ // So as soon as the user starts typing
+ // we create a command
+ // and call CmdHistory::self()->addInFlightCommand( cmd );
+ // addInFlightCommand() doesn't execute the command, it just
+ // adds it to the command history (To enable the undo button)
+ // For every keystroke after that the command is modified
+ // and we change our internal state to reflect the change
+ // (Basically changing it in the same way, executing would have.)
+
+ // At this point we have a modified state, but haven't send it
+ // to the other bookmarkmanagers
+ // That is done in commitChanges()
+ // commitChanges() should be called everywhere, where we are
+ // sure that the user has stopped typing.
+ // And a few other cleanups are done in commitChanges()
+ void commitChanges();
+ void commitTitle();
+ void commitURL();
+ void commitComment();
+
+signals:
+ void updateListViewItem();
+private:
+ NodeEditCommand *titlecmd;
+ EditCommand *urlcmd;
+ NodeEditCommand *commentcmd;
+ QTimer * timer;
+ BookmarkLineEdit *m_title_le, *m_url_le,
+ *m_comment_le;
+ KLineEdit *m_visitdate_le, *m_credate_le,
+ *m_visitcount_le;
+ KBookmark m_bk;
+ bool m_connected;
+};
+
+#endif
diff --git a/konqueror/keditbookmarks/bookmarkiterator.cpp b/konqueror/keditbookmarks/bookmarkiterator.cpp
new file mode 100644
index 000000000..588adb86c
--- /dev/null
+++ b/konqueror/keditbookmarks/bookmarkiterator.cpp
@@ -0,0 +1,105 @@
+// -*- indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "bookmarkiterator.h"
+
+#include "toplevel.h"
+#include "listview.h"
+
+#include <kdebug.h>
+
+#include <qtimer.h>
+
+BookmarkIterator::BookmarkIterator(QValueList<KBookmark> bks) : m_bklist(bks) {
+ connect(this, SIGNAL( deleteSelf(BookmarkIterator *) ),
+ SLOT( slotCancelTest(BookmarkIterator *) ));
+ delayedEmitNextOne();
+}
+
+BookmarkIterator::~BookmarkIterator() {
+ ;
+}
+
+void BookmarkIterator::delayedEmitNextOne() {
+ QTimer::singleShot(1, this, SLOT( nextOne() ));
+}
+
+void BookmarkIterator::slotCancelTest(BookmarkIterator *test) {
+ holder()->removeItr(test);
+}
+
+KEBListViewItem* BookmarkIterator::curItem() const {
+ if (!m_bk.hasParent())
+ return 0;
+ return ListView::self()->getItemAtAddress(m_bk.address());
+}
+
+const KBookmark BookmarkIterator::curBk() const {
+ assert(m_bk.hasParent());
+ return m_bk;
+}
+
+void BookmarkIterator::nextOne() {
+ // kdDebug() << "BookmarkIterator::nextOne" << endl;
+
+ if (m_bklist.isEmpty()) {
+ emit deleteSelf(this);
+ return;
+ }
+
+ QValueListIterator<KBookmark> head = m_bklist.begin();
+ KBookmark bk = (*head);
+
+ bool viable = bk.hasParent() && isApplicable(bk);
+
+ if (viable) {
+ m_bk = bk;
+ doAction();
+ }
+
+ m_bklist.remove(head);
+
+ if (!viable)
+ delayedEmitNextOne();
+}
+
+/* --------------------------- */
+
+BookmarkIteratorHolder::BookmarkIteratorHolder() {
+ m_itrs.setAutoDelete(true);
+}
+
+void BookmarkIteratorHolder::insertItr(BookmarkIterator *itr) {
+ m_itrs.insert(0, itr);
+ doItrListChanged();
+}
+
+void BookmarkIteratorHolder::removeItr(BookmarkIterator *itr) {
+ m_itrs.remove(itr);
+ doItrListChanged();
+}
+
+void BookmarkIteratorHolder::cancelAllItrs() {
+ m_itrs.clear();
+ doItrListChanged();
+}
+
+#include "bookmarkiterator.moc"
diff --git a/konqueror/keditbookmarks/bookmarkiterator.h b/konqueror/keditbookmarks/bookmarkiterator.h
new file mode 100644
index 000000000..baafb3486
--- /dev/null
+++ b/konqueror/keditbookmarks/bookmarkiterator.h
@@ -0,0 +1,74 @@
+// -*- mode:cperl; cperl-indent-level:4; cperl-continued-statement-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) 2002-2003 Alexander Kellett <lypanov@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __bookmarkiterator_h
+#define __bookmarkiterator_h
+
+#include <qobject.h>
+#include <qptrlist.h>
+#include <kbookmark.h>
+
+class KEBListViewItem;
+class BookmarkIteratorHolder;
+
+class BookmarkIterator : public QObject
+{
+ Q_OBJECT
+
+public:
+ BookmarkIterator(QValueList<KBookmark> bks);
+ virtual ~BookmarkIterator();
+ virtual BookmarkIteratorHolder* holder() const = 0;
+
+public slots:
+ void nextOne();
+ void delayedEmitNextOne();
+ void slotCancelTest(BookmarkIterator *t);
+
+signals:
+ void deleteSelf(BookmarkIterator *);
+
+protected:
+ virtual void doAction() = 0;
+ virtual bool isApplicable(const KBookmark &bk) const = 0;
+ KEBListViewItem* curItem() const;
+ const KBookmark curBk() const;
+
+private:
+ KBookmark m_bk;
+ QValueList<KBookmark> m_bklist;
+};
+
+class BookmarkIteratorHolder
+{
+public:
+ void cancelAllItrs();
+ void removeItr(BookmarkIterator*);
+ void insertItr(BookmarkIterator*);
+protected:
+ BookmarkIteratorHolder();
+ virtual ~BookmarkIteratorHolder() {};
+ virtual void doItrListChanged() = 0;
+ int count() const { return m_itrs.count(); }
+private:
+ QPtrList<BookmarkIterator> m_itrs;
+};
+
+#endif
diff --git a/konqueror/keditbookmarks/commands.cpp b/konqueror/keditbookmarks/commands.cpp
new file mode 100644
index 000000000..e545df54e
--- /dev/null
+++ b/konqueror/keditbookmarks/commands.cpp
@@ -0,0 +1,745 @@
+// -*- indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "commands.h"
+
+#include "kinsertionsort.h"
+
+#include "toplevel.h"
+#include "listview.h"
+
+#include <assert.h>
+#include <qvaluevector.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <kbookmarkdrag.h>
+#include <kbookmarkmanager.h>
+
+#include <kurldrag.h>
+#include <kdesktopfile.h>
+
+QString KEBMacroCommand::affectedBookmarks() const
+{
+ QPtrListIterator<KCommand> it(m_commands);
+ QString affectBook;
+ if(it.current())
+ affectBook = dynamic_cast<IKEBCommand *>(it.current())->affectedBookmarks();
+ ++it;
+ for ( ; it.current() ; ++it )
+ affectBook = KBookmark::commonParent( affectBook, dynamic_cast<IKEBCommand *>(it.current())->affectedBookmarks());
+ return affectBook;
+}
+
+QString DeleteManyCommand::prevOrParentAddress(QString addr)
+{
+ QString prev = KBookmark::previousAddress( addr );
+ if( CurrentMgr::bookmarkAt(prev).hasParent())
+ return prev;
+ else
+ return KBookmark::parentAddress( addr );
+}
+
+QString DeleteManyCommand::preOrderNextAddress(QString addr)
+{
+ QString rootAdr = CurrentMgr::self()->mgr()->root().address();
+ while(addr != rootAdr)
+ {
+ QString next = KBookmark::nextAddress(addr);
+ if(CurrentMgr::bookmarkAt( next ).hasParent() )
+ return next;
+ addr = KBookmark::parentAddress( addr );
+ }
+ return QString::null;
+}
+
+bool DeleteManyCommand::isConsecutive(const QValueList<QString> & addresses)
+{
+ QValueList<QString>::const_iterator it, end;
+ it = addresses.begin();
+ end = addresses.end();
+ QString addr = *(addresses.begin());
+ for( ; it != end; ++it)
+ {
+ if( *it != addr )
+ return false;
+ addr = KBookmark::nextAddress(addr);
+ }
+ return true;
+}
+
+
+DeleteManyCommand::DeleteManyCommand(const QString &name, const QValueList<QString> & addresses)
+ : KEBMacroCommand(name)
+{
+ QValueList<QString>::const_iterator it, begin;
+ begin = addresses.begin();
+ it = addresses.end();
+ while(begin != it)
+ {
+ --it;
+ DeleteCommand * dcmd = new DeleteCommand(*it);
+ addCommand(dcmd);
+ }
+
+ // Set m_currentAddress
+ if( addresses.count() == 1)
+ {
+ // First try next bookmark
+ if( CurrentMgr::bookmarkAt( KBookmark::nextAddress( *begin ) ).hasParent() )
+ m_currentAddress = *begin;
+ else
+ {
+ m_currentAddress = preOrderNextAddress( KBookmark::parentAddress( *begin ) );
+ if(m_currentAddress == QString::null)
+ m_currentAddress = prevOrParentAddress( *begin );
+ }
+ }
+ else // multi selection
+ {
+ // Check if all bookmarks are consecutive
+ if(isConsecutive(addresses)) // Mark next bookmark after all selected
+ { // That's a little work...
+ QValueList<QString>::const_iterator last = addresses.end();
+ --last;
+ if( CurrentMgr::bookmarkAt( KBookmark::nextAddress(*last) ).hasParent() )
+ m_currentAddress = *begin;
+ else
+ {
+ m_currentAddress = preOrderNextAddress( KBookmark::parentAddress( *begin ) );
+ if( m_currentAddress == QString::null)
+ m_currentAddress = prevOrParentAddress( *begin );
+ }
+ }
+ else // not consecutive, select the common parent (This could be more clever)
+ {
+ QValueList<QString>::const_iterator jt, end;
+ end = addresses.end();
+ m_currentAddress = *begin;
+ for( jt = addresses.begin(); jt != end; ++jt)
+ m_currentAddress = KBookmark::commonParent(m_currentAddress, *jt);
+ }
+ }
+}
+
+QString DeleteManyCommand::currentAddress() const
+{
+ return m_currentAddress;
+}
+
+
+QString CreateCommand::name() const {
+ if (m_separator) {
+ return i18n("Insert Separator");
+ } else if (m_group) {
+ return i18n("Create Folder");
+ } else if (!m_originalBookmark.isNull()) {
+ return i18n("Copy %1").arg(m_mytext);
+ } else {
+ return i18n("Create Bookmark");
+ }
+}
+
+void CreateCommand::execute() {
+ QString parentAddress = KBookmark::parentAddress(m_to);
+ KBookmarkGroup parentGroup =
+ CurrentMgr::bookmarkAt(parentAddress).toGroup();
+
+ QString previousSibling = KBookmark::previousAddress(m_to);
+
+ // kdDebug() << "CreateCommand::execute previousSibling="
+ // << previousSibling << endl;
+ KBookmark prev = (previousSibling.isEmpty())
+ ? KBookmark(QDomElement())
+ : CurrentMgr::bookmarkAt(previousSibling);
+
+ KBookmark bk = KBookmark(QDomElement());
+
+ if (m_separator) {
+ bk = parentGroup.createNewSeparator();
+
+ } else if (m_group) {
+ Q_ASSERT(!m_text.isEmpty());
+ bk = parentGroup.createNewFolder(CurrentMgr::self()->mgr(),
+ m_text, false);
+ bk.internalElement().setAttribute("folded", (m_open ? "no" : "yes"));
+ if (!m_iconPath.isEmpty()) {
+ bk.internalElement().setAttribute("icon", m_iconPath);
+ }
+
+ } else if (!m_originalBookmark.isNull()) {
+ // umm.. moveItem needs bk to be a child already!
+ bk = m_originalBookmark;
+
+ } else {
+ bk = parentGroup.addBookmark(CurrentMgr::self()->mgr(),
+ m_text, m_url,
+ m_iconPath, false);
+ }
+
+ // move to right position
+ parentGroup.moveItem(bk, prev);
+ if (!(name().isEmpty()) && !parentAddress.isEmpty() ) {
+ // open the parent (useful if it was empty) - only for manual commands
+ Q_ASSERT( parentGroup.internalElement().tagName() != "xbel" );
+ parentGroup.internalElement().setAttribute("folded", "no");
+ }
+
+ Q_ASSERT(bk.address() == m_to);
+}
+
+QString CreateCommand::finalAddress() const {
+ Q_ASSERT( !m_to.isEmpty() );
+ return m_to;
+}
+
+void CreateCommand::unexecute() {
+ // kdDebug() << "CreateCommand::unexecute deleting " << m_to << endl;
+
+ KBookmark bk = CurrentMgr::bookmarkAt(m_to);
+ Q_ASSERT(!bk.isNull() && !bk.parentGroup().isNull());
+
+ ListView::self()->invalidate(bk.address());
+
+ bk.parentGroup().deleteBookmark(bk);
+}
+
+QString CreateCommand::affectedBookmarks() const
+{
+ return KBookmark::parentAddress(m_to);
+}
+
+QString CreateCommand::currentAddress() const
+{
+ QString bk = KBookmark::previousAddress( m_to );
+ if(CurrentMgr::bookmarkAt( bk).hasParent())
+ return bk;
+ else
+ return KBookmark::parentAddress( m_to );
+}
+
+/* -------------------------------------- */
+
+QString EditCommand::name() const {
+ return i18n("%1 Change").arg(m_mytext);
+}
+
+void EditCommand::execute() {
+ KBookmark bk = CurrentMgr::bookmarkAt(m_address);
+ Q_ASSERT(!bk.isNull());
+
+ m_reverseEditions.clear();
+
+ QValueList<Edition>::Iterator it = m_editions.begin();
+
+ for ( ; it != m_editions.end() ; ++it) {
+ // backup current value
+ m_reverseEditions.append( Edition((*it).attr,
+ bk.internalElement().attribute((*it).attr)));
+ // set new value
+ bk.internalElement().setAttribute((*it).attr, (*it).value);
+ }
+}
+
+void EditCommand::unexecute() {
+ // code reuse
+ EditCommand cmd(m_address, m_reverseEditions);
+ cmd.execute();
+ // get the editions back from it,
+ // in case they changed
+ // (hmm, shouldn't happen - TODO CHECK!)
+ m_editions = cmd.m_reverseEditions;
+}
+
+QString EditCommand::affectedBookmarks() const
+{
+ return KBookmark::parentAddress(m_address);
+}
+
+void EditCommand::modify(const QString & a, const QString & v)
+{
+ QValueList<Edition>::Iterator it = m_editions.begin();
+ QValueList<Edition>::Iterator end = m_editions.end();
+ for ( ; it != end; ++it)
+ {
+ if( (*it).attr == a)
+ (*it).value = v;
+ }
+}
+
+/* -------------------------------------- */
+
+QString NodeEditCommand::name() const {
+ // TODO - make dynamic
+ return i18n("Renaming");
+}
+
+QString NodeEditCommand::getNodeText(KBookmark bk, const QStringList &nodehier) {
+ QDomNode subnode = bk.internalElement();
+ for (QStringList::ConstIterator it = nodehier.begin();
+ it != nodehier.end(); ++it)
+ {
+ subnode = subnode.namedItem((*it));
+ if (subnode.isNull())
+ return QString::null;
+ }
+ return (subnode.firstChild().isNull())
+ ? QString::null
+ : subnode.firstChild().toText().data();
+}
+
+QString NodeEditCommand::setNodeText(KBookmark bk, const QStringList &nodehier,
+ const QString newValue) {
+ QDomNode subnode = bk.internalElement();
+ for (QStringList::ConstIterator it = nodehier.begin();
+ it != nodehier.end(); ++it)
+ {
+ subnode = subnode.namedItem((*it));
+ if (subnode.isNull()) {
+ subnode = bk.internalElement().ownerDocument().createElement((*it));
+ bk.internalElement().appendChild(subnode);
+ }
+ }
+
+ if (subnode.firstChild().isNull()) {
+ QDomText domtext = subnode.ownerDocument().createTextNode("");
+ subnode.appendChild(domtext);
+ }
+
+ QDomText domtext = subnode.firstChild().toText();
+
+ QString oldText = domtext.data();
+ domtext.setData(newValue);
+ return oldText;
+}
+
+void NodeEditCommand::execute() {
+ // DUPLICATED HEAVILY FROM KIO/BOOKMARKS
+ KBookmark bk = CurrentMgr::bookmarkAt(m_address);
+ Q_ASSERT(!bk.isNull());
+ m_oldText = setNodeText(bk, QStringList() << m_nodename, m_newText);
+}
+
+void NodeEditCommand::unexecute() {
+ // reuse code
+ NodeEditCommand cmd(m_address, m_oldText, m_nodename);
+ cmd.execute();
+ // get the old text back from it, in case they changed
+ // (hmm, shouldn't happen)
+ // AK - DUP'ed from above???
+ m_newText = cmd.m_oldText;
+}
+
+void NodeEditCommand::modify(const QString & newText)
+{
+ m_newText = newText;
+}
+
+QString NodeEditCommand::affectedBookmarks() const
+{
+ return KBookmark::parentAddress(m_address);
+}
+
+/* -------------------------------------- */
+
+void DeleteCommand::execute() {
+ // kdDebug() << "DeleteCommand::execute " << m_from << endl;
+
+ KBookmark bk = CurrentMgr::bookmarkAt(m_from);
+ Q_ASSERT(!bk.isNull());
+
+ if (m_contentOnly) {
+ QDomElement groupRoot = bk.internalElement();
+
+ QDomNode n = groupRoot.firstChild();
+ while (!n.isNull()) {
+ QDomElement e = n.toElement();
+ if (!e.isNull()) {
+ // kdDebug() << e.tagName() << endl;
+ }
+ QDomNode next = n.nextSibling();
+ groupRoot.removeChild(n);
+ n = next;
+ }
+ return;
+ }
+
+ // TODO - bug - unparsed xml is lost after undo,
+ // we must store it all therefore
+ if (!m_cmd) {
+ if (bk.isGroup()) {
+ m_cmd = new CreateCommand(
+ m_from, bk.fullText(), bk.icon(),
+ bk.internalElement().attribute("folded") == "no");
+ m_subCmd = deleteAll(bk.toGroup());
+ m_subCmd->execute();
+
+ } else {
+ m_cmd = (bk.isSeparator())
+ ? new CreateCommand(m_from)
+ : new CreateCommand(m_from, bk.fullText(),
+ bk.icon(), bk.url());
+ }
+ }
+
+ m_cmd->unexecute();
+}
+
+void DeleteCommand::unexecute() {
+ // kdDebug() << "DeleteCommand::unexecute " << m_from << endl;
+
+ if (m_contentOnly) {
+ // TODO - recover saved metadata
+ return;
+ }
+
+ m_cmd->execute();
+
+ if (m_subCmd) {
+ m_subCmd->unexecute();
+ }
+}
+
+QString DeleteCommand::affectedBookmarks() const
+{
+ return KBookmark::parentAddress(m_from);
+}
+
+KEBMacroCommand* DeleteCommand::deleteAll(const KBookmarkGroup & parentGroup) {
+ KEBMacroCommand *cmd = new KEBMacroCommand(QString::null);
+ QStringList lstToDelete;
+ // we need to delete from the end, to avoid index shifting
+ for (KBookmark bk = parentGroup.first();
+ !bk.isNull(); bk = parentGroup.next(bk))
+ lstToDelete.prepend(bk.address());
+ for (QStringList::Iterator it = lstToDelete.begin();
+ it != lstToDelete.end(); ++it)
+ cmd->addCommand(new DeleteCommand((*it)));
+ return cmd;
+}
+
+/* -------------------------------------- */
+
+QString MoveCommand::name() const {
+ return i18n("Move %1").arg(m_mytext);
+}
+
+void MoveCommand::execute() {
+ // kdDebug() << "MoveCommand::execute moving from=" << m_from
+ // << " to=" << m_to << endl;
+
+ KBookmark bk = CurrentMgr::bookmarkAt(m_from);
+ Q_ASSERT(!bk.isNull());
+
+ // look for m_from in the QDom tree
+ KBookmark oldParent =
+ CurrentMgr::bookmarkAt(KBookmark::parentAddress(m_from));
+ bool wasFirstChild = (KBookmark::positionInParent(m_from) == 0);
+
+ KBookmark oldPreviousSibling = wasFirstChild
+ ? KBookmark(QDomElement())
+ : CurrentMgr::bookmarkAt(
+ KBookmark::previousAddress(m_from));
+
+ // look for m_to in the QDom tree
+ QString parentAddress = KBookmark::parentAddress(m_to);
+
+ KBookmark newParent = CurrentMgr::bookmarkAt(parentAddress);
+ Q_ASSERT(!newParent.isNull());
+ Q_ASSERT(newParent.isGroup());
+
+ bool isFirstChild = (KBookmark::positionInParent(m_to) == 0);
+
+ if (isFirstChild) {
+ newParent.toGroup().moveItem(bk, QDomElement());
+
+ } else {
+ QString afterAddress = KBookmark::previousAddress(m_to);
+
+ // kdDebug() << "MoveCommand::execute afterAddress="
+ // << afterAddress << endl;
+ KBookmark afterNow = CurrentMgr::bookmarkAt(afterAddress);
+ Q_ASSERT(!afterNow.isNull());
+
+ bool movedOkay = newParent.toGroup().moveItem(bk, afterNow);
+ Q_ASSERT(movedOkay);
+
+ // kdDebug() << "MoveCommand::execute after moving in the dom tree"
+ // ": item=" << bk.address() << endl;
+ }
+
+ // because we moved stuff around, the from/to
+ // addresses can have changed, update
+ m_to = bk.address();
+ m_from = (wasFirstChild)
+ ? (oldParent.address() + "/0")
+ : KBookmark::nextAddress(oldPreviousSibling.address());
+ // kdDebug() << "MoveCommand::execute : new addresses from="
+ // << m_from << " to=" << m_to << endl;
+}
+
+QString MoveCommand::finalAddress() const {
+ Q_ASSERT( !m_to.isEmpty() );
+ return m_to;
+}
+
+void MoveCommand::unexecute() {
+ // let's not duplicate code.
+ MoveCommand undoCmd(m_to, m_from);
+ undoCmd.execute();
+ // get the addresses back from that command, in case they changed
+ m_from = undoCmd.m_to;
+ m_to = undoCmd.m_from;
+}
+
+QString MoveCommand::affectedBookmarks() const
+{
+ return KBookmark::commonParent(KBookmark::parentAddress(m_from), KBookmark::parentAddress(m_to));
+}
+
+/* -------------------------------------- */
+
+class SortItem {
+ public:
+ SortItem(const KBookmark & bk) : m_bk(bk) { ; }
+
+ bool operator == (const SortItem & s) {
+ return (m_bk.internalElement() == s.m_bk.internalElement()); }
+
+ bool isNull() const {
+ return m_bk.isNull(); }
+
+ SortItem previousSibling() const {
+ return m_bk.parentGroup().previous(m_bk); }
+
+ SortItem nextSibling() const {
+ return m_bk.parentGroup().next(m_bk); }
+
+ const KBookmark& bookmark() const {
+ return m_bk; }
+
+ private:
+ KBookmark m_bk;
+};
+
+class SortByName {
+ public:
+ static QString key(const SortItem &item) {
+ return (item.bookmark().isGroup() ? "a" : "b")
+ + (item.bookmark().fullText().lower());
+ }
+};
+
+/* -------------------------------------- */
+
+void SortCommand::execute() {
+ if (m_commands.isEmpty()) {
+ KBookmarkGroup grp = CurrentMgr::bookmarkAt(m_groupAddress).toGroup();
+ Q_ASSERT(!grp.isNull());
+ SortItem firstChild(grp.first());
+ // this will call moveAfter, which will add
+ // the subcommands for moving the items
+ kInsertionSort<SortItem, SortByName, QString, SortCommand>
+ (firstChild, (*this));
+
+ } else {
+ // don't execute for second time on addCommand(cmd)
+ KEBMacroCommand::execute();
+ }
+}
+
+void SortCommand::moveAfter(const SortItem &moveMe,
+ const SortItem &afterMe) {
+ QString destAddress =
+ afterMe.isNull()
+ // move as first child
+ ? KBookmark::parentAddress(moveMe.bookmark().address()) + "/0"
+ // move after "afterMe"
+ : KBookmark::nextAddress(afterMe.bookmark().address());
+
+ MoveCommand *cmd = new MoveCommand(moveMe.bookmark().address(),
+ destAddress);
+ cmd->execute();
+ this->addCommand(cmd);
+}
+
+void SortCommand::unexecute() {
+ KEBMacroCommand::unexecute();
+}
+
+QString SortCommand::affectedBookmarks() const
+{
+ return m_groupAddress;
+}
+
+/* -------------------------------------- */
+
+KEBMacroCommand* CmdGen::setAsToolbar(const KBookmark &bk) {
+ KEBMacroCommand *mcmd = new KEBMacroCommand(i18n("Set as Bookmark Toolbar"));
+
+ KBookmarkGroup oldToolbar = CurrentMgr::self()->mgr()->toolbar();
+ if (!oldToolbar.isNull()) {
+ QValueList<EditCommand::Edition> lst;
+ lst.append(EditCommand::Edition("toolbar", "no"));
+ lst.append(EditCommand::Edition("icon", ""));
+ EditCommand *cmd1 = new EditCommand(oldToolbar.address(), lst);
+ mcmd->addCommand(cmd1);
+ }
+
+ QValueList<EditCommand::Edition> lst;
+ lst.append(EditCommand::Edition("toolbar", "yes"));
+ lst.append(EditCommand::Edition("icon", "bookmark_toolbar"));
+ // TODO - see below
+ EditCommand *cmd2 = new EditCommand(bk.address(), lst);
+ mcmd->addCommand(cmd2);
+
+ return mcmd;
+}
+
+bool CmdGen::shownInToolbar(const KBookmark &bk) {
+ return (bk.internalElement().attribute("showintoolbar") == "yes");
+}
+
+KEBMacroCommand* CmdGen::setShownInToolbar(const QValueList<KBookmark> &bks, bool show) {
+ QString i18n_name = i18n("%1 in Bookmark Toolbar").arg(show ? i18n("Show")
+ : i18n("Hide"));
+ KEBMacroCommand *mcmd = new KEBMacroCommand(i18n_name);
+
+ QValueList<KBookmark>::ConstIterator it, end;
+ end = bks.end();
+ for(it = bks.begin(); it != end; ++it)
+ {
+ QValueList<EditCommand::Edition> lst;
+ lst.append(EditCommand::Edition("showintoolbar", show ? "yes" : "no"));
+ EditCommand *cmd = new EditCommand((*it).address(), lst);
+ mcmd->addCommand(cmd);
+ }
+ return mcmd;
+}
+
+KEBMacroCommand* CmdGen::insertMimeSource(
+ const QString &cmdName, QMimeSource *_data, const QString &addr
+) {
+ QMimeSource *data = _data;
+ bool modified = false;
+ const char *format = 0;
+ for (int i = 0; format = data->format(i), format; i++) {
+ // qt docs don't say if encodedData(blah) where
+ // blah is not a stored mimetype should return null
+ // or not. so, we search. sucky...
+ if (strcmp(format, "GALEON_BOOKMARK") == 0) {
+ modified = true;
+ QStoredDrag *mydrag = new QStoredDrag("application/x-xbel");
+ mydrag->setEncodedData(data->encodedData("GALEON_BOOKMARK"));
+ data = mydrag;
+ break;
+ } else if( strcmp(format, "application/x-xbel" )==0) {
+ /* nothing we created a kbbookmarks drag when we copy element (slotcopy/slotpaste)*/
+ break;
+ } else if (strcmp(format, "text/uri-list") == 0) {
+ KURL::List uris;
+ if (!KURLDrag::decode(data, uris))
+ continue; // break out of format loop
+ KURL::List::ConstIterator uit = uris.begin();
+ KURL::List::ConstIterator uEnd = uris.end();
+ QValueList<KBookmark> urlBks;
+ for ( ; uit != uEnd ; ++uit ) {
+ if (!(*uit).url().endsWith(".desktop")) {
+ urlBks << KBookmark::standaloneBookmark((*uit).prettyURL(), (*uit));
+ continue;
+ }
+ KDesktopFile df((*uit).path(), true);
+ QString title = df.readName();
+ KURL url(df.readURL());
+ if (title.isNull())
+ title = url.prettyURL();
+ urlBks << KBookmark::standaloneBookmark(title, url, df.readIcon());
+ }
+ KBookmarkDrag *mydrag = KBookmarkDrag::newDrag(urlBks, 0);
+ modified = true;
+ data = mydrag;
+ }
+ }
+ if (!KBookmarkDrag::canDecode(data))
+ {
+ if (modified) // Shouldn't happen
+ delete data;
+ return 0;
+ }
+ KEBMacroCommand *mcmd = new KEBMacroCommand(cmdName);
+ QString currentAddress = addr;
+ QValueList<KBookmark> bookmarks = KBookmarkDrag::decode(data);
+ for (QValueListConstIterator<KBookmark> it = bookmarks.begin();
+ it != bookmarks.end(); ++it) {
+ CreateCommand *cmd = new CreateCommand(currentAddress, (*it));
+ cmd->execute();
+ mcmd->addCommand(cmd);
+ currentAddress = KBookmark::nextAddress(currentAddress);
+ }
+ if (modified)
+ delete data;
+ return mcmd;
+}
+
+KEBMacroCommand* CmdGen::itemsMoved(const QValueVector<KEBListViewItem *> & items,
+ const QString &newAddress, bool copy) {
+ KEBMacroCommand *mcmd = new KEBMacroCommand(copy ? i18n("Copy Items")
+ : i18n("Move Items"));
+
+ QValueList<KBookmark> list = ListView::self()->itemsToBookmarks( items );
+ QValueList<KBookmark>::const_iterator it, end;
+ it = list.begin();
+ end = list.end();
+
+ QString bkInsertAddr = newAddress;
+ for (; it != end; ++it) {
+ if (copy) {
+ CreateCommand *cmd;
+ cmd = new CreateCommand(
+ bkInsertAddr,
+ (*it).internalElement()
+ .cloneNode(true).toElement(),
+ (*it).text());
+
+ cmd->execute();
+ mcmd->addCommand(cmd);
+
+ bkInsertAddr = cmd->finalAddress();
+
+ } else /* if (move) */ {
+ QString oldAddress = (*it).address();
+ if (bkInsertAddr.startsWith(oldAddress)) //FIXME uses internal representation of address
+ continue;
+
+ MoveCommand *cmd = new MoveCommand(oldAddress, bkInsertAddr,
+ (*it).text());
+ cmd->execute();
+ mcmd->addCommand(cmd);
+
+ bkInsertAddr = cmd->finalAddress();
+ }
+
+ bkInsertAddr = KBookmark::nextAddress(bkInsertAddr);
+ }
+
+ return mcmd;
+}
diff --git a/konqueror/keditbookmarks/commands.h b/konqueror/keditbookmarks/commands.h
new file mode 100644
index 000000000..61363f9dd
--- /dev/null
+++ b/konqueror/keditbookmarks/commands.h
@@ -0,0 +1,256 @@
+// kate: space-indent on; indent-width 3; replace-tabs on;
+/* 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __commands_h
+#define __commands_h
+
+#include <kcommand.h>
+#include <kbookmark.h>
+#include <qvaluevector.h>
+
+// Interface adds the affectedBookmarks method
+// Any class should on call add those bookmarks which are
+// affected by executing or unexecuting the command
+// Or a common parent of the affected bookmarks
+// see KBookmarkManager::notifyChange(KBookmarkGroup)
+class IKEBCommand
+{
+public:
+ IKEBCommand() {};
+ virtual ~IKEBCommand() {};
+ virtual QString affectedBookmarks() const = 0;
+ virtual QString currentAddress() const { return QString::null; }
+};
+
+class KEBMacroCommand : public KMacroCommand, public IKEBCommand
+{
+public:
+ KEBMacroCommand(const QString &name)
+ : KMacroCommand(name) {};
+ virtual ~KEBMacroCommand() {};
+ virtual QString affectedBookmarks() const;
+};
+
+class DeleteManyCommand : public KEBMacroCommand
+{
+public:
+ DeleteManyCommand(const QString &name, const QValueList<QString> & addresses);
+ virtual ~DeleteManyCommand() {};
+ virtual QString currentAddress() const;
+private:
+ QString prevOrParentAddress(QString addr);
+ QString preOrderNextAddress(QString addr);
+ bool isConsecutive(const QValueList<QString> & addresses);
+ QString m_currentAddress;
+};
+
+class CreateCommand : public KCommand, public IKEBCommand
+{
+public:
+ // separator
+ CreateCommand(const QString &address)
+ : KCommand(), m_to(address),
+ m_group(false), m_separator(true), m_originalBookmark(QDomElement())
+ { ; }
+
+ // bookmark
+ CreateCommand(const QString &address,
+ const QString &text, const QString &iconPath,
+ const KURL &url)
+ : KCommand(), m_to(address), m_text(text), m_iconPath(iconPath), m_url(url),
+ m_group(false), m_separator(false), m_originalBookmark(QDomElement())
+ { ; }
+
+ // folder
+ CreateCommand(const QString &address,
+ const QString &text, const QString &iconPath,
+ bool open)
+ : KCommand(), m_to(address), m_text(text), m_iconPath(iconPath),
+ m_group(true), m_separator(false), m_open(open), m_originalBookmark(QDomElement())
+ { ; }
+
+ // clone existing bookmark
+ CreateCommand(const QString &address,
+ const KBookmark &original, const QString &name = QString::null)
+ : KCommand(), m_to(address), m_group(false), m_separator(false),
+ m_open(false), m_originalBookmark(original), m_mytext(name)
+ { ; }
+
+ QString finalAddress() const;
+
+ virtual ~CreateCommand() { ; }
+ virtual void execute();
+ virtual void unexecute();
+ virtual QString name() const;
+ virtual QString affectedBookmarks() const;
+ virtual QString currentAddress() const;
+private:
+ QString m_to;
+ QString m_text;
+ QString m_iconPath;
+ KURL m_url;
+ bool m_group:1;
+ bool m_separator:1;
+ bool m_open:1;
+ KBookmark m_originalBookmark;
+ QString m_mytext;
+};
+
+class EditCommand : public KCommand, public IKEBCommand
+{
+public:
+
+ struct Edition {
+ Edition() { ; } // needed for QValueList
+ Edition(const QString &a, const QString &v) : attr(a), value(v) {}
+ QString attr;
+ QString value;
+ };
+
+ // change one attribute
+ EditCommand(const QString &address, Edition edition, const QString &name = QString::null)
+ : KCommand(), m_address(address), m_mytext(name)
+ {
+ m_editions.append(edition);
+ }
+
+ // change multiple attributes
+ EditCommand(const QString &address,
+ const QValueList<Edition> &editions,
+ const QString &name = QString::null)
+ : KCommand(), m_address(address), m_editions(editions), m_mytext(name)
+ { ; }
+
+ void modify(const QString & a, const QString & v);
+
+ virtual ~EditCommand() { ; }
+ virtual void execute();
+ virtual void unexecute();
+ virtual QString name() const;
+ virtual QString affectedBookmarks() const;
+private:
+ QString m_address;
+ QValueList<Edition> m_editions;
+ QValueList<Edition> m_reverseEditions;
+ QString m_mytext;
+};
+
+class NodeEditCommand : public KCommand, public IKEBCommand
+{
+public:
+ NodeEditCommand(const QString &address,
+ const QString &newText,
+ const QString &nodeName)
+ : KCommand(), m_address(address), m_newText(newText), m_nodename(nodeName)
+ { ; }
+
+ void modify(const QString & newText);
+
+ virtual ~NodeEditCommand() { ; }
+ virtual void execute();
+ virtual void unexecute();
+ virtual QString affectedBookmarks() const;
+ virtual QString name() const;
+ static QString getNodeText(KBookmark bk, const QStringList &nodehier);
+ static QString setNodeText(KBookmark bk, const QStringList &nodehier,
+ QString newValue);
+private:
+ QString m_address;
+ QString m_newText;
+ QString m_oldText;
+ QString m_nodename;
+};
+
+class DeleteCommand : public KCommand, public IKEBCommand
+{
+public:
+ DeleteCommand(const QString &from, bool contentOnly = false)
+ : KCommand(), m_from(from), m_cmd(0L), m_subCmd(0L), m_contentOnly(contentOnly)
+ { ; }
+ virtual ~DeleteCommand() { delete m_cmd; delete m_subCmd;}
+ virtual void execute();
+ virtual void unexecute();
+ virtual QString name() const {
+ // NOTE - DeleteCommand needs no name, its always embedded in a macrocommand
+ return "";
+ };
+ virtual QString affectedBookmarks() const;
+ static KEBMacroCommand* deleteAll(const KBookmarkGroup &parentGroup);
+private:
+ QString m_from;
+ KCommand *m_cmd;
+ KEBMacroCommand *m_subCmd;
+ bool m_contentOnly;
+};
+
+class MoveCommand : public KCommand, public IKEBCommand
+{
+public:
+ // "Create it with itemsAlreadyMoved=true since
+ // "KListView moves the item before telling us about it."
+ MoveCommand(const QString &from, const QString &to, const QString &name = QString::null)
+ : KCommand(), m_from(from), m_to(to), m_mytext(name)
+ { ; }
+ QString finalAddress() const;
+ virtual ~MoveCommand() { ; }
+ virtual void execute();
+ virtual void unexecute();
+ virtual QString name() const;
+ virtual QString affectedBookmarks() const;
+private:
+ QString m_from;
+ QString m_to;
+ QString m_mytext;
+};
+
+class SortItem;
+
+class SortCommand : public KEBMacroCommand
+{
+public:
+ SortCommand(const QString &name, const QString &groupAddress)
+ : KEBMacroCommand(name), m_groupAddress(groupAddress)
+ { ; }
+ virtual ~SortCommand()
+ { ; }
+ virtual void execute();
+ virtual void unexecute();
+ virtual QString affectedBookmarks() const;
+ // internal
+ void moveAfter(const SortItem &moveMe, const SortItem &afterMe);
+private:
+ QString m_groupAddress;
+};
+
+class KEBListViewItem;
+
+class CmdGen {
+public:
+ static KEBMacroCommand* setAsToolbar(const KBookmark &bk);
+ static KEBMacroCommand* setShownInToolbar(const QValueList<KBookmark> &bk, bool show);
+ static bool shownInToolbar(const KBookmark &bk);
+ static KEBMacroCommand* deleteItems(const QString &commandName, const QValueVector<KEBListViewItem *> & items);
+ static KEBMacroCommand* insertMimeSource(const QString &cmdName, QMimeSource *data, const QString &addr);
+ static KEBMacroCommand* itemsMoved(const QValueVector<KEBListViewItem *> & items, const QString &newAddress, bool copy);
+private:
+ CmdGen() { ; }
+};
+
+#endif
diff --git a/konqueror/keditbookmarks/cr16-app-keditbookmarks.png b/konqueror/keditbookmarks/cr16-app-keditbookmarks.png
new file mode 100644
index 000000000..6a3fc5efe
--- /dev/null
+++ b/konqueror/keditbookmarks/cr16-app-keditbookmarks.png
Binary files differ
diff --git a/konqueror/keditbookmarks/cr32-app-keditbookmarks.png b/konqueror/keditbookmarks/cr32-app-keditbookmarks.png
new file mode 100644
index 000000000..b7e10c47f
--- /dev/null
+++ b/konqueror/keditbookmarks/cr32-app-keditbookmarks.png
Binary files differ
diff --git a/konqueror/keditbookmarks/cr48-app-keditbookmarks.png b/konqueror/keditbookmarks/cr48-app-keditbookmarks.png
new file mode 100644
index 000000000..d1f5e91cc
--- /dev/null
+++ b/konqueror/keditbookmarks/cr48-app-keditbookmarks.png
Binary files differ
diff --git a/konqueror/keditbookmarks/cr64-app-keditbookmarks.png b/konqueror/keditbookmarks/cr64-app-keditbookmarks.png
new file mode 100644
index 000000000..8f2504942
--- /dev/null
+++ b/konqueror/keditbookmarks/cr64-app-keditbookmarks.png
Binary files differ
diff --git a/konqueror/keditbookmarks/dcop.cpp b/konqueror/keditbookmarks/dcop.cpp
new file mode 100644
index 000000000..76b27b9b6
--- /dev/null
+++ b/konqueror/keditbookmarks/dcop.cpp
@@ -0,0 +1,67 @@
+// -*- indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "dcop.h"
+
+#include "listview.h"
+#include "toplevel.h"
+
+#include <stdlib.h>
+
+#include <qclipboard.h>
+#include <qpopupmenu.h>
+#include <qpainter.h>
+
+#include <klocale.h>
+#include <kbookmarkmanager.h>
+#include <dcopclient.h>
+#include <kdebug.h>
+#include <kapplication.h>
+
+
+KBookmarkEditorIface::KBookmarkEditorIface()
+ : QObject(), DCOPObject("KBookmarkEditor") {
+ // connect(KBookmarkNotifier_stub, SIGNAL( updatedAccessMetadata(QString,QString) ),
+ // this, SLOT( slotDcopUpdatedAccessMetadata(QString,QString) ));
+ connectDCOPSignal(0, "KBookmarkNotifier", "updatedAccessMetadata(QString,QString)", "slotDcopUpdatedAccessMetadata(QString,QString)", false);
+}
+
+void KBookmarkEditorIface::slotDcopUpdatedAccessMetadata(QString filename, QString url) {
+ // evil hack, konqi gets updates by way of historymgr,
+ // therefore konqi does'nt want "save" notification,
+ // unfortunately to stop konqi getting it is difficult
+ // and probably not needed until more notifier events
+ // are added. therefore, we always updateaccessmetadata
+ // without caring about our modified state like normal
+ // and thusly there is no need to the bkmgr to do a "save"
+
+ // TODO - i'm not sure this is really true :)
+
+ if (/*KEBApp::self()->modified() &&*/ filename == CurrentMgr::self()->path()) {
+ kdDebug() << "slotDcopUpdatedAccessMetadata(" << url << ")" << endl;
+ // no undo
+ CurrentMgr::self()->mgr()->updateAccessMetadata(url, false);
+ ListView::self()->updateStatus(url);
+ KEBApp::self()->updateStatus(url);
+ // notice - no save here! see! :)
+ }
+}
+#include "dcop.moc"
diff --git a/konqueror/keditbookmarks/dcop.h b/konqueror/keditbookmarks/dcop.h
new file mode 100644
index 000000000..3e8e545d8
--- /dev/null
+++ b/konqueror/keditbookmarks/dcop.h
@@ -0,0 +1,36 @@
+// -*- mode:cperl; cperl-indent-level:4; cperl-continued-statement-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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __dcop_h
+#define __dcop_h
+
+#include <dcopobject.h>
+
+class KBookmarkEditorIface : public QObject, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+public:
+ KBookmarkEditorIface();
+k_dcop_hidden:
+ void slotDcopUpdatedAccessMetadata(QString filename, QString url);
+};
+
+#endif
diff --git a/konqueror/keditbookmarks/exporters.cpp b/konqueror/keditbookmarks/exporters.cpp
new file mode 100644
index 000000000..4b1bbb5e7
--- /dev/null
+++ b/konqueror/keditbookmarks/exporters.cpp
@@ -0,0 +1,90 @@
+// -*- 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "exporters.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kapplication.h>
+
+#include <qfile.h>
+
+HTMLExporter::HTMLExporter()
+ : m_out(&m_string, IO_WriteOnly) {
+}
+
+void HTMLExporter::write(const KBookmarkGroup &grp, const QString &filename, bool showAddress) {
+ QFile file(filename);
+ if (!file.open(IO_WriteOnly)) {
+ kdError(7043) << "Can't write to file " << filename << endl;
+ return;
+ }
+ QTextStream tstream(&file);
+ tstream.setEncoding(QTextStream::UnicodeUTF8);
+ tstream << toString(grp, showAddress);
+}
+
+QString HTMLExporter::toString(const KBookmarkGroup &grp, bool showAddress)
+{
+ m_showAddress = showAddress;
+ traverse(grp);
+ return "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
+ "<html><head><title>"+i18n("My Bookmarks")+"</title>\n"
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
+ "</head>\n"
+ "<body>\n"
+ "<div>"
+ + m_string +
+ "</div>\n"
+ "</body>\n</html>\n";
+}
+
+void HTMLExporter::visit(const KBookmark &bk) {
+ // kdDebug() << "visit(" << bk.text() << ")" << endl;
+ if(bk.isSeparator())
+ {
+ m_out << bk.fullText() << "<br>"<<endl;
+ }
+ else
+ {
+ if(m_showAddress)
+ {
+ m_out << bk.fullText() <<"<br>"<< endl;
+ m_out << "<i><div style =\"margin-left: 1em\">" << bk.url().url().utf8() << "</div></i>";
+ }
+ else
+ {
+ m_out << "<a href=\"" << bk.url().url().utf8() << "\">";
+ m_out << bk.fullText() << "</a><br>" << endl;
+ }
+ }
+}
+
+void HTMLExporter::visitEnter(const KBookmarkGroup &grp) {
+ // kdDebug() << "visitEnter(" << grp.text() << ")" << endl;
+ m_out << "<b>" << grp.fullText() << "</b><br>" << endl;
+ m_out << "<div style=\"margin-left: 2em\">"<< endl;
+}
+
+void HTMLExporter::visitLeave(const KBookmarkGroup &) {
+ // kdDebug() << "visitLeave()" << endl;
+ m_out << "</div>" << endl;
+}
+
diff --git a/konqueror/keditbookmarks/exporters.h b/konqueror/keditbookmarks/exporters.h
new file mode 100644
index 000000000..cdc3844ba
--- /dev/null
+++ b/konqueror/keditbookmarks/exporters.h
@@ -0,0 +1,39 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __exporters_h
+#define __exporters_h
+
+#include <kbookmark.h>
+
+class HTMLExporter : private KBookmarkGroupTraverser {
+public:
+ HTMLExporter();
+ QString toString(const KBookmarkGroup &, bool showAddress = false);
+ void write(const KBookmarkGroup &, const QString &, bool showAddress = false);
+private:
+ virtual void visit(const KBookmark &);
+ virtual void visitEnter(const KBookmarkGroup &);
+ virtual void visitLeave(const KBookmarkGroup &);
+private:
+ QString m_string;
+ QTextStream m_out;
+ bool m_showAddress;
+};
+
+#endif
diff --git a/konqueror/keditbookmarks/favicons.cpp b/konqueror/keditbookmarks/favicons.cpp
new file mode 100644
index 000000000..b99371324
--- /dev/null
+++ b/konqueror/keditbookmarks/favicons.cpp
@@ -0,0 +1,100 @@
+// -*- indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* This file is part of the KDE project
+ Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "favicons.h"
+
+#include "bookmarkiterator.h"
+#include "listview.h"
+#include "toplevel.h"
+#include "updater.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kapplication.h>
+
+FavIconsItrHolder *FavIconsItrHolder::s_self = 0;
+
+FavIconsItrHolder::FavIconsItrHolder()
+ : BookmarkIteratorHolder() {
+ // do stuff
+}
+
+void FavIconsItrHolder::doItrListChanged() {
+ kdDebug()<<"FavIconsItrHolder::doItrListChanged() "<<count()<<" iterators"<<endl;
+ KEBApp::self()->setCancelFavIconUpdatesEnabled(count() > 0);
+ if(count() == 0)
+ {
+ kdDebug()<<"Notifing managers "<<m_affectedBookmark<<endl;
+ CurrentMgr::self()->notifyManagers(CurrentMgr::bookmarkAt(m_affectedBookmark).toGroup());
+ m_affectedBookmark = QString::null;
+ }
+}
+
+void FavIconsItrHolder::addAffectedBookmark( const QString & address )
+{
+ kdDebug()<<"addAffectedBookmark "<<address<<endl;
+ if(m_affectedBookmark.isNull())
+ m_affectedBookmark = address;
+ else
+ m_affectedBookmark = KBookmark::commonParent(m_affectedBookmark, address);
+ kdDebug()<<" m_affectedBookmark is now "<<m_affectedBookmark<<endl;
+}
+
+/* -------------------------- */
+
+FavIconsItr::FavIconsItr(QValueList<KBookmark> bks)
+ : BookmarkIterator(bks) {
+ m_updater = 0;
+}
+
+FavIconsItr::~FavIconsItr() {
+ if (curItem())
+ curItem()->restoreStatus();
+ delete m_updater;
+}
+
+void FavIconsItr::slotDone(bool succeeded) {
+ // kdDebug() << "FavIconsItr::slotDone()" << endl;
+ curItem()->setTmpStatus(succeeded ? i18n("OK") : i18n("No favicon found"));
+ holder()->addAffectedBookmark(KBookmark::parentAddress(curBk().address()));
+ delayedEmitNextOne();
+}
+
+bool FavIconsItr::isApplicable(const KBookmark &bk) const {
+ return (!bk.isGroup() && !bk.isSeparator());
+}
+
+void FavIconsItr::doAction() {
+ // kdDebug() << "FavIconsItr::doAction()" << endl;
+ curItem()->setTmpStatus(i18n("Updating favicon..."));
+ if (!m_updater) {
+ m_updater = new FavIconUpdater(kapp, "FavIconUpdater");
+ connect(m_updater, SIGNAL( done(bool) ),
+ this, SLOT( slotDone(bool) ) );
+ }
+ if (curBk().url().protocol().startsWith("http")) {
+ m_updater->downloadIcon(curBk());
+ } else {
+ curItem()->setTmpStatus(i18n("Local file"));
+ delayedEmitNextOne();
+ }
+}
+
+#include "favicons.moc"
diff --git a/konqueror/keditbookmarks/favicons.h b/konqueror/keditbookmarks/favicons.h
new file mode 100644
index 000000000..81f7ed923
--- /dev/null
+++ b/konqueror/keditbookmarks/favicons.h
@@ -0,0 +1,69 @@
+// -*- mode:cperl; cperl-indent-level:4; cperl-continued-statement-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) 2002-2003 Alexander Kellett <lypanov@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __favicons_h
+#define __favicons_h
+
+#include <kbookmark.h>
+#include <konq_faviconmgr.h>
+
+#include <kparts/part.h>
+#include <kparts/browserinterface.h>
+
+#include "bookmarkiterator.h"
+
+class FavIconsItrHolder : public BookmarkIteratorHolder {
+public:
+ static FavIconsItrHolder* self() {
+ if (!s_self) { s_self = new FavIconsItrHolder(); }; return s_self;
+ }
+ void addAffectedBookmark( const QString & address );
+protected:
+ virtual void doItrListChanged();
+private:
+ FavIconsItrHolder();
+ static FavIconsItrHolder *s_self;
+ QString m_affectedBookmark;
+};
+
+class FavIconUpdater;
+
+class FavIconsItr : public BookmarkIterator
+{
+ Q_OBJECT
+
+public:
+ FavIconsItr(QValueList<KBookmark> bks);
+ ~FavIconsItr();
+ virtual FavIconsItrHolder* holder() const { return FavIconsItrHolder::self(); }
+
+public slots:
+ void slotDone(bool succeeded);
+
+protected:
+ virtual void doAction();
+ virtual bool isApplicable(const KBookmark &bk) const;
+
+private:
+ FavIconUpdater *m_updater;
+};
+
+#endif
+
diff --git a/konqueror/keditbookmarks/importers.cpp b/konqueror/keditbookmarks/importers.cpp
new file mode 100644
index 000000000..6b59f04cd
--- /dev/null
+++ b/konqueror/keditbookmarks/importers.cpp
@@ -0,0 +1,293 @@
+// -*- indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "importers.h"
+
+#include "commands.h"
+#include "toplevel.h"
+#include "listview.h"
+
+#include <qregexp.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+
+#include <kbookmarkmanager.h>
+
+#include <kbookmarkimporter.h>
+#include <kbookmarkimporter_ie.h>
+#include <kbookmarkimporter_opera.h>
+#include <kbookmarkimporter_crash.h>
+#include <kbookmarkdombuilder.h>
+
+QString ImportCommand::name() const {
+ return i18n("Import %1 Bookmarks").arg(visibleName());
+}
+
+QString ImportCommand::folder() const {
+ return m_folder ? i18n("%1 Bookmarks").arg(visibleName()) : QString::null;
+}
+
+ImportCommand* ImportCommand::importerFactory(const QCString &type) {
+ if (type == "Galeon") return new GaleonImportCommand();
+ else if (type == "IE") return new IEImportCommand();
+ else if (type == "KDE2") return new KDE2ImportCommand();
+ else if (type == "Opera") return new OperaImportCommand();
+ else if (type == "Crashes") return new CrashesImportCommand();
+ else if (type == "Moz") return new MozImportCommand();
+ else if (type == "NS") return new NSImportCommand();
+ else {
+ kdError() << "ImportCommand::importerFactory() - invalid type (" << type << ")!" << endl;
+ return 0;
+ }
+}
+
+ImportCommand* ImportCommand::performImport(const QCString &type, QWidget *top) {
+ ImportCommand *importer = ImportCommand::importerFactory(type);
+
+ QString mydirname = importer->requestFilename();
+ if (mydirname.isEmpty()) {
+ delete importer;
+ return 0;
+ }
+
+ int answer =
+ KMessageBox::questionYesNoCancel(
+ top, i18n("Import as a new subfolder or replace all the current bookmarks?"),
+ i18n("%1 Import").arg(importer->visibleName()),
+ i18n("As New Folder"), i18n("Replace"));
+
+ if (answer == KMessageBox::Cancel) {
+ delete importer;
+ return 0;
+ }
+
+ importer->import(mydirname, answer == KMessageBox::Yes);
+ return importer;
+}
+
+void ImportCommand::doCreateHoldingFolder(KBookmarkGroup &bkGroup) {
+ bkGroup = CurrentMgr::self()->mgr()
+ ->root().createNewFolder(CurrentMgr::self()->mgr(), folder(), false);
+ bkGroup.internalElement().setAttribute("icon", m_icon);
+ m_group = bkGroup.address();
+}
+
+void ImportCommand::execute() {
+ KBookmarkGroup bkGroup;
+
+ if (!folder().isNull()) {
+ doCreateHoldingFolder(bkGroup);
+
+ } else {
+ // import into the root, after cleaning it up
+ bkGroup = CurrentMgr::self()->mgr()->root();
+ delete m_cleanUpCmd;
+ m_cleanUpCmd = DeleteCommand::deleteAll(bkGroup);
+
+ KMacroCommand *mcmd = (KMacroCommand*) m_cleanUpCmd;
+ mcmd->addCommand(new DeleteCommand(bkGroup.address(),
+ true /* contentOnly */));
+ m_cleanUpCmd->execute();
+
+ // import at the root
+ m_group = "";
+ }
+
+ doExecute(bkGroup);
+}
+
+void ImportCommand::unexecute() {
+ if ( !folder().isEmpty() ) {
+ // we created a group -> just delete it
+ DeleteCommand cmd(m_group);
+ cmd.execute();
+
+ } else {
+ // we imported at the root -> delete everything
+ KBookmarkGroup root = CurrentMgr::self()->mgr()->root();
+ KCommand *cmd = DeleteCommand::deleteAll(root);
+
+ cmd->execute();
+ delete cmd;
+
+ // and recreate what was there before
+ m_cleanUpCmd->unexecute();
+ }
+}
+
+QString ImportCommand::affectedBookmarks() const
+{
+ QString rootAdr = CurrentMgr::self()->mgr()->root().address();
+ if(m_group == rootAdr)
+ return m_group;
+ else
+ return KBookmark::parentAddress(m_group);
+}
+
+/* -------------------------------------- */
+
+QString MozImportCommand::requestFilename() const {
+ static KMozillaBookmarkImporterImpl importer;
+ return importer.findDefaultLocation();
+}
+
+QString NSImportCommand::requestFilename() const {
+ static KNSBookmarkImporterImpl importer;
+ return importer.findDefaultLocation();
+}
+
+QString OperaImportCommand::requestFilename() const {
+ static KOperaBookmarkImporterImpl importer;
+ return importer.findDefaultLocation();
+}
+
+QString CrashesImportCommand::requestFilename() const {
+ static KCrashBookmarkImporterImpl importer;
+ return importer.findDefaultLocation();
+}
+
+QString IEImportCommand::requestFilename() const {
+ static KIEBookmarkImporterImpl importer;
+ return importer.findDefaultLocation();
+}
+
+// following two are really just xbel
+
+QString GaleonImportCommand::requestFilename() const {
+ return KFileDialog::getOpenFileName(
+ QDir::homeDirPath() + "/.galeon",
+ i18n("*.xbel|Galeon Bookmark Files (*.xbel)"));
+}
+
+#include "kstandarddirs.h"
+
+QString KDE2ImportCommand::requestFilename() const {
+ return KFileDialog::getOpenFileName(
+ locateLocal("data", "konqueror"),
+ i18n("*.xml|KDE Bookmark Files (*.xml)"));
+}
+
+/* -------------------------------------- */
+
+static void parseInto(const KBookmarkGroup &bkGroup, KBookmarkImporterBase *importer) {
+ KBookmarkDomBuilder builder(bkGroup, CurrentMgr::self()->mgr());
+ builder.connectImporter(importer);
+ importer->parse();
+}
+
+void OperaImportCommand::doExecute(const KBookmarkGroup &bkGroup) {
+ KOperaBookmarkImporterImpl importer;
+ importer.setFilename(m_fileName);
+ parseInto(bkGroup, &importer);
+}
+
+void CrashesImportCommand::doExecute(const KBookmarkGroup &bkGroup) {
+ KCrashBookmarkImporterImpl importer;
+ importer.setShouldDelete(true);
+ importer.setFilename(m_fileName);
+ parseInto(bkGroup, &importer);
+}
+
+void IEImportCommand::doExecute(const KBookmarkGroup &bkGroup) {
+ KIEBookmarkImporterImpl importer;
+ importer.setFilename(m_fileName);
+ parseInto(bkGroup, &importer);
+}
+
+void HTMLImportCommand::doExecute(const KBookmarkGroup &bkGroup) {
+ KNSBookmarkImporterImpl importer;
+ importer.setFilename(m_fileName);
+ importer.setUtf8(m_utf8);
+ parseInto(bkGroup, &importer);
+}
+
+/* -------------------------------------- */
+
+void XBELImportCommand::doCreateHoldingFolder(KBookmarkGroup &) {
+ // rather than reuse the old group node we transform the
+ // root xbel node into the group when doing an xbel import
+}
+
+void XBELImportCommand::doExecute(const KBookmarkGroup &/*bkGroup*/) {
+ // check if already open first???
+ KBookmarkManager *pManager = KBookmarkManager::managerForFile(m_fileName, false);
+
+ QDomDocument doc = CurrentMgr::self()->mgr()->internalDocument();
+
+ // get the xbel
+ QDomNode subDoc = pManager->internalDocument().namedItem("xbel").cloneNode();
+ if (subDoc.isProcessingInstruction())
+ subDoc = subDoc.nextSibling();
+ if (subDoc.isDocumentType())
+ subDoc = subDoc.nextSibling();
+ if (subDoc.nodeName() != "xbel")
+ return;
+
+ if (!folder().isEmpty()) {
+ // transform into folder
+ subDoc.toElement().setTagName("folder");
+
+ // clear attributes
+ QStringList tags;
+ for (uint i = 0; i < subDoc.attributes().count(); i++)
+ tags << subDoc.attributes().item(i).toAttr().name();
+ for (QStringList::Iterator it = tags.begin(); it != tags.end(); ++it)
+ subDoc.attributes().removeNamedItem((*it));
+
+ subDoc.toElement().setAttribute("icon", m_icon);
+
+ // give the folder a name
+ QDomElement textElem = doc.createElement("title");
+ subDoc.insertBefore(textElem, subDoc.firstChild());
+ textElem.appendChild(doc.createTextNode(folder()));
+ }
+
+ // import and add it
+ QDomNode node = doc.importNode(subDoc, true);
+
+ if (!folder().isEmpty()) {
+ CurrentMgr::self()->mgr()->root().internalElement().appendChild(node);
+ m_group = KBookmarkGroup(node.toElement()).address();
+
+ } else {
+ QDomElement root = CurrentMgr::self()->mgr()->root().internalElement();
+
+ QValueList<QDomElement> childList;
+
+ QDomNode n = subDoc.firstChild().toElement();
+ while (!n.isNull()) {
+ QDomElement e = n.toElement();
+ if (!e.isNull())
+ childList.append(e);
+ n = n.nextSibling();
+ }
+
+ QValueList<QDomElement>::Iterator it = childList.begin();
+ QValueList<QDomElement>::Iterator end = childList.end();
+ for (; it!= end ; ++it)
+ root.appendChild((*it));
+ }
+}
+
+#include "importers.moc"
diff --git a/konqueror/keditbookmarks/importers.h b/konqueror/keditbookmarks/importers.h
new file mode 100644
index 000000000..929bf249a
--- /dev/null
+++ b/konqueror/keditbookmarks/importers.h
@@ -0,0 +1,192 @@
+// -*- mode:cperl; cperl-indent-level:4; cperl-continued-statement-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) 2000 David Faure <faure@kde.org>
+ Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __importers_h
+#define __importers_h
+
+#include "commands.h"
+#include <klocale.h>
+#include <kio/job.h>
+
+#include <kcommand.h>
+#include <kbookmark.h>
+
+#include <qptrstack.h>
+#include <qobject.h>
+
+// part pure
+class ImportCommand : public QObject, public KCommand, public IKEBCommand
+{
+ Q_OBJECT
+public:
+ ImportCommand()
+ : KCommand(), m_utf8(false), m_folder(false), m_cleanUpCmd(0L)
+ { ; }
+
+ virtual void import(const QString &fileName, bool folder) = 0;
+
+ virtual QString name() const;
+ virtual QString visibleName() const { return m_visibleName; }
+ virtual QString requestFilename() const = 0;
+
+ static ImportCommand* performImport(const QCString &, QWidget *);
+ static ImportCommand* importerFactory(const QCString &);
+
+ virtual ~ImportCommand()
+ { ; }
+
+ virtual void execute();
+ virtual void unexecute();
+ virtual QString affectedBookmarks() const;
+
+ QString groupAddress() const { return m_group; }
+ QString folder() const;
+
+protected:
+ /**
+ * @param fileName HTML file to import
+ * @param folder name of the folder to create. Empty for no creation (root()).
+ * @param icon icon for the new folder, if @p folder isn't empty
+ * @param utf8 true if the HTML is in utf-8 encoding
+ */
+ void init(const QString &fileName, bool folder, const QString &icon, bool utf8)
+ {
+ m_fileName = fileName;
+ m_folder = folder;
+ m_icon = icon;
+ m_utf8 = utf8;
+ }
+
+ virtual void doCreateHoldingFolder(KBookmarkGroup &bkGroup);
+ virtual void doExecute(const KBookmarkGroup &) = 0;
+
+protected:
+ QString m_visibleName;
+ QString m_fileName;
+ QString m_icon;
+ QString m_group;
+ bool m_utf8;
+
+private:
+ bool m_folder;
+ KMacroCommand *m_cleanUpCmd;
+};
+
+// part pure
+class XBELImportCommand : public ImportCommand
+{
+public:
+ XBELImportCommand() : ImportCommand() { ; }
+ virtual void import(const QString &fileName, bool folder) = 0;
+ virtual QString requestFilename() const = 0;
+private:
+ virtual void doCreateHoldingFolder(KBookmarkGroup &bkGroup);
+ virtual void doExecute(const KBookmarkGroup &);
+};
+
+class GaleonImportCommand : public XBELImportCommand
+{
+public:
+ GaleonImportCommand() : XBELImportCommand() { m_visibleName = i18n("Galeon"); }
+ virtual void import(const QString &fileName, bool folder) {
+ init(fileName, folder, "", false);
+ }
+ virtual QString requestFilename() const;
+};
+
+class KDE2ImportCommand : public XBELImportCommand
+{
+public:
+ KDE2ImportCommand() : XBELImportCommand() { m_visibleName = i18n("KDE"); }
+ virtual void import(const QString &fileName, bool folder) {
+ init(fileName, folder, "", false);
+ }
+ virtual QString requestFilename() const;
+};
+
+// part pure
+class HTMLImportCommand : public ImportCommand
+{
+public:
+ HTMLImportCommand() : ImportCommand() { ; }
+ virtual void import(const QString &fileName, bool folder) = 0;
+ virtual QString requestFilename() const = 0;
+private:
+ virtual void doExecute(const KBookmarkGroup &);
+};
+
+class NSImportCommand : public HTMLImportCommand
+{
+public:
+ NSImportCommand() : HTMLImportCommand() { m_visibleName = i18n("Netscape"); }
+ virtual void import(const QString &fileName, bool folder) {
+ init(fileName, folder, "netscape", false);
+ }
+ virtual QString requestFilename() const;
+};
+
+class MozImportCommand : public HTMLImportCommand
+{
+public:
+ MozImportCommand() : HTMLImportCommand() { m_visibleName = i18n("Mozilla"); }
+ virtual void import(const QString &fileName, bool folder) {
+ init(fileName, folder, "mozilla", true);
+ }
+ virtual QString requestFilename() const;
+};
+
+class IEImportCommand : public ImportCommand
+{
+public:
+ IEImportCommand() : ImportCommand() { m_visibleName = i18n("IE"); }
+ virtual void import(const QString &fileName, bool folder) {
+ init(fileName, folder, "", false);
+ }
+ virtual QString requestFilename() const;
+private:
+ virtual void doExecute(const KBookmarkGroup &);
+};
+
+class OperaImportCommand : public ImportCommand
+{
+public:
+ OperaImportCommand() : ImportCommand() { m_visibleName = i18n("Opera"); }
+ virtual void import(const QString &fileName, bool folder) {
+ init(fileName, folder, "opera", false);
+ }
+ virtual QString requestFilename() const;
+private:
+ virtual void doExecute(const KBookmarkGroup &);
+};
+
+class CrashesImportCommand : public ImportCommand
+{
+public:
+ CrashesImportCommand() : ImportCommand() { m_visibleName = i18n("Crashes"); }
+ virtual void import(const QString &fileName, bool folder) {
+ init(fileName, folder, "core", false);
+ }
+ virtual QString requestFilename() const;
+private:
+ virtual void doExecute(const KBookmarkGroup &);
+};
+
+#endif
diff --git a/konqueror/keditbookmarks/kbookmarkmerger.cpp b/konqueror/keditbookmarks/kbookmarkmerger.cpp
new file mode 100644
index 000000000..f1e4ad741
--- /dev/null
+++ b/konqueror/keditbookmarks/kbookmarkmerger.cpp
@@ -0,0 +1,138 @@
+/**
+ * kbookmarkmerger.cpp - Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kbookmarkmanager.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <kstandarddirs.h>
+
+#include <dcopclient.h>
+
+#include <qdir.h>
+#include <qdom.h>
+#include <qfile.h>
+
+#include <X11/Xlib.h>
+
+static const KCmdLineOptions cmdLineOptions[] =
+{
+ { "+directory", I18N_NOOP( "Directory to scan for extra bookmarks" ), 0 },
+ KCmdLineLastOption
+};
+
+// The code for this function was taken from kdesktop/kcheckrunning.cpp
+static bool kdeIsRunning()
+{
+ Display *dpy = XOpenDisplay( NULL );
+ if ( !dpy ) {
+ return false;
+ }
+
+ Atom atom = XInternAtom( dpy, "_KDE_RUNNING", False );
+ return XGetSelectionOwner( dpy, atom ) != None;
+}
+
+int main( int argc, char**argv )
+{
+ const bool kdeRunning = kdeIsRunning();
+
+ KAboutData aboutData( "kbookmarkmerger", I18N_NOOP( "KBookmarkMerger" ),
+ "1.0", I18N_NOOP( "Merges bookmarks installed by 3rd parties into the user's bookmarks" ),
+ KAboutData::License_BSD,
+ I18N_NOOP( "Copyright © 2005 Frerich Raabe" ) );
+ aboutData.addAuthor( "Frerich Raabe", I18N_NOOP( "Original author" ),
+ "raabe@kde.org" );
+
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( cmdLineOptions );
+
+ if ( !kdeRunning ) {
+ KApplication::disableAutoDcopRegistration();
+ }
+ KApplication app( false, false );
+ app.disableSessionManagement();
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ if ( args->count() != 1 ) {
+ kdError() << "No directory to scan for bookmarks specified." << endl;
+ return 1;
+ }
+
+ KBookmarkManager *konqBookmarks = KBookmarkManager::userBookmarksManager();
+ QStringList mergedFiles;
+ {
+ KBookmarkGroup root = konqBookmarks->root();
+ for ( KBookmark bm = root.first(); !bm.isNull(); bm = root.next( bm ) ) {
+ if ( bm.isGroup() ) {
+ continue;
+ }
+
+ QString mergedFrom = bm.metaDataItem( "merged_from" );
+ if ( !mergedFrom.isNull() ) {
+ mergedFiles << mergedFrom;
+ }
+ }
+ }
+
+ bool didMergeBookmark = false;
+
+ QString extraBookmarksDirName = QFile::decodeName( args->arg( 0 ) );
+ QDir extraBookmarksDir( extraBookmarksDirName, "*.xml" );
+ if ( !extraBookmarksDir.isReadable() ) {
+ kdError() << "Failed to read files in directory " << extraBookmarksDirName << endl;
+ return 1;
+ }
+
+ for ( unsigned int i = 0; i < extraBookmarksDir.count(); ++i ) {
+ const QString fileName = extraBookmarksDir[ i ];
+ if ( mergedFiles.find( fileName ) != mergedFiles.end() ) {
+ continue;
+ }
+
+ const QString absPath = extraBookmarksDir.filePath( fileName );
+ KBookmarkManager *mgr = KBookmarkManager::managerForFile( absPath, false );
+ KBookmarkGroup root = mgr->root();
+ for ( KBookmark bm = root.first(); !bm.isNull(); bm = root.next( bm ) ) {
+ if ( bm.isGroup() ) {
+ continue;
+ }
+ bm.setMetaDataItem( "merged_from", fileName );
+ konqBookmarks->root().addBookmark( konqBookmarks, bm , false );
+ didMergeBookmark = true;
+ }
+ }
+
+ if ( didMergeBookmark ) {
+ if ( !konqBookmarks->save() ) {
+ kdError() << "Failed to write merged bookmarks." << endl;
+ return 1;
+ }
+ if ( kdeRunning ) {
+ konqBookmarks->notifyChanged( "" );
+ }
+ }
+}
+
diff --git a/konqueror/keditbookmarks/kebsearchline.cpp b/konqueror/keditbookmarks/kebsearchline.cpp
new file mode 100644
index 000000000..5d0f07e59
--- /dev/null
+++ b/konqueror/keditbookmarks/kebsearchline.cpp
@@ -0,0 +1,82 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Daniel Teske <teske@squorn.de>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kebsearchline.h"
+#include "kebsearchline.moc"
+
+KEBSearchLine::KEBSearchLine(QWidget *parent, KListView *listView, const char *name)
+ : KListViewSearchLine(parent, listView, name)
+{
+ mmode = AND;
+}
+
+KEBSearchLine::KEBSearchLine(QWidget *parent, const char *name)
+ :KListViewSearchLine(parent, name)
+{
+ mmode = AND;
+}
+
+void KEBSearchLine::updateSearch(const QString &s)
+{
+ KListViewSearchLine::updateSearch(s);
+ emit searchUpdated();
+}
+
+KEBSearchLine::~KEBSearchLine()
+{
+}
+
+bool KEBSearchLine::itemMatches(const QListViewItem *item, const QString &s) const
+{
+ if(mmode == EXACTLY)
+ return KListViewSearchLine::itemMatches(item, s);
+
+ if(lastpattern != s)
+ {
+ splitted = QStringList::split(QChar(' '), s);
+ lastpattern = s;
+ }
+
+ QStringList::const_iterator it = splitted.begin();
+ QStringList::const_iterator end = splitted.end();
+
+ if(mmode == OR)
+ {
+ if(it == end) //Nothing to match
+ return true;
+ for( ; it != end; ++it)
+ if(KListViewSearchLine::itemMatches(item, *it))
+ return true;
+ }
+ else if(mmode == AND)
+ for( ; it != end; ++it)
+ if(! KListViewSearchLine::itemMatches(item, *it))
+ return false;
+
+ return (mmode == AND);
+}
+
+KEBSearchLine::modes KEBSearchLine::mode()
+{
+ return mmode;
+}
+
+void KEBSearchLine::setMode(modes m)
+{
+ mmode = m;
+}
diff --git a/konqueror/keditbookmarks/kebsearchline.h b/konqueror/keditbookmarks/kebsearchline.h
new file mode 100644
index 000000000..43248177e
--- /dev/null
+++ b/konqueror/keditbookmarks/kebsearchline.h
@@ -0,0 +1,52 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Daniel Teske <teske@squorn.de>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kebsearchline_h
+#define __kebsearchline_h
+
+#include <klistviewsearchline.h>
+#include <qobject.h>
+
+class KEBSearchLine : public KListViewSearchLine
+{
+ Q_OBJECT
+public:
+ KEBSearchLine(QWidget *parent = 0, KListView *listView = 0, const char *name = 0);
+
+ KEBSearchLine(QWidget *parent, const char *name);
+
+ virtual ~KEBSearchLine();
+
+ enum modes { EXACTLY, AND, OR } mmode;
+ modes mode();
+ void setMode(modes m);
+ virtual void updateSearch(const QString &s = QString::null);
+
+signals:
+ void searchUpdated();
+
+protected:
+
+ virtual bool itemMatches(const QListViewItem *item, const QString &s) const;
+
+private:
+ mutable QString lastpattern; // what was cached
+ mutable QStringList splitted; // cache of the splitted string
+};
+
+#endif
diff --git a/konqueror/keditbookmarks/keditbookmarks-genui.rc b/konqueror/keditbookmarks/keditbookmarks-genui.rc
new file mode 100644
index 000000000..3a88d720e
--- /dev/null
+++ b/konqueror/keditbookmarks/keditbookmarks-genui.rc
@@ -0,0 +1,146 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="keditbookmarks" version="25">
+
+<MenuBar>
+
+<Menu name="file" noMerge="1"><text>&amp;File</text>
+ <Action name="file_open"/>
+ <Action name="file_save_as"/>
+ <Separator/>
+ <Action name="file_print"/>
+ <Separator/>
+ <Action name="file_quit"/>
+</Menu>
+
+<Menu name="edit"><text>&amp;Edit</text>
+ <!-- undo/redo/cut/copy/paste stuff is
+ merged (?) at this point (ui_standards.rc) -->
+ <!-- Various things -->
+ <Action name="rename" append="edit_paste_merge"/>
+ <Action name="delete" append="edit_paste_merge"/>
+ <Separator/>
+ <Action name="changeurl"/>
+ <Action name="changecomment"/>
+ <Action name="changeicon"/>
+</Menu>
+
+<Menu name="view"><text>&amp;View</text>
+ <Action name="expandall"/>
+ <Action name="collapseall"/>
+</Menu>
+
+<Menu name="folder"><text>&amp;Folder</text>
+ <Action name="newfolder"/>
+ <Action name="insertseparator"/>
+ <Separator/>
+ <Action name="sort"/>
+ <Action name="recursivesort"/>
+ </Menu>
+
+<Menu name="bookmark"><text>&amp;Bookmark</text>
+ <Action name="newbookmark"/>
+</Menu>
+
+<Menu name="settings"><text>&amp;Settings</text>
+<!-- <Action name="settings_splitview" append="save_merge"/> -->
+</Menu>
+
+</MenuBar>
+
+<ToolBar name="mainToolBar" noMerge="1" fullWidth="true"><text>Main Toolbar</text>
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Separator/>
+ <Action name="newbookmark"/>
+ <Action name="newfolder"/>
+</ToolBar>
+
+<Menu name="popup_folder">
+ <!-- Stuff for folders -->
+ <Action name="setastoolbar"/>
+ <Action name="sort"/>
+ <Action name="recursivesort"/>
+ <Separator/>
+ <Action name="testlink"/>
+ <Action name="updatefavicon"/>
+ <Separator/><!-- Clipboard -->
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/><!-- Edition -->
+ <Action name="rename"/>
+ <Action name="changeurl"/>
+ <Action name="changeicon"/>
+ <Separator/><!-- Creation -->
+ <Action name="newbookmark"/>
+ <Action name="newfolder"/>
+ <Action name="insertseparator"/>
+ <Separator/><!-- Dangerous actions :/ -->
+ <Action name="delete"/>
+</Menu>
+
+<Menu name="popup_bookmark">
+ <!-- Stuff for bookmarks -->
+ <Separator/><!-- Clipboard stuff -->
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/><!-- Edition -->
+ <Action name="rename"/>
+ <Action name="changeurl"/>
+ <Action name="changeicon"/>
+ <Separator/><!-- Creation -->
+ <Action name="newbookmark"/>
+ <Action name="newfolder"/>
+ <Action name="insertseparator"/>
+ <Separator/><!-- Dangerous actions :/ -->
+ <Action name="delete"/>
+</Menu>
+
+<!-- APPLICATION STATES -->
+
+<State name="notreadonly">
+ <Enable>
+ <Action name="settings_saveonclose"/>
+ </Enable>
+</State>
+
+<State name="normal">
+ <Enable>
+ <Action name="file_open"/>
+ <Action name="file_save_as"/>
+ <Action name="file_quit"/>
+ <Action name="expandall"/>
+ <Action name="collapseall"/>
+ </Enable>
+</State>
+
+<State name="disablestuff">
+ <Disable>
+ <Action name="changecomment"/>
+ <Action name="changeicon"/>
+ <Action name="changeurl"/>
+ <Action name="delete"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_cut"/>
+ <Action name="edit_paste"/>
+ <Action name="edit_redo"/>
+ <Action name="edit_undo"/>
+ <Action name="insertseparator"/>
+ <Action name="newbookmark"/>
+ <Action name="newfolder"/>
+ <Action name="nexthit"/>
+ <Action name="openlink"/>
+ <Action name="rename"/>
+ <Action name="setastoolbar"/>
+ <Action name="sort"/>
+ <Action name="recursivesort"/>
+ <Action name="settings_saveonclose"/>
+ </Disable>
+</State>
+
+</kpartgui>
diff --git a/konqueror/keditbookmarks/keditbookmarks.kcfg b/konqueror/keditbookmarks/keditbookmarks.kcfg
new file mode 100644
index 000000000..16da3d8b9
--- /dev/null
+++ b/konqueror/keditbookmarks/keditbookmarks.kcfg
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="keditbookmarksrc" />
+
+ <group name="Columns">
+ <entry key="Name" type="Int">
+ <default>300</default>
+ <label></label>
+ <whatsthis></whatsthis>
+ </entry>
+ <entry key="URL" type="Int">
+ <default>300</default>
+ <label></label>
+ <whatsthis></whatsthis>
+ </entry>
+ <entry key="Comment" type="Int">
+ <default>300</default>
+ <label></label>
+ <whatsthis></whatsthis>
+ </entry>
+ <entry key="Status" type="Int">
+ <default>300</default>
+ <label></label>
+ <whatsthis></whatsthis>
+ </entry>
+ <entry key="Address" type="Int">
+ <default>300</default>
+ <label></label>
+ <whatsthis></whatsthis>
+ </entry>
+ </group>
+ <group name="General">
+ <entry name="SaveOnClose" key="Save On Close" type="Bool">
+ <label></label>
+ <whatsthis></whatsthis>
+ </entry>
+ </group>
+
+</kcfg> \ No newline at end of file
diff --git a/konqueror/keditbookmarks/keditbookmarksui.rc b/konqueror/keditbookmarks/keditbookmarksui.rc
new file mode 100644
index 000000000..c6a559b39
--- /dev/null
+++ b/konqueror/keditbookmarks/keditbookmarksui.rc
@@ -0,0 +1,218 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="keditbookmarks" version="30">
+
+<MenuBar>
+
+<Menu name="file" noMerge="1"><text>&amp;File</text>
+ <Action name="file_open"/>
+ <Action name="file_save_as"/>
+ <Separator/>
+ <Action name="file_print"/>
+ <Separator/>
+ <Menu name="import" noMerge="1"><text>&amp;Import</text>
+ <Action name="importIE"/>
+ <Action name="importOpera"/>
+ <Action name="importMoz"/>
+ <Action name="importNS"/>
+ <Action name="importKDE2"/>
+ <Action name="importGaleon"/>
+ <Separator/>
+ <Action name="importCrashes"/>
+ </Menu>
+ <Menu name="export" noMerge="1"><text>&amp;Export</text>
+ <Action name="exportIE"/>
+ <Action name="exportOpera"/>
+ <Action name="exportMoz"/>
+ <Action name="exportNS"/>
+ <Separator/>
+ <Action name="exportHTML"/>
+ </Menu>
+ <Separator/>
+ <Action name="file_quit"/>
+</Menu>
+
+<Menu name="edit"><text>&amp;Edit</text>
+ <!-- undo/redo/cut/copy/paste stuff is
+ merged (?) at this point (ui_standards.rc) -->
+ <!-- Various things -->
+ <Action name="rename" append="edit_paste_merge"/>
+ <Action name="delete" append="edit_paste_merge"/>
+ <Separator/>
+ <Action name="changeurl"/>
+ <Action name="changecomment"/>
+ <Action name="changeicon"/>
+ <Separator/>
+ <Action name="showintoolbar"/>
+ <Action name="hideintoolbar"/>
+</Menu>
+
+<Menu name="view"><text>&amp;View</text>
+ <Action name="expandall"/>
+ <Action name="collapseall"/>
+</Menu>
+
+<Menu name="folder"><text>&amp;Folder</text>
+ <Action name="newfolder"/>
+ <Action name="insertseparator"/>
+ <Separator/>
+ <Action name="setastoolbar"/>
+ <Action name="sort"/>
+ <Action name="recursivesort"/>
+ </Menu>
+
+<Menu name="bookmark"><text>&amp;Bookmark</text>
+ <Action name="newbookmark"/>
+ <Action name="openlink"/>
+ <Separator/>
+ <Action name="testlink"/>
+ <Action name="updatefavicon"/>
+</Menu>
+
+<Menu name="tools"><text>&amp;Tools</text>
+ <Action name="testall"/>
+ <Action name="canceltests"/>
+ <Separator/>
+ <Action name="updateallfavicons"/>
+ <Action name="cancelfaviconupdates"/>
+</Menu>
+
+<Menu name="settings"><text>&amp;Settings</text>
+ <Action name="settings_saveonclose" append="save_merge"/>
+<!-- <Action name="settings_splitview" append="save_merge"/> -->
+ <Action name="settings_showNS" append="save_merge"/>
+</Menu>
+
+</MenuBar>
+
+<ToolBar name="mainToolBar" noMerge="1" fullWidth="true"><text>Main Toolbar</text>
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Separator/>
+ <Action name="newbookmark"/>
+ <Action name="newfolder"/>
+ <Separator/>
+ <Action name="delete" />
+</ToolBar>
+
+<Menu name="popup_folder">
+ <!-- Stuff for folders -->
+ <Action name="setastoolbar"/>
+ <Action name="showintoolbar"/>
+ <Action name="hideintoolbar"/>
+ <Action name="sort"/>
+ <Action name="recursivesort"/>
+ <Separator/>
+ <Action name="testlink"/>
+ <Action name="updatefavicon"/>
+ <Separator/><!-- Clipboard -->
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/><!-- Edition -->
+ <Action name="rename"/>
+ <Action name="changeurl"/>
+ <Action name="changeicon"/>
+ <Separator/><!-- Creation -->
+ <Action name="newbookmark"/>
+ <Action name="newfolder"/>
+ <Action name="insertseparator"/>
+ <Separator/><!-- Dangerous actions :/ -->
+ <Action name="delete"/>
+</Menu>
+
+<Menu name="popup_bookmark">
+ <!-- Stuff for bookmarks -->
+ <Action name="showintoolbar"/>
+ <Action name="hideintoolbar"/>
+ <Action name="openlink"/>
+ <Action name="testlink"/>
+ <Action name="updatefavicon"/>
+ <Separator/><!-- Clipboard stuff -->
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/><!-- Edition -->
+ <Action name="rename"/>
+ <Action name="changeurl"/>
+ <Action name="changeicon"/>
+ <Separator/><!-- Creation -->
+ <Action name="newbookmark"/>
+ <Action name="newfolder"/>
+ <Action name="insertseparator"/>
+ <Separator/><!-- Dangerous actions :/ -->
+ <Action name="delete"/>
+</Menu>
+
+<!-- APPLICATION STATES -->
+
+<State name="notreadonly">
+ <Enable>
+ <Action name="importGaleon"/>
+ <Action name="importKDE2"/>
+ <Action name="importOpera"/>
+ <Action name="importCrashes"/>
+ <Action name="importIE"/>
+ <Action name="importNS"/>
+ <Action name="importMoz"/>
+ <Action name="settings_showNS"/>
+ <Action name="settings_saveonclose"/>
+ </Enable>
+</State>
+
+<State name="normal">
+ <Enable>
+ <Action name="file_open"/>
+ <Action name="file_save_as"/>
+ <Action name="file_quit"/>
+ <Action name="exportOpera"/>
+ <Action name="exportHTML"/>
+ <Action name="exportIE"/>
+ <Action name="exportNS"/>
+ <Action name="exportMoz"/>
+ <Action name="expandall"/>
+ <Action name="collapseall"/>
+ </Enable>
+</State>
+
+<State name="disablestuff">
+ <Disable>
+ <Action name="changecomment"/>
+ <Action name="changeicon"/>
+ <Action name="changeurl"/>
+ <Action name="delete"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_cut"/>
+ <Action name="edit_paste"/>
+ <!-- automated by KCommandHistory: <Action name="edit_redo"/> <Action name="edit_undo"/> -->
+ <Action name="importGaleon"/>
+ <Action name="importIE"/>
+ <Action name="importKDE2"/>
+ <Action name="importMoz"/>
+ <Action name="importNS"/>
+ <Action name="importOpera"/>
+ <Action name="importCrashes"/>
+ <Action name="insertseparator"/>
+ <Action name="newbookmark"/>
+ <Action name="newfolder"/>
+ <Action name="nexthit"/>
+ <Action name="openlink"/>
+ <Action name="rename"/>
+ <Action name="setastoolbar"/>
+ <Action name="showintoolbar"/>
+ <Action name="hideintoolbar"/>
+ <Action name="sort"/>
+ <Action name="recursivesort"/>
+ <Action name="testall"/>
+ <Action name="testlink"/>
+ <Action name="updateallfavicons"/>
+ <Action name="updatefavicon"/>
+ <Action name="settings_showNS"/>
+ <Action name="settings_saveonclose"/>
+ </Disable>
+</State>
+
+</kpartgui>
diff --git a/konqueror/keditbookmarks/kinsertionsort.h b/konqueror/keditbookmarks/kinsertionsort.h
new file mode 100644
index 000000000..5f71184ed
--- /dev/null
+++ b/konqueror/keditbookmarks/kinsertionsort.h
@@ -0,0 +1,59 @@
+// -*- mode:cperl; cperl-indent-level:4; cperl-continued-statement-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) 2000 David Faure <faure@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kinsertionsort_h
+#define __kinsertionsort_h
+
+/**
+ * A template-based insertion sort algorithm, but not really 100%
+ * generic. It is mostly written for lists, not for arrays.
+ *
+ * A good reason to use insertion sort over faster algorithms like
+ * heap sort or quick sort, is that it minimizes the number of
+ * movements of the items. This is important in applications which support
+ * undo, because the number of commands is kept to a minimum.
+ */
+
+// Item must define isNull(), previousSibling(), nextSibling()
+// SortHelper must define moveAfter( const Item &, const Item & )
+// Criteria must define static Key key(const Item &)
+template <class Item, class Criteria, class Key, class SortHelper>
+inline void kInsertionSort( Item& firstChild, SortHelper& sortHelper )
+{
+ if (firstChild.isNull()) return;
+ Item j = firstChild.nextSibling();
+ while ( !j.isNull() )
+ {
+ Key key = Criteria::key(j);
+ // Insert A[j] into the sorted sequence A[1..j-1]
+ Item i = j.previousSibling();
+ bool moved = false;
+ while ( !i.isNull() && Criteria::key(i) > key )
+ {
+ i = i.previousSibling();
+ moved = true;
+ }
+ if ( moved )
+ sortHelper.moveAfter( j, i ); // move j right after i. If i is null, move to first position.
+ j = j.nextSibling();
+ }
+}
+
+#endif
diff --git a/konqueror/keditbookmarks/listview.cpp b/konqueror/keditbookmarks/listview.cpp
new file mode 100644
index 000000000..25f72afb2
--- /dev/null
+++ b/konqueror/keditbookmarks/listview.cpp
@@ -0,0 +1,968 @@
+// -*- indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "listview.h"
+
+#include "toplevel.h"
+#include "bookmarkinfo.h"
+#include "commands.h"
+#include "testlink.h"
+#include "settings.h"
+
+#include <stdlib.h>
+
+#include <qclipboard.h>
+#include <qpopupmenu.h>
+#include <qpainter.h>
+#include <qheader.h>
+
+
+#include <klocale.h>
+#include <dcopclient.h>
+#include <kdebug.h>
+#include <kapplication.h>
+
+#include <kaction.h>
+#include <kstdaction.h>
+#include <kedittoolbar.h>
+#include <kfiledialog.h>
+#include <kkeydialog.h>
+#include <kmessagebox.h>
+#include <klineedit.h>
+#include <krun.h>
+#include <klistviewsearchline.h>
+
+#include <kbookmarkdrag.h>
+#include <kbookmarkmanager.h>
+
+// #define DEBUG_ADDRESSES
+
+ListView* ListView::s_self = 0;
+
+int ListView::s_myrenamecolumn = -1;
+KEBListViewItem *ListView::s_myrenameitem = 0;
+
+QStringList ListView::s_selected_addresses;
+QString ListView::s_current_address;
+
+ListView::ListView()
+ : m_needToFixUp(false)
+{
+}
+
+ListView::~ListView() {
+ self()->m_listView->saveColumnSetting();
+}
+
+void ListView::createListViews(QSplitter *splitter) {
+ s_self = new ListView();
+ self()->m_listView = new KEBListView(splitter, false);
+ splitter->setSizes(QValueList<int>() << 100 << 300);
+}
+
+void ListView::initListViews() {
+ self()->m_listView->init();
+}
+
+void ListView::updateListViewSetup(bool readonly) {
+ self()->m_listView->readonlyFlagInit(readonly);
+}
+
+void ListView::connectSignals() {
+ m_listView->makeConnections();
+}
+
+bool lessAddress(QString a, QString b)
+{
+ if(a == b)
+ return false;
+
+ QString error("ERROR");
+ if(a == error)
+ return false;
+ if(b == error)
+ return true;
+
+ a += "/";
+ b += "/";
+
+ uint aLast = 0;
+ uint bLast = 0;
+ uint aEnd = a.length();
+ uint bEnd = b.length();
+ // Each iteration checks one "/"-delimeted part of the address
+ // "" is treated correctly
+ while(true)
+ {
+ // Invariant: a[0 ... aLast] == b[0 ... bLast]
+ if(aLast + 1 == aEnd) //The last position was the last slash
+ return true; // That means a is shorter than b
+ if(bLast +1 == bEnd)
+ return false;
+
+ uint aNext = a.find("/", aLast + 1);
+ uint bNext = b.find("/", bLast + 1);
+
+ bool okay;
+ uint aNum = a.mid(aLast + 1, aNext - aLast - 1).toUInt(&okay);
+ if(!okay)
+ return false;
+ uint bNum = b.mid(bLast + 1, bNext - bLast - 1).toUInt(&okay);
+ if(!okay)
+ return true;
+
+ if(aNum != bNum)
+ return aNum < bNum;
+
+ aLast = aNext;
+ bLast = bNext;
+ }
+}
+
+bool operator<(const KBookmark & first, const KBookmark & second) //FIXME Using internal represantation
+{
+ return lessAddress(first.address(), second.address());
+}
+
+
+
+QValueList<KBookmark> ListView::itemsToBookmarks(const QValueVector<KEBListViewItem *> & items) const
+{
+ QValueList<KBookmark> bookmarks; //TODO optimize by using a QValueVector
+ QValueVector<KEBListViewItem *>::const_iterator it = items.constBegin();
+ QValueVector<KEBListViewItem *>::const_iterator end = items.constEnd();
+ for( ; it!=end; ++it)
+ {
+ if(*it != m_listView->rootItem() )
+ bookmarks.push_back( (*it)->bookmark() );
+ }
+ qHeapSort(bookmarks);
+ return bookmarks;
+}
+
+void ListView::invalidate(const QString & address)
+{
+ invalidate(getItemAtAddress(address));
+}
+
+void ListView::invalidate(QListViewItem * item)
+{
+ if(item->isSelected())
+ {
+ m_listView->setSelected(item, false);
+ m_needToFixUp = true;
+ }
+
+ if(m_listView->currentItem() == item)
+ {
+ // later overiden by fixUpCurrent
+ m_listView->setCurrentItem(m_listView->rootItem());
+ m_needToFixUp = true;
+ }
+
+ QListViewItem * child = item->firstChild();
+ while(child)
+ {
+ //invalidate(child);
+ child = child->nextSibling();
+ }
+}
+
+void ListView::fixUpCurrent(const QString & address)
+{
+ if(!m_needToFixUp)
+ return;
+ m_needToFixUp = false;
+
+ QListViewItem * item;
+ if(mSelectedItems.count() != 0)
+ {
+ QString least = mSelectedItems.begin().key()->bookmark().address();
+ QMap<KEBListViewItem *, bool>::iterator it, end;
+ end = mSelectedItems.end();
+ for(it = mSelectedItems.begin(); it != end; ++it)
+ if( lessAddress(it.key()->bookmark().address(), least))
+ least = it.key()->bookmark().address();
+ item = getItemAtAddress(least);
+ }
+ else
+ item = getItemAtAddress(address);
+ m_listView->setSelected( item, true );
+ m_listView->setCurrentItem( item );
+}
+
+
+void ListView::selected(KEBListViewItem * item, bool s)
+{
+ Q_ASSERT(item->bookmark().hasParent() || item == m_listView->rootItem());
+ QMap<KEBListViewItem *, bool>::iterator it;
+
+ if(s)
+ mSelectedItems[item] = item;
+ else
+ if((it = mSelectedItems.find(item)) != mSelectedItems.end())
+ mSelectedItems.remove(it);
+
+ KEBApp::self()->updateActions();
+
+ const QValueVector<KEBListViewItem *> & selected = selectedItemsMap();
+ if (selected.count() != 1)
+ {
+ KEBApp::self()->bkInfo()->showBookmark(KBookmark());
+ return;
+ }
+ //FIXME do it once somewhere
+ if (!KEBApp::self()->bkInfo()->connected()) {
+ connect(KEBApp::self()->bkInfo(), SIGNAL( updateListViewItem() ),
+ SLOT( slotBkInfoUpdateListViewItem() ));
+ KEBApp::self()->bkInfo()->setConnected(true);
+ }
+
+ KEBApp::self()->bkInfo()->showBookmark((*(selected.constBegin()))->bookmark());
+ firstSelected()->modUpdate();
+}
+
+QValueVector<KEBListViewItem *> ListView::selectedItemsMap() const
+{
+ QValueVector<KEBListViewItem *> selected;
+ QMap<KEBListViewItem *, bool>::ConstIterator it, end;
+ end = mSelectedItems.constEnd();
+ for(it = mSelectedItems.constBegin(); it != end; ++it)
+ {
+ if( it.key()->isVisible())
+ selected.push_back(it.key());
+ }
+ return selected;
+}
+
+KEBListViewItem * ListView::firstSelected() const
+{
+ if(mSelectedItems.isEmpty())
+ return 0L;
+
+ QValueVector<KEBListViewItem *> selected = selectedItemsMap();
+ if(selected.isEmpty())
+ return 0L;
+ else
+ return *(selected.constBegin());
+}
+
+void ListView::deselectAllChildren(KEBListViewItem *item)
+{
+ KEBListViewItem* child = static_cast<KEBListViewItem *>(item->firstChild());
+ while(child)
+ {
+ if (child)
+ {
+ if(child->isSelected())
+ child->listView()->setSelected(child, false); //calls deselectAllChildren
+ else
+ deselectAllChildren(child);
+ }
+ child->repaint();
+ child = static_cast<KEBListViewItem *>(child->nextSibling());
+ }
+}
+
+QValueList<QString> ListView::selectedAddresses()
+{
+ QValueList<QString> addresses;
+ QValueList<KBookmark> bookmarks = itemsToBookmarks( selectedItemsMap() );
+ QValueList<KBookmark>::const_iterator it, end;
+ end = bookmarks.end();
+ for( it = bookmarks.begin(); it != end; ++it)
+ addresses.append( (*it).address() );
+ return addresses;
+}
+
+
+QValueList<KBookmark> ListView::selectedBookmarksExpanded() const {
+ QValueList<KBookmark> bookmarks;
+ for (QListViewItemIterator it(m_listView); it.current() != 0; ++it) {
+ if (!it.current()->isSelected())
+ continue;
+ if(it.current() == m_listView->firstChild()) // root case
+ continue;
+ if(!it.current()->isVisible()) // skip over filtered bookmarks
+ continue;
+ if (it.current()->childCount() == 0) // non folder case
+ bookmarks.append(static_cast<KEBListViewItem *>(it.current())->bookmark());
+ else
+ selectedBookmarksExpandedHelper(static_cast<KEBListViewItem *>(it.current()), bookmarks);
+ }
+ return bookmarks;
+}
+
+
+void ListView::selectedBookmarksExpandedHelper(KEBListViewItem * item, QValueList<KBookmark> & bookmarks) const
+{
+ KEBListViewItem* child = static_cast<KEBListViewItem *>(item->firstChild());
+ while( child )
+ {
+ if(child->isVisible())
+ {
+ if (!child->isEmptyFolderPadder() && (child->childCount() == 0))
+ bookmarks.append(child->bookmark());
+ if(child->childCount())
+ selectedBookmarksExpandedHelper(child, bookmarks);
+ }
+ child = static_cast<KEBListViewItem *>(child->nextSibling());
+ }
+}
+
+QValueList<KBookmark> ListView::allBookmarks() const {
+ QValueList<KBookmark> bookmarks;
+ for (QListViewItemIterator it(m_listView); it.current() != 0; ++it)
+ {
+ KEBListViewItem * item = static_cast<KEBListViewItem *>(it.current());
+ if (!item->isEmptyFolderPadder() && (item->childCount() == 0))
+ bookmarks.append(static_cast<KEBListViewItem *>(it.current())->bookmark());
+ }
+ return bookmarks;
+}
+
+// DESIGN - make + "/0" a kbookmark:: thing?
+
+QString ListView::userAddress() const
+{
+ KBookmark current = firstSelected()->bookmark();
+ return (current.isGroup())
+ ? (current.address() + "/0") //FIXME internal represantation used
+ : KBookmark::nextAddress(current.address());
+}
+
+void ListView::setCurrent(KEBListViewItem *item, bool select) {
+ m_listView->setCurrentItem(item);
+ if(select)
+ {
+ m_listView->clearSelection();
+ m_listView->setSelected(item, true);
+ }
+}
+
+KEBListViewItem* ListView::getItemAtAddress(const QString &address) const {
+ //FIXME uses internal represantation of bookmark address
+ QListViewItem *item = m_listView->rootItem();
+
+ QStringList addresses = QStringList::split('/',address); // e.g /5/10/2
+
+ for (QStringList::Iterator it = addresses.begin(); it != addresses.end(); ++it) {
+ if (item = item->firstChild(), !item)
+ return 0;
+ for (unsigned int i = 0; i < (*it).toUInt(); ++i)
+ if (item = item->nextSibling(), !item)
+ return 0;
+ }
+ return static_cast<KEBListViewItem *>(item);
+}
+
+void ListView::setOpen(bool open) {
+ for (QListViewItemIterator it(m_listView); it.current() != 0; ++it)
+ if (it.current()->parent())
+ it.current()->setOpen(open);
+}
+
+SelcAbilities ListView::getSelectionAbilities() const {
+ SelcAbilities sa = { false, false, false, false, false, false, false, false, false };
+
+ if (mSelectedItems.count() > 0)
+ {
+ QValueVector<KEBListViewItem *> selected = selectedItemsMap();
+ if(!selected.isEmpty())
+ {
+ //Optimize
+ KBookmark nbk = (*(selected.constBegin()))->bookmark();
+ sa.itemSelected = true;
+ sa.group = nbk.isGroup();
+ sa.separator = nbk.isSeparator();
+ sa.urlIsEmpty = nbk.url().isEmpty();
+ sa.root = (*(selected.constBegin()) == m_listView->rootItem());
+ sa.multiSelect = (selected.count() > 1);
+ sa.singleSelect = (!sa.multiSelect && sa.itemSelected);
+ sa.tbShowState = CmdGen::shownInToolbar(nbk);
+ }
+ }
+
+ sa.notEmpty = (m_listView->rootItem()->childCount() > 0);
+
+ return sa;
+}
+
+void ListView::handleDropped(KEBListView *, QDropEvent *e, QListViewItem *newParent, QListViewItem *itemAfterQLVI) {
+ bool inApp = (e->source() == m_listView->viewport());
+
+ // drop before root item
+ if (!newParent)
+ return;
+
+ KEBListViewItem *itemAfter = static_cast<KEBListViewItem *>(itemAfterQLVI);
+
+ QString newAddress
+ = (!itemAfter || itemAfter->isEmptyFolderPadder())
+ ? (static_cast<KEBListViewItem *>(newParent)->bookmark().address() + "/0")
+ : (KBookmark::nextAddress(itemAfter->bookmark().address()));
+
+ KEBMacroCommand *mcmd = 0;
+
+ if (!inApp) {
+ mcmd = CmdGen::insertMimeSource(i18n("Drop Items"), e, newAddress);
+
+ } else {
+ const QValueVector<KEBListViewItem *> & selected = selectedItemsMap();
+ if (!(selected.count() > 0) || (*(selected.constBegin()) == itemAfterQLVI))
+ return;
+ bool copy = (e->action() == QDropEvent::Copy);
+ mcmd = CmdGen::itemsMoved(selected, newAddress, copy);
+ }
+
+ CmdHistory::self()->didCommand(mcmd);
+}
+
+void ListView::updateStatus(QString url) {
+ m_listView->updateByURL(url);
+}
+
+void ListView::updateListView()
+{
+ // this is upper border of the visible are
+ int lastCurrentY = m_listView->contentsY();
+
+ //Save selected items (restored in fillWithGroup)
+ s_selected_addresses.clear();
+ QMap<KEBListViewItem *, bool>::const_iterator it, end;
+ it = mSelectedItems.begin();
+ end = mSelectedItems.end();
+ for ( ; it != end; ++it)
+ s_selected_addresses << it.key()->bookmark().address();
+ if(m_listView->currentItem())
+ {
+ KEBListViewItem * item = static_cast<KEBListViewItem*>(m_listView->currentItem());
+ if(item->isEmptyFolderPadder())
+ s_current_address = static_cast<KEBListViewItem*>(item->parent())->bookmark().address();
+ else
+ s_current_address = item->bookmark().address();
+ }
+ else
+ s_current_address = QString::null;
+
+ updateTree();
+ m_searchline->updateSearch();
+
+ // ensureVisible wants to have the midpoint of the new visible area
+ m_listView->ensureVisible(0, lastCurrentY + m_listView->visibleHeight() / 2, 0, m_listView->visibleHeight() / 2 );
+}
+
+void ListView::updateTree() {
+ KBookmarkGroup root = CurrentMgr::self()->mgr()->root();
+ fillWithGroup(m_listView, root);
+}
+
+void ListView::fillWithGroup(KEBListView *lv, KBookmarkGroup group, KEBListViewItem *parentItem) {
+ KEBListViewItem *lastItem = 0;
+ if (!parentItem)
+ {
+ lv->clear();
+ KEBListViewItem *tree = new KEBListViewItem(lv, group);
+ fillWithGroup(lv, group, tree);
+ tree->QListViewItem::setOpen(true);
+ if (s_selected_addresses.contains(tree->bookmark().address()))
+ lv->setSelected(tree, true);
+ if(!s_current_address.isNull() && s_current_address == tree->bookmark().address())
+ lv->setCurrentItem(tree);
+ return;
+ }
+ for (KBookmark bk = group.first(); !bk.isNull(); bk = group.next(bk)) {
+ KEBListViewItem *item = 0;
+ if (bk.isGroup()) {
+ KBookmarkGroup grp = bk.toGroup();
+ item = (parentItem)
+ ? new KEBListViewItem(parentItem, lastItem, grp)
+ : new KEBListViewItem(lv, lastItem, grp);
+ fillWithGroup(lv, grp, item);
+ if (grp.isOpen())
+ item->QListViewItem::setOpen(true);
+ if (grp.first().isNull())
+ new KEBListViewItem(item, item); // empty folder
+ lastItem = item;
+
+ }
+ else
+ {
+ item = (parentItem)
+ ? ( (lastItem)
+ ? new KEBListViewItem(parentItem, lastItem, bk)
+ : new KEBListViewItem(parentItem, bk))
+ : ( (lastItem)
+ ? new KEBListViewItem(lv, lastItem, bk)
+ : new KEBListViewItem(lv, bk));
+ lastItem = item;
+ }
+ if (s_selected_addresses.contains(bk.address()))
+ lv->setSelected(item, true);
+ if(!s_current_address.isNull() && s_current_address == bk.address())
+ lv->setCurrentItem(item);
+ }
+}
+
+void ListView::handleMoved(KEBListView *) {
+ // kdDebug() << "ListView::handleMoved()" << endl;
+ /* TODO - neil's wishlist item - unfortunately handleMoved is not called sometimes...
+ * KMacroCommand *mcmd = CmdGen::self()->deleteItems( i18n("Moved Items"),
+ * ListView::self()->selectedItems());
+ * CmdHistory::self()->didCommand(mcmd);
+ */
+}
+
+void ListView::slotBkInfoUpdateListViewItem() {
+ // its not possible that the selection changed inbetween as
+ // handleSelectionChanged is the one that sets up bkInfo()
+ // to emit this signal, otoh. maybe this can cause various
+ // differing responses.
+ // kdDebug() << "slotBkInfoUpdateListViewItem()" << endl;
+ KEBListViewItem *i = firstSelected();
+ Q_ASSERT(i);
+ KBookmark bk = i->bookmark();
+ i->setText(KEBListView::NameColumn, bk.fullText());
+ i->setText(KEBListView::UrlColumn, bk.url().pathOrURL());
+ QString commentStr = NodeEditCommand::getNodeText(bk, QStringList() << "desc");
+ i->setText(KEBListView::CommentColumn, commentStr);
+}
+
+void ListView::handleContextMenu(KEBListView *, KListView *, QListViewItem *qitem, const QPoint &p) {
+ KEBListViewItem *item = static_cast<KEBListViewItem *>(qitem);
+ const char *type = ( !item
+ || (item == m_listView->rootItem())
+ || (item->bookmark().isGroup())
+ || (item->isEmptyFolderPadder()))
+ ? "popup_folder" : "popup_bookmark";
+ QWidget* popup = KEBApp::self()->popupMenuFactory(type);
+ if (popup)
+ static_cast<QPopupMenu*>(popup)->popup(p);
+}
+
+void ListView::handleDoubleClicked(KEBListView *lv, QListViewItem *item, const QPoint &, int column) {
+ lv->rename(item, column);
+}
+
+void ListView::handleItemRenamed(KEBListView *lv, QListViewItem *item, const QString &newText, int column) {
+ Q_ASSERT(item);
+ KBookmark bk = static_cast<KEBListViewItem *>(item)->bookmark();
+ KCommand *cmd = 0;
+ if (column == KEBListView::NameColumn) {
+ if (newText.isEmpty()) {
+ // can't have an empty name, therefore undo the user action
+ item->setText(KEBListView::NameColumn, bk.fullText());
+ } else if (bk.fullText() != newText) {
+ cmd = new NodeEditCommand(bk.address(), newText, "title");
+ }
+
+ } else if (column == KEBListView::UrlColumn && !lv->isFolderList()) {
+ if (bk.url().pathOrURL() != newText)
+ {
+ KURL u = KURL::fromPathOrURL(newText);
+ cmd = new EditCommand(bk.address(), EditCommand::Edition("href", u.url(0, 106)), i18n("URL"));
+ }
+
+ } else if (column == KEBListView::CommentColumn && !lv->isFolderList()) {
+ if (NodeEditCommand::getNodeText(bk, "desc") != newText)
+ cmd = new NodeEditCommand(bk.address(), newText, "desc");
+ }
+ CmdHistory::self()->addCommand(cmd);
+}
+
+// used by f2 and f3 shortcut slots - see actionsimpl
+void ListView::rename(int column) {
+ m_listView->rename(firstSelected(), column);
+}
+
+void ListView::clearSelection() {
+ m_listView->clearSelection();
+}
+
+void ListView::startRename(int column, KEBListViewItem *item) {
+ s_myrenamecolumn = column;
+ s_myrenameitem = item;
+}
+
+void ListView::renameNextCell(bool fwd) {
+ KEBListView *lv = m_listView;
+ while (1) {
+ if (fwd && s_myrenamecolumn < KEBListView::CommentColumn) {
+ s_myrenamecolumn++;
+ } else if (!fwd && s_myrenamecolumn > KEBListView::NameColumn) {
+ s_myrenamecolumn--;
+ } else {
+ s_myrenameitem =
+ static_cast<KEBListViewItem *>(
+ fwd ? ( s_myrenameitem->itemBelow()
+ ? s_myrenameitem->itemBelow() : lv->firstChild() )
+ : ( s_myrenameitem->itemAbove()
+ ? s_myrenameitem->itemAbove() : lv->lastItem() ) );
+ s_myrenamecolumn
+ = fwd ? KEBListView::NameColumn
+ : KEBListView::CommentColumn;
+ }
+ if (s_myrenameitem
+ && s_myrenameitem != m_listView->rootItem()
+ && !s_myrenameitem->isEmptyFolderPadder()
+ && !s_myrenameitem->bookmark().isSeparator()
+ && !(s_myrenamecolumn == KEBListView::UrlColumn && s_myrenameitem->bookmark().isGroup())
+ ) {
+ break;
+ }
+ }
+ lv->rename(s_myrenameitem, s_myrenamecolumn);
+}
+
+/* -------------------------------------- */
+
+class KeyPressEater : public QObject {
+ public:
+ KeyPressEater( QWidget *parent = 0, const char *name = 0 )
+ : QObject(parent, name) {
+ m_allowedToTab = true;
+ }
+ protected:
+ bool eventFilter(QObject *, QEvent *);
+ bool m_allowedToTab;
+};
+
+bool KeyPressEater::eventFilter(QObject *, QEvent *pe) {
+ if (pe->type() == QEvent::KeyPress) {
+ QKeyEvent *k = (QKeyEvent *) pe;
+ if ((k->key() == Qt::Key_Backtab || k->key() == Qt::Key_Tab)
+ && !(k->state() & ControlButton || k->state() & AltButton)
+ ) {
+ if (m_allowedToTab) {
+ bool fwd = (k->key() == Key_Tab && !(k->state() & ShiftButton));
+ ListView::self()->renameNextCell(fwd);
+ }
+ return true;
+ } else {
+ m_allowedToTab = (k->key() == Qt::Key_Escape || k->key() == Qt::Key_Enter);
+ }
+ }
+ return false;
+}
+
+/* -------------------------------------- */
+
+void KEBListView::loadColumnSetting()
+{
+ header()->resizeSection(KEBListView::NameColumn, KEBSettings::name());
+ header()->resizeSection(KEBListView::UrlColumn, KEBSettings::uRL());
+ header()->resizeSection(KEBListView::CommentColumn, KEBSettings::comment());
+ header()->resizeSection(KEBListView::StatusColumn, KEBSettings::status());
+#ifdef DEBUG_ADDRESSES
+ header()->resizeSection(KEBListView::AddressColumn, KEBSettings::address());
+#endif
+ m_widthsDirty = false;
+}
+
+void KEBListView::saveColumnSetting ()
+{
+ if (m_widthsDirty) {
+ KEBSettings::setName( header()->sectionSize(KEBListView::NameColumn));
+ KEBSettings::setURL( header()->sectionSize(KEBListView::UrlColumn));
+ KEBSettings::setComment( header()->sectionSize(KEBListView::CommentColumn));
+ KEBSettings::setStatus( header()->sectionSize(KEBListView::StatusColumn));
+#ifdef DEBUG_ADDRESSES
+ KEBSettings::setAddress( header()->sectionSize(KEBListView::AddressColumn));
+#endif
+ KEBSettings::writeConfig();
+ }
+}
+
+void KEBListView::slotColumnSizeChanged(int, int, int)
+{
+ m_widthsDirty = true;
+}
+
+void KEBListView::init() {
+ setRootIsDecorated(false);
+ if (!m_folderList) {
+ addColumn(i18n("Bookmark"), 0); // KEBListView::NameColumn
+ addColumn(i18n("URL"), 0);
+ addColumn(i18n("Comment"), 0);
+ addColumn(i18n("Status"), 0);
+#ifdef DEBUG_ADDRESSES
+ addColumn(i18n("Address"), 0);
+#endif
+ } else {
+ addColumn(i18n("Folder"), 0);
+ }
+ loadColumnSetting();
+ setRenameable(KEBListView::NameColumn);
+ setRenameable(KEBListView::UrlColumn);
+ setRenameable(KEBListView::CommentColumn);
+ setTabOrderedRenaming(false);
+ setSorting(-1, false);
+ setDragEnabled(true);
+ setSelectionModeExt((!m_folderList) ? KListView::Extended: KListView::Single);
+ setAllColumnsShowFocus(true);
+ connect(header(), SIGNAL(sizeChange(int, int, int)),
+ this, SLOT(slotColumnSizeChanged(int, int, int)));
+}
+
+void KEBListView::makeConnections() {
+ connect(this, SIGNAL( moved() ),
+ SLOT( slotMoved() ));
+ connect(this, SIGNAL( contextMenu(KListView *, QListViewItem*, const QPoint &) ),
+ SLOT( slotContextMenu(KListView *, QListViewItem *, const QPoint &) ));
+ connect(this, SIGNAL( itemRenamed(QListViewItem *, const QString &, int) ),
+ SLOT( slotItemRenamed(QListViewItem *, const QString &, int) ));
+ connect(this, SIGNAL( doubleClicked(QListViewItem *, const QPoint &, int) ),
+ SLOT( slotDoubleClicked(QListViewItem *, const QPoint &, int) ));
+ connect(this, SIGNAL( dropped(QDropEvent*, QListViewItem*, QListViewItem*) ),
+ SLOT( slotDropped(QDropEvent*, QListViewItem*, QListViewItem*) ));
+}
+
+void KEBListView::readonlyFlagInit(bool readonly) {
+ setItemsMovable(readonly); // we move items ourselves (for undo)
+ setItemsRenameable(!readonly);
+ setAcceptDrops(!readonly);
+ setDropVisualizer(!readonly);
+}
+
+void KEBListView::slotMoved()
+{ ListView::self()->handleMoved(this); }
+void KEBListView::slotContextMenu(KListView *a, QListViewItem *b, const QPoint &c)
+{ ListView::self()->handleContextMenu(this, a,b,c); }
+void KEBListView::slotItemRenamed(QListViewItem *a, const QString &b, int c)
+{ ListView::self()->handleItemRenamed(this, a,b,c); }
+void KEBListView::slotDoubleClicked(QListViewItem *a, const QPoint &b, int c)
+{ ListView::self()->handleDoubleClicked(this, a,b,c); }
+void KEBListView::slotDropped(QDropEvent *a, QListViewItem *b, QListViewItem *c)
+{ ListView::self()->handleDropped(this, a,b,c); }
+
+void KEBListView::rename(QListViewItem *qitem, int column) {
+ KEBListViewItem *item = static_cast<KEBListViewItem *>(qitem);
+ if ( !(column == NameColumn || column == UrlColumn || column == CommentColumn)
+ || KEBApp::self()->readonly()
+ || !item
+ || item == firstChild()
+ || item->isEmptyFolderPadder()
+ || item->bookmark().isSeparator()
+ || (column == UrlColumn && item->bookmark().isGroup())
+ ) {
+ return;
+ }
+ ListView::startRename(column, item);
+ KeyPressEater *keyPressEater = new KeyPressEater(this);
+ renameLineEdit()->installEventFilter(keyPressEater);
+ KListView::rename(item, column);
+}
+
+KEBListViewItem* KEBListView::rootItem() const {
+ return static_cast<KEBListViewItem *>(firstChild());
+}
+
+// Update display of bookmarks containing URL
+void KEBListView::updateByURL(QString url) {
+ for (QListViewItemIterator it(this); it.current(); it++) {
+ KEBListViewItem *p = static_cast<KEBListViewItem *>(it.current());
+ if (p->text(1) == url) {
+ p->modUpdate();
+ }
+ }
+}
+
+bool KEBListView::acceptDrag(QDropEvent * e) const {
+ return (e->source() == viewport() || KBookmarkDrag::canDecode(e));
+}
+
+QDragObject *KEBListView::dragObject() {
+ QValueList<KBookmark> bookmarks =
+ ListView::self()->itemsToBookmarks(ListView::self()->selectedItemsMap());
+ KBookmarkDrag *drag = KBookmarkDrag::newDrag(bookmarks, viewport());
+ const QString iconname =
+ (bookmarks.size() == 1) ? bookmarks.first().icon() : QString("bookmark");
+ drag->setPixmap(SmallIcon(iconname)) ;
+ return drag;
+}
+
+/* -------------------------------------- */
+
+bool KEBListViewItem::parentSelected(QListViewItem * item)
+{
+ QListViewItem *root = item->listView()->firstChild();
+ for( QListViewItem *parent = item->parent(); parent ; parent = parent->parent())
+ if (parent->isSelected() && parent != root)
+ return true;
+ return false;
+}
+
+void KEBListViewItem::setSelected(bool s)
+{
+ if( isEmptyFolderPadder())
+ {
+ parent()->setSelected(true);
+ return;
+ }
+
+ if(listView()->firstChild() == this)
+ {
+ ListView::self()->selected(this, s);
+ QListViewItem::setSelected( s );
+ return;
+ }
+
+ if(s == false)
+ {
+ ListView::self()->selected(this, false);
+ QListViewItem::setSelected( false );
+ ListView::deselectAllChildren( this ); //repaints
+ }
+ else if(parentSelected(this))
+ return;
+ else
+ {
+ ListView::self()->selected(this, true);
+ QListViewItem::setSelected( true );
+ ListView::deselectAllChildren(this);
+ }
+}
+
+void KEBListViewItem::normalConstruct(const KBookmark &bk) {
+#ifdef DEBUG_ADDRESSES
+ setText(KEBListView::AddressColumn, bk.address());
+#endif
+ setText(KEBListView::CommentColumn, NodeEditCommand::getNodeText(bk, "desc"));
+ bool shown = CmdGen::shownInToolbar(bk);
+ setPixmap(0, SmallIcon(shown ? QString("bookmark_toolbar") : bk.icon()));
+ // DESIGN - modUpdate badly needs a redesign
+ modUpdate();
+}
+
+// DESIGN - following constructors should be names classes or else just explicit
+
+// toplevel item (there should be only one!)
+KEBListViewItem::KEBListViewItem(QListView *parent, const KBookmarkGroup &gp)
+ : QListViewItem(parent, KEBApp::self()->caption().isNull()
+ ? i18n("Bookmarks")
+ : i18n("%1 Bookmarks").arg(KEBApp::self()->caption())),
+ m_bookmark(gp), m_emptyFolderPadder(false) {
+
+ setPixmap(0, SmallIcon("bookmark"));
+ setExpandable(true);
+}
+
+// empty folder item
+KEBListViewItem::KEBListViewItem(KEBListViewItem *parent, QListViewItem *after)
+ : QListViewItem(parent, after, i18n("Empty Folder") ), m_emptyFolderPadder(true) {
+ setPixmap(0, SmallIcon("bookmark"));
+}
+
+// group
+KEBListViewItem::KEBListViewItem(KEBListViewItem *parent, QListViewItem *after, const KBookmarkGroup &gp)
+ : QListViewItem(parent, after, gp.fullText()), m_bookmark(gp), m_emptyFolderPadder(false) {
+ setExpandable(true);
+ normalConstruct(gp);
+}
+
+// bookmark (first of its group)
+KEBListViewItem::KEBListViewItem(KEBListViewItem *parent, const KBookmark & bk)
+ : QListViewItem(parent, bk.fullText(), bk.url().pathOrURL()), m_bookmark(bk), m_emptyFolderPadder(false) {
+ normalConstruct(bk);
+}
+
+// bookmark (after another)
+KEBListViewItem::KEBListViewItem(KEBListViewItem *parent, QListViewItem *after, const KBookmark &bk)
+ : QListViewItem(parent, after, bk.fullText(), bk.url().pathOrURL()), m_bookmark(bk), m_emptyFolderPadder(false) {
+ normalConstruct(bk);
+}
+
+// root bookmark (first of its group)
+KEBListViewItem::KEBListViewItem(QListView *parent, const KBookmark & bk)
+ : QListViewItem(parent, bk.fullText(), bk.url().pathOrURL()), m_bookmark(bk), m_emptyFolderPadder(false) {
+ normalConstruct(bk);
+}
+
+// root bookmark (after another)
+KEBListViewItem::KEBListViewItem(QListView *parent, QListViewItem *after, const KBookmark &bk)
+ : QListViewItem(parent, after, bk.fullText(), bk.url().pathOrURL()), m_bookmark(bk), m_emptyFolderPadder(false) {
+ normalConstruct(bk);
+}
+
+// DESIGN - move this into kbookmark or into a helper
+void KEBListViewItem::setOpen(bool open) {
+ if (!parent())
+ return;
+ m_bookmark.internalElement().setAttribute("folded", open ? "no" : "yes");
+ QListViewItem::setOpen(open);
+}
+
+void KEBListViewItem::greyStyle(QColorGroup &cg) {
+ int h, s, v;
+ cg.background().hsv(&h, &s, &v);
+ QColor color = (v > 180 && v < 220) ? (Qt::darkGray) : (Qt::gray);
+ cg.setColor(QColorGroup::Text, color);
+}
+
+void KEBListViewItem::boldStyle(QPainter *p) {
+ QFont font = p->font();
+ font.setBold(true);
+ p->setFont(font);
+}
+
+void KEBListViewItem::paintCell(QPainter *p, const QColorGroup &ocg, int col, int w, int a) {
+ QColorGroup cg(ocg);
+ if (parentSelected(this)) {
+ int base_h, base_s, base_v;
+ cg.background().hsv(&base_h, &base_s, &base_v);
+
+ int hilite_h, hilite_s, hilite_v;
+ cg.highlight().hsv(&hilite_h, &hilite_s, &hilite_v);
+
+ QColor col(hilite_h,
+ (hilite_s + base_s + base_s ) / 3,
+ (hilite_v + base_v + base_v ) / 3,
+ QColor::Hsv);
+ cg.setColor(QColorGroup::Base, col);
+ }
+
+ if (col == KEBListView::StatusColumn) {
+ switch (m_paintStyle) {
+ case KEBListViewItem::GreyStyle:
+ {
+ greyStyle(cg);
+ break;
+ }
+ case KEBListViewItem::BoldStyle:
+ {
+ boldStyle(p);
+ break;
+ }
+ case KEBListViewItem::GreyBoldStyle:
+ {
+ greyStyle(cg);
+ boldStyle(p);
+ break;
+ }
+ case KEBListViewItem::DefaultStyle:
+ break;
+ }
+ }
+
+ QListViewItem::paintCell(p, cg, col, w,a);
+}
+
+#include "listview.moc"
diff --git a/konqueror/keditbookmarks/listview.h b/konqueror/keditbookmarks/listview.h
new file mode 100644
index 000000000..7741f5858
--- /dev/null
+++ b/konqueror/keditbookmarks/listview.h
@@ -0,0 +1,217 @@
+// kate: space-indent on; indent-width 3; replace-tabs on;
+/* This file is part of the KDE project
+ Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __listview_h
+#define __listview_h
+
+#include <assert.h>
+
+#include <qlistview.h>
+#include <qmap.h>
+#include <qvaluevector.h>
+
+#include <klocale.h>
+#include <kbookmark.h>
+#include <klistview.h>
+#include <kiconloader.h>
+
+#include "toplevel.h"
+
+class QSplitter;
+class KListViewSearchLine;
+
+class KEBListViewItem : public QListViewItem
+{
+public:
+ KEBListViewItem(QListView *, const KBookmarkGroup &);
+ KEBListViewItem(KEBListViewItem *, QListViewItem *);
+ KEBListViewItem(KEBListViewItem *, QListViewItem *, const KBookmarkGroup &);
+ KEBListViewItem(KEBListViewItem *, const KBookmark &);
+ KEBListViewItem(KEBListViewItem *, QListViewItem *, const KBookmark &);
+
+ KEBListViewItem(QListView *, const KBookmark &);
+ KEBListViewItem(QListView *, QListViewItem *, const KBookmark &);
+
+ void nsPut(const QString &nm);
+
+ void modUpdate();
+
+ void setOldStatus(const QString &);
+ void setTmpStatus(const QString &);
+ void restoreStatus();
+
+ void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment);
+ void setSelected ( bool s );
+
+ virtual void setOpen(bool);
+
+ bool isEmptyFolderPadder() const { return m_emptyFolderPadder; }
+ const KBookmark bookmark() const { return m_bookmark; }
+
+ typedef enum { GreyStyle, BoldStyle, GreyBoldStyle, DefaultStyle } PaintStyle;
+
+ static bool parentSelected(QListViewItem * item);
+
+private:
+ const QString nsGet() const;
+ void normalConstruct(const KBookmark &);
+
+ KBookmark m_bookmark;
+ PaintStyle m_paintStyle;
+ bool m_emptyFolderPadder;
+ QString m_oldStatus;
+ void greyStyle(QColorGroup &);
+ void boldStyle(QPainter *);
+};
+
+class KEBListView : public KListView
+{
+ Q_OBJECT
+public:
+ enum {
+ NameColumn = 0,
+ UrlColumn = 1,
+ CommentColumn = 2,
+ StatusColumn = 3,
+ AddressColumn = 4
+ };
+ KEBListView(QWidget *parent, bool folderList)
+ : KListView(parent), m_folderList(folderList) {}
+ virtual ~KEBListView() {}
+
+ void init();
+ void makeConnections();
+ void readonlyFlagInit(bool);
+
+ void loadColumnSetting();
+ void saveColumnSetting();
+
+ void updateByURL(QString url);
+
+ bool isFolderList() const { return m_folderList; }
+
+ KEBListViewItem* rootItem() const;
+
+public slots:
+ virtual void rename(QListViewItem *item, int c);
+ void slotMoved();
+ void slotContextMenu(KListView *, QListViewItem *, const QPoint &);
+ void slotItemRenamed(QListViewItem *, const QString &, int);
+ void slotDoubleClicked(QListViewItem *, const QPoint &, int);
+ void slotDropped(QDropEvent*, QListViewItem*, QListViewItem*);
+ void slotColumnSizeChanged(int, int, int);
+
+protected:
+ virtual bool acceptDrag(QDropEvent *e) const;
+ virtual QDragObject* dragObject();
+
+private:
+ bool m_folderList;
+ bool m_widthsDirty;
+};
+
+// DESIGN - make some stuff private if possible
+class ListView : public QObject
+{
+ Q_OBJECT
+public:
+ // init stuff
+ void initListViews();
+ void updateListViewSetup(bool readOnly);
+ void connectSignals();
+ void setSearchLine(KListViewSearchLine * searchline) { m_searchline = searchline; };
+
+ // selected item stuff
+ void selected(KEBListViewItem * item, bool s);
+
+ void invalidate(const QString & address);
+ void invalidate(QListViewItem * item);
+ void fixUpCurrent(const QString & address);
+
+ KEBListViewItem * firstSelected() const;
+ QValueVector<KEBListViewItem *> selectedItemsMap() const;
+
+ QValueList<QString> selectedAddresses();
+
+ // bookmark helpers
+ QValueList<KBookmark> itemsToBookmarks(const QValueVector<KEBListViewItem *> & items) const;
+
+ // bookmark stuff
+ QValueList<KBookmark> allBookmarks() const;
+ QValueList<KBookmark> selectedBookmarksExpanded() const;
+
+ // address stuff
+ KEBListViewItem* getItemAtAddress(const QString &address) const;
+ QString userAddress() const;
+
+ // gui stuff - DESIGN - all of it???
+ SelcAbilities getSelectionAbilities() const;
+
+ void updateListView();
+ void setOpen(bool open); // DESIGN -rename to setAllOpenFlag
+ void setCurrent(KEBListViewItem *item, bool select);
+ void renameNextCell(bool dir);
+
+ QWidget *widget() const { return m_listView; }
+ void rename(int);
+ void clearSelection();
+
+ void updateStatus(QString url);
+
+ static ListView* self() { return s_self; }
+ static void createListViews(QSplitter *parent);
+
+ void handleMoved(KEBListView *);
+ void handleDropped(KEBListView *, QDropEvent *, QListViewItem *, QListViewItem *);
+ void handleContextMenu(KEBListView *, KListView *, QListViewItem *, const QPoint &);
+ void handleDoubleClicked(KEBListView *, QListViewItem *, const QPoint &, int);
+ void handleItemRenamed(KEBListView *, QListViewItem *, const QString &, int);
+
+ static void startRename(int column, KEBListViewItem *item);
+
+ static void deselectAllChildren(KEBListViewItem *item);
+
+ ~ListView();
+
+public slots:
+ void slotBkInfoUpdateListViewItem();
+
+private:
+ void updateTree();
+ void selectedBookmarksExpandedHelper(KEBListViewItem * item, QValueList<KBookmark> & bookmarks) const;
+ void fillWithGroup(KEBListView *, KBookmarkGroup, KEBListViewItem * = 0);
+
+ ListView();
+
+ KEBListView *m_listView;
+ KListViewSearchLine * m_searchline;
+
+// Actually this is a std:set, the bool is ignored
+ QMap<KEBListViewItem *, bool> mSelectedItems;
+ bool m_needToFixUp;
+
+ // statics
+ static ListView *s_self;
+ static int s_myrenamecolumn;
+ static KEBListViewItem *s_myrenameitem;
+ static QStringList s_selected_addresses;
+ static QString s_current_address;
+};
+
+#endif
diff --git a/konqueror/keditbookmarks/main.cpp b/konqueror/keditbookmarks/main.cpp
new file mode 100644
index 000000000..755a6f703
--- /dev/null
+++ b/konqueror/keditbookmarks/main.cpp
@@ -0,0 +1,199 @@
+// -*- indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include "toplevel.h"
+#include "importers.h"
+
+#include <dcopclient.h>
+#include <dcopref.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kstandarddirs.h>
+
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <kuniqueapplication.h>
+
+#include <kmessagebox.h>
+#include <kwin.h>
+
+#include <kbookmarkmanager.h>
+#include <kbookmarkexporter.h>
+
+static KCmdLineOptions options[] = {
+ {"importmoz <filename>", I18N_NOOP("Import bookmarks from a file in Mozilla format"), 0},
+ {"importns <filename>", I18N_NOOP("Import bookmarks from a file in Netscape (4.x and earlier) format"), 0},
+ {"importie <filename>", I18N_NOOP("Import bookmarks from a file in Internet Explorer's Favorites format"), 0},
+ {"importopera <filename>", I18N_NOOP("Import bookmarks from a file in Opera format"), 0},
+
+ {"exportmoz <filename>", I18N_NOOP("Export bookmarks to a file in Mozilla format"), 0},
+ {"exportns <filename>", I18N_NOOP("Export bookmarks to a file in Netscape (4.x and earlier) format"), 0},
+ {"exporthtml <filename>", I18N_NOOP("Export bookmarks to a file in a printable HTML format"), 0},
+ {"exportie <filename>", I18N_NOOP("Export bookmarks to a file in Internet Explorer's Favorites format"), 0},
+ {"exportopera <filename>", I18N_NOOP("Export bookmarks to a file in Opera format"), 0},
+
+ {"address <address>", I18N_NOOP("Open at the given position in the bookmarks file"), 0},
+ {"customcaption <caption>", I18N_NOOP("Set the user readable caption for example \"Konsole\""), 0},
+ {"nobrowser", I18N_NOOP("Hide all browser related functions"), 0},
+ {"+[file]", I18N_NOOP("File to edit"), 0},
+ KCmdLineLastOption
+};
+
+static void continueInWindow(QString _wname) {
+ QCString wname = _wname.latin1();
+ int id = -1;
+
+ QCStringList apps = kapp->dcopClient()->registeredApplications();
+ for (QCStringList::Iterator it = apps.begin(); it != apps.end(); ++it) {
+ QCString &clientId = *it;
+
+ if (qstrncmp(clientId, wname, wname.length()) != 0)
+ continue;
+
+ DCOPRef client(clientId.data(), wname + "-mainwindow#1");
+ DCOPReply result = client.call("getWinID()");
+
+ if (result.isValid()) {
+ id = (int)result;
+ break;
+ }
+ }
+
+ KWin::activateWindow(id);
+}
+
+// TODO - make this register() or something like that and move dialog into main
+static int askUser(KApplication &app, QString filename, bool &readonly) {
+ QCString requestedName("keditbookmarks");
+
+ if (!filename.isEmpty())
+ requestedName += "-" + filename.utf8();
+
+ if (app.dcopClient()->registerAs(requestedName, false) == requestedName)
+ return true;
+
+ int ret = KMessageBox::warningYesNo(0,
+ i18n("Another instance of %1 is already running, do you really "
+ "want to open another instance or continue work in the same instance?\n"
+ "Please note that, unfortunately, duplicate views are read-only.").arg(kapp->caption()),
+ i18n("Warning"),
+ i18n("Run Another"), /* yes */
+ i18n("Continue in Same") /* no */);
+
+ if (ret == KMessageBox::No) {
+ continueInWindow(requestedName);
+ return false;
+ } else if (ret == KMessageBox::Yes) {
+ readonly = true;
+ }
+
+ return true;
+}
+
+#include <kactioncollection.h>
+
+extern "C" KDE_EXPORT int kdemain(int argc, char **argv) {
+ KLocale::setMainCatalogue("konqueror");
+ KAboutData aboutData("keditbookmarks", I18N_NOOP("Bookmark Editor"), VERSION,
+ I18N_NOOP("Konqueror Bookmarks Editor"),
+ KAboutData::License_GPL,
+ I18N_NOOP("(c) 2000 - 2003, KDE developers") );
+ aboutData.addAuthor("David Faure", I18N_NOOP("Initial author"), "faure@kde.org");
+ aboutData.addAuthor("Alexander Kellett", I18N_NOOP("Author"), "lypanov@kde.org");
+
+ KCmdLineArgs::init(argc, argv, &aboutData);
+ KApplication::addCmdLineOptions();
+ KCmdLineArgs::addCmdLineOptions(options);
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ bool isGui = !(args->isSet("exportmoz") || args->isSet("exportns") || args->isSet("exporthtml")
+ || args->isSet("exportie") || args->isSet("exportopera")
+ || args->isSet("importmoz") || args->isSet("importns")
+ || args->isSet("importie") || args->isSet("importopera"));
+
+ bool browser = args->isSet("browser");
+
+ KApplication::disableAutoDcopRegistration();
+ KApplication app(isGui, isGui);
+
+ bool gotArg = (args->count() == 1);
+
+ QString filename = gotArg
+ ? QString::fromLatin1(args->arg(0))
+ : locateLocal("data", QString::fromLatin1("konqueror/bookmarks.xml"));
+
+ if (!isGui) {
+ CurrentMgr::self()->createManager(filename);
+ CurrentMgr::ExportType exportType = CurrentMgr::MozillaExport; // uumm.. can i just set it to -1 ?
+ int got = 0;
+ const char *arg, *arg2 = 0, *importType = 0;
+ if (arg = "exportmoz", args->isSet(arg)) { exportType = CurrentMgr::MozillaExport; arg2 = arg; got++; }
+ if (arg = "exportns", args->isSet(arg)) { exportType = CurrentMgr::NetscapeExport; arg2 = arg; got++; }
+ if (arg = "exporthtml", args->isSet(arg)) { exportType = CurrentMgr::HTMLExport; arg2 = arg; got++; }
+ if (arg = "exportie", args->isSet(arg)) { exportType = CurrentMgr::IEExport; arg2 = arg; got++; }
+ if (arg = "exportopera", args->isSet(arg)) { exportType = CurrentMgr::OperaExport; arg2 = arg; got++; }
+ if (arg = "importmoz", args->isSet(arg)) { importType = "Moz"; arg2 = arg; got++; }
+ if (arg = "importns", args->isSet(arg)) { importType = "NS"; arg2 = arg; got++; }
+ if (arg = "importie", args->isSet(arg)) { importType = "IE"; arg2 = arg; got++; }
+ if (arg = "importopera", args->isSet(arg)) { importType = "Opera"; arg2 = arg; got++; }
+ if (!importType && arg2) {
+ Q_ASSERT(arg2);
+ // TODO - maybe an xbel export???
+ if (got > 1) // got == 0 isn't possible as !isGui is dependant on "export.*"
+ KCmdLineArgs::usage(I18N_NOOP("You may only specify a single --export option."));
+ QString path = QString::fromLocal8Bit(args->getOption(arg2));
+ CurrentMgr::self()->doExport(exportType, path);
+ } else if (importType) {
+ if (got > 1) // got == 0 isn't possible as !isGui is dependant on "import.*"
+ KCmdLineArgs::usage(I18N_NOOP("You may only specify a single --import option."));
+ QString path = QString::fromLocal8Bit(args->getOption(arg2));
+ ImportCommand *importer = ImportCommand::importerFactory(importType);
+ importer->import(path, true);
+ importer->execute();
+ CurrentMgr::self()->managerSave();
+ CurrentMgr::self()->notifyManagers();
+ }
+ return 0; // error flag on exit?, 1?
+ }
+
+ QString address = args->isSet("address")
+ ? QString::fromLocal8Bit(args->getOption("address"))
+ : QString("/0");
+
+ QString caption = args->isSet("customcaption")
+ ? QString::fromLocal8Bit(args->getOption("customcaption"))
+ : QString::null;
+
+ args->clear();
+
+ bool readonly = false; // passed by ref
+
+ if (askUser(app, (gotArg ? filename : QString::null), readonly)) {
+ KEBApp *toplevel = new KEBApp(filename, readonly, address, browser, caption);
+ toplevel->show();
+ app.setMainWidget(toplevel);
+ return app.exec();
+ }
+
+ return 0;
+}
diff --git a/konqueror/keditbookmarks/settings.kcfgc b/konqueror/keditbookmarks/settings.kcfgc
new file mode 100644
index 000000000..663f5876f
--- /dev/null
+++ b/konqueror/keditbookmarks/settings.kcfgc
@@ -0,0 +1,4 @@
+File=keditbookmarks.kcfg
+ClassName=KEBSettings
+Singleton=true
+Mutators=true \ No newline at end of file
diff --git a/konqueror/keditbookmarks/testlink.cpp b/konqueror/keditbookmarks/testlink.cpp
new file mode 100644
index 000000000..84919ef27
--- /dev/null
+++ b/konqueror/keditbookmarks/testlink.cpp
@@ -0,0 +1,395 @@
+// -*- indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "toplevel.h"
+#include "listview.h"
+#include "testlink.h"
+#include "commands.h"
+#include "bookmarkiterator.h"
+
+#include <qtimer.h>
+#include <qpainter.h>
+
+#include <kdebug.h>
+
+#include <krfcdate.h>
+#include <kcharsets.h>
+#include <kbookmarkmanager.h>
+
+#include <kaction.h>
+
+TestLinkItrHolder *TestLinkItrHolder::s_self = 0;
+
+TestLinkItrHolder::TestLinkItrHolder()
+ : BookmarkIteratorHolder() {
+ // do stuff
+}
+
+void TestLinkItrHolder::doItrListChanged() {
+ KEBApp::self()->setCancelTestsEnabled(count() > 0);
+ if(count() == 0)
+ {
+ kdDebug()<<"Notifing managers "<<m_affectedBookmark<<endl;
+ CurrentMgr::self()->notifyManagers(CurrentMgr::bookmarkAt(m_affectedBookmark).toGroup());
+ m_affectedBookmark = QString::null;
+ }
+}
+
+void TestLinkItrHolder::addAffectedBookmark( const QString & address )
+{
+ kdDebug()<<"addAffectedBookmark "<<address<<endl;
+ if(m_affectedBookmark.isNull())
+ m_affectedBookmark = address;
+ else
+ m_affectedBookmark = KBookmark::commonParent(m_affectedBookmark, address);
+ kdDebug()<<" m_affectedBookmark is now "<<m_affectedBookmark<<endl;
+}
+
+/* -------------------------- */
+
+TestLinkItr::TestLinkItr(QValueList<KBookmark> bks)
+ : BookmarkIterator(bks) {
+ m_job = 0;
+}
+
+TestLinkItr::~TestLinkItr() {
+ if (m_job) {
+ // kdDebug() << "JOB kill\n";
+ curItem()->restoreStatus();
+ m_job->disconnect();
+ m_job->kill(false);
+ }
+}
+
+bool TestLinkItr::isApplicable(const KBookmark &bk) const {
+ return (!bk.isGroup() && !bk.isSeparator());
+}
+
+void TestLinkItr::doAction() {
+ m_errSet = false;
+
+ m_job = KIO::get(curBk().url(), true, false);
+ m_job->addMetaData("errorPage", "true");
+ m_job->addMetaData( QString("cookies"), QString("none") );
+
+ connect(m_job, SIGNAL( result( KIO::Job *)),
+ this, SLOT( slotJobResult(KIO::Job *)));
+ connect(m_job, SIGNAL( data( KIO::Job *, const QByteArray &)),
+ this, SLOT( slotJobData(KIO::Job *, const QByteArray &)));
+
+ curItem()->setTmpStatus(i18n("Checking..."));
+ QString oldModDate = TestLinkItrHolder::self()->getMod(curBk().url().url());
+ curItem()->setOldStatus(oldModDate);
+ TestLinkItrHolder::self()->setMod(curBk().url().url(), i18n("Checking..."));
+}
+
+void TestLinkItr::slotJobData(KIO::Job *job, const QByteArray &data) {
+ KIO::TransferJob *transfer = (KIO::TransferJob *)job;
+
+ if (transfer->isErrorPage()) {
+ QStringList lines = QStringList::split('\n', data);
+ for (QStringList::Iterator it = lines.begin(); it != lines.end(); ++it) {
+ int open_pos = (*it).find("<title>", 0, false);
+ if (open_pos >= 0) {
+ QString leftover = (*it).mid(open_pos + 7);
+ int close_pos = leftover.findRev("</title>", -1, false);
+ if (close_pos >= 0) {
+ // if no end tag found then just
+ // print the first line of the <title>
+ leftover = leftover.left(close_pos);
+ }
+ curItem()->nsPut(KCharsets::resolveEntities(leftover));
+ m_errSet = true;
+ break;
+ }
+ }
+
+ } else {
+ QString modDate = transfer->queryMetaData("modified");
+ if (!modDate.isEmpty()) {
+ curItem()->nsPut(QString::number(KRFCDate::parseDate(modDate)));
+ }
+ }
+
+ transfer->kill(false);
+}
+
+void TestLinkItr::slotJobResult(KIO::Job *job) {
+ m_job = 0;
+ if ( !curItem() ) return;
+
+ KIO::TransferJob *transfer = (KIO::TransferJob *)job;
+ QString modDate = transfer->queryMetaData("modified");
+
+ bool chkErr = true;
+ if (transfer->error()) {
+ // can we assume that errorString will contain no entities?
+ QString jerr = job->errorString();
+ if (!jerr.isEmpty()) {
+ jerr.replace("\n", " ");
+ curItem()->nsPut(jerr);
+ chkErr = false;
+ }
+ }
+
+ if (chkErr) {
+ if (!modDate.isEmpty()) {
+ curItem()->nsPut(QString::number(KRFCDate::parseDate(modDate)));
+ } else if (!m_errSet) {
+ curItem()->nsPut(QString::number(KRFCDate::parseDate("0")));
+ }
+ }
+
+ curItem()->modUpdate();
+ holder()->addAffectedBookmark(KBookmark::parentAddress(curBk().address()));
+ delayedEmitNextOne();
+}
+
+/* -------------------------- */
+
+const QString TestLinkItrHolder::getMod(const QString &url) const {
+ return m_modify.contains(url)
+ ? m_modify[url]
+ : QString::null;
+}
+
+const QString TestLinkItrHolder::getOldVisit(const QString &url) const {
+ return self()->m_oldModify.contains(url)
+ ? self()->m_oldModify[url]
+ : QString::null;
+}
+
+void TestLinkItrHolder::setMod(const QString &url, const QString &val) {
+ m_modify[url] = val;
+}
+
+void TestLinkItrHolder::setOldVisit(const QString &url, const QString &val) {
+ m_oldModify[url] = val;
+}
+
+void TestLinkItrHolder::resetToValue(const QString &url, const QString &oldValue) {
+ if (!oldValue.isEmpty()) {
+ m_modify[url] = oldValue;
+ } else {
+ m_modify.remove(url);
+ }
+}
+
+/* -------------------------- */
+
+QString TestLinkItrHolder::calcPaintStyle(const QString &url, KEBListViewItem::PaintStyle &_style,
+ const QString &nVisit, const QString &Modify) {
+ bool newModValid = false;
+ int newMod = 0;
+ QString newModStr;
+ bool initial = false;
+ bool oldError = false;
+
+ if (!Modify.isNull() && Modify == "1") {
+ oldError = true;
+ }
+
+ // get new mod time if there is one
+ newModStr = self()->getMod(url);
+
+ // if no new mod time use previous one
+ if (newModStr.isNull()) {
+ newModStr = Modify;
+ initial = true;
+ }
+
+ if (!newModStr.isNull()) {
+ newMod = newModStr.toInt(&newModValid);
+ }
+
+
+// kdDebug() << "TestLink " << url << " " << "booktime=" << nVisit << " urltime=" << newModStr <<
+// " Modify=" << Modify << " init=" << initial << " newMod=" << newMod << "\n";
+
+ QString visitStr;
+
+ if (self()->getOldVisit(url).isNull()) {
+ // first time
+ visitStr = nVisit;
+ if (!nVisit.isEmpty())
+ self()->setOldVisit(url, visitStr);
+ } else {
+ // may be reading a second bookmark with same url
+ QString oom = nVisit;
+ visitStr = self()->getOldVisit(url);
+ if (oom.toInt() > visitStr.toInt()) {
+ self()->setOldVisit(url, oom);
+ visitStr = oom;
+ }
+ }
+
+ int visit = 0;
+ if (!visitStr.isNull())
+ visit = visitStr.toInt(); // TODO - check validity?
+
+ QString statusStr;
+ KEBListViewItem::PaintStyle style = KEBListViewItem::DefaultStyle;
+
+// kdDebug() << "TestLink " << "isNull=" << newModStr.isNull() << "newModValid="
+// << newModValid << "newMod > visit " << newMod << ">" << visit << "\n";
+
+ if (!newModStr.isNull() && !newModValid) {
+ // Current check has error
+ statusStr = newModStr;
+ if (oldError) {
+ style = KEBListViewItem::BoldStyle;
+ } else {
+ style = KEBListViewItem::DefaultStyle;
+ }
+
+ } else if (initial && oldError) {
+ // Previous check has error
+ style = KEBListViewItem::GreyStyle;
+ statusStr = i18n("Error ");
+
+ } else if (!initial && !newModStr.isNull() && (newMod == 0)) {
+ // Current check has no modify time
+ statusStr = i18n("Ok");
+
+ } else if (initial && !newModStr.isNull() && (newMod == 0)) {
+ // previous check has no modify time recorded
+ statusStr = QString::null;
+
+ } else if (!newModStr.isNull() && (newMod > visit)) {
+ // if modify time greater than last visit, show bold modify time
+ statusStr = CurrentMgr::makeTimeStr(newMod);
+ if (initial) {
+ style = KEBListViewItem::GreyBoldStyle;
+ } else {
+ style = KEBListViewItem::BoldStyle;
+ }
+
+ } else if (visit != 0) {
+ // modify time not greater than last visit, show last visit time
+ statusStr = CurrentMgr::makeTimeStr(visit);
+ if (initial) {
+ style = KEBListViewItem::GreyStyle;
+ } else {
+ style = KEBListViewItem::DefaultStyle;
+ }
+
+ } else {
+ statusStr = QString::null;
+ }
+
+ _style = style;
+ return statusStr;
+}
+
+static void parseInfo (KBookmark &bk, QString &nVisited) {
+ nVisited =
+ NodeEditCommand::getNodeText(bk, QStringList() << "info" << "metadata"
+ << "time_visited" );
+
+// kdDebug() << " Visited=" << nVisited << "\n";
+}
+
+static void parseNsInfo(const QString &nsinfo, QString &nCreate, QString &nAccess, QString &nModify) {
+ QStringList sl = QStringList::split(' ', nsinfo);
+
+ for (QStringList::Iterator it = sl.begin(); it != sl.end(); ++it) {
+ QStringList spl = QStringList::split('"', (*it));
+
+ if (spl[0] == "LAST_MODIFIED=") {
+ nModify = spl[1];
+ } else if (spl[0] == "ADD_DATE=") {
+ nCreate = spl[1];
+ } else if (spl[0] == "LAST_VISIT=") {
+ nAccess = spl[1];
+ }
+ }
+}
+
+// Still use nsinfo for storing old modify time
+static const QString updateNsInfoMod(const QString &_nsinfo, const QString &nm) {
+ QString nCreate, nAccess, nModify;
+ parseNsInfo(_nsinfo, nCreate, nAccess, nModify);
+
+ bool numValid = false;
+ nm.toInt(&numValid);
+
+ QString tmp;
+ tmp = "ADD_DATE=\"" + ((nCreate.isEmpty()) ? QString::number(time(0)) : nCreate) + "\"";
+ tmp += " LAST_VISIT=\"" + ((nAccess.isEmpty()) ? QString("0") : nAccess) + "\"";
+ tmp += " LAST_MODIFIED=\"" + ((numValid) ? nm : QString("1")) + "\"";
+
+// if (!numValid) kdDebug() << tmp << "\n";
+ return tmp;
+}
+
+// KEBListViewItem !!!!!!!!!!!
+void KEBListViewItem::nsPut(const QString &newModDate) {
+ static const QString NetscapeInfoAttribute = "netscapeinfo";
+ const QString info = m_bookmark.internalElement().attribute(NetscapeInfoAttribute);
+ QString blah = updateNsInfoMod(info, newModDate);
+ m_bookmark.internalElement().setAttribute(NetscapeInfoAttribute, blah);
+ TestLinkItrHolder::self()->setMod(m_bookmark.url().url(), newModDate);
+ setText(KEBListView::StatusColumn, newModDate);
+}
+
+// KEBListViewItem !!!!!!!!!!!
+void KEBListViewItem::modUpdate() {
+ QString nCreate, nAccess, oldModify;
+ QString iVisit;
+
+ QString nsinfo = m_bookmark.internalElement().attribute("netscapeinfo");
+ if (!nsinfo.isEmpty()) {
+ parseNsInfo(nsinfo, nCreate, nAccess, oldModify);
+ }
+
+ parseInfo(m_bookmark, iVisit);
+
+ QString statusLine;
+ statusLine = TestLinkItrHolder::calcPaintStyle(m_bookmark.url().url(), m_paintStyle, iVisit, oldModify);
+ if (statusLine != "Error")
+ setText(KEBListView::StatusColumn, statusLine);
+}
+
+/* -------------------------- */
+
+// KEBListViewItem !!!!!!!!!!!
+void KEBListViewItem::setOldStatus(const QString &oldStatus) {
+ // kdDebug() << "KEBListViewItem::setOldStatus" << endl;
+ m_oldStatus = oldStatus;
+}
+
+// KEBListViewItem !!!!!!!!!!!
+void KEBListViewItem::setTmpStatus(const QString &status) {
+ // kdDebug() << "KEBListViewItem::setTmpStatus" << endl;
+ m_paintStyle = KEBListViewItem::BoldStyle;
+ setText(KEBListView::StatusColumn, status);
+}
+
+// KEBListViewItem !!!!!!!!!!!
+void KEBListViewItem::restoreStatus() {
+ if (!m_oldStatus.isNull()) {
+ // kdDebug() << "KEBListViewItem::restoreStatus" << endl;
+ TestLinkItrHolder::self()->resetToValue(m_bookmark.url().url(), m_oldStatus);
+ modUpdate();
+ }
+}
+
+#include "testlink.moc"
diff --git a/konqueror/keditbookmarks/testlink.h b/konqueror/keditbookmarks/testlink.h
new file mode 100644
index 000000000..7b027edea
--- /dev/null
+++ b/konqueror/keditbookmarks/testlink.h
@@ -0,0 +1,75 @@
+/* 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __testlink_h
+#define __testlink_h
+
+#include <qobject.h>
+
+#include <kio/job.h>
+#include <kbookmark.h>
+
+#include "listview.h"
+#include "bookmarkiterator.h"
+
+class TestLinkItrHolder : public BookmarkIteratorHolder {
+public:
+ static TestLinkItrHolder* self() {
+ if (!s_self) { s_self = new TestLinkItrHolder(); }; return s_self;
+ }
+ void addAffectedBookmark( const QString & address );
+ void resetToValue(const QString &url, const QString &val);
+ const QString getMod(const QString &url) const;
+ const QString getOldVisit(const QString &url) const;
+ void setMod(const QString &url, const QString &val);
+ void setOldVisit(const QString &url, const QString &val);
+ static QString calcPaintStyle(const QString &, KEBListViewItem::PaintStyle&,
+ const QString &, const QString &);
+protected:
+ virtual void doItrListChanged();
+private:
+ TestLinkItrHolder();
+ static TestLinkItrHolder *s_self;
+ QMap<QString, QString> m_modify;
+ QMap<QString, QString> m_oldModify;
+ QString m_affectedBookmark;
+};
+
+class TestLinkItr : public BookmarkIterator
+{
+ Q_OBJECT
+
+public:
+ TestLinkItr(QValueList<KBookmark> bks);
+ ~TestLinkItr();
+ virtual TestLinkItrHolder* holder() const { return TestLinkItrHolder::self(); }
+
+public slots:
+ void slotJobResult(KIO::Job *job);
+ void slotJobData(KIO::Job *job, const QByteArray &data);
+
+private:
+ virtual void doAction();
+ virtual bool isApplicable(const KBookmark &bk) const;
+
+ KIO::TransferJob *m_job;
+ bool m_errSet;
+};
+
+#endif
diff --git a/konqueror/keditbookmarks/toplevel.cpp b/konqueror/keditbookmarks/toplevel.cpp
new file mode 100644
index 000000000..3f49d893a
--- /dev/null
+++ b/konqueror/keditbookmarks/toplevel.cpp
@@ -0,0 +1,356 @@
+// -*- indent-tabs-mode:nil -*-
+// vim: set ts=4 sts=4 sw=4 et:
+/* 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "toplevel.h"
+
+#include "bookmarkinfo.h"
+#include "listview.h"
+#include "actionsimpl.h"
+#include "dcop.h"
+#include "exporters.h"
+#include "settings.h"
+#include "commands.h"
+#include "kebsearchline.h"
+
+#include <stdlib.h>
+
+#include <qclipboard.h>
+#include <qsplitter.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <kapplication.h>
+#include <kstdaction.h>
+#include <kaction.h>
+#include <dcopclient.h>
+#include <dcopref.h>
+
+#include <kedittoolbar.h>
+#include <kmessagebox.h>
+#include <klineedit.h>
+#include <kfiledialog.h>
+
+#include <kdebug.h>
+
+#include <kbookmarkdrag.h>
+#include <kbookmarkmanager.h>
+
+CmdHistory* CmdHistory::s_self = 0;
+
+CmdHistory::CmdHistory(KActionCollection *collection)
+ : m_commandHistory(collection) {
+ connect(&m_commandHistory, SIGNAL( commandExecuted(KCommand *) ),
+ SLOT( slotCommandExecuted(KCommand *) ));
+ assert(!s_self);
+ s_self = this; // this is hacky
+}
+
+CmdHistory* CmdHistory::self() {
+ assert(s_self);
+ return s_self;
+}
+
+void CmdHistory::slotCommandExecuted(KCommand *k) {
+ KEBApp::self()->notifyCommandExecuted();
+
+ IKEBCommand * cmd = dynamic_cast<IKEBCommand *>(k);
+ Q_ASSERT(cmd);
+
+ KBookmark bk = CurrentMgr::bookmarkAt(cmd->affectedBookmarks());
+ Q_ASSERT(bk.isGroup());
+ CurrentMgr::self()->notifyManagers(bk.toGroup());
+
+ // sets currentItem to something sensible
+ // if the currentItem was invalidated by executing
+ // CreateCommand or DeleteManyCommand
+ // otherwise does nothing
+ // sensible is either a already selected item or cmd->currentAddress()
+ ListView::self()->fixUpCurrent( cmd->currentAddress() );
+}
+
+void CmdHistory::notifyDocSaved() {
+ m_commandHistory.documentSaved();
+}
+
+void CmdHistory::didCommand(KCommand *cmd) {
+ if (!cmd)
+ return;
+ m_commandHistory.addCommand(cmd, false);
+ CmdHistory::slotCommandExecuted(cmd);
+}
+
+void CmdHistory::addCommand(KCommand *cmd) {
+ if (!cmd)
+ return;
+ m_commandHistory.addCommand(cmd);
+}
+
+void CmdHistory::addInFlightCommand(KCommand *cmd)
+{
+ if(!cmd)
+ return;
+ m_commandHistory.addCommand(cmd, false);
+}
+
+void CmdHistory::clearHistory() {
+ m_commandHistory.clear();
+}
+
+/* -------------------------- */
+
+CurrentMgr *CurrentMgr::s_mgr = 0;
+
+KBookmark CurrentMgr::bookmarkAt(const QString &a) {
+ return self()->mgr()->findByAddress(a);
+}
+
+bool CurrentMgr::managerSave() { return mgr()->save(); }
+void CurrentMgr::saveAs(const QString &fileName) { mgr()->saveAs(fileName); }
+void CurrentMgr::setUpdate(bool update) { mgr()->setUpdate(update); }
+QString CurrentMgr::path() const { return mgr()->path(); }
+bool CurrentMgr::showNSBookmarks() const { return mgr()->showNSBookmarks(); }
+
+void CurrentMgr::createManager(const QString &filename) {
+ if (m_mgr) {
+ kdDebug()<<"ERROR calling createManager twice"<<endl;
+ disconnect(m_mgr, 0, 0, 0);
+ // still todo - delete old m_mgr
+ }
+
+ m_mgr = KBookmarkManager::managerForFile(filename, false);
+
+ connect(m_mgr, SIGNAL( changed(const QString &, const QString &) ),
+ SLOT( slotBookmarksChanged(const QString &, const QString &) ));
+}
+
+void CurrentMgr::slotBookmarksChanged(const QString &, const QString &) {
+ if(ignorenext > 0) //We ignore the first changed signal after every change we did
+ {
+ --ignorenext;
+ return;
+ }
+
+ CmdHistory::self()->clearHistory();
+ ListView::self()->updateListView();
+ KEBApp::self()->updateActions();
+}
+
+void CurrentMgr::notifyManagers(KBookmarkGroup grp)
+{
+ ++ignorenext;
+ mgr()->emitChanged(grp);
+}
+
+void CurrentMgr::notifyManagers() {
+ notifyManagers( mgr()->root() );
+}
+
+void CurrentMgr::reloadConfig() {
+ mgr()->emitConfigChanged();
+}
+
+QString CurrentMgr::makeTimeStr(const QString & in)
+{
+ int secs;
+ bool ok;
+ secs = in.toInt(&ok);
+ if (!ok)
+ return QString::null;
+ return makeTimeStr(secs);
+}
+
+QString CurrentMgr::makeTimeStr(int b)
+{
+ QDateTime dt;
+ dt.setTime_t(b);
+ return (dt.daysTo(QDateTime::currentDateTime()) > 31)
+ ? KGlobal::locale()->formatDate(dt.date(), false)
+ : KGlobal::locale()->formatDateTime(dt, false);
+}
+
+/* -------------------------- */
+
+KEBApp *KEBApp::s_topLevel = 0;
+
+KEBApp::KEBApp(
+ const QString &bookmarksFile, bool readonly,
+ const QString &address, bool browser, const QString &caption
+) : KMainWindow(), m_dcopIface(0), m_bookmarksFilename(bookmarksFile),
+ m_caption(caption), m_readOnly(readonly), m_browser(browser) {
+
+ m_cmdHistory = new CmdHistory(actionCollection());
+
+ s_topLevel = this;
+
+ int h = 20;
+
+ QSplitter *vsplitter = new QSplitter(this);
+
+ KToolBar *quicksearch = new KToolBar(vsplitter, "search toolbar");
+
+ KAction *resetQuickSearch = new KAction( i18n( "Reset Quick Search" ),
+ QApplication::reverseLayout() ? "clear_left" : "locationbar_erase",
+ 0, actionCollection(), "reset_quicksearch" );
+ resetQuickSearch->setWhatsThis( i18n( "<b>Reset Quick Search</b><br>"
+ "Resets the quick search so that all bookmarks are shown again." ) );
+ resetQuickSearch->plug( quicksearch );
+
+ QLabel *lbl = new QLabel(i18n("Se&arch:"), quicksearch, "kde toolbar widget");
+
+ KListViewSearchLine *searchLineEdit = new KEBSearchLine(quicksearch, 0, "KListViewSearchLine");
+ quicksearch->setStretchableWidget(searchLineEdit);
+ lbl->setBuddy(searchLineEdit);
+ connect(resetQuickSearch, SIGNAL(activated()), searchLineEdit, SLOT(clear()));
+ connect(searchLineEdit, SIGNAL(searchUpdated()), SLOT(updateActions()));
+
+ ListView::createListViews(vsplitter);
+ ListView::self()->initListViews();
+ searchLineEdit->setListView(static_cast<KListView*>(ListView::self()->widget()));
+ ListView::self()->setSearchLine(searchLineEdit);
+
+ m_bkinfo = new BookmarkInfoWidget(vsplitter);
+
+ vsplitter->setOrientation(QSplitter::Vertical);
+ vsplitter->setSizes(QValueList<int>() << h << 380
+ << m_bkinfo->sizeHint().height() );
+
+ setCentralWidget(vsplitter);
+ resize(ListView::self()->widget()->sizeHint().width(),
+ vsplitter->sizeHint().height());
+
+ createActions();
+ if (m_browser)
+ createGUI();
+ else
+ createGUI("keditbookmarks-genui.rc");
+
+ m_dcopIface = new KBookmarkEditorIface();
+
+ connect(kapp->clipboard(), SIGNAL( dataChanged() ),
+ SLOT( slotClipboardDataChanged() ));
+
+ ListView::self()->connectSignals();
+
+ KGlobal::locale()->insertCatalogue("libkonq");
+
+ m_canPaste = false;
+
+ construct();
+
+ ListView::self()->setCurrent(ListView::self()->getItemAtAddress(address), true);
+
+ setCancelFavIconUpdatesEnabled(false);
+ setCancelTestsEnabled(false);
+ updateActions();
+}
+
+void KEBApp::construct() {
+ CurrentMgr::self()->createManager(m_bookmarksFilename);
+
+ ListView::self()->updateListViewSetup(m_readOnly);
+ ListView::self()->updateListView();
+ ListView::self()->widget()->setFocus();
+
+ slotClipboardDataChanged();
+ setAutoSaveSettings();
+}
+
+void KEBApp::updateStatus(QString url)
+{
+ if(m_bkinfo->bookmark().url() == url)
+ m_bkinfo->updateStatus();
+}
+
+KEBApp::~KEBApp() {
+ s_topLevel = 0;
+ delete m_cmdHistory;
+ delete m_dcopIface;
+ delete ActionsImpl::self();
+ delete ListView::self();
+}
+
+KToggleAction* KEBApp::getToggleAction(const char *action) const {
+ return static_cast<KToggleAction*>(actionCollection()->action(action));
+}
+
+void KEBApp::resetActions() {
+ stateChanged("disablestuff");
+ stateChanged("normal");
+
+ if (!m_readOnly)
+ stateChanged("notreadonly");
+
+ getToggleAction("settings_showNS")
+ ->setChecked(CurrentMgr::self()->showNSBookmarks());
+}
+
+bool KEBApp::nsShown() const {
+ return getToggleAction("settings_showNS")->isChecked();
+}
+
+// this should be pushed from listview, not pulled
+void KEBApp::updateActions() {
+ resetActions();
+ setActionsEnabled(ListView::self()->getSelectionAbilities());
+}
+
+void KEBApp::slotClipboardDataChanged() {
+ // kdDebug() << "KEBApp::slotClipboardDataChanged" << endl;
+ if (!m_readOnly) {
+ m_canPaste = KBookmarkDrag::canDecode(
+ kapp->clipboard()->data(QClipboard::Clipboard));
+ updateActions();
+ }
+}
+
+/* -------------------------- */
+
+void KEBApp::notifyCommandExecuted() {
+ // kdDebug() << "KEBApp::notifyCommandExecuted()" << endl;
+ if (!m_readOnly) {
+ ListView::self()->updateListView();
+ updateActions();
+ }
+}
+
+/* -------------------------- */
+
+void KEBApp::slotConfigureToolbars() {
+ saveMainWindowSettings(KGlobal::config(), "MainWindow");
+ KEditToolbar dlg(actionCollection());
+ connect(&dlg, SIGNAL( newToolbarConfig() ),
+ SLOT( slotNewToolbarConfig() ));
+ dlg.exec();
+}
+
+void KEBApp::slotNewToolbarConfig() {
+ // called when OK or Apply is clicked
+ createGUI();
+ applyMainWindowSettings(KGlobal::config(), "MainWindow");
+}
+
+/* -------------------------- */
+
+#include "toplevel.moc"
+
diff --git a/konqueror/keditbookmarks/toplevel.h b/konqueror/keditbookmarks/toplevel.h
new file mode 100644
index 000000000..192f56028
--- /dev/null
+++ b/konqueror/keditbookmarks/toplevel.h
@@ -0,0 +1,175 @@
+// -*- mode:cperl; cperl-indent-level:4; cperl-continued-statement-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) 2000 David Faure <faure@kde.org>
+ Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __toplevel_h
+#define __toplevel_h
+
+#include <kmainwindow.h>
+#include <kcommand.h>
+#include <kbookmark.h>
+
+class KBookmarkManager;
+class KToggleAction;
+class KBookmarkEditorIface;
+class ImportCommand;
+class BookmarkInfoWidget;
+class IKEBCommand;
+
+struct SelcAbilities {
+ bool itemSelected:1;
+ bool group:1;
+ bool root:1;
+ bool separator:1;
+ bool urlIsEmpty:1;
+ bool multiSelect:1;
+ bool singleSelect:1;
+ bool notEmpty:1;
+ bool tbShowState:1;
+};
+
+class CmdHistory : public QObject {
+ Q_OBJECT
+public:
+ CmdHistory(KActionCollection *collection);
+ virtual ~CmdHistory() { ; }
+
+ void notifyDocSaved();
+
+ void clearHistory();
+ void addCommand(KCommand *);
+ void didCommand(KCommand *);
+
+ //For an explanation see bookmarkInfo::commitChanges()
+ void addInFlightCommand(KCommand *);
+
+ static CmdHistory *self();
+
+protected slots:
+ void slotCommandExecuted(KCommand *k);
+
+private:
+ KCommandHistory m_commandHistory;
+ static CmdHistory *s_self;
+};
+
+class KBookmark;
+class KBookmarkManager;
+
+class CurrentMgr : public QObject {
+ Q_OBJECT
+public:
+ typedef enum {HTMLExport, OperaExport, IEExport, MozillaExport, NetscapeExport} ExportType;
+
+ static CurrentMgr* self() { if (!s_mgr) { s_mgr = new CurrentMgr(); } return s_mgr; }
+ static KBookmark bookmarkAt(const QString & a);
+
+ KBookmarkManager* mgr() const { return m_mgr; }
+ bool showNSBookmarks() const;
+ QString path() const;
+
+ void createManager(const QString &filename);
+ void notifyManagers(KBookmarkGroup grp);
+ void notifyManagers();
+ bool managerSave();
+ void saveAs(const QString &fileName);
+ void doExport(ExportType type, const QString & path = QString::null);
+ void setUpdate(bool update);
+
+ void reloadConfig();
+
+ static QString makeTimeStr(const QString &);
+ static QString makeTimeStr(int);
+
+protected slots:
+ void slotBookmarksChanged(const QString &, const QString &);
+
+private:
+ CurrentMgr() : m_mgr(0), ignorenext(0) { ; }
+ KBookmarkManager *m_mgr;
+ static CurrentMgr *s_mgr;
+ uint ignorenext;
+};
+
+class KEBApp : public KMainWindow {
+ Q_OBJECT
+public:
+ static KEBApp* self() { return s_topLevel; }
+
+ KEBApp(const QString & bookmarksFile, bool readonly, const QString &address, bool browser, const QString &caption);
+ virtual ~KEBApp();
+
+ void updateStatus(QString url);
+ void setActionsEnabled(SelcAbilities);
+
+ void setCancelFavIconUpdatesEnabled(bool);
+ void setCancelTestsEnabled(bool);
+
+ void notifyCommandExecuted();
+ void findURL(QString url);
+
+ QWidget* popupMenuFactory(const char *type) {
+ return factory()->container(type, this);
+ }
+
+ KToggleAction* getToggleAction(const char *) const;
+
+ QString caption() const { return m_caption; }
+ bool readonly() const { return m_readOnly; }
+ bool browser() const { return m_browser; }
+ bool nsShown() const;
+
+ BookmarkInfoWidget *bkInfo() { return m_bkinfo; }
+
+public slots:
+ void updateActions();
+ void slotConfigureToolbars();
+
+protected slots:
+ void slotClipboardDataChanged();
+ void slotNewToolbarConfig();
+
+private:
+ static KBookmarkManager* bookmarkManager();
+
+ void resetActions();
+ void createActions();
+
+ void updateListView();
+
+ static KEBApp *s_topLevel;
+ KBookmarkEditorIface *m_dcopIface;
+
+public: // only temporary
+ CmdHistory *m_cmdHistory;
+ QString m_bookmarksFilename;
+ QString m_caption;
+
+ void construct();
+
+private:
+ BookmarkInfoWidget *m_bkinfo;
+
+ bool m_canPaste:1;
+ bool m_readOnly:1;
+ bool m_browser:1;
+};
+
+#endif
diff --git a/konqueror/keditbookmarks/uninstall.desktop b/konqueror/keditbookmarks/uninstall.desktop
new file mode 100644
index 000000000..e1e3e1732
--- /dev/null
+++ b/konqueror/keditbookmarks/uninstall.desktop
@@ -0,0 +1,2 @@
+[Desktop Entry]
+Hidden=true
diff --git a/konqueror/keditbookmarks/updater.cpp b/konqueror/keditbookmarks/updater.cpp
new file mode 100644
index 000000000..34c884617
--- /dev/null
+++ b/konqueror/keditbookmarks/updater.cpp
@@ -0,0 +1,180 @@
+// -*- 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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qtimer.h>
+
+#include "updater.h"
+
+#include "bookmarkiterator.h"
+#include "listview.h"
+#include "toplevel.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kapplication.h>
+
+#include <kio/job.h>
+
+#include <kparts/part.h>
+#include <kparts/componentfactory.h>
+#include <kparts/browserextension.h>
+
+FavIconUpdater::FavIconUpdater(QObject *parent, const char *name)
+ : KonqFavIconMgr(parent, name) {
+ m_part = 0;
+ m_webGrabber = 0;
+ m_browserIface = 0;
+ m_timer = 0;
+}
+
+void FavIconUpdater::slotCompleted() {
+ // kdDebug() << "FavIconUpdater::slotCompleted" << endl;
+ // kdDebug() << "emit done(true)" << endl;
+ m_timer->stop();
+ emit done(true);
+}
+
+void FavIconUpdater::timerDone() {
+ // Timeout: set completed
+ kdDebug() << "FavIconUpdater: Timeout" << endl;
+ slotCompleted();
+}
+
+void FavIconUpdater::downloadIcon(const KBookmark &bk) {
+ QString favicon = KonqFavIconMgr::iconForURL(bk.url().url());
+ if (!favicon.isNull()) {
+ // kdDebug() << "downloadIcon() - favicon" << favicon << endl;
+ bk.internalElement().setAttribute("icon", favicon);
+ KEBApp::self()->notifyCommandExecuted();
+ // kdDebug() << "emit done(true)" << endl;
+ emit done(true);
+
+ } else {
+ KonqFavIconMgr::downloadHostIcon(bk.url());
+ favicon = KonqFavIconMgr::iconForURL(bk.url().url());
+ // kdDebug() << "favicon == " << favicon << endl;
+ if (favicon.isNull()) {
+ downloadIconActual(bk);
+ }
+ }
+}
+
+FavIconUpdater::~FavIconUpdater() {
+ // kdDebug() << "~FavIconUpdater" << endl;
+ delete m_browserIface;
+ delete m_webGrabber;
+ delete m_part;
+ delete m_timer;
+}
+
+void FavIconUpdater::downloadIconActual(const KBookmark &bk) {
+ m_bk = bk;
+
+ if (!m_part) {
+ KParts::ReadOnlyPart *part
+ = KParts::ComponentFactory
+ ::createPartInstanceFromQuery<KParts::ReadOnlyPart>("text/html", QString::null);
+
+ part->setProperty("pluginsEnabled", QVariant(false, 1));
+ part->setProperty("javaScriptEnabled", QVariant(false, 1));
+ part->setProperty("javaEnabled", QVariant(false, 1));
+ part->setProperty("autoloadImages", QVariant(false, 1));
+
+ connect(part, SIGNAL( canceled(const QString &) ),
+ this, SLOT( slotCompleted() ));
+ connect(part, SIGNAL( completed() ),
+ this, SLOT( slotCompleted() ));
+
+ KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject(part);
+ assert(ext);
+
+ m_browserIface = new FavIconBrowserInterface(this, "browseriface");
+ ext->setBrowserInterface(m_browserIface);
+
+ connect(ext, SIGNAL( setIconURL(const KURL &) ),
+ this, SLOT( setIconURL(const KURL &) ));
+
+ m_part = part;
+ }
+
+ if (!m_timer) {
+ // Timeout to stop the updating hanging
+ m_timer = new QTimer(this);
+ connect( m_timer, SIGNAL(timeout()), this, SLOT(timerDone()) );
+ }
+ m_timer->start(15000,false);
+ m_webGrabber = new FavIconWebGrabber(m_part, bk.url());
+}
+
+// khtml callback
+void FavIconUpdater::setIconURL(const KURL &iconURL) {
+ setIconForURL(m_bk.url(), iconURL);
+}
+
+void FavIconUpdater::notifyChange(bool isHost, QString hostOrURL, QString iconName) {
+ // kdDebug() << "FavIconUpdater::notifyChange()" << endl;
+
+ Q_UNUSED(isHost);
+ // kdDebug() << isHost << endl;
+ Q_UNUSED(hostOrURL);
+ // kdDebug() << "FavIconUpdater::notifyChange" << hostOrURL << "==" << m_bk.url().url() << "-> " << iconName << endl;
+
+ m_bk.internalElement().setAttribute("icon", iconName);
+ KEBApp::self()->notifyCommandExecuted();
+}
+
+/* -------------------------- */
+
+FavIconWebGrabber::FavIconWebGrabber(KParts::ReadOnlyPart *part, const KURL &url)
+ : m_part(part), m_url(url) {
+
+ // kdDebug() << "FavIconWebGrabber::FavIconWebGrabber starting KIO::get() " << url << endl;
+
+// the use of KIO rather than directly using KHTML is to allow silently abort on error
+
+ KIO::Job *job = KIO::get(m_url, false, false);
+ job->addMetaData( QString("cookies"), QString("none") );
+ connect(job, SIGNAL( result( KIO::Job *)),
+ this, SLOT( slotFinished(KIO::Job *) ));
+ connect(job, SIGNAL( mimetype( KIO::Job *, const QString &) ),
+ this, SLOT( slotMimetype(KIO::Job *, const QString &) ));
+}
+
+void FavIconWebGrabber::slotMimetype(KIO::Job *job, const QString & /*type*/) {
+ KIO::SimpleJob *sjob = static_cast<KIO::SimpleJob *>(job);
+ m_url = sjob->url(); // allow for redirection
+ sjob->putOnHold();
+
+ // kdDebug() << "FavIconWebGrabber::slotMimetype " << m_url << "\n";
+
+ // QString typeLocal = typeUncopied; // local copy
+ // kdDebug() << "slotMimetype : " << typeLocal << endl;
+ // TODO - what to do if typeLocal is not text/html ??
+
+ m_part->openURL(m_url);
+}
+
+void FavIconWebGrabber::slotFinished(KIO::Job *job) {
+ if (job->error()) {
+ // kdDebug() << "FavIconWebGrabber::slotFinished() " << job->errorString() << endl;
+ }
+}
+
+#include "updater.moc"
diff --git a/konqueror/keditbookmarks/updater.h b/konqueror/keditbookmarks/updater.h
new file mode 100644
index 000000000..ff92ea55c
--- /dev/null
+++ b/konqueror/keditbookmarks/updater.h
@@ -0,0 +1,91 @@
+// -*- mode:cperl; cperl-indent-level:4; cperl-continued-statement-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 program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __updater_h
+#define __updater_h
+
+#include <kbookmark.h>
+#include <konq_faviconmgr.h>
+
+#include <kparts/part.h>
+#include <kparts/browserinterface.h>
+
+class FavIconWebGrabber : public QObject
+{
+ Q_OBJECT
+public:
+ FavIconWebGrabber(KParts::ReadOnlyPart *part, const KURL &url);
+ ~FavIconWebGrabber() {}
+
+protected slots:
+ void slotMimetype(KIO::Job *job, const QString &_type);
+ void slotFinished(KIO::Job *job);
+
+private:
+ KParts::ReadOnlyPart *m_part;
+ KURL m_url;
+};
+
+class FavIconBrowserInterface;
+
+class FavIconUpdater : public KonqFavIconMgr
+{
+ Q_OBJECT
+
+public:
+ FavIconUpdater(QObject *parent, const char *name);
+ ~FavIconUpdater();
+ void downloadIcon(const KBookmark &bk);
+ void downloadIconActual(const KBookmark &bk);
+
+ virtual void notifyChange(bool isHost, QString hostOrURL,
+ QString iconName);
+
+protected slots:
+ void setIconURL(const KURL &iconURL);
+ void slotCompleted();
+ void timerDone();
+
+
+signals:
+ void done(bool succeeded);
+
+private:
+ KParts::ReadOnlyPart *m_part;
+ FavIconBrowserInterface *m_browserIface;
+ FavIconWebGrabber *m_webGrabber;
+ QTimer *m_timer;
+ KBookmark m_bk;
+};
+
+class FavIconBrowserInterface : public KParts::BrowserInterface
+{
+ Q_OBJECT
+public:
+ FavIconBrowserInterface(FavIconUpdater *view, const char *name)
+ : KParts::BrowserInterface(view, name), m_view(view) {
+ ;
+ }
+private:
+ FavIconUpdater *m_view;
+};
+
+#endif
+