2022-03-05 22:41:29 +05:00

754 lines
25 KiB
C++

/*
SPDX-FileCopyrightText: 2003-2007 Craig Drummond <craig@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "JobRunner.h"
#include "ActionLabel.h"
#include "Fc.h"
#include "KfiConstants.h"
#include "Misc.h"
#include "config-fontinst.h"
#include <KConfigGroup>
#include <KIO/FileCopyJob>
#include <KIO/StatJob>
#include <KJobWidgets>
#include <KSharedConfig>
#include <QCheckBox>
#include <QCloseEvent>
#include <QDBusServiceWatcher>
#include <QDebug>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QLabel>
#include <QProcess>
#include <QProgressBar>
#include <QPushButton>
#include <QStackedWidget>
#include <QStyle>
#include <QStyleOption>
#include <QTemporaryDir>
#include <QTimer>
#include <QUrlQuery>
#include <QVBoxLayout>
#include <QX11Info>
#include <X11/Xlib.h>
#include <fontconfig/fontconfig.h>
#include <kio/global.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <unistd.h>
#define CFG_GROUP "Runner Dialog"
#define CFG_DONT_SHOW_FINISHED_MSG "DontShowFinishedMsg"
namespace KFI
{
Q_GLOBAL_STATIC(FontInstInterface, theInterface)
FontInstInterface *CJobRunner::dbus()
{
return theInterface;
}
QString CJobRunner::folderName(bool sys)
{
if (!theInterface) {
return QString();
}
QDBusPendingReply<QString> reply = theInterface->folderName(sys);
reply.waitForFinished();
return reply.isError() ? QString() : reply.argumentAt<0>();
}
void CJobRunner::startDbusService()
{
if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(OrgKdeFontinstInterface::staticInterfaceName())) {
const QString fontinst = QStringLiteral(KFONTINST_LIB_EXEC_DIR "/fontinst");
qDebug() << "Service " << OrgKdeFontinstInterface::staticInterfaceName() << " not registered, starting" << fontinst;
QProcess::startDetached(fontinst, QStringList());
}
}
static const int constDownloadFailed = -1;
static const int constInterfaceCheck = 5 * 1000;
static void decode(const QUrl &url, Misc::TFont &font, bool &system)
{
font = FC::decode(url);
QUrlQuery query(url);
system = (query.hasQueryItem("sys") && query.queryItemValue("sys") == QLatin1String("true"));
}
QUrl CJobRunner::encode(const QString &family, quint32 style, bool system)
{
QUrl url(FC::encode(family, style));
QUrlQuery query(url);
query.addQueryItem(QStringLiteral("sys"), system ? QStringLiteral("true") : QStringLiteral("false"));
url.setQuery(query);
return url;
}
enum EPages {
PAGE_PROGRESS,
PAGE_SKIP,
PAGE_ERROR,
PAGE_CANCEL,
PAGE_COMPLETE,
};
enum Response {
RESP_CONTINUE,
RESP_AUTO,
RESP_CANCEL,
};
static void addIcon(QGridLayout *layout, QFrame *page, const char *iconName, int iconSize)
{
QLabel *icon = new QLabel(page);
icon->setPixmap(QIcon::fromTheme(iconName).pixmap(iconSize));
icon->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
layout->addWidget(icon, 0, 0);
}
CJobRunner::CJobRunner(QWidget *parent, int xid)
: QDialog(parent)
, m_it(m_urls.end())
, m_end(m_it)
, m_autoSkip(false)
, m_cancelClicked(false)
, m_modified(false)
, m_tempDir(nullptr)
{
setModal(true);
if (nullptr == parent && 0 != xid) {
XSetTransientForHint(QX11Info::display(), winId(), xid);
}
m_buttonBox = new QDialogButtonBox;
connect(m_buttonBox, &QDialogButtonBox::clicked, this, &CJobRunner::slotButtonClicked);
m_skipButton = new QPushButton(i18n("Skip"));
m_buttonBox->addButton(m_skipButton, QDialogButtonBox::ActionRole);
m_skipButton->hide();
m_autoSkipButton = new QPushButton(i18n("AutoSkip"));
m_buttonBox->addButton(m_autoSkipButton, QDialogButtonBox::ActionRole);
m_autoSkipButton->hide();
m_stack = new QStackedWidget(this);
QVBoxLayout *mainLayout = new QVBoxLayout;
setLayout(mainLayout);
mainLayout->addWidget(m_stack);
mainLayout->addWidget(m_buttonBox);
QStyleOption option;
option.initFrom(this);
int iconSize = style()->pixelMetric(QStyle::PM_MessageBoxIconSize, &option, this);
QFrame *page = new QFrame(m_stack);
QGridLayout *layout = new QGridLayout(page);
m_statusLabel = new QLabel(page);
m_progress = new QProgressBar(page);
// m_statusLabel->setWordWrap(true);
layout->addWidget(m_actionLabel = new CActionLabel(this), 0, 0, 2, 1);
layout->addWidget(m_statusLabel, 0, 1);
layout->addWidget(m_progress, 1, 1);
layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding), 2, 0);
m_stack->insertWidget(PAGE_PROGRESS, page);
page = new QFrame(m_stack);
layout = new QGridLayout(page);
m_skipLabel = new QLabel(page);
m_skipLabel->setWordWrap(true);
addIcon(layout, page, "dialog-error", iconSize);
layout->addWidget(m_skipLabel, 0, 1);
layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding), 1, 0);
m_stack->insertWidget(PAGE_SKIP, page);
page = new QFrame(m_stack);
layout = new QGridLayout(page);
m_errorLabel = new QLabel(page);
m_errorLabel->setWordWrap(true);
addIcon(layout, page, "dialog-error", iconSize);
layout->addWidget(m_errorLabel, 0, 1);
layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding), 1, 0);
m_stack->insertWidget(PAGE_ERROR, page);
page = new QFrame(m_stack);
layout = new QGridLayout(page);
QLabel *cancelLabel = new QLabel(i18n("<h3>Cancel?</h3><p>Are you sure you wish to cancel?</p>"), page);
cancelLabel->setWordWrap(true);
addIcon(layout, page, "dialog-warning", iconSize);
layout->addWidget(cancelLabel, 0, 1);
layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding), 1, 0);
m_stack->insertWidget(PAGE_CANCEL, page);
if (KSharedConfig::openConfig(KFI_UI_CFG_FILE)->group(CFG_GROUP).readEntry(CFG_DONT_SHOW_FINISHED_MSG, false)) {
m_dontShowFinishedMsg = nullptr;
} else {
page = new QFrame(m_stack);
layout = new QGridLayout(page);
QLabel *finishedLabel = new QLabel(i18n("<h3>Finished</h3>"
"<p>Please note that any open applications will need to be "
"restarted in order for any changes to be noticed.</p>"),
page);
finishedLabel->setWordWrap(true);
addIcon(layout, page, "dialog-information", iconSize);
layout->addWidget(finishedLabel, 0, 1);
layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding), 1, 0);
m_dontShowFinishedMsg = new QCheckBox(i18n("Do not show this message again"), page);
m_dontShowFinishedMsg->setChecked(false);
layout->addItem(new QSpacerItem(0, layout->spacing(), QSizePolicy::Fixed, QSizePolicy::Fixed), 2, 0);
layout->addWidget(m_dontShowFinishedMsg, 3, 1);
layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding), 4, 0);
m_stack->insertWidget(PAGE_COMPLETE, page);
}
QDBusServiceWatcher *watcher = new QDBusServiceWatcher(QLatin1String(OrgKdeFontinstInterface::staticInterfaceName()),
QDBusConnection::sessionBus(),
QDBusServiceWatcher::WatchForOwnerChange,
this);
connect(watcher, &QDBusServiceWatcher::serviceOwnerChanged, this, &CJobRunner::dbusServiceOwnerChanged);
connect(dbus(), &OrgKdeFontinstInterface::status, this, &CJobRunner::dbusStatus);
setMinimumSize(420, 160);
}
CJobRunner::~CJobRunner()
{
delete m_tempDir;
}
void CJobRunner::getAssociatedUrls(const QUrl &url, QList<QUrl> &list, bool afmAndPfm, QWidget *widget)
{
QString ext(url.path());
int dotPos(ext.lastIndexOf('.'));
bool check(false);
if (-1 == dotPos) { // Hmm, no extension - check anyway...
check = true;
} else // Cool, got an extension - see if it is a Type1 font...
{
ext = ext.mid(dotPos + 1);
check = 0 == ext.compare("pfa", Qt::CaseInsensitive) || 0 == ext.compare("pfb", Qt::CaseInsensitive);
}
if (check) {
const char *afm[] = {"afm", "AFM", "Afm", nullptr}, *pfm[] = {"pfm", "PFM", "Pfm", nullptr};
bool gotAfm(false), localFile(url.isLocalFile());
int e;
for (e = 0; afm[e]; ++e) {
QUrl statUrl(url);
statUrl.setPath(Misc::changeExt(url.path(), afm[e]));
bool urlExists = false;
if (localFile) {
urlExists = Misc::fExists(statUrl.toLocalFile());
} else {
auto job = KIO::stat(statUrl);
KJobWidgets::setWindow(job, widget);
job->exec();
urlExists = !job->error();
}
if (urlExists) {
list.append(statUrl);
gotAfm = true;
break;
}
}
if (afmAndPfm || !gotAfm) {
for (e = 0; pfm[e]; ++e) {
QUrl statUrl(url);
statUrl.setPath(Misc::changeExt(url.path(), pfm[e]));
bool urlExists = false;
if (localFile) {
urlExists = Misc::fExists(statUrl.toLocalFile());
} else {
auto job = KIO::stat(statUrl);
KJobWidgets::setWindow(job, widget);
job->exec();
urlExists = !job->error();
}
if (urlExists) {
list.append(statUrl);
break;
}
}
}
}
}
static void addEnableActions(CJobRunner::ItemList &urls)
{
CJobRunner::ItemList modified;
CJobRunner::ItemList::ConstIterator it(urls.constBegin()), end(urls.constEnd());
for (; it != end; ++it) {
if ((*it).isDisabled) {
CJobRunner::Item item(*it);
item.fileName = QLatin1String("--");
modified.append(item);
}
modified.append(*it);
}
urls = modified;
}
int CJobRunner::exec(ECommand cmd, const ItemList &urls, bool destIsSystem)
{
m_autoSkip = m_cancelClicked = m_modified = false;
switch (cmd) {
case CMD_INSTALL:
setWindowTitle(i18n("Installing"));
break;
case CMD_DELETE:
setWindowTitle(i18n("Uninstalling"));
break;
case CMD_ENABLE:
setWindowTitle(i18n("Enabling"));
break;
case CMD_MOVE:
setWindowTitle(i18n("Moving"));
break;
case CMD_UPDATE:
setWindowTitle(i18n("Updating"));
m_modified = true;
break;
case CMD_REMOVE_FILE:
setWindowTitle(i18n("Removing"));
break;
default:
case CMD_DISABLE:
setWindowTitle(i18n("Disabling"));
}
m_destIsSystem = destIsSystem;
m_urls = urls;
if (CMD_INSTALL == cmd) {
std::sort(m_urls.begin(), m_urls.end()); // Sort list of fonts so that we have type1 fonts followed by their metrics...
} else if (CMD_MOVE == cmd) {
addEnableActions(m_urls);
}
m_it = m_urls.constBegin();
m_end = m_urls.constEnd();
m_prev = m_end;
m_progress->setValue(0);
m_progress->setRange(0, m_urls.count() + 1);
m_progress->show();
m_cmd = cmd;
m_currentFile = QString();
m_statusLabel->setText(QString());
setPage(PAGE_PROGRESS);
QTimer::singleShot(0, this, &CJobRunner::doNext);
QTimer::singleShot(constInterfaceCheck, this, &CJobRunner::checkInterface);
m_actionLabel->startAnimation();
int rv = QDialog::exec();
if (m_tempDir) {
delete m_tempDir;
m_tempDir = nullptr;
}
return rv;
}
void CJobRunner::doNext()
{
if (m_it == m_end /* || CMD_UPDATE==m_cmd*/) {
if (m_modified) {
// Force reconfig if command was already set to update...
dbus()->reconfigure(getpid(), CMD_UPDATE == m_cmd);
m_cmd = CMD_UPDATE;
m_statusLabel->setText(i18n("Updating font configuration. Please wait…"));
m_progress->setValue(m_progress->maximum());
Q_EMIT configuring();
} else {
m_actionLabel->stopAnimation();
if (PAGE_ERROR != m_stack->currentIndex()) {
reject();
}
}
} else {
Misc::TFont font;
bool system;
switch (m_cmd) {
case CMD_INSTALL: {
m_currentFile = fileName((*m_it));
if (m_currentFile.isEmpty()) { // Failed to download...
dbusStatus(getpid(), constDownloadFailed);
} else {
// Create AFM if this is a PFM, and the previous was not the AFM for this font...
bool createAfm =
Item::TYPE1_PFM == (*m_it).type && (m_prev == m_end || (*m_it).fileName != (*m_prev).fileName || Item::TYPE1_AFM != (*m_prev).type);
dbus()->install(m_currentFile, createAfm, m_destIsSystem, getpid(), false);
}
break;
}
case CMD_DELETE:
decode(*m_it, font, system);
dbus()->uninstall(font.family, font.styleInfo, system, getpid(), false);
break;
case CMD_ENABLE:
decode(*m_it, font, system);
dbus()->enable(font.family, font.styleInfo, system, getpid(), false);
break;
case CMD_DISABLE:
decode(*m_it, font, system);
dbus()->disable(font.family, font.styleInfo, system, getpid(), false);
break;
case CMD_MOVE:
decode(*m_it, font, system);
// To 'Move' a disabled font, we first need to enable it. To accomplish this, JobRunner creates a 'fake' entry
// with the filename "--"
if ((*m_it).fileName == QLatin1String("--")) {
setWindowTitle(i18n("Enabling"));
dbus()->enable(font.family, font.styleInfo, system, getpid(), false);
} else {
if (m_prev != m_end && (*m_prev).fileName == QLatin1String("--")) {
setWindowTitle(i18n("Moving"));
}
dbus()->move(font.family, font.styleInfo, m_destIsSystem, getpid(), false);
}
break;
case CMD_REMOVE_FILE:
decode(*m_it, font, system);
dbus()->removeFile(font.family, font.styleInfo, (*m_it).fileName, system, getpid(), false);
break;
default:
break;
}
m_statusLabel->setText(CMD_INSTALL == m_cmd ? (*m_it).url() : FC::createName(FC::decode(*m_it)));
m_progress->setValue(m_progress->value() + 1);
// Keep copy of this iterator - so that can check whether AFM should be created.
m_prev = m_it;
}
}
void CJobRunner::checkInterface()
{
if (m_it == m_urls.constBegin() && !FontInst::isStarted(dbus())) {
setPage(PAGE_ERROR, i18n("Unable to start backend."));
m_actionLabel->stopAnimation();
m_it = m_end;
}
}
void CJobRunner::dbusServiceOwnerChanged(const QString &name, const QString &from, const QString &to)
{
if (to.isEmpty() && !from.isEmpty() && name == QLatin1String(OrgKdeFontinstInterface::staticInterfaceName()) && m_it != m_end) {
setPage(PAGE_ERROR, i18n("Backend died, but has been restarted. Please try again."));
m_actionLabel->stopAnimation();
m_it = m_end;
}
}
void CJobRunner::dbusStatus(int pid, int status)
{
if (pid != getpid()) {
return;
}
if (CMD_UPDATE == m_cmd) {
setPage(PAGE_COMPLETE);
return;
}
m_lastDBusStatus = status;
if (m_cancelClicked) {
m_actionLabel->stopAnimation();
setPage(PAGE_CANCEL);
return;
/*
if(RESP_CANCEL==m_response)
m_it=m_end;
m_cancelClicked=false;
setPage(PAGE_PROGRESS);
m_actionLabel->startAnimation();
*/
}
// m_it will equal m_end if user decided to cancel the current op
if (m_it == m_end) {
doNext();
} else if (0 == status) {
m_modified = true;
++m_it;
doNext();
} else {
bool cont(m_autoSkip && m_urls.count() > 1);
QString currentName((*m_it).fileName);
if (!cont) {
m_actionLabel->stopAnimation();
if (FontInst::STATUS_SERVICE_DIED == status) {
setPage(PAGE_ERROR, errorString(status));
m_it = m_end;
} else {
ItemList::ConstIterator lastPartOfCurrent(m_it), next(m_it == m_end ? m_end : m_it + 1);
// If we're installing a Type1 font, and its already installed - then we need to skip past AFM/PFM
if (next != m_end && Item::TYPE1_FONT == (*m_it).type && (*next).fileName == currentName
&& (Item::TYPE1_AFM == (*next).type || Item::TYPE1_PFM == (*next).type)) {
next++;
if (next != m_end && (*next).fileName == currentName && (Item::TYPE1_AFM == (*next).type || Item::TYPE1_PFM == (*next).type)) {
next++;
}
}
if (1 == m_urls.count() || next == m_end) {
setPage(PAGE_ERROR, errorString(status));
} else {
setPage(PAGE_SKIP, errorString(status));
return;
}
}
}
contineuToNext(cont);
}
}
void CJobRunner::contineuToNext(bool cont)
{
m_actionLabel->startAnimation();
if (cont) {
if (CMD_INSTALL == m_cmd && Item::TYPE1_FONT == (*m_it).type) // Did we error on a pfa/pfb? if so, exclude the afm/pfm...
{
QString currentName((*m_it).fileName);
++m_it;
// Skip afm/pfm
if (m_it != m_end && (*m_it).fileName == currentName && (Item::TYPE1_AFM == (*m_it).type || Item::TYPE1_PFM == (*m_it).type)) {
++m_it;
}
// Skip pfm/afm
if (m_it != m_end && (*m_it).fileName == currentName && (Item::TYPE1_AFM == (*m_it).type || Item::TYPE1_PFM == (*m_it).type)) {
++m_it;
}
} else {
++m_it;
}
} else {
m_urls.empty();
m_it = m_end = m_urls.constEnd();
}
doNext();
}
void CJobRunner::slotButtonClicked(QAbstractButton *button)
{
switch (m_stack->currentIndex()) {
case PAGE_PROGRESS:
if (m_it != m_end) {
m_cancelClicked = true;
}
break;
case PAGE_SKIP:
setPage(PAGE_PROGRESS);
if (button == m_skipButton) {
contineuToNext(true);
} else if (button == m_autoSkipButton) {
m_autoSkip = true;
contineuToNext(true);
} else {
contineuToNext(false);
}
break;
case PAGE_CANCEL:
if (button == m_buttonBox->button(QDialogButtonBox::Yes)) {
m_it = m_end;
}
m_cancelClicked = false;
setPage(PAGE_PROGRESS);
m_actionLabel->startAnimation();
// Now continue...
dbusStatus(getpid(), m_lastDBusStatus);
break;
case PAGE_COMPLETE:
if (m_dontShowFinishedMsg) {
KConfigGroup grp(KSharedConfig::openConfig(KFI_UI_CFG_FILE)->group(CFG_GROUP));
grp.writeEntry(CFG_DONT_SHOW_FINISHED_MSG, m_dontShowFinishedMsg->isChecked());
}
case PAGE_ERROR:
QDialog::accept();
break;
}
}
void CJobRunner::closeEvent(QCloseEvent *e)
{
if (PAGE_COMPLETE != m_stack->currentIndex()) {
e->ignore();
slotButtonClicked(PAGE_CANCEL == m_stack->currentIndex() ? m_buttonBox->button(QDialogButtonBox::No) : m_buttonBox->button(QDialogButtonBox::Cancel));
}
}
void CJobRunner::setPage(int page, const QString &msg)
{
m_stack->setCurrentIndex(page);
switch (page) {
case PAGE_PROGRESS:
m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel);
m_skipButton->hide();
m_autoSkipButton->hide();
break;
case PAGE_SKIP:
m_skipLabel->setText(i18n("<h3>Error</h3>") + QLatin1String("<p>") + msg + QLatin1String("</p>"));
m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel);
m_skipButton->show();
m_autoSkipButton->show();
break;
case PAGE_ERROR:
m_errorLabel->setText(i18n("<h3>Error</h3>") + QLatin1String("<p>") + msg + QLatin1String("</p>"));
m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel);
m_skipButton->hide();
m_autoSkipButton->hide();
break;
case PAGE_CANCEL:
m_buttonBox->setStandardButtons(QDialogButtonBox::Yes | QDialogButtonBox::No);
m_skipButton->hide();
m_autoSkipButton->hide();
break;
case PAGE_COMPLETE:
if (!m_dontShowFinishedMsg || m_dontShowFinishedMsg->isChecked()) {
QDialog::accept();
} else {
m_buttonBox->setStandardButtons(QDialogButtonBox::Close);
m_skipButton->hide();
m_autoSkipButton->hide();
}
break;
}
}
QString CJobRunner::fileName(const QUrl &url)
{
if (url.isLocalFile()) {
return url.toLocalFile();
} else {
auto job = KIO::mostLocalUrl(url);
job->exec();
QUrl local = job->mostLocalUrl();
if (local.isLocalFile()) {
return local.toLocalFile(); // Yipee! no need to download!!
} else {
// Need to do actual download...
if (!m_tempDir) {
m_tempDir = new QTemporaryDir(QDir::tempPath() + "/fontinst");
m_tempDir->setAutoRemove(true);
}
QString tempName(m_tempDir->filePath(Misc::getFile(url.path())));
auto job = KIO::file_copy(url, QUrl::fromLocalFile(tempName), -1, KIO::Overwrite);
if (job->exec()) {
return tempName;
} else {
return QString();
}
}
}
}
QString CJobRunner::errorString(int value) const
{
Misc::TFont font(FC::decode(*m_it));
QString urlStr;
if (CMD_REMOVE_FILE == m_cmd) {
urlStr = (*m_it).fileName;
} else if (font.family.isEmpty()) {
urlStr = (*m_it).url();
} else {
urlStr = FC::createName(font.family, font.styleInfo);
}
switch (value) {
case constDownloadFailed:
return i18n("Failed to download <i>%1</i>", urlStr);
case FontInst::STATUS_SERVICE_DIED:
return i18n("System backend died. Please try again.<br><i>%1</i>", urlStr);
case FontInst::STATUS_BITMAPS_DISABLED:
return i18n("<i>%1</i> is a bitmap font, and these have been disabled on your system.", urlStr);
case FontInst::STATUS_ALREADY_INSTALLED:
return i18n("<i>%1</i> contains the font <b>%2</b>, which is already installed on your system.", urlStr, FC::getName(m_currentFile));
case FontInst::STATUS_NOT_FONT_FILE:
return i18n("<i>%1</i> is not a font.", urlStr);
case FontInst::STATUS_PARTIAL_DELETE:
return i18n("Could not remove all files associated with <i>%1</i>", urlStr);
case FontInst::STATUS_NO_SYS_CONNECTION:
return i18n("Failed to start the system daemon.<br><i>%1</i>", urlStr);
case KIO::ERR_FILE_ALREADY_EXIST: {
QString name(Misc::modifyName(Misc::getFile((*m_it).fileName))), destFolder(Misc::getDestFolder(folderName(m_destIsSystem), name));
return i18n("<i>%1</i> already exists.", destFolder + name);
}
case KIO::ERR_DOES_NOT_EXIST:
return i18n("<i>%1</i> does not exist.", urlStr);
case KIO::ERR_WRITE_ACCESS_DENIED:
return i18n("Permission denied.<br><i>%1</i>", urlStr);
case KIO::ERR_UNSUPPORTED_ACTION:
return i18n("Unsupported action.<br><i>%1</i>", urlStr);
case KIO::ERR_CANNOT_AUTHENTICATE:
return i18n("Authentication failed.<br><i>%1</i>", urlStr);
default:
return i18n("Unexpected error while processing: <i>%1</i>", urlStr);
}
}
CJobRunner::Item::Item(const QUrl &u, const QString &n, bool dis)
: QUrl(u)
, name(n)
, fileName(Misc::getFile(u.path()))
, isDisabled(dis)
{
type = Misc::checkExt(fileName, "pfa") || Misc::checkExt(fileName, "pfb") ? TYPE1_FONT
: Misc::checkExt(fileName, "afm") ? TYPE1_AFM
: Misc::checkExt(fileName, "pfm") ? TYPE1_PFM
: OTHER_FONT;
if (OTHER_FONT != type) {
int pos(fileName.lastIndexOf('.'));
if (-1 != pos) {
fileName.truncate(pos);
}
}
}
CJobRunner::Item::Item(const QString &file, const QString &family, quint32 style, bool system)
: QUrl(CJobRunner::encode(family, style, system))
, fileName(file)
, type(OTHER_FONT)
{
}
bool CJobRunner::Item::operator<(const Item &o) const
{
int nameComp(fileName.compare(o.fileName));
return nameComp < 0 || (0 == nameComp && type < o.type);
}
}