00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <cassert>
00023 #include <iostream>
00024 #include <QByteArray>
00025 #include <QDebug>
00026 #include <QGlobalStatic>
00027
00028 #include "cmserrorhandling.h"
00029 #include "commonstrings.h"
00030 #include "filewatcher.h"
00031 #include "pluginmanager.h"
00032 #include "prefsmanager.h"
00033 #include "scpaths.h"
00034 #include "scribusapp.h"
00035 #include "scribuscore.h"
00036 #include "splash.h"
00037 #include "undomanager.h"
00038 #include "util.h"
00039 #include "util_cms.h"
00040 #include "util_ghostscript.h"
00041
00042
00043 extern ScribusQApp* ScQApp;
00044
00045 #include "cmserrorhandling.h"
00046
00047 ScribusCore::ScribusCore() : QObject()
00048 {
00049 m_ScribusInitialized=false;
00050 m_SplashScreen=0;
00051 m_UseGUI=false;
00052 m_HaveCMS=false;
00053
00054 m_currScMW=0;
00055
00056 defaultRGBProfile = NULL;
00057 defaultCMYKProfile = NULL;
00058 defaultRGBToScreenSolidTrans = NULL;
00059 defaultRGBToScreenImageTrans = NULL;
00060 defaultCMYKToScreenImageTrans = NULL;
00061 defaultRGBToCMYKTrans = NULL;
00062 defaultCMYKToRGBTrans = NULL;
00063 }
00064
00065
00066
00067 ScribusCore::~ScribusCore()
00068 {
00069 TermDefaultColorTransforms();
00070
00071 }
00072
00073 #ifndef NDEBUG
00074 static void abort_on_error(QtMsgType t, const char * m)
00075 {
00076 std::cerr << m << "\n";
00077 if(t==QtFatalMsg) assert(false);
00078
00079 }
00080 #endif
00081
00082
00083 int ScribusCore::init(bool useGUI, bool swapDialogButtonOrder, const QString fileToUse)
00084 {
00085 m_UseGUI=useGUI;
00086 m_File=fileToUse;
00087 m_SwapDialogButtonOrder=swapDialogButtonOrder;
00088 #if !defined(NDEBUG) && !defined(_WIN32)
00089 qInstallMsgHandler( & abort_on_error );
00090 #endif
00091
00092 return 0;
00093 }
00094
00095 const QString& ScribusCore::getGuiLanguage() const
00096 {
00097 return ScQApp->currGUILanguage();
00098 }
00099
00100 int ScribusCore::startGUI(bool showSplash, bool showFontInfo, bool showProfileInfo, const QString newGuiLanguage, const QString prefsUserFile)
00101 {
00102
00103
00104 ScribusMainWindow* scribus = new ScribusMainWindow();
00105 Q_CHECK_PTR(scribus);
00106 if (!scribus)
00107 return(EXIT_FAILURE);
00108 ScMWList.append(scribus);
00109 m_currScMW=0;
00110
00111 int retVal=initScribusCore(showSplash, showFontInfo, showProfileInfo,newGuiLanguage, prefsUserFile);
00112 if (retVal == 1)
00113 return(EXIT_FAILURE);
00114
00115 retVal = scribus->initScMW(true);
00116 if (retVal == 1)
00117 return(EXIT_FAILURE);
00118
00119 closeSplash();
00120 m_ScribusInitialized=true;
00121
00122 connect(ScQApp, SIGNAL(lastWindowClosed()), ScQApp, SLOT(quit()));
00123
00124 scribus->show();
00125 scribus->ShowSubs();
00126
00127 if (!m_File.isEmpty())
00128 scribus->loadDoc(m_File);
00129 else
00130 {
00131 if (PrefsManager::instance()->appPrefs.showStartupDialog)
00132 scribus->startUpDialog();
00133 else
00134 scribus->setFocus();
00135 }
00136 qApp->setOverrideCursor(QCursor(Qt::ArrowCursor));
00137
00138
00139
00140
00141 emit appStarted();
00142
00143 return EXIT_SUCCESS;
00144 }
00145
00146 int ScribusCore::initScribusCore(bool showSplash, bool showFontInfo, bool showProfileInfo,
00147 const QString newGuiLanguage, const QString prefsUserFile)
00148 {
00149 CommonStrings::languageChange();
00150 int retVal=0;
00151
00152 initSplash(showSplash);
00153 prefsManager = PrefsManager::instance();
00154 prefsManager->setup();
00155
00156 bool haveFonts=false;
00157 #ifdef Q_OS_MAC
00158 haveFonts=ScCore->initFonts(true);
00159 #else
00160 haveFonts=ScCore->initFonts(showFontInfo);
00161 #endif
00162 if (!haveFonts)
00163 return 1;
00164 prefsManager->initDefaults();
00165 prefsManager->initDefaultGUIFont(qApp->font());
00166 prefsManager->initArrowStyles();
00167 undoManager = UndoManager::instance();
00168 fileWatcher = new FileWatcher(this);
00169 pluginManager = new PluginManager();
00170 setSplashStatus( tr("Initializing Plugins") );
00171 pluginManager->initPlugs();
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 setSplashStatus( tr("Initializing Keyboard Shortcuts") );
00183 prefsManager->initDefaultActionKeys();
00184 setSplashStatus( tr("Reading Preferences") );
00185 if (prefsUserFile.isNull())
00186 prefsManager->ReadPrefs();
00187 else
00188 prefsManager->ReadPrefs(prefsUserFile);
00189
00190
00191
00192 m_HaveGS = testGSAvailability();
00193 m_HavePngAlpha = testGSDeviceAvailability("pngalpha");
00194 m_HaveTiffSep = testGSDeviceAvailability("tiffsep");
00195
00196 ScCore->setSplashStatus( tr("Reading Color Profiles") );
00197 m_HaveCMS = false;
00198 getCMSProfiles(showProfileInfo);
00199 initCMS();
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 return retVal;
00231 }
00232
00233
00234 void ScribusCore::initSplash(bool showSplash)
00235 {
00236 if (showSplash)
00237 {
00238 m_SplashScreen = new SplashScreen();
00239 if (m_SplashScreen != NULL && m_SplashScreen->isVisible())
00240 setSplashStatus(QObject::tr("Initializing..."));
00241 }
00242 else
00243 m_SplashScreen = NULL;
00244 }
00245
00246 void ScribusCore::setSplashStatus(const QString& newText)
00247 {
00248 if (m_SplashScreen != NULL)
00249 {
00250 m_SplashScreen->setStatus( newText );
00251 qApp->processEvents();
00252 }
00253 }
00254
00255 void ScribusCore::showSplash(bool shown)
00256 {
00257 if (m_SplashScreen!=NULL && shown!=m_SplashScreen->isVisible())
00258 m_SplashScreen->setVisible(shown);
00259 }
00260
00261 bool ScribusCore::splashShowing() const
00262 {
00263 if (m_SplashScreen != NULL)
00264 return m_SplashScreen->isVisible();
00265 return false;
00266 }
00267
00268 void ScribusCore::closeSplash()
00269 {
00270 if (m_SplashScreen!=NULL)
00271 {
00272 m_SplashScreen->close();
00273 delete m_SplashScreen;
00274 m_SplashScreen = NULL;
00275 }
00276 }
00277
00278 bool ScribusCore::usingGUI() const
00279 {
00280 return m_UseGUI;
00281 }
00282
00283 bool ScribusCore::isMacGUI() const
00284 {
00285
00286 #if defined(Q_WS_MAC)
00287 return true;
00288 #else
00289 return false;
00290 #endif
00291 }
00292
00293 bool ScribusCore::isWinGUI() const
00294 {
00295
00296 #if defined(_WIN32)
00297 return true;
00298 #else
00299 return false;
00300 #endif
00301 }
00302
00303 bool ScribusCore::reverseDialogButtons() const
00304 {
00305 if (m_SwapDialogButtonOrder)
00306 return true;
00307
00308 #if defined(_WIN32)
00309 return false;
00310
00311 #elif defined(Q_WS_MAC)
00312 return true;
00313 #else
00314
00315 QString gnomesession= ::getenv("GNOME_DESKTOP_SESSION_ID");
00316 if (!gnomesession.isEmpty())
00317 return true;
00318
00319
00320
00321 QString kdesession= ::getenv("KDE_FULL_SESSION");
00322 if (!kdesession.isEmpty())
00323 return false;
00324 #endif
00325 return false;
00326 }
00327
00328
00329 bool ScribusCore::initFonts(bool showFontInfo)
00330 {
00331 setSplashStatus( tr("Searching for Fonts") );
00332 bool haveFonts=prefsManager->GetAllFonts(showFontInfo);
00333 if (!haveFonts)
00334 {
00335 closeSplash();
00336 QString mess = tr("There are no fonts found on your system.");
00337 mess += "\n" + tr("Exiting now.");
00338 QMessageBox::critical(0, tr("Fatal Error"), mess, 1, 0, 0);
00339 }
00340 else
00341 setSplashStatus( tr("Font System Initialized") );
00342 return haveFonts;
00343 }
00344
00345
00346 void ScribusCore::getCMSProfiles(bool showInfo)
00347 {
00348 QString profDir;
00349 QStringList profDirs;
00350 MonitorProfiles.clear();
00351 PrinterProfiles.clear();
00352 InputProfiles.clear();
00353 InputProfilesCMYK.clear();
00354 QString pfad = ScPaths::instance().libDir();
00355 pfad += "profiles/";
00356 profDirs = ScPaths::getSystemProfilesDirs();
00357 profDirs.prepend( prefsManager->appPrefs.ProfileDir );
00358 profDirs.prepend( pfad );
00359 for(int i = 0; i < profDirs.count(); i++)
00360 {
00361 profDir = profDirs[i];
00362 if(!profDir.isEmpty())
00363 {
00364 if(profDir.right(1) != "/")
00365 profDir += "/";
00366 getCMSProfilesDir(profDir, showInfo, true);
00367 }
00368 }
00369 if ((!PrinterProfiles.isEmpty()) && (!InputProfiles.isEmpty()) && (!MonitorProfiles.isEmpty()))
00370 m_HaveCMS = true;
00371 else
00372 m_HaveCMS = false;
00373 }
00374
00375 void ScribusCore::getCMSProfilesDir(QString pfad, bool showInfo, bool recursive)
00376 {
00377 QDir d(pfad, "*", QDir::Name, QDir::Files | QDir::Readable | QDir::Dirs | QDir::NoSymLinks);
00378 if ((d.exists()) && (d.count() != 0))
00379 {
00380 QString nam = "";
00381 const char *Descriptor;
00382 cmsHPROFILE hIn = NULL;
00383
00384 for (uint dc = 0; dc < d.count(); ++dc)
00385 {
00386 if (d[dc] == "." || d[dc] == "..")
00387 continue;
00388 QFileInfo fi(pfad + "/" + d[dc]);
00389 if (fi.isDir() && !recursive)
00390 continue;
00391 else if (fi.isDir() && d[dc][0] != '.')
00392 {
00393 getCMSProfilesDir(fi.filePath()+"/", showInfo, true);
00394 continue;
00395 }
00396
00397 QFile f(fi.filePath());
00398 QByteArray bb(40, ' ');
00399 if (!f.open(QIODevice::ReadOnly)) {
00400 sDebug(QString("couldn't open %1 as color profile").arg(fi.filePath()));
00401 continue;
00402 }
00403 int len = f.read(bb.data(), 40);
00404 f.close();
00405 if (len == 40 && bb[36] == 'a' && bb[37] == 'c' && bb[38] == 's' && bb[39] == 'p')
00406 {
00407 const QByteArray profilePath( QString(pfad + d[dc]).toLocal8Bit() );
00408 if (setjmp(cmsJumpBuffer))
00409 {
00410
00411 if (showInfo)
00412 sDebug(QString("Color profile %s is broken").arg(fi.filePath()));
00413
00414
00415 cmsSetErrorHandler(NULL);
00416 if (hIn)
00417 {
00418 cmsCloseProfile(hIn);
00419 hIn = NULL;
00420 }
00421 continue;
00422 }
00423 cmsSetErrorHandler(&cmsErrorHandler);
00424 hIn = cmsOpenProfileFromFile(profilePath.data(), "r");
00425 if (hIn == NULL)
00426 continue;
00427 Descriptor = cmsTakeProductDesc(hIn);
00428 nam = QString(Descriptor);
00429 switch (static_cast<int>(cmsGetDeviceClass(hIn)))
00430 {
00431 case icSigInputClass:
00432 if (static_cast<int>(cmsGetColorSpace(hIn)) == icSigRgbData)
00433 {
00434 if (!InputProfiles.contains(nam))
00435 InputProfiles.insert(nam, pfad + d[dc]);
00436 }
00437 break;
00438 case icSigColorSpaceClass:
00439 if (static_cast<int>(cmsGetColorSpace(hIn)) == icSigRgbData)
00440 {
00441 if (!InputProfiles.contains(nam))
00442 InputProfiles.insert(nam, pfad + d[dc]);
00443 }
00444 if (static_cast<int>(cmsGetColorSpace(hIn)) == icSigCmykData)
00445 {
00446 if (!InputProfilesCMYK.contains(nam))
00447 InputProfilesCMYK.insert(nam, pfad + d[dc]);
00448 }
00449 break;
00450 case icSigDisplayClass:
00451 if (static_cast<int>(cmsGetColorSpace(hIn)) == icSigRgbData)
00452 {
00453 if (!MonitorProfiles.contains(nam))
00454 MonitorProfiles.insert(nam, pfad + d[dc]);
00455 if (!InputProfiles.contains(nam))
00456 InputProfiles.insert(nam, pfad + d[dc]);
00457 }
00458 if (static_cast<int>(cmsGetColorSpace(hIn)) == icSigCmykData)
00459 {
00460 if (!InputProfilesCMYK.contains(nam))
00461 InputProfilesCMYK.insert(nam, pfad + d[dc]);
00462 }
00463 break;
00464 case icSigOutputClass:
00465
00466
00467 if (static_cast<int>(cmsGetColorSpace(hIn)) == icSigCmykData)
00468 {
00469 if (!PDFXProfiles.contains(nam))
00470 PDFXProfiles.insert(nam, pfad + d[dc]);
00471 if (!InputProfilesCMYK.contains(nam))
00472 InputProfilesCMYK.insert(nam, pfad + d[dc]);
00473 if (!PrinterProfiles.contains(nam))
00474 PrinterProfiles.insert(nam, pfad + d[dc]);
00475 }
00476 break;
00477 }
00478 cmsCloseProfile(hIn);
00479 hIn = NULL;
00480 if (showInfo)
00481 sDebug( QString("Color profile %1 loaded from %2").arg(nam).arg(pfad + d[dc]) );
00482 }
00483 }
00484 cmsSetErrorHandler(NULL);
00485 }
00486 }
00487
00488 void ScribusCore::InitDefaultColorTransforms(void)
00489 {
00490 TermDefaultColorTransforms();
00491
00492 cmsErrorAction(LCMS_ERROR_ABORT);
00493 if (setjmp(cmsJumpBuffer))
00494 {
00495
00496
00497 cmsSetErrorHandler(NULL);
00498 cmsErrorAction(LCMS_ERROR_IGNORE);
00499 TermDefaultColorTransforms();
00500 cmsErrorAction(LCMS_ERROR_ABORT);
00501 return;
00502 }
00503 cmsSetErrorHandler(&cmsErrorHandler);
00504
00505
00506 if (InputProfiles.contains("sRGB IEC61966-2.1"))
00507 {
00508 const QByteArray rgbProfPath(InputProfiles["sRGB IEC61966-2.1"].toLocal8Bit());
00509 defaultRGBProfile = cmsOpenProfileFromFile(rgbProfPath.data(), "r");
00510 }
00511 else
00512 defaultRGBProfile = cmsCreate_sRGBProfile();
00513
00514
00515 if (InputProfilesCMYK.contains("Fogra27L CMYK Coated Press"))
00516 {
00517 const QByteArray cmykProfPath(InputProfilesCMYK["Fogra27L CMYK Coated Press"].toLocal8Bit());
00518 defaultCMYKProfile = cmsOpenProfileFromFile(cmykProfPath.data(), "r");
00519 }
00520
00521 if (!defaultRGBProfile || !defaultCMYKProfile)
00522 {
00523 TermDefaultColorTransforms();
00524 cmsSetErrorHandler(NULL);
00525 return;
00526 }
00527
00528 int dcmsFlags = cmsFLAGS_LOWRESPRECALC | cmsFLAGS_BLACKPOINTCOMPENSATION;
00529 int intent = INTENT_RELATIVE_COLORIMETRIC;
00530
00531 defaultRGBToScreenSolidTrans = scCmsCreateTransform(defaultRGBProfile, TYPE_RGB_16,
00532 defaultRGBProfile, TYPE_RGB_16, intent, cmsFLAGS_NULLTRANSFORM);
00533 defaultRGBToScreenImageTrans = scCmsCreateTransform(defaultRGBProfile, TYPE_RGBA_8,
00534 defaultRGBProfile, TYPE_RGBA_8, intent, cmsFLAGS_NULLTRANSFORM);
00535 defaultCMYKToScreenImageTrans = scCmsCreateTransform(defaultRGBProfile, TYPE_CMYK_8,
00536 defaultCMYKProfile, TYPE_RGBA_8, intent, cmsFLAGS_NULLTRANSFORM);
00537 defaultRGBToCMYKTrans = scCmsCreateTransform(defaultRGBProfile, TYPE_RGB_16,
00538 defaultCMYKProfile, TYPE_CMYK_16, intent, dcmsFlags);
00539 defaultCMYKToRGBTrans = scCmsCreateTransform(defaultCMYKProfile, TYPE_CMYK_16,
00540 defaultRGBProfile, TYPE_RGB_16, intent, dcmsFlags);
00541 if (!defaultRGBToScreenSolidTrans || !defaultRGBToScreenImageTrans ||
00542 !defaultCMYKToScreenImageTrans || !defaultRGBToCMYKTrans ||
00543 !defaultCMYKToRGBTrans )
00544 {
00545 TermDefaultColorTransforms();
00546 }
00547 cmsSetErrorHandler(NULL);
00548 }
00549
00550 void ScribusCore::TermDefaultColorTransforms(void)
00551 {
00552 if (defaultRGBProfile)
00553 cmsCloseProfile(defaultRGBProfile);
00554 if (defaultCMYKProfile)
00555 cmsCloseProfile(defaultCMYKProfile);
00556 if (defaultRGBToScreenSolidTrans)
00557 cmsDeleteTransform(defaultRGBToScreenSolidTrans);
00558 if (defaultRGBToScreenImageTrans)
00559 cmsDeleteTransform(defaultRGBToScreenImageTrans);
00560 if (defaultCMYKToScreenImageTrans)
00561 cmsDeleteTransform(defaultCMYKToScreenImageTrans);
00562 if (defaultRGBToCMYKTrans)
00563 cmsDeleteTransform(defaultRGBToCMYKTrans);
00564 if (defaultCMYKToRGBTrans)
00565 cmsDeleteTransform(defaultCMYKToRGBTrans);
00566 defaultRGBProfile = NULL;
00567 defaultCMYKProfile = NULL;
00568 defaultRGBToScreenSolidTrans = NULL;
00569 defaultRGBToScreenImageTrans = NULL;
00570 defaultCMYKToScreenImageTrans = NULL;
00571 defaultRGBToCMYKTrans = NULL;
00572 defaultCMYKToRGBTrans = NULL;
00573 }
00574
00575 bool ScribusCore::IsDefaultProfile(cmsHPROFILE prof)
00576 {
00577 if (prof == defaultRGBProfile || prof == defaultCMYKProfile)
00578 return true;
00579 return false;
00580 }
00581
00582 bool ScribusCore::IsDefaultTransform(cmsHTRANSFORM trans)
00583 {
00584 if (trans == defaultRGBToScreenSolidTrans || trans == defaultRGBToScreenImageTrans)
00585 return true;
00586 if (trans == defaultCMYKToScreenImageTrans)
00587 return true;
00588 if (trans == defaultRGBToCMYKTrans || trans == defaultCMYKToRGBTrans)
00589 return true;
00590 return false;
00591 }
00592
00593 void ScribusCore::initCMS()
00594 {
00595 if (m_HaveCMS)
00596 {
00597 ProfilesL::Iterator ip;
00598 if ((prefsManager->appPrefs.DCMSset.DefaultImageRGBProfile.isEmpty()) || (!InputProfiles.contains(prefsManager->appPrefs.DCMSset.DefaultImageRGBProfile)))
00599 {
00600 ip = InputProfiles.begin();
00601 prefsManager->appPrefs.DCMSset.DefaultImageRGBProfile = ip.key();
00602 }
00603 if ((prefsManager->appPrefs.DCMSset.DefaultImageCMYKProfile.isEmpty()) || (!InputProfilesCMYK.contains(prefsManager->appPrefs.DCMSset.DefaultImageCMYKProfile)))
00604 {
00605 ip = InputProfilesCMYK.begin();
00606 prefsManager->appPrefs.DCMSset.DefaultImageCMYKProfile = ip.key();
00607 }
00608 if ((prefsManager->appPrefs.DCMSset.DefaultSolidColorRGBProfile.isEmpty()) || (!InputProfiles.contains(prefsManager->appPrefs.DCMSset.DefaultSolidColorRGBProfile)))
00609 {
00610 ip = InputProfiles.begin();
00611 prefsManager->appPrefs.DCMSset.DefaultSolidColorRGBProfile = ip.key();
00612 }
00613 if ((prefsManager->appPrefs.DCMSset.DefaultSolidColorCMYKProfile.isEmpty()) || (!InputProfilesCMYK.contains(prefsManager->appPrefs.DCMSset.DefaultSolidColorCMYKProfile)))
00614 {
00615 ip = InputProfilesCMYK.begin();
00616 prefsManager->appPrefs.DCMSset.DefaultSolidColorCMYKProfile = ip.key();
00617 }
00618 if ((prefsManager->appPrefs.DCMSset.DefaultMonitorProfile.isEmpty()) || (!MonitorProfiles.contains(prefsManager->appPrefs.DCMSset.DefaultMonitorProfile)))
00619 {
00620 ip = MonitorProfiles.begin();
00621 prefsManager->appPrefs.DCMSset.DefaultMonitorProfile = ip.key();
00622 }
00623 if ((prefsManager->appPrefs.DCMSset.DefaultPrinterProfile.isEmpty()) || (!PrinterProfiles.contains(prefsManager->appPrefs.DCMSset.DefaultPrinterProfile)))
00624 {
00625 ip = PrinterProfiles.begin();
00626 prefsManager->appPrefs.DCMSset.DefaultPrinterProfile = ip.key();
00627 }
00628 InitDefaultColorTransforms();
00629 }
00630 }
00631
00632 ScribusMainWindow * ScribusCore::primaryMainWindow( )
00633 {
00634 if (ScMWList.count() == 0 || m_currScMW > ScMWList.count())
00635 return 0;
00636 ScribusMainWindow* mw=ScMWList.at(m_currScMW);
00637 if (!mw)
00638 return 0;
00639 return mw;
00640 }
00641
00642 void ScribusCore::recheckGS()
00643 {
00644 m_HaveGS = testGSAvailability();
00645 m_HavePngAlpha = testGSDeviceAvailability("pngalpha");
00646 m_HaveTiffSep = testGSDeviceAvailability("tiffsep");
00647 }
00648
00649 bool ScribusCore::fileWatcherActive() const
00650 {
00651 if (fileWatcher!=NULL)
00652 return fileWatcher->isActive();
00653 return false;
00654 }