Skip to content

Commit f155030

Browse files
committedJul 31, 2017
[FEATURE] Add the possibility to save/open a project in .qgz
1 parent 15ed34c commit f155030

File tree

6 files changed

+144
-23
lines changed

6 files changed

+144
-23
lines changed
 

‎python/core/qgsproject.sip

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,23 @@ Returns the number of registered layers.
630630
:rtype: bool
631631
%End
632632

633+
bool zip();
634+
%Docstring
635+
:rtype: bool
636+
%End
637+
638+
QString zipFileName() const;
639+
%Docstring
640+
:rtype: str
641+
%End
642+
643+
void setZipFileName( const QString &filename );
644+
645+
bool unzipped() const;
646+
%Docstring
647+
:rtype: bool
648+
%End
649+
633650

634651
QList<QgsMapLayer *> addMapLayers( const QList<QgsMapLayer *> &mapLayers /Transfer/,
635652
bool addToLegend = true);

‎src/app/qgisapp.cpp

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5235,10 +5235,12 @@ void QgisApp::fileOpen()
52355235
// Retrieve last used project dir from persistent settings
52365236
QgsSettings settings;
52375237
QString lastUsedDir = settings.value( QStringLiteral( "UI/lastProjectDir" ), QDir::homePath() ).toString();
5238+
const QString qgs_ext = tr( "QGIS files" ) + " (*.qgs *.QGS)";
5239+
const QString zip_ext = tr( "QGZ files" ) + " (*.qgz)";
52385240
QString fullPath = QFileDialog::getOpenFileName( this,
52395241
tr( "Choose a QGIS project file to open" ),
52405242
lastUsedDir,
5241-
tr( "QGIS files" ) + " (*.qgs *.QGS)" );
5243+
qgs_ext + ";;" + zip_ext );
52425244
if ( fullPath.isNull() )
52435245
{
52445246
return;
@@ -5271,6 +5273,8 @@ void QgisApp::enableProjectMacros()
52715273
*/
52725274
bool QgisApp::addProject( const QString &projectFile )
52735275
{
5276+
bool zip = ( QFileInfo( projectFile ).suffix() == "qgz" ) ? true : false;
5277+
52745278
// close the previous opened project if any
52755279
closeProject();
52765280

@@ -5283,7 +5287,17 @@ bool QgisApp::addProject( const QString &projectFile )
52835287
bool autoSetupOnFirstLayer = mLayerTreeCanvasBridge->autoSetupOnFirstLayer();
52845288
mLayerTreeCanvasBridge->setAutoSetupOnFirstLayer( false );
52855289

5286-
if ( !QgsProject::instance()->read( projectFile ) )
5290+
bool readOk = false;
5291+
if ( zip )
5292+
{
5293+
readOk = QgsProject::instance()->unzip( projectFile );
5294+
}
5295+
else
5296+
{
5297+
readOk = QgsProject::instance()->read( projectFile );
5298+
}
5299+
5300+
if ( !readOk && !zip )
52875301
{
52885302
QString backupFile = projectFile + "~";
52895303
QString loadBackupPrompt;
@@ -5417,34 +5431,47 @@ bool QgisApp::fileSave()
54175431
// that the project file name is reset to null in fileNew()
54185432
QFileInfo fullPath;
54195433

5420-
if ( QgsProject::instance()->fileName().isNull() )
5434+
if ( QgsProject::instance()->fileName().isNull() && QgsProject::instance()->zipFileName().isNull() )
54215435
{
54225436
// Retrieve last used project dir from persistent settings
54235437
QgsSettings settings;
54245438
QString lastUsedDir = settings.value( QStringLiteral( "UI/lastProjectDir" ), QDir::homePath() ).toString();
54255439

5440+
const QString qgs_ext = tr( "QGIS files" ) + " (*.qgs)";
5441+
const QString zip_ext = tr( "QGZ files" ) + " (*.qgz)";
5442+
QString filter;
54265443
QString path = QFileDialog::getSaveFileName(
54275444
this,
54285445
tr( "Choose a QGIS project file" ),
54295446
lastUsedDir + '/' + QgsProject::instance()->title(),
5430-
tr( "QGIS files" ) + " (*.qgs *.QGS)" );
5447+
qgs_ext + ";;" + zip_ext, &filter );
54315448
if ( path.isEmpty() )
54325449
return false;
54335450

54345451
fullPath.setFile( path );
54355452

54365453
// make sure we have the .qgs extension in the file name
5437-
if ( "qgs" != fullPath.suffix().toLower() )
5454+
if ( filter == zip_ext )
54385455
{
5439-
fullPath.setFile( fullPath.filePath() + ".qgs" );
5440-
}
5456+
if ( "qgz" != fullPath.suffix().toLower() )
5457+
fullPath.setFile( fullPath.filePath() + ".qgz" );
54415458

5459+
QgsProject::instance()->setZipFileName( fullPath.filePath() );
5460+
}
5461+
else
5462+
{
5463+
if ( "qgs" != fullPath.suffix().toLower() )
5464+
fullPath.setFile( fullPath.filePath() + ".qgs" );
54425465

5443-
QgsProject::instance()->setFileName( fullPath.filePath() );
5466+
QgsProject::instance()->setFileName( fullPath.filePath() );
5467+
}
54445468
}
54455469
else
54465470
{
54475471
QFileInfo fi( QgsProject::instance()->fileName() );
5472+
if ( QgsProject::instance()->unzipped() )
5473+
fi.setFile( QgsProject::instance()->zipFileName() );
5474+
54485475
fullPath = fi.absoluteFilePath();
54495476
if ( fi.exists() && !mProjectLastModified.isNull() && mProjectLastModified != fi.lastModified() )
54505477
{
@@ -5468,20 +5495,34 @@ bool QgisApp::fileSave()
54685495
}
54695496
}
54705497

5471-
if ( QgsProject::instance()->write() )
5498+
bool writeOk = false;
5499+
QString writtenFileName;
5500+
5501+
if ( QgsProject::instance()->unzipped() )
5502+
{
5503+
writeOk = QgsProject::instance()->zip();
5504+
writtenFileName = QgsProject::instance()->zipFileName();
5505+
}
5506+
else
5507+
{
5508+
writeOk = QgsProject::instance()->write();
5509+
writtenFileName = QgsProject::instance()->fileName();
5510+
}
5511+
5512+
if ( writeOk )
54725513
{
54735514
setTitleBarText_( *this ); // update title bar
5474-
mStatusBar->showMessage( tr( "Saved project to: %1" ).arg( QDir::toNativeSeparators( QgsProject::instance()->fileName() ) ), 5000 );
5515+
mStatusBar->showMessage( tr( "Saved project to: %1" ).arg( QDir::toNativeSeparators( writtenFileName ) ), 5000 );
54755516

54765517
saveRecentProjectPath( fullPath.filePath() );
54775518

5478-
QFileInfo fi( QgsProject::instance()->fileName() );
5519+
QFileInfo fi( writtenFileName );
54795520
mProjectLastModified = fi.lastModified();
54805521
}
54815522
else
54825523
{
54835524
QMessageBox::critical( this,
5484-
tr( "Unable to save project %1" ).arg( QDir::toNativeSeparators( QgsProject::instance()->fileName() ) ),
5525+
tr( "Unable to save project %1" ).arg( QDir::toNativeSeparators( writtenFileName ) ),
54855526
QgsProject::instance()->error() );
54865527
return false;
54875528
}
@@ -5501,29 +5542,41 @@ void QgisApp::fileSaveAs()
55015542
QgsSettings settings;
55025543
QString lastUsedDir = settings.value( QStringLiteral( "UI/lastProjectDir" ), QDir::homePath() ).toString();
55035544

5545+
const QString qgs_ext = tr( "QGIS files" ) + " (*.qgs *.QGS)";
5546+
const QString zip_ext = tr( "QGZ files" ) + " (*.qgz)";
5547+
QString filter;
55045548
QString path = QFileDialog::getSaveFileName( this,
55055549
tr( "Choose a file name to save the QGIS project file as" ),
55065550
lastUsedDir + '/' + QgsProject::instance()->title(),
5507-
tr( "QGIS files" ) + " (*.qgs *.QGS)" );
5551+
qgs_ext + ";;" + zip_ext, &filter );
55085552
if ( path.isEmpty() )
55095553
return;
55105554

