kio Library API Documentation

kbookmarkmenu.cc

00001 // -*- mode: c++; c-basic-offset: 2 -*-
00002 /* This file is part of the KDE project
00003    Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 
00025 #include <assert.h>
00026 #include <dirent.h>
00027 #include <errno.h>
00028 #include <fcntl.h>
00029 #include <stddef.h>
00030 #include <stdlib.h>
00031 #include <unistd.h>
00032 
00033 #include "kbookmarkmenu.h"
00034 #include "kbookmarkimporter.h"
00035 
00036 #include <qfile.h>
00037 #include <qregexp.h>
00038 
00039 #include <kapplication.h>
00040 #include <kaction.h>
00041 #include <kdebug.h>
00042 #include <klocale.h>
00043 #include <kmessagebox.h>
00044 #include <kpopupmenu.h>
00045 #include <kstdaccel.h>
00046 #include <kstdaction.h>
00047 
00048 template class QPtrList<KBookmarkMenu>;
00049 
00050 /********************************************************************
00051  *
00052  * KBookmarkMenu
00053  *
00054  ********************************************************************/
00055 
00056 KBookmarkMenu::KBookmarkMenu( KBookmarkManager* mgr,
00057                               KBookmarkOwner * _owner, KPopupMenu * _parentMenu,
00058                               KActionCollection *collec, bool _isRoot, bool _add,
00059                               const QString & parentAddress )
00060   : m_bIsRoot(_isRoot), m_bAddBookmark(_add),
00061     m_pManager(mgr), m_pOwner(_owner),
00062     m_parentMenu( _parentMenu ),
00063     m_actionCollection( collec ),
00064     m_parentAddress( parentAddress )
00065 {
00066   m_parentMenu->setKeyboardShortcutsEnabled( true );
00067 
00068   m_lstSubMenus.setAutoDelete( true );
00069   m_actions.setAutoDelete( true );
00070 
00071   m_bNSBookmark = m_parentAddress.isNull();
00072   if ( !m_bNSBookmark ) // not for the netscape bookmark
00073   {
00074     //kdDebug(1203) << "KBookmarkMenu::KBookmarkMenu " << this << " address : " << m_parentAddress << endl;
00075 
00076     connect( _parentMenu, SIGNAL( aboutToShow() ),
00077              SLOT( slotAboutToShow() ) );
00078 
00079     if ( m_bIsRoot )
00080     {
00081       connect( m_pManager, SIGNAL( changed(const QString &, const QString &) ),
00082                SLOT( slotBookmarksChanged(const QString &) ) );
00083     }
00084   }
00085 
00086   // add entries that possibly have a shortcut, so they are available _before_ first popup
00087   if ( m_bIsRoot )
00088   {
00089     if ( m_bAddBookmark )
00090       addAddBookmark();
00091 
00092     addEditBookmarks();
00093   }
00094 
00095   m_bDirty = true;
00096 }
00097 
00098 KBookmarkMenu::~KBookmarkMenu()
00099 {
00100   //kdDebug(1203) << "KBookmarkMenu::~KBookmarkMenu() " << this << endl;
00101   QPtrListIterator<KAction> it( m_actions );
00102   for (; it.current(); ++it )
00103     it.current()->unplugAll();
00104 
00105   m_lstSubMenus.clear();
00106   m_actions.clear();
00107 }
00108 
00109 void KBookmarkMenu::ensureUpToDate()
00110 {
00111   slotAboutToShow();
00112 }
00113 
00114 
00115 void KBookmarkMenu::slotAboutToShow()
00116 {
00117   // Did the bookmarks change since the last time we showed them ?
00118   if ( m_bDirty )
00119   {
00120     m_bDirty = false;
00121     refill();
00122   }
00123 }
00124 
00125 void KBookmarkMenu::slotBookmarksChanged( const QString & groupAddress )
00126 {
00127   if (m_bNSBookmark)
00128     return;
00129 
00130   if ( groupAddress == m_parentAddress )
00131   {
00132     //kdDebug(1203) << "KBookmarkMenu::slotBookmarksChanged -> setting m_bDirty on " << groupAddress << endl;
00133     m_bDirty = true;
00134   }
00135   else
00136   {
00137     // Iterate recursively into child menus
00138     QPtrListIterator<KBookmarkMenu> it( m_lstSubMenus );
00139     for (; it.current(); ++it )
00140     {
00141       it.current()->slotBookmarksChanged( groupAddress );
00142     }
00143   }
00144 }
00145 
00146 void KBookmarkMenu::refill()
00147 {
00148   //kdDebug(1203) << "KBookmarkMenu::refill()" << endl;
00149   m_lstSubMenus.clear();
00150 
00151   QPtrListIterator<KAction> it( m_actions );
00152   for (; it.current(); ++it )
00153     it.current()->unplug( m_parentMenu );
00154 
00155   m_parentMenu->clear();
00156   m_actions.clear();
00157 
00158   fillBookmarkMenu();
00159   m_parentMenu->adjustSize();
00160 }
00161 
00162 void KBookmarkMenu::addAddBookmark()
00163 {
00164   if (!kapp->authorizeKAction("bookmarks"))
00165      return;
00166   
00167   QString title = i18n( "&Add Bookmark" );
00168   int p;
00169   while ( ( p = title.find( '&' ) ) >= 0 )
00170     title.remove( p, 1 );
00171 
00172   KAction * paAddBookmarks = new KAction( title,
00173                                           "bookmark_add",
00174                                           m_bIsRoot ? KStdAccel::addBookmark() : KShortcut(),
00175                                           this,
00176                                           SLOT( slotAddBookmark() ),
00177                                           m_actionCollection, m_bIsRoot ? "add_bookmark" : 0 );
00178 
00179   paAddBookmarks->setStatusText( i18n( "Add a bookmark for the current document" ) );
00180 
00181   paAddBookmarks->plug( m_parentMenu );
00182   m_actions.append( paAddBookmarks );
00183 }
00184 
00185 void KBookmarkMenu::addEditBookmarks()
00186 {
00187   if (!kapp->authorizeKAction("bookmarks"))
00188      return;
00189 
00190   KAction * m_paEditBookmarks = KStdAction::editBookmarks( m_pManager, SLOT( slotEditBookmarks() ),
00191                                                              m_actionCollection, "edit_bookmarks" );
00192   m_paEditBookmarks->plug( m_parentMenu );
00193   m_paEditBookmarks->setStatusText( i18n( "Edit your bookmark collection in a separate window" ) );
00194   m_actions.append( m_paEditBookmarks );
00195 }
00196 
00197 void KBookmarkMenu::addNewFolder()
00198 {
00199   if (!kapp->authorizeKAction("bookmarks"))
00200      return;
00201 
00202   QString title = i18n( "&New Bookmark Folder..." );
00203   int p;
00204   while ( ( p = title.find( '&' ) ) >= 0 )
00205     title.remove( p, 1 );
00206 
00207   KAction * paNewFolder = new KAction( title,
00208                                        "folder_new", //"folder",
00209                                        0,
00210                                        this,
00211                                        SLOT( slotNewFolder() ),
00212                                        m_actionCollection );
00213 
00214   paNewFolder->setStatusText( i18n( "Create a new bookmark folder in this menu" ) );
00215 
00216   paNewFolder->plug( m_parentMenu );
00217   m_actions.append( paNewFolder );
00218 }
00219 
00220 void KBookmarkMenu::fillBookmarkMenu()
00221 {
00222   if (!kapp->authorizeKAction("bookmarks"))
00223      return;
00224 
00225   if ( m_bIsRoot )
00226   {
00227     if ( m_bAddBookmark )
00228       addAddBookmark();
00229 
00230     addEditBookmarks();
00231 
00232     if ( m_bAddBookmark )
00233       addNewFolder();
00234 
00235     if ( m_pManager->showNSBookmarks()
00236          && QFile::exists( KNSBookmarkImporter::netscapeBookmarksFile() ) )
00237     {
00238       m_parentMenu->insertSeparator();
00239 
00240       KActionMenu * actionMenu = new KActionMenu( i18n("Netscape Bookmarks"), "netscape",
00241                                                   m_actionCollection, 0L );
00242       actionMenu->plug( m_parentMenu );
00243       m_actions.append( actionMenu );
00244       KBookmarkMenu *subMenu = new KBookmarkMenu( m_pManager, m_pOwner, actionMenu->popupMenu(),
00245                                                   m_actionCollection, false,
00246                                                   m_bAddBookmark, QString::null );
00247       m_lstSubMenus.append(subMenu);
00248       connect(actionMenu->popupMenu(), SIGNAL(aboutToShow()), subMenu, SLOT(slotNSLoad()));
00249     }
00250   }
00251 
00252   KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup();
00253   Q_ASSERT(!parentBookmark.isNull());
00254   bool separatorInserted = false;
00255   for ( KBookmark bm = parentBookmark.first(); !bm.isNull();  bm = parentBookmark.next(bm) )
00256   {
00257     QString text = bm.text();
00258     text.replace( QRegExp( "&" ), "&&" );
00259     if ( !separatorInserted && m_bIsRoot) { // inserted before the first konq bookmark, to avoid the separator if no konq bookmark
00260       m_parentMenu->insertSeparator();
00261       separatorInserted = true;
00262     }
00263     if ( !bm.isGroup() )
00264     {
00265       if ( bm.isSeparator() )
00266       {
00267         m_parentMenu->insertSeparator();
00268       }
00269       else
00270       {
00271         // kdDebug(1203) << "Creating URL bookmark menu item for " << bm.text() << endl;
00272         // create a normal URL item, with ID as a name
00273         KAction * action = new KAction( text, bm.icon(), 0,
00274                                         this, SLOT( slotBookmarkSelected() ),
00275                                         m_actionCollection, bm.url().url().utf8() );
00276 
00277         action->setStatusText( bm.url().prettyURL() );
00278 
00279         action->plug( m_parentMenu );
00280         m_actions.append( action );
00281       }
00282     }
00283     else
00284     {
00285       // kdDebug(1203) << "Creating bookmark submenu named " << bm.text() << endl;
00286       KActionMenu * actionMenu = new KActionMenu( text, bm.icon(),
00287                                                   m_actionCollection, 0L );
00288       actionMenu->plug( m_parentMenu );
00289       m_actions.append( actionMenu );
00290       KBookmarkMenu *subMenu = new KBookmarkMenu( m_pManager, m_pOwner, actionMenu->popupMenu(),
00291                                                   m_actionCollection, false,
00292                                                   m_bAddBookmark,
00293                                                   bm.address() );
00294       m_lstSubMenus.append( subMenu );
00295     }
00296   }
00297 
00298   if ( !m_bIsRoot && m_bAddBookmark )
00299   {
00300     if ( m_parentMenu->count() > 0 )
00301       m_parentMenu->insertSeparator();
00302     addAddBookmark();
00303     addNewFolder();
00304   }
00305 }
00306 
00307 void KBookmarkMenu::slotAddBookmark()
00308 {
00309   QString url = m_pOwner->currentURL();
00310   if (url.isEmpty())
00311   {
00312     KMessageBox::error( 0L, i18n("Can't add bookmark with empty URL"));
00313     return;
00314   }
00315   QString title = m_pOwner->currentTitle();
00316   if (title.isEmpty())
00317     title = url;
00318 
00319   KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup();
00320   Q_ASSERT(!parentBookmark.isNull());
00321   // If this title is already used, we'll try to find something unused.
00322   KBookmark ch = parentBookmark.first();
00323   int count = 1;
00324   QString uniqueTitle = title;
00325   do
00326   {
00327     while ( !ch.isNull() )
00328     {
00329       if ( uniqueTitle == ch.text() )
00330       {
00331         // Title already used !
00332         if ( url != ch.url().url() )
00333         {
00334           uniqueTitle = title + QString(" (%1)").arg(++count);
00335           // New title -> restart search from the beginning
00336           ch = parentBookmark.first();
00337           break;
00338         }
00339         else
00340         {
00341           // this exact URL already exists
00342           return;
00343         }
00344       }
00345       ch = parentBookmark.next( ch );
00346     }
00347   } while ( !ch.isNull() );
00348 
00349   parentBookmark.addBookmark( m_pManager, uniqueTitle, url );
00350   m_pManager->emitChanged( parentBookmark );
00351 }
00352 
00353 void KBookmarkMenu::slotNewFolder()
00354 {
00355   if ( !m_pOwner ) return; // this view doesn't handle bookmarks...
00356   KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup();
00357   Q_ASSERT(!parentBookmark.isNull());
00358   KBookmarkGroup group = parentBookmark.createNewFolder( m_pManager );
00359   if ( !group.isNull() )
00360   {
00361     KBookmarkGroup parentGroup = group.parentGroup();
00362     m_pManager->emitChanged( parentGroup );
00363   }
00364 }
00365 
00366 void KBookmarkMenu::slotBookmarkSelected()
00367 {
00368   //kdDebug(1203) << "KBookmarkMenu::slotBookmarkSelected()" << endl;
00369   if ( !m_pOwner ) return; // this view doesn't handle bookmarks...
00370   //kdDebug(1203) << sender()->name() << endl;
00371 
00372   // The name of the action is the URL to open
00373   m_pOwner->openBookmarkURL( QString::fromUtf8(sender()->name()) );
00374 }
00375 
00376 // -----------------------------------------------------------------------------
00377 
00378 void KBookmarkMenu::slotNSBookmarkSelected()
00379 {
00380     QString link(sender()->name()+8);
00381 
00382     m_pOwner->openBookmarkURL( link );
00383 }
00384 
00385 void KBookmarkMenu::slotNSLoad()
00386 {
00387   m_parentMenu->disconnect(SIGNAL(aboutToShow()));
00388 
00389   KBookmarkMenuNSImporter importer( m_pManager, this, m_actionCollection );
00390   importer.openNSBookmarks();
00391 }
00392 
00393 void KBookmarkMenuNSImporter::openNSBookmarks()
00394 {
00395   mstack.push(m_menu);
00396   KNSBookmarkImporter importer( KNSBookmarkImporter::netscapeBookmarksFile() );
00397   connect( &importer, SIGNAL( newBookmark( const QString &, const QCString &, const QString & ) ),
00398            SLOT( newBookmark( const QString &, const QCString &, const QString & ) ) );
00399   connect( &importer, SIGNAL( newFolder( const QString &, bool, const QString & ) ),
00400            SLOT( newFolder( const QString &, bool, const QString & ) ) );
00401   connect( &importer, SIGNAL( newSeparator() ), SLOT( newSeparator() ) );
00402   connect( &importer, SIGNAL( endFolder() ), SLOT( endFolder() ) );
00403   importer.parseNSBookmarks();
00404 }
00405 
00406 void KBookmarkMenuNSImporter::newBookmark( const QString & text, const QCString & url, const QString & )
00407 {
00408   QCString actionLink = "bookmark" + url;
00409   QString _text = text;
00410   _text.replace( QRegExp( "&" ), "&&" );
00411   KAction * action = new KAction( _text, "html", 0, m_menu, SLOT( slotNSBookmarkSelected() ),
00412                                   m_actionCollection, actionLink.data());
00413   action->setStatusText( url );
00414   action->plug( mstack.top()->m_parentMenu );
00415   mstack.top()->m_actions.append( action );
00416 }
00417 
00418 void KBookmarkMenuNSImporter::newFolder( const QString & text, bool, const QString & )
00419 {
00420   QString _text = text;
00421   _text.replace( QRegExp( "&" ), "&&" );
00422   KActionMenu * actionMenu = new KActionMenu( _text, "folder", m_actionCollection, 0L );
00423   actionMenu->plug( mstack.top()->m_parentMenu );
00424   mstack.top()->m_actions.append( actionMenu );
00425   KBookmarkMenu *subMenu = new KBookmarkMenu( m_pManager, m_menu->m_pOwner, actionMenu->popupMenu(),
00426                                               m_actionCollection, false,
00427                                               m_menu->m_bAddBookmark, QString::null );
00428   mstack.top()->m_lstSubMenus.append( subMenu );
00429 
00430   mstack.push(subMenu);
00431 }
00432 
00433 void KBookmarkMenuNSImporter::newSeparator()
00434 {
00435   mstack.top()->m_parentMenu->insertSeparator();
00436 }
00437 
00438 void KBookmarkMenuNSImporter::endFolder()
00439 {
00440   mstack.pop();
00441 }
00442 
00443 #include "kbookmarkmenu.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:21:28 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001