diff --git a/kcms/kfontinst/apps/installfont.desktop b/kcms/kfontinst/apps/installfont.desktop index 97afdcc31..e16506890 100644 --- a/kcms/kfontinst/apps/installfont.desktop +++ b/kcms/kfontinst/apps/installfont.desktop @@ -1,95 +1,95 @@ [Desktop Entry] -X-KDE-ServiceTypes=KonqPopupMenu/Plugin,application/x-font-ttf,application/x-font-type1,application/x-font-bdf,application/x-font-pcf,application/x-font-otf,application/x-font-afm,fonts/package +X-KDE-ServiceTypes=KonqPopupMenu/Plugin,application/x-font-ttf,application/x-font-type1,application/x-font-bdf,application/x-font-pcf,application/x-font-otf,application/x-font-afm,fonts/package,font/ttf,font/otf Actions=installFont; Type=Service [Desktop Action installFont] Name=Install... Name[af]=Installeer... Name[ar]=ثبّت... Name[as]=সংস্থাপন কৰক... Name[be]=Устанавіць... Name[be@latin]=Zainstaluj... Name[bg]=Инсталиране... Name[bn]=ইনস্টল... Name[bn_IN]=ইনস্টল করুন... Name[bs]=Instaliraj... Name[ca]=Instal·la... Name[ca@valencia]=Instal·la... Name[cs]=Instalovat... Name[csb]=Instalëjë... Name[da]=Installér... Name[de]=Installieren ... Name[el]=Εγκατάσταση... Name[en_GB]=Install... Name[eo]=Instali... Name[es]=Instalar... Name[et]=Paigalda... Name[eu]=Instalatu... Name[fa]=نصب... Name[fi]=Asenna… Name[fr]=Installer... Name[fy]=Ynstallearje... Name[ga]=Suiteáil... Name[gl]=Instalar… Name[gu]=સ્થાપન... Name[he]=התקנה... Name[hi]=संस्थापित करें... Name[hne]=इंस्टाल करव... Name[hr]=Instaliraj… Name[hsb]=instalować... Name[hu]=Telepítés... Name[ia]=Installa ... Name[id]=Pasang... Name[is]=Setja upp... Name[it]=Installa... Name[ja]=インストール... Name[kk]=Орнату... Name[km]=ដំឡើង... Name[kn]=ಅನುಸ್ಢಾಪಿಸು... Name[ko]=설치... Name[ku]=Sazkirin... Name[lt]=Įdiegti... Name[lv]=Instalēt... Name[mai]=संस्थापित करू... Name[mk]=Инсталирање... Name[ml]=ഇന്‍‌സ്റ്റോള്‍ ചെയ്യുക... Name[mr]=प्रतिष्ठापन... Name[nb]=Installer … Name[nds]=Installeren... Name[ne]=स्थापना गर्नुहोस् Name[nl]=Installeren... Name[nn]=Installer … Name[oc]=Installar... Name[or]=ସ୍ଥାପନ କରନ୍ତୁ... Name[pa]=ਇੰਸਟਾਲ... Name[pl]=Wgraj... Name[pt]=Instalar... Name[pt_BR]=Instalar... Name[ro]=Instalare... Name[ru]=Установить... Name[se]=Sajáiduhte … Name[si]=ස්ථාපනය... Name[sk]=Inštalovať... Name[sl]=Namesti ... Name[sr]=Инсталирај... Name[sr@ijekavian]=Инсталирај... Name[sr@ijekavianlatin]=Instaliraj... Name[sr@latin]=Instaliraj... Name[sv]=Installera... Name[ta]=நிறுவுக... Name[te]=సంస్థాపించు... Name[tg]=Коргузорӣ... Name[th]=ติดตั้ง... Name[tr]=Yükle... Name[ug]=ئورنات… Name[uk]=Встановити... Name[uz]=Oʻrnatish... Name[uz@cyrillic]=Ўрнатиш... Name[vi]=Cài đặt... Name[wa]=Astaler... Name[x-test]=xxInstall...xx Name[zh_CN]=安装... Name[zh_TW]=安裝... Icon=preferences-desktop-font-installer Exec=kfontinst %U diff --git a/kcms/kfontinst/apps/org.kde.kfontview.desktop b/kcms/kfontinst/apps/org.kde.kfontview.desktop index aa001a6b5..3d43913e0 100755 --- a/kcms/kfontinst/apps/org.kde.kfontview.desktop +++ b/kcms/kfontinst/apps/org.kde.kfontview.desktop @@ -1,191 +1,191 @@ [Desktop Entry] Name=KFontView Name[af]=KFontView Name[ar]=عارض خطوطك Name[be]=Прагляд шрыфтоў Name[be@latin]=KFontView Name[bg]=KFontView Name[bn]=কে-ফন্ট-ভিউ Name[bn_IN]=KFontView Name[br]=KFontView Name[bs]=K‑prikazivač-fontova Name[ca]=KFontView Name[ca@valencia]=KFontView Name[cs]=Prohlížeč písem Name[csb]=KFontView Name[cy]=KFontView Name[da]=KFontView Name[de]=KFontView Name[el]=KFontView Name[en_GB]=KFontView Name[eo]=KFontView Name[es]=KFontView Name[et]=KFontView Name[eu]=KFontWiew Name[fi]=KFontView Name[fr]=KFontView Name[fy]=KFontView Name[ga]=KFontView Name[gl]=KFontView Name[gu]=KFontView Name[he]=KFontView Name[hi]=के-फ़ॉन्ट-व्यू Name[hne]=के-फोंट-व्यू Name[hr]=KFontView Name[hsb]=KFontView Name[hu]=KFontView Name[ia]=KFontView Name[id]=KFontView Name[is]=KFontView Name[it]=KFontView Name[ja]=KFontView Name[ka]=KFontView Name[kk]=KFontView Name[km]=KFontView Name[kn]=ಕೆಫಾಂಟ್ ವ್ಯೂ Name[ko]=KFontView Name[ku]=KFontView Name[lt]=KFontView Name[lv]=KFontView Name[mai]=के-फान्ट-व्यू Name[mk]=КФонтПреглед Name[ml]=കെഫോണ്ട്‌വ്യൂ Name[mr]=केफॉन्टव्यू Name[ms]=KFontView Name[nb]=KFontView Name[nds]=KFontView Name[ne]=केडीई फन्ट दृश्य Name[nl]=KFontView Name[nn]=KFontView Name[oc]=KFontView Name[or]=KFontView Name[pa]=KFontView Name[pl]=KFontView Name[pt]=KFontView Name[pt_BR]=KFontView Name[ro]=KFontView Name[ru]=KFontView Name[se]=Fontačájeheaddji Name[si]=KFontView Name[sk]=KFontView Name[sl]=KFontView Name[sr]=К‑приказивач-фонтова Name[sr@ijekavian]=К‑приказивач-фонтова Name[sr@ijekavianlatin]=K‑prikazivač-fontova Name[sr@latin]=K‑prikazivač-fontova Name[sv]=Kfontview Name[ta]=KFontView Name[te]=KFontView Name[tg]=Намоиши ҳарф Name[th]=ดูแบบอักษร-K Name[tr]=KFontView Name[ug]=KFontView Name[uk]=KFontView Name[uz]=KFontView Name[uz@cyrillic]=KFontView Name[vi]=KFonView Name[wa]=Håyneu d' fontes Name[x-test]=xxKFontViewxx Name[zh_CN]=KFontView Name[zh_TW]=KFontView Exec=kfontview %U Icon=kfontview X-KDE-StartupNotify=true Type=Application -MimeType=application/x-font-ttf;application/x-font-type1;application/x-font-otf;application/x-font-pcf;application/x-font-bdf;application/vnd.kde.fontspackage; +MimeType=application/x-font-ttf;application/x-font-type1;application/x-font-otf;application/x-font-pcf;application/x-font-bdf;application/vnd.kde.fontspackage;font/otf;font/ttf; GenericName=Font Viewer GenericName[af]=Skriftipe Besigter GenericName[ar]=عارض الخطوط GenericName[be]=Прагляд шрыфта GenericName[be@latin]=Prahladnik šryftoŭ GenericName[bg]=Преглед на шрифтове GenericName[bn]=ফন্ট প্রদর্শক GenericName[bn_IN]=ফন্ট প্রদর্শক GenericName[br]=Gweler Nodrezhoù GenericName[bs]=Prikazivač fontova GenericName[ca]=Visor de tipus de lletra GenericName[ca@valencia]=Visor de tipus de lletra GenericName[cs]=Prohlížeč písem GenericName[csb]=Przezérnik fòntów GenericName[cy]=Gwelydd Wynebfathau GenericName[da]=Skrifttypevisning GenericName[de]=Schriftartenbetrachter GenericName[el]=Προβολέας γραμματοσειρών GenericName[en_GB]=Font Viewer GenericName[eo]=Tipara rigardilo GenericName[es]=Visor del tipo de letra GenericName[et]=Fontide näitaja GenericName[eu]=Letra-tipoen ikustailea GenericName[fa]=مشاهده‌گر قلم GenericName[fi]=Fonttikatselin GenericName[fr]=Afficheur de polices de caractères GenericName[fy]=Lettertypewerjefte GenericName[ga]=Amharcán Clónna GenericName[gl]=Visor de tipos de letra GenericName[gu]=ફોન્ટ દર્શક GenericName[he]=מציג גופנים GenericName[hi]=फ़ॉन्ट प्रदर्शक GenericName[hne]=फोंट प्रदर्सक GenericName[hr]=Preglednik fontova GenericName[hsb]=Přehladowar za pisma GenericName[hu]=Betűtípusböngésző GenericName[ia]=Visor de fronte GenericName[id]=Penampil Fonta GenericName[is]=Leturskoðari GenericName[it]=Visore di caratteri GenericName[ja]=フォントビューア GenericName[ka]=პროგრამა ფონტების სანახავად GenericName[kk]=Қаріпті қарау құралы GenericName[km]=កម្មវិធី​មើល​ពុម្ពអក្សរ GenericName[kn]=ಅಕ್ಷರಶೈಲಿ ವೀಕ್ಷಕ GenericName[ko]=글꼴 뷰어 GenericName[ku]=Nîşandêra Curetîpan GenericName[lt]=Šriftų žiūryklė GenericName[lv]=Fontu skatītājs GenericName[mai]=फान्ट प्रदर्शक GenericName[mk]=Прегледувач на фонтови GenericName[ml]=അക്ഷരസഞ്ചയദര്‍ശിനി GenericName[mr]=फॉन्ट प्रदर्शक GenericName[ms]=Pemapar Fon GenericName[nb]=Skriftviser GenericName[nds]=Schriftoortkieker GenericName[ne]=फन्ट दर्शक GenericName[nl]=Lettertypeweergave GenericName[nn]=Skriftvisar GenericName[or]=ଅକ୍ଷରରୂପ ପ୍ରଦର୍ଶକ GenericName[pa]=ਫੋਂਟ ਦਰਸ਼ਕ GenericName[pl]=Przeglądarka czcionek GenericName[pt]=Visualizador do Tipo de Letra GenericName[pt_BR]=Visualizador de fontes GenericName[ro]=Vizualizator de fonturi GenericName[ru]=Просмотр шрифтов GenericName[se]=Fontačájeheaddji GenericName[si]=අකුරු දසුන GenericName[sk]=Prehliadač písiem GenericName[sl]=Pregledovalnik pisav GenericName[sr]=Приказивач фонтова GenericName[sr@ijekavian]=Приказивач фонтова GenericName[sr@ijekavianlatin]=Prikazivač fontova GenericName[sr@latin]=Prikazivač fontova GenericName[sv]=Teckensnittsvisning GenericName[ta]=Font Viewer GenericName[te]=ఫాంట్ వీక్షణి GenericName[tg]=Намоишгари ҳарфҳо GenericName[th]=ดูตัวอย่างแบบอักษร GenericName[tr]=Yazı Tipi Görüntüleyici GenericName[ug]=خەت نۇسخا كۆرگۈ GenericName[uk]=Переглядач шрифтів GenericName[uz]=Shrift koʻruvchi GenericName[uz@cyrillic]=Шрифт кўрувчи GenericName[vi]=Trình xem phông chữ GenericName[wa]=Håyneu d' fontes GenericName[x-test]=xxFont Viewerxx GenericName[zh_CN]=字体查看器 GenericName[zh_TW]=字型檢視器 Terminal=false InitialPreference=1 NoDisplay=true Categories=Qt;KDE;Utility; X-DBUS-StartupType=Unique X-KDE-HasTempFileOption=true X-DBUS-ServiceName=org.kde.kfontview diff --git a/kcms/kfontinst/kcmfontinst/FontList.cpp b/kcms/kfontinst/kcmfontinst/FontList.cpp index 4c5e434f0..64df0917a 100644 --- a/kcms/kfontinst/kcmfontinst/FontList.cpp +++ b/kcms/kfontinst/kcmfontinst/FontList.cpp @@ -1,2057 +1,2059 @@ /* * 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 "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 "Fc.h" #include "KfiConstants.h" #include "GroupList.h" #include "FontInstInterface.h" #include "XmlStrings.h" #include "Family.h" #include "Style.h" #include "File.h" namespace KFI { -const QStringList CFontList::fontMimeTypes(QStringList() << "application/x-font-ttf" +const QStringList CFontList::fontMimeTypes(QStringList() << "font/ttf" + << "font/otf" + << "application/x-font-ttf" << "application/x-font-otf" << "application/x-font-type1" << "application/x-font-pcf" << "application/x-font-bdf" << "application/vnd.kde.fontspackage"); static const int constMaxSlowed = 250; static void decompose(const QString &name, QString &family, QString &style) { int commaPos=name.lastIndexOf(','); family=-1==commaPos ? name : name.left(commaPos); style=-1==commaPos ? KFI_WEIGHT_REGULAR : name.mid(commaPos+2); } static void addFont(CFontItem *font, CJobRunner::ItemList &urls, QStringList &fontNames, QSet *fonts, QSet &usedFonts, bool getEnabled, bool getDisabled) { if(!usedFonts.contains(font) && ( (getEnabled && font->isEnabled()) || (getDisabled && !font->isEnabled()) ) ) { urls.append(CJobRunner::Item(font->url(), font->name(), !font->isEnabled())); fontNames.append(font->name()); usedFonts.insert(font); if(fonts) fonts->insert(Misc::TFont(font->family(), font->styleInfo())); } } static QString replaceEnvVar(const QString &text) { QString mod(text); int endPos(text.indexOf('/')); if(endPos==-1) endPos=text.length()-1; else endPos--; if(endPos>0) { QString envVar(text.mid(1, endPos)); const char *val=getenv(envVar.toLatin1().constData()); if(val) mod=Misc::fileSyntax(QFile::decodeName(val)+mod.mid(endPos+1)); } return mod; } // // Convert from list such as: // // Arial // Arial, Bold // Courier // Times // Times, Italic // // To: // // Arial (Regular, Bold) // Coutier // Times (Regular, Italic) QStringList CFontList::compact(const QStringList &fonts) { QString lastFamily, entry; QStringList::ConstIterator it(fonts.begin()), end(fonts.end()); QStringList compacted; QSet usedStyles; for(; it!=end; ++it) { QString family, style; decompose(*it, family, style); if(family!=lastFamily) { usedStyles.clear(); if(entry.length()) { entry+=')'; compacted.append(entry); } entry=QString(family+" ("); lastFamily=family; } if(!usedStyles.contains(style)) { usedStyles.clear(); if(entry.length() && '('!=entry[entry.length()-1]) entry+=", "; entry+=style; usedStyles.insert(style); } } if(entry.length()) { entry+=')'; compacted.append(entry); } return compacted; } QString capitaliseFoundry(const QString &foundry) { QString f(foundry.toLower()); if(f==QLatin1String("ibm")) return QLatin1String("IBM"); else if(f==QLatin1String("urw")) return QLatin1String("URW"); else if(f==QLatin1String("itc")) return QLatin1String("ITC"); else if(f==QLatin1String("nec")) return QLatin1String("NEC"); else if(f==QLatin1String("b&h")) return QLatin1String("B&H"); else if(f==QLatin1String("dec")) return QLatin1String("DEC"); else { QChar *ch(f.data()); int len(f.length()); bool isSpace(true); while(len--) { if (isSpace) *ch=ch->toUpper(); isSpace=ch->isSpace(); ++ch; } } return f; } inline bool isSysFolder(const QString §) { return i18n(KFI_KIO_FONTS_SYS)==sect || KFI_KIO_FONTS_SYS==sect; } CFontItem::CFontItem(CFontModelItem *p, const Style &s, bool sys) : CFontModelItem(p), itsStyleName(FC::createStyleName(s.value())), itsStyle(s) { refresh(); if(!Misc::root()) setIsSystem(sys); } void CFontItem::refresh() { FileCont::ConstIterator it(itsStyle.files().begin()), end(itsStyle.files().end()); itsEnabled=false; for(; it!=end; ++it) if(!Misc::isHidden(Misc::getFile((*it).path()))) { itsEnabled=true; break; } } CFamilyItem::CFamilyItem(CFontList &p, const Family &f, bool sys) : CFontModelItem(NULL), itsStatus(ENABLED), itsRealStatus(ENABLED), itsRegularFont(NULL), itsParent(p) { itsName=f.name(); addFonts(f.styles(), sys); //updateStatus(); } CFamilyItem::~CFamilyItem() { qDeleteAll(itsFonts); itsFonts.clear(); } bool CFamilyItem::addFonts(const StyleCont &styles, bool sys) { StyleCont::ConstIterator it(styles.begin()), end(styles.end()); bool modified=false; for(; it!=end; ++it) { CFontItem *font=findFont((*it).value(), sys); if(!font) { // New font style! itsFonts.append(new CFontItem(this, *it, sys)); modified=true; } else { int before=(*it).files().size(); font->addFiles((*it).files()); if((*it).files().size()!=before) { modified=true; font->refresh(); } } } return modified; } CFontItem * CFamilyItem::findFont(quint32 style, bool sys) { CFontItemCont::ConstIterator fIt(itsFonts.begin()), fEnd(itsFonts.end()); for(; fIt!=fEnd; ++fIt) if((*(*fIt)).styleInfo()==style && (*(*fIt)).isSystem()==sys) return (*fIt); return NULL; } void CFamilyItem::getFoundries(QSet &foundries) const { CFontItemCont::ConstIterator it(itsFonts.begin()), end(itsFonts.end()); for(; it!=end; ++it) { FileCont::ConstIterator fIt((*it)->files().begin()), fEnd((*it)->files().end()); for(; fIt!=fEnd; ++fIt) if(!(*fIt).foundry().isEmpty()) foundries.insert(capitaliseFoundry((*fIt).foundry())); } } bool CFamilyItem::usable(const CFontItem *font, bool root) { return ( root || (font->isSystem() && itsParent.allowSys()) || (!font->isSystem() && itsParent.allowUser())); } void CFamilyItem::addFont(CFontItem *font, bool update) { itsFonts.append(font); if(update) { updateStatus(); updateRegularFont(font); } } void CFamilyItem::removeFont(CFontItem *font, bool update) { itsFonts.removeAll(font); if(update) updateStatus(); if(itsRegularFont==font) { itsRegularFont=NULL; if(update) updateRegularFont(NULL); } delete font; } void CFamilyItem::refresh() { updateStatus(); itsRegularFont=NULL; updateRegularFont(NULL); } bool CFamilyItem::updateStatus() { bool root(Misc::root()); EStatus oldStatus(itsStatus); CFontItemCont::ConstIterator it(itsFonts.begin()), end(itsFonts.end()); int en(0), dis(0), allEn(0), allDis(0); bool oldSys(isSystem()), sys(false); itsFontCount=0; for(; it!=end; ++it) if(usable(*it, root)) { if((*it)->isEnabled()) en++; else dis++; if(!sys) sys=(*it)->isSystem(); itsFontCount++; } else if((*it)->isEnabled()) allEn++; else allDis++; allEn+=en; allDis+=dis; itsStatus=en && dis ? PARTIAL : en ? ENABLED : DISABLED; itsRealStatus=allEn && allDis ? PARTIAL : allEn ? ENABLED : DISABLED; if(!root) setIsSystem(sys); return itsStatus!=oldStatus || isSystem()!=oldSys; } bool CFamilyItem::updateRegularFont(CFontItem *font) { static const quint32 constRegular=FC::createStyleVal(FC_WEIGHT_REGULAR, KFI_FC_WIDTH_NORMAL, FC_SLANT_ROMAN); CFontItem *oldFont(itsRegularFont); bool root(Misc::root()); if(font && usable(font, root)) { if(itsRegularFont) { int regDiff=abs((long)(itsRegularFont->styleInfo()-constRegular)), fontDiff=abs((long)(font->styleInfo()-constRegular)); if(fontDiffstyleInfo()-constRegular)); if(diff)), SLOT(fontList(int,QList))); } CFontList::~CFontList() { qDeleteAll(itsFamilies); itsFamilies.clear(); itsFamilyHash.clear(); } void CFontList::dbusServiceOwnerChanged(const QString &name, const QString &from, const QString &to) { Q_UNUSED(from); Q_UNUSED(to); if(name==QLatin1String(OrgKdeFontinstInterface::staticInterfaceName())) load(); } void CFontList::fontList(int pid, const QList &families) { // printf("**** fontList:%d/%d %d\n", pid, getpid(), families.count()); if(pid==getpid()) { QList::ConstIterator it(families.begin()), end(families.end()); int count(families.size()); for(int i=0; it!=end; ++it, ++i) { fontsAdded(*it); emit listingPercent(i*100/count); } emit listingPercent(100); } } void CFontList::unsetSlowUpdates() { setSlowUpdates(false); } void CFontList::load() { for(int t=0; tlist(FontInst::SYS_MASK|FontInst::USR_MASK, getpid()); } void CFontList::setSlowUpdates(bool slow) { if(itsSlowUpdates!=slow) { if(!slow) for(int i=0; i families; QDataStream ds(&encodedData, QIODevice::WriteOnly); for(; it!=end; ++it) if((*it).isValid()) { if((static_cast((*it).internalPointer()))->isFont()) { CFontItem *font=static_cast((*it).internalPointer()); families.insert(font->family()); } else { CFamilyItem *fam=static_cast((*it).internalPointer()); families.insert(fam->name()); } } ds << families; mimeData->setData(KFI_FONT_DRAG_MIME, encodedData); return mimeData; } QStringList CFontList::mimeTypes() const { QStringList types; types << "text/uri-list"; return types; } QVariant CFontList::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal) switch(role) { case Qt::DisplayRole: switch(section) { case COL_FONT: return i18n("Font"); case COL_STATUS: return i18n("Status"); default: break; } break; // case Qt::DecorationRole: // if(COL_STATUS==section) // return SmallIcon("fontstatus"); // break; case Qt::TextAlignmentRole: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); case Qt::ToolTipRole: if(COL_STATUS==section) return i18n("This column shows the status of the font family, and of the " "individual font styles."); break; case Qt::WhatsThisRole: return whatsThis(); default: break; } return QVariant(); } QModelIndex CFontList::index(int row, int column, const QModelIndex &parent) const { if(parent.isValid()) // Then font... { CFamilyItem *fam=static_cast(parent.internalPointer()); if(rowfonts().count()) return createIndex(row, column, fam->fonts().at(row)); } else // Family.... if(row(index.internalPointer()); if(mi->isFamily()) return QModelIndex(); else { CFontItem *font=static_cast(index.internalPointer()); return createIndex(itsFamilies.indexOf(((CFamilyItem *)font->parent())), 0, font->parent()); } } int CFontList::rowCount(const QModelIndex &parent) const { if(parent.isValid()) { CFontModelItem *mi=static_cast(parent.internalPointer()); if(mi->isFont()) return 0; CFamilyItem *fam=static_cast(parent.internalPointer()); return fam->fonts().count(); } else return itsFamilies.count(); } void CFontList::refresh(bool allowSys, bool allowUser) { itsAllowSys=allowSys; itsAllowUser=allowUser; CFamilyItemCont::ConstIterator it(itsFamilies.begin()), end(itsFamilies.end()); for(; it!=end; ++it) (*it)->refresh(); } void CFontList::getFamilyStats(QSet &enabled, QSet &disabled, QSet &partial) { CFamilyItemCont::ConstIterator it(itsFamilies.begin()), end(itsFamilies.end()); for(; it!=end; ++it) { switch((*it)->realStatus()) { case CFamilyItem::ENABLED: enabled.insert((*it)->name()); break; case CFamilyItem::PARTIAL: partial.insert((*it)->name()); break; case CFamilyItem::DISABLED: disabled.insert((*it)->name()); break; } } } void CFontList::getFoundries(QSet &foundries) const { CFamilyItemCont::ConstIterator it(itsFamilies.begin()), end(itsFamilies.end()); for(; it!=end; ++it) (*it)->getFoundries(foundries); } QString CFontList::whatsThis() const { return i18n("

This list shows your installed fonts. The fonts are grouped by family, and the" " number in square brackets represents the number of styles in which the family is" " available. e.g.

" "
    " "
  • Times [4]" "
    • Regular
    • " "
    • Bold
    • " "
    • Bold Italic
    • " "
    • Italic
    • " "
    " "
  • " "
"); } void CFontList::fontsAdded(const KFI::Families &families) { // printf("**** FONT ADDED:%d\n", families.items.count()); if(itsSlowUpdates) storeSlowedMessage(families, MSG_ADD); else addFonts(families.items, families.isSystem && !Misc::root()); } void CFontList::fontsRemoved(const KFI::Families &families) { // printf("**** FONT REMOVED:%d\n", families.items.count()); if(itsSlowUpdates) storeSlowedMessage(families, MSG_DEL); else removeFonts(families.items, families.isSystem && !Misc::root()); } void CFontList::storeSlowedMessage(const Families &families, EMsgType type) { int folder=families.isSystem ? FontInst::FOLDER_SYS : FontInst::FOLDER_USER; bool playOld=false; for(int i=0; iconstMaxSlowed) playOld=true; if(playOld) actionSlowedUpdates(families.isSystem); FamilyCont::ConstIterator family(families.items.begin()), fend(families.items.end()); for(; family!=fend; ++family) { FamilyCont::ConstIterator f=itsSlowedMsgs[type][folder].find(*family); if(f!=itsSlowedMsgs[type][folder].end()) { StyleCont::ConstIterator style((*family).styles().begin()), send((*family).styles().end()); for(; style!=send; ++style) { StyleCont::ConstIterator st=(*f).styles().find(*style); if(st==(*f).styles().end()) (*f).add(*style); else (*st).addFiles((*style).files()); } } else itsSlowedMsgs[type][folder].insert(*family); } } void CFontList::actionSlowedUpdates(bool sys) { int folder=sys ? FontInst::FOLDER_SYS : FontInst::FOLDER_USER; for(int i=0; i modifiedFamilies; for(; family!=end; ++family) { if((*family).styles().count()>0) { CFamilyItem *famItem=findFamily((*family).name()); if(famItem) { int rowFrom=famItem->fonts().count(); if(famItem->addFonts((*family).styles(), sys)) { int rowTo=famItem->fonts().count(); if(rowTo!=rowFrom) { beginInsertRows(createIndex(famItem->rowNumber(), 0, famItem), rowFrom, rowTo); endInsertRows(); } modifiedFamilies.insert(famItem); } } else { famItem=new CFamilyItem(*this, *family, sys); itsFamilies.append(famItem); itsFamilyHash[famItem->name()]=famItem; modifiedFamilies.insert(famItem); } } } int famRowTo=itsFamilies.count(); if(famRowTo!=famRowFrom) { beginInsertRows(QModelIndex(), famRowFrom, famRowTo); endInsertRows(); } if(!modifiedFamilies.isEmpty()) { QSet::Iterator it(modifiedFamilies.begin()), end(modifiedFamilies.end()); for(; it!=end; ++it) (*it)->refresh(); } // if(emitLayout) // emit layoutChanged(); } void CFontList::removeFonts(const FamilyCont &families, bool sys) { // if(!itsSlowUpdates) // emit layoutAboutToBeChanged(); FamilyCont::ConstIterator family(families.begin()), end(families.end()); QSet modifiedFamilies; for(; family!=end; ++family) { if((*family).styles().count()>0) { CFamilyItem *famItem=findFamily((*family).name()); if(famItem) { StyleCont::ConstIterator it((*family).styles().begin()), end((*family).styles().end()); for(; it!=end; ++it) { CFontItem *fontItem=famItem->findFont((*it).value(), sys); if(fontItem) { int before=fontItem->files().count(); fontItem->removeFiles((*it).files()); if(fontItem->files().count()!=before) { if(fontItem->files().isEmpty()) { int row=-1; if(1!=famItem->fonts().count()) { row=fontItem->rowNumber(); beginRemoveRows(createIndex(famItem->rowNumber(), 0, famItem), row, row); } famItem->removeFont(fontItem, false); if(-1!=row) endRemoveRows(); } else fontItem->refresh(); } } } if(famItem->fonts().isEmpty()) { int row=famItem->rowNumber(); beginRemoveRows(QModelIndex(), row, row); itsFamilyHash.remove(famItem->name()); itsFamilies.removeAt(row); endRemoveRows(); } else modifiedFamilies.insert(famItem); } } } if(!modifiedFamilies.isEmpty()) { QSet::Iterator it(modifiedFamilies.begin()), end(modifiedFamilies.end()); for(; it!=end; ++it) (*it)->refresh(); } // if(!itsSlowUpdates) // emit layoutChanged(); } CFamilyItem * CFontList::findFamily(const QString &familyName) { CFamilyItemHash::Iterator it=itsFamilyHash.find(familyName); return it==itsFamilyHash.end() ? 0L : *it; } inline bool matchString(const QString &str, const QString &pattern) { return pattern.isEmpty() || -1!=str.indexOf(pattern, 0, Qt::CaseInsensitive); } CFontListSortFilterProxy::CFontListSortFilterProxy(QObject *parent, QAbstractItemModel *model) : QSortFilterProxyModel(parent), itsGroup(NULL), itsFilterCriteria(CFontFilter::CRIT_FAMILY), itsFilterWs(0), itsFcQuery(NULL) { setSourceModel(model); setSortCaseSensitivity(Qt::CaseInsensitive); setFilterKeyColumn(0); setDynamicSortFilter(false); itsTimer=new QTimer(this); connect(itsTimer, SIGNAL(timeout()), SLOT(timeout())); connect(model, SIGNAL(layoutChanged()), SLOT(invalidate())); itsTimer->setSingleShot(true); } QVariant CFontListSortFilterProxy::data(const QModelIndex &idx, int role) const { if (!idx.isValid()) return QVariant(); static const int constMaxFiles=20; QModelIndex index(mapToSource(idx)); CFontModelItem *mi=static_cast(index.internalPointer()); if(!mi) return QVariant(); switch(role) { case Qt::ToolTipRole: if(CFontFilter::CRIT_FILENAME==itsFilterCriteria || CFontFilter::CRIT_LOCATION==itsFilterCriteria || CFontFilter::CRIT_FONTCONFIG==itsFilterCriteria) { if(mi->isFamily()) { CFamilyItem *fam=static_cast(index.internalPointer()); CFontItemCont::ConstIterator it(fam->fonts().begin()), end(fam->fonts().end()); FileCont allFiles; QString tip(""+fam->name()+""); bool markMatch(CFontFilter::CRIT_FONTCONFIG==itsFilterCriteria); tip+="

"; for(; it!=end; ++it) allFiles+=(*it)->files(); //qSort(allFiles); FileCont::ConstIterator fit(allFiles.begin()), fend(allFiles.end()); for(int i=0; fit!=fend && ifile()) tip+=""; else tip+=""; if(allFiles.count()>constMaxFiles) tip+=""; tip+="
"+Misc::contractHome((*fit).path())+"
"+Misc::contractHome((*fit).path())+"
"+i18n("...plus %1 more", allFiles.count()-constMaxFiles)+"

"; return tip; } else { CFontItem *font=static_cast(index.internalPointer()); QString tip(""+font->name()+""); const FileCont &files(font->files()); bool markMatch(CFontFilter::CRIT_FONTCONFIG==itsFilterCriteria); tip+="

"; //qSort(files); FileCont::ConstIterator fit(files.begin()), fend(files.end()); for(int i=0; fit!=fend && ifile()) tip+=""; else tip+=""; if(files.count()>constMaxFiles) tip+=""; tip+="
"+Misc::contractHome((*fit).path())+"
"+Misc::contractHome((*fit).path() )+"
"+i18n("...plus %1 more", files.count()-constMaxFiles)+"

"; return tip; } } break; case Qt::FontRole: if(COL_FONT==index.column() && mi->isSystem()) { QFont font; font.setItalic(true); return font; } break; case Qt::ForegroundRole: if(COL_FONT==index.column() && ( (mi->isFont() && !(static_cast(index.internalPointer()))->isEnabled()) || (mi->isFamily() && CFamilyItem::DISABLED==(static_cast(index.internalPointer()))->status())) ) return KColorScheme(QPalette::Active).foreground(KColorScheme::NegativeText).color(); break; case Qt::DisplayRole: if(COL_FONT==index.column()) { if(mi->isFamily()) { CFamilyItem *fam=static_cast(index.internalPointer()); return i18n("%1 [%2]", fam->name(), fam->fontCount()); } else return (static_cast(index.internalPointer()))->style(); } break; case Qt::DecorationRole: if(mi->isFamily()) { CFamilyItem *fam=static_cast(index.internalPointer()); switch(index.column()) { case COL_STATUS: switch(fam->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; } } else if(COL_STATUS==index.column()) return SmallIcon( (static_cast(index.internalPointer()))->isEnabled() ? "dialog-ok" : "dialog-cancel", 10); break; case Qt::SizeHintRole: if(mi->isFamily()) { const int s = KIconLoader::global()->currentSize(KIconLoader::Small); return QSize(s, s + 4); } default: break; } return QVariant(); } bool CFontListSortFilterProxy::acceptFont(CFontItem *fnt, bool checkFontText) const { if(itsGroup && (CGroupListItem::ALL!=itsGroup->type() || (!filterText().isEmpty() && checkFontText))) { bool fontMatch(!checkFontText); if(!fontMatch) switch(itsFilterCriteria) { case CFontFilter::CRIT_FONTCONFIG: fontMatch=itsFcQuery ? fnt->name()==itsFcQuery->font() // || fnt->files().contains(itsFcQuery->file()) : false; break; case CFontFilter::CRIT_STYLE: fontMatch=matchString(fnt->style(), itsFilterText); break; case CFontFilter::CRIT_FOUNDRY: { FileCont::ConstIterator it(fnt->files().begin()), end(fnt->files().end()); for(; it!=end && !fontMatch; ++it) fontMatch=0==(*it).foundry().compare(itsFilterText, Qt::CaseInsensitive); break; } case CFontFilter::CRIT_FILENAME: { FileCont::ConstIterator it(fnt->files().begin()), end(fnt->files().end()); for(; it!=end && !fontMatch; ++it) { QString file(Misc::getFile((*it).path())); int pos(Misc::isHidden(file) ? 1 : 0); if(pos==file.indexOf(itsFilterText, pos, Qt::CaseInsensitive)) fontMatch=true; } break; } case CFontFilter::CRIT_LOCATION: { FileCont::ConstIterator it(fnt->files().begin()), end(fnt->files().end()); for(; it!=end && !fontMatch; ++it) if(0==Misc::getDir((*it).path()).indexOf(itsFilterText, 0, Qt::CaseInsensitive)) fontMatch=true; break; } case CFontFilter::CRIT_FILETYPE: { FileCont::ConstIterator it(fnt->files().begin()), end(fnt->files().end()); QStringList::ConstIterator mimeEnd(itsFilterTypes.constEnd()); for(; it!=end && !fontMatch; ++it) { QStringList::ConstIterator mime(itsFilterTypes.constBegin()); for(; mime!=mimeEnd; ++mime) if(Misc::checkExt((*it).path(), *mime)) fontMatch=true; } break; } case CFontFilter::CRIT_WS: fontMatch=fnt->writingSystems()&itsFilterWs; break; default: break; } return fontMatch && itsGroup->hasFont(fnt); } return true; } bool CFontListSortFilterProxy::acceptFamily(CFamilyItem *fam) const { CFontItemCont::ConstIterator it(fam->fonts().begin()), end(fam->fonts().end()); bool familyMatch(CFontFilter::CRIT_FAMILY==itsFilterCriteria && matchString(fam->name(), itsFilterText)); for(; it!=end; ++it) if(acceptFont(*it, !familyMatch)) return true; return false; } bool CFontListSortFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { QModelIndex index(sourceModel()->index(sourceRow, 0, sourceParent)); if(index.isValid()) { CFontModelItem *mi=static_cast(index.internalPointer()); if(mi->isFont()) { CFontItem *font=static_cast(index.internalPointer()); return acceptFont(font, !(CFontFilter::CRIT_FAMILY==itsFilterCriteria && matchString(font->family(), itsFilterText))); } else return acceptFamily(static_cast(index.internalPointer())); } return false; } bool CFontListSortFilterProxy::lessThan(const QModelIndex &left, const QModelIndex &right) const { if(left.isValid() && right.isValid()) { CFontModelItem *lmi=static_cast(left.internalPointer()), *rmi=static_cast(right.internalPointer()); if(lmi->isFont()isFont()) return true; if(lmi->isFont()) { CFontItem *lfi=static_cast(left.internalPointer()), *rfi=static_cast(right.internalPointer()); if(COL_STATUS==filterKeyColumn()) { if(lfi->isEnabled()isEnabled() || (lfi->isEnabled()==rfi->isEnabled() && lfi->styleInfo()styleInfo())) return true; } else if(lfi->styleInfo()styleInfo()) return true; } else { CFamilyItem *lfi=static_cast(left.internalPointer()), *rfi=static_cast(right.internalPointer()); if(COL_STATUS==filterKeyColumn()) { if(lfi->status()status() || (lfi->status()==rfi->status() && QString::localeAwareCompare(lfi->name(), rfi->name())<0)) return true; } else if(QString::localeAwareCompare(lfi->name(), rfi->name())<0) return true; } } return false; } void CFontListSortFilterProxy::setFilterGroup(CGroupListItem *grp) { if(grp!=itsGroup) { // bool wasNull=!itsGroup; itsGroup=grp; // if(!(wasNull && itsGroup && CGroupListItem::ALL==itsGroup->type())) clear(); } } void CFontListSortFilterProxy::setFilterText(const QString &text) { if(text!=itsFilterText) { // // If we are filtering on file location, then expand ~ to /home/user, etc. if (CFontFilter::CRIT_LOCATION==itsFilterCriteria && !text.isEmpty() && ('~'==text[0] || '$'==text[0])) if('~'==text[0]) itsFilterText=1==text.length() ? QDir::homePath() : QString(text).replace(0, 1, QDir::homePath()); else itsFilterText=replaceEnvVar(text); else itsFilterText=text; if(itsFilterText.isEmpty()) { itsTimer->stop(); timeout(); } else itsTimer->start(CFontFilter::CRIT_FONTCONFIG==itsFilterCriteria ? 750 : 400); } } void CFontListSortFilterProxy::setFilterCriteria(CFontFilter::ECriteria crit, qulonglong ws, const QStringList &ft) { if(crit!=itsFilterCriteria || ws!=itsFilterWs || ft!=itsFilterTypes) { itsFilterWs=ws; itsFilterCriteria=crit; itsFilterTypes=ft; if(CFontFilter::CRIT_LOCATION==itsFilterCriteria) setFilterText(itsFilterText); itsTimer->stop(); timeout(); } } void CFontListSortFilterProxy::timeout() { if(CFontFilter::CRIT_FONTCONFIG==itsFilterCriteria) { int commaPos=itsFilterText.indexOf(','); QString query(itsFilterText); if(-1!=commaPos) { QString style(query.mid(commaPos+1)); query=query.left(commaPos); query=query.trimmed(); query+=":style="; style=style.trimmed(); query+=style; } else query=query.trimmed(); if(!itsFcQuery) { itsFcQuery=new CFcQuery(this); connect(itsFcQuery, SIGNAL(finished()), SLOT(fcResults())); } itsFcQuery->run(query); } else { clear(); emit refresh(); } } void CFontListSortFilterProxy::fcResults() { if(CFontFilter::CRIT_FONTCONFIG==itsFilterCriteria) { clear(); emit refresh(); } } CFontListView::CFontListView(QWidget *parent, CFontList *model) : QTreeView(parent), itsProxy(new CFontListSortFilterProxy(this, model)), itsModel(model), itsAllowDrops(false) { setModel(itsProxy); itsModel=model; header()->setStretchLastSection(false); resizeColumnToContents(COL_STATUS); header()->setResizeMode(COL_STATUS, QHeaderView::Fixed); header()->setResizeMode(COL_FONT, QHeaderView::Stretch); setSelectionMode(QAbstractItemView::ExtendedSelection); setSelectionBehavior(QAbstractItemView::SelectRows); setSortingEnabled(true); sortByColumn(COL_FONT, Qt::AscendingOrder); setAllColumnsShowFocus(true); setAlternatingRowColors(true); setAcceptDrops(true); setDropIndicatorShown(false); setDragEnabled(true); setDragDropMode(QAbstractItemView::DragDrop); header()->setClickable(true); header()->setSortIndicatorShown(true); connect(this, SIGNAL(collapsed(QModelIndex)), SLOT(itemCollapsed(QModelIndex))); connect(header(), SIGNAL(sectionClicked(int)), SLOT(setSortColumn(int))); connect(itsProxy, SIGNAL(refresh()), SIGNAL(refresh())); connect(itsModel, SIGNAL(listingPercent(int)), SLOT(listingPercent(int))); setWhatsThis(model->whatsThis()); header()->setWhatsThis(whatsThis()); itsMenu=new QMenu(this); itsDeleteAct=itsMenu->addAction(QIcon::fromTheme("edit-delete"), i18n("Delete"), 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())); if(!Misc::app(KFI_VIEWER).isEmpty()) itsMenu->addSeparator(); itsPrintAct=Misc::app(KFI_VIEWER).isEmpty() ? 0L : itsMenu->addAction(QIcon::fromTheme("document-print"), i18n("Print..."), this, SIGNAL(print())); itsViewAct=Misc::app(KFI_VIEWER).isEmpty() ? 0L : itsMenu->addAction(QIcon::fromTheme("kfontview"), i18n("Open in Font Viewer"), this, SLOT(view())); itsMenu->addSeparator(); itsMenu->addAction(QIcon::fromTheme("view-refresh"), i18n("Reload"), model, SLOT(load())); } void CFontListView::getFonts(CJobRunner::ItemList &urls, QStringList &fontNames, QSet *fonts, bool selected, bool getEnabled, bool getDisabled) { QModelIndexList selectedItems(selected ? selectedIndexes() : allIndexes()); QSet usedFonts; QModelIndex index; foreach(index, selectedItems) if(index.isValid()) { QModelIndex realIndex(itsProxy->mapToSource(index)); if(realIndex.isValid()) { if((static_cast(realIndex.internalPointer()))->isFont()) { CFontItem *font=static_cast(realIndex.internalPointer()); addFont(font, urls, fontNames, fonts, usedFonts, getEnabled, getDisabled); } else { CFamilyItem *fam=static_cast(realIndex.internalPointer()); for(int ch=0; chfontCount(); ++ch) { QModelIndex child(itsProxy->mapToSource(index.child(ch, 0))); if(child.isValid() && (static_cast(child.internalPointer()))->isFont()) { CFontItem *font=static_cast(child.internalPointer()); addFont(font, urls, fontNames, fonts, usedFonts, getEnabled, getDisabled); } } } } } fontNames=CFontList::compact(fontNames); } QSet CFontListView::getFiles() { QModelIndexList items(allIndexes()); QModelIndex index; QSet files; foreach(index, items) if(index.isValid()) { QModelIndex realIndex(itsProxy->mapToSource(index)); if(realIndex.isValid()) if((static_cast(realIndex.internalPointer()))->isFont()) { CFontItem *font=static_cast(realIndex.internalPointer()); FileCont::ConstIterator it(font->files().begin()), end(font->files().end()); for(; it!=end; ++it) { QStringList assoc; files.insert((*it).path()); Misc::getAssociatedFiles((*it).path(), assoc); QStringList::ConstIterator ait(assoc.constBegin()), aend(assoc.constEnd()); for(; ait!=aend; ++ait) files.insert(*ait); } } } return files; } void CFontListView::getPrintableFonts(QSet &items, bool selected) { QModelIndexList selectedItems(selected ? selectedIndexes() : allIndexes()); QModelIndex index; foreach(index, selectedItems) { CFontItem *font=NULL; if(index.isValid() && 0==index.column()) { QModelIndex realIndex(itsProxy->mapToSource(index)); if(realIndex.isValid()) { if((static_cast(realIndex.internalPointer()))->isFont()) font=static_cast(realIndex.internalPointer()); else { CFamilyItem *fam=static_cast(realIndex.internalPointer()); font=fam->regularFont(); } } } if(font && !font->isBitmap() && font->isEnabled()) items.insert(Misc::TFont(font->family(), font->styleInfo())); } } void CFontListView::setFilterGroup(CGroupListItem *grp) { CGroupListItem *oldGrp(itsProxy->filterGroup()); itsProxy->setFilterGroup(grp); itsAllowDrops=grp && !grp->isCustom(); if(!Misc::root()) { bool refreshStats(false); if(!grp || !oldGrp) refreshStats=true; else { // Check to see whether we have changed from listing all fonts, // listing just system or listing personal fonts. CGroupListItem::EType aType(CGroupListItem::CUSTOM==grp->type() || CGroupListItem::ALL==grp->type() || CGroupListItem::UNCLASSIFIED==grp->type() ? CGroupListItem::CUSTOM : grp->type()), bType(CGroupListItem::CUSTOM==oldGrp->type() || CGroupListItem::ALL==oldGrp->type() || CGroupListItem::UNCLASSIFIED==oldGrp->type() ? CGroupListItem::CUSTOM : oldGrp->type()); refreshStats=aType!=bType; } if(refreshStats) itsModel->refresh(!grp || !grp->isPersonal(), !grp || !grp->isSystem()); } // when switching groups, for some reason it is not always sorted. setSortingEnabled(true); } void CFontListView::listingPercent(int percent) { // when the font list is first loaded, for some reason it is not always sorted. // re-enabling sorting here seems to fix the issue - BUG 221610 if(100==percent) setSortingEnabled(true); } void CFontListView::refreshFilter() { itsProxy->clear(); } void CFontListView::filterText(const QString &text) { itsProxy->setFilterText(text); } void CFontListView::filterCriteria(int crit, qulonglong ws, const QStringList &ft) { itsProxy->setFilterCriteria((CFontFilter::ECriteria)crit, ws, ft); } void CFontListView::stats(int &enabled, int &disabled, int &partial) { enabled=disabled=partial=0; for(int i=0; irowCount(); ++i) { QModelIndex idx(itsProxy->index(i, 0, QModelIndex())); if(!idx.isValid()) break; QModelIndex sourceIdx(itsProxy->mapToSource(idx)); if(!sourceIdx.isValid()) break; if((static_cast(sourceIdx.internalPointer()))->isFamily()) switch((static_cast(sourceIdx.internalPointer()))->status()) { case CFamilyItem::ENABLED: enabled++; break; case CFamilyItem::DISABLED: disabled++; break; case CFamilyItem::PARTIAL: partial++; break; } } } void CFontListView::selectedStatus(bool &enabled, bool &disabled) { QModelIndexList selected(selectedIndexes()); QModelIndex index; enabled=disabled=false; foreach(index, selected) { QModelIndex realIndex(itsProxy->mapToSource(index)); if(realIndex.isValid()) { if((static_cast(realIndex.internalPointer()))->isFamily()) { switch((static_cast(realIndex.internalPointer()))->status()) { case CFamilyItem::ENABLED: enabled=true; break; case CFamilyItem::DISABLED: disabled=true; break; case CFamilyItem::PARTIAL: enabled=true; disabled=true; break; } } else { if((static_cast(realIndex.internalPointer()))->isEnabled()) enabled=true; else disabled=true; } } if(enabled && disabled) break; } } QModelIndexList CFontListView::allFonts() { QModelIndexList rv; int rowCount(itsProxy->rowCount()); for(int i=0; iindex(i, 0, QModelIndex())); int childRowCount(itsProxy->rowCount(idx)); for(int j=0; jindex(j, 0, idx)); if(child.isValid()) rv.append(itsProxy->mapToSource(child)); } } return rv; } void CFontListView::selectFirstFont() { if(0==selectedIndexes().count()) for(int i=0; iindex(0, i, QModelIndex())); if(idx.isValid()) selectionModel()->select(idx, QItemSelectionModel::Select); } } void CFontListView::setSortColumn(int col) { if(col!=itsProxy->filterKeyColumn()) { itsProxy->setFilterKeyColumn(col); itsProxy->clear(); } } void CFontListView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { QAbstractItemView::selectionChanged(selected, deselected); if(itsModel->slowUpdates()) return; emit itemsSelected(getSelectedItems()); } QModelIndexList CFontListView::getSelectedItems() { // // Go throgh current selection, and for any 'font' items that are selected, // ensure 'family' item is not... QModelIndexList selectedItems(selectedIndexes()), deselectList; QModelIndex index; QSet selectedFamilies; bool en(false), dis(false); foreach(index, selectedItems) if(index.isValid()) { QModelIndex realIndex(itsProxy->mapToSource(index)); if(realIndex.isValid()) { if((static_cast(realIndex.internalPointer()))->isFont()) { CFontItem *font=static_cast(realIndex.internalPointer()); if(font->isEnabled()) en=true; else dis=true; if(!selectedFamilies.contains(font->parent())) { selectedFamilies.insert(font->parent()); for(int i=0; imapFromSource( itsModel->createIndex(font->parent()->rowNumber(), i, font->parent()))); } } else { switch((static_cast(realIndex.internalPointer()))->status()) { case CFamilyItem::ENABLED: en=true; break; case CFamilyItem::DISABLED: dis=true; break; case CFamilyItem::PARTIAL: en=dis=true; break; } } } } if(deselectList.count()) foreach(index, deselectList) selectionModel()->select(index, QItemSelectionModel::Deselect); QModelIndexList sel; QSet pointers; selectedItems=selectedIndexes(); foreach(index, selectedItems) { QModelIndex idx(itsProxy->mapToSource(index)); if(!pointers.contains(idx.internalPointer())) { pointers.insert(idx.internalPointer()); sel.append(idx); } } return sel; } void CFontListView::itemCollapsed(const QModelIndex &idx) { if(idx.isValid()) { QModelIndex index(itsProxy->mapToSource(idx)); if(index.isValid() && (static_cast(index.internalPointer()))->isFamily()) { CFamilyItem *fam=static_cast(index.internalPointer()); CFontItemCont::ConstIterator it(fam->fonts().begin()), end(fam->fonts().end()); for(; it!=end; ++it) for(int i=0; iselect(itsProxy->mapFromSource(itsModel->createIndex((*it)->rowNumber(), i, *it)), QItemSelectionModel::Deselect); } } } static bool isScalable(const QString &str) { QByteArray cFile(QFile::encodeName(str)); return Misc::checkExt(cFile, "ttf") || Misc::checkExt(cFile, "otf") || Misc::checkExt(cFile, "ttc") || Misc::checkExt(cFile, "pfa") || Misc::checkExt(cFile, "pfb"); } void CFontListView::view() { // Number of fonts user has selected, before we ask if they really want to view them all... static const int constMaxBeforePrompt=10; QModelIndexList selectedItems(selectedIndexes()); QModelIndex index; QSet fonts; foreach(index, selectedItems) { QModelIndex realIndex(itsProxy->mapToSource(index)); if(realIndex.isValid()) { if((static_cast(realIndex.internalPointer()))->isFont()) { CFontItem *font(static_cast(realIndex.internalPointer())); fonts.insert(font); } else { CFontItem *font((static_cast(realIndex.internalPointer()))->regularFont()); if(font) fonts.insert(font); } } } if(fonts.count() && (fonts.count()::ConstIterator it(fonts.begin()), end(fonts.end()); QStringList args; for(; it!=end; ++it) { QString file; int index(0); if(!(*it)->isEnabled()) { // For a disabled font, we need to find the first scalable font entry in its file list... FileCont::ConstIterator fit((*it)->files().begin()), fend((*it)->files().end()); for(; fit!=fend; ++fit) if(isScalable((*fit).path())) { file=(*fit).path(); index=(*fit).index(); break; } if(file.isEmpty()) { file=(*it)->fileName(); index=(*it)->index(); } } args << FC::encode((*it)->family(), (*it)->styleInfo(), file, index).url(); } QProcess::startDetached(Misc::app(KFI_VIEWER), args); } } QModelIndexList CFontListView::allIndexes() { QModelIndexList rv; int rowCount(itsProxy->rowCount()); for(int i=0; iindex(i, 0, QModelIndex())); int childRowCount(itsProxy->rowCount(idx)); rv.append(idx); for(int j=0; jindex(j, 0, idx)); if(child.isValid()) rv.append(child); } } return rv; } void CFontListView::startDrag(Qt::DropActions supportedActions) { QModelIndexList indexes(selectedIndexes()); if (indexes.count()) { QMimeData *data = model()->mimeData(indexes); if (!data) return; QModelIndex index(itsProxy->mapToSource(indexes.first())); const char *icon="application-x-font-pcf"; if(index.isValid()) { CFontItem *font=(static_cast(index.internalPointer()))->isFont() ? static_cast(index.internalPointer()) : (static_cast(index.internalPointer()))->regularFont(); if(font && !font->isBitmap()) // if("application/x-font-type1"==font->mimetype()) // icon="application-x-font-type1"; // else icon="application-x-font-ttf"; } QPoint hotspot; QPixmap pix(DesktopIcon(icon, KIconLoader::SizeMedium)); hotspot.setX(0); // pix.width()/2); hotspot.setY(0); // pix.height()/2); QDrag *drag = new QDrag(this); drag->setPixmap(pix); drag->setMimeData(data); drag->setHotSpot(hotspot); drag->start(supportedActions); } } void CFontListView::dragEnterEvent(QDragEnterEvent *event) { if(itsAllowDrops && event->mimeData()->hasFormat("text/uri-list")) // "application/x-kde-urilist" ?? event->acceptProposedAction(); } void CFontListView::dropEvent(QDropEvent *event) { if(itsAllowDrops && event->mimeData()->hasFormat("text/uri-list")) { event->acceptProposedAction(); QList urls(event->mimeData()->urls()); QList::ConstIterator it(urls.begin()), end(urls.end()); QSet kurls; QMimeDatabase db; for (; it!=end; ++it) { QMimeType mime = db.mimeTypeForUrl(*it); foreach (const QString &fontMime, CFontList::fontMimeTypes) { if (mime.inherits(fontMime)) { kurls.insert(*it); break; } } } if(kurls.count()) emit fontsDropped(kurls); } } void CFontListView::contextMenuEvent(QContextMenuEvent *ev) { bool valid(indexAt(ev->pos()).isValid()); itsDeleteAct->setEnabled(valid); bool en(false), dis(false); QModelIndexList selectedItems(selectedIndexes()); QModelIndex index; foreach(index, selectedItems) { QModelIndex realIndex(itsProxy->mapToSource(index)); if(realIndex.isValid()) { if((static_cast(realIndex.internalPointer()))->isFont()) { if((static_cast(realIndex.internalPointer())->isEnabled())) en=true; else dis=true; } else { switch((static_cast(realIndex.internalPointer()))->status()) { case CFamilyItem::ENABLED: en=true; break; case CFamilyItem::DISABLED: dis=true; break; case CFamilyItem::PARTIAL: en=dis=true; break; } } } if(en && dis) break; } itsEnableAct->setEnabled(dis); itsDisableAct->setEnabled(en); if(itsPrintAct) itsPrintAct->setEnabled(en|dis); if(itsViewAct) itsViewAct->setEnabled(en|dis); itsMenu->popup(ev->globalPos()); } bool CFontListView::viewportEvent(QEvent *event) { executeDelayedItemsLayout(); return QTreeView::viewportEvent(event); } } diff --git a/kcms/kfontinst/lib/Misc.cpp b/kcms/kfontinst/lib/Misc.cpp index d722cc7df..a201b06af 100644 --- a/kcms/kfontinst/lib/Misc.cpp +++ b/kcms/kfontinst/lib/Misc.cpp @@ -1,492 +1,493 @@ /* * 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 "Misc.h" #include "config-paths.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace KFI { namespace Misc { QString prettyUrl(const QUrl &url) { QString u(url.url()); u.replace("%20", " "); return u; } QString dirSyntax(const QString &d) { if(!d.isEmpty()) { QString ds(d); ds.replace("//", "/"); int slashPos(ds.lastIndexOf('/')); if(slashPos!=(((int)ds.length())-1)) ds.append('/'); return ds; } return d; } QString fileSyntax(const QString &d) { if(!d.isEmpty()) { QString ds(d); ds.replace("//", "/"); int slashPos(ds.lastIndexOf('/')); if(slashPos==(((int)ds.length())-1)) ds.remove(slashPos, 1); return ds; } return d; } QString getDir(const QString &f) { QString d(f); int slashPos(d.lastIndexOf('/')); if(slashPos!=-1) d.remove(slashPos+1, d.length()); return dirSyntax(d); } QString getFile(const QString &f) { QString d(f); int slashPos=d.lastIndexOf('/'); if(slashPos!=-1) d.remove(0, slashPos+1); return d; } bool createDir(const QString &dir) { if (!QDir().mkpath(dir)) return false; // // Clear any umask before setting dir perms mode_t oldMask(umask(0000)); const QByteArray d = QFile::encodeName(dir); ::chmod(d.constData(), DIR_PERMS); // Reset umask ::umask(oldMask); return true; } void setFilePerms(const QByteArray &f) { // // Clear any umask before setting file perms mode_t oldMask(umask(0000)); ::chmod(f.constData(), FILE_PERMS); // Reset umask ::umask(oldMask); } bool doCmd(const QString &cmd, const QString &p1, const QString &p2, const QString &p3) { QStringList args; if(!p1.isEmpty()) args << p1; if(!p2.isEmpty()) args << p2; if(!p3.isEmpty()) args << p3; return 0==QProcess::execute(cmd, args); } QString changeExt(const QString &f, const QString &newExt) { QString newStr(f); int dotPos(newStr.lastIndexOf('.')); if(-1==dotPos) newStr+=QChar('.')+newExt; else { newStr.remove(dotPos+1, newStr.length()); newStr+=newExt; } return newStr; } // // Get a list of files associated with a file, e.g.: // // File: /home/a/courier.pfa // // Associated: /home/a/courier.afm /home/a/courier.pfm // void getAssociatedFiles(const QString &path, QStringList &files, bool afmAndPfm) { QString ext(path); int dotPos(ext.lastIndexOf('.')); bool check(false); if(-1==dotPos) // Hmm, no extension - check anyway... check=true; else // Cool, got an extension - see if it is a Type1 font... { ext=ext.mid(dotPos+1); check=0==ext.compare("pfa", Qt::CaseInsensitive) || 0==ext.compare("pfb", Qt::CaseInsensitive); } if(check) { const char *afm[]={"afm", "AFM", "Afm", NULL}, *pfm[]={"pfm", "PFM", "Pfm", NULL}; bool gotAfm(false); int e; for(e=0; afm[e]; ++e) { QString statFile(changeExt(path, afm[e])); if(fExists(statFile)) { files.append(statFile); gotAfm=true; break; } } if(afmAndPfm || !gotAfm) for(e=0; pfm[e]; ++e) { QString statFile(changeExt(path, pfm[e])); if(fExists(statFile)) { files.append(statFile); break; } } } } time_t getTimeStamp(const QString &item) { QT_STATBUF info; return !item.isEmpty() && 0==QT_LSTAT(QFile::encodeName(item), &info) ? info.st_mtime : 0; } bool check(const QString &path, bool file, bool checkW) { QT_STATBUF info; QByteArray pathC(QFile::encodeName(path)); return 0==QT_LSTAT(pathC, &info) && (file ? (S_ISREG(info.st_mode) || S_ISLNK(info.st_mode)) : S_ISDIR(info.st_mode)) && (!checkW || 0==::access(pathC, W_OK)); } QString getFolder(const QString &defaultDir, const QString &root, QStringList &dirs) { if(dirs.contains(defaultDir)) return defaultDir; else { QStringList::const_iterator it, end=dirs.constEnd(); bool found=false; for(it=dirs.constBegin(); it!=end && !found; ++it) if(0==(*it).indexOf(root)) return *it; } return defaultDir; } bool checkExt(const QString &fname, const QString &ext) { QString extension('.'+ext); return fname.length()>extension.length() ? 0==fname.mid(fname.length()-extension.length()).compare(extension, Qt::CaseInsensitive) : false; } bool isBitmap(const QString &str) { return checkExt(str, "pcf") || checkExt(str, "bdf") || checkExt(str, "pcf.gz") || checkExt(str, "bdf.gz"); } bool isMetrics(const QString &str) { return checkExt(str, "afm") || checkExt(str, "pfm"); } int getIntQueryVal(const QUrl &url, const char *key, int defVal) { QUrlQuery query(url); QString item(query.queryItemValue(key)); int val(defVal); if(!item.isNull()) val=item.toInt(); return val; } bool printable(const QString &mime) { - return "application/x-font-type1"==mime || "application/x-font-ttf"==mime || + return "font/otf"==mime || "font/ttf"==mime || + "application/x-font-type1"==mime || "application/x-font-ttf"==mime || "application/x-font-otf"==mime || "application/x-font-type1"==mime; } uint qHash(const KFI::Misc::TFont &key) { //return qHash(QString(key.family+'%'+QString().setNum(key.styleInfo, 16))); const QChar *p = key.family.unicode(); int n = key.family.size(); uint h = 0, g; h = (h << 4) + key.styleInfo; if ((g = (h & 0xf0000000)) != 0) h ^= g >> 23; h &= ~g; while (n--) { h = (h << 4) + (*p++).unicode(); if ((g = (h & 0xf0000000)) != 0) h ^= g >> 23; h &= ~g; } return h; } // Taken from qdom.cpp QString encodeText(const QString &str, QTextStream &s) { const QTextCodec *const codec = s.codec(); Q_ASSERT(codec); QString retval(str); int len = retval.length(), i = 0; while (i < len) { const QChar ati(retval.at(i)); if (ati == QLatin1Char('<')) { retval.replace(i, 1, QLatin1String("<")); len += 3; i += 4; } else if (ati == QLatin1Char('"')) { retval.replace(i, 1, QLatin1String(""")); len += 5; i += 6; } else if (ati == QLatin1Char('&')) { retval.replace(i, 1, QLatin1String("&")); len += 4; i += 5; } else if (ati == QLatin1Char('>') && i >= 2 && retval[i - 1] == QLatin1Char(']') && retval[i - 2] == QLatin1Char(']')) { retval.replace(i, 1, QLatin1String(">")); len += 3; i += 4; } else { if(codec->canEncode(ati)) ++i; else { // We have to use a character reference to get it through. const ushort codepoint(ati.unicode()); const QString replacement(QLatin1String("&#x") + QString::number(codepoint, 16) + QLatin1Char(';')); retval.replace(i, 1, replacement); i += replacement.length(); len += replacement.length() - 1; } } } return retval; } QString contractHome(QString path) { if (!path.isEmpty() && '/'==path[0]) { QString home(QDir::homePath()); if(path.startsWith(home)) { int len = home.length(); if(len>1 && (path.length() == len || path[len] == '/')) return path.replace(0, len, QString::fromLatin1("~")); } } return path; } QString expandHome(QString path) { if(!path.isEmpty() && '~'==path[0]) return 1==path.length() ? QDir::homePath() : path.replace(0, 1, QDir::homePath()); return path; } QMap getFontFileMap(const QSet &files) { QMap map; QSet::ConstIterator it=files.constBegin(), end=files.constEnd(); QMap > fontsFiles; for(;it!=end; ++it) fontsFiles[unhide(getFile(*it))].insert(getDir(*it)); QMap >::ConstIterator fIt(fontsFiles.constBegin()), fEnd(fontsFiles.constEnd()); for(; fIt!=fEnd; ++fIt) if(fIt.value().count()>1) { QVector orig(fIt.value().count()), modified(fIt.value().count()); QSet::ConstIterator oIt(fIt.value().constBegin()), oEnd(fIt.value().constEnd()); bool good=true; int count=fIt.value().count(); for(int i=0; i apps; if(!apps.contains(name)) { QStringList installPaths; if (qstrcmp(path, "libexec") == 0) installPaths.append(KFONTINST_LIBEXEC_DIR); apps[name] = QStandardPaths::findExecutable(name, installPaths); } return apps[name]; } } // Misc:: } // KFI:: diff --git a/kcms/kfontinst/thumbnail/FontThumbnail.cpp b/kcms/kfontinst/thumbnail/FontThumbnail.cpp index 52bfdb415..412272dd7 100644 --- a/kcms/kfontinst/thumbnail/FontThumbnail.cpp +++ b/kcms/kfontinst/thumbnail/FontThumbnail.cpp @@ -1,125 +1,125 @@ /* * 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 "FontThumbnail.h" #include "KfiConstants.h" #include "FcEngine.h" #include #include #include #include #include #include #include #include #include #include "debug.h" #define KFI_DBUG qCDebug(KCM_KFONTINST_THUMBNAIL) extern "C" { Q_DECL_EXPORT ThumbCreator *new_creator() { return new KFI::CFontThumbnail; } } namespace KFI { CFontThumbnail::CFontThumbnail() { } bool CFontThumbnail::create(const QString &path, int width, int height, QImage &img) { QString realPath(path); QTemporaryDir *tempDir = 0; KFI_DBUG << "Create font thumbnail for:" << path << endl; // Is this a appliaction/vnd.kde.fontspackage file? If so, extract 1 scalable font... QMimeDatabase db; if (Misc::isPackage(path) || "application/zip" == db.mimeTypeForFile(path, QMimeDatabase::MatchContent).name()) { KZip zip(path); if(zip.open(QIODevice::ReadOnly)) { const KArchiveDirectory *zipDir=zip.directory(); if(zipDir) { QStringList fonts(zipDir->entries()); if(fonts.count()) { QStringList::ConstIterator it(fonts.begin()), end(fonts.end()); for(; it!=end; ++it) { const KArchiveEntry *entry=zipDir->entry(*it); if(entry && entry->isFile()) { delete tempDir; tempDir=new QTemporaryDir(QDir::tempPath() + "/" KFI_TMP_DIR_PREFIX); tempDir->setAutoRemove(true); ((KArchiveFile *)entry)->copyTo(tempDir->path()); QString mime(db.mimeTypeForFile(tempDir->path()+QLatin1Char('/')+entry->name()).name()); - if(mime=="application/x-font-ttf" || mime=="application/x-font-otf" || - mime=="application/x-font-type1") + if(mime=="font/ttf" || mime=="font/otf" || mime=="application/x-font-ttf" || + mime=="application/x-font-otf" || mime=="application/x-font-type1") { realPath=tempDir->path()+QLatin1Char('/')+entry->name(); break; } else ::unlink(QFile::encodeName(tempDir->path()+QLatin1Char('/')+entry->name()).data()); } } } } } } QColor bgnd(Qt::black); bgnd.setAlpha(0); img=itsEngine.draw(realPath, KFI_NO_STYLE_INFO, 0, QApplication::palette().text().color(), bgnd, width, height, true); delete tempDir; return !img.isNull(); } ThumbCreator::Flags CFontThumbnail::flags() const { return None; } } diff --git a/kcms/kfontinst/thumbnail/fontthumbnail.desktop b/kcms/kfontinst/thumbnail/fontthumbnail.desktop index a2a86f797..4268ea126 100644 --- a/kcms/kfontinst/thumbnail/fontthumbnail.desktop +++ b/kcms/kfontinst/thumbnail/fontthumbnail.desktop @@ -1,97 +1,97 @@ [Desktop Entry] Type=Service Name=Font Files Name[af]=Skrif tipe Lêers Name[ar]=ملفّات الخطوط Name[be]=Файлы шрыфтоў Name[be@latin]=Fajły šryftoŭ Name[bg]=Файлове с шрифтове Name[bn]=ফন্ট ফাইল Name[bn_IN]=ফন্ট ফাইল Name[br]=Restroù Nodrezhoù Name[bs]=Datoteke fontova Name[ca]=Fitxers de tipus de lletra Name[ca@valencia]=Fitxers de tipus de lletra Name[cs]=Soubory s písmy Name[csb]=Lopczi fòntów Name[cy]=Ffeiliau Ffont Name[da]=Skrifttypefiler Name[de]=Schriftdateien Name[el]=Αρχεία γραμματοσειρών Name[en_GB]=Font Files Name[eo]=Tipardosieroj Name[es]=Archivos de tipos de letra Name[et]=Fondifailid Name[eu]=Letra-tipoen fitxategiak Name[fa]=پرونده قلمها Name[fi]=Fonttitiedostot Name[fr]=Fichiers de polices de caractères Name[fy]=Lettertypetriemmen Name[ga]=Comhaid Chló Name[gl]=Ficheiros de tipos de letra Name[gu]=ફોન્ટ ફાઇલો Name[he]=קבצי גופנים Name[hi]=फ़ॉन्ट फ़ाइलें Name[hne]=फोंट फाइल मन ल Name[hr]=Datoteke fontova Name[hsb]=Pismowe dataje Name[hu]=Betűtípusfájlok Name[ia]=Files de font Name[id]=Berkas Fonta Name[is]=Leturskrár Name[it]=File dei caratteri Name[ja]=フォントファイル Name[ka]=ფონტების ფაილები Name[kk]=Қаріп файлдары Name[km]=ឯកសារ​ពុម្ពអក្សរ Name[kn]=ಅಕ್ಷರಶೈಲಿ ಕಡತಗಳು Name[ko]=글꼴 파일 Name[ku]=Pelên Curetîpan Name[lt]=Šriftų failai Name[lv]=Fontu faili Name[mai]=फान्ट फाइलसभ Name[mk]=Датотеки со фонтови Name[ml]=അക്ഷരസഞ്ചയ ഫയലുകള്‍ Name[mr]=फॉन्ट फाईल्स Name[ms]=Fail Fon Name[nb]=Skriftfiler Name[nds]=Schriftoortdateien Name[ne]=फन्ट फाइल Name[nl]=Lettertypebestanden Name[nn]=Skriftfiler Name[oc]=Fichièrs de poliça Name[or]=ଅକ୍ଷରରୂପ ଫାଇଲଗୁଡ଼ିକ Name[pa]=ਫੋਂਟ ਫਾਈਲਾਂ Name[pl]=Pliki czcionek Name[pt]=Ficheiros de Tipos de Letra Name[pt_BR]=Arquivos de fonte Name[ro]=Fișiere font Name[ru]=Файлы шрифтов Name[se]=Fontafiillat Name[si]=අකුරු ගොනුව Name[sk]=Súbory písiem Name[sl]=Datoteke s pisavami Name[sr]=Фајлови фонтова Name[sr@ijekavian]=Фајлови фонтова Name[sr@ijekavianlatin]=Fajlovi fontova Name[sr@latin]=Fajlovi fontova Name[sv]=Teckensnittsfiler Name[ta]=மின்னெழுத்துக் கோப்புகள் Name[te]=ఫాంట్ ఫైళ్ళు Name[tg]=Файлҳои ҳарф Name[th]=แฟ้มแบบอักษรต่าง ๆ Name[tr]=Yazı Tipi Dosyaları Name[ug]=خەت نۇسخا ھۆججەتلەر Name[uk]=Файли шрифтів Name[uz]=Shrift-fayllari Name[uz@cyrillic]=Шрифт-файллари Name[vi]=Tập tin phông chữ Name[wa]=Fitchîs fontes Name[xh]=Iifayile Zohlobo lwamagama Name[x-test]=xxFont Filesxx Name[zh_CN]=字体文件 Name[zh_TW]=字型檔案 X-KDE-ServiceTypes=ThumbCreator -MimeType=application/x-font-ttf;application/x-font-type1;application/x-font-bdf;application/x-font-pcf;application/x-font-otf;fonts/package; +MimeType=application/x-font-ttf;application/x-font-type1;application/x-font-bdf;application/x-font-pcf;application/x-font-otf;fonts/package;font/ttf;font/otf; X-KDE-Library=fontthumbnail CacheThumbnail=true diff --git a/kcms/kfontinst/viewpart/FontViewPart.cpp b/kcms/kfontinst/viewpart/FontViewPart.cpp index 488c8d0c4..7138e9398 100644 --- a/kcms/kfontinst/viewpart/FontViewPart.cpp +++ b/kcms/kfontinst/viewpart/FontViewPart.cpp @@ -1,578 +1,578 @@ /* * 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 "FontViewPart.h" #include "Misc.h" #include "KfiConstants.h" #include "FcEngine.h" #include "PreviewSelectAction.h" #include "FontInstInterface.h" #include "FontInst.h" #include "config-workspace.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 "config-fontinst.h" // Enable the following to allow printing of non-installed fonts. Does not seem to work :-( //#define KFI_PRINT_APP_FONTS namespace KFI { static QString getFamily(const QString &font) { int commaPos=font.lastIndexOf(','); return -1==commaPos ? font : font.left(commaPos); } K_PLUGIN_FACTORY(CFontViewPartFactory, registerPlugin();) K_EXPORT_PLUGIN(CFontViewPartFactory("kfontview")) CFontViewPart::CFontViewPart(QWidget *parentWidget, QObject *parent, const QList &) : KParts::ReadOnlyPart(parent), itsConfig(KSharedConfig::openConfig()), itsProc(NULL), itsTempDir(NULL), itsInterface(new FontInstInterface()), itsOpening(false) { // create browser extension (for printing when embedded into browser) itsExtension = new BrowserExtension(this); itsFrame=new QFrame(parentWidget); QFrame *previewFrame=new QFrame(itsFrame); QWidget *controls=new QWidget(itsFrame); // QGroupBox *metaBox=new QGroupBox(i18n("Information:"), controls); itsFaceWidget=new QWidget(controls); QBoxLayout *mainLayout=new QBoxLayout(QBoxLayout::TopToBottom, itsFrame); QBoxLayout *previewLayout=new QBoxLayout(QBoxLayout::LeftToRight, previewFrame), *controlsLayout=new QBoxLayout(QBoxLayout::LeftToRight, controls), *faceLayout=new QBoxLayout(QBoxLayout::LeftToRight, itsFaceWidget); // QBoxLayout *metaLayout=new QBoxLayout(QBoxLayout::LeftToRight, metaBox); // itsMetaLabel=new QLabel(metaBox); // itsMetaLabel->setAlignment(Qt::AlignTop); // metaLayout->addWidget(itsMetaLabel); previewLayout->setMargin(0); previewLayout->setSpacing(0); faceLayout->setMargin(0); controlsLayout->setMargin(0); previewLayout->setSpacing(0); itsFrame->setFrameShape(QFrame::NoFrame); itsFrame->setFocusPolicy(Qt::ClickFocus); previewFrame->setFrameShape(QFrame::StyledPanel); previewFrame->setFrameShadow(QFrame::Sunken); KAboutData aboutData(KFI_NAME, i18n("FontViewPart"), WORKSPACE_VERSION_STRING); setComponentData(aboutData); itsPreview=new CFontPreview(previewFrame); itsPreview->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); itsFaceLabel=new QLabel(i18n("Show Face:"), itsFaceWidget); itsFaceSelector=new QSpinBox(itsFaceWidget); itsFaceSelector->setValue(1); itsInstallButton=new QPushButton(i18n("Install..."), controls); itsInstallButton->setEnabled(false); previewLayout->addWidget(itsPreview); faceLayout->addWidget(itsFaceLabel); faceLayout->addWidget(itsFaceSelector); faceLayout->addItem(new QSpacerItem(faceLayout->spacing(), 0, QSizePolicy::Fixed, QSizePolicy::Fixed)); itsFaceWidget->hide(); itsPreview->engine()->readConfig(*itsConfig); //controlsLayout->addWidget(metaBox); //controlsLayout->addStretch(2); controlsLayout->addWidget(itsFaceWidget); controlsLayout->addStretch(1); controlsLayout->addWidget(itsInstallButton); mainLayout->addWidget(previewFrame); mainLayout->addWidget(controls); connect(itsPreview, SIGNAL(status(bool)), SLOT(previewStatus(bool))); connect(itsInstallButton, SIGNAL(clicked()), SLOT(install())); connect(itsFaceSelector, SIGNAL(valueChanged(int)), SLOT(showFace(int))); itsChangeTextAction=actionCollection()->addAction("changeText"); itsChangeTextAction->setIcon(QIcon::fromTheme("edit-rename")); itsChangeTextAction->setText(i18n("Change Text...")); connect(itsChangeTextAction, SIGNAL(triggered(bool)), SLOT(changeText())); CPreviewSelectAction *displayTypeAction=new CPreviewSelectAction(this, CPreviewSelectAction::BlocksAndScripts); actionCollection()->addAction("displayType", displayTypeAction); connect(displayTypeAction, SIGNAL(range(QList)), SLOT(displayType(QList))); QAction *zoomIn=actionCollection()->addAction(KStandardAction::ZoomIn, itsPreview, SLOT(zoomIn())), *zoomOut=actionCollection()->addAction(KStandardAction::ZoomOut, itsPreview, SLOT(zoomOut())); connect(itsPreview, SIGNAL(atMax(bool)), zoomIn, SLOT(setDisabled(bool))); connect(itsPreview, SIGNAL(atMin(bool)), zoomOut, SLOT(setDisabled(bool))); setXMLFile("kfontviewpart.rc"); setWidget(itsFrame); itsExtension->enablePrint(false); FontInst::registerTypes(); connect(itsInterface, SIGNAL(status(int,int)), SLOT(dbusStatus(int,int))); connect(itsInterface, SIGNAL(fontStat(int,KFI::Family)), SLOT(fontStat(int,KFI::Family))); } CFontViewPart::~CFontViewPart() { delete itsTempDir; itsTempDir=NULL; delete itsInterface; itsInterface=NULL; } static inline QUrl mostLocalUrl(const QUrl &url, QWidget *widget) { auto job = KIO::mostLocalUrl(url); KJobWidgets::setWindow(job, widget); job->exec(); return job->mostLocalUrl(); } bool CFontViewPart::openUrl(const QUrl &url) { if (!url.isValid() || !closeUrl()) return false; // itsMetaLabel->setText(QString()); // itsMetaInfo.clear(); itsFontDetails=FC::decode(url); if(!itsFontDetails.family.isEmpty() || KFI_KIO_FONTS_PROTOCOL==url.scheme() || mostLocalUrl(url, itsFrame).isLocalFile()) { setUrl(url); emit started(0); setLocalFilePath(this->url().path()); bool ret=openFile(); if (ret) emit completed(); return ret; } else return ReadOnlyPart::openUrl(url); } bool CFontViewPart::openFile() { // NOTE: Can't do the real open here, as we don't seem to be able to use KIO::NetAccess functions // during initial start-up. Bug report 111535 indicates that calling "konqueror " crashes. itsInstallButton->setEnabled(false); QTimer::singleShot(0, this, SLOT(timeout())); return true; } static inline bool statUrl(const QUrl &url, KIO::UDSEntry *udsEntry) { auto job = KIO::stat(url); job->exec(); if (job->error()) return false; *udsEntry = job->statResult(); return true; } void CFontViewPart::timeout() { if(!itsInstallButton) return; bool isFonts(KFI_KIO_FONTS_PROTOCOL==url().scheme()), showFs(false), package(false); int fileIndex(-1); QString fontFile; // itsMetaUrl=url(); delete itsTempDir; itsTempDir=NULL; itsOpening=true; if(!itsFontDetails.family.isEmpty()) { emit setWindowCaption(FC::createName(itsFontDetails.family, itsFontDetails.styleInfo)); fontFile=FC::getFile(url()); fileIndex=FC::getIndex(url()); } else if(isFonts) { KIO::UDSEntry udsEntry; bool found = statUrl(url(), &udsEntry); if(!found) { // Check if url is "fonts:/ if so try fonts:/System/, then fonts:/Personal QStringList pathList(url().adjusted(QUrl::StripTrailingSlash).path().split('/', QString::SkipEmptyParts)); if(pathList.count()==1) { found = statUrl(QUrl(QString("fonts:/"+i18n(KFI_KIO_FONTS_SYS)+'/'+pathList[0])), &udsEntry); if (!found) found = statUrl(QUrl(QString("fonts:/"+i18n(KFI_KIO_FONTS_USER)+'/'+pathList[0])), &udsEntry); } } if(found) { if(udsEntry.numberValue(KIO::UDSEntry::UDS_HIDDEN, 0)) { fontFile=udsEntry.stringValue(UDS_EXTRA_FILE_NAME); fileIndex=udsEntry.numberValue(UDS_EXTRA_FILE_FACE, 0); } itsFontDetails.family=getFamily(udsEntry.stringValue(KIO::UDSEntry::UDS_NAME)); itsFontDetails.styleInfo=udsEntry.numberValue(UDS_EXTRA_FC_STYLE); emit setWindowCaption(udsEntry.stringValue(KIO::UDSEntry::UDS_NAME)); } else { previewStatus(false); return; } } else { QString path(localFilePath()); // Is this a application/vnd.kde.fontspackage file? If so, extract 1 scalable font... if((package=Misc::isPackage(path))) { KZip zip(path); if(zip.open(QIODevice::ReadOnly)) { const KArchiveDirectory *zipDir=zip.directory(); if(zipDir) { QStringList fonts(zipDir->entries()); if(fonts.count()) { QStringList::ConstIterator it(fonts.begin()), end(fonts.end()); for(; it!=end; ++it) { const KArchiveEntry *entry=zipDir->entry(*it); if(entry && entry->isFile()) { delete itsTempDir; itsTempDir=new QTemporaryDir(QDir::tempPath() + "/" KFI_TMP_DIR_PREFIX); itsTempDir->setAutoRemove(true); ((KArchiveFile *)entry)->copyTo(itsTempDir->path()); QMimeDatabase db; QString mime(db.mimeTypeForFile(itsTempDir->path()+QLatin1Char('/')+entry->name()).name()); - if(mime=="application/x-font-ttf" || mime=="application/x-font-otf" || - mime=="application/x-font-type1") + if(mime=="font/ttf" || mime=="font/otf" || mime=="application/x-font-ttf" || + mime=="application/x-font-otf" || mime=="application/x-font-type1") { fontFile=itsTempDir->path()+QLatin1Char('/')+entry->name(); //setLocalFilePath(itsTempDir->path()+QLatin1Char('/')+entry->name()); // itsMetaUrl=QUrl::fromLocalFile(localFilePath()); break; } else ::unlink(QFile::encodeName(itsTempDir->path()+QLatin1Char('/')+entry->name()).data()); } } } } } } } itsInstallButton->setEnabled(false); if(itsFontDetails.family.isEmpty()) emit setWindowCaption(url().toDisplayString()); else FcInitReinitialize(); itsPreview->showFont(!package && itsFontDetails.family.isEmpty() ? localFilePath() : fontFile.isEmpty() ? itsFontDetails.family : fontFile, itsFontDetails.styleInfo, fileIndex); if(!isFonts && itsPreview->engine()->getNumIndexes()>1) { showFs=true; itsFaceSelector->setRange(1, itsPreview->engine()->getNumIndexes()); itsFaceSelector->setSingleStep(1); itsFaceSelector->blockSignals(true); itsFaceSelector->setValue(1); itsFaceSelector->blockSignals(false); } itsFaceWidget->setVisible(showFs); } void CFontViewPart::previewStatus(bool st) { if(itsOpening) { bool printable(false); if(st) { checkInstallable(); if(Misc::app(KFI_PRINTER).isEmpty()) printable=false; if(KFI_KIO_FONTS_PROTOCOL==url().scheme()) printable=!Misc::isHidden(url()); else if(!FC::decode(url()).family.isEmpty()) printable=!Misc::isHidden(FC::getFile(url())); #ifdef KFI_PRINT_APP_FONTS else { // TODO: Make this work! Plus, printing of disabled TTF/OTF's should also be possible! KMimeType::Ptr mime=KMimeType::findByUrl(QUrl::fromLocalFile(localFilePath()), 0, false, true); printable=mime->is("application/x-font-ttf") || mime->is("application/x-font-otf"); } #endif } itsExtension->enablePrint(st && printable); itsOpening=false; } itsChangeTextAction->setEnabled(st); // if(st) // getMetaInfo(itsFaceSelector->isVisible() && itsFaceSelector->value()>0 // ? itsFaceSelector->value()-1 : 0); // else if(!st) KMessageBox::error(itsFrame, i18n("Could not read font.")); } void CFontViewPart::install() { if(!itsProc || QProcess::NotRunning==itsProc->state()) { QStringList args; if(!itsProc) itsProc=new QProcess(this); else itsProc->kill(); QString title = QGuiApplication::applicationDisplayName(); if (title.isEmpty()) title = QCoreApplication::applicationName(); args << "--embed" << QString().sprintf("0x%x", (unsigned int)(itsFrame->window()->winId())) << "--qwindowtitle" << title << "--qwindowicon" << "kfontview" << url().toDisplayString(); connect(itsProc, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(installlStatus())); itsProc->start(Misc::app(KFI_INSTALLER), args); itsInstallButton->setEnabled(false); } } void CFontViewPart::installlStatus() { checkInstallable(); } void CFontViewPart::dbusStatus(int pid, int status) { if(pid==getpid() && FontInst::STATUS_OK!=status) itsInstallButton->setEnabled(false); } void CFontViewPart::fontStat(int pid, const KFI::Family &font) { if(pid==getpid()) itsInstallButton->setEnabled(!Misc::app(KFI_INSTALLER).isEmpty() && font.styles().count()==0); } void CFontViewPart::changeText() { bool status; QString oldStr(itsPreview->engine()->getPreviewString()), newStr(QInputDialog::getText(itsFrame, i18n("Preview String"), i18n("Please enter new string:"), QLineEdit::Normal, oldStr, &status)); if(status && newStr!=oldStr) { itsPreview->engine()->setPreviewString(newStr); itsPreview->engine()->writeConfig(*itsConfig); itsPreview->showFont(); } } void CFontViewPart::print() { QStringList args; QString title = QGuiApplication::applicationDisplayName(); if (title.isEmpty()) title = QCoreApplication::applicationName(); if(!itsFontDetails.family.isEmpty()) { args << "--embed" << QString().sprintf("0x%x", (unsigned int)(itsFrame->window()->winId())) << "--qwindowtitle" << title << "--qwindowicon" << "kfontview" << "--size" << "0" << "--pfont" << QString(itsFontDetails.family+','+QString().setNum(itsFontDetails.styleInfo)); } #ifdef KFI_PRINT_APP_FONTS else args << "--embed" << QString().sprintf("0x%x", (unsigned int)(itsFrame->window()->winId())) << "--qwindowtitle" << title << "--qwindowicon" << "kfontview" << "--size " << "0" << localFilePath() << QString().setNum(KFI_NO_STYLE_INFO); #endif if(args.count()) QProcess::startDetached(Misc::app(KFI_PRINTER), args); } void CFontViewPart::displayType(const QList &range) { itsPreview->setUnicodeRange(range); itsChangeTextAction->setEnabled(0==range.count()); } void CFontViewPart::showFace(int face) { itsPreview->showFace(face-1); } void CFontViewPart::checkInstallable() { if(itsFontDetails.family.isEmpty()) { if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(OrgKdeFontinstInterface::staticInterfaceName())) QProcess::startDetached(QLatin1String(KFONTINST_LIB_EXEC_DIR"/fontinst"), QStringList()); itsInstallButton->setEnabled(false); itsInterface->statFont(itsPreview->engine()->descriptiveName(), FontInst::SYS_MASK|FontInst::USR_MASK, getpid()); } } #if 0 void CFontViewPart::getMetaInfo(int face) { if(itsMetaInfo[face].isEmpty()) { // Pass as much inofmration as possible to analyzer... if(KFI_KIO_FONTS_PROTOCOL!=itsMetaUrl.protocol()) { itsMetaUrl.removeQueryItem(KFI_KIO_FACE); if(face>0) itsMetaUrl.addQueryItem(KFI_KIO_FACE, QString().setNum(face)); } KFileMetaInfo meta(itsMetaUrl); if(meta.isValid() && meta.keys().count()) { QStringList keys(meta.keys()); QStringList::const_iterator it(keys.begin()), end(keys.end()); itsMetaInfo[face]=""; for(; it!=end; ++it) { KFileMetaInfoItem mi(meta.item(*it)); itsMetaInfo[face]+=""; } itsMetaInfo[face]+="
"+mi.name()+"
"+ mi.value().toString()+"
"; itsMetaLabel->setText(itsMetaInfo[face]); } else itsMetaLabel->setText(i18n("

No information

")); } else itsMetaLabel->setText(itsMetaInfo[face]); } #endif BrowserExtension::BrowserExtension(CFontViewPart *parent) : KParts::BrowserExtension(parent) { setURLDropHandlingEnabled(true); } void BrowserExtension::enablePrint(bool enable) { if(enable!=isActionEnabled("print") && (!enable || !Misc::app(KFI_PRINTER).isEmpty())) emit enableAction("print", enable); } void BrowserExtension::print() { if(!Misc::app(KFI_PRINTER).isEmpty()) static_cast(parent())->print(); } } #include "FontViewPart.moc"