#pragma once #include "javaruntime.h" #include #include #include #include #include #include #include #include class QJsonObject; class QNetworkAccessManager; class QNetworkReply; class QProcess; class QSaveFile; class QTimer; struct ZipExtraction; struct JavaFileTask { QUrl url; QString path; // абсолютный путь назначения QString sha1; qint64 size = 0; bool executable = false; int attempts = 0; }; struct JavaActiveDownload { JavaFileTask task; QNetworkReply *reply = nullptr; std::unique_ptr file; QCryptographicHash hash{QCryptographicHash::Sha1}; qint64 received = 0; }; class JavaInstaller : public QObject { Q_OBJECT public: explicit JavaInstaller(QObject *parent = nullptr); ~JavaInstaller() override; bool isRunning() const { return m_running; } QString runtimeId() const { return m_entry.id; } QString label() const { return m_label; } QString stage() const { return m_stage; } QString currentFile() const { return m_currentFile; } qint64 bytesDone() const; qint64 bytesTotal() const { return m_bytesTotal; } double fraction() const; // 0..1, либо -1 пока итог неизвестен void install(const JavaRuntimeEntry &entry); void cancel(); signals: void started(const QString &label); void progressChanged(); void finished(const QString &runtimeId, const QString &javaPath); void failed(const QString &label, const QString &message); void canceled(const QString &label); private: // ── Общее ─────────────────────────────────────────────────────────── void beginArchive(); void beginMojang(); void complete(); void fail(const QString &message); void reset(); void setStage(const QString &stage); void scheduleProgress(); void flushProgress(); // ── Temurin ───────────────────────────────────────────────────────── void downloadArchive(); void handleArchiveFinished(QNetworkReply *reply); void startExtraction(); void extractZipChunk(); void startTarExtraction(); // ── Mojang ────────────────────────────────────────────────────────── void handleManifest(const QByteArray &payload); bool prepareTree(const QJsonObject &files); void pump(); void startTask(JavaFileTask task); void handleFileFinished(const std::shared_ptr &context); bool retryOrFail(JavaFileTask task, const QString &reason); bool applyLinks(); QNetworkAccessManager *m_network; JavaRuntimeEntry m_entry; QString m_label; QString m_targetDir; QString m_archivePath; QString m_stage; QString m_currentFile; qint64 m_bytesSettled = 0; qint64 m_bytesTotal = 0; int m_stepsDone = 0; int m_stepsTotal = 0; QNetworkReply *m_reply = nullptr; // архив или манифест std::unique_ptr m_archiveFile; QCryptographicHash m_archiveHash{QCryptographicHash::Sha256}; QProcess *m_tar = nullptr; QTimer *m_extractTimer; QTimer *m_progressTimer; bool m_progressDirty = false; std::unique_ptr m_zip; QQueue m_queue; QList> m_active; QList> m_links; bool m_running = false; bool m_canceling = false; };