Notification system#160
Merged
Merged
Conversation
| } | ||
| } | ||
|
|
||
| TEST_CASE("Any notification manager", "[NotificationManager]") |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #160 +/- ##
===========================================
- Coverage 93.08% 92.96% -0.12%
===========================================
Files 158 201 +43
Lines 6075 8673 +2598
Branches 276 386 +110
===========================================
+ Hits 5655 8063 +2408
- Misses 420 610 +190 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
mrpilot2
force-pushed
the
develop+notification_system
branch
2 times, most recently
from
July 19, 2026 10:19
2602317 to
a4bbb95
Compare
| queue.pending.append(this); | ||
| return; | ||
| } | ||
| queue.current = this; |
Comment on lines
+42
to
+43
| TEST_CASE("NotificationGroupTableModel seeded with groups", | ||
| "[NotificationGroupTableModel]") |
mrpilot2
force-pushed
the
develop+notification_system
branch
2 times, most recently
from
July 20, 2026 22:31
121dbb6 to
63ac123
Compare
mrpilot2
force-pushed
the
develop
branch
2 times, most recently
from
July 20, 2026 22:52
6387295 to
c041009
Compare
mrpilot2
force-pushed
the
develop+notification_system
branch
from
July 20, 2026 23:12
27a0127 to
9c09a27
Compare
Locks in the notification value types (Notification, NotificationGroup, NotificationAction, NotificationId, NotificationType/DisplayType) and NotificationManagerInterface/NotificationManager per the design decisions in issue #143 (core API), #145 (display-type routing + DND), and #148's read-state amendment, wired into Application/ApplicationBuilder mirroring actionRegistry(). Unblocks the remaining per-surface build tickets (#150-#157). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reusable severity-tinted Banner strip (icon, message, optional action links, close button) plus MainWindow::addBanner/removeBanner, wrapping the central widget so several active banners stack vertically with hairline dividers, newest at the bottom. Caller-driven per #145: never goes through NotificationManager::post() and is never logged. Per-type icons and colours are placeholders until #157 lands themed severity assets. Closes #150. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Built exactly per #147: aide::widgets::NotificationBalloon is a frameless corner popup (severity stripe, icon, title, body, up to two inline action links plus a "More" overflow menu, close button) mirroring Banner's look. Transient balloons auto-dismiss after 8s with a countdown bar that pauses on hover; sticky balloons never time out. aide::gui::NotificationBalloonHost observes NotificationManagerInterface and shows a balloon for every Balloon/StickyBalloon-resolved notification, routed through the concrete NotificationManager's notificationPosted signal wired in ApplicationBuilder (string-based connect, same cross-DLL reasoning as the existing AppearanceManager wiring). Corner placement is the new global aide::NotificationBalloonPlacement setting (notifications.balloonPlacement, default BottomRight); stacking derives from the corner alone, growing toward screen center. Verified with dev-unix-static-debug (warnings-as-errors, ASAN+UBSAN, clang-tidy, cppcheck); full suite green (775 assertions, 157 test cases). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…`this` QTimer::singleShot() had no context object, so the queued lambda held a raw `this` with no lifetime guard. If the widget was destroyed before VISIBILITY_TOGGLE_DELAY elapsed, the timer fired into freed memory — caught by ASAN as a stack-use-after-return once test #153's added event pumping gave the timer enough wall-clock time to actually fire. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Implements the design locked in #147: a frameless GotItTooltip anchored to a target widget (Position::{Below,Above,Left,Right}, arrow pointing at it), caller-driven and independent of NotificationManager (#149) — only SettingsInterface and a target QWidget are needed. - Fluent withHeader/withStep/withLink/withShowCount/withTimeout setters, terminated by showGotIt(target, position). - Seen state is an int show-count at SettingsInterface key "aide/gotit/<id>" (canShow() == count < maxCount, default 1); reshow a changed tip by bumping the id (".v2" convention, caller's job). - Defers showing until the target has non-empty, visible bounds (watches both Show and Resize). - Single process-wide queue: only one tooltip shows at a time, closing one advances to the next. - isFirstRunAfterUpgrade() gates post-upgrade tips via a stored "aide/gotit/previous/run" build stamp vs the app version. Verified with dev-unix-static-debug (warnings-as-errors, ASAN+UBSAN, clang-tidy, cppcheck); full suite green (809 assertions, 166 test cases). Not blocked by #149 — unblocked per the map. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds aide::gui::NotificationsSettingsPage at group "Notifications", registered beside Keymap/Appearance in the SettingsDialog tree. A QTableView backed by NotificationGroupTableModel lists one row per registered NotificationGroup (Group / Popup type / Log), with a combo delegate for the popup type column. Do Not Disturb and balloon placement sit above the table as global controls. matches()/score()/ highlight() are overridden to search the model's rows in addition to the default child-widget scan, since table rows aren't child widgets. NotificationManagerInterface gains groups() to enumerate the group registry, needed to build the table. Closes #154.
Consolidate the notification settings key format (doNotDisturb, balloonPlacement, <group-id>.displayType) into a single header instead of three independent copies in NotificationManager, NotificationBalloonHost and NotificationsSettingsPage, so the locked key format is defined exactly once. Also nest the notification settings page under "Appearance & Behavior" in the settings tree, and show both the group's display name and its HierarchicalId in the Group column instead of hiding the id behind a tooltip only.
Build the notification-view widget per #148's design lock: a plain embeddable QWidget (not a docked tool window) showing the log as a flat, newest-first list. NotificationLogModel (core) observes the manager's notificationPosted/Removed/Updated/notificationsCleared signals via a dynamic_cast<QObject*> to the concrete NotificationManager, since the interface itself carries none (#145). NotificationLogItemDelegate paints each card (severity stripe/icon, bold title, absolute timestamp, body, up to 2 inline actions + "More" overflow, per-item settings/mute menu) and hit-tests the same rects in editorEvent(), reusing the placeholder severity palette pending #157. Read state stays boolean per #148's amendment: the view calls markRead() on show and on every post while visible; cards render uniform, no per-entry styling. BREAKING CHANGE: aide::Notification (aide/include/aide/notification.hpp) now declares Q_DECLARE_METATYPE(aide::Notification), changing the public header's ABI surface for downstream consumers. Closes #155. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Builds the shared notification visual language locked in #156: full-colour SVG glyphs for each NotificationType (dialog-information, emblem-success, dialog-warning, dialog-error) in both aide-light and aide-dark icon themes under scalable/status/, and a theme-aware AppearanceManager::severityColor() accessor returning the matching stripe colour. Consumers (banner #150, balloon #152, notification-view #155) keep placeholder icons until they migrate. Closes #157 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Move `MainWindowInterface` onto the framework's public include path and add `addBanner`/`removeBanner` so consumer code can reach the editor-banner mount point through `Application::mainWindow()` without touching internal `AideGui` headers. Source-compatible: the interface still derives `QMainWindow`, so every existing caller keeps compiling. Resolves #162, unblocks the notification-subsystem wayfinder map (#142). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ation group
setSearchPattern() re-emitted dataChanged even when the pattern was
unchanged. That signal is wired to onUserChangedAGuiElement(), which
clears the highlight by calling setSearchPattern("") again, so every
GUI-change notification retriggered itself and blew the stack.
Guard the setter so a redundant call is a no-op.
Balloons positioned themselves against the primary screen's geometry, so "bottom right" meant the desktop corner rather than the app window's corner, and they ignored the window moving, resizing, or minimizing. Also drop Qt::WindowStaysOnTopHint and instead parent each balloon to the main window: that hint floated the balloon above every window on the desktop, not just aide's own, so Alt+Tab to another app left the balloon stranded on top of it. A transient child window is kept above only its owner by the window manager, and is raised, moved, and minimized together with it. NotificationBalloonHost now positions balloons against the anchor widget's frameGeometry(), and installs an event filter on it to relayout on move/resize and to hide/restore balloons in step with the window's minimize state.
The balloon panel background was a fixed pastel tint per severity, so it stayed light even under a dark theme while the label text followed the app's (light) theme color, making it unreadable. Derive the background from the app's own QPalette::Window color instead, lightened under a dark theme and darkened under a light one: this keeps it high-contrast against the app's text color in both themes while still reading as a distinct, raised surface. Severity is now conveyed by the stripe and icon alone.
Same class of bugs as NotificationBalloon: the body used QPalette::ToolTipBase for its fill, which platform themes frequently don't honour for a custom-painted popup, leaving it unreadable in one theme; and Qt::WindowStaysOnTopHint floated it above every window on the desktop rather than just its target's, so it stayed open and visible across Alt+Tab and app minimize instead of following its owner. Derive the surface color from the app's own Window color instead (paired with an explicit WindowText override so labels stay contrasting), and reparent to the target's window in showGotIt() with WindowStaysOnTopHint dropped, so it becomes a proper transient child. The event filter that already tracked the target's window to detect when it becomes visible now stays installed for the tooltip's whole life, repositioning on move/resize and hiding/restoring in step with minimize - mirroring NotificationBalloonHost's anchor handling.
…nner Replaces the derived stripe-color darkening with fixed, designer- specified dark-theme backgrounds: info #263141, success #253327, warning #3a3320, error #3a2626. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
HierarchicalId stores raw const char* levels rather than owning copies. GotItTooltip built settings keys from m_id.c_str() (a heap string, not a literal), and MockSettings kept that HierarchicalId as a long-lived map key — once the tooltip was destroyed the key dangled, causing a heap-use-after-free the next time a comparison touched it (only caught under ASAN in CI). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a "Demo" menu (before "Help") with a "Notifications" action opening a launcher dialog. Its "Balloon" section registers two demo NotificationGroups at startup (Balloon/StickyBalloon) and posts real notifications through NotificationManager::post() to exercise info, success, warning, error, multi-action and sticky balloons. Closes #164
Code review flagged four near-identical connect() blocks for the Balloon section's Info/Success/Warning/Error buttons; a small per-button table removes the duplication.
…ncher Turns the manual acceptance-criteria walkthrough for #164 (Info/Success/ Warning/Error/2-action/Sticky buttons posting through NotificationManagerInterface) into a Catch2 + QTest test, run via ctest alongside the rest of the suite, using a fake NotificationManagerInterface to capture posted notifications without a real balloon host. Kept as a separate ut.aide.demo executable under demo/tests rather than folded into tests/ut/ut.aide, since tests/ is designed to build standalone against an installed Aide package without demo/ present.
Closes #165. Adds a "Got it" QGroupBox to NotificationLauncherDialog with a sample anchor button, a Below/Above/Right position selector, a Show button that raises a real GotItTooltip against AideSettingsProvider::unversionableSettings(), and a "Reset seen flag" button for repeatable evaluation. Links Aide::AideWidgets into the demo build, the first section that needs it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a "Dialog banner" section with an "Open dialog banner demo" button that shows a new NotificationDemoDialog (AideDialog subclass) whose Info/Success/Warning/Error buttons drive showBanner()/ clearBanner() on itself. Closes #166. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Closes #167. Info/Success/Warning/Error buttons in the launcher's "Editor banner" section call addBanner() via the MainWindowInterface now exposed by Application::mainWindow(), tracking the returned Banner* pointers so "Clear all" can remove every stacked banner.
mrpilot2
force-pushed
the
develop+notification_system
branch
from
July 20, 2026 23:15
9c09a27 to
c904f0a
Compare
AideDialog was missing AIDEWIDGETS_EXPORT, unlike its sibling Banner. On Windows shared-linkage builds this left staticMetaObject and the vtable unexported from the DLL, so any downstream consumer of a QObject-derived AideDialog subclass (e.g. the demo's NotificationDemoDialog) failed to link with LNK2001.
Fill translated strings for de_DE, zh_CN, hi_IN, es_ES, fr_FR, ar_SA and sv across the notification system UI (banners, balloons, settings page) plus demo launcher strings; en marked finished with empty translations per existing convention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add reference pages for the notification surfaces (manager, balloons, log view, banners, "Got it" tooltip, settings page) and for ApplicationConfig's feature toggles, and wire both into the nav. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
NotificationBalloon and GotItTooltip were separate Qt::Tool top-level windows positioned via absolute screen coordinates. Wayland gives clients no global coordinate space and ignores/reinterprets such requests for toplevels, so the compositor placed them near whatever window currently had focus instead of the intended anchor (e.g. a balloon anchored to the main window showing inside an unrelated dialog on top of it). Both now stay plain child widgets of their anchor, positioned in its local coordinate space, which needs no protocol-level placement and works identically on X11 and Wayland. Also fixes GotItTooltip sizing too small for wrapped body text: sizeHint() measured height against the layout's pre-resize width instead of the fixed TOOLTIP_WIDTH about to be applied; now uses layout()->totalHeightForWidth() at that width. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Broke in fd4d20b: GotItTooltip is now reparented to the target's window instead of staying a top-level Qt::Tool, so it no longer shows up in QApplication::topLevelWidgets(). Search the dialog's children instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
clang-tidy (ci-static preset) flagged modernize-use-designated-initializers on notification palette/aggregate structs and modernize-use-ranges on std::find/std::find_if/std::reverse calls across the new notification code. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
MainWindow now owns a NotificationView (#155), created via ApplicationBuilder::createNotificationLogView() and exposed through MainWindowInterface::notificationLogView(); its "Notification Settings..." overflow entries are wired internally to open the Settings dialog with the built-in Notifications page pre-selected (new ShowSettingsDialogController::showSettingsDialog(HierarchicalId) overload), so consumers only decide where to place the widget. Demo places it in a QSplitter on the right of the main window, behind a checkable View menu toggle whose visibility/width persist via QSettings. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
mrpilot2
force-pushed
the
develop+notification_system
branch
from
July 21, 2026 20:38
e564d68 to
e3c33d5
Compare
cppcheck can't see that manager.post() between the two liveBalloonCount() calls changes the live count, so it flags the equality check as always true. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements #142