Exemple #1
0
void BackupDialog::moveToAnotherFolder()
{
    KUrl selectedURL = KDirSelectDialog::selectDirectory(
                           /*startDir=*/Global::savesFolder(), /*localOnly=*/true, /*parent=*/0,
                           /*caption=*/i18n("Choose a Folder Where to Move Baskets"));

    if (!selectedURL.isEmpty()) {
        QString folder = selectedURL.path();
        QDir dir(folder);
        // The folder should not exists, or be empty (because KDirSelectDialog will likely create it anyway):
        if (dir.exists()) {
            // Get the content of the folder:
            QStringList content = dir.entryList();
            if (content.count() > 2) { // "." and ".."
                int result = KMessageBox::questionYesNo(
                                 0,
                                 "<qt>" + i18n("The folder <b>%1</b> is not empty. Do you want to override it?", folder),
                                 i18n("Override Folder?"),
                                 KGuiItem(i18n("&Override"), "document-save")
                             );
                if (result == KMessageBox::No)
                    return;
            }
            Tools::deleteRecursively(folder);
        }
        FormatImporter copier;
        copier.moveFolder(Global::savesFolder(), folder);
        Backup::setFolderAndRestart(folder, i18n("Your baskets have been successfully moved to <b>%1</b>. %2 is going to be restarted to take this change into account."));
    }
}
Exemple #2
0
void Archive::loadExtractedBaskets(const QString &extractionFolder, QDomNode &basketNode, QMap<QString, QString> &folderMap, Basket *parent)
{
	bool basketSetAsCurrent = (parent != 0);
	QDomNode n = basketNode;
	while ( ! n.isNull() ) {
		QDomElement element = n.toElement();
		if ( (!element.isNull()) && element.tagName() == "basket" ) {
			QString folderName = element.attribute("folderName");
			if (!folderName.isEmpty()) {
				// Move the basket folder to its destination, while renaming it uniquely:
				QString newFolderName = folderMap[folderName];
				FormatImporter copier;
				// The folder has been "reserved" by creating it. Avoid asking the user to override:
				QDir dir;
				dir.rmdir(Global::basketsFolder() + newFolderName);
				copier.moveFolder(extractionFolder + "baskets/" + folderName, Global::basketsFolder() + newFolderName);
				// Append and load the basket in the tree:
				Basket *basket = Global::bnpView->loadBasket(newFolderName);
				BasketListViewItem *basketItem = Global::bnpView->appendBasket(basket, (basket && parent ? Global::bnpView->listViewItemForBasket(parent) : 0));
				basketItem->setExpanded(!XMLWork::trueOrFalse(element.attribute("folded", "false"), false));
				QDomElement properties = XMLWork::getElement(element, "properties");
				importBasketIcon(properties, extractionFolder); // Rename the icon fileName if necessary
				basket->loadProperties(properties);
				// Open the first basket of the archive:
				if (!basketSetAsCurrent) {
					Global::bnpView->setCurrentBasket(basket);
					basketSetAsCurrent = true;
				}
				QDomNode node = element.firstChild();
				loadExtractedBaskets(extractionFolder, node, folderMap, basket);
			}
		}
		n = n.nextSibling();
	}
}
Exemple #3
0
void Archive::importBasketIcon(QDomElement properties, const QString &extractionFolder)
{
	QString iconName = XMLWork::getElementText(properties, "icon");
	if (!iconName.isEmpty() && iconName != "basket") {
		QPixmap icon = KIconLoader::global()->loadIcon(
            iconName, KIconLoader::NoGroup, 16, KIconLoader::DefaultState,
            QStringList(), 0L, /*canReturnNull=*/true
            );
		// The icon does not exists on that computer, import it:
		if (icon.isNull()) {
			QDir dir;
			dir.mkdir(Global::savesFolder() + "basket-icons/");
			FormatImporter copier; // Only used to copy files synchronously
			// Of the icon path was eg. "/home/seb/icon.png", it was exported as "basket-icons/_home_seb_icon.png".
			// So we need to copy that image to "~/.kde/share/apps/basket/basket-icons/icon.png":
			int slashIndex = iconName.lastIndexOf('/');
			QString iconFileName = (slashIndex < 0 ? iconName : iconName.right(slashIndex - 2));
			QString source       = extractionFolder + "basket-icons/" + iconName.replace('/', '_');
			QString destination = Global::savesFolder() + "basket-icons/" + iconFileName;
			if (!dir.exists(destination))
				copier.copyFolder(source, destination);
			// Replace the emblem path in the tags.xml copy:
			QDomElement iconElement = XMLWork::getElement(properties, "icon");
			properties.removeChild(iconElement);
			QDomDocument document = properties.ownerDocument();
			XMLWork::addElement(document, properties, "icon", destination);
		}
	}
}
Exemple #4
0
void Archive::importArchivedBackgroundImages(const QString &extractionFolder)
{
	FormatImporter copier; // Only used to copy files synchronously
	QString destFolder = KGlobal::dirs()->saveLocation("data", "basket/backgrounds/");

	QDir dir(extractionFolder + "backgrounds/", /*nameFilder=*/"*.png", /*sortSpec=*/QDir::Name | QDir::IgnoreCase, /*filterSpec=*/QDir::Files | QDir::NoSymLinks);
	QStringList files = dir.entryList();
	for (QStringList::Iterator it = files.begin(); it != files.end(); ++it) {
		QString image = *it;
		if (!Global::backgroundManager->exists(image)) {
			// Copy images:
			QString imageSource = extractionFolder + "backgrounds/" + image;
			QString imageDest   = destFolder + image;
			copier.copyFolder(imageSource, imageDest);
			// Copy configuration file:
			QString configSource = extractionFolder + "backgrounds/" + image + ".config";
			QString configDest   = destFolder + image;
			if (dir.exists(configSource))
				copier.copyFolder(configSource, configDest);
			// Copy preview:
			QString previewSource = extractionFolder + "backgrounds/previews/" + image;
			QString previewDest   = destFolder + "previews/" + image;
			if (dir.exists(previewSource)) {
				dir.mkdir(destFolder + "previews/"); // Make sure the folder exists!
				copier.copyFolder(previewSource, previewDest);
			}
			// Append image to database:
			Global::backgroundManager->addImage(imageDest);
		}
	}
}
Exemple #5
0
/**
 * When opening a basket archive that come from another computer,
 * it can contains tags that use icons (emblems) that are not present on that computer.
 * Fortunately, basket archives contains a copy of every used icons.
 * This method check for every emblems and import the missing ones.
 * It also modify the tags.xml copy for the emblems to point to the absolute path of the impported icons.
 */
