diff options
Diffstat (limited to 'src/plugins/platforms/qnx/qqnxfiledialoghelper.cpp')
-rw-r--r-- | src/plugins/platforms/qnx/qqnxfiledialoghelper.cpp | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/src/plugins/platforms/qnx/qqnxfiledialoghelper.cpp b/src/plugins/platforms/qnx/qqnxfiledialoghelper.cpp new file mode 100644 index 0000000000..e0e84dbb73 --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxfiledialoghelper.cpp @@ -0,0 +1,309 @@ +/*************************************************************************** +** +** Copyright (C) 2012 Research In Motion +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqnxfiledialoghelper.h" + +#include "qqnxbpseventfilter.h" +#include "qqnxscreen.h" + +#include <QDebug> +#include <QEventLoop> +#include <QScreen> +#include <QTimer> +#include <QWindow> + +#ifdef QQNXFILEDIALOGHELPER_DEBUG +#define qFileDialogHelperDebug qDebug +#else +#define qFileDialogHelperDebug QT_NO_QDEBUG_MACRO +#endif + +QT_BEGIN_NAMESPACE + +QQnxFileDialogHelper::QQnxFileDialogHelper(QQnxBpsEventFilter *eventFilter) + : QPlatformFileDialogHelper(), + m_eventFilter(eventFilter), + m_dialog(0), + m_acceptMode(QFileDialogOptions::AcceptOpen), + m_selectedFilter(), + m_result(QPlatformDialogHelper::Rejected), + m_paths() +{ +} + +QQnxFileDialogHelper::~QQnxFileDialogHelper() +{ + if (m_dialog) + dialog_destroy(m_dialog); +} + +bool QQnxFileDialogHelper::handleEvent(bps_event_t *event) +{ + qFileDialogHelperDebug() << Q_FUNC_INFO; + + // Check dialog event response type (OK vs CANCEL) + // CANCEL => index = 0 + // OK => index = 1 + int index = dialog_event_get_selected_index(event); + qFileDialogHelperDebug() << "Index =" << index; + if (index == 1) { + m_result = QPlatformDialogHelper::Accepted; + + if (m_acceptMode == QFileDialogOptions::AcceptOpen) { + // File open dialog + + // ###TODO Check that this actually gets multiple paths and cleans up properly + char **filePaths = 0; + int pathCount = 0; + int result = dialog_event_get_filebrowse_filepaths(event, &filePaths, &pathCount); + if (result != BPS_SUCCESS) { + qWarning() << "Could not get paths from native file dialog"; + return false; + } + + for (int i = 0; i < pathCount; ++i) { + QString path = QFile::decodeName(filePaths[i]); + m_paths.append(path); + qFileDialogHelperDebug() << "path =" << path; + } + + bps_free(filePaths); + } else { + // File save dialog + const char *filePath = dialog_event_get_filesave_filepath(event); + QString path = QFile::decodeName(filePath); + qFileDialogHelperDebug() << "path =" << path; + m_paths.append(path); + } + } else { // Cancel + m_result = QPlatformDialogHelper::Rejected; + } + + emit dialogClosed(); + + return true; +} + +void QQnxFileDialogHelper::exec() +{ + qFileDialogHelperDebug() << Q_FUNC_INFO; + + // Clear any previous results + m_paths.clear(); + + QEventLoop loop; + connect(this, SIGNAL(dialogClosed()), &loop, SLOT(quit())); + loop.exec(); + + if (m_result == QPlatformDialogHelper::Accepted) + emit accept(); + else + emit reject(); +} + +bool QQnxFileDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) +{ + Q_UNUSED(flags); + qFileDialogHelperDebug() << Q_FUNC_INFO; + + // We *really* need the bps event filter ;) + if (!m_eventFilter) + return false; + + // Native dialogs can only handle application modal use cases so far + if (modality != Qt::ApplicationModal) + return false; + + // Tear down any existing dialog and start again as dialog mode may have changed + if (m_dialog) { + dialog_destroy(m_dialog); + m_dialog = 0; + } + + // Create dialog + const QSharedPointer<QFileDialogOptions> &opts = options(); + if (opts->acceptMode() == QFileDialogOptions::AcceptOpen) { + if (dialog_create_filebrowse(&m_dialog) != BPS_SUCCESS) { + qWarning("dialog_create_filebrowse failed"); + return false; + } + + // Select one or many files? + bool multiSelect = (opts->fileMode() == QFileDialogOptions::ExistingFiles); + dialog_set_filebrowse_multiselect(m_dialog, multiSelect); + + // Set the actual list of extensions + if (!opts->nameFilters().isEmpty()) { + qFileDialogHelperDebug() << "nameFilters =" << opts->nameFilters(); + setNameFilter(opts->nameFilters().first()); + } else { + QString defaultNameFilter = QStringLiteral("*.*"); + setNameFilter(defaultNameFilter); + } + } else { + if (dialog_create_filesave(&m_dialog) != BPS_SUCCESS) { + qWarning("dialog_create_filesave failed"); + return false; + } + + // Maybe pre-select a filename + if (!opts->initiallySelectedFiles().isEmpty()) { + QString fileName = opts->initiallySelectedFiles().first(); + dialog_set_filesave_filename(m_dialog, QFile::encodeName(fileName).constData()); + } + + // Add OK and Cancel buttons. We add the buttons in the order "CANCEL" followed by "OK + // such that they have indices matching the buttons on the file open dialog which + // is automatically populated with buttons. + if (dialog_add_button(m_dialog, tr("CANCEL").toLocal8Bit().constData(), true, 0, true) != BPS_SUCCESS) { + qWarning("dialog_add_button failed"); + return false; + } + + if (dialog_add_button(m_dialog, tr("OK").toLocal8Bit().constData(), true, 0, true) != BPS_SUCCESS) { + qWarning("dialog_add_button failed"); + return false; + } + } + + // Cache the accept mode so we know which functions to use to get the results back + m_acceptMode = opts->acceptMode(); + + // Set the libscreen window group and common properties + QQnxScreen *nativeScreen = static_cast<QQnxScreen *>(parent->screen()->handle()); + dialog_set_group_id(m_dialog, nativeScreen->windowGroupName()); + dialog_set_title_text(m_dialog, opts->windowTitle().toLocal8Bit().constData()); + + // Register ourselves for dialog domain events from bps + m_eventFilter->registerForDialogEvents(this); + + // Show the dialog + dialog_show(m_dialog); + + return true; +} + +void QQnxFileDialogHelper::hide() +{ + qFileDialogHelperDebug() << Q_FUNC_INFO; + if (!m_dialog) + return; + dialog_cancel(m_dialog); +} + +bool QQnxFileDialogHelper::defaultNameFilterDisables() const +{ + qFileDialogHelperDebug() << Q_FUNC_INFO; + return false; +} + +void QQnxFileDialogHelper::setDirectory(const QString &directory) +{ + qFileDialogHelperDebug() << Q_FUNC_INFO << "directory =" << directory; + // No native API for setting the directory(!). The best we can do is to + // set it as the file name but even then only with a file save dialog. + if (m_dialog && m_acceptMode == QFileDialogOptions::AcceptSave) + dialog_set_filesave_filename(m_dialog, QFile::encodeName(directory).constData()); +} + +QString QQnxFileDialogHelper::directory() const +{ + qFileDialogHelperDebug() << Q_FUNC_INFO; + return m_paths.first(); +} + +void QQnxFileDialogHelper::selectFile(const QString &fileName) +{ + qFileDialogHelperDebug() << Q_FUNC_INFO << "filename =" << fileName; + if (m_dialog && m_acceptMode == QFileDialogOptions::AcceptSave) + dialog_set_filesave_filename(m_dialog, QFile::encodeName(fileName).constData()); +} + +QStringList QQnxFileDialogHelper::selectedFiles() const +{ + qFileDialogHelperDebug() << Q_FUNC_INFO; + return m_paths; +} + +void QQnxFileDialogHelper::setFilter() +{ + // No native api to support setting a filter from QDir::Filters + qFileDialogHelperDebug() << Q_FUNC_INFO; +} + +void QQnxFileDialogHelper::selectNameFilter(const QString &filter) +{ + qFileDialogHelperDebug() << Q_FUNC_INFO << "filter =" << filter; + setNameFilter(filter); +} + +QString QQnxFileDialogHelper::selectedNameFilter() const +{ + // For now there is no way for the user to change the selected filter + // so this just reflects what the developer has set programmatically. + qFileDialogHelperDebug() << Q_FUNC_INFO; + return m_selectedFilter; +} + +void QQnxFileDialogHelper::setNameFilter(const QString &filter) +{ + qFileDialogHelperDebug() << Q_FUNC_INFO << "filter =" << filter; + + // Extract the globbing expressions + QStringList filters = QPlatformFileDialogHelper::cleanFilterList(filter); + char **globs = new char*[filters.size()]; + for (int i = 0; i < filters.size(); ++i) { + QByteArray glob = filters.at(i).toLocal8Bit(); + globs[i] = new char[glob.length()]; + strcpy(globs[i], glob.constData()); + } + + // Set the filters + dialog_set_filebrowse_filter(m_dialog, const_cast<const char**>(globs), filters.size()); + m_selectedFilter = filter; + + // Cleanup + for (int i = 0; i < filters.size(); ++i) + delete[] globs[i]; + delete[] globs; +} + +QT_END_NAMESPACE |