From 41713baede9ff5e95042ecaad2d604fafe1b57f7 Mon Sep 17 00:00:00 2001 From: taynpg Date: Wed, 15 May 2024 23:06:48 +0800 Subject: [PATCH] =?UTF-8?q?func=EF=BC=9A1.=E6=B7=BB=E5=8A=A0=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD=E3=80=82=202.?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=BC=96=E8=BE=91=E5=B1=9E=E6=80=A7=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=203.=E5=88=A0=E9=99=A4=E6=B7=BB=E5=8A=A0=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E5=88=B0=E7=95=8C=E9=9D=A2=E6=9C=AA=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 2 +- CMakeLists.txt | 3 +- MainWidget.cpp | 128 +++++++++++++++++++++++++++++++++---- MainWidget.h | 29 +++++---- MainWidget.ui | 140 ++++++++++++++++++++++++++++++++++------- public_def.cpp | 26 ++++++-- public_def.h | 1 + src/attribute_edit.cpp | 93 +++++++++++++++++++++++++++ src/attribute_edit.h | 40 ++++++++++++ src/attribute_edit.ui | 62 ++++++++++++++++++ src/xml_opr.cpp | 50 ++++++++++++--- src/xml_opr.h | 29 ++++++--- 12 files changed, 534 insertions(+), 69 deletions(-) create mode 100644 src/attribute_edit.cpp create mode 100644 src/attribute_edit.h create mode 100644 src/attribute_edit.ui diff --git a/.vscode/settings.json b/.vscode/settings.json index 35b41b6..9a4d1bf 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -19,7 +19,7 @@ "visualizerFile": "${workspaceRoot}/.vscode/qt5.natvis" }, "cmake.environment": { - "PATH": "${env:PATH};C:/Qt/Qt5.14.2/5.14.2/msvc2017_64/bin;", + "PATH": "${env:PATH};C:/Qt/Qt5.14.2/5.14.2/msvc2017_64/bin", "LD_LIBRARY_PATH": "$LD_LIBRARY_PATH:/home/xxx" }, "cmake.options.statusBarVisibility": "visible", diff --git a/CMakeLists.txt b/CMakeLists.txt index d71d7ec..8a2a4cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,8 @@ set(PROJECT_SOURCES MainWidget.ui 3rd/tinyxml2.cpp src/xml_opr.h src/xml_opr.cpp src/config.h src/config.cpp public_def.cpp resource.qrc - resource/ico.rc + resource/ico.rc src/attribute_edit.ui src/attribute_edit.h + src/attribute_edit.cpp ) if (MSVC) diff --git a/MainWidget.cpp b/MainWidget.cpp index 8b5855d..702607e 100644 --- a/MainWidget.cpp +++ b/MainWidget.cpp @@ -1,32 +1,67 @@ #include "MainWidget.h" +#include #include "./ui_MainWidget.h" +constexpr std::size_t g_OnePage = 100; + MainWidget::MainWidget(QWidget* parent) : QWidget(parent), ui(new Ui::MainWidget) { ui->setupUi(this); - setWindowTitle(u8"OneLevelXmlOpr v1.0.0"); + setWindowTitle(u8"OneLevelXmlOpr v1.1"); setWindowIcon(QIcon("://resource/xml.ico")); + setMinimumWidth(900); + setMinimumHeight(800); + width_.push_back(280); for (int i = 0; i < 30; ++i) { width_.push_back(160); } + attri_edit_ = new CAttributeEdit(); + ui->edStatus->setEnabled(false); ui->btnSave->setEnabled(false); ui->btnCopySelectLine->setEnabled(false); ui->btnDelSelectLine->setEnabled(false); + ui->edAllPage->setEnabled(false); connect(ui->btnRead, &QPushButton::clicked, this, [&]() { read(); }); connect(ui->btnSearch, &QPushButton::clicked, this, [&]() { search(); }); connect(ui->btnSave, &QPushButton::clicked, this, [&]() { save(); }); connect(ui->btnCopySelectLine, &QPushButton::clicked, this, [&]() { copy_select_line(); }); connect(ui->btnDelSelectLine, &QPushButton::clicked, this, [&]() { del_select_line(); }); + connect(ui->btnReset, &QPushButton::clicked, this, &MainWidget::reset); + connect(ui->btnPagePre, &QPushButton::clicked, this, [&]() { + unsigned int cur = ui->edCurPage->text().toUInt(); + push_content(current_, cur - 1); + }); + connect(ui->btnPageNext, &QPushButton::clicked, this, [&]() { + unsigned int cur = ui->edCurPage->text().toUInt(); + push_content(current_, cur + 1); + }); + connect(ui->btnJump, &QPushButton::clicked, this, [&]() { + unsigned int cur = ui->edCurPage->text().toUInt(); + push_content(current_, cur); + }); + connect(ui->btnCopyKey, &QPushButton::clicked, this, &MainWidget::copy_key); +} + +void MainWidget::copy_key() +{ + Element_t* target = get_current_select_key(); + if (target == nullptr) { + return; + } + QClipboard* clip = QApplication::clipboard(); + clip->setText(QString(target->Attribute(keys_[0].c_str()))); + CUtil::msg(this, u8"已复制"); } MainWidget::~MainWidget() { + delete attri_edit_; delete ui; } @@ -67,15 +102,34 @@ void MainWidget::generate_table_widget() ui->widget->setLayout(lay); } -void MainWidget::push_content(const std::vector& eles) +void MainWidget::push_content(const std::vector& eles, std::size_t page) { + if (tab_widget_ == nullptr || page == 0) { + return; + } + + std::size_t all_size = eles.size(); + std::size_t max_show = g_OnePage * page; + all_page_ = all_size / 100; + + if (all_size % 100 != 0) { + ++all_page_; + } + + if (page < 1 || page > all_page_) { + CUtil::msg(this, u8"不在范围内"); + ui->edCurPage->setText(QString::number(cur_page_)); + return; + } + tab_widget_->clearContents(); tab_widget_->setRowCount(0); - for (const auto& ele : eles) { + + for (auto p = (page - 1) * g_OnePage; p < all_size && p < max_show; ++p) { int row_cnt = tab_widget_->rowCount(); tab_widget_->insertRow(row_cnt); for (auto i = 0; i < keys_.size(); ++i) { - const char* data = ele->Attribute(keys_[i].c_str()); + const char* data = eles[p]->Attribute(keys_[i].c_str()); QTableWidgetItem* wgItem = new QTableWidgetItem(); if (i == 0) { @@ -86,6 +140,26 @@ void MainWidget::push_content(const std::vector& eles) tab_widget_->setItem(row_cnt, i, wgItem); } } + ui->edCurPage->setText(QString::number(page)); + cur_page_ = page; + ui->edAllPage->setText(QString::number(all_page_)); + judge_btn_page(); +} + +void MainWidget::judge_btn_page() +{ + int cur = ui->edCurPage->text().trimmed().toUInt(); + if (cur <= 1) { + ui->btnPagePre->setEnabled(false); + } else { + ui->btnPagePre->setEnabled(true); + } + + if (cur >= all_page_) { + ui->btnPageNext->setEnabled(false); + } else { + ui->btnPageNext->setEnabled(true); + } } void MainWidget::read() @@ -154,8 +228,8 @@ void MainWidget::item_changed_handle(QTableWidgetItem* item) int row = item->row(); int col = item->column(); - QString xml_key = tab_widget_->item(row, 0)->text(); - element* result = get_element_bykey(xml_key); + QString xml_key = tab_widget_->item(row, 0)->text(); + Element_t* result = get_element_bykey(xml_key); if (result == nullptr) { return; } @@ -173,28 +247,49 @@ void MainWidget::save() void MainWidget::copy_select_line() { - element* target = get_current_select_key(); + if (!CUtil::affirm(this, u8"确认", u8"确认复制吗?")) { + return; + } + Element_t* target = get_current_select_key(); if (target == nullptr) { return; } - element* newer = xml_.copy_element(target); + Element_t* newer = xml_.copy_element(target); + + Property_t property; + xml_.get_key_value(newer, property); + + attri_edit_->set_attribute(property); + attri_edit_->exec(); + + if (!attri_edit_->is_ok_) { + return; + } + + attri_edit_->get_attribute(property); + xml_.key_value_to_element(newer, property); xml_.insert_brother_node(target, newer); // TODO: 添加到界面 - CUtil::msg(this, u8"已复制"); } void MainWidget::del_select_line() { - element* target = get_current_select_key(); + if (!CUtil::affirm(this, u8"确认", u8"确认删除吗?")) { + return; + } + Element_t* target = get_current_select_key(); if (target == nullptr) { return; } + xml_.del_element(target); + + // TODO: 添加到界面 } -element* MainWidget::get_current_select_key() +Element_t* MainWidget::get_current_select_key() { - element* ret = nullptr; + Element_t* ret = nullptr; if (tab_widget_ == nullptr) { return ret; } @@ -209,9 +304,16 @@ element* MainWidget::get_current_select_key() return ret; } +void MainWidget::reset() +{ + current_.clear(); + current_ = vec_; + push_content(current_); +} + tinyxml2::XMLElement* MainWidget::get_element_bykey(const QString& key) { - element* ret = nullptr; + Element_t* ret = nullptr; for (const auto& ele : current_) { const char* data = ele->Attribute(keys_[0].c_str()); QString qdata(data); diff --git a/MainWidget.h b/MainWidget.h index e3d967a..30fcfc3 100644 --- a/MainWidget.h +++ b/MainWidget.h @@ -6,6 +6,7 @@ #include #include "src/xml_opr.h" #include "src/config.h" +#include "src/attribute_edit.h" QT_BEGIN_NAMESPACE namespace Ui { @@ -24,19 +25,22 @@ public: public: void set_work_exe(char* path); void generate_table_widget(); - void push_content(const std::vector& eles); + void push_content(const std::vector& eles, std::size_t page = 1); private: - void read(); - void search(); - void item_changed_handle(QTableWidgetItem* item); - void save(); - void copy_select_line(); - void del_select_line(); - element* get_current_select_key(); + void read(); + void search(); + void item_changed_handle(QTableWidgetItem* item); + void save(); + void copy_select_line(); + void del_select_line(); + Element_t* get_current_select_key(); + void reset(); + void judge_btn_page(); + void copy_key(); private: - element* get_element_bykey(const QString& key); + Element_t* get_element_bykey(const QString& key); private: Ui::MainWidget* ui; @@ -44,10 +48,13 @@ private: CXmlOpr xml_{}; std::string exe_path_{}; QTableWidget* tab_widget_{}; - std::vector vec_{}; - std::vector current_{}; + std::vector vec_{}; + std::vector current_{}; std::vector keys_{}; std::vector width_{}; bool auto_add_{false}; + std::size_t cur_page_{1}; + std::size_t all_page_{1}; + CAttributeEdit* attri_edit_{}; }; #endif // MAINWIDGET_H diff --git a/MainWidget.ui b/MainWidget.ui index d2c261f..4b0686b 100644 --- a/MainWidget.ui +++ b/MainWidget.ui @@ -6,16 +6,29 @@ 0 0 - 1181 - 980 + 573 + 602 MainWidget + + + + + 0 + 0 + + + + + + + @@ -23,13 +36,6 @@ - - - - - - - @@ -48,12 +54,16 @@ - + - 保存 + 重置 + + + + @@ -67,6 +77,97 @@ + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + + + + + / + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + + + + + + + + + + + + 跳转 + + + + + + + 上一页 + + + + + + + 下一页 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 复制Key + + + @@ -81,18 +182,15 @@ + + + + 保存 + + + - - - - - 0 - 0 - - - - diff --git a/public_def.cpp b/public_def.cpp index c3365b8..d28bb52 100644 --- a/public_def.cpp +++ b/public_def.cpp @@ -1,12 +1,13 @@ #include "public_def.h" #include -std::vector splitString(const std::string& input, const std::string& delimiter) { +std::vector 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); tokens.push_back(token); @@ -22,3 +23,18 @@ void CUtil::msg(QWidget* parent, const QString& content) { QMessageBox::information(parent, u8"提示", content); } + +bool CUtil::affirm(QWidget* parent, const QString& titile, const QString& content) +{ + QMessageBox questionBox(parent); + questionBox.setText(content); + questionBox.setWindowTitle(titile); + questionBox.setIcon(QMessageBox::Question); + questionBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + int result = questionBox.exec(); + if (result != QMessageBox::Yes) { + return false; + } else { + return true; + } +} \ No newline at end of file diff --git a/public_def.h b/public_def.h index e87c35f..5adc864 100644 --- a/public_def.h +++ b/public_def.h @@ -21,6 +21,7 @@ public: ~CUtil() = default; public: static void msg(QWidget* parent, const QString& content); + static bool affirm(QWidget* parent, const QString& titile, const QString& content); }; #endif \ No newline at end of file diff --git a/src/attribute_edit.cpp b/src/attribute_edit.cpp new file mode 100644 index 0000000..1ef164f --- /dev/null +++ b/src/attribute_edit.cpp @@ -0,0 +1,93 @@ +#include "attribute_edit.h" +#include "ui_attribute_edit.h" + +CAttributeEdit::CAttributeEdit(QWidget* parent) : QDialog(parent), ui(new Ui::CAttributeEdit) +{ + ui->setupUi(this); + + setWindowTitle(u8"属性编辑"); + setMinimumSize(400, 600); + + connect(ui->btnOk, &QPushButton::clicked, this, &CAttributeEdit::handle_ok); + connect(ui->btnCancel, &QPushButton::clicked, this, [&]() { + is_ok_ = false; + close(); + }); +} + +void CAttributeEdit::handle_ok() +{ + property_.clear(); + int row = table_->rowCount(); + for (int i = 0; i < row; ++i) { + QString key = table_->item(i, 0)->text(); + QString value = table_->item(i, 1)->text(); + property_.emplace_back(key.toLocal8Bit().constData(), value.toLocal8Bit().constData()); + } + is_ok_ = true; + close(); +} + + +CAttributeEdit::~CAttributeEdit() +{ + delete ui; +} + +void CAttributeEdit::showEvent(QShowEvent* event) +{ + show_before(); + QDialog::showEvent(event); +} + +void CAttributeEdit::set_attribute(const Property_t& property) +{ + property_.clear(); + property_ = property; +} + +void CAttributeEdit::get_attribute(Property_t& property) +{ + property.clear(); + property = property_; +} + +void CAttributeEdit::show_before() +{ + init_table(); + + for (const auto& item : property_) { + int row = table_->rowCount(); + table_->insertRow(row); + + QTableWidgetItem* pkey = new QTableWidgetItem(); + pkey->setText(item.key.c_str()); + pkey->setFlags(pkey->flags() & ~Qt::ItemIsEditable); + table_->setItem(row, 0, pkey); + + QTableWidgetItem* pvalue = new QTableWidgetItem(); + pvalue->setText(item.value.c_str()); + table_->setItem(row, 1, pvalue); + } +} + +void CAttributeEdit::init_table() +{ + if (table_ == nullptr) { + QStringList list; + list << u8"属性" << u8"值"; + table_ = new QTableWidget(); + table_->setColumnCount(list.size()); + table_->setHorizontalHeaderLabels(list); + table_->setSelectionBehavior(QAbstractItemView::SelectRows); + table_->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); + table_->setColumnWidth(0, 80); + table_->setColumnWidth(1, 200); + QHBoxLayout* ly = new QHBoxLayout(); + ly->addWidget(table_); + ui->widget->setLayout(ly); + } else { + table_->clearContents(); + table_->setRowCount(0); + } +} \ No newline at end of file diff --git a/src/attribute_edit.h b/src/attribute_edit.h new file mode 100644 index 0000000..0c1650b --- /dev/null +++ b/src/attribute_edit.h @@ -0,0 +1,40 @@ +#ifndef ATTRIBUTE_EDIT_H +#define ATTRIBUTE_EDIT_H + +#include +#include +#include "xml_opr.h" + +namespace Ui { +class CAttributeEdit; +} + +class CAttributeEdit : public QDialog +{ + Q_OBJECT + +public: + explicit CAttributeEdit(QWidget* parent = nullptr); + ~CAttributeEdit(); + +protected: + void showEvent(QShowEvent* event) override; + +public: + void set_attribute(const Property_t& property); + void get_attribute(Property_t& property); +private: + void show_before(); + void init_table(); + void handle_ok(); + +public: + bool is_ok_{}; + +private: + Ui::CAttributeEdit* ui; + Property_t property_{}; + QTableWidget* table_{}; +}; + +#endif // ATTRIBUTE_EDIT_H diff --git a/src/attribute_edit.ui b/src/attribute_edit.ui new file mode 100644 index 0000000..cd67919 --- /dev/null +++ b/src/attribute_edit.ui @@ -0,0 +1,62 @@ + + + CAttributeEdit + + + + 0 + 0 + 318 + 618 + + + + Dialog + + + + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 确认 + + + + + + + 取消 + + + + + + + + + + diff --git a/src/xml_opr.cpp b/src/xml_opr.cpp index 933d053..75ead07 100644 --- a/src/xml_opr.cpp +++ b/src/xml_opr.cpp @@ -3,7 +3,7 @@ CXmlOpr::CXmlOpr() = default; CXmlOpr::~CXmlOpr() = default; -bool CXmlOpr::open(const std::string &xml_path) +bool CXmlOpr::open(const std::string& xml_path) { if (doc_.LoadFile(xml_path.c_str()) != tinyxml2::XML_SUCCESS) { return false; @@ -31,22 +31,20 @@ bool CXmlOpr::parse_xml(std::vector& vec) if (parent_node_ == nullptr) { parent_node_ = doc_.FirstChildElement(item.c_str()); - } - else { + } else { parent_node_ = parent_node_->FirstChildElement(item.c_str()); } } vec.clear(); - element* purpose_node = parent_node_->FirstChildElement(opr_base_.the_node.c_str()); - while (purpose_node) - { + Element_t* purpose_node = parent_node_->FirstChildElement(opr_base_.the_node.c_str()); + while (purpose_node) { vec.push_back(purpose_node); purpose_node = purpose_node->NextSiblingElement(); } return true; } -void CXmlOpr::insert_brother_node(element* brother, element* newer) +void CXmlOpr::insert_brother_node(Element_t* brother, Element_t* newer) { if (!brother || !newer) { return; @@ -54,12 +52,12 @@ void CXmlOpr::insert_brother_node(element* brother, element* newer) parent_node_->InsertAfterChild(brother, newer); } -element* CXmlOpr::copy_element(element* ele) +Element_t* CXmlOpr::copy_element(Element_t* ele) { if (!ele) { return nullptr; } - element* 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()); @@ -68,6 +66,11 @@ element* CXmlOpr::copy_element(element* ele) return ret; } +void CXmlOpr::del_element(Element_t* ele) +{ + parent_node_->DeleteChild(ele); +} + bool CXmlOpr::save() { auto ret = doc_.SaveFile(xml_path_.c_str()); @@ -76,3 +79,32 @@ bool CXmlOpr::save() } return true; } + +void CXmlOpr::get_key_value(Element_t* ele, Property_t& vec) +{ + if (ele == nullptr) { + return; + } + vec.clear(); + const auto* attribute = ele->FirstAttribute(); + while (attribute) { + vec.emplace_back(attribute->Name(), attribute->Value()); + attribute = attribute->Next(); + } +} + +void CXmlOpr::key_value_to_element(Element_t* ele, const Property_t& vec) +{ + if (ele == nullptr) { + return; + } + for (const auto& data : vec) { + ele->SetAttribute(data.key.c_str(), data.value.c_str()); + } +} + +SKeyValue::SKeyValue(const char* pkey, const char* pvalue) +{ + key = std::string(pkey); + value = std::string(pvalue); +} diff --git a/src/xml_opr.h b/src/xml_opr.h index 1e916ef..d7515e1 100644 --- a/src/xml_opr.h +++ b/src/xml_opr.h @@ -4,9 +4,17 @@ #include #include #include +#include #include "../public_def.h" -typedef tinyxml2::XMLElement element; +struct SKeyValue { + SKeyValue(const char* pkey, const char* pvalue); + std::string key; + std::string value; +}; + +typedef tinyxml2::XMLElement Element_t; +typedef std::vector Property_t; class CXmlOpr { public: @@ -14,18 +22,23 @@ public: ~CXmlOpr(); public: - bool open(const std::string& xml_path); - void set_baseinfo(const OprBase& base); - bool parse_xml(std::vector& vec); - void insert_brother_node(element* brother, element* newer); - element* copy_element(element* ele); - bool save(); + bool open(const std::string& xml_path); + void set_baseinfo(const OprBase& base); + bool parse_xml(std::vector& vec); + void insert_brother_node(Element_t* brother, Element_t* newer); + Element_t* copy_element(Element_t* ele); + void del_element(Element_t* ele); + bool save(); + +public: + void get_key_value(Element_t* ele, Property_t& vec); + void key_value_to_element(Element_t* ele, const Property_t& vec); private: tinyxml2::XMLDocument doc_{}; OprBase opr_base_{}; std::string xml_path_{}; - element* parent_node_{}; + Element_t* parent_node_{}; }; #endif \ No newline at end of file