/*************************************************************************** * Copyright (c) 2004 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * 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., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include # include # include # include # include # include # include # include # include # include # include # include # include # include #endif #if QT_VERSION < 0x050000 # include #endif #include #include #include #include "Splashscreen.h" #include "ui_AboutApplication.h" #include #include #include #include using namespace Gui; using namespace Gui::Dialog; namespace Gui { /** Displays all messages at startup inside the splash screen. * \author Werner Mayer */ class SplashObserver : public Base::ConsoleObserver { public: SplashObserver(QSplashScreen* splasher=0) : splash(splasher), alignment(Qt::AlignBottom|Qt::AlignLeft), textColor(Qt::black) { Base::Console().AttachObserver(this); // allow to customize text position and color const std::map& cfg = App::GetApplication().Config(); std::map::const_iterator al = cfg.find("SplashAlignment"); if (al != cfg.end()) { QString alt = QString::fromLatin1(al->second.c_str()); int align=0; if (alt.startsWith(QLatin1String("VCenter"))) align = Qt::AlignVCenter; else if (alt.startsWith(QLatin1String("Top"))) align = Qt::AlignTop; else align = Qt::AlignBottom; if (alt.endsWith(QLatin1String("HCenter"))) align += Qt::AlignHCenter; else if (alt.endsWith(QLatin1String("Right"))) align += Qt::AlignRight; else align += Qt::AlignLeft; alignment = align; } // choose text color std::map::const_iterator tc = cfg.find("SplashTextColor"); if (tc != cfg.end()) { QColor col; col.setNamedColor(QString::fromLatin1(tc->second.c_str())); if (col.isValid()) textColor = col; } } virtual ~SplashObserver() { Base::Console().DetachObserver(this); } const char* Name() { return "SplashObserver"; } void Warning(const char * s) { #ifdef FC_DEBUG Log(s); #else Q_UNUSED(s); #endif } void Message(const char * s) { #ifdef FC_DEBUG Log(s); #else Q_UNUSED(s); #endif } void Error (const char * s) { #ifdef FC_DEBUG Log(s); #else Q_UNUSED(s); #endif } void Log (const char * s) { QString msg(QString::fromUtf8(s)); QRegExp rx; // ignore 'Init:' and 'Mod:' prefixes rx.setPattern(QLatin1String("^\\s*(Init:|Mod:)\\s*")); int pos = rx.indexIn(msg); if (pos != -1) { msg = msg.mid(rx.matchedLength()); } else { // ignore activation of commands rx.setPattern(QLatin1String("^\\s*(\\+App::|Create|CmdC:|CmdG:|Act:)\\s*")); pos = rx.indexIn(msg); if (pos == 0) return; } #if QT_VERSION < 0x050000 const QGLContext* ctx = QGLContext::currentContext(); if (!ctx) #endif { splash->showMessage(msg.replace(QLatin1String("\n"), QString()), alignment, textColor); QMutex mutex; QMutexLocker ml(&mutex); QWaitCondition().wait(&mutex, 50); } } private: QSplashScreen* splash; int alignment; QColor textColor; }; } // namespace Gui // ------------------------------------------------------------------------------ /** * Constructs a splash screen that will display the pixmap. */ SplashScreen::SplashScreen( const QPixmap & pixmap , Qt::WindowFlags f ) : QSplashScreen(pixmap, f) { // write the messages to splasher messages = new SplashObserver(this); } /** Destruction. */ SplashScreen::~SplashScreen() { delete messages; } /** * Draws the contents of the splash screen using painter \a painter. The default * implementation draws the message passed by message(). */ void SplashScreen::drawContents ( QPainter * painter ) { QSplashScreen::drawContents(painter); } // ------------------------------------------------------------------------------ AboutDialogFactory* AboutDialogFactory::factory = 0; AboutDialogFactory::~AboutDialogFactory() { } QDialog *AboutDialogFactory::create(QWidget *parent) const { #ifdef _USE_3DCONNEXION_SDK return new AboutDialog(true, parent); #else return new AboutDialog(false, parent); #endif } const AboutDialogFactory *AboutDialogFactory::defaultFactory() { static const AboutDialogFactory this_factory; if (factory) return factory; return &this_factory; } void AboutDialogFactory::setDefaultFactory(AboutDialogFactory *f) { if (factory != f) delete factory; factory = f; } // ------------------------------------------------------------------------------ /* TRANSLATOR Gui::Dialog::AboutDialog */ /** * Constructs an AboutDialog which is a child of 'parent', with the * name 'name' and widget flags set to 'WStyle_Customize|WStyle_NoBorder|WType_Modal' * * The dialog will be modal. */ AboutDialog::AboutDialog(bool showLic, QWidget* parent) : QDialog(parent, Qt::FramelessWindowHint), ui(new Ui_AboutApplication) { Q_UNUSED(showLic); setModal(true); ui->setupUi(this); QRect rect = QApplication::desktop()->availableGeometry(); QPixmap image = getMainWindow()->splashImage(); // Make sure the image is not too big if (image.height() > rect.height()/2 || image.width() > rect.width()/2) { float scale = static_cast(image.width()) / static_cast(image.height()); int width = std::min(image.width(), rect.width()/2); int height = std::min(image.height(), rect.height()/2); height = std::min(height, static_cast(width / scale)); width = static_cast(scale * height); image = image.scaled(width, height); } ui->labelSplashPicture->setPixmap(image); // if (showLic) { // currently disabled. Additional license blocks are always shown. QString info(QLatin1String("SUCH DAMAGES.
")); // any additional piece of text to be added after the main license text goes below. // Please set title in

tags, license text in

tags // and add an


tag at the end to nicely separate license blocks #ifdef _USE_3DCONNEXION_SDK info += QString::fromLatin1( "

3D Mouse Support

" "

Development tools and related technology provided under license from 3Dconnexion." "(c) 1992 - 2012 3Dconnexion. All rights reserved

" "
" ); #endif QString lictext = ui->textBrowserLicense->toHtml(); lictext.replace(QString::fromLatin1("SUCH DAMAGES."),info); ui->textBrowserLicense->setHtml(lictext); // } ui->tabWidget->setCurrentIndex(0); // always start on the About tab setupLabels(); showLicenseInformation(); } /** * Destroys the object and frees any allocated resources */ AboutDialog::~AboutDialog() { // no need to delete child widgets, Qt does it all for us delete ui; } class SystemInfo { public: static QString getOperatingSystem() { #if QT_VERSION >= 0x050400 return QSysInfo::prettyProductName(); #endif #if defined (Q_OS_WIN32) switch(QSysInfo::windowsVersion()) { case QSysInfo::WV_NT: return QString::fromLatin1("Windows NT"); case QSysInfo::WV_2000: return QString::fromLatin1("Windows 2000"); case QSysInfo::WV_XP: return QString::fromLatin1("Windows XP"); case QSysInfo::WV_2003: return QString::fromLatin1("Windows Server 2003"); case QSysInfo::WV_VISTA: return QString::fromLatin1("Windows Vista"); case QSysInfo::WV_WINDOWS7: return QString::fromLatin1("Windows 7"); #if QT_VERSION >= 0x040800 case QSysInfo::WV_WINDOWS8: return QString::fromLatin1("Windows 8"); #endif #if ((QT_VERSION >= 0x050200) || (QT_VERSION >= 0x040806 && QT_VERSION < 0x050000)) case QSysInfo::WV_WINDOWS8_1: return QString::fromLatin1("Windows 8.1"); #endif #if QT_VERSION >= 0x040807 case QSysInfo::WV_WINDOWS10: return QString::fromLatin1("Windows 10"); #endif default: return QString::fromLatin1("Windows"); } #elif defined (Q_OS_MAC) switch(QSysInfo::MacVersion()) { case QSysInfo::MV_10_3: return QString::fromLatin1("Mac OS X 10.3"); case QSysInfo::MV_10_4: return QString::fromLatin1("Mac OS X 10.4"); case QSysInfo::MV_10_5: return QString::fromLatin1("Mac OS X 10.5"); #if QT_VERSION >= 0x040700 case QSysInfo::MV_10_6: return QString::fromLatin1("Mac OS X 10.6"); #endif #if QT_VERSION >= 0x040800 case QSysInfo::MV_10_7: return QString::fromLatin1("Mac OS X 10.7"); case QSysInfo::MV_10_8: return QString::fromLatin1("Mac OS X 10.8"); case QSysInfo::MV_10_9: return QString::fromLatin1("Mac OS X 10.9"); case QSysInfo::MV_10_10: return QString::fromLatin1("Mac OS X 10.10"); #endif #if QT_VERSION >= 0x050500 case QSysInfo::MV_10_11: return QString::fromLatin1("Mac OS X 10.11"); #endif #if QT_VERSION >= 0x050600 case QSysInfo::MV_10_12: return QString::fromLatin1("Mac OS X 10.12"); #endif default: return QString::fromLatin1("Mac OS X"); } #elif defined (Q_OS_LINUX) QString exe(QLatin1String("lsb_release")); QStringList args; args << QLatin1String("-ds"); QProcess proc; proc.setEnvironment(QProcess::systemEnvironment()); proc.start(exe, args); if (proc.waitForStarted() && proc.waitForFinished()) { QByteArray info = proc.readAll(); info.replace('\n',""); return QString::fromLatin1((const char*)info); } return QString::fromLatin1("Linux"); #elif defined (Q_OS_UNIX) return QString::fromLatin1("UNIX"); #else return QString(); #endif } static int getWordSizeOfOS() { #if defined(Q_OS_WIN64) return 64; // 64-bit process running on 64-bit windows #elif defined(Q_OS_WIN32) // determine if 32-bit process running on 64-bit windows in WOW64 emulation // or 32-bit process running on 32-bit windows // default bIsWow64 to false for 32-bit process on 32-bit windows BOOL bIsWow64 = false; // must default to false typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress( GetModuleHandle("kernel32"), "IsWow64Process"); if (NULL != fnIsWow64Process) { if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) { assert(false); // something went majorly wrong } } return bIsWow64 ? 64 : 32; #elif defined (Q_OS_LINUX) // http://stackoverflow.com/questions/246007/how-to-determine-whether-a-given-linux-is-32-bit-or-64-bit QString exe(QLatin1String("getconf")); QStringList args; args << QLatin1String("LONG_BIT"); QProcess proc; proc.setEnvironment(QProcess::systemEnvironment()); proc.start(exe, args); if (proc.waitForStarted() && proc.waitForFinished()) { QByteArray info = proc.readAll(); info.replace('\n',""); return info.toInt(); } return 0; // failed #elif defined (Q_OS_UNIX) || defined (Q_OS_MAC) QString exe(QLatin1String("uname")); QStringList args; args << QLatin1String("-m"); QProcess proc; proc.setEnvironment(QProcess::systemEnvironment()); proc.start(exe, args); if (proc.waitForStarted() && proc.waitForFinished()) { QByteArray info = proc.readAll(); info.replace('\n',""); if (info.indexOf("x86_64") >= 0) return 64; else if (info.indexOf("amd64") >= 0) return 64; else if (info.indexOf("ia64") >= 0) return 64; else if (info.indexOf("ppc64") >= 0) return 64; else if (info.indexOf("i386") >= 0) return 32; else if (info.indexOf("i686") >= 0) return 32; else if (info.indexOf("x86") >= 0) return 32; } return 0; // failed #else return 0; // unknown #endif } }; void AboutDialog::setupLabels() { //fonts are rendered smaller on Mac so point size can't be the same for all platforms int fontSize = 8; #ifdef Q_OS_MAC fontSize = 11; #endif //avoid overriding user set style sheet if (qApp->styleSheet().isEmpty()) { setStyleSheet(QString::fromLatin1("Gui--Dialog--AboutDialog QLabel {font-size: %1pt;}").arg(fontSize)); } QString exeName = qApp->applicationName(); std::map& config = App::Application::Config(); std::map::iterator it; QString banner = QString::fromUtf8(config["CopyrightInfo"].c_str()); banner = banner.left( banner.indexOf(QLatin1Char('\n')) ); QString major = QString::fromLatin1(config["BuildVersionMajor"].c_str()); QString minor = QString::fromLatin1(config["BuildVersionMinor"].c_str()); QString build = QString::fromLatin1(config["BuildRevision"].c_str()); QString disda = QString::fromLatin1(config["BuildRevisionDate"].c_str()); QString mturl = QString::fromLatin1(config["MaintainerUrl"].c_str()); // we use replace() to keep label formatting, so a label with text "Unknown" // gets replaced to "FreeCAD", for example QString author = ui->labelAuthor->text(); author.replace(QString::fromLatin1("Unknown Application"), exeName); author.replace(QString::fromLatin1("(c) Unknown Author"), banner); ui->labelAuthor->setText(author); ui->labelAuthor->setUrl(mturl); QString version = ui->labelBuildVersion->text(); version.replace(QString::fromLatin1("Unknown"), QString::fromLatin1("%1.%2").arg(major, minor)); ui->labelBuildVersion->setText(version); QString revision = ui->labelBuildRevision->text(); revision.replace(QString::fromLatin1("Unknown"), build); ui->labelBuildRevision->setText(revision); QString date = ui->labelBuildDate->text(); date.replace(QString::fromLatin1("Unknown"), disda); ui->labelBuildDate->setText(date); QString os = ui->labelBuildOS->text(); os.replace(QString::fromLatin1("Unknown"), SystemInfo::getOperatingSystem()); ui->labelBuildOS->setText(os); QString platform = ui->labelBuildPlatform->text(); platform.replace(QString::fromLatin1("Unknown"), QString::fromLatin1("%1-bit").arg(QSysInfo::WordSize)); ui->labelBuildPlatform->setText(platform); // branch name it = config.find("BuildRevisionBranch"); if (it != config.end()) { QString branch = ui->labelBuildBranch->text(); branch.replace(QString::fromLatin1("Unknown"), QString::fromUtf8(it->second.c_str())); ui->labelBuildBranch->setText(branch); } else { ui->labelBranch->hide(); ui->labelBuildBranch->hide(); } // hash id it = config.find("BuildRevisionHash"); if (it != config.end()) { QString hash = ui->labelBuildHash->text(); hash.replace(QString::fromLatin1("Unknown"), QString::fromLatin1(it->second.c_str())); ui->labelBuildHash->setText(hash); } else { ui->labelHash->hide(); ui->labelBuildHash->hide(); } } class AboutDialog::LibraryInfo { public: QString name; QString version; QString href; QString url; }; void AboutDialog::showLicenseInformation() { QWidget *tab_license = new QWidget(); tab_license->setObjectName(QString::fromLatin1("tab_license")); ui->tabWidget->addTab(tab_license, tr("Libraries")); QVBoxLayout* hlayout = new QVBoxLayout(tab_license); QTextBrowser* textField = new QTextBrowser(tab_license); textField->setOpenExternalLinks(false); textField->setOpenLinks(false); hlayout->addWidget(textField); QList libInfo; LibraryInfo li; QString baseurl = QString::fromLatin1("file:///%1/ThirdPartyLibraries.html") .arg(QString::fromUtf8(App::Application::getHelpDir().c_str())); //FIXME: Put all needed information into LibraryVersions.h // // Boost li.name = QLatin1String("Boost"); li.href = baseurl + QLatin1String("#_TocBoost"); li.url = QLatin1String("http://www.boost.org"); li.version = QLatin1String(BOOST_LIB_VERSION); libInfo << li; // Coin3D li.name = QLatin1String("Coin3D"); li.href = baseurl + QLatin1String("#_TocCoin3D"); li.url = QLatin1String("https://bitbucket.org/Coin3D/coin/"); li.version = QLatin1String(COIN_VERSION); libInfo << li; // Eigen3 li.name = QLatin1String("Eigen3"); li.href = baseurl + QLatin1String("#_TocEigen3"); li.url = QLatin1String("http://eigen.tuxfamily.org/"); li.version.clear(); libInfo << li; // FreeType li.name = QLatin1String("FreeType"); li.href = baseurl + QLatin1String("#_TocFreeType"); li.url = QLatin1String("http://freetype.org"); li.version.clear(); libInfo << li; // KDL li.name = QLatin1String("KDL"); li.href = baseurl + QLatin1String("#_TocKDL"); li.url = QLatin1String("http://www.orocos.org/kdl"); li.version.clear(); libInfo << li; // libarea li.name = QLatin1String("libarea"); li.href = baseurl + QLatin1String("#_TocLibArea"); li.url = QLatin1String("https://github.com/danielfalck/libarea"); li.version.clear(); libInfo << li; // OCCT #if defined(HAVE_OCC_VERSION) li.name = QLatin1String("Open CASCADE Technology"); li.href = baseurl + QLatin1String("#_TocOCCT"); li.url = QLatin1String("http://www.opencascade.com"); li.version = QLatin1String(OCC_VERSION_STRING_EXT); libInfo << li; #endif // pcl li.name = QLatin1String("Point Cloud Library"); li.href = baseurl + QLatin1String("#_TocPcl"); li.url = QLatin1String("http://www.pointclouds.org"); li.version.clear(); libInfo << li; // PyCXX li.name = QLatin1String("PyCXX"); li.href = baseurl + QLatin1String("#_TocPyCXX"); li.url = QLatin1String("http://cxx.sourceforge.net"); li.version.clear(); libInfo << li; // Python li.name = QLatin1String("Python"); li.href = baseurl + QLatin1String("#_TocPython"); li.url = QLatin1String("http://www.python.org"); li.version = QLatin1String(PY_VERSION); libInfo << li; // PySide li.name = QLatin1String("PySide"); li.href = baseurl + QLatin1String("#_TocPySide"); li.url = QLatin1String("http://www.pyside.org"); li.version.clear(); libInfo << li; // Qt li.name = QLatin1String("Qt"); li.href = baseurl + QLatin1String("#_TocQt"); li.url = QLatin1String("http://www.qt.io"); li.version = QLatin1String(QT_VERSION_STR); libInfo << li; // Salome SMESH li.name = QLatin1String("Salome SMESH"); li.href = baseurl + QLatin1String("#_TocSalomeSMESH"); li.url = QLatin1String("http://salome-platform.org"); li.version.clear(); libInfo << li; // Shiboken li.name = QLatin1String("Shiboken"); li.href = baseurl + QLatin1String("#_TocPySide"); li.url = QLatin1String("http://www.pyside.org"); li.version.clear(); libInfo << li; // vtk li.name = QLatin1String("vtk"); li.href = baseurl + QLatin1String("#_TocVtk"); li.url = QLatin1String("https://www.vtk.org"); li.version.clear(); libInfo << li; // Xerces-C li.name = QLatin1String("Xerces-C"); li.href = baseurl + QLatin1String("#_TocXercesC"); li.url = QLatin1String("https://xerces.apache.org/xerces-c"); li.version.clear(); libInfo << li; // Zipios++ li.name = QLatin1String("Zipios++"); li.href = baseurl + QLatin1String("#_TocZipios"); li.url = QLatin1String("http://zipios.sourceforge.net"); li.version.clear(); libInfo << li; // zlib li.name = QLatin1String("zlib"); li.href = baseurl + QLatin1String("#_TocZlib"); li.url = QLatin1String("http://zlib.net"); li.version = QLatin1String(ZLIB_VERSION); libInfo << li; QString msg = tr("This software uses open source components whose copyright and other " "proprietary rights belong to their respective owners:"); QString html; QTextStream out(&html); out << "" << "

" << msg << "

\n
    \n"; for (QList::iterator it = libInfo.begin(); it != libInfo.end(); ++it) { out << "
  • " << it->name << " " << it->version << "

    " "

    href << "\">" << it->url << "

  • \n"; } out << "
\n\n"; textField->setHtml(html); connect(textField, SIGNAL(anchorClicked(QUrl)), this, SLOT(linkActivated(QUrl))); } void AboutDialog::linkActivated(const QUrl& link) { //#if defined(Q_OS_WIN) && QT_VERSION < 0x050602 LicenseView* licenseView = new LicenseView(); licenseView->setAttribute(Qt::WA_DeleteOnClose); licenseView->show(); QString title = tr("License"); QString fragment = link.fragment(); if (fragment.startsWith(QLatin1String("_Toc"))) { QString prefix = fragment.mid(4); title = QString::fromLatin1("%1 %2").arg(prefix, title); } licenseView->setWindowTitle(title); getMainWindow()->addWindow(licenseView); licenseView->setSource(link); //#else // QDesktopServices::openUrl(link); //#endif } void AboutDialog::on_copyButton_clicked() { QString data; QTextStream str(&data); std::map& config = App::Application::Config(); std::map::iterator it; QString exe = QString::fromLatin1(App::GetApplication().getExecutableName()); QString major = QString::fromLatin1(config["BuildVersionMajor"].c_str()); QString minor = QString::fromLatin1(config["BuildVersionMinor"].c_str()); QString build = QString::fromLatin1(config["BuildRevision"].c_str()); str << "OS: " << SystemInfo::getOperatingSystem() << endl; int wordSize = SystemInfo::getWordSizeOfOS(); if (wordSize > 0) { str << "Word size of OS: " << wordSize << "-bit" << endl; } str << "Word size of " << exe << ": " << QSysInfo::WordSize << "-bit" << endl; str << "Version: " << major << "." << minor << "." << build; char *appimage = getenv("APPIMAGE"); if (appimage) str << " AppImage"; str << endl; #if defined(_DEBUG) || defined(DEBUG) str << "Build type: Debug" << endl; #elif defined(NDEBUG) str << "Build type: Release" << endl; #elif defined(CMAKE_BUILD_TYPE) str << "Build type: " << CMAKE_BUILD_TYPE << endl; #else str << "Build type: Unknown" << endl; #endif it = config.find("BuildRevisionBranch"); if (it != config.end()) str << "Branch: " << QString::fromUtf8(it->second.c_str()) << endl; it = config.find("BuildRevisionHash"); if (it != config.end()) str << "Hash: " << it->second.c_str() << endl; // report also the version numbers of the most important libraries in FreeCAD str << "Python version: " << PY_VERSION << endl; str << "Qt version: " << QT_VERSION_STR << endl; str << "Coin version: " << COIN_VERSION << endl; #if defined(HAVE_OCC_VERSION) str << "OCC version: " << OCC_VERSION_MAJOR << "." << OCC_VERSION_MINOR << "." << OCC_VERSION_MAINTENANCE #ifdef OCC_VERSION_DEVELOPMENT << "." OCC_VERSION_DEVELOPMENT #endif << endl; #endif QLocale loc; str << "Locale: " << loc.languageToString(loc.language()) << "/" << loc.countryToString(loc.country()) << " (" << loc.name() << ")" << endl; QClipboard* cb = QApplication::clipboard(); cb->setText(data); } // ---------------------------------------------------------------------------- /* TRANSLATOR Gui::LicenseView */ LicenseView::LicenseView(QWidget* parent) : MDIView(0,parent,0) { browser = new QTextBrowser(this); browser->setOpenExternalLinks(true); browser->setOpenLinks(true); setCentralWidget(browser); } LicenseView::~LicenseView() { } void LicenseView::setSource(const QUrl& url) { browser->setSource(url); } #include "moc_Splashscreen.cpp"