Skip to content

Commit

Permalink
drop legacy storage migration logic
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbruy committed Mar 27, 2023
1 parent 8b589be commit ad4fc79
Show file tree
Hide file tree
Showing 12 changed files with 0 additions and 493 deletions.
168 changes: 0 additions & 168 deletions app/androidutils.cpp
Expand Up @@ -18,14 +18,8 @@
#include <QFileInfo>
#include <QDir>
#include <QStandardPaths>
#include <QStorageInfo>

#include <QtConcurrent>
#include <QFuture>

#include "coreutils.h"
#include "inpututils.h"
#include "appsettings.h"
#endif

AndroidUtils::AndroidUtils( QObject *parent ): QObject( parent )
Expand Down Expand Up @@ -115,168 +109,6 @@ QString AndroidUtils::readExif( const QString &filePath, const QString &tag )
#endif
}

bool AndroidUtils::findLegacyFolder( QString &legacyFolderPath )
{
#ifdef ANDROID
legacyFolderPath = QStringLiteral();
QString dataPathRaw = QStringLiteral( "INPUT" );

QFileInfo extDir( "/sdcard/" );
if ( extDir.isDir() && extDir.isWritable() )
{
// seems that this directory transposes to the latter one in case there is no sdcard attached
dataPathRaw = extDir.path() + "/" + dataPathRaw;
QDir d( dataPathRaw );
if ( d.exists() )
{
legacyFolderPath = dataPathRaw;
return true;
}
}
else
{
CoreUtils::log( "$$: Migration", "Ext path " + extDir.path() + " is not readable!" );

QStringList split = QDir::homePath().split( "/" ); // something like /data/user/0/uk.co.lutraconsulting/files

QFileInfo usrDir( "/storage/emulated/" + split[2] + "/" );
dataPathRaw = usrDir.path() + "/" + dataPathRaw;

if ( usrDir.isDir() && usrDir.isWritable() )
{
QDir d( dataPathRaw );
if ( d.exists() )
{
legacyFolderPath = dataPathRaw;
return true;
}
}
}
#else
Q_UNUSED( legacyFolderPath );
#endif
return false;
}

void AndroidUtils::migrateLegacyProjects( const QString &legacyFolder, const QString &scopedStorageFolder )
{
#ifdef ANDROID
QString legacyFolderProjects = legacyFolder + QStringLiteral( "/projects" );
QString scopedStorageProjects = scopedStorageFolder + QStringLiteral( "/projects" );

CoreUtils::log( "LegacyFolderMigration", "Starting copy from:" + legacyFolderProjects + " to:" + scopedStorageProjects );

QDir legacyProjectsDir( legacyFolderProjects );
QStringList projectsToCopy = legacyProjectsDir.entryList( QDir::NoDotAndDotDot | QDir::Dirs | QDir::Hidden );

int cnt = 0;

emit migrationStarted( projectsToCopy.count() );
emit migrationProgressed( cnt );

for ( const QString &project : projectsToCopy )
{
bool copyResult = InputUtils::cpDir( legacyFolderProjects + "/" + project, scopedStorageProjects + "/" + project );
if ( !copyResult )
{
CoreUtils::log( "LegacyFolderMigration", "Could not copy project" + project + "!" );
emit migrationFinished( false );
return;
}

emit migrationProgressed( ++cnt );
}

// Final step: rename legacy folder to indicate that projects were successfully migrated
QDir legacyFolderDir( legacyFolder );
bool renameSuccessful = legacyFolderDir.rename( legacyFolder, legacyFolder + QStringLiteral( "_migrated" ) );
if ( !renameSuccessful )
{
CoreUtils::log( "LegacyFolderMigration", "Rename not successful, but data are copied" );
// Even though the folder is not renamed, it is copied, hence do not copy it again in future
emit migrationFinished( true );
return;
}

emit migrationFinished( true );
#else
Q_UNUSED( legacyFolder );
Q_UNUSED( scopedStorageFolder );
#endif
}

