qskinny/src/dialogs/QskDialogSubWindow.cpp

445 lines
10 KiB
C++
Raw Normal View History

2017-07-21 16:21:34 +00:00
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskDialogSubWindow.h"
2018-11-06 17:54:21 +00:00
#include "QskDialogButtonBox.h"
#include "QskPushButton.h"
#include "QskQuick.h"
2018-07-19 12:10:48 +00:00
#include <qeventloop.h>
#include <qquickwindow.h>
2018-11-06 17:54:21 +00:00
#include <qpointer.h>
2017-07-21 16:21:34 +00:00
2018-07-02 06:08:38 +00:00
static inline void qskSetRejectOnClose( QskDialogSubWindow* subWindow, bool on )
2017-07-21 16:21:34 +00:00
{
2018-07-02 06:08:38 +00:00
if ( on )
{
QObject::connect( subWindow, &QskPopup::closed,
subWindow, &QskDialogSubWindow::reject );
}
else
{
QObject::disconnect( subWindow, &QskPopup::closed,
subWindow, &QskDialogSubWindow::reject );
}
2017-07-21 16:21:34 +00:00
}
2018-11-06 17:54:21 +00:00
class QskDialogSubWindow::PrivateData
{
public:
QskDialog::Actions actions = QskDialog::NoAction;
QPointer< QQuickItem > contentItem;
QskDialogButtonBox* buttonBox = nullptr;
2018-11-07 09:10:48 +00:00
QMarginsF contentPadding;
2018-11-06 17:54:21 +00:00
QskDialog::DialogCode result = QskDialog::Rejected;
};
2018-08-03 06:15:28 +00:00
QskDialogSubWindow::QskDialogSubWindow( QQuickItem* parent )
: Inherited( parent )
2018-11-06 17:54:21 +00:00
, m_data( new PrivateData() )
2017-07-21 16:21:34 +00:00
{
2018-11-07 09:10:48 +00:00
setPolishOnResize( true );
2018-07-02 06:08:38 +00:00
qskSetRejectOnClose( this, true );
2017-07-21 16:21:34 +00:00
}
2018-07-02 06:08:38 +00:00
QskDialogSubWindow::~QskDialogSubWindow()
2017-07-21 16:21:34 +00:00
{
}
2018-11-06 17:54:21 +00:00
void QskDialogSubWindow::setDialogActions( QskDialog::Actions actions )
{
if ( m_data->actions == actions )
return;
m_data->actions = actions;
if ( actions == QskDialog::NoAction )
{
2018-11-07 09:10:48 +00:00
if ( m_data->buttonBox->parent() == this )
{
delete m_data->buttonBox;
}
else
{
m_data->buttonBox->setParentItem( nullptr );
disconnect( m_data->buttonBox, &QskDialogButtonBox::accepted,
this, &QskDialogSubWindow::accept );
disconnect( m_data->buttonBox, &QskDialogButtonBox::rejected,
this, &QskDialogSubWindow::reject );
}
2018-11-06 17:54:21 +00:00
m_data->buttonBox = nullptr;
}
else
{
if ( m_data->buttonBox == nullptr )
{
m_data->buttonBox = createButtonBox();
if ( m_data->buttonBox )
{
2018-11-07 09:10:48 +00:00
m_data->buttonBox->setParentItem( this );
if ( m_data->buttonBox->parent() == nullptr )
m_data->buttonBox->setParent( this );
2018-11-06 17:54:21 +00:00
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 );
}
2018-11-07 09:10:48 +00:00
resetImplicitSize();
polish();
2018-11-06 17:54:21 +00:00
}
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 )
{
2018-11-07 09:10:48 +00:00
if ( m_data->contentItem->parent() == this )
2018-11-06 17:54:21 +00:00
delete m_data->contentItem;
2018-11-07 09:10:48 +00:00
else
m_data->contentItem->setParentItem( nullptr );
2018-11-06 17:54:21 +00:00
}
m_data->contentItem = item;
if ( item )
2018-11-07 09:10:48 +00:00
{
item->setParentItem( this );
if ( item->parent() == nullptr )
item->setParent( this );
}
resetImplicitSize();
polish();
2018-11-06 17:54:21 +00:00
}
QQuickItem* QskDialogSubWindow::contentItem() const
{
return m_data->contentItem;
}
2018-11-07 09:10:48 +00:00
void QskDialogSubWindow::setContentPadding( const QMarginsF& padding )
{
// should be a skin hint ???
if ( m_data->contentPadding != padding )
{
m_data->contentPadding = padding;
resetImplicitSize();
polish();
}
}
QMarginsF QskDialogSubWindow::contentPadding() const
{
return m_data->contentPadding;
}
2018-11-06 17:54:21 +00:00
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;
}
2017-07-21 16:21:34 +00:00
void QskDialogSubWindow::setResult( QskDialog::DialogCode result )
{
2018-11-06 17:54:21 +00:00
m_data->result = result;
2017-07-21 16:21:34 +00:00
}
QskDialog::DialogCode QskDialogSubWindow::result() const
{
2018-11-06 17:54:21 +00:00
return m_data->result;
2017-07-21 16:21:34 +00:00
}
QskDialog::DialogCode QskDialogSubWindow::exec()
{
if ( window() == nullptr )
{
qWarning( "trying to exec a subwindow without window. " );
return QskDialog::Rejected;
}
if ( QQuickItem* mouseGrabber = window()->mouseGrabberItem() )
{
// when being called from QQuickWindow::mouseReleaseEvent
// the mouse grabber has not yet been released.
mouseGrabber->ungrabMouse();
}
open();
2017-07-21 16:21:34 +00:00
QEventLoop eventLoop;
connect( this, &QskDialogSubWindow::finished, &eventLoop, &QEventLoop::quit );
( void ) eventLoop.exec( QEventLoop::DialogExec );
2018-11-07 09:10:48 +00:00
return m_data->result;
2017-07-21 16:21:34 +00:00
}
void QskDialogSubWindow::done( QskDialog::DialogCode result )
{
2018-11-06 17:54:21 +00:00
m_data->result = result;
2017-07-21 16:21:34 +00:00
2018-07-02 06:08:38 +00:00
if ( !isOpen() )
return;
qskSetRejectOnClose( this, false );
close();
2017-07-21 16:21:34 +00:00
Q_EMIT finished( result );
if ( result == QskDialog::Accepted )
Q_EMIT accepted();
else
Q_EMIT rejected();
}
void QskDialogSubWindow::accept()
{
done( QskDialog::Accepted );
}
void QskDialogSubWindow::reject()
{
done( QskDialog::Rejected );
}
void QskDialogSubWindow::keyPressEvent( QKeyEvent* event )
{
2018-11-06 17:54:21 +00:00
if ( m_data->buttonBox &&
QskDialogButtonBox::isDefaultButtonKeyEvent( event ) )
{
auto button = m_data->buttonBox->defaultButton();
if ( button && button->isEnabled() )
button->click();
}
2017-07-21 16:21:34 +00:00
if ( event->matches( QKeySequence::Cancel ) )
{
// using shortcuts instead ???
reject();
return;
}
Inherited::keyPressEvent( event );
}
2018-11-06 17:54:21 +00:00
QskDialogButtonBox* QskDialogSubWindow::createButtonBox()
{
return new QskDialogButtonBox();
}
void QskDialogSubWindow::aboutToShow()
2017-07-21 16:21:34 +00:00
{
if ( size().isEmpty() )
2017-07-21 16:21:34 +00:00
{
// setting an initial size from the hint, centered inside the window
2018-11-07 09:10:48 +00:00
const qreal cx = 0.5 * parentItem()->width();
const qreal cy = 0.5 * parentItem()->height();
2017-07-21 16:21:34 +00:00
QRectF rect;
rect.setSize( sizeHint() );
2018-11-07 09:10:48 +00:00
rect.moveCenter( QPointF( cx, cy ) );
2017-07-21 16:21:34 +00:00
setGeometry( rect );
}
Inherited::aboutToShow();
2017-07-21 16:21:34 +00:00
}
2018-11-07 09:10:48 +00:00
void QskDialogSubWindow::updateLayout()
{
Inherited::updateLayout();
auto rect = layoutRect();
if ( m_data->buttonBox && m_data->buttonBox->isVisibleTo( this ) )
{
const auto h = m_data->buttonBox->sizeHint().height();
rect.setBottom( rect.bottom() - h );
m_data->buttonBox->setGeometry( rect.x(), rect.bottom(), rect.width(), h );
}
if ( m_data->contentItem )
{
rect = rect.marginsRemoved( m_data->contentPadding );
qskSetItemGeometry( m_data->contentItem, rect );
}
}
qreal QskDialogSubWindow::heightForWidth( qreal width ) const
{
qreal h = -1;
const auto innerSize = layoutRect().size();
const auto outerSize = size();
width -= outerSize.width() - innerSize.width();
if ( m_data->buttonBox && m_data->buttonBox->isVisibleTo( this ) )
h = m_data->buttonBox->sizeHint().height();
if ( auto* control = qobject_cast< const QskControl* >( m_data->contentItem ) )
{
const auto& m = m_data->contentPadding;
width -= m.left() + m.right();
const qreal height = control->heightForWidth( width );
if ( height >= 0 )
h += height + m.top() + m.bottom();
}
if ( h >= 0 )
h += outerSize.height() - innerSize.height();
return h;
}
qreal QskDialogSubWindow::widthForHeight( qreal height ) const
{
qreal w = -1;
const auto innerSize = layoutRect().size();
const auto outerSize = size();
height -= outerSize.height() - innerSize.height();
if ( m_data->buttonBox && m_data->buttonBox->isVisibleTo( this ) )
{
const auto hint = m_data->buttonBox->sizeHint();
w = hint.width();
height -= hint.height();
}
if ( auto* control = qobject_cast< const QskControl* >( m_data->contentItem ) )
{
const auto& m = m_data->contentPadding;
height -= m.top() + m.bottom();
const qreal width = control->widthForHeight( height );
if ( width >= 0 )
w = qMax( w, width + m.left() + m.right() );
}
if ( w >= 0 )
w += outerSize.width() - innerSize.width();
return w;
}
QSizeF QskDialogSubWindow::contentsSizeHint() const
{
qreal w = -1;
qreal h = -1;
if ( m_data->buttonBox && m_data->buttonBox->isVisibleTo( this ) )
{
const auto hint = m_data->buttonBox->sizeHint();
w = hint.width();
h = hint.height();
}
if ( auto* control = qobject_cast< const QskControl* >( m_data->contentItem ) )
{
const auto hint = control->sizeHint();
const auto& m = m_data->contentPadding;
if ( hint.width() >= 0 )
w = qMax( w, hint.width() + m.left() + m.right() );
if ( hint.height() >= 0 )
h += hint.height() + m.top() + m.bottom();
}
const auto innerSize = layoutRect().size();
const auto outerSize = size();
w += outerSize.width() - innerSize.width();
h += outerSize.height() - innerSize.height();
return QSizeF( w, h );
}
2017-07-21 16:21:34 +00:00
#include "moc_QskDialogSubWindow.cpp"