diff --git a/CMakeLists.txt b/CMakeLists.txt index a60725e..dd871aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,10 @@ add_compile_options(/wd4267) add_compile_options(-D_CRT_SECURE_NO_WARNINGS) endif() -add_executable(OneLevelXmlOpr ${PROJECT_SOURCES}) +add_executable(OneLevelXmlOpr ${PROJECT_SOURCES} + conf_setting.h conf_setting.cpp conf_setting.ui + src/history.h src/history.cpp + src/uhistory.h src/uhistory.cpp src/uhistory.ui) target_link_libraries(OneLevelXmlOpr PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) set_target_properties(OneLevelXmlOpr PROPERTIES ${BUNDLE_ID_OPTION} diff --git a/MainWidget.cpp b/MainWidget.cpp index 29ee01a..7e0c5d7 100644 --- a/MainWidget.cpp +++ b/MainWidget.cpp @@ -1,5 +1,8 @@ #include "MainWidget.h" +#include "./ui_MainWidget.h" +#include "src/data_edit.h" +#include "public_def.h" #include #include #include @@ -8,10 +11,6 @@ #include #include #include -#include - -#include "./ui_MainWidget.h" -#include "src/data_edit.h" constexpr std::size_t g_OnePage = 100; namespace fs = std::filesystem; @@ -19,7 +18,7 @@ MainWidget::MainWidget(QWidget* parent) : QWidget(parent), ui(new Ui::MainWidget { ui->setupUi(this); - setWindowTitle(u8"OneLevelXmlOpr v1.2.18"); + setWindowTitle(u8"OneLevelXmlOpr v1.3.0"); setWindowIcon(QIcon("://resource/xml.ico")); QScreen* primaryScreen = QGuiApplication::primaryScreen(); @@ -30,7 +29,11 @@ MainWidget::MainWidget(QWidget* parent) : QWidget(parent), ui(new Ui::MainWidget // setMinimumWidth(900); // setMinimumHeight(800); + his_ = new CHistory(); attri_edit_ = new CAttributeEdit(); + ini_oper_ = new CGroupIni(); + ini_oper_->load_ini(); + group_set_ = new CGroupSetting(this, ini_oper_); ui->edStatus->setReadOnly(true); ui->btnSave->setEnabled(false); @@ -50,8 +53,7 @@ MainWidget::MainWidget(QWidget* parent) : QWidget(parent), ui(new Ui::MainWidget if (file.isEmpty()) { return; } - read(file); - // ui->edStatus->setText(file); + ui->edStatus->setText(file); }); connect(ui->btnSearch, &QPushButton::clicked, this, [&]() { search(ui->edSearchKey->text()); }); connect(ui->btnBackup, &QPushButton::clicked, this, [&]() { backup_file(); }); @@ -61,6 +63,7 @@ MainWidget::MainWidget(QWidget* parent) : QWidget(parent), ui(new Ui::MainWidget connect(ui->btnReset, &QPushButton::clicked, this, &MainWidget::reset); connect(ui->btnReplace, &QPushButton::clicked, this, [&]() { replace_content(true); }); connect(ui->btnRxReplace, &QPushButton::clicked, this, [&]() { replace_content(false); }); + connect(ui->cbUnit, &QComboBox::currentTextChanged, this, [&](const QString& content) { unit_change(); }); connect(ui->btnExport, &QPushButton::clicked, this, &MainWidget::copy_multi_data); connect(ui->btnPagePre, &QPushButton::clicked, this, [&]() { unsigned int cur = ui->edCurPage->text().toUInt(); @@ -80,6 +83,20 @@ MainWidget::MainWidget(QWidget* parent) : QWidget(parent), ui(new Ui::MainWidget current_ = vec_; push_content(current_); }); + + connect(ui->btnSet, &QPushButton::clicked, this, [&]() { + group_set_->exec(); + base_init(); + }); + connect(ui->btnHis, &QPushButton::clicked, this, [&]() { + CUIHistory his(this, his_); + his.exec(); + + if (his.cur_ != "") { + ui->edStatus->setText(his.cur_); + } + }); + connect(ui->btnPageNext, &QPushButton::clicked, this, [&]() { unsigned int cur = ui->edCurPage->text().toUInt(); push_content(current_, cur + 1); @@ -114,14 +131,11 @@ MainWidget::MainWidget(QWidget* parent) : QWidget(parent), ui(new Ui::MainWidget init_menu(); - ini_.set_work_exe(exe_path_); - base_ = ini_.get_config(); - - if (base_.blank_width > 20) { - blank_with_ = base_.blank_width; + if (cur_config_.max_blank_add > 20) { + blank_with_ = cur_config_.max_blank_add; } - - ui->edStatus->setText(QString::fromStdString(base_.xml_path)); + // 基本处理 + base_init(); } void MainWidget::copy_key() @@ -147,19 +161,21 @@ void MainWidget::closeEvent(QCloseEvent* event) void MainWidget::keyPressEvent(QKeyEvent* event) { switch (event->key()) { - case Qt::Key_Return: - search(ui->edSearchKey->text()); - break; - default: - break; + case Qt::Key_Return: + search(ui->edSearchKey->text()); + break; + default: + break; } QWidget::keyPressEvent(event); } MainWidget::~MainWidget() { - delete attri_edit_; delete ui; + delete attri_edit_; + delete ini_oper_; + delete his_; } void MainWidget::set_work_exe(char* path) @@ -190,8 +206,7 @@ void MainWidget::generate_table_widget() connect(tab_widget_, &QTableWidget::itemChanged, this, [&](QTableWidgetItem* item) { item_changed_handle(item); }); connect(tab_widget_, &QTableWidget::customContextMenuRequested, this, &MainWidget::show_custom_menu); - auto config = ini_.get_config(); - auto keys = CUtil::splitString(config.purpose, ","); + auto keys = CUtil::splitString(cur_config_.propertis, ","); keys_.clear(); QStringList list; @@ -285,29 +300,48 @@ void MainWidget::judge_btn_page() } } -void MainWidget::read(const QString& file_path) +bool MainWidget::read(const QString& file_path) { - base_.xml_path = file_path.toStdString(); - if (!ini_.set_xml_path(base_.xml_path)) { - CUtil::msg(this, u8"没有ini配置文件或者保存ini失败。"); - return; + // 获取配置 + cur_config_.name = ui->cbConfig->currentText().toStdString(); + if (!ini_oper_->get_item(cur_config_)) { + CUtil::msg(this, u8"获取配置失败。"); + return false; } - ui->edStatus->setText(file_path); - if (!xml_.open(base_.xml_path)) { + if (!xml_.open(file_path.toStdString())) { CUtil::msg(this, u8"打开xml失败。"); - return; + return false; } - xml_.set_baseinfo(base_); + xml_.set_baseinfo(cur_config_); if (!xml_.parse_xml(vec_)) { CUtil::msg(this, u8"解析xml失败。"); - return; + return false; } - if (base_.allow_max_width < 0 || base_.allow_max_width > 1000) { + if (cur_config_.is_same) { + std::vector units; + xml_.get_all_unit(units); + QStringList list; + for (const auto& unit : units) { + list.append(QString::fromStdString(unit)); + } + u_ = true; + ui->cbUnit->clear(); + if (!list.isEmpty()) { + ui->cbUnit->addItems(list); + ui->cbUnit->setCurrentIndex(0); + } + u_ = false; + } + else { + ui->cbUnit->setEnabled(false); + } + + if (cur_config_.max_col_len < 0 || cur_config_.max_col_len > 1000) { allow_max_with_ = 100; } else { - allow_max_with_ = base_.allow_max_width; + allow_max_with_ = cur_config_.max_col_len; } generate_table_widget(); @@ -321,6 +355,13 @@ void MainWidget::read(const QString& file_path) ui->btnImport->setEnabled(true); ui->btnExport->setEnabled(true); ui->btnBackup->setEnabled(true); + + ui->cbConfig->setEnabled(false); + ui->btnSet->setEnabled(false); + + his_->push(ui->edStatus->text().toStdString()); + + return true; } void MainWidget::search(const QString& key) @@ -782,30 +823,30 @@ void MainWidget::get_related_elements(std::vector& out, ReplaceAre assert(tab_widget_); out.clear(); switch (area) { - case AREA_ALL_PAGE: { - out.resize(current_.size()); - std::transform(current_.begin(), current_.end(), out.begin(), [](Element_t* ele) { return new OperElement(ele, 0); }); - break; + case AREA_ALL_PAGE: { + out.resize(current_.size()); + std::transform(current_.begin(), current_.end(), out.begin(), [](Element_t* ele) { return new OperElement(ele, 0); }); + break; + } + case AREA_CUR_PAGE: { + int rows = tab_widget_->rowCount(); + for (int i = 0; i < rows; ++i) { + out.emplace_back(new OperElement(get_element_by_row(i), i)); } - case AREA_CUR_PAGE: { - int rows = tab_widget_->rowCount(); - for (int i = 0; i < rows; ++i) { - out.emplace_back(new OperElement(get_element_by_row(i), i)); - } - break; - } - case AREA_ALL: { - out.resize(vec_.size()); - std::transform(vec_.begin(), vec_.end(), out.begin(), [](Element_t* ele) { return new OperElement(ele, 0); }); - break; - } - default: { - QModelIndexList indexList = tab_widget_->selectionModel()->selectedRows(); - for (int i = 0; i < indexList.size(); ++i) { - out.emplace_back(new OperElement(get_element_by_row(indexList[i].row()), indexList[i].row())); - } - break; + break; + } + case AREA_ALL: { + out.resize(vec_.size()); + std::transform(vec_.begin(), vec_.end(), out.begin(), [](Element_t* ele) { return new OperElement(ele, 0); }); + break; + } + default: { + QModelIndexList indexList = tab_widget_->selectionModel()->selectedRows(); + for (int i = 0; i < indexList.size(); ++i) { + out.emplace_back(new OperElement(get_element_by_row(indexList[i].row()), indexList[i].row())); } + break; + } } } @@ -823,6 +864,39 @@ void MainWidget::backup_file() } } +void MainWidget::base_init() +{ + StrVec_t vec; + ini_oper_->get_all_node(vec); + + QStringList list; + for (const auto& data : vec) { + list.append(QString::fromStdString(data)); + } + ui->cbConfig->clear(); + + if (list.empty()) { + return; + } + + ui->cbConfig->addItems(list); + ui->cbConfig->setCurrentIndex(0); +} + +void MainWidget::unit_change() +{ + if (u_) { + return; + } + std::string unit = ui->cbUnit->currentText().toStdString(); + if (!xml_.get_all_elements(vec_, unit)) { + CUtil::msg(this, u8"获取单元信息失败:" + QString::fromStdString(unit)); + return; + } + push_content(vec_); + current_ = vec_; +} + std::string MainWidget::extract_prefix(const std::string& name) { auto pos = name.find('.'); diff --git a/MainWidget.h b/MainWidget.h index 5e13db3..f0a2b16 100644 --- a/MainWidget.h +++ b/MainWidget.h @@ -1,28 +1,36 @@ #ifndef MAINWIDGET_H #define MAINWIDGET_H -#include -#include -#include -#include -#include -#include -#include "src/xml_opr.h" -#include "src/config.h" +#include "conf_setting.h" #include "src/attribute_edit.h" +#include "src/config.h" +#include "src/xml_opr.h" +#include "src/history.h" +#include "src/uhistory.h" +#include +#include +#include +#include +#include +#include struct SElement_t { SElement_t(Element_t* e, std::string& s); - Element_t* ele; + Element_t* ele; std::string str; }; -enum ReplaceArea { AREA_SELECT, AREA_ALL_PAGE, AREA_CUR_PAGE, AREA_ALL }; +enum ReplaceArea { + AREA_SELECT, + AREA_ALL_PAGE, + AREA_CUR_PAGE, + AREA_ALL +}; struct OperElement { OperElement(Element_t* ele, int row); Element_t* element_{}; - int row_{0}; + int row_{0}; }; QT_BEGIN_NAMESPACE @@ -46,7 +54,7 @@ public: void push_content(const std::vector& eles, std::size_t page = 1); private: - void read(const QString& file_path); + bool read(const QString& file_path); void search(const QString& key); void item_changed_handle(QTableWidgetItem* item); void save(); @@ -64,6 +72,8 @@ private: void copy_multi_data(); void replace_content(bool is_common = true); void backup_file(); + void base_init(); + void unit_change(); private: std::string extract_prefix(const std::string& name); @@ -79,36 +89,39 @@ private: void get_related_elements(std::vector& out, ReplaceArea area); private: - Element_t* get_element_by_key(const QString& key); - Element_t* get_element_by_row(int row); - Element_t* get_current_select_key(); + Element_t* get_element_by_key(const QString& key); + Element_t* get_element_by_row(int row); + Element_t* get_current_select_key(); QTableWidgetItem* get_current_select_item(); private: - std::shared_ptr metrics_; + std::shared_ptr metrics_; private: - QMenu* menu_simple_{}; - QMenu* menu_multi_{}; - QAction* ac_edit_property_{}; - QAction* ac_copy_curline_{}; - QAction* ac_del_curline_{}; - QAction* ac_copy_key_{}; - Ui::MainWidget* ui; - ConfigIni ini_{}; - CXmlOpr xml_{}; - std::string exe_path_{}; - QTableWidget* tab_widget_{}; - std::vector vec_{}; - std::vector current_{}; + QMenu* menu_simple_{}; + QMenu* menu_multi_{}; + QAction* ac_edit_property_{}; + QAction* ac_copy_curline_{}; + QAction* ac_del_curline_{}; + QAction* ac_copy_key_{}; + Ui::MainWidget* ui; + CXmlOpr xml_{}; + std::string exe_path_{}; + QTableWidget* tab_widget_{}; + std::vector vec_{}; + std::vector current_{}; std::vector keys_{}; - bool auto_add_{false}; - std::size_t cur_page_{1}; - std::size_t all_page_{1}; - CAttributeEdit* attri_edit_{}; - OprBase base_{}; - long allow_max_with_{500}; - long blank_with_{50}; - ump_t col_with_{}; + bool auto_add_{false}; + std::size_t cur_page_{1}; + std::size_t all_page_{1}; + CAttributeEdit* attri_edit_{}; + long allow_max_with_{500}; + long blank_with_{50}; + ump_t col_with_{}; + CGroupSetting* group_set_{}; + CGroupIni* ini_oper_{}; + CHistory* his_{}; + OneGroupIni cur_config_{}; + bool u_{false}; }; #endif // MAINWIDGET_H diff --git a/MainWidget.ui b/MainWidget.ui index f293774..5211c91 100644 --- a/MainWidget.ui +++ b/MainWidget.ui @@ -6,7 +6,7 @@ 0 0 - 1048 + 1056 682 @@ -20,6 +20,13 @@ 1基本信息 + + + + 历史 + + + @@ -30,6 +37,9 @@ + + + @@ -70,7 +80,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -108,14 +118,14 @@ - 一般替换 + 一般替 - 正则替换 + 正则替 @@ -125,14 +135,14 @@ - Qt::Vertical + Qt::Orientation::Vertical - 区分大小写 + 区分大小 @@ -205,10 +215,33 @@ + + + - Qt::Horizontal + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + 配置设置 + + + + + + + Qt::Orientation::Horizontal diff --git a/conf_setting.cpp b/conf_setting.cpp new file mode 100644 index 0000000..1281ac6 --- /dev/null +++ b/conf_setting.cpp @@ -0,0 +1,130 @@ +#include "conf_setting.h" +#include "public_def.h" +#include "ui_conf_setting.h" + +CGroupSetting::CGroupSetting(QWidget* parent, CGroupIni* oper) : QDialog(parent), ui(new Ui::CGroupSetting) +{ + ini_opr_ = oper; + ui->setupUi(this); + + setWindowTitle(u8"配置编辑"); + + connect(ui->btnAddConfig, &QPushButton::clicked, this, [&]() { add_item(); }); + connect(ui->btnDelConfig, &QPushButton::clicked, this, [&]() { del_item(); }); + connect(ui->btnExit, &QPushButton::clicked, this, [&]() { close(); }); + connect(ui->cbConfig, &QComboBox::currentTextChanged, this, [&](const QString& content) { change_ini(); }); +} + +CGroupSetting::~CGroupSetting() +{ + delete ui; +} + +void CGroupSetting::showEvent(QShowEvent* event) +{ + update_ini(); + QDialog::showEvent(event); +} + +void CGroupSetting::add_item() +{ + QString config_name = ui->edConfigName->text(); + config_name = config_name.trimmed(); + if (config_name.isEmpty()) { + CUtil::msg(this, u8"配置名为空"); + return; + } + + // 验证重名 + + // 添加 + OneGroupIni gp; + gp.name = config_name.toStdString(); + gp.item_key = ui->edItemKey->text().toStdString(); + gp.main_nodes = ui->edMainPath->text().toStdString(); + gp.relative_nodes = ui->edRelativePath->text().toStdString(); + gp.max_col_len = ui->edMaxColLen->text().toLong(); + gp.max_blank_add = ui->edMaxFillLen->text().toLong(); + gp.propertis = ui->edProperties->text().toStdString(); + gp.is_same = ui->chbIsSame->isChecked(); + + if (!ini_opr_->add_item(gp)) { + CUtil::msg(this, u8"失败"); + return; + } + update_ini(); + CUtil::msg(this, u8"成功"); +} + +void CGroupSetting::del_item() +{ + std::string key = ui->cbConfig->currentText().toStdString(); + if (!ini_opr_->del_item(key)) { + CUtil::msg(this, u8"失败"); + return; + } + + // 删除成功之后要更新 cb + update_ini(); + + CUtil::msg(this, u8"成功"); +} + +void CGroupSetting::set_ui(const OneGroupIni& gp) +{ + ui->edConfigName->setText(QString::fromStdString(gp.name)); + ui->edItemKey->setText(QString::fromStdString(gp.item_key)); + ui->edMainPath->setText(QString::fromStdString(gp.main_nodes)); + ui->edRelativePath->setText(QString::fromStdString(gp.relative_nodes)); + ui->edMaxColLen->setText(QString::number(gp.max_col_len)); + ui->edMaxFillLen->setText(QString::number(gp.max_blank_add)); + ui->edProperties->setText(QString::fromStdString(gp.propertis)); + + if (gp.is_same) { + ui->chbIsSame->setChecked(true); + } + else { + ui->chbIsSame->setChecked(false); + } +} + +void CGroupSetting::change_ini() +{ + if (auto_add_) { + return; + } + QString name_key = ui->cbConfig->currentText(); + OneGroupIni gp; + gp.name = name_key.toStdString(); + if (!ini_opr_->get_item(gp)) { + CUtil::msg(this, u8"加载" + ui->cbConfig->currentText() + "失败"); + } else { + set_ui(gp); + } +} + +void CGroupSetting::update_ini() +{ + StrVec_t vec; + ini_opr_->get_all_node(vec); + + QStringList list; + for (const auto& data : vec) { + list.append(QString::fromStdString(data)); + } + + auto_add_ = true; + ui->cbConfig->clear(); + if (!list.empty()) { + ui->cbConfig->addItems(list); + ui->cbConfig->setCurrentIndex(0); + OneGroupIni gp; + gp.name = ui->cbConfig->currentText().toStdString(); + if (!ini_opr_->get_item(gp)) { + CUtil::msg(this, u8"加载" + ui->cbConfig->currentText() + "失败"); + } else { + set_ui(gp); + } + } + auto_add_ = false; +} diff --git a/conf_setting.h b/conf_setting.h new file mode 100644 index 0000000..37785e1 --- /dev/null +++ b/conf_setting.h @@ -0,0 +1,35 @@ +#ifndef CONF_SETTING_H +#define CONF_SETTING_H + +#include +#include "src/config.h" + +namespace Ui { +class CGroupSetting; +} + +class CGroupSetting : public QDialog +{ + Q_OBJECT + +public: + explicit CGroupSetting(QWidget *parent, CGroupIni* oper); + ~CGroupSetting(); + +protected: + void showEvent(QShowEvent* event) override; + +private: + void add_item(); + void del_item(); + void set_ui(const OneGroupIni& gp); + void change_ini(); + void update_ini(); + +private: + bool auto_add_{false}; + Ui::CGroupSetting *ui; + CGroupIni* ini_opr_{}; +}; + +#endif // CONF_SETTING_H diff --git a/conf_setting.ui b/conf_setting.ui new file mode 100644 index 0000000..9f83535 --- /dev/null +++ b/conf_setting.ui @@ -0,0 +1,150 @@ + + + CGroupSetting + + + + 0 + 0 + 339 + 530 + + + + Form + + + + + + 配置选择: + + + + + + + + + + 名称: + + + + + + + + + + + + 主节点路径: + + + + + + + 是否是相同结构 + + + + + + + + + + + + 操作节点路径(相对主节点,没有不填写): + + + + + + + + + + 子项头名称: + + + + + + + + + + 操作属性列表(半角逗号分隔):: + + + + + + + + + + 列最大宽度(默认1000): + + + + + + + + + + 单元右侧空白填充宽度(默认60): + + + + + + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + 新增/更新 + + + + + + + 删除 + + + + + + + 退出 + + + + + + + + + + diff --git a/public_def.cpp b/public_def.cpp index 8b73cff..f4ed16b 100644 --- a/public_def.cpp +++ b/public_def.cpp @@ -1,6 +1,6 @@ #include "public_def.h" -#include #include +#include #ifdef _WIN32 #include @@ -37,7 +37,7 @@ void CUtil::sort_by_repeat(std::vector& vec) std::size_t len1 = 0; std::size_t len2 = 0; std::size_t cur = 0; - auto compare = [&](const std::string& str1, const std::string& str2) { + auto compare = [&](const std::string& str1, const std::string& str2) { len1 = str1.size(); len2 = str2.size(); if (cur >= len1 || cur >= len2) { @@ -84,13 +84,12 @@ std::string CUtil::utf8_to_gbk(const std::string& utf8_str) } #endif - std::vector CUtil::splitString(const std::string& input, const std::string& delimiter) { std::vector tokens; - size_t pos = 0; - std::string backup = input; - std::string token; + size_t pos = 0; + std::string backup = input; + std::string token; while ((pos = backup.find(delimiter)) != std::string::npos) { token = backup.substr(0, pos); @@ -102,4 +101,3 @@ std::vector CUtil::splitString(const std::string& input, const std: return tokens; } - diff --git a/public_def.h b/public_def.h index 86074a1..0fa9f92 100644 --- a/public_def.h +++ b/public_def.h @@ -1,18 +1,9 @@ #ifndef PUBLIC_DEF_HEADER #define PUBLIC_DEF_HEADER +#include #include #include -#include - -struct OprBase { - std::string node_path{}; - std::string the_node{}; - std::string purpose{}; - std::string xml_path{}; - long allow_max_width{500}; - long blank_width{50}; -}; class CUtil { @@ -21,13 +12,13 @@ public: ~CUtil() = default; public: - static void msg(QWidget* parent, const QString& content); - static bool affirm(QWidget* parent, const QString& titile, const QString& content); + static void msg(QWidget* parent, const QString& content); + static bool affirm(QWidget* parent, const QString& titile, const QString& content); static QString select_file(QWidget* parent, const QString& info, const QString& filter); - static void sort_by_repeat(std::vector& vec); + static void sort_by_repeat(std::vector& vec); public: - static std::string utf8_to_gbk(const std::string& utf8_str); + static std::string utf8_to_gbk(const std::string& utf8_str); static std::vector splitString(const std::string& input, const std::string& delimiter); }; diff --git a/src/attribute_edit.cpp b/src/attribute_edit.cpp index b2104c3..34bb1c5 100644 --- a/src/attribute_edit.cpp +++ b/src/attribute_edit.cpp @@ -89,7 +89,7 @@ void CAttributeEdit::init_table() table_->setSelectionBehavior(QAbstractItemView::SelectRows); table_->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); table_->setColumnWidth(0, 100); - table_->setColumnWidth(1, 250); + table_->setColumnWidth(1, 550); QHBoxLayout* ly = new QHBoxLayout(); ly->addWidget(table_); ui->widget->setLayout(ly); @@ -97,4 +97,4 @@ void CAttributeEdit::init_table() table_->clearContents(); table_->setRowCount(0); } -} \ No newline at end of file +} diff --git a/src/attribute_edit.ui b/src/attribute_edit.ui index 2f070f3..a64cf1e 100644 --- a/src/attribute_edit.ui +++ b/src/attribute_edit.ui @@ -6,7 +6,7 @@ 0 0 - 318 + 769 618 @@ -29,7 +29,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -42,7 +42,7 @@ - Qt::NoFocus + Qt::FocusPolicy::NoFocus 确认 @@ -52,7 +52,7 @@ - Qt::NoFocus + Qt::FocusPolicy::NoFocus 取消 diff --git a/src/config.cpp b/src/config.cpp index cc155ae..4a44c1a 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1,53 +1,108 @@ #include "config.h" +#include #include namespace fs = std::filesystem; - -bool ConfigIni::set_work_exe(const std::string& dir) +CGroupIni::CGroupIni() { - work_dir_ = dir; + default_set(); +} - auto ini_path = fs::path(work_dir_).parent_path().append("xmlopr.ini"); - if (!fs::exists(ini_path)) { - return false; +void CGroupIni::default_set() +{ + QDir dir; + std::string path = dir.homePath().toStdString(); + fs::path p(path); + p.append(".config"); + + if (!fs::exists(p)) { + fs::create_directories(p); } - ini_path_ = ini_path.string(); - if (!parse_ini()) { + work_dir_ = p.string(); + p.append("OneLevelXmlOpr.ini"); + work_file_ = p.string(); +} + +bool CGroupIni::load_ini() +{ + SI_Error rc = ini_.LoadFile(work_file_.c_str()); + if (rc != SI_OK) { + rc = ini_.SaveFile(work_file_.c_str()); + if (rc < 0) { + return false; + } + return true; + } + return true; +} + +void CGroupIni::get_all_node(StrVec_t& vec) +{ + vec.clear(); + + CSimpleIni::TNamesDepend secs; + ini_.GetAllSections(secs); + for (const auto& sec : secs) { + vec.push_back(sec.pItem); + } +} + +bool CGroupIni::add_item(const OneGroupIni& group) +{ + ini_.SetValue(group.name.c_str(), "MainNodes", group.main_nodes.c_str()); + ini_.SetValue(group.name.c_str(), "RelativeNodes", group.relative_nodes.c_str()); + ini_.SetValue(group.name.c_str(), "ItemKey", group.item_key.c_str()); + ini_.SetValue(group.name.c_str(), "Properties", group.propertis.c_str()); + ini_.SetLongValue(group.name.c_str(), "MaxColLen", group.max_col_len); + ini_.SetLongValue(group.name.c_str(), "MaxBlankAdd", group.max_blank_add); + ini_.SetBoolValue(group.name.c_str(), "IsSameStruct", group.is_same); + + if (ini_.SaveFile(work_file_.c_str()) != SI_OK) { return false; } return true; } -bool ConfigIni::set_xml_path(const std::string& path) +bool CGroupIni::get_item(OneGroupIni& group) { - if (ini_.IsEmpty()) { + StrVec_t vec; + get_all_node(vec); + + bool find = false; + for (const auto& item : vec) { + if (group.name != item) { + continue; + } + find = true; + break; + } + + if (!find) { return false; } - ini_.SetValue("Basic", "xml_path", path.c_str()); - if (ini_.SaveFile(ini_path_.c_str()) != SI_OK) { + group.main_nodes = ini_.GetValue(group.name.c_str(), "MainNodes"); + group.relative_nodes = ini_.GetValue(group.name.c_str(), "RelativeNodes"); + group.item_key = ini_.GetValue(group.name.c_str(), "ItemKey"); + group.propertis = ini_.GetValue(group.name.c_str(), "Properties"); + group.max_col_len = ini_.GetLongValue(group.name.c_str(), "MaxColLen"); + group.max_blank_add = ini_.GetLongValue(group.name.c_str(), "MaxBlankAdd"); + group.is_same = ini_.GetBoolValue(group.name.c_str(), "IsSameStruct"); + + return true; +} + +bool CGroupIni::del_item(const std::string &key) +{ + ini_.Delete(key.c_str(), "MainNodes", true); + ini_.Delete(key.c_str(), "RelativeNodes", true); + ini_.Delete(key.c_str(), "ItemKey", true); + ini_.Delete(key.c_str(), "Properties", true); + ini_.Delete(key.c_str(), "MaxColLen", true); + ini_.Delete(key.c_str(), "MaxBlankAdd", true); + if (ini_.SaveFile(work_file_.c_str()) != SI_OK) { return false; } return true; } - -OprBase ConfigIni::get_config() -{ - return opr_base_; -} - -bool ConfigIni::parse_ini() -{ - if (ini_.LoadFile(ini_path_.c_str()) != SI_OK) { - return false; - } - ini_.SetUnicode(); - opr_base_.node_path = ini_.GetValue("Basic", "oper_node"); - opr_base_.purpose = ini_.GetValue("Basic", "purpose"); - opr_base_.the_node = ini_.GetValue("Basic", "the_node"); - opr_base_.xml_path = ini_.GetValue("Basic", "xml_path"); - opr_base_.allow_max_width = ini_.GetLongValue("Basic", "max_col_width"); - opr_base_.blank_width = ini_.GetLongValue("Basic", "blank_width"); - return true; -} diff --git a/src/config.h b/src/config.h index 573da6e..2fd8129 100644 --- a/src/config.h +++ b/src/config.h @@ -3,7 +3,6 @@ #include #include -#include "../public_def.h" /* @@ -12,25 +11,37 @@ oper_node=IODEF/ITEMS */ -class ConfigIni +using StrVec_t = std::vector; +struct OneGroupIni { + std::string name; + std::string main_nodes; + std::string relative_nodes; + std::string item_key; + std::string propertis; + long max_col_len{1000}; + long max_blank_add{60}; + bool is_same; +}; + +class CGroupIni { public: - ConfigIni() = default; - ~ConfigIni() = default; + CGroupIni(); public: - bool set_work_exe(const std::string& dir); - bool set_xml_path(const std::string& path); - OprBase get_config(); + bool load_ini(); + void get_all_node(StrVec_t& vec); + bool add_item(const OneGroupIni& group); + bool get_item(OneGroupIni& group); + bool del_item(const std::string& key); private: - bool parse_ini(); + void default_set(); private: std::string work_dir_{}; - std::string ini_path_{}; + std::string work_file_{}; CSimpleIniA ini_{}; - OprBase opr_base_{}; }; #endif diff --git a/src/history.cpp b/src/history.cpp new file mode 100644 index 0000000..515d914 --- /dev/null +++ b/src/history.cpp @@ -0,0 +1,80 @@ +#include "history.h" +#include +#include +#include +#include + +namespace fs = std::filesystem; + +CHistory::CHistory() +{ + default_set(); +} + +bool CHistory::push(const std::string& content) +{ + std::vector vec; + read_file(vec); + + if (std::find(vec.begin(), vec.end(), content) == vec.end()) { + vec.push_back(content); + } else { + return true; + } + + if (vec.size() > 10) { + vec.erase(vec.begin()); + } + if (!write_file(vec)) { + return false; + } + return true; +} + +bool CHistory::get_history(std::vector& vec) +{ + return read_file(vec); +} + +void CHistory::default_set() +{ + QDir dir; + std::string path = dir.homePath().toStdString(); + fs::path p(path); + p.append(".config"); + + if (!fs::exists(p)) { + fs::create_directories(p); + } + + work_dir_ = p.string(); + p.append("OneLevelXmlOpr.history"); + work_file_ = p.string(); +} + +bool CHistory::read_file(std::vector& vec) +{ + vec.clear(); + std::ifstream file(work_file_); + if (!file.is_open()) { + return false; + } + std::string line; + while (std::getline(file, line)) { + vec.push_back(line); + } + return true; +} + +bool CHistory::write_file(std::vector& vec) +{ + std::ofstream file(work_file_); + if (!file.is_open()) { + return false; + } + for (const auto& line : vec) { + file << line << std::endl; + } + file.close(); + return true; +} diff --git a/src/history.h b/src/history.h new file mode 100644 index 0000000..105d0fb --- /dev/null +++ b/src/history.h @@ -0,0 +1,27 @@ +#ifndef HISTORY_H +#define HISTORY_H + +#include +#include + +// 只保留最近的10条数据 +class CHistory +{ +public: + CHistory(); + +public: + bool push(const std::string& content); + bool get_history(std::vector& vec); + +private: + void default_set(); + bool read_file(std::vector& vec); + bool write_file(std::vector& vec); + +private: + std::string work_dir_{}; + std::string work_file_{}; +}; + +#endif // HISTORY_H diff --git a/src/uhistory.cpp b/src/uhistory.cpp new file mode 100644 index 0000000..7ad529f --- /dev/null +++ b/src/uhistory.cpp @@ -0,0 +1,44 @@ +#include "uhistory.h" + +#include "src/ui_uhistory.h" +#include "ui_uhistory.h" + +CUIHistory::CUIHistory(QWidget* parent, CHistory* his) : QDialog(parent), ui(new Ui::CUIHistory) +{ + ui->setupUi(this); + his_ = his; + + connect(ui->btnExit, &QPushButton::clicked, this, [&]() { close(); }); + connect(ui->btnOk, &QPushButton::clicked, this, [&]() { select_ok(); }); +} + +CUIHistory::~CUIHistory() +{ + delete ui; +} + +void CUIHistory::showEvent(QShowEvent* event) +{ + std::vector vec; + his_->get_history(vec); + + QStringList list; + for (const auto& data : vec) { + list.append(QString::fromStdString(data)); + } + if (!list.empty()) { + ui->listWidget->addItems(list); + } + cur_.clear(); + QDialog::showEvent(event); +} + +void CUIHistory::select_ok() +{ + auto re = ui->listWidget->selectedItems(); + if (re.empty()) { + return ; + } + cur_ = re[0]->text(); + close(); +} diff --git a/src/uhistory.h b/src/uhistory.h new file mode 100644 index 0000000..ceb0453 --- /dev/null +++ b/src/uhistory.h @@ -0,0 +1,31 @@ +#ifndef UHISTORY_H +#define UHISTORY_H + +#include +#include "history.h" + +namespace Ui { +class CUIHistory; +} + +class CUIHistory : public QDialog +{ + Q_OBJECT + +public: + explicit CUIHistory(QWidget *parent, CHistory* his); + ~CUIHistory(); + +private: + void showEvent(QShowEvent* event); + void select_ok(); + +public: + QString cur_{}; + +private: + Ui::CUIHistory *ui; + CHistory* his_{}; +}; + +#endif // UHISTORY_H diff --git a/src/uhistory.ui b/src/uhistory.ui new file mode 100644 index 0000000..b8e4440 --- /dev/null +++ b/src/uhistory.ui @@ -0,0 +1,67 @@ + + + CUIHistory + + + + 0 + 0 + 561 + 277 + + + + 历史文件加载 + + + + + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + 选择 + + + + + + + + 0 + 0 + + + + 退出 + + + + + + + + + + diff --git a/src/xml_opr.cpp b/src/xml_opr.cpp index 68e1b6d..dd4e57d 100644 --- a/src/xml_opr.cpp +++ b/src/xml_opr.cpp @@ -1,4 +1,5 @@ #include "xml_opr.h" +#include "../public_def.h" #include namespace fs = std::filesystem; @@ -34,15 +35,30 @@ bool CXmlOpr::backup_file(const std::string& desti_folder, const std::string& ti return fs::copy_file(xml_path_, des); } -void CXmlOpr::set_baseinfo(const OprBase& base) +void CXmlOpr::set_baseinfo(const OneGroupIni& base) { opr_base_ = base; } -bool CXmlOpr::get_all_elements(std::vector& vec) +bool CXmlOpr::get_all_elements(std::vector& vec, const std::string& unit) { vec.clear(); - Element_t* purpose_node = parent_node_->FirstChildElement(opr_base_.the_node.c_str()); + + Element_t* temp = parent_node_; + + if (!unit.empty()) { + temp = temp->FirstChildElement(unit.c_str()); + } + + if (!opr_base_.relative_nodes.empty()) { + auto v = CUtil::splitString(opr_base_.relative_nodes, ","); + // 向下子项跳跃 + for (const auto& it : v) { + temp = temp->FirstChildElement(it.c_str()); + } + } + + auto purpose_node = temp->FirstChildElement(opr_base_.item_key.c_str()); while (purpose_node) { vec.push_back(purpose_node); purpose_node = purpose_node->NextSiblingElement(); @@ -53,9 +69,9 @@ bool CXmlOpr::get_all_elements(std::vector& vec) bool CXmlOpr::parse_xml(std::vector& vec) { std::string next_node{}; - std::string node_path = opr_base_.node_path; + std::string node_path = opr_base_.item_key; keys_.clear(); - auto keys = CUtil::splitString(opr_base_.purpose, ","); + auto keys = CUtil::splitString(opr_base_.propertis, ","); for (const auto& item : keys) { if (item.empty()) { continue; @@ -63,7 +79,7 @@ bool CXmlOpr::parse_xml(std::vector& vec) keys_.push_back(item); } - auto nodes = CUtil::splitString(opr_base_.node_path, "/"); + auto nodes = CUtil::splitString(opr_base_.main_nodes, "/"); for (const auto& item : nodes) { if (item.empty()) { @@ -76,7 +92,27 @@ bool CXmlOpr::parse_xml(std::vector& vec) parent_node_ = parent_node_->FirstChildElement(item.c_str()); } } - get_all_elements(vec); + + if (opr_base_.is_same) { + units_.clear(); + auto p = parent_node_->FirstChildElement(); + while (p) { + units_.push_back(p->Name()); + p = p->NextSiblingElement(); + } + if (!units_.empty()) { + get_all_elements(vec, units_[0]); + } + } else { + get_all_elements(vec); + } + + return true; +} + +bool CXmlOpr::get_all_unit(std::vector &units) +{ + units = units_; return true; } @@ -85,7 +121,7 @@ void CXmlOpr::copy_and_del(std::vector& vec, std::vector { out.clear(); // 先找到最后一个节点 - Element_t* last_node = parent_node_->LastChildElement(opr_base_.the_node.c_str()); + Element_t* last_node = parent_node_->LastChildElement(opr_base_.item_key.c_str()); Element_t* last_node_bk = last_node; if (last_node == nullptr) { return; @@ -97,7 +133,7 @@ void CXmlOpr::copy_and_del(std::vector& vec, std::vector last_node = n; } // 删除原有的节点 - Element_t* fnode = parent_node_->FirstChildElement(opr_base_.the_node.c_str()); + Element_t* fnode = parent_node_->FirstChildElement(opr_base_.item_key.c_str()); Element_t* fnext = fnode->NextSiblingElement(); while (fnode != last_node_bk) { parent_node_->DeleteChild(fnode); @@ -120,7 +156,7 @@ Element_t* CXmlOpr::copy_element(Element_t* ele) if (!ele) { return nullptr; } - Element_t* ret = doc_.NewElement(ele->Name()); + Element_t* ret = doc_.NewElement(ele->Name()); const auto* attribute = ele->FirstAttribute(); while (attribute) { ret->SetAttribute(attribute->Name(), attribute->Value()); @@ -141,7 +177,7 @@ bool CXmlOpr::check_valid_xml_data(const std::string& data) bool CXmlOpr::check_same_struct(const std::string& data) { - auto* own_ele = parent_node_->FirstChildElement(opr_base_.the_node.c_str()); + auto* own_ele = parent_node_->FirstChildElement(opr_base_.item_key.c_str()); if (own_ele == nullptr) { return true; } @@ -150,12 +186,12 @@ bool CXmlOpr::check_same_struct(const std::string& data) if (doc.Error()) { return false; } - const auto* import_ele = doc.FirstChildElement(opr_base_.the_node.c_str()); + const auto* import_ele = doc.FirstChildElement(opr_base_.item_key.c_str()); if (import_ele == nullptr) { return false; } const auto* attribute = own_ele->FirstAttribute(); - int own_cnt = 0; + int own_cnt = 0; while (attribute) { ++own_cnt; if (import_ele->FindAttribute(attribute->Name()) == nullptr) { @@ -165,7 +201,7 @@ bool CXmlOpr::check_same_struct(const std::string& data) } const auto* attr_import = import_ele->FirstAttribute(); - int import_cnt = 0; + int import_cnt = 0; while (attr_import) { ++import_cnt; attr_import = attr_import->Next(); @@ -183,7 +219,7 @@ bool CXmlOpr::check_same_struct(const std::string& data) bool CXmlOpr::import_newer_data(const std::vector& vec, std::size_t& success_count) { success_count = 0; - auto* last_item = parent_node_->LastChildElement(opr_base_.the_node.c_str()); + auto* last_item = parent_node_->LastChildElement(opr_base_.item_key.c_str()); if (last_item == nullptr) { return false; } @@ -191,7 +227,7 @@ bool CXmlOpr::import_newer_data(const std::vector& vec, std::size_t for (const auto& data : vec) { tinyxml2::XMLDocument doc; doc.Parse(data.c_str()); - auto* item = doc.FirstChildElement(opr_base_.the_node.c_str()); + auto* item = doc.FirstChildElement(opr_base_.item_key.c_str()); if (item == nullptr) { continue; } @@ -224,7 +260,7 @@ bool CXmlOpr::check_key_exists(const std::string& key) if (keys_.size() < 1 || key.empty()) { return false; } - Element_t* purpose_node = parent_node_->FirstChildElement(opr_base_.the_node.c_str()); + Element_t* purpose_node = parent_node_->FirstChildElement(opr_base_.item_key.c_str()); while (purpose_node) { const char* value = purpose_node->Attribute(keys_[0].c_str()); if (key == std::string(value)) { diff --git a/src/xml_opr.h b/src/xml_opr.h index 08d2526..1f8e3b4 100644 --- a/src/xml_opr.h +++ b/src/xml_opr.h @@ -1,10 +1,10 @@ #ifndef XML_OPERT_HEADER #define XML_OPERT_HEADER +#include "config.h" #include #include #include -#include "../public_def.h" struct SKeyValue { SKeyValue(const char* pkey, const char* pvalue); @@ -12,7 +12,7 @@ struct SKeyValue { std::string value; }; -typedef tinyxml2::XMLElement Element_t; +typedef tinyxml2::XMLElement Element_t; typedef std::vector Property_t; class CXmlOpr { @@ -23,9 +23,10 @@ public: public: bool open(const std::string& xml_path); bool backup_file(const std::string& desti_folder, const std::string& time); - void set_baseinfo(const OprBase& base); + void set_baseinfo(const OneGroupIni& base); bool parse_xml(std::vector& vec); - bool get_all_elements(std::vector& vec); + bool get_all_unit(std::vector& units); + bool get_all_elements(std::vector& vec, const std::string& unit = ""); void copy_and_del(std::vector& vec, std::vector& out); void insert_brother_node(Element_t* brother, Element_t* newer); void del_element(Element_t* ele); @@ -47,11 +48,12 @@ public: void attributes_to_element(Element_t* ele, const Property_t& vec); private: - tinyxml2::XMLDocument doc_{}; - OprBase opr_base_{}; - std::string xml_path_{}; - Element_t* parent_node_{}; + tinyxml2::XMLDocument doc_{}; + OneGroupIni opr_base_{}; + std::string xml_path_{}; + Element_t* parent_node_{}; std::vector keys_{}; + std::vector units_{}; }; #endif