~ubuntu-branches/ubuntu/quantal/ark/quantal

« back to all changes in this revision

Viewing changes to plugins/karchiveplugin/karchiveplugin.cpp

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2012-06-06 18:50:49 UTC
  • mfrom: (1.1.7)
  • Revision ID: package-import@ubuntu.com-20120606185049-z43lsy5wwp3wtrgt
Tags: 4:4.8.80-0ubuntu1
* Merge with Debian git repository, remaining changes:
  - Suggest instead of recommend p7zip-full
  - Add and install utilities-file-archiver.xpm
* New upstream beta release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 *
20
20
 */
21
21
#include "karchiveplugin.h"
 
22
#include "kerfuffle/queries.h"
22
23
 
23
24
#include <KZip>
24
25
#include <KTar>
28
29
#include <QDir>
29
30
 
30
31
#include <QFileInfo>
 
32
#include <QSet>
31
33
 
32
34
KArchiveInterface::KArchiveInterface(QObject *parent, const QVariantList &args)
33
35
        : ReadWriteArchiveInterface(parent, args), m_archive(0)
46
48
    if (m_archive == 0) {
47
49
        KMimeType::Ptr mimeType = KMimeType::findByPath(filename());
48
50
 
49
 
        if (mimeType->is("application/zip")) {
 
51
        if (mimeType->is(QLatin1String("application/zip"))) {
50
52
            m_archive = new KZip(filename());
51
53
        } else {
52
54
            m_archive = new KTar(filename());
60
62
{
61
63
    kDebug();
62
64
    if (!archive()->isOpen() && !archive()->open(QIODevice::ReadOnly)) {
63
 
        error(i18nc("@info", "Could not open the archive <filename>%1</filename> for reading", filename()));
 
65
        emit error(i18nc("@info", "Could not open the archive <filename>%1</filename> for reading", filename()));
64
66
        return false;
65
67
    } else {
66
68
        return browseArchive(archive());
67
69
    }
68
70
}
69
71
 
 
72
void KArchiveInterface::getAllEntries(const KArchiveDirectory *dir, const QString &prefix, QList< QVariant > &list)
 
73
{
 
74
    foreach(const QString &entryName, dir->entries()) {
 
75
        const KArchiveEntry *entry = dir->entry(entryName);
 
76
        if (entry->isDirectory()) {
 
77
            QString newPrefix = (prefix.isEmpty() ? prefix : prefix + QLatin1Char('/')) + entryName;
 
78
            getAllEntries(static_cast<const KArchiveDirectory*>(entry), newPrefix, list);
 
79
        }
 
80
        else {
 
81
            list.append(prefix + QLatin1Char('/') + entryName);
 
82
        }
 
83
    }
 
84
}
 
85
 
70
86
bool KArchiveInterface::copyFiles(const QList<QVariant> &files, const QString &destinationDirectory, ExtractionOptions options)
71
87
{
72
88
    const bool preservePaths = options.value(QLatin1String("PreservePaths")).toBool();
 
89
    const KArchiveDirectory *dir = archive()->directory();
73
90
 
74
91
    if (!archive()->isOpen() && !archive()->open(QIODevice::ReadOnly)) {
75
 
        error(i18nc("@info", "Could not open the archive <filename>%1</filename> for reading", filename()));
 
92
        emit error(i18nc("@info", "Could not open the archive <filename>%1</filename> for reading", filename()));
76
93
        return false;
77
94
    }
78
95
 
79
 
    foreach(const QVariant &file, files) {
 
96
    QList<QVariant> extrFiles = files;
 
97
    if (extrFiles.isEmpty()) { // All files should be extracted
 
98
        getAllEntries(dir, QString(), extrFiles);
 
99
    }
 
100
 
 
101
    bool overwriteAllSelected = false;
 
102
    bool autoSkipSelected = false;
 
103
    QSet<QString> dirCache;
 
104
    foreach(const QVariant &file, extrFiles) {
80
105
        QString realDestination = destinationDirectory;
81
 
        const KArchiveEntry *archiveEntry = archive()->directory()->entry(file.toString());
 
106
        const KArchiveEntry *archiveEntry = dir->entry(file.toString());
82
107
        if (!archiveEntry) {
83
 
            error(i18nc("@info", "File <filename>%1</filename> not found in the archive" , file.toString()));
 
108
            emit error(i18nc("@info", "File <filename>%1</filename> not found in the archive" , file.toString()));
84
109
            return false;
85
110
        }
86
111
 
87
 
        // TODO: handle errors, copyTo fails silently
88
112
        if (preservePaths) {
89
113
            QFileInfo fi(file.toString());
90
114
            QDir dest(destinationDirectory);
91
115
            QString filepath = archiveEntry->isDirectory() ? fi.filePath() : fi.path();
92
 
            dest.mkpath(filepath);
93
 
            realDestination = dest.absolutePath() + '/' + filepath;
 
116
            if (!dirCache.contains(filepath)) {
 
117
                if (!dest.mkpath(filepath)) {
 
118
                    emit error(i18nc("@info", "Error creating directory <filename>%1</filename>", filepath));
 
119
                    return false;
 
120
                }
 
121
                dirCache << filepath;
 
122
            }
 
123
            realDestination = dest.absolutePath() + QLatin1Char('/') + filepath;
94
124
        }
95
 
        if (archiveEntry->isDirectory()) {
96
 
            kDebug() << "Calling copyTo(" << realDestination << ") for " << archiveEntry->name();
97
 
            static_cast<const KArchiveDirectory*>(archiveEntry)->copyTo(realDestination);
98
 
        } else {
99
 
            static_cast<const KArchiveFile*>(archiveEntry)->copyTo(realDestination);
 
125
 
 
126
        // TODO: handle errors, copyTo fails silently
 
127
        if (!archiveEntry->isDirectory()) { // We don't need to do anything about directories
 
128
            if (QFile::exists(realDestination + QLatin1Char('/') + archiveEntry->name()) && !overwriteAllSelected) {
 
129
                if (autoSkipSelected) {
 
130
                    continue;
 
131
                }
 
132
 
 
133
                int response = handleFileExistsMessage(realDestination, archiveEntry->name());
 
134
 
 
135
                if (response == OverwriteCancel) {
 
136
                    break;
 
137
                }
 
138
                if (response == OverwriteYes || response == OverwriteAll) {
 
139
                    static_cast<const KArchiveFile*>(archiveEntry)->copyTo(realDestination);
 
140
                    if (response == OverwriteAll) {
 
141
                        overwriteAllSelected = true;
 
142
                    }
 
143
                }
 
144
                if (response == OverwriteAutoSkip) {
 
145
                    autoSkipSelected = true;
 
146
                }
 
147
            }
 
148
            else {
 
149
                static_cast<const KArchiveFile*>(archiveEntry)->copyTo(realDestination);
 
150
            }
100
151
        }
101
152
    }
102
153
 
103
154
    return true;
104
155
}
105
156
 
 
157
int KArchiveInterface::handleFileExistsMessage(const QString &dir, const QString &fileName)
 
158
{
 
159
    Kerfuffle::OverwriteQuery query(dir + QLatin1Char('/') + fileName);
 
160
    query.setNoRenameMode(true);
 
161
    emit userQuery(&query);
 
162
    query.waitForResponse();
 
163
 
 
164
    if (query.responseOverwrite()) {
 
165
        return OverwriteYes;
 
166
    } else if (query.responseSkip()) {
 
167
        return OverwriteSkip;
 
168
    } else if (query.responseOverwriteAll()) {
 
169
        return OverwriteAll;
 
170
    } else if (query.responseAutoSkip()) {
 
171
        return OverwriteAutoSkip;
 
172
    }
 
173
 
 
174
    return OverwriteCancel;
 
175
}
 
176
 
106
177
bool KArchiveInterface::browseArchive(KArchive *archive)
107
178
{
108
179
    return processDir(archive->directory());
114
185
        const KArchiveEntry *entry = dir->entry(entryName);
115
186
        createEntryFor(entry, prefix);
116
187
        if (entry->isDirectory()) {
117
 
            QString newPrefix = (prefix.isEmpty() ? prefix : prefix + '/') + entryName;
 
188
            QString newPrefix = (prefix.isEmpty() ? prefix : prefix + QLatin1Char('/')) + entryName;
118
189
            processDir(static_cast<const KArchiveDirectory*>(entry), newPrefix);
119
190
        }
120
191
    }
124
195
void KArchiveInterface::createEntryFor(const KArchiveEntry *aentry, const QString& prefix)
125
196
{
126
197
    ArchiveEntry e;
127
 
    e[ FileName ]         = prefix.isEmpty() ? aentry->name() : prefix + '/' + aentry->name();
 
198
    QString fileName = prefix.isEmpty() ? aentry->name() : prefix + QLatin1Char('/') + aentry->name();
 
199
 
 
200
    if (aentry->isDirectory() && !fileName.endsWith(QLatin1Char('/')))
 
201
        fileName += QLatin1Char('/');
 
202
 
 
203
    e[ FileName ]         = fileName;
128
204
    e[ InternalID ]       = e[ FileName ];
129
205
    e[ Permissions ]      = permissionsString(aentry->permissions());
130
206
    e[ Owner ]            = aentry->user();
140
216
    else {
141
217
        e[ Size ] = 0;
142
218
    }
143
 
    entry(e);
 
219
    emit entry(e);
144
220
}
145
221
 
146
222
bool KArchiveInterface::addFiles(const QStringList &files, const Kerfuffle::CompressionOptions &options)
153
229
        archive()->close();
154
230
    }
155
231
    if (!archive()->open(QIODevice::ReadWrite)) {
156
 
        error(i18nc("@info", "Could not open the archive <filename>%1</filename> for writing.", filename()));
 
232
        emit error(i18nc("@info", "Could not open the archive <filename>%1</filename> for writing.", filename()));
157
233
        return false;
158
234
    }
159
235
 
167
243
        if (fi.isDir()) {
168
244
            if (archive()->addLocalDirectory(path, fi.fileName())) {
169
245
                const KArchiveEntry *entry = archive()->directory()->entry(fi.fileName());
170
 
                createEntryFor(entry, "");
 
246
                createEntryFor(entry, QString());
171
247
                processDir((KArchiveDirectory*) archive()->directory()->entry(fi.fileName()), fi.fileName());
172
248
            } else {
173
 
                error(i18nc("@info", "Could not add the directory <filename>%1</filename> to the archive", path));
 
249
                emit error(i18nc("@info", "Could not add the directory <filename>%1</filename> to the archive", path));
174
250
                return false;
175
251
            }
176
252
        } else {
177
253
            if (archive()->addLocalFile(path, fi.fileName())) {
178
254
                const KArchiveEntry *entry = archive()->directory()->entry(fi.fileName());
179
 
                createEntryFor(entry, "");
 
255
                createEntryFor(entry, QString());
180
256
            } else {
181
 
                error(i18nc("@info", "Could not add the file <filename>%1</filename> to the archive.", path));
 
257
                emit error(i18nc("@info", "Could not add the file <filename>%1</filename> to the archive.", path));
182
258
                return false;
183
259
            }
184
260
        }