Warning, file /office/calligra/libs/main/KoApplication.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE project 0002 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> 0003 Copyright (C) 2009 Thomas Zander <zander@kde.org> 0004 Copyright (C) 2012 Boudewijn Rempt <boud@valdyas.org> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "KoApplication.h" 0023 0024 #include "KoGlobal.h" 0025 0026 #ifndef QT_NO_DBUS 0027 #include "KoApplicationAdaptor.h" 0028 #include <QDBusConnection> 0029 #include <QDBusReply> 0030 #include <QDBusConnectionInterface> 0031 #endif 0032 0033 #include "KoPrintJob.h" 0034 #include "KoDocumentEntry.h" 0035 #include "KoDocument.h" 0036 #include "KoMainWindow.h" 0037 #include "KoAutoSaveRecoveryDialog.h" 0038 #include <KoDpi.h> 0039 #include "KoPart.h" 0040 #include <KoPluginLoader.h> 0041 #include <KoConfig.h> 0042 #include <KoResourcePaths.h> 0043 #include <KoComponentData.h> 0044 0045 #include <klocalizedstring.h> 0046 #include <kdesktopfile.h> 0047 #include <kmessagebox.h> 0048 #include <kiconloader.h> 0049 #include <MainDebug.h> 0050 #include <kconfig.h> 0051 #include <kconfiggroup.h> 0052 #include <krecentdirs.h> 0053 #include <KAboutData> 0054 #include <KSharedConfig> 0055 #include <KDBusService> 0056 0057 #include <QFile> 0058 #include <QWidget> 0059 #include <QSysInfo> 0060 #include <QStringList> 0061 #include <QProcessEnvironment> 0062 #include <QDir> 0063 #include <QPluginLoader> 0064 #include <QCommandLineParser> 0065 #include <QMimeDatabase> 0066 #include <QTimer> 0067 0068 #include <stdlib.h> 0069 0070 #ifdef Q_OS_WIN 0071 #include <windows.h> 0072 #include <tchar.h> 0073 #endif 0074 0075 0076 #include "MainDebug.h" 0077 #include <QDesktopWidget> 0078 0079 KoApplication* KoApplication::KoApp = 0; 0080 0081 namespace { 0082 const QTime appStartTime(QTime::currentTime()); 0083 } 0084 0085 class KoApplicationPrivate 0086 { 0087 public: 0088 KoApplicationPrivate() 0089 : splashScreen(0) 0090 {} 0091 QByteArray nativeMimeType; 0092 QWidget *splashScreen; 0093 QList<KoPart *> partList; 0094 QString roundtripFileName; 0095 QString pdfFileName; 0096 }; 0097 0098 class KoApplication::ResetStarting 0099 { 0100 public: 0101 ResetStarting(QWidget *splash = 0) 0102 : m_splash(splash) 0103 { 0104 } 0105 0106 ~ResetStarting() { 0107 if (m_splash) { 0108 0109 KConfigGroup cfg( KSharedConfig::openConfig(), "SplashScreen"); 0110 bool hideSplash = cfg.readEntry("HideSplashAfterStartup", false); 0111 if (hideSplash) { 0112 m_splash->hide(); 0113 } 0114 else { 0115 m_splash->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); 0116 QRect r(QPoint(), m_splash->size()); 0117 m_splash->move(QApplication::desktop()->screenGeometry().center() - r.center()); 0118 m_splash->setWindowTitle(qAppName()); 0119 foreach(QObject *o, m_splash->children()) { 0120 QWidget *w = qobject_cast<QWidget*>(o); 0121 if (w && w->isHidden()) { 0122 w->setVisible(true); 0123 } 0124 } 0125 0126 m_splash->show(); 0127 } 0128 } 0129 } 0130 0131 QWidget *m_splash; 0132 }; 0133 0134 0135 KoApplication::KoApplication(const QByteArray &nativeMimeType, 0136 const QString &windowIconName, 0137 AboutDataGenerator aboutDataGenerator, 0138 int &argc, char **argv) 0139 : QApplication(argc, argv) 0140 , d(new KoApplicationPrivate()) 0141 { 0142 QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); 0143 0144 QScopedPointer<KAboutData> aboutData(aboutDataGenerator()); 0145 KAboutData::setApplicationData(*aboutData); 0146 0147 setWindowIcon(QIcon::fromTheme(windowIconName, windowIcon())); 0148 0149 KoApplication::KoApp = this; 0150 0151 d->nativeMimeType = nativeMimeType; 0152 // Tell the iconloader about share/apps/calligra/icons 0153 KIconLoader::global()->addAppDir("calligra"); 0154 0155 // Initialize all Calligra directories etc. 0156 KoGlobal::initialize(); 0157 0158 #ifndef QT_NO_DBUS 0159 KDBusService service(KDBusService::Multiple); 0160 0161 new KoApplicationAdaptor(this); 0162 QDBusConnection::sessionBus().registerObject("/application", this); 0163 #endif 0164 0165 #ifdef Q_OS_MACX 0166 if ( QSysInfo::MacintoshVersion > QSysInfo::MV_10_8 ) 0167 { 0168 // fix Mac OS X 10.9 (mavericks) font issue 0169 // https://bugreports.qt-project.org/browse/QTBUG-32789 0170 QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande"); 0171 } 0172 0173 setAttribute(Qt::AA_DontShowIconsInMenus, true); 0174 #endif 0175 } 0176 0177 #if defined(Q_OS_WIN) && defined(ENV32BIT) 0178 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); 0179 0180 LPFN_ISWOW64PROCESS fnIsWow64Process; 0181 0182 BOOL isWow64() 0183 { 0184 BOOL bIsWow64 = FALSE; 0185 0186 //IsWow64Process is not available on all supported versions of Windows. 0187 //Use GetModuleHandle to get a handle to the DLL that contains the function 0188 //and GetProcAddress to get a pointer to the function if available. 0189 0190 fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress( 0191 GetModuleHandle(TEXT("kernel32")),"IsWow64Process"); 0192 0193 if(0 != fnIsWow64Process) 0194 { 0195 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) 0196 { 0197 //handle error 0198 } 0199 } 0200 return bIsWow64; 0201 } 0202 #endif 0203 0204 bool KoApplication::start() 0205 { 0206 KAboutData aboutData = KAboutData::applicationData(); 0207 // process commandline parameters 0208 QCommandLineParser parser; 0209 aboutData.setupCommandLine(&parser); 0210 0211 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("print"), i18n("Only print and exit"))); 0212 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("template"), i18n("Open a new document based on the given template (desktopfile name)"))); 0213 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("new"), i18n("Open a new document based on the given template file"))); 0214 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("dpi"), i18n("Override display DPI"), QStringLiteral("dpiX,dpiY"))); 0215 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("export-pdf"), i18n("Only export to PDF and exit"))); 0216 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("export-filename"), i18n("Filename for export-pdf"), QStringLiteral("filename"))); 0217 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("benchmark-loading"), i18n("just load the file and then exit"))); 0218 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("benchmark-loading-show-window"), i18n("load the file, show the window and progressbar and then exit"))); 0219 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("profile-filename"), i18n("Filename to write profiling information into."), QStringLiteral("filename"))); 0220 parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("roundtrip-filename"), i18n("Load a file and save it as an ODF file. Meant for debugging."), QStringLiteral("filename"))); 0221 parser.addPositionalArgument(QStringLiteral("[file(s)]"), i18n("File(s) or URL(s) to open")); 0222 0223 parser.process(*this); 0224 0225 aboutData.processCommandLine(&parser); 0226 0227 #if defined(Q_OS_WIN) || defined (Q_OS_MACX) 0228 #ifdef ENV32BIT 0229 if (isWow64()) { 0230 KMessageBox::information(0, 0231 i18n("You are running a 32 bits build on a 64 bits Windows.\n" 0232 "This is not recommended.\n" 0233 "Please download and install the x64 build instead."), 0234 qApp->applicationName(), 0235 "calligra_32_on_64_warning"); 0236 0237 } 0238 #endif 0239 QDir appdir(applicationDirPath()); 0240 appdir.cdUp(); 0241 0242 QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); 0243 if (!env.contains("XDG_DATA_DIRS")) { 0244 qputenv("XDG_DATA_DIRS", QFile::encodeName(appdir.absolutePath() + "/share")); 0245 } 0246 qputenv("PATH", QFile::encodeName(appdir.absolutePath() + "/bin" + ";" 0247 + appdir.absolutePath() + "/lib" + ";" 0248 + appdir.absolutePath() + "/lib/kde4" + ";" 0249 + appdir.absolutePath() + "/Frameworks" + ";" 0250 + appdir.absolutePath())); 0251 #endif 0252 0253 if (d->splashScreen) { 0254 d->splashScreen->show(); 0255 d->splashScreen->repaint(); 0256 processEvents(); 0257 } 0258 0259 ResetStarting resetStarting(d->splashScreen); // remove the splash when done 0260 Q_UNUSED(resetStarting); 0261 0262 // Find the part component file corresponding to the application instance name 0263 KoDocumentEntry entry; 0264 QList<QPluginLoader*> pluginLoaders = KoPluginLoader::pluginLoaders("calligra/parts", d->nativeMimeType); 0265 Q_FOREACH (QPluginLoader *loader, pluginLoaders) { 0266 if (loader->fileName().contains(applicationName()+QString("part"))) { 0267 entry = KoDocumentEntry(loader); 0268 pluginLoaders.removeOne(loader); 0269 break; 0270 } 0271 } 0272 qDeleteAll(pluginLoaders); 0273 0274 if (entry.isEmpty()) { 0275 QMessageBox::critical(0, i18n("%1: Critical Error", applicationName()), i18n("Essential application components could not be found.\n" 0276 "This might be an installation issue.\n" 0277 "Try restarting or reinstalling.")); 0278 return false; 0279 } 0280 0281 // Get the command line arguments which we have to parse 0282 QString dpiValues = parser.value("dpi"); 0283 if (!dpiValues.isEmpty()) { 0284 int sep = dpiValues.indexOf(QRegExp("[x, ]")); 0285 int dpiX; 0286 int dpiY = 0; 0287 bool ok = true; 0288 if (sep != -1) { 0289 dpiY = dpiValues.mid(sep + 1).toInt(&ok); 0290 dpiValues.truncate(sep); 0291 } 0292 if (ok) { 0293 dpiX = dpiValues.toInt(&ok); 0294 if (ok) { 0295 if (!dpiY) dpiY = dpiX; 0296 KoDpi::setDPI(dpiX, dpiY); 0297 } 0298 } 0299 } 0300 // No argument -> create an empty document 0301 const QStringList fileUrls = parser.positionalArguments(); 0302 0303 if (fileUrls.isEmpty()) { 0304 // if there's no document, add the current working directory 0305 // to the recent dirs so the open dialog and open pane show 0306 // the directory from where the app was started, instead of 0307 // the last directory from where we opened a file 0308 KRecentDirs::add(":OpenDialog", QDir::currentPath()); 0309 QString errorMsg; 0310 KoPart *part = entry.createKoPart(&errorMsg); 0311 d->partList << part; 0312 0313 if (!part) { 0314 if (!errorMsg.isEmpty()) 0315 KMessageBox::error(0, errorMsg); 0316 return false; 0317 } 0318 0319 // XXX: the document should be separate plugin 0320 KoDocument *doc = part->document(); 0321 0322 KoMainWindow *mainWindow = part->createMainWindow(); 0323 mainWindow->show(); 0324 QObject::connect(doc, SIGNAL(sigProgress(int)), mainWindow, SLOT(slotProgress(int))); 0325 // for initDoc to fill in the recent docs list 0326 // and for KoDocument::slotStarted 0327 part->addMainWindow(mainWindow); 0328 0329 // Check for autosave files from a previous run. There can be several, and 0330 // we want to offer a restore for every one. Including a nice thumbnail! 0331 QStringList autoSaveFiles; 0332 0333 // get all possible autosave files in the home dir, this is for unsaved document autosave files 0334 // Using the extension allows to avoid relying on the mime magic when opening 0335 QMimeType mimeType = QMimeDatabase().mimeTypeForName(doc->nativeFormatMimeType()); 0336 if (!mimeType.isValid()) { 0337 qFatal("It seems your installation is broken/incomplete because we failed to load the native mimetype \"%s\".", doc->nativeFormatMimeType().constData()); 0338 } 0339 const QString extension = mimeType.preferredSuffix(); 0340 0341 QStringList filters; 0342 filters << QString(".%1-%2-%3-autosave%4").arg(part->componentData().componentName()).arg("*").arg("*").arg(extension); 0343 0344 #ifdef Q_OS_WIN 0345 QDir autosaveDir = QDir::tempPath(); 0346 #else 0347 QDir autosaveDir = QDir::home(); 0348 #endif 0349 // all autosave files for our application 0350 autoSaveFiles = autosaveDir.entryList(filters, QDir::Files | QDir::Hidden); 0351 0352 QStringList pids; 0353 QString ourPid; 0354 ourPid.setNum(applicationPid()); 0355 0356 #ifndef QT_NO_DBUS 0357 // all running instances of our application -- bit hackish, but we cannot get at the dbus name here, for some reason 0358 QDBusReply<QStringList> reply = QDBusConnection::sessionBus().interface()->registeredServiceNames(); 0359 0360 foreach (const QString &name, reply.value()) { 0361 if (name.contains(part->componentData().componentName())) { 0362 // we got another instance of ourselves running, let's get the pid 0363 QString pid = name.split('-').last(); 0364 if (pid != ourPid) { 0365 pids << pid; 0366 } 0367 } 0368 } 0369 #endif 0370 0371 // remove the autosave files that are saved for other, open instances of ourselves 0372 foreach(const QString &autoSaveFileName, autoSaveFiles) { 0373 if (!QFile::exists(autosaveDir.absolutePath() + QDir::separator() + autoSaveFileName)) { 0374 autoSaveFiles.removeAll(autoSaveFileName); 0375 continue; 0376 } 0377 QStringList split = autoSaveFileName.split('-'); 0378 if (split.size() == 4) { 0379 if (pids.contains(split[1])) { 0380 // We've got an active, owned autosave file. Remove. 0381 autoSaveFiles.removeAll(autoSaveFileName); 0382 } 0383 } 0384 } 0385 0386 // Allow the user to make their selection 0387 if (autoSaveFiles.size() > 0) { 0388 KoAutoSaveRecoveryDialog dlg(autoSaveFiles); 0389 if (dlg.exec() == QDialog::Accepted) { 0390 QStringList filesToRecover = dlg.recoverableFiles(); 0391 foreach (const QString &autoSaveFileName, autoSaveFiles) { 0392 if (!filesToRecover.contains(autoSaveFileName)) { 0393 // remove the files the user didn't want to recover 0394 QFile::remove(autosaveDir.absolutePath() + QDir::separator() + autoSaveFileName); 0395 } 0396 } 0397 autoSaveFiles = filesToRecover; 0398 } 0399 else { 0400 // don't recover any of the files, but don't delete them either 0401 autoSaveFiles.clear(); 0402 } 0403 } 0404 0405 if (autoSaveFiles.size() > 0) { 0406 short int numberOfOpenDocuments = 0; // number of documents open 0407 // bah, we need to re-use the document that was already created 0408 QUrl url = QUrl::fromLocalFile(autosaveDir.absolutePath() + QDir::separator() + autoSaveFiles.takeFirst()); 0409 if (mainWindow->openDocument(part, url)) { 0410 doc->resetURL(); 0411 doc->setModified(true); 0412 // TODO: what if the app crashes immediately, before another autosave was made? better keep & rename 0413 QFile::remove(url.toLocalFile()); 0414 numberOfOpenDocuments++; 0415 } 0416 0417 // And then for the other autosave files, we copy & paste the code 0418 // and loop through them. 0419 foreach(const QString &autoSaveFile, autoSaveFiles) { 0420 // For now create an empty document 0421 QString errorMsg; 0422 KoPart *part = entry.createKoPart(&errorMsg); 0423 d->partList << part; 0424 if (part) { 0425 url = QUrl::fromLocalFile(autosaveDir.absolutePath() + QDir::separator() + autoSaveFile); 0426 0427 KoMainWindow *mainWindow = part->createMainWindow(); 0428 mainWindow->show(); 0429 if (mainWindow->openDocument(part, url)) { 0430 doc->resetURL(); 0431 doc->setModified(true); 0432 // TODO: what if the app crashes immediately, before another autosave was made? better keep & rename 0433 QFile::remove(url.toLocalFile()); 0434 numberOfOpenDocuments++; 0435 } 0436 } 0437 } 0438 return (numberOfOpenDocuments > 0); 0439 } 0440 else { 0441 part->showStartUpWidget(mainWindow); 0442 } 0443 0444 } 0445 else { 0446 const bool print = parser.isSet("print"); 0447 const bool exportAsPdf = parser.isSet("export-pdf"); 0448 d->pdfFileName = parser.value("export-filename"); 0449 d->roundtripFileName = parser.value("roundtrip-filename"); 0450 const bool doTemplate = parser.isSet("template"); 0451 const bool doNew = parser.isSet("new"); 0452 const bool benchmarkLoading = parser.isSet("benchmark-loading") 0453 || parser.isSet("benchmark-loading-show-window") 0454 || !d->roundtripFileName.isEmpty(); 0455 // only show the mainWindow when no command-line mode option is passed 0456 const bool showmainWindow = 0457 parser.isSet("benchmark-loading-show-window") || ( 0458 parser.isSet("export-pdf")) || ( 0459 !parser.isSet("benchmark-loading") 0460 && !parser.isSet("roundtrip-filename") 0461 && d->roundtripFileName.isEmpty()); 0462 const QString profileFileName = parser.value("profile-filename"); 0463 0464 QTextStream profileoutput; 0465 QFile profileFile(profileFileName); 0466 if (!profileFileName.isEmpty() 0467 && profileFile.open(QFile::WriteOnly | QFile::Truncate)) { 0468 profileoutput.setDevice(&profileFile); 0469 } 0470 0471 // Loop through arguments 0472 0473 short int numberOfOpenDocuments = 0; // number of documents open 0474 short int nPrinted = 0; 0475 // TODO: remove once Qt has proper handling itself 0476 const QRegExp withProtocolChecker( QStringLiteral("^[a-zA-Z]+:") ); 0477 for (int argNumber = 0; argNumber < fileUrls.size(); ++argNumber) { 0478 const QString fileUrl = fileUrls.at(argNumber); 0479 // convert to an url 0480 const bool startsWithProtocol = (withProtocolChecker.indexIn(fileUrl) == 0); 0481 const QUrl url = startsWithProtocol ? 0482 QUrl::fromUserInput(fileUrl) : 0483 QUrl::fromLocalFile(QDir::current().absoluteFilePath(fileUrl)); 0484 0485 // For now create an empty document 0486 QString errorMsg; 0487 KoPart *part = entry.createKoPart(&errorMsg); 0488 d->partList << part; 0489 if (part) { 0490 KoDocument *doc = part->document(); 0491 // show a mainWindow asap 0492 KoMainWindow *mainWindow = part->createMainWindow(); 0493 if (showmainWindow) { 0494 mainWindow->show(); 0495 } 0496 if (benchmarkLoading) { 0497 doc->setReadWrite(false); 0498 } 0499 0500 if (profileoutput.device()) { 0501 doc->setProfileStream(&profileoutput); 0502 profileoutput << "KoApplication::start\t" 0503 << appStartTime.msecsTo(QTime::currentTime()) 0504 <<"\t0" << endl; 0505 doc->setAutoErrorHandlingEnabled(false); 0506 } 0507 doc->setProfileReferenceTime(appStartTime); 0508 0509 // are we just trying to open a Calligra-style template? 0510 if (doTemplate) { 0511 QString templatePath; 0512 if (url.isLocalFile() && QFile::exists(url.toLocalFile())) { 0513 templatePath = url.toLocalFile(); 0514 debugMain << "using full path..."; 0515 } else { 0516 QString desktopName(fileUrls.at(argNumber)); 0517 const QString templatesResourcePath = part->templatesResourcePath(); 0518 0519 QStringList paths = KoResourcePaths::findAllResources("data", templatesResourcePath + "*/" + desktopName); 0520 if (paths.isEmpty()) { 0521 paths = KoResourcePaths::findAllResources("data", templatesResourcePath + desktopName); 0522 } 0523 if (paths.isEmpty()) { 0524 KMessageBox::error(0, i18n("No template found for: %1", desktopName)); 0525 delete mainWindow; 0526 } else if (paths.count() > 1) { 0527 KMessageBox::error(0, i18n("Too many templates found for: %1", desktopName)); 0528 delete mainWindow; 0529 } else { 0530 templatePath = paths.at(0); 0531 } 0532 } 0533 0534 if (!templatePath.isEmpty()) { 0535 QUrl templateBase; 0536 templateBase.setPath(templatePath); 0537 KDesktopFile templateInfo(templatePath); 0538 0539 QString templateName = templateInfo.readUrl(); 0540 QUrl templateURL; 0541 templateURL.setPath(templateBase.adjusted(QUrl::RemoveFilename|QUrl::StripTrailingSlash).path() + '/' + templateName); 0542 if (mainWindow->openDocument(part, templateURL)) { 0543 doc->resetURL(); 0544 doc->setEmpty(); 0545 doc->setTitleModified(); 0546 debugMain << "Template loaded..."; 0547 numberOfOpenDocuments++; 0548 } else { 0549 KMessageBox::error(0, i18n("Template %1 failed to load.", templateURL.toDisplayString())); 0550 delete mainWindow; 0551 } 0552 } 0553 // now try to load 0554 } 0555 else if (doNew) { 0556 if (url.isLocalFile() && !QFile::exists(url.toLocalFile())) { 0557 KMessageBox::error(0, i18n("No template found at: %1", url.toDisplayString())); 0558 delete mainWindow; 0559 } else { 0560 if (mainWindow->openDocument(part, url)) { 0561 doc->resetURL(); 0562 doc->setEmpty(); 0563 doc->setTitleModified(); 0564 debugMain << "Template loaded..."; 0565 numberOfOpenDocuments++; 0566 } else { 0567 KMessageBox::error(0, i18n("Template %1 failed to load.", url.toDisplayString())); 0568 delete mainWindow; 0569 } 0570 } 0571 } 0572 else { 0573 if (print) { 0574 connect( 0575 mainWindow, SIGNAL(loadCompleted(KoMainWindow *)), 0576 this, SLOT(slotFilePrint(KoMainWindow *))); 0577 } else if (exportAsPdf) { 0578 connect(mainWindow, SIGNAL(loadCompleted(KoMainWindow*)), 0579 this, SLOT(slotExportToPdf(KoMainWindow*))); 0580 } 0581 if (mainWindow->openDocument(part, url)) { 0582 if (benchmarkLoading) { 0583 if (profileoutput.device()) { 0584 profileoutput << "KoApplication::start\t" 0585 << appStartTime.msecsTo(QTime::currentTime()) 0586 <<"\t100" << endl; 0587 } 0588 QTimer::singleShot(0, this, SLOT(benchmarkLoadingFinished())); 0589 return true; // only load one document! 0590 } 0591 if (print || exportAsPdf) 0592 nPrinted++; 0593 else 0594 numberOfOpenDocuments++; 0595 } else { 0596 // .... if failed 0597 // delete doc; done by openDocument 0598 // delete mainWindow; done by ~KoDocument 0599 } 0600 } 0601 0602 if (profileoutput.device()) { 0603 profileoutput << "KoApplication::start\t" 0604 << appStartTime.msecsTo(QTime::currentTime()) 0605 <<"\t100" << endl; 0606 } 0607 0608 } 0609 } 0610 if (benchmarkLoading) { 0611 return false; // no valid urls found. 0612 } 0613 if (print || exportAsPdf) 0614 return nPrinted > 0; 0615 if (numberOfOpenDocuments == 0) // no doc, e.g. all URLs were malformed 0616 return false; 0617 } 0618 0619 // not calling this before since the program will quit there. 0620 return true; 0621 } 0622 0623 KoApplication::~KoApplication() 0624 { 0625 delete d; 0626 } 0627 0628 void KoApplication::benchmarkLoadingFinished() 0629 { 0630 KoPart *part = d->partList.value(0); 0631 if (!part) { 0632 return; 0633 } 0634 KoMainWindow *mainWindow = part->mainWindows().value(0); 0635 if (!mainWindow) { 0636 return; 0637 } 0638 if (!d->roundtripFileName.isEmpty()) { 0639 part->document()->saveAs(QUrl("file:" + d->roundtripFileName)); 0640 } 0641 // close the document 0642 mainWindow->slotFileQuit(); 0643 } 0644 0645 void KoApplication::setSplashScreen(QWidget *splashScreen) 0646 { 0647 d->splashScreen = splashScreen; 0648 } 0649 0650 QList<KoPart*> KoApplication::partList() const 0651 { 0652 return d->partList; 0653 } 0654 0655 QStringList KoApplication::mimeFilter(KoFilterManager::Direction direction) const 0656 { 0657 KoDocumentEntry entry = KoDocumentEntry::queryByMimeType(d->nativeMimeType); 0658 QJsonObject json = entry.metaData(); 0659 #ifdef CALLIGRA_OLD_PLUGIN_METADATA 0660 QStringList mimeTypes = json.value("X-KDE-ExtraNativeMimeTypes").toString().split(','); 0661 #else 0662 QStringList mimeTypes = json.value("X-KDE-ExtraNativeMimeTypes").toVariant().toStringList(); 0663 #endif 0664 0665 return KoFilterManager::mimeFilter(d->nativeMimeType, direction, mimeTypes); 0666 } 0667 0668 0669 bool KoApplication::notify(QObject *receiver, QEvent *event) 0670 { 0671 try { 0672 return QApplication::notify(receiver, event); 0673 } catch (std::exception &e) { 0674 qWarning("Error %s sending event %i to object %s", 0675 e.what(), event->type(), qPrintable(receiver->objectName())); 0676 } catch (...) { 0677 qWarning("Error <unknown> sending event %i to object %s", 0678 event->type(), qPrintable(receiver->objectName())); 0679 } 0680 return false; 0681 0682 } 0683 0684 void KoApplication::slotFilePrint(KoMainWindow *mainWindow) 0685 { 0686 mainWindow->slotFilePrint(); 0687 //delete mainWindow; done by ~KoDocument 0688 } 0689 0690 void KoApplication::slotExportToPdf(KoMainWindow *mainWindow) 0691 { 0692 KoPrintJob *job = mainWindow->exportToPdf(d->pdfFileName); 0693 // TODO: exit if all jobs over 0694 } 0695 0696 KoApplication *KoApplication::koApplication() 0697 { 0698 return KoApp; 0699 }