Navigation Menu

Skip to content

Commit

Permalink
Merge pull request #4845 from pblottiere/zip
Browse files Browse the repository at this point in the history
[FEATURE] New zip format
  • Loading branch information
m-kuhn committed Aug 4, 2017
2 parents 3c58599 + 86c63a1 commit b20f4c6
Show file tree
Hide file tree
Showing 19 changed files with 1,139 additions and 34 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -35,6 +35,7 @@ matrix:
- poppler-utils
- xvfb
- clang-3.8
- libzip-dev


- os: linux
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Expand Up @@ -210,6 +210,7 @@ IF(WITH_CORE)
IF (WITH_GUI)
FIND_PACKAGE(Qwt REQUIRED)
ENDIF (WITH_GUI)
FIND_PACKAGE(LibZip REQUIRED)

IF (WITH_INTERNAL_QEXTSERIALPORT)
SET(QEXTSERIALPORT_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src/core/gps/qextserialport)
Expand Down
40 changes: 40 additions & 0 deletions cmake/FindLibZip.cmake
@@ -0,0 +1,40 @@
# CMake module to search for libzip
#
# Once done this will define
#
# LIBZIP_FOUND - system has the zip library
# LIBZIP_INCLUDE_DIR - the zip include directory
# LIBZIP_LIBRARY - Link this to use the zip library
#
# Copyright (c) 2017, Paul Blottiere, <paul.blottiere@oslandia.com>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.

FIND_PATH(LIBZIP_INCLUDE_DIR
zip.h
PATHS
/usr/local/include
/usr/include
"$ENV{LIB_DIR}/include"
"$ENV{INCLUDE}"
)

FIND_LIBRARY(LIBZIP_LIBRARY
NAMES zip
PATHS
/usr/local/lib
/usr/lib
"$ENV{LIB_DIR}/lib"
"$ENV{LIB}"
)

IF (LIBZIP_LIBRARY AND LIBZIP_INCLUDE_DIR)
SET(LIBZIP_FOUND TRUE)
ENDIF (LIBZIP_LIBRARY AND LIBZIP_INCLUDE_DIR)

IF (LIBZIP_FOUND)
MESSAGE(STATUS "Found libzip: ${LIBZIP_LIBRARY}")
ELSE (LIPZIP_FOUND)
MESSAGE(FATAL_ERROR "Could not find libzip")
ENDIF (LIBZIP_FOUND)
2 changes: 2 additions & 0 deletions python/core/core_auto.sip
Expand Up @@ -127,6 +127,8 @@
%Include qgsvirtuallayerdefinitionutils.sip
%Include qgsmapthemecollection.sip
%Include qgsxmlutils.sip
%Include qgsarchive.sip
%Include qgsziputils.sip
%Include qgsvector.sip
%Include auth/qgsauthcertutils.sip
%Include auth/qgsauthconfig.sip
Expand Down
135 changes: 135 additions & 0 deletions python/core/qgsarchive.sip
@@ -0,0 +1,135 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsarchive.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsArchive
{
%Docstring
Class allowing to manage the zip/unzip actions
.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsarchive.h"
%End
public:

QgsArchive();
%Docstring
Constructor
%End

QgsArchive( const QgsArchive &other );
%Docstring
Copy constructor
%End


virtual ~QgsArchive();
%Docstring
Destructor
%End

bool zip( const QString &zipFilename );
%Docstring
Zip the content of this archive
\param zipFilename The name of the zip to generate
:return: false if something goes wrong, true otherwise
:rtype: bool
%End

virtual bool unzip( const QString &zipFilename );
%Docstring
Clear the current content of this archive and unzip. Files are unzipped
in the temporary directory.
\param zipFilename The zip file to unzip
:return: true if unzip action is a success, false otherwise
:rtype: bool
%End

void clear();
%Docstring
Clear the current content of this archive and create a new temporary
directory.
%End

void addFile( const QString &filename );
%Docstring
Add a new file to this archive. During a zip action, this file will be
part of the resulting zipped file.
\param filename A file to add when zipping this archive
%End

bool removeFile( const QString &filename );
%Docstring
Remove a file from this archive and from the filesystem.
\param filename The path of the file to remove
:return: true if the file has been removed from the filesystem, false otherwise
:rtype: bool
%End

QStringList files() const;
%Docstring
Returns the list of files within this archive
:rtype: list of str
%End

QString dir() const;
%Docstring
Returns the current temporary directory.
:rtype: str
%End

};

