libkonq Library API Documentation

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., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include <qdir.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 <dcopclient.h>
00047 
00048 
00049 class KonqPopupMenuGUIBuilder : public KXMLGUIBuilder
00050 {
00051 public:
00052   KonqPopupMenuGUIBuilder( QPopupMenu *menu )
00053   : KXMLGUIBuilder( 0 )
00054   {
00055     m_menu = menu;
00056   }
00057   virtual ~KonqPopupMenuGUIBuilder()
00058   {
00059   }
00060 
00061   virtual QWidget *createContainer( QWidget *parent, int index,
00062           const QDomElement &element,
00063           int &id )
00064   {
00065     if ( !parent && element.attribute( "name" ) == "popupmenu" )
00066       return m_menu;
00067 
00068     return KXMLGUIBuilder::createContainer( parent, index, element, id );
00069   }
00070 
00071   QPopupMenu *m_menu;
00072 };
00073 
00074 class KonqPopupMenu::KonqPopupMenuPrivate
00075 {
00076 public:
00077   KonqPopupMenuPrivate() : m_parentWidget(0)
00078   {
00079     m_itemFlags=KParts::BrowserExtension::DefaultPopupItems;
00080   }
00081   QString m_urlTitle;
00082   QWidget *m_parentWidget;
00083   KParts::BrowserExtension::PopupFlags m_itemFlags;
00084 };
00085 
00086 KonqPopupMenu::ProtocolInfo::ProtocolInfo( )
00087 {
00088   m_Reading = false;
00089   m_Writing = false;
00090   m_Deleting = false;
00091   m_Moving = false;
00092   m_TrashIncluded = false;
00093 }
00094 bool KonqPopupMenu::ProtocolInfo::supportsReading() const
00095 {
00096   return m_Reading;
00097 }
00098 bool KonqPopupMenu::ProtocolInfo::supportsWriting() const
00099 {
00100   return m_Writing;
00101 }
00102 bool KonqPopupMenu::ProtocolInfo::supportsDeleting() const
00103 {
00104   return m_Deleting;
00105 }
00106 bool KonqPopupMenu::ProtocolInfo::supportsMoving() const
00107 {
00108   return m_Moving;
00109 }
00110 bool KonqPopupMenu::ProtocolInfo::trashIncluded() const
00111 {
00112   return m_TrashIncluded;
00113 }
00114 
00115 KonqPopupMenu::KonqPopupMenu( KBookmarkManager *mgr, const KFileItemList &items,
00116                               KURL viewURL,
00117                               KActionCollection & actions,
00118                               KNewMenu * newMenu,
00119                               bool showProperties )
00120   : QPopupMenu( 0L, "konq_popupmenu" ), m_actions( actions ), m_ownActions( static_cast<QObject *>( 0 ), "KonqPopupMenu::m_ownActions" ),
00121     m_pMenuNew( newMenu ), m_sViewURL(viewURL), m_lstItems(items), m_pManager(mgr)
00122 
00123 {
00124   KonqPopupFlags kpf = ( showProperties ? ShowProperties : IsLink ) | ShowNewWindow;
00125   init(0, kpf, KParts::BrowserExtension::DefaultPopupItems);
00126 }
00127 
00128 KonqPopupMenu::KonqPopupMenu( KBookmarkManager *mgr, const KFileItemList &items,
00129                               KURL viewURL,
00130                               KActionCollection & actions,
00131                               KNewMenu * newMenu,
00132                               QWidget * parentWidget,
00133                               bool showProperties )
00134   : QPopupMenu( parentWidget, "konq_popupmenu" ), m_actions( actions ), m_ownActions( static_cast<QObject *>( 0 ), "KonqPopupMenu::m_ownActions" ), m_pMenuNew( newMenu ), m_sViewURL(viewURL), m_lstItems(items), m_pManager(mgr)
00135 {
00136   KonqPopupFlags kpf = ( showProperties ? ShowProperties : IsLink ) | ShowNewWindow;
00137   init(parentWidget, kpf, KParts::BrowserExtension::DefaultPopupItems);
00138 }
00139 
00140 KonqPopupMenu::KonqPopupMenu( KBookmarkManager *mgr, const KFileItemList &items,
00141                               const KURL& viewURL,
00142                               KActionCollection & actions,
00143                               KNewMenu * newMenu,
00144                               QWidget * parentWidget,
00145                               KonqPopupFlags kpf,
00146                               KParts::BrowserExtension::PopupFlags flags)
00147   : QPopupMenu( parentWidget, "konq_popupmenu" ), m_actions( actions ), m_ownActions( static_cast<QObject *>( 0 ), "KonqPopupMenu::m_ownActions" ), m_pMenuNew( newMenu ), m_sViewURL(viewURL), m_lstItems(items), m_pManager(mgr)
00148 {
00149   init(parentWidget, kpf, flags);
00150 }
00151 
00152 void KonqPopupMenu::init (QWidget * parentWidget, KonqPopupFlags kpf, KParts::BrowserExtension::PopupFlags flags)
00153 {
00154   d = new KonqPopupMenuPrivate;
00155   d->m_parentWidget = parentWidget;
00156   d->m_itemFlags = flags;
00157   setup(kpf);
00158 }
00159 
00160 
00161 int KonqPopupMenu::insertServicesSubmenus(const QMap<QString, ServiceList>& submenus,
00162                                           QDomElement& menu,
00163                                           bool isBuiltin)
00164 {
00165     int count = 0;
00166     QMap<QString, ServiceList>::ConstIterator it;
00167 
00168     for (it = submenus.begin(); it != submenus.end(); ++it)
00169     {
00170         if (it.data().isEmpty())
00171         {
00172             //avoid empty sub-menus
00173             continue;
00174         }
00175 
00176         QDomElement actionSubmenu = m_doc.createElement( "menu" );
00177         actionSubmenu.setAttribute( "name", "actions " + it.key() );
00178         menu.appendChild( actionSubmenu );
00179         QDomElement subtext = m_doc.createElement( "text" );
00180         actionSubmenu.appendChild( subtext );
00181         subtext.appendChild( m_doc.createTextNode( it.key() ) );
00182         count += insertServices(it.data(), actionSubmenu, isBuiltin);
00183     }
00184 
00185     return count;
00186 }
00187 
00188 int KonqPopupMenu::insertServices(const ServiceList& list,
00189                                   QDomElement& menu,
00190                                   bool isBuiltin)
00191 {
00192     static int id = 1000;
00193     int count = 0;
00194 
00195     ServiceList::const_iterator it = list.begin();
00196     for( ; it != list.end(); ++it )
00197     {
00198         if ((*it).isEmpty())
00199         {
00200             if (!menu.firstChild().isNull() &&
00201                 menu.lastChild().toElement().tagName().lower() != "separator")
00202             {
00203                 QDomElement separator = m_doc.createElement( "separator" );
00204                 menu.appendChild(separator);
00205             }
00206             continue;
00207         }
00208 
00209         if (isBuiltin || (*it).m_display == true)
00210         {
00211             QCString name;
00212             name.setNum( id );
00213             name.prepend( isBuiltin ? "builtinservice_" : "userservice_" );
00214             KAction * act = new KAction( (*it).m_strName, 0,
00215                                          this, SLOT( slotRunService() ),
00216                                          &m_ownActions, name );
00217 
00218             if ( !(*it).m_strIcon.isEmpty() )
00219             {
00220                 QPixmap pix = SmallIcon( (*it).m_strIcon );
00221                 act->setIconSet( pix );
00222             }
00223 
00224             addAction( act, menu ); // Add to toplevel menu
00225 
00226             m_mapPopupServices[ id++ ] = *it;
00227             ++count;
00228         }
00229     }
00230 
00231     return count;
00232 }
00233 
00234 bool KonqPopupMenu::KIOSKAuthorizedAction(KConfig& cfg)
00235 {
00236     if ( !cfg.hasKey( "X-KDE-AuthorizeAction") )
00237     {
00238         return true;
00239     }
00240 
00241     QStringList list = cfg.readListEntry("X-KDE-AuthorizeAction");
00242     if (kapp && !list.isEmpty())
00243     {
00244         for(QStringList::ConstIterator it = list.begin();
00245             it != list.end();
00246             ++it)
00247         {
00248             if (!kapp->authorize((*it).stripWhiteSpace()))
00249             {
00250                 return false;
00251             }
00252         }
00253     }
00254 
00255     return true;
00256 }
00257 
00258 
00259 void KonqPopupMenu::setup(KonqPopupFlags kpf)
00260 {
00261     assert( m_lstItems.count() >= 1 );
00262 
00263     m_ownActions.setWidget( this );
00264 
00265     bool bIsLink        = (kpf & IsLink);
00266     bool currentDir     = false;
00267     bool sReading       = true;
00268     bool sWriting       = true;
00269     bool sDeleting      = true;
00270     bool sMoving        = true;
00271     m_sMimeType         = m_lstItems.first()->mimetype();
00272     QString mimeGroup   = m_sMimeType.left(m_sMimeType.find('/'));
00273     mode_t mode         = m_lstItems.first()->mode();
00274     bool isDirectory    = m_sMimeType == "inode/directory";
00275     bool bTrashIncluded = false;
00276     bool bCanChangeSharing = false;
00277     m_lstPopupURLs.clear();
00278     int id = 0;
00279     if( isDirectory && m_lstItems.first()->isLocalFile())
00280         bCanChangeSharing=true;
00281     setFont(KGlobalSettings::menuFont());
00282     m_pluginList.setAutoDelete( true );
00283     m_ownActions.setHighlightingEnabled( true );
00284 
00285     attrName = QString::fromLatin1( "name" );
00286 
00287     prepareXMLGUIStuff();
00288     m_builder = new KonqPopupMenuGUIBuilder( this );
00289     m_factory = new KXMLGUIFactory( m_builder );
00290 
00291     KURL url;
00292     KFileItemListIterator it ( m_lstItems );
00293     // Check whether all URLs are correct
00294     bool devicesFile = false;
00295     for ( ; it.current(); ++it )
00296     {
00297         url = (*it)->url();
00298 
00299         // Build the list of URLs
00300         m_lstPopupURLs.append( url );
00301 
00302         // Determine if common mode among all URLs
00303         if ( mode != (*it)->mode() )
00304             mode = 0; // modes are different => reset to 0
00305 
00306         // Determine if common mimetype among all URLs
00307         if ( m_sMimeType != (*it)->mimetype() )
00308         {
00309             m_sMimeType = QString::null; // mimetypes are different => null
00310 
00311             if ( mimeGroup != (*it)->mimetype().left((*it)->mimetype().find('/')))
00312                 mimeGroup = QString::null; // mimetype groups are different as well!
00313         }
00314 
00315         if ( !bTrashIncluded &&
00316              (*it)->url().isLocalFile() &&
00317              (*it)->url().path( 1 ) == KGlobalSettings::trashPath() )
00318             bTrashIncluded = true;
00319 
00320         if ( sReading )
00321             sReading = KProtocolInfo::supportsReading( url );
00322 
00323         if ( sWriting )
00324             sWriting = KProtocolInfo::supportsWriting( url );
00325 
00326         if ( sDeleting )
00327             sDeleting = KProtocolInfo::supportsDeleting( url );
00328 
00329         if ( url.path(1).contains("/usr/share/apps/kdesktop/Desktop"))
00330             sMoving = false;
00331         else if ( sMoving )
00332             sMoving = KProtocolInfo::supportsMoving( url );
00333         if ( url.protocol().find("device", 0, false)==0)
00334             devicesFile = true;
00335     }
00336     // Be on the safe side when including the trash
00337     if ( bTrashIncluded )
00338     {
00339         sMoving = false;
00340         sDeleting = false;
00341     }
00342     //check if current url is trash
00343     url = m_sViewURL;
00344     url.cleanPath();
00345 
00346     m_info.m_Reading = sReading;
00347     m_info.m_Writing = sWriting;
00348     m_info.m_Deleting = sDeleting;
00349     m_info.m_Moving = sMoving;
00350     m_info.m_TrashIncluded = bTrashIncluded;
00351 
00352     //check if url is current directory
00353     if ( m_lstItems.count() == 1 )
00354     {
00355         KURL firstPopupURL ( m_lstItems.first()->url() );
00356         firstPopupURL.cleanPath();
00357         //kdDebug(1203) << "View path is " << url.url() << endl;
00358         //kdDebug(1203) << "First popup path is " << firstPopupURL.url() << endl;
00359         currentDir = firstPopupURL.equals( url, true /* ignore_trailing */ );
00360     }
00361 
00362     bool isCurrentTrash = ( url.isLocalFile() &&
00363                             url.path(1) == KGlobalSettings::trashPath() &&
00364                             currentDir) ||
00365                           ( m_lstItems.count() == 1 && bTrashIncluded );
00366     bool isIntoTrash =  url.isLocalFile() && url.path(1).startsWith(KGlobalSettings::trashPath());
00367     clear();
00368 
00370 
00371     KAction * act;
00372 
00373     if (!isCurrentTrash)
00374         addMerge( "konqueror" );
00375 
00376     bool isKDesktop = QCString(  kapp->name() ) == "kdesktop";
00377     KAction *actNewWindow = 0;
00378 
00379     if (( kpf & ShowProperties ) && isKDesktop &&
00380         !kapp->authorize("editable_desktop_icons"))
00381     {
00382         kpf &= ~ShowProperties; // remove flag
00383     }
00384 
00385     // Either 'newview' is in the actions we're given (probably in the tabhandling group)
00386     // or we need to insert it ourselves (e.g. for kdesktop). In the first case, actNewWindow must remain 0.
00387     if ( ((kpf & ShowNewWindow) != 0) && sReading )
00388     {
00389         QString openStr = isKDesktop ? i18n( "&Open" ) : i18n( "Open in New &Window" );
00390         actNewWindow = new KAction( openStr, "window_new", 0, this, SLOT( slotPopupNewView() ), &m_ownActions, "newview" );
00391     }
00392 
00393     if ( actNewWindow && !isKDesktop )
00394     {
00395         if (isCurrentTrash)
00396             actNewWindow->setStatusText( i18n( "Open the trash in a new window" ) );
00397         else
00398             actNewWindow->setStatusText( i18n( "Open the document in a new window" ) );
00399     }
00400 
00401     if ( isCurrentTrash )
00402     {
00403         if (actNewWindow)
00404         {
00405             addAction( actNewWindow );
00406             addSeparator();
00407         }
00408         addGroup( "tabhandling" ); // includes a separator
00409 
00410         act = new KAction( i18n( "&Empty Trash Bin" ), 0, this, SLOT( slotPopupEmptyTrashBin() ), &m_ownActions, "empytrash" );
00411         addAction( act );
00412         if ( KPropertiesDialog::canDisplay( m_lstItems ) && (kpf & ShowProperties) )
00413         {
00414             act = new KAction( i18n( "&Properties" ), 0, this, SLOT( slotPopupProperties() ),
00415                                &m_ownActions, "properties" );
00416             addAction( act );
00417         }
00418         m_factory->addClient( this );
00419         return;
00420     }
00421     else
00422     {
00423         if ( S_ISDIR(mode) && sWriting && !isIntoTrash ) // A dir, and we can create things into it
00424         {
00425             if ( currentDir && m_pMenuNew ) // Current dir -> add the "new" menu
00426             {
00427                 // As requested by KNewMenu :
00428                 m_pMenuNew->slotCheckUpToDate();
00429                 m_pMenuNew->setPopupFiles( m_lstPopupURLs );
00430 
00431                 addAction( m_pMenuNew );
00432 
00433                 addSeparator();
00434             }
00435             else
00436             {
00437                 if (d->m_itemFlags & KParts::BrowserExtension::ShowCreateDirectory)
00438                 {
00439                     KAction *actNewDir = new KAction( i18n( "Create &Folder..." ), "folder_new", 0, this, SLOT( slotPopupNewDir() ), &m_ownActions, "newdir" );
00440                     addAction( actNewDir );
00441                     addSeparator();
00442                 }
00443             }
00444         }
00445 
00446         if (d->m_itemFlags & KParts::BrowserExtension::ShowNavigationItems)
00447         {
00448             addAction( "back" );
00449             addAction( "forward" );
00450             if (d->m_itemFlags & KParts::BrowserExtension::ShowUp)
00451                addAction( "up" );
00452             if (d->m_itemFlags & KParts::BrowserExtension::ShowReload)
00453                 addAction( "reload" );
00454             addSeparator();
00455         }
00456 
00457         // "open in new window" is either provided by us, or by the tabhandling group
00458         if (actNewWindow)
00459         {
00460             addAction( actNewWindow );
00461             addSeparator();
00462         }
00463         addGroup( "tabhandling" ); // includes a separator
00464 
00465         if ( !bIsLink )
00466         {
00467             if ( !currentDir && sReading && !isIntoTrash &&!devicesFile ) {
00468                 if ( sDeleting ) {
00469                     addAction( "cut" );
00470                 }
00471                 addAction( "copy" );
00472             }
00473 
00474             if ( S_ISDIR(mode) && sWriting && !isIntoTrash) {
00475                 if ( currentDir )
00476                     addAction( "paste" );
00477                 else
00478                     addAction( "pasteto" );
00479             }
00480             if ( !isIntoTrash )
00481             {
00482                 if (!currentDir )
00483                 {
00484                     if ( m_lstItems.count() == 1 && sWriting )
00485                         addAction("rename");
00486 
00487                     if ( sMoving )
00488                         addAction( "trash" );
00489 
00490                     if ( sDeleting ) {
00491                         addAction( "del" );
00492                     }
00493                 }
00494             }
00495         }
00496         addGroup( "editactions" );
00497     }
00498 
00499     if (d->m_itemFlags & KParts::BrowserExtension::ShowTextSelectionItems) {
00500       addMerge( 0 );
00501       m_factory->addClient( this );
00502       return;
00503     }
00504 
00505     if ( !isCurrentTrash && !isIntoTrash && (d->m_itemFlags & KParts::BrowserExtension::ShowBookmark))
00506     {
00507         addSeparator();
00508         QString caption;
00509         if (currentDir)
00510         {
00511            bool httpPage = (m_sViewURL.protocol().find("http", 0, false) == 0);
00512            if (httpPage)
00513               caption = i18n("&Bookmark This Page");
00514            else
00515               caption = i18n("&Bookmark This Location");
00516         }
00517         else if (S_ISDIR(mode))
00518            caption = i18n("&Bookmark This Folder");
00519         else if (bIsLink)
00520            caption = i18n("&Bookmark This Link");
00521         else
00522            caption = i18n("&Bookmark This File");
00523 
00524         act = new KAction( caption, "bookmark_add", 0, this, SLOT( slotPopupAddToBookmark() ), &m_ownActions, "bookmark_add" );
00525         if (m_lstItems.count() > 1)
00526             act->setEnabled(false);
00527         if (kapp->authorizeKAction("bookmarks"))
00528             addAction( act );
00529         if (bIsLink)
00530             addGroup( "linkactions" );
00531     }
00532 
00534 
00535     ServiceList builtin;
00536     ServiceList user, userToplevel, userPriority;
00537     QMap<QString, ServiceList> userSubmenus, userToplevelSubmenus, userPrioritySubmenus;
00538 
00539     bool isSingleLocal = (m_lstItems.count() == 1 && m_lstItems.first()->url().isLocalFile());
00540     // 1 - Look for builtin and user-defined services
00541     if ( m_sMimeType == "application/x-desktop" && isSingleLocal ) // .desktop file
00542     {
00543         // get builtin services, like mount/unmount
00544         builtin = KDEDesktopMimeType::builtinServices( m_lstItems.first()->url() );
00545         user = KDEDesktopMimeType::userDefinedServices( m_lstItems.first()->url().path(), url.isLocalFile() );
00546     }
00547 
00548     if ( !isCurrentTrash && !isIntoTrash && sReading)
00549     {
00550 
00551         // 2 - Look for "servicesmenus" bindings (konqueror-specific user-defined services)
00552 
00553         // first check the .directory if this is a directory
00554         if (isDirectory && isSingleLocal)
00555         {
00556             QString dotDirectoryFile = m_lstItems.first()->url().path(1).append(".directory");
00557             KSimpleConfig cfg( dotDirectoryFile, true );
00558             cfg.setDesktopGroup();
00559 
00560             if (KIOSKAuthorizedAction(cfg))
00561             {
00562                 QString submenuName = cfg.readEntry( "X-KDE-Submenu" );
00563                 if (submenuName.isEmpty())
00564                 {
00565                     user += KDEDesktopMimeType::userDefinedServices( dotDirectoryFile, true );
00566                 }
00567                 else
00568                 {
00569                     userSubmenus[submenuName] += KDEDesktopMimeType::userDefinedServices( dotDirectoryFile, true );
00570                 }
00571             }
00572         }
00573 
00574         QStringList dirs = KGlobal::dirs()->findDirs( "data", "konqueror/servicemenus/" );
00575         QStringList::ConstIterator dIt = dirs.begin();
00576         QStringList::ConstIterator dEnd = dirs.end();
00577 
00578         for (; dIt != dEnd; ++dIt )
00579         {
00580             QDir dir( *dIt );
00581 
00582             QStringList entries = dir.entryList( "*.desktop", QDir::Files );
00583             QStringList::ConstIterator eIt = entries.begin();
00584             QStringList::ConstIterator eEnd = entries.end();
00585 
00586             for (; eIt != eEnd; ++eIt )
00587             {
00588                 KSimpleConfig cfg( *dIt + *eIt, true );
00589                 cfg.setDesktopGroup();
00590 
00591                 if (!KIOSKAuthorizedAction(cfg))
00592                 {
00593                     continue;
00594                 }
00595 
00596                 if ( cfg.hasKey( "X-KDE-ShowIfRunning" ) )
00597                 {
00598                     QString app = cfg.readEntry( "X-KDE-ShowIfRunning" );
00599                     if ( !kapp->dcopClient()->isApplicationRegistered( app.utf8() ) )
00600                         continue;
00601                 }
00602 
00603                 if ( cfg.hasKey( "Actions" ) && cfg.hasKey( "ServiceTypes" ) )
00604                 {
00605                     QStringList types = cfg.readListEntry( "ServiceTypes" );
00606                     QStringList excludeTypes = cfg.readListEntry( "ExcludeServiceTypes" );
00607                     bool ok = false;
00608 
00609                     // check for exact matches or a typeglob'd mimetype if we have a mimetype
00610                     for (QStringList::iterator it = types.begin();
00611                          it != types.end() && !ok;
00612                          ++it)
00613                     {
00614                         // we could cram the following three if statements into
00615                         // one gigantic boolean statement but that would be a
00616                         // hororr show for readability
00617 
00618                         // first check if we have an all mimetype
00619                         if (*it == "all/all" ||
00620                             *it == "allfiles" /*compat with KDE up to 3.0.3*/)
00621                         {
00622                             ok = true;
00623                             for (QStringList::iterator itex = excludeTypes.begin(); itex != excludeTypes.end(); ++itex)
00624                             {
00625                                 if( ((*itex).right(1) == "*" && (*itex).left((*itex).find('/')) == mimeGroup) ||
00626                                     ((*itex) == m_sMimeType) )
00627                                 {
00628                                     ok = false;
00629                                     break;
00630                                 }
00631                             }
00632                         }
00633 
00634                         // next, do we match all files?
00635                         if (!ok &&
00636                             !isDirectory /* ## or inherits from it */ &&
00637                             *it == "all/allfiles")
00638                         {
00639                             ok = true;
00640                             for (QStringList::iterator itex = excludeTypes.begin(); itex != excludeTypes.end(); ++itex)
00641                             {
00642                                 if( ((*itex).right(1) == "*" && (*itex).left((*itex).find('/')) == mimeGroup) ||
00643                                     ((*itex) == m_sMimeType) )
00644                                 {
00645                                     ok = false;
00646                                     break;
00647                                 }
00648                             }
00649 
00650                         }
00651 
00652                         // if we have a mimetype, see if we have an exact or a type globbed match
00653                         if (!ok &&
00654                             (!m_sMimeType.isEmpty() &&
00655                               *it == m_sMimeType) ||
00656                             (!mimeGroup.isEmpty() &&
00657                              ((*it).right(1) == "*" &&
00658                               (*it).left((*it).find('/')) == mimeGroup)))
00659                         {
00660                             ok = true;
00661                             for (QStringList::iterator itex = excludeTypes.begin(); itex != excludeTypes.end(); ++itex)
00662                             {
00663                                 if( ((*itex).right(1) == "*" && (*itex).left((*itex).find('/')) == mimeGroup) ||
00664                                     ((*itex) == m_sMimeType) )
00665                                 {
00666                                     ok = false;
00667                                     break;
00668                                 }
00669                             }
00670                         }
00671                     }
00672 
00673                     if ( ok )
00674                     {
00675                         // we use the categories .desktop entry to define submenus
00676                         // if none is defined, we just pop it in the main menu
00677                         QString priority = cfg.readEntry("X-KDE-Priority");
00678                         QString submenuName = cfg.readEntry( "X-KDE-Submenu" );
00679                         ServiceList* list = &user;
00680 
00681                         if (submenuName.isEmpty())
00682                         {
00683                             if (priority == "TopLevel")
00684                             {
00685                                 list = &userToplevel;
00686                             }
00687                             else if (priority == "Important")
00688                             {
00689                                 list = &userPriority;
00690                             }
00691                         }
00692                         else if (priority == "TopLevel")
00693                         {
00694                             list = &(userToplevelSubmenus[submenuName]);
00695                         }
00696                         else if (priority == "Important")
00697                         {
00698                             list = &(userPrioritySubmenus[submenuName]);
00699                         }
00700                         else
00701                         {
00702                             list = &(userSubmenus[submenuName]);
00703                         }
00704 
00705                         (*list) += KDEDesktopMimeType::userDefinedServices( *dIt + *eIt, url.isLocalFile() );
00706                     }
00707                 }
00708             }
00709         }
00710 
00711         KTrader::OfferList offers;
00712 
00713         if (kapp->authorizeKAction("openwith"))
00714         {
00715             // if check m_sMimeType.isNull (no commom mime type) set it to all/all
00716             // 3 - Query for applications
00717             offers = KTrader::self()->query( m_sMimeType.isNull( ) ? QString::fromLatin1( "all/all" ) : m_sMimeType ,
00718                                              "Type == 'Application' and DesktopEntryName != 'kfmclient' and DesktopEntryName != 'kfmclient_dir' and DesktopEntryName != 'kfmclient_html'" );
00719         }
00720 
00722 
00723         m_mapPopup.clear();
00724         m_mapPopupServices.clear();
00725         if ( !devicesFile)
00726         {
00727             if ( !offers.isEmpty() )
00728             {
00729                 // First block, app and preview offers
00730                 addSeparator();
00731 
00732                 id = 1;
00733 
00734                 QDomElement menu = m_menuElement;
00735 
00736                 if ( offers.count() > 1 ) // submenu 'open with'
00737                 {
00738                     menu = m_doc.createElement( "menu" );
00739                     menu.setAttribute( "name", "openwith submenu" );
00740                     m_menuElement.appendChild( menu );
00741                     QDomElement text = m_doc.createElement( "text" );
00742                     menu.appendChild( text );
00743                     text.appendChild( m_doc.createTextNode( i18n("&Open With") ) );
00744                 }
00745 
00746                 if ( menu == m_menuElement ) // no submenu -> open with... above the single offer
00747                 {
00748                     KAction *openWithAct = new KAction( i18n( "&Open With..." ), 0, this, SLOT( slotPopupOpenWith() ), &m_ownActions, "openwith" );
00749                     addAction( openWithAct, menu );
00750                 }
00751 
00752                 KTrader::OfferList::ConstIterator it = offers.begin();
00753                 for( ; it != offers.end(); it++ )
00754                 {
00755                     QCString nam;
00756                     nam.setNum( id );
00757 
00758                     act = new KAction( (*it)->name(), (*it)->pixmap( KIcon::Small ), 0,
00759                                        this, SLOT( slotRunService() ),
00760                                        &m_ownActions, nam.prepend( "appservice_" ) );
00761                     addAction( act, menu );
00762 
00763                     m_mapPopup[ id++ ] = *it;
00764                 }
00765 
00766                 if ( menu != m_menuElement ) // submenu
00767                 {
00768                     addSeparator( menu );
00769                     KAction *openWithAct = new KAction( i18n( "&Other..." ), 0, this, SLOT( slotPopupOpenWith() ), &m_ownActions, "openwith" );
00770                     addAction( openWithAct, menu ); // Other...
00771                 }
00772             }
00773             else // no app offers -> Open With...
00774             {
00775                 addSeparator();
00776                 act = new KAction( i18n( "&Open With..." ), 0, this, SLOT( slotPopupOpenWith() ), &m_ownActions, "openwith" );
00777                 addAction( act );
00778             }
00779 
00780             addGroup( "preview" );
00781         }
00782     }
00783 
00784     // Second block, builtin + user
00785     QDomElement actionMenu = m_menuElement;
00786     int userItemCount = 0;
00787     if (user.count() + userSubmenus.count() +
00788         userPriority.count() + userPrioritySubmenus.count() > 1)
00789     {
00790         // we have more than one item, so let's make a submenu
00791         actionMenu = m_doc.createElement( "menu" );
00792         actionMenu.setAttribute( "name", "actions submenu" );
00793         m_menuElement.appendChild( actionMenu );
00794         QDomElement text = m_doc.createElement( "text" );
00795         actionMenu.appendChild( text );
00796         text.appendChild( m_doc.createTextNode( i18n("Ac&tions") ) );
00797     }
00798 
00799     userItemCount += insertServicesSubmenus(userPrioritySubmenus, actionMenu, false);
00800     userItemCount += insertServices(userPriority, actionMenu, false);
00801 
00802     // see if we need to put a separator between our priority items and our regular items
00803     if (userItemCount > 0 &&
00804         (user.count() > 0 ||
00805          userSubmenus.count() > 0 ||
00806          builtin.count() > 0) &&
00807          actionMenu.lastChild().toElement().tagName().lower() != "separator")
00808     {
00809         QDomElement separator = m_doc.createElement( "separator" );
00810         actionMenu.appendChild(separator);
00811     }
00812 
00813     userItemCount += insertServicesSubmenus(userSubmenus, actionMenu, false);
00814     userItemCount += insertServices(user, actionMenu, false);
00815     userItemCount += insertServices(builtin, m_menuElement, true);
00816 
00817     userItemCount += insertServicesSubmenus(userToplevelSubmenus, m_menuElement, false);
00818     userItemCount += insertServices(userToplevel, m_menuElement, false);
00819 
00820     if (userItemCount > 0)
00821     {
00822         addSeparator();
00823     }
00824 
00825     if ( !isCurrentTrash && !isIntoTrash && !devicesFile && sReading)
00826         addPlugins( ); // now it's time to add plugins
00827 
00828     if ( KPropertiesDialog::canDisplay( m_lstItems ) && (kpf & ShowProperties) )
00829     {
00830         act = new KAction( i18n( "&Properties" ), 0, this, SLOT( slotPopupProperties() ),
00831                            &m_ownActions, "properties" );
00832         addAction( act );
00833     }
00834 
00835     while ( !m_menuElement.lastChild().isNull() &&
00836             m_menuElement.lastChild().toElement().tagName().lower() == "separator" )
00837         m_menuElement.removeChild( m_menuElement.lastChild() );
00838 
00839     if( bCanChangeSharing && !isCurrentTrash && !isIntoTrash )
00840     {
00841         if(KFileShare::authorization()==KFileShare::Authorized)
00842         {
00843             addSeparator();
00844             act = new KAction( i18n("Share"), 0, this, SLOT( slotOpenShareFileDialog() ),
00845                                &m_ownActions, "sharefile" );
00846             addAction( act );
00847         }
00848     }
00849 
00850 
00851     addMerge( 0 );
00852 
00853     m_factory->addClient( this );
00854 }
00855 
00856 void KonqPopupMenu::slotOpenShareFileDialog()
00857 {
00858     //kdDebug()<<"KonqPopupMenu::slotOpenShareFileDialog()\n";
00859     // It may be that the kfileitem was created by hand
00860     // (see KonqKfmIconView::slotMouseButtonPressed)
00861     // In that case, we can get more precise info in the properties
00862     // (like permissions) if we stat the URL.
00863     if ( m_lstItems.count() == 1 )
00864     {
00865         KFileItem * item = m_lstItems.first();
00866         if (item->entry().count() == 0) // this item wasn't listed by a slave
00867         {
00868             // KPropertiesDialog will use stat to get more info on the file
00869             KPropertiesDialog*dlg= new KPropertiesDialog( item->url(), d->m_parentWidget );
00870             dlg->showFileSharingPage();
00871 
00872             return;
00873         }
00874     }
00875     KPropertiesDialog*dlg=new KPropertiesDialog( m_lstItems, d->m_parentWidget );
00876     dlg->showFileSharingPage();
00877 }
00878 
00879 KonqPopupMenu::~KonqPopupMenu()
00880 {
00881   m_pluginList.clear();
00882   delete m_factory;
00883   delete m_builder;
00884   delete d;
00885   kdDebug(1203) << "~KonqPopupMenu leave" << endl;
00886 }
00887 
00888 void KonqPopupMenu::setURLTitle( const QString& urlTitle )
00889 {
00890     d->m_urlTitle = urlTitle;
00891 }
00892 
00893 void KonqPopupMenu::slotPopupNewView()
00894 {
00895   KURL::List::ConstIterator it = m_lstPopupURLs.begin();
00896   for ( ; it != m_lstPopupURLs.end(); it++ )
00897     (void) new KRun(*it);
00898 }
00899 
00900 void KonqPopupMenu::slotPopupNewDir()
00901 {
00902   if (m_lstPopupURLs.empty())
00903     return;
00904 
00905   KonqOperations::newDir(d->m_parentWidget, m_lstPopupURLs.first());
00906 }
00907 
00908 void KonqPopupMenu::slotPopupEmptyTrashBin()
00909 {
00910   KonqOperations::emptyTrash();
00911 }
00912 
00913 void KonqPopupMenu::slotPopupOpenWith()
00914 {
00915   KRun::displayOpenWithDialog( m_lstPopupURLs );
00916 }
00917 
00918 void KonqPopupMenu::slotPopupAddToBookmark()
00919 {
00920   KBookmarkGroup root;
00921   if ( m_lstPopupURLs.count() == 1 ) {
00922     KURL url = m_lstPopupURLs.first();
00923     QString title = d->m_urlTitle.isEmpty() ? url.prettyURL() : d->m_urlTitle;
00924     root = m_pManager->addBookmarkDialog( url.prettyURL(), title );
00925   }
00926   else
00927   {
00928     root = m_pManager->root();
00929     KURL::List::ConstIterator it = m_lstPopupURLs.begin();
00930     for ( ; it != m_lstPopupURLs.end(); it++ )
00931       root.addBookmark( m_pManager, (*it).prettyURL(), (*it) );
00932   }
00933   m_pManager->emitChanged( root );
00934 }
00935 
00936 void KonqPopupMenu::slotRunService()
00937 {
00938   QCString senderName = sender()->name();
00939   int id = senderName.mid( senderName.find( '_' ) + 1 ).toInt();
00940 
00941   // Is it a usual service (application)
00942   QMap<int,KService::Ptr>::Iterator it = m_mapPopup.find( id );
00943   if ( it != m_mapPopup.end() )
00944   {
00945     KRun::run( **it, m_lstPopupURLs );
00946     return;
00947   }
00948 
00949   // Is it a service specific to desktop entry files ?
00950   QMap<int,KDEDesktopMimeType::Service>::Iterator it2 = m_mapPopupServices.find( id );
00951   if ( it2 != m_mapPopupServices.end() )
00952   {
00953       KDEDesktopMimeType::executeService( m_lstPopupURLs, it2.data() );
00954   }
00955 
00956   return;
00957 }
00958 
00959 void KonqPopupMenu::slotPopupMimeType()
00960 {
00961   KonqOperations::editMimeType( m_sMimeType );
00962 }
00963 
00964 void KonqPopupMenu::slotPopupProperties()
00965 {
00966     // It may be that the kfileitem was created by hand
00967     // (see KonqKfmIconView::slotMouseButtonPressed)
00968     // In that case, we can get more precise info in the properties
00969     // (like permissions) if we stat the URL.
00970     if ( m_lstItems.count() == 1 )
00971     {
00972         KFileItem * item = m_lstItems.first();
00973         if (item->entry().count() == 0) // this item wasn't listed by a slave
00974         {
00975             // KPropertiesDialog will use stat to get more info on the file
00976             (void) new KPropertiesDialog( item->url(), d->m_parentWidget );
00977             return;
00978         }
00979     }
00980     (void) new KPropertiesDialog( m_lstItems, d->m_parentWidget );
00981 }
00982 
00983 KAction *KonqPopupMenu::action( const QDomElement &element ) const
00984 {
00985   QCString name = element.attribute( attrName ).ascii();
00986   KAction *res = m_ownActions.action( name );
00987 
00988   if ( !res )
00989     res = m_actions.action( name );
00990 
00991   if ( !res && m_pMenuNew && strcmp( name, m_pMenuNew->name() ) == 0 )
00992     return m_pMenuNew;
00993 
00994   return res;
00995 }
00996 KActionCollection *KonqPopupMenu::actionCollection() const
00997 {
00998   return const_cast<KActionCollection *>( &m_ownActions );
00999 }
01000 
01001 QString KonqPopupMenu::mimeType( ) const {
01002     return m_sMimeType;
01003 }
01004 KonqPopupMenu::ProtocolInfo KonqPopupMenu::protocolInfo() const
01005 {
01006   return m_info;
01007 }
01008 void KonqPopupMenu::addPlugins( ){
01009         // search for Konq_PopupMenuPlugins inspired by simons kpropsdlg
01010         //search for a plugin with the right protocol
01011         KTrader::OfferList plugin_offers;
01012         unsigned int pluginCount = 0;
01013         plugin_offers = KTrader::self()->query( m_sMimeType.isNull() ? QString::fromLatin1( "all/all" ) : m_sMimeType , "'KonqPopupMenu/Plugin' in ServiceTypes");
01014         if ( plugin_offers.isEmpty() )
01015           return; // no plugins installed do not bother about it
01016 
01017         KTrader::OfferList::ConstIterator iterator = plugin_offers.begin( );
01018         KTrader::OfferList::ConstIterator end = plugin_offers.end( );
01019 
01020         addGroup( "plugins" );
01021         // travers the offerlist
01022         for(; iterator != end; ++iterator, ++pluginCount ){
01023                 KonqPopupMenuPlugin *plugin =
01024                         KParts::ComponentFactory::
01025                         createInstanceFromLibrary<KonqPopupMenuPlugin>( (*iterator)->library().local8Bit(),
01026                                                                         this,
01027                                                                         (*iterator)->name().latin1() );
01028                 if ( !plugin )
01029                         continue;
01030                 QString pluginClientName = QString::fromLatin1( "Plugin%1" ).arg( pluginCount );
01031                 addMerge( pluginClientName );
01032                 plugin->domDocument().documentElement().setAttribute( "name", pluginClientName );
01033                 m_pluginList.append( plugin );
01034                 insertChildClient( plugin );
01035         }
01036 
01037         addMerge( "plugins" );
01038         addSeparator();
01039 }
01040 KURL KonqPopupMenu::url( ) const {
01041   return m_sViewURL;
01042 }
01043 KFileItemList KonqPopupMenu::fileItemList( ) const {
01044   return m_lstItems;
01045 }
01046 KURL::List KonqPopupMenu::popupURLList( ) const {
01047   return m_lstPopupURLs;
01048 }
01053 KonqPopupMenuPlugin::KonqPopupMenuPlugin( KonqPopupMenu *parent, const char *name )
01054     : QObject( parent, name ) {
01055 }
01056 KonqPopupMenuPlugin::~KonqPopupMenuPlugin( ){
01057 
01058 }
01059 #include "konq_popupmenu.moc"
KDE Logo
This file is part of the documentation for libkonq Library Version 3.3.90.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 5 03:59:20 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003