KDEUI
kfontcombobox.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kfontcombobox.h"
00022 #include "fonthelpers_p.h"
00023
00024 #include "kdebug.h"
00025 #include "klocale.h"
00026 #include "kcolorscheme.h"
00027 #include "kglobalsettings.h"
00028 #include "kfontchooser.h"
00029 #include "kcompletion.h"
00030
00031 #include <QEvent>
00032 #include <QListView>
00033 #include <QFontDatabase>
00034 #include <QIcon>
00035 #include <QAbstractItemDelegate>
00036 #include <QStringListModel>
00037 #include <QPainter>
00038 #include <QList>
00039 #include <QHash>
00040 #include <QScrollBar>
00041
00042 static QString alphabetSample ()
00043 {
00044 return i18nc("short",
00045
00046
00047
00048
00049 "The Quick Brown Fox Jumps Over The Lazy Dog");
00050 }
00051
00052 class KFontFamilyDelegate : public QAbstractItemDelegate
00053 {
00054 Q_OBJECT
00055 public:
00056 explicit KFontFamilyDelegate (QObject *parent);
00057
00058 void paint (QPainter *painter,
00059 const QStyleOptionViewItem &option,
00060 const QModelIndex &index) const;
00061
00062 QSize sizeHint (const QStyleOptionViewItem &option,
00063 const QModelIndex &index) const;
00064
00065 QIcon truetype;
00066 QIcon bitmap;
00067 double sizeFactFamily;
00068 double sizeFactSample;
00069
00070 QHash<QString, QString> fontFamilyTrMap;
00071 };
00072
00073 KFontFamilyDelegate::KFontFamilyDelegate (QObject *parent)
00074 : QAbstractItemDelegate(parent)
00075 {
00076 truetype = QIcon(QLatin1String(":/trolltech/styles/commonstyle/images/fonttruetype-16.png"));
00077 bitmap = QIcon(QLatin1String(":/trolltech/styles/commonstyle/images/fontbitmap-16.png"));
00078
00079
00080
00081 sizeFactFamily = 1.0;
00082 sizeFactSample = 1.0;
00083 }
00084
00085 void KFontFamilyDelegate::paint (QPainter *painter,
00086 const QStyleOptionViewItem &option,
00087 const QModelIndex &index) const
00088 {
00089 QBrush sampleBrush;
00090 if (option.state & QStyle::State_Selected) {
00091 painter->save();
00092 painter->setBrush(option.palette.highlight());
00093 painter->setPen(Qt::NoPen);
00094 painter->drawRect(option.rect);
00095 painter->setPen(QPen(option.palette.highlightedText(), 0));
00096 sampleBrush = option.palette.highlightedText();
00097 } else {
00098 sampleBrush = KColorScheme(QPalette::Normal).foreground(KColorScheme::InactiveText);
00099 }
00100
00101 QFont baseFont = KGlobalSettings::generalFont();
00102 QString trFontFamily = index.data(Qt::DisplayRole).toString();
00103 QString fontFamily = fontFamilyTrMap[trFontFamily];
00104
00105
00106 QList<QFontDatabase::WritingSystem> availableSystems = QFontDatabase().writingSystems(fontFamily);
00107
00108
00109
00110
00111 bool canShowLanguageSample = true;
00112 if (availableSystems.count() > 0) {
00113 canShowLanguageSample = false;
00114 QString scriptsSpec = i18nc("Numeric IDs of scripts for font previews",
00115
00116
00117
00118
00119
00120 "1");
00121 QStringList scriptStrIds = scriptsSpec.split(',');
00122 foreach (const QString &scriptStrId, scriptStrIds) {
00123 bool convOk;
00124 int ws = scriptStrId.toInt(&convOk);
00125 if ( convOk && ws > 0 && ws < QFontDatabase::WritingSystemsCount
00126 && availableSystems.contains(static_cast<QFontDatabase::WritingSystem>(ws))) {
00127 canShowLanguageSample = true;
00128 break;
00129 }
00130 }
00131 }
00132
00133
00134 const QIcon *icon = &bitmap;
00135 if (QFontDatabase().isSmoothlyScalable(fontFamily)) {
00136 icon = &truetype;
00137 }
00138 QRect r = option.rect;
00139 icon->paint(painter, r, Qt::AlignLeft|Qt::AlignTop);
00140
00141
00142 QSize actualSize = icon->actualSize(r.size());
00143 if (option.direction == Qt::RightToLeft) {
00144 r.setRight(r.right() - actualSize.width() - 4);
00145 } else {
00146 r.setLeft(r.left() + actualSize.width() + 4);
00147 }
00148
00149
00150 QFont oldPainterFont = painter->font();
00151 QFont familyFont = baseFont;
00152 familyFont.setPointSize(qRound(familyFont.pointSize() * sizeFactFamily));
00153 painter->setFont(familyFont);
00154 painter->drawText(r, Qt::AlignTop|Qt::AlignLeading|Qt::TextSingleLine, trFontFamily);
00155
00156
00157 int h = painter->fontMetrics().lineSpacing();
00158 r.setTop(r.top() + h);
00159
00160
00161
00162
00163 QString sample;
00164 if (canShowLanguageSample) {
00165 sample = alphabetSample();
00166 } else {
00167 foreach (const QFontDatabase::WritingSystem &ws, availableSystems) {
00168 sample += QFontDatabase::writingSystemSample(ws) + " ";
00169 if (sample.length() > 40) {
00170 break;
00171 }
00172 }
00173 sample = sample.trimmed();
00174 }
00175 QFont sampleFont;
00176 sampleFont.setFamily(fontFamily);
00177 sampleFont.setPointSize(qRound(sampleFont.pointSize() * sizeFactSample));
00178 painter->setFont(sampleFont);
00179 QPen oldPen = painter->pen();
00180 painter->setPen(sampleBrush.color());
00181 painter->drawText(r, Qt::AlignTop|Qt::AlignLeading|Qt::TextSingleLine, sample);
00182 painter->setFont(oldPainterFont);
00183 painter->setPen(oldPen);
00184
00185 if (option.state & QStyle::State_Selected) {
00186 painter->restore();
00187 }
00188 }
00189
00190 QSize KFontFamilyDelegate::sizeHint (const QStyleOptionViewItem &option,
00191 const QModelIndex &index) const
00192 {
00193 Q_UNUSED(option);
00194
00195 QFont baseFont = KGlobalSettings::generalFont();
00196 QString trFontFamily = index.data(Qt::DisplayRole).toString();
00197 QString fontFamily = fontFamilyTrMap[trFontFamily];
00198
00199 QFont familyFont = baseFont;
00200 familyFont.setPointSize(qRound(familyFont.pointSize() * sizeFactFamily));
00201 QFontMetrics familyMetrics(familyFont);
00202
00203 QFont sampleFont = baseFont;
00204 sampleFont.setFamily(fontFamily);
00205 sampleFont.setPointSize(qRound(sampleFont.pointSize() * sizeFactSample));
00206 QFontMetrics sampleMetrics(familyFont);
00207 QString sample = alphabetSample();
00208
00209
00210 return QSize(qMax(familyMetrics.width(trFontFamily), sampleMetrics.width(sample)),
00211 qRound(familyMetrics.lineSpacing() + sampleMetrics.lineSpacing() * 1.2));
00212 }
00213
00214 class KFontComboBoxPrivate
00215 {
00216 public:
00217 KFontComboBoxPrivate (KFontComboBox *parent);
00218 void updateDatabase ();
00219 void updateIndexToFont ();
00220 void _k_currentFontChanged (int index);
00221
00222 KFontComboBox *k;
00223 QFont currentFont;
00224 bool onlyFixed;
00225 bool signalsAllowed;
00226 KFontFamilyDelegate *delegate;
00227 QStringListModel *model;
00228 };
00229
00230 KFontComboBoxPrivate::KFontComboBoxPrivate (KFontComboBox *parent)
00231 {
00232 k = parent;
00233 currentFont = KGlobalSettings::generalFont();
00234 onlyFixed = false;
00235 signalsAllowed = true;
00236 }
00237
00238 void KFontComboBoxPrivate::updateDatabase ()
00239 {
00240 QStringList fontFamilies;
00241 KFontChooser::getFontList(fontFamilies,
00242 onlyFixed ? KFontChooser::FixedWidthFonts : 0);
00243
00244
00245 delegate->fontFamilyTrMap.clear();
00246 QStringList trFontFamilies =
00247 translateFontNameList(fontFamilies, &(delegate->fontFamilyTrMap));
00248
00249
00250 model->setStringList(trFontFamilies);
00251 KCompletion *completion = k->completionObject();
00252 if (completion) {
00253 completion->insertItems(trFontFamilies);
00254 completion->setIgnoreCase(true);
00255 }
00256 }
00257
00258 void KFontComboBoxPrivate::updateIndexToFont ()
00259 {
00260
00261 QString selectedFontFamily = QFontInfo(currentFont).family();
00262 QString trSelectedFontFamily = translateFontName(selectedFontFamily);
00263 const QStringList trFontFamilies = model->stringList();
00264 if (!trFontFamilies.count()) {
00265 return;
00266 }
00267
00268
00269 int index = 0;
00270 foreach (const QString &trFontFamily, trFontFamilies) {
00271 if (trSelectedFontFamily == trFontFamily) {
00272 break;
00273 }
00274 ++index;
00275 }
00276 if (index == trFontFamilies.count()) {
00277
00278 index = 0;
00279 currentFont = QFont(delegate->fontFamilyTrMap[trFontFamilies[0]]);
00280 emit k->currentFontChanged(currentFont);
00281 }
00282
00283
00284 signalsAllowed = false;
00285 k->setCurrentIndex(index);
00286 signalsAllowed = true;
00287 }
00288
00289 void KFontComboBoxPrivate::_k_currentFontChanged (int index)
00290 {
00291 if (!signalsAllowed) {
00292 return;
00293 }
00294
00295 QString trFontFamily = k->itemText(index);
00296 QString fontFamily = delegate->fontFamilyTrMap[trFontFamily];
00297 if (!fontFamily.isEmpty()) {
00298 currentFont = QFont(fontFamily);
00299 emit k->currentFontChanged(currentFont);
00300 } else {
00301
00302
00303 QStringList lst = model->stringList();
00304 lst.removeAll(trFontFamily);
00305 model->setStringList(lst);
00306 }
00307 }
00308
00309 KFontComboBox::KFontComboBox (QWidget *parent)
00310 : KComboBox(true, parent), d(new KFontComboBoxPrivate(this))
00311 {
00312
00313 setInsertPolicy(QComboBox::NoInsert);
00314
00315
00316 d->delegate = new KFontFamilyDelegate(this);
00317 setItemDelegate(d->delegate);
00318 d->model = new QStringListModel(this);
00319 setModel(d->model);
00320
00321
00322 connect(this, SIGNAL(currentIndexChanged(int)),
00323 this, SLOT(_k_currentFontChanged(int)));
00324
00325
00326 d->updateDatabase();
00327 d->updateIndexToFont();
00328 }
00329
00330 KFontComboBox::~KFontComboBox ()
00331 {
00332 delete d;
00333 }
00334
00335 void KFontComboBox::setOnlyFixed (bool onlyFixed)
00336 {
00337 if (onlyFixed != d->onlyFixed) {
00338 d->onlyFixed = onlyFixed;
00339 d->updateDatabase();
00340 }
00341 }
00342
00343 QFont KFontComboBox::currentFont () const
00344 {
00345 return d->currentFont;
00346 }
00347
00348 void KFontComboBox::setCurrentFont (const QFont &font)
00349 {
00350 if (font != d->currentFont) {
00351 d->currentFont = font;
00352 emit currentFontChanged(d->currentFont);
00353 d->updateIndexToFont();
00354 }
00355 }
00356
00357 bool KFontComboBox::event (QEvent *e)
00358 {
00359 if (e->type() == QEvent::Resize) {
00360 QListView *lview = qobject_cast<QListView*>(view());
00361 if (lview) {
00362 QString sample = alphabetSample();
00363
00364 if (sample.length() > 60) {
00365 sample = sample.left(57) + "...";
00366 }
00367 QFont approxFont = KGlobalSettings::generalFont();
00368 approxFont.setPointSize(qRound( approxFont.pointSize()
00369 * d->delegate->sizeFactSample));
00370 int widgetWidth = width();
00371 int sampleWidth = QFontMetrics(approxFont).width(sample);
00372 sampleWidth = qRound(sampleWidth * 1.1);
00373 int iconWidth = d->delegate->truetype.actualSize(size()).width();
00374 int vsbarWidth = 0;
00375 if (lview->verticalScrollBar()) {
00376 vsbarWidth = lview->verticalScrollBar()->width();
00377 }
00378 lview->window()->setFixedWidth( qMax(widgetWidth, sampleWidth)
00379 + iconWidth + vsbarWidth);
00380 }
00381 }
00382 return KComboBox::event(e);
00383 }
00384
00385 QSize KFontComboBox::sizeHint() const
00386 {
00387 QSize sz = KComboBox::sizeHint();
00388 QFontMetrics fm(KGlobalSettings::generalFont());
00389 sz.setWidth(fm.width("m") * 14);
00390 return sz;
00391 }
00392
00393 #include "kfontcombobox.moc"
00394 #include "moc_kfontcombobox.moc"
00395