2 changed files with 0 additions and 344 deletions
@ -1,210 +0,0 @@
@@ -1,210 +0,0 @@
|
||||
/****************************************************************************
|
||||
* |
||||
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
|
||||
* |
||||
* QGroundControl is licensed according to the terms in the file |
||||
* COPYING.md in the root of the source code directory. |
||||
* |
||||
****************************************************************************/ |
||||
|
||||
|
||||
#include "QGCQFileDialog.h" |
||||
#include "QGCApplication.h" |
||||
|
||||
#ifdef UNITTEST_BUILD |
||||
#include "UnitTest.h" |
||||
#endif |
||||
|
||||
#include <QRegularExpression> |
||||
#include <QMessageBox> |
||||
#include <QPushButton> |
||||
|
||||
QString QGCQFileDialog::getExistingDirectory( |
||||
QWidget* parent, |
||||
const QString& caption, |
||||
const QString& dir, |
||||
Options options) |
||||
{ |
||||
_validate(options); |
||||
|
||||
#ifdef UNITTEST_BUILD |
||||
if (qgcApp()->runningUnitTests()) { |
||||
return UnitTest::_getExistingDirectory(parent, caption, dir, options); |
||||
} else |
||||
#endif |
||||
{ |
||||
return QFileDialog::getExistingDirectory(parent, caption, dir, options); |
||||
} |
||||
} |
||||
|
||||
QString QGCQFileDialog::getOpenFileName( |
||||
QWidget* parent, |
||||
const QString& caption, |
||||
const QString& dir, |
||||
const QString& filter, |
||||
Options options) |
||||
{ |
||||
_validate(options); |
||||
|
||||
#ifdef UNITTEST_BUILD |
||||
if (qgcApp()->runningUnitTests()) { |
||||
return UnitTest::_getOpenFileName(parent, caption, dir, filter, options); |
||||
} else |
||||
#endif |
||||
{ |
||||
return QFileDialog::getOpenFileName(parent, caption, dir, filter, NULL, options); |
||||
} |
||||
} |
||||
|
||||
QStringList QGCQFileDialog::getOpenFileNames( |
||||
QWidget* parent, |
||||
const QString& caption, |
||||
const QString& dir, |
||||
const QString& filter, |
||||
Options options) |
||||
{ |
||||
_validate(options); |
||||
|
||||
#ifdef UNITTEST_BUILD |
||||
if (qgcApp()->runningUnitTests()) { |
||||
return UnitTest::_getOpenFileNames(parent, caption, dir, filter, options); |
||||
} else |
||||
#endif |
||||
{ |
||||
return QFileDialog::getOpenFileNames(parent, caption, dir, filter, NULL, options); |
||||
} |
||||
} |
||||
|
||||
QString QGCQFileDialog::getSaveFileName( |
||||
QWidget* parent, |
||||
const QString& caption, |
||||
const QString& dir, |
||||
const QString& filter, |
||||
const QString& defaultSuffix, |
||||
bool strict, |
||||
Options options) |
||||
{ |
||||
_validate(options); |
||||
|
||||
#ifdef UNITTEST_BUILD |
||||
if (qgcApp()->runningUnitTests()) { |
||||
return UnitTest::_getSaveFileName(parent, caption, dir, filter, defaultSuffix, options); |
||||
} else |
||||
#endif |
||||
{ |
||||
QString defaultSuffixCopy(defaultSuffix); |
||||
QFileDialog dlg(parent, caption, dir, filter); |
||||
dlg.setAcceptMode(QFileDialog::AcceptSave); |
||||
if (options) { |
||||
dlg.setOptions(options); |
||||
} |
||||
if (!defaultSuffixCopy.isEmpty()) { |
||||
//-- Make sure dot is not present
|
||||
if (defaultSuffixCopy.startsWith(".")) { |
||||
defaultSuffixCopy.remove(0,1); |
||||
} |
||||
dlg.setDefaultSuffix(defaultSuffixCopy); |
||||
} |
||||
while (true) { |
||||
if (dlg.exec()) { |
||||
if (dlg.selectedFiles().count()) { |
||||
QString result = dlg.selectedFiles().first(); |
||||
//-- If we don't care about the extension, just return it
|
||||
if (!strict) { |
||||
return result; |
||||
} else { |
||||
//-- We must enforce the file extension
|
||||
QFileInfo fi(result); |
||||
QString userSuffix(fi.suffix()); |
||||
if (_validateExtension(filter, userSuffix)) { |
||||
return result; |
||||
} |
||||
//-- Do we have a default extension?
|
||||
if (defaultSuffixCopy.isEmpty()) { |
||||
//-- We don't, so get the first one in the filter
|
||||
defaultSuffixCopy = _getFirstExtensionInFilter(filter); |
||||
} |
||||
//-- If this is set to strict, we have to have a default extension
|
||||
if (defaultSuffixCopy.isEmpty()) { |
||||
qWarning() << "Internal error"; |
||||
} |
||||
//-- Forcefully append our desired extension
|
||||
result += "."; |
||||
result += defaultSuffixCopy; |
||||
//-- Check and see if this new file already exists
|
||||
fi.setFile(result); |
||||
if (fi.exists()) { |
||||
//-- Ask user what to do
|
||||
QMessageBox msgBox( |
||||
QMessageBox::Warning, |
||||
tr("File Exists"), |
||||
tr("%1 already exists.\nDo you want to replace it?").arg(fi.fileName()), |
||||
QMessageBox::Cancel, |
||||
parent); |
||||
msgBox.addButton(QMessageBox::Retry); |
||||
QPushButton *overwriteButton = msgBox.addButton(tr("Replace"), QMessageBox::ActionRole); |
||||
msgBox.setDefaultButton(QMessageBox::Retry); |
||||
msgBox.setWindowModality(Qt::ApplicationModal); |
||||
if (msgBox.exec() == QMessageBox::Retry) { |
||||
continue; |
||||
} else if (msgBox.clickedButton() == overwriteButton) { |
||||
return result; |
||||
} |
||||
} else { |
||||
return result; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
return {}; |
||||
} |
||||
} |
||||
|
||||
/// @brief Make sure filename is using one of the valid extensions defined in the filter
|
||||
bool QGCQFileDialog::_validateExtension(const QString& filter, const QString& extension) { |
||||
QRegularExpression re("(\\*\\.\\w+)"); |
||||
QRegularExpressionMatchIterator i = re.globalMatch(filter); |
||||
while (i.hasNext()) { |
||||
QRegularExpressionMatch match = i.next(); |
||||
if (match.hasMatch()) { |
||||
//-- Compare "foo" with "*.foo"
|
||||
if(extension == match.captured(0).mid(2)) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/// @brief Returns first extension found in filter
|
||||
QString QGCQFileDialog::_getFirstExtensionInFilter(const QString& filter) { |
||||
QRegularExpression re("(\\*\\.\\w+)"); |
||||
QRegularExpressionMatchIterator i = re.globalMatch(filter); |
||||
while (i.hasNext()) { |
||||
QRegularExpressionMatch match = i.next(); |
||||
if (match.hasMatch()) { |
||||
//-- Return "foo" from "*.foo"
|
||||
return match.captured(0).mid(2); |
||||
} |
||||
} |
||||
return {}; |
||||
} |
||||
|
||||
/// @brief Validates and updates the parameters for the file dialog calls
|
||||
void QGCQFileDialog::_validate(Options& options) |
||||
{ |
||||
Q_UNUSED(options) |
||||
|
||||
// You can't use QGCQFileDialog if QGCApplication is not created yet.
|
||||
if (!qgcApp()) { |
||||
qWarning() << "Internal error"; |
||||
return; |
||||
} |
||||
|
||||
if (QThread::currentThread() != qgcApp()->thread()) { |
||||
qWarning() << "Threading issue: QGCQFileDialog can only be called from main thread"; |
||||
return; |
||||
} |
||||
} |
@ -1,134 +0,0 @@
@@ -1,134 +0,0 @@
|
||||
/****************************************************************************
|
||||
* |
||||
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
|
||||
* |
||||
* QGroundControl is licensed according to the terms in the file |
||||
* COPYING.md in the root of the source code directory. |
||||
* |
||||
****************************************************************************/ |
||||
|
||||
|
||||
#ifndef QGCFILEDIALOG_H |
||||
#define QGCFILEDIALOG_H |
||||
|
||||
#ifdef __mobile__ |
||||
#error Should not be included in mobile builds |
||||
#endif |
||||
|
||||
#include <QCoreApplication> |
||||
#include <QFileDialog> |
||||
|
||||
/// @file
|
||||
/// @brief Subclass of <a href="http://qt-project.org/doc/qt-5/qfiledialog.html">QFileDialog</a>
|
||||
/// @author Don Gagne <don@thegagnes.com>
|
||||
|
||||
/*!
|
||||
Subclass of <a href="http://qt-project.org/doc/qt-5/qfiledialog.html">QFileDialog</a> which re-implements the static public functions. The reason for this |
||||
is that the <a href="http://qt-project.org/doc/qt-5/qfiledialog.html">QFileDialog</a> implementations of these use the native os dialogs. On OSX these |
||||
these can intermittently hang. So instead here we use the native dialogs. It also allows |
||||
use to catch these dialogs for unit testing. |
||||
@remark If you need to know what type of file was returned by these functions, you can use something like: |
||||
@code{.cpp} |
||||
QString filename = QGCQFileDialog::getSaveFileName(this, tr("Save File"), "~/", "Foo files (*.foo);;All Files (*.*)", "foo"); |
||||
if (!filename.isEmpty()) { |
||||
QFileInfo fi(filename); |
||||
QString fileExtension(fi.suffix()); |
||||
if (fileExtension == QString("foo")) { |
||||
// do something
|
||||
} |
||||
} |
||||
@endcode |
||||
*/ |
||||
|
||||
class QGCQFileDialog : public QFileDialog { |
||||
Q_DECLARE_TR_FUNCTIONS(QGCQFileDialog) |
||||
public: |
||||
|
||||
//! Static helper that will return an existing directory selected by the user.
|
||||
/*!
|
||||
@param[in] parent The parent QWidget. |
||||
@param[in] caption The caption displayed at the top of the dialog. |
||||
@param[in] dir The initial directory shown to the user. |
||||
@param[in] options Set the various options that affect the look and feel of the dialog. |
||||
@return The chosen path or \c QString("") if none. |
||||
@sa <a href="http://qt-project.org/doc/qt-5/qfiledialog.html#getExistingDirectory">QFileDialog::getExistingDirectory()</a> |
||||
*/ |
||||
static QString getExistingDirectory( |
||||
QWidget* parent = 0, |
||||
const QString& caption = QString(), |
||||
const QString& dir = QString(), |
||||
Options options = ShowDirsOnly); |
||||
|
||||
//! Static helper that invokes a File Open dialog where the user can select a file to be opened.
|
||||
/*!
|
||||
@param[in] parent The parent QWidget. |
||||
@param[in] caption The caption displayed at the top of the dialog. |
||||
@param[in] dir The initial directory shown to the user. |
||||
@param[in] filter The filter used for selecting the file type. |
||||
@param[in] options Set the various options that affect the look and feel of the dialog. |
||||
@return The full path and filename to be opened or \c QString("") if none. |
||||
@sa <a href="http://qt-project.org/doc/qt-5/qfiledialog.html#getOpenFileName">QFileDialog::getOpenFileName()</a> |
||||
*/ |
||||
static QString getOpenFileName( |
||||
QWidget* parent = 0, |
||||
const QString& caption = QString(), |
||||
const QString& dir = QString(), |
||||
const QString& filter = QString(), |
||||
Options options = Options()); |
||||
|
||||
//! Static helper that invokes a File Open dialog where the user can select one or more files to be opened.
|
||||
/*!
|
||||
@param[in] parent The parent QWidget. |
||||
@param[in] caption The caption displayed at the top of the dialog. |
||||
@param[in] dir The initial directory shown to the user. |
||||
@param[in] filter The filter used for selecting the file type. |
||||
@param[in] options Set the various options that affect the look and feel of the dialog. |
||||
@return A <a href="http://qt-project.org/doc/qt-5/qstringlist.html">QStringList</a> object containing zero or more files to be opened. |
||||
@sa <a href="http://qt-project.org/doc/qt-5/qfiledialog.html#getOpenFileNames">QFileDialog::getOpenFileNames()</a> |
||||
*/ |
||||
static QStringList getOpenFileNames( |
||||
QWidget* parent = 0, |
||||
const QString& caption = QString(), |
||||
const QString& dir = QString(), |
||||
const QString& filter = QString(), |
||||
Options options = Options()); |
||||
|
||||
//! Static helper that invokes a File Save dialog where the user can select a directory and enter a filename to be saved.
|
||||
/*!
|
||||
@param[in] parent The parent QWidget. |
||||
@param[in] caption The caption displayed at the top of the dialog. |
||||
@param[in] dir The initial directory shown to the user. |
||||
@param[in] filter The filter used for selecting the file type. |
||||
@param[in] defaultSuffix Specifies a string that will be added to the filename if it has no suffix already. The suffix is typically used to indicate the file type (e.g. "txt" indicates a text file). |
||||
@param[in] strict Makes the default suffix mandatory. Only files with those extensions will be allowed. |
||||
@param[in] options Set the various options that affect the look and feel of the dialog. |
||||
@return The full path and filename to be used to save the file or \c QString("") if none. |
||||
@sa <a href="http://qt-project.org/doc/qt-5/qfiledialog.html#getSaveFileName">QFileDialog::getSaveFileName()</a> |
||||
@remark If a default suffix is given, it will be appended to the filename if the user does not enter one themselves. That is, if the user simply enters \e foo and the default suffix is set to \e bar, |
||||
the returned filename will be \e foo.bar. However, if the user specifies a suffix, the \e strict flag will determine what is done. If the user enters \e foo.txt and \e strict is false, the function |
||||
returns \e foo.txt (no suffix enforced). If \e strict is true however, the default suffix is appended no matter what. In the case above, the function will return \e foo.txt.bar (suffix enforced). |
||||
@remark If \e strict is set and the file name given by the user is renamed (the \e foo.txt.bar example above), the function will check and see if the file already exists. If that's the case, it will |
||||
ask the user if they want to overwrite it. |
||||
*/ |
||||
static QString getSaveFileName( |
||||
QWidget* parent = 0, |
||||
const QString& caption = QString(), |
||||
const QString& dir = QString(), |
||||
const QString& filter = QString(), |
||||
const QString& defaultSuffix = QString(), |
||||
bool strict = false, |
||||
Options options = Options()); |
||||
|
||||
private slots: |
||||
/// @brief The exec slot is private because we only want QGCQFileDialog users to use the static methods. Otherwise it will break
|
||||
/// unit testing.
|
||||
int exec(void) { return QFileDialog::exec(); } |
||||
|
||||
private: |
||||
static void _validate(Options& options); |
||||
static bool _validateExtension(const QString& filter, const QString& extension); |
||||
static QString _getFirstExtensionInFilter(const QString& filter); |
||||
}; |
||||
|
||||
|
||||
#endif |
Loading…
Reference in new issue