diff --git a/src/dialogs/QskDialog.cpp b/src/dialogs/QskDialog.cpp index 5d72803d..ff8cf6c6 100644 --- a/src/dialogs/QskDialog.cpp +++ b/src/dialogs/QskDialog.cpp @@ -19,6 +19,29 @@ #include #include +static QskDialog::Action qskActionCandidate( const QskDialogButtonBox* buttonBox ) +{ + // not the fastest code ever, but usually we always + // have a AcceptRole or YesRole button + + const QskDialog::ActionRole candidates[] = + { + QskDialog::AcceptRole, QskDialog::YesRole, + QskDialog::RejectRole, QskDialog::NoRole, QskDialog::DestructiveRole, + QskDialog::UserRole, QskDialog::ResetRole, + QskDialog::ApplyRole, QskDialog::HelpRole + }; + + for ( auto role : candidates ) + { + const auto& buttons = buttonBox->buttons( role ); + if ( !buttons.isEmpty() ) + return buttonBox->action( buttons.first() ); + } + + return QskDialog::NoAction; +} + static QskDialog::DialogCode qskExec( QskDialogWindow* dialogWindow ) { #if 1 @@ -50,14 +73,14 @@ static QQuickWindow* qskSomeQuickWindow() static void qskSetupSubWindow( const QString& title, QskDialog::Actions actions, - QskDialog::Action defaultAction, QskInputSubWindow* subWindow ) + QskDialog::Action defaultAction, QskDialogSubWindow* subWindow ) { subWindow->setModal( true ); subWindow->setWindowTitle( title ); subWindow->setDialogActions( actions ); - if ( defaultAction == QskDialog::NoAction ) - defaultAction = subWindow->buttonBox()->defaultActionCandidate(); + if ( actions != QskDialog::NoAction && defaultAction == QskDialog::NoAction ) + defaultAction = qskActionCandidate( subWindow->buttonBox() ); subWindow->setDefaultDialogAction( defaultAction ); } @@ -65,15 +88,15 @@ static void qskSetupSubWindow( static void qskSetupWindow( QWindow* transientParent, const QString& title, QskDialog::Actions actions, QskDialog::Action defaultAction, - QskInputWindow* window ) + QskDialogWindow* window ) { window->setTransientParent( transientParent ); window->setTitle( title ); window->setDialogActions( actions ); - if ( defaultAction == QskDialog::NoAction ) - defaultAction = window->buttonBox()->defaultActionCandidate(); + if ( actions != QskDialog::NoAction && defaultAction == QskDialog::NoAction ) + defaultAction = qskActionCandidate( window->buttonBox() ); window->setDefaultDialogAction( defaultAction ); diff --git a/src/dialogs/QskDialogButtonBox.cpp b/src/dialogs/QskDialogButtonBox.cpp index 2d4a7770..ad535e00 100644 --- a/src/dialogs/QskDialogButtonBox.cpp +++ b/src/dialogs/QskDialogButtonBox.cpp @@ -9,7 +9,9 @@ #include "QskSkin.h" #include +#include #include + #include #include @@ -59,6 +61,7 @@ class QskDialogButtonBox::PrivateData QskLinearBox* layoutBox = nullptr; QVector< QskPushButton* > buttons[ QskDialog::NActionRoles ]; + QPointer< QskPushButton > defaultButton; QskDialog::Action clickedAction = QskDialog::NoAction; @@ -255,6 +258,12 @@ void QskDialogButtonBox::addButton( if ( button->parent() == nullptr ) button->setParent( this ); + /* + To have a proper ownership, inserting the buttons + according to the layout rules will be done later + */ + button->setParentItem( m_data->layoutBox ); + connect( button, &QskPushButton::clicked, this, &QskDialogButtonBox::onButtonClicked ); @@ -308,6 +317,16 @@ void QskDialogButtonBox::clear() invalidateLayout(); } +void QskDialogButtonBox::setDefaultButton( QskPushButton* button ) +{ + m_data->defaultButton = button; +} + +QskPushButton* QskDialogButtonBox::defaultButton() const +{ + return m_data->defaultButton; +} + void QskDialogButtonBox::setActions( QskDialog::Actions actions ) { for ( int i = 0; i < QskDialog::NActionRoles; i++ ) @@ -336,6 +355,16 @@ QVector< QskPushButton* > QskDialogButtonBox::buttons() const return buttons; } +QVector< QskPushButton* > QskDialogButtonBox::buttons( + QskDialog::ActionRole role ) const +{ + if ( role < 0 || role >= QskDialog::NActionRoles ) + return QVector< QskPushButton* >(); + + return m_data->buttons[ role ]; +} + + QskDialog::ActionRole QskDialogButtonBox::actionRole( const QskPushButton* button ) const { @@ -353,29 +382,6 @@ QskDialog::ActionRole QskDialogButtonBox::actionRole( return QskDialog::InvalidRole; } -QskDialog::Action QskDialogButtonBox::defaultActionCandidate() const -{ - // not the fastest code ever, but usually we always - // have a AcceptRole or YesRole button - - static const QVector< QskDialog::ActionRole > fallBackRoles = - { - QskDialog::AcceptRole, QskDialog::YesRole, - QskDialog::RejectRole, QskDialog::NoRole, QskDialog::DestructiveRole, - QskDialog::UserRole, QskDialog::ResetRole, - QskDialog::ApplyRole, QskDialog::HelpRole - }; - - for ( auto role : fallBackRoles ) - { - const auto defaultAction = action( buttonFromRole( role ) ); - if ( defaultAction != QskDialog::NoAction ) - return defaultAction; - } - - return QskDialog::NoAction; -} - void QskDialogButtonBox::onButtonClicked() { auto button = qobject_cast< QskPushButton* >( sender() ); @@ -458,15 +464,6 @@ QskPushButton* QskDialogButtonBox::button( QskDialog::Action action ) const return nullptr; } -QskPushButton* QskDialogButtonBox::buttonFromRole( QskDialog::ActionRole role ) const -{ - if ( role < 0 || role >= QskDialog::NActionRoles ) - return nullptr; - - const auto& buttons = m_data->buttons[ role ]; - return buttons.isEmpty() ? nullptr : buttons.first(); -} - QskDialog::Action QskDialogButtonBox::clickedAction() const { return m_data->clickedAction; diff --git a/src/dialogs/QskDialogButtonBox.h b/src/dialogs/QskDialogButtonBox.h index 73dbdf44..cd6ae289 100644 --- a/src/dialogs/QskDialogButtonBox.h +++ b/src/dialogs/QskDialogButtonBox.h @@ -44,16 +44,15 @@ class QSK_EXPORT QskDialogButtonBox : public QskBox void clear(); QVector< QskPushButton* > buttons() const; + QVector< QskPushButton* > buttons( QskDialog::ActionRole ) const; + QskDialog::ActionRole actionRole( const QskPushButton* ) const; void setActions( QskDialog::Actions ); QskDialog::Actions actions() const; QskDialog::Action action( const QskPushButton* ) const; - QskDialog::Action defaultActionCandidate() const; - QskPushButton* button( QskDialog::Action ) const; - QskPushButton* buttonFromRole( QskDialog::ActionRole ) const; QskDialog::Action clickedAction() const; @@ -62,6 +61,9 @@ class QSK_EXPORT QskDialogButtonBox : public QskBox QskAspect::Subcontrol effectiveSubcontrol( QskAspect::Subcontrol ) const override; + void setDefaultButton( QskPushButton* ); + QskPushButton* defaultButton() const; + static bool isDefaultButtonKeyEvent( const QKeyEvent* ); static QString buttonText( QskDialog::Action ); diff --git a/src/dialogs/QskDialogSubWindow.cpp b/src/dialogs/QskDialogSubWindow.cpp index f89dff15..a48bea7d 100644 --- a/src/dialogs/QskDialogSubWindow.cpp +++ b/src/dialogs/QskDialogSubWindow.cpp @@ -4,9 +4,14 @@ *****************************************************************************/ #include "QskDialogSubWindow.h" +#include "QskDialogButtonBox.h" +#include "QskLinearBox.h" +#include "QskPushButton.h" +#include "QskQuick.h" #include #include +#include static inline void qskSetRejectOnClose( QskDialogSubWindow* subWindow, bool on ) { @@ -22,10 +27,26 @@ static inline void qskSetRejectOnClose( QskDialogSubWindow* subWindow, bool on ) } } +class QskDialogSubWindow::PrivateData +{ + public: + QskDialog::Actions actions = QskDialog::NoAction; + + QPointer< QQuickItem > contentItem; + QskDialogButtonBox* buttonBox = nullptr; + QskLinearBox* layoutBox; + + QskDialog::DialogCode result = QskDialog::Rejected; +}; + QskDialogSubWindow::QskDialogSubWindow( QQuickItem* parent ) : Inherited( parent ) - , m_result( QskDialog::Rejected ) + , m_data( new PrivateData() ) { + // doing the layout manually instead ??? + setAutoLayoutChildren( true ); + m_data->layoutBox = new QskLinearBox( Qt::Vertical, this ); + qskSetRejectOnClose( this, true ); } @@ -33,14 +54,129 @@ QskDialogSubWindow::~QskDialogSubWindow() { } +void QskDialogSubWindow::setDialogActions( QskDialog::Actions actions ) +{ + if ( m_data->actions == actions ) + return; + + m_data->actions = actions; + + if ( actions == QskDialog::NoAction ) + { + delete m_data->buttonBox; + m_data->buttonBox = nullptr; + } + else + { + if ( m_data->buttonBox == nullptr ) + { + m_data->buttonBox = createButtonBox(); + + if ( m_data->buttonBox ) + { + m_data->layoutBox->addItem( m_data->buttonBox ); + + connect( m_data->buttonBox, &QskDialogButtonBox::accepted, + this, &QskDialogSubWindow::accept, Qt::UniqueConnection ); + + connect( m_data->buttonBox, &QskDialogButtonBox::rejected, + this, &QskDialogSubWindow::reject, Qt::UniqueConnection ); + } + } + + if ( m_data->buttonBox ) + m_data->buttonBox->setActions( actions ); + } +} + +QskDialog::Actions QskDialogSubWindow::dialogActions() const +{ + if ( m_data->buttonBox ) + return m_data->buttonBox->actions(); + + return QskDialog::NoAction; +} + +void QskDialogSubWindow::setContentItem( QQuickItem* item ) +{ + if ( item == m_data->contentItem ) + return; + + if ( m_data->contentItem ) + { + m_data->layoutBox->removeAt( 0 ); + if ( m_data->contentItem->parent() == m_data->layoutBox ) + delete m_data->contentItem; + } + + m_data->contentItem = item; + + if ( item ) + m_data->layoutBox->insertItem( 0, item ); +} + +QQuickItem* QskDialogSubWindow::contentItem() const +{ + return m_data->contentItem; +} + +void QskDialogSubWindow::setDefaultDialogAction( QskDialog::Action action ) +{ + QskPushButton* button = nullptr; + + if ( m_data->buttonBox ) + button = m_data->buttonBox->button( action ); + + setDefaultButton( button ); +} + +void QskDialogSubWindow::setDefaultButton( QskPushButton* button ) +{ + if ( !qskIsAncestorOf( m_data->buttonBox, button ) ) + { +#if defined( QT_DEBUG ) + qWarning( "Only buttons of the QskDialogButtonBox can be the default button." ); +#endif + return; + } + + m_data->buttonBox->setDefaultButton( button ); +} + +QskPushButton* QskDialogSubWindow::defaultButton() const +{ + if ( m_data->buttonBox == nullptr ) + return nullptr; + + return m_data->buttonBox->defaultButton(); +} + +QskDialogButtonBox* QskDialogSubWindow::buttonBox() +{ + return m_data->buttonBox; +} + +const QskDialogButtonBox* QskDialogSubWindow::buttonBox() const +{ + return m_data->buttonBox; +} + +QskDialog::Action QskDialogSubWindow::clickedAction() const +{ + if ( m_data->buttonBox ) + return m_data->buttonBox->clickedAction(); + + return QskDialog::NoAction; +} + void QskDialogSubWindow::setResult( QskDialog::DialogCode result ) { - m_result = result; + m_data->result = result; } QskDialog::DialogCode QskDialogSubWindow::result() const { - return m_result; + return m_data->result; } QskDialog::DialogCode QskDialogSubWindow::exec() @@ -66,12 +202,12 @@ QskDialog::DialogCode QskDialogSubWindow::exec() connect( this, &QskDialogSubWindow::finished, &eventLoop, &QEventLoop::quit ); ( void ) eventLoop.exec( QEventLoop::DialogExec ); - return m_result; + return m_data->result;; } void QskDialogSubWindow::done( QskDialog::DialogCode result ) { - m_result = result; + m_data->result = result; if ( !isOpen() ) return; @@ -99,6 +235,14 @@ void QskDialogSubWindow::reject() void QskDialogSubWindow::keyPressEvent( QKeyEvent* event ) { + if ( m_data->buttonBox && + QskDialogButtonBox::isDefaultButtonKeyEvent( event ) ) + { + auto button = m_data->buttonBox->defaultButton(); + if ( button && button->isEnabled() ) + button->click(); + } + if ( event->matches( QKeySequence::Cancel ) ) { // using shortcuts instead ??? @@ -110,6 +254,11 @@ void QskDialogSubWindow::keyPressEvent( QKeyEvent* event ) Inherited::keyPressEvent( event ); } +QskDialogButtonBox* QskDialogSubWindow::createButtonBox() +{ + return new QskDialogButtonBox(); +} + void QskDialogSubWindow::aboutToShow() { if ( size().isEmpty() ) diff --git a/src/dialogs/QskDialogSubWindow.h b/src/dialogs/QskDialogSubWindow.h index b04b0678..41f985fb 100644 --- a/src/dialogs/QskDialogSubWindow.h +++ b/src/dialogs/QskDialogSubWindow.h @@ -9,19 +9,41 @@ #include "QskDialog.h" #include "QskSubWindow.h" +class QskDialogButtonBox; +class QskPushButton; + class QSK_EXPORT QskDialogSubWindow : public QskSubWindow { Q_OBJECT + Q_PROPERTY( QskDialog::Actions dialogActions + READ dialogActions WRITE setDialogActions ) + using Inherited = QskSubWindow; public: QskDialogSubWindow( QQuickItem* parent = nullptr ); ~QskDialogSubWindow() override; + QskDialog::Actions dialogActions() const; + void setDialogActions( QskDialog::Actions ); + + Q_INVOKABLE QskDialog::Action clickedAction() const; + Q_INVOKABLE QskDialog::DialogCode result() const; Q_INVOKABLE QskDialog::DialogCode exec(); + void setDefaultDialogAction( QskDialog::Action ); + + void setDefaultButton( QskPushButton* ); + QskPushButton* defaultButton() const; + + QskDialogButtonBox* buttonBox(); + const QskDialogButtonBox* buttonBox() const; + + void setContentItem( QQuickItem* ); + QQuickItem* contentItem() const; + Q_SIGNALS: void finished( QskDialog::DialogCode ); void accepted(); @@ -33,13 +55,16 @@ class QSK_EXPORT QskDialogSubWindow : public QskSubWindow void reject(); protected: - void setResult( QskDialog::DialogCode r ); + void setResult( QskDialog::DialogCode ); void keyPressEvent( QKeyEvent* ) override; void aboutToShow() override; + virtual QskDialogButtonBox* createButtonBox(); + private: - QskDialog::DialogCode m_result; + class PrivateData; + std::unique_ptr< PrivateData > m_data; }; #endif diff --git a/src/dialogs/QskDialogWindow.cpp b/src/dialogs/QskDialogWindow.cpp index 0c20f270..cc49f86f 100644 --- a/src/dialogs/QskDialogWindow.cpp +++ b/src/dialogs/QskDialogWindow.cpp @@ -4,6 +4,11 @@ *****************************************************************************/ #include "QskDialogWindow.h" +#include "QskDialogButtonBox.h" +#include "QskLinearBox.h" +#include "QskPushButton.h" +#include "QskQuick.h" + #include #include @@ -16,6 +21,12 @@ class QskDialogWindow::PrivateData { } + QskDialog::Actions actions = QskDialog::NoAction; + + QPointer< QQuickItem > dialogContentItem; + QskDialogButtonBox* buttonBox = nullptr; + QskLinearBox* layoutBox; + QskDialog::DialogCode result : 1; bool inDone : 1; // flag blocking recursive done calls }; @@ -26,12 +37,132 @@ QskDialogWindow::QskDialogWindow( QWindow* parent ) { setFlags( Qt::Dialog | Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint ); + + // doing the layout manually instead ??? + setAutoLayoutChildren( true ); + m_data->layoutBox = new QskLinearBox( Qt::Vertical, contentItem() ); + m_data->layoutBox->setMargins( 5 ); } QskDialogWindow::~QskDialogWindow() { } +void QskDialogWindow::setDialogActions( QskDialog::Actions actions ) +{ + if ( m_data->actions == actions ) + return; + + m_data->actions = actions; + + if ( actions == QskDialog::NoAction ) + { + delete m_data->buttonBox; + m_data->buttonBox = nullptr; + } + else + { + if ( m_data->buttonBox == nullptr ) + { + m_data->buttonBox = createButtonBox(); + + if ( m_data->buttonBox ) + { + m_data->layoutBox->addItem( m_data->buttonBox ); + + connect( m_data->buttonBox, &QskDialogButtonBox::accepted, + this, &QskDialogWindow::accept, Qt::UniqueConnection ); + + connect( m_data->buttonBox, &QskDialogButtonBox::rejected, + this, &QskDialogWindow::reject, Qt::UniqueConnection ); + } + } + + if ( m_data->buttonBox ) + m_data->buttonBox->setActions( actions ); + } +} + +QskDialog::Actions QskDialogWindow::dialogActions() const +{ + if ( m_data->buttonBox ) + return m_data->buttonBox->actions(); + + return QskDialog::NoAction; +} + +void QskDialogWindow::setDialogContentItem( QQuickItem* item ) +{ + if ( item == m_data->dialogContentItem ) + return; + + if ( m_data->dialogContentItem ) + { + m_data->layoutBox->removeAt( 0 ); + if ( m_data->dialogContentItem->parent() == m_data->layoutBox ) + delete m_data->dialogContentItem; + } + + m_data->dialogContentItem = item; + + if ( item ) + m_data->layoutBox->insertItem( 0, item ); +} + +QQuickItem* QskDialogWindow::dialogContentItem() const +{ + return m_data->dialogContentItem; +} + +void QskDialogWindow::setDefaultButton( QskPushButton* button ) +{ + if ( !qskIsAncestorOf( m_data->buttonBox, button ) ) + { +#if defined( QT_DEBUG ) + qWarning( "Only buttons of the QskDialogButtonBox can be the default button." ); +#endif + return; + } + + m_data->buttonBox->setDefaultButton( button ); +} + +QskPushButton* QskDialogWindow::defaultButton() const +{ + if ( m_data->buttonBox == nullptr ) + return nullptr; + + return m_data->buttonBox->defaultButton(); +} + +void QskDialogWindow::setDefaultDialogAction( QskDialog::Action action ) +{ + QskPushButton* button = nullptr; + + if ( m_data->buttonBox ) + button = m_data->buttonBox->button( action ); + + setDefaultButton( button ); +} + +QskDialogButtonBox* QskDialogWindow::buttonBox() +{ + return m_data->buttonBox; +} + +const QskDialogButtonBox* QskDialogWindow::buttonBox() const +{ + return m_data->buttonBox; +} + +QskDialog::Action QskDialogWindow::clickedAction() const +{ + if ( m_data->buttonBox ) + return m_data->buttonBox->clickedAction(); + + return QskDialog::NoAction; +} + void QskDialogWindow::setResult( QskDialog::DialogCode result ) { m_data->result = result; @@ -110,6 +241,14 @@ bool QskDialogWindow::event( QEvent* event ) void QskDialogWindow::keyPressEvent( QKeyEvent* event ) { + if ( m_data->buttonBox && + QskDialogButtonBox::isDefaultButtonKeyEvent( event ) ) + { + auto button = m_data->buttonBox->defaultButton(); + if ( button && button->isEnabled() ) + button->click(); + } + if ( event->matches( QKeySequence::Cancel ) ) { // using shortcuts instead ??? @@ -121,4 +260,9 @@ void QskDialogWindow::keyPressEvent( QKeyEvent* event ) Inherited::keyPressEvent( event ); } +QskDialogButtonBox* QskDialogWindow::createButtonBox() +{ + return new QskDialogButtonBox(); +} + #include "moc_QskDialogWindow.cpp" diff --git a/src/dialogs/QskDialogWindow.h b/src/dialogs/QskDialogWindow.h index f2a690c9..24056c20 100644 --- a/src/dialogs/QskDialogWindow.h +++ b/src/dialogs/QskDialogWindow.h @@ -9,21 +9,41 @@ #include "QskDialog.h" #include "QskWindow.h" -#include +class QskDialogButtonBox; +class QskPushButton; class QSK_EXPORT QskDialogWindow : public QskWindow { Q_OBJECT + Q_PROPERTY( QskDialog::Actions dialogActions + READ dialogActions WRITE setDialogActions ) + using Inherited = QskWindow; public: QskDialogWindow( QWindow* parent = nullptr ); ~QskDialogWindow() override; + QskDialog::Actions dialogActions() const; + void setDialogActions( QskDialog::Actions ); + + Q_INVOKABLE QskDialog::Action clickedAction() const; + Q_INVOKABLE QskDialog::DialogCode result() const; Q_INVOKABLE QskDialog::DialogCode exec(); + void setDefaultDialogAction( QskDialog::Action ); + + void setDefaultButton( QskPushButton* ); + QskPushButton* defaultButton() const; + + QskDialogButtonBox* buttonBox(); + const QskDialogButtonBox* buttonBox() const; + + void setDialogContentItem( QQuickItem* ); + QQuickItem* dialogContentItem() const; + Q_SIGNALS: void finished( QskDialog::DialogCode result ); void accepted(); @@ -36,6 +56,7 @@ class QSK_EXPORT QskDialogWindow : public QskWindow protected: void setResult( QskDialog::DialogCode r ); + virtual QskDialogButtonBox* createButtonBox(); bool event( QEvent* ) override; void keyPressEvent( QKeyEvent* ) override; diff --git a/src/dialogs/QskInputSubWindow.cpp b/src/dialogs/QskInputSubWindow.cpp deleted file mode 100644 index cc252505..00000000 --- a/src/dialogs/QskInputSubWindow.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the QSkinny License, Version 1.0 - *****************************************************************************/ - -#include "QskInputSubWindow.h" -#include "QskDialogButtonBox.h" -#include "QskGraphic.h" -#include "QskGraphicLabel.h" -#include "QskLinearBox.h" -#include "QskPushButton.h" -#include "QskSkin.h" -#include "QskTextLabel.h" - -#include -#include - -namespace -{ - class TextLabel final : public QskTextLabel - { - public: - TextLabel( QskInputSubWindow* box ) - { - setObjectName( QStringLiteral( "QskInputSubWindowTextLabel" ) ); - - setWrapMode( QskTextOptions::WordWrap ); - - connect( this, &QskTextLabel::textChanged, - box, &QskInputSubWindow::infoTextChanged ); - - connect( this, &QskTextLabel::textOptionsChanged, - box, &QskInputSubWindow::infoTextOptionsChanged ); - } - }; - - class SymbolLabel final : public QskGraphicLabel - { - public: - SymbolLabel( QskInputSubWindow* ) - { - setObjectName( QStringLiteral( "QskInputSubWindowSymbolLabel" ) ); - updateSourceSize(); - } - - protected: - void changeEvent( QEvent* event ) override - { - if ( event->type() == QEvent::FontChange ) - updateSourceSize(); - - QskGraphicLabel::changeEvent( event ); - } - - private: - void updateSourceSize() - { - // when there is no explicit size known, - // we always adjust the icon according to the font - - if ( sourceSize().isEmpty() ) - { - const QFont font = effectiveFont( QskTextLabel::Text ); - setPreferredSize( -1.0, 1.5 * QFontMetricsF( font ).height() ); - } - } - }; -} - -class QskInputSubWindow::PrivateData -{ - public: - QskDialog::Actions actions = QskDialog::NoAction; - QskDialog::Action defaultAction = QskDialog::NoAction; - - QskTextLabel* infoTextLabel; - QskGraphicLabel* symbolLabel; - QPointer< QskControl > inputControl; - QskLinearBox* titleBox; - QskDialogButtonBox* buttonBox; - QskLinearBox* layoutBox; -}; - -QskInputSubWindow::QskInputSubWindow( QQuickItem* parent ) - : Inherited( parent ) - , m_data( new PrivateData() ) -{ - m_data->infoTextLabel = new TextLabel( this ); - m_data->infoTextLabel->setSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Preferred ); - m_data->infoTextLabel->setAlignment( Qt::AlignHCenter | Qt::AlignTop ); - - m_data->symbolLabel = new SymbolLabel( this ); - m_data->symbolLabel->setAlignment( Qt::AlignTop | Qt::AlignHCenter ); - m_data->symbolLabel->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); - m_data->symbolLabel->hide(); - - m_data->titleBox = new QskLinearBox( Qt::Horizontal ); - m_data->titleBox->setSpacing( 0 ); - m_data->titleBox->addItem( m_data->symbolLabel, Qt::AlignTop | Qt::AlignHCenter ); - m_data->titleBox->addItem( m_data->infoTextLabel, Qt::AlignTop | Qt::AlignHCenter ); - m_data->titleBox->setStretchFactor( m_data->infoTextLabel, 10 ); - - m_data->buttonBox = new QskDialogButtonBox(); - m_data->buttonBox->hide(); - - m_data->layoutBox = new QskLinearBox( Qt::Vertical, this ); - m_data->layoutBox->addItem( m_data->titleBox ); - m_data->layoutBox->addItem( m_data->buttonBox ); - - setAutoLayoutChildren( true ); - - connect( m_data->buttonBox, &QskDialogButtonBox::accepted, - this, &QskInputSubWindow::accept ); - - connect( m_data->buttonBox, &QskDialogButtonBox::rejected, - this, &QskInputSubWindow::reject ); - - updateTitleBox(); -} - -QskInputSubWindow::~QskInputSubWindow() -{ -} - -void QskInputSubWindow::setDialogActions( QskDialog::Actions actions ) -{ - if ( m_data->actions == actions ) - return; - - m_data->actions = actions; - - m_data->buttonBox->setActions( actions ); - m_data->buttonBox->setVisible( actions != QskDialog::NoAction ); - -#if 1 - const auto buttons = m_data->buttonBox->buttons(); - if ( !buttons.isEmpty() ) - buttons[ 0 ]->setFocus( true ); -#endif -} - -QskDialog::Actions QskInputSubWindow::dialogActions() const -{ - return m_data->buttonBox->actions(); -} - -QskDialog::Action QskInputSubWindow::defaultDialogAction() const -{ - return m_data->defaultAction; -} - -void QskInputSubWindow::setDefaultDialogAction( QskDialog::Action action ) -{ - m_data->defaultAction = action; -} - -void QskInputSubWindow::setInfoText( const QString& text ) -{ - m_data->infoTextLabel->setText( text ); - updateTitleBox(); -} - -QString QskInputSubWindow::infoText() const -{ - return m_data->infoTextLabel->text(); -} - -void QskInputSubWindow::setInfoTextOptions( const QskTextOptions& options ) -{ - m_data->infoTextLabel->setTextOptions( options ); -} - -QskTextOptions QskInputSubWindow::infoTextOptions() const -{ - return m_data->infoTextLabel->textOptions(); -} - -void QskInputSubWindow::setSymbolSource( const QUrl& url ) -{ - m_data->symbolLabel->setSource( url ); - m_data->symbolLabel->setVisible( !url.isEmpty() ); - - auto box = qobject_cast< QskLinearBox* >( - m_data->symbolLabel->parentItem() ); - - box->setSpacing( m_data->symbolLabel->isVisible() ? 15 : 0 ); // metrics !! - updateTitleBox(); -} - -void QskInputSubWindow::setSymbolType( int symbolType ) -{ - setSymbol( effectiveSkin()->symbol( symbolType ) ); -} - -QUrl QskInputSubWindow::symbolSource() const -{ - return m_data->symbolLabel->source(); -} - -void QskInputSubWindow::setSymbol( const QskGraphic& symbol ) -{ - m_data->symbolLabel->setVisible( !symbol.isNull() ); - m_data->symbolLabel->setGraphic( symbol ); - updateTitleBox(); -} - -QskGraphic QskInputSubWindow::symbol() const -{ - return m_data->symbolLabel->graphic(); -} - -void QskInputSubWindow::setInputControl( QskControl* control ) -{ - if ( control == m_data->inputControl ) - return; - - delete m_data->inputControl; - m_data->inputControl = control; - - if ( m_data->inputControl ) - m_data->layoutBox->insertItem( 1, control ); -} - -QskControl* QskInputSubWindow::inputControl() const -{ - return m_data->inputControl; -} - -QskDialogButtonBox* QskInputSubWindow::buttonBox() -{ - return m_data->buttonBox; -} - -const QskDialogButtonBox* QskInputSubWindow::buttonBox() const -{ - return m_data->buttonBox; -} - -QskDialog::Action QskInputSubWindow::clickedAction() const -{ - return m_data->buttonBox->clickedAction(); -} - -void QskInputSubWindow::keyPressEvent( QKeyEvent* event ) -{ - if ( QskDialogButtonBox::isDefaultButtonKeyEvent( event ) ) - { - auto button = m_data->buttonBox->button( defaultDialogAction() ); - if ( button && button->isEnabled() ) - button->click(); - } - - Inherited::keyPressEvent( event ); -} - -void QskInputSubWindow::updateTitleBox() -{ - m_data->titleBox->setVisible( !( m_data->symbolLabel->isEmpty() && - m_data->infoTextLabel->text().isEmpty() ) ); -} - -#include "moc_QskInputSubWindow.cpp" diff --git a/src/dialogs/QskInputSubWindow.h b/src/dialogs/QskInputSubWindow.h deleted file mode 100644 index fb835c19..00000000 --- a/src/dialogs/QskInputSubWindow.h +++ /dev/null @@ -1,85 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the QSkinny License, Version 1.0 - *****************************************************************************/ - -#ifndef QSK_INPUT_SUB_WINDOW_H -#define QSK_INPUT_SUB_WINDOW_H 1 - -#include "QskDialogSubWindow.h" - -class QskGraphic; -class QskTextOptions; -class QskDialogButtonBox; - -class QSK_EXPORT QskInputSubWindow : public QskDialogSubWindow -{ - Q_OBJECT - - Q_PROPERTY( QString infoText READ infoText - WRITE setInfoText NOTIFY infoTextChanged FINAL ) - - Q_PROPERTY( QskTextOptions infoTextOptions READ infoTextOptions - WRITE setInfoTextOptions NOTIFY infoTextOptionsChanged ) - - Q_PROPERTY( QUrl symbolSource READ symbolSource - WRITE setSymbolSource NOTIFY symbolSourceChanged FINAL ) - - Q_PROPERTY( QskDialog::Actions dialogActions - READ dialogActions WRITE setDialogActions ) - - Q_PROPERTY( QskDialog::Action defaultDialogAction - READ defaultDialogAction WRITE setDefaultDialogAction ) - - using Inherited = QskDialogSubWindow; - - public: - QskInputSubWindow( QQuickItem* parent = nullptr ); - ~QskInputSubWindow() override; - - QskDialog::Actions dialogActions() const; - void setDialogActions( QskDialog::Actions ); - - QskDialog::Action defaultDialogAction() const; - void setDefaultDialogAction( QskDialog::Action ); - - void setInfoTextOptions( const QskTextOptions& ); - QskTextOptions infoTextOptions() const; - - QString infoText() const; - - void setSymbolSource( const QUrl& url ); - QUrl symbolSource() const; - - void setSymbolType( int symbolType ); - - void setSymbol( const QskGraphic& ); - QskGraphic symbol() const; - - QskDialog::Action clickedAction() const; - - QskDialogButtonBox* buttonBox(); - const QskDialogButtonBox* buttonBox() const; - - public Q_SLOTS: - void setInfoText( const QString& ); - - Q_SIGNALS: - void infoTextChanged(); - void infoTextOptionsChanged(); - void symbolSourceChanged(); - - protected: - void setInputControl( QskControl* ); - QskControl* inputControl() const; - - void keyPressEvent( QKeyEvent* ) override; - - private: - void updateTitleBox(); - - class PrivateData; - std::unique_ptr< PrivateData > m_data; -}; - -#endif diff --git a/src/dialogs/QskInputWindow.cpp b/src/dialogs/QskInputWindow.cpp deleted file mode 100644 index 37b6f0b7..00000000 --- a/src/dialogs/QskInputWindow.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the QSkinny License, Version 1.0 - *****************************************************************************/ - -#include "QskInputWindow.h" -#include "QskGraphic.h" -#include "QskInputSubWindow.h" -#include "QskTextOptions.h" - -QskInputWindow::QskInputWindow( QWindow* parent ) - : QskDialogWindow( parent ) - , m_subWindow( nullptr ) -{ - setFlags( Qt::Dialog | Qt::WindowTitleHint | - Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint ); - - setAutoLayoutChildren( true ); -} - -QskInputWindow::~QskInputWindow() -{ -} - -void QskInputWindow::setSubWindow( QskInputSubWindow* subWindow ) -{ - if ( subWindow == m_subWindow ) - return; - - if ( m_subWindow ) - delete m_subWindow; - - m_subWindow = subWindow; - - if ( m_subWindow ) - { -#if 1 - // we shoudn't have a subwindow here TODO ... - m_subWindow->setModal( false ); - m_subWindow->setDecorated( false ); - m_subWindow->setOverlay( false ); - m_subWindow->setFaderEffect( false ); - m_subWindow->open(); -#endif - - addItem( m_subWindow ); - - connect( m_subWindow, &QskInputSubWindow::finished, - this, &QskInputWindow::done ); - } -} - -QskInputSubWindow* QskInputWindow::subWindow() const -{ - return m_subWindow; -} - -QskDialog::Actions QskInputWindow::dialogActions() const -{ - return m_subWindow ? m_subWindow->dialogActions() : QskDialog::NoAction; -} - -void QskInputWindow::setDialogActions( QskDialog::Actions actions ) -{ - if ( m_subWindow ) - m_subWindow->setDialogActions( actions ); -} - -QskDialog::Action QskInputWindow::defaultDialogAction() const -{ - return m_subWindow ? m_subWindow->defaultDialogAction() : QskDialog::NoAction; -} - -void QskInputWindow::setDefaultDialogAction( QskDialog::Action action ) -{ - if ( m_subWindow ) - m_subWindow->setDefaultDialogAction( action ); -} - -void QskInputWindow::setInfoText( const QString& text ) -{ - if ( m_subWindow && text != m_subWindow->infoText() ) - { - m_subWindow->setInfoText( text ); - Q_EMIT infoTextChanged(); - } -} - -QString QskInputWindow::infoText() const -{ - return m_subWindow ? m_subWindow->infoText() : QString(); -} - -void QskInputWindow::setInfoTextOptions( const QskTextOptions& options ) -{ - if ( m_subWindow && options != m_subWindow->infoTextOptions() ) - { - m_subWindow->setInfoTextOptions( options ); - Q_EMIT infoTextOptionsChanged(); - } -} - -QskTextOptions QskInputWindow::infoTextOptions() const -{ - return m_subWindow ? m_subWindow->infoTextOptions() : QskTextOptions(); -} - -void QskInputWindow::setSymbolSource( const QUrl& url ) -{ - if ( m_subWindow && url != m_subWindow->symbolSource() ) - { - m_subWindow->setSymbolSource( url ); - Q_EMIT symbolSourceChanged(); - } -} - -QUrl QskInputWindow::symbolSource() const -{ - return m_subWindow ? m_subWindow->symbolSource() : QUrl(); -} - -void QskInputWindow::setSymbolType( int symbolType ) -{ - if ( m_subWindow ) - m_subWindow->setSymbolType( symbolType ); -} - -void QskInputWindow::setSymbol( const QskGraphic& symbol ) -{ - if ( m_subWindow ) - m_subWindow->setSymbol( symbol ); -} - -QskGraphic QskInputWindow::symbol() const -{ - return m_subWindow ? m_subWindow->symbol() : QskGraphic(); -} - -QskDialog::Action QskInputWindow::clickedAction() const -{ - return m_subWindow->clickedAction(); -} - -QskDialogButtonBox* QskInputWindow::buttonBox() -{ - return m_subWindow ? m_subWindow->buttonBox() : nullptr; -} - -const QskDialogButtonBox* QskInputWindow::buttonBox() const -{ - return m_subWindow ? m_subWindow->buttonBox() : nullptr; -} - -#include "moc_QskInputWindow.cpp" diff --git a/src/dialogs/QskInputWindow.h b/src/dialogs/QskInputWindow.h deleted file mode 100644 index 5cc3455d..00000000 --- a/src/dialogs/QskInputWindow.h +++ /dev/null @@ -1,82 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the QSkinny License, Version 1.0 - *****************************************************************************/ - -#ifndef QSK_INPUT_WINDOW_H -#define QSK_INPUT_WINDOW_H 1 - -#include "QskDialogWindow.h" - -class QskGraphic; -class QskTextOptions; -class QskDialogButtonBox; -class QskControl; -class QskInputSubWindow; - -class QSK_EXPORT QskInputWindow : public QskDialogWindow -{ - Q_OBJECT - - Q_PROPERTY( QString infoText READ infoText - WRITE setInfoText NOTIFY infoTextChanged FINAL ) - - Q_PROPERTY( QskTextOptions infoTextOptions READ infoTextOptions - WRITE setInfoTextOptions NOTIFY infoTextOptionsChanged ) - - Q_PROPERTY( QUrl symbolSource READ symbolSource - WRITE setSymbolSource NOTIFY symbolSourceChanged FINAL ) - - Q_PROPERTY( QskDialog::Actions dialogActions - READ dialogActions WRITE setDialogActions ) - - Q_PROPERTY( QskDialog::Action defaultDialogAction - READ defaultDialogAction WRITE setDefaultDialogAction ) - - using Inherited = QskDialogWindow; - - public: - QskInputWindow( QWindow* parent = nullptr ); - ~QskInputWindow() override; - - QskDialog::Actions dialogActions() const; - void setDialogActions( QskDialog::Actions ); - - QskDialog::Action defaultDialogAction() const; - void setDefaultDialogAction( QskDialog::Action ); - - void setInfoTextOptions( const QskTextOptions& ); - QskTextOptions infoTextOptions() const; - - QString infoText() const; - - void setSymbolType( int ); - - void setSymbolSource( const QUrl& ); - QUrl symbolSource() const; - - void setSymbol( const QskGraphic& ); - QskGraphic symbol() const; - - QskDialog::Action clickedAction() const; - - QskDialogButtonBox* buttonBox(); - const QskDialogButtonBox* buttonBox() const; - - public Q_SLOTS: - void setInfoText( const QString& ); - - Q_SIGNALS: - void infoTextChanged(); - void infoTextOptionsChanged(); - void symbolSourceChanged(); - - protected: - void setSubWindow( QskInputSubWindow* ); - QskInputSubWindow* subWindow() const; - - private: - QskInputSubWindow* m_subWindow; -}; - -#endif diff --git a/src/dialogs/QskMessageSubWindow.cpp b/src/dialogs/QskMessageSubWindow.cpp index 741d1048..59df844c 100644 --- a/src/dialogs/QskMessageSubWindow.cpp +++ b/src/dialogs/QskMessageSubWindow.cpp @@ -4,14 +4,150 @@ *****************************************************************************/ #include "QskMessageSubWindow.h" +#include "QskGraphic.h" +#include "QskGraphicLabel.h" +#include "QskLinearBox.h" +#include "QskSkin.h" +#include "QskTextLabel.h" + +#include + +namespace +{ + class TextLabel final : public QskTextLabel + { + public: + TextLabel( QskMessageSubWindow* box ) + { + setObjectName( QStringLiteral( "QskMessageSubWindowTextLabel" ) ); + initSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Preferred ); + + setAlignment( Qt::AlignHCenter | Qt::AlignTop ); + setWrapMode( QskTextOptions::WordWrap ); + + connect( this, &QskTextLabel::textChanged, + box, &QskMessageSubWindow::infoTextChanged ); + + connect( this, &QskTextLabel::textOptionsChanged, + box, &QskMessageSubWindow::infoTextOptionsChanged ); + } + }; + + class SymbolLabel final : public QskGraphicLabel + { + public: + SymbolLabel( QskMessageSubWindow* ) + { + setObjectName( QStringLiteral( "QskMessageSubWindowSymbolLabel" ) ); + initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); + + setAlignment( Qt::AlignTop | Qt::AlignHCenter ); + updateSourceSize(); + } + + protected: + void changeEvent( QEvent* event ) override + { + if ( event->type() == QEvent::FontChange ) + updateSourceSize(); + + QskGraphicLabel::changeEvent( event ); + } + + private: + void updateSourceSize() + { + // when there is no explicit size known, + // we always adjust the icon according to the font + + if ( sourceSize().isEmpty() ) + { + const QFont font = effectiveFont( QskTextLabel::Text ); + setPreferredSize( -1.0, 1.5 * QFontMetricsF( font ).height() ); + } + } + }; +} + +class QskMessageSubWindow::PrivateData +{ + public: + QskGraphicLabel* symbolLabel; + QskTextLabel* infoTextLabel; +}; QskMessageSubWindow::QskMessageSubWindow( QQuickItem* parent ) : Inherited( parent ) + , m_data( new PrivateData() ) { + m_data->infoTextLabel = new TextLabel( this ); + + m_data->symbolLabel = new SymbolLabel( this ); + m_data->symbolLabel->hide(); + + const auto alignment = Qt::AlignTop | Qt::AlignHCenter; + + auto box = new QskLinearBox( Qt::Horizontal ); + box->setSpacing( 0 ); + box->addItem( m_data->symbolLabel, alignment ); + box->addItem( m_data->infoTextLabel, alignment ); + box->setStretchFactor( m_data->infoTextLabel, 10 ); + + setContentItem( box ); } QskMessageSubWindow::~QskMessageSubWindow() { } +void QskMessageSubWindow::setInfoText( const QString& text ) +{ + m_data->infoTextLabel->setText( text ); +} + +QString QskMessageSubWindow::infoText() const +{ + return m_data->infoTextLabel->text(); +} + +void QskMessageSubWindow::setInfoTextOptions( const QskTextOptions& options ) +{ + m_data->infoTextLabel->setTextOptions( options ); +} + +QskTextOptions QskMessageSubWindow::infoTextOptions() const +{ + return m_data->infoTextLabel->textOptions(); +} + +void QskMessageSubWindow::setSymbolSource( const QUrl& url ) +{ + m_data->symbolLabel->setSource( url ); + m_data->symbolLabel->setVisible( !url.isEmpty() ); + + if ( auto box = qobject_cast< QskLinearBox* >( contentItem() ) ) + box->setSpacing( m_data->symbolLabel->isVisible() ? 15 : 0 ); // metrics !! +} + +void QskMessageSubWindow::setSymbolType( int symbolType ) +{ + setSymbol( effectiveSkin()->symbol( symbolType ) ); +} + +QUrl QskMessageSubWindow::symbolSource() const +{ + return m_data->symbolLabel->source(); +} + +void QskMessageSubWindow::setSymbol( const QskGraphic& symbol ) +{ + m_data->symbolLabel->setVisible( !symbol.isNull() ); + m_data->symbolLabel->setGraphic( symbol ); +} + +QskGraphic QskMessageSubWindow::symbol() const +{ + return m_data->symbolLabel->graphic(); +} + #include "moc_QskMessageSubWindow.cpp" diff --git a/src/dialogs/QskMessageSubWindow.h b/src/dialogs/QskMessageSubWindow.h index 070a5793..48863b35 100644 --- a/src/dialogs/QskMessageSubWindow.h +++ b/src/dialogs/QskMessageSubWindow.h @@ -6,17 +6,52 @@ #ifndef QSK_MESSAGE_SUB_WINDOW_H #define QSK_MESSAGE_SUB_WINDOW_H 1 -#include "QskInputSubWindow.h" +#include "QskDialogSubWindow.h" -class QSK_EXPORT QskMessageSubWindow : public QskInputSubWindow +class QskGraphic; +class QskTextOptions; + +class QSK_EXPORT QskMessageSubWindow : public QskDialogSubWindow { Q_OBJECT - using Inherited = QskInputSubWindow; + Q_PROPERTY( QString infoText READ infoText + WRITE setInfoText NOTIFY infoTextChanged ) + + Q_PROPERTY( QskTextOptions infoTextOptions READ infoTextOptions + WRITE setInfoTextOptions NOTIFY infoTextOptionsChanged ) + + Q_PROPERTY( QUrl symbolSource READ symbolSource WRITE setSymbolSource ) + + using Inherited = QskDialogSubWindow; public: QskMessageSubWindow( QQuickItem* parent = nullptr ); ~QskMessageSubWindow() override; + + void setInfoTextOptions( const QskTextOptions& ); + QskTextOptions infoTextOptions() const; + + QString infoText() const; + + void setSymbolSource( const QUrl& url ); + QUrl symbolSource() const; + + void setSymbolType( int symbolType ); + + void setSymbol( const QskGraphic& ); + QskGraphic symbol() const; + + public Q_SLOTS: + void setInfoText( const QString& ); + + Q_SIGNALS: + void infoTextChanged( const QString& ); + void infoTextOptionsChanged( const QskTextOptions& ); + + private: + class PrivateData; + std::unique_ptr< PrivateData > m_data; }; #endif diff --git a/src/dialogs/QskMessageWindow.cpp b/src/dialogs/QskMessageWindow.cpp index d4ba408c..46097ebf 100644 --- a/src/dialogs/QskMessageWindow.cpp +++ b/src/dialogs/QskMessageWindow.cpp @@ -4,16 +4,155 @@ *****************************************************************************/ #include "QskMessageWindow.h" -#include "QskMessageSubWindow.h" +#include "QskGraphicLabel.h" +#include "QskGraphic.h" +#include "QskLinearBox.h" +#include "QskSkin.h" +#include "QskTextLabel.h" +#include "QskTextOptions.h" + +#include + +namespace +{ + class TextLabel final : public QskTextLabel + { + public: + TextLabel( QskMessageWindow* box ) + { + setObjectName( QStringLiteral( "QskMessageWindowTextLabel" ) ); + initSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Preferred ); + + setAlignment( Qt::AlignHCenter | Qt::AlignTop ); + setWrapMode( QskTextOptions::WordWrap ); + + connect( this, &QskTextLabel::textChanged, + box, &QskMessageWindow::infoTextChanged ); + + connect( this, &QskTextLabel::textOptionsChanged, + box, &QskMessageWindow::infoTextOptionsChanged ); + } + }; + + class SymbolLabel final : public QskGraphicLabel + { + public: + SymbolLabel( QskMessageWindow* ) + { + setObjectName( QStringLiteral( "QskMessageWindowSymbolLabel" ) ); + initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); + + setAlignment( Qt::AlignTop | Qt::AlignHCenter ); + updateSourceSize(); + } + + protected: + void changeEvent( QEvent* event ) override + { + if ( event->type() == QEvent::FontChange ) + updateSourceSize(); + + QskGraphicLabel::changeEvent( event ); + } + + private: + void updateSourceSize() + { + // when there is no explicit size known, + // we always adjust the icon according to the font + + if ( sourceSize().isEmpty() ) + { + const QFont font = effectiveFont( QskTextLabel::Text ); + setPreferredSize( -1.0, 1.5 * QFontMetricsF( font ).height() ); + } + } + }; +} + +class QskMessageWindow::PrivateData +{ + public: + QskGraphicLabel* symbolLabel; + QskTextLabel* textLabel; +}; QskMessageWindow::QskMessageWindow( QWindow* parent ) : Inherited( parent ) + , m_data( new PrivateData() ) { - setSubWindow( new QskMessageSubWindow() ); + setFlags( Qt::Dialog | Qt::WindowTitleHint | + Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint ); + + m_data->textLabel = new TextLabel( this ); + + m_data->symbolLabel = new SymbolLabel( this ); + m_data->symbolLabel->hide(); + + const auto alignment = Qt::AlignTop | Qt::AlignHCenter; + + auto box = new QskLinearBox( Qt::Horizontal ); + box->setSpacing( 0 ); + box->addItem( m_data->symbolLabel, alignment ); + box->addItem( m_data->textLabel, alignment ); + box->setStretchFactor( m_data->textLabel, 10 ); + + setDialogContentItem( box ); } QskMessageWindow::~QskMessageWindow() { } +void QskMessageWindow::setInfoText( const QString& text ) +{ + m_data->textLabel->setText( text ); +} + +QString QskMessageWindow::infoText() const +{ + return m_data->textLabel->text(); +} + +void QskMessageWindow::setInfoTextOptions( const QskTextOptions& options ) +{ + m_data->textLabel->setTextOptions( options ); +} + +QskTextOptions QskMessageWindow::infoTextOptions() const +{ + return m_data->textLabel->textOptions(); +} + +void QskMessageWindow::setSymbolSource( const QUrl& url ) +{ + m_data->symbolLabel->setSource( url ); + m_data->symbolLabel->setVisible( !url.isEmpty() ); + + if ( auto box = qobject_cast< QskLinearBox* >( contentItem() ) ) + box->setSpacing( m_data->symbolLabel->isVisible() ? 15 : 0 ); // metrics !! +} + +void QskMessageWindow::setSymbolType( int symbolType ) +{ + const auto skin = m_data->symbolLabel->effectiveSkin(); + setSymbol( skin->symbol( symbolType ) ); +} + +QUrl QskMessageWindow::symbolSource() const +{ + return m_data->symbolLabel->source(); +} + +void QskMessageWindow::setSymbol( const QskGraphic& symbol ) +{ + m_data->symbolLabel->setVisible( !symbol.isNull() ); + m_data->symbolLabel->setGraphic( symbol ); +} + +QskGraphic QskMessageWindow::symbol() const +{ + return m_data->symbolLabel->graphic(); +} + #include "moc_QskMessageWindow.cpp" diff --git a/src/dialogs/QskMessageWindow.h b/src/dialogs/QskMessageWindow.h index c348c657..24f5fdb0 100644 --- a/src/dialogs/QskMessageWindow.h +++ b/src/dialogs/QskMessageWindow.h @@ -6,19 +6,53 @@ #ifndef QSK_MESSAGE_WINDOW_H #define QSK_MESSAGE_WINDOW_H 1 -#include "QskInputWindow.h" +#include "QskDialogWindow.h" -class QskMessageDialogBox; +class QskTextOptions; +class QskGraphic; -class QSK_EXPORT QskMessageWindow : public QskInputWindow +class QSK_EXPORT QskMessageWindow : public QskDialogWindow { Q_OBJECT - using Inherited = QskInputWindow; + Q_PROPERTY( QString infoText READ infoText + WRITE setInfoText NOTIFY infoTextChanged ) + + Q_PROPERTY( QskTextOptions infoTextOptions READ infoTextOptions + WRITE setInfoTextOptions NOTIFY infoTextOptionsChanged ) + + Q_PROPERTY( QUrl symbolSource READ symbolSource WRITE setSymbolSource ) + + using Inherited = QskDialogWindow; public: QskMessageWindow( QWindow* parent = nullptr ); ~QskMessageWindow() override; + + void setInfoTextOptions( const QskTextOptions& ); + QskTextOptions infoTextOptions() const; + + QString infoText() const; + + void setSymbolSource( const QUrl& url ); + QUrl symbolSource() const; + + void setSymbolType( int symbolType ); + + void setSymbol( const QskGraphic& ); + QskGraphic symbol() const; + + public Q_SLOTS: + void setInfoText( const QString& ); + + Q_SIGNALS: + void infoTextChanged( const QString& ); + void infoTextOptionsChanged( const QskTextOptions& ); + + private: + class PrivateData; + std::unique_ptr< PrivateData > m_data; + }; #endif diff --git a/src/dialogs/QskSelectionSubWindow.cpp b/src/dialogs/QskSelectionSubWindow.cpp index e46d757c..13c6648c 100644 --- a/src/dialogs/QskSelectionSubWindow.cpp +++ b/src/dialogs/QskSelectionSubWindow.cpp @@ -4,10 +4,31 @@ *****************************************************************************/ #include "QskSelectionSubWindow.h" +#include "QskLinearBox.h" #include "QskSimpleListBox.h" +#include "QskTextLabel.h" namespace { + class TextLabel final : public QskTextLabel + { + public: + TextLabel( QskSelectionSubWindow* subWindow ) + { + setObjectName( QStringLiteral( "QskSelectionSubWindowTextLabel" ) ); + initSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Constrained ); + + setAlignment( Qt::AlignLeft | Qt::AlignTop ); + setWrapMode( QskTextOptions::WordWrap ); + + connect( this, &QskTextLabel::textChanged, + subWindow, &QskSelectionSubWindow::infoTextChanged ); + + connect( this, &QskTextLabel::textOptionsChanged, + subWindow, &QskSelectionSubWindow::infoTextOptionsChanged ); + } + }; + class ListBox final : public QskSimpleListBox { public: @@ -35,10 +56,29 @@ namespace }; } +class QskSelectionSubWindow::PrivateData +{ + public: + QskTextLabel* textLabel; + QskSimpleListBox* listBox; +}; + QskSelectionSubWindow::QskSelectionSubWindow( QQuickItem* parent ) : Inherited( parent ) + , m_data( new PrivateData ) { - setInputControl( new ListBox( this ) ); + m_data->textLabel = new TextLabel( this ); + m_data->textLabel->setVisible( false ); + + m_data->listBox = new ListBox( this ); + + auto box = new QskLinearBox( Qt::Vertical ); + box->setSpacing( 10 ); // hint + box->addItem( m_data->textLabel ); + box->addItem( m_data->listBox ); + box->setStretchFactor( 1, 10 ); + + setContentItem( box ); setDialogActions( QskDialog::Ok | QskDialog::Cancel ); } @@ -46,34 +86,54 @@ QskSelectionSubWindow::~QskSelectionSubWindow() { } +void QskSelectionSubWindow::setInfoText( const QString& text ) +{ + m_data->textLabel->setText( text ); + m_data->textLabel->setVisible( !text.isEmpty() ); +} + +QString QskSelectionSubWindow::infoText() const +{ + return m_data->textLabel->text(); +} + +void QskSelectionSubWindow::setInfoTextOptions( const QskTextOptions& options ) +{ + if ( options != infoTextOptions() ) + { + m_data->textLabel->setTextOptions( options ); + Q_EMIT infoTextOptionsChanged( options ); + } +} + +QskTextOptions QskSelectionSubWindow::infoTextOptions() const +{ + return m_data->textLabel->textOptions(); +} + void QskSelectionSubWindow::setEntries( const QStringList& entries ) { - auto listBox = static_cast< ListBox* >( inputControl() ); - listBox->setEntries( entries ); + m_data->listBox->setEntries( entries ); } QStringList QskSelectionSubWindow::entries() const { - const auto* listBox = static_cast< const ListBox* >( inputControl() ); - return listBox->entries(); + return m_data->listBox->entries(); } void QskSelectionSubWindow::setSelectedRow( int row ) { - auto* listBox = static_cast< ListBox* >( inputControl() ); - listBox->setSelectedRow( row ); + m_data->listBox->setSelectedRow( row ); } int QskSelectionSubWindow::selectedRow() const { - const auto listBox = static_cast< const ListBox* >( inputControl() ); - return listBox->selectedRow(); + return m_data->listBox->selectedRow(); } QString QskSelectionSubWindow::selectedEntry() const { - const auto listBox = static_cast< const ListBox* >( inputControl() ); - return listBox->selectedEntry(); + return m_data->listBox->selectedEntry(); } #include "moc_QskSelectionSubWindow.cpp" diff --git a/src/dialogs/QskSelectionSubWindow.h b/src/dialogs/QskSelectionSubWindow.h index 36aa1186..5259c7df 100644 --- a/src/dialogs/QskSelectionSubWindow.h +++ b/src/dialogs/QskSelectionSubWindow.h @@ -6,38 +6,56 @@ #ifndef QSK_SELECTION_SUB_WINDOW_H #define QSK_SELECTION_SUB_WINDOW_H 1 -#include "QskInputSubWindow.h" +#include "QskDialogSubWindow.h" -class QskSelectionDialogBox; +class QskTextOptions; -class QSK_EXPORT QskSelectionSubWindow : public QskInputSubWindow +class QSK_EXPORT QskSelectionSubWindow : public QskDialogSubWindow { Q_OBJECT + Q_PROPERTY( QString infoText READ infoText + WRITE setInfoText NOTIFY infoTextChanged ) + + Q_PROPERTY( QskTextOptions infoTextOptions READ infoTextOptions + WRITE setInfoTextOptions NOTIFY infoTextOptionsChanged ) + Q_PROPERTY( QStringList entries READ entries WRITE setEntries NOTIFY entriesChanged FINAL ) Q_PROPERTY( int selectedRow READ selectedRow WRITE setSelectedRow NOTIFY selectedRowChanged FINAL ) - using Inherited = QskInputSubWindow; + using Inherited = QskDialogSubWindow; public: QskSelectionSubWindow( QQuickItem* parent = nullptr ); ~QskSelectionSubWindow() override; + void setInfoTextOptions( const QskTextOptions& ); + QskTextOptions infoTextOptions() const; + + QString infoText() const; + Q_INVOKABLE QStringList entries() const; Q_INVOKABLE int selectedRow() const; Q_INVOKABLE QString selectedEntry() const; public Q_SLOTS: + void setInfoText( const QString& ); void setEntries( const QStringList& ); void setSelectedRow( int row ); Q_SIGNALS: + void infoTextChanged( const QString& ); + void infoTextOptionsChanged( const QskTextOptions& ); void selectedRowChanged( int ); void selectedEntryChanged( const QString& ); void entriesChanged(); + + private: + class PrivateData; + std::unique_ptr< PrivateData > m_data; }; #endif diff --git a/src/dialogs/QskSelectionWindow.cpp b/src/dialogs/QskSelectionWindow.cpp index a798c63c..4f275649 100644 --- a/src/dialogs/QskSelectionWindow.cpp +++ b/src/dialogs/QskSelectionWindow.cpp @@ -4,57 +4,143 @@ *****************************************************************************/ #include "QskSelectionWindow.h" -#include "QskSelectionSubWindow.h" +#include "QskGraphicLabel.h" +#include "QskGraphic.h" +#include "QskLinearBox.h" +#include "QskSimpleListBox.h" +#include "QskTextLabel.h" +#include "QskTextOptions.h" + +namespace +{ + class TextLabel final : public QskTextLabel + { + public: + TextLabel( QskSelectionWindow* window ) + { + setObjectName( QStringLiteral( "QskSelectionWindowTextLabel" ) ); + initSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Preferred ); + + setAlignment( Qt::AlignLeft | Qt::AlignTop ); + setWrapMode( QskTextOptions::WordWrap ); + + connect( this, &QskTextLabel::textChanged, + window, &QskSelectionWindow::infoTextChanged ); + + connect( this, &QskTextLabel::textOptionsChanged, + window, &QskSelectionWindow::infoTextOptionsChanged ); + } + }; + + class ListBox final : public QskSimpleListBox + { + public: + ListBox( QskSelectionWindow* window ) + { + setObjectName( QStringLiteral( "QskSelectionWindowListBox" ) ); + + connect( this, &QskSimpleListBox::selectedRowChanged, + window, &QskSelectionWindow::selectedRowChanged ); + + connect( this, &QskSimpleListBox::selectedEntryChanged, + window, &QskSelectionWindow::selectedEntryChanged ); + + connect( this, &QskSimpleListBox::entriesChanged, + window, &QskSelectionWindow::entriesChanged ); + } + +#if 1 + // how to find a reasonable default size ??? + QSizeF contentsSizeHint() const override + { + return QSizeF( 500, 500 ); + } +#endif + }; +} + +class QskSelectionWindow::PrivateData +{ + public: + QskTextLabel* textLabel; + QskSimpleListBox* listBox; +}; QskSelectionWindow::QskSelectionWindow( QWindow* parent ) : Inherited( parent ) + , m_data( new PrivateData ) { - auto subWindow = new QskSelectionSubWindow(); + setFlags( Qt::Dialog | Qt::WindowTitleHint | + Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint ); - connect( subWindow, &QskSelectionSubWindow::selectedRowChanged, - this, &QskSelectionWindow::selectedRowChanged ); + m_data->textLabel = new TextLabel( this ); + m_data->textLabel->setVisible( false ); - connect( subWindow, &QskSelectionSubWindow::selectedEntryChanged, - this, &QskSelectionWindow::selectedEntryChanged ); + m_data->listBox = new ListBox( this ); - connect( subWindow, &QskSelectionSubWindow::entriesChanged, - this, &QskSelectionWindow::entriesChanged ); + auto box = new QskLinearBox( Qt::Vertical ); + box->setMargins( 5 ); + box->setSpacing( 10 ); + box->addItem( m_data->textLabel ); + box->addItem( m_data->listBox ); + box->setStretchFactor( m_data->listBox, 10 ); - setSubWindow( subWindow ); + setDialogContentItem( box ); + setDialogActions( QskDialog::Ok | QskDialog::Cancel ); } QskSelectionWindow::~QskSelectionWindow() { } +void QskSelectionWindow::setInfoText( const QString& text ) +{ + m_data->textLabel->setText( text ); + m_data->textLabel->setVisible( !text.isEmpty() ); +} + +QString QskSelectionWindow::infoText() const +{ + return m_data->textLabel->text(); +} + +void QskSelectionWindow::setInfoTextOptions( const QskTextOptions& options ) +{ + if ( options != infoTextOptions() ) + { + m_data->textLabel->setTextOptions( options ); + Q_EMIT infoTextOptionsChanged( options ); + } +} + +QskTextOptions QskSelectionWindow::infoTextOptions() const +{ + return m_data->textLabel->textOptions(); +} + void QskSelectionWindow::setEntries( const QStringList& entries ) { - auto subWindow = static_cast< QskSelectionSubWindow* >( this->subWindow() ); - subWindow->setEntries( entries ); + m_data->listBox->setEntries( entries ); } QStringList QskSelectionWindow::entries() const { - auto w = static_cast< const QskSelectionSubWindow* >( this->subWindow() ); - return w->entries(); + return m_data->listBox->entries(); } void QskSelectionWindow::setSelectedRow( int row ) { - auto subWindow = static_cast< QskSelectionSubWindow* >( this->subWindow() ); - subWindow->setSelectedRow( row ); + m_data->listBox->setSelectedRow( row ); } int QskSelectionWindow::selectedRow() const { - auto subWindow = static_cast< const QskSelectionSubWindow* >( this->subWindow() ); - return subWindow->selectedRow(); + return m_data->listBox->selectedRow(); } QString QskSelectionWindow::selectedEntry() const { - auto subWindow = static_cast< const QskSelectionSubWindow* >( this->subWindow() ); - return subWindow->selectedEntry(); + return m_data->listBox->selectedEntry(); } #include "moc_QskSelectionWindow.cpp" diff --git a/src/dialogs/QskSelectionWindow.h b/src/dialogs/QskSelectionWindow.h index 3971ed03..dc13a322 100644 --- a/src/dialogs/QskSelectionWindow.h +++ b/src/dialogs/QskSelectionWindow.h @@ -6,38 +6,56 @@ #ifndef QSK_SELECTION_WINDOW_H #define QSK_SELECTION_WINDOW_H 1 -#include "QskInputWindow.h" +#include "QskDialogWindow.h" -class QskSelectionDialogBox; +class QskTextOptions; -class QSK_EXPORT QskSelectionWindow : public QskInputWindow +class QSK_EXPORT QskSelectionWindow : public QskDialogWindow { Q_OBJECT + Q_PROPERTY( QString infoText READ infoText + WRITE setInfoText NOTIFY infoTextChanged ) + + Q_PROPERTY( QskTextOptions infoTextOptions READ infoTextOptions + WRITE setInfoTextOptions NOTIFY infoTextOptionsChanged ) + Q_PROPERTY( QStringList entries READ entries WRITE setEntries NOTIFY entriesChanged FINAL ) Q_PROPERTY( int selectedRow READ selectedRow WRITE setSelectedRow NOTIFY selectedRowChanged FINAL ) - using Inherited = QskInputWindow; + using Inherited = QskDialogWindow; public: QskSelectionWindow( QWindow* parent = nullptr ); ~QskSelectionWindow() override; + void setInfoTextOptions( const QskTextOptions& ); + QskTextOptions infoTextOptions() const; + + QString infoText() const; + Q_INVOKABLE QStringList entries() const; Q_INVOKABLE int selectedRow() const; Q_INVOKABLE QString selectedEntry() const; public Q_SLOTS: + void setInfoText( const QString& ); void setEntries( const QStringList& ); void setSelectedRow( int row ); Q_SIGNALS: + void infoTextChanged( const QString& ); + void infoTextOptionsChanged( const QskTextOptions& ); void selectedRowChanged( int ); void selectedEntryChanged( const QString& ); void entriesChanged(); + + private: + class PrivateData; + std::unique_ptr< PrivateData > m_data; }; #endif diff --git a/src/src.pro b/src/src.pro index f71a5239..c52a7a67 100644 --- a/src/src.pro +++ b/src/src.pro @@ -276,8 +276,6 @@ HEADERS += \ dialogs/QskDialogButtonBox.h \ dialogs/QskDialogSubWindow.h \ dialogs/QskDialogWindow.h \ - dialogs/QskInputSubWindow.h \ - dialogs/QskInputWindow.h \ dialogs/QskMessageSubWindow.h \ dialogs/QskMessageWindow.h \ dialogs/QskSelectionSubWindow.h \ @@ -289,8 +287,6 @@ SOURCES += \ dialogs/QskDialog.cpp \ dialogs/QskDialogSubWindow.cpp \ dialogs/QskDialogWindow.cpp \ - dialogs/QskInputSubWindow.cpp \ - dialogs/QskInputWindow.cpp \ dialogs/QskMessageSubWindow.cpp \ dialogs/QskMessageWindow.cpp \ dialogs/QskSelectionSubWindow.cpp \