void AndroidUtils::handleLegacyFolderMigration( AppSettings *appsettings, bool demoProjectsCopiedThisRun )
{
#ifdef ANDROID
// Step 1: already migrated? - do not copy
if ( appsettings->legacyFolderMigrated() )
{
CoreUtils::log( "LegacyFolderMigration", "Ignoring legacy folder logic, already migrated!" );
return;
}

// Step 2: is this first run of application (after install or reset of all data)? - do not copy
if ( demoProjectsCopiedThisRun )
{
CoreUtils::log( "LegacyFolderMigration", "Ignoring legacy folder logic, just installed or removed app data!" );
appsettings->setLegacyFolderMigrated( true );
return;
}

// Step 3: make sure we have a WRITE permission to storage
// this check should not be that important since previous app versions could not run without this permission - all updated
// versions will thus have it granted. Anyways..
QFuture<QtAndroidPrivate::PermissionResult> res = QtAndroidPrivate::checkPermission( "android.permission.WRITE_EXTERNAL_STORAGE" );
res.waitForFinished();
if ( res.result() != QtAndroidPrivate::PermissionResult::Authorized )
{
if ( !checkAndAcquirePermissions( "android.permission.WRITE_EXTERNAL_STORAGE" ) )
{
showToast( tr( "Without storage permission you will not be able to access previous projects" ) );
CoreUtils::log( "LegacyFolderMigration", "Storage permission not granted after rationale, leaving!" );
return;
}
CoreUtils::log( "LegacyFolderMigration", "Storage permission granted after rationale, continuing!" );
}

// Step 4: check existence of legacy folder
QString legacyFolderPath;
bool containsLegacyFolder = findLegacyFolder( legacyFolderPath );

if ( !containsLegacyFolder )
{
appsettings->setLegacyFolderMigrated( true );
CoreUtils::log( "LegacyFolderMigration", "Could not find legacy folder" );
return;
}

// Step 5: is there enough space to copy the folder?
// https://doc.qt.io/qt-5/qstorageinfo.html
QDir legacyDir( legacyFolderPath );
QStorageInfo storage( legacyDir );

qint64 freeSpace = storage.bytesAvailable();
qint64 neededSpace = InputUtils::dirSize( legacyFolderPath );

if ( freeSpace < neededSpace )
{
emit notEnoughSpaceLeftToMigrate( InputUtils::bytesToHumanSize( neededSpace ) );
CoreUtils::log( "LegacyFolderMigration", "Device does not have enough space to copy the folder, needed: " + \
InputUtils::bytesToHumanSize( neededSpace ) + \
" free space: " + InputUtils::bytesToHumanSize( freeSpace ) );
return;
}

// Step 6: finally, let's copy the projects folder, project after project
QtConcurrent::run( &AndroidUtils::migrateLegacyProjects, this, legacyFolderPath, externalStorageAppFolder() );

CoreUtils::log( "LegacyFolderMigration", "Data migration has been sent to other thread!" );
#else
Q_UNUSED( appsettings );
Q_UNUSED( demoProjectsCopiedThisRun );
#endif
}

