Made tar.gz parser
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
parent
ab7fc2e46c
commit
1a6dfd04d6
@ -869,6 +869,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
|||||||
m_metacache->addBase("translations", QDir("translations").absolutePath());
|
m_metacache->addBase("translations", QDir("translations").absolutePath());
|
||||||
m_metacache->addBase("icons", QDir("cache/icons").absolutePath());
|
m_metacache->addBase("icons", QDir("cache/icons").absolutePath());
|
||||||
m_metacache->addBase("meta", QDir("meta").absolutePath());
|
m_metacache->addBase("meta", QDir("meta").absolutePath());
|
||||||
|
m_metacache->addBase("java", QDir("cache/java").absolutePath());
|
||||||
m_metacache->Load();
|
m_metacache->Load();
|
||||||
qDebug() << "<> Cache initialized.";
|
qDebug() << "<> Cache initialized.";
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,14 @@ QVariant BaseVersionList::data(const QModelIndex& index, int role) const
|
|||||||
case TypeRole:
|
case TypeRole:
|
||||||
return version->typeString();
|
return version->typeString();
|
||||||
|
|
||||||
|
case JavaMajorRole: {
|
||||||
|
auto major = version->name();
|
||||||
|
if (major.startsWith("java")) {
|
||||||
|
major = "Java " + major.mid(4);
|
||||||
|
}
|
||||||
|
return major;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@ -112,5 +120,6 @@ QHash<int, QByteArray> BaseVersionList::roleNames() const
|
|||||||
roles.insert(PathRole, "path");
|
roles.insert(PathRole, "path");
|
||||||
roles.insert(JavaNameRole, "javaName");
|
roles.insert(JavaNameRole, "javaName");
|
||||||
roles.insert(CPUArchitectureRole, "architecture");
|
roles.insert(CPUArchitectureRole, "architecture");
|
||||||
|
roles.insert(JavaMajorRole, "javaMajor");
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@ class BaseVersionList : public QAbstractListModel {
|
|||||||
BranchRole,
|
BranchRole,
|
||||||
PathRole,
|
PathRole,
|
||||||
JavaNameRole,
|
JavaNameRole,
|
||||||
|
JavaMajorRole,
|
||||||
CPUArchitectureRole,
|
CPUArchitectureRole,
|
||||||
SortRole
|
SortRole
|
||||||
};
|
};
|
||||||
|
@ -24,6 +24,8 @@ set(CORE_SOURCES
|
|||||||
NullInstance.h
|
NullInstance.h
|
||||||
MMCZip.h
|
MMCZip.h
|
||||||
MMCZip.cpp
|
MMCZip.cpp
|
||||||
|
Untar.h
|
||||||
|
Untar.cpp
|
||||||
StringUtils.h
|
StringUtils.h
|
||||||
StringUtils.cpp
|
StringUtils.cpp
|
||||||
QVariantUtils.h
|
QVariantUtils.h
|
||||||
|
@ -276,6 +276,9 @@ bool ensureFolderPathExists(const QFileInfo folderPath)
|
|||||||
{
|
{
|
||||||
QDir dir;
|
QDir dir;
|
||||||
QString ensuredPath = folderPath.filePath();
|
QString ensuredPath = folderPath.filePath();
|
||||||
|
if (folderPath.exists())
|
||||||
|
return true;
|
||||||
|
|
||||||
bool success = dir.mkpath(ensuredPath);
|
bool success = dir.mkpath(ensuredPath);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
262
launcher/Untar.cpp
Normal file
262
launcher/Untar.cpp
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2023-2024 Trial97 <alexandru.tripon97@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#include "Untar.h"
|
||||||
|
#include <qfileinfo.h>
|
||||||
|
#include <qlogging.h>
|
||||||
|
#include <quagzipfile.h>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QString>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "FileSystem.h"
|
||||||
|
|
||||||
|
// adaptation of the:
|
||||||
|
// - https://github.com/madler/zlib/blob/develop/contrib/untgz/untgz.c
|
||||||
|
// - https://en.wikipedia.org/wiki/Tar_(computing)
|
||||||
|
// - https://github.com/euroelessar/cutereader/blob/master/karchive/src/ktar.cpp
|
||||||
|
|
||||||
|
#define BLOCKSIZE 512
|
||||||
|
#define SHORTNAMESIZE 100
|
||||||
|
|
||||||
|
enum class TypeFlag : char {
|
||||||
|
Regular = '0', // regular file
|
||||||
|
ARegular = 0, // regular file
|
||||||
|
Link = '1', // link
|
||||||
|
Symlink = '2', // reserved
|
||||||
|
Character = '3', // character special
|
||||||
|
Block = '4', // block special
|
||||||
|
Directory = '5', // directory
|
||||||
|
FIFO = '6', // FIFO special
|
||||||
|
Contiguous = '7', // reserved
|
||||||
|
// Posix stuff
|
||||||
|
GlobalPosixHeader = 'g',
|
||||||
|
ExtendedPosixHeader = 'x',
|
||||||
|
// 'A'– 'Z' Vendor specific extensions(POSIX .1 - 1988)
|
||||||
|
// GNU
|
||||||
|
GNULongLink = 'K', /* long link name */
|
||||||
|
GNULongName = 'L', /* long file name */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Header { /* byte offset */
|
||||||
|
char name[100]; /* 0 */
|
||||||
|
char mode[8]; /* 100 */
|
||||||
|
char uid[8]; /* 108 */
|
||||||
|
char gid[8]; /* 116 */
|
||||||
|
char size[12]; /* 124 */
|
||||||
|
char mtime[12]; /* 136 */
|
||||||
|
char chksum[8]; /* 148 */
|
||||||
|
TypeFlag typeflag; /* 156 */
|
||||||
|
char linkname[100]; /* 157 */
|
||||||
|
char magic[6]; /* 257 */
|
||||||
|
char version[2]; /* 263 */
|
||||||
|
char uname[32]; /* 265 */
|
||||||
|
char gname[32]; /* 297 */
|
||||||
|
char devmajor[8]; /* 329 */
|
||||||
|
char devminor[8]; /* 337 */
|
||||||
|
char prefix[155]; /* 345 */
|
||||||
|
/* 500 */
|
||||||
|
};
|
||||||
|
|
||||||
|
union Buffer {
|
||||||
|
char buffer[BLOCKSIZE];
|
||||||
|
struct Header header;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool readLonglink(QIODevice* in, Buffer buffer, QByteArray& longlink)
|
||||||
|
{
|
||||||
|
qint64 n = 0;
|
||||||
|
qint64 size = strtoll(buffer.header.size, NULL, 8);
|
||||||
|
size--; // ignore trailing null
|
||||||
|
if (errno == ERANGE) {
|
||||||
|
qCritical() << "The filename size can't be read";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (size < 0) {
|
||||||
|
qCritical() << "The filename size is negative";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
longlink.resize(size + (BLOCKSIZE - size % BLOCKSIZE)); // make the size divisible by BLOCKSIZE
|
||||||
|
for (qint64 offset = 0; offset < longlink.size(); offset += BLOCKSIZE) {
|
||||||
|
n = in->read(longlink.data() + offset, BLOCKSIZE);
|
||||||
|
if (n != BLOCKSIZE) {
|
||||||
|
qCritical() << "The expected blocksize was not respected for the name";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
longlink.truncate(qstrlen(longlink.constData()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Tar::extract(QIODevice* in, QString dst)
|
||||||
|
{
|
||||||
|
Buffer buffer;
|
||||||
|
QString name, symlink, firstFolderName;
|
||||||
|
bool doNotReset = false;
|
||||||
|
while (true) {
|
||||||
|
auto n = in->read(buffer.buffer, BLOCKSIZE);
|
||||||
|
if (n != BLOCKSIZE) { // allways expect complete blocks
|
||||||
|
qCritical() << "The expected blocksize was not respected";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (buffer.header.name[0] == 0) { // end of archive
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int mode = strtol(buffer.header.mode, NULL, 8) | QFile::ReadUser | QFile::WriteUser; // hack to ensure write and read permisions
|
||||||
|
if (errno == ERANGE) {
|
||||||
|
qCritical() << "The file mode can't be read";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// there are names that are exactly 100 bytes long
|
||||||
|
// and neither longlink nor \0 terminated (bug:101472)
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
name = QFile::decodeName(QByteArray(buffer.header.name, qstrnlen(buffer.header.name, 100)));
|
||||||
|
if (!firstFolderName.isEmpty() && name.startsWith(firstFolderName)) {
|
||||||
|
name = name.mid(firstFolderName.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (symlink.isEmpty())
|
||||||
|
symlink = QFile::decodeName(QByteArray(buffer.header.linkname, qstrnlen(buffer.header.linkname, 100)));
|
||||||
|
switch (buffer.header.typeflag) {
|
||||||
|
case TypeFlag::Regular:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::ARegular: {
|
||||||
|
auto fileName = FS::PathCombine(dst, name);
|
||||||
|
if (!FS::ensureFilePathExists(fileName)) {
|
||||||
|
qCritical() << "Can't ensure the file path to exist: " << fileName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QFile out(fileName);
|
||||||
|
if (!out.open(QFile::WriteOnly, QFile::Permission(mode))) {
|
||||||
|
qCritical() << "Can't open file:" << fileName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
qint64 size = strtoll(buffer.header.size, NULL, 8);
|
||||||
|
if (errno == ERANGE) {
|
||||||
|
qCritical() << "The file size can't be read";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (size > 0) {
|
||||||
|
QByteArray tmp(BLOCKSIZE, 0);
|
||||||
|
n = in->read(tmp.data(), BLOCKSIZE);
|
||||||
|
if (n != BLOCKSIZE) {
|
||||||
|
qCritical() << "The expected blocksize was not respected when reading file";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tmp.truncate(qMin(BLOCKSIZE, size));
|
||||||
|
out.write(tmp);
|
||||||
|
size -= BLOCKSIZE;
|
||||||
|
}
|
||||||
|
QFile::setPermissions(fileName, QFile::Permissions(mode));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeFlag::Directory: {
|
||||||
|
if (firstFolderName.isEmpty()) {
|
||||||
|
firstFolderName = name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto folderPath = FS::PathCombine(dst, name);
|
||||||
|
if (!FS::ensureFolderPathExists(folderPath)) {
|
||||||
|
qCritical() << "Can't ensure that folder exists: " << folderPath;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeFlag::GNULongLink: {
|
||||||
|
doNotReset = true;
|
||||||
|
QByteArray longlink;
|
||||||
|
if (readLonglink(in, buffer, longlink)) {
|
||||||
|
symlink = QFile::decodeName(longlink.constData());
|
||||||
|
} else {
|
||||||
|
qCritical() << "Failed to read long link";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeFlag::GNULongName: {
|
||||||
|
doNotReset = true;
|
||||||
|
QByteArray longlink;
|
||||||
|
if (readLonglink(in, buffer, longlink)) {
|
||||||
|
name = QFile::decodeName(longlink.constData());
|
||||||
|
} else {
|
||||||
|
qCritical() << "Failed to read long name";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeFlag::Link:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::Symlink: {
|
||||||
|
auto fileName = FS::PathCombine(dst, name);
|
||||||
|
if (!FS::create_link(FS::PathCombine(QFileInfo(fileName).path(), symlink), fileName)()) { // do not use symlinks
|
||||||
|
qCritical() << "Can't create link for:" << fileName << " to:" << FS::PathCombine(QFileInfo(fileName).path(), symlink);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FS::ensureFilePathExists(fileName);
|
||||||
|
QFile::setPermissions(fileName, QFile::Permissions(mode));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeFlag::Character:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::Block:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::FIFO:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::Contiguous:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::GlobalPosixHeader:
|
||||||
|
/* fallthrough */
|
||||||
|
case TypeFlag::ExtendedPosixHeader:
|
||||||
|
/* fallthrough */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!doNotReset) {
|
||||||
|
name.truncate(0);
|
||||||
|
symlink.truncate(0);
|
||||||
|
}
|
||||||
|
doNotReset = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GZTar::extract(QString src, QString dst)
|
||||||
|
{
|
||||||
|
QuaGzipFile a(src);
|
||||||
|
if (!a.open(QIODevice::ReadOnly)) {
|
||||||
|
qCritical() << "Can't open tar file:" << src;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Tar::extract(&a, dst);
|
||||||
|
}
|
46
launcher/Untar.h
Normal file
46
launcher/Untar.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (c) 2023-2024 Trial97 <alexandru.tripon97@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <QIODevice>
|
||||||
|
|
||||||
|
// this is a hack used for the java downloader (feel free to remove it in favor of a library)
|
||||||
|
// both extract functions will extract the first folder inside dest(disregarding the prefix)
|
||||||
|
namespace Tar {
|
||||||
|
bool extract(QIODevice* in, QString dst);
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace GZTar {
|
||||||
|
bool extract(QString src, QString dst);
|
||||||
|
};
|
@ -120,6 +120,8 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation,
|
|||||||
return tr("Path");
|
return tr("Path");
|
||||||
case JavaName:
|
case JavaName:
|
||||||
return tr("Java Name");
|
return tr("Java Name");
|
||||||
|
case JavaMajor:
|
||||||
|
return tr("Major");
|
||||||
case Time:
|
case Time:
|
||||||
return tr("Released");
|
return tr("Released");
|
||||||
}
|
}
|
||||||
@ -139,6 +141,8 @@ QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation,
|
|||||||
return tr("Filesystem path to this version");
|
return tr("Filesystem path to this version");
|
||||||
case JavaName:
|
case JavaName:
|
||||||
return tr("The alternative name of the java version");
|
return tr("The alternative name of the java version");
|
||||||
|
case JavaMajor:
|
||||||
|
return tr("The java major version");
|
||||||
case Time:
|
case Time:
|
||||||
return tr("Release date of this version");
|
return tr("Release date of this version");
|
||||||
}
|
}
|
||||||
@ -175,6 +179,8 @@ QVariant VersionProxyModel::data(const QModelIndex& index, int role) const
|
|||||||
return sourceModel()->data(parentIndex, BaseVersionList::PathRole);
|
return sourceModel()->data(parentIndex, BaseVersionList::PathRole);
|
||||||
case JavaName:
|
case JavaName:
|
||||||
return sourceModel()->data(parentIndex, BaseVersionList::JavaNameRole);
|
return sourceModel()->data(parentIndex, BaseVersionList::JavaNameRole);
|
||||||
|
case JavaMajor:
|
||||||
|
return sourceModel()->data(parentIndex, BaseVersionList::JavaMajorRole);
|
||||||
case Time:
|
case Time:
|
||||||
return sourceModel()->data(parentIndex, Meta::VersionList::TimeRole).toDate();
|
return sourceModel()->data(parentIndex, Meta::VersionList::TimeRole).toDate();
|
||||||
default:
|
default:
|
||||||
@ -323,6 +329,9 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel* replacingRaw)
|
|||||||
if (roles.contains(BaseVersionList::JavaNameRole)) {
|
if (roles.contains(BaseVersionList::JavaNameRole)) {
|
||||||
m_columns.push_back(JavaName);
|
m_columns.push_back(JavaName);
|
||||||
}
|
}
|
||||||
|
if (roles.contains(BaseVersionList::JavaMajorRole)) {
|
||||||
|
m_columns.push_back(JavaMajor);
|
||||||
|
}
|
||||||
if (roles.contains(Meta::VersionList::TimeRole)) {
|
if (roles.contains(Meta::VersionList::TimeRole)) {
|
||||||
m_columns.push_back(Time);
|
m_columns.push_back(Time);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ class VersionFilterModel;
|
|||||||
class VersionProxyModel : public QAbstractProxyModel {
|
class VersionProxyModel : public QAbstractProxyModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum Column { Name, ParentVersion, Branch, Type, CPUArchitecture, Path, Time, JavaName };
|
enum Column { Name, ParentVersion, Branch, Type, CPUArchitecture, Path, Time, JavaName, JavaMajor };
|
||||||
using FilterMap = QHash<BaseVersionList::ModelRoles, std::shared_ptr<Filter>>;
|
using FilterMap = QHash<BaseVersionList::ModelRoles, std::shared_ptr<Filter>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "MMCZip.h"
|
#include "MMCZip.h"
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
#include "Untar.h"
|
||||||
#include "net/ChecksumValidator.h"
|
#include "net/ChecksumValidator.h"
|
||||||
#include "net/NetJob.h"
|
#include "net/NetJob.h"
|
||||||
#include "tasks/Task.h"
|
#include "tasks/Task.h"
|
||||||
@ -69,6 +70,28 @@ void ArchiveDownloadTask::executeTask()
|
|||||||
void ArchiveDownloadTask::extractJava(QString input)
|
void ArchiveDownloadTask::extractJava(QString input)
|
||||||
{
|
{
|
||||||
setStatus(tr("Extracting java"));
|
setStatus(tr("Extracting java"));
|
||||||
|
if (input.endsWith("tar")) {
|
||||||
|
setStatus(tr("Extracting java(the progress will not be reported for tar)"));
|
||||||
|
QFile in(input);
|
||||||
|
if (!in.open(QFile::ReadOnly)) {
|
||||||
|
emitFailed(tr("Unable to open supplied tar file."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!Tar::extract(&in, QDir(m_final_path).absolutePath())) {
|
||||||
|
emitFailed(tr("Unable to extract supplied tar file."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emitSucceeded();
|
||||||
|
return;
|
||||||
|
} else if (input.endsWith("tar.gz") || input.endsWith("taz") || input.endsWith("tgz")) {
|
||||||
|
setStatus(tr("Extracting java(the progress will not be reported for tar)"));
|
||||||
|
if (!GZTar::extract(input, QDir(m_final_path).absolutePath())) {
|
||||||
|
emitFailed(tr("Unable to extract supplied tar file."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emitSucceeded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto zip = std::make_shared<QuaZip>(input);
|
auto zip = std::make_shared<QuaZip>(input);
|
||||||
if (!zip->open(QuaZip::mdUnzip)) {
|
if (!zip->open(QuaZip::mdUnzip)) {
|
||||||
emitFailed(tr("Unable to open supplied zip file."));
|
emitFailed(tr("Unable to open supplied zip file."));
|
||||||
|
@ -92,6 +92,13 @@ QVariant VersionList::data(const QModelIndex& index, int role) const
|
|||||||
return QVariant::fromValue(version);
|
return QVariant::fromValue(version);
|
||||||
case RecommendedRole:
|
case RecommendedRole:
|
||||||
return version->isRecommended();
|
return version->isRecommended();
|
||||||
|
case JavaMajorRole: {
|
||||||
|
auto major = version->version();
|
||||||
|
if (major.startsWith("java")) {
|
||||||
|
major = "Java " + major.mid(4);
|
||||||
|
}
|
||||||
|
return major;
|
||||||
|
}
|
||||||
// FIXME: this should be determined in whatever view/proxy is used...
|
// FIXME: this should be determined in whatever view/proxy is used...
|
||||||
// case LatestRole: return version == getLatestStable();
|
// case LatestRole: return version == getLatestStable();
|
||||||
default:
|
default:
|
||||||
|
@ -54,7 +54,6 @@ void VerifyJavaInstall::executeTask()
|
|||||||
auto javaArchitecture = settings->get("JavaArchitecture").toString();
|
auto javaArchitecture = settings->get("JavaArchitecture").toString();
|
||||||
auto maxMemAlloc = settings->get("MaxMemAlloc").toInt();
|
auto maxMemAlloc = settings->get("MaxMemAlloc").toInt();
|
||||||
|
|
||||||
emit logLine(tr("Java architecture is x%1.").arg(javaArchitecture), MessageLevel::Info);
|
|
||||||
if (javaArchitecture == "32" && maxMemAlloc > 2048) {
|
if (javaArchitecture == "32" && maxMemAlloc > 2048) {
|
||||||
emit logLine(tr("Max memory allocation exceeds the supported value.\n"
|
emit logLine(tr("Max memory allocation exceeds the supported value.\n"
|
||||||
"The selected java is 32-bit and doesn't support more than 2048MiB of RAM.\n"
|
"The selected java is 32-bit and doesn't support more than 2048MiB of RAM.\n"
|
||||||
|
@ -19,16 +19,19 @@
|
|||||||
#include "InstallJavaDialog.h"
|
#include "InstallJavaDialog.h"
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
|
#include <QMessageBox>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
#include "BaseVersionList.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
#include "java/download/ArchiveDownloadTask.h"
|
#include "java/download/ArchiveDownloadTask.h"
|
||||||
#include "java/download/ManifestDownloadTask.h"
|
#include "java/download/ManifestDownloadTask.h"
|
||||||
#include "meta/Index.h"
|
#include "meta/Index.h"
|
||||||
#include "meta/VersionList.h"
|
#include "meta/VersionList.h"
|
||||||
|
#include "ui/dialogs/CustomMessageBox.h"
|
||||||
#include "ui/dialogs/ProgressDialog.h"
|
#include "ui/dialogs/ProgressDialog.h"
|
||||||
#include "ui/java/VersionList.h"
|
#include "ui/java/VersionList.h"
|
||||||
#include "ui/widgets/PageContainer.h"
|
#include "ui/widgets/PageContainer.h"
|
||||||
@ -71,8 +74,7 @@ class InstallJavaPage : public QWidget, public BasePage {
|
|||||||
//! loads the list if needed.
|
//! loads the list if needed.
|
||||||
void initialize(Meta::VersionList::Ptr vlist)
|
void initialize(Meta::VersionList::Ptr vlist)
|
||||||
{
|
{
|
||||||
vlist->setProvidedRoles({ BaseVersionList::VersionRole, BaseVersionList::RecommendedRole, BaseVersionList::VersionPointerRole });
|
vlist->setProvidedRoles({ BaseVersionList::JavaMajorRole, BaseVersionList::RecommendedRole, BaseVersionList::VersionPointerRole });
|
||||||
vlist->sort(1);
|
|
||||||
majorVersionSelect->initialize(vlist.get());
|
majorVersionSelect->initialize(vlist.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +221,11 @@ void InstallDialog::done(int result)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto deletePath = [final_path] { FS::deletePath(final_path); };
|
auto deletePath = [final_path] { FS::deletePath(final_path); };
|
||||||
connect(task.get(), &Task::failed, this, deletePath);
|
connect(task.get(), &Task::failed, this, [this, &deletePath](QString reason) {
|
||||||
|
QString error = QString("Java download failed: %1").arg(reason);
|
||||||
|
CustomMessageBox::selectable(this, tr("Error"), error, QMessageBox::Warning)->show();
|
||||||
|
deletePath();
|
||||||
|
});
|
||||||
connect(task.get(), &Task::aborted, this, deletePath);
|
connect(task.get(), &Task::aborted, this, deletePath);
|
||||||
ProgressDialog pg(this);
|
ProgressDialog pg(this);
|
||||||
pg.setSkipButton(true, tr("Abort"));
|
pg.setSkipButton(true, tr("Abort"));
|
||||||
|
@ -78,6 +78,13 @@ QVariant VersionList::data(const QModelIndex& index, int role) const
|
|||||||
return false; // do not recommend any version
|
return false; // do not recommend any version
|
||||||
case JavaNameRole:
|
case JavaNameRole:
|
||||||
return version->name();
|
return version->name();
|
||||||
|
case JavaMajorRole: {
|
||||||
|
auto major = version->version.toString();
|
||||||
|
if (major.startsWith("java")) {
|
||||||
|
major = "Java " + major.mid(4);
|
||||||
|
}
|
||||||
|
return major;
|
||||||
|
}
|
||||||
case TypeRole:
|
case TypeRole:
|
||||||
return version->packageType;
|
return version->packageType;
|
||||||
case Meta::VersionList::TimeRole:
|
case Meta::VersionList::TimeRole:
|
||||||
|
@ -180,7 +180,7 @@ void JavaSettingsWidget::initialize()
|
|||||||
tr("%1 can automatically download the correct Java version for each version of Minecraft..\n"
|
tr("%1 can automatically download the correct Java version for each version of Minecraft..\n"
|
||||||
"Do you want to enable Java auto-download?\n")
|
"Do you want to enable Java auto-download?\n")
|
||||||
.arg(BuildConfig.LAUNCHER_DISPLAYNAME),
|
.arg(BuildConfig.LAUNCHER_DISPLAYNAME),
|
||||||
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)
|
QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)
|
||||||
->exec();
|
->exec();
|
||||||
if (button == QMessageBox::Yes) {
|
if (button == QMessageBox::Yes) {
|
||||||
m_autodetectJavaCheckBox->setChecked(true);
|
m_autodetectJavaCheckBox->setChecked(true);
|
||||||
|
Loading…
Reference in New Issue
Block a user