1 /***************************************************************************
2 testqgsexternalstoragefilewidget.cpp
3 --------------------------------------
4 Date : August 2021
5 Copyright : (C) 2021 Julien Cabieces
6 Email : julien dot cabieces at oslandia dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16
17 #include "qgstest.h"
18
19 #include "qgsexternalstoragefilewidget.h"
20 #include "qgsmimedatautils.h"
21 #include "qgsdataitem.h"
22 #include "qgsbrowsermodel.h"
23 #include "qgslayeritem.h"
24 #include "qgsdirectoryitem.h"
25 #include "qgsexternalstorage.h"
26 #include "qgsexternalstorageregistry.h"
27 #include "qgsmessagebar.h"
28 #include "qgsexpressioncontextutils.h"
29 #include <memory>
30
31 #include <QLabel>
32 #include <QToolButton>
33 #include <QProgressBar>
34
35 class TestQgsExternalStorageFileWidget: public QObject
36 {
37 Q_OBJECT
38 private slots:
39 void initTestCase(); // will be called before the first testfunction is executed.
40 void cleanupTestCase(); // will be called after the last testfunction was executed.
41 void init(); // will be called before each testfunction is executed.
42 void cleanup(); // will be called after every testfunction.
43 void testLayout_data();
44 void testLayout();
45 void testStoring();
46 void testStoring_data();
47 void testStoringSeveralFiles_data();
48 void testStoringSeveralFiles();
49 void testStoringSeveralFilesError_data();
50 void testStoringSeveralFilesError();
51 void testStoringSeveralFilesCancel_data();
52 void testStoringSeveralFilesCancel();
53 void testStoringDirectory_data();
54 void testStoringDirectory();
55 void testStoringChangeFeature();
56 void testStoringBadExpression_data();
57 void testStoringBadExpression();
58 void testDragAndDrop();
59 };
60
61 class QgsTestExternalStorageStoredContent : public QgsExternalStorageStoredContent
62 {
63 Q_OBJECT
64
65 public:
66
QgsTestExternalStorageStoredContent(const QString & filePath,const QString & url)67 QgsTestExternalStorageStoredContent( const QString &filePath, const QString &url )
68 : QgsExternalStorageStoredContent(),
69 mUrl( filePath.endsWith( QLatin1String( "mydir" ) ) ? url + "mydir/" : url )
70 {}
71
store()72 void store() override
73 {
74 mStatus = Qgis::ContentStatus::Running;
75 }
76
cancel()77 void cancel() override
78 {
79 mStatus = Qgis::ContentStatus::Canceled;
80 emit canceled();
81 };
82
error()83 void error()
84 {
85 mStatus = Qgis::ContentStatus::Failed;
86 mErrorString = QStringLiteral( "error" );
87 emit errorOccurred( mErrorString );
88 }
89
setProgress(double progress)90 void setProgress( double progress )
91 {
92 emit progressChanged( progress );
93 }
94
finish()95 void finish()
96 {
97 mStatus = Qgis::ContentStatus::Finished;
98 emit stored();
99 }
100
url() const101 QString url() const override
102 {
103 return mUrl;
104 }
105
106 private:
107
108 QString mUrl;
109
110 };
111
112 class QgsTestExternalStorage : public QgsExternalStorage
113 {
114 public:
115
type() const116 QString type() const override { return QStringLiteral( "test" ); }
117
displayName() const118 QString displayName() const override { return QStringLiteral( "Test" ); }
119
120 static QPointer<QgsTestExternalStorageStoredContent> sCurrentStoredContent;
121
122 protected:
123
doStore(const QString & filePath,const QString & url,const QString & authcfg=QString ()) const124 QgsExternalStorageStoredContent *doStore( const QString &filePath, const QString &url, const QString &authcfg = QString() ) const override
125 {
126 Q_UNUSED( authcfg );
127 sCurrentStoredContent = new QgsTestExternalStorageStoredContent( filePath, url );
128 return sCurrentStoredContent;
129 }
130
doFetch(const QString & url,const QString & authcfg=QString ()) const131 QgsExternalStorageFetchedContent *doFetch( const QString &url, const QString &authcfg = QString() ) const override
132 {
133 Q_UNUSED( url );
134 Q_UNUSED( authcfg );
135 return nullptr;
136 }
137 };
138
139 QPointer<QgsTestExternalStorageStoredContent> QgsTestExternalStorage::sCurrentStoredContent;
140
initTestCase()141 void TestQgsExternalStorageFileWidget::initTestCase()
142 {
143 QgsApplication::externalStorageRegistry()->registerExternalStorage( new QgsTestExternalStorage() );
144 }
145
cleanupTestCase()146 void TestQgsExternalStorageFileWidget::cleanupTestCase()
147 {
148 }
149
init()150 void TestQgsExternalStorageFileWidget::init()
151 {
152 }
153
cleanup()154 void TestQgsExternalStorageFileWidget::cleanup()
155 {
156 }
157
testLayout_data()158 void TestQgsExternalStorageFileWidget::testLayout_data()
159 {
160 QTest::addColumn<QString>( "storageType" );
161
162 QTest::newRow( "without external storage" ) << QString();
163 QTest::newRow( "with external storage" ) << QStringLiteral( "test" );
164 }
165
testLayout()166 void TestQgsExternalStorageFileWidget::testLayout()
167 {
168 // test correct buttons are displayed according to different mode and interactions
169
170 QFETCH( QString, storageType );
171
172 QgsExternalStorageFileWidget w;
173 w.setStorageType( storageType );
174 w.show();
175
176 QIcon editIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) );
177 QIcon saveIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionSaveEdits.svg" ) );
178
179 // with link, read-only
180 w.setReadOnly( true );
181 w.setUseLink( true );
182
183 QVERIFY( w.mLinkLabel->isVisible() );
184 QVERIFY( !w.mLinkEditButton->isVisible() );
185 QVERIFY( !w.mLineEdit->isVisible() );
186 QVERIFY( w.mFileWidgetButton->isVisible() );
187 QVERIFY( !w.mFileWidgetButton->isEnabled() );
188 QVERIFY( !w.mProgressLabel->isVisible() );
189 QVERIFY( !w.mProgressBar->isVisible() );
190 QVERIFY( !w.mCancelButton->isVisible() );
191
192 // with link, edit mode
193 w.setReadOnly( false );
194
195 QVERIFY( w.mLinkLabel->isVisible() );
196 QVERIFY( w.mLinkEditButton->isVisible() );
197 QCOMPARE( w.mLinkEditButton->icon(), editIcon );
198 QVERIFY( !w.mLineEdit->isVisible() );
199 QVERIFY( w.mFileWidgetButton->isVisible() );
200 QVERIFY( w.mFileWidgetButton->isEnabled() );
201 QVERIFY( !w.mProgressLabel->isVisible() );
202 QVERIFY( !w.mProgressBar->isVisible() );
203 QVERIFY( !w.mCancelButton->isVisible() );
204
205 // with link, edit mode, we edit the link
206 w.editLink();
207
208 QVERIFY( !w.mLinkLabel->isVisible() );
209 QVERIFY( w.mLinkEditButton->isVisible() );
210 QCOMPARE( w.mLinkEditButton->icon(), saveIcon );
211 QVERIFY( w.mLineEdit->isVisible() );
212 QVERIFY( w.mLineEdit->isEnabled() );
213 QVERIFY( w.mFileWidgetButton->isVisible() );
214 QVERIFY( w.mFileWidgetButton->isEnabled() );
215 QVERIFY( !w.mProgressLabel->isVisible() );
216 QVERIFY( !w.mProgressBar->isVisible() );
217 QVERIFY( !w.mCancelButton->isVisible() );
218
219 // with link, edit mode, we finish editing the link
220 w.editLink();
221
222 QVERIFY( w.mLinkLabel->isVisible() );
223 QVERIFY( w.mLinkEditButton->isVisible() );
224 QCOMPARE( w.mLinkEditButton->icon(), editIcon );
225 QVERIFY( !w.mLineEdit->isVisible() );
226 QVERIFY( w.mFileWidgetButton->isVisible() );
227 QVERIFY( w.mFileWidgetButton->isEnabled() );
228 QVERIFY( !w.mProgressLabel->isVisible() );
229 QVERIFY( !w.mProgressBar->isVisible() );
230 QVERIFY( !w.mCancelButton->isVisible() );
231
232 // without link, read-only
233 w.setUseLink( false );
234 w.setReadOnly( true );
235
236 QVERIFY( !w.mLinkLabel->isVisible() );
237 QVERIFY( !w.mLinkEditButton->isVisible() );
238 QVERIFY( w.mLineEdit->isVisible() );
239 QVERIFY( !w.mLineEdit->isEnabled() );
240 QVERIFY( w.mFileWidgetButton->isVisible() );
241 QVERIFY( !w.mFileWidgetButton->isEnabled() );
242 QVERIFY( !w.mProgressLabel->isVisible() );
243 QVERIFY( !w.mProgressBar->isVisible() );
244 QVERIFY( !w.mCancelButton->isVisible() );
245
246 // without link, edit mode
247 w.setReadOnly( false );
248
249 QVERIFY( !w.mLinkLabel->isVisible() );
250 QVERIFY( !w.mLinkEditButton->isVisible() );
251 QVERIFY( w.mLineEdit->isVisible() );
252 QVERIFY( w.mLineEdit->isEnabled() );
253 QVERIFY( w.mFileWidgetButton->isVisible() );
254 QVERIFY( w.mFileWidgetButton->isEnabled() );
255 QVERIFY( !w.mProgressLabel->isVisible() );
256 QVERIFY( !w.mProgressBar->isVisible() );
257 QVERIFY( !w.mCancelButton->isVisible() );
258 }
259
testStoring_data()260 void TestQgsExternalStorageFileWidget::testStoring_data()
261 {
262 QTest::addColumn<bool>( "useLink" );
263
264 QTest::newRow( "use link" ) << true;
265 QTest::newRow( "don't use link" ) << false;
266 }
267
testStoring()268 void TestQgsExternalStorageFileWidget::testStoring()
269 {
270 // test widget when an external storage is used
271
272 QFETCH( bool, useLink );
273
274 QgsExternalStorageFileWidget w;
275 w.show();
276
277 QIcon editIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) );
278
279 w.setStorageType( "test" );
280 w.setStorageUrlExpression( "'http://test.url.com/test/' || file_name(@selected_file_path)" );
281
282 // start edit mode
283 w.setUseLink( useLink );
284 w.setReadOnly( false );
285
286 const QStringList fileNames = QStringList() << "myfile1.txt" << "myfile2.txt" ;
287 for ( QString fileName : fileNames )
288 {
289 QVERIFY( useLink == w.mLinkLabel->isVisible() );
290 QVERIFY( useLink == w.mLinkEditButton->isVisible() );
291 if ( useLink ) QCOMPARE( w.mLinkEditButton->icon(), editIcon );
292 QVERIFY( useLink != w.mLineEdit->isVisible() );
293 QVERIFY( w.mFileWidgetButton->isVisible() );
294 QVERIFY( w.mFileWidgetButton->isEnabled() );
295 QVERIFY( !w.mProgressLabel->isVisible() );
296 QVERIFY( !w.mProgressBar->isVisible() );
297 QVERIFY( !w.mCancelButton->isVisible() );
298
299 QString currentLabel = useLink ? w.mLinkLabel->text() : w.mLineEdit->text();
300
301 w.setSelectedFileNames( QStringList() << fileName );
302
303 QVERIFY( QgsTestExternalStorage::sCurrentStoredContent );
304
305 QVERIFY( !w.mLinkLabel->isVisible() );
306 QVERIFY( !w.mLinkEditButton->isVisible() );
307 QVERIFY( !w.mLineEdit->isVisible() );
308 QVERIFY( !w.mFileWidgetButton->isVisible() );
309 QVERIFY( w.mProgressLabel->isVisible() );
310 QVERIFY( w.mProgressBar->isVisible() );
311 QCOMPARE( w.mProgressBar->value(), 0 );
312 QVERIFY( w.mCancelButton->isVisible() );
313
314 // link is not yet updated
315 if ( useLink )
316 QCOMPARE( currentLabel, w.mLinkLabel->text() );
317 else
318 QCOMPARE( currentLabel, w.mLineEdit->text() );
319
320 QgsTestExternalStorage::sCurrentStoredContent->setProgress( 50 );
321 QVERIFY( w.mProgressBar->isVisible() );
322 QCOMPARE( w.mProgressBar->value(), 50 );
323
324 QgsTestExternalStorage::sCurrentStoredContent->finish();
325
326 QVERIFY( useLink == w.mLinkLabel->isVisible() );
327 QVERIFY( useLink == w.mLinkEditButton->isVisible() );
328 if ( useLink ) QCOMPARE( w.mLinkEditButton->icon(), editIcon );
329 QVERIFY( useLink != w.mLineEdit->isVisible() );
330 QVERIFY( w.mFileWidgetButton->isVisible() );
331 QVERIFY( w.mFileWidgetButton->isEnabled() );
332 QVERIFY( !w.mProgressLabel->isVisible() );
333 QVERIFY( !w.mProgressBar->isVisible() );
334 QVERIFY( !w.mCancelButton->isVisible() );
335 if ( useLink )
336 QCOMPARE( w.mLinkLabel->text(), QStringLiteral( "<a href=\"http://test.url.com/test/%1\">%1</a>" ).arg( fileName ) );
337 else
338 QCOMPARE( w.mLineEdit->text(), QStringLiteral( "http://test.url.com/test/%1" ).arg( fileName ) );
339 }
340 }
341
342
testStoringSeveralFiles_data()343 void TestQgsExternalStorageFileWidget::testStoringSeveralFiles_data()
344 {
345 QTest::addColumn<bool>( "useLink" );
346
347 QTest::newRow( "use link" ) << true;
348 QTest::newRow( "don't use link" ) << false;
349 }
350
testStoringSeveralFiles()351 void TestQgsExternalStorageFileWidget::testStoringSeveralFiles()
352 {
353 // test widget when storing several files with an external storage
354 QEventLoop loop;
355 QFETCH( bool, useLink );
356
357 QgsExternalStorageFileWidget w;
358 w.show();
359
360 QIcon editIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) );
361
362 w.setStorageType( "test" );
363 w.setStorageUrlExpression( "'http://test.url.com/test/' || file_name(@selected_file_path)" );
364 w.setStorageMode( QgsFileWidget::GetMultipleFiles );
365
366 // start edit mode
367 w.setUseLink( useLink );
368 w.setReadOnly( false );
369
370 QVERIFY( useLink == w.mLinkLabel->isVisible() );
371 QVERIFY( useLink == w.mLinkEditButton->isVisible() );
372 if ( useLink ) QCOMPARE( w.mLinkEditButton->icon(), editIcon );
373 QVERIFY( useLink != w.mLineEdit->isVisible() );
374 QVERIFY( w.mFileWidgetButton->isVisible() );
375 QVERIFY( w.mFileWidgetButton->isEnabled() );
376 QVERIFY( !w.mProgressLabel->isVisible() );
377 QVERIFY( !w.mProgressBar->isVisible() );
378 QVERIFY( !w.mCancelButton->isVisible() );
379
380 w.setSelectedFileNames( QStringList() << QStringLiteral( "myfile1" ) << QStringLiteral( "myfile2" ) );
381
382 QPointer<QgsTestExternalStorageStoredContent> content1 = QgsTestExternalStorage::sCurrentStoredContent;
383 QVERIFY( content1 );
384
385 QVERIFY( !w.mLinkLabel->isVisible() );
386 QVERIFY( !w.mLinkEditButton->isVisible() );
387 QVERIFY( !w.mLineEdit->isVisible() );
388 QVERIFY( !w.mFileWidgetButton->isVisible() );
389 QVERIFY( w.mProgressLabel->isVisible() );
390 QVERIFY( w.mProgressBar->isVisible() );
391 QVERIFY( w.mCancelButton->isVisible() );
392 QVERIFY( w.mLinkLabel->text().isEmpty() );
393
394 QgsTestExternalStorage::sCurrentStoredContent->finish();
395
396 // second file is being stored
397 QVERIFY( content1 );
398 QVERIFY( QgsTestExternalStorage::sCurrentStoredContent );
399 QVERIFY( content1 != QgsTestExternalStorage::sCurrentStoredContent );
400
401 QVERIFY( !w.mLinkLabel->isVisible() );
402 QVERIFY( !w.mLinkEditButton->isVisible() );
403 QVERIFY( !w.mLineEdit->isVisible() );
404 QVERIFY( !w.mFileWidgetButton->isVisible() );
405 QVERIFY( w.mProgressLabel->isVisible() );
406 QVERIFY( w.mProgressBar->isVisible() );
407 QVERIFY( w.mCancelButton->isVisible() );
408 QVERIFY( w.mLinkLabel->text().isEmpty() );
409
410 // wait for first file content to be destroyed
411 connect( content1, &QObject::destroyed, &loop, &QEventLoop::quit );
412 loop.exec();
413 QVERIFY( !content1 );
414 QVERIFY( QgsTestExternalStorage::sCurrentStoredContent );
415
416 // end second store
417 QgsTestExternalStorage::sCurrentStoredContent->finish();
418
419 QVERIFY( useLink == w.mLinkLabel->isVisible() );
420 QVERIFY( useLink == w.mLinkEditButton->isVisible() );
421 if ( useLink ) QCOMPARE( w.mLinkEditButton->icon(), editIcon );
422 QVERIFY( useLink != w.mLineEdit->isVisible() );
423 QVERIFY( w.mFileWidgetButton->isVisible() );
424 QVERIFY( w.mFileWidgetButton->isEnabled() );
425 QVERIFY( !w.mProgressLabel->isVisible() );
426 QVERIFY( !w.mProgressBar->isVisible() );
427 QVERIFY( !w.mCancelButton->isVisible() );
428 if ( useLink )
429 QCOMPARE( w.mLinkLabel->text(), QStringLiteral( "<a>\"http://test.url.com/test/myfile1\" \"http://test.url.com/test/myfile2\"</a>" ) );
430 else
431 QCOMPARE( w.mLineEdit->text(), QStringLiteral( "\"http://test.url.com/test/myfile1\" \"http://test.url.com/test/myfile2\"" ) );
432
433 // wait for second file content to be destroyed
434 connect( QgsTestExternalStorage::sCurrentStoredContent, &QObject::destroyed, &loop, &QEventLoop::quit );
435 loop.exec();
436 QVERIFY( !QgsTestExternalStorage::sCurrentStoredContent );
437 }
438
testStoringSeveralFilesError_data()439 void TestQgsExternalStorageFileWidget::testStoringSeveralFilesError_data()
440 {
441 QTest::addColumn<bool>( "useLink" );
442
443 QTest::newRow( "use link" ) << true;
444 QTest::newRow( "don't use link" ) << false;
445 }
446
testStoringSeveralFilesError()447 void TestQgsExternalStorageFileWidget::testStoringSeveralFilesError()
448 {
449 // test widget when storing several files with an external storage and an error occurred
450 QEventLoop loop;
451 QFETCH( bool, useLink );
452
453 QgsExternalStorageFileWidget w;
454 QgsMessageBar messageBar;
455 w.show();
456
457 QIcon editIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) );
458
459 w.setStorageType( "test" );
460 w.setStorageUrlExpression( "'http://test.url.com/test/' || file_name(@selected_file_path)" );
461 w.setMessageBar( &messageBar );
462
463 // start edit mode
464 w.setUseLink( useLink );
465 w.setReadOnly( false );
466
467 QVERIFY( useLink == w.mLinkLabel->isVisible() );
468 QVERIFY( useLink == w.mLinkEditButton->isVisible() );
469 if ( useLink ) QCOMPARE( w.mLinkEditButton->icon(), editIcon );
470 QVERIFY( useLink != w.mLineEdit->isVisible() );
471 QVERIFY( w.mFileWidgetButton->isVisible() );
472 QVERIFY( w.mFileWidgetButton->isEnabled() );
473 QVERIFY( !w.mProgressLabel->isVisible() );
474 QVERIFY( !w.mProgressBar->isVisible() );
475 QVERIFY( !w.mCancelButton->isVisible() );
476
477 w.setSelectedFileNames( QStringList() << QStringLiteral( "myfile1" ) << QStringLiteral( "error.txt" ) );
478
479 QPointer<QgsTestExternalStorageStoredContent> content1 = QgsTestExternalStorage::sCurrentStoredContent;
480 QVERIFY( content1 );
481
482 QVERIFY( !w.mLinkLabel->isVisible() );
483 QVERIFY( !w.mLinkEditButton->isVisible() );
484 QVERIFY( !w.mLineEdit->isVisible() );
485 QVERIFY( !w.mFileWidgetButton->isVisible() );
486 QVERIFY( w.mProgressLabel->isVisible() );
487 QVERIFY( w.mProgressBar->isVisible() );
488 QVERIFY( w.mCancelButton->isVisible() );
489 QVERIFY( w.mLinkLabel->text().isEmpty() );
490 QVERIFY( !messageBar.currentItem() );
491
492 QgsTestExternalStorage::sCurrentStoredContent->finish();
493
494 // second file is being stored
495 QVERIFY( content1 );
496 QVERIFY( QgsTestExternalStorage::sCurrentStoredContent );
497 QVERIFY( content1 != QgsTestExternalStorage::sCurrentStoredContent );
498
499 QVERIFY( !w.mLinkLabel->isVisible() );
500 QVERIFY( !w.mLinkEditButton->isVisible() );
501 QVERIFY( !w.mLineEdit->isVisible() );
502 QVERIFY( !w.mFileWidgetButton->isVisible() );
503 QVERIFY( w.mProgressLabel->isVisible() );
504 QVERIFY( w.mProgressBar->isVisible() );
505 QVERIFY( w.mCancelButton->isVisible() );
506 QVERIFY( w.mLinkLabel->text().isEmpty() );
507
508 // wait for first file content to be destroyed
509 connect( content1, &QObject::destroyed, &loop, &QEventLoop::quit );
510 loop.exec();
511 QVERIFY( !content1 );
512 QVERIFY( QgsTestExternalStorage::sCurrentStoredContent );
513
514 // error while storing second file
515 QgsTestExternalStorage::sCurrentStoredContent->error();
516
517 QVERIFY( useLink == w.mLinkLabel->isVisible() );
518 QVERIFY( useLink == w.mLinkEditButton->isVisible() );
519 if ( useLink ) QCOMPARE( w.mLinkEditButton->icon(), editIcon );
520 QVERIFY( useLink != w.mLineEdit->isVisible() );
521 QVERIFY( w.mFileWidgetButton->isVisible() );
522 QVERIFY( w.mFileWidgetButton->isEnabled() );
523 QVERIFY( !w.mProgressLabel->isVisible() );
524 QVERIFY( !w.mProgressBar->isVisible() );
525 QVERIFY( !w.mCancelButton->isVisible() );
526 if ( useLink )
527 QVERIFY( w.mLinkLabel->text().isEmpty() );
528 else
529 QVERIFY( w.mLineEdit->text().isEmpty() );
530 QVERIFY( messageBar.currentItem() );
531
532 // wait for second file content to be destroyed
533 connect( QgsTestExternalStorage::sCurrentStoredContent, &QObject::destroyed, &loop, &QEventLoop::quit );
534 loop.exec();
535 QVERIFY( !QgsTestExternalStorage::sCurrentStoredContent );
536 }
537
538
testStoringSeveralFilesCancel_data()539 void TestQgsExternalStorageFileWidget::testStoringSeveralFilesCancel_data()
540 {
541 QTest::addColumn<bool>( "useLink" );
542
543 QTest::newRow( "use link" ) << true;
544 QTest::newRow( "don't use link" ) << false;
545 }
546
testStoringSeveralFilesCancel()547 void TestQgsExternalStorageFileWidget::testStoringSeveralFilesCancel()
548 {
549 // test widget when storing several files with an external storage and user cancel operation
550 QEventLoop loop;
551 QFETCH( bool, useLink );
552
553 QgsExternalStorageFileWidget w;
554 w.show();
555
556 QIcon editIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) );
557
558 w.setStorageType( "test" );
559 w.setStorageUrlExpression( "'http://test.url.com/test/' || file_name(@selected_file_path)" );
560
561 // start edit mode
562 w.setUseLink( useLink );
563 w.setReadOnly( false );
564
565 QVERIFY( useLink == w.mLinkLabel->isVisible() );
566 QVERIFY( useLink == w.mLinkEditButton->isVisible() );
567 if ( useLink ) QCOMPARE( w.mLinkEditButton->icon(), editIcon );
568 QVERIFY( useLink != w.mLineEdit->isVisible() );
569 QVERIFY( w.mFileWidgetButton->isVisible() );
570 QVERIFY( w.mFileWidgetButton->isEnabled() );
571 QVERIFY( !w.mProgressLabel->isVisible() );
572 QVERIFY( !w.mProgressBar->isVisible() );
573 QVERIFY( !w.mCancelButton->isVisible() );
574
575 w.setSelectedFileNames( QStringList() << QStringLiteral( "myfile1" ) << QStringLiteral( "error.txt" ) );
576
577 QPointer<QgsTestExternalStorageStoredContent> content1 = QgsTestExternalStorage::sCurrentStoredContent;
578 QVERIFY( content1 );
579
580 QVERIFY( !w.mLinkLabel->isVisible() );
581 QVERIFY( !w.mLinkEditButton->isVisible() );
582 QVERIFY( !w.mLineEdit->isVisible() );
583 QVERIFY( !w.mFileWidgetButton->isVisible() );
584 QVERIFY( w.mProgressLabel->isVisible() );
585 QVERIFY( w.mProgressBar->isVisible() );
586 QVERIFY( w.mCancelButton->isVisible() );
587 QVERIFY( w.mLinkLabel->text().isEmpty() );
588
589 QgsTestExternalStorage::sCurrentStoredContent->finish();
590
591 // second file is being stored
592 QVERIFY( content1 );
593 QVERIFY( QgsTestExternalStorage::sCurrentStoredContent );
594 QVERIFY( content1 != QgsTestExternalStorage::sCurrentStoredContent );
595
596 QVERIFY( !w.mLinkLabel->isVisible() );
597 QVERIFY( !w.mLinkEditButton->isVisible() );
598 QVERIFY( !w.mLineEdit->isVisible() );
599 QVERIFY( !w.mFileWidgetButton->isVisible() );
600 QVERIFY( w.mProgressLabel->isVisible() );
601 QVERIFY( w.mProgressBar->isVisible() );
602 QVERIFY( w.mCancelButton->isVisible() );
603 QVERIFY( w.mLinkLabel->text().isEmpty() );
604
605 // wait for first file content to be destroyed
606 connect( content1, &QObject::destroyed, &loop, &QEventLoop::quit );
607 loop.exec();
608 QVERIFY( !content1 );
609 QVERIFY( QgsTestExternalStorage::sCurrentStoredContent );
610
611 // cancel while storing second file
612 QgsTestExternalStorage::sCurrentStoredContent->cancel();
613
614 QVERIFY( useLink == w.mLinkLabel->isVisible() );
615 QVERIFY( useLink == w.mLinkEditButton->isVisible() );
616 if ( useLink ) QCOMPARE( w.mLinkEditButton->icon(), editIcon );
617 QVERIFY( useLink != w.mLineEdit->isVisible() );
618 QVERIFY( w.mFileWidgetButton->isVisible() );
619 QVERIFY( w.mFileWidgetButton->isEnabled() );
620 QVERIFY( !w.mProgressLabel->isVisible() );
621 QVERIFY( !w.mProgressBar->isVisible() );
622 QVERIFY( !w.mCancelButton->isVisible() );
623 if ( useLink )
624 QVERIFY( w.mLinkLabel->text().isEmpty() );
625 else
626 QVERIFY( w.mLineEdit->text().isEmpty() );
627
628 // wait for second file content to be destroyed
629 connect( QgsTestExternalStorage::sCurrentStoredContent, &QObject::destroyed, &loop, &QEventLoop::quit );
630 loop.exec();
631 QVERIFY( !QgsTestExternalStorage::sCurrentStoredContent );
632 }
633
634
testStoringChangeFeature()635 void TestQgsExternalStorageFileWidget::testStoringChangeFeature()
636 {
637 // test widget with external storage to store files with different features
638
639 QgsExternalStorageFileWidget w;
640 w.show();
641
642 QgsFields fields;
643 fields.append( QgsField( QStringLiteral( "myfield" ), QVariant::String ) );
644
645 QgsFeature f1( fields );
646 f1.setAttribute( QStringLiteral( "myfield" ), QStringLiteral( "val1" ) );
647
648 w.setStorageType( "test" );
649 w.setStorageUrlExpression( "'http://test.url.com/' || attribute( @current_feature, 'myfield' )" );
650
651 QgsExpressionContext expressionContext;
652 expressionContext.appendScope( QgsExpressionContextUtils::formScope( f1 ) );
653 w.setExpressionContext( expressionContext );
654
655 w.setUseLink( false );
656 w.setReadOnly( false );
657
658 w.setSelectedFileNames( QStringList() << QStringLiteral( "blank" ) );
659
660 QgsTestExternalStorage::sCurrentStoredContent->finish();
661
662 QCOMPARE( w.mLineEdit->text(), QStringLiteral( "http://test.url.com/val1" ) );
663
664 QgsFeature f2( fields );
665 f2.setAttribute( QStringLiteral( "myfield" ), QStringLiteral( "val2" ) );
666
667 QgsExpressionContext expressionContext2;
668 expressionContext2.appendScope( QgsExpressionContextUtils::formScope( f2 ) );
669 w.setExpressionContext( expressionContext2 );
670
671 w.setSelectedFileNames( QStringList() << QStringLiteral( "blank" ) );
672
673 QgsTestExternalStorage::sCurrentStoredContent->finish();
674
675 QCOMPARE( w.mLineEdit->text(), QStringLiteral( "http://test.url.com/val2" ) );
676 }
677
testStoringBadExpression_data()678 void TestQgsExternalStorageFileWidget::testStoringBadExpression_data()
679 {
680 QTest::addColumn<bool>( "useLink" );
681
682 QTest::newRow( "use link" ) << true;
683 QTest::newRow( "don't use link" ) << false;
684 }
685
testStoringBadExpression()686 void TestQgsExternalStorageFileWidget::testStoringBadExpression()
687 {
688 // test widget when an external storage is used and the given expression if incorrect
689
690 QFETCH( bool, useLink );
691
692 QgsExternalStorageFileWidget w;
693 w.show();
694
695 QIcon editIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) );
696
697 w.setStorageType( "test" );
698 w.setStorageUrlExpression( "'http://test.url.com/test/' || file_name(@not_existing_variable)" );
699
700 // start edit mode
701 w.setUseLink( useLink );
702 w.setReadOnly( false );
703
704 QVERIFY( useLink == w.mLinkLabel->isVisible() );
705 QVERIFY( useLink == w.mLinkEditButton->isVisible() );
706 if ( useLink ) QCOMPARE( w.mLinkEditButton->icon(), editIcon );
707 QVERIFY( useLink != w.mLineEdit->isVisible() );
708 QVERIFY( w.mFileWidgetButton->isVisible() );
709 QVERIFY( w.mFileWidgetButton->isEnabled() );
710 QVERIFY( !w.mProgressLabel->isVisible() );
711 QVERIFY( !w.mProgressBar->isVisible() );
712 QVERIFY( !w.mCancelButton->isVisible() );
713
714 w.setSelectedFileNames( QStringList() << QStringLiteral( "myfile" ) );
715
716 QVERIFY( !QgsTestExternalStorage::sCurrentStoredContent );
717
718 QVERIFY( useLink == w.mLinkLabel->isVisible() );
719 QVERIFY( useLink == w.mLinkEditButton->isVisible() );
720 if ( useLink ) QCOMPARE( w.mLinkEditButton->icon(), editIcon );
721 QVERIFY( useLink != w.mLineEdit->isVisible() );
722 QVERIFY( w.mFileWidgetButton->isVisible() );
723 QVERIFY( w.mFileWidgetButton->isEnabled() );
724 QVERIFY( !w.mProgressLabel->isVisible() );
725 QVERIFY( !w.mProgressBar->isVisible() );
726 QVERIFY( !w.mCancelButton->isVisible() );
727
728 // link is not updated
729 QVERIFY( w.mLinkLabel->text().isEmpty() );
730 }
731
testStoringDirectory_data()732 void TestQgsExternalStorageFileWidget::testStoringDirectory_data()
733 {
734 QTest::addColumn<bool>( "useLink" );
735
736 QTest::newRow( "use link" ) << true;
737 QTest::newRow( "don't use link" ) << false;
738 }
739
testStoringDirectory()740 void TestQgsExternalStorageFileWidget::testStoringDirectory()
741 {
742 // test widget when storing a directory with an external storage
743 QEventLoop loop;
744 QFETCH( bool, useLink );
745
746 QgsExternalStorageFileWidget w;
747 w.show();
748
749 QIcon editIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) );
750
751 w.setStorageType( "test" );
752 w.setStorageUrlExpression( "'http://test.url.com/test/'" );
753 w.setStorageMode( QgsFileWidget::GetDirectory );
754
755 // start edit mode
756 w.setUseLink( useLink );
757 w.setReadOnly( false );
758
759 QVERIFY( useLink == w.mLinkLabel->isVisible() );
760 QVERIFY( useLink == w.mLinkEditButton->isVisible() );
761 if ( useLink ) QCOMPARE( w.mLinkEditButton->icon(), editIcon );
762 QVERIFY( useLink != w.mLineEdit->isVisible() );
763 QVERIFY( w.mFileWidgetButton->isVisible() );
764 QVERIFY( w.mFileWidgetButton->isEnabled() );
765 QVERIFY( !w.mProgressLabel->isVisible() );
766 QVERIFY( !w.mProgressBar->isVisible() );
767 QVERIFY( !w.mCancelButton->isVisible() );
768
769 w.setSelectedFileNames( QStringList() << "/tmp/mydir" );
770
771 QVERIFY( QgsTestExternalStorage::sCurrentStoredContent );
772
773 QVERIFY( !w.mLinkLabel->isVisible() );
774 QVERIFY( !w.mLinkEditButton->isVisible() );
775 QVERIFY( !w.mLineEdit->isVisible() );
776 QVERIFY( !w.mFileWidgetButton->isVisible() );
777 QVERIFY( w.mProgressLabel->isVisible() );
778 QVERIFY( w.mProgressBar->isVisible() );
779 QVERIFY( w.mCancelButton->isVisible() );
780 QVERIFY( w.mLinkLabel->text().isEmpty() );
781
782 QgsTestExternalStorage::sCurrentStoredContent->finish();
783
784 QVERIFY( useLink == w.mLinkLabel->isVisible() );
785 QVERIFY( useLink == w.mLinkEditButton->isVisible() );
786 if ( useLink ) QCOMPARE( w.mLinkEditButton->icon(), editIcon );
787 QVERIFY( useLink != w.mLineEdit->isVisible() );
788 QVERIFY( w.mFileWidgetButton->isVisible() );
789 QVERIFY( w.mFileWidgetButton->isEnabled() );
790 QVERIFY( !w.mProgressLabel->isVisible() );
791 QVERIFY( !w.mProgressBar->isVisible() );
792 QVERIFY( !w.mCancelButton->isVisible() );
793 if ( useLink )
794 QCOMPARE( w.mLinkLabel->text(), QStringLiteral( "<a href=\"http://test.url.com/test/mydir/\"></a>" ) );
795 else
796 QCOMPARE( w.mLineEdit->text(), QStringLiteral( "http://test.url.com/test/mydir/" ) );
797
798 // wait for file content to be destroyed
799 connect( QgsTestExternalStorage::sCurrentStoredContent, &QObject::destroyed, &loop, &QEventLoop::quit );
800 loop.exec();
801 QVERIFY( !QgsTestExternalStorage::sCurrentStoredContent );
802 }
803
testDragAndDrop()804 void TestQgsExternalStorageFileWidget::testDragAndDrop()
805 {
806 // test widget when drag and droping urls with an external storage
807 QEventLoop loop;
808
809 QgsExternalStorageFileWidget w;
810 w.show();
811
812 std::unique_ptr<QMimeData> mime( new QMimeData() );
813 mime->setUrls( QList<QUrl>() << QUrl::fromLocalFile( TEST_DATA_DIR + QStringLiteral( "/bug5598.shp" ) ) );
814
815 QIcon editIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) );
816
817 QVERIFY( !w.acceptDrops() );
818
819 w.setReadOnly( true );
820 w.setStorageType( "test" );
821 w.setStorageUrlExpression( "'http://test.url.com/test/' || file_name(@selected_file_path)" );
822 w.setStorageMode( QgsFileWidget::GetFile );
823 QVERIFY( !w.acceptDrops() );
824
825 // start edit mode
826 w.setUseLink( true );
827 w.setReadOnly( false );
828
829 QVERIFY( w.mLinkLabel->isVisible() );
830 QVERIFY( w.mLinkEditButton->isVisible() );
831 QCOMPARE( w.mLinkEditButton->icon(), editIcon );
832 QVERIFY( !w.mLineEdit->isVisible() );
833 QVERIFY( w.mFileWidgetButton->isVisible() );
834 QVERIFY( w.mFileWidgetButton->isEnabled() );
835 QVERIFY( !w.mProgressLabel->isVisible() );
836 QVERIFY( !w.mProgressBar->isVisible() );
837 QVERIFY( !w.mCancelButton->isVisible() );
838 QVERIFY( w.acceptDrops() );
839
840 std::unique_ptr<QDragEnterEvent> dragEvent( new QDragEnterEvent( QPoint( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
841 w.dragEnterEvent( dragEvent.get() );
842 QVERIFY( dragEvent->isAccepted() );
843
844 std::unique_ptr<QDropEvent> dropEvent( new QDropEvent( QPoint( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
845 w.dropEvent( dropEvent.get() );
846 QVERIFY( dropEvent->isAccepted() );
847
848 QVERIFY( QgsTestExternalStorage::sCurrentStoredContent );
849
850 QVERIFY( !w.mLinkLabel->isVisible() );
851 QVERIFY( !w.mLinkEditButton->isVisible() );
852 QVERIFY( !w.mLineEdit->isVisible() );
853 QVERIFY( !w.mFileWidgetButton->isVisible() );
854 QVERIFY( w.mProgressLabel->isVisible() );
855 QVERIFY( w.mProgressBar->isVisible() );
856 QVERIFY( w.mCancelButton->isVisible() );
857 QVERIFY( w.mLinkLabel->text().isEmpty() );
858
859 QgsTestExternalStorage::sCurrentStoredContent->finish();
860
861 QVERIFY( w.mLinkLabel->isVisible() );
862 QVERIFY( w.mLinkEditButton->isVisible() );
863 QCOMPARE( w.mLinkEditButton->icon(), editIcon );
864 QVERIFY( !w.mLineEdit->isVisible() );
865 QVERIFY( w.mFileWidgetButton->isVisible() );
866 QVERIFY( w.mFileWidgetButton->isEnabled() );
867 QVERIFY( !w.mProgressLabel->isVisible() );
868 QVERIFY( !w.mProgressBar->isVisible() );
869 QVERIFY( !w.mCancelButton->isVisible() );
870 QCOMPARE( w.mLinkLabel->text(), QStringLiteral( "<a href=\"http://test.url.com/test/bug5598.shp\">bug5598.shp</a>" ) );
871
872 // wait for file content to be destroyed
873 connect( QgsTestExternalStorage::sCurrentStoredContent, &QObject::destroyed, &loop, &QEventLoop::quit );
874 loop.exec();
875 QVERIFY( !QgsTestExternalStorage::sCurrentStoredContent );
876 }
877
878
879 QGSTEST_MAIN( TestQgsExternalStorageFileWidget )
880 #include "testqgsexternalstoragefilewidget.moc"
881