class QgsProjectArchive : QgsArchive
{
%Docstring
Class allowing to manage the zip/unzip actions on project file
.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsarchive.h"
%End
public:

virtual bool unzip( const QString &zipFilename );

%Docstring
Clear the current content of this archive and unzip. If a project file
is found in the content, then this archive may be considered as a valid
one. Files are unzipped in the temporary directory.
\param zipFilename The zip file to unzip
:return: true if a project file has been found, false otherwise
:rtype: bool
%End

QString projectFile() const;
%Docstring
Returns the current .qgs project file or an empty string if there's none
:rtype: str
%End

bool clearProjectFile();
%Docstring
Remove the current .qgs project file from the temporary directory.
:return: true if the file is well removed, false otherwise
:rtype: bool
%End
};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsarchive.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
6 changes: 6 additions & 0 deletions python/core/qgsproject.sip
Expand Up @@ -612,6 +612,12 @@ Returns the number of registered layers.
:rtype: QMap<str, QgsMapLayer *>
%End

bool isZipped() const;
%Docstring
Returns true if the project comes from a zip archive, false otherwise.
:rtype: bool
%End


QList<QgsMapLayer *> addMapLayers( const QList<QgsMapLayer *> &mapLayers /Transfer/,
bool addToLegend = true);
Expand Down
57 changes: 57 additions & 0 deletions python/core/qgsziputils.sip
@@ -0,0 +1,57 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsziputils.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/



%ModuleHeaderCode
#include "qgsziputils.h"
%End

