KoApplication.cpp 24 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

            KConfigGroup cfg(KGlobal::config(), "SplashScreen");
            bool hideSplash = cfg.readEntry("HideSplashAfterStartup", false);
            if (hideSplash) {
                m_splash->hide();
            }
            else {
109
                m_splash->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
110 111 112
                m_splash->setParent(qApp->activeWindow());
                QRect r(QPoint(), m_splash->size());
                m_splash->move(QApplication::desktop()->screenGeometry().center() - r.center());
113
                m_splash->setWindowTitle(qAppName());
114 115 116 117 118 119
                foreach(QObject *o, m_splash->children()) {
                    QWidget *w = qobject_cast<QWidget*>(o);
                    if (w && w->isHidden()) {
                        w->setVisible(true);
                    }
                }
120 121

                m_splash->show();
122
            }
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
        KoPart *part = entry.createKoPart(&errorMsg);
306
        d->partList << part;
307 308

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

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

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

324 325 326 327 328 329 330 331
        // 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
332
            qFatal("It seems your installation is broken/incomplete because we failed to load the native mimetype \"%s\".", doc->nativeFormatMimeType().constData());
333 334 335 336 337
        }
        QString extension = mime->property("X-KDE-NativeExtension").toString();
        if (extension.isEmpty()) extension = mime->mainExtension();

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

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

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

352 353 354 355
#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();

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

        // 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;
            }
373
            QStringList split = autoSaveFileName.split('-');
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 405
            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());
406
            if (mainWindow->openDocument(part, url)) {
407 408 409 410 411 412 413 414 415 416 417
                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;
418
                KoPart *part = entry.createKoPart(&errorMsg);
419
                d->partList << part;
420
                if (part) {
421
                    url.setPath(QDir::homePath() + "/" + autoSaveFile);
422

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

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

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

Casper Boemann's avatar
Casper Boemann committed
466 467
        // Loop through arguments

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

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

495 496 497
                // are we just trying to open a template?
                if (doTemplate) {
                    QStringList paths;
498 499
                    if (args->url(argNumber).isLocalFile() && QFile::exists(args->url(argNumber).toLocalFile())) {
                        paths << QString(args->url(argNumber).toLocalFile());
500 501
                        kDebug(30003) << "using full path...";
                    } else {
502
                        QString desktopName(args->arg(argNumber));
503 504 505 506 507 508 509
                        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
510
                            KMessageBox::error(0, i18n("No template found for: %1", desktopName));
511
                            delete mainWindow;
512
                        } else if (paths.count() > 1) {
Thomas Zander's avatar
Thomas Zander committed
513
                            KMessageBox::error(0, i18n("Too many templates found for: %1", desktopName));
514
                            delete mainWindow;
515 516 517 518 519 520 521 522 523 524 525
                        }
                    }

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

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

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

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

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

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

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

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

610 611 612 613 614 615 616 617 618 619
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());
}


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

}

635 636 637 638 639
KoApplication *KoApplication::koApplication()
{
    return KoApp;
}

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