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 }