/* * KFontInst - KDE Font Installer * * Copyright 2003-2009 Craig Drummond * * ---- * * 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 #include #include #include #include #include #include #include #include #include #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 fonts; for(int i=0; i<(isSystem ? 1 : FOLDER_COUNT); ++i) if(0==folders || folders&(1<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 movedFonts; QHash movedAssoc; QSet 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::ConstIterator fit(movedFonts.constBegin()), fend(movedFonts.constEnd()); QHash::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::ConstIterator it(itsConnections.begin()), end(itsConnections.end()); QSet 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; } }