File indexing completed on 2024-05-12 16:28:29
0001 /* This file is part of the KDE project 0002 Copyright (C) 2010 Jarosław Staniek <staniek@kde.org> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include <QTextStream> 0021 #include <QCommandLineParser> 0022 #include <QApplication> 0023 #include <QUrl> 0024 #include <QDebug> 0025 #include <QMimeDatabase> 0026 0027 #include <KAboutData> 0028 #include <klocalizedstring.h> 0029 #include <kmimetypetrader.h> 0030 #include <KServiceTypeTrader> 0031 #include <krun.h> 0032 #include <ktoolinvocation.h> 0033 #include <kmessagebox.h> 0034 #include <kguiitem.h> 0035 0036 #include <calligraversion.h> 0037 0038 static void listApplicationNames() 0039 { 0040 const KService::List services = KServiceTypeTrader::self()->query("Calligra/Application"); 0041 QTextStream out(stdout, QIODevice::WriteOnly); 0042 QStringList names; 0043 foreach (KService::Ptr service, services) { 0044 names.append(service->desktopEntryName()); 0045 } 0046 names.sort(); 0047 foreach (const QString& name, names) { 0048 out << name << '\n'; 0049 } 0050 } 0051 0052 static void showWelcomeWindow() 0053 { 0054 } 0055 0056 static bool startService(KService::Ptr service, const QUrl& url) 0057 { 0058 qDebug() << "service->entryPath():" << service->entryPath(); 0059 QString error; 0060 QString serviceName; 0061 int pid = 0; 0062 int res = KToolInvocation::startServiceByDesktopPath( 0063 service->entryPath(), url.url(), &error, &serviceName, &pid 0064 ); 0065 // could not check result - does not work for custom KDEDIRS: ok = res == 0; 0066 //ok = true; 0067 qDebug() << "KToolInvocation::startServiceByDesktopPath:" << res << pid << error << serviceName; 0068 return res == 0; 0069 } 0070 0071 static int handleUrls(const QStringList& files) 0072 { 0073 KMimeTypeTrader* mimeTrader = KMimeTypeTrader::self(); 0074 QList<QUrl> notHandledUrls; 0075 const QRegExp withProtocolChecker( QStringLiteral("^[a-zA-Z]+:") ); 0076 foreach(const QString& file, files) { 0077 // convert to an url 0078 const bool startsWithProtocol = (withProtocolChecker.indexIn(file) == 0); 0079 QUrl url = startsWithProtocol ? QUrl::fromUserInput(file) : QUrl::fromLocalFile(file); 0080 const QMimeType mimetype = QMimeDatabase().mimeTypeForUrl(url); 0081 if (mimetype.isDefault()) { 0082 KMessageBox::error(0, i18nc("@info", "Mimetype for <filename>%1</filename> not found!", 0083 url.toString())); 0084 return 1; 0085 } 0086 qDebug() << url << mimetype.name(); 0087 /* 0088 Find apps marked with Calligra/Applications service type 0089 and having given mimetype on the X-Calligra-Default-MimeTypes list. 0090 This is needed because, single mimetype can be supported by more than 0091 one Calligra application but only one application should be selected 0092 for opening given document using the calligra command. 0093 0094 Example: application/vnd.oasis.opendocument.graphic, supported 0095 by Flow and Karbon already; out of these two, Karbon is selected 0096 for opening the document. 0097 */ 0098 const QString constraint = QString("'%1' in [X-Calligra-DefaultMimeTypes]").arg(mimetype.name()); 0099 qDebug() << constraint; 0100 KService::List services; 0101 KService::List offers = KServiceTypeTrader::self()->query("Calligra/Application"); 0102 foreach(KService::Ptr offer, offers) { 0103 QStringList defaultMimeTypes = offer->property("X-Calligra-DefaultMimeTypes").toStringList(); 0104 if (defaultMimeTypes.contains(mimetype.name())) { 0105 services << offer; 0106 } 0107 } 0108 0109 KService::Ptr service; 0110 //bool ok = false; 0111 if (!services.isEmpty()) { 0112 service = services.first(); 0113 qDebug() << "-" << service->name() << service->property("X-Calligra-DefaultMimeTypes"); 0114 #if 0 0115 ok = KRun::run(*service.data(), QList<QUrl>() << url, 0); 0116 qDebug() << "KRun::run:" << ok; 0117 #else 0118 startService(service, url); 0119 return 0; 0120 #endif 0121 } 0122 //if (!ok) { 0123 // if above not found or app cannot be executed: 0124 KService::List mimeServices = mimeTrader->query(mimetype.name(), "Calligra/Application"); 0125 qDebug() << "Found" << mimeServices.count() << "services by MimeType field:"; 0126 foreach (KService::Ptr service, mimeServices) { 0127 //qDebug() << "-" << service->name() << service->property("X-DBUS-ServiceName", QVariant::String); 0128 qDebug() << "-" << service->name() << service->hasServiceType("Calligra/Application") 0129 << service->hasMimeType(mimetype.name()); 0130 //QVariant isCalligraApp = service->property("X-Calligra-App", QVariant::Bool); 0131 /*if (isCalligraApp.isValid() && isCalligraApp.toBool()) { 0132 qDebug() << "FOUND:" << service->name(); 0133 }*/ 0134 } 0135 if (mimeServices.isEmpty()) { 0136 service = mimeTrader->preferredService(mimetype.name()); 0137 qDebug() << "mimeTrader->preferredService():" << service->name(); 0138 if (service) { 0139 KGuiItem openItem(KStandardGuiItem::open()); 0140 openItem.setText(i18nc("@action:button", "Open with <application>%1</application>", 0141 service->property("Name").toString())); 0142 if (KMessageBox::Yes != KMessageBox::questionYesNo( 0143 0, 0144 i18nc("@info", 0145 "Could not find Calligra application suitable for opening <filename>%1</filename>.<nl/>" 0146 "Do you want to open the file using default application <application>%2</application>?", 0147 url.url(), service->property("Name").toString()), 0148 i18nc("@title:window", "Calligra Application Not Found"), openItem, KStandardGuiItem::cancel())) 0149 { 0150 return 2; 0151 } 0152 } 0153 } 0154 else { 0155 service = mimeServices.first(); 0156 } 0157 if (service) { 0158 startService(service, url); 0159 return 0; 0160 } 0161 else { 0162 notHandledUrls.append(url); 0163 } 0164 //} 0165 } 0166 if (!notHandledUrls.isEmpty()) { 0167 KRun::displayOpenWithDialog(notHandledUrls, 0); 0168 return 0; 0169 } 0170 return 0; 0171 } 0172 0173 int main( int argc, char **argv ) 0174 { 0175 QApplication app(argc, argv); 0176 KLocalizedString::setApplicationDomain( "calligra-opener" ); 0177 0178 KAboutData aboutData("calligra", i18n("Calligra Opener"), 0179 QStringLiteral(CALLIGRA_VERSION_STRING), 0180 i18n("Calligra Document Opener"), 0181 KAboutLicense::GPL, 0182 i18n("Copyright 2010-%1 Calligra developers", QStringLiteral(CALLIGRA_YEAR))); 0183 aboutData.addAuthor(i18n("Jarosław Staniek"), QString(), "staniek@kde.org"); 0184 0185 KAboutData::setApplicationData(aboutData); 0186 0187 QCommandLineParser parser; 0188 aboutData.setupCommandLine(&parser); 0189 0190 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("apps"), i18n("Lists names of all available Calligra applications"))); 0191 parser.addPositionalArgument(QStringLiteral("[FILE(S)]"), i18n("Files to open")); 0192 0193 parser.process(app); 0194 aboutData.processCommandLine(&parser); 0195 0196 if (parser.isSet("apps")) { 0197 listApplicationNames(); 0198 return 0; 0199 } 0200 const QStringList files = parser.positionalArguments(); 0201 if (files.isEmpty()) { 0202 //! @todo show cool Welcome window for app selection 0203 showWelcomeWindow(); 0204 } 0205 else { 0206 return handleUrls(files); 0207 } 0208 return 0; 0209 }