1
/***************************************************************************
2
* Copyright (C) 2006 by Sébastien Laoût *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 2 of the License, or *
8
* (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program; if not, write to the *
17
* Free Software Foundation, Inc., *
18
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19
***************************************************************************/
22
#include <qstringlist.h>
23
#include <qvaluelist.h>
28
#include <kmessagebox.h>
31
#include <kstandarddirs.h>
32
#include <kapplication.h>
33
#include <kiconloader.h>
34
#include <kprogress.h>
35
#include <kmainwindow.h>
41
#include "basketlistview.h"
42
#include "basketfactory.h"
46
#include "backgroundmanager.h"
47
#include "formatimporter.h"
51
void Archive::save(Basket *basket, bool withSubBaskets, const QString &destination)
55
KProgressDialog dialog(0, 0, i18n("Save as Basket Archive"), i18n("Saving as basket archive. Please wait..."), /*Not modal, for password dialogs!*/false);
56
dialog.showCancelButton(false);
57
dialog.setAutoClose(true);
59
KProgress *progress = dialog.progressBar();
60
progress->setTotalSteps(/*Preparation:*/1 + /*Finishing:*/1 + /*Basket:*/1 + /*SubBaskets:*/(withSubBaskets ? Global::bnpView->basketCount(Global::bnpView->listViewItemForBasket(basket)) : 0));
61
progress->setValue(0);
63
// Create the temporar folder:
64
QString tempFolder = Global::savesFolder() + "temp-archive/";
65
dir.mkdir(tempFolder);
67
// Create the temporar archive file:
68
QString tempDestination = tempFolder + "temp-archive.tar.gz";
69
KTar tar(tempDestination, "application/x-gzip");
70
tar.open(IO_WriteOnly);
71
tar.writeDir("baskets", "", "");
73
progress->advance(1); // Preparation finished
74
std::cout << "Preparation finished out of " << progress->totalSteps() << std::endl;
76
// Copy the baskets data into the archive:
77
QStringList backgrounds;
78
saveBasketToArchive(basket, withSubBaskets, &tar, backgrounds, tempFolder, progress);
80
// Create a Small baskets.xml Document:
81
QDomDocument document("basketTree");
82
QDomElement root = document.createElement("basketTree");
83
document.appendChild(root);
84
Global::bnpView->saveSubHierarchy(Global::bnpView->listViewItemForBasket(basket), document, root, withSubBaskets);
85
Basket::safelySaveToFile(tempFolder + "baskets.xml", "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + document.toString());
86
tar.addLocalFile(tempFolder + "baskets.xml", "baskets/baskets.xml");
87
dir.remove(tempFolder + "baskets.xml");
89
// Save a Small tags.xml Document:
90
QValueList<Tag*> tags;
91
listUsedTags(basket, withSubBaskets, tags);
92
Tag::saveTagsTo(tags, tempFolder + "tags.xml");
93
tar.addLocalFile(tempFolder + "tags.xml", "tags.xml");
94
dir.remove(tempFolder + "tags.xml");
96
// Save Tag Emblems (in case they are loaded on a computer that do not have those icons):
97
QString tempIconFile = tempFolder + "icon.png";
98
for (Tag::List::iterator it = tags.begin(); it != tags.end(); ++it) {
99
State::List states = (*it)->states();
100
for (State::List::iterator it2 = states.begin(); it2 != states.end(); ++it2) {
101
State *state = (*it2);
102
QPixmap icon = kapp->iconLoader()->loadIcon(state->emblem(), KIcon::Small, 16, KIcon::DefaultState, /*path_store=*/0L, /*canReturnNull=*/true);
103
if (!icon.isNull()) {
104
icon.save(tempIconFile, "PNG");
105
QString iconFileName = state->emblem().replace('/', '_');
106
tar.addLocalFile(tempIconFile, "tag-emblems/" + iconFileName);
110
dir.remove(tempIconFile);
112
// Finish Tar.Gz Exportation:
115
// Computing the File Preview:
116
Basket *previewBasket = basket; // FIXME: Use the first non-empty basket!
117
QPixmap previewPixmap(previewBasket->visibleWidth(), previewBasket->visibleHeight());
118
QPainter painter(&previewPixmap);
119
// Save old state, and make the look clean ("smile, you are filmed!"):
120
NoteSelection *selection = previewBasket->selectedNotes();
121
previewBasket->unselectAll();
122
Note *focusedNote = previewBasket->focusedNote();
123
previewBasket->setFocusedNote(0);
124
previewBasket->doHoverEffects(0, Note::None);
125
// Take the screenshot:
126
previewBasket->drawContents(&painter, 0, 0, previewPixmap.width(), previewPixmap.height());
127
// Go back to the old look:
128
previewBasket->selectSelection(selection);
129
previewBasket->setFocusedNote(focusedNote);
130
previewBasket->doHoverEffects();
131
// End and save our splandid painting:
133
QImage previewImage = previewPixmap.convertToImage();
134
const int PREVIEW_SIZE = 256;
135
previewImage = previewImage.scale(PREVIEW_SIZE, PREVIEW_SIZE, QImage::ScaleMin);
136
previewImage.save(tempFolder + "preview.png", "PNG");
138
// Finaly Save to the Real Destination file:
139
QFile file(destination);
140
if (file.open(IO_WriteOnly)) {
141
ulong previewSize = QFile(tempFolder + "preview.png").size();
142
ulong archiveSize = QFile(tempDestination).size();
143
QTextStream stream(&file);
144
stream.setEncoding(QTextStream::Latin1);
145
stream << "BasKetNP:archive\n"
147
// << "read-compatible:0.6.1\n"
148
// << "write-compatible:0.6.1\n"
149
<< "preview*:" << previewSize << "\n";
150
// Copy the Preview File:
151
const Q_ULONG BUFFER_SIZE = 1024;
152
char *buffer = new char[BUFFER_SIZE];
154
QFile previewFile(tempFolder + "preview.png");
155
if (previewFile.open(IO_ReadOnly)) {
156
while ((sizeRead = previewFile.readBlock(buffer, BUFFER_SIZE)) > 0)
157
file.writeBlock(buffer, sizeRead);
159
stream << "archive*:" << archiveSize << "\n";
160
// Copy the Archive File:
161
QFile archiveFile(tempDestination);
162
if (archiveFile.open(IO_ReadOnly)) {
163
while ((sizeRead = archiveFile.readBlock(buffer, BUFFER_SIZE)) > 0)
164
file.writeBlock(buffer, sizeRead);
172
progress->advance(1); // Finishing finished
173
std::cout << "Finishing finished" << std::endl;
175
// Clean Up Everything:
176
dir.remove(tempFolder + "preview.png");
177
dir.remove(tempDestination);
178
dir.rmdir(tempFolder);
181
void Archive::saveBasketToArchive(Basket *basket, bool recursive, KTar *tar, QStringList &backgrounds, const QString &tempFolder, KProgress *progress)
183
// Basket need to be loaded for tags exportation.
184
// We load it NOW so that the progress bar really reflect the state of the exportation:
185
if (!basket->isLoaded()) {
191
tar->addLocalDirectory(basket->fullPath(), "baskets/" + basket->folderName());
192
tar->addLocalFile(basket->fullPath() + ".basket", "baskets/" + basket->folderName() + ".basket"); // The hidden files were not added
194
QString tempIconFile = tempFolder + "icon.png";
195
if (!basket->icon().isEmpty() && basket->icon() != "basket") {
196
QPixmap icon = kapp->iconLoader()->loadIcon(basket->icon(), KIcon::Small, 16, KIcon::DefaultState, /*path_store=*/0L, /*canReturnNull=*/true);
197
if (!icon.isNull()) {
198
icon.save(tempIconFile, "PNG");
199
QString iconFileName = basket->icon().replace('/', '_');
200
tar->addLocalFile(tempIconFile, "basket-icons/" + iconFileName);
203
// Save basket backgorund image:
204
QString imageName = basket->backgroundImageName();
205
if (!basket->backgroundImageName().isEmpty() && !backgrounds.contains(imageName)) {
206
QString backgroundPath = Global::backgroundManager->pathForImageName(imageName);
207
if (!backgroundPath.isEmpty()) {
208
// Save the background image:
209
tar->addLocalFile(backgroundPath, "backgrounds/" + imageName);
210
// Save the preview image:
211
QString previewPath = Global::backgroundManager->previewPathForImageName(imageName);
212
if (!previewPath.isEmpty())
213
tar->addLocalFile(previewPath, "backgrounds/previews/" + imageName);
214
// Save the configuration file:
215
QString configPath = backgroundPath + ".config";
216
if (dir.exists(configPath))
217
tar->addLocalFile(configPath, "backgrounds/" + imageName + ".config");
219
backgrounds.append(imageName);
222
progress->advance(1); // Basket exportation finished
223
std::cout << basket->basketName() << " finished" << std::endl;
225
// Recursively save child baskets:
226
BasketListViewItem *item = Global::bnpView->listViewItemForBasket(basket);
227
if (recursive && item->firstChild()) {
228
for (BasketListViewItem *child = (BasketListViewItem*) item->firstChild(); child; child = (BasketListViewItem*) child->nextSibling()) {
229
saveBasketToArchive(child->basket(), recursive, tar, backgrounds, tempFolder, progress);
234
void Archive::listUsedTags(Basket *basket, bool recursive, QValueList<Tag*> &list)
236
basket->listUsedTags(list);
237
BasketListViewItem *item = Global::bnpView->listViewItemForBasket(basket);
238
if (recursive && item->firstChild()) {
239
for (BasketListViewItem *child = (BasketListViewItem*) item->firstChild(); child; child = (BasketListViewItem*) child->nextSibling()) {
240
listUsedTags(child->basket(), recursive, list);
245
void Archive::open(const QString &path)
247
// Create the temporar folder:
248
QString tempFolder = Global::savesFolder() + "temp-archive/";
250
dir.mkdir(tempFolder);
251
const Q_ULONG BUFFER_SIZE = 1024;
254
if (file.open(IO_ReadOnly)) {
255
QTextStream stream(&file);
256
stream.setEncoding(QTextStream::Latin1);
257
QString line = stream.readLine();
258
if (line != "BasKetNP:archive") {
259
KMessageBox::error(0, i18n("This file is not a basket archive."), i18n("Basket Archive Error"));
261
Tools::deleteRecursively(tempFolder);
265
QStringList readCompatibleVersions;
266
QStringList writeCompatibleVersions;
267
while (!stream.atEnd()) {
268
// Get Key/Value Pair From the Line to Read:
269
line = stream.readLine();
270
int index = line.find(':');
274
key = line.left(index);
275
value = line.right(line.length() - index - 1);
280
if (key == "version") {
282
} else if (key == "read-compatible") {
283
readCompatibleVersions = QStringList::split(value, ";");
284
} else if (key == "write-compatible") {
285
writeCompatibleVersions = QStringList::split(value, ";");
286
} else if (key == "preview*") {
288
ulong size = value.toULong(&ok);
290
KMessageBox::error(0, i18n("This file is corrupted. It can not be opened."), i18n("Basket Archive Error"));
292
Tools::deleteRecursively(tempFolder);
295
// Get the preview file:
296
//FIXME: We do not need the preview for now
297
// QFile previewFile(tempFolder + "preview.png");
298
// if (previewFile.open(IO_WriteOnly)) {
299
char *buffer = new char[BUFFER_SIZE];
301
while ((sizeRead = file.readBlock(buffer, QMIN(BUFFER_SIZE, size))) > 0) {
302
// previewFile.writeBlock(buffer, sizeRead);
305
// previewFile.close();
308
} else if (key == "archive*") {
309
if (version != "0.6.1" && readCompatibleVersions.contains("0.6.1") && !writeCompatibleVersions.contains("0.6.1")) {
310
KMessageBox::information(
312
i18n("This file was created with a recent version of %1. "
313
"It can be opened but not every information will be available to you. "
314
"For instance, some notes may be missing because they are of a type only available in new versions. "
315
"When saving the file back, consider to save it to another file, to preserve the original one.")
316
.arg(kapp->aboutData()->programName()),
317
i18n("Basket Archive Error")
320
if (version != "0.6.1" && !readCompatibleVersions.contains("0.6.1") && !writeCompatibleVersions.contains("0.6.1")) {
323
i18n("This file was created with a recent version of %1. Please upgrade to a newer version to be able to open that file.")
324
.arg(kapp->aboutData()->programName()),
325
i18n("Basket Archive Error")
328
Tools::deleteRecursively(tempFolder);
333
ulong size = value.toULong(&ok);
335
KMessageBox::error(0, i18n("This file is corrupted. It can not be opened."), i18n("Basket Archive Error"));
337
Tools::deleteRecursively(tempFolder);
341
Global::mainWindow()->raise();
343
// Get the archive file:
344
QString tempArchive = tempFolder + "temp-archive.tar.gz";
345
QFile archiveFile(tempArchive);
346
if (archiveFile.open(IO_WriteOnly)) {
347
char *buffer = new char[BUFFER_SIZE];
349
while ((sizeRead = file.readBlock(buffer, QMIN(BUFFER_SIZE, size))) > 0) {
350
archiveFile.writeBlock(buffer, sizeRead);
356
// Extract the Archive:
357
QString extractionFolder = tempFolder + "extraction/";
359
dir.mkdir(extractionFolder);
360
KTar tar(tempArchive, "application/x-gzip");
361
tar.open(IO_ReadOnly);
362
tar.directory()->copyTo(extractionFolder);
366
importTagEmblems(extractionFolder); // Import and rename tag emblems BEFORE loading them!
367
QMap<QString, QString> mergedStates = Tag::loadTags(extractionFolder + "tags.xml");
368
QMap<QString, QString>::Iterator it;
369
if (mergedStates.count() > 0) {
373
// Import the Background Images:
374
importArchivedBackgroundImages(extractionFolder);
376
// Import the Baskets:
377
renameBasketFolders(extractionFolder, mergedStates);
380
} else if (key.endsWith("*")) {
381
// We do not know what it is, but we should read the embedded-file in order to discard it:
383
ulong size = value.toULong(&ok);
385
KMessageBox::error(0, i18n("This file is corrupted. It can not be opened."), i18n("Basket Archive Error"));
387
Tools::deleteRecursively(tempFolder);
390
// Get the archive file:
391
char *buffer = new char[BUFFER_SIZE];
393
while ((sizeRead = file.readBlock(buffer, QMIN(BUFFER_SIZE, size))) > 0) {
398
// We do not know what it is, and we do not care.
400
// Analyse the Value, if Understood:
404
Tools::deleteRecursively(tempFolder);
408
* When opening a basket archive that come from another computer,
409
* it can contains tags that use icons (emblems) that are not present on that computer.
410
* Fortunately, basket archives contains a copy of every used icons.
411
* This method check for every emblems and import the missing ones.
412
* It also modify the tags.xml copy for the emblems to point to the absolute path of the impported icons.
414
void Archive::importTagEmblems(const QString &extractionFolder)
416
QDomDocument *document = XMLWork::openFile("basketTags", extractionFolder + "tags.xml");
419
QDomElement docElem = document->documentElement();
422
dir.mkdir(Global::savesFolder() + "tag-emblems/");
423
FormatImporter copier; // Only used to copy files synchronously
425
QDomNode node = docElem.firstChild();
426
while (!node.isNull()) {
427
QDomElement element = node.toElement();
428
if ( (!element.isNull()) && element.tagName() == "tag" ) {
429
QDomNode subNode = element.firstChild();
430
while (!subNode.isNull()) {
431
QDomElement subElement = subNode.toElement();
432
if ( (!subElement.isNull()) && subElement.tagName() == "state" ) {
433
QString emblemName = XMLWork::getElementText(subElement, "emblem");
434
if (!emblemName.isEmpty()) {
435
QPixmap emblem = kapp->iconLoader()->loadIcon(emblemName, KIcon::NoGroup, 16, KIcon::DefaultState, 0L, /*canReturnNull=*/true);
436
// The icon does not exists on that computer, import it:
437
if (emblem.isNull()) {
438
// Of the emblem path was eg. "/home/seb/emblem.png", it was exported as "tag-emblems/_home_seb_emblem.png".
439
// So we need to copy that image to "~/.kde/share/apps/basket/tag-emblems/emblem.png":
440
int slashIndex = emblemName.findRev("/");
441
QString emblemFileName = (slashIndex < 0 ? emblemName : emblemName.right(slashIndex - 2));
442
QString source = extractionFolder + "tag-emblems/" + emblemName.replace('/', '_');
443
QString destination = Global::savesFolder() + "tag-emblems/" + emblemFileName;
444
if (!dir.exists(destination))
445
copier.copyFolder(source, destination);
446
// Replace the emblem path in the tags.xml copy:
447
QDomElement emblemElement = XMLWork::getElement(subElement, "emblem");
448
subElement.removeChild(emblemElement);
449
XMLWork::addElement(*document, subElement, "emblem", destination);
453
subNode = subNode.nextSibling();
456
node = node.nextSibling();
458
Basket::safelySaveToFile(extractionFolder + "tags.xml", document->toString());
461
void Archive::importArchivedBackgroundImages(const QString &extractionFolder)
463
FormatImporter copier; // Only used to copy files synchronously
464
QString destFolder = KGlobal::dirs()->saveLocation("data", "basket/backgrounds/");
466
QDir dir(extractionFolder + "backgrounds/", /*nameFilder=*/"*.png", /*sortSpec=*/QDir::Name | QDir::IgnoreCase, /*filterSpec=*/QDir::Files | QDir::NoSymLinks);
467
QStringList files = dir.entryList();
468
for (QStringList::Iterator it = files.begin(); it != files.end(); ++it) {
470
if (!Global::backgroundManager->exists(image)) {
472
QString imageSource = extractionFolder + "backgrounds/" + image;
473
QString imageDest = destFolder + image;
474
copier.copyFolder(imageSource, imageDest);
475
// Copy configuration file:
476
QString configSource = extractionFolder + "backgrounds/" + image + ".config";
477
QString configDest = destFolder + image;
478
if (dir.exists(configSource))
479
copier.copyFolder(configSource, configDest);
481
QString previewSource = extractionFolder + "backgrounds/previews/" + image;
482
QString previewDest = destFolder + "previews/" + image;
483
if (dir.exists(previewSource)) {
484
dir.mkdir(destFolder + "previews/"); // Make sure the folder exists!
485
copier.copyFolder(previewSource, previewDest);
487
// Append image to database:
488
Global::backgroundManager->addImage(imageDest);
493
void Archive::renameBasketFolders(const QString &extractionFolder, QMap<QString, QString> &mergedStates)
495
QDomDocument *doc = XMLWork::openFile("basketTree", extractionFolder + "baskets/baskets.xml");
497
QMap<QString, QString> folderMap;
498
QDomElement docElem = doc->documentElement();
499
QDomNode node = docElem.firstChild();
500
renameBasketFolder(extractionFolder, node, folderMap, mergedStates);
501
loadExtractedBaskets(extractionFolder, node, folderMap, 0);
505
void Archive::renameBasketFolder(const QString &extractionFolder, QDomNode &basketNode, QMap<QString, QString> &folderMap, QMap<QString, QString> &mergedStates)
507
QDomNode n = basketNode;
508
while ( ! n.isNull() ) {
509
QDomElement element = n.toElement();
510
if ( (!element.isNull()) && element.tagName() == "basket" ) {
511
QString folderName = element.attribute("folderName");
512
if (!folderName.isEmpty()) {
513
// Find a folder name:
514
QString newFolderName = BasketFactory::newFolderName();
515
folderMap[folderName] = newFolderName;
516
// Reserve the folder name:
518
dir.mkdir(Global::basketsFolder() + newFolderName);
519
// Rename the merged tag ids:
520
// if (mergedStates.count() > 0) {
521
renameMergedStatesAndBasketIcon(extractionFolder + "baskets/" + folderName + ".basket", mergedStates, extractionFolder);
524
QDomNode node = element.firstChild();
525
renameBasketFolder(extractionFolder, node, folderMap, mergedStates);
532
void Archive::renameMergedStatesAndBasketIcon(const QString &fullPath, QMap<QString, QString> &mergedStates, const QString &extractionFolder)
534
QDomDocument *doc = XMLWork::openFile("basket", fullPath);
537
QDomElement docElem = doc->documentElement();
538
QDomElement properties = XMLWork::getElement(docElem, "properties");
539
importBasketIcon(properties, extractionFolder);
540
QDomElement notes = XMLWork::getElement(docElem, "notes");
541
if (mergedStates.count() > 0)
542
renameMergedStates(notes, mergedStates);
543
Basket::safelySaveToFile(fullPath, /*"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + */doc->toString());
546
void Archive::importBasketIcon(QDomElement properties, const QString &extractionFolder)
548
QString iconName = XMLWork::getElementText(properties, "icon");
549
if (!iconName.isEmpty() && iconName != "basket") {
550
QPixmap icon = kapp->iconLoader()->loadIcon(iconName, KIcon::NoGroup, 16, KIcon::DefaultState, 0L, /*canReturnNull=*/true);
551
// The icon does not exists on that computer, import it:
554
dir.mkdir(Global::savesFolder() + "basket-icons/");
555
FormatImporter copier; // Only used to copy files synchronously
556
// Of the icon path was eg. "/home/seb/icon.png", it was exported as "basket-icons/_home_seb_icon.png".
557
// So we need to copy that image to "~/.kde/share/apps/basket/basket-icons/icon.png":
558
int slashIndex = iconName.findRev("/");
559
QString iconFileName = (slashIndex < 0 ? iconName : iconName.right(slashIndex - 2));
560
QString source = extractionFolder + "basket-icons/" + iconName.replace('/', '_');
561
QString destination = Global::savesFolder() + "basket-icons/" + iconFileName;
562
if (!dir.exists(destination))
563
copier.copyFolder(source, destination);
564
// Replace the emblem path in the tags.xml copy:
565
QDomElement iconElement = XMLWork::getElement(properties, "icon");
566
properties.removeChild(iconElement);
567
QDomDocument document = properties.ownerDocument();
568
XMLWork::addElement(document, properties, "icon", destination);
573
void Archive::renameMergedStates(QDomNode notes, QMap<QString, QString> &mergedStates)
575
QDomNode n = notes.firstChild();
576
while ( ! n.isNull() ) {
577
QDomElement element = n.toElement();
578
if (!element.isNull()) {
579
if (element.tagName() == "group" ) {
580
renameMergedStates(n, mergedStates);
581
} else if (element.tagName() == "note") {
582
QString tags = XMLWork::getElementText(element, "tags");
583
if (!tags.isEmpty()) {
584
QStringList tagNames = QStringList::split(";", tags);
585
for (QStringList::Iterator it = tagNames.begin(); it != tagNames.end(); ++it) {
587
if (mergedStates.contains(tag)) {
588
tag = mergedStates[tag];
591
QString newTags = tagNames.join(";");
592
QDomElement tagsElement = XMLWork::getElement(element, "tags");
593
element.removeChild(tagsElement);
594
QDomDocument document = element.ownerDocument();
595
XMLWork::addElement(document, element, "tags", newTags);
603
void Archive::loadExtractedBaskets(const QString &extractionFolder, QDomNode &basketNode, QMap<QString, QString> &folderMap, Basket *parent)
605
bool basketSetAsCurrent = (parent != 0);
606
QDomNode n = basketNode;
607
while ( ! n.isNull() ) {
608
QDomElement element = n.toElement();
609
if ( (!element.isNull()) && element.tagName() == "basket" ) {
610
QString folderName = element.attribute("folderName");
611
if (!folderName.isEmpty()) {
612
// Move the basket folder to its destination, while renaming it uniquely:
613
QString newFolderName = folderMap[folderName];
614
FormatImporter copier;
615
// The folder has been "reserved" by creating it. Avoid asking the user to override:
617
dir.rmdir(Global::basketsFolder() + newFolderName);
618
copier.moveFolder(extractionFolder + "baskets/" + folderName, Global::basketsFolder() + newFolderName);
619
// Append and load the basket in the tree:
620
Basket *basket = Global::bnpView->loadBasket(newFolderName);
621
BasketListViewItem *basketItem = Global::bnpView->appendBasket(basket, (basket && parent ? Global::bnpView->listViewItemForBasket(parent) : 0));
622
basketItem->setOpen(!XMLWork::trueOrFalse(element.attribute("folded", "false"), false));
623
QDomElement properties = XMLWork::getElement(element, "properties");
624
importBasketIcon(properties, extractionFolder); // Rename the icon fileName if necessary
625
basket->loadProperties(properties);
626
// Open the first basket of the archive:
627
if (!basketSetAsCurrent) {
628
Global::bnpView->setCurrentBasket(basket);
629
basketSetAsCurrent = true;
631
QDomNode node = element.firstChild();
632
loadExtractedBaskets(extractionFolder, node, folderMap, basket);