KoApplication.cpp 24.1 KB
Newer Older
Casper Boemann's avatar
Casper Boemann committed
1 2
/* This file is part of the KDE project
   Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3
   Copyright (C) 2009 Thomas Zander <zander@kde.org>
4
   Copyright (C) 2012 Boudewijn Rempt <boud@valdyas.org>
Casper Boemann's avatar
Casper Boemann committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

#include "KoApplication.h"
23

24
#include "KoGlobal.h"
25 26

#ifndef QT_NO_DBUS
Casper Boemann's avatar
Casper Boemann committed
27
#include "KoApplicationAdaptor.h"
28
#include <QtDBus>
29 30
#endif

31
#include "KoPrintJob.h"
32
#include "KoDocumentEntry.h"
33 34
#include "KoDocument.h"
#include "KoMainWindow.h"
35
#include "KoAutoSaveRecoveryDialog.h"
36
#include <KoDpi.h>
37
#include "KoPart.h"
38
#include <KoConfig.h>
39

Halla Rempt's avatar
Halla Rempt committed
40
#include <kdeversion.h>
Casper Boemann's avatar
Casper Boemann committed
41 42 43 44 45 46
#include <klocale.h>
#include <kcmdlineargs.h>
#include <kdesktopfile.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <kiconloader.h>
47
#include <kdebug.h>
48
#include <kmimetype.h>
49 50 51
#include <kconfig.h>
#include <kglobal.h>
#include <kconfiggroup.h>
Halla Rempt's avatar
Halla Rempt committed
52

53
#if KDE_IS_VERSION(4,6,0)
Halla Rempt's avatar
Halla Rempt committed
54
#include <krecentdirs.h>
55
#endif
Halla Rempt's avatar
Halla Rempt committed
56

57
#include <QFile>
58
#include <QWidget>
59
#include <QSysInfo>
60
#include <QStringList>
61 62 63 64 65 66
#include <QDesktopServices>
#include <QProcessEnvironment>
#include <QDir>

#include <stdlib.h>

67 68 69 70
#ifdef Q_OS_WIN
#include <windows.h>
#include <tchar.h>
#endif
71

72 73 74

#include <QDesktopWidget>

75 76
KoApplication* KoApplication::KoApp = 0;

77
namespace {
Yue Liu's avatar
Yue Liu committed
78
const QTime appStartTime(QTime::currentTime());
79 80
}

Casper Boemann's avatar
Casper Boemann committed
81 82 83
class KoApplicationPrivate
{
public:
84
    KoApplicationPrivate()
85 86
        : splashScreen(0)
    {}
87
    QByteArray nativeMimeType;
88
    QWidget *splashScreen;
89
    QList<KoPart *> partList;
Casper Boemann's avatar
Casper Boemann committed
90 91
};

92 93 94 95 96 97 98 99 100 101
class KoApplication::ResetStarting
{
public:
    ResetStarting(QWidget *splash = 0)
        : m_splash(splash)
    {
    }

    ~ResetStarting()  {
        if (m_splash) {
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122

            KConfigGroup cfg(KGlobal::config(), "SplashScreen");
            bool hideSplash = cfg.readEntry("HideSplashAfterStartup", false);

            if (hideSplash) {
                m_splash->hide();
            }
            else {
                m_splash->setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
                m_splash->setWindowModality(Qt::ApplicationModal);
                m_splash->setParent(qApp->activeWindow());
                QRect r(QPoint(), m_splash->size());
                m_splash->move(QApplication::desktop()->screenGeometry().center() - r.center());
                m_splash->show();
                foreach(QObject *o, m_splash->children()) {
                    QWidget *w = qobject_cast<QWidget*>(o);
                    if (w && w->isHidden()) {
                        w->setVisible(true);
                    }
                }
            }
123 124 125 126 127 128
        }
    }

    QWidget *m_splash;
};

129
KoApplication::KoApplication(const QByteArray &nativeMimeType)
Yue Liu's avatar
Yue Liu committed
130 131
    : KApplication(initHack())
    , d(new KoApplicationPrivate)
Casper Boemann's avatar
Casper Boemann committed
132
{
133 134 135
    KoApplication::KoApp = this;

    d->nativeMimeType = nativeMimeType;
Halla Rempt's avatar
Halla Rempt committed
136 137
    // Tell the iconloader about share/apps/calligra/icons
    KIconLoader::global()->addAppDir("calligra");
Casper Boemann's avatar
Casper Boemann committed
138

Halla Rempt's avatar
Halla Rempt committed
139
    // Initialize all Calligra directories etc.
Casper Boemann's avatar
Casper Boemann committed
140 141
    KoGlobal::initialize();

142
#ifndef QT_NO_DBUS
Casper Boemann's avatar
Casper Boemann committed
143 144
    new KoApplicationAdaptor(this);
    QDBusConnection::sessionBus().registerObject("/application", this);
145
#endif
Casper Boemann's avatar
Casper Boemann committed
146

147 148 149 150 151 152 153
#ifdef Q_OS_MACX
    if ( QSysInfo::MacintoshVersion > QSysInfo::MV_10_8 )
    {
        // fix Mac OS X 10.9 (mavericks) font issue
        // https://bugreports.qt-project.org/browse/QTBUG-32789
        QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
    }
Yue Liu's avatar
Yue Liu committed
154

Yue Liu's avatar
Yue Liu committed
155
    setAttribute(Qt::AA_DontShowIconsInMenus, true);
156
#endif
157

158
    if (applicationName() == "krita" && qgetenv("KDE_FULL_SESSION").isEmpty()) {
159
        // There are two themes that work for Krita, oxygen and plastique. Try to set plastique first, then oxygen
160 161 162
        setStyle("Plastique");
        setStyle("Oxygen");
    }
Casper Boemann's avatar
Casper Boemann committed
163 164 165 166 167
}

// This gets called before entering KApplication::KApplication
bool KoApplication::initHack()
{
168 169 170 171
    KCmdLineOptions options;
    options.add("print", ki18n("Only print and exit"));
    options.add("template", ki18n("Open a new document with a template"));
    options.add("dpi <dpiX,dpiY>", ki18n("Override display DPI"));
172 173
    options.add("export-pdf", ki18n("Only export to PDF and exit"));
    options.add("export-filename <filename>", ki18n("Filename for export-pdf"));
174
    options.add("benchmark-loading", ki18n("just load the file and then exit"));
175
    options.add("benchmark-loading-show-window", ki18n("load the file, show the window and progressbar and then exit"));
176
    options.add("profile-filename <filename>", ki18n("Filename to write profiling information into."));
177
    options.add("roundtrip-filename <filename>", ki18n("Load a file and save it as an ODF file. Meant for debugging."));
178
    KCmdLineArgs::addCmdLineOptions(options, ki18n("Calligra"), "calligra", "kde");
Casper Boemann's avatar
Casper Boemann committed
179 180 181
    return true;
}

Halla Rempt's avatar
Halla Rempt committed
182
#if defined(Q_OS_WIN) && defined(ENV32BIT)
Andrius da Costa Ribas's avatar
Andrius da Costa Ribas committed
183
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
Halla Rempt's avatar
Halla Rempt committed
184 185 186

LPFN_ISWOW64PROCESS fnIsWow64Process;

Andrius da Costa Ribas's avatar
Andrius da Costa Ribas committed
187
BOOL isWow64()
Halla Rempt's avatar
Halla Rempt committed
188
{
Andrius da Costa Ribas's avatar
Andrius da Costa Ribas committed
189
    BOOL bIsWow64 = FALSE;
Halla Rempt's avatar
Halla Rempt committed
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208

    //IsWow64Process is not available on all supported versions of Windows.
    //Use GetModuleHandle to get a handle to the DLL that contains the function
    //and GetProcAddress to get a pointer to the function if available.

    fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
        GetModuleHandle(TEXT("kernel32")),"IsWow64Process");

    if(NULL != fnIsWow64Process)
    {
        if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
        {
            //handle error
        }
    }
    return bIsWow64;
}
#endif

Casper Boemann's avatar
Casper Boemann committed
209 210
bool KoApplication::start()
{
211
#ifdef Q_OS_WIN
Halla Rempt's avatar
Halla Rempt committed
212 213 214
#ifdef ENV32BIT
    if (isWow64()) {
    	KMessageBox::information(0, 
Halla Rempt's avatar
Halla Rempt committed
215
                                 i18n("You are running a 32 bits build on a 64 bits Windows.\n"
Halla Rempt's avatar
Halla Rempt committed
216 217 218 219 220 221 222
                                      "This is not recommended.\n"
                                      "Please download and install the x64 build instead."),
                                 qApp->applicationName(), 
                                 "calligra_32_on_64_warning");

    }
#endif
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
    QDir appdir(applicationDirPath());
    appdir.cdUp();
    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
    // If there's no kdehome, set it and restart the process.
    if (!env.contains("KDEHOME")) {
        qputenv("KDEHOME", QFile::encodeName(QDesktopServices::storageLocation(QDesktopServices::DataLocation)));
    }
    if (!env.contains("KDESYCOCA")) {
        qputenv("KDESYCOCA", QFile::encodeName(appdir.absolutePath() + "/sycoca"));
    }
    if (!env.contains("XDG_DATA_DIRS")) {
        qputenv("XDG_DATA_DIRS", QFile::encodeName(appdir.absolutePath() + "/share"));
    }
    if (!env.contains("KDEDIR")) {
        qputenv("KDEDIR", QFile::encodeName(appdir.absolutePath()));
    }
    if (!env.contains("KDEDIRS")) {
        qputenv("KDEDIRS", QFile::encodeName(appdir.absolutePath()));
    }
    qputenv("PATH", QFile::encodeName(appdir.absolutePath() + "/bin" + ";"
Yue Liu's avatar
Yue Liu committed
243 244 245
                                      + appdir.absolutePath() + "/lib" + ";"
                                      + appdir.absolutePath() + "/lib"  +  "/kde4" + ";"
                                      + appdir.absolutePath()));
246 247
#endif

248 249
    if (d->splashScreen) {
        d->splashScreen->show();
250
        d->splashScreen->repaint();
251
    }
Halla Rempt's avatar
Halla Rempt committed
252

Halla Rempt's avatar
Halla Rempt committed
253
    ResetStarting resetStarting(d->splashScreen); // remove the splash when done
254
    Q_UNUSED(resetStarting);
Casper Boemann's avatar
Casper Boemann committed
255 256

    // Find the *.desktop file corresponding to the kapp instance name
257
    KoDocumentEntry entry = KoDocumentEntry::queryByMimeType(d->nativeMimeType);
258 259
    if (entry.isEmpty()) {
        kError(30003) << KGlobal::mainComponent().componentName() << "part.desktop not found." << endl;
260
        kError(30003) << "Run 'kde4-config --path services' to see which directories were searched, assuming kde startup had the same environment as your current mainWindow." << endl;
261
        kError(30003) << "Check your installation (did you install Calligra in a different prefix than KDE, without adding the prefix to /etc/kderc ?)" << endl;
262 263 264 265 266 267 268
        kError(30003) << KGlobal::mainComponent().componentName() << "part.desktop not found." << endl;
        QMessageBox::critical(0, applicationName() + i18n(": Critical Error"), i18n("Essential application components could not be found.\n"
                                                                                    "This might be an installation issue.\n"
                                                                                    "Try restarting, running kbuildsycoca4.exe or reinstalling."));
#ifdef Q_OS_WIN
        QProcess::execute(applicationDirPath() + "/kbuildsycoca4.exe");
#endif
Casper Boemann's avatar
Casper Boemann committed
269 270 271 272
        return false;
    }

    // Get the command line arguments which we have to parse
273
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
Casper Boemann's avatar
Casper Boemann committed
274 275
    int argsCount = args->count();

276
    KCmdLineArgs *koargs = KCmdLineArgs::parsedArgs("calligra");
277 278 279
    QString dpiValues = koargs->getOption("dpi");
    if (!dpiValues.isEmpty()) {
        int sep = dpiValues.indexOf(QRegExp("[x, ]"));
Casper Boemann's avatar
Casper Boemann committed
280 281 282
        int dpiX;
        int dpiY = 0;
        bool ok = true;
283 284 285
        if (sep != -1) {
            dpiY = dpiValues.mid(sep + 1).toInt(&ok);
            dpiValues.truncate(sep);
Casper Boemann's avatar
Casper Boemann committed
286
        }
287 288 289 290
        if (ok) {
            dpiX = dpiValues.toInt(&ok);
            if (ok) {
                if (!dpiY) dpiY = dpiX;
291
                KoDpi::setDPI(dpiX, dpiY);
Casper Boemann's avatar
Casper Boemann committed
292 293 294 295
            }
        }
    }
    // No argument -> create an empty document
296
    if (!argsCount) {
297
#if KDE_IS_VERSION(4,6,0)
298 299 300 301 302
        // if there's no document, add the current working directory
        // to the recent dirs so the open dialog and open pane show
        // the directory from where the app was started, instead of
        // the last directory from where we opened a file
        KRecentDirs::add(":OpenDialog", QDir::currentPath());
303
#endif
Casper Boemann's avatar
Casper Boemann committed
304
        QString errorMsg;
305 306 307
        KoPart *part = entry.createKoPart(&errorMsg);

        if (!part) {
308 309
            if (!errorMsg.isEmpty())
                KMessageBox::error(0, errorMsg);
Casper Boemann's avatar
Casper Boemann committed
310 311
            return false;
        }
312 313 314 315

        // XXX: the document should be separate plugin
        KoDocument *doc = part->document();

316 317 318
        KoMainWindow *mainWindow = part->createMainWindow();
        mainWindow->show();
        QObject::connect(doc, SIGNAL(sigProgress(int)), mainWindow, SLOT(slotProgress(int)));
Casper Boemann's avatar
Casper Boemann committed
319 320
        // for initDoc to fill in the recent docs list
        // and for KoDocument::slotStarted
321
        part->addMainWindow(mainWindow);
Casper Boemann's avatar
Casper Boemann committed
322

323 324 325 326 327 328 329 330
        // Check for autosave files from a previous run. There can be several, and
        // we want to offer a restore for every one. Including a nice thumbnail!
        QStringList autoSaveFiles;

        // get all possible autosave files in the home dir, this is for unsaved document autosave files
        // Using the extension allows to avoid relying on the mime magic when opening
        KMimeType::Ptr mime = KMimeType::mimeType(doc->nativeFormatMimeType());
        if (!mime) {
Halla Rempt's avatar
Halla Rempt committed
331
            qFatal("It seems your installation is broken/incomplete because we failed to load the native mimetype \"%s\".", doc->nativeFormatMimeType().constData());
332 333 334 335 336
        }
        QString extension = mime->property("X-KDE-NativeExtension").toString();
        if (extension.isEmpty()) extension = mime->mainExtension();

        QStringList filters;
337
        filters << QString(".%1-%2-%3-autosave%4").arg(part->componentData().componentName()).arg("*").arg("*").arg(extension);
338

339 340 341 342 343
#ifdef Q_OS_WIN
        QDir dir = QDir::tempPath();
#else
        QDir dir = QDir::home();
#endif
344 345 346 347 348 349 350
        // all autosave files for our application
        autoSaveFiles = dir.entryList(filters, QDir::Files | QDir::Hidden);

        QStringList pids;
        QString ourPid;
        ourPid.setNum(kapp->applicationPid());

351 352 353 354
#ifndef QT_NO_DBUS
        // all running instances of our application -- bit hackish, but we cannot get at the dbus name here, for some reason
        QDBusReply<QStringList> reply = QDBusConnection::sessionBus().interface()->registeredServiceNames();

355
        foreach (const QString &name, reply.value()) {
356
            if (name.contains(part->componentData().componentName())) {
357
                // we got another instance of ourselves running, let's get the pid
358
                QString pid = name.split('-').last();
359 360 361 362 363
                if (pid != ourPid) {
                    pids << pid;
                }
            }
        }
364
#endif
365 366 367 368 369 370 371

        // remove the autosave files that are saved for other, open instances of ourselves
        foreach(const QString &autoSaveFileName, autoSaveFiles) {
            if (!QFile::exists(QDir::homePath() + "/" + autoSaveFileName)) {
                autoSaveFiles.removeAll(autoSaveFileName);
                continue;
            }
372
            QStringList split = autoSaveFileName.split('-');
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
            if (split.size() == 4) {
                if (pids.contains(split[1])) {
                    // We've got an active, owned autosave file. Remove.
                    autoSaveFiles.removeAll(autoSaveFileName);
                }
            }
        }

        // Allow the user to make their selection
        if (autoSaveFiles.size() > 0) {
            KoAutoSaveRecoveryDialog dlg(autoSaveFiles);
            if (dlg.exec() == QDialog::Accepted) {
                QStringList filesToRecover = dlg.recoverableFiles();
                foreach (const QString &autosaveFile, autoSaveFiles) {
                    if (!filesToRecover.contains(autosaveFile)) {
                        // remove the files the user didn't want to recover
                        QFile::remove(QDir::homePath() + "/" + autosaveFile);
                    }
                }
                autoSaveFiles = filesToRecover;
            }
            else {
                // don't recover any of the files, but don't delete them either
                autoSaveFiles.clear();
            }
        }

        if (autoSaveFiles.size() > 0) {
            short int numberOfOpenDocuments = 0; // number of documents open
            KUrl url;
            // bah, we need to re-use the document that was already created
            url.setPath(QDir::homePath() + "/" + autoSaveFiles.takeFirst());
405
            if (mainWindow->openDocument(part, url)) {
406 407 408 409 410 411 412 413 414 415 416
                doc->resetURL();
                doc->setModified(true);
                QFile::remove(url.toLocalFile());
                numberOfOpenDocuments++;
            }

            // And then for the other autosave files, we copy & paste the code
            // and loop through them.
            foreach(const QString &autoSaveFile, autoSaveFiles) {
                // For now create an empty document
                QString errorMsg;
417 418
                KoPart *part = entry.createKoPart(&errorMsg);
                if (part) {
419
                    url.setPath(QDir::homePath() + "/" + autoSaveFile);
420

421 422 423
                    KoMainWindow *mainWindow = part->createMainWindow();
                    mainWindow->show();
                    if (mainWindow->openDocument(part, url)) {
424 425 426 427 428 429 430 431 432 433
                        doc->resetURL();
                        doc->setModified(true);
                        QFile::remove(url.toLocalFile());
                        numberOfOpenDocuments++;
                    }
                }
            }
            return (numberOfOpenDocuments > 0);
        }
        else {
434
            part->showStartUpWidget(mainWindow);
Casper Boemann's avatar
Casper Boemann committed
435 436
        }

437 438
    }
    else {
439 440
        const bool print = koargs->isSet("print");
        const bool exportAsPdf = koargs->isSet("export-pdf");
441 442
        const QString pdfFileName = koargs->getOption("export-filename");
        const QString roundtripFileName = koargs->getOption("roundtrip-filename");
443
        const bool doTemplate = koargs->isSet("template");
444
        const bool benchmarkLoading = koargs->isSet("benchmark-loading")
Yue Liu's avatar
Yue Liu committed
445 446
                || koargs->isSet("benchmark-loading-show-window")
                || !roundtripFileName.isEmpty();
447 448
        // only show the mainWindow when no command-line mode option is passed
        const bool showmainWindow =
449 450 451 452 453
                koargs->isSet("benchmark-loading-show-window") || (
                    !koargs->isSet("export-pdf")
                    && !koargs->isSet("benchmark-loading")
                    && !koargs->isSet("roundtrip-filename")
                    && roundtripFileName.isEmpty());
454
        const QString profileFileName = koargs->getOption("profile-filename");
Casper Boemann's avatar
Casper Boemann committed
455 456
        koargs->clear();

457 458 459 460 461 462 463
        QTextStream profileoutput;
        QFile profileFile(profileFileName);
        if (!profileFileName.isEmpty()
                && profileFile.open(QFile::WriteOnly | QFile::Truncate)) {
            profileoutput.setDevice(&profileFile);
        }

Casper Boemann's avatar
Casper Boemann committed
464 465
        // Loop through arguments

466
        short int numberOfOpenDocuments = 0; // number of documents open
Casper Boemann's avatar
Casper Boemann committed
467
        short int nPrinted = 0;
468
        for (int argNumber = 0; argNumber < argsCount; argNumber++) {
Casper Boemann's avatar
Casper Boemann committed
469 470
            // For now create an empty document
            QString errorMsg;
471 472 473
            KoPart *part = entry.createKoPart(&errorMsg);
            if (part) {
                KoDocument *doc = part->document();
474 475 476 477
                // show a mainWindow asap
                KoMainWindow *mainWindow = part->createMainWindow();
                if (showmainWindow) {
                    mainWindow->show();
478
                }
479 480 481
                if (benchmarkLoading) {
                    doc->setReadWrite(false);
                }
482

483 484 485
                if (profileoutput.device()) {
                    doc->setProfileStream(&profileoutput);
                    profileoutput << "KoApplication::start\t"
Yue Liu's avatar
Yue Liu committed
486 487
                                  << appStartTime.msecsTo(QTime::currentTime())
                                  <<"\t0" << endl;
488 489 490 491
                    doc->setAutoErrorHandlingEnabled(false);
                }
                doc->setProfileReferenceTime(appStartTime);

492 493 494
                // are we just trying to open a template?
                if (doTemplate) {
                    QStringList paths;
495 496
                    if (args->url(argNumber).isLocalFile() && QFile::exists(args->url(argNumber).toLocalFile())) {
                        paths << QString(args->url(argNumber).toLocalFile());
497 498
                        kDebug(30003) << "using full path...";
                    } else {
499
                        QString desktopName(args->arg(argNumber));
500 501 502 503 504 505 506
                        QString appName = KGlobal::mainComponent().componentName();

                        paths = KGlobal::dirs()->findAllResources("data", appName + "/templates/*/" + desktopName);
                        if (paths.isEmpty()) {
                            paths = KGlobal::dirs()->findAllResources("data", appName + "/templates/" + desktopName);
                        }
                        if (paths.isEmpty()) {
Thomas Zander's avatar
Thomas Zander committed
507
                            KMessageBox::error(0, i18n("No template found for: %1", desktopName));
508
                            delete mainWindow;
509
                        } else if (paths.count() > 1) {
Thomas Zander's avatar
Thomas Zander committed
510
                            KMessageBox::error(0, i18n("Too many templates found for: %1", desktopName));
511
                            delete mainWindow;
512 513 514 515 516 517 518 519 520 521 522
                        }
                    }

                    if (!paths.isEmpty()) {
                        KUrl templateBase;
                        templateBase.setPath(paths[0]);
                        KDesktopFile templateInfo(paths[0]);

                        QString templateName = templateInfo.readUrl();
                        KUrl templateURL;
                        templateURL.setPath(templateBase.directory() + '/' + templateName);
523
                        if (mainWindow->openDocument(part, templateURL)) {
524 525 526 527
                            doc->resetURL();
                            doc->setEmpty();
                            doc->setTitleModified();
                            kDebug(30003) << "Template loaded...";
528
                            numberOfOpenDocuments++;
529
                        } else {
Thomas Zander's avatar
Thomas Zander committed
530
                            KMessageBox::error(0, i18n("Template %1 failed to load.", templateURL.prettyUrl()));
531
                            delete mainWindow;
532 533 534
                        }
                    }
                    // now try to load
