You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
753 lines
25 KiB
753 lines
25 KiB
/* |
|
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()); |
|
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); |
|
} |
|
|
|
}
|
|
|