File indexing completed on 2025-01-19 03:50:38
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2009-02-15 0007 * Description : contextmenu helper class - Services methods. 0008 * 0009 * SPDX-FileCopyrightText: 2009-2011 by Andi Clemens <andi dot clemens at gmail dot com> 0010 * SPDX-FileCopyrightText: 2010-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "contextmenuhelper_p.h" 0017 0018 namespace Digikam 0019 { 0020 0021 void ContextMenuHelper::addServicesMenu(const QList<QUrl>& selectedItems) 0022 { 0023 setSelectedItems(selectedItems); 0024 0025 #ifdef Q_OS_WIN 0026 0027 if (selectedItems.length() == 1) 0028 { 0029 QAction* const openWith = new QAction(i18nc("@action: context menu", "Open With"), this); 0030 addAction(openWith); 0031 0032 connect(openWith, SIGNAL(triggered()), 0033 this, SLOT(slotOpenWith())); 0034 } 0035 0036 #elif defined Q_OS_MAC 0037 0038 QList<QUrl> appUrls = DServiceMenu::MacApplicationsForFiles(selectedItems); 0039 0040 if (!appUrls.isEmpty()) 0041 { 0042 QMenu* const servicesMenu = new QMenu(d->parent); 0043 qDeleteAll(servicesMenu->actions()); 0044 0045 QAction* const serviceAction = servicesMenu->menuAction(); 0046 serviceAction->setText(i18nc("@action: context menu", "Open With")); 0047 0048 Q_FOREACH (const QUrl& aurl, appUrls) 0049 { 0050 QAction* const action = servicesMenu->addAction(DServiceMenu::MacApplicationBundleName(aurl)); 0051 action->setIcon(DServiceMenu::MacApplicationBundleIcon(aurl)); 0052 action->setData(aurl); 0053 } 0054 0055 addAction(serviceAction); 0056 0057 connect(servicesMenu, SIGNAL(triggered(QAction*)), 0058 this, SLOT(slotOpenWith(QAction*))); 0059 } 0060 0061 #else // LINUX 0062 0063 KService::List offers = DServiceMenu::servicesForOpenWith(selectedItems); 0064 0065 if (!offers.isEmpty()) 0066 { 0067 QMenu* const servicesMenu = new QMenu(d->parent); 0068 qDeleteAll(servicesMenu->actions()); 0069 0070 QAction* const serviceAction = servicesMenu->menuAction(); 0071 serviceAction->setText(i18nc("@action: context menu", "Open With")); 0072 0073 Q_FOREACH (const KService::Ptr& service, offers) 0074 { 0075 QString name = service->name().replace(QLatin1Char('&'), QLatin1String("&&")); 0076 QAction* const action = servicesMenu->addAction(name); 0077 action->setIcon(QIcon::fromTheme(service->icon())); 0078 action->setData(service->name()); 0079 d->servicesMap[name] = service; 0080 } 0081 0082 # ifdef HAVE_KIO 0083 0084 servicesMenu->addSeparator(); 0085 servicesMenu->addAction(i18nc("@action: open item with other application", "Other...")); 0086 0087 addAction(serviceAction); 0088 0089 connect(servicesMenu, SIGNAL(triggered(QAction*)), 0090 this, SLOT(slotOpenWith(QAction*))); 0091 } 0092 else 0093 { 0094 QAction* const serviceAction = new QAction(i18nc("@action: context menu", "Open With..."), this); 0095 addAction(serviceAction); 0096 0097 connect(serviceAction, SIGNAL(triggered()), 0098 this, SLOT(slotOpenWith())); 0099 0100 # endif // HAVE_KIO 0101 0102 } 0103 0104 #endif // Q_OS_WIN 0105 0106 } 0107 0108 void ContextMenuHelper::slotOpenWith() 0109 { 0110 // call the slot with an "empty" action 0111 0112 slotOpenWith(nullptr); 0113 } 0114 0115 void ContextMenuHelper::slotOpenWith(QAction* action) 0116 { 0117 0118 #ifdef Q_OS_WIN 0119 0120 Q_UNUSED(action); 0121 0122 // See Bug #380065 for details. 0123 0124 if (d->selectedItems.length() == 1) 0125 { 0126 SHELLEXECUTEINFO sei = {}; 0127 sei.cbSize = sizeof(sei); 0128 sei.fMask = SEE_MASK_INVOKEIDLIST | SEE_MASK_NOASYNC; 0129 sei.nShow = SW_SHOWNORMAL; 0130 sei.lpVerb = (LPCWSTR)QString::fromLatin1("openas").utf16(); 0131 sei.lpFile = (LPCWSTR)QDir::toNativeSeparators(d->selectedItems.first().toLocalFile()).utf16(); 0132 ShellExecuteEx(&sei); 0133 0134 qCDebug(DIGIKAM_GENERAL_LOG) << "ShellExecuteEx::openas return code:" << GetLastError(); 0135 } 0136 0137 #elif defined Q_OS_MAC 0138 0139 QList<QUrl> list = d->selectedItems; 0140 QUrl aurl = action ? action->data().toUrl() : QUrl(); 0141 0142 if (!aurl.isEmpty()) 0143 { 0144 DServiceMenu::MacOpenFilesWithApplication(list, aurl); 0145 } 0146 0147 #else // LINUX 0148 0149 KService::Ptr service; 0150 QList<QUrl> list = d->selectedItems; 0151 QString name = action ? action->data().toString() : QString(); 0152 0153 # ifdef HAVE_KIO 0154 0155 if (name.isEmpty()) 0156 { 0157 QPointer<KOpenWithDialog> dlg = new KOpenWithDialog(list); 0158 0159 if (dlg->exec() != KOpenWithDialog::Accepted) 0160 { 0161 delete dlg; 0162 return; 0163 } 0164 0165 service = dlg->service(); 0166 0167 if (!service) 0168 { 0169 // User entered a custom command 0170 0171 if (!dlg->text().isEmpty()) 0172 { 0173 DServiceMenu::runFiles(dlg->text(), list); 0174 } 0175 0176 delete dlg; 0177 return; 0178 } 0179 0180 delete dlg; 0181 } 0182 else 0183 0184 # endif // HAVE_KIO 0185 0186 { 0187 service = d->servicesMap[name]; 0188 } 0189 0190 DServiceMenu::runFiles(service, list); 0191 0192 #endif // Q_OS_WIN 0193 0194 } 0195 0196 void ContextMenuHelper::slotOpenInFileManager() 0197 { 0198 DFileOperations::openInFileManager(d->selectedItems); 0199 } 0200 0201 } // namespace Digikam