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