新增: 添加不同平台的通知显示函数

 新增: 实现 Windows、macOS 和 Linux 的通知显示
📝 修改: 调整命令历史记录相关注释
📝 修改: 增加工作目录管理逻辑
main
机械师 2025-09-12 17:50:53 +08:00
parent b8227c46d3
commit eb3a5aa939
4 changed files with 88 additions and 28 deletions

View File

@ -16,7 +16,7 @@ public:
void SaveSettings();
void ApplySettings();
// 新增:启动命令历史记录管理
// 启动命令历史记录管理
void AddCommandToHistory(const std::string& command);
void RemoveCommandFromHistory(int index);
void ClearCommandHistory();
@ -27,6 +27,8 @@ public:
CLIProcess cli_process;
char command_input[256]{};
char send_command[256]{};
char working_directory[256]{};
bool auto_working_dir;
bool auto_scroll_logs;
bool enable_colored_logs;
int max_log_lines;

View File

@ -35,7 +35,13 @@ public:
// 设置回调函数
void SetShowWindowCallback(const ShowWindowCallback &callback);
void SetExitCallback(const ExitCallback &callback);
#ifdef _WIN32
void ShowWindowsNotification(const std::wstring& title, const std::wstring& message);
#elif __APPLE__
void ShowMacNotification(const std::string& title, const std::string& message);
#else
void ShowLinuxNotification(const std::string& title, const std::string& message);
#endif
private:
void CreateMenu();
void DestroyMenu();

View File

