增加本地html浏览

修改大公式的图片显示方式,采用自动换行单独显示大公式图片
This commit is contained in:
JackLee 2025-03-11 21:09:31 +08:00
parent 010fb8aa53
commit aba2524edf
9 changed files with 89 additions and 19 deletions

View File

@ -16,6 +16,7 @@
<file>res/img/btn/default_header.png</file> <file>res/img/btn/default_header.png</file>
<file>res/img/btn/btn_msg_menu.png</file> <file>res/img/btn/btn_msg_menu.png</file>
<file>res/img/btn/btn_info_browser.png</file>
<file>res/img/btn/btn_info_copy.png</file> <file>res/img/btn/btn_info_copy.png</file>
<file>res/img/btn/btn_info_delete.png</file> <file>res/img/btn/btn_info_delete.png</file>
<file>res/img/btn/btn_info_down.png</file> <file>res/img/btn/btn_info_down.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -94,6 +94,13 @@ QPushButton#m_msg_copy{
background-color: #FFFFFF; background-color: #FFFFFF;
image:url(":/res/img/btn/btn_info_copy.png"); image:url(":/res/img/btn/btn_info_copy.png");
} }
QPushButton#m_msg_browser{
height:25px;
width:25px;
border:none;
background-color: #FFFFFF;
image:url(":/res/img/btn/btn_info_browser.png");
}
QPushButton#m_msg_save{ QPushButton#m_msg_save{
height:25px; height:25px;
width:25px; width:25px;

View File

@ -123,8 +123,9 @@ void ctaiHistoryTextEdit::connect_signals(msg_type msg_type_mode)
connect(m_msg_tokens, SIGNAL(clicked()), this, SLOT(on_tokens_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_mode(QString)), this, SLOT(on_display_changed(QString)));
connect(m_msg_tools, SIGNAL(on_signals_display_font_size()), this, SLOT(on_display_font_size_changed())); connect(m_msg_tools, SIGNAL(on_signals_display_font_size()), this, SLOT(on_display_font_size_changed()));
connect(m_msg_tools, SIGNAL(on_signals_send_browser()), this, SLOT(on_send_browser()));
// save菜单功能 // save菜单功能
connect(m_msg_tools, SIGNAL(on_signals_save_file(int)), this, SLOT(on_save_file(int))); connect(m_msg_tools, SIGNAL(on_signals_save_file(QString,int)), this, SLOT(on_save_file(QString,int)));
// 其他功能菜单 // 其他功能菜单
connect(m_msg_tools, SIGNAL(on_signals_menu()), this, SLOT(on_menu_slots())); connect(m_msg_tools, SIGNAL(on_signals_menu()), this, SLOT(on_menu_slots()));
} }
@ -134,6 +135,11 @@ void ctaiHistoryTextEdit::connect_signals(msg_type msg_type_mode)
} }
connect(m_msg_history, SIGNAL(textChanged()), this, SLOT(on_sync_text_height())); connect(m_msg_history, SIGNAL(textChanged()), this, SLOT(on_sync_text_height()));
} }
void ctaiHistoryTextEdit::on_send_browser(){
QString save_path=QDir::currentPath()+"/html/"+m_msg_sned_id+".html";
on_save_file(save_path,1);
QDesktopServices::openUrl(save_path);
}
void ctaiHistoryTextEdit::on_menu_slots() void ctaiHistoryTextEdit::on_menu_slots()
{ {
} }
@ -153,20 +159,17 @@ void ctaiHistoryTextEdit::on_copy_slots()
QClipboard *clipboard = QApplication::clipboard(); QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(text); clipboard->setText(text);
} }
void ctaiHistoryTextEdit::on_save_file(int index) void ctaiHistoryTextEdit::on_save_file(QString save_path,int index)
{ {
QString fileName;
QString temp_current_content; QString temp_current_content;
fileName = QFileDialog::getSaveFileName(this, tr("保存消息"), m_msg_sned_id + save_extend[index], save_extend_str[index]); if(save_path.isEmpty()){
if (fileName.isEmpty()) save_path = QFileDialog::getSaveFileName(this, tr("保存消息"), m_msg_sned_id + save_extend[index], save_extend_str[index]);
{
return;
} }
QFile file(fileName); QFile file(save_path);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{ {
QMessageBox::warning(this, tr("保存失败"), QMessageBox::warning(this, tr("保存失败"),
tr("无法保存文件 %1:\n%2").arg(fileName).arg(file.errorString())); tr("无法保存文件 %1:\n%2").arg(save_path).arg(file.errorString()));
return; return;
} }
QTextStream out(&file); QTextStream out(&file);
@ -186,7 +189,7 @@ void ctaiHistoryTextEdit::on_save_file(int index)
} }
if (!temp_current_content.isEmpty()) if (!temp_current_content.isEmpty())
{ {
out << m_current_content << "\n\n"; out << temp_current_content << "\n\n";
} }
file.close(); file.close();
} }
@ -212,6 +215,8 @@ void ctaiHistoryTextEdit::on_display_changed(QString mode)
else if (mode == "HTML渲染" || mode == "Markdown渲染") else if (mode == "HTML渲染" || mode == "Markdown渲染")
{ {
m_msg_history->setHtml(m_math_convert->replace_tags_svg(m_current_content, m_msg_tools->getFontSize().toInt())); m_msg_history->setHtml(m_math_convert->replace_tags_svg(m_current_content, m_msg_tools->getFontSize().toInt()));
QTextDocument *doc = m_msg_history->document();
doc->adjustSize();
} }
} }
void ctaiHistoryTextEdit::on_tokens_slots() void ctaiHistoryTextEdit::on_tokens_slots()

