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;
 | ||
| }
 |