diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 4aed2c8219774f5d797760606b8489a92ddc5163 (patch) | |
tree | 3f8c130f7d269626bf6a9447407ef6c35954426a /konqueror/keditbookmarks | |
download | tdebase-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')
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 Binary files differnew file mode 100644 index 000000000..6a3fc5efe --- /dev/null +++ b/konqueror/keditbookmarks/cr16-app-keditbookmarks.png diff --git a/konqueror/keditbookmarks/cr32-app-keditbookmarks.png b/konqueror/keditbookmarks/cr32-app-keditbookmarks.png Binary files differnew file mode 100644 index 000000000..b7e10c47f --- /dev/null +++ b/konqueror/keditbookmarks/cr32-app-keditbookmarks.png diff --git a/konqueror/keditbookmarks/cr48-app-keditbookmarks.png b/konqueror/keditbookmarks/cr48-app-keditbookmarks.png Binary files differnew file mode 100644 index 000000000..d1f5e91cc --- /dev/null +++ b/konqueror/keditbookmarks/cr48-app-keditbookmarks.png diff --git a/konqueror/keditbookmarks/cr64-app-keditbookmarks.png b/konqueror/keditbookmarks/cr64-app-keditbookmarks.png Binary files differnew file mode 100644 index 000000000..8f2504942 --- /dev/null +++ b/konqueror/keditbookmarks/cr64-app-keditbookmarks.png 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>&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>&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>&View</text> + <Action name="expandall"/> + <Action name="collapseall"/> +</Menu> + +<Menu name="folder"><text>&Folder</text> + <Action name="newfolder"/> + <Action name="insertseparator"/> + <Separator/> + <Action name="sort"/> + <Action name="recursivesort"/> + </Menu> + +<Menu name="bookmark"><text>&Bookmark</text> + <Action name="newbookmark"/> +</Menu> + +<Menu name="settings"><text>&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>&File</text> + <Action name="file_open"/> + <Action name="file_save_as"/> + <Separator/> + <Action name="file_print"/> + <Separator/> + <Menu name="import" noMerge="1"><text>&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>&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>&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>&View</text> + <Action name="expandall"/> + <Action name="collapseall"/> +</Menu> + +<Menu name="folder"><text>&Folder</text> + <Action name="newfolder"/> + <Action name="insertseparator"/> + <Separator/> + <Action name="setastoolbar"/> + <Action name="sort"/> + <Action name="recursivesort"/> + </Menu> + +<Menu name="bookmark"><text>&Bookmark</text> + <Action name="newbookmark"/> + <Action name="openlink"/> + <Separator/> + <Action name="testlink"/> + <Action name="updatefavicon"/> +</Menu> + +<Menu name="tools"><text>&Tools</text> + <Action name="testall"/> + <Action name="canceltests"/> + <Separator/> + <Action name="updateallfavicons"/> + <Action name="cancelfaviconupdates"/> +</Menu> + +<Menu name="settings"><text>&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 + |