void AndroidUtils::turnBluetoothOn()
{
#ifdef ANDROID
Expand Down
15 changes: 0 additions & 15 deletions app/androidutils.h
Expand Up @@ -19,8 +19,6 @@
#endif
#include <QObject>

class AppSettings;

class AndroidUtils: public QObject
#ifdef ANDROID
, QAndroidActivityResultReceiver
Expand Down Expand Up @@ -50,13 +48,6 @@ class AndroidUtils: public QObject
bool requestCameraPermission();
bool requestMediaLocationPermission();

// Copies legacy app folder INPUT from external storage to app specific folder based on several rules.
// Returns true if migration has been done, false otherwise
void handleLegacyFolderMigration( AppSettings *appsettings, bool demoProjectsCopiedThisRun );

bool findLegacyFolder( QString &legacyFolderPath );
void migrateLegacyProjects( const QString &from, const QString &to );

void turnBluetoothOn();
bool isBluetoothTurnedOn();

Expand Down Expand Up @@ -85,11 +76,6 @@ class AndroidUtils: public QObject
signals:
void imageSelected( QString imagePath );

void migrationFinished( bool success );
void migrationProgressed( int progress );
void migrationStarted( int numOfProjectsToCopy );
void notEnoughSpaceLeftToMigrate( QString neededSpace );

void bluetoothEnabled( bool state );

void qrScanFinished( QString scanValue );
Expand All @@ -100,7 +86,6 @@ class AndroidUtils: public QObject
void showToast( QString message );

private:
bool mIsAndroid;

#ifdef ANDROID
QBluetoothLocalDevice mBluetooth;
Expand Down
34 changes: 0 additions & 34 deletions app/appsettings.cpp
Expand Up @@ -30,8 +30,6 @@ AppSettings::AppSettings( QObject *parent ): QObject( parent )
int streamingIntervalType = settings.value( "intervalType", 0 ).toInt();
StreamingIntervalType::IntervalType intervalType = static_cast<StreamingIntervalType::IntervalType>( streamingIntervalType );
bool reuseLastEnteredValues = settings.value( "reuseLastEnteredValues", false ).toBool();
QString savedAppVersion = settings.value( QStringLiteral( "appVersion" ), QStringLiteral() ).toString();
bool legacyFolderMigrated = settings.value( QStringLiteral( "legacyFolderMigrated" ), false ).toBool();
QString activeProviderId = settings.value( QStringLiteral( "activePositionProviderId" ) ).toString();
bool autosync = settings.value( QStringLiteral( "autosyncAllowed" ), false ).toBool();
bool ignoreWhatsNew = settings.value( QStringLiteral( "ignoreWhatsNew" ), false ).toBool();
Expand All @@ -49,8 +47,6 @@ AppSettings::AppSettings( QObject *parent ): QObject( parent )
setLineRecordingInterval( lineRecordingInterval );
setIntervalType( intervalType );
setReuseLastEnteredValues( reuseLastEnteredValues );
setAppVersion( savedAppVersion );
setLegacyFolderMigrated( legacyFolderMigrated );
setActivePositionProviderId( activeProviderId );
setAutosyncAllowed( autosync );
setIgnoreWhatsNew( ignoreWhatsNew );
Expand Down Expand Up @@ -220,36 +216,6 @@ void AppSettings::setGpsAccuracyWarning( bool gpsAccuracyWarning )
}
}

QString AppSettings::appVersion() const
{
return mAppVersion;
}

void AppSettings::setAppVersion( const QString &newAppVersion )
{
if ( mAppVersion == newAppVersion )
return;

mAppVersion = newAppVersion;
setValue( QStringLiteral( "appVersion" ), newAppVersion );
emit appVersionChanged( mAppVersion );
}

bool AppSettings::legacyFolderMigrated()
{
return mLegacyFolderMigrated;
}

void AppSettings::setLegacyFolderMigrated( bool hasBeenMigrated )
{
if ( mLegacyFolderMigrated == hasBeenMigrated )
return;

mLegacyFolderMigrated = hasBeenMigrated;
setValue( QStringLiteral( "legacyFolderMigrated" ), hasBeenMigrated );
emit legacyFolderMigratedChanged( mLegacyFolderMigrated );
}

