Rev 24991 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <iostream> // only for debugging
#include <QFile>
#include <QLabel>
#include <QPixmap>
#include <QPushButton>
#include <QShowEvent>
#include <QString>
#include <QStringList>
#include <QTabWidget>
#include <QTextStream>
#include <QToolTip>
#include <QWidget>
#include "scconfig.h"
#include "about.h"
#include "api/api_application.h"
#include "commonstrings.h"
#include "scpaths.h"
#include <cairo.h>
#include <harfbuzz/hb.h>
#include <lcms2.h>
#ifdef HAVE_PODOFO
#include <podofo/podofo.h>
#endif
#ifdef HAVE_POPPLER
#include <poppler/cpp/poppler-version.h>
#endif
#include "scpaths.h"
#ifdef HAVE_SVNVERSION
#include "svnversion.h"
#endif
#include "util_ghostscript.h"
#include "iconmanager.h"
#include "upgradechecker.h"
#include "langmgr.h"
/*
* The content for the About dialog is mostly built from the files in
* // SCRIBUS_INSTALL_DIRECTORY/share/doc/scribus-1.3.5svn/
*
* The format of the files should follow this pattern:
* - AUTHOR
* Tr(Title)
* first_name name email_address
* first_name name email_address
*
* Tr(Title)
* ...
*
* - TRANSLATION
* Tr(Title)
*
* Language(language_code)
* first_name name (email_address)
*
* Language(language_code)
* first_name name (email_address)
*
*
* Tr(Title)
* ...
* - LINKS
* Tr(Title)
* url
*
*
* Tr(Title)
* ...
*
*
* Text which has to be translated has to be added to the local tr...Title()
* methods, otherwise in won't be added to the list of translatable strings
*
* a.l.e
*/
/*!
\fn About::About( QWidget* parent, AboutMode diaMode )
\author Franz Schmid
\date
\brief Constructor for About dialog box
\param parent QWidget pointer to parent window
\param diaMode a dialog mode. See AboutMode.
\retval About dialog
*/
About::About( QWidget* parent, AboutMode diaMode ) : QDialog( parent )
{
m_mode = diaMode;
m_firstShow = true;
setWindowTitle( tr("About Scribus %1").arg(ScribusAPI::getVersion()) );
setWindowIcon(IconManager::instance().loadIcon("AppIcon.png", true));
setModal(true);
aboutLayout = new QVBoxLayout( this );
aboutLayout->setSpacing(6);
aboutLayout->setContentsMargins(9, 9, 9, 9);
tabWidget2 = new QTabWidget( this );
tab = new QWidget( tabWidget2 );
tabLayout1 = new QVBoxLayout( tab );
tabLayout1->setSpacing(6);
tabLayout1->setContentsMargins(9, 9, 9, 9);
double pixelRatio = devicePixelRatioF();
QPixmap splashPixmap = IconManager::instance().loadPixmap("scribus_splash.png", true);
double splashPixmapW = splashPixmap.width();
double splashPixmapH = splashPixmap.height();
if (pixelRatio != 1.0)
{
int w = qRound(splashPixmap.width() * pixelRatio);
int h = qRound(splashPixmap.height() * pixelRatio);
double integralPart = 0;
bool isIntegerRatio = (modf(pixelRatio, &integralPart) == 0.0);
splashPixmap = splashPixmap.scaled(w, h, Qt::IgnoreAspectRatio, isIntegerRatio ? Qt::FastTransformation : Qt::SmoothTransformation);
splashPixmap.setDevicePixelRatio(pixelRatio);
}
pixmapLabel1 = new QLabel( tab );
pixmapLabel1->setPixmap(splashPixmap);
pixmapLabel1->setFixedSize(QSize(splashPixmapW, splashPixmapH));
pixmapLabel1->setAlignment(Qt::AlignCenter);
tabLayout1->addWidget( pixmapLabel1 );
buildID = new QLabel( tab );
buildID->setAlignment(Qt::AlignCenter);
buildID->setTextInteractionFlags(Qt::TextSelectableByMouse);
buildID->setText( tr("<p align=\"center\"><b>%1 %2</b></p>").arg( tr("Scribus Version"), ScribusAPI::getVersion()));
tabLayout1->addWidget( buildID, 0, Qt::AlignHCenter );
tabWidget2->addTab( tab, tr("&About") );
/*! AUTHORS tab */
tab_2 = new QWidget( tabWidget2 );
tabLayout = new QHBoxLayout( tab_2 );
tabLayout->setSpacing(6);
tabLayout->setContentsMargins(9, 9, 9, 9);
authorView = new QTextBrowser( tab_2 );
authorView->setHtml(About::parseAuthorFile(ScPaths::instance().docDir() + "AUTHORS"));
tabLayout->addWidget( authorView );
tabWidget2->addTab( tab_2, tr("A&uthors"));
/*! TRANSLATION tab */
tab_3 = new QWidget( tabWidget2 );
tabLayout_2 = new QHBoxLayout( tab_3 );
tabLayout_2->setSpacing(6);
tabLayout_2->setContentsMargins(9, 9, 9, 9);
transView = new QTextBrowser( tab_3);
transView->setHtml(About::parseTranslationFile(ScPaths::instance().docDir() + "TRANSLATION"));
tabLayout_2->addWidget( transView );
tabWidget2->addTab( tab_3, tr("&Translations") );
/*! ONLINE tab (03/04/2004 petr vanek) */
tab_4 = new QWidget( tabWidget2 );
onlineView = new QTextBrowser( tab_4 );
onlineView->setHtml(About::parseLinksFile(ScPaths::instance().docDir() + "LINKS"));
onlineView->setOpenExternalLinks(true);
tabLayout_4 = new QHBoxLayout( tab_4 );
tabLayout_4->setSpacing(6);
tabLayout_4->setContentsMargins(9, 9, 9, 9);
tabLayout_4->addWidget( onlineView );
tabWidget2->addTab( tab_4, tr("&Online") );
/*! UPDATE tab */
tab_5 = new QWidget( tabWidget2 );
tabWidget2->addTab( tab_5, tr("&Updates") );
updateLayout = new QVBoxLayout( tab_5 );
updateLayout->setSpacing(6);
updateLayout->setContentsMargins(9, 9, 9, 9);
checkForUpdateButton = new QPushButton( tr("Check for Updates"), tab_5 );
updateView = new QTextBrowser( tab_5);
updateLayout->addWidget( checkForUpdateButton );
updateLayout->addWidget( updateView );
/*! LICENCE tab */
tab_Licence = new QWidget( tabWidget2 );
tabWidget2->addTab( tab_Licence, tr("&Licence") );
licenceLayout = new QVBoxLayout( tab_Licence );
licenceLayout->setSpacing(6);
licenceLayout->setContentsMargins(9, 9, 9, 9);
textViewLicence = new QTextBrowser( tab_Licence);
licenceLayout->addWidget( textViewLicence );
QFile licenceFile(ScPaths::instance().docDir() + "/COPYING");
if (!licenceFile.open(QIODevice::ReadOnly | QIODevice::Text))
textViewLicence->setPlainText(tr("Unable to open licence file. Please check your install directory or the Scribus website for licencing information.") );
else
{
QTextStream inTS(&licenceFile);
inTS.setAutoDetectUnicode(true);
inTS.setCodec("UTF-8");
QString licenceText = inTS.readAll();
textViewLicence->setPlainText(licenceText);
}
/*! BUILD tab */
tab_build = new QWidget( tabWidget2 );
tabWidget2->addTab( tab_build, tr("&Build Information") );
buildLayout = new QVBoxLayout( tab_build );
buildLayout->setSpacing(6);
buildLayout->setContentsMargins(9, 9, 9, 9);
textViewBuild = new QTextBrowser( tab_build);
buildLayout->addWidget( textViewBuild );
textViewBuild->setText(generateBuildInfo());
//Add tab widget to about window
aboutLayout->addWidget( tabWidget2 );
layout2 = new QHBoxLayout;
layout2->setSpacing(6);
layout2->setContentsMargins(0, 0, 0, 0);
QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
layout2->addItem( spacer );
okButton = new QPushButton( tr("&Close"), this );
okButton->setDefault( true );
layout2->addWidget( okButton );
aboutLayout->addLayout( layout2 );
setMaximumSize(sizeHint());
//tooltips
checkForUpdateButton->setToolTip( "<qt>" + tr("Check for updates to Scribus. No data from your machine will be transferred off it.") + "</qt>");
// signals and slots connections
connect( okButton, SIGNAL( clicked() ), this, SLOT( accept() ) );
connect( checkForUpdateButton, SIGNAL( clicked() ), this, SLOT( runUpdateCheck() ) );
resize(minimumSizeHint());
}
void About::showEvent (QShowEvent * event)
{
if (m_mode == About::CheckUpdates && m_firstShow)
tabWidget2->setCurrentIndex(4);
QDialog::showEvent(event);
}
QString About::trAuthorTitle(const QString& title)
{
QString result;
if (title == "Development Team:")
result = tr("Development Team:");
else if (title == "Mac OS® X Aqua Port:")
result = tr("Mac OS® X Aqua Port:");
else if (title == "OS/2®/eComStation™ Port:")
result = tr("OS/2®/eComStation™ Port:");
else if (title == "Windows® Port:")
result = tr("Windows® Port:");
else if (title == "Haiku Port:")
result = tr("Haiku Port:");
else if (title == "Contributions from:")
result = tr("Contributions from:");
else if (title == "Official Documentation:")
result = tr("Official Documentation:");
else if (title == "Doc Translators:")
result = tr("Doc Translators:");
else if (title == "Other Documentation:")
result = tr("Other Documentation:");
else if (title == "Webmasters:")
result = tr("Webmasters:");
else if (title == "Splash Screen:")
result = tr("Splash Screen:");
else if (title == "Tango Project Icons:")
result = tr("Tango Project Icons:");
else if (title == "Scribus 1.5.1+ Icon Set:")
result = tr("Scribus 1.5.1+ Icon Set:");
else if (title == "AppImage for Linux:")
result = tr("AppImage for Linux:");
else if (title == "Refactoring text layout code, the new boxes model & CTL text layout, Oman House of Open Source Technology team:")
result = tr("Refactoring text layout code, the new boxes model & CTL text layout, Oman House of Open Source Technology team:");
else
{
std::cout << "please add the untranslated title \"" << qPrintable(title) << "\" to About::trAuthorTitle()" << std::endl;
result = title;
}
return result;
}
QString About::trTranslationTitle(const QString& title)
{
QString result;
if (title == "Official Translations and Translators (in order of locale shortcode):")
result = tr("Official Translations and Translators (in order of locale shortcode):");
else if (title == "Previous Translation Contributors:")
result = tr("Previous Translation Contributors:");
else
{
std::cout << "please add the untranslated title \"" << qPrintable(title) << "\" to About::trTranslationTitle()" << std::endl;
result = title;
}
return result;
}
QString About::trLinksTitle(const QString& title)
{
QString result;
if (title == "Homepage")
result = tr("Homepage");
else if (title == "Online Reference")
result = tr("Online Reference");
else if (title == "Wiki")
result = tr("Wiki");
else if (title == "Bugs and Feature Requests")
result = tr("Bugs and Feature Requests");
else if (title == "Developer Blog")
result = tr("Developer Blog");
else if (title == "Mailing List")
result = tr("Mailing List");
else
{
std::cout << "please add the untranslated title \"" << qPrintable(title) << "\" to About::trLinksTitle()" << std::endl;
result = title;
}
return result;
}
/*!
* parse a text file and return an author list in an html table:
* left the names and right the contact address
* the html table can be "split" in sections
* @param QString fileName the file to be parsed
* @return QString the html table
*/
QString About::parseAuthorFile(const QString& fileName)
{
QString result;
QString file;
QFile authorsFile(fileName);
if (authorsFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream inTS(&authorsFile);
inTS.setCodec("UTF-8");
inTS.setAutoDetectUnicode(true);
QString lineTS;
QStringList fieldTS;
QString name;
QString contact;
bool isTitle = true;
bool startText = false;
bool startTitle = false;
result = "<table>";
while (!inTS.atEnd())
{
lineTS = inTS.readLine();
// convert (r) "�" to ®, "�" to ™
// lineTS = QString::fromUtf8(lineTS);
lineTS.replace("<", "<");
lineTS.replace(">", ">");
lineTS.replace("�", "®");
lineTS.replace("�", "™");
name = "";
contact = "";
if (!lineTS.isEmpty())
{
if (isTitle)
{
startTitle = false;
result += "<tr><td><b>" + About::trAuthorTitle(lineTS) + "</b></td><td></td></tr>";
}
else
{
startText = false;
fieldTS = lineTS.split(" ");
contact = fieldTS.isEmpty() ? QString() : fieldTS.takeLast();
name = fieldTS.isEmpty() ? QString() : fieldTS.join(" ");
result += "<tr><td>" +name + "</td><td>" + (contact == "@" ? "" : contact) + "</td></tr>";
}
} // if is empty line
else
{
// empty lines switch between title and text
if (!startText && !startTitle)
{
isTitle = !isTitle;
if (isTitle)
{
result += "<tr><td></td><td></td></tr>";
startTitle = true;
}
else
{
startText = true;
}
}
} // else is empty line
} // while ! atEnd
result += "<table>";
} // if file found
else
{
if (!fileName.isEmpty())
{
QStringList field = fileName.split("/");
if (!field.isEmpty())
{
file = field.takeLast();
}
}
result = tr("Unable to open %1 file. Please check your install directory or the Scribus website for %1 information.").arg(file);
result = "";
} // else file found
return result;
} // parseTextFile()
/*!
* parse a text file and return an author list in an html table:
* left the names and right the contact address
* the html table can be "split" in sections
* @param QString fileName the file to be parsed
* @return QString the html table
*/
QString About::parseTranslationFile(const QString& fileName)
{
QString result;
QString file;
QFile translationFile(fileName);
if (translationFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream inTS(&translationFile);
inTS.setCodec("UTF-8");
inTS.setAutoDetectUnicode(true);
QString lineTS;
QStringList fieldTS;
QString code;
QString name;
QString contact;
// LanguageManager langmgr;
// langmgr.init(false);
bool isSectionTitle = true;
bool isTitle = false;
bool startText = false;
bool startTitle = false;
result = "<table>";
QMap<QString, QString> sections;
QMap<QString, QString> languages;
QMultiMap<QString, QString> names;
QString currLang;
int section=0;
QString snum;
while (!inTS.atEnd())
{
lineTS = inTS.readLine();
lineTS.replace("<", "<");
lineTS.replace(">", ">");
name = "";
contact = "";
if (!lineTS.isEmpty())
{
if (isSectionTitle)
{
++section;
snum.setNum(section);
//result += "<tr><td><b><i>"+About::trTranslationTitle(lineTS)+"</i></b></td><td></td></tr>";
sections.insert(snum, "<tr><td><b><i>"+About::trTranslationTitle(lineTS)+"</i></b></td><td></td></tr>");
isSectionTitle = false;
isTitle = false;
startTitle = false;
}
else if (isTitle)
{
startTitle = false;
fieldTS = lineTS.split(" ");
code = (fieldTS.isEmpty() ? "" : fieldTS.takeLast());
if (!code.isEmpty())
{
code.replace("(", "");
code.replace(")", "");
code = LanguageManager::instance()->getLangFromAbbrev(code);
}
//result += "<tr><td><b>"+code+"</b></td><td></td></tr>";
languages.insert(snum+":"+code, "<tr><td><b>"+code+"</b></td><td></td></tr>");
isTitle = false;
currLang=code;
} // if is title
else
{
startText = false;
fieldTS = lineTS.split(" ");
contact = (fieldTS.isEmpty() ? "" : fieldTS.takeLast());
contact.replace("(", "");
contact.replace(")", "");
name = (fieldTS.isEmpty() ? "" : fieldTS.join(" "));
//result += "<tr><td>"+name+"</td><td>"+(contact == "@" ? "" : contact)+"</td></tr>";
names.insert(snum+":"+code, "<tr><td>"+name+"</td><td>"+(contact == "@" ? "" : contact)+"</td></tr>");
} // else is title
} // if is empty line
else
{
// empty lines switch between title and text
if (!startText && !startTitle)
{
isTitle = !isTitle;
if (isTitle)
{
//result += "<tr><td></td><td></td></tr>";
startTitle = true;
}
else
{
startText = true;
}
//
// multiple empty lines start a section instead of marking a title
}
else if (startTitle)
{
isTitle = false;
isSectionTitle = true;
}
} // else is empty line
} // while ! atEnd
QMapIterator<QString, QString> s(sections);
while (s.hasNext())
{
s.next();
result += s.value();
result += "<tr><td></td><td></td></tr>";
QMapIterator<QString, QString> l(languages);
while (l.hasNext())
{
l.next();
QStringList sl=l.key().split(":");
if (s.key()==sl.first())
{
result += l.value();
QMapIterator<QString, QString> n(names);
while (n.hasNext())
{
n.next();
if (n.key()==l.key())
result += n.value();
}
result += "<tr><td></td><td></td></tr>";
}
}
result += "<tr><td></td><td></td></tr><tr><td></td><td></td></tr>";
}
result += "<table>";
} // if file found
else
{
if (!fileName.isEmpty())
{
QStringList field = fileName.split("/");
if (!field.isEmpty())
{
file = field.takeLast();
}
}
result = tr("Unable to open %1 file. Please check your install directory or the Scribus website for %1 information.").arg(file);
result = "";
} // else file found
return result;
} // parseTranslationFile()
/*!
* parse a text file and return a links list in html format:
* left the names and right the contact address
* the html table can be "split" in sections
* @param QString fileName the file to be parsed
* @return QString the html table
*/
QString About::parseLinksFile(const QString& fileName)
{
QString result;
QString file;
QFile linksFile(fileName);
if (linksFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream inTS(&linksFile);
inTS.setCodec("UTF-8");
inTS.setAutoDetectUnicode(true);
QString lineTS;
bool isTitle = true;
result = "<table>";
while (!inTS.atEnd())
{
lineTS = inTS.readLine();
// convert (r) "�" to ®, "�" to ™
// lineTS = QString::fromUtf8(lineTS);
lineTS.replace("<", "<");
lineTS.replace(">", ">");
lineTS.replace("�", "®");
lineTS.replace("�", "™");
if (!lineTS.isEmpty())
{
if (isTitle)
{
isTitle = false;
result += "<tr><td><b>"+About::trLinksTitle(lineTS)+"</b></td></tr>";
} // if is title
else
{
result += "<tr><td><a href=\""+lineTS+"\">"+lineTS+"</a></td></tr>";
} // else is title
} // if is empty line
else
{
// empty lines switch to title (one line)
result += "<tr><td></td></tr>";
isTitle = true;
} // else is empty line
} // while ! atEnd
result += "<table>";
} // if file found
else
{
if (!fileName.isEmpty())
{
QStringList field = fileName.split("/");
if (!field.isEmpty())
file = field.takeLast();
}
result = tr("Unable to open %1 file. Please check your install directory or the Scribus website for %1 information.").arg(file);
result = "";
} // else file found
return result;
} // parseLinksFile()
QString About::generateBuildInfo()
{
QString BUILD_DAY = "26";
QString BUILD_MONTH = CommonStrings::september;
QString BUILD_YEAR = "2022";
QString BUILD_TIME;
QString BUILD_TZ;
QString BUILD_NAME;
QString built = tr("%1 %2 %3").arg(BUILD_DAY, BUILD_MONTH, BUILD_YEAR);
QString version(ScribusAPI::getVersion());
if (BUILD_NAME != "")
version += " \"" + BUILD_NAME + "\"";
if (BUILD_NAME == "BleedingEdge")
built = tr("%3-%2-%1 %4 %5").arg(BUILD_DAY, BUILD_MONTH, BUILD_YEAR, BUILD_TIME, BUILD_TZ);
QString revText;
if (ScribusAPI::isSVN() && ScribusAPI::haveSVNRevision())
revText = tr("SVN Revision: %1").arg(ScribusAPI::getSVNRevision());
QString gsver(getGSVersion());
if (gsver.isEmpty())
gsver = tr("No Ghostscript version available");
QString buildText;
buildText.append("<p>");
buildText.append("<b>");
buildText.append(tr("Scribus Version %1").arg(version));
buildText.append("</b>");
buildText.append("</p><p>");
buildText.append(tr("Build ID: %1").arg(ScribusAPI::getBuildInformation()));
buildText.append("<br>");
if (!revText.isEmpty())
{
buildText.append(revText);
buildText.append("<br>");
}
buildText.append(tr("Built: %1").arg(built));
buildText.append("</p>");
buildText.append("<b>");
buildText.append(tr("Companion Programs:"));
buildText.append("</b>");
buildText.append("</p><p>");
buildText.append(tr("Ghostscript: %1").arg(gsver));
buildText.append("</p><p>");
buildText.append("<b>");
buildText.append(tr("Libraries:"));
buildText.append("</b>");
buildText.append("</p><p>");
buildText.append(tr("cairo: %1").arg(CAIRO_VERSION_STRING));
buildText.append("<br>");
buildText.append(tr("Harfbuzz: %1").arg(HB_VERSION_STRING));
buildText.append("<br>");
buildText.append(tr("littlcms: %1").arg(LCMS_VERSION));
buildText.append("<br>");
QString podofoVersion;
#ifdef HAVE_PODOFO
podofoVersion.append(PODOFO_VERSION_STRING);
#endif
buildText.append(tr("podofo: %1").arg(podofoVersion));
buildText.append("<br>");
QString popplerVersion;
#ifdef HAVE_POPPLER
popplerVersion.append(POPPLER_VERSION);
#endif
buildText.append(tr("poppler: %1").arg(popplerVersion));
buildText.append("</p>");
return buildText;
}
void About::setVisible (bool visible)
{
QDialog::setVisible(visible);
if (m_firstShow && (m_mode == About::CheckUpdates) && visible)
{
m_firstShow = false;
runUpdateCheck();
}
}
void About::runUpdateCheck()
{
updateView->clear();
UpgradeCheckerGUI uc(updateView);
disconnect( checkForUpdateButton, SIGNAL( clicked() ), this, SLOT( runUpdateCheck() ) );
uc.fetch();
connect( checkForUpdateButton, SIGNAL( clicked() ), this, SLOT( runUpdateCheck() ) );
}