void Archive::importTagEmblems(const QString &extractionFolder)
{
	QDomDocument *document = XMLWork::openFile("basketTags", extractionFolder + "tags.xml");
	if (document == 0)
		return;
	QDomElement docElem = document->documentElement();

	QDir dir;
	dir.mkdir(Global::savesFolder() + "tag-emblems/");
	FormatImporter copier; // Only used to copy files synchronously

	QDomNode node = docElem.firstChild();
	while (!node.isNull()) {
		QDomElement element = node.toElement();
		if ( (!element.isNull()) && element.tagName() == "tag" ) {
			QDomNode subNode = element.firstChild();
			while (!subNode.isNull()) {
				QDomElement subElement = subNode.toElement();
				if ( (!subElement.isNull()) && subElement.tagName() == "state" ) {
					QString emblemName = XMLWork::getElementText(subElement, "emblem");
					if (!emblemName.isEmpty()) {
						QPixmap emblem = KIconLoader::global()->loadIcon(emblemName, KIconLoader::NoGroup, 16, KIconLoader::DefaultState,  QStringList(), 0L, /*canReturnNull=*/true);
						// The icon does not exists on that computer, import it:
						if (emblem.isNull()) {
							// Of the emblem path was eg. "/home/seb/emblem.png", it was exported as "tag-emblems/_home_seb_emblem.png".
							// So we need to copy that image to "~/.kde/share/apps/basket/tag-emblems/emblem.png":
							int slashIndex = emblemName.lastIndexOf('/');
							QString emblemFileName = (slashIndex < 0 ? emblemName : emblemName.right(slashIndex - 2));
							QString source      = extractionFolder + "tag-emblems/" + emblemName.replace('/', '_');
							QString destination = Global::savesFolder() + "tag-emblems/" + emblemFileName;
							if (!dir.exists(destination) && dir.exists(source))
								copier.copyFolder(source, destination);
							// Replace the emblem path in the tags.xml copy:
							QDomElement emblemElement = XMLWork::getElement(subElement, "emblem");
							subElement.removeChild(emblemElement);
							XMLWork::addElement(*document, subElement, "emblem", destination);
						}
					}
				}
				subNode = subNode.nextSibling();
			}
		}
		node = node.nextSibling();
	}
	Basket::safelySaveToFile(extractionFolder + "tags.xml", document->toString());
}
Exemple #6
0
void BackupDialog::restore()
{
    // Get last backup folder:
    KConfig *config = KGlobal::config().data();
    KConfigGroup configGroup(config, "Backups");
    QString folder = configGroup.readEntry("lastFolder", QDir::homePath()) + "/";

    // Ask a file name to the user:
    QString filter = "*.tar.gz|" + i18n("Tar Archives Compressed by Gzip") + "\n*|" + i18n("All Files");
    QString path = KFileDialog::getOpenFileName(folder, filter, this, i18n("Open Basket Archive"));
    if (path.isEmpty()) // User has canceled
        return;

    // Before replacing the basket data folder with the backup content, we safely backup the current baskets to the home folder.
    // So if the backup is corrupted or something goes wrong while restoring (power cut...) the user will be able to restore the old working data:
    QString safetyPath = Backup::newSafetyFolder();
    FormatImporter copier;
    copier.moveFolder(Global::savesFolder(), safetyPath);

    // Add the README file for user to cancel a bad restoration:
    QString readmePath = safetyPath + i18n("README.txt");
    QFile file(readmePath);
    if (file.open(QIODevice::WriteOnly)) {
        QTextStream stream(&file);
        stream << i18n("This is a safety copy of your baskets like they were before you started to restore the backup %1.", KUrl(path).fileName()) + "\n\n"
        << i18n("If the restoration was a success and you restored what you wanted to restore, you can remove this folder.") + "\n\n"
        << i18n("If something went wrong during the restoration process, you can re-use this folder to store your baskets and nothing will be lost.") + "\n\n"
        << i18n("Choose \"Basket\" -> \"Backup & Restore...\" -> \"Use Another Existing Folder...\" and select that folder.") + "\n";
        file.close();
    }

    QString message =
        "<p><nobr>" + i18n("Restoring <b>%1</b>. Please wait...", KUrl(path).fileName()) + "</nobr></p><p>" +
        i18n("If something goes wrong during the restoration process, read the file <b>%1</b>.", readmePath);

    KProgressDialog *dialog = new KProgressDialog(0, i18n("Restore Baskets"), message);
    dialog->setModal(/*modal=*/true);
    dialog->setAllowCancel(false);
    dialog->setAutoClose(true);
    dialog->show();
    QProgressBar *progress = dialog->progressBar();
    progress->setRange(0, 0/*Busy/Undefined*/);
    progress->setValue(0);
    progress->setTextVisible(false);

    // Uncompress:
    RestoreThread thread(path, Global::savesFolder());
    thread.start();
    while (thread.isRunning()) {
        progress->setValue(progress->value() + 1); // Or else, the animation is not played!
        kapp->processEvents();
        usleep(300); // Not too long because if the restore process is finished, we wait for nothing
    }

    dialog->hide(); // The restore is finished, do not continue to show it while telling the user the application is going to be restarted
    delete dialog; // If we only hidden it, it reappeared just after having restored a small backup... Very strange.
    dialog = 0;    // This was annoying since it is modal and the "BasKet Note Pads is going to be restarted" message was not reachable.
    //kapp->processEvents();

    // Check for errors:
    if (!thread.success()) {
        // Restore the old baskets:
        QDir dir;
        dir.remove(readmePath);
        copier.moveFolder(safetyPath, Global::savesFolder());
        // Tell the user:
        KMessageBox::error(0, i18n("This archive is either not a backup of baskets or is corrupted. It cannot be imported. Your old baskets have been preserved instead."), i18n("Restore Error"));
        return;
    }

    // Note: The safety backup is not removed now because the code can has been wrong, somehow, or the user perhapse restored an older backup by error...
    //       The restore process will not be called very often (it is possible it will only be called once or twice arround the world during the next years).
    //       So it is rare enough to force the user to remove the safety folder, but keep him in control and let him safely recover from restoration errors.

    Backup::setFolderAndRestart(Global::savesFolder()/*No change*/, i18n("Your backup has been successfuly restored to <b>%1</b>. %2 is going to be restarted to take this change into account."));
}
Exemple #7
0
void FormatImporter::importBaskets()
{
	kDebug() << "Import Baskets: Preparing...";

	// Some preliminary preparations (create the destination folders and the basket tree file):
	QDir dirPrep;
	dirPrep.mkdir(Global::savesFolder());
	dirPrep.mkdir(Global::basketsFolder());
	QDomDocument document("basketTree");
	QDomElement root = document.createElement("basketTree");
	document.appendChild(root);

	// First up, establish a list of every baskets, ensure the old order (if any), and count them.
	QStringList baskets;

	// Read the 0.5.0 baskets order:
	QDomDocument *doc = XMLWork::openFile("container", Global::savesFolder() + "container.baskets");
	if (doc != 0) {
		QDomElement docElem = doc->documentElement();
		QDomElement basketsElem = XMLWork::getElement(docElem, "baskets");
		QDomNode n = basketsElem.firstChild();
		while (!n.isNull()) {
			QDomElement e = n.toElement();
			if ((!e.isNull()) && e.tagName() == "basket")
				baskets.append(e.text());
			n = n.nextSibling();
		}
	}

	// Then load the baskets that weren't loaded (import < 0.5.0 ones):
	QDir dir(Global::savesFolder(), QString::null, QDir::Name | QDir::IgnoreCase, QDir::Dirs | QDir::NoSymLinks);
	QStringList list = dir.entryList();
	if (list.count() > 2) // Pass "." and ".."
		for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) // For each folder
			if (*it != "." && *it != ".." && dir.exists(Global::savesFolder() + *it + "/.basket")) // If it can be a basket folder
				if (! (baskets.contains((*it) + "/")) && baskets.contains(*it) ) // And if it is not already in the imported baskets list
					baskets.append(*it);

	kDebug() << "Import Baskets: Found " << baskets.count() << " baskets to import.";

	// Import every baskets:
	int i = 0;
	for (QStringList::iterator it = baskets.begin(); it != baskets.end(); ++it) {
		++i;
		kDebug() << "Import Baskets: Importing basket " << i << " of " << baskets.count() << "...";

		// Move the folder to the new repository (normal basket) or copy the folder (mirorred folder):
		QString folderName = *it;
		if (folderName.startsWith("/")) { // It was a folder mirror:
			KMessageBox::information(0, i18n("<p>Folder mirroring is not possible anymore (see <a href='http://basket.kde.org/'>basket.kde.org</a> for more information).</p>"
				"<p>The folder <b>%1</b> has been copied for the basket needs. You can either delete this folder or delete the basket, or use both. But remember that "
				"modifying one will not modify the other anymore as they are now separate entities.</p>", folderName), i18n("Folder Mirror Import"),
				"", KMessageBox::AllowLink);
			// Also modify folderName to be only the folder name and not the full path anymore:
			QString newFolderName = folderName;
			if (newFolderName.endsWith("/"))
				newFolderName = newFolderName.left(newFolderName.length() - 1);
			newFolderName = newFolderName.mid(newFolderName.lastIndexOf('/') + 1);
			newFolderName = Tools::fileNameForNewFile(newFolderName, Global::basketsFolder());
			FormatImporter f;
			f.copyFolder(folderName, Global::basketsFolder() + newFolderName);
			folderName = newFolderName;
		} else
			dir.rename(Global::savesFolder() + folderName, Global::basketsFolder() + folderName); // Move the folder

		// Import the basket structure file and get the properties (to add them in the tree basket-properties cache):
		QDomElement properties = importBasket(folderName);

		// Add it to the XML document:
		QDomElement basketElement = document.createElement("basket");
		root.appendChild(basketElement);
		basketElement.setAttribute("folderName", folderName);
		basketElement.appendChild(properties);
	}

	// Finalize (write to disk and delete now useless files):
	kDebug() << "Import Baskets: Finalizing...";

	QFile file(Global::basketsFolder() + "baskets.xml");
	if (file.open(QIODevice::WriteOnly)) {
		QTextStream stream(&file);
		stream.setCodec("UTF-8");
		QString xml = document.toString();
		stream << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
		stream << xml;
		file.close();
	}

	Tools::deleteRecursively(Global::savesFolder() + ".tmp");
	dir.remove(Global::savesFolder() + "container.baskets");

	kDebug() << "Import Baskets: Finished.";
}