diff --git a/share/icons/hicolor/16x16/apps/iptux-icon-reverse.png b/share/icons/hicolor/16x16/apps/iptux-icon-reverse.png new file mode 100644 index 000000000..00d1ea7d0 Binary files /dev/null and b/share/icons/hicolor/16x16/apps/iptux-icon-reverse.png differ diff --git a/share/icons/hicolor/22x22/apps/iptux-icon-reverse.png b/share/icons/hicolor/22x22/apps/iptux-icon-reverse.png new file mode 100644 index 000000000..0a0d7ac64 Binary files /dev/null and b/share/icons/hicolor/22x22/apps/iptux-icon-reverse.png differ diff --git a/share/icons/hicolor/24x24/apps/iptux-icon-reverse.png b/share/icons/hicolor/24x24/apps/iptux-icon-reverse.png new file mode 100644 index 000000000..0bc11b957 Binary files /dev/null and b/share/icons/hicolor/24x24/apps/iptux-icon-reverse.png differ diff --git a/share/icons/hicolor/32x32/apps/iptux-icon-reverse.png b/share/icons/hicolor/32x32/apps/iptux-icon-reverse.png new file mode 100644 index 000000000..ac52f41ce Binary files /dev/null and b/share/icons/hicolor/32x32/apps/iptux-icon-reverse.png differ diff --git a/share/icons/hicolor/48x48/apps/iptux-icon-reverse.png b/share/icons/hicolor/48x48/apps/iptux-icon-reverse.png new file mode 100644 index 000000000..10966a105 Binary files /dev/null and b/share/icons/hicolor/48x48/apps/iptux-icon-reverse.png differ diff --git a/share/icons/hicolor/64x64/apps/iptux-icon-reverse.png b/share/icons/hicolor/64x64/apps/iptux-icon-reverse.png new file mode 100644 index 000000000..985df507c Binary files /dev/null and b/share/icons/hicolor/64x64/apps/iptux-icon-reverse.png differ diff --git a/share/iptux/pixmaps/icon/iptux-icon-reverse.png b/share/iptux/pixmaps/icon/iptux-icon-reverse.png new file mode 100644 index 000000000..985df507c Binary files /dev/null and b/share/iptux/pixmaps/icon/iptux-icon-reverse.png differ diff --git a/src/config.h.in b/src/config.h.in index 10bba306f..f2882649a 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -11,6 +11,7 @@ #define __LOCALE_PATH "@SHARE_DIR@/locale" #define __SOUND_PATH "@SHARE_IPTUX_DIR@/sound" #define __UI_PATH "@SHARE_IPTUX_DIR@/ui" +#define __ICON_PATH "@SHARE_DIR@/icons/hicolor" #define IPTUX_PATH "/iptux" #define LOG_PATH "/iptux/log" diff --git a/src/iptux/AppIndicator.cpp b/src/iptux/AppIndicator.cpp index edf31e54f..c46ca8f09 100644 --- a/src/iptux/AppIndicator.cpp +++ b/src/iptux/AppIndicator.cpp @@ -4,12 +4,17 @@ #include #include +#include "iptux-utils/output.h" + namespace iptux { class IptuxAppIndicatorPrivate { public: IptuxAppIndicatorPrivate(IptuxAppIndicator* owner) : owner(owner) {} ~IptuxAppIndicatorPrivate() { + if (blinkTimerId) { + g_source_remove(blinkTimerId); + } if (indicator) { g_object_unref(indicator); } @@ -22,12 +27,49 @@ class IptuxAppIndicatorPrivate { GtkBuilder* menuBuilder; StatusIconMode mode = STATUS_ICON_MODE_NORMAL; int unreadCount = 0; + guint blinkTimerId = 0; + bool blinkState = false; static void onScrollEvent(IptuxAppIndicatorPrivate* self) { self->owner->sigActivateMainWindow.emit(); } }; +static gboolean blinkTimerCallback(gpointer data) { + auto priv = static_cast(data); + priv->blinkState = !priv->blinkState; + if (priv->blinkState) { + LOG_DEBUG("blinkTimerCallback: switching to reverse icon"); + app_indicator_set_icon_full(priv->indicator, "iptux-icon-reverse", + "iptux-icon-reverse"); + } else { + LOG_DEBUG("blinkTimerCallback: switching to normal icon"); + app_indicator_set_icon_full(priv->indicator, "iptux-icon", "iptux-icon"); + } + return G_SOURCE_CONTINUE; +} + +static void startBlinkTimer(IptuxAppIndicatorPrivate* priv) { + if (priv->blinkTimerId) { + LOG_DEBUG("startBlinkTimer: timer already running (id=%u)", priv->blinkTimerId); + return; + } + priv->blinkState = false; + priv->blinkTimerId = g_timeout_add(500, blinkTimerCallback, priv); + LOG_DEBUG("startBlinkTimer: blinking started (timerId=%u)", priv->blinkTimerId); +} + +static void stopBlinkTimer(IptuxAppIndicatorPrivate* priv) { + if (priv->blinkTimerId) { + LOG_DEBUG("stopBlinkTimer: blinking stopped (timerId=%u)", priv->blinkTimerId); + g_source_remove(priv->blinkTimerId); + priv->blinkTimerId = 0; + } else { + LOG_DEBUG("stopBlinkTimer: no timer was running"); + } + priv->blinkState = false; +} + IptuxAppIndicator::IptuxAppIndicator(GActionGroup* action_group) { this->priv = std::make_shared(this); @@ -42,7 +84,7 @@ IptuxAppIndicator::IptuxAppIndicator(GActionGroup* action_group) { app_indicator_set_status(priv->indicator, APP_INDICATOR_STATUS_ACTIVE); app_indicator_set_attention_icon_full(priv->indicator, "iptux-attention", "iptux-attention"); - + app_indicator_set_icon_theme_path(priv->indicator, __ICON_PATH); app_indicator_set_title(priv->indicator, _("Iptux")); priv->menuBuilder = @@ -59,8 +101,24 @@ IptuxAppIndicator::IptuxAppIndicator(GActionGroup* action_group) { } void IptuxAppIndicator::SetUnreadCount(int i) { + LOG_DEBUG("SetUnreadCount: count=%d, mode=%d", i, priv->mode); priv->unreadCount = i; - if (priv->mode == STATUS_ICON_MODE_NONE) return; + if (priv->mode == STATUS_ICON_MODE_NONE) { + LOG_DEBUG("SetUnreadCount: early return (mode=NONE)"); + return; + } + + if (priv->mode == STATUS_ICON_MODE_BLINKING) { + if (i > 0) { + startBlinkTimer(priv.get()); + } else { + stopBlinkTimer(priv.get()); + app_indicator_set_icon_full(priv->indicator, "iptux-icon", "iptux-icon"); + app_indicator_set_status(priv->indicator, APP_INDICATOR_STATUS_ACTIVE); + } + return; + } + if (i > 0) { app_indicator_set_status(priv->indicator, APP_INDICATOR_STATUS_ATTENTION); } else { @@ -69,7 +127,15 @@ void IptuxAppIndicator::SetUnreadCount(int i) { } void IptuxAppIndicator::SetMode(StatusIconMode mode) { + LOG_DEBUG("SetMode: mode=%d (old=%d)", mode, priv->mode); + StatusIconMode oldMode = priv->mode; priv->mode = mode; + + if (oldMode == STATUS_ICON_MODE_BLINKING) { + stopBlinkTimer(priv.get()); + app_indicator_set_icon_full(priv->indicator, "iptux-icon", "iptux-icon"); + } + if (mode == STATUS_ICON_MODE_NONE) { app_indicator_set_status(priv->indicator, APP_INDICATOR_STATUS_PASSIVE); } else { @@ -77,4 +143,12 @@ void IptuxAppIndicator::SetMode(StatusIconMode mode) { } } +void IptuxAppIndicator::StopBlinking() { + LOG_DEBUG("StopBlinking called"); + stopBlinkTimer(priv.get()); + app_indicator_set_icon_full(priv->indicator, "iptux-icon", "iptux-icon"); + if (priv->mode == STATUS_ICON_MODE_NONE) return; + app_indicator_set_status(priv->indicator, APP_INDICATOR_STATUS_ACTIVE); +} + } // namespace iptux diff --git a/src/iptux/AppIndicator.h b/src/iptux/AppIndicator.h index 56c5a4c96..af0da1129 100644 --- a/src/iptux/AppIndicator.h +++ b/src/iptux/AppIndicator.h @@ -14,10 +14,15 @@ class IptuxAppIndicator { IptuxAppIndicator(GActionGroup* action_group); void SetUnreadCount(int count); void SetMode(StatusIconMode mode); + void StopBlinking(); sigc::signal sigActivateMainWindow; private: std::shared_ptr priv; }; +#ifdef __APPLE__ +void ActivateApplication(); +#endif + } // namespace iptux diff --git a/src/iptux/AppIndicatorDummy.cpp b/src/iptux/AppIndicatorDummy.cpp index 0d421f95a..fac4d442f 100644 --- a/src/iptux/AppIndicatorDummy.cpp +++ b/src/iptux/AppIndicatorDummy.cpp @@ -12,4 +12,8 @@ void IptuxAppIndicator::SetUnreadCount(int) { void IptuxAppIndicator::SetMode(StatusIconMode) { // Dummy implementation } + +void IptuxAppIndicator::StopBlinking() { + // Dummy implementation +} } // namespace iptux diff --git a/src/iptux/AppIndicatorMac.mm b/src/iptux/AppIndicatorMac.mm index cfa286df2..00a7d6504 100644 --- a/src/iptux/AppIndicatorMac.mm +++ b/src/iptux/AppIndicatorMac.mm @@ -6,6 +6,8 @@ #include #include +#include "iptux-utils/output.h" + #import // Objective-C helper class for NSStatusItem callbacks. @@ -36,6 +38,7 @@ - (instancetype)initWithActionGroup:(GActionGroup*)actionGroup - (void)openMainWindow:(id)sender { (void)sender; + g_debug("AppIndicatorMac: openMainWindow menu item clicked"); g_action_group_activate_action(actionGroup_, "open_main_window", NULL); } @@ -111,6 +114,9 @@ - (void)statusItemClicked:(id)sender { public: IptuxAppIndicatorPrivate() {} ~IptuxAppIndicatorPrivate() { + if (blinkTimerId) { + g_source_remove(blinkTimerId); + } if (statusItem) { [[NSStatusBar systemStatusBar] removeStatusItem:statusItem]; [statusItem release]; @@ -124,14 +130,20 @@ - (void)statusItemClicked:(id)sender { if (attentionIcon) { [attentionIcon release]; } + if (reverseIcon) { + [reverseIcon release]; + } } NSStatusItem* statusItem = nil; IptuxStatusItemHelper* helper = nil; NSImage* normalIcon = nil; NSImage* attentionIcon = nil; + NSImage* reverseIcon = nil; StatusIconMode mode = STATUS_ICON_MODE_NORMAL; int unreadCount = 0; + guint blinkTimerId = 0; + bool blinkState = false; }; IptuxAppIndicator::IptuxAppIndicator(GActionGroup* action_group) { @@ -143,6 +155,7 @@ - (void)statusItemClicked:(id)sender { // Load icons priv->normalIcon = loadIcon("iptux-icon", 64); priv->attentionIcon = loadIcon("iptux-attention", 64); + priv->reverseIcon = loadIcon("iptux-icon-reverse", 64); // Create status item priv->statusItem = @@ -186,9 +199,68 @@ - (void)statusItemClicked:(id)sender { [menu release]; } +static gboolean blinkTimerCallback(gpointer data) { + auto priv = static_cast(data); + if (!priv->statusItem) { + LOG_DEBUG("blinkTimerCallback: statusItem is nil, removing timer"); + return G_SOURCE_REMOVE; + } + priv->blinkState = !priv->blinkState; + if (priv->blinkState && priv->reverseIcon) { + LOG_DEBUG("blinkTimerCallback: switching to reverse icon"); + priv->statusItem.button.image = priv->reverseIcon; + } else if (priv->normalIcon) { + LOG_DEBUG("blinkTimerCallback: switching to normal icon"); + priv->statusItem.button.image = priv->normalIcon; + } else { + LOG_DEBUG("blinkTimerCallback: no icon available (blinkState=%d, reverseIcon=%p, normalIcon=%p)", + priv->blinkState, priv->reverseIcon, priv->normalIcon); + } + return G_SOURCE_CONTINUE; +} + +static void startBlinkTimer(IptuxAppIndicatorPrivate* priv) { + if (priv->blinkTimerId) { + LOG_DEBUG("startBlinkTimer: timer already running (id=%u)", priv->blinkTimerId); + return; + } + priv->blinkState = false; + priv->blinkTimerId = g_timeout_add(500, blinkTimerCallback, priv); + LOG_DEBUG("startBlinkTimer: blinking started (timerId=%u)", priv->blinkTimerId); +} + +static void stopBlinkTimer(IptuxAppIndicatorPrivate* priv) { + if (priv->blinkTimerId) { + LOG_DEBUG("stopBlinkTimer: blinking stopped (timerId=%u)", priv->blinkTimerId); + g_source_remove(priv->blinkTimerId); + priv->blinkTimerId = 0; + } else { + LOG_DEBUG("stopBlinkTimer: no timer was running"); + } + priv->blinkState = false; +} + void IptuxAppIndicator::SetUnreadCount(int count) { + LOG_DEBUG("SetUnreadCount: count=%d, mode=%d, statusItem=%p", count, priv->mode, + priv->statusItem); priv->unreadCount = count; - if (!priv->statusItem || priv->mode == STATUS_ICON_MODE_NONE) return; + if (!priv->statusItem || priv->mode == STATUS_ICON_MODE_NONE) { + LOG_DEBUG("SetUnreadCount: early return (statusItem=%p, mode=%d)", + priv->statusItem, priv->mode); + return; + } + + if (priv->mode == STATUS_ICON_MODE_BLINKING) { + if (count > 0) { + startBlinkTimer(priv.get()); + } else { + stopBlinkTimer(priv.get()); + if (priv->normalIcon) { + priv->statusItem.button.image = priv->normalIcon; + } + } + return; + } if (count > 0 && priv->attentionIcon) { priv->statusItem.button.image = priv->attentionIcon; @@ -198,12 +270,35 @@ - (void)statusItemClicked:(id)sender { } void IptuxAppIndicator::SetMode(StatusIconMode mode) { + LOG_DEBUG("SetMode: mode=%d (old=%d)", mode, priv->mode); + StatusIconMode oldMode = priv->mode; priv->mode = mode; if (!priv->statusItem) return; priv->statusItem.visible = (mode != STATUS_ICON_MODE_NONE); + + if (oldMode == STATUS_ICON_MODE_BLINKING) { + stopBlinkTimer(priv.get()); + if (priv->normalIcon) { + priv->statusItem.button.image = priv->normalIcon; + } + } + if (mode != STATUS_ICON_MODE_NONE) { SetUnreadCount(priv->unreadCount); } } +void IptuxAppIndicator::StopBlinking() { + LOG_DEBUG("StopBlinking called"); + stopBlinkTimer(priv.get()); + if (!priv->statusItem || priv->mode == STATUS_ICON_MODE_NONE) return; + if (priv->normalIcon) { + priv->statusItem.button.image = priv->normalIcon; + } +} + +void ActivateApplication() { + [NSApp activateIgnoringOtherApps:YES]; +} + } // namespace iptux diff --git a/src/iptux/Application.cpp b/src/iptux/Application.cpp index cc9b2062a..cd825e741 100644 --- a/src/iptux/Application.cpp +++ b/src/iptux/Application.cpp @@ -130,11 +130,16 @@ void Application::onStartup(Application& self) { make_shared(G_ACTION_GROUP(self.app)); self.app_indicator->SetMode(StatusIconMode(self.data->statusIconMode())); self.app_indicator->sigActivateMainWindow.connect([&self]() { + LOG_DEBUG("sigActivateMainWindow: emitted, activating open_main_window action"); g_action_group_activate_action(G_ACTION_GROUP(self.app), "open_main_window", NULL); }); self.cthrd->sigUnreadMsgCountUpdated.connect( sigc::mem_fun(*self.app_indicator, &IptuxAppIndicator::SetUnreadCount)); + + // Removed notify::is-active StopBlinking handler. + // Blinking now stops only when the user interacts with the dialog + // (button-press-event or key-press-event via ClearNotify). } bool use_app_menu = true; @@ -227,6 +232,11 @@ void Application::onActivate(Application& self) { } void Application::onQuit(void*, void*, Application& self) { + // Close the preference dialog if it's open, so its modal loop doesn't block quit. + if (self.preference_dialog_) { + gtk_dialog_response(GTK_DIALOG(self.preference_dialog_), + GTK_RESPONSE_DELETE_EVENT); + } if (!transModelIsFinished(self.transModel)) { if (!pop_request_quit(GTK_WINDOW(self.window->getWindow()))) { return; @@ -240,6 +250,7 @@ void Application::onPreferences(void*, void*, Application& self) { } void Application::onOpenMainWindow(void*, void*, Application& self) { + LOG_DEBUG("onOpenMainWindow: action triggered"); self.getMainWindow()->Show(); } diff --git a/src/iptux/DataSettings.cpp b/src/iptux/DataSettings.cpp index 552e7e46d..5b4b00b9e 100644 --- a/src/iptux/DataSettings.cpp +++ b/src/iptux/DataSettings.cpp @@ -354,6 +354,35 @@ GtkWidget* DataSettings::CreateSystem() { g_datalist_set_data(&widset, "font-chooser-widget", widget); gtk_grid_attach(GTK_GRID(box), widget, 1, row, 1, 1); +#if HAVE_STATUS_ICON + row++; + label = gtk_label_new(_("Status icon:")); + gtk_widget_set_halign(label, GTK_ALIGN_END); + gtk_grid_attach(GTK_GRID(box), label, 0, row, 1, 1); + + { + auto store = gtk_list_store_new(STATUS_ICON_MODEL_N_COLS, G_TYPE_STRING, + G_TYPE_STRING); + for (const auto& entry : kStatusIconModes) { + GtkTreeIter iter; + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, STATUS_ICON_MODEL_COL_ID, + std::to_string(entry.mode).c_str(), + STATUS_ICON_MODEL_COL_LABEL, _(entry.label), -1); + } + widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); + g_object_unref(store); + gtk_combo_box_set_id_column(GTK_COMBO_BOX(widget), + STATUS_ICON_MODEL_COL_ID); + auto cell = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), cell, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(widget), cell, "text", + STATUS_ICON_MODEL_COL_LABEL, NULL); + } + gtk_grid_attach(GTK_GRID(box), widget, 1, row, 1, 1); + g_datalist_set_data(&widset, "status-icon-mode-combo-widget", widget); +#endif + row++; /* 有消息时直接弹出聊天窗口 */ @@ -425,35 +454,6 @@ GtkWidget* DataSettings::CreateSystem() { g_datalist_set_data(&widset, "taskbar-check-widget", widget); #endif -#if HAVE_STATUS_ICON - row++; - label = gtk_label_new(_("Status icon:")); - gtk_widget_set_halign(label, GTK_ALIGN_END); - gtk_grid_attach(GTK_GRID(box), label, 0, row, 1, 1); - - { - auto store = gtk_list_store_new(STATUS_ICON_MODEL_N_COLS, G_TYPE_STRING, - G_TYPE_STRING); - for (const auto& entry : kStatusIconModes) { - GtkTreeIter iter; - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, STATUS_ICON_MODEL_COL_ID, - std::to_string(entry.mode).c_str(), - STATUS_ICON_MODEL_COL_LABEL, _(entry.label), -1); - } - widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); - g_object_unref(store); - gtk_combo_box_set_id_column(GTK_COMBO_BOX(widget), - STATUS_ICON_MODEL_COL_ID); - auto cell = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), cell, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(widget), cell, "text", - STATUS_ICON_MODEL_COL_LABEL, NULL); - } - gtk_grid_attach(GTK_GRID(box), widget, 1, row, 1, 1); - g_datalist_set_data(&widset, "status-icon-mode-combo-widget", widget); -#endif - return GTK_WIDGET(box); } diff --git a/src/iptux/DialogBase.cpp b/src/iptux/DialogBase.cpp index b885f4ad2..dc15c8444 100644 --- a/src/iptux/DialogBase.cpp +++ b/src/iptux/DialogBase.cpp @@ -225,7 +225,7 @@ void DialogBase::MainWindowSignalSetup(GtkWindow* window) { G_CALLBACK(DragDataReceived), this); g_signal_connect(window, "configure-event", G_CALLBACK(WindowConfigureEvent), &dtset); - g_signal_connect(window, "focus-in-event", G_CALLBACK(ClearNotify), NULL); + g_signal_connect(window, "event-after", G_CALLBACK(ClearNotify), NULL); } /** @@ -470,13 +470,20 @@ void DialogBase::DialogDestory(DialogBase* dialog) { /** * 清除提示,这个提示只是窗口闪动的提示 */ -gboolean DialogBase::ClearNotify(GtkWidget* window, GdkEventConfigure*) { +void DialogBase::ClearNotify(GtkWidget* window, GdkEvent* event) { + if (event) { + GdkEventType type = gdk_event_get_event_type(event); + if (type != GDK_BUTTON_PRESS && type != GDK_KEY_PRESS) + return; + LOG_DEBUG("ClearNotify: user interaction on dialog window (type=%d)", type); + } else { + LOG_DEBUG("ClearNotify: called directly (window is active)"); + } if (gtk_window_get_urgency_hint(GTK_WINDOW(window))) gtk_window_set_urgency_hint(GTK_WINDOW(window), FALSE); DialogBase* self = (DialogBase*)g_object_get_data(G_OBJECT(window), "session-class"); self->grpinf->readAllMsg(); - return FALSE; } /** diff --git a/src/iptux/DialogBase.h b/src/iptux/DialogBase.h index 356c1d9fc..e6a45142b 100644 --- a/src/iptux/DialogBase.h +++ b/src/iptux/DialogBase.h @@ -64,7 +64,7 @@ class DialogBase : public SessionAbstract, public sigc::trackable { // 回调部分 static void DialogDestory(DialogBase*); - static gboolean ClearNotify(GtkWidget* window, GdkEventConfigure* event); + static void ClearNotify(GtkWidget* window, GdkEvent* event); static void DragDataReceived(DialogBase* dlgpr, GdkDragContext* context, gint x, diff --git a/src/iptux/DialogPeer.cpp b/src/iptux/DialogPeer.cpp index c19a450d8..95ff247af 100644 --- a/src/iptux/DialogPeer.cpp +++ b/src/iptux/DialogPeer.cpp @@ -1068,9 +1068,9 @@ void DialogPeer::onNewFileReceived(GroupInfo*) { void DialogPeer::onGroupInfoUpdated(GroupInfo* groupInfo) { if (groupInfo != this->grpinf) return; - if (gtk_window_is_active(GTK_WINDOW(this->window))) { - ClearNotify(GTK_WIDGET(this->window), nullptr); - } + // Don't auto-read messages just because the window is active. + // Messages are marked as read only on user interaction + // (button-press or key-press via ClearNotify). } void DialogPeer::refreshSendAction() { diff --git a/src/iptux/MainWindow.cpp b/src/iptux/MainWindow.cpp index 08c68fa51..621737be9 100644 --- a/src/iptux/MainWindow.cpp +++ b/src/iptux/MainWindow.cpp @@ -11,6 +11,7 @@ // #include "config.h" #include "MainWindow.h" +#include "AppIndicator.h" #include "iptux-core/Const.h" #include "iptux-utils/output.h" #include "iptux-utils/utils.h" @@ -100,7 +101,13 @@ GtkWidget* MainWindow::getWindow() { } void MainWindow::Show() { + LOG_DEBUG("MainWindow::Show: presenting window %p, visible=%d", window, + gtk_widget_get_visible(window)); gtk_window_present(GTK_WINDOW(window)); + gtk_window_deiconify(GTK_WINDOW(window)); +#ifdef __APPLE__ + ActivateApplication(); +#endif } static void mainWindowDestroy(gpointer data) { @@ -1210,6 +1217,7 @@ void MainWindow::onPaltreeItemActivated(GtkWidget* treeview, /* 检查是否需要新建对话框 */ if (grpinf->getDialog()) { gtk_window_present(GTK_WINDOW(grpinf->getDialog())); + grpinf->readAllMsg(); return; } @@ -1225,6 +1233,7 @@ void MainWindow::onPaltreeItemActivated(GtkWidget* treeview, default: break; } + grpinf->readAllMsg(); } /** @@ -1555,6 +1564,7 @@ void MainWindow::PallistItemActivated(GtkWidget* treeview, DialogPeer::PeerDialogEntry(self->app, grpinf); else gtk_window_present(GTK_WINDOW(grpinf->getDialog())); + grpinf->readAllMsg(); } } diff --git a/src/iptux/UiCoreThread.cpp b/src/iptux/UiCoreThread.cpp index 757059f04..d2eabb7c7 100644 --- a/src/iptux/UiCoreThread.cpp +++ b/src/iptux/UiCoreThread.cpp @@ -494,7 +494,9 @@ void UiCoreThread::PopItemFromEnclosureList(FileInfo* file) { delete file; } -void UiCoreThread::onGroupInfoMsgCountUpdate(GroupInfo* grpinf, int, int) { +void UiCoreThread::onGroupInfoMsgCountUpdate(GroupInfo* grpinf, int oldCount, int newCount) { + LOG_DEBUG("onGroupInfoMsgCountUpdate: oldCount=%d, newCount=%d, totalUnread=%d", + oldCount, newCount, unread_msg_count()); sigGroupInfoUpdated.emit(grpinf); sigUnreadMsgCountUpdated.emit(unread_msg_count()); } diff --git a/src/iptux/UiModels.cpp b/src/iptux/UiModels.cpp index ec243be59..a75d1de84 100644 --- a/src/iptux/UiModels.cpp +++ b/src/iptux/UiModels.cpp @@ -532,11 +532,14 @@ void GroupInfo::clearInputBuffer() { void GroupInfo::addMsgCount(int i) { int oldCount = getUnreadMsgCount(); allMsgCount += i; + LOG_DEBUG("addMsgCount: i=%d, oldCount=%d, newCount=%d", i, oldCount, + getUnreadMsgCount()); signalUnreadMsgCountUpdated.emit(this, oldCount, getUnreadMsgCount()); } void GroupInfo::readAllMsg() { int oldCount = getUnreadMsgCount(); + LOG_DEBUG("readAllMsg: oldCount=%d", oldCount); if (oldCount != 0) { readMsgCount = allMsgCount; signalUnreadMsgCountUpdated.emit(this, oldCount, getUnreadMsgCount()); @@ -806,7 +809,9 @@ void GroupInfo::_addMsgPara(const MsgPara& para, time_t now) { break; } } - addMsgCount(1); + if (para.stype == MessageSourceType::PAL) { + addMsgCount(1); + } } bool transModelIsFinished(TransModel* model) {