2 * KFontInst - KDE Font Installer
4 * Copyright 2003-2007 Craig Drummond <craig@kde.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
25 #include <KDE/KGlobal>
26 #include <KDE/KStandardDirs>
27 #include <KDE/KLocale>
28 #include <KDE/KMimeType>
30 #include <KDE/KIconLoader>
32 #include <KDE/KMessageBox>
33 #include <QtCore/QProcess>
34 #include <QtGui/QFont>
35 #include <QtCore/QMap>
36 #include <QtCore/QFile>
37 #include <QtGui/QImage>
38 #include <QtCore/QDir>
39 #include <QtCore/QFileInfo>
40 #include <QtGui/QPixmap>
41 #include <QtGui/QDropEvent>
42 #include <QtCore/QDateTime>
43 #include <QtGui/QX11Info>
44 #include <QtGui/QHeaderView>
45 #include <QtGui/QStyledItemDelegate>
46 #include <QtGui/QPainter>
47 #include <QtGui/QMenu>
48 #include <QtCore/QTimer>
49 #include <QtGui/QApplication>
54 #include "KfiConstants.h"
55 #include "GroupList.h"
56 #include <config-workspace.h>
58 //#define KFI_FONTLIST_DEBUG
60 // #define to control whether generated inline preview thumbs should be
62 #define KFI_SAVE_PIXMAPS
64 #ifdef KFI_FONTLIST_DEBUG
71 int CFontList::theirPreviewSize
=CFontList::constDefaultPreviewSize
;
73 static void decompose(const QString
&name
, QString
&family
, QString
&style
)
75 int commaPos
=name
.lastIndexOf(',');
77 family
=-1==commaPos
? name
: name
.left(commaPos
);
78 style
=-1==commaPos
? KFI_WEIGHT_REGULAR
: name
.mid(commaPos
+2);
81 static void addFont(CFontItem
*font
, CJobRunner::ItemList
&urls
, QStringList
&fontNames
,
82 QSet
<Misc::TFont
> *fonts
, bool *hasSys
, QSet
<CFontItem
*> &usedFonts
,
83 bool getEnabled
, bool getDisabled
)
85 if(!usedFonts
.contains(font
) &&
86 ( (getEnabled
&& font
->isEnabled()) ||
87 (getDisabled
&& !font
->isEnabled()) ) )
89 urls
.append(CJobRunner::Item(font
->url(), font
->name()));
90 fontNames
.append(font
->name());
91 usedFonts
.insert(font
);
93 fonts
->insert(Misc::TFont(font
->family(), font
->styleInfo()));
94 if(hasSys
&& !(*hasSys
) && font
->isSystem())
99 static QString
getName(const KFileItem
&item
)
101 return !item
.isNull()
102 ? item
.entry().stringValue(KIO::UDSEntry::UDS_NAME
)
106 static QString
replaceEnvVar(const QString
&text
)
109 int endPos(text
.indexOf('/'));
112 endPos
=text
.length()-1;
118 QString
envVar(text
.mid(1, endPos
));
120 const char *val
=getenv(envVar
.toLatin1().constData());
123 mod
=Misc::fileSyntax(QFile::decodeName(val
)+mod
.mid(endPos
+1));
130 // Convert from list such as:
140 // Arial (Regular, Bold)
142 // Times (Regular, Italic)
143 QStringList
CFontList::compact(const QStringList
&fonts
)
147 QStringList::ConstIterator
it(fonts
.begin()),
149 QStringList compacted
;
150 QSet
<QString
> usedStyles
;
157 decompose(*it
, family
, style
);
159 if(family
!=lastFamily
)
165 compacted
.append(entry
);
167 entry
=QString(family
+" (");
170 if(!usedStyles
.contains(style
))
173 if(entry
.length() && '('!=entry
[entry
.length()-1])
176 usedStyles
.insert(style
);
183 compacted
.append(entry
);
193 CPreviewCache(CFcEngine
*eng
);
194 #ifdef KFI_SAVE_PIXMAPS
195 ~CPreviewCache() { clearOld(); }
198 static QString
thumbKey(const QString
&family
, quint32 style
, int height
, const QColor
&col
);
199 QPixmap
* getPixmap(const QString
&family
, const QString
&name
, const QString
&fileName
,
200 int height
, quint32 stlye
, bool selected
, bool force
=false);
201 #ifdef KFI_SAVE_PIXMAPS
208 CFcEngine
*itsFcEngine
;
209 QMap
<QString
, QPixmap
> itsMap
;
210 #ifdef KFI_SAVE_PIXMAPS
215 CPreviewCache::CPreviewCache(CFcEngine
*eng
)
217 #ifdef KFI_SAVE_PIXMAPS
218 , itsPath(KGlobal::dirs()->saveLocation("cache", "fontpreview"))
223 static QString
replaceChars(const QString
&in
)
227 rv
=rv
.replace('/', '_');
232 QString
capitaliseFoundry(const QString
&foundry
)
234 QString
f(foundry
.toLower());
236 if(f
==QString::fromLatin1("ibm"))
237 return QString::fromLatin1("IBM");
238 else if(f
==QString::fromLatin1("urw"))
239 return QString::fromLatin1("URW");
240 else if(f
==QString::fromLatin1("itc"))
241 return QString::fromLatin1("ITC");
242 else if(f
==QString::fromLatin1("nec"))
243 return QString::fromLatin1("NEC");
244 else if(f
==QString::fromLatin1("b&h"))
245 return QString::fromLatin1("B&H");
257 isSpace
=ch
->isSpace();
266 static void toggle(QString
&file
, bool enable
)
268 QString
newFile(enable
269 ? Misc::getDir(file
)+Misc::unhide(Misc::getFile(file
))
270 : Misc::getDir(file
)+QChar('.')+Misc::unhide(Misc::getFile(file
)));
272 if(!Misc::fExists(file
) && Misc::fExists(newFile
))
276 #ifdef KFI_SAVE_PIXMAPS
277 static void setTimeStamp(const QString
&f
)
279 QByteArray
fC(QFile::encodeName(f
));
280 KDE_struct_stat fStat
;
282 if(0==KDE_lstat(fC
, &fStat
))
284 struct utimbuf times
;
286 times
.actime
=times
.modtime
=time(NULL
);
291 QString
CPreviewCache::thumbKey(const QString
&name
, quint32 style
, int height
, const QColor
&col
)
293 return replaceChars(name
)+
294 QString().sprintf("-%06lX%02d%02X%02X%02X.png", (long unsigned int)style
, height
,
295 col
.red(), col
.green(), col
.blue());
298 QPixmap
* CPreviewCache::getPixmap(const QString
&family
, const QString
&name
, const QString
&fileName
,
299 int height
, quint32 style
, bool selected
, bool force
)
301 #ifdef KFI_SAVE_PIXMAPS
302 static const char *constFileType
="PNG";
305 QColor
col(QApplication::palette().color(selected
? QPalette::HighlightedText
: QPalette::Text
));
306 QString
thumbName(thumbKey(family
, style
, height
, col
));
308 if(!force
&& !itsMap
[thumbName
].isNull())
309 return &(itsMap
[thumbName
]);
311 #ifdef KFI_SAVE_PIXMAPS
312 QString
thumbFile(itsPath
+thumbName
);
314 if(!force
&& itsMap
[thumbName
].load(thumbFile
, constFileType
))
315 return &(itsMap
[thumbName
]);
318 itsMap
[thumbName
]=QPixmap();
320 if(itsFcEngine
->drawPreview(fileName
.isEmpty() ? name
: fileName
, itsMap
[thumbName
], col
,
321 height
, style
)) // CPD:TODO face???
323 #ifdef KFI_SAVE_PIXMAPS
324 QFile
pngFile(thumbFile
);
326 if(pngFile
.open(QIODevice::WriteOnly
))
329 QImage thumb
=itsMap
[thumbName
].toImage();
331 #ifdef KFI_SAVE_PIXMAPS
332 thumb
.save(&pngFile
, constFileType
);
335 itsMap
[thumbName
]=QPixmap::fromImage(thumb
);
336 return &(itsMap
[thumbName
]);
337 #ifdef KFI_SAVE_PIXMAPS
342 itsMap
[thumbName
]=QPixmap(1, 1);
347 #ifdef KFI_SAVE_PIXMAPS
348 void CPreviewCache::clearOld()
351 // Remove any files that have not been accessed for constMaxAge days.
352 // ...this should be OK, as this function is called after the font list is completed,
353 // so any existing fonts will already have accessed their thumbnail.
355 static const int constMaxAge
= 7;
361 d
.setFilter(QDir::Files
);
363 QFileInfoList
list(d
.entryInfoList());
364 QDateTime
current(QDateTime::currentDateTime());
366 for (int i
= 0; i
< list
.size(); ++i
)
368 QFileInfo
fileInfo(list
.at(i
));
369 int diff
=abs(current
.daysTo(fileInfo
.lastRead()));
371 if(diff
>constMaxAge
) // More than constMaxAge days ago, so remove
372 ::unlink(QFile::encodeName(fileInfo
.absoluteFilePath()));
378 void CPreviewCache::empty()
380 #ifdef KFI_SAVE_PIXMAPS
385 d
.setFilter(QDir::Files
);
387 QFileInfoList
list(d
.entryInfoList());
389 for (int i
= 0; i
< list
.size(); ++i
)
391 QFileInfo
fileInfo(list
.at(i
));
393 if(-1!=fileInfo
.fileName().lastIndexOf(".png"))
394 ::unlink(QFile::encodeName(fileInfo
.absoluteFilePath()));
401 static CPreviewCache
*theCache
=NULL
;
403 inline bool isSysFolder(const QString
§
)
405 return i18n(KFI_KIO_FONTS_SYS
)==sect
|| KFI_KIO_FONTS_SYS
==sect
;
408 CFontItem::CFontItem(CFontModelItem
*p
, const KFileItem
&item
, const QString
&style
)
412 const KIO::UDSEntry
&udsEntry(item
.entry());
414 itsPixmap
[0]=itsPixmap
[1]=0L;
416 itsName
=udsEntry
.stringValue(KIO::UDSEntry::UDS_NAME
);
417 itsFileName
=udsEntry
.stringValue((uint
)UDS_EXTRA_FILE_NAME
);
418 itsStyleInfo
=udsEntry
.numberValue((uint
)UDS_EXTRA_FC_STYLE
);
419 itsIndex
=Misc::getIntQueryVal(KUrl(udsEntry
.stringValue((uint
)KIO::UDSEntry::UDS_URL
)),
421 itsWritingSystems
=udsEntry
.numberValue((uint
)UDS_EXTRA_WRITING_SYSTEMS
);
422 itsMimeType
=item
.mimetype();
423 itsBitmap
="application/x-font-pcf"==itsMimeType
|| "application/x-font-bdf"==itsMimeType
;
427 setIsSystem(isSysFolder(url().path().section('/', 1, 1)));
429 QString files
=udsEntry
.stringValue((uint
)UDS_EXTRA_FILE_LIST
);
432 itsFiles
.fromString(files
);
434 itsFiles
.prepend(CDisabledFonts::TFile(itsFileName
, itsIndex
,
435 udsEntry
.stringValue((uint
)UDS_EXTRA_FOUNDRY
)));
438 void CFontItem::touchThumbnail()
440 #ifdef KFI_SAVE_PIXMAPS
441 // Access thumbFile, if it exists, to prevent its removal from the cache
444 QColor
norm(QApplication::palette().color(QPalette::Text
)),
445 sel(QApplication::palette().color(QPalette::HighlightedText
));
447 setTimeStamp(CPreviewCache::thumbKey(family(), itsStyleInfo
, CFontList::previewSize(), norm
));
449 setTimeStamp(CPreviewCache::thumbKey(family(), itsStyleInfo
, CFontList::previewSize(), sel
));
454 void CFontItem::setUrl(const KUrl
&url
)
457 itsEnabled
=!Misc::isHidden(itsUrl
);
459 if(!itsFiles
.isEmpty()) // Then we changed state, so need to alter filename list...
461 toggle(itsFileName
, itsEnabled
);
463 CDisabledFonts::TFileList::Iterator
it(itsFiles
.begin()),
467 toggle((*it
).path
, itsEnabled
);
471 const QPixmap
* CFontItem::pixmap(bool selected
, bool force
)
473 int idx(selected
? 1 : 0);
476 (!itsPixmap
[idx
] || itsPixmap
[idx
]->isNull() || force
||
477 itsPixmap
[idx
]->height()!=CFontList::previewSize()))
478 itsPixmap
[idx
]=theCache
->getPixmap(family(), name(), isEnabled()
481 CFontList::previewSize(), itsStyleInfo
, selected
, force
);
483 return itsPixmap
[idx
];
486 CFamilyItem::CFamilyItem(CFontList
&p
, const QString
&n
)
487 : CFontModelItem(NULL
),
490 itsRealStatus(ENABLED
),
491 itsRegularFont(NULL
),
496 CFamilyItem::~CFamilyItem()
498 qDeleteAll(itsFonts
);
502 void CFamilyItem::touchThumbnail()
505 itsRegularFont
->touchThumbnail();
508 CFontItem
* CFamilyItem::findFont(const KFileItem
&i
)
510 QList
<CFontItem
*>::ConstIterator
fIt(itsFonts
.begin()),
511 fEnd(itsFonts
.end());
513 for(; fIt
!=fEnd
; ++fIt
)
514 if((*(*fIt
)).url()==i
.url())
520 void CFamilyItem::getFoundries(QSet
<QString
> &foundries
) const
522 QList
<CFontItem
*>::ConstIterator
it(itsFonts
.begin()),
527 CDisabledFonts::TFileList::ConstIterator
fIt((*it
)->files().begin()),
528 fEnd((*it
)->files().end());
530 for(; fIt
!=fEnd
; ++fIt
)
531 if(!(*fIt
).foundry
.isEmpty())
532 foundries
.insert(capitaliseFoundry((*fIt
).foundry
));
536 bool CFamilyItem::usable(const CFontItem
*font
, bool root
)
538 return (!font
->isHidden() || itsParent
.allowDisabled()) &&
540 (font
->isSystem() && itsParent
.allowSys()) ||
541 (!font
->isSystem() && itsParent
.allowUser()));
544 void CFamilyItem::addFont(CFontItem
*font
)
546 itsFonts
.append(font
);
548 updateRegularFont(font
);
551 void CFamilyItem::removeFont(CFontItem
*font
)
553 itsFonts
.removeAll(font
);
555 if(itsRegularFont
==font
)
558 updateRegularFont(NULL
);
563 void CFamilyItem::refresh()
567 updateRegularFont(NULL
);
571 bool CFamilyItem::updateStatus()
573 bool root(Misc::root());
574 QString
oldIcon(itsIcon
);
575 EStatus
oldStatus(itsStatus
);
576 QList
<CFontItem
*>::ConstIterator
it(itsFonts
.begin()),
578 int en(0), dis(0), allEn(0), allDis(0);
579 bool oldSys(isSystem()),
581 QStringList mimeTypes
;
585 if(usable(*it
, root
))
587 QString
mime((*it
)->mimetype());
589 if((*it
)->isEnabled())
593 if(!mimeTypes
.contains(mime
))
594 mimeTypes
.append(mime
);
596 sys
=(*it
)->isSystem();
600 if((*it
)->isEnabled())
614 itsRealStatus
=allEn
&& allDis
620 itsIcon
=1==mimeTypes
.count()
621 ? KMimeType::mimeType(mimeTypes
[0])->iconName()
622 : "application-x-font-ttf";
627 return itsStatus
!=oldStatus
|| itsIcon
!=oldIcon
|| isSystem()!=oldSys
;
630 bool CFamilyItem::updateRegularFont(CFontItem
*font
)
632 static const quint32 constRegular
=FC::createStyleVal(FC_WEIGHT_REGULAR
, KFI_FC_WIDTH_NORMAL
, FC_SLANT_ROMAN
);
634 CFontItem
*oldFont(itsRegularFont
);
635 bool root(Misc::root());
637 if(font
&& usable(font
, root
))
641 int regDiff
=abs((long)(itsRegularFont
->styleInfo()-constRegular
)),
642 fontDiff
=abs((long)(font
->styleInfo()-constRegular
));
650 else // This case happens when the regular font is deleted...
652 QList
<CFontItem
*>::ConstIterator
it(itsFonts
.begin()),
654 quint32 current
=0x0FFFFFFF;
657 if(usable(*it
, root
))
659 quint32 diff
=abs((long) ((*it
)->styleInfo()-constRegular
));
663 itsRegularFont
=(*it
);
669 return oldFont
!=itsRegularFont
;
672 CFontList::CFontList(CFcEngine
*eng
, QWidget
*parent
)
673 : QAbstractItemModel(parent
),
678 theCache
=new CPreviewCache(eng
);
681 int pixelSize((int)(((font
.pointSizeF()*QX11Info::appDpiY())/72.0)+0.5));
683 setPreviewSize(pixelSize
+12);
684 itsLister
=new CFontLister(this);
685 connect(itsLister
, SIGNAL(started()), SIGNAL(started()));
686 connect(itsLister
, SIGNAL(completed()), SLOT(listingCompleted()));
687 connect(itsLister
, SIGNAL(newItems(const KFileItemList
&)),
688 SLOT(newItems(const KFileItemList
&)));
689 connect(itsLister
, SIGNAL(deleteItems(const KFileItemList
&)),
690 SLOT(deleteItems(const KFileItemList
&)));
691 connect(itsLister
, SIGNAL(renameItems(const RenameList
&)),
692 SLOT(renameItems(const RenameList
&)));
693 connect(itsLister
, SIGNAL(percent(int)), SIGNAL(percent(int)));
694 connect(itsLister
, SIGNAL(message(QString
)), SIGNAL(status(QString
)));
697 CFontList::~CFontList()
703 qDeleteAll(itsFamilies
);
708 int CFontList::columnCount(const QModelIndex
&) const
713 QVariant
CFontList::data(const QModelIndex
&, int) const
718 Qt::ItemFlags
CFontList::flags(const QModelIndex
&index
) const
720 if (!index
.isValid())
721 return Qt::ItemIsEnabled
| Qt::ItemIsDropEnabled
;
722 return Qt::ItemIsEnabled
| Qt::ItemIsSelectable
| Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled
;
725 Qt::DropActions
CFontList::supportedDropActions() const
727 return Qt::CopyAction
| Qt::MoveAction
;
730 QMimeData
* CFontList::mimeData(const QModelIndexList
&indexes
) const
732 QMimeData
*mimeData
= new QMimeData();
733 QByteArray encodedData
;
734 QModelIndexList::ConstIterator
it(indexes
.begin()),
736 QSet
<QString
> families
;
737 QDataStream
ds(&encodedData
, QIODevice::WriteOnly
);
741 if((static_cast<CFontModelItem
*>((*it
).internalPointer()))->isFont())
743 CFontItem
*font
=static_cast<CFontItem
*>((*it
).internalPointer());
745 families
.insert(font
->family());
749 CFamilyItem
*fam
=static_cast<CFamilyItem
*>((*it
).internalPointer());
751 families
.insert(fam
->name());
755 mimeData
->setData(KFI_FONT_DRAG_MIME
, encodedData
);
759 QStringList
CFontList::mimeTypes() const
763 types
<< "text/uri-list";
767 QVariant
CFontList::headerData(int section
, Qt::Orientation orientation
,
770 if (orientation
== Qt::Horizontal
)
773 case Qt::DisplayRole
:
779 return i18n("Preview");
784 case Qt::DecorationRole
:
785 if(COL_STATUS
==section
)
786 return SmallIcon("fontstatus");
788 case Qt::TextAlignmentRole
:
789 return Qt::AlignLeft
;
790 case Qt::ToolTipRole
:
791 if(COL_STATUS
==section
)
792 return i18n("This column shows the status of the font family, and of the "
793 "individual font styles.");
795 case Qt::WhatsThisRole
:
804 QModelIndex
CFontList::index(int row
, int column
, const QModelIndex
&parent
) const
806 if(parent
.isValid()) // Then font...
808 CFamilyItem
*fam
=static_cast<CFamilyItem
*>(parent
.internalPointer());
810 if(row
<fam
->fonts().count())
811 return createIndex(row
, column
, fam
->fonts().at(row
));
814 if(row
<itsFamilies
.count())
815 return createIndex(row
, column
, itsFamilies
.at(row
));
817 return QModelIndex();
820 QModelIndex
CFontList::parent(const QModelIndex
&index
) const
823 return QModelIndex();
825 CFontModelItem
*mi
=static_cast<CFontModelItem
*>(index
.internalPointer());
828 return QModelIndex();
831 CFontItem
*font
=static_cast<CFontItem
*>(index
.internalPointer());
833 return createIndex(itsFamilies
.indexOf(((CFamilyItem
*)font
->parent())), 0, font
->parent());
837 int CFontList::rowCount(const QModelIndex
&parent
) const
841 CFontModelItem
*mi
=static_cast<CFontModelItem
*>(parent
.internalPointer());
846 CFamilyItem
*fam
=static_cast<CFamilyItem
*>(parent
.internalPointer());
848 return fam
->fonts().count();
851 return itsFamilies
.count();
854 void CFontList::forceNewPreviews()
856 QList
<CFamilyItem
*>::ConstIterator
it(itsFamilies
.begin()),
857 end(itsFamilies
.end());
861 QList
<CFontItem
*>::ConstIterator
fit((*it
)->fonts().begin()),
862 fend((*it
)->fonts().end());
864 for(; fit
!=fend
; ++fit
)
865 (*fit
)->clearPixmap();
871 void CFontList::refresh(bool allowSys
, bool allowUser
)
873 itsAllowSys
=allowSys
;
874 itsAllowUser
=allowUser
;
875 QList
<CFamilyItem
*>::ConstIterator
it(itsFamilies
.begin()),
876 end(itsFamilies
.end());
882 void CFontList::setAllowDisabled(bool on
)
885 QList
<CFamilyItem
*>::ConstIterator
it(itsFamilies
.begin()),
886 end(itsFamilies
.end());
892 void CFontList::getFamilyStats(QSet
<QString
> &enabled
, QSet
<QString
> &disabled
, QSet
<QString
> &partial
)
894 QList
<CFamilyItem
*>::ConstIterator
it(itsFamilies
.begin()),
895 end(itsFamilies
.end());
899 switch((*it
)->realStatus())
901 case CFamilyItem::ENABLED
:
902 enabled
.insert((*it
)->name());
904 case CFamilyItem::PARTIAL
:
905 partial
.insert((*it
)->name());
907 case CFamilyItem::DISABLED
:
908 disabled
.insert((*it
)->name());
914 void CFontList::getFoundries(QSet
<QString
> &foundries
) const
916 QList
<CFamilyItem
*>::ConstIterator
it(itsFamilies
.begin()),
917 end(itsFamilies
.end());
920 (*it
)->getFoundries(foundries
);
923 QString
CFontList::whatsThis() const
925 return i18n("<p>This list shows your installed fonts. The fonts are grouped by family, and the"
926 " number in square brackets represents the number of styles in which the family is"
927 " available. e.g.</p>"
930 "<ul><li>Regular</li>"
932 "<li>Bold Italic</li>"
939 void CFontList::listingCompleted()
945 void CFontList::newItems(const KFileItemList
&items
)
947 emit
layoutAboutToBeChanged();
949 #ifdef KFI_FONTLIST_DEBUG
950 kDebug() << "************** " << items
.count();
952 // for(KFileItemList::const_iterator it(items.begin()), end(items.end()) ; it!=end ; ++it)
953 // kDebug() << " " << (int)(*it);
956 for(KFileItemList::const_iterator
it(items
.begin()), end(items
.end()) ; it
!=end
; ++it
)
959 emit
layoutChanged();
962 void CFontList::clearItems()
964 #ifdef KFI_FONTLIST_DEBUG
965 kDebug() << "**************";
968 beginRemoveRows(QModelIndex(), 0, itsFamilies
.count());
970 qDeleteAll(itsFamilies
);
975 void CFontList::renameItems(const RenameList
&items
)
977 emit
layoutAboutToBeChanged();
979 #ifdef KFI_FONTLIST_DEBUG
980 kDebug() << "************** " << items
.count();
982 for(RenameList::const_iterator
it(items
.begin()), end(items
.end()) ; it
!=end
; ++it
)
983 kDebug() << " " << (*it
).from
.prettyUrl();
986 QSet
<CFamilyItem
*> families
;
988 for(RenameList::const_iterator
it(items
.begin()), end(items
.end()) ; it
!=end
; ++it
)
990 CFontItem
*font
=findFont((*it
).from
);
994 font
->setUrl((*it
).to
);
995 itsFonts
.insert((*it
).to
, font
);
996 itsFonts
.erase(itsFonts
.find((*it
).from
));
997 #ifdef KFI_FONTLIST_DEBUG
998 kDebug() << " Found font, status now:" << font
->isEnabled()
999 << " from:" << (*it
).from
.prettyUrl()
1000 << " to:" << (*it
).to
.prettyUrl();
1002 families
.insert(static_cast<CFamilyItem
*>(font
->parent()));
1004 #ifdef KFI_FONTLIST_DEBUG
1006 kDebug() << " Could not locate font :-( " << (*it
).from
.prettyUrl();
1010 QSet
<CFamilyItem
*>::ConstIterator
it(families
.begin()),
1011 end(families
.end());
1013 for(; it
!=end
; ++it
)
1014 (*it
)->updateStatus();
1016 emit
layoutChanged();
1019 void CFontList::deleteItems(const KFileItemList
&items
)
1021 emit
layoutAboutToBeChanged();
1023 #ifdef KFI_FONTLIST_DEBUG
1024 kDebug() << "************** " << items
.count();
1027 KFileItemList::ConstIterator
it(items
.begin()),
1030 for(; it
!=end
; ++it
)
1032 CFontItem
*font
=findFont((*it
).url());
1036 CFamilyItem
*fam
=static_cast<CFamilyItem
*>(font
->parent());
1038 if(1==fam
->fonts().count())
1039 itsFamilies
.removeAll(fam
);
1041 fam
->removeFont(font
);
1042 itsFonts
.remove((*it
).url());
1046 emit
layoutChanged();
1049 void CFontList::addItem(const KFileItem
&item
)
1051 CFontItem
*font
=findFont(item
.url());
1053 #ifdef KFI_FONTLIST_DEBUG
1054 kDebug() << "************** " << item
.url();
1061 decompose(getName(item
), family
, style
);
1063 CFamilyItem
*fam
=findFamily(family
, true);
1067 font
=new CFontItem(fam
, item
, style
);
1070 itsFonts
.insert(item
.url(), font
);
1072 #ifdef KFI_FONTLIST_DEBUG
1074 kDebug() << " Could not locate family!";
1077 #ifdef KFI_FONTLIST_DEBUG
1079 kDebug() << " Font already exists!";
1083 CFamilyItem
* CFontList::findFamily(const QString
&familyName
, bool create
)
1085 CFamilyItem
*fam
=NULL
;
1086 QList
<CFamilyItem
*>::ConstIterator
it(itsFamilies
.begin()),
1087 end(itsFamilies
.end());
1089 for(; it
!=end
&& !fam
; ++it
)
1090 if((*it
)->name()==familyName
)
1095 fam
=new CFamilyItem(*this, familyName
);
1096 itsFamilies
.append(fam
);
1102 CFontItem
* CFontList::findFont(const KUrl
&url
)
1104 return itsFonts
.contains(url
)
1109 void CFontList::touchThumbnails()
1111 #ifdef KFI_SAVE_PIXMAPS
1112 QList
<CFamilyItem
*>::ConstIterator
it(itsFamilies
.begin()),
1113 end(itsFamilies
.end());
1115 for(; it
!=end
; ++it
)
1116 (*it
)->touchThumbnail();
1120 inline bool matchString(const QString
&str
, const QString
&pattern
)
1122 return pattern
.isEmpty() || -1!=str
.indexOf(pattern
, 0, Qt::CaseInsensitive
);
1125 CFontListSortFilterProxy::CFontListSortFilterProxy(QObject
*parent
, QAbstractItemModel
*model
)
1126 : QSortFilterProxyModel(parent
),
1129 itsFilterCriteria(CFontFilter::CRIT_FAMILY
),
1133 setSourceModel(model
);
1134 setSortCaseSensitivity(Qt::CaseInsensitive
);
1135 setFilterKeyColumn(0);
1136 setDynamicSortFilter(false);
1137 itsTimer
=new QTimer(this);
1138 connect(itsTimer
, SIGNAL(timeout()), SLOT(timeout()));
1139 itsTimer
->setSingleShot(true);
1142 QVariant
CFontListSortFilterProxy::data(const QModelIndex
&idx
, int role
) const
1147 static const int constMaxFiles
=20;
1149 QModelIndex
index(mapToSource(idx
));
1150 CFontModelItem
*mi
=static_cast<CFontModelItem
*>(index
.internalPointer());
1154 case Qt::ToolTipRole
:
1155 if(itsMgtMode
&& (CFontFilter::CRIT_FILENAME
==itsFilterCriteria
|| CFontFilter::CRIT_LOCATION
==itsFilterCriteria
||
1156 CFontFilter::CRIT_FONTCONFIG
==itsFilterCriteria
))
1159 CFamilyItem
*fam
=static_cast<CFamilyItem
*>(index
.internalPointer());
1160 QList
<CFontItem
*>::ConstIterator
it(fam
->fonts().begin()),
1161 end(fam
->fonts().end());
1162 CDisabledFonts::TFileList allFiles
;
1163 QString
tip("<b>"+fam
->name()+"</b>");
1165 bool markMatch(CFontFilter::CRIT_FONTCONFIG
==itsFilterCriteria
);
1166 tip
+="<p style='white-space:pre'><table>";
1168 for(; it
!=end
; ++it
)
1170 allFiles
+=(*it
)->files();
1171 size
+=(*it
)->size();
1175 CDisabledFonts::TFileList::ConstIterator
fit(allFiles
.begin()),
1176 fend(allFiles
.end());
1178 for(int i
=0; fit
!=fend
&& i
<constMaxFiles
; ++fit
, ++i
)
1179 if(markMatch
&& itsFcQuery
&& (*fit
)==itsFcQuery
->file())
1180 tip
+="<tr><td><b>"+Misc::contractHome(*fit
)+"</b></td></tr>";
1182 tip
+="<tr><td>"+Misc::contractHome(*fit
)+"</td></tr>";
1183 if(allFiles
.count()>constMaxFiles
)
1184 tip
+="<tr><td><i>"+i18n("...plus %1 more", allFiles
.count()-constMaxFiles
)+"</td></tr>";
1186 tip
+="</table></p>";
1191 CFontItem
*font
=static_cast<CFontItem
*>(index
.internalPointer());
1192 QString
tip("<b>"+font
->name()+"</b>");
1193 const CDisabledFonts::TFileList
&files(font
->files());
1194 bool markMatch(CFontFilter::CRIT_FONTCONFIG
==itsFilterCriteria
);
1196 tip
+="<p style='white-space:pre'><table>";
1199 CDisabledFonts::TFileList::ConstIterator
fit(files
.begin()),
1202 for(int i
=0; fit
!=fend
&& i
<constMaxFiles
; ++fit
, ++i
)
1203 if(markMatch
&& itsFcQuery
&& (*fit
)==itsFcQuery
->file())
1204 tip
+="<tr><td><b>"+Misc::contractHome(*fit
)+"</b></td></tr>";
1206 tip
+="<tr><td>"+Misc::contractHome(*fit
)+"</td></tr>";
1207 if(files
.count()>constMaxFiles
)
1208 tip
+="<tr><td><i>"+i18n("...plus %1 more", files
.count()-constMaxFiles
)+"</td></tr></li>";
1210 tip
+="</table></p>";
1215 if(COL_FONT
==index
.column())
1217 bool sys(mi
->isSystem()),
1218 disabled( (mi
->isFont() && !(static_cast<CFontItem
*>(index
.internalPointer()))->isEnabled()) ||
1220 CFamilyItem::DISABLED
==(static_cast<CFamilyItem
*>(index
.internalPointer()))->status()));
1224 font
.setItalic(disabled
);
1230 case Qt::DisplayRole
:
1231 if(COL_FONT
==index
.column())
1234 CFamilyItem
*fam
=static_cast<CFamilyItem
*>(index
.internalPointer());
1236 return i18n("%1 [%2]", fam
->name(), fam
->fontCount());
1239 return (static_cast<CFontItem
*>(index
.internalPointer()))->style();
1241 case Qt::DecorationRole
:
1244 CFamilyItem
*fam
=static_cast<CFamilyItem
*>(index
.internalPointer());
1246 switch(index
.column())
1249 return SmallIcon(fam
->icon(), 0,
1250 CFamilyItem::ENABLED
==fam
->status()
1251 ? KIconLoader::DefaultState
1252 : KIconLoader::DisabledState
);
1255 switch(fam
->status())
1257 case CFamilyItem::PARTIAL
:
1258 return SmallIcon("dialog-ok", 0, KIconLoader::DisabledState
);
1259 case CFamilyItem::ENABLED
:
1260 return SmallIcon("dialog-ok");
1261 case CFamilyItem::DISABLED
:
1262 return SmallIcon("dialog-cancel");
1270 if(COL_STATUS
==index
.column())
1271 return SmallIcon( (static_cast<CFontItem
*>(index
.internalPointer()))->isEnabled()
1272 ? "dialog-ok" : "dialog-cancel", 10);
1279 bool CFontListSortFilterProxy::acceptFont(CFontItem
*fnt
, bool checkFontText
) const
1281 if((fnt
->isBitmap() && !itsMgtMode
) ||
1282 (fnt
->isHidden() && !itsMgtMode
))
1285 if(itsGroup
&& (CGroupListItem::ALL
!=itsGroup
->type() || (!filterText().isEmpty() && checkFontText
)))
1287 bool fontMatch(!checkFontText
);
1290 switch(itsFilterCriteria
)
1292 case CFontFilter::CRIT_FONTCONFIG
:
1293 fontMatch
=itsFcQuery
1294 ? fnt
->name()==itsFcQuery
->font() // || fnt->files().contains(itsFcQuery->file())
1297 case CFontFilter::CRIT_STYLE
:
1298 fontMatch
=matchString(fnt
->style(), itsFilterText
);
1300 case CFontFilter::CRIT_FOUNDRY
:
1302 CDisabledFonts::TFileList::ConstIterator
it(fnt
->files().begin()),
1303 end(fnt
->files().end());
1305 for(; it
!=end
&& !fontMatch
; ++it
)
1306 fontMatch
=0==(*it
).foundry
.compare(itsFilterText
, Qt::CaseInsensitive
);
1309 case CFontFilter::CRIT_FILENAME
:
1311 CDisabledFonts::TFileList::ConstIterator
it(fnt
->files().begin()),
1312 end(fnt
->files().end());
1314 for(; it
!=end
&& !fontMatch
; ++it
)
1316 QString
file(Misc::getFile(*it
));
1317 int pos(Misc::isHidden(file
) ? 1 : 0);
1319 if(pos
==file
.indexOf(itsFilterText
, pos
, Qt::CaseInsensitive
))
1324 case CFontFilter::CRIT_LOCATION
:
1326 CDisabledFonts::TFileList::ConstIterator
it(fnt
->files().begin()),
1327 end(fnt
->files().end());
1329 for(; it
!=end
&& !fontMatch
; ++it
)
1330 if(0==Misc::getDir(*it
).indexOf(itsFilterText
, 0, Qt::CaseInsensitive
))
1334 case CFontFilter::CRIT_WS
:
1335 fontMatch
=fnt
->writingSystems()&itsFilterWs
;
1341 return fontMatch
&& itsGroup
->hasFont(fnt
);
1347 bool CFontListSortFilterProxy::acceptFamily(CFamilyItem
*fam
) const
1349 if(CFamilyItem::DISABLED
==fam
->status() && !itsMgtMode
)
1352 QList
<CFontItem
*>::ConstIterator
it(fam
->fonts().begin()),
1353 end(fam
->fonts().end());
1354 bool familyMatch(CFontFilter::CRIT_FAMILY
==itsFilterCriteria
&&
1355 matchString(fam
->name(), itsFilterText
));
1357 for(; it
!=end
; ++it
)
1358 if(acceptFont(*it
, !familyMatch
))
1363 bool CFontListSortFilterProxy::filterAcceptsRow(int sourceRow
, const QModelIndex
&sourceParent
) const
1365 QModelIndex
index(sourceModel()->index(sourceRow
, 0, sourceParent
));
1369 CFontModelItem
*mi
=static_cast<CFontModelItem
*>(index
.internalPointer());
1373 CFontItem
*font
=static_cast<CFontItem
*>(index
.internalPointer());
1375 return acceptFont(font
, !(CFontFilter::CRIT_FAMILY
==itsFilterCriteria
&&
1376 matchString(font
->family(), itsFilterText
)));
1379 return acceptFamily(static_cast<CFamilyItem
*>(index
.internalPointer()));
1385 bool CFontListSortFilterProxy::lessThan(const QModelIndex
&left
, const QModelIndex
&right
) const
1387 if(left
.isValid() && right
.isValid())
1389 CFontModelItem
*lmi
=static_cast<CFontModelItem
*>(left
.internalPointer()),
1390 *rmi
=static_cast<CFontModelItem
*>(right
.internalPointer());
1392 if(lmi
->isFont()<rmi
->isFont())
1397 CFontItem
*lfi
=static_cast<CFontItem
*>(left
.internalPointer()),
1398 *rfi
=static_cast<CFontItem
*>(right
.internalPointer());
1400 if(COL_STATUS
==filterKeyColumn())
1402 if(lfi
->isEnabled()<rfi
->isEnabled() ||
1403 (lfi
->isEnabled()==rfi
->isEnabled() &&
1404 lfi
->styleInfo()<rfi
->styleInfo()))
1408 if(lfi
->styleInfo()<rfi
->styleInfo())
1413 CFamilyItem
*lfi
=static_cast<CFamilyItem
*>(left
.internalPointer()),
1414 *rfi
=static_cast<CFamilyItem
*>(right
.internalPointer());
1416 if(COL_STATUS
==filterKeyColumn())
1418 if(lfi
->status()<rfi
->status() ||
1419 (lfi
->status()==rfi
->status() && QString::localeAwareCompare(lfi
->name(), rfi
->name())<0))
1423 if(QString::localeAwareCompare(lfi
->name(), rfi
->name())<0)
1431 void CFontListSortFilterProxy::setFilterGroup(CGroupListItem
*grp
)
1435 // bool wasNull=!itsGroup;
1439 // if(!(wasNull && itsGroup && CGroupListItem::ALL==itsGroup->type()))
1444 void CFontListSortFilterProxy::setFilterText(const QString
&text
)
1446 if(text
!=itsFilterText
)
1449 // If we are filtering on file location, then expand ~ to /home/user, etc.
1450 if (CFontFilter::CRIT_LOCATION
==itsFilterCriteria
&& !text
.isEmpty() && ('~'==text
[0] || '$'==text
[0]))
1452 itsFilterText
=1==text
.length()
1454 : QString(text
).replace(0, 1, QDir::homePath());
1456 itsFilterText
=replaceEnvVar(text
);
1460 if(itsFilterText
.isEmpty())
1466 itsTimer
->start(CFontFilter::CRIT_FONTCONFIG
==itsFilterCriteria
? 750 : 400);
1470 void CFontListSortFilterProxy::setFilterCriteria(CFontFilter::ECriteria crit
, qulonglong ws
)
1472 if(crit
!=itsFilterCriteria
|| ws
!=itsFilterWs
)
1475 itsFilterCriteria
=crit
;
1476 if(CFontFilter::CRIT_LOCATION
==itsFilterCriteria
)
1477 setFilterText(itsFilterText
);
1483 void CFontListSortFilterProxy::setMgtMode(bool on
)
1492 void CFontListSortFilterProxy::timeout()
1494 if(CFontFilter::CRIT_FONTCONFIG
==itsFilterCriteria
)
1496 int commaPos
=itsFilterText
.indexOf(',');
1497 QString
query(itsFilterText
);
1501 QString
style(query
.mid(commaPos
+1));
1502 query
=query
.left(commaPos
);
1503 query
=query
.trimmed();
1505 style
=style
.trimmed();
1509 query
=query
.trimmed();
1513 itsFcQuery
=new CFcQuery(this);
1514 connect(itsFcQuery
, SIGNAL(finished()), SLOT(fcResults()));
1517 itsFcQuery
->run(query
);
1526 void CFontListSortFilterProxy::fcResults()
1528 if(CFontFilter::CRIT_FONTCONFIG
==itsFilterCriteria
)
1535 class CFontListViewDelegate
: public QStyledItemDelegate
1539 CFontListViewDelegate(QObject
*p
, QSortFilterProxyModel
*px
) : QStyledItemDelegate(p
), itsProxy(px
) { }
1540 virtual ~CFontListViewDelegate() { }
1542 void paint(QPainter
*painter
, const QStyleOptionViewItem
&option
, const QModelIndex
&idx
) const
1544 QStyledItemDelegate::paint(painter
, option
, idx
);
1546 QModelIndex
index(itsProxy
->mapToSource(idx
));
1548 if(index
.isValid() && (static_cast<CFontModelItem
*>(index
.internalPointer()))->isFamily() &&
1549 COL_PREVIEW
==index
.column())
1551 CFamilyItem
*fam
=static_cast<CFamilyItem
*>(index
.internalPointer());
1553 if(fam
->regularFont())
1555 const QPixmap
*pix
=fam
->regularFont()->pixmap(option
.state
&QStyle::State_Selected
);
1558 if(Qt::RightToLeft
==QApplication::layoutDirection())
1559 painter
->drawPixmap(option
.rect
.x()-(pix
->width()-option
.rect
.width()),
1560 option
.rect
.y(), *pix
);
1562 painter
->drawPixmap(option
.rect
.x(), option
.rect
.y(), *pix
);
1567 QSize
sizeHint(const QStyleOptionViewItem
&option
, const QModelIndex
&idx
) const
1569 QModelIndex
index(itsProxy
->mapToSource(idx
));
1571 return (index
.isValid() && (static_cast<CFontModelItem
*>(index
.internalPointer()))->isFamily())
1572 ? QSize(CFontList::previewSize(), CFontList::previewSize())
1573 : QStyledItemDelegate::sizeHint(option
, index
);
1578 QSortFilterProxyModel
*itsProxy
;
1581 #define COL_FONT_SIZE "FontNameColSize"
1583 CFontListView::CFontListView(QWidget
*parent
, CFontList
*model
)
1584 : QTreeView(parent
),
1585 itsProxy(new CFontListSortFilterProxy(this, model
)),
1587 itsAllowDrops(false)
1590 setItemDelegate(new CFontListViewDelegate(this, itsProxy
));
1592 resizeColumnToContents(COL_STATUS
);
1593 setSelectionMode(QAbstractItemView::ExtendedSelection
);
1594 setSelectionBehavior(QAbstractItemView::SelectRows
);
1595 setSortingEnabled(true);
1596 sortByColumn(COL_FONT
, Qt::AscendingOrder
);
1597 setAllColumnsShowFocus(true);
1598 setAlternatingRowColors(true);
1599 setAcceptDrops(true);
1600 setDropIndicatorShown(false);
1601 setDragEnabled(true);
1602 setDragDropMode(QAbstractItemView::DragDrop
);
1603 header()->setClickable(true);
1604 header()->setSortIndicatorShown(true);
1605 setColumnHidden(COL_STATUS
, true);
1606 connect(this, SIGNAL(collapsed(const QModelIndex
&)), SLOT(itemCollapsed(const QModelIndex
&)));
1607 connect(header(), SIGNAL(sectionClicked(int)), SLOT(setSortColumn(int)));
1608 connect(itsProxy
, SIGNAL(refresh()), SIGNAL(refresh()));
1610 setWhatsThis(model
->whatsThis());
1611 header()->setWhatsThis(whatsThis());
1612 itsStdMenu
=new QMenu(this);
1613 itsDeleteAct
=itsStdMenu
->addAction(KIcon("edit-delete"), i18n("Delete"),
1614 this, SIGNAL(del()));
1615 itsPrintAct
=itsStdMenu
->addAction(KIcon("document-print"), i18n("Print..."),
1616 this, SIGNAL(print()));
1617 itsViewAct
=itsStdMenu
->addAction(KIcon("kfontview"), i18n("Open in Font Viewer"),
1618 this, SLOT(view()));
1619 itsStdMenu
->addSeparator();
1620 QAction
*reloadAct
=itsStdMenu
->addAction(KIcon("view-refresh"), i18n("Reload"), this, SIGNAL(reload()));
1622 itsMgtMenu
=new QMenu(this);
1623 itsMgtMenu
->addAction(itsDeleteAct
);
1624 itsMgtMenu
->addSeparator();
1625 itsEnableAct
=itsMgtMenu
->addAction(KIcon("enablefont"), i18n("Enable"),
1626 this, SIGNAL(enable()));
1627 itsDisableAct
=itsMgtMenu
->addAction(KIcon("disablefont"), i18n("Disable"),
1628 this, SIGNAL(disable()));
1629 itsMgtMenu
->addSeparator();
1630 itsMgtMenu
->addAction(itsPrintAct
);
1631 itsMgtMenu
->addAction(itsViewAct
);
1632 itsMgtMenu
->addSeparator();
1633 itsMgtMenu
->addAction(reloadAct
);
1636 void CFontListView::readConfig(KConfigGroup
&cg
)
1638 setColumnWidth(COL_FONT
, cg
.readEntry(COL_FONT_SIZE
, 200));
1641 void CFontListView::writeConfig(KConfigGroup
&cg
)
1643 cg
.writeEntry(COL_FONT_SIZE
, columnWidth(COL_FONT
));
1646 void CFontListView::getFonts(CJobRunner::ItemList
&urls
, QStringList
&fontNames
, QSet
<Misc::TFont
> *fonts
,
1647 bool *hasSys
, bool selected
, bool getEnabled
, bool getDisabled
)
1649 QModelIndexList
selectedItems(selected
? selectedIndexes() : allIndexes());
1650 QSet
<CFontItem
*> usedFonts
;
1653 foreach(index
, selectedItems
)
1656 QModelIndex
realIndex(itsProxy
->mapToSource(index
));
1658 if(realIndex
.isValid())
1659 if((static_cast<CFontModelItem
*>(realIndex
.internalPointer()))->isFont())
1661 CFontItem
*font
=static_cast<CFontItem
*>(realIndex
.internalPointer());
1663 addFont(font
, urls
, fontNames
, fonts
, hasSys
, usedFonts
,
1664 getEnabled
, getDisabled
);
1668 CFamilyItem
*fam
=static_cast<CFamilyItem
*>(realIndex
.internalPointer());
1670 for(int ch
=0; ch
<fam
->fontCount(); ++ch
)
1672 QModelIndex
child(itsProxy
->mapToSource(index
.child(ch
, 0)));
1674 if(child
.isValid() &&
1675 (static_cast<CFontModelItem
*>(child
.internalPointer()))->isFont())
1677 CFontItem
*font
=static_cast<CFontItem
*>(child
.internalPointer());
1679 addFont(font
, urls
, fontNames
, fonts
, hasSys
, usedFonts
,
1680 getEnabled
, getDisabled
);
1686 fontNames
=CFontList::compact(fontNames
);
1689 void CFontListView::getPrintableFonts(QSet
<Misc::TFont
> &items
, bool selected
)
1691 QModelIndexList
selectedItems(selected
? selectedIndexes() : allIndexes());
1694 foreach(index
, selectedItems
)
1696 CFontItem
*font
=NULL
;
1698 if(index
.isValid() && 0==index
.column())
1700 QModelIndex
realIndex(itsProxy
->mapToSource(index
));
1702 if(realIndex
.isValid())
1703 if((static_cast<CFontModelItem
*>(realIndex
.internalPointer()))->isFont())
1704 font
=static_cast<CFontItem
*>(realIndex
.internalPointer());
1707 CFamilyItem
*fam
=static_cast<CFamilyItem
*>(realIndex
.internalPointer());
1708 font
=fam
->regularFont();
1712 if(font
&& Misc::printable(font
->mimetype()) && font
->isEnabled())
1713 items
.insert(Misc::TFont(font
->family(), font
->styleInfo()));
1717 void CFontListView::setFilterGroup(CGroupListItem
*grp
)
1719 CGroupListItem
*oldGrp(itsProxy
->filterGroup());
1721 itsProxy
->setFilterGroup(grp
);
1722 itsAllowDrops
=grp
&& !grp
->isCustom();
1726 bool refreshStats(false);
1732 // Check to see whether we have changed from listing all fonts,
1733 // listing just system or listing personal fonts.
1734 CGroupListItem::EType
aType(CGroupListItem::CUSTOM
==grp
->type() ||
1735 CGroupListItem::ALL
==grp
->type() ||
1736 CGroupListItem::UNCLASSIFIED
==grp
->type()
1737 ? CGroupListItem::CUSTOM
: grp
->type()),
1738 bType(CGroupListItem::CUSTOM
==oldGrp
->type() ||
1739 CGroupListItem::ALL
==oldGrp
->type() ||
1740 CGroupListItem::UNCLASSIFIED
==oldGrp
->type()
1741 ? CGroupListItem::CUSTOM
: oldGrp
->type());
1742 refreshStats
=aType
!=bType
;
1746 itsModel
->refresh(!grp
|| !grp
->isPersonal(),
1747 !grp
|| !grp
->isSystem());
1751 void CFontListView::refreshFilter()
1756 void CFontListView::filterText(const QString
&text
)
1758 itsProxy
->setFilterText(text
);
1761 void CFontListView::filterCriteria(int crit
, qulonglong ws
)
1763 itsProxy
->setFilterCriteria((CFontFilter::ECriteria
)crit
, ws
);
1766 void CFontListView::stats(int &enabled
, int &disabled
, int &partial
)
1768 enabled
=disabled
=partial
=0;
1770 for(int i
=0; i
<itsProxy
->rowCount(); ++i
)
1772 QModelIndex
idx(itsProxy
->index(i
, 0, QModelIndex()));
1777 QModelIndex
sourceIdx(itsProxy
->mapToSource(idx
));
1779 if(!sourceIdx
.isValid())
1782 if((static_cast<CFontModelItem
*>(sourceIdx
.internalPointer()))->isFamily())
1783 switch((static_cast<CFamilyItem
*>(sourceIdx
.internalPointer()))->status())
1785 case CFamilyItem::ENABLED
:
1788 case CFamilyItem::DISABLED
:
1791 case CFamilyItem::PARTIAL
:
1798 void CFontListView::selectedStatus(bool &enabled
, bool &disabled
)
1800 QModelIndexList
selected(selectedItems());
1803 enabled
=disabled
=false;
1805 foreach(index
, selected
)
1807 QModelIndex
realIndex(itsProxy
->mapToSource(index
));
1809 if(realIndex
.isValid())
1810 if((static_cast<CFontModelItem
*>(realIndex
.internalPointer()))->isFamily())
1811 switch((static_cast<CFamilyItem
*>(realIndex
.internalPointer()))->status())
1813 case CFamilyItem::ENABLED
:
1816 case CFamilyItem::DISABLED
:
1819 case CFamilyItem::PARTIAL
:
1825 if((static_cast<CFontItem
*>(realIndex
.internalPointer()))->isEnabled())
1829 if(enabled
&& disabled
)
1834 QModelIndexList
CFontListView::allFonts()
1837 int rowCount(itsProxy
->rowCount());
1839 for(int i
=0; i
<rowCount
; ++i
)
1841 QModelIndex
idx(itsProxy
->index(i
, 0, QModelIndex()));
1842 int childRowCount(itsProxy
->rowCount(idx
));
1844 for(int j
=0; j
<childRowCount
; ++j
)
1846 QModelIndex
child(itsProxy
->index(j
, 0, idx
));
1849 rv
.append(itsProxy
->mapToSource(child
));
1856 void CFontListView::setMgtMode(bool on
)
1858 if(on
!=itsProxy
->mgtMode())
1861 setDragDropMode(on
? QAbstractItemView::DragDrop
: QAbstractItemView::DropOnly
);
1862 setColumnHidden(COL_STATUS
, !on
);
1864 resizeColumnToContents(COL_STATUS
);
1866 itsModel
->setAllowDisabled(on
);
1867 itsProxy
->setMgtMode(on
);
1868 setMouseTracking(on
);
1872 void CFontListView::selectFirstFont()
1874 if(0==selectedItems().count())
1875 for(int i
=0; i
<NUM_COLS
; ++i
)
1877 QModelIndex
idx(itsProxy
->index(0, i
, QModelIndex()));
1880 selectionModel()->select(idx
, QItemSelectionModel::Select
);
1884 void CFontListView::setSortColumn(int col
)
1886 if(col
!=itsProxy
->filterKeyColumn())
1888 itsProxy
->setFilterKeyColumn(col
);
1893 void CFontListView::selectionChanged(const QItemSelection
&selected
,
1894 const QItemSelection
&deselected
)
1896 QAbstractItemView::selectionChanged(selected
, deselected
);
1899 // Go throgh current selection, and for any 'font' items that are selected,
1900 // ensure 'family' item is not...
1901 QModelIndexList
selectedItems(selectedIndexes()),
1904 QSet
<CFontModelItem
*> selectedFamilies
;
1908 foreach(index
, selectedItems
)
1911 QModelIndex
realIndex(itsProxy
->mapToSource(index
));
1913 if(realIndex
.isValid())
1914 if((static_cast<CFontModelItem
*>(realIndex
.internalPointer()))->isFont())
1916 CFontItem
*font
=static_cast<CFontItem
*>(realIndex
.internalPointer());
1918 if(font
->isEnabled())
1922 if(!selectedFamilies
.contains(font
->parent()))
1924 selectedFamilies
.insert(font
->parent());
1926 for(int i
=0; i
<NUM_COLS
; ++i
)
1927 deselectList
.append(itsProxy
->mapFromSource(
1928 itsModel
->createIndex(font
->parent()->rowNumber(),
1929 i
, font
->parent())));
1933 switch((static_cast<CFamilyItem
*>(realIndex
.internalPointer()))->status())
1935 case CFamilyItem::ENABLED
:
1938 case CFamilyItem::DISABLED
:
1941 case CFamilyItem::PARTIAL
:
1947 if(deselectList
.count())
1948 foreach(index
, deselectList
)
1949 selectionModel()->select(index
, QItemSelectionModel::Deselect
);
1951 emit
itemSelected(selectedItems
.count()
1952 ? itsProxy
->mapToSource(selectedItems
.last())
1953 : QModelIndex(), en
, dis
);
1956 void CFontListView::itemCollapsed(const QModelIndex
&idx
)
1960 QModelIndex
index(itsProxy
->mapToSource(idx
));
1962 if(index
.isValid() && (static_cast<CFontModelItem
*>(index
.internalPointer()))->isFamily())
1964 CFamilyItem
*fam
=static_cast<CFamilyItem
*>(index
.internalPointer());
1965 QList
<CFontItem
*>::ConstIterator
it(fam
->fonts().begin()),
1966 end(fam
->fonts().end());
1968 for(; it
!=end
; ++it
)
1969 for(int i
=0; i
<NUM_COLS
; ++i
)
1970 selectionModel()->select(itsProxy
->mapFromSource(itsModel
->createIndex((*it
)->rowNumber(),
1972 QItemSelectionModel::Deselect
);
1977 static bool isScalable(const QString
&str
)
1979 QByteArray
cFile(QFile::encodeName(str
));
1981 return Misc::checkExt(cFile
, "ttf") || Misc::checkExt(cFile
, "otf") || Misc::checkExt(cFile
, "ttc") ||
1982 Misc::checkExt(cFile
, "pfa") || Misc::checkExt(cFile
, "pfb");
1985 void CFontListView::view()
1987 // Number of fonts user has selected, before we ask if they really want to view them all...
1988 static const int constMaxBeforePrompt
=10;
1990 QModelIndexList
selectedItems(selectedIndexes());
1992 QSet
<CFontItem
*> fonts
;
1994 foreach(index
, selectedItems
)
1996 QModelIndex
realIndex(itsProxy
->mapToSource(index
));
1998 if(realIndex
.isValid())
1999 if((static_cast<CFontModelItem
*>(realIndex
.internalPointer()))->isFont())
2001 CFontItem
*font(static_cast<CFontItem
*>(realIndex
.internalPointer()));
2007 CFontItem
*font((static_cast<CFamilyItem
*>(realIndex
.internalPointer()))->regularFont());
2015 (fonts
.count()<constMaxBeforePrompt
||
2016 KMessageBox::Yes
==KMessageBox::questionYesNo(this, i18n("Open all %1 fonts in font viewer?", fonts
.count()))))
2018 QSet
<CFontItem
*>::ConstIterator
it(fonts
.begin()),
2022 for(; it
!=end
; ++it
)
2025 // If we can, speed up font viewer by passing the font details...
2026 if((*it
)->isEnabled())
2028 KUrl
url((*it
)->url());
2030 url
.addQueryItem(KFI_NAME_QUERY
, (*it
)->name());
2031 url
.addQueryItem(KFI_STYLE_QUERY
, QString().setNum((*it
)->styleInfo()));
2032 url
.addQueryItem(KFI_MIME_QUERY
, (*it
)->mimetype());
2038 // For a disalbed font, we need to find the first scalable font entry in its file list...
2039 CDisabledFonts::TFileList::ConstIterator
fit((*it
)->files().begin()),
2040 fend((*it
)->files().end());
2043 for(; fit
!=fend
; ++fit
)
2044 if(isScalable(*fit
))
2046 QString
urlStr(KFI_KIO_FONTS_PROTOCOL
":/");
2049 if((*it
)->isSystem())
2050 urlStr
+=KFI_KIO_FONTS_SYS
"/";
2052 urlStr
+=KFI_KIO_FONTS_USER
"/";
2053 urlStr
+=(*it
)->name();
2057 url
.addQueryItem(KFI_FILE_QUERY
, *fit
);
2058 url
.addQueryItem(KFI_KIO_FACE
, QString().setNum((*it
)->index()));
2059 url
.addQueryItem(KFI_MIME_QUERY
, (*it
)->mimetype());
2067 args
<< (*it
)->url().url();
2071 QProcess::startDetached(KFI_VIEWER
, args
);
2075 QModelIndexList
CFontListView::allIndexes()
2078 int rowCount(itsProxy
->rowCount());
2080 for(int i
=0; i
<rowCount
; ++i
)
2082 QModelIndex
idx(itsProxy
->index(i
, 0, QModelIndex()));
2083 int childRowCount(itsProxy
->rowCount(idx
));
2087 for(int j
=0; j
<childRowCount
; ++j
)
2089 QModelIndex
child(itsProxy
->index(j
, 0, idx
));
2099 void CFontListView::startDrag(Qt::DropActions supportedActions
)
2101 QModelIndexList
indexes(selectedIndexes());
2103 if (indexes
.count())
2105 QMimeData
*data
= model()->mimeData(indexes
);
2109 QModelIndex
index(itsProxy
->mapToSource(indexes
.first()));
2110 const char *icon
="application-x-font-pcf";
2114 CFontItem
*font
=(static_cast<CFontModelItem
*>(index
.internalPointer()))->isFont()
2115 ? static_cast<CFontItem
*>(index
.internalPointer())
2116 : (static_cast<CFamilyItem
*>(index
.internalPointer()))->regularFont();
2118 if(font
&& !font
->isBitmap())
2119 if("application/x-font-type1"==font
->mimetype())
2120 icon
="application-x-font-type1";
2122 icon
="application-x-font-ttf";
2126 QPixmap
pix(DesktopIcon(icon
, KIconLoader::SizeMedium
));
2128 hotspot
.setX(0); // pix.width()/2);
2129 hotspot
.setY(0); // pix.height()/2);
2131 QDrag
*drag
= new QDrag(this);
2132 drag
->setPixmap(pix
);
2133 drag
->setMimeData(data
);
2134 drag
->setHotSpot(hotspot
);
2135 drag
->start(supportedActions
);
2139 void CFontListView::dragEnterEvent(QDragEnterEvent
*event
)
2141 if(itsAllowDrops
&& event
->provides("text/uri-list")) // "application/x-kde-urilist" ??
2142 event
->acceptProposedAction();
2145 void CFontListView::dropEvent(QDropEvent
*event
)
2147 if(itsAllowDrops
&& event
->provides("text/uri-list"))
2149 event
->acceptProposedAction();
2151 QList
<QUrl
> urls(event
->mimeData()->urls());
2152 QList
<QUrl
>::ConstIterator
it(urls
.begin()),
2156 for(; it
!=end
; ++it
)
2158 KMimeType::Ptr mime
=KMimeType::findByUrl(*it
, 0, false, true);
2160 if(mime
->is("application/x-font-ttf") ||
2161 mime
->is("application/x-font-otf") ||
2162 mime
->is("application/x-font-type1") ||
2163 mime
->is("fonts/package") ||
2164 (itsProxy
->mgtMode() &&
2165 (mime
->is("application/x-font-pcf") ||
2166 mime
->is("application/x-font-bdf"))))
2171 emit
fontsDropped(kurls
);
2175 void CFontListView::contextMenuEvent(QContextMenuEvent
*ev
)
2177 bool valid(indexAt(ev
->pos()).isValid());
2179 itsDeleteAct
->setEnabled(valid
);
2181 if(!itsProxy
->mgtMode())
2183 itsPrintAct
->setEnabled(valid
);
2184 itsViewAct
->setEnabled(valid
);
2185 itsStdMenu
->popup(ev
->globalPos());
2191 QModelIndexList
selectedItems(selectedIndexes());
2194 foreach(index
, selectedItems
)
2196 QModelIndex
realIndex(itsProxy
->mapToSource(index
));
2198 if(realIndex
.isValid())
2199 if((static_cast<CFontModelItem
*>(realIndex
.internalPointer()))->isFont())
2201 if((static_cast<CFontItem
*>(realIndex
.internalPointer())->isEnabled()))
2207 switch((static_cast<CFamilyItem
*>(realIndex
.internalPointer()))->status())
2209 case CFamilyItem::ENABLED
:
2212 case CFamilyItem::DISABLED
:
2215 case CFamilyItem::PARTIAL
:
2223 itsEnableAct
->setEnabled(dis
);
2224 itsDisableAct
->setEnabled(en
);
2225 itsPrintAct
->setEnabled(en
|dis
);
2226 itsViewAct
->setEnabled(en
|dis
);
2227 itsMgtMenu
->popup(ev
->globalPos());
2231 bool CFontListView::viewportEvent(QEvent
*event
)
2233 executeDelayedItemsLayout();
2234 return QTreeView::viewportEvent(event
);
2239 #include "FontList.moc"