197 lines
6.8 KiB
C++
197 lines
6.8 KiB
C++
#define SETTINGSTEP 6
|
||
#include "downloadthread.h"
|
||
#include <QProgressDialog>
|
||
#include <QFile>
|
||
#include <QNetworkAccessManager>
|
||
#include <QNetworkRequest>
|
||
#include <QEventLoop>
|
||
#include <QTimer>
|
||
#include <QNetworkReply>
|
||
#include <QMessageBox>
|
||
#include <QCoreApplication>
|
||
// 文件操作
|
||
#include <QDir>
|
||
// 命令执行
|
||
#include <QProcess>
|
||
// 获取内存总量
|
||
#if defined(Q_OS_LINUX) // 区分系统平台
|
||
#include "sys/statfs.h" // Linux 上
|
||
#else // Windows 上
|
||
#pragma comment(lib, "Kernel32.lib")
|
||
#pragma comment(lib, "Psapi.lib")
|
||
#include <windows.h>
|
||
#include <tlhelp32.h>
|
||
#endif
|
||
|
||
DownloadThread::DownloadThread(QProgressDialog *progressDialog, QString url, QString name, QString mouse, bool NotDownload){
|
||
dialog = progressDialog;
|
||
fileUrl = url;
|
||
vmName = name;
|
||
setMouse = mouse;
|
||
notDownload = NotDownload;
|
||
}
|
||
|
||
// 文件下载
|
||
void DownloadThread::run(){
|
||
// 创建文件夹
|
||
QDir dir;
|
||
QString configDir = QCoreApplication::applicationDirPath() + "/VM";
|
||
if(!dir.exists(configDir)){
|
||
// 文件不存在
|
||
dir.mkpath(configDir);
|
||
}
|
||
configDir = QCoreApplication::applicationDirPath() + "/VM/" + vmName;
|
||
if(!dir.exists(configDir)){
|
||
// 文件不存在
|
||
dir.mkpath(configDir);
|
||
}
|
||
QString savePath = configDir + "/vm.ova";
|
||
// 文件下载
|
||
int timeout = 0;
|
||
QFile f(savePath);
|
||
if(!f.open(QIODevice::WriteOnly)){
|
||
emit MessageBoxError("文件无法写入");
|
||
f.close();
|
||
delete dialog;
|
||
dialog->close();
|
||
return;
|
||
}
|
||
if(notDownload){
|
||
qDebug() << "b";
|
||
SettingVirtualMachine(savePath);
|
||
return;
|
||
}
|
||
QNetworkAccessManager m;
|
||
QNetworkRequest req;
|
||
// 响应 https(就是不行)
|
||
//QSslConfiguration conf = req.sslConfiguration();
|
||
//conf.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||
//conf.setProtocol(QSsl::TlsV1_1);
|
||
//req.setSslConfiguration(conf);
|
||
req.setUrl(QUrl("https://code.gitlink.org.cn/gfdgd_xi/wine-mirrors/raw/branch/master/spark-wine7-devel-7.14.7z"));
|
||
// 下载文件
|
||
QNetworkReply *reply = m.get(req);
|
||
QEventLoop loop;
|
||
QTimer t;
|
||
qDebug() << reply->rawHeader(QString("Content-Length").toUtf8());
|
||
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||
connect(reply, &QNetworkReply::downloadProgress, [=, &f, &t](qint64 bytesRead, qint64 totalBytes){
|
||
f.write(reply->readAll());
|
||
dialog->setValue((float)bytesRead / totalBytes * 100);
|
||
dialog->setLabelText(QString::number(bytesRead / 1024 / 1024) + "MB/" + QString::number(totalBytes / 1024 / 1024) + "MB");
|
||
if(t.isActive()){
|
||
t.start(timeout);
|
||
}
|
||
});
|
||
if(timeout > 0){
|
||
connect(&t, &QTimer::timeout, &loop, &QEventLoop::quit);
|
||
t.start(timeout);
|
||
}
|
||
loop.exec();
|
||
if(reply->error() != QNetworkReply::NoError){
|
||
emit MessageBoxError("下载失败");
|
||
f.close();
|
||
delete reply;
|
||
delete dialog;
|
||
dialog->close();
|
||
return;
|
||
}
|
||
f.close();
|
||
delete reply;
|
||
SettingVirtualMachine(savePath);
|
||
}
|
||
|
||
void DownloadThread::SettingVirtualMachine(QString savePath){
|
||
// 设置虚拟机
|
||
dialog->setLabelText("设置虚拟机");
|
||
dialog->setWindowTitle("正在设置“" + vmName + "”");
|
||
dialog->setValue(100 / SETTINGSTEP * 0);
|
||
dialog->show();
|
||
// 拷贝 OVA 文件
|
||
if(notDownload){
|
||
if(QFile::exists(savePath)){
|
||
QFile::remove(savePath);
|
||
}
|
||
if(!QFile::copy(fileUrl, savePath)){
|
||
emit MessageBoxError("文件复制错误,无法继续");
|
||
}
|
||
}
|
||
// 导入 OVA 镜像
|
||
QProcess progress;
|
||
QStringList command;
|
||
dialog->setValue(100 / SETTINGSTEP * 1);
|
||
command << "import" << savePath;
|
||
progress.start("VBoxManage", command);
|
||
progress.waitForFinished();
|
||
qDebug() << "正常信息:\n";
|
||
qDebug() << progress.readAllStandardOutput();
|
||
qDebug() << "错误信息:\n";
|
||
qDebug() << progress.readAllStandardError();
|
||
// 获取内存
|
||
dialog->setValue(100 / SETTINGSTEP * 2);
|
||
int memtotal = 0;
|
||
#if defined (Q_OS_LINUX) // 在 Linux 下读取总内存
|
||
progress.start("free -m");
|
||
progress.waitForFinished();
|
||
progress.readLine(); // 忽略第一行
|
||
QString memoryInfo = progress.readLine(); // 只读取第 2 行
|
||
qDebug() << memoryInfo;
|
||
memoryInfo.replace("\n", ""); // 忽略换行符
|
||
memoryInfo.replace(QRegExp("( ){1,}"), " "); // 将连续的空格换为单个空格
|
||
auto memoryList = memoryInfo.split(" "); // 根据空格切割内容
|
||
qDebug() << memoryList;
|
||
if(memoryList.size() >= 2){ // 保证至少有两个
|
||
// 理论上列表应该出现的是如下的内容
|
||
// ["Mem:", "13998", "9622", "197", "803", "4179", "3331"]
|
||
// 因此要读[1]
|
||
memtotal = memoryList[1].toDouble();
|
||
}
|
||
else{
|
||
emit MessageBoxError("内存读取错误,请自行打开 VirtualBox 设置内存");
|
||
return;
|
||
}
|
||
#endif
|
||
// 设置内存
|
||
// 示例命令:VBoxManage modifyvm [name] --memory 4096
|
||
command.clear(); // 清空参数列表
|
||
command << "modifyvm" << vmName << "--memory" << QString::number(memtotal / 2);
|
||
progress.start("VBoxManage", command);
|
||
progress.waitForFinished();
|
||
// 设置显卡,默认的 VMSVGA 在 Android X86 上运行有很多问题,应设为 VBoxVGA
|
||
// 示例命令:VBoxManage modifyvm [name] --graphicscontroller vboxvga
|
||
dialog->setValue(100 / SETTINGSTEP * 3);
|
||
command.clear(); // 清空参数列表
|
||
command << "modifyvm" << vmName << "--graphicscontroller" << "vboxvga";
|
||
qDebug() << command;
|
||
progress.start("VBoxManage", command);
|
||
progress.waitForFinished();
|
||
// 设置声卡
|
||
// VBoxManage modifyvm [name] --audio pulse --audiocontroller hda --audioin on --audioout on
|
||
dialog->setValue(100 / SETTINGSTEP * 4);
|
||
command.clear(); // 清空参数列表
|
||
command << "modifyvm" << vmName << "--audio" << "pulse" << "--audiocontroller" << "hda" << "--audioin" << "on" << "--audioout" << "on";
|
||
progress.start("VBoxManage", command);
|
||
progress.waitForFinished();
|
||
// 设置显存
|
||
// VBoxManage modifyvm [name] --vram 128
|
||
dialog->setValue(100 / SETTINGSTEP * 5);
|
||
command.clear(); // 清空参数列表
|
||
command << "modifyvm" << vmName << "--vram" << "128";
|
||
progress.start("VBoxManage", command);
|
||
progress.waitForFinished();
|
||
// 设置鼠标
|
||
// VBoxManage modifyvm [name] --mouse ps2
|
||
dialog->setValue(100 / SETTINGSTEP * 6);
|
||
if(setMouse == "ps2"){
|
||
command.clear(); // 清空参数列表
|
||
command << "modifyvm" << vmName << "--mouse" << "ps2";
|
||
progress.start("VBoxManage", command);
|
||
progress.waitForFinished();
|
||
}
|
||
// 结束
|
||
dialog->setValue(100);
|
||
emit MessageBoxOpenVM(vmName);
|
||
dialog->close();
|
||
delete dialog;
|
||
}
|