diff --git a/kcms/kfontinst/kcmfontinst/FontFilter.cpp b/kcms/kfontinst/kcmfontinst/FontFilter.cpp
index 82865ba07..7be1ed526 100644
--- a/kcms/kfontinst/kcmfontinst/FontFilter.cpp
+++ b/kcms/kfontinst/kcmfontinst/FontFilter.cpp
@@ -1,395 +1,395 @@
/*
* KFontInst - KDE Font Installer
*
* Copyright 2003-2007 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 "FontFilter.h"
#include "FontFilterProxyStyle.h"
#include "FontList.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace KFI
{
static const int constArrowPad(5);
static void deselectCurrent(QActionGroup *act)
{
QAction *prev(act->checkedAction());
if(prev)
prev->setChecked(false);
}
static void deselectCurrent(KSelectAction *act)
{
deselectCurrent(act->selectableActionGroup());
}
// FIXME: Go back to using StyleSheets instead of a proxy style
// once Qt has been fixed not to mess with widget font when
// using StyleSheets
class CFontFilterStyle : public CFontFilterProxyStyle
{
public:
CFontFilterStyle(CFontFilter *parent, int ol) : CFontFilterProxyStyle(parent), overlap(ol) {}
QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const override;
int overlap;
};
QRect CFontFilterStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
{
if (SE_LineEditContents==element)
{
QRect rect(style()->subElementRect(SE_LineEditContents, option, widget));
return rect.adjusted(overlap, 0, -overlap, 0);
}
return CFontFilterProxyStyle::subElementRect(element, option, widget);
}
struct SortAction
{
SortAction(QAction *a) : action(a) { }
bool operator<(const SortAction &o) const { return action->text().localeAwareCompare(o.action->text())<0; }
QAction *action;
};
static void sortActions(KSelectAction *group)
{
if(group->actions().count()>1)
{
QList actions=group->actions();
QList::ConstIterator it(actions.constBegin()),
end(actions.constEnd());
QList sorted;
for(; it!=end; ++it)
{
sorted.append(SortAction(*it));
group->removeAction(*it);
}
qSort(sorted);
QList::ConstIterator s(sorted.constBegin()),
sEnd(sorted.constEnd());
for(; s!=sEnd; ++s)
group->addAction((*s).action);
}
}
CFontFilter::CFontFilter(QWidget *parent)
: KLineEdit(parent)
{
setClearButtonShown(true);
setTrapReturnKey(true);
itsMenuButton = new QLabel(this);
itsMenuButton->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
itsMenuButton->setCursor(Qt::ArrowCursor);
itsMenuButton->setToolTip(i18n("Set Criteria"));
itsMenu=new QMenu(this);
itsPixmaps[CRIT_FAMILY]=SmallIcon("draw-text");
itsPixmaps[CRIT_STYLE]=SmallIcon("format-text-bold");
itsPixmaps[CRIT_FOUNDRY]=SmallIcon("user-identity");
itsPixmaps[CRIT_FONTCONFIG]=SmallIcon("system-search");
itsPixmaps[CRIT_FILETYPE]=SmallIcon("preferences-desktop-font-installer");
itsPixmaps[CRIT_FILENAME]=SmallIcon("application-x-font-type1");
itsPixmaps[CRIT_LOCATION]=SmallIcon("folder");
itsPixmaps[CRIT_WS]=SmallIcon("character-set");
itsActionGroup=new QActionGroup(this);
addAction(CRIT_FAMILY, i18n("Family"), true);
addAction(CRIT_STYLE, i18n("Style"), false);
KSelectAction *foundryMenu=new KSelectAction(QIcon(itsPixmaps[CRIT_FOUNDRY]), i18n("Foundry"), this);
itsActions[CRIT_FOUNDRY]=foundryMenu;
itsMenu->addAction(itsActions[CRIT_FOUNDRY]);
foundryMenu->setData((int)CRIT_FOUNDRY);
foundryMenu->setVisible(false);
connect(foundryMenu, SIGNAL(triggered(QString)), SLOT(foundryChanged(QString)));
addAction(CRIT_FONTCONFIG, i18n("FontConfig Match"), false);
KSelectAction *ftMenu=new KSelectAction(QIcon(itsPixmaps[CRIT_FILETYPE]), i18n("File Type"), this);
itsActions[CRIT_FILETYPE]=ftMenu;
itsMenu->addAction(itsActions[CRIT_FILETYPE]);
ftMenu->setData((int)CRIT_FILETYPE);
QStringList::ConstIterator it(CFontList::fontMimeTypes.constBegin()),
end(CFontList::fontMimeTypes.constEnd());
QMimeDatabase db;
for(; it!=end; ++it)
if((*it)!="application/vnd.kde.fontspackage")
{
QMimeType mime = db.mimeTypeForName(*it);
KToggleAction *act=new KToggleAction(QIcon::fromTheme(mime.iconName()), mime.comment(), this);
ftMenu->addAction(act);
act->setChecked(false);
QStringList mimes;
foreach (QString pattern, mime.globPatterns())
mimes.append(pattern.remove(QStringLiteral("*.")));
act->setData(mimes);
}
sortActions(ftMenu);
connect(ftMenu, SIGNAL(triggered(QString)), SLOT(ftChanged(QString)));
itsCurrentFileTypes.clear();
addAction(CRIT_FILENAME, i18n("File Name"), false);
addAction(CRIT_LOCATION, i18n("File Location"), false);
KSelectAction *wsMenu=new KSelectAction(QIcon(itsPixmaps[CRIT_WS]), i18n("Writing System"), this);
itsActions[CRIT_WS]=wsMenu;
itsMenu->addAction(itsActions[CRIT_WS]);
wsMenu->setData((int)CRIT_WS);
itsCurrentWs=QFontDatabase::Any;
for(int i=QFontDatabase::Latin; iaddAction(wsAct);
wsAct->setChecked(false);
wsAct->setData(i);
}
sortActions(wsMenu);
connect(wsMenu, SIGNAL(triggered(QString)), SLOT(wsChanged(QString)));
setCriteria(CRIT_FAMILY);
setStyle(new CFontFilterStyle(this, itsMenuButton->width()));
}
void CFontFilter::setFoundries(const QSet ¤tFoundries)
{
QAction *act(((KSelectAction *)itsActions[CRIT_FOUNDRY])->currentAction());
QString prev(act && act->isChecked() ? act->text() : QString());
bool changed(false);
QList prevFoundries(((KSelectAction *)itsActions[CRIT_FOUNDRY])->actions());
QList::ConstIterator fIt(prevFoundries.constBegin()),
fEnd(prevFoundries.constEnd());
QSet foundries(currentFoundries);
// Determine which of 'foundries' are new ones, and which old ones need to be removed...
for(; fIt!=fEnd; ++fIt)
{
if(foundries.contains((*fIt)->text()))
foundries.remove((*fIt)->text());
else
{
((KSelectAction *)itsActions[CRIT_FOUNDRY])->removeAction(*fIt);
(*fIt)->deleteLater();
changed=true;
}
}
if(!foundries.isEmpty())
{
// Add foundries to menu - replacing '&' with '&&', as '&' is taken to be
// a shortcut!
QSet::ConstIterator it(foundries.begin()),
end(foundries.end());
for(; it!=end; ++it)
{
QString foundry(*it);
foundry.replace("&", "&&");
((KSelectAction *)itsActions[CRIT_FOUNDRY])->addAction(foundry);
}
changed=true;
}
if(changed)
{
sortActions((KSelectAction *)itsActions[CRIT_FOUNDRY]);
if(!prev.isEmpty())
{
act=((KSelectAction *)itsActions[CRIT_FOUNDRY])->action(prev);
if(act)
((KSelectAction *)itsActions[CRIT_FOUNDRY])->setCurrentAction(act);
else
((KSelectAction *)itsActions[CRIT_FOUNDRY])->setCurrentItem(0);
}
itsActions[CRIT_FOUNDRY]->setVisible(((KSelectAction *)itsActions[CRIT_FOUNDRY])->actions().count());
}
}
QSize CFontFilter::sizeHint() const
{
return QSize(fontMetrics().width(placeholderText())+56, KLineEdit::sizeHint().height());
}
void CFontFilter::filterChanged()
{
QAction *act(itsActionGroup->checkedAction());
if(act)
{
ECriteria crit((ECriteria)act->data().toInt());
if(itsCurrentCriteria!=crit)
{
deselectCurrent((KSelectAction *)itsActions[CRIT_FOUNDRY]);
deselectCurrent((KSelectAction *)itsActions[CRIT_FILETYPE]);
deselectCurrent((KSelectAction *)itsActions[CRIT_WS]);
setText(QString());
itsCurrentWs=QFontDatabase::Any;
itsCurrentFileTypes.clear();
setCriteria(crit);
setPlaceholderText(i18n("Filter by %1...", act->text()));
setReadOnly(false);
}
}
}
void CFontFilter::ftChanged(const QString &ft)
{
deselectCurrent((KSelectAction *)itsActions[CRIT_FOUNDRY]);
deselectCurrent((KSelectAction *)itsActions[CRIT_WS]);
deselectCurrent(itsActionGroup);
QAction *act(((KSelectAction *)itsActions[CRIT_FILETYPE])->currentAction());
if(act)
itsCurrentFileTypes=act->data().toStringList();
itsCurrentCriteria=CRIT_FILETYPE;
setReadOnly(true);
setCriteria(itsCurrentCriteria);
setText(ft);
setPlaceholderText(text());
}
void CFontFilter::wsChanged(const QString &writingSystemName)
{
deselectCurrent((KSelectAction *)itsActions[CRIT_FOUNDRY]);
deselectCurrent((KSelectAction *)itsActions[CRIT_FILETYPE]);
deselectCurrent(itsActionGroup);
QAction *act(((KSelectAction *)itsActions[CRIT_WS])->currentAction());
if(act)
itsCurrentWs=(QFontDatabase::WritingSystem)act->data().toInt();
itsCurrentCriteria=CRIT_WS;
setReadOnly(true);
setCriteria(itsCurrentCriteria);
setText(writingSystemName);
setPlaceholderText(text());
}
void CFontFilter::foundryChanged(const QString &foundry)
{
deselectCurrent((KSelectAction *)itsActions[CRIT_WS]);
deselectCurrent((KSelectAction *)itsActions[CRIT_FILETYPE]);
deselectCurrent(itsActionGroup);
itsCurrentCriteria=CRIT_FOUNDRY;
setReadOnly(true);
setText(foundry);
setPlaceholderText(text());
setCriteria(itsCurrentCriteria);
}
void CFontFilter::addAction(ECriteria crit, const QString &text, bool on)
{
itsActions[crit]=new KToggleAction(QIcon(itsPixmaps[crit]),
text, this);
itsMenu->addAction(itsActions[crit]);
itsActionGroup->addAction(itsActions[crit]);
itsActions[crit]->setData((int)crit);
itsActions[crit]->setChecked(on);
if(on)
- setPlaceholderText(i18n("Filter by %1", text));
+ setPlaceholderText(i18n("Filter by %1...", text));
connect(itsActions[crit], SIGNAL(toggled(bool)), SLOT(filterChanged()));
}
void CFontFilter::resizeEvent(QResizeEvent *ev)
{
KLineEdit::resizeEvent(ev);
int frameWidth(style()->pixelMetric(QStyle::PM_DefaultFrameWidth)),
y((height()-itsMenuButton->height())/2);
if (qApp->isLeftToRight())
itsMenuButton->move(frameWidth + 2, y);
else
itsMenuButton->move(size().width() - frameWidth - itsMenuButton->width() - 2, y);
}
void CFontFilter::mousePressEvent(QMouseEvent *ev)
{
if(Qt::LeftButton==ev->button() && itsMenuButton->underMouse())
itsMenu->popup(mapToGlobal(QPoint(0, height())), nullptr);
else
KLineEdit::mousePressEvent(ev);
}
void CFontFilter::setCriteria(ECriteria crit)
{
QPixmap arrowmap(itsPixmaps[crit].width()+constArrowPad, itsPixmaps[crit].height());
QColor bgnd(palette().color(QPalette::Active, QPalette::Base));
bgnd.setAlphaF(0.0);
arrowmap.fill(bgnd);
QPainter p(&arrowmap);
p.drawPixmap(0, 0, itsPixmaps[crit]);
QStyleOption opt;
opt.state = QStyle::State_Enabled;
opt.rect = QRect(arrowmap.width()-(constArrowPad+1), arrowmap.height()-(constArrowPad+1), constArrowPad, constArrowPad);
style()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &opt, &p, itsMenuButton);
p.end();
itsMenuButton->setPixmap(arrowmap);
itsMenuButton->resize(arrowmap.width(), arrowmap.height());
itsCurrentCriteria=crit;
emit criteriaChanged(crit, ((qulonglong)1) << (int)itsCurrentWs, itsCurrentFileTypes);
}
}
diff --git a/kcms/kfontinst/kcmfontinst/GroupList.cpp b/kcms/kfontinst/kcmfontinst/GroupList.cpp
index 82092d4b6..485352ba0 100644
--- a/kcms/kfontinst/kcmfontinst/GroupList.cpp
+++ b/kcms/kfontinst/kcmfontinst/GroupList.cpp
@@ -1,1026 +1,1026 @@
/*
* KFontInst - KDE Font Installer
*
* Copyright 2003-2007 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 "GroupList.h"
#include "FontList.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "FcEngine.h"
#include "Misc.h"
#include "KfiConstants.h"
namespace KFI
{
#define GROUPS_DOC "groups"
#define GROUP_TAG "group"
#define NAME_ATTR "name"
#define FAMILY_TAG "family"
enum EGroupColumns
{
COL_GROUP_NAME,
NUM_GROUP_COLS
};
CGroupListItem::CGroupListItem(const QString &name)
: itsName(name),
itsType(CUSTOM),
itsHighlighted(false),
itsStatus(CFamilyItem::ENABLED)
{
itsData.validated=false;
}
CGroupListItem::CGroupListItem(EType type, CGroupList *p)
: itsType(type),
itsHighlighted(false),
itsStatus(CFamilyItem::ENABLED)
{
switch(itsType)
{
case ALL:
itsName=i18n("All Fonts");
break;
case PERSONAL:
itsName=i18n("Personal Fonts");
break;
case SYSTEM:
itsName=i18n("System Fonts");
break;
default:
itsName=i18n("Unclassified");
}
itsData.parent=p;
}
bool CGroupListItem::hasFont(const CFontItem *fnt) const
{
switch(itsType)
{
case CUSTOM:
return itsFamilies.contains(fnt->family());
case PERSONAL:
return !fnt->isSystem();
case SYSTEM:
return fnt->isSystem();
case ALL:
return true;
case UNCLASSIFIED:
{
QList::ConstIterator it(itsData.parent->itsGroups.begin()),
end(itsData.parent->itsGroups.end());
for(; it!=end; ++it)
if((*it)->isCustom() && (*it)->families().contains(fnt->family()))
return false;
return true;
}
default:
return false;
}
return false;
}
void CGroupListItem::updateStatus(QSet &enabled, QSet &disabled, QSet &partial)
{
QSet families(itsFamilies);
if(0!=families.intersect(partial).count())
itsStatus=CFamilyItem::PARTIAL;
else
{
families=itsFamilies;
bool haveEnabled(0!=families.intersect(enabled).count());
families=itsFamilies;
bool haveDisabled(0!=families.intersect(disabled).count());
if(haveEnabled && haveDisabled)
itsStatus=CFamilyItem::PARTIAL;
else if(haveEnabled && !haveDisabled)
itsStatus=CFamilyItem::ENABLED;
else
itsStatus=CFamilyItem::DISABLED;
}
}
bool CGroupListItem::load(QDomElement &elem)
{
if(elem.hasAttribute(NAME_ATTR))
{
itsName=elem.attribute(NAME_ATTR);
addFamilies(elem);
return true;
}
return false;
}
bool CGroupListItem::addFamilies(QDomElement &elem)
{
int b4(itsFamilies.count());
for(QDomNode n=elem.firstChild(); !n.isNull(); n=n.nextSibling())
{
QDomElement ent=n.toElement();
if(FAMILY_TAG==ent.tagName())
itsFamilies.insert(ent.text());
}
return b4!=itsFamilies.count();
}
void CGroupListItem::save(QTextStream &str)
{
str << " <" GROUP_TAG " " NAME_ATTR "=\"" << Misc::encodeText(itsName, str) << "\">" << endl;
if(!itsFamilies.isEmpty())
{
QSet::ConstIterator it(itsFamilies.begin()),
end(itsFamilies.end());
for(; it!=end; ++it)
str << " <" FAMILY_TAG ">" << Misc::encodeText(*it, str) << "" FAMILY_TAG ">" << endl;
}
str << " " GROUP_TAG ">" << endl;
}
CGroupList::CGroupList(QWidget *parent)
: QAbstractItemModel(parent),
itsTimeStamp(0),
itsModified(false),
itsParent(parent),
itsSortOrder(Qt::AscendingOrder)
{
itsSpecialGroups[CGroupListItem::ALL]=new CGroupListItem(CGroupListItem::ALL, this);
itsGroups.append(itsSpecialGroups[CGroupListItem::ALL]);
if(Misc::root())
itsSpecialGroups[CGroupListItem::PERSONAL]=
itsSpecialGroups[CGroupListItem::SYSTEM]=NULL;
else
{
itsSpecialGroups[CGroupListItem::PERSONAL]=new CGroupListItem(CGroupListItem::PERSONAL, this);
itsGroups.append(itsSpecialGroups[CGroupListItem::PERSONAL]);
itsSpecialGroups[CGroupListItem::SYSTEM]=new CGroupListItem(CGroupListItem::SYSTEM, this);
itsGroups.append(itsSpecialGroups[CGroupListItem::SYSTEM]);
}
itsSpecialGroups[CGroupListItem::UNCLASSIFIED]=
new CGroupListItem(CGroupListItem::UNCLASSIFIED, this);
// Locate groups.xml file - normall will be ~/.config/fontgroups.xml
QString path(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + '/');
if(!Misc::dExists(path))
Misc::createDir(path);
itsFileName=path+'/'+KFI_GROUPS_FILE;
rescan();
}
CGroupList::~CGroupList()
{
save();
qDeleteAll(itsGroups);
itsGroups.clear();
}
int CGroupList::columnCount(const QModelIndex &) const
{
return NUM_GROUP_COLS;
}
void CGroupList::update(const QModelIndex &unHighlight, const QModelIndex &highlight)
{
if(unHighlight.isValid())
{
CGroupListItem *grp=static_cast(unHighlight.internalPointer());
if(grp)
grp->setHighlighted(false);
emit dataChanged(unHighlight, unHighlight);
}
if(highlight.isValid())
{
CGroupListItem *grp=static_cast(highlight.internalPointer());
if(grp)
grp->setHighlighted(true);
emit dataChanged(highlight, highlight);
}
}
void CGroupList::updateStatus(QSet &enabled, QSet &disabled,
QSet &partial)
{
QList::Iterator it(itsGroups.begin()),
end(itsGroups.end());
for(; it!=end; ++it)
if((*it)->isCustom())
(*it)->updateStatus(enabled, disabled, partial);
emit layoutChanged();
}
inline QColor midColour(const QColor &a, const QColor &b)
{
return QColor((a.red()+b.red())>>1, (a.green()+b.green())>>1, (a.blue()+b.blue())>>1);
}
QVariant CGroupList::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
CGroupListItem *grp=static_cast(index.internalPointer());
if(grp)
switch(index.column())
{
case COL_GROUP_NAME:
switch(role)
{
case Qt::FontRole:
if(CGroupListItem::SYSTEM==grp->type())
{
QFont font;
font.setItalic(true);
return font;
}
break;
case Qt::SizeHintRole:
{
const int s = KIconLoader::global()->currentSize(KIconLoader::Small);
return QSize(s, s + 4);
}
case Qt::EditRole:
case Qt::DisplayRole:
return grp->name();
case Qt::DecorationRole:
if(grp->highlighted())
switch(grp->type())
{
case CGroupListItem::ALL: // Removing from a group
return SmallIcon("list-remove");
case CGroupListItem::PERSONAL: // Copying/moving
case CGroupListItem::SYSTEM: // Copying/moving
return SmallIcon(Qt::LeftToRight==QApplication::layoutDirection()
? "go-next" : "go-previous");
case CGroupListItem::CUSTOM: // Adding to a group
return SmallIcon("list-add");
default:
break;
}
else
switch(grp->type())
{
case CGroupListItem::ALL:
return SmallIcon("font");
case CGroupListItem::PERSONAL:
return SmallIcon("user-identity");
case CGroupListItem::SYSTEM:
return SmallIcon("computer");
case CGroupListItem::UNCLASSIFIED:
return SmallIcon("fontstatus");
case CGroupListItem::CUSTOM:
if(0==grp->families().count())
return SmallIcon("image-missing");
switch(grp->status())
{
case CFamilyItem::PARTIAL:
return SmallIcon("dialog-ok", 0, KIconLoader::DisabledState);
case CFamilyItem::ENABLED:
return SmallIcon("dialog-ok");
case CFamilyItem::DISABLED:
return SmallIcon("dialog-cancel");
}
break;
}
default:
break;
}
break;
}
return QVariant();
}
bool CGroupList::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(Qt::EditRole==role && index.isValid())
{
QString name(value.toString().trimmed());
if(!name.isEmpty())
{
CGroupListItem *grp=static_cast(index.internalPointer());
if(grp && grp->isCustom() && grp->name()!=name && !exists(name, false))
{
grp->setName(name);
itsModified=true;
save();
sort(0, itsSortOrder);
return true;
}
}
}
return false;
}
Qt::ItemFlags CGroupList::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::ItemIsEnabled;
CGroupListItem *grp=static_cast(index.internalPointer());
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled |
(grp && grp->type()==CGroupListItem::CUSTOM ? Qt::ItemIsEditable : Qt::NoItemFlags);
}
QVariant CGroupList::headerData(int section, Qt::Orientation orientation, int role) const
{
if (Qt::Horizontal==orientation && COL_GROUP_NAME==section)
switch(role)
{
case Qt::DisplayRole:
return i18n("Group");
case Qt::TextAlignmentRole:
return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
case Qt::WhatsThisRole:
return whatsThis();
default:
break;
}
return QVariant();
}
QModelIndex CGroupList::index(int row, int column, const QModelIndex &parent) const
{
if(!parent.isValid())
{
CGroupListItem *grp=itsGroups.value(row);
if(grp)
return createIndex(row, column, grp);
}
return QModelIndex();
}
QModelIndex CGroupList::parent(const QModelIndex &) const
{
return QModelIndex();
}
int CGroupList::rowCount(const QModelIndex &) const
{
return itsGroups.count();
}
void CGroupList::rescan()
{
save();
load();
sort(0, itsSortOrder);
}
void CGroupList::load()
{
time_t ts=Misc::getTimeStamp(itsFileName);
if(!ts || ts!=itsTimeStamp)
{
clear();
itsTimeStamp=ts;
if(load(itsFileName))
itsModified=false;
}
}
bool CGroupList::load(const QString &file)
{
QFile f(file);
bool rv(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(GROUP_TAG==e.tagName() && e.hasAttribute(NAME_ATTR))
{
QString name(e.attribute(NAME_ATTR));
CGroupListItem *item=find(name);
if(!item)
{
item=new CGroupListItem(name);
if(!itsGroups.contains(itsSpecialGroups[CGroupListItem::UNCLASSIFIED]))
itsGroups.append(itsSpecialGroups[CGroupListItem::UNCLASSIFIED]);
itsGroups.append(item);
rv=true;
}
if(item->addFamilies(e))
rv=true;
}
}
}
return rv;
}
bool CGroupList::save()
{
if(itsModified && save(itsFileName, nullptr))
{
itsTimeStamp=Misc::getTimeStamp(itsFileName);
return true;
}
return false;
}
bool CGroupList::save(const QString &fileName, CGroupListItem *grp)
{
QSaveFile file(fileName);
if (file.open(QIODevice::WriteOnly))
{
QTextStream str(&file);
str << "<" GROUPS_DOC ">" << endl;
if(grp)
grp->save(str);
else
{
QList::Iterator it(itsGroups.begin()),
end(itsGroups.end());
for(; it!=end; ++it)
if((*it)->isCustom())
(*it)->save(str);
}
str << "" GROUPS_DOC ">" << endl;
itsModified=false;
return file.commit();
}
return false;
}
void CGroupList::merge(const QString &file)
{
if(load(file))
{
itsModified=true;
sort(0, itsSortOrder);
}
}
void CGroupList::clear()
{
beginResetModel();
itsGroups.removeFirst(); // Remove all
if(itsSpecialGroups[CGroupListItem::SYSTEM])
{
itsGroups.removeFirst(); // Remove personal
itsGroups.removeFirst(); // Remove system
}
if(itsGroups.contains(itsSpecialGroups[CGroupListItem::UNCLASSIFIED]))
itsGroups.removeFirst(); // Remove unclassif...
qDeleteAll(itsGroups);
itsGroups.clear();
itsGroups.append(itsSpecialGroups[CGroupListItem::ALL]);
if(itsSpecialGroups[CGroupListItem::SYSTEM])
{
itsGroups.append(itsSpecialGroups[CGroupListItem::PERSONAL]);
itsGroups.append(itsSpecialGroups[CGroupListItem::SYSTEM]);
}
// Don't add 'Unclassif' until we have some user groups
endResetModel();
}
QModelIndex CGroupList::index(CGroupListItem::EType t)
{
return createIndex(t, 0, itsSpecialGroups[t]);
}
void CGroupList::createGroup(const QString &name)
{
if(!exists(name))
{
if(!itsGroups.contains(itsSpecialGroups[CGroupListItem::UNCLASSIFIED]))
itsGroups.append(itsSpecialGroups[CGroupListItem::UNCLASSIFIED]);
itsGroups.append(new CGroupListItem(name));
itsModified=true;
save();
sort(0, itsSortOrder);
}
}
bool CGroupList::removeGroup(const QModelIndex &idx)
{
if(idx.isValid())
{
CGroupListItem *grp=static_cast(idx.internalPointer());
if(grp && grp->isCustom() &&
- KMessageBox::Yes==KMessageBox::warningYesNo(itsParent,
+ KMessageBox::Continue==KMessageBox::warningContinueCancel(itsParent,
i18n("Do you really want to remove \'%1\'?
"
"This will only remove the group, and not "
"the actual fonts.
", grp->name()),
i18n("Remove Group"), KGuiItem(i18n("Remove"), "list-remove",
i18n("Remove group"))))
{
itsModified=true;
itsGroups.removeAll(grp);
int stdGroups=1 +// All
(itsSpecialGroups[CGroupListItem::SYSTEM] ? 2 : 0)+ // Personal, System
1; // Unclassified
if(stdGroups==itsGroups.count() && itsGroups.contains(itsSpecialGroups[CGroupListItem::UNCLASSIFIED]))
itsGroups.removeAll(itsSpecialGroups[CGroupListItem::UNCLASSIFIED]);
delete grp;
save();
sort(0, itsSortOrder);
return true;
}
}
return false;
}
void CGroupList::removeFromGroup(const QModelIndex &group, const QSet &families)
{
if(group.isValid())
{
CGroupListItem *grp=static_cast(group.internalPointer());
if(grp && grp->isCustom())
{
QSet::ConstIterator it(families.begin()),
end(families.end());
bool update(false);
for(; it!=end; ++it)
if(removeFromGroup(grp, *it))
update=true;
if(update)
emit refresh();
}
}
}
QString CGroupList::whatsThis() const
{
return i18n("Font Groups
This list displays the font groups available on your system. "
"There are 2 main types of font groups:"
"
- Standard are special groups used by the font manager.
"
"- Custom are groups created by you. To add a font family to one of "
"these groups simply drag it from the list of fonts, and drop "
"onto the desired group. To remove a family from the group, drag "
"the font onto the \"All Fonts\" group.
"
"
",
Misc::root()
? i18n("All Fonts contains all the fonts installed on your system."
"Unclassified contains all fonts that have not yet been placed "
"within a \"Custom\" group.")
: i18n("All Fonts contains all the fonts installed on your system - "
"both \"System\" and \"Personal\"."
"System contains all fonts that are installed system-wide (i.e. "
"available to all users)."
"Personal contains your personal fonts."
"Unclassified contains all fonts that have not yet been placed "
"within a \"Custom\" group."));
}
void CGroupList::addToGroup(const QModelIndex &group, const QSet &families)
{
if(group.isValid())
{
CGroupListItem *grp=static_cast(group.internalPointer());
if(grp && grp->isCustom())
{
QSet::ConstIterator it(families.begin()),
end(families.end());
bool update(false);
for(; it!=end; ++it)
if(!grp->hasFamily(*it))
{
grp->addFamily(*it);
update=true;
itsModified=true;
}
if(update)
emit refresh();
}
}
}
void CGroupList::removeFamily(const QString &family)
{
QList::ConstIterator it(itsGroups.begin()),
end(itsGroups.end());
for(; it!=end; ++it)
removeFromGroup(*it, family);
}
bool CGroupList::removeFromGroup(CGroupListItem *grp, const QString &family)
{
if(grp && grp->isCustom() && grp->hasFamily(family))
{
grp->removeFamily(family);
itsModified=true;
return true;
}
return false;
}
static bool groupNameLessThan(const CGroupListItem *f1, const CGroupListItem *f2)
{
return f1 && f2 && (f1->type()type() ||
(f1->type()==f2->type() && QString::localeAwareCompare(f1->name(), f2->name())<0));
}
static bool groupNameGreaterThan(const CGroupListItem *f1, const CGroupListItem *f2)
{
return f1 && f2 && (f1->type()type() ||
(f1->type()==f2->type() && QString::localeAwareCompare(f1->name(), f2->name())>0));
}
void CGroupList::sort(int, Qt::SortOrder order)
{
itsSortOrder=order;
qSort(itsGroups.begin(), itsGroups.end(),
Qt::AscendingOrder==order ? groupNameLessThan : groupNameGreaterThan);
emit layoutChanged();
}
Qt::DropActions CGroupList::supportedDropActions() const
{
return Qt::CopyAction | Qt::MoveAction;
}
QStringList CGroupList::mimeTypes() const
{
QStringList types;
types << KFI_FONT_DRAG_MIME;
return types;
}
CGroupListItem * CGroupList::find(const QString &name)
{
QList::ConstIterator it(itsGroups.begin()),
end(itsGroups.end());
for(; it!=end; ++it)
if((*it)->name()==name)
return (*it);
return nullptr;
}
bool CGroupList::exists(const QString &name, bool showDialog)
{
if(nullptr!=find(name))
{
if(showDialog)
KMessageBox::error(itsParent, i18n("A group named \'%1\' already "
"exists.", name));
return true;
}
return false;
}
class CGroupListViewDelegate : public QStyledItemDelegate
{
public:
CGroupListViewDelegate(QObject *p) : QStyledItemDelegate(p) { }
~CGroupListViewDelegate() override { }
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &idx) const override
{
CGroupListItem *grp=static_cast(idx.internalPointer());
QStyleOptionViewItem opt(option);
if(grp && grp->isUnclassified())
opt.rect.adjust(0, 0, 0, -1);
QStyledItemDelegate::paint(painter, opt, idx);
if(grp && grp->isUnclassified())
{
opt.rect.adjust(2, 0, -2, 1);
painter->setPen(QApplication::palette().color(QPalette::Text));
painter->drawLine(opt.rect.bottomLeft(), opt.rect.bottomRight());
}
}
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &idx) const override
{
QSize sz(QStyledItemDelegate::sizeHint(option, idx));
CGroupListItem *grp=static_cast(idx.internalPointer());
if(grp && grp->isUnclassified())
sz.setHeight(sz.height()+1);
return sz;
}
static bool isCloseEvent(QKeyEvent *event)
{
return Qt::Key_Tab==event->key() || Qt::Key_Backtab==event->key() ||
Qt::Key_Enter==event->key() || Qt::Key_Return==event->key();
}
bool eventFilter(QObject *editor, QEvent *event) override
{
if(editor && event && QEvent::KeyPress==event->type() && isCloseEvent(static_cast(event)) &&
qobject_cast(editor))
{
QString text=static_cast(editor)->text().trimmed();
if(!text.isEmpty() &&
!static_cast(static_cast(parent())->model())->exists(text, false))
{
emit commitData(static_cast(editor));
emit closeEditor(static_cast(editor));
return true;
}
}
return false;
}
};
CGroupListView::CGroupListView(QWidget *parent, CGroupList *model)
: QTreeView(parent)
{
setModel(model);
setItemDelegate(new CGroupListViewDelegate(this));
sortByColumn(COL_GROUP_NAME, Qt::AscendingOrder);
setSelectionMode(QAbstractItemView::SingleSelection);
setSortingEnabled(true);
setAllColumnsShowFocus(true);
setAlternatingRowColors(true);
setAcceptDrops(true);
setDragDropMode(QAbstractItemView::DropOnly);
setDropIndicatorShown(true);
setDragEnabled(false);
header()->setSortIndicatorShown(true);
setRootIsDecorated(false);
itsMenu=new QMenu(this);
itsDeleteAct=itsMenu->addAction(QIcon::fromTheme("list-remove"), i18n("Remove"),
this, SIGNAL(del()));
itsMenu->addSeparator();
itsEnableAct=itsMenu->addAction(QIcon::fromTheme("enablefont"), i18n("Enable"),
this, SIGNAL(enable()));
itsDisableAct=itsMenu->addAction(QIcon::fromTheme("disablefont"), i18n("Disable"),
this, SIGNAL(disable()));
itsMenu->addSeparator();
itsRenameAct=itsMenu->addAction(QIcon::fromTheme("edit-rename"), i18n("Rename..."),
this, SLOT(rename()));
if(!Misc::app(KFI_PRINTER).isEmpty())
{
itsMenu->addSeparator();
itsPrintAct=itsMenu->addAction(QIcon::fromTheme("document-print"), i18n("Print..."),
this, SIGNAL(print()));
}
else
itsPrintAct= nullptr;
itsMenu->addSeparator();
itsExportAct=itsMenu->addAction(QIcon::fromTheme("document-export"), i18n("Export..."),
this, SIGNAL(zip()));
setWhatsThis(model->whatsThis());
header()->setWhatsThis(whatsThis());
connect(this, SIGNAL(addFamilies(QModelIndex,QSet)),
model, SLOT(addToGroup(QModelIndex,QSet)));
connect(this, SIGNAL(removeFamilies(QModelIndex,QSet)),
model, SLOT(removeFromGroup(QModelIndex,QSet)));
}
CGroupListItem::EType CGroupListView::getType()
{
QModelIndexList selectedItems(selectedIndexes());
if(!selectedItems.isEmpty() && selectedItems.last().isValid())
{
CGroupListItem *grp=static_cast(selectedItems.last().internalPointer());
return grp->type();
}
return CGroupListItem::ALL;
}
void CGroupListView::controlMenu(bool del, bool en, bool dis, bool p, bool exp)
{
itsDeleteAct->setEnabled(del);
itsRenameAct->setEnabled(del);
itsEnableAct->setEnabled(en);
itsDisableAct->setEnabled(dis);
if(itsPrintAct)
itsPrintAct->setEnabled(p);
itsExportAct->setEnabled(exp);
}
void CGroupListView::selectionChanged(const QItemSelection &selected,
const QItemSelection &deselected)
{
QModelIndexList deselectedItems(deselected.indexes());
QAbstractItemView::selectionChanged(selected, deselected);
QModelIndexList selectedItems(selectedIndexes());
if(0==selectedItems.count() && 1==deselectedItems.count())
selectionModel()->select(deselectedItems.last(), QItemSelectionModel::Select);
else
emit itemSelected(selectedItems.count()
? selectedItems.last()
: QModelIndex());
}
void CGroupListView::rename()
{
QModelIndex index(currentIndex());
if(index.isValid())
edit(index);
}
void CGroupListView::emitMoveFonts()
{
emit moveFonts();
}
void CGroupListView::contextMenuEvent(QContextMenuEvent *ev)
{
if(indexAt(ev->pos()).isValid())
itsMenu->popup(ev->globalPos());
}
void CGroupListView::dragEnterEvent(QDragEnterEvent *event)
{
if(event->mimeData()->hasFormat(KFI_FONT_DRAG_MIME))
event->acceptProposedAction();
}
void CGroupListView::dragMoveEvent(QDragMoveEvent *event)
{
if(event->mimeData()->hasFormat(KFI_FONT_DRAG_MIME))
{
QModelIndex index(indexAt(event->pos()));
if(index.isValid())
{
if(COL_GROUP_NAME!=index.column())
index=((CGroupList *)model())->createIdx(index.row(), COL_GROUP_NAME, index.internalPointer());
CGroupListItem *dest=static_cast(index.internalPointer());
CGroupListItem::EType type=getType();
if(dest)
if(!selectedIndexes().contains(index))
{
bool ok(true);
if(dest->isCustom())
emit info(i18n("Add to \"%1\".", dest->name()));
else if(CGroupListItem::CUSTOM==type && dest->isAll())
emit info(i18n("Remove from current group."));
else if(!Misc::root() && dest->isPersonal() && CGroupListItem::SYSTEM==type)
emit info(i18n("Move to personal folder."));
else if(!Misc::root() && dest->isSystem() && CGroupListItem::PERSONAL==type)
emit info(i18n("Move to system folder."));
else
ok=false;
if(ok)
{
drawHighlighter(index);
event->acceptProposedAction();
return;
}
}
}
event->ignore();
drawHighlighter(QModelIndex());
emit info(QString());
}
}
void CGroupListView::dragLeaveEvent(QDragLeaveEvent *)
{
drawHighlighter(QModelIndex());
emit info(QString());
}
void CGroupListView::dropEvent(QDropEvent *event)
{
emit info(QString());
drawHighlighter(QModelIndex());
if(event->mimeData()->hasFormat(KFI_FONT_DRAG_MIME))
{
event->acceptProposedAction();
QSet families;
QByteArray encodedData(event->mimeData()->data(KFI_FONT_DRAG_MIME));
QDataStream ds(&encodedData, QIODevice::ReadOnly);
QModelIndex from(selectedIndexes().last()),
to(indexAt(event->pos()));
ds >> families;
// Are we moving/copying, removing a font from the current group?
if(to.isValid() && from.isValid())
{
if( ((static_cast(from.internalPointer()))->isSystem() &&
(static_cast(to.internalPointer()))->isPersonal()) ||
((static_cast(from.internalPointer()))->isPersonal() &&
(static_cast(to.internalPointer()))->isSystem()))
QTimer::singleShot(0, this, SLOT(emitMoveFonts()));
else if((static_cast(from.internalPointer()))->isCustom() &&
!(static_cast(to.internalPointer()))->isCustom())
emit removeFamilies(from, families);
else
emit addFamilies(to, families);
}
if(isUnclassified())
emit unclassifiedChanged();
}
}
void CGroupListView::drawHighlighter(const QModelIndex &idx)
{
if(itsCurrentDropItem!=idx)
{
((CGroupList *)model())->update(itsCurrentDropItem, idx);
itsCurrentDropItem=idx;
}
}
bool CGroupListView::viewportEvent(QEvent *event)
{
executeDelayedItemsLayout();
return QTreeView::viewportEvent(event);
}
}
diff --git a/kcms/kfontinst/kcmfontinst/KCmFontInst.cpp b/kcms/kfontinst/kcmfontinst/KCmFontInst.cpp
index d0589de9d..4ee7cb8e4 100644
--- a/kcms/kfontinst/kcmfontinst/KCmFontInst.cpp
+++ b/kcms/kfontinst/kcmfontinst/KCmFontInst.cpp
@@ -1,1277 +1,1276 @@
/*
* KFontInst - KDE Font Installer
*
* Copyright 2003-2007 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 "KCmFontInst.h"
#include "KfiConstants.h"
#include "PrintDialog.h"
#include "FcEngine.h"
#include "FontPreview.h"
#include "FontsPackage.h"
#include "Misc.h"
#include "FontList.h"
#include "DuplicatesDialog.h"
#include "FontFilter.h"
#include "PreviewSelectAction.h"
#include "PreviewList.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CFG_GROUP "Main Settings"
#define CFG_PREVIEW_SPLITTER_SIZES "PreviewSplitterSizes"
#define CFG_GROUP_SPLITTER_SIZES "GroupSplitterSizes"
#define CFG_FONT_SIZE "FontSize"
K_PLUGIN_FACTORY(FontInstallFactory,
registerPlugin();
)
K_EXPORT_PLUGIN(FontInstallFactory("fontinst"))
namespace KFI
{
static QString partialIcon(bool load=true)
{
QString name = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/kfi/partial.png";
if(Misc::fExists(name))
{
if(!load)
QFile::remove(name);
}
else if(load)
{
QString pth;
QPixmap pix=KIconLoader::global()->loadIcon("dialog-ok", KIconLoader::Small, KIconLoader::SizeSmall,
KIconLoader::DisabledState);
pix.save(name, "PNG");
}
return name;
}
class CPushButton : public QPushButton
{
public:
CPushButton(const KGuiItem &item, QWidget *parent)
: QPushButton(parent)
{
KGuiItem::assign(this, item);
theirHeight=qMax(theirHeight, QPushButton::sizeHint().height());
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
}
QSize sizeHint() const override
{
QSize sh(QPushButton::sizeHint());
sh.setHeight(theirHeight);
if(sh.width()addAppDir(KFI_NAME);
KAboutData *about = new KAboutData(QStringLiteral("fontinst"), i18n("Font Management"), QStringLiteral("1.0"), QString(),
KAboutLicense::GPL, i18n("(C) Craig Drummond, 2000 - 2009"));
about->addAuthor(i18n("Craig Drummond"), i18n("Developer and maintainer"), QStringLiteral("craig@kde.org"));
setAboutData(about);
KConfigGroup cg(&itsConfig, CFG_GROUP);
itsGroupSplitter=new QSplitter(this);
itsGroupSplitter->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
QWidget *groupWidget=new QWidget(itsGroupSplitter),
*fontWidget=new QWidget(itsGroupSplitter);
itsPreviewSplitter=new QSplitter(fontWidget);
itsPreviewSplitter->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
QWidget *toolbarWidget=new QWidget(this),
*fontControlWidget=new QWidget(fontWidget);
CToolBar *toolbar=new CToolBar(toolbarWidget);
QGridLayout *groupsLayout=new QGridLayout(groupWidget);
QBoxLayout *mainLayout=new QBoxLayout(QBoxLayout::TopToBottom, this),
*toolbarLayout=new QBoxLayout(QBoxLayout::LeftToRight, toolbarWidget),
*fontsLayout=new QBoxLayout(QBoxLayout::TopToBottom, fontWidget),
*fontControlLayout=new QBoxLayout(QBoxLayout::LeftToRight, fontControlWidget);
toolbarLayout->setMargin(0);
mainLayout->setMargin(0);
groupsLayout->setMargin(0);
fontsLayout->setMargin(0);
fontControlLayout->setMargin(0);
// Toolbar...
duplicateFontsAct=new QAction(QIcon::fromTheme("system-search"), i18n("Scan for Duplicate Fonts..."), this);
// validateFontsAct=new QAction(QIcon::fromTheme("checkmark"), i18n("Validate Fonts..."), this);
toolbar->addAction(duplicateFontsAct);
// toolbar->addAction(validateFontsAct);
toolbar->setToolButtonStyle(Qt::ToolButtonFollowStyle);
itsFilter=new CFontFilter(toolbarWidget);
// Details - Groups...
itsGroupList=new CGroupList(groupWidget);
itsGroupListView=new CGroupListView(groupWidget, itsGroupList);
QPushButton *createGroup=new CPushButton(KGuiItem(QString(), "list-add",
- i18n("Create a new group")),
+ i18n("Create New Group...")),
groupWidget);
- itsDeleteGroupControl=new CPushButton(KGuiItem(QString(), "edit-delete",
- i18n("Remove group")),
+ itsDeleteGroupControl=new CPushButton(KGuiItem(QString(), "list-remove",
+ i18n("Remove Group...")),
groupWidget);
itsEnableGroupControl=new CPushButton(KGuiItem(QString(), "enablefont",
- i18n("Enable all disabled fonts in the current group")),
+ i18n("Enable Fonts in Group...")),
groupWidget);
itsDisableGroupControl=new CPushButton(KGuiItem(QString(), "disablefont",
- i18n("Disable all enabled fonts in the current group")),
+ i18n("Disable Fonts in Group...")),
groupWidget);
groupsLayout->addWidget(itsGroupListView, 0, 0, 1, 5);
groupsLayout->addWidget(createGroup, 1, 0);
groupsLayout->addWidget(itsDeleteGroupControl, 1, 1);
groupsLayout->addWidget(itsEnableGroupControl, 1, 2);
groupsLayout->addWidget(itsDisableGroupControl, 1, 3);
groupsLayout->addItem(new QSpacerItem(itsDisableGroupControl->width(), groupsLayout->spacing(),
QSizePolicy::Expanding, QSizePolicy::Fixed), 1, 4);
itsPreviewWidget = new QWidget(this);
QBoxLayout *previewWidgetLayout = new QBoxLayout(QBoxLayout::TopToBottom, itsPreviewWidget);
previewWidgetLayout->setMargin(0);
previewWidgetLayout->setSpacing(0);
// Preview
QFrame *previewFrame=new QFrame(itsPreviewWidget);
QBoxLayout *previewFrameLayout=new QBoxLayout(QBoxLayout::LeftToRight, previewFrame);
previewFrameLayout->setMargin(0);
previewFrameLayout->setSpacing(0);
previewFrame->setFrameShape(QFrame::StyledPanel);
previewFrame->setFrameShadow(QFrame::Sunken);
previewFrame->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
itsPreview=new CFontPreview(previewFrame);
itsPreview->setWhatsThis(i18n("This displays a preview of the selected font."));
itsPreview->setContextMenuPolicy(Qt::CustomContextMenu);
previewFrameLayout->addWidget(itsPreview);
previewWidgetLayout->addWidget(previewFrame);
itsPreview->engine()->readConfig(itsConfig);
// List-style preview...
itsPreviewList = new CPreviewListView(itsPreview->engine(), itsPreviewWidget);
previewWidgetLayout->addWidget(itsPreviewList);
itsPreviewList->setVisible(false);
// Font List...
itsFontList=new CFontList(fontWidget);
itsFontListView=new CFontListView(itsPreviewSplitter, itsFontList);
itsFontListView->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
itsAddFontControl=new CPushButton(KGuiItem(i18n("Install from File..."), "document-import",
i18n("Install fonts from a local file")),
fontControlWidget);
itsGetNewFontsControl=new CPushButton(KGuiItem(i18n("Get New Fonts..."), "get-hot-new-stuff",
i18n("Download new fonts")),
fontControlWidget);
- itsDeleteFontControl=new CPushButton(KGuiItem(i18n("Delete"), "edit-delete",
- i18n("Delete all selected fonts")),
+ itsDeleteFontControl=new CPushButton(KGuiItem(QString(), "edit-delete",
+ i18n("Delete Selected Fonts...")),
fontControlWidget);
itsPreviewSplitter->addWidget(itsPreviewWidget);
itsPreviewSplitter->setCollapsible(1, true);
itsStatusLabel = new QLabel(fontControlWidget);
itsStatusLabel->setAlignment(Qt::AlignVCenter|Qt::AlignRight);
itsListingProgress=new CProgressBar(fontControlWidget, itsStatusLabel->height());
itsListingProgress->setRange(0, 100);
// Layout widgets...
toolbarLayout->addWidget(toolbar);
- toolbarLayout->addItem(new QSpacerItem(toolbarLayout->spacing(), 2, QSizePolicy::MinimumExpanding, QSizePolicy::Fixed));
toolbarLayout->addWidget(itsFilter);
mainLayout->addWidget(toolbarWidget);
mainLayout->addWidget(itsGroupSplitter);
fontControlLayout->addWidget(itsDeleteFontControl);
fontControlLayout->addWidget(itsStatusLabel);
fontControlLayout->addItem(new QSpacerItem(0, itsListingProgress->height()+4,
QSizePolicy::Fixed, QSizePolicy::Fixed));
fontControlLayout->addWidget(itsListingProgress);
fontControlLayout->addWidget(itsAddFontControl);
fontControlLayout->addWidget(itsGetNewFontsControl);
fontsLayout->addWidget(itsPreviewSplitter);
fontsLayout->addWidget(fontControlWidget);
// Set size of widgets...
itsPreviewSplitter->setChildrenCollapsible(false);
itsGroupSplitter->setChildrenCollapsible(false);
itsGroupSplitter->setStretchFactor(0, 0);
itsGroupSplitter->setStretchFactor(1, 1);
itsPreviewSplitter->setStretchFactor(0, 1);
itsPreviewSplitter->setStretchFactor(1, 0);
// Set sizes for 3 views...
QList defaultSizes;
defaultSizes+=300;
defaultSizes+=220;
itsPreviewSplitter->setSizes(cg.readEntry(CFG_PREVIEW_SPLITTER_SIZES, defaultSizes));
itsPreviewHidden=itsPreviewSplitter->sizes().at(1)<8;
defaultSizes.clear();
defaultSizes+=110;
defaultSizes+=350;
itsGroupSplitter->setSizes(cg.readEntry(CFG_GROUP_SPLITTER_SIZES, defaultSizes));
// Preview widget pop-up menu
itsPreviewMenu = new QMenu(itsPreview);
QAction *zoomIn=KStandardAction::create(KStandardAction::ZoomIn, itsPreview, SLOT(zoomIn()), this),
*zoomOut=KStandardAction::create(KStandardAction::ZoomOut, itsPreview, SLOT(zoomOut()), this);
itsPreviewMenu->addAction(zoomIn);
itsPreviewMenu->addAction(zoomOut);
itsPreviewMenu->addSeparator();
CPreviewSelectAction *prevSel=new CPreviewSelectAction(itsPreviewMenu);
itsPreviewMenu->addAction(prevSel);
QAction *changeTextAct=new QAction(QIcon::fromTheme("edit-rename"), i18n("Change Preview Text..."), this);
itsPreviewMenu->addAction(changeTextAct),
itsPreviewListMenu = new QMenu(itsPreviewList);
itsPreviewListMenu->addAction(changeTextAct),
// Connect signals...
connect(itsPreview, SIGNAL(atMax(bool)), zoomIn, SLOT(setDisabled(bool)));
connect(itsPreview, SIGNAL(atMin(bool)), zoomOut, SLOT(setDisabled(bool)));
connect(prevSel, SIGNAL(range(QList)),
itsPreview, SLOT(setUnicodeRange(QList)));
connect(changeTextAct, SIGNAL(triggered(bool)), SLOT(changeText()));
connect(itsFilter, SIGNAL(textChanged(QString)), itsFontListView, SLOT(filterText(QString)));
connect(itsFilter, SIGNAL(criteriaChanged(int,qulonglong,QStringList)),
itsFontListView, SLOT(filterCriteria(int,qulonglong,QStringList)));
connect(itsGroupListView, SIGNAL(del()), SLOT(removeGroup()));
connect(itsGroupListView, SIGNAL(print()), SLOT(printGroup()));
connect(itsGroupListView, SIGNAL(enable()), SLOT(enableGroup()));
connect(itsGroupListView, SIGNAL(disable()), SLOT(disableGroup()));
connect(itsGroupListView, SIGNAL(moveFonts()), SLOT(moveFonts()));
connect(itsGroupListView, SIGNAL(zip()), SLOT(zipGroup()));
connect(itsGroupListView, SIGNAL(itemSelected(QModelIndex)),
SLOT(groupSelected(QModelIndex)));
connect(itsGroupListView, SIGNAL(info(QString)),
SLOT(showInfo(QString)));
connect(itsGroupList, SIGNAL(refresh()), SLOT(refreshFontList()));
connect(itsFontList, SIGNAL(listingPercent(int)), SLOT(listingPercent(int)));
connect(itsFontList, SIGNAL(layoutChanged()), SLOT(setStatusBar()));
connect(itsFontListView, SIGNAL(del()), SLOT(deleteFonts()));
connect(itsFontListView, SIGNAL(print()), SLOT(print()));
connect(itsFontListView, SIGNAL(enable()), SLOT(enableFonts()));
connect(itsFontListView, SIGNAL(disable()), SLOT(disableFonts()));
connect(itsFontListView, SIGNAL(fontsDropped(QSet)),
SLOT(addFonts(QSet)));
connect(itsFontListView, SIGNAL(itemsSelected(QModelIndexList)), SLOT(fontsSelected(QModelIndexList)));
connect(itsFontListView, SIGNAL(refresh()), SLOT(setStatusBar()));
connect(itsGroupListView, SIGNAL(unclassifiedChanged()), itsFontListView, SLOT(refreshFilter()));
connect(createGroup, SIGNAL(clicked()), SLOT(addGroup()));
connect(itsDeleteGroupControl, SIGNAL(clicked()), SLOT(removeGroup()));
connect(itsEnableGroupControl, SIGNAL(clicked()), SLOT(enableGroup()));
connect(itsDisableGroupControl, SIGNAL(clicked()), SLOT(disableGroup()));
connect(itsAddFontControl, SIGNAL(clicked()), SLOT(addFonts()));
connect(itsGetNewFontsControl, SIGNAL(clicked()), SLOT(downloadFonts()));
connect(itsDeleteFontControl, SIGNAL(clicked()), SLOT(deleteFonts()));
connect(duplicateFontsAct, SIGNAL(triggered(bool)), SLOT(duplicateFonts()));
//connect(validateFontsAct, SIGNAL(triggered(bool)), SLOT(validateFonts()));
connect(itsPreview, SIGNAL(customContextMenuRequested(QPoint)), SLOT(previewMenu(QPoint)));
connect(itsPreviewList, SIGNAL(showMenu(QPoint)), SLOT(previewMenu(QPoint)));
connect(itsPreviewSplitter, SIGNAL(splitterMoved(int,int)), SLOT(splitterMoved()));
selectMainGroup();
itsFontList->load();
}
CKCmFontInst::~CKCmFontInst()
{
KConfigGroup cg(&itsConfig, CFG_GROUP);
cg.writeEntry(CFG_PREVIEW_SPLITTER_SIZES, itsPreviewSplitter->sizes());
cg.writeEntry(CFG_GROUP_SPLITTER_SIZES, itsGroupSplitter->sizes());
delete itsTempDir;
partialIcon(false);
}
QString CKCmFontInst::quickHelp() const
{
return Misc::root()
? i18n("Font Installer
This module allows you to"
" install TrueType, Type1, and Bitmap"
" fonts.
You may also install fonts using Konqueror:"
" type fonts:/ into Konqueror's location bar"
" and this will display your installed fonts. To install a"
" font, simply copy one into the folder.
")
: i18n("Font Installer
This module allows you to"
" install TrueType, Type1, and Bitmap"
" fonts.
You may also install fonts using Konqueror:"
" type fonts:/ into Konqueror's location bar"
" and this will display your installed fonts. To install a"
" font, simply copy it into the appropriate folder - "
" \"%1\" for fonts available to just yourself, or "
" \"%2\" for system-wide fonts (available to all).
",
i18n(KFI_KIO_FONTS_USER), i18n(KFI_KIO_FONTS_SYS));
}
void CKCmFontInst::previewMenu(const QPoint &pos)
{
if(itsPreviewList->isHidden())
itsPreviewMenu->popup(itsPreview->mapToGlobal(pos));
else
itsPreviewListMenu->popup(itsPreviewList->mapToGlobal(pos));
}
void CKCmFontInst::splitterMoved()
{
if(itsPreviewWidget->width()>8 && itsPreviewHidden)
{
itsPreviewHidden=false;
fontsSelected(itsFontListView->getSelectedItems());
}
else if(!itsPreviewHidden && itsPreviewWidget->width()<8)
itsPreviewHidden=true;
}
void CKCmFontInst::fontsSelected(const QModelIndexList &list)
{
if(!itsPreviewHidden)
{
if(!list.isEmpty())
{
if(list.count()<2)
{
CFontModelItem *mi=static_cast(list.last().internalPointer());
CFontItem *font=mi->parent()
? static_cast(mi)
: (static_cast(mi))->regularFont();
if(font)
itsPreview->showFont(font->isEnabled() ? font->family() : font->fileName(),
font->styleInfo(), font->index());
}
else
itsPreviewList->showFonts(list);
}
itsPreviewList->setVisible(list.count()>1);
itsPreview->parentWidget()->setVisible(list.count()<2);
}
itsDeleteFontControl->setEnabled(list.count());
}
void CKCmFontInst::addFonts()
{
QFileDialog dlg(this, i18n("Add Fonts"));
dlg.setFileMode(QFileDialog::ExistingFiles);
dlg.setMimeTypeFilters(CFontList::fontMimeTypes);
QList list;
if (dlg.exec() == QDialog::Accepted)
list = dlg.selectedUrls();
if(!list.isEmpty())
{
QSet urls;
QList::Iterator it(list.begin()),
end(list.end());
for(; it!=end; ++it)
{
if(KFI_KIO_FONTS_PROTOCOL!=(*it).scheme()) // Do not try to install from fonts:/ !!!
{
auto job = KIO::mostLocalUrl(*it);
KJobWidgets::setWindow(job, this);
job->exec();
QUrl url = job->mostLocalUrl();
if(url.isLocalFile())
{
QString file(url.toLocalFile());
if(Misc::isPackage(file)) // If its a package we need to unzip 1st...
urls+=FontsPackage::extract(url.toLocalFile(), &itsTempDir);
else if(!Misc::isMetrics(url))
urls.insert(url);
}
else if(!Misc::isMetrics(url))
urls.insert(url);
}
}
if(!urls.isEmpty())
addFonts(urls);
delete itsTempDir;
itsTempDir=nullptr;
}
}
void CKCmFontInst::groupSelected(const QModelIndex &index)
{
CGroupListItem *grp=nullptr;
if(index.isValid())
grp=static_cast(index.internalPointer());
else
return;
itsFontListView->setFilterGroup(grp);
setStatusBar();
//
// Check fonts listed within group are still valid!
if(grp->isCustom() && !grp->validated())
{
QSet remList;
QSet::Iterator it(grp->families().begin()),
end(grp->families().end());
for(; it!=end; ++it)
if(!itsFontList->hasFamily(*it))
remList.insert(*it);
it=remList.begin();
end=remList.end();
for(; it!=end; ++it)
itsGroupList->removeFromGroup(grp, *it);
grp->setValidated();
}
itsGetNewFontsControl->setEnabled(grp->isPersonal() || grp->isAll());
}
void CKCmFontInst::print(bool all)
{
//
// In order to support printing of newly installed/enabled fonts, the actual printing
// is carried out by the kfontinst helper app. This way we know Qt's font list will be
// up to date.
if((!itsPrintProc || QProcess::NotRunning==itsPrintProc->state()) && !Misc::app(KFI_PRINTER).isEmpty())
{
QSet fonts;
itsFontListView->getPrintableFonts(fonts, !all);
if(!fonts.isEmpty())
{
CPrintDialog dlg(this);
KConfigGroup cg(&itsConfig, CFG_GROUP);
if(dlg.exec(cg.readEntry(CFG_FONT_SIZE, 1)))
{
static const int constSizes[]={0, 12, 18, 24, 36, 48};
QSet::ConstIterator it(fonts.begin()),
end(fonts.end());
QTemporaryFile tmpFile;
bool useFile(fonts.count()>16),
startProc(true);
QStringList args;
if(!itsPrintProc)
itsPrintProc=new QProcess(this);
else
itsPrintProc->kill();
QString title = QGuiApplication::applicationDisplayName();
if (title.isEmpty())
title = QCoreApplication::applicationName();
//
// If we have lots of fonts to print, pass kfontinst a temporary groups file to print
// instead of passing font by font...
if(useFile)
{
if(tmpFile.open())
{
QTextStream str(&tmpFile);
for(; it!=end; ++it)
str << (*it).family << endl
<< (*it).styleInfo << endl;
args << "--embed" << QString().sprintf("0x%x", (unsigned int)window()->winId())
<< "--qwindowtitle" << title
<< "--qwindowicon" << "preferences-desktop-font-installer"
<< "--size" << QString().setNum(constSizes[dlg.chosenSize() < 6 ? dlg.chosenSize() : 2])
<< "--listfile" << tmpFile.fileName()
<< "--deletefile";
}
else
{
KMessageBox::error(this, i18n("Failed to save list of fonts to print."));
startProc=false;
}
}
else
{
args << "--embed" << QString().sprintf("0x%x", (unsigned int)window()->winId())
<< "--qwindowtitle" << title
<< "--qwindowicon" << "preferences-desktop-font-installer"
<< "--size" << QString().setNum(constSizes[dlg.chosenSize()<6 ? dlg.chosenSize() : 2]);
for(; it!=end; ++it)
args << "--pfont" << QString((*it).family.toUtf8()+','+QString().setNum((*it).styleInfo));
}
if(startProc)
{
itsPrintProc->start(Misc::app(KFI_PRINTER), args);
if(itsPrintProc->waitForStarted(1000))
{
if(useFile)
tmpFile.setAutoRemove(false);
}
else
KMessageBox::error(this, i18n("Failed to start font printer."));
}
cg.writeEntry(CFG_FONT_SIZE, dlg.chosenSize());
}
}
else
KMessageBox::information(this, i18n("There are no printable fonts.\n"
"You can only print non-bitmap and enabled fonts."),
i18n("Cannot Print"));
}
}
void CKCmFontInst::deleteFonts()
{
CJobRunner::ItemList urls;
QStringList fontNames;
QSet fonts;
itsDeletedFonts.clear();
itsFontListView->getFonts(urls, fontNames, &fonts, true);
if(urls.isEmpty())
KMessageBox::information(this, i18n("You did not select anything to delete."),
i18n("Nothing to Delete"));
else
{
QSet::ConstIterator it(fonts.begin()),
end(fonts.end());
bool doIt=false;
for(; it!=end; ++it)
itsDeletedFonts.insert((*it).family);
switch(fontNames.count())
{
case 0:
break;
case 1:
- doIt = KMessageBox::Yes==KMessageBox::warningYesNo(this,
+ doIt = KMessageBox::Continue==KMessageBox::warningContinueCancel(this,
i18n("Do you really want to "
"delete
\'%1\'?
", fontNames.first()),
i18n("Delete Font"), KStandardGuiItem::del());
break;
default:
- doIt = KMessageBox::Yes==KMessageBox::warningYesNoList(this,
+ doIt = KMessageBox::Continue==KMessageBox::warningContinueCancelList(this,
i18np("Do you really want to delete this font?",
"Do you really want to delete these %1 fonts?",
fontNames.count()),
fontNames, i18n("Delete Fonts"), KStandardGuiItem::del());
}
if(doIt)
{
itsStatusLabel->setText(i18n("Deleting font(s)..."));
doCmd(CJobRunner::CMD_DELETE, urls);
}
}
}
void CKCmFontInst::moveFonts()
{
CJobRunner::ItemList urls;
QStringList fontNames;
itsDeletedFonts.clear();
itsFontListView->getFonts(urls, fontNames, nullptr, true);
if(urls.isEmpty())
KMessageBox::information(this, i18n("You did not select anything to move."),
i18n("Nothing to Move"));
else
{
bool doIt=false;
switch(fontNames.count())
{
case 0:
break;
case 1:
- doIt = KMessageBox::Yes==KMessageBox::warningYesNo(this,
+ doIt = KMessageBox::Continue==KMessageBox::warningContinueCancel(this,
i18n("Do you really want to "
"move
\'%1\'
from %2 to %3?
",
fontNames.first(),
itsGroupListView->isSystem() ? i18n(KFI_KIO_FONTS_SYS) : i18n(KFI_KIO_FONTS_USER),
itsGroupListView->isSystem() ? i18n(KFI_KIO_FONTS_USER) : i18n(KFI_KIO_FONTS_SYS)),
i18n("Move Font"), KGuiItem(i18n("Move")));
break;
default:
- doIt = KMessageBox::Yes==KMessageBox::warningYesNoList(this,
+ doIt = KMessageBox::Continue==KMessageBox::warningContinueCancelList(this,
i18np("Do you really want to move this font from %2 to %3?
",
"Do you really want to move these %1 fonts from %2 to %3?
",
fontNames.count(),
itsGroupListView->isSystem() ? i18n(KFI_KIO_FONTS_SYS) : i18n(KFI_KIO_FONTS_USER),
itsGroupListView->isSystem() ? i18n(KFI_KIO_FONTS_USER) : i18n(KFI_KIO_FONTS_SYS)),
fontNames, i18n("Move Fonts"), KGuiItem(i18n("Move")));
}
if(doIt)
{
itsStatusLabel->setText(i18n("Moving font(s)..."));
doCmd(CJobRunner::CMD_MOVE, urls, !itsGroupListView->isSystem());
}
}
}
void CKCmFontInst::zipGroup()
{
QModelIndex idx(itsGroupListView->currentIndex());
if(idx.isValid())
{
CGroupListItem *grp=static_cast(idx.internalPointer());
if(grp)
{
QFileDialog dlg(this, i18n("Export Group"));
dlg.setAcceptMode(QFileDialog::AcceptSave);
dlg.setDirectoryUrl(QUrl::fromLocalFile(grp->name()));
dlg.setMimeTypeFilters(QStringList() << QStringLiteral("application/zip"));
QString fileName;
if (dlg.exec() == QDialog::Accepted)
fileName = dlg.selectedFiles().value(0);
if(!fileName.isEmpty())
{
KZip zip(fileName);
if(zip.open(QIODevice::WriteOnly))
{
QSet files;
files=itsFontListView->getFiles();
if(!files.isEmpty())
{
QMap map=Misc::getFontFileMap(files);
QMap::ConstIterator it(map.constBegin()),
end(map.constEnd());
for(; it!=end; ++it)
zip.addLocalFile(it.value(), it.key());
zip.close();
}
else
KMessageBox::error(this, i18n("No files?"));
}
else
KMessageBox::error(this, i18n("Failed to open %1 for writing", fileName));
}
}
}
}
void CKCmFontInst::enableFonts()
{
toggleFonts(true);
}
void CKCmFontInst::disableFonts()
{
toggleFonts(false);
}
void CKCmFontInst::addGroup()
{
bool ok;
QString name(QInputDialog::getText(this, i18n("Create New Group"),
- i18n("Please enter the name of the new group:"),
+ i18n("Name of New Group:"),
QLineEdit::Normal,
i18n("New Group"), &ok));
if(ok && !name.isEmpty())
itsGroupList->createGroup(name);
}
void CKCmFontInst::removeGroup()
{
if(itsGroupList->removeGroup(itsGroupListView->currentIndex()))
selectMainGroup();
}
void CKCmFontInst::enableGroup()
{
toggleGroup(true);
}
void CKCmFontInst::disableGroup()
{
toggleGroup(false);
}
void CKCmFontInst::changeText()
{
bool status;
QString oldStr(itsPreview->engine()->getPreviewString()),
newStr(QInputDialog::getText(this, i18n("Preview Text"),
i18n("Please enter new text:"),
QLineEdit::Normal,
oldStr, &status));
if(status && oldStr!=newStr)
{
itsPreview->engine()->setPreviewString(newStr);
itsPreview->showFont();
itsPreviewList->refreshPreviews();
}
}
void CKCmFontInst::duplicateFonts()
{
CDuplicatesDialog(this, itsFontList).exec();
}
//void CKCmFontInst::validateFonts()
//{
//}
void CKCmFontInst::downloadFonts()
{
KNS3::DownloadDialog *newStuff = new KNS3::DownloadDialog("kfontinst.knsrc", this);
newStuff->exec();
if(!newStuff->changedEntries().isEmpty()) // We have new fonts, so need to reconfigure fontconfig...
{
// Ask dbus helper for the current fonts folder name...
// We then sym-link our knewstuff3 download folder into the fonts folder...
QString destFolder=CJobRunner::folderName(false);
if(!destFolder.isEmpty()) {
destFolder+="kfontinst";
if(!QFile::exists(destFolder)) {
QFile _file(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + "kfontinst");
_file.link(destFolder);
}
}
doCmd(CJobRunner::CMD_UPDATE, CJobRunner::ItemList());
}
delete newStuff;
}
void CKCmFontInst::print()
{
print(false);
}
void CKCmFontInst::printGroup()
{
print(true);
}
void CKCmFontInst::listingPercent(int p)
{
if(0==p)
{
showInfo(i18n("Scanning font list..."));
itsListingProgress->show();
}
else if(100==p && p!=itsListingProgress->value())
{
removeDeletedFontsFromGroups();
QSet foundries;
itsFontList->getFoundries(foundries);
itsFilter->setFoundries(foundries);
refreshFamilies();
itsListingProgress->hide();
itsFontListView->selectFirstFont();
}
itsListingProgress->setValue(p);
}
void CKCmFontInst::refreshFontList()
{
itsFontListView->refreshFilter();
refreshFamilies();
}
void CKCmFontInst::refreshFamilies()
{
QSet enabledFamilies,
disabledFamilies,
partialFamilies;
itsFontList->getFamilyStats(enabledFamilies, disabledFamilies, partialFamilies);
itsGroupList->updateStatus(enabledFamilies, disabledFamilies, partialFamilies);
setStatusBar();
}
void CKCmFontInst::showInfo(const QString &info)
{
if(info.isEmpty())
if(itsLastStatusBarMsg.isEmpty())
setStatusBar();
else
{
itsStatusLabel->setText(itsLastStatusBarMsg);
itsLastStatusBarMsg=QString();
}
else
{
if(itsLastStatusBarMsg.isEmpty())
itsLastStatusBarMsg=itsStatusLabel->text();
itsStatusLabel->setText(info);
}
}
void CKCmFontInst::setStatusBar()
{
if(itsFontList->slowUpdates())
return;
int enabled=0,
disabled=0,
partial=0;
bool selectedEnabled=false,
selectedDisabled=false;
itsStatusLabel->setToolTip(QString());
if(0==itsFontList->families().count())
itsStatusLabel->setText(i18n("No fonts"));
else
{
itsFontListView->stats(enabled, disabled, partial);
itsFontListView->selectedStatus(selectedEnabled, selectedDisabled);
QString text(i18np("1 Font", "%1 Fonts", enabled+disabled+partial));
if(disabled||partial)
{
text+=QString(" (%2").arg(KIconLoader::global()->iconPath("dialog-ok", -KIconLoader::SizeSmall)).arg(enabled)
+QString(" %2").arg(KIconLoader::global()->iconPath("dialog-cancel", -KIconLoader::SizeSmall)).arg(disabled);
if(partial)
text+=QString(" %2").arg(partialIcon()).arg(partial);
text+=QLatin1Char(')');
itsStatusLabel->setToolTip(partial
? i18n(""
"Enabled: | %1 |
"
"Disabled: | %2 |
"
"Partially enabled: | %3 |
"
"Total: | %4 |
"
"
", enabled, disabled, partial, enabled+disabled+partial)
: i18n(""
"Enabled: | %1 |
"
"Disabled: | %2 |
"
"Total: | %3 |
"
"
", enabled, disabled, enabled+disabled));
}
itsStatusLabel->setText(disabled||partial ? ""+text+"
" : text);
}
CGroupListItem::EType type(itsGroupListView->getType());
bool isStd(CGroupListItem::CUSTOM==type);
itsAddFontControl->setEnabled(CGroupListItem::ALL==type||CGroupListItem::UNCLASSIFIED==type||
CGroupListItem::PERSONAL==type||CGroupListItem::SYSTEM==type);
itsDeleteGroupControl->setEnabled(isStd);
itsEnableGroupControl->setEnabled(disabled||partial);
itsDisableGroupControl->setEnabled(isStd && (enabled||partial));
itsGroupListView->controlMenu(itsDeleteGroupControl->isEnabled(),
itsEnableGroupControl->isEnabled(),
itsDisableGroupControl->isEnabled(), enabled||partial, enabled||disabled);
itsDeleteFontControl->setEnabled(selectedEnabled||selectedDisabled);
}
void CKCmFontInst::addFonts(const QSet &src)
{
if(!src.isEmpty() && !itsGroupListView->isCustom())
{
bool system;
if(Misc::root())
system=true;
else
{
switch(itsGroupListView->getType())
{
case CGroupListItem::ALL:
case CGroupListItem::UNCLASSIFIED:
switch(KMessageBox::questionYesNoCancel(this,
i18n("Do you wish to install the font(s) for personal use "
"(only available to you), or "
"system-wide (available to all users)?"),
i18n("Where to Install"), KGuiItem(i18n(KFI_KIO_FONTS_USER)),
KGuiItem(i18n(KFI_KIO_FONTS_SYS))))
{
case KMessageBox::Yes:
system=false;
break;
case KMessageBox::No:
system=true;
break;
default:
case KMessageBox::Cancel:
return;
}
break;
case CGroupListItem::PERSONAL:
system=false;
break;
case CGroupListItem::SYSTEM:
system=true;
break;
default:
return;
}
}
QSet copy;
QSet::ConstIterator it,
end(src.end());
//
// Check if font has any associated AFM or PFM file...
itsStatusLabel->setText(i18n("Looking for any associated files..."));
if(!itsProgress)
{
itsProgress = new QProgressDialog(this);
itsProgress->setWindowTitle(i18n("Scanning Files..."));
itsProgress->setLabelText(i18n("Looking for additional files to install..."));
itsProgress->setModal(true);
itsProgress->setAutoReset(true);
itsProgress->setAutoClose(true);
}
itsProgress->setCancelButton(nullptr);
itsProgress->setMinimumDuration(500);
itsProgress->setRange(0, src.size());
itsProgress->setValue(0);
int steps=src.count()<200 ? 1 : src.count()/10;
for(it=src.begin(); it!=end; ++it)
{
QList associatedUrls;
itsProgress->setLabelText(i18n("Looking for files associated with %1", (*it).url()));
itsProgress->setValue(itsProgress->value()+1);
if(1==steps || 0==(itsProgress->value()%steps))
{
bool dialogVisible(itsProgress->isVisible());
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
if(dialogVisible && !itsProgress->isVisible()) // User closed dialog! re-open!!!
itsProgress->show();
}
CJobRunner::getAssociatedUrls(*it, associatedUrls, false, this);
copy.insert(*it);
QList::Iterator aIt(associatedUrls.begin()),
aEnd(associatedUrls.end());
for(; aIt!=aEnd; ++aIt)
copy.insert(*aIt);
}
itsProgress->close();
CJobRunner::ItemList installUrls;
end=copy.end();
for(it=copy.begin(); it!=end; ++it)
installUrls.append(*it);
itsStatusLabel->setText(i18n("Installing font(s)..."));
doCmd(CJobRunner::CMD_INSTALL, installUrls, system);
}
}
void CKCmFontInst::removeDeletedFontsFromGroups()
{
if(!itsDeletedFonts.isEmpty())
{
QSet::Iterator it(itsDeletedFonts.begin()),
end(itsDeletedFonts.end());
for(; it!=end; ++it)
if(!itsFontList->hasFamily(*it))
itsGroupList->removeFamily(*it);
itsDeletedFonts.clear();
}
}
void CKCmFontInst::selectGroup(CGroupListItem::EType grp)
{
QModelIndex current(itsGroupListView->currentIndex());
if(current.isValid())
{
CGroupListItem *grpItem=static_cast(current.internalPointer());
if(grpItem && grp==grpItem->type())
return;
else
itsGroupListView->selectionModel()->select(current,
QItemSelectionModel::Deselect);
}
QModelIndex idx(itsGroupList->index(grp));
itsGroupListView->selectionModel()->select(idx, QItemSelectionModel::Select);
itsGroupListView->setCurrentIndex(idx);
groupSelected(idx);
itsFontListView->refreshFilter();
setStatusBar();
}
void CKCmFontInst::toggleGroup(bool enable)
{
QModelIndex idx(itsGroupListView->currentIndex());
if(idx.isValid())
{
CGroupListItem *grp=static_cast(idx.internalPointer());
if(grp)
toggleFonts(enable, grp->name());
}
}
void CKCmFontInst::toggleFonts(bool enable, const QString &grp)
{
CJobRunner::ItemList urls;
QStringList fonts;
itsFontListView->getFonts(urls, fonts, nullptr, grp.isEmpty(), !enable, enable);
if(urls.isEmpty())
KMessageBox::information(this,
enable ? i18n("You did not select anything to enable.")
: i18n("You did not select anything to disable."),
enable ? i18n("Nothing to Enable") : i18n("Nothing to Disable"));
else
toggleFonts(urls, fonts, enable, grp);
}
void CKCmFontInst::toggleFonts(CJobRunner::ItemList &urls, const QStringList &fonts, bool enable,
const QString &grp)
{
bool doIt=false;
switch(fonts.count())
{
case 0:
break;
case 1:
- doIt = KMessageBox::Yes==KMessageBox::warningYesNo(this,
+ doIt = KMessageBox::Continue==KMessageBox::warningContinueCancel(this,
grp.isEmpty()
? enable ? i18n("Do you really want to "
"enable
\'%1\'?
", fonts.first())
: i18n("Do you really want to "
"disable
\'%1\'?
", fonts.first())
: enable ? i18n("Do you really want to "
"enable
\'%1\', "
"contained within group \'%2\'?
",
fonts.first(), grp)
: i18n("Do you really want to "
"disable
\'%1\', "
"contained within group \'%2\'?
",
fonts.first(), grp),
enable ? i18n("Enable Font") : i18n("Disable Font"),
enable ? KGuiItem(i18n("Enable"), "enablefont", i18n("Enable Font"))
: KGuiItem(i18n("Disable"), "disablefont", i18n("Disable Font")));
break;
default:
- doIt = KMessageBox::Yes==KMessageBox::warningYesNoList(this,
+ doIt = KMessageBox::Continue==KMessageBox::warningContinueCancelList(this,
grp.isEmpty()
? enable ? i18np("Do you really want to enable this font?",
"Do you really want to enable these %1 fonts?",
urls.count())
: i18np("Do you really want to disable this font?",
"Do you really want to disable these %1 fonts?",
urls.count())
: enable ? i18np("Do you really want to enable this font "
"contained within group \'%2\'?
",
"Do you really want to enable these %1 fonts "
"contained within group \'%2\'?
",
urls.count(), grp)
: i18np("Do you really want to disable this font "
"contained within group \'%2\'?
",
"Do you really want to disable these %1 fonts "
"contained within group \'%2\'?
",
urls.count(), grp),
fonts,
enable ? i18n("Enable Fonts") : i18n("Disable Fonts"),
enable ? KGuiItem(i18n("Enable"), "enablefont", i18n("Enable Fonts"))
: KGuiItem(i18n("Disable"), "disablefont", i18n("Disable Fonts")));
}
if(doIt)
{
if(enable)
itsStatusLabel->setText(i18n("Enabling font(s)..."));
else
itsStatusLabel->setText(i18n("Disabling font(s)..."));
doCmd(enable ? CJobRunner::CMD_ENABLE : CJobRunner::CMD_DISABLE, urls);
}
}
void CKCmFontInst::selectMainGroup()
{
selectGroup(/*Misc::root()
? */CGroupListItem::ALL/* : CGroupListItem::PERSONAL*/);
}
void CKCmFontInst::doCmd(CJobRunner::ECommand cmd, const CJobRunner::ItemList &urls, bool system)
{
itsFontList->setSlowUpdates(true);
CJobRunner runner(this);
connect(&runner, SIGNAL(configuring()), itsFontList, SLOT(unsetSlowUpdates()));
runner.exec(cmd, urls, system);
itsFontList->setSlowUpdates(false);
refreshFontList();
if(CJobRunner::CMD_DELETE==cmd)
itsFontListView->clearSelection();
CFcEngine::setDirty();
setStatusBar();
delete itsTempDir;
itsTempDir=nullptr;
itsFontListView->repaint();
removeDeletedFontsFromGroups();
}
}
#include "KCmFontInst.moc"