mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 18:32:49 +00:00
1078 lines
36 KiB
C++
1078 lines
36 KiB
C++
/*
|
|
Copyright (C) 1996 Bernd Johannes Wuebben <wuebben@kde.org>
|
|
Copyright (c) 1999 Preston Brown <pbrown@kde.org>
|
|
Copyright (c) 1999 Mario Weilguni <mweilguni@kde.org>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library 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
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "kfontchooser.h"
|
|
#include "fonthelpers_p.h"
|
|
#include "sampleedit_p.h"
|
|
|
|
#include <QtGui/QCheckBox>
|
|
#include <QtGui/QLabel>
|
|
#include <QtGui/QLayout>
|
|
#include <QtGui/QSplitter>
|
|
#include <QtGui/QScrollBar>
|
|
#include <QtGui/QFontDatabase>
|
|
#include <QtGui/QGroupBox>
|
|
#include <kcharsets.h>
|
|
#include <kconfig.h>
|
|
#include <kdialog.h>
|
|
#include <kglobal.h>
|
|
#include <kglobalsettings.h>
|
|
#include <klineedit.h>
|
|
#include <klistwidget.h>
|
|
#include <klocale.h>
|
|
#include <kstandarddirs.h>
|
|
#include <kdebug.h>
|
|
#include <knuminput.h>
|
|
#include <kconfiggroup.h>
|
|
|
|
#include <cmath>
|
|
|
|
// When message extraction needs to be avoided.
|
|
#define I18NC_NOX i18nc
|
|
|
|
static int minimumListWidth( const QListWidget *list )
|
|
{
|
|
int w=0;
|
|
for( int i=0; i<list->count(); i++ )
|
|
{
|
|
int itemWidth = list->visualItemRect(list->item(i)).width();
|
|
// ...and add a space on both sides for not too tight look.
|
|
itemWidth += list->fontMetrics().width(' ') * 2;
|
|
w = qMax(w,itemWidth);
|
|
}
|
|
if( w == 0 ) { w = 40; }
|
|
w += list->frameWidth() * 2;
|
|
w += list->verticalScrollBar()->sizeHint().width();
|
|
return w;
|
|
}
|
|
|
|
static int minimumListHeight( const QListWidget *list, int numVisibleEntry )
|
|
{
|
|
int w = list->count() > 0 ? list->visualItemRect(list->item(0)).height() :
|
|
list->fontMetrics().lineSpacing();
|
|
|
|
if( w < 0 ) { w = 10; }
|
|
if( numVisibleEntry <= 0 ) { numVisibleEntry = 4; }
|
|
return ( w * numVisibleEntry + 2 * list->frameWidth() );
|
|
}
|
|
|
|
static QString formatFontSize(qreal size)
|
|
{
|
|
return KGlobal::locale()->formatNumber(size, (size == floor(size)) ? 0 : 1);
|
|
}
|
|
|
|
class KFontChooser::Private
|
|
{
|
|
public:
|
|
Private( KFontChooser* qq )
|
|
: q( qq )
|
|
{
|
|
m_palette.setColor(QPalette::Active, QPalette::Text, Qt::black);
|
|
m_palette.setColor(QPalette::Active, QPalette::Base, Qt::white);
|
|
signalsAllowed = true;
|
|
selectedSize = -1;
|
|
customSizeRow = -1;
|
|
}
|
|
|
|
// pointer to an optinally supplied list of fonts to
|
|
// inserted into the fontdialog font-family combo-box
|
|
// QStringList fontList;
|
|
|
|
void setFamilyBoxItems(const QStringList &fonts);
|
|
void fillFamilyListBox(bool onlyFixedFonts = false);
|
|
int nearestSizeRow(qreal val, bool customize);
|
|
qreal fillSizeList(const QList<qreal> &sizes = QList<qreal>());
|
|
qreal setupSizeListBox(const QString& family, const QString& style);
|
|
|
|
void setupDisplay();
|
|
QString styleIdentifier (const QFont &font);
|
|
|
|
void _k_toggled_checkbox();
|
|
void _k_family_chosen_slot(const QString&);
|
|
void _k_size_chosen_slot(const QString&);
|
|
void _k_style_chosen_slot(const QString&);
|
|
void _k_displaySample(const QFont &font);
|
|
void _k_showXLFDArea(bool);
|
|
void _k_size_value_slot(double);
|
|
|
|
KFontChooser *q;
|
|
|
|
QPalette m_palette;
|
|
bool signalsAllowed:1;
|
|
|
|
bool usingFixed:1;
|
|
|
|
KDoubleNumInput *sizeOfFont;
|
|
|
|
SampleEdit *sampleEdit;
|
|
KLineEdit *xlfdEdit;
|
|
|
|
QLabel *familyLabel;
|
|
QLabel *styleLabel;
|
|
QCheckBox *familyCheckbox;
|
|
QCheckBox *styleCheckbox;
|
|
QCheckBox *sizeCheckbox;
|
|
QLabel *sizeLabel;
|
|
KListWidget *familyListBox;
|
|
KListWidget *styleListBox;
|
|
KListWidget *sizeListBox;
|
|
QCheckBox *sizeIsRelativeCheckBox;
|
|
|
|
QFont selFont;
|
|
|
|
QString selectedStyle;
|
|
qreal selectedSize;
|
|
|
|
int customSizeRow;
|
|
QString standardSizeAtCustom;
|
|
|
|
// Mappings of translated to Qt originated family and style strings.
|
|
QHash<QString, QString> qtFamilies;
|
|
QHash<QString, QString> qtStyles;
|
|
// Mapping of translated style strings to internal style identifiers.
|
|
QHash<QString, QString> styleIDs;
|
|
|
|
};
|
|
|
|
|
|
KFontChooser::KFontChooser( QWidget *parent,
|
|
const DisplayFlags& flags,
|
|
const QStringList &fontList,
|
|
int visibleListSize,
|
|
Qt::CheckState *sizeIsRelativeState )
|
|
: QWidget(parent),
|
|
d( new KFontChooser::Private( this ) )
|
|
{
|
|
d->usingFixed = flags & FixedFontsOnly;
|
|
setWhatsThis(i18nc("@info:whatsthis", "Here you can choose the font to be used." ));
|
|
|
|
// The top layout is divided vertically into a splitter with font
|
|
// attribute widgets and preview on the top, and XLFD data at the bottom.
|
|
QVBoxLayout *topLayout = new QVBoxLayout( this );
|
|
topLayout->setMargin( 0 );
|
|
int checkBoxGap = KDialog::spacingHint() / 2;
|
|
|
|
// The splitter contains font attribute widgets in the top part,
|
|
// and the font preview in the bottom part.
|
|
// The splitter is there to allow the user to resize the font preview.
|
|
QSplitter *splitter = new QSplitter(Qt::Vertical, this);
|
|
splitter->setChildrenCollapsible(false);
|
|
topLayout->addWidget(splitter);
|
|
|
|
// Build the grid of font attribute widgets for the upper splitter part.
|
|
//
|
|
QWidget *page;
|
|
QGridLayout *gridLayout;
|
|
int row = 0;
|
|
if( flags & DisplayFrame )
|
|
{
|
|
page = new QGroupBox( i18n("Requested Font"), this );
|
|
splitter->addWidget(page);
|
|
gridLayout = new QGridLayout( page );
|
|
row = 1;
|
|
}
|
|
else
|
|
{
|
|
page = new QWidget( this );
|
|
splitter->addWidget(page);
|
|
gridLayout = new QGridLayout( page );
|
|
gridLayout->setMargin( 0 );
|
|
}
|
|
|
|
//
|
|
// first, create the labels across the top
|
|
//
|
|
QHBoxLayout *familyLayout = new QHBoxLayout();
|
|
familyLayout->addSpacing( checkBoxGap );
|
|
if ( flags & ShowDifferences ) {
|
|
d->familyCheckbox = new QCheckBox(i18nc("@option:check","Font"), page);
|
|
connect(d->familyCheckbox, SIGNAL(toggled(bool)),
|
|
this, SLOT(_k_toggled_checkbox()));
|
|
familyLayout->addWidget(d->familyCheckbox, 0, Qt::AlignLeft);
|
|
d->familyCheckbox->setWhatsThis(i18nc("@info:whatsthis","Enable this checkbox to change the font family settings."));
|
|
d->familyCheckbox->setToolTip(i18nc("@info:tooltip","Change font family?") );
|
|
d->familyLabel = 0;
|
|
} else {
|
|
d->familyCheckbox = 0;
|
|
d->familyLabel = new QLabel( i18nc("@label","Font:"), page );
|
|
familyLayout->addWidget(d->familyLabel, 1, Qt::AlignLeft);
|
|
}
|
|
gridLayout->addLayout(familyLayout, row, 0 );
|
|
|
|
QHBoxLayout *styleLayout = new QHBoxLayout();
|
|
if ( flags & ShowDifferences ) {
|
|
d->styleCheckbox = new QCheckBox(i18nc("@option:check","Font style"), page);
|
|
connect(d->styleCheckbox, SIGNAL(toggled(bool)),
|
|
this, SLOT(_k_toggled_checkbox()));
|
|
styleLayout->addWidget(d->styleCheckbox, 0, Qt::AlignLeft);
|
|
d->styleCheckbox->setWhatsThis(i18nc("@info:whatsthis","Enable this checkbox to change the font style settings."));
|
|
d->styleCheckbox->setToolTip(i18nc("@info:tooltip","Change font style?"));
|
|
d->styleLabel = 0;
|
|
} else {
|
|
d->styleCheckbox = 0;
|
|
d->styleLabel = new QLabel(i18n("Font style:"), page );
|
|
styleLayout->addWidget(d->styleLabel, 1, Qt::AlignLeft);
|
|
}
|
|
styleLayout->addSpacing( checkBoxGap );
|
|
gridLayout->addLayout(styleLayout, row, 1 );
|
|
|
|
QHBoxLayout *sizeLayout = new QHBoxLayout();
|
|
if ( flags & ShowDifferences ) {
|
|
d->sizeCheckbox = new QCheckBox(i18nc("@option:check","Size"),page);
|
|
connect(d->sizeCheckbox, SIGNAL(toggled(bool)),
|
|
this, SLOT(_k_toggled_checkbox()));
|
|
sizeLayout->addWidget(d->sizeCheckbox, 0, Qt::AlignLeft);
|
|
d->sizeCheckbox->setWhatsThis(i18nc("@info:whatsthis","Enable this checkbox to change the font size settings."));
|
|
d->sizeCheckbox->setToolTip(i18nc("@info:tooltip","Change font size?"));
|
|
d->sizeLabel = 0;
|
|
} else {
|
|
d->sizeCheckbox = 0;
|
|
d->sizeLabel = new QLabel(i18nc("@label:listbox Font size", "Size:"), page );
|
|
sizeLayout->addWidget(d->sizeLabel, 1, Qt::AlignLeft);
|
|
}
|
|
sizeLayout->addSpacing( checkBoxGap );
|
|
sizeLayout->addSpacing( checkBoxGap ); // prevent label from eating border
|
|
gridLayout->addLayout(sizeLayout, row, 2 );
|
|
|
|
row ++;
|
|
|
|
//
|
|
// now create the actual boxes that hold the info
|
|
//
|
|
d->familyListBox = new KListWidget( page );
|
|
d->familyListBox->setEnabled( flags ^ ShowDifferences );
|
|
gridLayout->addWidget( d->familyListBox, row, 0 );
|
|
QString fontFamilyWhatsThisText (
|
|
i18nc("@info:whatsthis","Here you can choose the font family to be used." ));
|
|
d->familyListBox->setWhatsThis(fontFamilyWhatsThisText );
|
|
|
|
if ( flags & ShowDifferences ) {
|
|
d->familyCheckbox->setWhatsThis(fontFamilyWhatsThisText );
|
|
} else {
|
|
d->familyLabel->setWhatsThis(fontFamilyWhatsThisText );
|
|
}
|
|
|
|
connect(d->familyListBox, SIGNAL(currentTextChanged(QString)),
|
|
this, SLOT(_k_family_chosen_slot(QString)));
|
|
if ( !fontList.isEmpty() ) {
|
|
d->setFamilyBoxItems(fontList);
|
|
}
|
|
else
|
|
{
|
|
d->fillFamilyListBox( flags & FixedFontsOnly );
|
|
}
|
|
|
|
d->familyListBox->setMinimumWidth( minimumListWidth( d->familyListBox ) );
|
|
d->familyListBox->setMinimumHeight(
|
|
minimumListHeight( d->familyListBox, visibleListSize ) );
|
|
|
|
d->styleListBox = new KListWidget( page );
|
|
d->styleListBox->setEnabled( flags ^ ShowDifferences );
|
|
gridLayout->addWidget(d->styleListBox, row, 1);
|
|
d->styleListBox->setWhatsThis(i18nc("@info:whatsthis","Here you can choose the font style to be used." ));
|
|
if ( flags & ShowDifferences ) {
|
|
((QWidget *)d->styleCheckbox)->setWhatsThis(fontFamilyWhatsThisText );
|
|
} else {
|
|
((QWidget *)d->styleLabel)->setWhatsThis( fontFamilyWhatsThisText );
|
|
}
|
|
// Populate usual styles, to determine minimum list width;
|
|
// will be replaced later with correct styles.
|
|
d->styleListBox->addItem(I18NC_NOX("QFontDatabase", "Normal"));
|
|
d->styleListBox->addItem(i18nc("@item font","Italic"));
|
|
d->styleListBox->addItem(i18nc("@item font","Oblique"));
|
|
d->styleListBox->addItem(i18nc("@item font","Bold"));
|
|
d->styleListBox->addItem(i18nc("@item font","Bold Italic"));
|
|
d->styleListBox->setMinimumWidth( minimumListWidth( d->styleListBox ) );
|
|
d->styleListBox->setMinimumHeight(
|
|
minimumListHeight( d->styleListBox, visibleListSize ) );
|
|
|
|
connect(d->styleListBox, SIGNAL(currentTextChanged(QString)),
|
|
this, SLOT(_k_style_chosen_slot(QString)));
|
|
|
|
|
|
d->sizeListBox = new KListWidget( page );
|
|
d->sizeOfFont = new KDoubleNumInput(page);
|
|
d->sizeOfFont->setMinimum(4);
|
|
d->sizeOfFont->setMaximum(999);
|
|
d->sizeOfFont->setDecimals(1);
|
|
d->sizeOfFont->setSingleStep(1);
|
|
d->sizeOfFont->setSliderEnabled(false);
|
|
|
|
d->sizeListBox->setEnabled( flags ^ ShowDifferences );
|
|
d->sizeOfFont->setEnabled( flags ^ ShowDifferences );
|
|
if( sizeIsRelativeState ) {
|
|
QString sizeIsRelativeCBText =
|
|
i18nc("@item font size","Relative");
|
|
QString sizeIsRelativeCBToolTipText =
|
|
i18n("Font size<br /><i>fixed</i> or <i>relative</i><br />to environment");
|
|
QString sizeIsRelativeCBWhatsThisText =
|
|
i18n("Here you can switch between fixed font size and font size "
|
|
"to be calculated dynamically and adjusted to changing "
|
|
"environment (e.g. widget dimensions, paper size)." );
|
|
d->sizeIsRelativeCheckBox = new QCheckBox( sizeIsRelativeCBText,
|
|
page );
|
|
d->sizeIsRelativeCheckBox->setTristate( flags & ShowDifferences );
|
|
QGridLayout *sizeLayout2 = new QGridLayout();
|
|
sizeLayout2->setSpacing( KDialog::spacingHint()/2 );
|
|
gridLayout->addLayout(sizeLayout2, row, 2);
|
|
sizeLayout2->setColumnStretch( 1, 1 ); // to prevent text from eating the right border
|
|
sizeLayout2->addWidget( d->sizeOfFont, 0, 0, 1, 2);
|
|
sizeLayout2->addWidget(d->sizeListBox, 1,0, 1,2);
|
|
sizeLayout2->addWidget(d->sizeIsRelativeCheckBox, 2, 0, Qt::AlignLeft);
|
|
d->sizeIsRelativeCheckBox->setWhatsThis(sizeIsRelativeCBWhatsThisText );
|
|
d->sizeIsRelativeCheckBox->setToolTip( sizeIsRelativeCBToolTipText );
|
|
}
|
|
else {
|
|
d->sizeIsRelativeCheckBox = 0L;
|
|
QGridLayout *sizeLayout2 = new QGridLayout();
|
|
sizeLayout2->setSpacing( KDialog::spacingHint()/2 );
|
|
gridLayout->addLayout(sizeLayout2, row, 2);
|
|
sizeLayout2->addWidget( d->sizeOfFont, 0, 0);
|
|
sizeLayout2->addWidget(d->sizeListBox, 1,0);
|
|
}
|
|
QString fontSizeWhatsThisText =
|
|
i18n("Here you can choose the font size to be used." );
|
|
d->sizeListBox->setWhatsThis(fontSizeWhatsThisText );
|
|
|
|
if ( flags & ShowDifferences ) {
|
|
((QWidget *)d->sizeCheckbox)->setWhatsThis(fontSizeWhatsThisText );
|
|
} else {
|
|
((QWidget *)d->sizeLabel)->setWhatsThis( fontSizeWhatsThisText );
|
|
}
|
|
|
|
// Populate with usual sizes, to determine minimum list width;
|
|
// will be replaced later with correct sizes.
|
|
d->fillSizeList();
|
|
d->sizeListBox->setMinimumWidth( minimumListWidth(d->sizeListBox) +
|
|
d->sizeListBox->fontMetrics().maxWidth() );
|
|
d->sizeListBox->setMinimumHeight(
|
|
minimumListHeight( d->sizeListBox, visibleListSize ) );
|
|
|
|
connect( d->sizeOfFont, SIGNAL(valueChanged(double)),
|
|
this, SLOT(_k_size_value_slot(double)));
|
|
|
|
connect( d->sizeListBox, SIGNAL(currentTextChanged(QString)),
|
|
this, SLOT(_k_size_chosen_slot(QString)) );
|
|
|
|
row ++;
|
|
//
|
|
// Completed the font attribute grid.
|
|
|
|
// Add the font preview into the lower part of the splitter.
|
|
//
|
|
d->sampleEdit = new SampleEdit(page);
|
|
d->sampleEdit->setAcceptRichText(false);
|
|
QFont tmpFont( KGlobalSettings::generalFont().family(), 64, QFont::Black );
|
|
d->sampleEdit->setFont(tmpFont);
|
|
d->sampleEdit->setMinimumHeight( d->sampleEdit->fontMetrics().lineSpacing() );
|
|
// i18n: A classical test phrase, with all letters of the English alphabet.
|
|
// Replace it with a sample text in your language, such that it is
|
|
// representative of language's writing system.
|
|
// If you wish, you can input several lines of text separated by \n.
|
|
setSampleText(i18n("The Quick Brown Fox Jumps Over The Lazy Dog"));
|
|
d->sampleEdit->setTextCursor(QTextCursor(d->sampleEdit->document()));
|
|
QString sampleEditWhatsThisText =
|
|
i18n("This sample text illustrates the current settings. "
|
|
"You may edit it to test special characters." );
|
|
d->sampleEdit->setWhatsThis(sampleEditWhatsThisText );
|
|
|
|
connect(this, SIGNAL(fontSelected(QFont)),
|
|
this, SLOT(_k_displaySample(QFont)));
|
|
|
|
splitter->addWidget(d->sampleEdit);
|
|
//
|
|
// Finished setting up the splitter.
|
|
|
|
// Add XLFD data below the font attributes/preview splitter.
|
|
//
|
|
QVBoxLayout *vbox;
|
|
if( flags & DisplayFrame )
|
|
{
|
|
page = new QGroupBox( i18n("Actual Font"), this );
|
|
topLayout->addWidget(page);
|
|
vbox = new QVBoxLayout( page );
|
|
vbox->addSpacing( fontMetrics().lineSpacing() );
|
|
}
|
|
else
|
|
{
|
|
page = new QWidget( this );
|
|
topLayout->addWidget(page);
|
|
vbox = new QVBoxLayout( page );
|
|
vbox->setMargin( 0 );
|
|
QLabel *label = new QLabel( i18n("Actual Font"), page );
|
|
vbox->addWidget( label );
|
|
}
|
|
|
|
d->xlfdEdit = new KLineEdit( page );
|
|
vbox->addWidget( d->xlfdEdit );
|
|
//
|
|
// Finished setting up the chooser layout.
|
|
|
|
// lets initialize the display if possible
|
|
setFont( d->usingFixed ? KGlobalSettings::fixedFont() : KGlobalSettings::generalFont(), d->usingFixed );
|
|
|
|
// check or uncheck or gray out the "relative" checkbox
|
|
if( sizeIsRelativeState && d->sizeIsRelativeCheckBox )
|
|
setSizeIsRelative( *sizeIsRelativeState );
|
|
|
|
KConfigGroup cg(KGlobal::config(), QLatin1String("General"));
|
|
d->_k_showXLFDArea(cg.readEntry(QLatin1String("fontSelectorShowXLFD"), false));
|
|
|
|
// Set focus to the size list as this is the most commonly changed property
|
|
d->sizeListBox->setFocus();
|
|
}
|
|
|
|
KFontChooser::~KFontChooser()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
void KFontChooser::setColor( const QColor & col )
|
|
{
|
|
d->m_palette.setColor( QPalette::Active, QPalette::Text, col );
|
|
QPalette pal = d->sampleEdit->palette();
|
|
pal.setColor( QPalette::Active, QPalette::Text, col );
|
|
d->sampleEdit->setPalette( pal );
|
|
QTextCursor cursor = d->sampleEdit->textCursor();
|
|
d->sampleEdit->selectAll();
|
|
d->sampleEdit->setTextColor( col );
|
|
d->sampleEdit->setTextCursor( cursor );
|
|
}
|
|
|
|
QColor KFontChooser::color() const
|
|
{
|
|
return d->m_palette.color( QPalette::Active, QPalette::Text );
|
|
}
|
|
|
|
void KFontChooser::setBackgroundColor( const QColor & col )
|
|
{
|
|
d->m_palette.setColor( QPalette::Active, QPalette::Base, col );
|
|
QPalette pal = d->sampleEdit->palette();
|
|
pal.setColor( QPalette::Active, QPalette::Base, col );
|
|
d->sampleEdit->setPalette( pal );
|
|
}
|
|
|
|
QColor KFontChooser::backgroundColor() const
|
|
{
|
|
return d->m_palette.color( QPalette::Active, QPalette::Base );
|
|
}
|
|
|
|
void KFontChooser::setSizeIsRelative( Qt::CheckState relative )
|
|
{
|
|
// check or uncheck or gray out the "relative" checkbox
|
|
if( d->sizeIsRelativeCheckBox ) {
|
|
if( Qt::PartiallyChecked == relative )
|
|
d->sizeIsRelativeCheckBox->setCheckState(Qt::PartiallyChecked);
|
|
else
|
|
d->sizeIsRelativeCheckBox->setCheckState( (Qt::Checked == relative ) ? Qt::Checked : Qt::Unchecked);
|
|
}
|
|
}
|
|
|
|
Qt::CheckState KFontChooser::sizeIsRelative() const
|
|
{
|
|
return d->sizeIsRelativeCheckBox
|
|
? d->sizeIsRelativeCheckBox->checkState()
|
|
: Qt::PartiallyChecked;
|
|
}
|
|
|
|
QString KFontChooser::sampleText() const
|
|
{
|
|
return d->sampleEdit->toPlainText();
|
|
}
|
|
|
|
void KFontChooser::setSampleText( const QString &text )
|
|
{
|
|
d->sampleEdit->setPlainText(text);
|
|
}
|
|
|
|
void KFontChooser::setSampleBoxVisible( bool visible )
|
|
{
|
|
d->sampleEdit->setVisible( visible );
|
|
}
|
|
|
|
QSize KFontChooser::sizeHint( void ) const
|
|
{
|
|
return minimumSizeHint();
|
|
}
|
|
|
|
|
|
void KFontChooser::enableColumn( int column, bool state )
|
|
{
|
|
if( column & FamilyList )
|
|
{
|
|
d->familyListBox->setEnabled(state);
|
|
}
|
|
if( column & StyleList )
|
|
{
|
|
d->styleListBox->setEnabled(state);
|
|
}
|
|
if( column & SizeList )
|
|
{
|
|
d->sizeListBox->setEnabled(state);
|
|
d->sizeOfFont->setEnabled(state);
|
|
}
|
|
}
|
|
|
|
|
|
void KFontChooser::setFont( const QFont& aFont, bool onlyFixed )
|
|
{
|
|
d->selFont = aFont;
|
|
d->selectedSize=aFont.pointSizeF();
|
|
if (d->selectedSize == -1)
|
|
d->selectedSize = QFontInfo(aFont).pointSizeF();
|
|
|
|
if( onlyFixed != d->usingFixed)
|
|
{
|
|
d->usingFixed = onlyFixed;
|
|
d->fillFamilyListBox(d->usingFixed);
|
|
}
|
|
d->setupDisplay();
|
|
}
|
|
|
|
|
|
KFontChooser::FontDiffFlags KFontChooser::fontDiffFlags() const
|
|
{
|
|
FontDiffFlags diffFlags = NoFontDiffFlags;
|
|
|
|
if ( d->familyCheckbox && d->familyCheckbox->isChecked() ) {
|
|
diffFlags |= FontDiffFamily;
|
|
}
|
|
|
|
if ( d->styleCheckbox && d->styleCheckbox->isChecked() ) {
|
|
diffFlags |= FontDiffStyle;
|
|
}
|
|
|
|
if ( d->sizeCheckbox && d->sizeCheckbox->isChecked() ) {
|
|
diffFlags |= FontDiffSize;
|
|
}
|
|
|
|
return diffFlags;
|
|
}
|
|
|
|
QFont KFontChooser::font() const
|
|
{
|
|
return d->selFont;
|
|
}
|
|
|
|
void KFontChooser::Private::_k_toggled_checkbox()
|
|
{
|
|
familyListBox->setEnabled( familyCheckbox->isChecked() );
|
|
styleListBox->setEnabled( styleCheckbox->isChecked() );
|
|
sizeListBox->setEnabled( sizeCheckbox->isChecked() );
|
|
sizeOfFont->setEnabled( sizeCheckbox->isChecked() );
|
|
}
|
|
|
|
void KFontChooser::Private::_k_family_chosen_slot(const QString& family)
|
|
{
|
|
if ( !signalsAllowed ) {
|
|
return;
|
|
}
|
|
signalsAllowed = false;
|
|
|
|
QString currentFamily;
|
|
if (family.isEmpty()) {
|
|
Q_ASSERT( familyListBox->currentItem() );
|
|
if (familyListBox->currentItem()) {
|
|
currentFamily = qtFamilies[familyListBox->currentItem()->text()];
|
|
}
|
|
}
|
|
else {
|
|
currentFamily = qtFamilies[family];
|
|
}
|
|
|
|
// Get the list of styles available in this family.
|
|
QFontDatabase dbase;
|
|
QStringList styles = dbase.styles(currentFamily);
|
|
if (styles.isEmpty()) {
|
|
// Avoid extraction, it is in kdeqt.po
|
|
styles.append(I18NC_NOX("QFontDatabase", "Normal"));
|
|
}
|
|
|
|
// Filter style strings and add to the listbox.
|
|
QString pureFamily;
|
|
splitFontString(family, &pureFamily);
|
|
QStringList filteredStyles;
|
|
qtStyles.clear();
|
|
styleIDs.clear();
|
|
foreach (const QString &style, styles) {
|
|
// Sometimes the font database will report an invalid style,
|
|
// that falls back back to another when set.
|
|
// Remove such styles, by checking set/get round-trip.
|
|
QFont testFont = dbase.font(currentFamily, style, 10);
|
|
if (dbase.styleString(testFont) != style) {
|
|
styles.removeAll(style);
|
|
continue;
|
|
}
|
|
|
|
// i18n: Filtering message, so that translators can script the
|
|
// style string according to the font family name (e.g. may need
|
|
// noun-adjective congruence wrt. gender of the family name).
|
|
// The message provides the dynamic context 'family', which is
|
|
// the family name to which the style string corresponds.
|
|
QString fstyle = ki18nc("@item Font style", "%1").subs(style).inContext("family", pureFamily).toString();
|
|
if (!filteredStyles.contains(fstyle)) {
|
|
filteredStyles.append(fstyle);
|
|
qtStyles.insert(fstyle, style);
|
|
styleIDs.insert(fstyle, styleIdentifier(testFont));
|
|
}
|
|
}
|
|
styleListBox->clear();
|
|
styleListBox->addItems(filteredStyles);
|
|
|
|
// Try to set the current style in the listbox to that previous.
|
|
int listPos = filteredStyles.indexOf(selectedStyle.isEmpty() ? I18NC_NOX("QFontDatabase", "Normal") : selectedStyle);
|
|
if (listPos < 0) {
|
|
// Make extra effort to have Italic selected when Oblique was chosen,
|
|
// and vice versa, as that is what the user would probably want.
|
|
QString styleIt = i18nc("@item font", "Italic");
|
|
QString styleOb = i18nc("@item font", "Oblique");
|
|
for (int i = 0; i < 2; ++i) {
|
|
int pos = selectedStyle.indexOf(styleIt);
|
|
if (pos >= 0) {
|
|
QString style = selectedStyle;
|
|
style.replace(pos, styleIt.length(), styleOb);
|
|
listPos = filteredStyles.indexOf(style);
|
|
if (listPos >= 0) break;
|
|
}
|
|
qSwap(styleIt, styleOb);
|
|
}
|
|
}
|
|
styleListBox->setCurrentRow(listPos >= 0 ? listPos : 0);
|
|
QString currentStyle = qtStyles[styleListBox->currentItem()->text()];
|
|
|
|
// Recompute the size listbox for this family/style.
|
|
qreal currentSize = setupSizeListBox(currentFamily, currentStyle);
|
|
sizeOfFont->setValue(currentSize);
|
|
|
|
selFont = dbase.font(currentFamily, currentStyle, int(currentSize));
|
|
if (dbase.isSmoothlyScalable(currentFamily, currentStyle) && selFont.pointSize() == floor(currentSize)) {
|
|
selFont.setPointSizeF(currentSize);
|
|
}
|
|
emit q->fontSelected(selFont);
|
|
|
|
signalsAllowed = true;
|
|
}
|
|
|
|
void KFontChooser::Private::_k_style_chosen_slot(const QString& style)
|
|
{
|
|
if ( !signalsAllowed ) {
|
|
return;
|
|
}
|
|
signalsAllowed = false;
|
|
|
|
QFontDatabase dbase;
|
|
QString currentFamily = qtFamilies[familyListBox->currentItem()->text()];
|
|
QString currentStyle;
|
|
if (style.isEmpty()) {
|
|
currentStyle = qtStyles[styleListBox->currentItem()->text()];
|
|
} else {
|
|
currentStyle = qtStyles[style];
|
|
}
|
|
|
|
// Recompute the size listbox for this family/style.
|
|
qreal currentSize = setupSizeListBox(currentFamily, currentStyle);
|
|
sizeOfFont->setValue(currentSize);
|
|
|
|
selFont = dbase.font(currentFamily, currentStyle, int(currentSize));
|
|
if (dbase.isSmoothlyScalable(currentFamily, currentStyle) && selFont.pointSize() == floor(currentSize)) {
|
|
selFont.setPointSizeF(currentSize);
|
|
}
|
|
emit q->fontSelected(selFont);
|
|
|
|
if (!style.isEmpty()) {
|
|
selectedStyle = currentStyle;
|
|
}
|
|
|
|
signalsAllowed = true;
|
|
}
|
|
|
|
void KFontChooser::Private::_k_size_chosen_slot(const QString& size)
|
|
{
|
|
if ( !signalsAllowed ) {
|
|
return;
|
|
}
|
|
|
|
signalsAllowed = false;
|
|
|
|
qreal currentSize;
|
|
if (size.isEmpty()) {
|
|
currentSize = KGlobal::locale()->readNumber(sizeListBox->currentItem()->text());
|
|
} else {
|
|
currentSize = KGlobal::locale()->readNumber(size);
|
|
}
|
|
|
|
// Reset the customized size slot in the list if not needed.
|
|
if (customSizeRow >= 0 && selFont.pointSizeF() != currentSize) {
|
|
sizeListBox->item(customSizeRow)->setText(standardSizeAtCustom);
|
|
customSizeRow = -1;
|
|
}
|
|
|
|
sizeOfFont->setValue(currentSize);
|
|
selFont.setPointSizeF(currentSize);
|
|
emit q->fontSelected(selFont);
|
|
|
|
if (!size.isEmpty()) {
|
|
selectedSize = currentSize;
|
|
}
|
|
|
|
signalsAllowed = true;
|
|
}
|
|
|
|
void KFontChooser::Private::_k_size_value_slot(double dval)
|
|
{
|
|
if ( !signalsAllowed ) {
|
|
return;
|
|
}
|
|
signalsAllowed = false;
|
|
|
|
// We compare with qreal, so convert for platforms where qreal != double.
|
|
qreal val = qreal(dval);
|
|
|
|
QFontDatabase dbase;
|
|
QString family = qtFamilies[familyListBox->currentItem()->text()];
|
|
QString style = qtStyles[styleListBox->currentItem()->text()];
|
|
|
|
// Reset current size slot in list if it was customized.
|
|
if (customSizeRow >= 0 && sizeListBox->currentRow() == customSizeRow) {
|
|
sizeListBox->item(customSizeRow)->setText(standardSizeAtCustom);
|
|
customSizeRow = -1;
|
|
}
|
|
|
|
bool canCustomize = true;
|
|
|
|
// For Qt-bad-sizes workaround: skip this block unconditionally
|
|
if (!dbase.isSmoothlyScalable(family, style)) {
|
|
// Bitmap font, allow only discrete sizes.
|
|
// Determine the nearest in the direction of change.
|
|
canCustomize = false;
|
|
int nrows = sizeListBox->count();
|
|
int row = sizeListBox->currentRow();
|
|
int nrow;
|
|
if (val - selFont.pointSizeF() > 0) {
|
|
for (nrow = row + 1; nrow < nrows; ++nrow)
|
|
if (KGlobal::locale()->readNumber(sizeListBox->item(nrow)->text()) >= val)
|
|
break;
|
|
}
|
|
else {
|
|
for (nrow = row - 1; nrow >= 0; --nrow)
|
|
if (KGlobal::locale()->readNumber(sizeListBox->item(nrow)->text()) <= val)
|
|
break;
|
|
}
|
|
// Make sure the new row is not out of bounds.
|
|
nrow = nrow < 0 ? 0 : nrow >= nrows ? nrows - 1 : nrow;
|
|
// Get the size from the new row and set the spinbox to that size.
|
|
val = KGlobal::locale()->readNumber(sizeListBox->item(nrow)->text());
|
|
sizeOfFont->setValue(val);
|
|
}
|
|
|
|
// Set the current size in the size listbox.
|
|
int row = nearestSizeRow(val, canCustomize);
|
|
sizeListBox->setCurrentRow(row);
|
|
|
|
selectedSize = val;
|
|
selFont.setPointSizeF(val);
|
|
emit q->fontSelected( selFont );
|
|
|
|
signalsAllowed = true;
|
|
}
|
|
|
|
void KFontChooser::Private::_k_displaySample( const QFont& font )
|
|
{
|
|
sampleEdit->setFont(font);
|
|
//sampleEdit->setCursorPosition(0);
|
|
|
|
xlfdEdit->setText(font.rawName());
|
|
xlfdEdit->setCursorPosition(0);
|
|
|
|
//QFontInfo a = QFontInfo(font);
|
|
//kDebug() << "font: " << a.family () << ", " << a.pointSize ();
|
|
//kDebug() << " (" << font.toString() << ")\n";
|
|
}
|
|
|
|
int KFontChooser::Private::nearestSizeRow (qreal val, bool customize)
|
|
{
|
|
qreal diff = 1000;
|
|
int row = 0;
|
|
for (int r = 0; r < sizeListBox->count(); ++r) {
|
|
qreal cval = KGlobal::locale()->readNumber(sizeListBox->item(r)->text());
|
|
if (qAbs(cval - val) < diff) {
|
|
diff = qAbs(cval - val);
|
|
row = r;
|
|
}
|
|
}
|
|
// For Qt-bad-sizes workaround: ignore value of customize, use true
|
|
if (customize && diff > 0) {
|
|
customSizeRow = row;
|
|
standardSizeAtCustom = sizeListBox->item(row)->text();
|
|
sizeListBox->item(row)->setText(formatFontSize(val));
|
|
}
|
|
return row;
|
|
}
|
|
|
|
qreal KFontChooser::Private::fillSizeList (const QList<qreal> &sizes_)
|
|
{
|
|
if ( !sizeListBox ) {
|
|
return 0; //assertion.
|
|
}
|
|
|
|
QList<qreal> sizes = sizes_;
|
|
bool canCustomize = false;
|
|
if (sizes.count() == 0) {
|
|
static const int c[] = {
|
|
4, 5, 6, 7,
|
|
8, 9, 10, 11,
|
|
12, 13, 14, 15,
|
|
16, 17, 18, 19,
|
|
20, 22, 24, 26,
|
|
28, 32, 48, 64,
|
|
72, 80, 96, 128,
|
|
0
|
|
};
|
|
for (int i = 0; c[i]; ++i) {
|
|
sizes.append(c[i]);
|
|
}
|
|
// Since sizes were not supplied, this is a vector font,
|
|
// and size slot customization is allowed.
|
|
canCustomize = true;
|
|
}
|
|
|
|
// Insert sizes into the listbox.
|
|
sizeListBox->clear();
|
|
qSort(sizes);
|
|
foreach (qreal size, sizes) {
|
|
sizeListBox->addItem(formatFontSize(size));
|
|
}
|
|
|
|
// Return the nearest to selected size.
|
|
// If the font is vector, the nearest size is always same as selected,
|
|
// thus size slot customization is allowed.
|
|
// If the font is bitmap, the nearest size need not be same as selected,
|
|
// thus size slot customization is not allowed.
|
|
customSizeRow = -1;
|
|
int row = nearestSizeRow(selectedSize, canCustomize);
|
|
return KGlobal::locale()->readNumber(sizeListBox->item(row)->text());
|
|
}
|
|
|
|
qreal KFontChooser::Private::setupSizeListBox (const QString& family, const QString& style)
|
|
{
|
|
QFontDatabase dbase;
|
|
QList<qreal> sizes;
|
|
if (dbase.isSmoothlyScalable(family, style)) {
|
|
// A vector font.
|
|
//>sampleEdit->setPaletteBackgroundPixmap( VectorPixmap ); // TODO
|
|
}
|
|
else {
|
|
// A bitmap font.
|
|
//sampleEdit->setPaletteBackgroundPixmap( BitmapPixmap ); // TODO
|
|
QList<int> smoothSizes = dbase.smoothSizes(family, style);
|
|
foreach (int size, smoothSizes) {
|
|
sizes.append(size);
|
|
}
|
|
}
|
|
|
|
// Fill the listbox (uses default list of sizes if the given is empty).
|
|
// Collect the best fitting size to selected size, to use if not smooth.
|
|
qreal bestFitSize = fillSizeList(sizes);
|
|
|
|
// Set the best fit size as current in the listbox if available.
|
|
const QList<QListWidgetItem*> selectedSizeList =
|
|
sizeListBox->findItems( formatFontSize(bestFitSize),
|
|
Qt::MatchExactly );
|
|
if ( !selectedSizeList.isEmpty() ) {
|
|
sizeListBox->setCurrentItem(selectedSizeList.first());
|
|
}
|
|
//TODO - KDE4 : sizeListBox->scrollTo(sizeListBox->currentItem());
|
|
|
|
return bestFitSize;
|
|
}
|
|
|
|
void KFontChooser::Private::setupDisplay()
|
|
{
|
|
QFontDatabase dbase;
|
|
QString family = selFont.family().toLower();
|
|
QString styleID = styleIdentifier(selFont);
|
|
qreal size = selFont.pointSizeF();
|
|
if (size == -1)
|
|
size = QFontInfo( selFont ).pointSizeF();
|
|
|
|
int numEntries, i;
|
|
|
|
// Direct family match.
|
|
numEntries = familyListBox->count();
|
|
for (i = 0; i < numEntries; i++) {
|
|
if (family == qtFamilies[familyListBox->item(i)->text()].toLower()) {
|
|
familyListBox->setCurrentRow(i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 1st family fallback.
|
|
if ( i == numEntries )
|
|
{
|
|
if (family.contains('['))
|
|
{
|
|
family = family.left(family.indexOf('[')).trimmed();
|
|
for (i = 0; i < numEntries; i++) {
|
|
if (family == qtFamilies[familyListBox->item(i)->text()].toLower()) {
|
|
familyListBox->setCurrentRow(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2nd family fallback.
|
|
if ( i == numEntries )
|
|
{
|
|
QString fallback = family+" [";
|
|
for (i = 0; i < numEntries; i++) {
|
|
if (qtFamilies[familyListBox->item(i)->text()].toLower().startsWith(fallback)) {
|
|
familyListBox->setCurrentRow(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3rd family fallback.
|
|
if ( i == numEntries )
|
|
{
|
|
for (i = 0; i < numEntries; i++) {
|
|
if (qtFamilies[familyListBox->item(i)->text()].toLower().startsWith(family)) {
|
|
familyListBox->setCurrentRow(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Family fallback in case nothing matched. Otherwise, diff doesn't work
|
|
if ( i == numEntries ) {
|
|
familyListBox->setCurrentRow( 0 );
|
|
}
|
|
|
|
// By setting the current item in the family box, the available
|
|
// styles and sizes for that family have been collected.
|
|
// Try now to set the current items in the style and size boxes.
|
|
|
|
// Set current style in the listbox.
|
|
numEntries = styleListBox->count();
|
|
for (i = 0; i < numEntries; i++) {
|
|
if (styleID == styleIDs[styleListBox->item(i)->text()]) {
|
|
styleListBox->setCurrentRow(i);
|
|
break;
|
|
}
|
|
}
|
|
if (i == numEntries) {
|
|
// Style not found, fallback.
|
|
styleListBox->setCurrentRow(0);
|
|
}
|
|
|
|
// Set current size in the listbox.
|
|
// If smoothly scalable, allow customizing one of the standard size slots,
|
|
// otherwise just select the nearest available size.
|
|
QString currentFamily = qtFamilies[familyListBox->currentItem()->text()];
|
|
QString currentStyle = qtStyles[styleListBox->currentItem()->text()];
|
|
bool canCustomize = dbase.isSmoothlyScalable(currentFamily, currentStyle);
|
|
sizeListBox->setCurrentRow(nearestSizeRow(size, canCustomize));
|
|
|
|
// Set current size in the spinbox.
|
|
sizeOfFont->setValue(KGlobal::locale()->readNumber(sizeListBox->currentItem()->text()));
|
|
}
|
|
|
|
|
|
void KFontChooser::getFontList( QStringList &list, uint fontListCriteria)
|
|
{
|
|
QFontDatabase dbase;
|
|
QStringList lstSys(dbase.families());
|
|
|
|
// if we have criteria; then check fonts before adding
|
|
if (fontListCriteria)
|
|
{
|
|
QStringList lstFonts;
|
|
for (QStringList::const_iterator it = lstSys.constBegin(); it != lstSys.constEnd(); ++it)
|
|
{
|
|
if ((fontListCriteria & FixedWidthFonts) > 0 && !dbase.isFixedPitch(*it)) continue;
|
|
if (((fontListCriteria & (SmoothScalableFonts | ScalableFonts)) == ScalableFonts) &&
|
|
!dbase.isBitmapScalable(*it)) continue;
|
|
if ((fontListCriteria & SmoothScalableFonts) > 0 && !dbase.isSmoothlyScalable(*it)) continue;
|
|
lstFonts.append(*it);
|
|
}
|
|
|
|
if((fontListCriteria & FixedWidthFonts) > 0) {
|
|
// Fallback.. if there are no fixed fonts found, it's probably a
|
|
// bug in the font server or Qt. In this case, just use 'fixed'
|
|
if (lstFonts.count() == 0)
|
|
lstFonts.append("fixed");
|
|
}
|
|
|
|
lstSys = lstFonts;
|
|
}
|
|
|
|
lstSys.sort();
|
|
|
|
list = lstSys;
|
|
}
|
|
|
|
void KFontChooser::Private::setFamilyBoxItems(const QStringList &fonts)
|
|
{
|
|
signalsAllowed = false;
|
|
|
|
QStringList trfonts = translateFontNameList(fonts, &qtFamilies);
|
|
familyListBox->clear();
|
|
familyListBox->addItems(trfonts);
|
|
|
|
signalsAllowed = true;
|
|
}
|
|
|
|
void KFontChooser::Private::fillFamilyListBox(bool onlyFixedFonts)
|
|
{
|
|
QStringList fontList;
|
|
getFontList(fontList, onlyFixedFonts?FixedWidthFonts:0);
|
|
setFamilyBoxItems(fontList);
|
|
}
|
|
|
|
void KFontChooser::Private::_k_showXLFDArea(bool show)
|
|
{
|
|
if( show )
|
|
{
|
|
xlfdEdit->parentWidget()->show();
|
|
}
|
|
else
|
|
{
|
|
xlfdEdit->parentWidget()->hide();
|
|
}
|
|
}
|
|
|
|
// Human-readable style identifiers returned by QFontDatabase::styleString()
|
|
// do not always survive round trip of QFont serialization/deserialization,
|
|
// causing wrong style in the style box to be highlighted when
|
|
// the chooser dialog is opened. This will cause the style to be changed
|
|
// when the dialog is closed and the user did not touch the style box.
|
|
// Hence, construct custom style identifiers sufficient for the purpose.
|
|
QString KFontChooser::Private::styleIdentifier(const QFont &font)
|
|
{
|
|
const QChar comma(QLatin1Char(','));
|
|
return QString::number(font.weight()) + comma
|
|
+ QString::number((int)font.style()) + comma
|
|
+ QString::number(font.stretch());
|
|
}
|
|
|
|
#include "kfontchooser.moc"
|
|
#include "sampleedit_p.moc"
|