@ -7,6 +7,7 @@ AppState::AppState() :
show_main_window(true),
auto_start(false),
auto_scroll_logs(true),
auto_working_dir(true),
enable_colored_logs(true),
max_log_lines(1000),
stop_timeout_ms(5000),
@ -77,7 +78,7 @@ std::string AppState::SerializeCommandHistory() const {
return oss.str();
}
// 新增:反序列化命令历史记录
// 反序列化命令历史记录
void AppState::DeserializeCommandHistory(const std::string& serialized) {
command_history.clear();
if (serialized.empty()) return;
@ -185,6 +186,9 @@ void AppState::LoadSettings() {
if (key == "CommandInput") {
strncpy_s(command_input, value.c_str(), sizeof(command_input) - 1);
}
else if (key == "WorkingDirectory") {
strncpy_s(working_directory, value.c_str(), sizeof(working_directory) - 1);
}
else if (key == "MaxLogLines") {
max_log_lines = std::stoi(value);
max_log_lines = std::max(100, std::min(max_log_lines, 10000));
@ -198,6 +202,9 @@ void AppState::LoadSettings() {
else if (key == "AutoStart") {
auto_start = (value == "1");
}
else if (key == "AutoWorkDirectory") {
auto_working_dir = (value == "1");
}
else if (key == "WebUrl") {
strncpy_s(web_url, value.c_str(), sizeof(web_url) - 1);
}
@ -240,10 +247,12 @@ void AppState::SaveSettings() {
file << "[Settings]\n";
file << "CommandInput=" << command_input << "\n";
file << "WorkingDirectory=" << working_directory << "\n";
file << "MaxLogLines=" << max_log_lines << "\n";
file << "AutoScrollLogs=" << (auto_scroll_logs ? "1" : "0") << "\n";
file << "EnableColoredLogs=" << (enable_colored_logs ? "1" : "0") << "\n";
file << "AutoStart=" << (auto_start ? "1" : "0") << "\n";
file << "AutoWorkDirectory=" << (auto_working_dir ? "1" : "0") << "\n";
file << "WebUrl=" << web_url << "\n";
// 停止命令相关配置的保存
@ -284,6 +293,11 @@ void AppState::ApplySettings() {
cli_process.SetEnvironmentVariables({});
}
// 新增:应用输出编码设置
if (strlen(working_directory)>0) {
cli_process.SetWorkingDirectory(working_directory);
}
cli_process.SetAutoWorkingDir(auto_working_dir);
// 应用输出编码设置
cli_process.SetOutputEncoding(output_encoding);
}

View File

@ -4,7 +4,6 @@
#ifdef _WIN32
TrayIcon::TrayIcon(HWND hwnd, HICON icon)
: m_hwnd(hwnd), m_icon(icon), m_visible(false), m_menu(nullptr) {
ZeroMemory(&m_nid, sizeof(m_nid));
m_nid.cbSize = sizeof(m_nid);
m_nid.hWnd = m_hwnd;
@ -53,14 +52,15 @@ void TrayIcon::Hide() {
}
#ifdef _WIN32
void TrayIcon::UpdateWebUrl(const std::wstring& url) {
void TrayIcon::UpdateWebUrl(const std::wstring &url) {
m_web_url = url;
// 重新创建菜单以更新Web URL显示
DestroyMenu();
CreateMenu();
}
#else
void TrayIcon::UpdateWebUrl(const std::string& url) {
void TrayIcon::UpdateWebUrl(const std::string &url)
{
m_web_url = url;
// 重新创建菜单以更新Web URL显示
DestroyMenu();
@ -76,6 +76,32 @@ void TrayIcon::SetExitCallback(const ExitCallback &callback) {
m_exit_callback = callback;
}
#ifdef _WIN32
void TrayIcon::ShowWindowsNotification(const std::wstring &title, const std::wstring &message) {
NOTIFYICONDATA nid = m_nid;
nid.uFlags |= NIF_INFO;
wcsncpy_s(nid.szInfoTitle, title.c_str(), _TRUNCATE);
wcsncpy_s(nid.szInfo, message.c_str(), _TRUNCATE);
nid.dwInfoFlags = NIIF_INFO; // 信息图标,可选 NIIF_WARNING, NIIF_ERROR
Shell_NotifyIcon(NIM_MODIFY, &nid);
}
#elif __APPLE__
void TrayIcon::ShowMacNotification(const std::string &title, const std::string &message)
{
// 通过 AppleScript 或 Objective-C 桥接
std::string script = "display notification \"" + message + "\" with title \"" + title + "\"";
std::string cmd = "osascript -e '" + script + "'";
system(cmd.c_str());
}
#else
void TrayIcon::ShowLinuxNotification(const std::string &title, const std::string &message)
{
// 使用 notify-send 命令
std::string cmd = "notify-send \"" + title + "\" \"" + message + "\"";
system(cmd.c_str());
}
#endif
void TrayIcon::CreateMenu() {
#ifdef _WIN32
if (m_menu) {
@ -174,47 +200,56 @@ LRESULT CALLBACK TrayIcon::WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
void TrayIcon::UpdateStatus(const std::wstring &status, const std::wstring &pid) {
m_status = status;
m_pid = pid;
// 重新创建菜单以更新Status显示
// 重新创建菜单以更新Status显示
DestroyMenu();
CreateMenu();
}
#else
// macOS 特定实现
void TrayIcon::ShowMacTrayIcon() {
void TrayIcon::ShowMacTrayIcon()
{
// 通过 Objective-C 接口显示托盘图标
ShowMacTrayIconImpl(m_app_delegate, m_icon);
}
void TrayIcon::HideMacTrayIcon() {
void TrayIcon::HideMacTrayIcon()
{
// 通过 Objective-C 接口隐藏托盘图标
HideMacTrayIconImpl(m_app_delegate);
}
void TrayIcon::CreateMacMenu() {
void TrayIcon::CreateMacMenu()
{
// 通过 Objective-C 接口创建菜单
CreateMacMenuImpl(m_app_delegate, m_web_url.c_str());
}
void TrayIcon::DestroyMacMenu() {
void TrayIcon::DestroyMacMenu()
{
// 通过 Objective-C 接口销毁菜单
DestroyMacMenuImpl(m_app_delegate);
}
void TrayIcon::OnMacMenuAction(int action) {
switch (action) {
void TrayIcon::OnMacMenuAction(int action)
{
switch (action)
{
case 1001: // 显示主窗口
if (m_show_window_callback) {
if (m_show_window_callback)
{
m_show_window_callback();
}
break;
case 1002: // 打开Web页面
if (!m_web_url.empty()) {
if (!m_web_url.empty())
{
OpenWebPageMac(m_web_url.c_str());
}
break;
case 1003: // 退出
if (m_exit_callback) {
if (m_exit_callback)
{
m_exit_callback();
}
break;
@ -222,18 +257,21 @@ void TrayIcon::OnMacMenuAction(int action) {
}
// C 接口函数,供 Objective-C 调用
extern "C" void TrayIconMenuCallback(void* tray_instance, int action) {
if (tray_instance) {
static_cast<TrayIcon*>(tray_instance)->OnMacMenuAction(action);
extern "C" void TrayIconMenuCallback(void *tray_instance, int action)
{
if (tray_instance)
{
static_cast<TrayIcon *>(tray_instance)->OnMacMenuAction(action);
}
}
// 外部声明的 Objective-C 接口函数
extern "C" {
void ShowMacTrayIconImpl(void* app_delegate, void* icon);
void HideMacTrayIconImpl(void* app_delegate);
void CreateMacMenuImpl(void* app_delegate, const char* web_url);
void DestroyMacMenuImpl(void* app_delegate);
void OpenWebPageMac(const char* url);
extern "C"
{
void ShowMacTrayIconImpl(void *app_delegate, void *icon);
void HideMacTrayIconImpl(void *app_delegate);
void CreateMacMenuImpl(void *app_delegate, const char *web_url);
void DestroyMacMenuImpl(void *app_delegate);
void OpenWebPageMac(const char *url);
}
#endif