Marble

DataMigration.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2010 Bastian Holst <bastianholst@gmx.de>
4//
5
6// Self
7#include "DataMigration.h"
8
9// Marble
10#include "MarbleDebug.h"
11#include "MarbleDirs.h"
12#include "ui_DataMigrationWidget.h"
13
14// Qt
15#include <QDebug>
16#include <QDialog>
17#include <QDir>
18#include <QDirIterator>
19#include <QPointer>
20#include <QProgressDialog>
21#include <QStack>
22
23// std
24#include <limits>
25
26namespace Marble
27{
28
29DataMigration::DataMigration(QObject *parent)
30 : QObject(parent)
31{
32}
33
34DataMigration::~DataMigration() = default;
35
36void DataMigration::exec()
37{
38 QStringList oldLocalPaths = MarbleDirs::oldLocalPaths();
39
40 if (oldLocalPaths.isEmpty()) {
41 return;
42 }
43
44 QString currentLocalPath = MarbleDirs::localPath();
45 QDir currentLocalDir(currentLocalPath);
46 if (currentLocalDir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot).size() != 0) {
47 return;
48 }
49
50 for (const QString &oldLocalPath : oldLocalPaths) {
51 QDir oldLocalDir(oldLocalPath);
52
53 if (oldLocalDir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot).size() == 0) {
54 continue;
55 }
56
57 QPointer<QDialog> dialog = new QDialog();
58 Ui::DataMigrationWidget dataMigrationWidget;
59
60 dataMigrationWidget.setupUi(dialog);
61 if (dialog->exec() == QDialog::Accepted) {
62 DataMigration::moveFiles(oldLocalPath, currentLocalPath);
63 }
64 delete dialog;
65
66 return;
67 }
68}
69
70void DataMigration::moveFiles(const QString &source, const QString &target)
71{
72 if (!QDir().rmdir(target)) {
73 mDebug() << "Removing of the target directory failed";
74 }
75
76 // Trying to simply rename the directory. This is the fastest method, but it is not always
77 // possible. For example when the directories are on different file systems.
78 // If the renaming of the directory is not successful, we have to copy and delete each
79 // file separately.
80 mDebug() << "Rename" << source << "to" << target;
81 if (!QDir().rename(source, target)) {
82 mDebug() << "Simple renaming of the data directory failed. Moving single files";
83
84 QProgressDialog progressDialog;
85 progressDialog.setWindowModality(Qt::WindowModal);
86 progressDialog.setMinimum(0);
87 progressDialog.setMaximum(std::numeric_limits<int>::max());
88 progressDialog.setAutoReset(false);
89 progressDialog.setAutoClose(false);
90 progressDialog.setWindowTitle(tr("Marble data conversion"));
91 progressDialog.setLabelText(tr("Converting data ..."));
92
93 QDir().mkpath(target);
94 QString sourcePath = QDir(source).canonicalPath();
95 int sourcePathLength = sourcePath.length();
96
97 // Running through all files recursively
98 QStack<QString> dirs;
99 dirs.push(sourcePath);
100
101 QStack<int> progressSliceSizeStack;
102 progressSliceSizeStack.push(progressDialog.maximum());
103 int progress = 0;
104
105 while (!dirs.isEmpty()) {
106 if (progressDialog.wasCanceled()) {
107 return;
108 }
109
110 QString sourceDirPath = dirs.top();
111 mDebug() << "DataMigration: Current source dir path =" << sourceDirPath;
112 mDebug() << "SliceSize =" << progressSliceSizeStack.top();
113
114 if (!sourceDirPath.startsWith(sourcePath)) {
115 dirs.pop();
116 progress += progressSliceSizeStack.pop();
117 progressDialog.setValue(progress);
118 continue;
119 }
120
121 QDir sourceDir(sourceDirPath);
122 // Creating child file/dir lists.
123 QStringList files = sourceDir.entryList(QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot);
124 QStringList childDirs = sourceDir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
125 int childSliceSize = 0;
126 if (!childDirs.isEmpty()) {
127 childSliceSize = progressSliceSizeStack.pop() / childDirs.size();
128 progressSliceSizeStack.push(0);
129 }
130
131 if (files.isEmpty() && childDirs.isEmpty()) {
132 // Remove empty directory
133 mDebug() << "DataMigration:" << dirs.top() << "finished";
134 QDir().rmdir(dirs.pop());
135 progress += progressSliceSizeStack.pop();
136 progressDialog.setValue(progress);
137 } else {
138 // Add child directories to the stack
139 for (const QString &childDir : childDirs) {
140 dirs.push(sourceDirPath + QLatin1Char('/') + childDir);
141 progressSliceSizeStack.push(childSliceSize);
142 }
143
144 // Creating target dir
145 QString targetDirPath = sourceDirPath;
146 targetDirPath.remove(0, sourcePathLength);
147 targetDirPath.prepend(target);
148 QDir().mkpath(targetDirPath);
149
150 // Copying contents
151 for (const QString &file : files) {
152 if (progressDialog.wasCanceled()) {
153 return;
154 }
155
156 const QString sourceFilePath = sourceDirPath + QLatin1Char('/') + file;
157
158 if (!sourceFilePath.startsWith(sourcePath)) {
159 continue;
160 }
161
162 QString targetFilePath = sourceFilePath;
163 targetFilePath.remove(0, sourcePathLength);
164 targetFilePath.prepend(target);
165
166 QFile::copy(sourceFilePath, targetFilePath);
167 QFile::remove(sourceFilePath);
168 }
169 }
170 }
171 }
172}
173
174}
175
176#include "moc_DataMigration.cpp"
KIOCORE_EXPORT SimpleJob * rmdir(const QUrl &url)
KIOCORE_EXPORT SimpleJob * rename(const QUrl &src, const QUrl &dest, JobFlags flags=DefaultFlags)
Binds a QML item to a specific geodetic location in screen coordinates.
QString canonicalPath() const const
bool mkpath(const QString &dirPath) const const
bool rmdir(const QString &dirName) const const
bool copy(const QString &fileName, const QString &newName)
bool remove()
bool isEmpty() const const
qsizetype size() const const
void setAutoClose(bool close)
void setAutoReset(bool reset)
void setLabelText(const QString &text)
void setMaximum(int maximum)
void setMinimum(int minimum)
void setValue(int progress)
void push(const T &t)
T & top()
qsizetype length() const const
QString & prepend(QChar ch)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
WindowModal
void setWindowModality(Qt::WindowModality windowModality)
void setWindowTitle(const QString &)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 8 2024 12:02:42 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.