kde-workspace/kcontrol/kfontinst/dbus/FontInst.cpp
2015-05-20 13:39:58 +00:00

971 lines
31 KiB
C++

/*
* KFontInst - KDE Font Installer
*
* Copyright 2003-2009 Craig Drummond <craig@kde.org>
*
* ----
*
* 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.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <QtDBus/QDBusConnection>
#include <QtCore/QTimer>
#include <kauth.h>
#include <KDebug>
#include <kio/global.h>
#include <kde_file.h>
#include <fontconfig/fontconfig.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include "FontInst.h"
#include "fontinstadaptor.h"
#include "Misc.h"
#include "Fc.h"
#include "WritingSystems.h"
#include "Utils.h"
#include "FontinstIface.h"
#define KFI_DBUG kDebug() << time(0L)
namespace KFI
{
static void decompose(const QString &name, QString &family, QString &style)
{
int commaPos=name.lastIndexOf(',');
family=-1==commaPos ? name : name.left(commaPos);
style=-1==commaPos ? KFI_WEIGHT_REGULAR : name.mid(commaPos+2);
}
static bool isSystem=false;
static Folder theFolders[FontInst::FOLDER_COUNT];
static const int constSystemReconfigured=-1;
static const int constConnectionsTimeout = 30 * 1000;
static const int constFontListTimeout = 10 * 1000;
typedef void (*SignalHandler)(int);
static void registerSignalHandler(SignalHandler handler)
{
if (!handler)
handler = SIG_DFL;
sigset_t mask;
sigemptyset(&mask);
#ifdef SIGSEGV
signal(SIGSEGV, handler);
sigaddset(&mask, SIGSEGV);
#endif
#ifdef SIGFPE
signal(SIGFPE, handler);
sigaddset(&mask, SIGFPE);
#endif
#ifdef SIGILL
signal(SIGILL, handler);
sigaddset(&mask, SIGILL);
#endif
#ifdef SIGABRT
signal(SIGABRT, handler);
sigaddset(&mask, SIGABRT);
#endif
sigprocmask(SIG_UNBLOCK, &mask, 0);
}
void signalHander(int)
{
static bool inHandler=false;
if(!inHandler)
{
inHandler=true;
theFolders[isSystem ? FontInst::FOLDER_SYS : FontInst::FOLDER_USER].saveDisabled();
inHandler=false;
}
}
FontInst::FontInst()
{
isSystem=Misc::root();
registerTypes();
new FontinstAdaptor(this);
QDBusConnection bus=QDBusConnection::sessionBus();
KFI_DBUG << "Connecting to session bus";
if(!bus.registerService(OrgKdeFontinstInterface::staticInterfaceName()))
{
KFI_DBUG << "Failed to register service!";
::exit(-1);
}
if(!bus.registerObject(FONTINST_PATH, this))
{
KFI_DBUG << "Failed to register object!";
::exit(-1);
}
registerSignalHandler(signalHander);
itsConnectionsTimer=new QTimer(this);
itsFontListTimer=new QTimer(this);
connect(itsConnectionsTimer, SIGNAL(timeout()), SLOT(connectionsTimeout()));
connect(itsFontListTimer, SIGNAL(timeout()), SLOT(fontListTimeout()));
itsConnectionsTimer->start(constConnectionsTimeout);
itsFontListTimer->start(constFontListTimeout);
for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i)
theFolders[i].init(FOLDER_SYS==i, isSystem);
updateFontList(false);
}
FontInst::~FontInst()
{
for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i)
theFolders[i].saveDisabled();
}
void FontInst::list(int folders, int pid)
{
KFI_DBUG << folders << pid;
itsConnections.insert(pid);
updateFontList(false);
QList<KFI::Families> fonts;
for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i)
if(0==folders || folders&(1<<i))
fonts+=theFolders[i].list();
itsConnectionsTimer->start(constConnectionsTimeout);
itsFontListTimer->start(constFontListTimeout);
emit fontList(pid, fonts);
}
void FontInst::stat(const QString &name, int folders, int pid)
{
KFI_DBUG << name << folders << pid;
bool checkSystem=0==folders || folders&SYS_MASK || isSystem,
checkUser=0==folders || (folders&USR_MASK && !isSystem);
FamilyCont::ConstIterator fam;
StyleCont::ConstIterator st;
itsConnections.insert(pid);
if( (checkSystem && findFont(name, FOLDER_SYS, fam, st)) ||
(checkUser && findFont(name, FOLDER_USER, fam, st, !checkSystem)) )
{
Family rv((*fam).name());
rv.add(*st);
KFI_DBUG << "Found font, emit details...";
emit fontStat(pid, rv);
}
else
{
KFI_DBUG << "Font not found, emit empty details...";
emit fontStat(pid, Family(name));
}
}
void FontInst::install(const QString &file, bool createAfm, bool toSystem, int pid, bool checkConfig)
{
KFI_DBUG << file << createAfm << toSystem << pid << checkConfig;
itsConnections.insert(pid);
if(checkConfig)
updateFontList();
EFolder folder=isSystem || toSystem ? FOLDER_SYS : FOLDER_USER;
Family font;
Utils::EFileType type=Utils::check(file, font);
int result=Utils::FILE_BITMAP==type && !FC::bitmapsEnabled()
? STATUS_BITMAPS_DISABLED
: Utils::FILE_INVALID==type
? STATUS_NOT_FONT_FILE
: STATUS_OK;
if(STATUS_OK==result)
{
if(Utils::FILE_AFM!=type && Utils::FILE_PFM!=type)
for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT) && STATUS_OK==result; ++i)
if(theFolders[i].contains(font.name(), (*font.styles().begin()).value()))
result=STATUS_ALREADY_INSTALLED;
if(STATUS_OK==result)
{
QString name(Misc::modifyName(Misc::getFile(file))),
destFolder(Misc::getDestFolder(theFolders[folder].location(), name));
result=Utils::FILE_AFM!=type && Utils::FILE_PFM!=type && Misc::fExists(destFolder+name) ? (int)KIO::ERR_FILE_ALREADY_EXIST : (int)STATUS_OK;
if(STATUS_OK==result)
{
if(toSystem && !isSystem)
{
KFI_DBUG << "Send request to system helper" << file << destFolder << name;
QVariantMap args;
args["method"] = "install";
args["file"] = file;
args["name"] = name;
args["destFolder"] = destFolder;
args["createAfm"] = createAfm;
args["type"] = (int)type;
result=performAction(args);
}
else
{
if(!Misc::dExists(destFolder))
result=Misc::createDir(destFolder) ? (int)STATUS_OK : (int)KIO::ERR_WRITE_ACCESS_DENIED;
if(STATUS_OK==result)
result=QFile::copy(file, destFolder+name) ? (int)STATUS_OK : (int)KIO::ERR_WRITE_ACCESS_DENIED;
if(STATUS_OK==result)
{
Misc::setFilePerms(QFile::encodeName(destFolder+name));
if((Utils::FILE_SCALABLE==type || Utils::FILE_PFM==type) && createAfm)
Utils::createAfm(destFolder+name, type);
}
}
if(STATUS_OK==result && Utils::FILE_AFM!=type && Utils::FILE_PFM!=type)
{
StyleCont::ConstIterator st(font.styles().begin());
FileCont::ConstIterator f((*st).files().begin());
File df(destFolder+name, (*f).foundry(), (*f).index());
(*st).clearFiles();
(*st).add(df);
theFolders[folder].add(font);
theFolders[folder].addModifiedDir(destFolder);
emit fontsAdded(Families(font, FOLDER_SYS==folder));
}
}
}
}
emit status(pid, result);
itsConnectionsTimer->start(constConnectionsTimeout);
itsFontListTimer->start(constFontListTimeout);
}
void FontInst::uninstall(const QString &family, quint32 style, bool fromSystem, int pid, bool checkConfig)
{
KFI_DBUG << family << style << fromSystem << pid << checkConfig;
itsConnections.insert(pid);
if(checkConfig)
updateFontList();
EFolder folder=isSystem || fromSystem ? FOLDER_SYS : FOLDER_USER;
FamilyCont::ConstIterator fam;
StyleCont::ConstIterator st;
int result=findFont(family, style, folder, fam, st) ? (int)STATUS_OK : (int)KIO::ERR_DOES_NOT_EXIST;
if(STATUS_OK==result)
{
Family del((*fam).name());
Style s((*st).value(), (*st).scalable(), (*st).writingSystems());
FileCont files((*st).files());
FileCont::ConstIterator it(files.begin()),
end(files.end());
if(fromSystem && !isSystem)
{
QStringList fileList;
bool wasDisabled(false);
for(; it!=end; ++it)
{
fileList.append((*it).path());
theFolders[FOLDER_SYS].addModifiedDir(Misc::getDir((*it).path()));
if(!wasDisabled && Misc::isHidden(Misc::getFile((*it).path())))
wasDisabled=true;
}
QVariantMap args;
args["method"] = "uninstall";
args["files"] = fileList;
result=performAction(args);
if(STATUS_OK==result)
{
FileCont empty;
s.setFiles(files);
(*st).setFiles(empty);
if(wasDisabled)
theFolders[FOLDER_SYS].setDisabledDirty();
}
}
else
{
for(; it!=end; ++it)
if(!Misc::fExists((*it).path()) || QFile::remove((*it).path()))
{
// Also remove any AFM or PFM files...
QStringList other;
Misc::getAssociatedFiles((*it).path(), other);
QStringList::ConstIterator oit(other.constBegin()),
oend(other.constEnd());
for(; oit!=oend; ++oit)
QFile::remove(*oit);
theFolders[folder].addModifiedDir(Misc::getDir((*it).path()));
(*st).remove(*it);
s.add(*it);
if(!theFolders[folder].disabledDirty() && Misc::isHidden(Misc::getFile((*it).path())))
theFolders[folder].setDisabledDirty();
}
}
if(STATUS_OK==result)
{
if((*st).files().isEmpty())
{
(*fam).remove(*st);
if((*fam).styles().isEmpty())
theFolders[folder].removeFont(*fam);
}
else
result=STATUS_PARTIAL_DELETE;
del.add(s);
}
emit fontsRemoved(Families(del, FOLDER_SYS==folder));
}
KFI_DBUG << "status" << result;
emit status(pid, result);
itsConnectionsTimer->start(constConnectionsTimeout);
itsFontListTimer->start(constFontListTimeout);
}
void FontInst::uninstall(const QString &name, bool fromSystem, int pid, bool checkConfig)
{
KFI_DBUG << name << fromSystem << pid << checkConfig;
FamilyCont::ConstIterator fam;
StyleCont::ConstIterator st;
if(findFont(name, fromSystem || isSystem ? FOLDER_SYS : FOLDER_USER, fam, st))
uninstall((*fam).name(), (*st).value(), fromSystem, pid, checkConfig);
else
emit status(pid, KIO::ERR_DOES_NOT_EXIST);
}
void FontInst::move(const QString &family, quint32 style, bool toSystem, int pid, bool checkConfig)
{
KFI_DBUG << family << style << toSystem << pid << checkConfig;
itsConnections.insert(pid);
if(checkConfig)
updateFontList();
if(isSystem)
emit status(pid, KIO::ERR_UNSUPPORTED_ACTION);
else
{
FamilyCont::ConstIterator fam;
StyleCont::ConstIterator st;
EFolder from=toSystem ? FOLDER_USER : FOLDER_SYS,
to=toSystem ? FOLDER_SYS : FOLDER_USER;
if(findFont(family, style, from, fam, st))
{
FileCont::ConstIterator it((*st).files().begin()),
end((*st).files().end());
QStringList files;
for(; it!=end; ++it)
{
files.append((*it).path());
theFolders[from].addModifiedDir(Misc::getDir((*it).path()));
// Actual 'to' folder does not really matter, as we only want to call fc-cache
// ...actual folders only matter for xreating fonts.dir, etc, and we wont be doing this...
theFolders[to].addModifiedDir(theFolders[to].location());
}
QVariantMap args;
args["method"] = "move";
args["files"] = files;
args["toSystem"] = toSystem;
args["dest"] = theFolders[to].location();
args["uid"] = getuid();
args["gid"] = getgid();
int result=performAction(args);
if(STATUS_OK==result)
updateFontList();
emit status(pid, result);
}
else
{
KFI_DBUG << "does not exist";
emit status(pid, KIO::ERR_DOES_NOT_EXIST);
}
}
itsConnectionsTimer->start(constConnectionsTimeout);
itsFontListTimer->start(constFontListTimeout);
}
static bool renameFontFile(const QString &from, const QString &to, int uid=-1, int gid=-1)
{
QByteArray src(QFile::encodeName(from)),
dest(QFile::encodeName(to));
if(KDE_rename(src.data(), dest.data()))
return false;
Misc::setFilePerms(dest);
if(-1!=uid && -1!=gid)
::chown(dest.data(), uid, gid);
return true;
}
void FontInst::enable(const QString &family, quint32 style, bool inSystem, int pid, bool checkConfig)
{
KFI_DBUG << family << style << inSystem << pid << checkConfig;
toggle(true, family, style, inSystem, pid, checkConfig);
}
void FontInst::disable(const QString &family, quint32 style, bool inSystem, int pid, bool checkConfig)
{
KFI_DBUG << family << style << inSystem << pid << checkConfig;
toggle(false, family, style, inSystem, pid, checkConfig);
}
void FontInst::removeFile(const QString &family, quint32 style, const QString &file, bool fromSystem, int pid,
bool checkConfig)
{
KFI_DBUG << family << style << file << fromSystem << pid << checkConfig;
itsConnections.insert(pid);
if(checkConfig)
updateFontList();
// First find the family/style
EFolder folder=isSystem || fromSystem ? FOLDER_SYS : FOLDER_USER;
FamilyCont::ConstIterator fam;
StyleCont::ConstIterator st;
int result=findFont(family, style, folder, fam, st) ? (int)STATUS_OK : (int)KIO::ERR_DOES_NOT_EXIST;
if(STATUS_OK==result)
{
// Family/style found - now check that the requested file is *within* the same folder as one
// of the files linked to this font...
FileCont files((*st).files());
FileCont::ConstIterator it(files.begin()),
end(files.end());
QString dir(Misc::getDir(file));
result=KIO::ERR_DOES_NOT_EXIST;
for(; it!=end && STATUS_OK!=result; ++it)
if(Misc::getDir((*it).path())==dir)
result=STATUS_OK;
if(STATUS_OK==result)
{
// OK, found folder - so can now proceed to delete the file...
if(fromSystem && !isSystem)
{
QVariantMap args;
args["method"] = "removeFile";
args["file"] = file;
result=performAction(args);
}
else
{
result=Misc::fExists(file)
? QFile::remove(file)
? (int)STATUS_OK
: (int)KIO::ERR_WRITE_ACCESS_DENIED
: (int)KIO::ERR_DOES_NOT_EXIST;
}
if(STATUS_OK==result)
theFolders[folder].addModifiedDir(dir);
}
}
emit status(pid, result);
}
void FontInst::reconfigure(int pid, bool force)
{
KFI_DBUG << pid << force;
bool sysModified(theFolders[FOLDER_SYS].isModified());
saveDisabled();
KFI_DBUG << theFolders[FOLDER_USER].isModified() << sysModified;
if(!isSystem && (force || theFolders[FOLDER_USER].isModified()))
theFolders[FOLDER_USER].configure(force);
if(sysModified)
{
if(isSystem)
{
theFolders[FOLDER_SYS].configure();
}
else
{
QVariantMap args;
args["method"] = "reconfigure";
performAction(args);
theFolders[FOLDER_SYS].clearModified();
}
}
itsConnectionsTimer->start(constConnectionsTimeout);
itsFontListTimer->start(constFontListTimeout);
updateFontList();
emit status(pid, isSystem ? constSystemReconfigured : STATUS_OK);
}
QString FontInst::folderName(bool sys)
{
return theFolders[sys || isSystem ? FOLDER_SYS : FOLDER_USER].location();
}
void FontInst::saveDisabled()
{
if(isSystem)
theFolders[FOLDER_SYS].saveDisabled();
else
for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i)
if(FOLDER_SYS==i && !isSystem)
{
if(theFolders[i].disabledDirty())
{
QVariantMap args;
args["method"] = "saveDisabled";
performAction(args);
theFolders[i].saveDisabled();
}
}
else
theFolders[i].saveDisabled();
}
void FontInst::connectionsTimeout()
{
bool canExit(true);
KFI_DBUG << "exiting";
checkConnections();
for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i)
{
if(theFolders[i].disabledDirty())
canExit=false;
theFolders[i].saveDisabled();
}
if(0==itsConnections.count())
{
if(canExit)
qApp->exit(0);
else // Try again later...
itsConnectionsTimer->start(constConnectionsTimeout);
}
}
void FontInst::fontListTimeout()
{
updateFontList(true);
itsFontListTimer->start(constFontListTimeout);
}
void FontInst::updateFontList(bool emitChanges)
{
// For some reason just the "!FcConfigUptoDate(0)" check does not always work :-(
FcBool fcModified=!FcConfigUptoDate(0);
if(fcModified ||
theFolders[FOLDER_SYS].fonts().isEmpty() ||
(!isSystem && theFolders[FOLDER_USER].fonts().isEmpty()) ||
theFolders[FOLDER_SYS].disabledDirty() ||
(!isSystem && theFolders[FOLDER_USER].disabledDirty()))
{
KFI_DBUG << "Need to refresh font lists";
if(fcModified)
{
KFI_DBUG << "Re-init FC";
if(!FcInitReinitialize())
KFI_DBUG << "Re-init failed????";
}
Folder::Flat old[FOLDER_COUNT];
if(emitChanges)
{
KFI_DBUG << "Flatten existing font lists";
for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i)
old[i]=theFolders[i].flatten();
}
saveDisabled();
for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i)
theFolders[i].clearFonts();
KFI_DBUG << "update list of fonts";
FcPattern *pat = FcPatternCreate();
FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_FAMILY, FC_FAMILYLANG,
FC_WEIGHT, FC_LANG, FC_CHARSET, FC_SCALABLE,
#ifndef KFI_FC_NO_WIDTHS
FC_WIDTH,
#endif
FC_SLANT, FC_INDEX, FC_FOUNDRY, (void*)0);
FcFontSet *list=FcFontList(0, pat, os);
FcPatternDestroy(pat);
FcObjectSetDestroy(os);
theFolders[FOLDER_SYS].loadDisabled();
if(!isSystem)
theFolders[FOLDER_USER].loadDisabled();
if(list)
{
QString home(Misc::dirSyntax(QDir::homePath()));
for (int i = 0; i < list->nfont; i++)
{
QString fileName(Misc::fileSyntax(FC::getFcString(list->fonts[i], FC_FILE)));
if(!fileName.isEmpty() && Misc::fExists(fileName)) // && 0!=fileName.indexOf(constDefomaLocation))
{
QString family,
foundry;
quint32 styleVal;
int index;
qulonglong writingSystems(WritingSystems::instance()->get(list->fonts[i]));
FcBool scalable=FcFalse;
if(FcResultMatch!=FcPatternGetBool(list->fonts[i], FC_SCALABLE, 0, &scalable))
scalable=FcFalse;
FC::getDetails(list->fonts[i], family, styleVal, index, foundry);
FamilyCont::ConstIterator fam=theFolders[isSystem || 0!=fileName.indexOf(home)
? FOLDER_SYS : FOLDER_USER].addFont(Family(family));
StyleCont::ConstIterator style=(*fam).add(Style(styleVal));
FileCont::ConstIterator file=(*style).add(File(fileName, foundry, index));
(*style).setWritingSystems((*style).writingSystems()|writingSystems);
if(scalable)
(*style).setScalable();
}
}
FcFontSetDestroy(list);
}
if(emitChanges)
{
KFI_DBUG << "Look for differences";
for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i)
{
KFI_DBUG << "Flatten, and take copies...";
Folder::Flat newList=theFolders[i].flatten(),
onlyNew=newList;
KFI_DBUG << "Determine differences...";
onlyNew.subtract(old[i]);
old[i].subtract(newList);
KFI_DBUG << "Emit changes...";
Families families=onlyNew.build(isSystem || i==FOLDER_SYS);
if(!families.items.isEmpty())
emit fontsAdded(families);
families=old[i].build(isSystem || i==FOLDER_SYS);
if(!families.items.isEmpty())
emit fontsRemoved(families);
}
}
KFI_DBUG << "updated list of fonts";
}
}
void FontInst::toggle(bool enable, const QString &family, quint32 style, bool inSystem, int pid, bool checkConfig)
{
KFI_DBUG;
itsConnections.insert(pid);
if(checkConfig)
updateFontList();
EFolder folder=isSystem || inSystem ? FOLDER_SYS : FOLDER_USER;
FamilyCont::ConstIterator fam;
StyleCont::ConstIterator st;
int result=findFont(family, style, folder, fam, st) ? (int)STATUS_OK : (int)KIO::ERR_DOES_NOT_EXIST;
if(STATUS_OK==result)
{
FileCont files((*st).files()),
toggledFiles;
FileCont::ConstIterator it(files.begin()),
end(files.end());
QHash<File, QString> movedFonts;
QHash<QString, QString> movedAssoc;
QSet<QString> modifiedDirs;
for(; it!=end && STATUS_OK==result; ++it)
{
QString to=Misc::getDir((*it).path())+
QString(enable ? Misc::unhide(Misc::getFile((*it).path()))
: Misc::hide(Misc::getFile((*it).path())));
if(to!=(*it).path())
{
KFI_DBUG << "MOVE:" << (*it).path() << " to " << to;
// If the font is a system font, and we're not root, then just go through the actions here - so
// that we can build the list of changes that would happen...
if((inSystem && !isSystem) || renameFontFile((*it).path(), to))
{
modifiedDirs.insert(Misc::getDir(enable ? to : (*it).path()));
toggledFiles.insert(File(to, (*it).foundry(), (*it).index()));
// Now try to move an associated AFM or PFM files...
QStringList assoc;
movedFonts[*it]=to;
Misc::getAssociatedFiles((*it).path(), assoc);
QStringList::ConstIterator ait(assoc.constBegin()),
aend(assoc.constEnd());
for(; ait!=aend && STATUS_OK==result; ++ait)
{
to=Misc::getDir(*ait)+
QString(enable ? Misc::unhide(Misc::getFile(*ait))
: Misc::hide(Misc::getFile(*ait)));
if(to!=*ait)
{
if((inSystem && !isSystem) || renameFontFile(*ait, to))
{
movedAssoc[*ait]=to;
}
else
{
result=KIO::ERR_WRITE_ACCESS_DENIED;
}
}
}
}
else
{
result=KIO::ERR_WRITE_ACCESS_DENIED;
}
}
}
if(inSystem && !isSystem)
{
Family toggleFam((*fam).name());
toggleFam.add(*st);
QVariantMap args;
args["method"] = "toggle";
QString xml;
QTextStream str(&xml);
toggleFam.toXml(false, str);
args["xml"] = xml;
args["enable"] = enable;
result=performAction(args);
}
if(STATUS_OK==result)
{
Family addFam((*fam).name()),
delFam((*fam).name());
Style addStyle((*st).value(), (*st).scalable(), (*st).writingSystems()),
delStyle((*st).value(), (*st).scalable(), (*st).writingSystems());
addStyle.setFiles(toggledFiles);
addFam.add(addStyle);
delStyle.setFiles(files);
delFam.add(delStyle);
(*st).setFiles(toggledFiles);
theFolders[folder].addModifiedDirs(modifiedDirs);
emit fontsAdded(Families(addFam, FOLDER_SYS==folder));
emit fontsRemoved(Families(delFam, FOLDER_SYS==folder));
theFolders[folder].setDisabledDirty();
}
else // un-move fonts!
{
QHash<File, QString>::ConstIterator fit(movedFonts.constBegin()),
fend(movedFonts.constEnd());
QHash<QString, QString>::ConstIterator ait(movedAssoc.constBegin()),
aend(movedAssoc.constEnd());
for(; fit!=fend; ++fit)
renameFontFile(fit.value(), fit.key().path());
for(; ait!=aend; ++ait)
renameFontFile(ait.value(), ait.key());
}
}
emit status(pid, result);
itsConnectionsTimer->start(constConnectionsTimeout);
itsFontListTimer->start(constFontListTimeout);
}
void FontInst::addModifedSysFolders(const Family &family)
{
StyleCont::ConstIterator style(family.styles().begin()),
styleEnd(family.styles().end());
for(; style!=styleEnd; ++style)
{
FileCont::ConstIterator file((*style).files().begin()),
fileEnd((*style).files().end());
for(; file!=fileEnd; ++file)
theFolders[FOLDER_SYS].addModifiedDir(Misc::getDir((*file).path()));
}
}
void FontInst::checkConnections()
{
KFI_DBUG;
QSet<int>::ConstIterator it(itsConnections.begin()),
end(itsConnections.end());
QSet<int> remove;
for(; it!=end; ++it)
if(0!=kill(*it, 0))
remove.insert(*it);
itsConnections.subtract(remove);
}
bool FontInst::findFontReal(const QString &family, const QString &style, EFolder folder,
FamilyCont::ConstIterator &fam, StyleCont::ConstIterator &st)
{
KFI_DBUG;
Family f(family);
fam=theFolders[folder].fonts().find(f);
if(theFolders[folder].fonts().end()==fam)
return false;
StyleCont::ConstIterator end((*fam).styles().end());
for(st=(*fam).styles().begin(); st!=end; ++st)
if(FC::createStyleName((*st).value())==style)
return true;
return false;
}
bool FontInst::findFont(const QString &font, EFolder folder,
FamilyCont::ConstIterator &fam, StyleCont::ConstIterator &st,
bool updateList)
{
KFI_DBUG;
QString family,
style;
decompose(font, family, style);
if(!findFontReal(family, style, folder, fam, st))
{
if(updateList)
{
// Not found, so refresh font list and try again...
updateFontList();
return findFontReal(family, style, folder, fam, st);
}
else
{
return false;
}
}
return true;
}
bool FontInst::findFontReal(const QString &family, quint32 style, EFolder folder,
FamilyCont::ConstIterator &fam, StyleCont::ConstIterator &st)
{
KFI_DBUG;
fam=theFolders[folder].fonts().find(Family(family));
if(theFolders[folder].fonts().end()==fam)
return false;
else
{
st=(*fam).styles().find(style);
return (*fam).styles().end()!=st;
}
}
bool FontInst::findFont(const QString &family, quint32 style, EFolder folder,
FamilyCont::ConstIterator &fam, StyleCont::ConstIterator &st,
bool updateList)
{
KFI_DBUG;
if(!findFontReal(family, style, folder, fam, st))
{
if(updateList)
{
// Not found, so refresh font list and try again...
updateFontList();
return findFontReal(family, style, folder, fam, st);
}
else
{
return false;
}
}
return true;
}
int FontInst::performAction(const QVariantMap &args)
{
KAuth::Action action("org.kde.fontinst.manage");
action.setHelperID("org.kde.fontinst");
action.setArguments(args);
KFI_DBUG << "Call " << args["method"].toString() << " on helper";
itsFontListTimer->stop();
itsConnectionsTimer->stop();
KAuth::ActionReply reply = action.execute();
switch(reply.type())
{
case KAuth::ActionReply::KAuthError:
KFI_DBUG << "KAuth failed - error code:" << reply.errorCode();
return KIO::ERR_COULD_NOT_AUTHENTICATE;
case KAuth::ActionReply::HelperError:
KFI_DBUG << "Helper failed - error code:" << reply.errorCode();
return (int)reply.errorCode();
}
KFI_DBUG << "Success!";
return STATUS_OK;
}
}