QGCFileDialog.cc 7.64 KB
Newer Older
Don Gagne's avatar
Don Gagne committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*=====================================================================
 
 QGroundControl Open Source Ground Control Station
 
 (c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 
 This file is part of the QGROUNDCONTROL project
 
 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
 
 ======================================================================*/

#include "QGCFileDialog.h"
#include "QGCApplication.h"
26
#include <QRegularExpression>
27
#include "MainWindow.h"
Don Gagne's avatar
Don Gagne committed
28
#ifdef QT_DEBUG
dogmaphobic's avatar
dogmaphobic committed
29
#ifndef __mobile__
Don Gagne's avatar
Don Gagne committed
30
31
#include "UnitTest.h"
#endif
dogmaphobic's avatar
dogmaphobic committed
32
#endif
Don Gagne's avatar
Don Gagne committed
33

34
35
36
37
38
QString QGCFileDialog::getExistingDirectory(
    QWidget* parent,
    const QString& caption,
    const QString& dir,
    Options options)
Don Gagne's avatar
Don Gagne committed
39
{
40
    _validate(options);
Don Gagne's avatar
Don Gagne committed
41
42
    
#ifdef QT_DEBUG
dogmaphobic's avatar
dogmaphobic committed
43
#ifndef __mobile__
Don Gagne's avatar
Don Gagne committed
44
45
46
    if (qgcApp()->runningUnitTests()) {
        return UnitTest::_getExistingDirectory(parent, caption, dir, options);
    } else
dogmaphobic's avatar
dogmaphobic committed
47
#endif
Don Gagne's avatar
Don Gagne committed
48
49
50
51
52
53
#endif
    {
        return QFileDialog::getExistingDirectory(parent, caption, dir, options);
    }
}

54
55
56
57
58
59
QString QGCFileDialog::getOpenFileName(
    QWidget* parent,
    const QString& caption,
    const QString& dir,
    const QString& filter,
    Options options)
Don Gagne's avatar
Don Gagne committed
60
{
61
    _validate(options);
Don Gagne's avatar
Don Gagne committed
62
63
    
#ifdef QT_DEBUG
dogmaphobic's avatar
dogmaphobic committed
64
#ifndef __mobile__
Don Gagne's avatar
Don Gagne committed
65
    if (qgcApp()->runningUnitTests()) {
66
        return UnitTest::_getOpenFileName(parent, caption, dir, filter, options);
Don Gagne's avatar
Don Gagne committed
67
    } else
dogmaphobic's avatar
dogmaphobic committed
68
#endif
Don Gagne's avatar
Don Gagne committed
69
70
#endif
    {
71
        return QFileDialog::getOpenFileName(parent, caption, dir, filter, NULL, options);
Don Gagne's avatar
Don Gagne committed
72
73
74
    }
}

75
76
77
78
79
80
QStringList QGCFileDialog::getOpenFileNames(
    QWidget* parent,
    const QString& caption,
    const QString& dir,
    const QString& filter,
    Options options)
Don Gagne's avatar
Don Gagne committed
81
{
82
    _validate(options);
Don Gagne's avatar
Don Gagne committed
83
84
    
#ifdef QT_DEBUG
dogmaphobic's avatar
dogmaphobic committed
85
#ifndef __mobile__
Don Gagne's avatar
Don Gagne committed
86
    if (qgcApp()->runningUnitTests()) {
87
        return UnitTest::_getOpenFileNames(parent, caption, dir, filter, options);
Don Gagne's avatar
Don Gagne committed
88
    } else
dogmaphobic's avatar
dogmaphobic committed
89
#endif
Don Gagne's avatar
Don Gagne committed
90
91
#endif
    {
92
        return QFileDialog::getOpenFileNames(parent, caption, dir, filter, NULL, options);
Don Gagne's avatar
Don Gagne committed
93
94
95
    }
}

96
97
QString QGCFileDialog::getSaveFileName(
    QWidget* parent,
98
99
100
    const QString& caption,
    const QString& dir,
    const QString& filter,
101
    const QString& defaultSuffix,
102
    bool strict,
103
    Options options)
Don Gagne's avatar
Don Gagne committed
104
{
105
    _validate(options);
106

Don Gagne's avatar
Don Gagne committed
107
#ifdef QT_DEBUG
dogmaphobic's avatar
dogmaphobic committed
108
#ifndef __mobile__
Don Gagne's avatar
Don Gagne committed
109
    if (qgcApp()->runningUnitTests()) {
110
        return UnitTest::_getSaveFileName(parent, caption, dir, filter, defaultSuffix, options);
Don Gagne's avatar
Don Gagne committed
111
    } else
dogmaphobic's avatar
dogmaphobic committed
112
#endif
Don Gagne's avatar
Don Gagne committed
113
114
#endif
    {
115
        QString defaultSuffixCopy(defaultSuffix);
116
        QFileDialog dlg(parent, caption, dir, filter);
117
        dlg.setAcceptMode(QFileDialog::AcceptSave);
118
        if (options) {
119
            dlg.setOptions(options);
120
        }
121
        if (!defaultSuffixCopy.isEmpty()) {
122
            //-- Make sure dot is not present
123
124
            if (defaultSuffixCopy.startsWith(".")) {
                defaultSuffixCopy.remove(0,1);
125
            }
126
            dlg.setDefaultSuffix(defaultSuffixCopy);
127
        }
128
129
130
        while (true) {
            if (dlg.exec()) {
                if (dlg.selectedFiles().count()) {
131
132
133
134
135
136
137
138
139
140
141
142
                    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?
143
                        if (defaultSuffixCopy.isEmpty()) {
144
                            //-- We don't, so get the first one in the filter
145
                            defaultSuffixCopy = _getFirstExtensionInFilter(filter);
146
                        }
147
148
                        //-- If this is set to strict, we have to have a default extension
                        Q_ASSERT(defaultSuffixCopy.isEmpty() == false);
149
150
                        //-- Forcefully append our desired extension
                        result += ".";
151
                        result += defaultSuffixCopy;
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
                        //-- 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;
173
174
                        }
                    }
175
                }
176
            }
177
            break;
178
        }
179
        return QString("");
Don Gagne's avatar
Don Gagne committed
180
181
182
    }
}

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/// @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()) {
206
207
            //-- Return "foo" from "*.foo"
            return match.captured(0).mid(2);
208
209
210
211
212
        }
    }
    return QString("");
}

Don Gagne's avatar
Don Gagne committed
213
/// @brief Validates and updates the parameters for the file dialog calls
214
void QGCFileDialog::_validate(Options& options)
Don Gagne's avatar
Don Gagne committed
215
216
217
218
{
    // You can't use QGCFileDialog if QGCApplication is not created yet.
    Q_ASSERT(qgcApp());
    
219
    Q_ASSERT_X(QThread::currentThread() == qgcApp()->thread(), "Threading issue", "QGCFileDialog can only be called from main thread");
dogmaphobic's avatar
dogmaphobic committed
220
#ifdef __mobile__
dogmaphobic's avatar
dogmaphobic committed
221
222
    Q_UNUSED(options)
#else
Don Gagne's avatar
Don Gagne committed
223
    // On OSX native dialog can hang so we always use Qt dialogs
Don Gagne's avatar
Don Gagne committed
224
    options |= DontUseNativeDialog;
dogmaphobic's avatar
dogmaphobic committed
225
#endif
226
227
228
    if (MainWindow::instance()) {
        MainWindow::instance()->hideSplashScreen();
    }
Don Gagne's avatar
Don Gagne committed
229
}