QGIS API Documentation 3.99.0-Master (8e76e220402)
Loading...
Searching...
No Matches
qgsarchive.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsarchive.cpp
3 ----------------
4
5 begin : July 07, 2017
6 copyright : (C) 2017 by Paul Blottiere
8 ***************************************************************************/
9
10/***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
19#include "qgsarchive.h"
20
21#include "qgsauxiliarystorage.h"
22#include "qgsmessagelog.h"
23#include "qgsziputils.h"
24
25#include <QString>
26
27using namespace Qt::StringLiterals;
28
29#ifdef Q_OS_WIN
30#include <windows.h>
31#endif
32
33#include <QStandardPaths>
34#include <QUuid>
35#include <memory>
36
38 : mDir( new QTemporaryDir() )
39{
40}
41
43 : mFiles( other.mFiles )
44 , mDir( new QTemporaryDir() )
45{
46}
47
49{
50 if ( this != &other )
51 {
52 mFiles = other.mFiles;
53 mDir = std::make_unique<QTemporaryDir>( );
54 }
55
56 return *this;
57}
58
59QString QgsArchive::dir() const
60{
61 return mDir->path();
62}
63
65{
66 mDir = std::make_unique<QTemporaryDir>( );
67 mFiles.clear();
68}
69
70bool QgsArchive::zip( const QString &filename )
71{
72 const QString tempPath( QDir::temp().absoluteFilePath( u"qgis-project-XXXXXX.zip"_s ) );
73
74 // zip content
75 if ( ! QgsZipUtils::zip( tempPath, mFiles, true ) )
76 {
77 const QString err = QObject::tr( "Unable to zip content" );
78 QgsMessageLog::logMessage( err, u"QgsArchive"_s );
79 return false;
80 }
81
82 QString target {filename};
83
84 // remove existing zip file
85 if ( QFile::exists( target ) )
86 {
87 // If symlink -> we want to write to its target instead
88 const QFileInfo targetFileInfo( target );
89 target = targetFileInfo.canonicalFilePath();
90 // If target still exists, remove (might not exist if was a dangling symlink)
91 if ( QFile::exists( target ) )
92 QFile::remove( target );
93 }
94
95#ifdef Q_OS_WIN
96 // Clear temporary flag (see GH #32118)
97 DWORD dwAttrs;
98#ifdef UNICODE
99 dwAttrs = GetFileAttributes( qUtf16Printable( tempPath ) );
100 SetFileAttributes( qUtf16Printable( tempPath ), dwAttrs & ~ FILE_ATTRIBUTE_TEMPORARY );
101#else
102 dwAttrs = GetFileAttributes( tempPath.toLocal8Bit( ).data( ) );
103 SetFileAttributes( tempPath.toLocal8Bit( ).data( ), dwAttrs & ~ FILE_ATTRIBUTE_TEMPORARY );
104#endif
105
106#endif // Q_OS_WIN
107
108 // save zip archive
109 if ( !QFile::rename( tempPath, target ) )
110 {
111 const QString err = QObject::tr( "Unable to save zip file '%1'" ).arg( target );
112 QgsMessageLog::logMessage( err, u"QgsArchive"_s );
113 return false;
114 }
115
116 return true;
117}
118
119bool QgsArchive::unzip( const QString &filename )
120{
121 clear();
122 return QgsZipUtils::unzip( filename, mDir->path(), mFiles );
123}
124
125void QgsArchive::addFile( const QString &file )
126{
127 mFiles.append( file );
128}
129
130bool QgsArchive::removeFile( const QString &file )
131{
132 bool rc = false;
133
134 if ( !file.isEmpty() && mFiles.contains( file ) && QFile::exists( file ) )
135 rc = QFile::remove( file );
136
137 mFiles.removeOne( file );
138
139 return rc;
140}
141
142QStringList QgsArchive::files() const
143{
144 return mFiles;
145}
146
148{
149 return QFileInfo::exists( mDir->path() );
150}
151
153{
154 const auto constFiles = files();
155 for ( const QString &file : constFiles )
156 {
157 const QFileInfo fileInfo( file );
158 if ( fileInfo.suffix().compare( "qgs"_L1, Qt::CaseInsensitive ) == 0 )
159 return file;
160 }
161
162 return QString();
163}
164
165bool QgsProjectArchive::unzip( const QString &filename )
166{
167 if ( QgsArchive::unzip( filename ) )
168 return ! projectFile().isEmpty();
169 else
170 return false;
171}
172
177
179{
180 const QString extension = QgsAuxiliaryStorage::extension();
181
182 const QStringList fileList = files();
183 for ( const QString &file : fileList )
184 {
185 const QFileInfo fileInfo( file );
186 if ( fileInfo.suffix().compare( extension, Qt::CaseInsensitive ) == 0 )
187 return file;
188 }
189
190 return QString();
191}
QgsArchive & operator=(const QgsArchive &other)
virtual bool unzip(const QString &zipFilename)
Clear the current content of this archive and unzip.
bool zip(const QString &zipFilename)
Zip the content of this archive.
void clear()
Clear the current content of this archive and create a new temporary directory.
bool exists() const
Returns true if the archive exists on the filesystem, false otherwise.
void addFile(const QString &filename)
Add a new file to this archive.
bool removeFile(const QString &filename)
Remove a file from this archive and from the filesystem.
QString dir() const
Returns the current temporary directory.
QStringList files() const
Returns the list of files within this archive.
static QString extension()
Returns the extension used for auxiliary databases.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
QString projectFile() const
Returns the current .qgs project file or an empty string if there's none.
QString auxiliaryStorageFile() const
Returns the current .qgd auxiliary storage file or an empty string if there's none.
bool clearProjectFile()
Remove the current .qgs project file from the temporary directory.
bool unzip(const QString &zipFilename) override
Clear the current content of this archive and unzip.
static bool zip(const QString &zip, const QStringList &files, bool overwrite=false)
Zip the list of files in the zip file.
static bool unzip(const QString &zip, const QString &dir, QStringList &files, bool checkConsistency=true)
Unzip a zip file in an output directory.