#include "MainWidget.h" #include "./ui_MainWidget.h" #include "adddesktop.h" #include #include MainWidget::MainWidget(QWidget* parent) : QWidget(parent), ui(new Ui::MainWidget) { ui->setupUi(this); setWindowTitle("packqt v1.0.0"); connect_operator(); control_init(); } MainWidget::~MainWidget() { delete ui; } void MainWidget::connect_operator() { connect(ui->btnSelcetBinary, &QPushButton::clicked, this, [=]() { SelectFile(this, ui->edBinary, "请选择Qt二进制文件", "所有文件 (*)"); }); connect(ui->btnSelectOut, &QPushButton::clicked, this, [=]() { SelectDirectory(this, ui->edOutDir); }); connect(ui->btnSelectQt, &QPushButton::clicked, this, [=]() { SelectDirectory(this, ui->edQtDir); }); connect(ui->btnAddEnv, &QPushButton::clicked, this, [=]() { add_env_btn(); }); connect(ui->btnDelEnv, &QPushButton::clicked, this, [=]() { del_env_btn(); }); connect(ui->btnGenerate, &QPushButton::clicked, this, [=]() { generate(); }); connect(ui->btnInstall, &QPushButton::clicked, this, [=]() { install_bin2menu(); }); connect(ui->btnExit, &QPushButton::clicked, this, [=]() { QApplication::exit(); }); } void MainWidget::control_init() { ui->plainTextEdit->setEnabled(false); ui->edQtDir->setText(QDir::homePath() + "/Qt5.14.2/5.14.2/gcc_64"); ui->edOutDir->setText(QDir::homePath() + "/program"); #if !defined(NDEBUG) #endif } void MainWidget::add_env_btn() { QString env = SelectDirectory(this, nullptr); if (env.isEmpty()) { return; } ui->listWidget->addItem(env); } void MainWidget::simple_log(const QString& info, bool enter) { // dd if (enter) { ui->plainTextEdit->appendPlainText(info + "\n"); } else { ui->plainTextEdit->appendPlainText(info); } } // 将二进制文件安装到菜单栏 void MainWidget::install_bin2menu() { // QString bin = SelectFile(this, ui->edBinary, "请选择二进制可执行文件", "所有文件 (*)"); // if (bin.isEmpty()) { // return; // } AddDesktop add(this); add.exec(); } // 将某个文件夹拷贝到制定目录下 bool MainWidget::copy_dir(const std::string& source_dir, const std::string& des_dir) { if (!fs::exists(source_dir) || !fs::exists(des_dir)) { return false; } fs::path des_parent_dir = fs::path(des_dir).append(fs::path(source_dir).filename()); if (!fs::exists(des_parent_dir)) { fs::create_directories(des_parent_dir); } std::list paths{}; for (const auto& entry : fs::directory_iterator(source_dir)) { paths.push_back(entry); } while (!paths.empty()) { fs::path path = paths.front(); paths.pop_front(); fs::path destination(boost::replace_all_copy(path.string(), source_dir, des_parent_dir.string())); if (fs::is_directory(path)) { if (!fs::exists(destination)) { fs::create_directories(destination); } for (const auto& entry : fs::directory_iterator(path)) { paths.push_back(entry); } continue; } fs::copy_file(path, destination, fs::copy_options::overwrite_existing); } return true; } std::vector MainWidget::get_depend_on(const std::string& name, const std::vector& env) { std::vector vec; std::string cmd{}; if (!env.empty()) { cmd.append("export LD_LIBRARY_PATH=$LD_LIBRARY_PATH"); for (const auto& data : env) { cmd.append(":" + data); } } cmd.append(" && ldd " + name); char buffer[1024]{}; FILE* pf = nullptr; if ((pf = popen(cmd.c_str(), "r")) == nullptr) { return vec; } std::string result{}; while (std::fgets(buffer, sizeof(buffer), pf)) { result.append(buffer); } boost::split(vec, result, boost::is_any_of("\t")); return vec; } std::list MainWidget::handle_result(const std::vector& vec) { std::list ret; for (const auto& data : vec) { if (data.empty()) { continue; } if (boost::contains(data, "not found")) { simple_log(QString::fromStdString("未找到依赖:" + data), false); continue; } std::string tdata = boost::replace_all_copy(data, "=>", ""); std::vector vt; boost::split(vt, tdata, boost::is_any_of(" ")); if (vt.size() != 4) { // QString info = "原始数据:" + QString::fromStdString(data); // simple_log(info, false); continue; } if (boost::starts_with(vt[2], "/lib")) { continue; } ret.push_back(vt[2]); // simple_log(QString::fromStdString(vt[2]), false); } return ret; } void MainWidget::del_env_btn() { QListWidgetItem* item = ui->listWidget->currentItem(); if (!item) { return; } delete ui->listWidget->takeItem(ui->listWidget->currentRow()); } QString MainWidget::SelectDirectory(QWidget* parent, QLineEdit* pEdit, const QString& pre_path) { QString start_path = pre_path; QDir folder(start_path); if (start_path.isEmpty() || !folder.exists()) { start_path = QDir::homePath(); } QString selectedDirectory = QFileDialog::getExistingDirectory(parent, u8"选择文件夹", start_path); if (selectedDirectory.isEmpty()) { return ""; } if (pEdit) { pEdit->setText(selectedDirectory); } return selectedDirectory; } QString MainWidget::SelectFile(QWidget* parent, QLineEdit* pEdit, const QString& info, const QString& filter) { QString filePath = QFileDialog::getOpenFileName(parent, info, QDir::homePath(), filter); if (!filePath.isEmpty() && pEdit) { pEdit->setText(filePath); } return filePath; } bool MainWidget::isOk(QWidget* parent, const QString& title, const QString& content) { QMessageBox questionBox(parent); questionBox.setText(content); questionBox.setWindowTitle(title); questionBox.setIcon(QMessageBox::Question); questionBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); int result = questionBox.exec(); if (result != QMessageBox::Yes) { return false; } else { return true; } } void MainWidget::message(QWidget* parent, const QString& content) { QMessageBox::information(parent, "提示", content); } void MainWidget::cmd_exec(const std::string& cmd) { int r = system(cmd.c_str()); (void)r; } void MainWidget::generate() { ui->plainTextEdit->clear(); envs_.clear(); sos_.clear(); binary_ = ui->edBinary->text().trimmed(); fs::path binary_dir = fs::path(binary_.toStdString()).parent_path(); envs_.push_back(binary_dir.string()); std::string filename = fs::path(binary_.toStdString()).filename().string(); int env_cnt = ui->listWidget->count(); for (int i = 0; i < env_cnt; ++i) { envs_.push_back(ui->listWidget->item(i)->text().toStdString()); } auto retPrevious = get_depend_on(binary_.toStdString(), envs_); auto result = handle_result(retPrevious); std::vector dynamic_so{}; std::copy(result.begin(), result.end(), std::back_inserter(dynamic_so)); // 处理 platform文件夹 std::list platform{}; fs::path qt_platform(ui->edQtDir->text().trimmed().toStdString()); qt_platform.append("plugins/platforms"); for (const auto& entry : fs::directory_iterator(qt_platform)) { result.push_back(entry.path().string()); } while (!result.empty()) { std::string bin = result.front(); result.pop_front(); auto tmp_retPrevious = get_depend_on(bin, envs_); auto tmp_result = handle_result(tmp_retPrevious); for (const auto& data : tmp_result) { auto iter = std::find(dynamic_so.begin(), dynamic_so.end(), data); if (iter != dynamic_so.end()) { continue; } dynamic_so.push_back(data); result.push_back(data); } } fs::path out_dir(ui->edOutDir->text().trimmed().toStdString()); out_dir.append(filename); if (!fs::exists(out_dir)) { fs::create_directories(out_dir); } for (const auto& data : dynamic_so) { std::string purpose = fs::path(out_dir).append(fs::path(data).filename()).string(); fs::copy_file(data, purpose, fs::copy_options::overwrite_existing); } // 复制platform文件夹 copy_dir(qt_platform.string(), out_dir.string()); // 复制主体文件 fs::path out_binary = fs::path(out_dir).append(fs::path(binary_.toStdString()).filename()); fs::copy_file(binary_.toStdString(), out_binary, fs::copy_options::overwrite_existing); // 生成一个启动文件夹 QFile file("://resource/run.sh"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { return; } QTextStream in(&file); // 读取文件内容 QString content = in.readAll(); file.close(); std::string run_sh = content.toStdString(); boost::replace_all(run_sh, "replace_string", filename); std::string out_sh = fs::path(out_dir).append("run.sh").string(); std::ofstream out(out_sh, std::ios::out); if (!out.is_open()) { return; } out << run_sh; out.close(); cmd_exec(std::string("chmod +x " + out_sh)); message(this, "完成"); }