QGCFileDialog.cc 6.83 KB
Newer Older
1
2
3
4
5
6
7
8
9
/****************************************************************************
 *
 *   (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.
 *
 ****************************************************************************/

Don Gagne's avatar
Don Gagne committed
10
11
12

#include "QGCFileDialog.h"
#include "QGCApplication.h"
13
#include "MainWindow.h"
14

15
16
#ifdef UNITTEST_BUILD
    #include "UnitTest.h"
dogmaphobic's avatar
dogmaphobic committed
17
#endif
Don Gagne's avatar
Don Gagne committed
18

Don Gagne's avatar
Don Gagne committed
19
20
#include <QRegularExpression>
#include <QMessageBox>
21
#include <QPushButton>
Don Gagne's avatar
Don Gagne committed
22

23
24
25
26
27
QString QGCFileDialog::getExistingDirectory(
    QWidget* parent,
    const QString& caption,
    const QString& dir,
    Options options)
Don Gagne's avatar
Don Gagne committed
28
{
29
    _validate(options);
Don Gagne's avatar
Don Gagne committed
30
    
31
#ifdef UNITTEST_BUILD
Don Gagne's avatar
Don Gagne committed
32
33
34
35
36
37
38
39
40
    if (qgcApp()->runningUnitTests()) {
        return UnitTest::_getExistingDirectory(parent, caption, dir, options);
    } else
#endif
    {
        return QFileDialog::getExistingDirectory(parent, caption, dir, options);
    }
}

41
42
43
44
45
46
QString QGCFileDialog::getOpenFileName(
    QWidget* parent,
    const QString& caption,
    const QString& dir,
    const QString& filter,
    Options options)
Don Gagne's avatar
Don Gagne committed
47
{
48
    _validate(options);
Don Gagne's avatar
Don Gagne committed
49
    
50
#ifdef UNITTEST_BUILD
Don Gagne's avatar
Don Gagne committed
51
    if (qgcApp()->runningUnitTests()) {
52
        return UnitTest::_getOpenFileName(parent, caption, dir, filter, options);
Don Gagne's avatar
Don Gagne committed
53
54
55
    } else
#endif
    {
56
        return QFileDialog::getOpenFileName(parent, caption, dir, filter, NULL, options);
Don Gagne's avatar
Don Gagne committed
57
58
59
    }
}

60
61
62
63
64
65
QStringList QGCFileDialog::getOpenFileNames(
    QWidget* parent,
    const QString& caption,
    const QString& dir,
    const QString& filter,
    Options options)
Don Gagne's avatar
Don Gagne committed
66
{
67
    _validate(options);
Don Gagne's avatar
Don Gagne committed
68
    
69
#ifdef UNITTEST_BUILD
Don Gagne's avatar
Don Gagne committed
70
    if (qgcApp()->runningUnitTests()) {
71
        return UnitTest::_getOpenFileNames(parent, caption, dir, filter, options);
Don Gagne's avatar
Don Gagne committed
72
73
74
    } else
#endif
    {
75
        return QFileDialog::getOpenFileNames(parent, caption, dir, filter, NULL, options);
Don Gagne's avatar
Don Gagne committed
76
77
78
    }
}

79
80
QString QGCFileDialog::getSaveFileName(
    QWidget* parent,
81
82
83
    const QString& caption,
    const QString& dir,
    const QString& filter,
84
    const QString& defaultSuffix,
85
    bool strict,
86
    Options options)
Don Gagne's avatar
Don Gagne committed
87
{
88
    _validate(options);
89

90
#ifdef UNITTEST_BUILD
Don Gagne's avatar
Don Gagne committed
91
    if (qgcApp()->runningUnitTests()) {
92
        return UnitTest::_getSaveFileName(parent, caption, dir, filter, defaultSuffix, options);
Don Gagne's avatar
Don Gagne committed
93
94
95
    } else
#endif
    {
96
        QString defaultSuffixCopy(defaultSuffix);
97
        QFileDialog dlg(parent, caption, dir, filter);
98
        dlg.setAcceptMode(QFileDialog::AcceptSave);
99
        if (options) {
100
            dlg.setOptions(options);
101
        }
102
        if (!defaultSuffixCopy.isEmpty()) {
103
            //-- Make sure dot is not present
104
105
            if (defaultSuffixCopy.startsWith(".")) {
                defaultSuffixCopy.remove(0,1);
106
            }
107
            dlg.setDefaultSuffix(defaultSuffixCopy);
108
        }
109
110
111
        while (true) {
            if (dlg.exec()) {
                if (dlg.selectedFiles().count()) {
112
113
114
115
116
117
118
119
120
121
122
123
                    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?
124
                        if (defaultSuffixCopy.isEmpty()) {
125
                            //-- We don't, so get the first one in the filter
126
                            defaultSuffixCopy = _getFirstExtensionInFilter(filter);
127
                        }
128
129
                        //-- If this is set to strict, we have to have a default extension
                        Q_ASSERT(defaultSuffixCopy.isEmpty() == false);
130
131
                        //-- Forcefully append our desired extension
                        result += ".";
132
                        result += defaultSuffixCopy;
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
                        //-- 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;
154
155
                        }
                    }
156
                }
157
            }
158
            break;
159
        }
160
        return QString("");
Don Gagne's avatar
Don Gagne committed
161
162
163
    }
}

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/// @brief Make sure filename is using one of the valid extensions defined in the filter
bool QGCFileDialog::_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 QGCFileDialog::_getFirstExtensionInFilter(const QString& filter) {
    QRegularExpression re("(\\*\\.\\w+)");
    QRegularExpressionMatchIterator i = re.globalMatch(filter);
    while (i.hasNext()) {
        QRegularExpressionMatch match = i.next();
        if (match.hasMatch()) {
187
188
            //-- Return "foo" from "*.foo"
            return match.captured(0).mid(2);
189
190
191
192
193
        }
    }
    return QString("");
}

Don Gagne's avatar
Don Gagne committed
194
/// @brief Validates and updates the parameters for the file dialog calls
195
void QGCFileDialog::_validate(Options& options)
Don Gagne's avatar
Don Gagne committed
196
{
Don Gagne's avatar
Don Gagne committed
197
198
    Q_UNUSED(options)

Don Gagne's avatar
Don Gagne committed
199
200
201
    // You can't use QGCFileDialog if QGCApplication is not created yet.
    Q_ASSERT(qgcApp());
    
202
    Q_ASSERT_X(QThread::currentThread() == qgcApp()->thread(), "Threading issue", "QGCFileDialog can only be called from main thread");
203
204
    if (MainWindow::instance()) {
    }
Don Gagne's avatar
Don Gagne committed
205
}