diff --git a/examples/gallery/dialog/DialogPage.cpp b/examples/gallery/dialog/DialogPage.cpp index 62e8f8a1..08864387 100644 --- a/examples/gallery/dialog/DialogPage.cpp +++ b/examples/gallery/dialog/DialogPage.cpp @@ -9,6 +9,8 @@ #include #include +#include + #if QT_CONFIG(thread) /* WebAssembly without asyncify support does not allow recursive @@ -96,6 +98,9 @@ namespace auto selectButton = new Button( "Selection", this ); connect( selectButton, &Button::clicked, this, &ButtonBox::execSelection ); + auto fileSelectionButton = new Button( "File selection", this ); + connect( fileSelectionButton, &Button::clicked, this, &ButtonBox::execFileSelection ); + setExtraSpacingAt( Qt::BottomEdge ); } @@ -155,6 +160,15 @@ namespace QskDialog::Ok | QskDialog::Cancel, QskDialog::Ok, entries, 7 ); #else (void )qskDialog->select( title, entries, 7 ); +#endif + } + + void execFileSelection() + { +#ifndef QSK_USE_EXEC + // not implemented for now (class is not public) +#else + ( void ) qskDialog->selectFile( "select file", QDir::currentPath() ); #endif } }; diff --git a/playground/systemdialogs/main.cpp b/playground/systemdialogs/main.cpp index 0a144e92..b6054eac 100644 --- a/playground/systemdialogs/main.cpp +++ b/playground/systemdialogs/main.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -108,10 +109,29 @@ namespace if ( qGuiApp->testAttribute( Qt::AA_DontUseNativeDialogs ) ) { - const auto metaEnum = QMetaEnum::fromType(); - m_dialog = createQml( metaEnum.key( dialogType ) ); - if ( m_dialog ) - m_dialog->setParentWindow( window() ); + switch( dialogType ) + { + case FileDialog: + { + auto file = qskDialog->selectFile( "select file", "." ); + qDebug() << "selected file" << file; + break; + } + case MessageDialog: + { + auto action = qskDialog->message( "message", "The quick brown fox jumps over the lazy dog" ); + qDebug() << "got message action" << action; + break; + } + default: + { + const auto metaEnum = QMetaEnum::fromType(); + m_dialog = createQml( metaEnum.key( dialogType ) ); + + if ( m_dialog ) + m_dialog->setParentWindow( window() ); + } + } } else { diff --git a/src/dialogs/QskDialog.cpp b/src/dialogs/QskDialog.cpp index fc2493c8..bf522116 100644 --- a/src/dialogs/QskDialog.cpp +++ b/src/dialogs/QskDialog.cpp @@ -6,12 +6,17 @@ #include "QskDialog.h" #include "QskDialogButtonBox.h" +#include "QskLinearBox.h" + #include "QskMessageSubWindow.h" #include "QskMessageWindow.h" #include "QskSelectionSubWindow.h" #include "QskSelectionWindow.h" +#include "QskSimpleListBox.h" +#include "QskTextLabel.h" + #include "QskFocusIndicator.h" #include @@ -43,6 +48,192 @@ static QskDialog::Action qskActionCandidate( const QskDialogButtonBox* buttonBox return QskDialog::NoAction; } +namespace +{ + template< typename W, typename T, typename... Args > + class WindowOrSubWindow : public W, public T + { + public: + WindowOrSubWindow( QObject* parent, const QString& title, + QskDialog::Actions actions, QskDialog::Action defaultAction, Args... args ) + : W( parent, title, actions, defaultAction ) + , T( parent, args... ) + { + } + + void setContentItem() + { + } + }; + + template< typename T, typename... Args > + class WindowOrSubWindow< QskDialogWindow, T, Args... > : public QskDialogWindow, public T + { + public: + WindowOrSubWindow( QObject* parent, const QString& title, + QskDialog::Actions actions, QskDialog::Action defaultAction, Args... args ) + : QskDialogWindow( static_cast< QWindow* >( parent ) ) + , T( parent, args... ) + { + 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 ); + } + + if ( size.isValid() ) + { + setFlags( flags() | Qt::MSWindowsFixedSizeDialogHint ); + setFixedSize( size ); + } + + setModality( Qt::ApplicationModal ); + } + + QskDialog::DialogCode exec() + { + return qskExec( this ); + } + + void setContentItem( QQuickItem* item ) + { + QskDialogWindow::setDialogContentItem( item ); + } + + QQuickItem* rootItem() + { + return contentItem(); + } + }; + + template< typename T, typename... Args > + class WindowOrSubWindow< QskDialogSubWindow, T, Args... > : public QskDialogSubWindow, public T + { + public: + WindowOrSubWindow( QObject* parent, const QString& title, + QskDialog::Actions actions, QskDialog::Action defaultAction, Args... args ) + : QskDialogSubWindow( static_cast< QQuickWindow* >( parent )->contentItem() ) + , T( parent, args... ) + { + 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 ); + } + + QQuickItem* rootItem() + { + return this; + } + }; + + class FileSelection + { + public: + FileSelection( QObject* parent, const QString& directory ) + : m_dir( directory ) + { + Q_UNUSED( parent ) + + m_dir.setFilter( QDir::Files | QDir::NoDotAndDotDot ); + } + + QString selectedFile() const + { + return {}; + } + + QDir currentDir() + { + return m_dir; + } + + private: + QDir m_dir; + }; + + template< typename W > + class FileSelectionWindow : public WindowOrSubWindow< W, FileSelection, QString > + { + using Inherited = WindowOrSubWindow< W, FileSelection, QString >; + + public: + FileSelectionWindow( QObject* parent, const QString& title, + QskDialog::Actions actions, QskDialog::Action defaultAction,const QString& directory ) + : WindowOrSubWindow< W, FileSelection, QString >( parent, title, actions, defaultAction, directory ) + { + auto* outerBox = new QskLinearBox( Qt::Vertical ); +#if 1 + outerBox->setPreferredSize( 500, 500 ); +#endif + setupHeader( outerBox ); + setupListBox( outerBox ); + + Inherited::setContentItem( outerBox ); + } + + private: + void setupHeader( QQuickItem* parentItem ) + { + m_header = new QskTextLabel( parentItem ); + const auto path = FileSelection::currentDir().absolutePath(); + updateHeader( path ); + } + + void updateHeader( const QString& path ) + { + // m_header->setText( s ); + } + + void setupListBox( QQuickItem* parentItem ) + { + m_listBox = new QskSimpleListBox( parentItem ); + loadContents(); + } + + void loadContents() + { + m_listBox->removeBulk( 0 ); + m_listBox->setEntries( FileSelection::currentDir().entryList() ); + } + + QskSimpleListBox* m_listBox; + QskTextLabel* m_header; + }; +} + static QskDialog::DialogCode qskExec( QskDialogWindow* dialogWindow ) { #if 1 @@ -108,6 +299,7 @@ static void qskSetupWindow( window->setModality( transientParent ? Qt::WindowModal : Qt::ApplicationModal ); const QSize size = window->sizeConstraint(); + qDebug() << "sc:" << size; if ( window->parent() ) { @@ -207,6 +399,17 @@ static QString qskSelectWindow( return selectedEntry; } +template< typename W > +static QString qskSelectFile( FileSelectionWindow< W >& window ) +{ + QString selectedFile = window.selectedFile(); + + if( window.exec() == QskDialog::Accepted ) + selectedFile = window.selectedFile(); + + return selectedFile; +} + class QskDialog::PrivateData { public: @@ -321,6 +524,33 @@ QString QskDialog::select( const QString& title, } +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 + + 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 ); + return qskSelectFile< QskDialogSubWindow >( window ); + } + } + + FileSelectionWindow< QskDialogWindow > window( m_data->transientParent, title, actions, defaultAction, directory ); + return qskSelectFile< QskDialogWindow >( window ); +} + QskDialog::ActionRole QskDialog::actionRole( Action action ) { using Q = QPlatformDialogHelper; diff --git a/src/dialogs/QskDialog.h b/src/dialogs/QskDialog.h index 863a456f..89259a1e 100644 --- a/src/dialogs/QskDialog.h +++ b/src/dialogs/QskDialog.h @@ -130,6 +130,9 @@ class QSK_EXPORT QskDialog : public QObject Q_INVOKABLE QString select( const QString& title, const QStringList& entries, int selectedRow = 0 ) const; + Q_INVOKABLE QString selectFile( const QString& title, + const QString& directory ) const; + static ActionRole actionRole( Action action ); Q_SIGNALS: