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