File indexing completed on 2024-04-21 03:49:30
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2010 Bastian Holst <bastianholst@gmx.de> 0004 // 0005 0006 // Self 0007 #include "DataMigration.h" 0008 0009 // Marble 0010 #include "MarbleDebug.h" 0011 #include "MarbleDirs.h" 0012 #include "ui_DataMigrationWidget.h" 0013 0014 // Qt 0015 #include <QDebug> 0016 #include <QDir> 0017 #include <QDirIterator> 0018 #include <QPointer> 0019 #include <QStack> 0020 #include <QDialog> 0021 #include <QProgressDialog> 0022 0023 // std 0024 #include <limits> 0025 0026 namespace Marble 0027 { 0028 0029 DataMigration::DataMigration( QObject *parent ) 0030 : QObject( parent ) 0031 { 0032 } 0033 0034 DataMigration::~DataMigration() 0035 { 0036 } 0037 0038 void DataMigration::exec() 0039 { 0040 QStringList oldLocalPaths = MarbleDirs::oldLocalPaths(); 0041 0042 if( oldLocalPaths.isEmpty() ) { 0043 return; 0044 } 0045 0046 QString currentLocalPath = MarbleDirs::localPath(); 0047 QDir currentLocalDir( currentLocalPath ); 0048 if( currentLocalDir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot ).size() != 0 ) { 0049 return; 0050 } 0051 0052 for( const QString& oldLocalPath: oldLocalPaths ) { 0053 QDir oldLocalDir( oldLocalPath ); 0054 0055 if( oldLocalDir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot ).size() == 0 ) { 0056 continue; 0057 } 0058 0059 QPointer<QDialog> dialog = new QDialog(); 0060 Ui::DataMigrationWidget dataMigrationWidget; 0061 0062 dataMigrationWidget.setupUi( dialog ); 0063 if( dialog->exec() == QDialog::Accepted ) { 0064 DataMigration::moveFiles( oldLocalPath, currentLocalPath ); 0065 } 0066 delete dialog; 0067 0068 return; 0069 } 0070 } 0071 0072 void DataMigration::moveFiles( const QString& source, const QString& target ) 0073 { 0074 if( !QDir().rmdir( target ) ) { 0075 mDebug() << "Removing of the target directory failed"; 0076 } 0077 0078 // Trying to simply rename the directory. This is the fastest method, but it is not always 0079 // possible. For example when the directories are on different file systems. 0080 // If the renaming of the directory is not successful, we have to copy and delete each 0081 // file separately. 0082 mDebug() << "Rename" << source << "to" << target; 0083 if( !QDir().rename( source, target ) ) { 0084 mDebug() << "Simple renaming of the data directory failed. Moving single files"; 0085 0086 QProgressDialog progressDialog; 0087 progressDialog.setWindowModality( Qt::WindowModal ); 0088 progressDialog.setMinimum( 0 ); 0089 progressDialog.setMaximum( std::numeric_limits<int>::max() ); 0090 progressDialog.setAutoReset( false ); 0091 progressDialog.setAutoClose( false ); 0092 progressDialog.setWindowTitle( tr( "Marble data conversion" ) ); 0093 progressDialog.setLabelText( tr( "Converting data ..." ) ); 0094 0095 QDir().mkpath( target ); 0096 QString sourcePath = QDir( source ).canonicalPath(); 0097 int sourcePathLength = sourcePath.length(); 0098 0099 // Running through all files recursively 0100 QStack<QString> dirs; 0101 dirs.push( sourcePath ); 0102 0103 QStack<int> progressSliceSizeStack; 0104 progressSliceSizeStack.push( progressDialog.maximum() ); 0105 int progress = 0; 0106 0107 while( !dirs.isEmpty() ) { 0108 if( progressDialog.wasCanceled() ) { 0109 return; 0110 } 0111 0112 QString sourceDirPath = dirs.top(); 0113 mDebug() << "DataMigration: Current source dir path =" 0114 << sourceDirPath; 0115 mDebug() << "SliceSize =" << progressSliceSizeStack.top(); 0116 0117 if( !sourceDirPath.startsWith( sourcePath ) ) { 0118 dirs.pop(); 0119 progress += progressSliceSizeStack.pop(); 0120 progressDialog.setValue( progress ); 0121 continue; 0122 } 0123 0124 QDir sourceDir( sourceDirPath ); 0125 // Creating child file/dir lists. 0126 QStringList files = sourceDir.entryList( QDir::Files 0127 | QDir::NoSymLinks 0128 | QDir::NoDotAndDotDot ); 0129 QStringList childDirs = sourceDir.entryList( QDir::Dirs 0130 | QDir::NoSymLinks 0131 | QDir::NoDotAndDotDot ); 0132 int childSliceSize = 0; 0133 if( !childDirs.isEmpty() ) { 0134 childSliceSize = progressSliceSizeStack.pop() / childDirs.size(); 0135 progressSliceSizeStack.push( 0 ); 0136 } 0137 0138 if( files.isEmpty() && childDirs.isEmpty() ) 0139 { 0140 // Remove empty directory 0141 mDebug() << "DataMigration:" << dirs.top() 0142 << "finished"; 0143 QDir().rmdir( dirs.pop() ); 0144 progress += progressSliceSizeStack.pop(); 0145 progressDialog.setValue( progress ); 0146 } 0147 else { 0148 // Add child directories to the stack 0149 for( const QString& childDir: childDirs ) { 0150 dirs.push(sourceDirPath + QLatin1Char('/') + childDir); 0151 progressSliceSizeStack.push( childSliceSize ); 0152 } 0153 0154 // Creating target dir 0155 QString targetDirPath = sourceDirPath; 0156 targetDirPath.remove( 0, sourcePathLength ); 0157 targetDirPath.prepend( target ); 0158 QDir().mkpath( targetDirPath ); 0159 0160 // Copying contents 0161 for( const QString& file: files ) { 0162 if( progressDialog.wasCanceled() ) { 0163 return; 0164 } 0165 0166 const QString sourceFilePath = sourceDirPath + QLatin1Char('/') + file; 0167 0168 if( !sourceFilePath.startsWith( sourcePath ) ) { 0169 continue; 0170 } 0171 0172 QString targetFilePath = sourceFilePath; 0173 targetFilePath.remove( 0, sourcePathLength ); 0174 targetFilePath.prepend( target ); 0175 0176 QFile::copy( sourceFilePath, targetFilePath ); 0177 QFile::remove( sourceFilePath ); 0178 } 0179 } 0180 } 0181 } 0182 } 0183 0184 } 0185 0186 #include "moc_DataMigration.cpp"