55115555
QFileInfo fullPath( path );
55125556

55135557
settings.setValue( QStringLiteral( "UI/lastProjectDir" ), fullPath.path() );
55145558

5515-
// make sure the .qgs extension is included in the path name. if not, add it...
5516-
if ( "qgs" != fullPath.suffix().toLower() )
5559+
bool writeOk = false;
5560+
if ( filter == zip_ext )
55175561
{
5518-
fullPath.setFile( fullPath.filePath() + ".qgs" );
5562+
if ( "qgz" != fullPath.suffix().toLower() )
5563+
fullPath.setFile( fullPath.filePath() + ".qgz" );
5564+
5565+
writeOk = QgsProject::instance()->zip( fullPath.filePath() );
55195566
}
5567+
else // .qgs
5568+
{
5569+
if ( "qgs" != fullPath.suffix().toLower() )
5570+
fullPath.setFile( fullPath.filePath() + ".qgs" );
55205571

5521-
QgsProject::instance()->setFileName( fullPath.filePath() );
5572+
QgsProject::instance()->setFileName( fullPath.filePath() );
5573+
writeOk = QgsProject::instance()->write();
5574+
}
55225575

5523-
if ( QgsProject::instance()->write() )
5576+
if ( writeOk )
55245577
{
55255578
setTitleBarText_( *this ); // update title bar
5526-
mStatusBar->showMessage( tr( "Saved project to: %1" ).arg( QDir::toNativeSeparators( QgsProject::instance()->fileName() ) ), 5000 );
5579+
mStatusBar->showMessage( tr( "Saved project to: %1" ).arg( QDir::toNativeSeparators( fullPath.filePath() ) ), 5000 );
55275580
// add this to the list of recently used project files
55285581
saveRecentProjectPath( fullPath.filePath() );
55295582
mProjectLastModified = fullPath.lastModified();

‎src/core/qgsarchive.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ QString QgsArchive::filename() const
9595
return mFilename;
9696
}
9797

