101 lines
4.0 KiB
C++
101 lines
4.0 KiB
C++
#pragma once
|
|
|
|
#include <QJsonObject>
|
|
#include <QObject>
|
|
#include <QString>
|
|
#include <QStringList>
|
|
|
|
class QThread;
|
|
class BuildArchiveWorker;
|
|
|
|
// Смена активной сборки: содержимое .minecraft уезжает в архив своей сборки,
|
|
// папка чистится, на её место разворачивается архив выбранной.
|
|
//
|
|
// Порядок шагов подчинён одному правилу: пока новый архив не записан целиком и
|
|
// не переименован на место, из .minecraft не удаляется ничего. Отметка о
|
|
// начатом переключении пишется в builds/index.json до первого разрушающего
|
|
// действия, поэтому обрыв питания или kill -9 всегда обнаружим на следующем
|
|
// запуске — см. recoverIfNeeded().
|
|
class BuildSwitcher : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit BuildSwitcher(QObject *parent = nullptr);
|
|
~BuildSwitcher() override;
|
|
|
|
bool isRunning() const { return m_state != Idle; }
|
|
QString stage() const { return m_stage; }
|
|
QString status() const { return m_status; }
|
|
double fraction() const; // 0..1, либо -1 пока итог неизвестен
|
|
|
|
// Общие для всех сборок каталоги: они не архивируются и не чистятся.
|
|
static QStringList sharedTopLevel();
|
|
|
|
void switchTo(int fromBuildId,
|
|
const QString &fromName,
|
|
int toBuildId,
|
|
const QString &toName,
|
|
const QString &gameDir);
|
|
void cancel();
|
|
|
|
// Сборку удалили: убираем её архив и запись о нём. Возвращает false, если
|
|
// папку архива не удалось удалить целиком.
|
|
bool forgetBuild(int buildId);
|
|
|
|
// Есть ли у сборки сохранённый архив (для текста предупреждения об удалении).
|
|
bool hasArchive(int buildId) const { return !archivePathOf(buildId).isEmpty(); }
|
|
|
|
// Незавершённое переключение с прошлого запуска. Возвращает пустую строку,
|
|
// если всё в порядке, иначе — текст для пользователя.
|
|
QString interruptedSwitchWarning() const;
|
|
// Доигрывает прерванное переключение: очистка и распаковка целевой сборки.
|
|
void resumeInterrupted(const QString &gameDir);
|
|
|
|
signals:
|
|
void progressChanged();
|
|
void finished(int toBuildId);
|
|
void failed(int toBuildId, const QString &message, bool gameDirIntact);
|
|
|
|
private:
|
|
enum State { Idle, Archiving, Clearing, Restoring };
|
|
|
|
// Сигналы к рабочему объекту в другом потоке.
|
|
void requestArchive(const QString &gameDir, const QString &tempZip, const QStringList &exclude);
|
|
void requestClear(const QString &gameDir, const QStringList &keep);
|
|
void requestRestore(const QString &zipPath, const QString &gameDir);
|
|
|
|
void onWorkerFinished(bool ok, const QString &error);
|
|
void onWorkerProgress(int done, int total, const QString ¤tPath);
|
|
|
|
void commitArchive();
|
|
void beginClearing();
|
|
void beginRestoring();
|
|
void finish();
|
|
void fail(const QString &message, bool gameDirIntact);
|
|
|
|
QString buildDir(int buildId) const;
|
|
QString archivePathOf(int buildId) const;
|
|
void setStage(const QString &stage);
|
|
|
|
QJsonObject readIndex() const;
|
|
void writeIndex(const QJsonObject &index) const;
|
|
void sweepTempArchives() const;
|
|
|
|
QThread *m_thread;
|
|
BuildArchiveWorker *m_worker;
|
|
|
|
State m_state = Idle;
|
|
QString m_stage;
|
|
QString m_status;
|
|
int m_done = 0;
|
|
int m_total = 0;
|
|
|
|
int m_fromId = -1;
|
|
int m_toId = -1;
|
|
QString m_fromName;
|
|
QString m_toName;
|
|
QString m_gameDir;
|
|
QString m_tempZip;
|
|
};
|