From 33d9e8822f9cd978d175e87aab22ad67334e62bc Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Wed, 29 Jan 2025 11:58:32 +0100 Subject: [PATCH] add font selection window --- examples/gallery/dialog/DialogPage.cpp | 12 ++ playground/systemdialogs/main.cpp | 39 +----- src/CMakeLists.txt | 2 + src/dialogs/QskColorSelectionWindow.h | 2 - src/dialogs/QskDialog.cpp | 41 ++++++- src/dialogs/QskDialog.h | 2 + src/dialogs/QskFontSelectionWindow.cpp | 160 +++++++++++++++++++++++++ src/dialogs/QskFontSelectionWindow.h | 32 +++++ 8 files changed, 254 insertions(+), 36 deletions(-) create mode 100644 src/dialogs/QskFontSelectionWindow.cpp create mode 100644 src/dialogs/QskFontSelectionWindow.h diff --git a/examples/gallery/dialog/DialogPage.cpp b/examples/gallery/dialog/DialogPage.cpp index e96a10eb..08cda235 100644 --- a/examples/gallery/dialog/DialogPage.cpp +++ b/examples/gallery/dialog/DialogPage.cpp @@ -107,6 +107,9 @@ namespace auto colorSelectionButton = new Button( "Color selection", this ); connect( colorSelectionButton, &Button::clicked, this, &ButtonBox::execColorSelection ); + auto fontSelectionButton = new Button( "Font selection", this ); + connect( fontSelectionButton, &Button::clicked, this, &ButtonBox::execFontSelection ); + setExtraSpacingAt( Qt::BottomEdge ); } @@ -193,6 +196,15 @@ namespace // not implemented for now (class is not public) #else ( void ) qskDialog->selectColor( "select color" ); +#endif + } + + void execFontSelection() + { +#ifndef QSK_USE_EXEC + // not implemented for now (class is not public) +#else + ( void ) qskDialog->selectFont( "select font" ); #endif } }; diff --git a/playground/systemdialogs/main.cpp b/playground/systemdialogs/main.cpp index 291157a5..77aa73c0 100644 --- a/playground/systemdialogs/main.cpp +++ b/playground/systemdialogs/main.cpp @@ -21,34 +21,6 @@ #include #include -#include - -static QQuickAbstractDialog* createQml( const char* className ) -{ - static QQmlEngine engine( nullptr ); - - QByteArray qmlCode = "import QtQuick.Dialogs\n"; - qmlCode += className; - qmlCode += " {}"; - - auto component = new QQmlComponent( &engine ); - component->setData( qmlCode.constData(), QUrl() ); - - if ( component->status() != QQmlComponent::Ready ) - { - qWarning() << component->errorString(); - delete component; - - return nullptr; - } - - auto dialog = qobject_cast< QQuickAbstractDialog* >( component->create() ); - QObject::connect( dialog, &QObject::destroyed, - component, &QObject::deleteLater ); - - return dialog; -} - namespace { class ButtonBox : public QskLinearBox @@ -126,6 +98,11 @@ namespace auto file = qskDialog->selectDirectory( "select directory", QDir::currentPath() ); break; } + case FontDialog: + { + qskDialog->selectFont( "select font" ); + break; + } case MessageDialog: { auto action = qskDialog->message( "message", "The quick brown fox jumps over the lazy dog" ); @@ -134,11 +111,7 @@ namespace } default: { - const auto metaEnum = QMetaEnum::fromType(); - m_dialog = createQml( metaEnum.key( dialogType ) ); - - if ( m_dialog ) - m_dialog->setParentWindow( window() ); + qWarning() << "unknown dialog type detected"; } } } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 572ce6fd..9d88a1fa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -457,6 +457,7 @@ list(APPEND PRIVATE_HEADERS dialogs/QskColorPickerSkinlet.h dialogs/QskColorSelectionWindow.h dialogs/QskFileSelectionWindow.h + dialogs/QskFontSelectionWindow.h dialogs/QskWindowOrSubWindow.h ) @@ -470,6 +471,7 @@ list(APPEND SOURCES dialogs/QskDialogSubWindow.cpp dialogs/QskDialogWindow.cpp dialogs/QskFileSelectionWindow.cpp + dialogs/QskFontSelectionWindow.cpp dialogs/QskMessageSubWindow.cpp dialogs/QskMessageWindow.cpp dialogs/QskSelectionSubWindow.cpp diff --git a/src/dialogs/QskColorSelectionWindow.h b/src/dialogs/QskColorSelectionWindow.h index 9efca02f..e603aa4c 100644 --- a/src/dialogs/QskColorSelectionWindow.h +++ b/src/dialogs/QskColorSelectionWindow.h @@ -8,8 +8,6 @@ #include "QskWindowOrSubWindow.h" -class QskColorPicker; - template< typename W > class QskColorSelectionWindow : public QskWindowOrSubWindow< W > { diff --git a/src/dialogs/QskDialog.cpp b/src/dialogs/QskDialog.cpp index 084618a3..f0406d73 100644 --- a/src/dialogs/QskDialog.cpp +++ b/src/dialogs/QskDialog.cpp @@ -16,9 +16,9 @@ #include "QskBoxBorderMetrics.h" #include "QskColorSelectionWindow.h" #include "QskFileSelectionWindow.h" +#include "QskFontSelectionWindow.h" #include "QskEvent.h" #include "QskFunctions.h" -#include "QskListView.h" #include "QskFocusIndicator.h" @@ -245,6 +245,17 @@ static QColor qskSelectColor( QskColorSelectionWindow< W >& window ) return selectedColor; } +template< typename W > +static QFont qskSelectFont( QskFontSelectionWindow< W >& window ) +{ + QFont selectedFont = window.selectedFont(); + + if( window.exec() == QskDialog::Accepted ) + selectedFont = window.selectedFont(); + + return selectedFont; +} + class QskDialog::PrivateData { public: @@ -449,6 +460,34 @@ QColor QskDialog::selectColor( const QString& title ) const return qskSelectColor< QskDialogWindow >( window ); } +QFont QskDialog::selectFont( const QString& title ) const +{ +#if 1 + // should be parameters + const auto actions = QskDialog::Ok | QskDialog::Cancel; + const auto defaultAction = QskDialog::Ok; +#endif + + if ( m_data->policy == EmbeddedBox ) + { + auto quickWindow = qobject_cast< QQuickWindow* >( m_data->transientParent ); + + if ( quickWindow == nullptr ) + quickWindow = qskSomeQuickWindow(); + + if ( quickWindow ) + { + QskFontSelectionWindow< QskDialogSubWindow > window( quickWindow, title, + actions, defaultAction ); + return qskSelectFont< QskDialogSubWindow >( window ); + } + } + + QskFontSelectionWindow< QskDialogWindow > window( m_data->transientParent, title, + actions, defaultAction ); + return qskSelectFont< QskDialogWindow >( window ); +} + QskDialog::ActionRole QskDialog::actionRole( Action action ) { using Q = QPlatformDialogHelper; diff --git a/src/dialogs/QskDialog.h b/src/dialogs/QskDialog.h index 72bbf9b2..d2cf6906 100644 --- a/src/dialogs/QskDialog.h +++ b/src/dialogs/QskDialog.h @@ -139,6 +139,8 @@ class QSK_EXPORT QskDialog : public QObject Q_INVOKABLE QColor selectColor( const QString& title ) const; + Q_INVOKABLE QFont selectFont( const QString& title ) const; + static ActionRole actionRole( Action action ); Q_SIGNALS: diff --git a/src/dialogs/QskFontSelectionWindow.cpp b/src/dialogs/QskFontSelectionWindow.cpp new file mode 100644 index 00000000..55ade2e5 --- /dev/null +++ b/src/dialogs/QskFontSelectionWindow.cpp @@ -0,0 +1,160 @@ +/****************************************************************************** + * QSkinny - Copyright (C) The authors + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "QskFontSelectionWindow.h" + +#include "QskFontRole.h" +#include "QskGridBox.h" +#include "QskLinearBox.h" +#include "QskSimpleListBox.h" +#include "QskTextLabel.h" + +#include + +template< typename W > +class QskFontSelectionWindow< W >::PrivateData +{ + public: + QFont selectedFont; + + QskSimpleListBox* familyView; + QskSimpleListBox* styleView; + QskSimpleListBox* sizeView; + + QskTextLabel* outputLabel; +}; + +template< typename W > +QskFontSelectionWindow< W >::QskFontSelectionWindow( QObject* parent, const QString& title, + QskDialog::Actions actions, QskDialog::Action defaultAction ) + : Inherited( parent, title, actions, defaultAction ) + , m_data( new PrivateData ) +{ + auto* outerBox = new QskLinearBox( Qt::Vertical ); + outerBox->setMargins( 20 ); + outerBox->setSpacing( 20 ); +#if 1 + outerBox->setFixedSize( 700, 500 ); +#endif + + setupControls( outerBox ); + loadFontInfo(); + + Inherited::setContentItem( outerBox ); +} + +template< typename W > +QskFontSelectionWindow< W >::~QskFontSelectionWindow() = default; + +template< typename W > +QFont QskFontSelectionWindow< W >::selectedFont() const +{ + return m_data->selectedFont; +} + +template< typename W > +void QskFontSelectionWindow< W >::setupControls( QQuickItem* parentItem ) +{ + auto* gridBox = new QskGridBox( parentItem ); + gridBox->setSpacing( 10 ); + + const QskFontRole role( QskFontRole::Subtitle, QskFontRole::Normal ); + + auto* familyLabel = new QskTextLabel( "Family", gridBox ); + familyLabel->setFontRole( role ); + gridBox->addItem( familyLabel, 0, 0 ); + + auto* styleLabel = new QskTextLabel( "Style", gridBox ); + styleLabel->setFontRole( role ); + gridBox->addItem( styleLabel, 0, 1 ); + + auto* sizeLabel = new QskTextLabel( "Size", gridBox ); + sizeLabel->setFontRole( role ); + gridBox->addItem( sizeLabel, 0, 2 ); + + m_data->familyView = new QskSimpleListBox( gridBox ); + m_data->familyView->setSizePolicy( Qt::Vertical, QskSizePolicy::Expanding ); + gridBox->addItem( m_data->familyView, 1, 0 ); + + m_data->styleView = new QskSimpleListBox( gridBox ); + m_data->styleView->setSizePolicy( Qt::Vertical, QskSizePolicy::Expanding ); + gridBox->addItem( m_data->styleView, 1, 1 ); + + m_data->sizeView = new QskSimpleListBox( gridBox ); + m_data->sizeView->setSizePolicy( Qt::Vertical, QskSizePolicy::Expanding ); + gridBox->addItem( m_data->sizeView, 1, 2 ); + + auto* sampleLabel = new QskTextLabel( "Sample", gridBox ); + sampleLabel->setFontRole( role ); + gridBox->addItem( sampleLabel, 2, 0 ); + + m_data->outputLabel = new QskTextLabel( gridBox ); + m_data->outputLabel->setSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Minimum ); + m_data->outputLabel->setElideMode( Qt::ElideRight ); + gridBox->addItem( m_data->outputLabel, 3, 0, 1, 3 ); + + gridBox->setColumnStretchFactor( 0, 5 ); + gridBox->setColumnStretchFactor( 1, 3 ); + gridBox->setColumnStretchFactor( 2, 2 ); +} + +template< typename W > +void QskFontSelectionWindow< W >::loadFontInfo() +{ + const auto families = QFontDatabase::families(); + m_data->familyView->setEntries( families ); + + QObject::connect( m_data->familyView, &QskSimpleListBox::selectedEntryChanged, + this, [this]( const QString& family ) + { + const auto styles = QFontDatabase::styles( family ); + m_data->styleView->setEntries( styles ); + } ); + + QObject::connect( m_data->familyView, &QskSimpleListBox::selectedEntryChanged, + this, [this]( const QString& family ) + { + const auto sizes = QFontDatabase::pointSizes( family ); + QStringList sizesString; + sizesString.reserve( sizes.count() ); + + for( const auto size : sizes ) + { + sizesString.append( QString::number( size ) ); + } + + m_data->sizeView->setEntries( sizesString ); + } ); + + auto displaySample = [this]() + { + const auto family = m_data->familyView->selectedEntry(); + const auto style = m_data->styleView->selectedEntry(); + const auto size = m_data->sizeView->selectedEntry(); + + if( !family.isNull() && !style.isNull() && !size.isNull() ) + { + auto& f = m_data->selectedFont; + + f = QFont( family, size.toInt() ); + f.setStyleName( style ); + + m_data->outputLabel->setSkinHint( QskTextLabel::Text | QskAspect::FontRole, f ); + m_data->outputLabel->resetImplicitSize(); + m_data->outputLabel->setText( "The quick brown fox jumps over the lazy dog" ); + } + else + { + m_data->outputLabel->setText( {} ); + } + }; + + QObject::connect( m_data->familyView, &QskSimpleListBox::selectedEntryChanged, this, displaySample ); + QObject::connect( m_data->styleView, &QskSimpleListBox::selectedEntryChanged, this, displaySample ); + QObject::connect( m_data->sizeView, &QskSimpleListBox::selectedEntryChanged, this, displaySample ); +} + +template class QskFontSelectionWindow< QskDialogWindow >; +template class QskFontSelectionWindow< QskDialogSubWindow >; diff --git a/src/dialogs/QskFontSelectionWindow.h b/src/dialogs/QskFontSelectionWindow.h new file mode 100644 index 00000000..f35ac1b5 --- /dev/null +++ b/src/dialogs/QskFontSelectionWindow.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * QSkinny - Copyright (C) The authors + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#ifndef QSK_FONT_SELECTION_WINDODW_H +#define QSK_FONT_SELECTION_WINDODW_H + +#include "QskWindowOrSubWindow.h" + +template< typename W > +class QskFontSelectionWindow : public QskWindowOrSubWindow< W > +{ + using Inherited = QskWindowOrSubWindow< W >; + + public: + + QskFontSelectionWindow( QObject* parent, const QString& title, + QskDialog::Actions actions, QskDialog::Action defaultAction ); + ~QskFontSelectionWindow(); + + QFont selectedFont() const; + + private: + void setupControls( QQuickItem* ); + void loadFontInfo(); + + class PrivateData; + std::unique_ptr< PrivateData > m_data; +}; + +#endif