Skip to content

Commit 9047416

Browse files
author
jef
committed
[FEATURE] allow managing missing layers in a list
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@15353 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 80152af commit 9047416

File tree

4 files changed

+530
-0
lines changed

4 files changed

+530
-0
lines changed

src/app/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ SET(QGIS_APP_SRCS
9292
qgsvectorlayerproperties.cpp
9393
qgsquerybuilder.cpp
9494
qgshighlight.cpp
95+
qgshandlebadlayers.cpp
9596

9697
qgsmanageconnectionsdialog.cpp
9798

@@ -218,6 +219,7 @@ SET (QGIS_APP_MOC_HDRS
218219
qgsuniquevaluedialog.h
219220
qgsvectorlayerproperties.h
220221
qgswmssourceselect.h
222+
qgshandlebadlayers.h
221223

222224
composer/qgsattributeselectiondialog.h
223225
composer/qgscomposer.h

src/app/qgshandlebadlayers.cpp

Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
1+
/***************************************************************************
2+
qgshandlebadlayers.cpp - description
3+
-------------------
4+
begin : Sat 5 Mar 2011
5+
copyright : (C) 2011 by Juergen E. Fischer, norBIT GmbH
6+
email : jef at norbit dot de
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
/* $Id$ */
18+
19+
#include "qgshandlebadlayers.h"
20+
#include "qgisapp.h"
21+
#include "qgisgui.h"
22+
#include "qgsdatasourceuri.h"
23+
#include "qgslogger.h"
24+
#include "qgsrasterlayer.h"
25+
#include "qgsproviderregistry.h"
26+
27+
#include <QDomDocument>
28+
#include <QDomElement>
29+
#include <QPushButton>
30+
#include <QMessageBox>
31+
32+
QgsHandleBadLayersHandler::QgsHandleBadLayersHandler()
33+
{
34+
}
35+
36+
void QgsHandleBadLayersHandler::handleBadLayers( QList<QDomNode> layers, QDomDocument projectDom )
37+
{
38+
QApplication::setOverrideCursor( Qt::ArrowCursor );
39+
QgsHandleBadLayers *dialog = new QgsHandleBadLayers( layers, projectDom );
40+
dialog->exec();
41+
delete dialog;
42+
QApplication::restoreOverrideCursor();
43+
}
44+
45+
46+
QgsHandleBadLayers::QgsHandleBadLayers( const QList<QDomNode> &layers, const QDomDocument &projectDom )
47+
: QDialog( QgisApp::instance() )
48+
, mLayers( layers )
49+
{
50+
setupUi( this );
51+
52+
53+
mVectorFileFilter = QgsProviderRegistry::instance()->fileVectorFilters();
54+
QgsRasterLayer::buildSupportedRasterFileFilter( mRasterFileFilter );
55+
56+
mBrowseButton = new QPushButton( tr( "Browse" ) );
57+
buttonBox->addButton( mBrowseButton, QDialogButtonBox::ActionRole );
58+
mBrowseButton->setDisabled( true );
59+
60+
connect( mLayerList, SIGNAL( itemSelectionChanged() ), this, SLOT( selectionChanged() ) );
61+
connect( mLayerList, SIGNAL( itemChanged( QTableWidgetItem * ) ), this, SLOT( itemChanged( QTableWidgetItem * ) ) );
62+
connect( mLayerList, SIGNAL( cellDoubleClicked( int, int ) ), this, SLOT( cellDoubleClicked( int, int ) ) );
63+
connect( mBrowseButton, SIGNAL( clicked() ), this, SLOT( browseClicked() ) );
64+
65+
mLayerList->clear();
66+
mLayerList->setSortingEnabled( true );
67+
mLayerList->setSelectionBehavior( QAbstractItemView::SelectRows );
68+
mLayerList->setColumnCount( 5 );
69+
70+
mLayerList->setHorizontalHeaderLabels( QStringList()
71+
<< tr( "Layer name" )
72+
<< tr( "Type" )
73+
<< tr( "Provider" )
74+
<< tr( "New file" )
75+
<< tr( "New datasource" )
76+
);
77+
78+
int j = 0;
79+
for ( int i = 0; i < mLayers.size(); i++ )
80+
{
81+
const QDomNode &node = mLayers[i];
82+
83+
QString name = node.namedItem( "layername" ).toElement().text();
84+
QString type = node.toElement().attribute( "type" );
85+
QString datasource = node.namedItem( "datasource" ).toElement().text();
86+
QString provider;
87+
88+
QString filename = datasource;
89+
90+
if ( type == "vector" )
91+
{
92+
provider = node.namedItem( "provider" ).toElement().text();
93+
if ( provider == "spatialite" )
94+
{
95+
QgsDataSourceURI uri( datasource );
96+
filename = uri.database();
97+
}
98+
else if ( provider == "ogr" )
99+
{
100+
QStringList theURIParts = datasource.split( "|" );
101+
filename = theURIParts[0];
102+
}
103+
else if ( provider == "delimitedtext" )
104+
{
105+
QStringList theURIParts = datasource.split( "?" );
106+
filename = theURIParts[0];
107+
}
108+
else if ( provider == "postgres" || provider == "sqlanywhere" )
109+
{
110+
continue;
111+
}
112+
}
113+
else
114+
{
115+
provider = tr( "none" );
116+
}
117+
118+
QgsDebugMsg( QString( "name=%1 type=%2 provider=%3 filename=%4 datasource='%5'" )
119+
.arg( name )
120+
.arg( type )
121+
.arg( provider )
122+
.arg( filename )
123+
.arg( datasource ) );
124+
125+
mLayerList->setRowCount( j + 1 );
126+
127+
QTableWidgetItem *item;
128+
129+
item = new QTableWidgetItem( name );
130+
item->setData( Qt::UserRole + 0, i );
131+
item->setFlags( item->flags() & ~Qt::ItemIsEditable );
132+
mLayerList->setItem( j, 0, item );
133+
134+
item = new QTableWidgetItem( type );
135+
item->setFlags( item->flags() & ~Qt::ItemIsEditable );
136+
mLayerList->setItem( j, 1, item );
137+
138+
item = new QTableWidgetItem( provider );
139+
item->setFlags( item->flags() & ~Qt::ItemIsEditable );
140+
mLayerList->setItem( j, 2, item );
141+
142+
item = new QTableWidgetItem( filename );
143+
mLayerList->setItem( j, 3, item );
144+
145+
item = new QTableWidgetItem( datasource );
146+
item->setFlags( item->flags() & ~Qt::ItemIsEditable );
147+
mLayerList->setItem( j, 4, item );
148+
149+
j++;
150+
}
151+
152+
mLayerList->resizeColumnsToContents();
153+
}
154+
155+
QgsHandleBadLayers::~QgsHandleBadLayers()
156+
{
157+
}
158+
159+
void QgsHandleBadLayers::itemChanged( QTableWidgetItem *item )
160+
{
161+
if ( item->column() != 3 )
162+
return;
163+
164+
QFileInfo fi( item->text() );
165+
166+
item->setForeground( fi.exists() ? QBrush( Qt::green ) : QBrush( Qt::red ) );
167+
}
168+
169+
void QgsHandleBadLayers::cellDoubleClicked( int row, int column )
170+
{
171+
if ( column != 3 || !mBrowseButton->isEnabled() )
172+
return;
173+
174+
mBrowseButton->click();
175+
}
176+
177+
void QgsHandleBadLayers::selectionChanged()
178+
{
179+
QgsDebugMsg( "entered." );
180+
181+
mRows.clear();
182+
183+
foreach( QTableWidgetItem *item, mLayerList->selectedItems() )
184+
{
185+
if ( item->column() != 0 )
186+
continue;
187+
188+
mRows << item->row();
189+
}
190+
191+
mBrowseButton->setEnabled( mRows.size() > 0 );
192+
}
193+
194+
void QgsHandleBadLayers::browseClicked()
195+
{
196+
QgsDebugMsg( "entered." );
197+
198+
if ( mRows.size() == 1 )
199+
{
200+
QString memoryQualifier;
201+
QString fileFilter;
202+
int idx = mLayerList->item( mRows[0], 0 )->data( Qt::UserRole ).toInt();
203+
QTableWidgetItem *fileItem = mLayerList->item( mRows[0], 3 );
204+
205+
if ( mLayers[ idx ].toElement().attribute( "type" ) == "vector" )
206+
{
207+
memoryQualifier = "lastVectorFileFilter";
208+
fileFilter = mVectorFileFilter;
209+
}
210+
else
211+
{
212+
memoryQualifier = "lastRasterFileFilter";
213+
fileFilter = mRasterFileFilter;
214+
}
215+
216+
QStringList selectedFiles;
217+
QString enc;
218+
QString title = tr( "Select file to replace '%1'" ).arg( fileItem->text() );
219+
220+
QgisGui::openFilesRememberingFilter( memoryQualifier, fileFilter, selectedFiles, enc, title );
221+
222+
if ( selectedFiles.size() != 1 )
223+
{
224+
QMessageBox::information( this, title, tr( "Please select exactly one file." ) );
225+
return;
226+
}
227+
228+
fileItem->setText( selectedFiles[0] );
229+
}
230+
else if ( mRows.size() > 1 )
231+
{
232+
QStringList selectedFiles;
233+
QString enc;
234+
QString title = tr( "Select new directory of selected files" );
235+
236+
QgisGui::openFilesRememberingFilter( "missingDirectory", tr( "All files (*)" ), selectedFiles, enc, title );
237+
238+
if ( selectedFiles.isEmpty() )
239+
{
240+
return;
241+
}
242+
243+
QFileInfo path( selectedFiles[0] );
244+
if ( !path.exists() )
245+
{
246+
return;
247+
}
248+
249+
foreach( int i, mRows )
250+
{
251+
QTableWidgetItem *fileItem = mLayerList->item( i, 3 );
252+
253+
QFileInfo fi( fileItem->text() );
254+
fi.setFile( path.dir(), fi.fileName() );
255+
256+
if ( !fi.exists() )
257+
continue;
258+
259+
fileItem->setText( fi.absoluteFilePath() );
260+
}
261+
}
262+
}
263+
264+
void QgsHandleBadLayers::apply()
265+
{
266+
QgsDebugMsg( "entered." );
267+
for ( int i = 0; i < mLayerList->rowCount(); i++ )
268+
{
269+
int idx = mLayerList->item( i, 0 )->data( Qt::UserRole ).toInt();
270+
QDomNode &node = const_cast<QDomNode &>( mLayers[ idx ] );
271+
272+
QString type = mLayerList->item( i, 1 )->text();
273+
QString provider = mLayerList->item( i, 2 )->text();
274+
QTableWidgetItem *fileItem = mLayerList->item( i, 3 );
275+
QString datasource = mLayerList->item( i, 4 )->text();
276+
277+
QString filename = fileItem->text();
278+
if ( !QFileInfo( filename ).exists() )
279+
{
280+
continue;
281+
}
282+
283+
if ( type == "vector" )
284+
{
285+
if ( provider == "spatialite" )
286+
{
287+
QgsDataSourceURI uri( datasource );
288+
uri.setDatabase( filename );
289+
datasource = uri.uri();
290+
}
291+
else if ( provider == "ogr" )
292+
{
293+
QStringList theURIParts = datasource.split( "|" );
294+
theURIParts[0] = filename;
295+
datasource = theURIParts.join( "|" );
296+
}
297+
else if ( provider == "delimitedtext" )
298+
{
299+
QStringList theURIParts = datasource.split( "?" );
300+
theURIParts[0] = filename;
301+
datasource = theURIParts.join( "?" );
302+
}
303+
}
304+
else
305+
{
306+
datasource = filename;
307+
}
308+
309+
node.namedItem( "datasource" ).toElement().firstChild().toText().setData( datasource );
310+
if ( QgsProject::instance()->read( node ) )
311+
{
312+
mLayerList->removeRow( i-- );
313+
}
314+
else
315+
{
316+
fileItem->setForeground( QBrush( Qt::red ) );
317+
}
318+
}
319+
}
320+
321+
void QgsHandleBadLayers::accept()
322+
{
323+
QgsDebugMsg( "entered." );
324+
apply();
325+
326+
if ( mLayerList->rowCount() > 0 &&
327+
QMessageBox::warning( this,
328+
tr( "Unhandled layer will be lost." ),
329+
tr( "There are still %n unhandled layer(s), that will be lost if you closed now.",
330+
"unhandled layers",
331+
mLayerList->rowCount() ),
332+
QMessageBox::Ok | QMessageBox::Cancel,
333+
QMessageBox::Cancel ) == QMessageBox::Cancel )
334+
{
335+
return;
336+
}
337+
338+
QDialog::accept();
339+
}
340+
341+
void QgsHandleBadLayers::rejected()
342+
{
343+
QgsDebugMsg( "entered." );
344+
345+
if ( mLayerList->rowCount() > 0 &&
346+
QMessageBox::warning( this,
347+
tr( "Unhandled layer will be lost." ),
348+
tr( "There are still %n unhandled layer(s), that will be lost if you closed now.",
349+
"unhandled layers",
350+
mLayerList->rowCount() ),
351+
QMessageBox::Ok | QMessageBox::Cancel,
352+
QMessageBox::Cancel ) == QMessageBox::Cancel )
353+
{
354+
return;
355+
}
356+
357+
QDialog::reject();
358+
}

0 commit comments

Comments
 (0)