From 742a640c3f0a843e4ce642271fe28951ce0dfc23 Mon Sep 17 00:00:00 2001 From: JackLee <809262979@qq.com> Date: Tue, 11 Mar 2025 16:41:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86=E5=8A=9F=E8=83=BD=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 5 +- src/CMakeLists.txt | 14 ---- src/ctaiHistoryTextEdit.cpp | 105 +++++++++--------------------- src/ctaiHistoryTextEdit.h | 14 ++-- src/ctaiHistoryTools.cpp | 47 ++++++-------- src/ctaiHistoryTools.h | 19 +++--- src/ctaiMathConvert.cpp | 126 +++++++++++++++++++++++------------- src/ctaiMathConvert.h | 6 +- src/ctai_base.h | 58 ++++++++++------- 9 files changed, 183 insertions(+), 211 deletions(-) delete mode 100644 src/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index a32f52b..d7fd5d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,7 +82,7 @@ MESSAGE(STATUS "---------- END---------------") #增加sui的cpp -FILE(GLOB src_sui "${PROJECT_SOURCE_DIR}/src/*.*") +FILE(GLOB src_sui "${PROJECT_SOURCE_DIR}/src/*.*") SET(PROJECT_SOURCES ${src_sui}) # 设置消息策略为qFatal来禁用qDebug信息 @@ -150,8 +150,7 @@ target_link_libraries( CURL::libcurl LaTeX libcmark-gfm_static - libcmark-gfm-extensions_static - + libcmark-gfm-extensions_static ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 7bf2783..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ - -cmake_minimum_required(VERSION 3.19) - -project(ctai) -# 设置库的版本号 -set_target_properties(sui PROPERTIES VERSION 1.0 SOVERSION 1) - -#include dir -include_directories(${PROJECT_SOURCE_DIR}/include) - -file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") - -add_library(ctai STATIC ${SRC_LIST}) - diff --git a/src/ctaiHistoryTextEdit.cpp b/src/ctaiHistoryTextEdit.cpp index ff41df8..9f95803 100644 --- a/src/ctaiHistoryTextEdit.cpp +++ b/src/ctaiHistoryTextEdit.cpp @@ -60,6 +60,7 @@ void ctaiHistoryTextEdit::init_msg_header_layout(msg_type msg_type_mode) m_msg_header = new QLineEdit(); m_msg_header->setObjectName("m_msg_header"); m_msg_header->setReadOnly(true); + m_msg_tools = new ctaiHistoryTools(); if (msg_type_mode == SYSTEM) { // 1.SYSTEM消息头水平左信息区 @@ -81,8 +82,7 @@ void ctaiHistoryTextEdit::init_msg_header_layout(msg_type msg_type_mode) header_info_layout->addWidget(m_msg_tokens); header_info_layout->addWidget(m_restart_to_send); header_info_layout->addWidget(m_msg_system_del); - // 3.SYSTEM消息头垂直第二排功能区 - m_msg_tools = new ctaiHistoryTools(); + // 3.SYSTEM消息头垂直第二排功能区 header_opts_layout->addWidget(m_msg_tools); // 4.添加到消息头主布局 header_layout->addLayout(header_info_layout); @@ -111,7 +111,7 @@ void ctaiHistoryTextEdit::init_msg_header_layout(msg_type msg_type_mode) } void ctaiHistoryTextEdit::set_default_opts() { - m_msg_history->setFont(QFont(m_font, m_font_size)); + m_msg_history->setFont(QFont(m_msg_tools->getFont(), m_msg_tools->getFontSize().toInt())); } void ctaiHistoryTextEdit::connect_signals(msg_type msg_type_mode) { @@ -122,13 +122,9 @@ void ctaiHistoryTextEdit::connect_signals(msg_type msg_type_mode) connect(m_msg_tools, SIGNAL(on_signals_fold()), this, SLOT(on_fold_slots())); connect(m_msg_tokens, SIGNAL(clicked()), this, SLOT(on_tokens_slots())); connect(m_msg_tools, SIGNAL(on_signals_display_mode(QString)), this, SLOT(on_display_changed(QString))); - connect(m_msg_tools, SIGNAL(on_signals_display_font(QString)), this, SLOT(on_display_font_changed(QString))); - connect(m_msg_tools, SIGNAL(on_signals_display_font_size(QString)), this, SLOT(on_display_font_size_changed(QString))); + connect(m_msg_tools, SIGNAL(on_signals_display_font_size()), this, SLOT(on_display_font_size_changed())); // save菜单功能 - connect(m_msg_tools, SIGNAL(on_signals_save_text()), this, SLOT(on_save_text())); - connect(m_msg_tools, SIGNAL(on_signals_save_html()), this, SLOT(on_save_html())); - connect(m_msg_tools, SIGNAL(on_signals_save_pdf()), this, SLOT(on_save_pdf())); - connect(m_msg_tools, SIGNAL(on_signals_save_markdown()), this, SLOT(on_save_markdown())); + connect(m_msg_tools, SIGNAL(on_signals_save_file(int)), this, SLOT(on_save_file(int))); // 其他功能菜单 connect(m_msg_tools, SIGNAL(on_signals_menu()), this, SLOT(on_menu_slots())); } @@ -141,15 +137,9 @@ void ctaiHistoryTextEdit::connect_signals(msg_type msg_type_mode) void ctaiHistoryTextEdit::on_menu_slots() { } -void ctaiHistoryTextEdit::on_display_font_size_changed(QString font_size) +void ctaiHistoryTextEdit::on_display_font_size_changed() { - m_font_size = font_size.toInt(); - m_msg_history->setFont(QFont(m_font, m_font_size)); -} -void ctaiHistoryTextEdit::on_display_font_changed(QString font) -{ - m_font = font; - m_msg_history->setFont(QFont(m_font, m_font_size)); + m_msg_history->setFont(QFont(m_msg_tools->getFont(), m_msg_tools->getFontSize().toInt())); } void ctaiHistoryTextEdit::on_delete_slots() { @@ -164,13 +154,16 @@ void ctaiHistoryTextEdit::on_copy_slots() QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(text); } -void ctaiHistoryTextEdit::on_save_text() +// 保存文件 +void ctaiHistoryTextEdit::on_save_file(int index) { - QString fileName = QFileDialog::getSaveFileName(this, - tr("保存消息"), m_msg_sned_id + ".txt", - tr("文本文件 (*.txt)")); + QString fileName; + QString temp_current_content; + fileName = QFileDialog::getSaveFileName(this, tr("保存消息"), m_msg_sned_id + save_extend[index], save_extend_str[index]); if (fileName.isEmpty()) + { return; + } QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { @@ -179,57 +172,25 @@ void ctaiHistoryTextEdit::on_save_text() return; } QTextStream out(&file); - out << m_msg_history->toPlainText() << "\n\n"; - file.close(); -} -void ctaiHistoryTextEdit::on_save_html() -{ - QString fileName = QFileDialog::getSaveFileName(this, - tr("保存HTML"), - m_msg_sned_id + ".html", - tr("HTML 文件 (*.html)")); - if (fileName.isEmpty()) - return; - - QFile file(fileName); - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) - { - QMessageBox::warning(this, tr("保存失败"), - tr("无法保存文件 %1:\n%2").arg(fileName).arg(file.errorString())); - return; + switch(index){ + case 0: + temp_current_content=m_msg_history->toPlainText(); + break; + case 1: + temp_current_content=m_msg_history->toHtml(); + break; + case 2: + temp_current_content=m_msg_history->toMarkdown(); + break; + case 3: + break; } - - QTextStream out(&file); - out << m_msg_history->toHtml(); + if(!temp_current_content.isEmpty()){ + out << m_current_content << "\n\n"; + } file.close(); } -void ctaiHistoryTextEdit::on_save_markdown() -{ - QString fileName = QFileDialog::getSaveFileName(this, - tr("保存 Markdown"), - m_msg_sned_id + ".md", - tr("Markdown 文件 (*.md)")); - if (fileName.isEmpty()) - return; - - QFile file(fileName); - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) - { - QMessageBox::warning(this, tr("保存失败"), - tr("无法保存文件 %1:\n%2").arg(fileName).arg(file.errorString())); - return; - } - - QTextStream out(&file); - out << m_msg_history->toMarkdown(); - file.close(); -} - -void ctaiHistoryTextEdit::on_save_pdf() -{ -} - // 实现折叠功能的槽函数 void ctaiHistoryTextEdit::on_fold_slots() { @@ -252,12 +213,10 @@ void ctaiHistoryTextEdit::on_display_changed(QString mode) } else if (mode == "HTML渲染" || mode == "Markdown渲染") { - m_msg_history->setHtml(m_math_convert->replace_tags_svg(m_current_content, m_font_size)); - qDebug() << "LaTeX Markdown:" << m_msg_history->toMarkdown(); - on_save_html(); - on_save_markdown(); + m_msg_history->setHtml(m_math_convert->replace_tags_svg(m_current_content, m_msg_tools->getFontSize().toInt())); } } + // tokens按钮实现功能的槽函数 void ctaiHistoryTextEdit::on_tokens_slots() { @@ -343,7 +302,7 @@ void ctaiHistoryTextEdit::add_user_message(const model_data &message) QString disp_data; disp_data = QSL(message.send_user_data); m_msg_sned_id = QSL(message.send_user_id); - m_msg_history->setHtml(m_math_convert->replace_tags_svg(disp_data, m_font_size)); + m_msg_history->setHtml(m_math_convert->replace_tags_svg(disp_data, m_msg_tools->getFontSize().toInt())); } void ctaiHistoryTextEdit::add_system_message(const model_data &message) diff --git a/src/ctaiHistoryTextEdit.h b/src/ctaiHistoryTextEdit.h index b4cd5fd..b471d44 100644 --- a/src/ctaiHistoryTextEdit.h +++ b/src/ctaiHistoryTextEdit.h @@ -68,13 +68,9 @@ private slots: void on_fold_slots(); // 折叠按钮 void on_tokens_slots(); // tokens按钮 void on_display_changed(QString); // 显示模式改变 - void on_display_font_changed(QString); // 字体大小改变 - void on_display_font_size_changed(QString); // 字体大小改变 + void on_display_font_size_changed(); // 字体大小改变 void on_sync_text_height(); - void on_save_text(); // 保存文本 - void on_save_html(); // 保存html - void on_save_markdown(); // 保存markdown - void on_save_pdf(); // 保存pdf + void on_save_file(int); // 保存文本 void on_menu_slots(); signals: void delete_requested(QString); // 请求删除此消息 @@ -121,12 +117,10 @@ private: QString m_msg_sned_id = {}; // 本次信息 QString m_current_content; - //默认字体跟随软件全局字体 - QString m_font = sui_font_table[sui_config.font];//"Arial"; //粗体字 bool m_bold=false; - //字号大小 - int m_font_size = 14; + std::vector save_extend={".txt",".html",".md",".pdf"}; + std::vector save_extend_str={"文本文件 (*.txt)","HTML 文件 (*.html)","Markdown 文件 (*.md)","PDF 文件 (*.pdf)"}; QSpacerItem *bottom_spacer = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding); }; diff --git a/src/ctaiHistoryTools.cpp b/src/ctaiHistoryTools.cpp index a075a28..f458de7 100644 --- a/src/ctaiHistoryTools.cpp +++ b/src/ctaiHistoryTools.cpp @@ -63,7 +63,7 @@ void ctaiHistoryTools::initDisplayMode() for(auto str:sui_font_table){ m_msg_display_font_combobox->addItem(str); } - m_msg_display_font_size_combobox->setCurrentIndex(5); + m_msg_display_font_size_combobox->setCurrentIndex(3); m_msg_display_font_combobox->setCurrentIndex(sui_config.font); } void ctaiHistoryTools::initConnect() @@ -73,8 +73,8 @@ void ctaiHistoryTools::initConnect() connect(m_msg_menu, SIGNAL(clicked()), this, SLOT(on_opts_menu_slots())); connect(m_msg_fold, SIGNAL(clicked()), this, SIGNAL(on_signals_fold())); connect(m_msg_display_combobox, SIGNAL(currentTextChanged(QString)), this, SIGNAL(on_signals_display_mode(QString))); - connect(m_msg_display_font_size_combobox, SIGNAL(currentTextChanged(QString)), this, SIGNAL(on_signals_display_font_size(QString))); - connect(m_msg_display_font_combobox, SIGNAL(currentTextChanged(QString)), this, SIGNAL(on_signals_display_font(QString))); + connect(m_msg_display_font_size_combobox, SIGNAL(currentTextChanged(QString)), this, SIGNAL(on_signals_display_font_size())); + connect(m_msg_display_font_combobox, SIGNAL(currentTextChanged(QString)), this, SIGNAL(on_signals_display_font_size())); } void ctaiHistoryTools::setFoldIco(QIcon ico) { @@ -86,33 +86,20 @@ void ctaiHistoryTools::on_save_menu_slots() if (!m_msg_save_menu) { m_msg_save_menu = new QMenu(); + for(int i=0;i<=ds_save_menu.count()-1;i++){ + QAction* action=new QAction(ds_save_menu[i]); + action->setObjectName(QString::number(i)); + connect(action, SIGNAL(triggered(bool)), this, SLOT(on_save_action_slots())); + save_ver.push_back(action); + m_msg_save_menu->addAction(action); + } } - if (!m_msg_save_text) - { - m_msg_save_text = new QAction(tr("另存为文本")); - connect(m_msg_save_text, SIGNAL(triggered(bool)), this, SIGNAL(on_signals_save_text())); - } - if (!m_msg_save_html) - { - m_msg_save_html = new QAction(tr("另存为HTML")); - connect(m_msg_save_html, SIGNAL(triggered(bool)), this, SIGNAL(on_signals_save_html())); - } - if (!m_msg_save_markdown) - { - m_msg_save_markdown = new QAction(tr("另存为Markdown")); - connect(m_msg_save_markdown, SIGNAL(triggered(bool)), this, SIGNAL(on_signals_save_markdown())); - } - if (!m_msg_save_pdf) - { - m_msg_save_pdf = new QAction(tr("另存为PDF")); - connect(m_msg_save_pdf, SIGNAL(triggered(bool)), this, SIGNAL(on_signals_save_pdf())); - } - m_msg_save_menu->addAction(m_msg_save_text); - m_msg_save_menu->addAction(m_msg_save_html); - m_msg_save_menu->addAction(m_msg_save_markdown); - m_msg_save_menu->addAction(m_msg_save_pdf); m_msg_save_menu->exec(QCursor::pos()); } +void ctaiHistoryTools::on_save_action_slots(){ + save_index=sender()->objectName().toInt(); + emit on_signals_save_file(save_index); +} void ctaiHistoryTools::on_opts_menu_slots() { QMenu menu(this); @@ -126,4 +113,10 @@ void ctaiHistoryTools::on_opts_menu_slots() // 显示菜单 QPoint pos = m_msg_menu->mapToGlobal(m_msg_menu->rect().bottomRight()); QAction *act = menu.exec(pos); +} +QString ctaiHistoryTools::getFontSize(){ + return m_msg_display_font_size_combobox->currentText(); +} +QString ctaiHistoryTools::getFont(){ + return m_msg_display_font_combobox->currentText(); } \ No newline at end of file diff --git a/src/ctaiHistoryTools.h b/src/ctaiHistoryTools.h index ce958e6..32cd46b 100644 --- a/src/ctaiHistoryTools.h +++ b/src/ctaiHistoryTools.h @@ -18,6 +18,8 @@ public: void initLayout(); void initConnect(); void setFoldIco(QIcon ico); + QString getFontSize(); + QString getFont(); private: QHBoxLayout *header_opts_Layout = {}; QPushButton *m_msg_copy = {}; @@ -35,28 +37,23 @@ private: QComboBox *m_msg_display_font_combobox = {}; // save保存菜单 QMenu *m_msg_save_menu = {}; - QAction *m_msg_save_text = {}; - QAction *m_msg_save_html = {}; - QAction *m_msg_save_markdown = {}; - QAction *m_msg_save_pdf = {}; QSpacerItem *sparcer_item = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed); QStringList ds_mode_str={"原始文本","HTML源码","HTML渲染","Markdown源码","Markdown渲染"}; QStringList ds_font_size_str={"4","6","8","10","12","14","16","18","20"}; - + QStringList ds_save_menu={"另存为文本","另存为HTML","另存为Markdown","另存为PDF"}; + std::vector save_ver; + int save_index; private: void initDisplayMode(); signals: void on_signals_copy(); void on_signals_fold(); void on_signals_display_mode(QString); - void on_signals_display_font_size(QString); - void on_signals_display_font(QString); - void on_signals_save_text(); - void on_signals_save_html(); - void on_signals_save_markdown(); - void on_signals_save_pdf(); + void on_signals_display_font_size(); + void on_signals_save_file(int); public slots: void on_save_menu_slots(); void on_opts_menu_slots(); + void on_save_action_slots(); }; #endif \ No newline at end of file diff --git a/src/ctaiMathConvert.cpp b/src/ctaiMathConvert.cpp index f6b9962..40fd00d 100644 --- a/src/ctaiMathConvert.cpp +++ b/src/ctaiMathConvert.cpp @@ -28,15 +28,14 @@ QByteArray ctaiMathConvert::svg_to_base64(QPixmap &pix) } QString ctaiMathConvert::math_convert_svg(const QString &math) { - QString res=QDir::currentPath() + "/res/"; + QString res = QDir::currentPath() + "/res/"; auto render = LaTeX::parse(math.toStdWString(), m_render_width, m_text_size, m_lineSpace, m_color); - qDebug() << render->getWidth() << render->getHeight(); - QPixmap pix(render->getWidth()+m_padding*2, render->getHeight()+m_padding*2); + QPixmap pix(render->getWidth() + m_padding * 2, render->getHeight() + m_padding * 2); pix.fill(Qt::white); QPainter painter(&pix); painter.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing); Graphics2D_qt g2(&painter); - render->draw(g2,m_padding,m_padding); + render->draw(g2, m_padding, m_padding); save_svg(pix); return QString::fromUtf8(svg_to_base64(pix)); } @@ -66,16 +65,15 @@ QString ctaiMathConvert::clean_latex_for_mula(const QString &formula) return result; } -QString ctaiMathConvert::replace_tags_svg(const QString &text,int font_size) +QString ctaiMathConvert::replace_tags_svg(const QString &text, int font_size) { - m_text_size=font_size; - //QString result("4566545646\\[\n f'(a) = \\lim_{h \\to 0} \\frac{f(a + h) - f(a)}{h}\n \\]654564646"); - QString result=text; + m_text_size = font_size*1.5; + QString result = text; // 使用改进的正则表达式模式 QRegularExpression latexPattern( QString(R"(\\[(](.*?)\\[)]|\\[{](.*?)\\[}]|\\[[](.*?)\\])"), QRegularExpression::MultilineOption | - QRegularExpression::DotMatchesEverythingOption); + QRegularExpression::DotMatchesEverythingOption); // 添加调试信息 qDebug() << "输入文本:" << result; @@ -84,7 +82,7 @@ QString ctaiMathConvert::replace_tags_svg(const QString &text,int font_size) QRegularExpressionMatchIterator iterator = latexPattern.globalMatch(result); - //收集所有替换操作 + // 收集所有替换操作 QList> replacements; QStringList svgResults; // 定义基础图片标签 @@ -93,8 +91,10 @@ QString ctaiMathConvert::replace_tags_svg(const QString &text,int font_size) { QRegularExpressionMatch match = iterator.next(); QString matchedText = match.captured(0); - // 调试输出 - debug_latex_match(result, match); + if (debug_node_print) + { + debug_latex_match(result, match); + } // 清理和转换公式 QString cleanFormula = clean_latex_for_mula(matchedText); QString svg_markdown = markdown_base + math_convert_svg(cleanFormula) + ")"; @@ -111,46 +111,80 @@ QString ctaiMathConvert::replace_tags_svg(const QString &text,int font_size) } return markdown_to_html(result); } -QString ctaiMathConvert::markdown_to_html(const QString& text){ - // 转换为UTF-8编码的字符串 - QByteArray markdown = text.toUtf8(); +QString ctaiMathConvert::markdown_to_html(const QString &text) +{ + // 转换为UTF-8编码的字符串 + QByteArray markdown = text.toUtf8(); - // 启用所有 GFM 扩展选项 - int options = CMARK_OPT_SOURCEPOS | - CMARK_OPT_VALIDATE_UTF8 | - CMARK_OPT_SMART | - CMARK_OPT_GITHUB_PRE_LANG | - CMARK_OPT_LIBERAL_HTML_TAG | - CMARK_OPT_FOOTNOTES| - CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE| - CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES| - CMARK_OPT_FULL_INFO_STRING; + // 启用所有 GFM 扩展选项 + int options = CMARK_OPT_SOURCEPOS | + CMARK_OPT_VALIDATE_UTF8 | + CMARK_OPT_SMART | + CMARK_OPT_GITHUB_PRE_LANG | + CMARK_OPT_LIBERAL_HTML_TAG | + CMARK_OPT_FOOTNOTES | + CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE | + CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES | + CMARK_OPT_FULL_INFO_STRING; - // 使用cmark-gfm解析Markdown - char *html = cmark_markdown_to_html( - markdown.constData(), - markdown.size(), - options); + // 解析Markdown为AST + cmark_node *doc = cmark_parse_document(markdown.constData(), markdown.size(), options); + if (debug_node_print) + { + // 递归打印AST节点 + print_ast_node(doc, 0); + } + // 转换为HTML + char *html = cmark_render_html(doc, options, NULL); + // 转换回QString并处理代码块 + QString result = QString::fromUtf8(html); + replace_symbol(result); + // 释放内存 + cmark_node_free(doc); + free(html); - // 转换回QString并处理代码块 - QString result = QString::fromUtf8(html); - free(html); - return fix_img_str_line_height(result.toUtf8()); } -QString ctaiMathConvert::fix_img_str_line_height(QString html) { - // 修正图片样式,使其与文本在同一行显示 - html.replace("
  • fullToHalfMap = { + {",", ","}, + {"。", "."}, + {"!", "!"}, + {"?", "?"}, + {":", ":"}, + {";", ";"}, + {"(", "("}, + {")", ")"}, + {"[", "["}, + {"]", "]"}, + {"【", "["}, + {"】", "]"}, + {"{", "{"}, + {"}", "}"}, + {"|", "|"}, + {""", "\""}, + {"'", "'"}, + {" ̄", "~"}, + {"<", "<"}, + {">", ">"}, + {"=", "="}, + {"+", "+"}, + {"-", "-"}, + {"*", "*"}, + {"/", "/"}, + {"%", "%"}, + {"#", "#"}, + {"&", "&"}, + {"@", "@"}, + {"`", "`"}, + {" ", " "} // 全角空格转换为半角空格 };