You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/konqueror/sidebar/trees/bookmark_module/bookmark_module.cpp

584 lines
19 KiB

/* This file is part of the KDE project
Copyright (C) 2000 David Faure <faure@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <qclipboard.h>
#include <qcursor.h>
#include <qpopupmenu.h>
#include <kaction.h>
#include <kactioncollection.h>
#include <kapplication.h>
#include <kbookmarkdrag.h>
#include <kiconloader.h>
#include <klineedit.h>
#include <kmessagebox.h>
#include <dcopclient.h>
#include <dcopref.h>
#include "bookmark_module.h"
#include "bookmark_item.h"
#include <konqbookmarkmanager.h>
#include <kdebug.h>
KonqSidebarBookmarkModule::KonqSidebarBookmarkModule( KonqSidebarTree * parentTree )
: QObject( 0L ), KonqSidebarTreeModule( parentTree ),
m_topLevelItem( 0L ), m_ignoreOpenChange(true)
{
// formats handled by KBookmarkDrag:
QStringList formats;
formats << "text/uri-list" << "application/x-xbel" << "text/plain";
tree()->setDropFormats(formats);
connect(tree(), SIGNAL(moved(QListViewItem*,QListViewItem*,QListViewItem*)),
this, SLOT(slotMoved(QListViewItem*,QListViewItem*,QListViewItem*)));
connect(tree(), SIGNAL(dropped(KListView*,QDropEvent*,QListViewItem*,QListViewItem*)),
this, SLOT(slotDropped(KListView*,QDropEvent*,QListViewItem*,QListViewItem*)));
connect(tree(), SIGNAL(expanded(QListViewItem*)),
this, SLOT(slotOpenChange(QListViewItem*)));
connect(tree(), SIGNAL(collapsed(QListViewItem*)),
this, SLOT(slotOpenChange(QListViewItem*)));
m_collection = new KActionCollection( this, "bookmark actions" );
(void) new KAction( i18n("&Create New Folder"), "folder_new", 0, this,
SLOT( slotCreateFolder() ), m_collection, "create_folder");
(void) new KAction( i18n("Delete Folder"), "editdelete", 0, this,
SLOT( slotDelete() ), m_collection, "delete_folder");
(void) new KAction( i18n("Delete Bookmark"), "editdelete", 0, this,
SLOT( slotDelete() ), m_collection, "delete_bookmark");
(void) new KAction( i18n("Properties"), "edit", 0, this,
SLOT( slotProperties() ), m_collection, "item_properties");
(void) new KAction( i18n("Open in New Window"), "window_new", 0, this,
SLOT( slotOpenNewWindow() ), m_collection, "open_window");
(void) new KAction( i18n("Open in New Tab"), "tab_new", 0, this,
SLOT( slotOpenTab() ), m_collection, "open_tab");
(void) new KAction( i18n("Open Folder in Tabs"), "tab_new", 0, this,
SLOT( slotOpenTab() ), m_collection, "folder_open_tabs");
(void) new KAction( i18n("Copy Link Address"), "editcopy", 0, this,
SLOT( slotCopyLocation() ), m_collection, "copy_location");
KStdAction::editBookmarks( KonqBookmarkManager::self(), SLOT( slotEditBookmarks() ),
m_collection, "edit_bookmarks" );
connect( KonqBookmarkManager::self(), SIGNAL(changed(const QString &, const QString &) ),
SLOT( slotBookmarksChanged(const QString &) ) );
}
KonqSidebarBookmarkModule::~KonqSidebarBookmarkModule()
{
}
void KonqSidebarBookmarkModule::addTopLevelItem( KonqSidebarTreeTopLevelItem * item )
{
m_ignoreOpenChange = true;
m_topLevelItem = item;
fillListView();
m_ignoreOpenChange = false;
}
bool KonqSidebarBookmarkModule::handleTopLevelContextMenu( KonqSidebarTreeTopLevelItem *, const QPoint& )
{
QPopupMenu *menu = new QPopupMenu;
if (tree()->tabSupport()) {
m_collection->action("folder_open_tabs")->plug(menu);
menu->insertSeparator();
}
m_collection->action("create_folder")->plug(menu);
menu->insertSeparator();
m_collection->action("edit_bookmarks")->plug(menu);
menu->exec( QCursor::pos() );
delete menu;
return true;
}
void KonqSidebarBookmarkModule::showPopupMenu()
{
KonqSidebarBookmarkItem *bi = dynamic_cast<KonqSidebarBookmarkItem*>( tree()->selectedItem() );
if (!bi)
return;
bool tabSupported = tree()->tabSupport();
QPopupMenu *menu = new QPopupMenu;
if (bi->bookmark().isGroup()) {
if (tabSupported) {
m_collection->action("folder_open_tabs")->plug(menu);
menu->insertSeparator();
}
m_collection->action("create_folder")->plug(menu);
m_collection->action("delete_folder")->plug(menu);
} else {
m_collection->action("open_window")->plug(menu);
if (tabSupported)
m_collection->action("open_tab")->plug(menu);
m_collection->action("copy_location")->plug(menu);
menu->insertSeparator();
m_collection->action("create_folder")->plug(menu);
m_collection->action("delete_bookmark")->plug(menu);
}
menu->insertSeparator();
m_collection->action("item_properties")->plug(menu);
menu->exec( QCursor::pos() );
delete menu;
}
void KonqSidebarBookmarkModule::slotMoved(QListViewItem *i, QListViewItem*, QListViewItem *after)
{
KonqSidebarBookmarkItem *item = dynamic_cast<KonqSidebarBookmarkItem*>( i );
if (!item)
return;
KBookmark bookmark = item->bookmark();
KBookmark afterBookmark;
KonqSidebarBookmarkItem *afterItem = dynamic_cast<KonqSidebarBookmarkItem*>(after);
if (afterItem)
afterBookmark = afterItem->bookmark();
KBookmarkGroup oldParentGroup = bookmark.parentGroup();
KBookmarkGroup parentGroup;
// try to get the parent group (assume that the QListViewItem has been reparented by KListView)...
// if anything goes wrong, use the root.
if (item->parent()) {
bool error = false;
KonqSidebarBookmarkItem *parent = dynamic_cast<KonqSidebarBookmarkItem*>( (item->parent()) );
if (!parent) {
error = true;
} else {
if (parent->bookmark().isGroup())
parentGroup = parent->bookmark().toGroup();
else
error = true;
}
if (error)
parentGroup = KonqBookmarkManager::self()->root();
} else {
// No parent! This means the user dropped it before the top level item
// And KListView has moved the item there, we need to correct it
tree()->moveItem(item, m_topLevelItem, 0L);
parentGroup = KonqBookmarkManager::self()->root();
}
// remove the old reference.
oldParentGroup.deleteBookmark( bookmark );
// insert the new item.
parentGroup.moveItem(bookmark, afterBookmark);
// inform others about the changed groups. quite expensive, so do
// our best to update them in only one emitChanged call.
QString oldAddress = oldParentGroup.address();
QString newAddress = parentGroup.address();
if (oldAddress == newAddress) {
KonqBookmarkManager::self()->emitChanged( parentGroup );
} else {
int i = 0;
while (true) {
QChar c1 = oldAddress[i];
QChar c2 = newAddress[i];
if (c1 == QChar::null) {
// oldParentGroup is probably parent of parentGroup.
KonqBookmarkManager::self()->emitChanged( oldParentGroup );
break;
} else if (c2 == QChar::null) {
// parentGroup is probably parent of oldParentGroup.
KonqBookmarkManager::self()->emitChanged( parentGroup );
break;
} else {
if (c1 == c2) {
// step to the next character.
++i;
} else {
// ugh... need to update both groups separately.
KonqBookmarkManager::self()->emitChanged( oldParentGroup );
KonqBookmarkManager::self()->emitChanged( parentGroup );
break;
}
}
}
}
}
void KonqSidebarBookmarkModule::slotDropped(KListView *, QDropEvent *e, QListViewItem *parent, QListViewItem *after)
{
if (!KBookmarkDrag::canDecode(e))
return;
KBookmark afterBookmark;
KonqSidebarBookmarkItem *afterItem = dynamic_cast<KonqSidebarBookmarkItem*>(after);
if (afterItem)
afterBookmark = afterItem->bookmark();
KBookmarkGroup parentGroup;
// try to get the parent group...
if (after) {
parentGroup = afterBookmark.parentGroup();
} else if (parent) {
if(KonqSidebarBookmarkItem *p = dynamic_cast<KonqSidebarBookmarkItem*>(parent))
{
if (!p)
return;
KBookmark bm = p->bookmark();
if (bm.isGroup())
parentGroup = bm.toGroup();
else
return;
}
else if(parent == m_topLevelItem)
{
parentGroup = KonqBookmarkManager::self()->root();
}
} else {
// it's most probably the root...
parentGroup = KonqBookmarkManager::self()->root();
}
QValueList<KBookmark> bookmarks = KBookmarkDrag::decode(e);
// copy
QValueList<KBookmark>::iterator it = bookmarks.begin();
for (;it != bookmarks.end(); ++it) {
// insert new item.
parentGroup.moveItem(*it, afterBookmark);
}
KonqBookmarkManager::self()->emitChanged( parentGroup );
}
void KonqSidebarBookmarkModule::slotCreateFolder()
{
KonqSidebarBookmarkItem *bi = dynamic_cast<KonqSidebarBookmarkItem*>( tree()->selectedItem() );
KBookmarkGroup parentGroup;
if (bi)
{
if (bi->bookmark().isGroup())
parentGroup = bi->bookmark().toGroup();
else
parentGroup = bi->bookmark().parentGroup();
}
else if(tree()->selectedItem() == m_topLevelItem)
{
parentGroup = KonqBookmarkManager::self()->root();
}
else
return;
KBookmark bookmark = parentGroup.createNewFolder(KonqBookmarkManager::self());
if(bi && !(bi->bookmark().isGroup()))
parentGroup.moveItem(bookmark, bi->bookmark());
KonqBookmarkManager::self()->emitChanged( parentGroup );
}
void KonqSidebarBookmarkModule::slotDelete()
{
KonqSidebarBookmarkItem *bi = dynamic_cast<KonqSidebarBookmarkItem*>( tree()->selectedItem() );
if (!bi)
return;
KBookmark bookmark = bi->bookmark();
bool folder = bookmark.isGroup();
if (KMessageBox::warningYesNo(
tree(),
folder ? i18n("Are you sure you wish to remove the bookmark folder\n\"%1\"?").arg(bookmark.text())
: i18n("Are you sure you wish to remove the bookmark\n\"%1\"?").arg(bookmark.text()),
folder ? i18n("Bookmark Folder Deletion")
: i18n("Bookmark Deletion"),
KGuiItem( i18n("&Delete"), "editdelete"), KStdGuiItem::cancel())
!= KMessageBox::Yes
)
return;
KBookmarkGroup parentBookmark = bookmark.parentGroup();
parentBookmark.deleteBookmark( bookmark );
KonqBookmarkManager::self()->emitChanged( parentBookmark );
}
void makeTextNodeMod(KBookmark bk, const QString &m_nodename, const QString &m_newText) {
QDomNode subnode = bk.internalElement().namedItem(m_nodename);
if (subnode.isNull()) {
subnode = bk.internalElement().ownerDocument().createElement(m_nodename);
bk.internalElement().appendChild(subnode);
}
if (subnode.firstChild().isNull()) {
QDomText domtext = subnode.ownerDocument().createTextNode("");
subnode.appendChild(domtext);
}
QDomText domtext = subnode.firstChild().toText();
QString m_oldText = domtext.data();
domtext.setData(m_newText);
}
void KonqSidebarBookmarkModule::slotProperties(KonqSidebarBookmarkItem *bi)
{
if (!bi) {
bi = dynamic_cast<KonqSidebarBookmarkItem*>( tree()->selectedItem() );
if (!bi)
return;
}
KBookmark bookmark = bi->bookmark();
QString folder = bookmark.isGroup() ? QString::null : bookmark.url().pathOrURL();
BookmarkEditDialog dlg( bookmark.fullText(), folder, 0, 0,
i18n("Bookmark Properties") );
if ( dlg.exec() != KDialogBase::Accepted )
return;
makeTextNodeMod(bookmark, "title", dlg.finalTitle());
if ( !dlg.finalUrl().isNull() )
{
KURL u = KURL::fromPathOrURL(dlg.finalUrl());
bookmark.internalElement().setAttribute("href", u.url(0, 106));
}
KBookmarkGroup parentBookmark = bookmark.parentGroup();
KonqBookmarkManager::self()->emitChanged( parentBookmark );
}
void KonqSidebarBookmarkModule::slotOpenNewWindow()
{
KonqSidebarBookmarkItem *bi = dynamic_cast<KonqSidebarBookmarkItem*>( tree()->selectedItem() );
if (!bi)
return;
emit tree()->createNewWindow( bi->bookmark().url() );
}
void KonqSidebarBookmarkModule::slotOpenTab()
{
KonqSidebarBookmarkItem *bi = dynamic_cast<KonqSidebarBookmarkItem*>( tree()->selectedItem() );
KBookmark bookmark;
if (bi)
{
bookmark = bi->bookmark();
}
else if(tree()->selectedItem() == m_topLevelItem)
bookmark = KonqBookmarkManager::self()->root();
else
return;
DCOPRef ref(kapp->dcopClient()->appId(), tree()->topLevelWidget()->name());
if (bookmark.isGroup()) {
KBookmarkGroup group = bookmark.toGroup();
bookmark = group.first();
while (!bookmark.isNull()) {
if (!bookmark.isGroup() && !bookmark.isSeparator())
ref.call( "newTab(QString)", bookmark.url().url() );
bookmark = group.next(bookmark);
}
} else {
ref.call( "newTab(QString)", bookmark.url().url() );
}
}
void KonqSidebarBookmarkModule::slotCopyLocation()
{
KonqSidebarBookmarkItem *bi = dynamic_cast<KonqSidebarBookmarkItem*>( tree()->selectedItem() );
if (!bi)
return;
KBookmark bookmark = bi->bookmark();
if ( !bookmark.isGroup() )
{
kapp->clipboard()->setData( KBookmarkDrag::newDrag(bookmark, 0),
QClipboard::Selection );
kapp->clipboard()->setData( KBookmarkDrag::newDrag(bookmark, 0),
QClipboard::Clipboard );
}
}
void KonqSidebarBookmarkModule::slotOpenChange(QListViewItem* i)
{
if (m_ignoreOpenChange)
return;
KonqSidebarBookmarkItem *bi = dynamic_cast<KonqSidebarBookmarkItem*>( i );
if (!bi)
return;
KBookmark bookmark = bi->bookmark();
bool open = bi->isOpen();
if (!open)
m_folderOpenState.remove(bookmark.address()); // no need to store closed folders...
else
m_folderOpenState[bookmark.address()] = open;
}
void KonqSidebarBookmarkModule::slotBookmarksChanged( const QString & groupAddress )
{
m_ignoreOpenChange = true;
// update the right part of the tree
KBookmarkGroup group = KonqBookmarkManager::self()->findByAddress( groupAddress ).toGroup();
KonqSidebarBookmarkItem * item = findByAddress( groupAddress );
Q_ASSERT(!group.isNull());
Q_ASSERT(item);
if (!group.isNull() && item)
{
// Delete all children of item
QListViewItem * child = item->firstChild();
while( child ) {
QListViewItem * next = child->nextSibling();
delete child;
child = next;
}
fillGroup( item, group );
}
m_ignoreOpenChange = false;
}
void KonqSidebarBookmarkModule::fillListView()
{
m_ignoreOpenChange = true;
KBookmarkGroup root = KonqBookmarkManager::self()->root();
fillGroup( m_topLevelItem, root );
m_ignoreOpenChange = false;
}
void KonqSidebarBookmarkModule::fillGroup( KonqSidebarTreeItem * parentItem, KBookmarkGroup group )
{
int n = 0;
for ( KBookmark bk = group.first() ; !bk.isNull() ; bk = group.next(bk), ++n )
{
KonqSidebarBookmarkItem * item = new KonqSidebarBookmarkItem( parentItem, m_topLevelItem, bk, n );
if ( bk.isGroup() )
{
KBookmarkGroup grp = bk.toGroup();
fillGroup( item, grp );
QString address(grp.address());
if (m_folderOpenState.contains(address))
item->setOpen(m_folderOpenState[address]);
else
item->setOpen(false);
}
else if ( bk.isSeparator() )
item->setVisible( false );
else
item->setExpandable( false );
}
}
// Borrowed from KEditBookmarks
KonqSidebarBookmarkItem * KonqSidebarBookmarkModule::findByAddress( const QString & address ) const
{
QListViewItem * item = m_topLevelItem;
// The address is something like /5/10/2
QStringList addresses = QStringList::split('/',address);
for ( QStringList::Iterator it = addresses.begin() ; it != addresses.end() ; ++it )
{
uint number = (*it).toUInt();
item = item->firstChild();
for ( uint i = 0 ; i < number ; ++i )
item = item->nextSibling();
}
Q_ASSERT(item);
return static_cast<KonqSidebarBookmarkItem *>(item);
}
// Borrowed&modified from KBookmarkMenu...
BookmarkEditDialog::BookmarkEditDialog(const QString& title, const QString& url,
QWidget * parent, const char * name, const QString& caption )
: KDialogBase(parent, name, true, caption,
(Ok|Cancel),
Ok, false, KGuiItem()),
m_title(0), m_location(0)
{
setButtonOK( i18n( "&Update" ) );
QWidget *main = new QWidget( this );
setMainWidget( main );
bool folder = url.isNull();
QGridLayout *grid = new QGridLayout( main, 2, folder?1:2, spacingHint() );
QLabel *nameLabel = new QLabel(i18n("Name:"), main, "title label");
grid->addWidget(nameLabel, 0, 0);
m_title = new KLineEdit(main, "title edit");
m_title->setText(title);
nameLabel->setBuddy(m_title);
grid->addWidget(m_title, 0, 1);
if(!folder) {
QLabel *locationLabel = new QLabel(i18n("Location:"), main, "location label");
grid->addWidget(locationLabel, 1, 0);
m_location = new KLineEdit(main, "location edit");
m_location->setText(url);
locationLabel->setBuddy(m_location);
grid->addWidget(m_location, 1, 1);
}
main->setMinimumSize( 300, 0 );
}
void BookmarkEditDialog::slotOk()
{
accept();
}
void BookmarkEditDialog::slotCancel()
{
reject();
}
QString BookmarkEditDialog::finalUrl() const
{
if (m_location!=0)
return m_location->text();
else
return QString::null;
}
QString BookmarkEditDialog::finalTitle() const
{
if (m_title!=0)
return m_title->text();
else
return QString::null;
}
extern "C"
{
KDE_EXPORT KonqSidebarTreeModule* create_konq_sidebartree_bookmarks(KonqSidebarTree* par,const bool)
{
return new KonqSidebarBookmarkModule(par);
}
}
#include "bookmark_module.moc"