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