mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-24 19:02:51 +00:00
417 lines
12 KiB
C++
417 lines
12 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 <QtCore/QDir>
|
|
#include <QtCore/QFile>
|
|
#include <QtCore/QCoreApplication>
|
|
#include <QtCore/QTextStream>
|
|
#include <QtCore/QProcess>
|
|
#include <QtXml/QDomDocument>
|
|
#include <QtXml/QDomElement>
|
|
#include <QtXml/QDomNode>
|
|
#include <KDE/KStandardDirs>
|
|
#include <KDE/KSaveFile>
|
|
#include <KDE/KShell>
|
|
#include <KDE/KDebug>
|
|
#include <fontconfig/fontconfig.h>
|
|
#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<File> 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<File>::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 << "</"DISABLED_FONTS">" << 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 << "</"FONTLIST_TAG">" << endl;
|
|
rv.append(string);
|
|
string=QString();
|
|
}
|
|
str << "<"FONTLIST_TAG" " << SYSTEM_ATTR"=\"" << (itsIsSystem ? "true" : "false") << "\">" << endl;
|
|
}
|
|
|
|
(*it).toXml(false, str);
|
|
}
|
|
|
|
if(!string.isEmpty())
|
|
{
|
|
str << "</"FONTLIST_TAG">" << 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<QString>::ConstIterator it(itsModifiedDirs.constBegin()),
|
|
end(itsModifiedDirs.constEnd());
|
|
QSet<QString> 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;
|
|
}
|
|
|
|
}
|