535
                }
536
                else if (mainWindow->openDocument(part, args->url(argNumber))) {
537
                    if (benchmarkLoading) {
538 539
                        if (profileoutput.device()) {
                            profileoutput << "KoApplication::start\t"
Yue Liu's avatar
Yue Liu committed
540 541
                                          << appStartTime.msecsTo(QTime::currentTime())
                                          <<"\t100" << endl;
542
                        }
543
                        if (!roundtripFileName.isEmpty()) {
544
                            part->document()->saveAs(KUrl("file:"+roundtripFileName));
545
                        }
546
                        // close the document
547
                        mainWindow->slotFileQuit();
548
                        return true; // only load one document!
549 550
                    }
                    else if (print) {
551 552
                        mainWindow->slotFilePrint();
                        // delete mainWindow; done by ~KoDocument
Casper Boemann's avatar
Casper Boemann committed
553
                        nPrinted++;
554
                    } else if (exportAsPdf) {
555
                        KoPrintJob *job = mainWindow->exportToPdf(pdfFileName);
556
                        if (job)
557
                            connect (job, SIGNAL(destroyed(QObject*)), mainWindow,
Yue Liu's avatar
Yue Liu committed
558
                                     SLOT(slotFileQuit()), Qt::QueuedConnection);
559
                        nPrinted++;
560
                    } else {
Casper Boemann's avatar
Casper Boemann committed
561
                        // Normal case, success
562
                        numberOfOpenDocuments++;
Casper Boemann's avatar
Casper Boemann committed
563 564 565 566
                    }
                } else {
                    // .... if failed
                    // delete doc; done by openDocument
567
                    // delete mainWindow; done by ~KoDocument
Casper Boemann's avatar
Casper Boemann committed
568
                }