namespace QgsZipUtils
{

bool isZipFile( const QString &filename );
%Docstring
Returns true if the file name is a zipped file ( i.e with a '.qgz'
extension, false otherwise.
\param filename The name of the file
:return: true if the file is zipped, false otherwise
:rtype: bool
%End

bool unzip( const QString &zip, const QString &dir, QStringList &files /Out/ );
%Docstring
Unzip a zip file in an output directory. An error is returned if the zip
filename does not exist, the output directory does not exist or is
not writable.
\param zip The zip filename
\param dir The output directory
\param files The absolute path of unzipped files
.. versionadded:: 3.0
:rtype: bool
%End

bool zip( const QString &zip, const QStringList &files );
%Docstring
Zip the list of files in the zip file. If the zip file already exists or is
empty, an error is returned. If an input file does not exist, an error is
also returned.
\param zip The zip filename
\param files The absolute path to files to embed within the zip
.. versionadded:: 3.0
:rtype: bool
%End
};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsziputils.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
2 changes: 2 additions & 0 deletions scripts/spell_check/spelling.dat
Expand Up @@ -2943,6 +2943,8 @@ fiel:field
fiels:fields
fiercly:fiercely
fightings:fighting
fille:file
filles:files
filesytem:filesystem
filesytems:filesystems
fileystem:filesystem
Expand Down
37 changes: 27 additions & 10 deletions src/app/qgisapp.cpp
Expand Up @@ -77,6 +77,7 @@
#include <qgscomposition.h>
#include <qgslayerstylingwidget.h>
#include "qgstaskmanager.h"
#include "qgsziputils.h"

#include <QNetworkReply>
#include <QNetworkProxy>
Expand Down Expand Up @@ -5230,7 +5231,7 @@ void QgisApp::fileOpen()
QString fullPath = QFileDialog::getOpenFileName( this,
tr( "Choose a QGIS project file to open" ),
lastUsedDir,
tr( "QGIS files" ) + " (*.qgs *.QGS)" );
tr( "QGIS files" ) + " (*.qgs *.qgz *.QGS)" );
if ( fullPath.isNull() )
{
return;
Expand Down Expand Up @@ -5275,7 +5276,7 @@ bool QgisApp::addProject( const QString &projectFile )
bool autoSetupOnFirstLayer = mLayerTreeCanvasBridge->autoSetupOnFirstLayer();
mLayerTreeCanvasBridge->setAutoSetupOnFirstLayer( false );

if ( !QgsProject::instance()->read( projectFile ) )
if ( !QgsProject::instance()->read( projectFile ) && !QgsZipUtils::isZipFile( projectFile ) )
{
QString backupFile = projectFile + "~";
QString loadBackupPrompt;
Expand Down Expand Up @@ -5415,22 +5416,30 @@ bool QgisApp::fileSave()
QgsSettings settings;
QString lastUsedDir = settings.value( QStringLiteral( "UI/lastProjectDir" ), QDir::homePath() ).toString();

const QString qgsExt = tr( "QGIS files" ) + " (*.qgs)";
const QString zipExt = tr( "QGZ files" ) + " (*.qgz)";
QString filter;
QString path = QFileDialog::getSaveFileName(
this,
tr( "Choose a QGIS project file" ),
lastUsedDir + '/' + QgsProject::instance()->title(),
tr( "QGIS files" ) + " (*.qgs *.QGS)" );
qgsExt + ";;" + zipExt, &filter );
if ( path.isEmpty() )
return false;

fullPath.setFile( path );

// make sure we have the .qgs extension in the file name
if ( "qgs" != fullPath.suffix().toLower() )
if ( filter == zipExt )
{
fullPath.setFile( fullPath.filePath() + ".qgs" );
if ( fullPath.suffix().compare( QLatin1String( "qgz" ), Qt::CaseInsensitive ) != 0 )
fullPath.setFile( fullPath.filePath() + ".qgz" );
}
else
{
if ( fullPath.suffix().compare( QLatin1String( "qgs" ), Qt::CaseInsensitive ) != 0 )
fullPath.setFile( fullPath.filePath() + ".qgs" );
}


QgsProject::instance()->setFileName( fullPath.filePath() );
}
Expand Down Expand Up @@ -5493,21 +5502,29 @@ void QgisApp::fileSaveAs()
QgsSettings settings;
QString lastUsedDir = settings.value( QStringLiteral( "UI/lastProjectDir" ), QDir::homePath() ).toString();

const QString qgsExt = tr( "QGIS files" ) + " (*.qgs *.QGS)";
const QString zipExt = tr( "QGZ files" ) + " (*.qgz)";
QString filter;
QString path = QFileDialog::getSaveFileName( this,
tr( "Choose a file name to save the QGIS project file as" ),
lastUsedDir + '/' + QgsProject::instance()->title(),
tr( "QGIS files" ) + " (*.qgs *.QGS)" );
qgsExt + ";;" + zipExt, &filter );
if ( path.isEmpty() )
return;

QFileInfo fullPath( path );

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

// make sure the .qgs extension is included in the path name. if not, add it...
if ( "qgs" != fullPath.suffix().toLower() )
if ( filter == zipExt )
{
if ( fullPath.suffix().compare( QLatin1String( "qgz" ), Qt::CaseInsensitive ) != 0 )
fullPath.setFile( fullPath.filePath() + ".qgz" );
}
else // .qgs
{
fullPath.setFile( fullPath.filePath() + ".qgs" );
if ( fullPath.suffix().compare( QLatin1String( "qgs" ), Qt::CaseInsensitive ) != 0 )
fullPath.setFile( fullPath.filePath() + ".qgs" );
}

QgsProject::instance()->setFileName( fullPath.filePath() );
Expand Down

0 comments on commit b20f4c6

Please sign in to comment.