/* * 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 #include #include #include "Folder.h" #include "FcConfig.h" #include "Misc.h" #include "KfiConstants.h" #include "XmlStrings.h" #include "Style.h" #include "File.h" #include "config-fontinst.h" #define DISABLED_FONTS "disabledfonts" #define KFI_DBUG kDebug() << time(0L) namespace KFI { bool Folder::CfgFile::modified() { return timestamp!=Misc::getTimeStamp(name); } void Folder::CfgFile::updateTimeStamp() { timestamp=Misc::getTimeStamp(name); } Folder::~Folder() { saveDisabled(); } void Folder::init(bool system, bool systemBus) { itsIsSystem=system; if(!system) { FcStrList *list=FcConfigGetFontDirs(FcInitLoadConfigAndFonts()); QStringList dirs; FcChar8 *fcDir; while((fcDir=FcStrListNext(list))) dirs.append(Misc::dirSyntax((const char *)fcDir)); itsLocation=Misc::getFolder(Misc::dirSyntax(QDir::homePath()+"/.fonts/"), Misc::dirSyntax(QDir::homePath()), dirs); } else itsLocation=KFI_DEFAULT_SYS_FONTS_FOLDER; if((!system && !systemBus) || (system && systemBus)) FcConfig::addDir(itsLocation, system); itsDisabledCfg.dirty=false; if(itsDisabledCfg.name.isEmpty()) { QString fileName("/"DISABLED_FONTS".xml"); if(system) itsDisabledCfg.name=QString::fromLatin1(KFI_ROOT_CFG_DIR)+fileName; else { QString path=KGlobal::dirs()->localxdgconfdir(); if(!Misc::dExists(path)) Misc::createDir(path); itsDisabledCfg.name=path+fileName; } itsDisabledCfg.timestamp=0; } } bool Folder::allowToggling() const { return Misc::fExists(itsDisabledCfg.name) ? Misc::fWritable(itsDisabledCfg.name) : Misc::dWritable(Misc::getDir(itsDisabledCfg.name)); } void Folder::loadDisabled() { if(itsDisabledCfg.dirty) saveDisabled(); QFile f(itsDisabledCfg.name); KFI_DBUG << itsDisabledCfg.name; itsDisabledCfg.dirty=false; if(f.open(QIODevice::ReadOnly)) { QDomDocument doc; if(doc.setContent(&f)) for(QDomNode n=doc.documentElement().firstChild(); !n.isNull(); n=n.nextSibling()) { QDomElement e=n.toElement(); if(FONT_TAG==e.tagName()) { Family fam(e, false); if(!fam.name().isEmpty()) { Style style(e, false); if(KFI_NO_STYLE_INFO!=style.value()) { QList files; if(e.hasAttribute(PATH_ATTR)) { File file(e, true); if(!file.path().isEmpty()) files.append(file); else itsDisabledCfg.dirty=true; } else { for(QDomNode n=e.firstChild(); !n.isNull(); n=n.nextSibling()) { QDomElement ent=n.toElement(); if(FILE_TAG==ent.tagName()) { File file(ent, true); if(!file.path().isEmpty()) files.append(file); else { KFI_DBUG << "Set dirty from load"; itsDisabledCfg.dirty=true; } } } } if(files.count()>0) { QList::ConstIterator it(files.begin()), end(files.end()); FamilyCont::ConstIterator f(itsFonts.insert(fam)); StyleCont::ConstIterator s((*f).add(style)); for(; it!=end; ++it) (*s).add(*it); } } } } } f.close(); itsDisabledCfg.updateTimeStamp(); } saveDisabled(); } void Folder::saveDisabled() { if(itsDisabledCfg.dirty) { if(!itsIsSystem || Misc::root()) { KFI_DBUG << itsDisabledCfg.name; KSaveFile file; file.setFileName(itsDisabledCfg.name); if(!file.open()) { KFI_DBUG << "Exit - cant open save file"; qApp->exit(0); } QTextStream str(&file); str << "<"DISABLED_FONTS">" << endl; FamilyCont::ConstIterator it(itsFonts.begin()), end(itsFonts.end()); for(; it!=end; ++it) (*it).toXml(true, str); str << "" << endl; str.flush(); if(!file.finalize()) { KFI_DBUG << "Exit - cant finalize save file"; qApp->exit(0); } } itsDisabledCfg.updateTimeStamp(); itsDisabledCfg.dirty=false; } } QStringList Folder::toXml(int max) { QStringList rv; FamilyCont::ConstIterator it(itsFonts.begin()), end(itsFonts.end()); QString string; QTextStream str(&string); for(int i=0; it!=end; ++it, ++i) { if(0==(i%max)) { if(i) { str << "" << endl; rv.append(string); string=QString(); } str << "<"FONTLIST_TAG" " << SYSTEM_ATTR"=\"" << (itsIsSystem ? "true" : "false") << "\">" << endl; } (*it).toXml(false, str); } if(!string.isEmpty()) { str << "" << endl; rv.append(string); } return rv; } Families Folder::list() { Families fam(itsIsSystem); FamilyCont::ConstIterator it(itsFonts.begin()), end(itsFonts.end()); for(int i=0; it!=end; ++it, ++i) fam.items.insert(*it); return fam; } bool Folder::contains(const QString &family, quint32 style) { FamilyCont::ConstIterator fam=itsFonts.find(Family(family)); if(fam==itsFonts.end()) return false; StyleCont::ConstIterator st=(*fam).styles().find(Style(style)); return st!=(*fam).styles().end(); } void Folder::add(const Family &family) { FamilyCont::ConstIterator existingFamily=itsFonts.find(family); if(existingFamily==itsFonts.end()) itsFonts.insert(family); else { StyleCont::ConstIterator it(family.styles().begin()), end(family.styles().end()); for(; it!=end; ++it) { StyleCont::ConstIterator existingStyle=(*existingFamily).styles().find(*it); if(existingStyle==(*existingFamily).styles().end()) (*existingFamily).add(*it); else { FileCont::ConstIterator fit((*it).files().begin()), fend((*it).files().end()); for(; fit!=fend; ++fit) { FileCont::ConstIterator f=(*existingStyle).files().find(*fit); if(f==(*existingStyle).files().end()) (*existingStyle).add(*fit); } (*existingStyle).setWritingSystems((*existingStyle).writingSystems()|(*it).writingSystems()); if(!(*existingStyle).scalable() && (*it).scalable()) (*existingStyle).setScalable(true); } } } } void Folder::configure(bool force) { KFI_DBUG << "EMPTY MODIFIED " << itsModifiedDirs.isEmpty(); if(force || !itsModifiedDirs.isEmpty()) { saveDisabled(); QSet::ConstIterator it(itsModifiedDirs.constBegin()), end(itsModifiedDirs.constEnd()); QSet dirs; for(; it!=end; ++it) if(Misc::fExists((*it)+"fonts.dir")) dirs.insert(KShell::quoteArg(*it)); if(!dirs.isEmpty()) QProcess::startDetached(QLatin1String(KFONTINST_LIB_EXEC_DIR"/fontinst_x11"), dirs.toList()); itsModifiedDirs.clear(); KFI_DBUG << "RUN FC"; Misc::doCmd("fc-cache"); KFI_DBUG << "DONE"; } } Folder::Flat Folder::flatten() const { FamilyCont::ConstIterator fam=itsFonts.begin(), famEnd=itsFonts.end(); Flat rv; for(; fam!=famEnd; ++fam) { StyleCont::ConstIterator style((*fam).styles().begin()), styleEnd((*fam).styles().end()); for(; style!=styleEnd; ++style) { FileCont::ConstIterator file((*style).files().begin()), fileEnd((*style).files().end()); for(; file!=fileEnd; ++file) rv.insert(FlatFont(*fam, *style, *file)); } } return rv; } Families Folder::Flat::build(bool system) const { ConstIterator it(begin()), e(end()); Families families(system); for(; it!=e; ++it) { Family f((*it).family); Style s((*it).styleInfo, (*it).scalable, (*it).writingSystems); FamilyCont::ConstIterator fam=families.items.constFind(f); if(families.items.constEnd()==fam) { s.add((*it).file); f.add(s); families.items.insert(f); } else { StyleCont::ConstIterator st=(*fam).styles().constFind(s); if((*fam).styles().constEnd()==st) { s.add((*it).file); (*fam).add(s); } else (*st).add((*it).file); } } return families; } }