569 570 571

                if (profileoutput.device()) {
                    profileoutput << "KoApplication::start\t"
Yue Liu's avatar
Yue Liu committed
572 573
                                  << appStartTime.msecsTo(QTime::currentTime())
                                  <<"\t100" << endl;
574
                }
575 576

                d->partList << part;
Casper Boemann's avatar
Casper Boemann committed
577 578
            }
        }
579
        if (benchmarkLoading) {
580
            return false; // no valid urls found.
581
        }
582
        if (print || exportAsPdf)
Casper Boemann's avatar
Casper Boemann committed
583
            return nPrinted > 0;
584
        if (numberOfOpenDocuments == 0) // no doc, e.g. all URLs were malformed
Casper Boemann's avatar
Casper Boemann committed
585 586 587 588 589 590 591 592 593 594 595 596 597
            return false;
    }

    args->clear();
    // not calling this before since the program will quit there.
    return true;
}

KoApplication::~KoApplication()
{
    delete d;
}

598
void KoApplication::setSplashScreen(QWidget *splashScreen)
599 600 601 602
{
    d->splashScreen = splashScreen;
}

603 604 605 606 607
QList<KoPart*> KoApplication::partList() const
{
    return d->partList;
}

608 609 610 611 612 613 614
void KoApplication::removeSplash()
{
    d->splashScreen->hide();
    delete d->splashScreen;
    d->splashScreen = 0;
}

