kio Library API Documentation

kbookmarkmenu.cc

00001 //  -*- c-basic-offset:4; indent-tabs-mode:nil -*-
00002 // vim: set ts=4 sts=4 sw=4 et:
00003 /* This file is part of the KDE project
00004    Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019    Boston, MA 02111-1307, USA.
00020 */
00021 
00022 #include "kbookmarkmenu.h"
00023 #include "kbookmarkmenu_p.h"
00024 #include "kbookmarkimporter.h"
00025 #include "kbookmarkimporter_opera.h"
00026 #include "kbookmarkimporter_ie.h"
00027 #include "kbookmarkdrag.h"
00028 
00029 #include <qstring.h>
00030 #include <qlineedit.h>
00031 #include <qlabel.h>
00032 #include <kdialogbase.h>
00033 #include <qlayout.h>
00034 #include <qpushbutton.h>
00035 
00036 #include <qclipboard.h>
00037 
00038 #include <klineedit.h>
00039 
00040 #include <qfile.h>
00041 
00042 #include <kapplication.h>
00043 #include <kaction.h>
00044 #include <kdebug.h>
00045 #include <klocale.h>
00046 #include <kmessagebox.h>
00047 #include <kpopupmenu.h>
00048 #include <kstdaccel.h>
00049 #include <kstdaction.h>
00050 #include <kconfig.h>
00051 
00052 #include <qlistview.h>
00053 #include <qheader.h>
00054 
00055 #include <kiconloader.h>
00056 
00057 #include <dptrtemplate.h>
00058 
00059 template class QPtrList<KBookmarkMenu>;
00060 
00061 static QString makeTextNodeMod(KBookmark bk, const QString &m_nodename, const QString &m_newText) {
00062   QDomNode subnode = bk.internalElement().namedItem(m_nodename);
00063   if (subnode.isNull()) {
00064     subnode = bk.internalElement().ownerDocument().createElement(m_nodename);
00065     bk.internalElement().appendChild(subnode);
00066   }
00067 
00068   if (subnode.firstChild().isNull()) {
00069     QDomText domtext = subnode.ownerDocument().createTextNode("");
00070     subnode.appendChild(domtext);
00071   }
00072 
00073   QDomText domtext = subnode.firstChild().toText();
00074 
00075   QString m_oldText = domtext.data();
00076   domtext.setData(m_newText);
00077 
00078   return m_oldText;
00079 }
00080 
00081 /********************************************************************/
00082 /********************************************************************/
00083 /********************************************************************/
00084 
00085 KBookmarkMenu::KBookmarkMenu( KBookmarkManager* mgr,
00086                               KBookmarkOwner * _owner, KPopupMenu * _parentMenu,
00087                               KActionCollection *collec, bool _isRoot, bool _add,
00088                               const QString & parentAddress )
00089   : m_bIsRoot(_isRoot), m_bAddBookmark(_add),
00090     m_bAddShortcuts(true),
00091     m_pManager(mgr), m_pOwner(_owner),
00092     m_parentMenu( _parentMenu ),
00093     m_actionCollection( collec ),
00094     m_parentAddress( parentAddress )
00095 {
00096   m_parentMenu->setKeyboardShortcutsEnabled( true );
00097 
00098   m_lstSubMenus.setAutoDelete( true );
00099   m_actions.setAutoDelete( true );
00100 
00101   if (m_actionCollection)
00102   {
00103     m_actionCollection->setHighlightingEnabled(true);
00104     disconnect( m_actionCollection, SIGNAL( actionHighlighted( KAction * ) ), 0, 0 );
00105     connect( m_actionCollection, SIGNAL( actionHighlighted( KAction * ) ),
00106              this, SLOT( slotActionHighlighted( KAction * ) ) );
00107   }
00108 
00109   m_bNSBookmark = m_parentAddress.isNull();
00110   if ( !m_bNSBookmark ) // not for the netscape bookmark
00111   {
00112     //kdDebug(7043) << "KBookmarkMenu::KBookmarkMenu " << this << " address : " << m_parentAddress << endl;
00113 
00114     connect( _parentMenu, SIGNAL( aboutToShow() ),
00115              SLOT( slotAboutToShow() ) );
00116 
00117     if ( KBookmarkSettings::self()->m_contextmenu )
00118     {
00119       (void) _parentMenu->contextMenu();
00120       connect( _parentMenu, SIGNAL( aboutToShowContextMenu(KPopupMenu*, int, QPopupMenu*) ),
00121                this, SLOT( slotAboutToShowContextMenu(KPopupMenu*, int, QPopupMenu*) ));
00122     }
00123 
00124     if ( m_bIsRoot )
00125     {
00126       connect( m_pManager, SIGNAL( changed(const QString &, const QString &) ),
00127                SLOT( slotBookmarksChanged(const QString &) ) );
00128     }
00129   }
00130 
00131   // add entries that possibly have a shortcut, so they are available _before_ first popup
00132   if ( m_bIsRoot )
00133   {
00134     if ( m_bAddBookmark )
00135     {
00136       addAddBookmark();
00137       if ( extOwner() )
00138         addAddBookmarksList(); // FIXME
00139     }
00140 
00141     addEditBookmarks();
00142   }
00143 
00144   m_bDirty = true;
00145 }
00146 
00147 KBookmarkMenu::~KBookmarkMenu()
00148 {
00149   //kdDebug(7043) << "KBookmarkMenu::~KBookmarkMenu() " << this << endl;
00150   QPtrListIterator<KAction> it( m_actions );
00151   for (; it.current(); ++it )
00152     it.current()->unplugAll();
00153 
00154   m_lstSubMenus.clear();
00155   m_actions.clear();
00156 }
00157 
00158 void KBookmarkMenu::ensureUpToDate()
00159 {
00160   slotAboutToShow();
00161 }
00162 
00163 void KBookmarkMenu::slotAboutToShow()
00164 {
00165   // Did the bookmarks change since the last time we showed them ?
00166   if ( m_bDirty )
00167   {
00168     m_bDirty = false;
00169     refill();
00170   }
00171 }
00172 
00173 QString KBookmarkMenu::s_highlightedAddress;
00174 QString KBookmarkMenu::s_highlightedImportType;
00175 QString KBookmarkMenu::s_highlightedImportLocation;
00176 
00177 void KBookmarkMenu::slotActionHighlighted( KAction* action )
00178 {
00179   if (action->isA("KBookmarkActionMenu") || action->isA("KBookmarkAction"))
00180   {
00181     s_highlightedAddress = action->property("address").toString();
00182     //kdDebug() << "KBookmarkMenu::slotActionHighlighted" << s_highlightedAddress << endl;
00183   }
00184   else if (action->isA("KImportedBookmarksActionMenu"))
00185   {
00186     s_highlightedImportType = action->property("type").toString();
00187     s_highlightedImportLocation = action->property("location").toString();
00188   }
00189   else
00190   {
00191     s_highlightedAddress = QString::null;
00192     s_highlightedImportType = QString::null;
00193     s_highlightedImportLocation = QString::null;
00194   }
00195 }
00196 
00197 /********************************************************************/
00198 /********************************************************************/
00199 /********************************************************************/
00200 
00201 class KBookmarkMenuRMBAssoc : public dPtrTemplate<KBookmarkMenu, RMB> { };
00202 template<> QPtrDict<RMB>* dPtrTemplate<KBookmarkMenu, RMB>::d_ptr = 0;
00203 
00204 static RMB* rmbSelf(KBookmarkMenu *m) { return KBookmarkMenuRMBAssoc::d(m); }
00205 
00206 // TODO check via dcop before making any changes to the bookmarks file???
00207 
00208 void RMB::begin_rmb_action(KBookmarkMenu *self)
00209 {
00210   RMB *s = rmbSelf(self);
00211   s->recv = self;
00212   s->m_parentAddress = self->m_parentAddress;
00213   s->s_highlightedAddress = KBookmarkMenu::s_highlightedAddress;
00214   s->m_pManager = self->m_pManager;
00215   s->m_pOwner = self->m_pOwner;
00216   s->m_parentMenu = self->m_parentMenu;
00217 }
00218 
00219 bool RMB::invalid( int val )
00220 {
00221   bool valid = true;
00222 
00223   if (val == 1)
00224     s_highlightedAddress = m_parentAddress;
00225 
00226   if (s_highlightedAddress.isNull())
00227     valid = false;
00228 
00229   return !valid;
00230 }
00231 
00232 KBookmark RMB::atAddress(const QString & address)
00233 {
00234   KBookmark bookmark = m_pManager->findByAddress( address );
00235   Q_ASSERT(!bookmark.isNull());
00236   return bookmark;
00237 }
00238 
00239 void KBookmarkMenu::slotAboutToShowContextMenu( KPopupMenu*, int, QPopupMenu* contextMenu )
00240 {
00241   //kdDebug(7043) << "KBookmarkMenu::slotAboutToShowContextMenu" << s_highlightedAddress << endl;
00242   if (s_highlightedAddress.isNull())
00243   {
00244     KPopupMenu::contextMenuFocus()->hideContextMenu();
00245     return;
00246   }
00247   contextMenu->clear();
00248   fillContextMenu( contextMenu, s_highlightedAddress, 0 );
00249 }
00250 
00251 void RMB::fillContextMenu( QPopupMenu* contextMenu, const QString & address, int val )
00252 {
00253   KBookmark bookmark = atAddress(address);
00254 
00255   int id;
00256 
00257   // binner:
00258   // "Add Bookmark Here" when pointing at a bookmark looks strange and if you
00259   // call it you have to close and reopen the menu to see an entry was added?
00260   //
00261   // TODO rename these, but, message freeze... umm...
00262 
00263 //  if (bookmark.isGroup()) {
00264     id = contextMenu->insertItem( SmallIcon("bookmark_add"), i18n( "Add Bookmark Here" ), recv, SLOT(slotRMBActionInsert(int)) );
00265     contextMenu->setItemParameter( id, val );
00266 /*  }
00267   else
00268   {
00269     id = contextMenu->insertItem( SmallIcon("bookmark_add"), i18n( "Add Bookmark Here" ), recv, SLOT(slotRMBActionInsert(int)) );
00270     contextMenu->setItemParameter( id, val );
00271   }*/
00272 }
00273 
00274 void RMB::fillContextMenu2( QPopupMenu* contextMenu, const QString & address, int val )
00275 {
00276   KBookmark bookmark = atAddress(address);
00277 
00278   int id;
00279 
00280   if (bookmark.isGroup()) {
00281     id = contextMenu->insertItem( i18n( "Open Folder in Bookmark Editor" ), recv, SLOT(slotRMBActionEditAt(int)) );
00282     contextMenu->setItemParameter( id, val );
00283     contextMenu->insertSeparator();
00284     id = contextMenu->insertItem( SmallIcon("editdelete"), i18n( "Delete Folder" ), recv, SLOT(slotRMBActionRemove(int)) );
00285     contextMenu->setItemParameter( id, val );
00286     contextMenu->insertSeparator();
00287     id = contextMenu->insertItem( i18n( "Properties" ), recv, SLOT(slotRMBActionProperties(int)) );
00288     contextMenu->setItemParameter( id, val );
00289   }
00290   else
00291   {
00292     id = contextMenu->insertItem( i18n( "Copy Link Address" ), recv, SLOT(slotRMBActionCopyLocation(int)) );
00293     contextMenu->setItemParameter( id, val );
00294     contextMenu->insertSeparator();
00295     id = contextMenu->insertItem( SmallIcon("editdelete"), i18n( "Delete Bookmark" ), recv, SLOT(slotRMBActionRemove(int)) );
00296     contextMenu->setItemParameter( id, val );
00297     contextMenu->insertSeparator();
00298     id = contextMenu->insertItem( i18n( "Properties" ), recv, SLOT(slotRMBActionProperties(int)) );
00299     contextMenu->setItemParameter( id, val );
00300   }
00301 }
00302 
00303 void RMB::slotRMBActionEditAt( int val )
00304 {
00305   kdDebug(7043) << "KBookmarkMenu::slotRMBActionEditAt" << s_highlightedAddress << endl;
00306   if (invalid(val)) { hidePopup(); return; }
00307 
00308   KBookmark bookmark = atAddress(s_highlightedAddress);
00309 
00310   m_pManager->slotEditBookmarksAtAddress( s_highlightedAddress );
00311 }
00312 
00313 void RMB::slotRMBActionProperties( int val )
00314 {
00315   kdDebug(7043) << "KBookmarkMenu::slotRMBActionProperties" << s_highlightedAddress << endl;
00316   if (invalid(val)) { hidePopup(); return; }
00317 
00318   KBookmark bookmark = atAddress(s_highlightedAddress);
00319 
00320   QString folder = bookmark.isGroup() ? QString::null : bookmark.url().url();
00321   KBookmarkEditDialog dlg( bookmark.fullText(), folder,
00322                            m_pManager, KBookmarkEditDialog::ModifyMode, 0,
00323                            0, 0, i18n("Bookmark Properties") );
00324   if ( dlg.exec() != KDialogBase::Accepted )
00325     return;
00326 
00327   makeTextNodeMod(bookmark, "title", dlg.finalTitle());
00328   if ( !dlg.finalUrl().isNull() )
00329     bookmark.internalElement().setAttribute("href", dlg.finalUrl());
00330 
00331   kdDebug(7043) << "Requested move to " << dlg.finalAddress() << "!" << endl;
00332 
00333   KBookmarkGroup parentBookmark = atAddress(m_parentAddress).toGroup();
00334   m_pManager->emitChanged( parentBookmark );
00335 }
00336 
00337 void RMB::slotRMBActionInsert( int val )
00338 {
00339   kdDebug(7043) << "KBookmarkMenu::slotRMBActionInsert" << s_highlightedAddress << endl;
00340   if (invalid(val)) { hidePopup(); return; }
00341 
00342   QString url = m_pOwner->currentURL();
00343   if (url.isEmpty())
00344   {
00345     KMessageBox::error( 0L, i18n("Cannot add bookmark with empty URL."));
00346     return;
00347   }
00348   QString title = m_pOwner->currentTitle();
00349   if (title.isEmpty())
00350     title = url;
00351 
00352   KBookmark bookmark = atAddress( s_highlightedAddress );
00353 
00354   // TODO use unique title
00355 
00356   if (bookmark.isGroup())
00357   {
00358     KBookmarkGroup parentBookmark = bookmark.toGroup();
00359     Q_ASSERT(!parentBookmark.isNull());
00360     parentBookmark.addBookmark( m_pManager, title, KURL(  url ) );
00361     m_pManager->emitChanged( parentBookmark );
00362   }
00363   else
00364   {
00365     KBookmarkGroup parentBookmark = bookmark.parentGroup();
00366     Q_ASSERT(!parentBookmark.isNull());
00367     KBookmark newBookmark = parentBookmark.addBookmark( m_pManager, title, KURL( url ) );
00368     parentBookmark.moveItem( newBookmark, parentBookmark.previous(bookmark) );
00369     m_pManager->emitChanged( parentBookmark );
00370   }
00371 }
00372 
00373 void RMB::slotRMBActionRemove( int val )
00374 {
00375   //kdDebug(7043) << "KBookmarkMenu::slotRMBActionRemove" << s_highlightedAddress << endl;
00376   if (invalid(val)) { hidePopup(); return; }
00377 
00378   KBookmark bookmark = atAddress( s_highlightedAddress );
00379   bool folder = bookmark.isGroup();
00380 
00381   if (KMessageBox::warningYesNo(
00382           m_parentMenu,
00383           folder ? i18n("Are you sure you wish to remove this bookmark folder?")
00384                  : i18n("Are you sure you wish to remove this bookmark?"),
00385           folder ? i18n("Bookmark Folder Deletion")
00386                  : i18n("Bookmark Deletion"),
00387           KGuiItem( i18n("&Delete"), "editdelete"), KStdGuiItem::cancel())
00388         != KMessageBox::Yes
00389      )
00390     return;
00391 
00392   KBookmarkGroup parentBookmark = atAddress( m_parentAddress ).toGroup();
00393   parentBookmark.deleteBookmark( bookmark );
00394   m_pManager->emitChanged( parentBookmark );
00395   if (m_parentMenu)
00396     m_parentMenu->hide();
00397 }
00398 
00399 void RMB::slotRMBActionCopyLocation( int val )
00400 {
00401   //kdDebug(7043) << "KBookmarkMenu::slotRMBActionCopyLocation" << s_highlightedAddress << endl;
00402   if (invalid(val)) { hidePopup(); return; }
00403 
00404   KBookmark bookmark = atAddress( s_highlightedAddress );
00405 
00406   if ( !bookmark.isGroup() )
00407   {
00408     kapp->clipboard()->setData( KBookmarkDrag::newDrag(bookmark, 0),
00409                                 QClipboard::Selection );
00410     kapp->clipboard()->setData( KBookmarkDrag::newDrag(bookmark, 0),
00411                                 QClipboard::Clipboard );
00412   }
00413 }
00414 
00415 void RMB::hidePopup() {
00416   KPopupMenu::contextMenuFocus()->hideContextMenu();
00417 }
00418 
00419 /********************************************************************/
00420 /********************************************************************/
00421 /********************************************************************/
00422 
00423 void KBookmarkMenu::fillContextMenu( QPopupMenu* contextMenu, const QString & address, int val )
00424 {
00425   RMB::begin_rmb_action(this);
00426   rmbSelf(this)->fillContextMenu(contextMenu, address, val);
00427   emit aboutToShowContextMenu( rmbSelf(this)->atAddress(address), contextMenu);
00428   rmbSelf(this)->fillContextMenu2(contextMenu, address, val);
00429 }
00430 
00431 void KBookmarkMenu::slotRMBActionEditAt( int val )
00432 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionEditAt( val ); }
00433 
00434 void KBookmarkMenu::slotRMBActionProperties( int val )
00435 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionProperties( val ); }
00436 
00437 void KBookmarkMenu::slotRMBActionInsert( int val )
00438 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionInsert( val ); }
00439 
00440 void KBookmarkMenu::slotRMBActionRemove( int val )
00441 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionRemove( val ); }
00442 
00443 void KBookmarkMenu::slotRMBActionCopyLocation( int val )
00444 { RMB::begin_rmb_action(this); rmbSelf(this)->slotRMBActionCopyLocation( val ); }
00445 
00446 void KBookmarkMenu::slotBookmarksChanged( const QString & groupAddress )
00447 {
00448   if (m_bNSBookmark)
00449     return;
00450 
00451   if ( groupAddress == m_parentAddress )
00452   {
00453     //kdDebug(7043) << "KBookmarkMenu::slotBookmarksChanged -> setting m_bDirty on " << groupAddress << endl;
00454     m_bDirty = true;
00455   }
00456   else
00457   {
00458     // Iterate recursively into child menus
00459     QPtrListIterator<KBookmarkMenu> it( m_lstSubMenus );
00460     for (; it.current(); ++it )
00461     {
00462       it.current()->slotBookmarksChanged( groupAddress );
00463     }
00464   }
00465 }
00466 
00467 void KBookmarkMenu::refill()
00468 {
00469   //kdDebug(7043) << "KBookmarkMenu::refill()" << endl;
00470   m_lstSubMenus.clear();
00471 
00472   QPtrListIterator<KAction> it( m_actions );
00473   for (; it.current(); ++it )
00474     it.current()->unplug( m_parentMenu );
00475 
00476   m_parentMenu->clear();
00477   m_actions.clear();
00478 
00479   fillBookmarkMenu();
00480   m_parentMenu->adjustSize();
00481 }
00482 
00483 void KBookmarkMenu::addAddBookmarksList()
00484 {
00485   if (!kapp->authorizeKAction("bookmarks"))
00486      return;
00487 
00488   QString title = i18n( "Bookmark Tabs as Folder..." );
00489 
00490   KAction * paAddBookmarksList = new KAction( title,
00491                                           "bookmarks_list_add",
00492                                           0,
00493                                           this,
00494                                           SLOT( slotAddBookmarksList() ),
00495                                           m_actionCollection, m_bIsRoot ? "add_bookmarks_list" : 0 );
00496 
00497   paAddBookmarksList->setToolTip( i18n( "Add a folder of bookmarks for all open tabs." ) );
00498 
00499   paAddBookmarksList->plug( m_parentMenu );
00500   m_actions.append( paAddBookmarksList );
00501 }
00502 
00503 void KBookmarkMenu::addAddBookmark()
00504 {
00505   if (!kapp->authorizeKAction("bookmarks"))
00506      return;
00507 
00508   QString title = i18n( "&Add Bookmark" );
00509   int p;
00510   while ( ( p = title.find( '&' ) ) >= 0 )
00511     title.remove( p, 1 );
00512 
00513   KAction * paAddBookmarks = new KAction( title,
00514                                           "bookmark_add",
00515                                           m_bIsRoot && m_bAddShortcuts ? KStdAccel::addBookmark() : KShortcut(),
00516                                           this,
00517                                           SLOT( slotAddBookmark() ),
00518                                           m_actionCollection, m_bIsRoot ? "add_bookmark" : 0 );
00519 
00520   paAddBookmarks->setToolTip( i18n( "Add a bookmark for the current document" ) );
00521 
00522   paAddBookmarks->plug( m_parentMenu );
00523   m_actions.append( paAddBookmarks );
00524 }
00525 
00526 void KBookmarkMenu::addEditBookmarks()
00527 {
00528   if (!kapp->authorizeKAction("bookmarks"))
00529      return;
00530 
00531   KAction * m_paEditBookmarks = KStdAction::editBookmarks( m_pManager, SLOT( slotEditBookmarks() ),
00532                                                              m_actionCollection, "edit_bookmarks" );
00533   m_paEditBookmarks->plug( m_parentMenu );
00534   m_paEditBookmarks->setToolTip( i18n( "Edit your bookmark collection in a separate window" ) );
00535   m_actions.append( m_paEditBookmarks );
00536 }
00537 
00538 void KBookmarkMenu::addNewFolder()
00539 {
00540   if (!kapp->authorizeKAction("bookmarks"))
00541      return;
00542 
00543   QString title = i18n( "&New Bookmark Folder..." );
00544   int p;
00545   while ( ( p = title.find( '&' ) ) >= 0 )
00546     title.remove( p, 1 );
00547 
00548   KAction * paNewFolder = new KAction( title,
00549                                        "folder_new", //"folder",
00550                                        0,
00551                                        this,
00552                                        SLOT( slotNewFolder() ),
00553                                        m_actionCollection );
00554 
00555   paNewFolder->setToolTip( i18n( "Create a new bookmark folder in this menu" ) );
00556 
00557   paNewFolder->plug( m_parentMenu );
00558   m_actions.append( paNewFolder );
00559 }
00560 
00561 void KBookmarkMenu::fillBookmarkMenu()
00562 {
00563   if (!kapp->authorizeKAction("bookmarks"))
00564      return;
00565 
00566   if ( m_bIsRoot )
00567   {
00568     if ( m_bAddBookmark )
00569     {
00570       addAddBookmark();
00571       if ( extOwner() )
00572         addAddBookmarksList(); // FIXME
00573     }
00574 
00575     addEditBookmarks();
00576 
00577     if ( m_bAddBookmark && !KBookmarkSettings::self()->m_advancedaddbookmark )
00578       addNewFolder();
00579   }
00580 
00581   if ( m_bIsRoot
00582     && KBookmarkManager::userBookmarksManager()->path() == m_pManager->path() )
00583   {
00584     bool haveSep = false;
00585 
00586     QValueList<QString> keys = KBookmarkMenu::dynamicBookmarksList();
00587     QValueList<QString>::const_iterator it;
00588     for ( it = keys.begin(); it != keys.end(); ++it )
00589     {
00590        DynMenuInfo info;
00591        info = showDynamicBookmarks((*it));
00592 
00593        if ( !info.show || !QFile::exists( info.location ) )
00594           continue;
00595 
00596        if (!haveSep)
00597        {
00598           m_parentMenu->insertSeparator();
00599           haveSep = true;
00600        }
00601 
00602        KActionMenu * actionMenu;
00603        actionMenu = new KImportedBookmarksActionMenu(
00604                               info.name, info.type,
00605                               m_actionCollection, "kbookmarkmenu" );
00606 
00607        actionMenu->setProperty( "type", info.type );
00608        actionMenu->setProperty( "location", info.location );
00609 
00610        actionMenu->plug( m_parentMenu );
00611        m_actions.append( actionMenu );
00612 
00613        KBookmarkMenu *subMenu =
00614           new KBookmarkMenu( m_pManager, m_pOwner, actionMenu->popupMenu(),
00615                              m_actionCollection, false,
00616                              m_bAddBookmark, QString::null );
00617        m_lstSubMenus.append(subMenu);
00618 
00619        connect(actionMenu->popupMenu(), SIGNAL(aboutToShow()), subMenu, SLOT(slotNSLoad()));
00620     }
00621   }
00622 
00623   KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup();
00624   Q_ASSERT(!parentBookmark.isNull());
00625   bool separatorInserted = false;
00626   for ( KBookmark bm = parentBookmark.first(); !bm.isNull();  bm = parentBookmark.next(bm) )
00627   {
00628     QString text = bm.text();
00629     text.replace( '&', "&&" );
00630     if ( !separatorInserted && m_bIsRoot) {
00631       // inserted before the first konq bookmark, to avoid the separator if no konq bookmark
00632       m_parentMenu->insertSeparator();
00633       separatorInserted = true;
00634     }
00635     if ( !bm.isGroup() )
00636     {
00637       if ( bm.isSeparator() )
00638       {
00639         m_parentMenu->insertSeparator();
00640       }
00641       else
00642       {
00643         //kdDebug(7043) << "Creating URL bookmark menu item for " << bm.text() << endl;
00644         KAction * action = new KBookmarkAction( text, bm.icon(), 0,
00645                                                 this, SLOT( slotBookmarkSelected() ),
00646                                                 m_actionCollection, 0 );
00647 
00648         action->setProperty( "url", bm.url().url() );
00649         action->setProperty( "address", bm.address() );
00650 
00651         action->setToolTip( bm.url().prettyURL() );
00652 
00653         action->plug( m_parentMenu );
00654         m_actions.append( action );
00655       }
00656     }
00657     else
00658     {
00659       //kdDebug(7043) << "Creating bookmark submenu named " << bm.text() << endl;
00660       KActionMenu * actionMenu = new KBookmarkActionMenu( text, bm.icon(),
00661                                                           m_actionCollection,
00662                                                           "kbookmarkmenu" );
00663       actionMenu->setProperty( "address", bm.address() );
00664       actionMenu->plug( m_parentMenu );
00665       m_actions.append( actionMenu );
00666 
00667       KBookmarkMenu *subMenu = new KBookmarkMenu( m_pManager, m_pOwner, actionMenu->popupMenu(),
00668                                                   m_actionCollection, false,
00669                                                   m_bAddBookmark,
00670                                                   bm.address() );
00671       connect(subMenu, SIGNAL( aboutToShowContextMenu(const KBookmark &, QPopupMenu * ) ),
00672                  this, SIGNAL( aboutToShowContextMenu(const KBookmark &, QPopupMenu * ) ));
00673       m_lstSubMenus.append( subMenu );
00674     }
00675   }
00676 
00677   if ( !m_bIsRoot && m_bAddBookmark )
00678   {
00679     if ( m_parentMenu->count() > 0 )
00680       m_parentMenu->insertSeparator();
00681 
00682     if ( KBookmarkSettings::self()->m_quickactions )
00683     {
00684       KActionMenu * actionMenu = new KActionMenu( i18n("Quick Actions"), m_actionCollection, 0L );
00685       fillContextMenu( actionMenu->popupMenu(), m_parentAddress, 1 );
00686       actionMenu->plug( m_parentMenu );
00687       m_actions.append( actionMenu );
00688     }
00689     else
00690     {
00691       addAddBookmark();
00692       if ( extOwner() )
00693         addAddBookmarksList(); // FIXME
00694       addNewFolder();
00695     }
00696   }
00697 }
00698 
00699 void KBookmarkMenu::slotAddBookmarksList()
00700 {
00701   KExtendedBookmarkOwner *extOwner = dynamic_cast<KExtendedBookmarkOwner*>(m_pOwner);
00702   if (!extOwner)
00703   {
00704     kdWarning() << "erm, sorry ;-)" << endl;
00705     return;
00706   }
00707 
00708   KExtendedBookmarkOwner::QStringPairList list;
00709   extOwner->fillBookmarksList( list );
00710 
00711   KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup();
00712   Q_ASSERT(!parentBookmark.isNull());
00713   KBookmarkGroup group = parentBookmark.createNewFolder( m_pManager );
00714   if ( group.isNull() )
00715     return; // user canceled i guess
00716 
00717   KExtendedBookmarkOwner::QStringPairList::const_iterator it;
00718   for ( it = list.begin(); it != list.end(); ++it )
00719     group.addBookmark( m_pManager, (*it).first, KURL((*it).second) );
00720 
00721   m_pManager->emitChanged( parentBookmark );
00722 }
00723 
00724 
00725 void KBookmarkMenu::slotAddBookmark()
00726 {
00727   KBookmarkGroup parentBookmark;
00728   parentBookmark = m_pManager->addBookmarkDialog(m_pOwner->currentURL(), m_pOwner->currentTitle(), m_parentAddress);
00729   if (!parentBookmark.isNull())
00730     m_pManager->emitChanged( parentBookmark );
00731 }
00732 
00733 void KBookmarkMenu::slotNewFolder()
00734 {
00735   if ( !m_pOwner ) return; // this view doesn't handle bookmarks...
00736   KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup();
00737   Q_ASSERT(!parentBookmark.isNull());
00738   KBookmarkGroup group = parentBookmark.createNewFolder( m_pManager );
00739   if ( !group.isNull() )
00740   {
00741     KBookmarkGroup parentGroup = group.parentGroup();
00742     m_pManager->emitChanged( parentGroup );
00743   }
00744 }
00745 
00746 void KBookmarkMenu::slotBookmarkSelected()
00747 {
00748   //kdDebug(7043) << "KBookmarkMenu::slotBookmarkSelected()" << endl;
00749   if ( !m_pOwner ) return; // this view doesn't handle bookmarks...
00750   m_pOwner->openBookmarkURL( sender()->property("url").toString() );
00751 }
00752 
00753 KExtendedBookmarkOwner* KBookmarkMenu::extOwner()
00754 {
00755   return dynamic_cast<KExtendedBookmarkOwner*>(m_pOwner);
00756 }
00757 
00758 void KBookmarkMenu::slotNSLoad()
00759 {
00760   // only fill menu once
00761   m_parentMenu->disconnect(SIGNAL(aboutToShow()));
00762 
00763   // not NSImporter, but kept old name for BC reasons
00764   KBookmarkMenuNSImporter importer( m_pManager, this, m_actionCollection );
00765   importer.openBookmarks(s_highlightedImportLocation, s_highlightedImportType);
00766 }
00767 
00768 /********************************************************************/
00769 /********************************************************************/
00770 /********************************************************************/
00771 
00772 KBookmarkEditFields::KBookmarkEditFields(QWidget *main, QBoxLayout *vbox, FieldsSet fieldsSet)
00773 {
00774   bool isF = (fieldsSet != FolderFieldsSet);
00775 
00776   QGridLayout *grid = new QGridLayout( vbox, 2, isF ? 2 : 1 );
00777 
00778   m_title = new KLineEdit( main );
00779   grid->addWidget( m_title, 0, 1 );
00780   grid->addWidget( new QLabel( m_title, i18n( "Name:" ), main ), 0, 0 );
00781   m_title->setFocus();
00782   if (isF)
00783   {
00784     m_url = new KLineEdit( main );
00785     grid->addWidget( m_url, 1, 1 );
00786     grid->addWidget( new QLabel( m_url, i18n( "Location:" ), main ), 1, 0 );
00787   }
00788   else
00789   {
00790     m_url = 0;
00791   }
00792   
00793   main->setMinimumSize( 300, 0 );
00794 }
00795 
00796 void KBookmarkEditFields::setName(const QString &str)
00797 {
00798   m_title->setText(str);
00799 }
00800 
00801 void KBookmarkEditFields::setLocation(const QString &str)
00802 {
00803   m_url->setText(str);
00804 }
00805 
00806 /********************************************************************/
00807 /********************************************************************/
00808 /********************************************************************/
00809 
00810 // TODO - make the dialog use Properties as a title when in Modify mode... (dirk noticed the bug...)
00811 KBookmarkEditDialog::KBookmarkEditDialog(const QString& title, const QString& url, KBookmarkManager * mgr, BookmarkEditType editType, const QString& address,
00812                                          QWidget * parent, const char * name, const QString& caption )
00813   : KDialogBase(parent, name, true, caption,
00814                 (editType == InsertionMode) ? (User1|Ok|Cancel) : (Ok|Cancel),
00815                 Ok, false, KGuiItem()),
00816     m_folderTree(0), m_mgr(mgr), m_editType(editType), m_address(address)
00817 {
00818   setButtonOK( (editType == InsertionMode) ? KGuiItem( i18n( "&Add" ), "bookmark_add") : i18n( "&Update" ) );
00819   if (editType == InsertionMode) {
00820     setButtonGuiItem( User1, KGuiItem( i18n( "&New Folder..." ), "folder_new") );
00821   }
00822 
00823   bool folder = url.isNull();
00824 
00825   m_main = new QWidget( this );
00826   setMainWidget( m_main );
00827 
00828   QBoxLayout *vbox = new QVBoxLayout( m_main, spacingHint() );
00829   KBookmarkEditFields::FieldsSet fs =
00830     folder ? KBookmarkEditFields::FolderFieldsSet
00831            : KBookmarkEditFields::BookmarkFieldsSet;
00832   m_fields = new KBookmarkEditFields(m_main, vbox, fs);
00833   m_fields->setName(title);
00834   if ( !folder )
00835     m_fields->setLocation(url);
00836 
00837   if ( editType == InsertionMode )
00838   {
00839     m_folderTree = KBookmarkFolderTree::createTree( m_mgr, m_main, name, m_address );
00840     connect( m_folderTree, SIGNAL( doubleClicked(QListViewItem*) ),
00841              this,         SLOT( slotDoubleClicked(QListViewItem*) ) );
00842     vbox->addWidget( m_folderTree );
00843     connect( this, SIGNAL( user1Clicked() ), SLOT( slotUser1() ) );
00844   }
00845 }
00846 
00847 void KBookmarkEditDialog::slotDoubleClicked( QListViewItem* item )
00848 {
00849   Q_ASSERT( m_folderTree );
00850   m_folderTree->setCurrentItem( item );
00851   accept();
00852 }
00853 
00854 void KBookmarkEditDialog::slotOk()
00855 {
00856   accept();
00857 }
00858 
00859 void KBookmarkEditDialog::slotCancel()
00860 {
00861   reject();
00862 }
00863 
00864 QString KBookmarkEditDialog::finalAddress() const
00865 {
00866   Q_ASSERT( m_folderTree );
00867   return KBookmarkFolderTree::selectedAddress( m_folderTree );
00868 }
00869 
00870 QString KBookmarkEditDialog::finalUrl() const
00871 {
00872   return m_fields->m_url ? m_fields->m_url->text() : QString::null;
00873 }
00874 
00875 QString KBookmarkEditDialog::finalTitle() const
00876 {
00877   return m_fields->m_title ? m_fields->m_title->text() : QString::null;
00878 }
00879 
00880 void KBookmarkEditDialog::slotUser1()
00881 {
00882   // kdDebug(7043) << "KBookmarkEditDialog::slotUser1" << endl;
00883   Q_ASSERT( m_folderTree );
00884 
00885   QString address = KBookmarkFolderTree::selectedAddress( m_folderTree );
00886   if ( address.isNull() ) return;
00887   KBookmarkGroup bm = m_mgr->findByAddress( address ).toGroup();
00888   Q_ASSERT(!bm.isNull());
00889   Q_ASSERT(m_editType == InsertionMode);
00890 
00891   KBookmarkGroup group = bm.createNewFolder( m_mgr );
00892   if ( !group.isNull() )
00893   {
00894     KBookmarkGroup parentGroup = group.parentGroup();
00895     m_mgr->emitChanged( parentGroup );
00896   }
00897   KBookmarkFolderTree::fillTree( m_folderTree, m_mgr );
00898 }
00899 
00900 /********************************************************************/
00901 /********************************************************************/
00902 /********************************************************************/
00903 
00904 static void fillGroup( QListView* listview, KBookmarkFolderTreeItem * parentItem, KBookmarkGroup group, bool expandOpenGroups = true, const QString& address = QString::null )
00905 {
00906   bool noSubGroups = true;
00907   KBookmarkFolderTreeItem * lastItem = 0L;
00908   KBookmarkFolderTreeItem * item = 0L;
00909   for ( KBookmark bk = group.first() ; !bk.isNull() ; bk = group.next(bk) )
00910   {
00911     if ( bk.isGroup() )
00912     {
00913       KBookmarkGroup grp = bk.toGroup();
00914       item = new KBookmarkFolderTreeItem( parentItem, lastItem, grp );
00915       fillGroup( listview, item, grp, expandOpenGroups, address );
00916       if ( expandOpenGroups && grp.isOpen() )
00917         item->setOpen( true );
00918       lastItem = item;
00919       noSubGroups = false;
00920     }
00921     if (bk.address() == address) {
00922       listview->setCurrentItem( lastItem );
00923       listview->ensureItemVisible( item );
00924     }
00925   }
00926   if ( noSubGroups ) {
00927      parentItem->setOpen( true );
00928   }
00929 }
00930 
00931 QListView* KBookmarkFolderTree::createTree( KBookmarkManager* mgr, QWidget* parent, const char* name, const QString& address )
00932 {
00933   QListView *listview = new QListView( parent, name );
00934 
00935   listview->setRootIsDecorated( false );
00936   listview->header()->hide();
00937   listview->addColumn( i18n("Bookmark"), 200 );
00938   listview->setSorting( -1, false );
00939   listview->setSelectionMode( QListView::Single );
00940   listview->setAllColumnsShowFocus( true );
00941   listview->setResizeMode( QListView::AllColumns );
00942   listview->setMinimumSize( 60, 100 );
00943 
00944   fillTree( listview, mgr, address );
00945 
00946   return listview;
00947 }
00948 
00949 void KBookmarkFolderTree::fillTree( QListView *listview, KBookmarkManager* mgr, const QString& address )
00950 {
00951   listview->clear();
00952 
00953   KBookmarkGroup root = mgr->root();
00954   KBookmarkFolderTreeItem * rootItem = new KBookmarkFolderTreeItem( listview, root );
00955   listview->setCurrentItem( rootItem );
00956   rootItem->setSelected( true );
00957   fillGroup( listview, rootItem, root, (address == root.groupAddress() || address == QString::null) ? true : false, address );
00958   rootItem->setOpen( true );
00959 }
00960 
00961 static KBookmarkFolderTreeItem* ft_cast( QListViewItem *i )
00962 {
00963   return static_cast<KBookmarkFolderTreeItem*>( i );
00964 }
00965 
00966 QString KBookmarkFolderTree::selectedAddress( QListView *listview )
00967 {
00968   if ( !listview)
00969     return QString::null;
00970   KBookmarkFolderTreeItem *item = ft_cast( listview->currentItem() );
00971   return item ? item->m_bookmark.address() : QString::null;
00972 }
00973 
00974 void KBookmarkFolderTree::setAddress( QListView *listview, const QString & address )
00975 {
00976   KBookmarkFolderTreeItem* it = ft_cast( listview->firstChild() );
00977   while ( true ) {
00978     kdDebug(7043) << it->m_bookmark.address() << endl;
00979     it = ft_cast( it->itemBelow() );
00980     if ( !it )
00981       return;
00982     if ( it->m_bookmark.address() == address )
00983       break;
00984   }
00985   it->setSelected( true );
00986   listview->setCurrentItem( it );
00987 }
00988 
00989 /********************************************************************/
00990 /********************************************************************/
00991 /********************************************************************/
00992 
00993 // toplevel item
00994 KBookmarkFolderTreeItem::KBookmarkFolderTreeItem( QListView *parent, const KBookmark & gp )
00995    : QListViewItem(parent, i18n("Bookmarks")), m_bookmark(gp)
00996 {
00997   setPixmap(0, SmallIcon("bookmark"));
00998   setExpandable(true);
00999 }
01000 
01001 // group
01002 KBookmarkFolderTreeItem::KBookmarkFolderTreeItem( KBookmarkFolderTreeItem *parent, QListViewItem *after, const KBookmarkGroup & gp )
01003    : QListViewItem(parent, after, gp.fullText()), m_bookmark(gp)
01004 {
01005   setPixmap(0, SmallIcon( gp.icon() ) );
01006   setExpandable(true);
01007 }
01008 
01009 /********************************************************************/
01010 /********************************************************************/
01011 /********************************************************************/
01012 
01013 // NOTE - KBookmarkMenuNSImporter is really === KBookmarkMenuImporter
01014 //        i.e, it is _not_ ns specific. and in KDE4 it should be renamed.
01015 
01016 void KBookmarkMenuNSImporter::openNSBookmarks()
01017 {
01018   openBookmarks( KNSBookmarkImporter::netscapeBookmarksFile(), "netscape" );
01019 }
01020 
01021 void KBookmarkMenuNSImporter::openBookmarks( const QString &location, const QString &type )
01022 {
01023   mstack.push(m_menu);
01024 
01025   KBookmarkImporterBase *importer = KBookmarkImporterBase::factory(type);
01026   if (!importer)
01027      return;
01028   importer->setFilename(location);
01029   connectToImporter(*importer);
01030   importer->parse();
01031 
01032   delete importer;
01033 }
01034 
01035 void KBookmarkMenuNSImporter::connectToImporter(const QObject &importer)
01036 {
01037   connect( &importer, SIGNAL( newBookmark( const QString &, const QCString &, const QString & ) ),
01038            SLOT( newBookmark( const QString &, const QCString &, const QString & ) ) );
01039   connect( &importer, SIGNAL( newFolder( const QString &, bool, const QString & ) ),
01040            SLOT( newFolder( const QString &, bool, const QString & ) ) );
01041   connect( &importer, SIGNAL( newSeparator() ), SLOT( newSeparator() ) );
01042   connect( &importer, SIGNAL( endFolder() ), SLOT( endFolder() ) );
01043 }
01044 
01045 void KBookmarkMenuNSImporter::newBookmark( const QString & text, const QCString & url, const QString & )
01046 {
01047   QString _text = text;
01048   _text.replace( '&', "&&" );
01049   KAction * action = new KBookmarkAction(_text, "html", 0,
01050                                          m_menu, SLOT( slotBookmarkSelected() ),
01051                                          m_actionCollection, 0);
01052   action->setProperty( "url", url );
01053   action->setToolTip( url );
01054   action->plug( mstack.top()->m_parentMenu );
01055   mstack.top()->m_actions.append( action );
01056 }
01057 
01058 void KBookmarkMenuNSImporter::newFolder( const QString & text, bool, const QString & )
01059 {
01060   QString _text = text;
01061   _text.replace( '&', "&&" );
01062   KActionMenu * actionMenu = new KActionMenu( _text, "folder", m_actionCollection, 0L );
01063   actionMenu->plug( mstack.top()->m_parentMenu );
01064   mstack.top()->m_actions.append( actionMenu );
01065   KBookmarkMenu *subMenu = new KBookmarkMenu( m_pManager, m_menu->m_pOwner, actionMenu->popupMenu(),
01066                                               m_actionCollection, false,
01067                                               m_menu->m_bAddBookmark, QString::null );
01068   mstack.top()->m_lstSubMenus.append( subMenu );
01069 
01070   mstack.push(subMenu);
01071 }
01072 
01073 void KBookmarkMenuNSImporter::newSeparator()
01074 {
01075   mstack.top()->m_parentMenu->insertSeparator();
01076 }
01077 
01078 void KBookmarkMenuNSImporter::endFolder()
01079 {
01080   mstack.pop();
01081 }
01082 
01083 /********************************************************************/
01084 /********************************************************************/
01085 /********************************************************************/
01086 
01087 KBookmarkMenu::DynMenuInfo KBookmarkMenu::showDynamicBookmarks( const QString &id )
01088 {
01089   KConfig config("kbookmarkrc", false, false);
01090   config.setGroup("Bookmarks");
01091 
01092   DynMenuInfo info;
01093   info.show = false;
01094 
01095   if (!config.hasKey("DynamicMenus")) {
01096     // upgrade path
01097     if (id == "netscape") {
01098       KBookmarkManager *manager = KBookmarkManager::userBookmarksManager();
01099       info.show = manager->root().internalElement().attribute("hide_nsbk") != "yes";
01100       info.location = KNSBookmarkImporter::netscapeBookmarksFile();
01101       info.type = "netscape";
01102       info.name = i18n("Netscape Bookmarks");
01103     } // else, no show
01104 
01105   } else {
01106     // have new version config
01107     if (config.hasGroup("DynamicMenu-" + id)) {
01108       config.setGroup("DynamicMenu-" + id);
01109       info.show = config.readBoolEntry("Show");
01110       info.location = config.readPathEntry("Location");
01111       info.type = config.readEntry("Type");
01112       info.name = config.readEntry("Name");
01113     } // else, no show
01114   }
01115 
01116   return info;
01117 }
01118 
01119 QStringList KBookmarkMenu::dynamicBookmarksList()
01120 {
01121   KConfig config("kbookmarkrc", false, false);
01122   config.setGroup("Bookmarks");
01123 
01124   QStringList mlist;
01125   if (config.hasKey("DynamicMenus"))
01126     mlist = config.readListEntry("DynamicMenus");
01127   else
01128     mlist << "netscape";
01129 
01130   return mlist;
01131 }
01132 
01133 void KBookmarkMenu::setDynamicBookmarks(const QString &id, const DynMenuInfo &newMenu)
01134 {
01135   KConfig config("kbookmarkrc", false, false);
01136 
01137   // add group unconditionally
01138   config.setGroup("DynamicMenu-" + id);
01139   config.writeEntry("Show", newMenu.show);
01140   config.writePathEntry("Location", newMenu.location);
01141   config.writeEntry("Type", newMenu.type);
01142   config.writeEntry("Name", newMenu.name);
01143 
01144   QStringList elist;
01145 
01146   config.setGroup("Bookmarks");
01147   if (!config.hasKey("DynamicMenus")) {
01148     if (newMenu.type != "netscape") {
01149       // update from old xbel method to new rc method
01150       // though only if not writing the netscape setting
01151       config.setGroup("DynamicMenu-" "netscape");
01152       DynMenuInfo xbelSetting;
01153       xbelSetting = showDynamicBookmarks("netscape");
01154       config.writeEntry("Show", xbelSetting.show);
01155       config.writePathEntry("Location", xbelSetting.location);
01156       config.writeEntry("Type", xbelSetting.type);
01157       config.writeEntry("Name", xbelSetting.name);
01158     }
01159   } else {
01160     elist = config.readListEntry("DynamicMenus");
01161   }
01162 
01163   // make sure list includes type
01164   config.setGroup("Bookmarks");
01165   if (elist.contains(id) < 1) {
01166     elist << id;
01167     config.writeEntry("DynamicMenus", elist);
01168   }
01169 
01170   config.sync();
01171 }
01172 
01173 #include "kbookmarkmenu.moc"
01174 #include "kbookmarkmenu_p.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Sep 23 17:12:21 2004 by doxygen 1.3.8-20040913 written by Dimitri van Heesch, © 1997-2003