const QString &AppSettings::activePositionProviderId() const
{
return mActivePositionProviderId;
Expand Down
19 changes: 0 additions & 19 deletions app/appsettings.h
Expand Up @@ -31,8 +31,6 @@ class AppSettings: public QObject
Q_PROPERTY( double gpsAccuracyTolerance READ gpsAccuracyTolerance WRITE setGpsAccuracyTolerance NOTIFY gpsAccuracyToleranceChanged )
Q_PROPERTY( bool gpsAccuracyWarning READ gpsAccuracyWarning WRITE setGpsAccuracyWarning NOTIFY gpsAccuracyWarningChanged )
Q_PROPERTY( bool reuseLastEnteredValues READ reuseLastEnteredValues WRITE setReuseLastEnteredValues NOTIFY reuseLastEnteredValuesChanged )
Q_PROPERTY( QString appVersion READ appVersion WRITE setAppVersion NOTIFY appVersionChanged )
Q_PROPERTY( bool legacyFolderMigrated READ legacyFolderMigrated WRITE setLegacyFolderMigrated NOTIFY legacyFolderMigratedChanged )
Q_PROPERTY( QString activePositionProviderId READ activePositionProviderId WRITE setActivePositionProviderId NOTIFY activePositionProviderIdChanged )
Q_PROPERTY( bool autosyncAllowed READ autosyncAllowed WRITE setAutosyncAllowed NOTIFY autosyncAllowedChanged )
Q_PROPERTY( bool ignoreWhatsNew READ ignoreWhatsNew WRITE setIgnoreWhatsNew NOTIFY ignoreWhatsNewChanged )
Expand Down Expand Up @@ -73,12 +71,6 @@ class AppSettings: public QObject
bool gpsAccuracyWarning() const;
void setGpsAccuracyWarning( bool gpsAccuracyWarning );

QString appVersion() const;
void setAppVersion( const QString &newAppVersion );

bool legacyFolderMigrated();
void setLegacyFolderMigrated( bool hasBeenMigrated );

// SavedPositionProviders property is read only when needed ~ not at startup time.
// It returns list of all external position providers (does not include internal/simulated position providers)
QVariantList savedPositionProviders() const;
Expand Down Expand Up @@ -118,8 +110,6 @@ class AppSettings: public QObject
void intervalTypeChanged();

void reuseLastEnteredValuesChanged( bool reuseLastEnteredValues );
void legacyFolderMigratedChanged( bool legacyFolderMigrated );
void appVersionChanged( const QString &version );
void activePositionProviderIdChanged( const QString & );

void autosyncAllowedChanged( bool autosyncAllowed );
Expand All @@ -141,15 +131,6 @@ class AppSettings: public QObject
// Digitizing period in seconds
int mLineRecordingInterval = 3;
StreamingIntervalType::IntervalType mIntervalType = StreamingIntervalType::IntervalType::Time;
// Application version, helps to differentiate between app installation, update or regular run:
// 1. if the value is null, this run is first after installation (or after user reset application data in settings)
// 2. if the value is different from current version, this is first run after update
// 3. if the value is the same as current version, this is regular run
// these check is possible to do during startup (in main.cpp)
QString mAppVersion;
// signalizes if application has already successfully migrated legacy Android folder
// this flag can be removed in future (prob. jan 2022), all users should have app version higher than 1.0.2 at that time
bool mLegacyFolderMigrated;

// Projects path -> defaultLayer name
QHash<QString, QString> mDefaultLayers;
Expand Down
29 changes: 0 additions & 29 deletions app/inpututils.cpp
Expand Up @@ -653,35 +653,6 @@ bool InputUtils::cpDir( const QString &srcPath, const QString &dstPath, bool onl
return result;
}

// https://stackoverflow.com/a/47854799/7875594
qint64 InputUtils::dirSize( const QString &path )
{
qint64 size = 0;
QDir dir( path );

if ( !dir.exists() )
{
return size;
}

QStringList subFiles = dir.entryList( QDir::Files | QDir::Hidden );

for ( QString filePath : subFiles )
{
QFileInfo fi( dir, filePath );
size += fi.size();
}

// add size of child directories recursively
QStringList subDirs = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden );

for ( QString subDirPath : subDirs )
{
size += dirSize( path + QDir::separator() + subDirPath );
}
return size;
}

QString InputUtils::renameWithDateTime( const QString &srcPath, const QDateTime &dateTime )
{
if ( QFile::exists( srcPath ) )
Expand Down
3 changes: 0 additions & 3 deletions app/inpututils.h
Expand Up @@ -150,9 +150,6 @@ class InputUtils: public QObject
*/
static bool cpDir( const QString &srcPath, const QString &dstPath, bool onlyDiffable = false );

// Returns size of directory in bytes, 0 if path does not exist
static qint64 dirSize( const QString &path );

static QString filesToString( QList<MerginFile> files );

/** InputApp platform */
Expand Down
17 changes: 0 additions & 17 deletions app/main.cpp
Expand Up @@ -715,23 +715,6 @@ int main( int argc, char *argv[] )
QNativeInterface::QAndroidApplication::hideSplashScreen();
#endif

// Android scoped storage migration logic
#ifdef ANDROID
QObject::connect( &au, &AndroidUtils::migrationFinished, [ &localProjectsManager, &as ]( bool success )
{
if ( success )
{
localProjectsManager.reloadDataDir();
}
as.setLegacyFolderMigrated( true );
} );

au.handleLegacyFolderMigration( &as, hasLoadedDemoProjects );
#endif

// save app version to settings
as.setAppVersion( version );

// Photos bigger that 512 MB (when uncompressed) will not load
QImageReader::setAllocationLimit( 512 );

Expand Down

1 comment on commit ad4fc79

@inputapp-bot
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iOS - version 23.03.418511 just submitted!

Please sign in to comment.