923 lines
27 KiB
C++
923 lines
27 KiB
C++
/******************************************************************************
|
|
* QSkinny - Copyright (C) The authors
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*****************************************************************************/
|
|
|
|
#include "QskDialog.h"
|
|
#include "QskDialogButtonBox.h"
|
|
|
|
#include "QskLinearBox.h"
|
|
|
|
#include "QskMessageSubWindow.h"
|
|
#include "QskMessageWindow.h"
|
|
|
|
#include "QskSelectionSubWindow.h"
|
|
#include "QskSelectionWindow.h"
|
|
|
|
#include "QskBoxBorderColors.h"
|
|
#include "QskBoxBorderMetrics.h"
|
|
#include "QskBoxShapeMetrics.h"
|
|
#include "QskColorPicker.h"
|
|
#include "QskEvent.h"
|
|
#include "QskFunctions.h"
|
|
#include "QskListView.h"
|
|
#include "QskPushButton.h"
|
|
#include "QskScrollArea.h"
|
|
#include "QskSlider.h"
|
|
|
|
#include "QskFocusIndicator.h"
|
|
|
|
#include <qfontmetrics.h>
|
|
#include <qfilesystemmodel.h>
|
|
#include <qguiapplication.h>
|
|
#include <qpointer.h>
|
|
#include <qquickwindow.h>
|
|
#include <qtimer.h>
|
|
|
|
#include <qpa/qplatformdialoghelper.h>
|
|
|
|
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
|
|
auto focusIndicator = new QskFocusIndicator();
|
|
focusIndicator->setObjectName( QStringLiteral( "DialogFocusIndicator" ) );
|
|
dialogWindow->addItem( focusIndicator );
|
|
#endif
|
|
|
|
return dialogWindow->exec();
|
|
}
|
|
|
|
namespace
|
|
{
|
|
template< typename W >
|
|
class WindowOrSubWindow : public W
|
|
{
|
|
public:
|
|
WindowOrSubWindow( QObject* parent, const QString& title,
|
|
QskDialog::Actions actions, QskDialog::Action defaultAction )
|
|
: W( parent, title, actions, defaultAction )
|
|
{
|
|
}
|
|
};
|
|
|
|
template<>
|
|
class WindowOrSubWindow< QskDialogWindow > : public QskDialogWindow
|
|
{
|
|
public:
|
|
WindowOrSubWindow( QObject* parent, const QString& title,
|
|
QskDialog::Actions actions, QskDialog::Action defaultAction )
|
|
: QskDialogWindow( static_cast< QWindow* >( parent ) )
|
|
{
|
|
auto* transientParent = static_cast< QWindow* >( parent );
|
|
setTransientParent( transientParent );
|
|
|
|
setTitle( title );
|
|
setDialogActions( actions );
|
|
|
|
if ( actions != QskDialog::NoAction && defaultAction == QskDialog::NoAction )
|
|
defaultAction = qskActionCandidate( buttonBox() );
|
|
|
|
setDefaultDialogAction( defaultAction );
|
|
|
|
setModality( transientParent ? Qt::WindowModal : Qt::ApplicationModal );
|
|
|
|
const QSize size = sizeConstraint();
|
|
|
|
if ( this->parent() )
|
|
{
|
|
QRect r( QPoint(), size );
|
|
r.moveCenter( QRect( QPoint(), this->parent()->size() ).center() );
|
|
|
|
setGeometry( r );
|
|
}
|
|
|
|
auto adjustSize = [this]()
|
|
{
|
|
const QSize size = sizeConstraint();
|
|
|
|
if ( size.isValid() )
|
|
{
|
|
setFlags( flags() | Qt::MSWindowsFixedSizeDialogHint );
|
|
setFixedSize( size );
|
|
}
|
|
};
|
|
|
|
connect( contentItem(), &QQuickItem::widthChanged, this, adjustSize );
|
|
connect( contentItem(), &QQuickItem::heightChanged, this, adjustSize );
|
|
}
|
|
|
|
QskDialog::DialogCode exec()
|
|
{
|
|
return qskExec( this );
|
|
}
|
|
|
|
void setContentItem( QQuickItem* item )
|
|
{
|
|
QskDialogWindow::setDialogContentItem( item );
|
|
}
|
|
};
|
|
|
|
template<>
|
|
class WindowOrSubWindow< QskDialogSubWindow > : public QskDialogSubWindow
|
|
{
|
|
public:
|
|
WindowOrSubWindow( QObject* parent, const QString& title,
|
|
QskDialog::Actions actions, QskDialog::Action defaultAction )
|
|
: QskDialogSubWindow( static_cast< QQuickWindow* >( parent )->contentItem() )
|
|
{
|
|
setPopupFlag( QskPopup::DeleteOnClose );
|
|
setModal( true );
|
|
setTitle( title );
|
|
setDialogActions( actions );
|
|
|
|
if ( actions != QskDialog::NoAction && defaultAction == QskDialog::NoAction )
|
|
defaultAction = qskActionCandidate( buttonBox() );
|
|
|
|
setDefaultDialogAction( defaultAction );
|
|
}
|
|
|
|
QskDialog::DialogCode exec()
|
|
{
|
|
return QskDialogSubWindow::exec();
|
|
}
|
|
|
|
void setContentItem( QQuickItem* item )
|
|
{
|
|
QskDialogSubWindow::setContentItem( item );
|
|
}
|
|
};
|
|
|
|
// copied from QskListView.cpp:
|
|
static inline int qskRowAt( const QskListView* listView, const QPointF& pos )
|
|
{
|
|
const auto rect = listView->viewContentsRect();
|
|
if ( rect.contains( pos ) )
|
|
{
|
|
const auto y = pos.y() - rect.top() + listView->scrollPos().y();
|
|
|
|
const int row = y / listView->rowHeight();
|
|
if ( row >= 0 && row < listView->rowCount() )
|
|
return row;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// copied from QskGestureRecognizer.cpp:
|
|
static QMouseEvent* qskClonedMouseEvent( const QMouseEvent* event )
|
|
{
|
|
QMouseEvent* clonedEvent;
|
|
|
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
|
clonedEvent = QQuickWindowPrivate::cloneMouseEvent(
|
|
const_cast< QMouseEvent* >( event ), nullptr );
|
|
#else
|
|
clonedEvent = event->clone();
|
|
#endif
|
|
clonedEvent->setAccepted( false );
|
|
|
|
return clonedEvent;
|
|
}
|
|
|
|
class FileSystemView : public QskListView
|
|
{
|
|
using Inherited = QskListView;
|
|
|
|
public:
|
|
FileSystemView( const QString& directory, QDir::Filters filters, QQuickItem* parent = nullptr )
|
|
: QskListView( parent )
|
|
, m_model( new QFileSystemModel( this ) )
|
|
{
|
|
const auto defaultWidth = 50;
|
|
|
|
connect( m_model, &QFileSystemModel::directoryLoaded, this, [this, defaultWidth]()
|
|
{
|
|
m_columnWidths.fill( defaultWidth );
|
|
updateScrollableSize();
|
|
setScrollPos( { 0, 0 } );
|
|
setSelectedRow( -1 );
|
|
});
|
|
|
|
m_model->setFilter( filters );
|
|
m_model->setRootPath( {} ); // invalidate to make sure to get an update
|
|
m_model->setRootPath( directory );
|
|
|
|
m_columnWidths.fill( defaultWidth, m_model->columnCount() );
|
|
}
|
|
|
|
virtual int rowCount() const override
|
|
{
|
|
const auto index = m_model->index( m_model->rootPath() );
|
|
return m_model->rowCount( index );
|
|
}
|
|
|
|
virtual int columnCount() const override
|
|
{
|
|
const auto index = m_model->index( m_model->rootPath() );
|
|
return m_model->columnCount( index );
|
|
}
|
|
|
|
virtual qreal columnWidth( int col ) const override
|
|
{
|
|
auto w = m_columnWidths.at( col );
|
|
|
|
if( col == 0 )
|
|
{
|
|
w = qMax( 250, w ); // min width for the name
|
|
}
|
|
|
|
return w + 15; // spacing
|
|
}
|
|
|
|
virtual qreal rowHeight() const override
|
|
{
|
|
const auto hint = strutSizeHint( Cell );
|
|
const auto padding = paddingHint( Cell );
|
|
|
|
qreal h = effectiveFontHeight( Text );
|
|
h += padding.top() + padding.bottom();
|
|
|
|
return qMax( h, hint.height() );
|
|
}
|
|
|
|
virtual QVariant valueAt( int row, int col ) const override
|
|
{
|
|
const auto rootIndex = m_model->index( m_model->rootPath() );
|
|
|
|
const auto index = m_model->index( row, col, rootIndex );
|
|
const auto v = m_model->data( index );
|
|
|
|
const auto w = qskHorizontalAdvance( effectiveFont( Text ), v.toString() );
|
|
|
|
if( w > m_columnWidths.at( col ) )
|
|
{
|
|
m_columnWidths[ col ] = w;
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
QFileSystemModel* model()
|
|
{
|
|
return m_model;
|
|
}
|
|
|
|
protected:
|
|
|
|
void mousePressEvent( QMouseEvent* event ) override
|
|
{
|
|
if( m_doubleClickEvent && m_doubleClickEvent->timestamp() == event->timestamp() )
|
|
{
|
|
// do not select rows from double click mouse events
|
|
m_doubleClickEvent = nullptr;
|
|
}
|
|
else
|
|
{
|
|
Inherited::mousePressEvent( event );
|
|
}
|
|
}
|
|
|
|
void mouseDoubleClickEvent( QMouseEvent* event ) override
|
|
{
|
|
m_doubleClickEvent = qskClonedMouseEvent( event );
|
|
|
|
const int row = qskRowAt( this, qskMousePosition( event ) );
|
|
const auto path = valueAt( row, 0 ).toString();
|
|
|
|
QFileInfo fi( m_model->rootPath(), path );
|
|
|
|
if( fi.isDir() )
|
|
{
|
|
m_model->setRootPath( fi.absoluteFilePath() );
|
|
}
|
|
|
|
Inherited::mouseDoubleClickEvent( event );
|
|
}
|
|
|
|
private:
|
|
QFileSystemModel* const m_model;
|
|
mutable QVector< int > m_columnWidths;
|
|
QMouseEvent* m_doubleClickEvent = nullptr;
|
|
};
|
|
|
|
template< typename W >
|
|
class FileSelectionWindow : public WindowOrSubWindow< W >
|
|
{
|
|
using Inherited = WindowOrSubWindow< W >;
|
|
|
|
public:
|
|
|
|
FileSelectionWindow( QObject* parent, const QString& title,
|
|
QskDialog::Actions actions, QskDialog::Action defaultAction,
|
|
const QString& directory, QDir::Filters filters )
|
|
: WindowOrSubWindow< W >( parent, title, actions, defaultAction )
|
|
{
|
|
auto* outerBox = new QskLinearBox( Qt::Vertical );
|
|
outerBox->setMargins( 20 );
|
|
outerBox->setSpacing( 20 );
|
|
#if 1
|
|
outerBox->setFixedSize( 700, 500 );
|
|
#endif
|
|
setupHeader( outerBox );
|
|
setupFileSystemView( directory, filters, outerBox );
|
|
|
|
updateHeader( directory );
|
|
|
|
Inherited::setContentItem( outerBox );
|
|
}
|
|
|
|
QString selectedPath() const
|
|
{
|
|
if( m_fileView->selectedRow() != -1 )
|
|
{
|
|
const auto path = m_fileView->valueAt( m_fileView->selectedRow(), 0 ).toString();
|
|
QFileInfo fi( m_fileView->model()->rootPath(), path );
|
|
return fi.absoluteFilePath();
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
private:
|
|
void setupHeader( QQuickItem* parentItem )
|
|
{
|
|
m_headerScrollArea = new QskScrollArea( parentItem );
|
|
m_headerScrollArea->setSizePolicy( Qt::Vertical, QskSizePolicy::Fixed );
|
|
m_headerScrollArea->setFlickableOrientations( Qt::Horizontal );
|
|
|
|
m_headerBox = new QskLinearBox( Qt::Horizontal, m_headerScrollArea );
|
|
m_headerScrollArea->setScrolledItem( m_headerBox );
|
|
}
|
|
|
|
static QStringList splitPath( const QString& path )
|
|
{
|
|
const auto cleanPath = QDir::cleanPath( path );
|
|
|
|
QDir dir( cleanPath );
|
|
|
|
QStringList result;
|
|
|
|
do
|
|
{
|
|
if( dir != QDir::root() )
|
|
{
|
|
result.prepend( dir.absolutePath() );
|
|
}
|
|
}
|
|
while( dir.cdUp() );
|
|
|
|
return result;
|
|
}
|
|
|
|
void updateHeader( const QString& path )
|
|
{
|
|
const auto dirPaths = splitPath( path );
|
|
|
|
for( int i = 0; i < dirPaths.count(); ++i )
|
|
{
|
|
QskPushButton* b;
|
|
|
|
if( m_breadcrumbsButtons.count() <= i )
|
|
{
|
|
b = new QskPushButton( m_headerBox );
|
|
b->setStrutSizeHint( QskPushButton::Panel, { -1, -1 } );
|
|
m_breadcrumbsButtons.append( b );
|
|
}
|
|
else
|
|
{
|
|
b = m_breadcrumbsButtons.at( i );
|
|
b->disconnect();
|
|
}
|
|
|
|
QFileInfo fi( dirPaths.at( i ) );
|
|
b->setText( fi.baseName() );
|
|
|
|
QObject::connect( b, &QskPushButton::clicked, this, [this, fi]()
|
|
{
|
|
m_fileView->model()->setRootPath( fi.filePath() );
|
|
});
|
|
}
|
|
|
|
for( int i = dirPaths.count(); i < m_breadcrumbsButtons.count(); i++ )
|
|
{
|
|
m_breadcrumbsButtons.at( i )->deleteLater();
|
|
}
|
|
|
|
m_breadcrumbsButtons.remove( dirPaths.count(), m_breadcrumbsButtons.count() - dirPaths.count() );
|
|
|
|
if( !m_breadcrumbsButtons.isEmpty() )
|
|
{
|
|
auto* b = m_breadcrumbsButtons.last();
|
|
|
|
// button might just have been created and not be layed out yet:
|
|
QObject::connect( b, &QskPushButton::widthChanged, this, [this, b]()
|
|
{
|
|
m_headerScrollArea->ensureItemVisible( b );
|
|
} );
|
|
}
|
|
}
|
|
|
|
void setupFileSystemView( const QString& directory, QDir::Filters filters, QQuickItem* parentItem )
|
|
{
|
|
m_fileView = new FileSystemView( directory, filters, parentItem );
|
|
|
|
QObject::connect( m_fileView->model(), &QFileSystemModel::rootPathChanged,
|
|
this, &FileSelectionWindow< W >::updateHeader );
|
|
|
|
QObject::connect( m_fileView, &QskListView::selectedRowChanged, this, [this]()
|
|
{
|
|
if( m_fileView->model()->filter() & QDir::Files )
|
|
{
|
|
QFileInfo fi( selectedPath() );
|
|
W::defaultButton()->setEnabled( !fi.isDir() );
|
|
}
|
|
} );
|
|
}
|
|
|
|
QskScrollArea* m_headerScrollArea;
|
|
QskLinearBox* m_headerBox;
|
|
QVector< QskPushButton* > m_breadcrumbsButtons;
|
|
|
|
FileSystemView* m_fileView;
|
|
};
|
|
|
|
template< typename W >
|
|
class ColorSelectionWindow : public WindowOrSubWindow< W >
|
|
{
|
|
using Inherited = WindowOrSubWindow< W >;
|
|
|
|
public:
|
|
|
|
ColorSelectionWindow( QObject* parent, const QString& title,
|
|
QskDialog::Actions actions, QskDialog::Action defaultAction )
|
|
: WindowOrSubWindow< W >( parent, title, actions, defaultAction )
|
|
{
|
|
auto* outerBox = new QskLinearBox( Qt::Vertical );
|
|
outerBox->setMargins( 20 );
|
|
outerBox->setSpacing( 20 );
|
|
#if 1
|
|
outerBox->setFixedSize( 700, 500 );
|
|
#endif
|
|
auto* upperBox = new QskLinearBox( Qt::Horizontal, outerBox );
|
|
upperBox->setSpacing( 12 );
|
|
|
|
m_picker = new QskColorPicker( upperBox );
|
|
m_picker->setStrutSizeHint( QskColorPicker::Selector, { 18, 18 } );
|
|
m_picker->setBoxShapeHint( QskColorPicker::Selector, { 100, Qt::RelativeSize } );
|
|
m_picker->setBoxBorderMetricsHint( QskColorPicker::Selector, 2 );
|
|
m_picker->setBoxBorderColorsHint( QskColorPicker::Selector, Qt::black );
|
|
m_picker->setGradientHint( QskColorPicker::Selector, Qt::transparent );
|
|
|
|
auto* outputBox = new QskBox( upperBox );
|
|
outputBox->setPanel( true );
|
|
|
|
QObject::connect( m_picker, &QskColorPicker::selectedColorChanged,
|
|
this, [this, outputBox]()
|
|
{
|
|
const auto c = m_picker->selectedColor();
|
|
outputBox->setGradientHint( QskBox::Panel, c );
|
|
} );
|
|
|
|
upperBox->setStretchFactor( m_picker, 9 );
|
|
upperBox->setStretchFactor( outputBox, 1 );
|
|
|
|
|
|
auto* valueSlider = new QskSlider( outerBox );
|
|
valueSlider->setBoundaries( 0, 1 );
|
|
valueSlider->setValue( m_picker->value() );
|
|
|
|
QskGradient g( Qt::black, Qt::white );
|
|
g.setLinearDirection( Qt::Horizontal );
|
|
valueSlider->setGradientHint( QskSlider::Groove, g );
|
|
valueSlider->setGradientHint( QskSlider::Fill, Qt::transparent );
|
|
valueSlider->setGradientHint( QskSlider::Handle, Qt::black );
|
|
|
|
QObject::connect( valueSlider, &QskSlider::valueChanged,
|
|
m_picker, &QskColorPicker::setValueAsRatio );
|
|
|
|
Inherited::setContentItem( outerBox );
|
|
}
|
|
|
|
QColor selectedColor() const
|
|
{
|
|
return m_picker->selectedColor();
|
|
}
|
|
|
|
private:
|
|
QskColorPicker* m_picker;
|
|
};
|
|
}
|
|
|
|
static QQuickWindow* qskSomeQuickWindow()
|
|
{
|
|
// not the best code ever, but as it is a fallback only
|
|
// maybe we should also add the stacking order
|
|
|
|
const auto windows = QGuiApplication::topLevelWindows();
|
|
for ( auto window : windows )
|
|
{
|
|
if ( window->isVisible() )
|
|
{
|
|
if ( auto quickWindow = qobject_cast< QQuickWindow* >( window ) )
|
|
return quickWindow;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
static void qskSetupSubWindow(
|
|
const QString& title, QskDialog::Actions actions,
|
|
QskDialog::Action defaultAction, QskDialogSubWindow* subWindow )
|
|
{
|
|
subWindow->setPopupFlag( QskPopup::DeleteOnClose );
|
|
subWindow->setModal( true );
|
|
#if 0
|
|
subWindow->setWindowTitle( ... );
|
|
#endif
|
|
subWindow->setTitle( title );
|
|
subWindow->setDialogActions( actions );
|
|
|
|
if ( actions != QskDialog::NoAction && defaultAction == QskDialog::NoAction )
|
|
defaultAction = qskActionCandidate( subWindow->buttonBox() );
|
|
|
|
subWindow->setDefaultDialogAction( defaultAction );
|
|
}
|
|
|
|
static void qskSetupWindow(
|
|
QWindow* transientParent, const QString& title,
|
|
QskDialog::Actions actions, QskDialog::Action defaultAction,
|
|
QskDialogWindow* window )
|
|
{
|
|
window->setTransientParent( transientParent );
|
|
|
|
window->setTitle( title );
|
|
window->setDialogActions( actions );
|
|
|
|
if ( actions != QskDialog::NoAction && defaultAction == QskDialog::NoAction )
|
|
defaultAction = qskActionCandidate( window->buttonBox() );
|
|
|
|
window->setDefaultDialogAction( defaultAction );
|
|
|
|
window->setModality( transientParent ? Qt::WindowModal : Qt::ApplicationModal );
|
|
|
|
const QSize size = window->sizeConstraint();
|
|
qDebug() << "sc:" << size;
|
|
|
|
if ( window->parent() )
|
|
{
|
|
QRect r( QPoint(), size );
|
|
r.moveCenter( QRect( QPoint(), window->parent()->size() ).center() );
|
|
|
|
window->setGeometry( r );
|
|
}
|
|
|
|
if ( size.isValid() )
|
|
{
|
|
window->setFlags( window->flags() | Qt::MSWindowsFixedSizeDialogHint );
|
|
window->setFixedSize( size );
|
|
}
|
|
|
|
window->setModality( Qt::ApplicationModal );
|
|
}
|
|
|
|
static QskDialog::Action qskMessageSubWindow(
|
|
QQuickWindow* window, const QString& title,
|
|
const QString& text, uint priority, QskDialog::Actions actions,
|
|
QskDialog::Action defaultAction )
|
|
{
|
|
auto subWindow = new QskMessageSubWindow( window->contentItem() );
|
|
subWindow->setPriority( priority );
|
|
subWindow->setText( text );
|
|
|
|
qskSetupSubWindow( title, actions, defaultAction, subWindow );
|
|
( void ) subWindow->exec();
|
|
|
|
auto clickedAction = subWindow->clickedAction();
|
|
if ( clickedAction == QskDialog::NoAction )
|
|
{
|
|
// dialog might have been closed by the window menu
|
|
clickedAction = QskDialog::Cancel;
|
|
}
|
|
|
|
return clickedAction;
|
|
}
|
|
|
|
static QskDialog::Action qskMessageWindow(
|
|
QWindow* transientParent, const QString& title,
|
|
const QString& text, uint priority, QskDialog::Actions actions,
|
|
QskDialog::Action defaultAction )
|
|
{
|
|
Q_UNUSED( priority ); // can we do something with it ?
|
|
|
|
QskMessageWindow messageWindow;
|
|
messageWindow.setText( text );
|
|
|
|
qskSetupWindow( transientParent, title, actions, defaultAction, &messageWindow );
|
|
( void ) qskExec( &messageWindow );
|
|
|
|
auto clickedAction = messageWindow.clickedAction();
|
|
if ( clickedAction == QskDialog::NoAction )
|
|
{
|
|
// dialog might have been closed by the window menu
|
|
clickedAction = QskDialog::Cancel;
|
|
}
|
|
|
|
return clickedAction;
|
|
}
|
|
|
|
static QString qskSelectSubWindow(
|
|
QQuickWindow* window, const QString& title,
|
|
QskDialog::Actions actions, QskDialog::Action defaultAction,
|
|
const QStringList& entries, int selectedRow )
|
|
{
|
|
auto subWindow = new QskSelectionSubWindow( window->contentItem() );
|
|
subWindow->setEntries( entries );
|
|
subWindow->setSelectedRow( selectedRow );
|
|
|
|
QString selectedEntry;
|
|
|
|
qskSetupSubWindow( title, actions, defaultAction, subWindow );
|
|
if ( subWindow->exec() == QskDialog::Accepted )
|
|
selectedEntry = subWindow->selectedEntry();
|
|
|
|
return selectedEntry;
|
|
}
|
|
|
|
static QString qskSelectWindow(
|
|
QWindow* transientParent, const QString& title,
|
|
QskDialog::Actions actions, QskDialog::Action defaultAction,
|
|
const QStringList& entries, int selectedRow )
|
|
{
|
|
QskSelectionWindow window;
|
|
window.setEntries( entries );
|
|
window.setSelectedRow( selectedRow );
|
|
|
|
QString selectedEntry = window.selectedEntry();
|
|
|
|
qskSetupWindow( transientParent, title, actions, defaultAction, &window );
|
|
if ( qskExec( &window ) == QskDialog::Accepted )
|
|
selectedEntry = window.selectedEntry();
|
|
|
|
return selectedEntry;
|
|
}
|
|
|
|
template< typename W >
|
|
static QString qskSelectPath( FileSelectionWindow< W >& window )
|
|
{
|
|
QString selectedFile = window.selectedPath();
|
|
|
|
if( window.exec() == QskDialog::Accepted )
|
|
selectedFile = window.selectedPath();
|
|
|
|
return selectedFile;
|
|
}
|
|
|
|
template< typename W >
|
|
static QColor qskSelectColor( ColorSelectionWindow< W >& window )
|
|
{
|
|
QColor selectedColor = window.selectedColor();
|
|
|
|
if( window.exec() == QskDialog::Accepted )
|
|
selectedColor = window.selectedColor();
|
|
|
|
return selectedColor;
|
|
}
|
|
|
|
class QskDialog::PrivateData
|
|
{
|
|
public:
|
|
QPointer< QWindow > transientParent;
|
|
QskDialog::Policy policy = QskDialog::TopLevelWindow;
|
|
};
|
|
|
|
QskDialog::QskDialog()
|
|
: m_data( new PrivateData )
|
|
{
|
|
}
|
|
|
|
QskDialog::~QskDialog()
|
|
{
|
|
}
|
|
|
|
QskDialog* QskDialog::instance()
|
|
{
|
|
static QskDialog instance;
|
|
return &instance;
|
|
}
|
|
|
|
void QskDialog::setPolicy( Policy policy )
|
|
{
|
|
if ( policy != m_data->policy )
|
|
{
|
|
m_data->policy = policy;
|
|
Q_EMIT policyChanged();
|
|
}
|
|
}
|
|
|
|
QskDialog::Policy QskDialog::policy() const
|
|
{
|
|
return m_data->policy;
|
|
}
|
|
|
|
void QskDialog::setTransientParent( QWindow* window )
|
|
{
|
|
if ( m_data->transientParent != window )
|
|
{
|
|
m_data->transientParent = window;
|
|
Q_EMIT transientParentChanged();
|
|
}
|
|
}
|
|
|
|
QWindow* QskDialog::transientParent() const
|
|
{
|
|
return m_data->transientParent;
|
|
}
|
|
|
|
QskDialog::Action QskDialog::message(
|
|
const QString& title, const QString& text, uint priority,
|
|
Actions actions, Action defaultAction ) const
|
|
{
|
|
if ( m_data->policy == EmbeddedBox )
|
|
{
|
|
auto quickWindow = qobject_cast< QQuickWindow* >( m_data->transientParent );
|
|
|
|
if ( quickWindow == nullptr )
|
|
quickWindow = qskSomeQuickWindow();
|
|
|
|
if ( quickWindow )
|
|
{
|
|
return qskMessageSubWindow( quickWindow,
|
|
title, text, priority, actions, defaultAction );
|
|
}
|
|
}
|
|
|
|
return qskMessageWindow( m_data->transientParent,
|
|
title, text, priority, actions, defaultAction );
|
|
}
|
|
|
|
QskDialog::Action QskDialog::information(
|
|
const QString& title, const QString& text,
|
|
Actions actions, Action defaultAction ) const
|
|
{
|
|
return QskDialog::message( title, text, 0, actions, defaultAction );
|
|
}
|
|
|
|
QskDialog::Action QskDialog::question(
|
|
const QString& title, const QString& text,
|
|
Actions actions, Action defaultAction ) const
|
|
{
|
|
return QskDialog::message( title, text, 0, actions, defaultAction );
|
|
}
|
|
|
|
QString QskDialog::select( const QString& title,
|
|
const QStringList& entries, int selectedRow ) 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 )
|
|
{
|
|
return qskSelectSubWindow( quickWindow,
|
|
title, actions, defaultAction, entries, selectedRow );
|
|
}
|
|
}
|
|
|
|
return qskSelectWindow( m_data->transientParent, title,
|
|
actions, defaultAction, entries, selectedRow );
|
|
|
|
}
|
|
|
|
QString QskDialog::selectFile(
|
|
const QString& title, const QString& directory ) const
|
|
{
|
|
#if 1
|
|
// should be parameters
|
|
const auto actions = QskDialog::Ok | QskDialog::Cancel;
|
|
const auto defaultAction = QskDialog::Ok;
|
|
#endif
|
|
|
|
const auto filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs;
|
|
|
|
if ( m_data->policy == EmbeddedBox )
|
|
{
|
|
auto quickWindow = qobject_cast< QQuickWindow* >( m_data->transientParent );
|
|
|
|
if ( quickWindow == nullptr )
|
|
quickWindow = qskSomeQuickWindow();
|
|
|
|
if ( quickWindow )
|
|
{
|
|
FileSelectionWindow< QskDialogSubWindow > window( quickWindow, title,
|
|
actions, defaultAction, directory, filters );
|
|
return qskSelectPath< QskDialogSubWindow >( window );
|
|
}
|
|
}
|
|
|
|
FileSelectionWindow< QskDialogWindow > window( m_data->transientParent, title,
|
|
actions, defaultAction, directory, filters );
|
|
return qskSelectPath< QskDialogWindow >( window );
|
|
}
|
|
|
|
QString QskDialog::selectDirectory(
|
|
const QString& title, const QString& directory ) const
|
|
{
|
|
#if 1
|
|
// should be parameters
|
|
const auto actions = QskDialog::Ok | QskDialog::Cancel;
|
|
const auto defaultAction = QskDialog::Ok;
|
|
#endif
|
|
|
|
const auto filters = QDir::NoDotAndDotDot | QDir::AllDirs;
|
|
|
|
if ( m_data->policy == EmbeddedBox )
|
|
{
|
|
auto quickWindow = qobject_cast< QQuickWindow* >( m_data->transientParent );
|
|
|
|
if ( quickWindow == nullptr )
|
|
quickWindow = qskSomeQuickWindow();
|
|
|
|
if ( quickWindow )
|
|
{
|
|
FileSelectionWindow< QskDialogSubWindow > window( quickWindow, title,
|
|
actions, defaultAction, directory, filters );
|
|
return qskSelectPath< QskDialogSubWindow >( window );
|
|
}
|
|
}
|
|
|
|
FileSelectionWindow< QskDialogWindow > window( m_data->transientParent, title,
|
|
actions, defaultAction, directory, filters );
|
|
return qskSelectPath< QskDialogWindow >( window );
|
|
}
|
|
|
|
QColor QskDialog::selectColor( 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 )
|
|
{
|
|
ColorSelectionWindow< QskDialogSubWindow > window( quickWindow, title,
|
|
actions, defaultAction );
|
|
return qskSelectColor< QskDialogSubWindow >( window );
|
|
}
|
|
}
|
|
|
|
ColorSelectionWindow< QskDialogWindow > window( m_data->transientParent, title,
|
|
actions, defaultAction );
|
|
return qskSelectColor< QskDialogWindow >( window );
|
|
}
|
|
|
|
QskDialog::ActionRole QskDialog::actionRole( Action action )
|
|
{
|
|
using Q = QPlatformDialogHelper;
|
|
|
|
const auto role = Q::buttonRole( static_cast< Q::StandardButton >( action ) );
|
|
return static_cast< ActionRole >( role );
|
|
}
|
|
|
|
#include "moc_QskDialog.cpp"
|