View File

@ -26,6 +26,7 @@
#include <QComboBox> #include <QComboBox>
#include <QTextBlock> #include <QTextBlock>
#include <QChar> #include <QChar>
#include <QDesktopServices>
// Qt对话框 // Qt对话框
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
@ -36,7 +37,6 @@
#include "ctai_base.h" #include "ctai_base.h"
#include "ctaiMathConvert.h" #include "ctaiMathConvert.h"
#include "ctaiHistoryTools.h" #include "ctaiHistoryTools.h"
typedef struct tokens_args typedef struct tokens_args
{ {
QString prompt_tokens = {}; QString prompt_tokens = {};
@ -70,8 +70,9 @@ private slots:
void on_display_changed(QString); // 显示模式改变 void on_display_changed(QString); // 显示模式改变
void on_display_font_size_changed(); // 字体大小改变 void on_display_font_size_changed(); // 字体大小改变
void on_sync_text_height(); void on_sync_text_height();
void on_save_file(int); // 保存文本 void on_save_file(QString,int); // 保存文本
void on_menu_slots(); void on_menu_slots();
void on_send_browser();
signals: signals:
void delete_requested(QString); // 请求删除此消息 void delete_requested(QString); // 请求删除此消息
void row_height_changed(bool); void row_height_changed(bool);
@ -91,8 +92,8 @@ private:
QPushButton *m_msg_system_header_ico = {}; QPushButton *m_msg_system_header_ico = {};
QPushButton *m_msg_user_header_ico = {}; QPushButton *m_msg_user_header_ico = {};
QLineEdit *m_msg_header = {}; QLineEdit *m_msg_header = {};
QTextEdit *m_msg_history = {}; QTextEdit *m_msg_history = {};
QPushButton *m_msg_user_del = {}; QPushButton *m_msg_user_del = {};
QPushButton *m_msg_system_del = {}; QPushButton *m_msg_system_del = {};
QPushButton *m_msg_tokens = {}; QPushButton *m_msg_tokens = {};

View File

@ -12,6 +12,7 @@ void ctaiHistoryTools::initLayout()
{ {
// 消息功能区 // 消息功能区
header_opts_Layout = new QHBoxLayout(); header_opts_Layout = new QHBoxLayout();
m_msg_browser=new QPushButton();
m_msg_copy = new QPushButton(); m_msg_copy = new QPushButton();
m_msg_save = new QPushButton(); m_msg_save = new QPushButton();
m_msg_menu = new QPushButton(); m_msg_menu = new QPushButton();
@ -28,6 +29,7 @@ void ctaiHistoryTools::initLayout()
m_msg_display_font_size_combobox->setObjectName("m_msg_font_size_combobox"); m_msg_display_font_size_combobox->setObjectName("m_msg_font_size_combobox");
m_msg_display_font_label->setObjectName("m_msg_font_label"); m_msg_display_font_label->setObjectName("m_msg_font_label");
m_msg_display_font_combobox->setObjectName("m_msg_font_combobox"); m_msg_display_font_combobox->setObjectName("m_msg_font_combobox");
m_msg_browser->setObjectName("m_msg_browser");
m_msg_copy->setObjectName("m_msg_copy"); m_msg_copy->setObjectName("m_msg_copy");
m_msg_save->setObjectName("m_msg_save"); m_msg_save->setObjectName("m_msg_save");
m_msg_menu->setObjectName("m_msg_menu"); m_msg_menu->setObjectName("m_msg_menu");
@ -42,6 +44,7 @@ void ctaiHistoryTools::initLayout()
header_opts_Layout->addWidget(m_msg_display_font_size_combobox); header_opts_Layout->addWidget(m_msg_display_font_size_combobox);
header_opts_Layout->addWidget(m_msg_display_label); header_opts_Layout->addWidget(m_msg_display_label);
header_opts_Layout->addWidget(m_msg_display_combobox); header_opts_Layout->addWidget(m_msg_display_combobox);
header_opts_Layout->addWidget(m_msg_browser);
header_opts_Layout->addWidget(m_msg_copy); header_opts_Layout->addWidget(m_msg_copy);
header_opts_Layout->addWidget(m_msg_save); header_opts_Layout->addWidget(m_msg_save);
header_opts_Layout->addWidget(m_msg_menu); header_opts_Layout->addWidget(m_msg_menu);
@ -68,6 +71,7 @@ void ctaiHistoryTools::initDisplayMode()
} }
void ctaiHistoryTools::initConnect() void ctaiHistoryTools::initConnect()
{ {
connect(m_msg_browser, SIGNAL(clicked()), this, SIGNAL(on_signals_send_browser()));
connect(m_msg_copy, SIGNAL(clicked()), this, SIGNAL(on_signals_copy())); connect(m_msg_copy, SIGNAL(clicked()), this, SIGNAL(on_signals_copy()));
connect(m_msg_save, SIGNAL(clicked()), this, SLOT(on_save_menu_slots())); connect(m_msg_save, SIGNAL(clicked()), this, SLOT(on_save_menu_slots()));
connect(m_msg_menu, SIGNAL(clicked()), this, SLOT(on_opts_menu_slots())); connect(m_msg_menu, SIGNAL(clicked()), this, SLOT(on_opts_menu_slots()));
@ -98,7 +102,7 @@ void ctaiHistoryTools::on_save_menu_slots()
} }
void ctaiHistoryTools::on_save_action_slots(){ void ctaiHistoryTools::on_save_action_slots(){
save_index=sender()->objectName().toInt(); save_index=sender()->objectName().toInt();
emit on_signals_save_file(save_index); emit on_signals_save_file({},save_index);
} }
void ctaiHistoryTools::on_opts_menu_slots() void ctaiHistoryTools::on_opts_menu_slots()
{ {

View File

@ -22,6 +22,7 @@ public:
QString getFont(); QString getFont();
private: private:
QHBoxLayout *header_opts_Layout = {}; QHBoxLayout *header_opts_Layout = {};
QPushButton *m_msg_browser={};
QPushButton *m_msg_copy = {}; QPushButton *m_msg_copy = {};
QPushButton *m_msg_save = {}; QPushButton *m_msg_save = {};
QPushButton *m_msg_menu = {}; QPushButton *m_msg_menu = {};
@ -50,7 +51,8 @@ signals:
void on_signals_fold(); void on_signals_fold();
void on_signals_display_mode(QString); void on_signals_display_mode(QString);
void on_signals_display_font_size(); void on_signals_display_font_size();
void on_signals_save_file(int); void on_signals_save_file(QString,int);
void on_signals_send_browser();
public slots: public slots:
void on_save_menu_slots(); void on_save_menu_slots();
void on_opts_menu_slots(); void on_opts_menu_slots();

View File

@ -17,7 +17,7 @@ void ctaiHistoryWidget::setup_table()
// 设置自动滚动属性 // 设置自动滚动属性
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
// 滚动步长 // 滚动步长
verticalScrollBar()->setSingleStep(5); verticalScrollBar()->setSingleStep(10);
} }
ctaiHistoryWidget::~ctaiHistoryWidget() ctaiHistoryWidget::~ctaiHistoryWidget()

View File

@ -36,7 +36,7 @@ QString ctaiMathConvert::math_convert_svg(const QString &math)
painter.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing); painter.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing);
Graphics2D_qt g2(&painter); Graphics2D_qt g2(&painter);
render->draw(g2, m_padding, m_padding); render->draw(g2, m_padding, m_padding);
save_svg(pix); // save_svg(pix);
return QString::fromUtf8(svg_to_base64(pix)); return QString::fromUtf8(svg_to_base64(pix));
} }
@ -67,7 +67,7 @@ QString ctaiMathConvert::clean_latex_for_mula(const QString &formula)
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*1.5; m_text_size = font_size * 1.5;
QString result = text; QString result = text;
// 使用改进的正则表达式模式 // 使用改进的正则表达式模式
QRegularExpression latexPattern( QRegularExpression latexPattern(
@ -119,6 +119,7 @@ QString ctaiMathConvert::markdown_to_html(const QString &text)
// 启用所有 GFM 扩展选项 // 启用所有 GFM 扩展选项
int options = CMARK_OPT_SOURCEPOS | int options = CMARK_OPT_SOURCEPOS |
CMARK_OPT_VALIDATE_UTF8 | CMARK_OPT_VALIDATE_UTF8 |
CMARK_OPT_HARDBREAKS |
CMARK_OPT_SMART | CMARK_OPT_SMART |
CMARK_OPT_GITHUB_PRE_LANG | CMARK_OPT_GITHUB_PRE_LANG |
CMARK_OPT_LIBERAL_HTML_TAG | CMARK_OPT_LIBERAL_HTML_TAG |
@ -138,6 +139,55 @@ QString ctaiMathConvert::markdown_to_html(const QString &text)
char *html = cmark_render_html(doc, options, NULL); char *html = cmark_render_html(doc, options, NULL);
// 转换回QString并处理代码块 // 转换回QString并处理代码块
QString result = QString::fromUtf8(html); QString result = QString::fromUtf8(html);
// 添加基础CSS样式
const QString css = R"(
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
line-height: 1.6;
padding: 0 1em;
}
pre {
background-color: #f6f8fa;
border-radius: 3px;
padding: 16px;
overflow: auto;
}
code {
background-color: rgba(175,184,193,0.2);
border-radius: 3px;
padding: .2em .4em;
font-family: ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace;
}
pre code {
background-color: transparent;
padding: 0;
}
table {
border-collapse: collapse;
margin: 1em 0;
}
th, td {
border: 1px solid #d0d7de;
padding: 6px 13px;
}
th {
background-color: #f6f8fa;
}
blockquote {
color: #57606a;
border-left: 4px solid #d0d7de;
margin: 1em 0;
padding: 0 1em;
}
.custom-height {
height: 60px;
}
</style>
)";
// 在<head>标签后插入CSS
result.replace("<head>", "<head>" + css);
result.replace("<li", "<li class=\"custom-height\"");
replace_symbol(result); replace_symbol(result);
// 释放内存 // 释放内存
cmark_node_free(doc); cmark_node_free(doc);