615 616 617 618 619 620 621 622 623 624
QStringList KoApplication::mimeFilter(KoFilterManager::Direction direction) const
{
    KoDocumentEntry entry = KoDocumentEntry::queryByMimeType(d->nativeMimeType);
    KService::Ptr service = entry.service();
    return KoFilterManager::mimeFilter(d->nativeMimeType,
                                       direction,
                                       service->property("X-KDE-ExtraNativeMimeTypes").toStringList());
}


625 626 627 628 629
bool KoApplication::notify(QObject *receiver, QEvent *event)
{
    try {
        return QApplication::notify(receiver, event);
    } catch (std::exception &e) {
Halla Rempt's avatar
Halla Rempt committed
630
        qWarning("Error %s sending event %i to object %s",
631 632
                 e.what(), event->type(), qPrintable(receiver->objectName()));
    } catch (...) {
Halla Rempt's avatar
Halla Rempt committed
633
        qWarning("Error <unknown> sending event %i to object %s",
634 635 636 637 638 639
                 event->type(), qPrintable(receiver->objectName()));
    }
    return false;

}

640 641 642 643 644
KoApplication *KoApplication::koApplication()
{
    return KoApp;
}

Casper Boemann's avatar
Casper Boemann committed
645
#include <KoApplication.moc>