MailJD nbsp;·nbsp; Test Dashboard nbsp;·nbsp; Coverage
LCOV - code coverage report
Current view: top level - app - SearchCoordinator.h (source / functions) Coverage Total Hit
Test: MailJD Coverage (Unit + E2E) Lines: 100.0 % 6 6
Test Date: 2026-06-21 21:10:19 Functions: 100.0 % 6 6
Legend: Lines:     hit not hit

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : #include <QObject>
       4              : #include <QPair>
       5              : #include <QSet>
       6              : #include <QStringList>
       7              : #include <functional>
       8              : 
       9              : #include "data/MailCache.h"
      10              : #include "data/Models.h"
      11              : 
      12              : class CommandBar;
      13              : class FolderTree;
      14              : class MailController;
      15              : class MailFilterProxyModel;
      16              : class MailListModel;
      17              : class QTimer;
      18              : class SearchPanel;
      19              : 
      20              : // SearchCoordinator owns the complete search-mode state and logic that
      21              : // historically lived inside MainWindow (Sprint 65 P2.1 extraction):
      22              : //   - running a search (local FTS page + server-side IMAP SEARCH)
      23              : //   - local-result pagination (":search-more")
      24              : //   - the CommandBar live quick-search dropdown results
      25              : //   - the SearchPanel wiring (explicit run, live-filter debounce, reset)
      26              : //   - the virtual "Suche" folder node lifecycle
      27              : //   - the three historic "leave search" variants (kept behavior-identical):
      28              : //       exitSearch()            — Esc on results / panel reset / node close
      29              : //       onRealFolderSelected()  — user picked a real folder; the search node
      30              : //                                 and its query survive for later restore
      31              : //       onCommandBarCancelled() — Esc while the bar is open; node survives
      32              : //
      33              : // It communicates with collaborators it was given (cache, controller, models,
      34              : // tree, panel, bar) directly, and with MainWindow exclusively via signals —
      35              : // no back-pointer.
      36              : class SearchCoordinator : public QObject {
      37            2 :   Q_OBJECT
      38              : #ifdef MAILJD_UNIT_TEST
      39              :   friend class TestSearchCoordinator;
      40              :   friend class TestMainWindow;
      41              :   friend class TestSprint59MainWindow;
      42              :   friend class TestMainWindow;
      43              : #endif
      44              : 
      45              : public:
      46              :   struct Deps {
      47              :     MailCache *cache = nullptr;
      48              :     MailController *controller = nullptr;
      49              :     MailListModel *listModel = nullptr;
      50              :     MailFilterProxyModel *proxy = nullptr;
      51              :     FolderTree *folderTree = nullptr;
      52              :     SearchPanel *searchPanel = nullptr;
      53              :     CommandBar *commandBar = nullptr;
      54              :     // 67.A3: snapshot of the currently selected mail as (folderId, uid),
      55              :     // (-1, -1) when nothing is selected. Used to restore the selection
      56              :     // after a search re-run rebuilds the result list (model reset).
      57              :     std::function<QPair<qint64, qint64>()> currentSelection;
      58              :   };
      59              : 
      60              :   explicit SearchCoordinator(const Deps &deps, QObject *parent = nullptr);
      61              : 
      62              :   // Active search mode = a canonical query is set (free text and/or facets).
      63          466 :   bool isSearchMode() const { return !m_lastSearchQuery.isEmpty(); }
      64            2 :   QString lastSearchQuery() const { return m_lastSearchQuery; }
      65            5 :   QString searchNodeQuery() const { return m_searchNodeQuery; }
      66              : 
      67              :   // Folder paths offered as completion in the SearchPanel folder facet.
      68            6 :   void setKnownFolders(const QStringList &paths) { m_knownFolders = paths; }
      69              : 
      70              :   // Run a full search (local FTS + server IMAP SEARCH) for the given raw
      71              :   // query. Shared by the CommandBar submit, the SearchPanel and the "Suche"
      72              :   // node restore.
      73              :   void runSearch(const QString &query);
      74              : 
      75              :   // Cancel a running server search, clear all search state, remove the
      76              :   // "Suche" node and return to the pre-search folder.
      77              :   void exitSearch();
      78              : 
      79              :   // ":search-more" — append the next local FTS page (emits status feedback).
      80              :   void loadMoreLocalResults();
      81              : 
      82              :   // Leave-search variant: a real folder was selected. Search-mode state is
      83              :   // cleared but the "Suche" node and its query survive for later restore.
      84              :   void onRealFolderSelected();
      85              : 
      86              :   // Leave-search variant: Esc pressed while the CommandBar was open in
      87              :   // Search mode. Full UI teardown + pre-search folder restore, but no
      88              :   // server-search cancellation (historic behavior).
      89              :   void onSearchBarEscape();
      90              : 
      91              :   // Leave-search variant: CommandBar cancelled. Cancels the server search
      92              :   // and restores the folder, but the node, panel and keyed status survive
      93              :   // (historic behavior).
      94              :   void onCommandBarCancelled();
      95              : 
      96              :   // CommandBar live quick-search dropdown: query → top-20 local results.
      97              :   void updateQuickResults(const QString &query);
      98            2 :   int quickResultCount() const { return m_quickResults.size(); }
      99              :   MailCache::SearchResult quickResultAt(int index) const;
     100              : 
     101              : signals:
     102              :   void windowTitleChangeRequested(const QString &title);
     103              :   void statusMessage(const QString &message);
     104              :   void keyedStatusMessage(const QString &key, const QString &message,
     105              :                           int timeoutMs);
     106              :   void statusCleared(const QString &key);
     107              :   void mailListFocusRequested();
     108              :   void mailSelectionClearRequested();
     109              :   // 67.A3: re-select this mail after a result-list rebuild (ClearAndSelect
     110              :   // + scroll — handled by MainWindow's reveal helper).
     111              :   void mailRevealRequested(qint64 folderId, qint64 uid);
     112              : 
     113              : private:
     114              :   // Resolve cache search results to display headers: de-duplicates via
     115              :   // Message-Id and prefixes the subject with the folder path.
     116              :   QList<MailHeader> headersForSearchResults(
     117              :       const QList<MailCache::SearchResult> &results);
     118              :   int appendLocalSearchPage(const QString &displayQuery, bool replace);
     119              :   void clearLocalSearchPagination();
     120              :   void resetSearchPanel();
     121              : 
     122              :   Deps m_d;
     123              : 
     124              :   QStringList m_knownFolders;
     125              :   QList<MailCache::SearchResult> m_quickResults;
     126              : 
     127              :   QString m_lastSearchQuery;      // canonical query while search mode active
     128              :   QString m_lastLocalSearchQuery; // parsed FTS query for local pagination
     129              :   MailCache::SearchFilter m_lastSearchFilter;
     130              :   int m_localSearchOffset = 0;
     131              :   bool m_localSearchHasMore = false;
     132              :   QString m_preSearchFolder; // folder to return to on Esc
     133              :   // Raw query backing the "Suche" tree node; kept while the node exists so
     134              :   // the search can be restored even after navigating to a real folder.
     135              :   QString m_searchNodeQuery;
     136              :   QSet<QString> m_searchMessageIds; // result de-dup across local + server
     137              :   QTimer *m_searchDebounce = nullptr; // live-search debounce (SearchPanel)
     138              : };
        

Generated by: LCOV version 2.0-1