98+
void QgsArchive::setFileName( const QString &filename )
99+
{
100+
mFilename = filename;
101+
}
102+
98103
QString QgsArchive::projectFile() const
99104
{
100105
Q_FOREACH ( const QString &file, mFiles )

‎src/core/qgsarchive.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class CORE_EXPORT QgsArchive
4949

5050
void addFile( const QString &filename );
5151

52+
void setFileName( const QString &filename );
53+
5254
QString filename() const;
5355

5456
QString projectFile() const;

‎src/core/qgsproject.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,8 @@ void QgsProject::setFileName( const QString &name )
425425
if ( newHomePath != oldHomePath )
426426
emit homePathChanged();
427427

428+
mArchive->clear();
429+
428430
setDirty( true );
429431
}
430432

@@ -763,6 +765,9 @@ bool QgsProject::read()
763765
{
764766
clearError();
765767

768+
if ( ! mUnzipping )
769+
mArchive->clear();
770+
766771
std::unique_ptr<QDomDocument> doc( new QDomDocument( QStringLiteral( "qgis" ) ) );
767772

768773
if ( !mFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
@@ -2085,27 +2090,38 @@ bool QgsProject::unzip( const QString &filename )
20852090
}
20862091

20872092
// read the project file
2093+
mUnzipping = true;
20882094
if ( ! read( archive->projectFile() ) )
20892095
{
2096+
mUnzipping = false;
20902097
setError( tr( "Cannot read unzipped qgs project file" ) );
20912098
return false;
20922099
}
20932100

20942101
// keep the archive
2102+
mUnzipping = false;
20952103
mArchive.reset( archive.release() );
20962104

20972105
return true;
20982106
}
20992107

2108+
bool QgsProject::zip()
2109+
{
2110+
if ( unzipped() )
2111+
return zip( mArchive->filename() );
2112+
2113+
return false;
2114+
}
2115+
21002116
bool QgsProject::zip( const QString &filename )
21012117
{
21022118
clearError();
21032119

21042120
// save the current project in a temporary .qgs file
2105-
QgsArchive archive;
2121+
std::unique_ptr<QgsArchive> archive( new QgsArchive() );
21062122
const QString baseName = QFileInfo( filename ).baseName();
21072123
const QString qgsFileName = QString( "%1.qgs" ).arg( baseName );
2108-
QFile qgsFile( QDir( archive.dir() ).filePath( qgsFileName ) );
2124+
QFile qgsFile( QDir( archive->dir() ).filePath( qgsFileName ) );
21092125

21102126
bool writeOk;
21112127
if ( qgsFile.open( QIODevice::WriteOnly ) )
@@ -2127,19 +2143,38 @@ bool QgsProject::zip( const QString &filename )
21272143
}
21282144

21292145
// create the archive
2130-
archive.addFile( qgsFile.fileName() );
2146+
archive->addFile( qgsFile.fileName() );
21312147

21322148
// zip
21332149
QString errMsg;
2134-
if ( !archive.zip( filename ) )
2150+
if ( !archive->zip( filename ) )
21352151
{
21362152
setError( tr( "Unable to perform zip" ) );
21372153
return false;
21382154
}
21392155

2156+
// keep the archive
2157+
mArchive.reset( archive.release() );
2158+
21402159
return true;
21412160
}
21422161

2162+
bool QgsProject::unzipped() const
2163+
{
2164+
return !mArchive->filename().isEmpty();
2165+
}
2166+
2167+
QString QgsProject::zipFileName() const
2168+
{
2169+
return mArchive->filename();
2170+
}
2171+
2172+
void QgsProject::setZipFileName( const QString &filename )
2173+
{
2174+
mArchive.reset( new QgsArchive() );
2175+
mArchive->setFileName( filename );
2176+
}
2177+
21432178
QList<QgsMapLayer *> QgsProject::addMapLayers(
21442179
const QList<QgsMapLayer *> &layers,
21452180
bool addToLegend,

‎src/core/qgsproject.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,14 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera
592592
*/
593593
bool zip( const QString &filename );
594594

595+
bool zip();
596+
597+
QString zipFileName() const;
598+
599+
void setZipFileName( const QString &filename );
600+
601+
bool unzipped() const;
602+
595603
#ifndef SIP_RUN
596604

597605
/** Returns a list of registered map layers with a specified layer type.
@@ -1066,6 +1074,7 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera
10661074
QVariantMap mCustomVariables;
10671075

10681076
std::unique_ptr<QgsArchive> mArchive;
1077+
bool mUnzipping;
10691078

10701079
QFile mFile; // current physical project file
10711080
mutable QgsProjectPropertyKey mProperties; // property hierarchy, TODO: this shouldn't be mutable

0 commit comments

Comments
 (0)