• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KIO

kfileitemactions.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 1998-2009 David Faure <faure@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or modify
00005    it under the terms of the GNU Library General Public License as published
00006    by the Free Software Foundation; either version 2 of the License or
00007    ( at your option ) version 3 or, at the discretion of KDE e.V.
00008    ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kfileitemactions.h"
00022 #include "kfileitemactions_p.h"
00023 #include <kaction.h>
00024 #include <krun.h>
00025 #include <kmimetypetrader.h>
00026 #include <kdebug.h>
00027 #include <kdesktopfileactions.h>
00028 #include <kmenu.h>
00029 #include <klocale.h>
00030 #include <kauthorized.h>
00031 #include <kconfiggroup.h>
00032 #include <kdesktopfile.h>
00033 #include <kglobal.h>
00034 #include <kicon.h>
00035 #include <kstandarddirs.h>
00036 #include <kservice.h>
00037 #include <kservicetypetrader.h>
00038 #include <QFile>
00039 
00040 #include <QtDBus/QtDBus>
00041 
00042 static bool KIOSKAuthorizedAction(const KConfigGroup& cfg)
00043 {
00044     if (!cfg.hasKey("X-KDE-AuthorizeAction")) {
00045         return true;
00046     }
00047     const QStringList list = cfg.readEntry("X-KDE-AuthorizeAction", QStringList());
00048     for(QStringList::ConstIterator it = list.constBegin();
00049         it != list.constEnd(); ++it) {
00050         if (!KAuthorized::authorize((*it).trimmed())) {
00051             return false;
00052         }
00053     }
00054     return true;
00055 }
00056 
00057 // This helper class stores the .desktop-file actions and the servicemenus
00058 // in order to support X-KDE-Priority and X-KDE-Submenu.
00059 namespace KIO {
00060 class PopupServices
00061 {
00062 public:
00063     ServiceList& selectList(const QString& priority, const QString& submenuName);
00064 
00065     ServiceList builtin;
00066     ServiceList user, userToplevel, userPriority;
00067     QMap<QString, ServiceList> userSubmenus, userToplevelSubmenus, userPrioritySubmenus;
00068 };
00069 
00070 ServiceList& PopupServices::selectList(const QString& priority, const QString& submenuName)
00071 {
00072     // we use the categories .desktop entry to define submenus
00073     // if none is defined, we just pop it in the main menu
00074     if (submenuName.isEmpty()) {
00075         if (priority == "TopLevel") {
00076             return userToplevel;
00077         } else if (priority == "Important") {
00078             return userPriority;
00079         }
00080     } else if (priority == "TopLevel") {
00081         return userToplevelSubmenus[submenuName];
00082     } else if (priority == "Important") {
00083         return userPrioritySubmenus[submenuName];
00084     } else {
00085         return userSubmenus[submenuName];
00086     }
00087     return user;
00088 }
00089 } // namespace
00090 
00092 
00093 KFileItemActionsPrivate::KFileItemActionsPrivate()
00094     : QObject(),
00095       m_executeServiceActionGroup(static_cast<QWidget *>(0)),
00096       m_runApplicationActionGroup(static_cast<QWidget *>(0)),
00097       m_parentWidget(0)
00098 {
00099     QObject::connect(&m_executeServiceActionGroup, SIGNAL(triggered(QAction*)),
00100                      this, SLOT(slotExecuteService(QAction*)));
00101     QObject::connect(&m_runApplicationActionGroup, SIGNAL(triggered(QAction*)),
00102                      this, SLOT(slotRunApplication(QAction*)));
00103 }
00104 
00105 KFileItemActionsPrivate::~KFileItemActionsPrivate()
00106 {
00107     qDeleteAll(m_ownActions);
00108 }
00109 
00110 int KFileItemActionsPrivate::insertServicesSubmenus(const QMap<QString, ServiceList>& submenus,
00111                                                    QMenu* menu,
00112                                                    bool isBuiltin)
00113 {
00114     int count = 0;
00115     QMap<QString, ServiceList>::ConstIterator it;
00116     for (it = submenus.begin(); it != submenus.end(); ++it) {
00117         if (it.value().isEmpty()) {
00118             //avoid empty sub-menus
00119             continue;
00120         }
00121 
00122         QMenu* actionSubmenu = new KMenu(menu);
00123         actionSubmenu->setTitle(it.key());
00124         actionSubmenu->menuAction()->setObjectName("services_submenu"); // for the unittest
00125         menu->addMenu(actionSubmenu);
00126         count += insertServices(it.value(), actionSubmenu, isBuiltin);
00127     }
00128 
00129     return count;
00130 }
00131 
00132 int KFileItemActionsPrivate::insertServices(const ServiceList& list,
00133                                            QMenu* menu,
00134                                            bool isBuiltin)
00135 {
00136     int count = 0;
00137     ServiceList::const_iterator it = list.begin();
00138     for(; it != list.end(); ++it) {
00139         if ((*it).isSeparator()) {
00140             const QList<QAction*> actions = menu->actions();
00141             if (!actions.isEmpty() && !actions.last()->isSeparator()) {
00142                 menu->addSeparator();
00143             }
00144             continue;
00145         }
00146 
00147         if (isBuiltin || !(*it).noDisplay()) {
00148             KAction *act = new KAction(m_parentWidget);
00149             m_ownActions.append(act);
00150             act->setObjectName("menuaction"); // for the unittest
00151             QString text = (*it).text();
00152             text.replace('&',"&&");
00153             act->setText(text);
00154             if (!(*it).icon().isEmpty()) {
00155                 act->setIcon(KIcon((*it).icon()));
00156             }
00157             act->setData(QVariant::fromValue(*it));
00158             m_executeServiceActionGroup.addAction(act);
00159 
00160             menu->addAction(act); // Add to toplevel menu
00161             ++count;
00162         }
00163     }
00164 
00165     return count;
00166 }
00167 
00168 void KFileItemActionsPrivate::slotExecuteService(QAction* act)
00169 {
00170     KServiceAction serviceAction = act->data().value<KServiceAction>();
00171     KDesktopFileActions::executeService(m_props.urlList(), serviceAction);
00172 }
00173 
00175 
00176 KFileItemActions::KFileItemActions(QObject* parent)
00177     : QObject(parent), d(new KFileItemActionsPrivate)
00178 {
00179 }
00180 
00181 
00182 KFileItemActions::~KFileItemActions()
00183 {
00184     delete d;
00185 }
00186 
00187 void KFileItemActions::setItemListProperties(const KFileItemListProperties& itemListProperties)
00188 {
00189     d->m_props = itemListProperties;
00190 }
00191 
00192 int KFileItemActions::addServiceActionsTo(QMenu* mainMenu)
00193 {
00194     const KFileItemList items = d->m_props.items();
00195     const KFileItem firstItem = items.first();
00196     const QString protocol = firstItem.url().protocol(); // assumed to be the same for all items
00197     const bool isLocal = !firstItem.localPath().isEmpty();
00198     const bool isSingleLocal = items.count() == 1 && isLocal;
00199     const KUrl::List urlList = d->m_props.urlList();
00200 
00201     KIO::PopupServices s;
00202 
00203     // 1 - Look for builtin and user-defined services
00204     if (isSingleLocal && d->m_props.mimeType() == "application/x-desktop") { // .desktop file
00205         // get builtin services, like mount/unmount
00206         const QString path = firstItem.localPath();
00207         s.builtin = KDesktopFileActions::builtinServices(path);
00208         KDesktopFile desktopFile(path);
00209         KConfigGroup cfg = desktopFile.desktopGroup();
00210         const QString priority = cfg.readEntry("X-KDE-Priority");
00211         const QString submenuName = cfg.readEntry("X-KDE-Submenu");
00212 #if 0
00213         if (cfg.readEntry("Type") == "Link") {
00214            d->m_url = cfg.readEntry("URL");
00215            // TODO: Do we want to make all the actions apply on the target
00216            // of the .desktop file instead of the .desktop file itself?
00217         }
00218 #endif
00219         ServiceList& list = s.selectList(priority, submenuName);
00220         list = KDesktopFileActions::userDefinedServices(path, desktopFile, true /*isLocal*/);
00221     }
00222 
00223     // 2 - Look for "servicemenus" bindings (user-defined services)
00224 
00225     // first check the .directory if this is a directory
00226     if (d->m_props.isDirectory() && isSingleLocal) {
00227         QString dotDirectoryFile = KUrl::fromPath(firstItem.localPath()).path(KUrl::AddTrailingSlash).append(".directory");
00228         if (QFile::exists(dotDirectoryFile)) {
00229             const KDesktopFile desktopFile(dotDirectoryFile);
00230             const KConfigGroup cfg = desktopFile.desktopGroup();
00231 
00232             if (KIOSKAuthorizedAction(cfg)) {
00233                 const QString priority = cfg.readEntry("X-KDE-Priority");
00234                 const QString submenuName = cfg.readEntry("X-KDE-Submenu");
00235                 ServiceList& list = s.selectList(priority, submenuName);
00236                 list += KDesktopFileActions::userDefinedServices(dotDirectoryFile, desktopFile, true);
00237             }
00238         }
00239     }
00240 
00241     const KConfig config("kservicemenurc", KConfig::NoGlobals);
00242     const KConfigGroup showGroup = config.group("Show");
00243 
00244     const QString commonMimeType = d->m_props.mimeType();
00245     const QString commonMimeGroup = d->m_props.mimeGroup();
00246     const KMimeType::Ptr mimeTypePtr = commonMimeType.isEmpty() ? KMimeType::Ptr() : KMimeType::mimeType(commonMimeType);
00247     const KService::List entries = KServiceTypeTrader::self()->query("KonqPopupMenu/Plugin");
00248     KService::List::const_iterator eEnd = entries.end();
00249     for (KService::List::const_iterator it2 = entries.begin(); it2 != eEnd; ++it2) {
00250         QString file = KStandardDirs::locate("services", (*it2)->entryPath());
00251         KDesktopFile desktopFile(file);
00252         const KConfigGroup cfg = desktopFile.desktopGroup();
00253 
00254         if (!KIOSKAuthorizedAction(cfg)) {
00255             continue;
00256         }
00257 
00258         if (cfg.hasKey("X-KDE-ShowIfRunning")) {
00259             const QString app = cfg.readEntry("X-KDE-ShowIfRunning");
00260             if (QDBusConnection::sessionBus().interface()->isServiceRegistered(app)) {
00261                 continue;
00262             }
00263         }
00264         if (cfg.hasKey("X-KDE-ShowIfDBusCall")) {
00265             QString calldata = cfg.readEntry("X-KDE-ShowIfDBusCall");
00266             QStringList parts = calldata.split(' ');
00267             const QString &app = parts.at(0);
00268             const QString &obj = parts.at(1);
00269             QString interface = parts.at(2);
00270             QString method;
00271             int pos = interface.lastIndexOf(QLatin1Char('.'));
00272             if (pos != -1) {
00273                 method = interface.mid(pos + 1);
00274                 interface.truncate(pos);
00275             }
00276 
00277             //if (!QDBus::sessionBus().busService()->nameHasOwner(app))
00278             //    continue; //app does not exist so cannot send call
00279 
00280             QDBusMessage reply = QDBusInterface(app, obj, interface).
00281                                  call(method, urlList.toStringList());
00282             if (reply.arguments().count() < 1 || reply.arguments().at(0).type() != QVariant::Bool || !reply.arguments().at(0).toBool()) {
00283                 continue;
00284             }
00285 
00286         }
00287         if (cfg.hasKey("X-KDE-Protocol")) {
00288             const QString protocol = cfg.readEntry("X-KDE-Protocol");
00289             if (protocol.startsWith('!')) {
00290                 const QString excludedProtocol = protocol.mid(1);
00291                 if (excludedProtocol == protocol) {
00292                     continue;
00293                 }
00294             } else if (protocol != protocol) {
00295                 continue;
00296             }
00297         }
00298         else if (cfg.hasKey("X-KDE-Protocols")) {
00299             const QStringList protocols = cfg.readEntry("X-KDE-Protocols", QStringList());
00300             if (!protocols.contains(protocol)) {
00301                 continue;
00302             }
00303         }
00304         else if (protocol == "trash") {
00305             // Require servicemenus for the trash to ask for protocol=trash explicitly.
00306             // Trashed files aren't supposed to be available for actions.
00307             // One might want a servicemenu for trash.desktop itself though.
00308             continue;
00309         }
00310 
00311         if (cfg.hasKey("X-KDE-Require")) {
00312             const QStringList capabilities = cfg.readEntry("X-KDE-Require" , QStringList());
00313             if (capabilities.contains("Write") && !d->m_props.supportsWriting()) {
00314                 continue;
00315             }
00316         }
00317         if (cfg.hasKey("Actions") || cfg.hasKey("X-KDE-GetActionMenu")) {
00318             // Like KService, we support ServiceTypes, X-KDE-ServiceTypes, and MimeType.
00319             QStringList types = cfg.readEntry("ServiceTypes", QStringList());
00320             types += cfg.readEntry("X-KDE-ServiceTypes", QStringList());
00321             types += cfg.readXdgListEntry("MimeType");
00322             //kDebug() << file << types;
00323 
00324             if (types.isEmpty()) {
00325                 continue;
00326             }
00327             const QStringList excludeTypes = cfg.readEntry("ExcludeServiceTypes" , QStringList());
00328             bool ok = false;
00329 
00330             // check for exact matches or a typeglob'd mimetype if we have a mimetype
00331             for (QStringList::ConstIterator it = types.constBegin();
00332                  it != types.constEnd() && !ok;
00333                  ++it)
00334             {
00335                 // first check if we have an all mimetype
00336                 bool checkTheMimetypes = false;
00337                 if (*it == "all/all" ||
00338                     *it == "allfiles" /*compat with KDE up to 3.0.3*/) {
00339                     checkTheMimetypes = true;
00340                 }
00341 
00342                 // next, do we match all files?
00343                 if (!ok &&
00344                     !d->m_props.isDirectory() &&
00345                     *it == "all/allfiles") {
00346                     checkTheMimetypes = true;
00347                 }
00348 
00349                 // if we have a mimetype, see if we have an exact or a type globbed match
00350                 if (!ok && (
00351                     (mimeTypePtr && mimeTypePtr->is(*it)) ||
00352                     (!commonMimeGroup.isEmpty() &&
00353                      ((*it).right(1) == "*" &&
00354                       (*it).left((*it).indexOf('/')) == commonMimeGroup)))) {
00355                     checkTheMimetypes = true;
00356                 }
00357 
00358                 if (checkTheMimetypes) {
00359                     ok = true;
00360                     for (QStringList::ConstIterator itex = excludeTypes.constBegin(); itex != excludeTypes.constEnd(); ++itex) {
00361                         if(((*itex).endsWith('*') && (*itex).left((*itex).indexOf('/')) == commonMimeGroup) ||
00362                             ((*itex) == commonMimeType)) {
00363                             ok = false;
00364                             break;
00365                         }
00366                     }
00367                 }
00368             }
00369 
00370             if (ok) {
00371                 const QString priority = cfg.readEntry("X-KDE-Priority");
00372                 const QString submenuName = cfg.readEntry("X-KDE-Submenu");
00373 
00374                 ServiceList& list = s.selectList(priority, submenuName);
00375                 const ServiceList userServices = KDesktopFileActions::userDefinedServices(*(*it2), isLocal, urlList);
00376                 foreach (const KServiceAction& action, userServices) {
00377                     if (showGroup.readEntry(action.name(), true)) {
00378                         list += action;
00379                     }
00380                 }
00381             }
00382         }
00383     }
00384 
00385 
00386 
00387     QMenu* actionMenu = mainMenu;
00388     int userItemCount = 0;
00389     if (s.user.count() + s.userSubmenus.count() +
00390         s.userPriority.count() + s.userPrioritySubmenus.count() > 1) {
00391         // we have more than one item, so let's make a submenu
00392         actionMenu = new KMenu(i18nc("@title:menu", "&Actions"), mainMenu);
00393         actionMenu->menuAction()->setObjectName("actions_submenu"); // for the unittest
00394         mainMenu->addMenu(actionMenu);
00395     }
00396 
00397     userItemCount += d->insertServicesSubmenus(s.userPrioritySubmenus, actionMenu, false);
00398     userItemCount += d->insertServices(s.userPriority, actionMenu, false);
00399 
00400     // see if we need to put a separator between our priority items and our regular items
00401     if (userItemCount > 0 &&
00402         (s.user.count() > 0 ||
00403          s.userSubmenus.count() > 0 ||
00404          s.builtin.count() > 0) &&
00405         !actionMenu->actions().last()->isSeparator()) {
00406         actionMenu->addSeparator();
00407     }
00408     userItemCount += d->insertServicesSubmenus(s.userSubmenus, actionMenu, false);
00409     userItemCount += d->insertServices(s.user, actionMenu, false);
00410     userItemCount += d->insertServices(s.builtin, mainMenu, true);
00411     userItemCount += d->insertServicesSubmenus(s.userToplevelSubmenus, mainMenu, false);
00412     userItemCount += d->insertServices(s.userToplevel, mainMenu, false);
00413     return userItemCount;
00414 }
00415 
00416 
00417 KService::List KFileItemActionsPrivate::associatedApplications(const QString& traderConstraint)
00418 {
00419     if (!KAuthorized::authorizeKAction("openwith")) {
00420         return KService::List();
00421     }
00422 
00423     const KFileItemList items = m_props.items();
00424     QStringList mimeTypeList;
00425     KFileItemList::const_iterator kit = items.constBegin();
00426     const KFileItemList::const_iterator kend = items.constEnd();
00427     for (; kit != kend; ++kit) {
00428         if (!mimeTypeList.contains((*kit).mimetype()))
00429             mimeTypeList << (*kit).mimetype();
00430     }
00431 
00432     QString constraint = traderConstraint;
00433     const QString subConstraint = " and '%1' in ServiceTypes";
00434 
00435     QStringList::ConstIterator it = mimeTypeList.constBegin();
00436     const QStringList::ConstIterator end = mimeTypeList.constEnd();
00437     Q_ASSERT(it != end);
00438     QString firstMimeType = *it;
00439     ++it;
00440     for (; it != end ; ++it) {
00441         constraint += subConstraint.arg(*it);
00442     }
00443 
00444     KService::List offers = KMimeTypeTrader::self()->query(firstMimeType, "Application", constraint);
00445 
00446     QSet<QString> seenTexts;
00447     for (KService::List::iterator it = offers.begin(); it != offers.end();) {
00448         bool skipThisEntry = false;
00449         // The offer list from the KTrader returns duplicate
00450         // application entries (kde3 and kde4). Although this is a configuration
00451         // problem, duplicated entries just will be skipped here.
00452         const KService::Ptr service = (*it);
00453         const QString appName(service->name());
00454         if (!seenTexts.contains(appName)) {
00455             seenTexts.insert(appName);
00456         } else {
00457             skipThisEntry = true;
00458         }
00459 
00460         if (!skipThisEntry) {
00461             // Skip OnlyShowIn=Foo and NotShowIn=KDE entries,
00462             // but still offer NoDisplay=true entries, that's the
00463             // whole point of such desktop files. This is why we don't
00464             // use service->noDisplay() here.
00465             const QString onlyShowIn = service->property("OnlyShowIn", QVariant::String).toString();
00466             if (!onlyShowIn.isEmpty()) {
00467                 const QStringList aList = onlyShowIn.split(';', QString::SkipEmptyParts);
00468                 if (!aList.contains("KDE")) {
00469                     skipThisEntry = true;
00470                 }
00471             }
00472             const QString notShowIn = service->property("NotShowIn", QVariant::String).toString();
00473             if (!notShowIn.isEmpty()) {
00474                 const QStringList aList = notShowIn.split(';', QString::SkipEmptyParts);
00475                 if (aList.contains("KDE")) {
00476                     skipThisEntry = true;
00477                 }
00478             }
00479         }
00480 
00481         if (skipThisEntry) {
00482             it = offers.erase(it);
00483         } else {
00484             ++it;
00485         }
00486     }
00487     return offers;
00488 }
00489 
00490 void KFileItemActions::addOpenWithActionsTo(QMenu* topMenu, const QString& traderConstraint)
00491 {
00492     const KService::List offers = d->associatedApplications(traderConstraint);
00493 
00495 
00496     const KFileItemList items = d->m_props.items();
00497     const KFileItem firstItem = items.first();
00498     const bool isLocal = firstItem.url().isLocalFile();
00499     // "Open With..." for folders is really not very useful, especially for remote folders.
00500     // (media:/something, or trash:/, or ftp://...)
00501     if (!d->m_props.isDirectory() || isLocal) {
00502         if (!topMenu->actions().isEmpty()) {
00503             topMenu->addSeparator();
00504         }
00505 
00506         if (!offers.isEmpty()) {
00507             QMenu* menu = topMenu;
00508 
00509             if (offers.count() > 1) { // submenu 'open with'
00510                 menu = new QMenu(i18nc("@title:menu", "&Open With"), topMenu);
00511                 menu->menuAction()->setObjectName("openWith_submenu"); // for the unittest
00512                 topMenu->addMenu(menu);
00513             }
00514             //kDebug() << offers.count() << "offers" << topMenu << menu;
00515 
00516             KService::List::ConstIterator it = offers.constBegin();
00517             for(; it != offers.constEnd(); it++) {
00518                 KAction* act = d->createAppAction(*it,
00519                                                   // no submenu -> prefix single offer
00520                                                   menu == topMenu);
00521                 menu->addAction(act);
00522             }
00523 
00524             QString openWithActionName;
00525             if (menu != topMenu) { // submenu
00526                 menu->addSeparator();
00527                 openWithActionName = i18nc("@action:inmenu Open With", "&Other...");
00528             } else {
00529                 openWithActionName = i18nc("@title:menu", "&Open With...");
00530             }
00531             KAction *openWithAct = new KAction(d->m_parentWidget);
00532             d->m_ownActions.append(openWithAct);
00533             openWithAct->setText(openWithActionName);
00534             QObject::connect(openWithAct, SIGNAL(triggered()), d, SLOT(slotOpenWithDialog()));
00535             menu->addAction(openWithAct);
00536         }
00537         else // no app offers -> Open With...
00538         {
00539             KAction *act = new KAction(d->m_parentWidget);
00540             d->m_ownActions.append(act);
00541             act->setText(i18nc("@title:menu", "&Open With..."));
00542             QObject::connect(act, SIGNAL(triggered()), d, SLOT(slotOpenWithDialog()));
00543             topMenu->addAction(act);
00544         }
00545 
00546     }
00547 }
00548 
00549 void KFileItemActionsPrivate::slotRunApplication(QAction* act)
00550 {
00551     // Is it an application, from one of the "Open With" actions
00552     KService::Ptr app = act->data().value<KService::Ptr>();
00553     Q_ASSERT(app);
00554     if (app) {
00555         KRun::run(*app, m_props.urlList(), m_parentWidget);
00556     }
00557 }
00558 
00559 void KFileItemActionsPrivate::slotOpenWithDialog()
00560 {
00561     // The item 'Other...' or 'Open With...' has been selected
00562     KRun::displayOpenWithDialog(m_props.urlList(), m_parentWidget);
00563 }
00564 
00565 KAction* KFileItemActionsPrivate::createAppAction(const KService::Ptr& service, bool singleOffer)
00566 {
00567     QString actionName(service->name().replace('&', "&&"));
00568     if (singleOffer) {
00569         actionName = i18n("Open &with %1", actionName);
00570     }
00571 
00572     KAction *act = new KAction(m_parentWidget);
00573     m_ownActions.append(act);
00574     act->setIcon(KIcon(service->icon()));
00575     act->setText(actionName);
00576     act->setData(QVariant::fromValue(service));
00577     m_runApplicationActionGroup.addAction(act);
00578     return act;
00579 }
00580 
00581 KAction* KFileItemActions::preferredOpenWithAction(const QString& traderConstraint)
00582 {
00583     const KService::List offers = d->associatedApplications(traderConstraint);
00584     if (offers.isEmpty()) {
00585         return 0;
00586     }
00587     return d->createAppAction(offers.first(), true);
00588 }
00589 
00590 void KFileItemActions::setParentWidget(QWidget* widget)
00591 {
00592     d->m_parentWidget = widget;
00593 }

KIO

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal