• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • libkonq
 

libkonq

konq_popupmenu.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999 David Faure <faure@kde.org>
00003    Copyright (C) 2001 Holger Freyther <freyther@yahoo.com>
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., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include <tqdir.h>
00022 
00023 #include <klocale.h>
00024 #include <kapplication.h>
00025 #include <kbookmarkmanager.h>
00026 #include <kdebug.h>
00027 #include <krun.h>
00028 #include <kprotocolinfo.h>
00029 #include <kiconloader.h>
00030 #include <kinputdialog.h>
00031 #include <kglobalsettings.h>
00032 #include <kstandarddirs.h>
00033 #include <kxmlguifactory.h>
00034 #include <kxmlguibuilder.h>
00035 #include <kparts/componentfactory.h>
00036 
00037 #include <assert.h>
00038 
00039 #include <kfileshare.h>
00040 #include <kprocess.h>
00041 
00042 #include "kpropertiesdialog.h"
00043 #include "knewmenu.h"
00044 #include "konq_popupmenu.h"
00045 #include "konq_operations.h"
00046 #include "konq_xmlguiclient.h"
00047 #include <dcopclient.h>
00048 
00049 /*
00050  Test cases:
00051   iconview file: background
00052   iconview file: file (with and without servicemenus)
00053   iconview file: directory
00054   iconview remote protocol (e.g. ftp: or fish:)
00055   iconview trash:/
00056   sidebar directory tree
00057   sidebar Devices / Hard Disc
00058   khtml background
00059   khtml link
00060   khtml image (www.kde.org RMB on K logo)
00061   khtmlimage (same as above, then choose View image, then RMB)
00062   selected text in khtml
00063   embedded katepart
00064   kdesktop folder
00065   trash link on desktop
00066   trashed file or directory
00067   application .desktop file
00068  Then the same after uninstalling kdeaddons/konq-plugins (kuick and arkplugin in particular)
00069 */
00070 
00071 class KonqPopupMenuGUIBuilder : public KXMLGUIBuilder
00072 {
00073 public:
00074   KonqPopupMenuGUIBuilder( TQPopupMenu *menu )
00075   : KXMLGUIBuilder( 0 )
00076   {
00077     m_menu = menu;
00078   }
00079   virtual ~KonqPopupMenuGUIBuilder()
00080   {
00081   }
00082 
00083   virtual TQWidget *createContainer( TQWidget *parent, int index,
00084           const TQDomElement &element,
00085           int &id )
00086   {
00087     if ( !parent && element.attribute( "name" ) == "popupmenu" )
00088       return m_menu;
00089 
00090     return KXMLGUIBuilder::createContainer( parent, index, element, id );
00091   }
00092 
00093   TQPopupMenu *m_menu;
00094 };
00095 
00096 class KonqPopupMenu::KonqPopupMenuPrivate
00097 {
00098 public:
00099   KonqPopupMenuPrivate() : m_parentWidget( 0 ),
00100                            m_itemFlags( KParts::BrowserExtension::DefaultPopupItems )
00101   {
00102   }
00103   TQString m_urlTitle;
00104   TQWidget *m_parentWidget;
00105   KParts::BrowserExtension::PopupFlags m_itemFlags;
00106 };
00107 
00108 KonqPopupMenu::ProtocolInfo::ProtocolInfo()
00109 {
00110   m_Reading = false;
00111   m_Writing = false;
00112   m_Deleting = false;
00113   m_Moving = false;
00114   m_TrashIncluded = false;
00115 }
00116 
00117 bool KonqPopupMenu::ProtocolInfo::supportsReading() const
00118 {
00119   return m_Reading;
00120 }
00121 
00122 bool KonqPopupMenu::ProtocolInfo::supportsWriting() const
00123 {
00124   return m_Writing;
00125 }
00126 
00127 bool KonqPopupMenu::ProtocolInfo::supportsDeleting() const
00128 {
00129   return m_Deleting;
00130 }
00131 
00132 bool KonqPopupMenu::ProtocolInfo::supportsMoving() const
00133 {
00134   return m_Moving;
00135 }
00136 
00137 bool KonqPopupMenu::ProtocolInfo::trashIncluded() const
00138 {
00139   return m_TrashIncluded;
00140 }
00141 
00142 // This helper class stores the .desktop-file actions and the servicemenus
00143 // in order to support X-KDE-Priority and X-KDE-Submenu.
00144 class PopupServices
00145 {
00146 public:
00147     ServiceList* selectList( const TQString& priority, const TQString& submenuName );
00148 
00149     ServiceList builtin;
00150     ServiceList user, userToplevel, userPriority;
00151     TQMap<TQString, ServiceList> userSubmenus, userToplevelSubmenus, userPrioritySubmenus;
00152 };
00153 
00154 ServiceList* PopupServices::selectList( const TQString& priority, const TQString& submenuName )
00155 {
00156     // we use the categories .desktop entry to define submenus
00157     // if none is defined, we just pop it in the main menu
00158     if (submenuName.isEmpty())
00159     {
00160         if (priority == "TopLevel")
00161         {
00162             return &userToplevel;
00163         }
00164         else if (priority == "Important")
00165         {
00166             return &userPriority;
00167         }
00168     }
00169     else if (priority == "TopLevel")
00170     {
00171         return &(userToplevelSubmenus[submenuName]);
00172     }
00173     else if (priority == "Important")
00174     {
00175         return &(userPrioritySubmenus[submenuName]);
00176     }
00177     else
00178     {
00179         return &(userSubmenus[submenuName]);
00180     }
00181     return &user;
00182 }
00183 
00185 
00186 KonqPopupMenu::KonqPopupMenu( KBookmarkManager *mgr, const KFileItemList &items,
00187                               KURL viewURL,
00188                               KActionCollection & actions,
00189                               KNewMenu * newMenu,
00190                               bool showProperties )
00191     : TQPopupMenu( 0L, "konq_popupmenu" ),
00192       m_actions( actions ), m_ownActions( static_cast<TQWidget *>( 0 ), "KonqPopupMenu::m_ownActions" ),
00193           m_pMenuNew( newMenu ), m_sViewURL(viewURL), m_lstItems(items), m_pManager(mgr)
00194 {
00195     KonqPopupFlags kpf = ( showProperties ? ShowProperties : IsLink ) | ShowNewWindow;
00196     init(0, kpf, KParts::BrowserExtension::DefaultPopupItems);
00197 }
00198 
00199 KonqPopupMenu::KonqPopupMenu( KBookmarkManager *mgr, const KFileItemList &items,
00200                               KURL viewURL,
00201                               KActionCollection & actions,
00202                               KNewMenu * newMenu,
00203                               TQWidget * parentWidget,
00204                               bool showProperties )
00205     : TQPopupMenu( parentWidget, "konq_popupmenu" ), m_actions( actions ), m_ownActions( static_cast<TQWidget *>( 0 ), "KonqPopupMenu::m_ownActions" ), m_pMenuNew( newMenu ), m_sViewURL(viewURL), m_lstItems(items), m_pManager(mgr)
00206 {
00207     KonqPopupFlags kpf = ( showProperties ? ShowProperties : IsLink ) | ShowNewWindow;
00208     init(parentWidget, kpf, KParts::BrowserExtension::DefaultPopupItems);
00209 }
00210 
00211 KonqPopupMenu::KonqPopupMenu( KBookmarkManager *mgr, const KFileItemList &items,
00212                               const KURL& viewURL,
00213                               KActionCollection & actions,
00214                               KNewMenu * newMenu,
00215                               TQWidget * parentWidget,
00216                               KonqPopupFlags kpf,
00217                               KParts::BrowserExtension::PopupFlags flags)
00218   : TQPopupMenu( parentWidget, "konq_popupmenu" ), m_actions( actions ), m_ownActions( static_cast<TQWidget *>( 0 ), "KonqPopupMenu::m_ownActions" ), m_pMenuNew( newMenu ), m_sViewURL(viewURL), m_lstItems(items), m_pManager(mgr)
00219 {
00220     init(parentWidget, kpf, flags);
00221 }
00222 
00223 void KonqPopupMenu::init (TQWidget * parentWidget, KonqPopupFlags kpf, KParts::BrowserExtension::PopupFlags flags)
00224 {
00225     d = new KonqPopupMenuPrivate;
00226     d->m_parentWidget = parentWidget;
00227     d->m_itemFlags = flags;
00228     setup(kpf);
00229 }
00230 
00231 int KonqPopupMenu::insertServicesSubmenus(const TQMap<TQString, ServiceList>& submenus,
00232                                           TQDomElement& menu,
00233                                           bool isBuiltin)
00234 {
00235     int count = 0;
00236     TQMap<TQString, ServiceList>::ConstIterator it;
00237 
00238     for (it = submenus.begin(); it != submenus.end(); ++it)
00239     {
00240         if (it.data().isEmpty())
00241         {
00242             //avoid empty sub-menus
00243             continue;
00244         }
00245 
00246         TQDomElement actionSubmenu = m_doc.createElement( "menu" );
00247         actionSubmenu.setAttribute( "name", "actions " + it.key() );
00248         menu.appendChild( actionSubmenu );
00249         TQDomElement subtext = m_doc.createElement( "text" );
00250         actionSubmenu.appendChild( subtext );
00251         subtext.appendChild( m_doc.createTextNode( it.key() ) );
00252         count += insertServices(it.data(), actionSubmenu, isBuiltin);
00253     }
00254 
00255     return count;
00256 }
00257 
00258 int KonqPopupMenu::insertServices(const ServiceList& list,
00259                                   TQDomElement& menu,
00260                                   bool isBuiltin)
00261 {
00262     static int id = 1000;
00263     int count = 0;
00264 
00265     ServiceList::const_iterator it = list.begin();
00266     for( ; it != list.end(); ++it )
00267     {
00268         if ((*it).isEmpty())
00269         {
00270             if (!menu.firstChild().isNull() &&
00271                 menu.lastChild().toElement().tagName().lower() != "separator")
00272             {
00273                 TQDomElement separator = m_doc.createElement( "separator" );
00274                 menu.appendChild(separator);
00275             }
00276             continue;
00277         }
00278 
00279         if (isBuiltin || (*it).m_display == true)
00280         {
00281             TQCString name;
00282             name.setNum( id );
00283             name.prepend( isBuiltin ? "builtinservice_" : "userservice_" );
00284             KAction * act = new KAction( TQString((*it).m_strName).replace('&',"&&"), 0,
00285                                          TQT_TQOBJECT(this), TQT_SLOT( slotRunService() ),
00286                                          &m_ownActions, name );
00287 
00288             if ( !(*it).m_strIcon.isEmpty() )
00289             {
00290                 TQPixmap pix = SmallIcon( (*it).m_strIcon );
00291                 act->setIconSet( pix );
00292             }
00293 
00294             addAction( act, menu ); // Add to toplevel menu
00295 
00296             m_mapPopupServices[ id++ ] = *it;
00297             ++count;
00298         }
00299     }
00300 
00301     return count;
00302 }
00303 
00304 bool KonqPopupMenu::KIOSKAuthorizedAction(KConfig& cfg)
00305 {
00306     if ( !cfg.hasKey( "X-KDE-AuthorizeAction") )
00307     {
00308         return true;
00309     }
00310 
00311     TQStringList list = cfg.readListEntry("X-KDE-AuthorizeAction");
00312     if (kapp && !list.isEmpty())
00313     {
00314         for(TQStringList::ConstIterator it = list.begin();
00315             it != list.end();
00316             ++it)
00317         {
00318             if (!kapp->authorize((*it).stripWhiteSpace()))
00319             {
00320                 return false;
00321             }
00322         }
00323     }
00324 
00325     return true;
00326 }
00327 
00328 
00329 void KonqPopupMenu::setup(KonqPopupFlags kpf)
00330 {
00331     assert( m_lstItems.count() >= 1 );
00332 
00333     m_ownActions.setWidget( this );
00334 
00335     const bool bIsLink  = (kpf & IsLink);
00336     bool currentDir     = false;
00337     bool sReading       = true;
00338     bool sDeleting      = ( d->m_itemFlags & KParts::BrowserExtension::NoDeletion ) == 0;
00339     bool sMoving        = sDeleting;
00340     bool sWriting       = sDeleting && m_lstItems.first()->isWritable();
00341     m_sMimeType         = m_lstItems.first()->mimetype();
00342     TQString mimeGroup   = m_sMimeType.left(m_sMimeType.find('/'));
00343     mode_t mode         = m_lstItems.first()->mode();
00344     bool isDirectory    = S_ISDIR(mode);
00345     bool bTrashIncluded = false;
00346     bool mediaFiles     = false;
00347     bool isReallyLocal = m_lstItems.first()->isLocalFile();
00348     bool isLocal        = isReallyLocal
00349                        || m_lstItems.first()->url().protocol()=="media"
00350                        || m_lstItems.first()->url().protocol()=="system";
00351     bool isTrashLink     = false;
00352     m_lstPopupURLs.clear();
00353     int id = 0;
00354     setFont(KGlobalSettings::menuFont());
00355     m_pluginList.setAutoDelete( true );
00356     m_ownActions.setHighlightingEnabled( true );
00357 
00358     attrName = TQString::fromLatin1( "name" );
00359 
00360     prepareXMLGUIStuff();
00361     m_builder = new KonqPopupMenuGUIBuilder( this );
00362     m_factory = new KXMLGUIFactory( m_builder );
00363 
00364     KURL url;
00365     KFileItemListIterator it ( m_lstItems );
00366     TQStringList mimeTypeList;
00367     // Check whether all URLs are correct
00368     for ( ; it.current(); ++it )
00369     {
00370         url = (*it)->url();
00371 
00372         // Build the list of URLs
00373         m_lstPopupURLs.append( url );
00374 
00375         // Determine if common mode among all URLs
00376         if ( mode != (*it)->mode() )
00377             mode = 0; // modes are different => reset to 0
00378 
00379         // Determine if common mimetype among all URLs
00380         if ( m_sMimeType != (*it)->mimetype() )
00381         {
00382             m_sMimeType = TQString::null; // mimetypes are different => null
00383 
00384             if ( mimeGroup != (*it)->mimetype().left((*it)->mimetype().find('/')))
00385                 mimeGroup = TQString::null; // mimetype groups are different as well!
00386         }
00387 
00388         if ( mimeTypeList.findIndex( (*it)->mimetype() ) == -1 )
00389             mimeTypeList << (*it)->mimetype();
00390 
00391         if ( isReallyLocal && !url.isLocalFile() )
00392             isReallyLocal = false;
00393         if ( isLocal && !url.isLocalFile() && url.protocol() != "media" && url.protocol() != "system" )
00394             isLocal = false;
00395 
00396         if ( !bTrashIncluded && (
00397              ( url.protocol() == "trash" && url.path().length() <= 1 )
00398              || url.url() == "system:/trash" || url.url() == "system:/trash/" ) ) {
00399             bTrashIncluded = true;
00400             isLocal = false;
00401         }
00402 
00403         if ( sReading )
00404             sReading = KProtocolInfo::supportsReading( url );
00405 
00406         if ( sWriting )
00407             sWriting = KProtocolInfo::supportsWriting( url ) && (*it)->isWritable();
00408 
00409         if ( sDeleting )
00410             sDeleting = KProtocolInfo::supportsDeleting( url );
00411 
00412         if ( sMoving )
00413             sMoving = KProtocolInfo::supportsMoving( url );
00414         if ( (*it)->mimetype().startsWith("media/") )
00415             mediaFiles = true;
00416     }
00417     url = m_sViewURL;
00418     url.cleanPath();
00419 
00420     //check if url is current directory
00421     if ( m_lstItems.count() == 1 )
00422     {
00423         KURL firstPopupURL( m_lstItems.first()->url() );
00424         firstPopupURL.cleanPath();
00425         //kdDebug(1203) << "View path is " << url.url() << endl;
00426         //kdDebug(1203) << "First popup path is " << firstPopupURL.url() << endl;
00427         currentDir = firstPopupURL.equals( url, true /* ignore_trailing */ );
00428         if ( isLocal && ((m_sMimeType == "application/x-desktop")
00429                       || (m_sMimeType == "media/builtin-mydocuments")
00430                       || (m_sMimeType == "media/builtin-mycomputer")
00431                       || (m_sMimeType == "media/builtin-mynetworkplaces")
00432                       || (m_sMimeType == "media/builtin-printers")
00433                       || (m_sMimeType == "media/builtin-trash")
00434                       || (m_sMimeType == "media/builtin-webbrowser")) ) {
00435             KSimpleConfig cfg( firstPopupURL.path(), true );
00436             cfg.setDesktopGroup();
00437             isTrashLink = ( cfg.readEntry("Type") == "Link" && cfg.readEntry("URL") == "trash:/" );
00438         }
00439 
00440         if ( isTrashLink ) {
00441             sDeleting = false;
00442         }
00443     }
00444 
00445     m_info.m_Reading = sReading;
00446     m_info.m_Writing = sWriting;
00447     m_info.m_Deleting = sDeleting;
00448     m_info.m_Moving = sMoving;
00449     m_info.m_TrashIncluded = bTrashIncluded;
00450 
00451     // isCurrentTrash: popup on trash:/ itself, or on the trash.desktop link
00452     bool isCurrentTrash = ( m_lstItems.count() == 1 && bTrashIncluded ) || isTrashLink;
00453     bool isIntoTrash = ( url.protocol() == "trash" || url.url().startsWith( "system:/trash" ) ) && !isCurrentTrash; // trashed file, not trash:/ itself
00454     //kdDebug() << "isLocal=" << isLocal << " url=" << url << " isCurrentTrash=" << isCurrentTrash << " isIntoTrash=" << isIntoTrash << " bTrashIncluded=" << bTrashIncluded << endl;
00455     bool isSingleMedium = m_lstItems.count() == 1 && mediaFiles;
00456     clear();
00457 
00459 
00460     KAction * act;
00461 
00462     if (!isCurrentTrash)
00463         addMerge( "konqueror" );
00464 
00465     bool isKDesktop = TQCString( kapp->name() ) == "kdesktop";
00466     KAction *actNewWindow = 0;
00467 
00468     if (( kpf & ShowProperties ) && isKDesktop &&
00469         !kapp->authorize("editable_desktop_icons"))
00470     {
00471         kpf &= ~ShowProperties; // remove flag
00472     }
00473 
00474     // Either 'newview' is in the actions we're given (probably in the tabhandling group)
00475     // or we need to insert it ourselves (e.g. for kdesktop). In the first case, actNewWindow must remain 0.
00476     if ( ((kpf & ShowNewWindow) != 0) && sReading )
00477     {
00478         TQString openStr = isKDesktop ? i18n( "&Open" ) : i18n( "Open in New &Window" );
00479         actNewWindow = new KAction( openStr, "window_new", 0, TQT_TQOBJECT(this), TQT_SLOT( slotPopupNewView() ), &m_ownActions, "newview" );
00480     }
00481 
00482     if ( actNewWindow && !isKDesktop )
00483     {
00484         if (isCurrentTrash)
00485             actNewWindow->setToolTip( i18n( "Open the trash in a new window" ) );
00486         else if (isSingleMedium)
00487             actNewWindow->setToolTip( i18n( "Open the medium in a new window") );
00488         else
00489             actNewWindow->setToolTip( i18n( "Open the document in a new window" ) );
00490     }
00491 
00492     if ( S_ISDIR(mode) && sWriting && !isCurrentTrash ) // A dir, and we can create things into it
00493     {
00494         if ( currentDir && m_pMenuNew ) // Current dir -> add the "new" menu
00495         {
00496             // As requested by KNewMenu :
00497             m_pMenuNew->slotCheckUpToDate();
00498             m_pMenuNew->setPopupFiles( m_lstPopupURLs );
00499 
00500             addAction( m_pMenuNew );
00501 
00502             addSeparator();
00503         }
00504         else
00505         {
00506             if (d->m_itemFlags & KParts::BrowserExtension::ShowCreateDirectory)
00507             {
00508                 KAction *actNewDir = new KAction( i18n( "Create &Folder..." ), "folder_new", 0, TQT_TQOBJECT(this), TQT_SLOT( slotPopupNewDir() ), &m_ownActions, "newdir" );
00509                 addAction( actNewDir );
00510                 addSeparator();
00511             }
00512         }
00513     } else if ( isIntoTrash ) {
00514         // Trashed item, offer restoring
00515         act = new KAction( i18n( "&Restore" ), 0, TQT_TQOBJECT(this), TQT_SLOT( slotPopupRestoreTrashedItems() ), &m_ownActions, "restore" );
00516         addAction( act );
00517     }
00518 
00519     if (d->m_itemFlags & KParts::BrowserExtension::ShowNavigationItems)
00520     {
00521         if (d->m_itemFlags & KParts::BrowserExtension::ShowUp)
00522             addAction( "up" );
00523         addAction( "back" );
00524         addAction( "forward" );
00525         if (d->m_itemFlags & KParts::BrowserExtension::ShowReload)
00526             addAction( "reload" );
00527         addSeparator();
00528     }
00529 
00530     // "open in new window" is either provided by us, or by the tabhandling group
00531     if (actNewWindow)
00532     {
00533         addAction( actNewWindow );
00534         addSeparator();
00535     }
00536     addGroup( "tabhandling" ); // includes a separator
00537 
00538     if ( !bIsLink )
00539     {
00540         if ( !currentDir && sReading ) {
00541             if ( sDeleting ) {
00542                 addAction( "cut" );
00543             }
00544             addAction( "copy" );
00545         }
00546 
00547         if ( S_ISDIR(mode) && sWriting ) {
00548             if ( currentDir )
00549                 addAction( "paste" );
00550             else
00551                 addAction( "pasteto" );
00552         }
00553         if ( !currentDir )
00554         {
00555             if ( m_lstItems.count() == 1 && sMoving )
00556                 addAction( "rename" );
00557 
00558             bool addTrash = false;
00559             bool addDel = false;
00560 
00561             if ( sMoving && !isIntoTrash && !isTrashLink )
00562                 addTrash = true;
00563 
00564             if ( sDeleting ) {
00565                 if ( !isLocal )
00566                     addDel = true;
00567                 else if (KApplication::keyboardMouseState() & TQt::ShiftButton) {
00568                     addTrash = false;
00569                     addDel = true;
00570                 }
00571                 else {
00572                     KConfigGroup configGroup( kapp->config(), "KDE" );
00573                     if ( configGroup.readBoolEntry( "ShowDeleteCommand", false ) )
00574                         addDel = true;
00575                 }
00576             }
00577 
00578             if ( addTrash )
00579                 addAction( "trash" );
00580             if ( addDel )
00581                 addAction( "del" );
00582         }
00583     }
00584     if ( isCurrentTrash )
00585     {
00586         act = new KAction( i18n( "&Empty Trash Bin" ), "emptytrash", 0, TQT_TQOBJECT(this), TQT_SLOT( slotPopupEmptyTrashBin() ), &m_ownActions, "empytrash" );
00587         KSimpleConfig trashConfig( "trashrc", true );
00588         trashConfig.setGroup( "Status" );
00589         act->setEnabled( !trashConfig.readBoolEntry( "Empty", true ) );
00590         addAction( act );
00591     }
00592     addGroup( "editactions" );
00593 
00594     if (d->m_itemFlags & KParts::BrowserExtension::ShowTextSelectionItems) {
00595       addMerge( 0 );
00596       m_factory->addClient( this );
00597       return;
00598     }
00599 
00600     if ( !isCurrentTrash && !isIntoTrash && (d->m_itemFlags & KParts::BrowserExtension::ShowBookmark))
00601     {
00602         addSeparator();
00603         TQString caption;
00604         if (currentDir)
00605         {
00606            bool httpPage = (m_sViewURL.protocol().find("http", 0, false) == 0);
00607            if (httpPage)
00608               caption = i18n("&Bookmark This Page");
00609            else
00610               caption = i18n("&Bookmark This Location");
00611         }
00612         else if (S_ISDIR(mode))
00613            caption = i18n("&Bookmark This Folder");
00614         else if (bIsLink)
00615            caption = i18n("&Bookmark This Link");
00616         else
00617            caption = i18n("&Bookmark This File");
00618 
00619         act = new KAction( caption, "bookmark_add", 0, TQT_TQOBJECT(this), TQT_SLOT( slotPopupAddToBookmark() ), &m_ownActions, "bookmark_add" );
00620         if (m_lstItems.count() > 1)
00621             act->setEnabled(false);
00622         if (kapp->authorizeKAction("bookmarks"))
00623             addAction( act );
00624         if (bIsLink)
00625             addGroup( "linkactions" );
00626     }
00627 
00629 
00630     const bool isSingleLocal = m_lstItems.count() == 1 && isLocal;
00631     PopupServices s;
00632     KURL urlForServiceMenu( m_lstItems.first()->url() );
00633     if (isLocal && !isReallyLocal) { // media or system
00634         bool dummy;
00635         urlForServiceMenu = m_lstItems.first()->mostLocalURL(dummy);
00636     }
00637 
00638     // 1 - Look for builtin and user-defined services
00639     if ( ((m_sMimeType == "application/x-desktop")
00640        || (m_sMimeType == "media/builtin-mydocuments")
00641        || (m_sMimeType == "media/builtin-mycomputer")
00642        || (m_sMimeType == "media/builtin-mynetworkplaces")
00643        || (m_sMimeType == "media/builtin-printers")
00644        || (m_sMimeType == "media/builtin-trash")
00645        || (m_sMimeType == "media/builtin-webbrowser")) && isSingleLocal ) // .desktop file
00646     {
00647         // get builtin services, like mount/unmount
00648         s.builtin = KDEDesktopMimeType::builtinServices( urlForServiceMenu );
00649         const TQString path = urlForServiceMenu.path();
00650         KSimpleConfig cfg( path, true );
00651         cfg.setDesktopGroup();
00652         const TQString priority = cfg.readEntry("X-KDE-Priority");
00653         const TQString submenuName = cfg.readEntry( "X-KDE-Submenu" );
00654         if ( cfg.readEntry("Type") == "Link" ) {
00655            urlForServiceMenu = cfg.readEntry("URL");
00656            // TODO: Do we want to make all the actions apply on the target
00657            // of the .desktop file instead of the .desktop file itself?
00658         }
00659         ServiceList* list = s.selectList( priority, submenuName );
00660         (*list) = KDEDesktopMimeType::userDefinedServices( path, cfg, urlForServiceMenu.isLocalFile() );
00661     }
00662 
00663     if ( sReading )
00664     {
00665 
00666         // 2 - Look for "servicesmenus" bindings (konqueror-specific user-defined services)
00667 
00668         // first check the .directory if this is a directory
00669         if (isDirectory && isSingleLocal)
00670         {
00671             TQString dotDirectoryFile = urlForServiceMenu.path(1).append(".directory");
00672             KSimpleConfig cfg( dotDirectoryFile, true );
00673             cfg.setDesktopGroup();
00674 
00675             if (KIOSKAuthorizedAction(cfg))
00676             {
00677                 const TQString priority = cfg.readEntry("X-KDE-Priority");
00678                 const TQString submenuName = cfg.readEntry( "X-KDE-Submenu" );
00679                 ServiceList* list = s.selectList( priority, submenuName );
00680                 (*list) += KDEDesktopMimeType::userDefinedServices( dotDirectoryFile, cfg, true );
00681             }
00682         }
00683 
00684         // findAllResources() also removes duplicates
00685         const TQStringList entries = KGlobal::dirs()->findAllResources("data",
00686                                                                       "konqueror/servicemenus/*.desktop",
00687                                                                       false /* recursive */,
00688                                                                       true /* unique */);
00689         TQStringList::ConstIterator eIt = entries.begin();
00690         const TQStringList::ConstIterator eEnd = entries.end();
00691         for (; eIt != eEnd; ++eIt )
00692         {
00693             KSimpleConfig cfg( *eIt, true );
00694             cfg.setDesktopGroup();
00695 
00696             if (!KIOSKAuthorizedAction(cfg))
00697             {
00698                 continue;
00699             }
00700 
00701             if ( cfg.hasKey( "X-KDE-ShowIfRunning" ) )
00702             {
00703                 const TQString app = cfg.readEntry( "X-KDE-ShowIfRunning" );
00704                 if ( !kapp->dcopClient()->isApplicationRegistered( app.utf8() ) )
00705                     continue;
00706             }
00707             if ( cfg.hasKey( "X-KDE-ShowIfDcopCall" ) )
00708             {
00709                 TQString dcopcall = cfg.readEntry( "X-KDE-ShowIfDcopCall" );
00710                 const TQCString app = TQString(dcopcall.section(' ', 0,0)).utf8();
00711 
00712                 //if( !kapp->dcopClient()->isApplicationRegistered( app ))
00713                 //  continue; //app does not exist so cannot send call
00714 
00715                 TQByteArray dataToSend;
00716                 TQDataStream dataStream(dataToSend, IO_WriteOnly);
00717                 dataStream << m_lstPopupURLs;
00718 
00719                 TQCString replyType;
00720                 TQByteArray replyData;
00721                 TQCString object = TQString(dcopcall.section(' ', 1,-2)).utf8();
00722                 TQString function =  TQString(dcopcall.section(' ', -1));
00723                 if(!function.endsWith("(KURL::List)")) {
00724                     kdWarning() << "Desktop file " << *eIt << " contains an invalid X-KDE-ShowIfDcopCall - the function must take the exact parameter (KURL::List) and must be specified." << endl;
00725                     continue; //Be safe.
00726                 }
00727 
00728                 if(!kapp->dcopClient()->call( app, object,
00729                                               function.utf8(),
00730                                               dataToSend, replyType, replyData, true, 1000))
00731                     continue;
00732                 if(replyType != "bool" || !replyData[0])
00733                     continue;
00734 
00735             }
00736             if ( cfg.hasKey( "X-KDE-Protocol" ) )
00737             {
00738                 const TQString protocol = cfg.readEntry( "X-KDE-Protocol" );
00739                 if ( protocol != urlForServiceMenu.protocol() )
00740                     continue;
00741             }
00742             else if ( cfg.hasKey( "X-KDE-Protocols" ) )
00743             {
00744                 TQStringList protocols = TQStringList::split( "," , cfg.readEntry( "X-KDE-Protocols" ) );
00745                 if ( !protocols.contains( urlForServiceMenu.protocol() ) )
00746                     continue;
00747             }
00748             else if ( urlForServiceMenu.protocol() == "trash" || urlForServiceMenu.url().startsWith( "system:/trash" ) )
00749             {
00750                 // Require servicemenus for the trash to ask for protocol=trash explicitely.
00751                 // Trashed files aren't supposed to be available for actions.
00752                 // One might want a servicemenu for trash.desktop itself though.
00753                 continue;
00754             }
00755 
00756             if ( cfg.hasKey( "X-KDE-Require" ) )
00757             {
00758                 const TQStringList capabilities = cfg.readListEntry( "X-KDE-Require" );
00759                 if ( capabilities.contains( "Write" ) && !sWriting )
00760                     continue;
00761             }
00762             if ( (cfg.hasKey( "Actions" ) || cfg.hasKey( "X-KDE-GetActionMenu") ) && cfg.hasKey( "ServiceTypes" ) )
00763             {
00764                 const TQStringList types = cfg.readListEntry( "ServiceTypes" );
00765                 const TQStringList excludeTypes = cfg.readListEntry( "ExcludeServiceTypes" );
00766                 bool ok = false;
00767 
00768                 // check for exact matches or a typeglob'd mimetype if we have a mimetype
00769                 for (TQStringList::ConstIterator it = types.begin();
00770                      it != types.end() && !ok;
00771                      ++it)
00772                 {
00773                     // first check if we have an all mimetype
00774                     bool checkTheMimetypes = false;
00775                     if (*it == "all/all" ||
00776                         *it == "allfiles" /*compat with KDE up to 3.0.3*/)
00777                     {
00778                         checkTheMimetypes = true;
00779                     }
00780 
00781                     // next, do we match all files?
00782                     if (!ok &&
00783                         !isDirectory &&
00784                         *it == "all/allfiles")
00785                     {
00786                         checkTheMimetypes = true;
00787                     }
00788 
00789                     // if we have a mimetype, see if we have an exact or a type globbed match
00790                     if (!ok &&
00791                         (!m_sMimeType.isEmpty() &&
00792                          *it == m_sMimeType) ||
00793                         (!mimeGroup.isEmpty() &&
00794                          ((*it).right(1) == "*" &&
00795                           (*it).left((*it).find('/')) == mimeGroup)))
00796                     {
00797                         checkTheMimetypes = true;
00798                     }
00799 
00800                     if (checkTheMimetypes)
00801                     {
00802                         ok = true;
00803                         for (TQStringList::ConstIterator itex = excludeTypes.begin(); itex != excludeTypes.end(); ++itex)
00804                         {
00805                             if( ((*itex).right(1) == "*" && (*itex).left((*itex).find('/')) == mimeGroup) ||
00806                                 ((*itex) == m_sMimeType) )
00807                             {
00808                                 ok = false;
00809                                 break;
00810                             }
00811                         }
00812                     }
00813                 }
00814 
00815                 if ( ok )
00816                 {
00817                     const TQString priority = cfg.readEntry("X-KDE-Priority");
00818                     const TQString submenuName = cfg.readEntry( "X-KDE-Submenu" );
00819 
00820                     ServiceList* list = s.selectList( priority, submenuName );
00821                     (*list) += KDEDesktopMimeType::userDefinedServices( *eIt, cfg, url.isLocalFile(), m_lstPopupURLs );
00822                 }
00823             }
00824         }
00825 
00826         KTrader::OfferList offers;
00827 
00828         if (kapp->authorizeKAction("openwith"))
00829         {
00830             TQString constraint = "Type == 'Application' and DesktopEntryName != 'kfmclient' and DesktopEntryName != 'kfmclient_dir' and DesktopEntryName != 'kfmclient_html'";
00831             TQString subConstraint = " and '%1' in ServiceTypes";
00832 
00833             TQStringList::ConstIterator it = mimeTypeList.begin();
00834             TQStringList::ConstIterator end = mimeTypeList.end();
00835             Q_ASSERT( it != end );
00836             TQString first = *it;
00837             ++it;
00838             while ( it != end ) {
00839                 constraint += subConstraint.arg( *it );
00840                 ++it;
00841             }
00842 
00843             offers = KTrader::self()->query( first, constraint );
00844         }
00845 
00847 
00848         m_mapPopup.clear();
00849         m_mapPopupServices.clear();
00850         // "Open With..." for folders is really not very useful, especially for remote folders.
00851         // (media:/something, or trash:/, or ftp://...)
00852         if ( !isDirectory || isLocal )
00853         {
00854             if ( hasAction() )
00855                 addSeparator();
00856 
00857             if ( !offers.isEmpty() )
00858             {
00859                 // First block, app and preview offers
00860                 id = 1;
00861 
00862                 TQDomElement menu = m_menuElement;
00863 
00864                 if ( offers.count() > 1 ) // submenu 'open with'
00865                 {
00866                     menu = m_doc.createElement( "menu" );
00867                     menu.setAttribute( "name", "openwith submenu" );
00868                     m_menuElement.appendChild( menu );
00869                     TQDomElement text = m_doc.createElement( "text" );
00870                     menu.appendChild( text );
00871                     text.appendChild( m_doc.createTextNode( i18n("&Open With") ) );
00872                 }
00873 
00874                 KTrader::OfferList::ConstIterator it = offers.begin();
00875                 for( ; it != offers.end(); it++ )
00876                 {
00877                     KService::Ptr service = (*it);
00878 
00879                     // Skip OnlyShowIn=Foo and NotShowIn=KDE entries,
00880                     // but still offer NoDisplay=true entries, that's the
00881                     // whole point of such desktop files. This is why we don't
00882                     // use service->noDisplay() here.
00883                     const TQString onlyShowIn = service->property("OnlyShowIn", TQVariant::String).toString();
00884                     if ( !onlyShowIn.isEmpty() ) {
00885                         const TQStringList aList = TQStringList::split(';', onlyShowIn);
00886                         if (!aList.contains("KDE"))
00887                             continue;
00888                     }
00889                     const TQString notShowIn = service->property("NotShowIn", TQVariant::String).toString();
00890                     if ( !notShowIn.isEmpty() ) {
00891                         const TQStringList aList = TQStringList::split(';', notShowIn);
00892                         if (aList.contains("KDE"))
00893                             continue;
00894                     }
00895 
00896                     TQCString nam;
00897                     nam.setNum( id );
00898 
00899                     TQString actionName( (*it)->name().replace("&", "&&") );
00900                     if ( menu == m_menuElement ) // no submenu -> prefix single offer
00901                         actionName = i18n( "Open with %1" ).arg( actionName );
00902 
00903                     act = new KAction( actionName, (*it)->pixmap( KIcon::Small ), 0,
00904                                        TQT_TQOBJECT(this), TQT_SLOT( slotRunService() ),
00905                                        &m_ownActions, nam.prepend( "appservice_" ) );
00906                     addAction( act, menu );
00907 
00908                     m_mapPopup[ id++ ] = *it;
00909                 }
00910 
00911                 TQString openWithActionName;
00912                 if ( menu != m_menuElement ) // submenu
00913                 {
00914                     addSeparator( menu );
00915                     openWithActionName = i18n( "&Other..." );
00916                 }
00917                 else
00918                 {
00919                     openWithActionName = i18n( "&Open With..." );
00920                 }
00921                 KAction *openWithAct = new KAction( openWithActionName, 0, TQT_TQOBJECT(this), TQT_SLOT( slotPopupOpenWith() ), &m_ownActions, "openwith" );
00922                 addAction( openWithAct, menu );
00923             }
00924             else // no app offers -> Open With...
00925             {
00926                 act = new KAction( i18n( "&Open With..." ), 0, TQT_TQOBJECT(this), TQT_SLOT( slotPopupOpenWith() ), &m_ownActions, "openwith" );
00927                 addAction( act );
00928             }
00929 
00930         }
00931         addGroup( "preview" );
00932     }
00933 
00934     // Second block, builtin + user
00935     TQDomElement actionMenu = m_menuElement;
00936     int userItemCount = 0;
00937     if (s.user.count() + s.userSubmenus.count() +
00938         s.userPriority.count() + s.userPrioritySubmenus.count() > 1)
00939     {
00940         // we have more than one item, so let's make a submenu
00941         actionMenu = m_doc.createElement( "menu" );
00942         actionMenu.setAttribute( "name", "actions submenu" );
00943         m_menuElement.appendChild( actionMenu );
00944         TQDomElement text = m_doc.createElement( "text" );
00945         actionMenu.appendChild( text );
00946         text.appendChild( m_doc.createTextNode( i18n("Ac&tions") ) );
00947     }
00948 
00949     userItemCount += insertServicesSubmenus(s.userPrioritySubmenus, actionMenu, false);
00950     userItemCount += insertServices(s.userPriority, actionMenu, false);
00951 
00952     // see if we need to put a separator between our priority items and our regular items
00953     if (userItemCount > 0 &&
00954         (s.user.count() > 0 ||
00955          s.userSubmenus.count() > 0 ||
00956          s.builtin.count() > 0) &&
00957          actionMenu.lastChild().toElement().tagName().lower() != "separator")
00958     {
00959         TQDomElement separator = m_doc.createElement( "separator" );
00960         actionMenu.appendChild(separator);
00961     }
00962 
00963     userItemCount += insertServicesSubmenus(s.userSubmenus, actionMenu, false);
00964     userItemCount += insertServices(s.user, actionMenu, false);
00965     userItemCount += insertServices(s.builtin, m_menuElement, true);
00966 
00967     userItemCount += insertServicesSubmenus(s.userToplevelSubmenus, m_menuElement, false);
00968     userItemCount += insertServices(s.userToplevel, m_menuElement, false);
00969 
00970     if ( userItemCount > 0 )
00971     {
00972         addPendingSeparator();
00973     }
00974 
00975     if ( !isCurrentTrash && !isIntoTrash && !mediaFiles && sReading )
00976         addPlugins(); // now it's time to add plugins
00977 
00978     if ( KPropertiesDialog::canDisplay( m_lstItems ) && (kpf & ShowProperties) )
00979     {
00980         act = new KAction( i18n( "&Properties" ), 0, TQT_TQOBJECT(this), TQT_SLOT( slotPopupProperties() ),
00981                            &m_ownActions, "properties" );
00982         addAction( act );
00983     }
00984 
00985     while ( !m_menuElement.lastChild().isNull() &&
00986             m_menuElement.lastChild().toElement().tagName().lower() == "separator" )
00987         m_menuElement.removeChild( m_menuElement.lastChild() );
00988 
00989     if ( isDirectory && isLocal )
00990     {
00991         if ( KFileShare::authorization() == KFileShare::Authorized )
00992         {
00993             addSeparator();
00994             act = new KAction( i18n("Share"), 0, TQT_TQOBJECT(this), TQT_SLOT( slotOpenShareFileDialog() ),
00995                                &m_ownActions, "sharefile" );
00996             addAction( act );
00997         }
00998     }
00999 
01000     addMerge( 0 );
01001     //kdDebug() << k_funcinfo << domDocument().toString() << endl;
01002 
01003     m_factory->addClient( this );
01004 }
01005 
01006 void KonqPopupMenu::slotOpenShareFileDialog()
01007 {
01008     KPropertiesDialog* dlg = showPropertiesDialog();
01009     dlg->showFileSharingPage();
01010 }
01011 
01012 KonqPopupMenu::~KonqPopupMenu()
01013 {
01014   m_pluginList.clear();
01015   delete m_factory;
01016   delete m_builder;
01017   delete d;
01018   //kdDebug(1203) << "~KonqPopupMenu leave" << endl;
01019 }
01020 
01021 void KonqPopupMenu::setURLTitle( const TQString& urlTitle )
01022 {
01023     d->m_urlTitle = urlTitle;
01024 }
01025 
01026 void KonqPopupMenu::slotPopupNewView()
01027 {
01028   KURL::List::ConstIterator it = m_lstPopupURLs.begin();
01029   for ( ; it != m_lstPopupURLs.end(); it++ )
01030     (void) new KRun(*it);
01031 }
01032 
01033 void KonqPopupMenu::slotPopupNewDir()
01034 {
01035   if (m_lstPopupURLs.empty())
01036     return;
01037 
01038   KonqOperations::newDir(d->m_parentWidget, m_lstPopupURLs.first());
01039 }
01040 
01041 void KonqPopupMenu::slotPopupEmptyTrashBin()
01042 {
01043   KonqOperations::emptyTrash();
01044 }
01045 
01046 void KonqPopupMenu::slotPopupRestoreTrashedItems()
01047 {
01048   KonqOperations::restoreTrashedItems( m_lstPopupURLs );
01049 }
01050 
01051 void KonqPopupMenu::slotPopupOpenWith()
01052 {
01053   KRun::displayOpenWithDialog( m_lstPopupURLs );
01054 }
01055 
01056 void KonqPopupMenu::slotPopupAddToBookmark()
01057 {
01058   KBookmarkGroup root;
01059   if ( m_lstPopupURLs.count() == 1 ) {
01060     KURL url = m_lstPopupURLs.first();
01061     TQString title = d->m_urlTitle.isEmpty() ? url.prettyURL() : d->m_urlTitle;
01062     root = m_pManager->addBookmarkDialog( url.prettyURL(), title );
01063   }
01064   else
01065   {
01066     root = m_pManager->root();
01067     KURL::List::ConstIterator it = m_lstPopupURLs.begin();
01068     for ( ; it != m_lstPopupURLs.end(); it++ )
01069       root.addBookmark( m_pManager, (*it).prettyURL(), (*it) );
01070   }
01071   m_pManager->emitChanged( root );
01072 }
01073 
01074 void KonqPopupMenu::slotRunService()
01075 {
01076   TQCString senderName = TQT_TQOBJECT_CONST(sender())->name();
01077   int id = senderName.mid( senderName.find( '_' ) + 1 ).toInt();
01078 
01079   // Is it a usual service (application)
01080   TQMap<int,KService::Ptr>::Iterator it = m_mapPopup.find( id );
01081   if ( it != m_mapPopup.end() )
01082   {
01083     KRun::run( **it, m_lstPopupURLs );
01084     return;
01085   }
01086 
01087   // Is it a service specific to desktop entry files ?
01088   TQMap<int,KDEDesktopMimeType::Service>::Iterator it2 = m_mapPopupServices.find( id );
01089   if ( it2 != m_mapPopupServices.end() )
01090   {
01091       KDEDesktopMimeType::executeService( m_lstPopupURLs, it2.data() );
01092   }
01093 
01094   return;
01095 }
01096 
01097 void KonqPopupMenu::slotPopupMimeType()
01098 {
01099     KonqOperations::editMimeType( m_sMimeType );
01100 }
01101 
01102 void KonqPopupMenu::slotPopupProperties()
01103 {
01104     (void)showPropertiesDialog();
01105 }
01106 
01107 KPropertiesDialog* KonqPopupMenu::showPropertiesDialog()
01108 {
01109     // It may be that the kfileitem was created by hand
01110     // (see KonqKfmIconView::slotMouseButtonPressed)
01111     // In that case, we can get more precise info in the properties
01112     // (like permissions) if we stat the URL.
01113     if ( m_lstItems.count() == 1 )
01114     {
01115         KFileItem * item = m_lstItems.first();
01116         if (item->entry().count() == 0) // this item wasn't listed by a slave
01117         {
01118             // KPropertiesDialog will use stat to get more info on the file
01119             return new KPropertiesDialog( item->url(), d->m_parentWidget );
01120         }
01121     }
01122     return new KPropertiesDialog( m_lstItems, d->m_parentWidget );
01123 }
01124 
01125 KAction *KonqPopupMenu::action( const TQDomElement &element ) const
01126 {
01127   TQCString name = element.attribute( attrName ).ascii();
01128   KAction *res = m_ownActions.action( static_cast<const char *>(name) );
01129 
01130   if ( !res )
01131     res = m_actions.action( static_cast<const char *>(name) );
01132 
01133   if ( !res && m_pMenuNew && strcmp( name, m_pMenuNew->name() ) == 0 )
01134     return m_pMenuNew;
01135 
01136   return res;
01137 }
01138 
01139 KActionCollection *KonqPopupMenu::actionCollection() const
01140 {
01141     return const_cast<KActionCollection *>( &m_ownActions );
01142 }
01143 
01144 TQString KonqPopupMenu::mimeType() const
01145 {
01146     return m_sMimeType;
01147 }
01148 
01149 KonqPopupMenu::ProtocolInfo KonqPopupMenu::protocolInfo() const
01150 {
01151     return m_info;
01152 }
01153 
01154 void KonqPopupMenu::addPlugins()
01155 {
01156     // search for Konq_PopupMenuPlugins inspired by simons kpropsdlg
01157     //search for a plugin with the right protocol
01158     KTrader::OfferList plugin_offers;
01159     unsigned int pluginCount = 0;
01160     plugin_offers = KTrader::self()->query( m_sMimeType.isNull() ? TQString::fromLatin1( "all/all" ) : m_sMimeType, "'KonqPopupMenu/Plugin' in ServiceTypes");
01161     if ( plugin_offers.isEmpty() )
01162         return; // no plugins installed do not bother about it
01163 
01164     KTrader::OfferList::ConstIterator iterator = plugin_offers.begin();
01165     KTrader::OfferList::ConstIterator end = plugin_offers.end();
01166 
01167     addGroup( "plugins" );
01168     // travers the offerlist
01169     for(; iterator != end; ++iterator, ++pluginCount ) {
01170         //kdDebug() << (*iterator)->library() << endl;
01171         KonqPopupMenuPlugin *plugin =
01172             KParts::ComponentFactory::
01173             createInstanceFromLibrary<KonqPopupMenuPlugin>( TQFile::encodeName( (*iterator)->library() ),
01174                                                             TQT_TQOBJECT(this),
01175                                                             (*iterator)->name().latin1() );
01176         if ( !plugin )
01177             continue;
01178         // This make the kuick plugin insert its stuff above "Properties"
01179         TQString pluginClientName = TQString::fromLatin1( "Plugin%1" ).arg( pluginCount );
01180         addMerge( pluginClientName );
01181         plugin->domDocument().documentElement().setAttribute( "name", pluginClientName );
01182         m_pluginList.append( plugin );
01183         insertChildClient( plugin );
01184     }
01185 
01186     // ## Where is this used?
01187     addMerge( "plugins" );
01188 }
01189 
01190 KURL KonqPopupMenu::url() const // ### should be viewURL()
01191 {
01192   return m_sViewURL;
01193 }
01194 
01195 KFileItemList KonqPopupMenu::fileItemList() const
01196 {
01197   return m_lstItems;
01198 }
01199 
01200 KURL::List KonqPopupMenu::popupURLList() const
01201 {
01202   return m_lstPopupURLs;
01203 }
01204 
01209 KonqPopupMenuPlugin::KonqPopupMenuPlugin( KonqPopupMenu *parent, const char *name )
01210     : TQObject( parent, name )
01211 {
01212 }
01213 
01214 KonqPopupMenuPlugin::~KonqPopupMenuPlugin()
01215 {
01216 }
01217 
01218 #include "konq_popupmenu.moc"

libkonq

Skip menu "libkonq"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

libkonq

Skip menu "libkonq"
  • kate
  • kwin
  •   lib
  • libkonq
Generated for libkonq by doxygen 1.7.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |