1 /***************************************************************************
2 testqgsfilewidget.cpp
3 --------------------------------------
4 Date : December 2014
5 Copyright : (C) 2014 Nyall Dawson
6 Email : nyall dot dawson at gmail 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 "qgsfilewidget.h"
20 #include "qgsmimedatautils.h"
21 #include "qgsdataitem.h"
22 #include "qgsbrowsermodel.h"
23 #include "qgslayeritem.h"
24 #include "qgsdirectoryitem.h"
25 #include <memory>
26
27 class TestQgsFileWidget: public QObject
28 {
29 Q_OBJECT
30 private slots:
31 void initTestCase(); // will be called before the first testfunction is executed.
32 void cleanupTestCase(); // will be called after the last testfunction was executed.
33 void init(); // will be called before each testfunction is executed.
34 void cleanup(); // will be called after every testfunction.
35 void relativePath();
36 void toUrl();
37 void testDroppedFiles();
38 void testMultipleFiles();
39 void testSplitFilePaths();
40 };
41
initTestCase()42 void TestQgsFileWidget::initTestCase()
43 {
44 }
45
cleanupTestCase()46 void TestQgsFileWidget::cleanupTestCase()
47 {
48 }
49
init()50 void TestQgsFileWidget::init()
51 {
52 }
53
cleanup()54 void TestQgsFileWidget::cleanup()
55 {
56 }
57
relativePath()58 void TestQgsFileWidget::relativePath()
59 {
60 QgsFileWidget *w = new QgsFileWidget();
61 w->setDefaultRoot( QStringLiteral( "/home/test" ) );
62 w->setRelativeStorage( QgsFileWidget::Absolute );
63 QCOMPARE( w->relativePath( "/home/test2/file1.ext", true ), QString( "/home/test2/file1.ext" ) );
64 QCOMPARE( w->relativePath( "/home/test2/file2.ext", false ), QString( "/home/test2/file2.ext" ) );
65 w->setRelativeStorage( QgsFileWidget::RelativeDefaultPath );
66 QCOMPARE( w->relativePath( "/home/test2/file3.ext", true ), QString( "../test2/file3.ext" ) );
67 QCOMPARE( w->relativePath( "../test2/file4.ext", true ), QString( "../test2/file4.ext" ) );
68 QCOMPARE( w->relativePath( "/home/test2/file5.ext", false ), QString( "/home/test2/file5.ext" ) );
69 QCOMPARE( w->relativePath( "../test2/file6.ext", false ), QString( "/home/test2/file6.ext" ) );
70 }
71
toUrl()72 void TestQgsFileWidget::toUrl()
73 {
74 QgsFileWidget *w = new QgsFileWidget();
75 w->setDefaultRoot( QStringLiteral( "/home/test" ) );
76 w->setRelativeStorage( QgsFileWidget::Absolute );
77 w->setFullUrl( true );
78 QCOMPARE( w->toUrl( "/home/test2/file1.ext" ), QString( "<a href=\"file:///home/test2/file1.ext\">/home/test2/file1.ext</a>" ) );
79 w->setFullUrl( false );
80 QCOMPARE( w->toUrl( "/home/test2/file2.ext" ), QString( "<a href=\"file:///home/test2/file2.ext\">file2.ext</a>" ) );
81 w->setRelativeStorage( QgsFileWidget::RelativeDefaultPath );
82 w->setFullUrl( true );
83 QCOMPARE( w->toUrl( "/home/test2/file3.ext" ), QString( "<a href=\"file:///home/test2/file3.ext\">/home/test2/file3.ext</a>" ) );
84 QCOMPARE( w->toUrl( "../test2/file4.ext" ), QString( "<a href=\"file:///home/test2/file4.ext\">../test2/file4.ext</a>" ) );
85 w->setFullUrl( false );
86 QCOMPARE( w->toUrl( "/home/test2/file5.ext" ), QString( "<a href=\"file:///home/test2/file5.ext\">file5.ext</a>" ) );
87 QCOMPARE( w->toUrl( "../test2/file6.ext" ), QString( "<a href=\"file:///home/test2/file6.ext\">file6.ext</a>" ) );
88 }
89
testDroppedFiles()90 void TestQgsFileWidget::testDroppedFiles()
91 {
92 QgsFileWidget *w = new QgsFileWidget();
93 w->setStorageMode( QgsFileWidget::GetFile );
94
95 // should not accept dropped folders
96 std::unique_ptr< QMimeData > mime( new QMimeData() );
97 mime->setUrls( QList<QUrl>() << QUrl::fromLocalFile( TEST_DATA_DIR ) );
98 std::unique_ptr< QDropEvent > event( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
99
100 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
101 QVERIFY( w->lineEdit()->text().isEmpty() );
102
103 // but dropped files should be fine
104 mime->setUrls( QList<QUrl>() << QUrl::fromLocalFile( TEST_DATA_DIR + QStringLiteral( "/bug5598.shp" ) ) );
105 event.reset( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
106 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
107 QCOMPARE( w->lineEdit()->text(), QString( TEST_DATA_DIR + QStringLiteral( "/bug5598.shp" ) ) );
108
109 // also should support files dragged from browser
110 mime->setUrls( QList<QUrl>() );
111 QgsMimeDataUtils::Uri uri;
112 uri.uri = TEST_DATA_DIR + QStringLiteral( "/mesh/quad_and_triangle.2dm" );
113 QgsMimeDataUtils::UriList uriList;
114 uriList << uri;
115 mime.reset( QgsMimeDataUtils::encodeUriList( uriList ) );
116 event.reset( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
117 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
118 QCOMPARE( w->lineEdit()->text(), QString( TEST_DATA_DIR + QStringLiteral( "/mesh/quad_and_triangle.2dm" ) ) );
119
120 QgsBrowserModel m;
121 m.initialize();
122 QgsLayerItem *layerItem = new QgsLayerItem( nullptr, QStringLiteral( "Test" ), QString(), TEST_DATA_DIR + QStringLiteral( "/mesh/quad_and_triangle.txt" ), Qgis::BrowserLayerType::Mesh, "mdal" );
123 m.driveItems().first()->addChild( layerItem );
124 mime.reset( m.mimeData( QModelIndexList() << m.findItem( layerItem ) ) );
125 event.reset( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
126 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
127 QCOMPARE( w->lineEdit()->text(), QString( QString( TEST_DATA_DIR ) + QStringLiteral( "/mesh/quad_and_triangle.txt" ) ) );
128
129 // plain text should also be permitted
130 mime = std::make_unique< QMimeData >();
131 mime->setText( TEST_DATA_DIR + QStringLiteral( "/mesh/quad_and_triangle.2dm" ) );
132 event.reset( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
133 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
134 QCOMPARE( w->lineEdit()->text(), QString( TEST_DATA_DIR + QStringLiteral( "/mesh/quad_and_triangle.2dm" ) ) );
135
136 mime.reset( new QMimeData() );
137 mime->setUrls( QList<QUrl>() << QUrl::fromLocalFile( TEST_DATA_DIR + QStringLiteral( "/bug5598.shp" ) ) );
138 event.reset( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
139 // with file filter
140 w->setFilter( QStringLiteral( "Data (*.shp)" ) );
141 w->setFilePath( QString() );
142 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
143 QCOMPARE( w->lineEdit()->text(), QString( TEST_DATA_DIR + QStringLiteral( "/bug5598.shp" ) ) );
144 w->setFilePath( QString() );
145 // should be rejected, not compatible with filter
146 mime->setUrls( QList<QUrl>() << QUrl::fromLocalFile( TEST_DATA_DIR + QStringLiteral( "/encoded_html.html" ) ) );
147 event.reset( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
148 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
149 QVERIFY( w->lineEdit()->text().isEmpty() );
150 // new filter, should be allowed now
151 w->setFilter( QStringLiteral( "Data (*.shp);;HTML (*.HTML)" ) );
152 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
153 QCOMPARE( w->lineEdit()->text(), QString( TEST_DATA_DIR + QStringLiteral( "/encoded_html.html" ) ) );
154
155 //try with wildcard filter
156 w->setFilter( QStringLiteral( "All files (*.*);;Data (*.shp);;HTML (*.HTML)" ) );
157 mime->setUrls( QList<QUrl>() << QUrl::fromLocalFile( TEST_DATA_DIR + QStringLiteral( "/bug5598.prj" ) ) );
158 event.reset( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
159 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
160 QCOMPARE( w->lineEdit()->text(), QString( TEST_DATA_DIR + QStringLiteral( "/bug5598.prj" ) ) );
161
162 // try with folders
163 w->setStorageMode( QgsFileWidget::GetDirectory );
164 w->setFilePath( QString() );
165 // dropping a file should accept only the folder containing that file
166 mime->setUrls( QList<QUrl>() << QUrl::fromLocalFile( TEST_DATA_DIR + QStringLiteral( "/mesh/quad_and_triangle.2dm" ) ) );
167 event.reset( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
168 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
169 QCOMPARE( w->lineEdit()->text(), QString( QString( TEST_DATA_DIR ) + QStringLiteral( "/mesh" ) ) );
170
171 // but dropping a folder should work
172 mime->setUrls( QList<QUrl>() << QUrl::fromLocalFile( TEST_DATA_DIR ) );
173 event.reset( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
174 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
175 QCOMPARE( w->lineEdit()->text(), QString( TEST_DATA_DIR ) );
176
177 // integration test - dropping a directory item's mime data
178 QgsDirectoryItem *dirItem = new QgsDirectoryItem( nullptr, QStringLiteral( "Test" ), TEST_DATA_DIR + QStringLiteral( "/mesh" ) );
179 m.driveItems().first()->addChild( dirItem );
180 mime.reset( m.mimeData( QModelIndexList() << m.findItem( dirItem ) ) );
181 event.reset( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
182 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
183 QCOMPARE( w->lineEdit()->text(), QString( QString( TEST_DATA_DIR ) + QStringLiteral( "/mesh" ) ) );
184 }
185
testMultipleFiles()186 void TestQgsFileWidget::testMultipleFiles()
187 {
188 QgsFileWidget *w = new QgsFileWidget();
189 w->setStorageMode( QgsFileWidget::GetMultipleFiles );
190
191 std::unique_ptr< QMimeData > mime( new QMimeData() );
192 mime->setUrls( QList<QUrl>() << QUrl::fromLocalFile( TEST_DATA_DIR + QStringLiteral( "/bug5598.shp" ) )
193 << QUrl::fromLocalFile( TEST_DATA_DIR + QStringLiteral( "/elev.gpx" ) ) );
194 const std::unique_ptr< QDropEvent > event( new QDropEvent( QPointF( 1, 1 ), Qt::CopyAction, mime.get(), Qt::LeftButton, Qt::NoModifier ) );
195
196 qobject_cast< QgsFileDropEdit * >( w->lineEdit() )->dropEvent( event.get() );
197 QCOMPARE( w->lineEdit()->text(), QStringLiteral( "\"%1\" \"%2\"" ).arg( TEST_DATA_DIR + QStringLiteral( "/bug5598.shp" ) )
198 .arg( TEST_DATA_DIR + QStringLiteral( "/elev.gpx" ) ) );
199 }
200
201
testSplitFilePaths()202 void TestQgsFileWidget::testSplitFilePaths()
203 {
204 const QString path = QString( TEST_DATA_DIR + QStringLiteral( "/bug5598.shp" ) );
205 QCOMPARE( QgsFileWidget::splitFilePaths( QStringLiteral( "\"%1\" \"%1\"" ).arg( path ) ), QStringList() << path << path );
206 QCOMPARE( QgsFileWidget::splitFilePaths( QStringLiteral( "\"%1\" \"%1\"" ).arg( path ) ), QStringList() << path << path );
207 QCOMPARE( QgsFileWidget::splitFilePaths( QStringLiteral( " \"%1\" \"%1\"" ).arg( path ) ), QStringList() << path << path );
208 QCOMPARE( QgsFileWidget::splitFilePaths( QStringLiteral( " \"%1\" \"%1\" " ).arg( path ) ), QStringList() << path << path );
209 QCOMPARE( QgsFileWidget::splitFilePaths( QStringLiteral( "\"%1\" \"%1\" " ).arg( path ) ), QStringList() << path << path );
210 QCOMPARE( QgsFileWidget::splitFilePaths( path ), QStringList() << path );
211 }
212
213 QGSTEST_MAIN( TestQgsFileWidget )
214 #include "testqgsfilewidget.moc"
215