568 lines
18 KiB
C++
568 lines
18 KiB
C++
/***************************************************************************
|
|
* Copyright (c) 2004 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
|
* *
|
|
* 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 <QApplication>
|
|
# include <QClipboard>
|
|
# include <QDialogButtonBox>
|
|
# include <QMutex>
|
|
# include <QProcess>
|
|
# include <QSysInfo>
|
|
# include <QTextStream>
|
|
# include <QWaitCondition>
|
|
# include <Inventor/C/basic.h>
|
|
#endif
|
|
|
|
#include <LibraryVersions.h>
|
|
|
|
#include "Splashscreen.h"
|
|
#include "ui_AboutApplication.h"
|
|
#include <Base/Console.h>
|
|
#include <CXX/WrapPython.h>
|
|
#include <App/Application.h>
|
|
#include <Gui/MainWindow.h>
|
|
|
|
|
|
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, const char* name=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<std::string,std::string>& cfg = App::GetApplication().Config();
|
|
std::map<std::string,std::string>::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<std::string,std::string>::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);
|
|
#endif
|
|
}
|
|
void Message(const char * s)
|
|
{
|
|
#ifdef FC_DEBUG
|
|
Log(s);
|
|
#endif
|
|
}
|
|
void Error (const char * s)
|
|
{
|
|
#ifdef FC_DEBUG
|
|
Log(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;
|
|
}
|
|
|
|
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)
|
|
{
|
|
setModal(true);
|
|
ui->setupUi(this);
|
|
ui->labelSplashPicture->setPixmap(getMainWindow()->splashImage());
|
|
if (!showLic)
|
|
ui->licenseButton->hide();
|
|
setupLabels();
|
|
}
|
|
|
|
/**
|
|
* 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 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");
|
|
#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<std::string, std::string>& config = App::Application::Config();
|
|
std::map<std::string,std::string>::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());
|
|
|
|
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).arg(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::fromLatin1(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();
|
|
}
|
|
}
|
|
|
|
namespace Gui {
|
|
namespace Dialog {
|
|
|
|
class GuiExport LicenseDialog : public QDialog
|
|
{
|
|
public:
|
|
LicenseDialog(QWidget *parent = 0) : QDialog(parent, Qt::FramelessWindowHint)
|
|
{
|
|
QString info;
|
|
#ifdef _USE_3DCONNEXION_SDK
|
|
info = QString::fromLatin1(
|
|
"3D Mouse Support:\n"
|
|
"Development tools and related technology provided under license from 3Dconnexion.\n"
|
|
"(c) 1992 - 2012 3Dconnexion. All rights reserved");
|
|
#endif
|
|
statusLabel = new QLabel(info);
|
|
buttonBox = new QDialogButtonBox;
|
|
buttonBox->setStandardButtons(QDialogButtonBox::Ok);
|
|
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
|
|
|
QHBoxLayout *topLayout = new QHBoxLayout;
|
|
topLayout->addWidget(statusLabel);
|
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
|
mainLayout->addLayout(topLayout);
|
|
mainLayout->addWidget(buttonBox);
|
|
setLayout(mainLayout);
|
|
|
|
setWindowTitle(tr("Copyright"));
|
|
}
|
|
~LicenseDialog()
|
|
{
|
|
}
|
|
|
|
private:
|
|
QLabel *statusLabel;
|
|
QDialogButtonBox *buttonBox;
|
|
};
|
|
|
|
} // namespace Dialog
|
|
} // namespace Gui
|
|
|
|
void AboutDialog::on_licenseButton_clicked()
|
|
{
|
|
#ifdef _USE_3DCONNEXION_SDK
|
|
LicenseDialog dlg(this);
|
|
dlg.exec();
|
|
#endif
|
|
}
|
|
|
|
void AboutDialog::on_copyButton_clicked()
|
|
{
|
|
QString data;
|
|
QTextStream str(&data);
|
|
std::map<std::string, std::string>& config = App::Application::Config();
|
|
std::map<std::string,std::string>::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 << 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: " << 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
|
|
|
|
QClipboard* cb = QApplication::clipboard();
|
|
cb->setText(data);
|
|
}
|
|
|
|
#include "moc_Splashscreen.cpp"
|