1-调整类名和类文件名

2-给公式显示svg增加边距
3-增加字体和字号功能(未实装)
This commit is contained in:
JackLee 2025-03-09 18:29:30 +08:00
parent e0ffdbd010
commit 5247485491
30 changed files with 708 additions and 574 deletions

View File

@ -134,9 +134,9 @@ void LaTeX::setDebug(bool debug) {
TeXRender* LaTeX::parse(const wstring& latex, int width, float textSize, float lineSpace, color fg) {
bool lined = true;
if (startswith(latex, L"$$") || startswith(latex, L"\\[")) {
lined = false;
}
// if (startswith(latex, L"$$") || startswith(latex, L"\\[")) {
// lined = false;
// }
Alignment align = lined ? Alignment::left : Alignment::center;
_formula->setLaTeX(latex);
TeXRender* render =

View File

@ -9,7 +9,7 @@ ctai::~ctai(){
void ctai::init_layout(){
m_layout=new QHBoxLayout();
m_widget=new QWidget();
m_tabwidget=new ctai_tabwidget();
m_tabwidget=new ctaiTabWidget();
m_tabwidget->init_layout();
title()->set_title(tr("CTAI"));
m_layout->addWidget(m_tabwidget);

View File

@ -2,8 +2,8 @@
#define CTAI_H
#include "sui.h"
#include <QTextEdit>
#include "ctai_tabbar.h"
#include "ctai_tabwidget.h"
#include "ctaiTabBar.h"
#include "ctaiTabWidget.h"
class ctai:public sui{
Q_OBJECT
public:
@ -14,10 +14,10 @@ private:
QWidget* m_widget;
QHBoxLayout* m_layout;
ctai_tabwidget* m_tabwidget;
ctaiTabWidget* m_tabwidget;
QTextEdit* m_log_info;
QTextEdit* m_user_info;
ctai_tabbar* m_tabbar;
ctaiTabBar* m_tabbar;
};
#endif

View File

@ -1,6 +1,6 @@
#include "ctai_cmd.h"
#include "ctaiCmd.h"
ctai_cmd::ctai_cmd()
ctaiCmd::ctaiCmd()
{
QVBoxLayout *layout = new QVBoxLayout(this);
textEdit = new QPlainTextEdit(this);
@ -18,7 +18,7 @@ ctai_cmd::ctai_cmd()
});
process = new QProcess(this);
process->setProcessChannelMode(QProcess::MergedChannels); // 合并输出通道
connect(process, &QProcess::readyRead, this, &ctai_cmd::slots_readProcessOutput);
connect(process, &QProcess::readyRead, this, &ctaiCmd::slots_readProcessOutput);
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[](int code, QProcess::ExitStatus status){
QMessageBox::warning(nullptr, "Process",
@ -31,11 +31,11 @@ ctai_cmd::ctai_cmd()
process->start("/bin/bash");
#endif
}
ctai_cmd::~ctai_cmd()
ctaiCmd::~ctaiCmd()
{
}
void ctai_cmd::slots_readProcessOutput() {
void ctaiCmd::slots_readProcessOutput() {
// 实时读取输出
QByteArray output = process->readAll();
textEdit->appendPlainText(QString::fromLocal8Bit(output));
@ -45,7 +45,7 @@ void ctai_cmd::slots_readProcessOutput() {
cursor.movePosition(QTextCursor::End);
textEdit->setTextCursor(cursor);
}
void ctai_cmd::slots_executeCommand(const QString &command)
void ctaiCmd::slots_executeCommand(const QString &command)
{
if (!command.isEmpty()) {
// 写入命令到进程

View File

@ -1,5 +1,5 @@
#ifndef CTAI_CMD_H
#define CTAI_CMD_H
#ifndef CTAICMD_H
#define CTAICMD_H
#include <QPlainTextEdit>
#include <QPushButton>
@ -9,11 +9,11 @@
#include <QStringList>
#include <QMessageBox>
#include <QProcess>
class ctai_cmd : public QWidget {
class ctaiCmd : public QWidget {
Q_OBJECT
public:
ctai_cmd();
~ctai_cmd();
ctaiCmd();
~ctaiCmd();
private slots:
void slots_executeCommand(const QString &command);
void slots_readProcessOutput();

View File

@ -1,11 +1,11 @@
#include "ctai_curl.h"
#include "ctaiCurl.h"
ctai_curl::ctai_curl() : m_curl(nullptr),
ctaiCurl::ctaiCurl() : m_curl(nullptr),
m_headers(nullptr),
m_initialized(false) // 初始化标志
{
}
ctai_curl::~ctai_curl()
ctaiCurl::~ctaiCurl()
{
if (m_curl != nullptr)
{
@ -36,14 +36,14 @@ size_t not_stream_callback(void *buffer, size_t sz, size_t nmemb, void *userdata
//qDebug() << "not steam data chunk:" << *psResponse;
return sz * nmemb;
}
void ctai_curl::set_send_post_headers(std::string head_str)
void ctaiCurl::set_send_post_headers(std::string head_str)
{
m_headers = curl_slist_append(m_headers, head_str.c_str());
qDebug() << "header:" << head_str;
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_headers);
}
void ctai_curl::set_curl_ssl(bool ssl_state)
void ctaiCurl::set_curl_ssl(bool ssl_state)
{
std::string ca_bundle = QDir::currentPath().toStdString() + "/cert/cacert.pem";
if (ssl_state)
@ -60,12 +60,12 @@ void ctai_curl::set_curl_ssl(bool ssl_state)
}
qDebug() << "curl opts ssl:" << ssl_state << "ssl_pem:" << ca_bundle;
}
void ctai_curl::set_curl_timeout(int time)
void ctaiCurl::set_curl_timeout(int time)
{
curl_easy_setopt(m_curl, CURLOPT_TIMEOUT, time);
qDebug() << "curl opts timeout:" << time;
}
void ctai_curl::set_curl_followlocation(bool followlocation_state)
void ctaiCurl::set_curl_followlocation(bool followlocation_state)
{
if (followlocation_state)
{
@ -77,7 +77,7 @@ void ctai_curl::set_curl_followlocation(bool followlocation_state)
}
qDebug() << "curl opts followlocation_state:" << followlocation_state;
}
void ctai_curl::set_curl_debug_verbose(bool verbose_state)
void ctaiCurl::set_curl_debug_verbose(bool verbose_state)
{
if (verbose_state)
{
@ -89,7 +89,7 @@ void ctai_curl::set_curl_debug_verbose(bool verbose_state)
}
qDebug() << "curl opts verbose_state:" << verbose_state;
}
void ctai_curl::set_curl_tcp_keepalive(bool keepalive_state)
void ctaiCurl::set_curl_tcp_keepalive(bool keepalive_state)
{
if (keepalive_state)
{
@ -108,7 +108,7 @@ void ctai_curl::set_curl_tcp_keepalive(bool keepalive_state)
qDebug() << "curl opts keepalive_state:" << keepalive_state;
}
std::vector<std::string> ctai_curl::steam_extract(const std::string &input)
std::vector<std::string> ctaiCurl::steam_extract(const std::string &input)
{
std::vector<std::string> result;
// 定义正则表达式模式,用于匹配 data: 和 \n\n 之间的内容
@ -125,13 +125,13 @@ std::vector<std::string> ctai_curl::steam_extract(const std::string &input)
}
return result;
}
std::string ctai_curl::send_timestamp_to_time(time_t timestamp)
std::string ctaiCurl::send_timestamp_to_time(time_t timestamp)
{
// 将时间戳转换为 QDateTime 对象
QDateTime dateTime = QDateTime::fromSecsSinceEpoch(timestamp);
return dateTime.toString("yyyy-MM-dd hh:mm:ss").toStdString();
}
void ctai_curl::send_stream(model_data &data, std::string response_data)
void ctaiCurl::send_stream(model_data &data, std::string response_data)
{
std::vector<std::string> _info_data = steam_extract(response_data);
if (!_info_data.empty())
@ -152,7 +152,7 @@ void ctai_curl::send_stream(model_data &data, std::string response_data)
}
}
}
void ctai_curl::send_not_stream(model_data &data, std::string response_data)
void ctaiCurl::send_not_stream(model_data &data, std::string response_data)
{
json response = json::parse(response_data);
if (data.postback_stream_mode)
@ -214,7 +214,7 @@ void ctai_curl::send_not_stream(model_data &data, std::string response_data)
}
}
}
std::string ctai_curl::send_send_body(model_data m_data)
std::string ctaiCurl::send_send_body(model_data m_data)
{
json _request_body = {
{"model", m_data.user_model},
@ -224,7 +224,7 @@ std::string ctai_curl::send_send_body(model_data m_data)
qDebug() << "request_body_str:" << _request_body.dump(4);
return _request_body.dump();
}
void ctai_curl::set_send_post_option()
void ctaiCurl::set_send_post_option()
{
set_curl_ssl(c_opts.ssl_state);
set_curl_timeout(c_opts.timeout);
@ -242,7 +242,7 @@ void ctai_curl::set_send_post_option()
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDSIZE, c_data.request_body.length());
curl_easy_setopt(m_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
}
void ctai_curl::set_send_post_opts_reset()
void ctaiCurl::set_send_post_opts_reset()
{
// 先清理 headers
if (m_headers)
@ -264,7 +264,7 @@ void ctai_curl::set_send_post_opts_reset()
}
}
}
void ctai_curl::curl_init()
void ctaiCurl::curl_init()
{
if (!m_initialized)
{
@ -283,7 +283,7 @@ void ctai_curl::curl_init()
throw std::runtime_error("Failed to initialize CURL handle");
}
}
void ctai_curl::send_post_response(model_data m_data, curl_opts opts)
void ctaiCurl::send_post_response(model_data m_data, curl_opts opts)
{
if (!m_curl)
{

View File

@ -1,5 +1,5 @@
#ifndef CTAI_CURL_H
#define CTAI_CURL_H
#ifndef CTAICURL_H
#define CTAICURL_H
#include <QObject>
#include <QDir>
@ -13,14 +13,12 @@
#include <regex>
using json = nlohmann::json;
class ctai_curl : public QObject
class ctaiCurl : public QObject
{
Q_OBJECT
public:
ctai_curl();
~ctai_curl();
ctaiCurl();
~ctaiCurl();
void curl_init();
void send_post_response(model_data,curl_opts);
void send_stream(model_data &, std::string response_data);
@ -52,7 +50,7 @@ signals:
typedef struct call_back_context
{
ctai_curl *instance;
ctaiCurl *instance;
model_data m_data;
} call_back_context;

View File

@ -1,33 +1,73 @@
#include "ctai_history_textedit.h"
#include "ctaiHistoryTextEdit.h"
ctai_history_textedit::ctai_history_textedit(QWidget *parent)
ctaiHistoryTextEdit::ctaiHistoryTextEdit(QWidget *parent)
: QWidget(parent)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
}
ctai_history_textedit::~ctai_history_textedit()
ctaiHistoryTextEdit::~ctaiHistoryTextEdit()
{
}
void ctai_history_textedit::init_layout(msg_type msg_type_mode)
void ctaiHistoryTextEdit::init_layout(msg_type msg_type_mode)
{
// 主垂直布局
mainLayout = new QVBoxLayout();
// 1. 消息头垂直
headerLayout = new QVBoxLayout();
header_info_Layout = new QHBoxLayout();
main_layout = new QVBoxLayout();
init_msg_line();
init_msg_header_layout(msg_type_mode);
init_msg_history_layout();
//主布局
main_layout->addLayout(header_layout);
main_layout->addLayout(history_layout);
main_layout->addItem(bottom_spacer);
main_layout->setStretch(0, 1);
main_layout->setSpacing(1);
main_layout->setContentsMargins(0, 0, 0, 0);
setLayout(main_layout);
connect_signals(msg_type_mode);
}
void ctaiHistoryTextEdit::init_msg_line()
{
//分割线区域
msg_line = new QFrame;
msg_line->setFrameShape(QFrame::HLine); // 关键属性
msg_line->setFrameShadow(QFrame::Sunken); // 凹陷效果
msg_line->setLineWidth(2); // 线宽
}
void ctaiHistoryTextEdit::init_msg_history_layout()
{
history_layout = new QVBoxLayout();
// 历史信息QTextEdit
m_msg_history = new QTextEdit();
m_math_convert = new ctaiMathConvert();
m_msg_history->setUndoRedoEnabled(false); // 关闭撤销历史以节省内存
m_msg_history->setAcceptRichText(true);
m_msg_history->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_msg_history->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
m_msg_history->setObjectName("m_msg_history");
m_msg_history->setReadOnly(true);
history_layout->addWidget(m_msg_history);
history_layout->addWidget(msg_line);
history_layout->setContentsMargins(0, 0, 0, 0);
}
void ctaiHistoryTextEdit::init_msg_header_layout(msg_type msg_type_mode)
{
//消息头左区域布局,ico,id,fp,time
header_info_layout = new QHBoxLayout();
//消息区头整体垂直
header_layout = new QVBoxLayout();
header_opts_layout=new QHBoxLayout();
m_msg_header = new QLineEdit();
m_msg_header->setObjectName("m_msg_header");
m_msg_header->setReadOnly(true);
if (msg_type_mode == SYSTEM)
{
// SYSTEM消息头水平
// 1.SYSTEM消息头水平左信息区
m_msg_system_header_ico = new QPushButton();
m_msg_system_header_ico->setObjectName("m_msg_system_header_ico");
header_info_Layout->addWidget(m_msg_system_header_ico);
header_info_Layout->addWidget(m_msg_header);
header_info_Layout->setContentsMargins(0, 0, 0, 0);
headerLayout->addLayout(header_info_Layout);
// 2.tokens功能按钮
header_info_layout->addWidget(m_msg_system_header_ico);
header_info_layout->addWidget(m_msg_header);
header_info_layout->setContentsMargins(0, 0, 0, 0);
// 2.SYSTEM消息头水平右信息区
m_msg_tokens = new QPushButton();
m_history_to_send = new QPushButton();
m_msg_system_del = new QPushButton();
@ -36,51 +76,25 @@ void ctai_history_textedit::init_layout(msg_type msg_type_mode)
m_history_to_send->setObjectName("m_history_to_send");
m_msg_system_del->setObjectName("m_msg_system_del");
m_restart_to_send->setObjectName("m_restart_to_send");
header_info_Layout->addWidget(m_history_to_send);
header_info_Layout->addWidget(m_msg_tokens);
header_info_Layout->addWidget(m_restart_to_send);
header_info_Layout->addWidget(m_msg_system_del);
// 3.消息功能区
header_opts_Layout = new QHBoxLayout();
m_msg_copy = new QPushButton();
m_msg_save = new QPushButton();
m_msg_menu = new QPushButton();
m_msg_fold = new QPushButton();
m_msg_display_combobox=new QComboBox();
m_msg_display_label=new QLabel("显示模式:");
m_msg_display_label->setObjectName("m_msg_menu_label");
m_msg_display_combobox->setObjectName("m_msg_display_combobox");
m_msg_copy->setObjectName("m_msg_copy");
m_msg_save->setObjectName("m_msg_save");
m_msg_menu->setObjectName("m_msg_menu");
m_msg_fold->setObjectName("m_msg_fold");
m_msg_fold->setIcon(QIcon(":res/img/btn/btn_info_up.png"));
m_msg_fold->setIconSize(QSize(25, 25));
m_msg_display_combobox->addItem("原始文本");
m_msg_display_combobox->addItem("LaTeX Markdown");
header_opts_Layout->addItem(sparcer_item);
header_opts_Layout->addWidget(m_msg_display_label);
header_opts_Layout->addWidget(m_msg_display_combobox);
header_opts_Layout->addWidget(m_msg_copy);
header_opts_Layout->addWidget(m_msg_save);
header_opts_Layout->addWidget(m_msg_menu);
header_opts_Layout->addWidget(m_msg_fold);
header_opts_Layout->addItem(sparcer_item);
header_opts_Layout->setContentsMargins(0, 0, 0, 0);
headerLayout->addLayout(header_opts_Layout);
header_info_layout->addWidget(m_history_to_send);
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();
header_opts_layout->addWidget(m_msg_tools);
// 4.添加到消息头主布局
header_layout->addLayout(header_info_layout);
header_layout->addLayout(header_opts_layout);
}
else
{
// SYSTEM MSG ICO
m_msg_user_header_ico = new QPushButton();
m_msg_user_header_ico->setObjectName("m_msg_system_header_ico");
header_info_Layout->addWidget(m_msg_user_header_ico);
header_info_Layout->addWidget(m_msg_header);
header_info_Layout->setContentsMargins(0, 0, 0, 0);
headerLayout->addLayout(header_info_Layout);
header_info_layout->addWidget(m_msg_user_header_ico);
header_info_layout->addWidget(m_msg_header);
header_info_layout->setContentsMargins(0, 0, 0, 0);
// USER DELETE BUTTON
m_msg_user_del = new QPushButton();
m_msg_user_del->setObjectName("m_msg_user_del");
@ -88,59 +102,104 @@ void ctai_history_textedit::init_layout(msg_type msg_type_mode)
m_history_to_send->setObjectName("m_history_to_send");
m_restart_to_send = new QPushButton();
m_restart_to_send->setObjectName("m_restart_to_send");
header_info_Layout->addWidget(m_history_to_send);
header_info_Layout->addWidget(m_restart_to_send);
header_info_Layout->addWidget(m_msg_user_del);
header_info_layout->addWidget(m_history_to_send);
header_info_layout->addWidget(m_restart_to_send);
header_info_layout->addWidget(m_msg_user_del);
header_layout->addLayout(header_info_layout);
}
// 4.分割线区域
hLine = new QFrame;
hLine->setFrameShape(QFrame::HLine); // 关键属性
hLine->setFrameShadow(QFrame::Sunken); // 凹陷效果
hLine->setLineWidth(2); // 线宽
// 5. 历史信息QTextEdit
historyLayout = new QVBoxLayout();
m_msg_history = new QTextEdit();
m_math_convert=new ctai_math_convert();
m_msg_history->setUndoRedoEnabled(false); // 关闭撤销历史以节省内存
m_msg_history->setAcceptRichText(true);
m_msg_history->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_msg_history->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
m_msg_history->setObjectName("m_msg_history");
m_msg_history->setReadOnly(true);
historyLayout->addWidget(m_msg_history);
historyLayout->addWidget(hLine);
historyLayout->setContentsMargins(0, 0, 0, 0);
// 组合布局
mainLayout->addLayout(headerLayout);
mainLayout->addLayout(historyLayout);
mainLayout->addItem(bottom_spacer);
mainLayout->setStretch(0, 1);
mainLayout->setSpacing(1);
mainLayout->setContentsMargins(0, 0, 0, 0);
setLayout(mainLayout);
connect_signals(msg_type_mode);
}
void ctai_history_textedit::connect_signals(msg_type msg_type_mode)
void ctaiHistoryTextEdit::connect_signals(msg_type msg_type_mode)
{
if (msg_type_mode == SYSTEM)
{
connect(m_msg_system_del, SIGNAL(clicked()), this, SLOT(on_delete_clicked()));
connect(m_msg_copy, SIGNAL(clicked()), this, SLOT(on_copy_clicked()));
connect(m_msg_save, SIGNAL(clicked()), this, SLOT(on_save_clicked()));
connect(m_msg_menu, SIGNAL(clicked()), this, SLOT(on_menu_clicked()));
connect(m_msg_fold, SIGNAL(clicked()), this, SLOT(on_fold_clicked()));
connect(m_msg_tokens, SIGNAL(clicked()), this, SLOT(on_tokens_clicked()));
connect(m_msg_display_combobox, SIGNAL(currentTextChanged(QString)), this, SLOT(on_display_changed(QString)));
connect(m_msg_system_del, SIGNAL(clicked()), this, SLOT(on_delete_slots()));
connect(m_msg_tools, SIGNAL(on_signals_copy()), this, SLOT(on_copy_slots()));
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)));
//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_menu()), this, SLOT(on_menu_slots()));
}
else
{
connect(m_msg_user_del, SIGNAL(clicked()), this, SLOT(on_delete_clicked()));
connect(m_msg_user_del, SIGNAL(clicked()), this, SLOT(on_delete_slots()));
}
connect(m_msg_history, SIGNAL(textChanged()), this, SLOT(on_sync_text_height()));
}
void ctai_history_textedit::on_display_changed(QString mode)
void ctaiHistoryTextEdit::on_menu_slots()
{
}
void ctaiHistoryTextEdit::on_display_font_size_changed(QString font_size)
{
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));
}
void ctaiHistoryTextEdit::on_delete_slots()
{
// 发送删除请求信号
emit delete_requested(m_msg_sned_id);
}
void ctaiHistoryTextEdit::on_copy_slots()
{
// 获取文本并复制到剪贴板
QString text = m_msg_history->toPlainText();
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(text);
}
void ctaiHistoryTextEdit::on_save_text()
{
QString fileName = QFileDialog::getSaveFileName(this,
tr("保存消息"), m_msg_sned_id + ".txt",
tr("文本文件 (*.txt)"));
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->toPlainText() << "\n\n";
}
void ctaiHistoryTextEdit::on_save_html()
{
}
void ctaiHistoryTextEdit::on_save_markdown()
{
}
void ctaiHistoryTextEdit::on_save_pdf()
{
}
// 实现折叠功能的槽函数
void ctaiHistoryTextEdit::on_fold_slots()
{
m_is_folded = !m_is_folded;
m_msg_history->setFixedHeight(m_is_folded ? 0 : m_original_height);
m_msg_tools->setFoldIco(QIcon(m_is_folded ? ":res/img/btn/btn_info_down.png" : ":res/img/btn/btn_info_up.png"));
updateGeometry();
emit row_height_changed(m_is_folded);
}
void ctaiHistoryTextEdit::on_display_changed(QString mode)
{
// 根据显示模式设置文本
if (mode == "原始文本")
@ -154,7 +213,7 @@ void ctai_history_textedit::on_display_changed(QString mode)
}
}
// tokens按钮实现功能的槽函数
void ctai_history_textedit::on_tokens_clicked()
void ctaiHistoryTextEdit::on_tokens_slots()
{
if (!m_msg_tokens_menu)
{
@ -187,51 +246,8 @@ void ctai_history_textedit::on_tokens_clicked()
m_msg_tokens_menu->addAction(m_menu_total_tokens);
m_msg_tokens_menu->exec(QCursor::pos());
}
// save按钮实现功能的槽函数
void ctai_history_textedit::on_save_clicked()
{
if (!m_msg_save_menu)
{
m_msg_save_menu = new QMenu();
}
if (!m_msg_save_text)
{
m_msg_save_text = new QAction(tr("另存为文本"));
connect(m_msg_save_text, SIGNAL(triggered(bool)), this, SLOT(on_save_text()));
}
if (!m_msg_save_html)
{
m_msg_save_html = new QAction(tr("另存为HTML"));
connect(m_msg_save_html, SIGNAL(triggered(bool)), this, SLOT(on_save_html()));
}
if (!m_msg_save_markdown)
{
m_msg_save_markdown = new QAction(tr("另存为Markdown"));
connect(m_msg_save_markdown, SIGNAL(triggered(bool)), this, SLOT(on_save_markdown()));
}
if (!m_msg_save_pdf)
{
m_msg_save_pdf = new QAction(tr("另存为PDF"));
connect(m_msg_save_pdf, SIGNAL(triggered(bool)), this, SLOT(on_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 ctai_history_textedit::on_fold_clicked()
{
m_is_folded = !m_is_folded;
m_msg_history->setFixedHeight(m_is_folded ? 0 : m_original_height);
m_msg_fold->setIcon(QIcon(m_is_folded ? ":res/img/btn/btn_info_down.png" : ":res/img/btn/btn_info_up.png"));
updateGeometry();
emit row_height_changed(m_is_folded);
}
void ctai_history_textedit::on_sync_text_height()
void ctaiHistoryTextEdit::on_sync_text_height()
{
// 防抖动处理如果上次更新在100ms内则延迟处理
static QTimer debounceTimer;
@ -276,7 +292,7 @@ void ctai_history_textedit::on_sync_text_height()
// 设置下一次检查的延迟
debounceTimer.start(100);
}
void ctai_history_textedit::add_user_message(const model_data &message)
void ctaiHistoryTextEdit::add_user_message(const model_data &message)
{
QString disp_data;
disp_data = QSL(message.send_user_data);
@ -284,7 +300,7 @@ void ctai_history_textedit::add_user_message(const model_data &message)
m_msg_history->setMarkdown(disp_data);
}
void ctai_history_textedit::add_system_message(const model_data &message)
void ctaiHistoryTextEdit::add_system_message(const model_data &message)
{
m_msg_sned_id = QSL(message.postback_send_id);
std::lock_guard<std::mutex> lock(m_mutex);
@ -304,7 +320,7 @@ void ctai_history_textedit::add_system_message(const model_data &message)
}
}
// 增加tokens信息
void ctai_history_textedit::update_tokens_message(const model_data &message)
void ctaiHistoryTextEdit::update_tokens_message(const model_data &message)
{
if (message.msg_type_mode == SYSTEM)
{
@ -316,7 +332,7 @@ void ctai_history_textedit::update_tokens_message(const model_data &message)
}
}
// 增加头信息
void ctai_history_textedit::add_header_message(const model_data &message)
void ctaiHistoryTextEdit::add_header_message(const model_data &message)
{
QString disp_header;
if (message.msg_type_mode == SYSTEM)
@ -329,78 +345,3 @@ void ctai_history_textedit::add_header_message(const model_data &message)
}
m_msg_header->setText(disp_header);
}
void ctai_history_textedit::on_delete_clicked()
{
// 发送删除请求信号
emit delete_requested(m_msg_sned_id);
}
void ctai_history_textedit::on_copy_clicked()
{
// 获取文本并复制到剪贴板
QString text = m_msg_history->toPlainText();
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(text);
}
void ctai_history_textedit::on_save_text()
{
QString fileName = QFileDialog::getSaveFileName(this,
tr("保存消息"), m_msg_sned_id + ".txt",
tr("文本文件 (*.txt)"));
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->toPlainText() << "\n\n";
}
void ctai_history_textedit::on_save_html()
{
}
void ctai_history_textedit::on_save_markdown()
{
}
void ctai_history_textedit::on_save_pdf()
{
}
void ctai_history_textedit::on_menu_clicked()
{
QMenu menu(this);
// 添加菜单项
QAction *actCopy = menu.addAction(tr("复制"));
QAction *actSave = menu.addAction(tr("保存"));
menu.addSeparator();
QAction *actDelete = menu.addAction(tr("删除"));
// 显示菜单
QPoint pos = m_msg_menu->mapToGlobal(m_msg_menu->rect().bottomRight());
QAction *act = menu.exec(pos);
// 处理菜单选择
if (act == actCopy)
{
on_copy_clicked();
}
else if (actSave)
{
on_save_clicked();
}
else if (act == actDelete)
{
on_delete_clicked();
}
}

126
src/ctaiHistoryTextEdit.h Normal file
View File

@ -0,0 +1,126 @@
// ctaitextedit.h
#ifndef CTAIHISTORYTEXTEDIT_H
#define CTAIHISTORYTEXTEDIT_H
// Qt核心组件
#include <QWidget>
#include <QString>
#include <QApplication>
#include <QClipboard>
// Qt布局相关
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QSpacerItem>
// Qt控件相关
#include <QPushButton>
#include <QTextEdit>
#include <QLineEdit>
#include <QFrame>
#include <QMenu>
#include <QAction>
#include <QAbstractTextDocumentLayout>
#include <QAbstractScrollArea>
#include <QTimer>
#include <QLabel>
#include <QComboBox>
// Qt对话框
#include <QFileDialog>
#include <QMessageBox>
// 系统相关
#include <mutex>
// 项目相关头文件
#include "ctai_base.h"
#include "ctaiMathConvert.h"
#include "ctaiHistoryTools.h"
typedef struct tokens_args
{
QString prompt_tokens = {};
QString completion_tokens = {};
QString total_tokens = {};
QString cache_hit_tokens = {};
QString cache_miss_tokens = {};
} tokens_data;
std::mutex m_mutex;
class ctaiHistoryTextEdit : public QWidget
{
Q_OBJECT
public:
ctaiHistoryTextEdit(QWidget *parent = nullptr);
~ctaiHistoryTextEdit();
void init_layout(msg_type msg_type_mode);
void init_msg_header_layout(msg_type msg_type_mode);
void init_msg_history_layout();
void init_msg_line();
void add_user_message(const model_data &message);
void add_system_message(const model_data &message);
void update_tokens_message(const model_data &message);
void add_header_message(const model_data &message);
private slots:
void on_delete_slots(); // 删除按钮
void on_copy_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_sync_text_height();
void on_save_text(); // 保存文本
void on_save_html(); // 保存html
void on_save_markdown(); // 保存markdown
void on_save_pdf(); // 保存pdf
void on_menu_slots();
signals:
void delete_requested(QString); // 请求删除此消息
void row_height_changed(bool);
private:
void connect_signals(msg_type msg_type_mode); // 连接信号和槽
private:
ctaiMathConvert *m_math_convert;
QFrame *msg_line;
QSpacerItem *sparcer_item = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed);
QVBoxLayout *main_layout = {};
QVBoxLayout *header_layout = {};
QHBoxLayout *header_info_layout = {};
QHBoxLayout *header_opts_layout = {};
QVBoxLayout *history_layout = {};
QPushButton *m_msg_system_header_ico = {};
QPushButton *m_msg_user_header_ico = {};
QLineEdit *m_msg_header = {};
QTextEdit *m_msg_history = {};
QPushButton *m_msg_user_del = {};
QPushButton *m_msg_system_del = {};
QPushButton *m_msg_tokens = {};
QPushButton *m_history_to_send = {};
QPushButton *m_restart_to_send = {};
// 信息功能区
ctaiHistoryTools *m_msg_tools = {};
// tokens消耗显示
QMenu *m_msg_tokens_menu = {};
QAction *m_menu_prompt_tokens = {};
QAction *m_menu_completion_tokens = {};
QAction *m_menu_total_tokens = {};
QAction *m_menu_cache_hit_tokens = {};
QAction *m_menu_cache_miss_tokens = {};
// 保存展开时的原始高度
int m_original_height = 0;
// 折叠状态
bool m_is_folded = false;
// 本次会话的tokens消耗信息
tokens_data m_tokens_data;
// 本次信息ID
QString m_msg_sned_id = {};
// 本次信息
QString m_current_content;
QString m_font = "Arial";
int m_font_size = 8;
QSpacerItem *bottom_spacer = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding);
};
#endif // ctai_history_textedit_H

127
src/ctaiHistoryTools.cpp Normal file
View File

@ -0,0 +1,127 @@
#include "ctaiHistoryTools.h"
ctaiHistoryTools::ctaiHistoryTools()
{
initLayout();
initConnect();
}
ctaiHistoryTools::~ctaiHistoryTools()
{
}
void ctaiHistoryTools::initLayout()
{
// 消息功能区
header_opts_Layout = new QHBoxLayout();
m_msg_copy = new QPushButton();
m_msg_save = new QPushButton();
m_msg_menu = new QPushButton();
m_msg_fold = new QPushButton();
m_msg_display_combobox = new QComboBox();
m_msg_display_font_size_combobox = new QComboBox();
m_msg_display_font_combobox = new QComboBox();
m_msg_display_font_label = new QLabel("字体:");
m_msg_display_font_size_label = new QLabel("大小:");
m_msg_display_label = new QLabel("模式:");
m_msg_display_label->setObjectName("m_msg_menu_label");
m_msg_display_combobox->setObjectName("m_msg_display_combobox");
m_msg_display_font_size_label->setObjectName("m_msg_font_size_label");
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_combobox->setObjectName("m_msg_font_combobox");
m_msg_copy->setObjectName("m_msg_copy");
m_msg_save->setObjectName("m_msg_save");
m_msg_menu->setObjectName("m_msg_menu");
m_msg_fold->setObjectName("m_msg_fold");
m_msg_fold->setIcon(QIcon(":res/img/btn/btn_info_up.png"));
m_msg_fold->setIconSize(QSize(25, 25));
initDisplayMode();
header_opts_Layout->addItem(sparcer_item);
header_opts_Layout->addWidget(m_msg_display_font_label);
header_opts_Layout->addWidget(m_msg_display_font_combobox);
header_opts_Layout->addWidget(m_msg_display_font_size_label);
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_combobox);
header_opts_Layout->addWidget(m_msg_copy);
header_opts_Layout->addWidget(m_msg_save);
header_opts_Layout->addWidget(m_msg_menu);
header_opts_Layout->addWidget(m_msg_fold);
header_opts_Layout->addItem(sparcer_item);
header_opts_Layout->setContentsMargins(0, 0, 0, 0);
setLayout(header_opts_Layout);
}
void ctaiHistoryTools::initDisplayMode()
{
for(auto str:ds_mode_str)
{
m_msg_display_combobox->addItem(str);
}
for(auto str:ds_font_size_str)
{
m_msg_display_font_size_combobox->addItem(str);
}
for(auto str:sui_font_table){
m_msg_display_font_combobox->addItem(str);
}
}
void ctaiHistoryTools::initConnect()
{
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_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)));
}
void ctaiHistoryTools::setFoldIco(QIcon ico)
{
m_msg_fold->setIcon(ico);
}
// save按钮实现功能的槽函数
void ctaiHistoryTools::on_save_menu_slots()
{
if (!m_msg_save_menu)
{
m_msg_save_menu = new QMenu();
}
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_opts_menu_slots()
{
QMenu menu(this);
// 添加菜单项
QAction *actCopy = menu.addAction(tr("复制"));
QAction *actSave = menu.addAction(tr("保存"));
menu.addSeparator();
QAction *actDelete = menu.addAction(tr("删除"));
// 显示菜单
QPoint pos = m_msg_menu->mapToGlobal(m_msg_menu->rect().bottomRight());
QAction *act = menu.exec(pos);
}

62
src/ctaiHistoryTools.h Normal file
View File

@ -0,0 +1,62 @@
#ifndef CTAIHISTORYTOOLS_H
#define CTAIHISTORYTOOLS_H
#include <QWidget>
#include <QHBoxLayout>
#include <QPushButton>
#include <QComboBox>
#include <QLabel>
#include <QMenu>
#include <QAction>
#include "sui_base.h"
class ctaiHistoryTools : public QWidget
{
Q_OBJECT
public:
ctaiHistoryTools();
~ctaiHistoryTools();
void initLayout();
void initConnect();
void setFoldIco(QIcon ico);
private:
QHBoxLayout *header_opts_Layout = {};
QPushButton *m_msg_copy = {};
QPushButton *m_msg_save = {};
QPushButton *m_msg_menu = {};
QPushButton *m_msg_fold = {};
//显示模式
QLabel *m_msg_display_label = {};
QComboBox *m_msg_display_combobox = {};
//字体大小
QLabel *m_msg_display_font_size_label = {};
QComboBox *m_msg_display_font_size_combobox = {};
//字体
QLabel *m_msg_display_font_label = {};
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={"原始文本","LaTeX Markdown"};
QStringList ds_font_size_str={"4","6","8","10","12","14","16","18","20"};
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();
public slots:
void on_save_menu_slots();
void on_opts_menu_slots();
};
#endif

View File

@ -1,12 +1,12 @@
#include "ctai_history_widget.h"
#include "ctaiHistoryWidget.h"
ctai_history_widget::ctai_history_widget(QWidget *parent)
ctaiHistoryWidget::ctaiHistoryWidget(QWidget *parent)
: QTableWidget(parent)
{
setup_table();
}
void ctai_history_widget::setup_table()
void ctaiHistoryWidget::setup_table()
{
setColumnCount(1);
setShowGrid(false);
@ -20,7 +20,7 @@ void ctai_history_widget::setup_table()
verticalScrollBar()->setSingleStep(5);
}
ctai_history_widget::~ctai_history_widget()
ctaiHistoryWidget::~ctaiHistoryWidget()
{
for (auto &pair : message_map_)
{
@ -29,7 +29,7 @@ ctai_history_widget::~ctai_history_widget()
clear();
}
void ctai_history_widget::add_message(const model_data &message)
void ctaiHistoryWidget::add_message(const model_data &message)
{
QString send_id;
if (message.msg_type_mode == SYSTEM)
@ -56,7 +56,7 @@ void ctai_history_widget::add_message(const model_data &message)
{
// 更新传入信息
stored_data->postback_model_data += message.postback_model_data;
if (auto message_widget = qobject_cast<ctai_history_textedit *>(widget))
if (auto message_widget = qobject_cast<ctaiHistoryTextEdit *>(widget))
{
message_widget->add_system_message(message);
}
@ -65,7 +65,7 @@ void ctai_history_widget::add_message(const model_data &message)
{
// 更新tokens信息
update_stored_data(stored_data, message);
if (auto message_widget = qobject_cast<ctai_history_textedit *>(widget))
if (auto message_widget = qobject_cast<ctaiHistoryTextEdit *>(widget))
{
message_widget->update_tokens_message(message);
}
@ -75,7 +75,7 @@ void ctai_history_widget::add_message(const model_data &message)
{
// 添加新消息
model_data *new_data = new model_data(message);
ctai_history_textedit *message_widget = new ctai_history_textedit(this);
ctaiHistoryTextEdit *message_widget = new ctaiHistoryTextEdit(this);
message_widget->init_layout(new_data->msg_type_mode);
message_widget->show();
if (new_data->msg_type_mode == SYSTEM)
@ -107,7 +107,7 @@ void ctai_history_widget::add_message(const model_data &message)
scrollToBottom();
}
// 自适应信息高度
void ctai_history_widget::on_rows_height_changed(bool fold_state)
void ctaiHistoryWidget::on_rows_height_changed(bool fold_state)
{
if (fold_state)
{
@ -131,7 +131,7 @@ void ctai_history_widget::on_rows_height_changed(bool fold_state)
}
}
void ctai_history_widget::on_msg_remove(QString send_id)
void ctaiHistoryWidget::on_msg_remove(QString send_id)
{
qDebug()<<"send_id:"<<send_id;
auto it = message_map_.find(send_id);
@ -161,17 +161,17 @@ void ctai_history_widget::on_msg_remove(QString send_id)
}
}
ctai_history_textedit *ctai_history_widget::current_message() const
ctaiHistoryTextEdit *ctaiHistoryWidget::current_message() const
{
int current_row = currentRow();
if (current_row >= 0)
{
return qobject_cast<ctai_history_textedit *>(cellWidget(current_row, 0));
return qobject_cast<ctaiHistoryTextEdit *>(cellWidget(current_row, 0));
}
return nullptr;
}
void ctai_history_widget::update_stored_data(model_data *stored_data, const model_data &message)
void ctaiHistoryWidget::update_stored_data(model_data *stored_data, const model_data &message)
{
stored_data->api_key = message.api_key;
stored_data->api_url = message.api_url;

29
src/ctaiHistoryWidget.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef CTAIHISTORYWIDGET_H
#define CTAIHISTORYWIDGET_H
#include <QTableWidget>
#include <QScrollBar>
#include <QHeaderView>
#include <map>
#include "ctaiHistoryTextEdit.h"
class ctaiHistoryWidget : public QTableWidget
{
Q_OBJECT
public:
ctaiHistoryWidget(QWidget *parent = nullptr);
~ctaiHistoryWidget();
void add_message(const model_data &message);
ctaiHistoryTextEdit *current_message() const;
private:
std::map<QString, std::pair<model_data *, int>> message_map_; // int存储行号
void setup_table();
void update_stored_data(model_data *stored_data, const model_data &message);
private slots:
void on_msg_remove(QString send_id);
void on_rows_height_changed(bool); // 新增槽函数处理高度变化
};
#endif

View File

@ -1,23 +1,23 @@
#include "ctai_math_convert.h"
#include "ctaiMathConvert.h"
ctai_math_convert::ctai_math_convert()
ctaiMathConvert::ctaiMathConvert()
{
}
ctai_math_convert::~ctai_math_convert()
ctaiMathConvert::~ctaiMathConvert()
{
}
void ctai_math_convert::set_convert_opts()
void ctaiMathConvert::set_convert_opts()
{
}
void ctai_math_convert::save_svg(QPixmap &img)
void ctaiMathConvert::save_svg(QPixmap &img)
{
QString uid = QUuid::createUuid().toString(QUuid::WithoutBraces);
QString svgName = QDir::currentPath() + "/svg/" + uid + ".png";
bool ok = img.save(svgName);
}
QByteArray ctai_math_convert::svg_to_base64(QPixmap &pix)
QByteArray ctaiMathConvert::svg_to_base64(QPixmap &pix)
{
QByteArray data;
@ -28,21 +28,22 @@ QByteArray ctai_math_convert::svg_to_base64(QPixmap &pix)
data = data.toBase64();
return data;
}
QString ctai_math_convert::math_convert_svg(const QString &math)
QString ctaiMathConvert::math_convert_svg(const QString &math)
{
auto render = tex::LaTeX::parse(math.toStdWString(), m_width, m_text_size, m_lineSpace, m_color);
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(), render->getHeight());
QPixmap pix(render->getWidth()+m_padding*2, render->getHeight()+m_padding*2);
pix.fill(Qt::white);
QPainter painter(&pix);
painter.setRenderHint(QPainter::Antialiasing, true);
tex::Graphics2D_qt g2(&painter);
render->draw(g2, 0, 0);
painter.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing);
Graphics2D_qt g2(&painter);
render->draw(g2,m_padding,m_padding);
save_svg(pix);
return QString::fromUtf8(svg_to_base64(pix));
}
void ctai_math_convert::debug_latex_match(const QString &text, const QRegularExpressionMatch &match)
void ctaiMathConvert::debug_latex_match(const QString &text, const QRegularExpressionMatch &match)
{
qDebug() << "=== LaTeX匹配信息 ===";
qDebug() << "匹配位置:" << match.capturedStart() << "-" << match.capturedEnd();
@ -58,7 +59,7 @@ void ctai_math_convert::debug_latex_match(const QString &text, const QRegularExp
qDebug() << "==================";
}
QString ctai_math_convert::clean_latex_for_mula(const QString &formula)
QString ctaiMathConvert::clean_latex_for_mula(const QString &formula)
{
QString result = formula;
// 清理可能的多余空白字符
@ -68,7 +69,7 @@ QString ctai_math_convert::clean_latex_for_mula(const QString &formula)
return result;
}
QString ctai_math_convert::replace_tags_svg(const QString &text)
QString ctaiMathConvert::replace_tags_svg(const QString &text)
{
//QString result("4566545646\\[\n f'(a) = \\lim_{h \\to 0} \\frac{f(a + h) - f(a)}{h}\n \\]654564646");
QString result=text;
@ -100,7 +101,7 @@ QString ctai_math_convert::replace_tags_svg(const QString &text)
// 清理和转换公式
//QString cleanFormula = clean_latex_for_mula(matchedText);
QString svg_markdown = markdown_base + math_convert_svg(matchedText) + ")";
QString svg_html = html_base + math_convert_svg(matchedText) + "/>";
//QString svg_html = html_base + math_convert_svg(matchedText) + "/>";
// 保存替换信息
replacements.prepend({match.capturedStart(), match.capturedLength()});
svgResults.prepend(svg_markdown);

View File

@ -1,5 +1,5 @@
#ifndef CTAI_MATH_CONVERT_H
#define CTAI_MATH_CONVERT_H
#ifndef CTAIMATHCONVERT_H
#define CTAIMATHCONVERT_H
#include "latex.h"
#include "platform/qt/graphic_qt.h"
@ -14,6 +14,7 @@
#include "ctai_base.h"
#include <regex>
#include <string>
class TexGuard {
public:
TexGuard() {
@ -25,12 +26,13 @@ class TexGuard {
}
};
class ctai_math_convert :public QObject
using namespace tex;
class ctaiMathConvert :public QObject
{
Q_OBJECT
public:
explicit ctai_math_convert();
~ctai_math_convert();
explicit ctaiMathConvert();
~ctaiMathConvert();
QString replace_tags_svg(const QString &text);
void set_convert_opts();
void save_svg(QPixmap& img);
@ -42,13 +44,16 @@ private:
QByteArray svg_to_base64(QPixmap& pix);
TexGuard texGuard;
//宽度
int m_width=300;
int m_render_width=300;
int m_render_height=64;
//文本大小
int m_text_size=14;
int m_text_size=20;
//行距
float m_lineSpace=20 / 3.f;
//颜色
tex::color m_color=0xff424242;
//边距
int m_padding=3;
//处理后保存模式
bool save_mode=false;

View File

@ -1,17 +1,17 @@
#include "ctai_session_info.h"
#include "ctaiSessionInfo.h"
ctai_session_info::ctai_session_info()
ctaiSessionInfo::ctaiSessionInfo()
{
init_layout();
init_sub_layout();
init_curl();
}
ctai_session_info::~ctai_session_info()
ctaiSessionInfo::~ctaiSessionInfo()
{
}
void ctai_session_info::init_layout()
void ctaiSessionInfo::init_layout()
{
mainLayout = new QVBoxLayout();
splitter = new QSplitter(Qt::Vertical);
@ -24,7 +24,7 @@ void ctai_session_info::init_layout()
mainLayout->setContentsMargins(0, 0, 0, 0);
setLayout(mainLayout);
}
void ctai_session_info::init_sub_layout()
void ctaiSessionInfo::init_sub_layout()
{
m_list_widget = new QListWidget();
m_list_widget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
@ -40,7 +40,7 @@ void ctai_session_info::init_sub_layout()
height: 0px;
}
)");
m_session_systeam_info = new ctai_history_widget();
m_session_systeam_info = new ctaiHistoryWidget();
m_session_systeam_info->setObjectName(tr("m_session_systeam_info"));
m_session_systeam_info_layout = new QVBoxLayout();
m_session_systeam_info_layout->addWidget(m_session_systeam_info);
@ -54,7 +54,7 @@ void ctai_session_info::init_sub_layout()
m_session_user_edit_layout->addWidget(m_session_user_edit_info);
m_session_user_btn_layout = new QHBoxLayout();
m_stream_switch = new ctai_switch_button();
m_stream_switch = new ctaiSwitchButton();
m_stream_switch->setMinimumSize(QSize(75, 25));
m_stream_mode_tips = new QLabel(tr("流式模式:"));
m_info_error_tips = new QLabel();
@ -66,7 +66,7 @@ void ctai_session_info::init_sub_layout()
m_session_user_group_layout->setContentsMargins(0, 0, 0, 0);
m_sub_user_widget->setLayout(m_session_user_group_layout);
}
void ctai_session_info::init_user_btn_layout()
void ctaiSessionInfo::init_user_btn_layout()
{
for (int i = 0; i <= m_user_btn_list.size() - 1; i++)
{
@ -108,24 +108,24 @@ void ctai_session_info::init_user_btn_layout()
}
}
}
void ctai_session_info::init_user_btn_size_tips(QPushButton &btn, QSize size, QString tip_str)
void ctaiSessionInfo::init_user_btn_size_tips(QPushButton &btn, QSize size, QString tip_str)
{
btn.setIconSize(size);
btn.setToolTip(tip_str);
}
void ctai_session_info::init_curl()
void ctaiSessionInfo::init_curl()
{
m_curl = new ctai_curl();
m_curl = new ctaiCurl();
m_curl->curl_init();
connect(m_curl, SIGNAL(send_post_out_data(model_data)), this, SLOT(ctai_session_postback_info(model_data)));
connect(m_curl, SIGNAL(send_post_out_error(std::string)), this, SLOT(ctai_session_curl_state_tips(std::string)));
}
void ctai_session_info::btn_disable_enable(bool state)
void ctaiSessionInfo::btn_disable_enable(bool state)
{
m_btns[5]->setEnabled(state);
}
void ctai_session_info::ctai_session_postback_info(model_data resp_data)
void ctaiSessionInfo::ctai_session_postback_info(model_data resp_data)
{
if (resp_data.postback_send_id != current_info_id)
{
@ -143,16 +143,16 @@ void ctai_session_info::ctai_session_postback_info(model_data resp_data)
btn_disable_enable(true);
ctai_session_curl_state_tips("");
}
void ctai_session_info::ctai_session_curl_state_tips(std::string state_str)
void ctaiSessionInfo::ctai_session_curl_state_tips(std::string state_str)
{
m_info_error_tips->setText(QString::fromStdString(state_str));
}
void ctai_session_info::ctai_session_set_steam_mode(bool state)
void ctaiSessionInfo::ctai_session_set_steam_mode(bool state)
{
m_stream_mode = state; // 直接将switch的状态赋值给m_stream_mode
qDebug() << "steam mode:" << m_stream_mode;
}
void ctai_session_info::ctai_session_user_sending()
void ctaiSessionInfo::ctai_session_user_sending()
{
if (m_session_user_edit_info->toPlainText().isEmpty())
{

View File

@ -1,5 +1,5 @@
#ifndef CTAI_SESSION_INFO_H
#define CTAI_SESSION_INFO_H
#ifndef CTAISESSIONINFO_H
#define CTAISESSIONINFO_H
#include <QHBoxLayout>
#include <QTextEdit>
@ -10,15 +10,15 @@
#include <QListWidget>
#include <QDir>
#include <QFile>
#include "ctai_switch_button.h"
#include "ctai_curl.h"
#include "ctai_history_widget.h"
class ctai_session_info : public QWidget
#include "ctaiSwitchButton.h"
#include "ctaiCurl.h"
#include "ctaiHistoryWidget.h"
class ctaiSessionInfo : public QWidget
{
Q_OBJECT
public:
ctai_session_info();
~ctai_session_info();
ctaiSessionInfo();
~ctaiSessionInfo();
private:
void init_curl();
void init_layout();
@ -34,7 +34,7 @@ private:
//信息输出窗口布局
QListWidget *m_list_widget;
ctai_history_widget *m_session_systeam_info;
ctaiHistoryWidget *m_session_systeam_info;
QVBoxLayout *m_session_systeam_info_layout;
//用户询问信息布局
QTextEdit *m_session_user_edit_info;
@ -43,7 +43,7 @@ private:
std::vector<QPushButton *> m_btns;
QLabel *m_stream_mode_tips;
QLabel *m_info_error_tips;
ctai_switch_button *m_stream_switch;
ctaiSwitchButton *m_stream_switch;
QHBoxLayout *m_session_user_btn_layout;
QVBoxLayout *m_session_user_group_layout;
@ -68,7 +68,7 @@ private:
":/res/img/btn/btn_clear_context.png",
":/res/img/btn/btn_sending_info.png"};
QSpacerItem *sparcer_item = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed);
ctai_curl *m_curl;
ctaiCurl *m_curl;
model_data user_model_data;
curl_opts curl_opt;
std::string current_info_id;

View File

@ -1,17 +1,17 @@
#include "ctai_session_setting.h"
#include "ctaiSessionSetting.h"
ctai_session_setting::ctai_session_setting(QWidget *parent)
ctaiSessionSetting::ctaiSessionSetting(QWidget *parent)
: QWidget(parent)
{
initUI();
setupConnections();
}
ctai_session_setting::~ctai_session_setting()
ctaiSessionSetting::~ctaiSessionSetting()
{
}
void ctai_session_setting::initUI()
void ctaiSessionSetting::initUI()
{
mainLayout = new QVBoxLayout(this);
mainLayout->setSpacing(10);
@ -57,7 +57,7 @@ void ctai_session_setting::initUI()
}
}
void ctai_session_setting::setupConnections()
void ctaiSessionSetting::setupConnections()
{
// 在这里添加信号和槽的连接
}

View File

@ -1,5 +1,5 @@
#ifndef CTAI_SESSION_SETTING_H
#define CTAI_SESSION_SETTING_H
#ifndef CTAISESSIONSETTING_H
#define CTAISESSIONSETTING_H
#include <QWidget>
#include <QLabel>
@ -7,12 +7,12 @@
#include <QVBoxLayout>
#include <QHBoxLayout>
class ctai_session_setting : public QWidget
class ctaiSessionSetting : public QWidget
{
Q_OBJECT
public:
explicit ctai_session_setting(QWidget *parent = nullptr);
~ctai_session_setting();
explicit ctaiSessionSetting(QWidget *parent = nullptr);
~ctaiSessionSetting();
private:
// 布局

View File

@ -1,11 +1,11 @@
#include "ctai_session_widget.h"
#include "ctaiSessionWidget.h"
ctai_session_widget::ctai_session_widget()
ctaiSessionWidget::ctaiSessionWidget()
{
init_layout();
connect_signals();
}
ctai_session_widget::~ctai_session_widget()
ctaiSessionWidget::~ctaiSessionWidget()
{
for (auto* s : m_session_map) {
if (s) {
@ -15,7 +15,7 @@ ctai_session_widget::~ctai_session_widget()
}
m_session_map.clear();
}
void ctai_session_widget::init_layout()
void ctaiSessionWidget::init_layout()
{
m_session_layout = new QHBoxLayout();
m_session_table_btn_layout = new QVBoxLayout();
@ -44,7 +44,7 @@ void ctai_session_widget::init_layout()
m_session_table_layout = new QHBoxLayout();
m_session_table = new QTableWidget();
// 初始化设置界面
m_session_setting = new ctai_session_setting();
m_session_setting = new ctaiSessionSetting();
m_session_setting->hide(); // 初始时隐藏设置界面
is_setting_visible = false;
m_session_table->setColumnCount(1); // 设置列数为1
@ -79,7 +79,7 @@ void ctai_session_widget::init_layout()
m_session_layout->setContentsMargins(0, 0, 0, 0);
setLayout(m_session_layout);
}
void ctai_session_widget::connect_signals()
void ctaiSessionWidget::connect_signals()
{
// 连接信号槽
connect(m_btn_new_chat, SIGNAL(clicked()), this, SLOT(on_new_chat_clicked()));
@ -91,9 +91,9 @@ void ctai_session_widget::connect_signals()
});
// 连接表格项目编辑完成信号
connect(m_session_table, &QTableWidget::itemChanged,
this, &ctai_session_widget::on_session_name_changed);
this, &ctaiSessionWidget::on_session_name_changed);
}
void ctai_session_widget::on_new_chat_clicked()
void ctaiSessionWidget::on_new_chat_clicked()
{
// 生成唯一会话ID
QString session_id = QUuid::createUuid().toString(QUuid::WithoutBraces);
@ -103,7 +103,7 @@ void ctai_session_widget::on_new_chat_clicked()
new_session->session_id = session_id;
new_session->session_name = tr("新会话");
new_session->session_type = "chat";
new_session->session_info = new ctai_session_info();
new_session->session_info = new ctaiSessionInfo();
// 添加到vector中
m_session_map.push_back(new_session);
@ -125,7 +125,7 @@ void ctai_session_widget::on_new_chat_clicked()
}
}
void ctai_session_widget::on_del_chat_clicked()
void ctaiSessionWidget::on_del_chat_clicked()
{
int currentRow = m_session_table->currentRow();
if (currentRow < 0 || currentRow >= m_session_map.size()) {
@ -143,7 +143,7 @@ void ctai_session_widget::on_del_chat_clicked()
m_session_table->removeRow(currentRow);
}
void ctai_session_widget::on_session_selected(int currentRow, int currentColumn)
void ctaiSessionWidget::on_session_selected(int currentRow, int currentColumn)
{
if (currentRow < 0 || currentRow >= m_session_map.size()) return;
@ -165,7 +165,7 @@ void ctai_session_widget::on_session_selected(int currentRow, int currentColumn)
}
}
void ctai_session_widget::on_session_name_changed(QTableWidgetItem* item)
void ctaiSessionWidget::on_session_name_changed(QTableWidgetItem* item)
{
if (!item) return;
@ -179,7 +179,7 @@ void ctai_session_widget::on_session_name_changed(QTableWidgetItem* item)
}
}
void ctai_session_widget::on_set_chat_clicked()
void ctaiSessionWidget::on_set_chat_clicked()
{
is_setting_visible = !is_setting_visible;

View File

@ -1,5 +1,5 @@
#ifndef CTAI_SESSION_WIDGET_H
#define CTAI_SESSION_WIDGET_H
#ifndef CTAISESSIONWIDGET_H
#define CTAISESSIONWIDGET_H
#include <QWidget>
#include <QTextEdit>
@ -15,22 +15,22 @@
#include <QString>
#include <QUuid>
#include "ctai_session_info.h"
#include "ctai_session_setting.h"
#include "ctaiSessionInfo.h"
#include "ctaiSessionSetting.h"
typedef struct c_session
{
QString session_id;
QString session_name;
QString session_type;
ctai_session_info* session_info;
ctaiSessionInfo* session_info;
}session;
class ctai_session_widget : public QWidget
class ctaiSessionWidget : public QWidget
{
Q_OBJECT
public:
ctai_session_widget();
~ctai_session_widget();
ctaiSessionWidget();
~ctaiSessionWidget();
void init_layout();
private:
void on_session_selected(int currentRow, int currentColumn);
@ -53,7 +53,7 @@ private:
//会话信息布局
QHBoxLayout *m_session_info_layout;
//会话设置
ctai_session_setting *m_session_setting;
ctaiSessionSetting *m_session_setting;
bool is_setting_visible;
// 会话管理mapkey为会话IDvalue为对应的会话信息对象
std::vector<session*> m_session_map;

View File

@ -1,6 +1,6 @@
#include "ctai_switch_button.h"
#include "ctaiSwitchButton.h"
ctai_switch_button::ctai_switch_button(QWidget *parent)
ctaiSwitchButton::ctaiSwitchButton(QWidget *parent)
: QWidget(parent),
m_SwBtn_Status(false),
m_SwBtn_background(Qt::black),
@ -15,33 +15,33 @@ ctai_switch_button::ctai_switch_button(QWidget *parent)
setCursor(Qt::PointingHandCursor);
connect(&m_SwBtn_timer,SIGNAL(timeout()),this,SLOT(SwBtn_Slide()));
}
bool ctai_switch_button::SwBtn_isChecked() const
bool ctaiSwitchButton::SwBtn_isChecked() const
{
return m_SwBtn_Status;
}
void ctai_switch_button::setSwBtn_Status(bool check)
void ctaiSwitchButton::setSwBtn_Status(bool check)
{
m_SwBtn_Status=check;
m_SwBtn_timer.start(1);
}
void ctai_switch_button::setSwBtn_BackgroundColor(QColor color)
void ctaiSwitchButton::setSwBtn_BackgroundColor(QColor color)
{
m_SwBtn_background=color;
}
void ctai_switch_button::setSwBtn_CheckedColor(QColor color)
void ctaiSwitchButton::setSwBtn_CheckedColor(QColor color)
{
m_SwBtn_checkedColor=color;
}
void ctai_switch_button::setSwBtn_DisabilityColor(QColor color)
void ctaiSwitchButton::setSwBtn_DisabilityColor(QColor color)
{
m_SwBtn_disabilityColor=color;
}
void ctai_switch_button::setSwBtn_WidgetSize(int m_width, int m_height)
void ctaiSwitchButton::setSwBtn_WidgetSize(int m_width, int m_height)
{
this->m_SwBtn_Height=m_width-m_height;
this->m_SwBtn_Margin=m_height-(m_width/2);
@ -49,7 +49,7 @@ void ctai_switch_button::setSwBtn_WidgetSize(int m_width, int m_height)
update();
}
void ctai_switch_button::paintEvent(QPaintEvent *event)
void ctaiSwitchButton::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
@ -99,7 +99,7 @@ void ctai_switch_button::paintEvent(QPaintEvent *event)
height()-10,
height()-10));
}
void ctai_switch_button::mousePressEvent(QMouseEvent *event)
void ctaiSwitchButton::mousePressEvent(QMouseEvent *event)
{
if(isEnabled()){
if(event->button()==Qt::LeftButton){ //**
@ -109,7 +109,7 @@ void ctai_switch_button::mousePressEvent(QMouseEvent *event)
event->ignore();
}
}
void ctai_switch_button::mouseReleaseEvent(QMouseEvent *event)
void ctaiSwitchButton::mouseReleaseEvent(QMouseEvent *event)
{
if(isEnabled()){
if((event->type()==QMouseEvent::MouseButtonRelease)&&(event->button()==Qt::LeftButton)){
@ -125,21 +125,21 @@ void ctai_switch_button::mouseReleaseEvent(QMouseEvent *event)
}
//重现大小改变事件
void ctai_switch_button::resizeEvent(QResizeEvent *event)
void ctaiSwitchButton::resizeEvent(QResizeEvent *event)
{
m_SwBtn_X=0;
m_SwBtn_Y=0;
QWidget::resizeEvent(event);
}
QSize ctai_switch_button::sizeHint() const
QSize ctaiSwitchButton::sizeHint() const
{
return minimumSizeHint();
}
QSize ctai_switch_button::minimumSizeHint() const
QSize ctaiSwitchButton::minimumSizeHint() const
{
return QSize(2*(m_SwBtn_Height+m_SwBtn_Margin),m_SwBtn_Height+2*m_SwBtn_Margin);
}
void ctai_switch_button::SwBtn_Slide()
void ctaiSwitchButton::SwBtn_Slide()
{
if(m_SwBtn_Status){
m_SwBtn_X+=1;

View File

@ -1,5 +1,5 @@
#ifndef CTAI_SWITCH_BUTTON_H
#define CTAI_SWITCH_BUTTON_H
#ifndef CTAISWITCHBUTTON_H
#define CTAISWITCHBUTTON_H
#include <QWidget>
#include <QTimer>
@ -7,11 +7,11 @@
#include <QMouseEvent>
#include <QPainterPath>
class ctai_switch_button : public QWidget
class ctaiSwitchButton : public QWidget
{
Q_OBJECT
public:
explicit ctai_switch_button(QWidget *parent = nullptr);
explicit ctaiSwitchButton(QWidget *parent = nullptr);
bool SwBtn_isChecked() const;
void setSwBtn_Status(bool check);
void setSwBtn_BackgroundColor(QColor color);

View File

@ -1,19 +1,19 @@
#include "ctai_tabbar.h"
#include "ctaiTabBar.h"
ctai_tabbar::ctai_tabbar()
ctaiTabBar::ctaiTabBar()
{
// 设置图标与文字间距
setIconSize(QSize(20, 20));
}
ctai_tabbar::~ctai_tabbar()
ctaiTabBar::~ctaiTabBar()
{
}
QSize ctai_tabbar::tabSizeHint(int index) const
QSize ctaiTabBar::tabSizeHint(int index) const
{
QSize size = QTabBar::tabSizeHint(index);
return QSize(size.width() + 60, size.height()-30); // 扩大标签尺寸
}
void ctai_tabbar::paintEvent(QPaintEvent *event)
void ctaiTabBar::paintEvent(QPaintEvent *event)
{
//创建一个QStylePainter对象painter用于绘制此小部件的样式元素
QStylePainter painter(this);

View File

@ -1,16 +1,16 @@
#ifndef CTAI_TABBAR_H
#define CTAI_TABBAR_H
#ifndef CTAITABBAR_H
#define CTAITABBAR_H
#include <QTabBar>
#include <QStylePainter>
#include <QStyle>
#include <QStyleOptionTab>
class ctai_tabbar : public QTabBar
class ctaiTabBar : public QTabBar
{
Q_OBJECT
public:
ctai_tabbar();
~ctai_tabbar();
ctaiTabBar();
~ctaiTabBar();
protected:
QSize tabSizeHint(int index) const override;
void paintEvent(QPaintEvent *event) override;

View File

@ -1,17 +1,17 @@
#include "ctai_tabwidget.h"
#include "ctaiTabWidget.h"
ctai_tabwidget::ctai_tabwidget(){
ctaiTabWidget::ctaiTabWidget(){
}
ctai_tabwidget::~ctai_tabwidget(){
ctaiTabWidget::~ctaiTabWidget(){
}
void ctai_tabwidget::init_layout(){
setTabBar(new ctai_tabbar);
void ctaiTabWidget::init_layout(){
setTabBar(new ctaiTabBar);
setTabPosition(QTabWidget::West);
m_session_widget=new ctai_session_widget();
m_session_widget=new ctaiSessionWidget();
addTab(m_session_widget,QIcon(":/res/img/btn/btn_chat.png"),tr("会话"));
addTab(new ctai_cmd(),QIcon(":/res/img/btn/btn_cmd.png"),tr("命令行"));
addTab(new ctaiCmd(),QIcon(":/res/img/btn/btn_cmd.png"),tr("命令行"));
addTab(new QWidget(),QIcon(":/res/img/btn/btn_knowledge.png"),tr("知识库"));
addTab(new QWidget(),QIcon(":/res/img/btn/btn_tips.png"),tr("提示词"));
addTab(new QWidget(),QIcon(":/res/img/btn/btn_setting.png"),tr("设置"));

21
src/ctaiTabWidget.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef CTAITABWIDGET_H
#define CTAITABWIDGET_H
#include <QTabWidget>
#include <QPaintEvent>
#include <QStyle>
#include "ctaiTabBar.h"
#include "ctaiSessionWidget.h"
#include "ctaiCmd.h"
class ctaiTabWidget : public QTabWidget
{
Q_OBJECT
public:
ctaiTabWidget();
~ctaiTabWidget();
void init_layout();
private:
ctaiSessionWidget* m_session_widget;
};
#endif // CTAI_TABWIDGET_H

View File

@ -1,127 +0,0 @@
// ctaitextedit.h
#ifndef CTAI_HISTORY_TEXTEDIT_H
#define CTAI_HISTORY_TEXTEDIT_H
// Qt核心组件
#include <QWidget>
#include <QString>
#include <QApplication>
#include <QClipboard>
// Qt布局相关
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QSpacerItem>
// Qt控件相关
#include <QPushButton>
#include <QTextEdit>
#include <QLineEdit>
#include <QFrame>
#include <QMenu>
#include <QAction>
#include <QAbstractTextDocumentLayout>
#include <QAbstractScrollArea>
#include <QTimer>
#include <QLabel>
#include <QComboBox>
// Qt对话框
#include <QFileDialog>
#include <QMessageBox>
// 系统相关
#include <mutex>
// 项目相关头文件
#include "ctai_base.h"
#include "ctai_math_convert.h"
typedef struct tokens_args{
QString prompt_tokens={};
QString completion_tokens={};
QString total_tokens={};
QString cache_hit_tokens={};
QString cache_miss_tokens={};
}tokens_data;
std::mutex m_mutex;
class ctai_history_textedit : public QWidget
{
Q_OBJECT
public:
ctai_history_textedit(QWidget *parent = nullptr);
~ctai_history_textedit();
void init_layout(msg_type msg_type_mode);
void add_user_message(const model_data &message);
void add_system_message(const model_data &message);
void update_tokens_message(const model_data &message);
void add_header_message(const model_data &message);
private slots:
void on_delete_clicked(); // 删除按钮
void on_copy_clicked(); // 复制按钮
void on_save_clicked(); // 保存按钮
void on_menu_clicked(); // 菜单按钮
void on_fold_clicked(); // 折叠按钮
void on_tokens_clicked(); // tokens按钮
void on_display_changed(QString); // 显示模式改变
void on_save_text(); // 保存文本
void on_save_html(); // 保存html
void on_save_markdown(); // 保存markdown
void on_save_pdf(); // 保存pdf
void on_sync_text_height();
signals:
void delete_requested(QString); // 请求删除此消息
void row_height_changed(bool);
private:
void connect_signals(msg_type msg_type_mode);// 连接信号和槽
private:
ctai_math_convert* m_math_convert;
QFrame *hLine;
QSpacerItem *sparcer_item = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed);
QVBoxLayout *mainLayout={};
QVBoxLayout *headerLayout={};
QHBoxLayout *header_info_Layout={};
QVBoxLayout *historyLayout={};
QHBoxLayout *header_opts_Layout={};
QPushButton *m_msg_system_header_ico={};
QPushButton *m_msg_user_header_ico={};
QLineEdit *m_msg_header={};
QTextEdit *m_msg_history={};
QPushButton *m_msg_user_del={};
QPushButton *m_msg_system_del={};
QPushButton *m_msg_copy={};
QPushButton *m_msg_save={};
QPushButton *m_msg_menu={};
QPushButton *m_msg_fold={}; // 折叠按钮
QPushButton *m_msg_tokens={};
QPushButton *m_history_to_send={};
QPushButton *m_restart_to_send={};
QLabel *m_msg_display_label={};
QComboBox *m_msg_display_combobox={};
//tokens消耗显示
QMenu *m_msg_tokens_menu={};
QAction *m_menu_prompt_tokens={};
QAction *m_menu_completion_tokens={};
QAction *m_menu_total_tokens={};
QAction *m_menu_cache_hit_tokens={};
QAction *m_menu_cache_miss_tokens={};
//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={};
// 保存展开时的原始高度
int m_original_height = 0;
//折叠状态
bool m_is_folded = false;
//本次会话的tokens消耗信息
tokens_data m_tokens_data;
//本次信息ID
QString m_msg_sned_id={};
//本次信息
QString m_current_content;
QSpacerItem *bottom_spacer = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding);
};
#endif // ctai_history_textedit_H

View File

@ -1,28 +0,0 @@
#ifndef CTAI_HISTORY_WIDGET_H
#define CTAI_HISTORY_WIDGET_H
#include <QTableWidget>
#include <QScrollBar>
#include <QHeaderView>
#include <map>
#include "ctai_history_textedit.h"
class ctai_history_widget : public QTableWidget
{
Q_OBJECT
public:
ctai_history_widget(QWidget *parent = nullptr);
~ctai_history_widget();
void add_message(const model_data &message);
ctai_history_textedit *current_message() const;
private:
std::map<QString, std::pair<model_data*, int>> message_map_; // int存储行号
void setup_table();
void update_stored_data(model_data* stored_data, const model_data& message);
private slots:
void on_msg_remove(QString send_id);
void on_rows_height_changed(bool); // 新增槽函数处理高度变化
};
#endif

View File

@ -1,21 +0,0 @@
#ifndef CTAI_TABWIDGET_H
#define CTAI_TABWIDGET_H
#include <QTabWidget>
#include <QPaintEvent>
#include <QStyle>
#include "ctai_tabbar.h"
#include "ctai_session_widget.h"
#include "ctai_cmd.h"
class ctai_tabwidget : public QTabWidget
{
Q_OBJECT
public:
ctai_tabwidget();
~ctai_tabwidget();
void init_layout();
private:
ctai_session_widget* m_session_widget;
};
#endif // CTAI_TABWIDGET_H