Generated reference › API — ICoreEssentials/UI/Widgets
kind: generated#api#icoreessentials-ui-widgets

API — ICoreEssentials/UI/Widgets

The public contract of 34 header(s) under src/ICoreEssentials/UI/Widgets — 34 class/struct definition(s), 597 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.

HeaderDefinesDeclarationsBases
ICoreButton.h0
ICoreComboBox.hICoreComboBox14public ICoreWidget
ICoreCompleter.hICoreCompleter12
ICoreCompletionPopup.hICoreCompletionPopupView3public ICoreListView
ICoreDocumentView.hICoreDocumentView17public ICoreNativeWidget
ICoreHBoxButton.hICoreHBoxButton13public ICoreWidget
ICoreInfoLabel.hICoreInfoLabel4public ICoreWidget
ICoreItemDelegate.hICoreItemRenderContext, ICoreItemDelegate8public ICoreNativeObject
ICoreLabel.h0
ICoreLineEdit.hICoreLineEdit55public ICoreNativeWidget
ICoreListBox.hICoreListBoxItem, ICoreListBox27public ICoreNativeWidget
ICoreListView.hICoreListView1public QListView
ICoreProgressBar.hICoreProgressBar12public ICoreNativeWidget
ICoreRadioButton.hICoreRadioButton9public ICoreNativeWidget
ICoreRichTextEdit.h0
ICoreRotatableArrowIcon.h0
ICoreScrollPane.hICoreScrollPane21public ICoreNativeWidget
ICoreSlider.hICoreSlider8public ICoreNativeWidget
ICoreSpinBox.hICoreSpinBox22public ICoreLineEdit
ICoreSplitter.hICoreSplitter16public ICoreNativeWidget
ICoreStackedWidget.hICoreStackedWidget8public ICoreNativeWidget
ICoreStandardItemImpl.hICoreStandardItem6:Impl : public QStandardItem
ICoreTable.hICoreTable12public ICoreWidget
ICoreTableEntryRow.hICoreTableEntryRow3public ICoreWidget
ICoreTableTitlesRow.hICoreTableTitlesRow6public ICoreWidget
ICoreTableTitlesRowSplitter.hICoreTableTitlesRowSplitter6public ICoreWidget
ICoreTextEdit.hICoreTextEdit33public ICoreNativeWidget
ICoreToggleButton.hICoreToggleButton12public ICoreWidget
ICoreTree.hICoreTreeItem, ICoreTree53public ICoreNativeWidget
ICoreTreeView.hICoreTreeRow, ICoreStandardItem, ICoreTreeView65public ICoreNativeWidget
ICoreTreeViewModel.hICoreTreeViewModel14public ICoreNativeObject
ICoreWidget.hICoreWidget130public ICoreNativeWidget
ICoreWidgetGrid.hICoreWidgetGrid7public ICoreWidget
ICoreWidgetPaintCommands.h0

ICoreButton.h#

src/ICoreEssentials/UI/Widgets/ICoreButton.h

Declares no class of its own — see the file.

ICoreComboBox.h#

src/ICoreEssentials/UI/Widgets/ICoreComboBox.h

ICoreComboBox#

ICoreComboBox.h:21 · class · bases public ICoreWidget · pImpl · 14 declaration(s)

An inline option picker: the chosen option and a pair of arrows, opening a drop-down list styled like ICoreGlobalSearchDialog (rounded raised surface, hairline, drop shadow, themed rows) instead of...

class ICoreComboBox : public ICoreWidget {
public:
    // Mirror of the optionUpdated signal, for clients outside the wrapper zone.
    ICoreSignal<ICoreString> onOptionUpdated;

    // Fixed is the default and is what all thirteen existing call sites get:
    // the value must be one of the offered options and anything else is a bug
    // worth logging. Editable adds a typed value -- the user may enter a name
    // the list does not contain, which is what a "category" field needs, since
    // offering the categories already in use is a convenience rather than a
    // constraint (C21).
    enum class Entry { Fixed, Editable };

    explicit ICoreComboBox(ICoreNativeWidget* parent = nullptr);
    ICoreComboBox(Entry entry, ICoreNativeWidget* parent = nullptr);

    [[nodiscard]] Entry entry() const;

    // In Editable mode `chosenOption` need NOT appear in `availableOption`.
    void loadOptions(const std::string& chosenOption, const std::vector<std::string>& availableOption);

    void reset();

    void onOptionUpdate();

    std::string getChosenOption();

    ~ICoreComboBox() override;

protected:
    void paintContent(ICorePainter& painter) override;
    void pointerEntered() override;
    void pointerLeft() override;
    bool mousePressed(const ICoreMouseEvent& event) override;
    void resized(const ICoreSizeF& newSize, const ICoreSizeF& oldSize) override;

public:
    [[nodiscard]] ICoreSizeF preferredSize() const override;

protected:

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreCompleter.h#

src/ICoreEssentials/UI/Widgets/ICoreCompleter.h

ICoreCompleter#

ICoreCompleter.h:39 · class · pImpl · 12 declaration(s)

Live name completion for a text field or code editor: the popup list, the prefix filtering behind it, and which entry is currently picked.

class ICoreCompleter {
public:
    // `host` is the widget the popup positions itself against and whose key
    // events walk the list. Not owned.
    explicit ICoreCompleter(ICoreNativeWidget* host);
    ~ICoreCompleter();

    ICoreCompleter(const ICoreCompleter&) = delete;
    ICoreCompleter& operator=(const ICoreCompleter&) = delete;

    // The names offered. Replacing them re-filters against the current prefix
    // the next time showFor() runs.
    void setEntries(const ICoreStringList& entries);

    // Entries fetched on first use instead of up front, for a catalog that is
    // still empty when the field is built. Called at most once, by showFor(),
    // and only while the list is still empty.
    void setEntrySource(std::function<ICoreStringList()> source);

    // How many entries the popup shows before it scrolls. Defaults to 8.
    void setMaxVisibleEntries(int count);

    // Filter to the entries starting with `prefix` (case-insensitively) and
    // show the popup at the host's caret. An empty prefix, or a prefix nothing
    // matches, hides the popup instead.
    //
    // Returns whether the popup is showing afterwards. Always clears the
    // highlighted entry: see the class comment.
    //
    // `showOnEmptyPrefix` offers the whole list instead of hiding when the
    // prefix is empty -- what an explicit "show me the completions" gesture
    // (Ctrl+Space in the script editor) means, as opposed to typing.
    bool showFor(const ICoreString& prefix, bool showOnEmptyPrefix = false);

    // Same, but anchored to `anchor` in the host's coordinates rather than to
    // the host widget itself. A multi-line editor needs it: the list belongs
    // under the CARET, which is somewhere inside a widget that may be the whole
    // window tall.
    //
    // The anchor's WIDTH is ignored -- the popup is widened to fit its longest
    // entry plus its scroll bar. A caller passing a caret rect cannot know that
    // width, and the two call sites that needed it were both reaching into the
    // popup's item view to compute it by hand.
    bool showFor(const ICoreString& prefix, const ICoreRect& anchor,
                 bool showOnEmptyPrefix = false);

    void hidePopup();
    [[nodiscard]] bool isPopupVisible() const;

    // The entry the user has arrowed onto, or "" when nothing is picked yet.
    [[nodiscard]] ICoreString highlightedEntry() const;

    // Whether there is a pick for Enter/Tab to accept -- i.e. the popup is up
    // AND the user has actually walked onto an entry. The question every key
    // handler asks; spelled once so no call site has to remember it is two
    // conditions rather than one.
    [[nodiscard]] bool hasHighlightedEntry() const;

    // Raised as the user walks the popup. This is what makes an entry "picked".
    ICoreSignal<ICoreString> onHighlighted;

    // Raised when an entry is chosen -- clicked, or Enter while the popup owns
    // the key. The client splices the name into its own line.
    ICoreSignal<ICoreString> onActivated;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreCompletionPopup.h#

src/ICoreEssentials/UI/Widgets/ICoreCompletionPopup.h

Shared pieces of the console's live suggestion list, so the Quick Code prompt (ICoreCommandBar) and the Script Runner editor (ICoreScriptCodeEditor) look and behave as one feature: same surface, same rules for where a name may be completed.

ICoreCompletionPopupView#

ICoreCompletionPopup.h:26 · class · bases public ICoreListView · 3 declaration(s)

The list's surface, painted the way ICoreGlobalSearchDialog paints the global search panel: a raised panel behind one hairline, rounded.

class ICoreCompletionPopupView : public ICoreListView {
public:
    ICoreCompletionPopupView();

    // Call once the completer has re-parented this into its popup window
    // (QCompleter::setPopup resets the window flags).
    void makeWindowTranslucent();

protected:
    void paintEvent(QPaintEvent* event) override;
};
};

ICoreDocumentView.h#

src/ICoreEssentials/UI/Widgets/ICoreDocumentView.h

ICoreDocumentView#

ICoreDocumentView.h:22 · class · final · bases public ICoreNativeWidget · pImpl · 17 declaration(s)

A read-only pane of formatted text that scrolls: the library card's body, and anything else that shows HTML rather than accepting typing.

class ICoreDocumentView final : public ICoreNativeWidget {
public:
    explicit ICoreDocumentView(ICoreNativeWidget* parent = nullptr);
    ~ICoreDocumentView() override;

    ICoreDocumentView(const ICoreDocumentView&) = delete;
    ICoreDocumentView& operator=(const ICoreDocumentView&) = delete;

    // No frame of its own -- the owner draws whatever border there is.
    void setChromeless(bool chromeless);

    // False makes the text unselectable, i.e. purely something to read.
    void setSelectable(bool selectable);

    void setLinksClickable(bool clickable);

    void setScrollBars(bool vertical, bool horizontal);

    // CSS applied to the HTML this view renders. Distinct from setStyleSheet:
    // this styles the DOCUMENT, that styles the WIDGET around it.
    void setDocumentCss(const ICoreString& css);

    void setDocumentMargin(double margin);

    void setHtml(const ICoreString& html);

    // Lay the document out at this width, so contentHeight() can be asked.
    void setContentWidth(double width);
    [[nodiscard]] double contentHeight() const;

    // What a vertical scroll bar would take from the content width.
    [[nodiscard]] int verticalScrollBarWidth() const;

    void scrollToTop();

    // The pane's own QSS. Inherited before; explicit now.
    void setStyleSheet(const ICoreString& styleSheet);

    ICoreNativeHandle nativeWidgetHandle() const override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreHBoxButton.h#

src/ICoreEssentials/UI/Widgets/ICoreHBoxButton.h

ICoreHBoxButton#

ICoreHBoxButton.h:17 · class · bases public ICoreWidget · pImpl · 13 declaration(s)

class ICoreHBoxButton : public ICoreWidget {
public:
    explicit ICoreHBoxButton(ICoreNativeWidget* parent = nullptr);

    void setText(const std::string& text) const;
    void setIcon(const ICoreIcon& icon);
    void setIconSize(const ICoreSizeF& size);
    void setHeight(const double& height);
    void setWidth(const double& width);
    void setLabelXPos(const int& xPos);
    void setIconPos(const int& newIconPosX, const int& newIconPosY);
    void setHoldHoverStyle(const bool& holdHoverStyle);

    // Out of line: m_hoverAnimation's unique_ptr needs the complete type there.
    ~ICoreHBoxButton() override;

protected:
    // The hover treatment is painted rather than styled, so it can animate and
    // carry the accent edge. See the paint order in the .cpp.
    void paintContent(ICorePainter& painter) override;
    void pointerEntered() override;
    void pointerLeft() override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreInfoLabel.h#

src/ICoreEssentials/UI/Widgets/ICoreInfoLabel.h

ICoreInfoLabel#

ICoreInfoLabel.h:16 · class · bases public ICoreWidget · pImpl · 4 declaration(s)

class ICoreInfoLabel : public ICoreWidget {
public:
    explicit ICoreInfoLabel(ICoreNativeWidget* parent);

    // `technique` places the card relative to objectUnderCursor: "middleRight",
    // "aboveCenter", "belowLeft", or anything else for the default below-right.
    //
    // `prominentTitle` is opt-in and off by default, so every existing caller
    // keeps the uniform toolbar-tooltip look. Turning it on draws the title at
    // the theme's TITLE size and the description in the MONO face -- the shape
    // a card wants when its title is a name and its description is a path, not
    // a sentence. It is a per-call flag rather than a setter because this
    // widget is a per-window singleton shared by every hover site in the app:
    // state left on it would leak into the next caller's card.
    void showInfoLabel(const ICoreString &title, const ICoreString &description, const ICoreNativeWidget* objectUnderCursor, const ICoreString &technique, double delayDuration, bool prominentTitle = false);
    void hideInfoLabel();

    ~ICoreInfoLabel() override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreItemDelegate.h#

src/ICoreEssentials/UI/Widgets/ICoreItemDelegate.h

ICoreItemRenderContext#

ICoreItemDelegate.h:14 · struct · 0 declaration(s)

Everything a row-painting override needs to know, as ICore values.

struct ICoreItemRenderContext {
public:
    ICoreRect rect;
    bool selected = false;
    bool hovered = false;
    int row = -1;
    int column = -1;
    ICoreString text;
    ICoreString tag;

    // The colour the row was given for its text (what setForeground put on the
    // item). INVALID when the row was given none -- an ICoreColor that no call
    // site set, which is the same thing the model says by holding nothing.
    ICoreColor foreground;
};
};

ICoreItemDelegate#

ICoreItemDelegate.h:51 · class · bases public ICoreNativeObject · pImpl · 8 declaration(s)

ICoreItemDelegate -- custom row painting for the item views.

class ICoreItemDelegate : public ICoreNativeObject {
public:
    ICoreItemDelegate();
    ~ICoreItemDelegate() override;

    ICoreItemDelegate(const ICoreItemDelegate&) = delete;
    ICoreItemDelegate& operator=(const ICoreItemDelegate&) = delete;

    // How a view is handed this delegate -- ICoreTree::setItemDelegate resolves
    // it through here. The delegate is NOT owned by the view: hold the wrapper
    // as a member for at least as long as the view that paints with it.
    ICoreNativeHandle nativeObjectHandle() const override;

protected:
    // Return true if the row was painted; false falls back to the default
    // rendering (so a delegate can special-case only some rows).
    virtual bool paintItem(ICorePainter& painter, const ICoreItemRenderContext& context);

    // A zero size means "use the default".
    virtual ICoreSizeF itemSizeHint(const ICoreItemRenderContext& context);

    // The colour a SELECTED row's text should be drawn in, asked just before
    // the default painting runs. An invalid return -- the default -- leaves the
    // style's own highlighted-text colour in place.
    //
    // This is the one thing paintItem cannot express. The style paints selected
    // text in one flat colour for the whole view, so a view whose rows carry
    // meaning in their colour (a log's severities) loses it the moment a block
    // is selected; recovering that through paintItem would mean redrawing
    // indent, branch strip, icon and text by hand, i.e. reimplementing the
    // selection itself. Answering with the row's own colour changes the colour
    // and nothing else.
    virtual ICoreColor selectedTextColor(const ICoreItemRenderContext& context);

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreLabel.h#

src/ICoreEssentials/UI/Widgets/ICoreLabel.h

Declares no class of its own — see the file.

ICoreLineEdit.h#

src/ICoreEssentials/UI/Widgets/ICoreLineEdit.h

ICoreLineEdit#

ICoreLineEdit.h:26 · class · bases public ICoreNativeWidget · pImpl · 55 declaration(s)

P5.11: converted.

class ICoreLineEdit : public ICoreNativeWidget {
public:

    // ⚠ Takes ICoreFont, and deliberately does NOT re-export a QFont overload.
    // P7.6 converted ICoreFont, so it no longer converts to QFont and every
    // call site passing one needs a sink that speaks the wrapper.
    void setFont(const ICoreFont& font);

    // The Impl QLineEdit -- out of line because the header only
    // forward-declares Impl. Was `this` while the Qt base existed.
    ICoreNativeHandle nativeWidgetHandle() const override;

    // Which of the field's own chrome this instance wears. Field is the default
    // and is everything described above; None paints and styles NOTHING, so the
    // widget is behaviourally a plain QLineEdit.
    //
    // None exists for the fields that sit INSIDE something that already owns the
    // chrome -- ICoreSearchTextBox lives in a search bar that draws the border
    // and the ground, ICoreNavBarLineEdit carries getStyle_DirectoryTextField().
    // Painting the field's own rounded border on top of those would show two
    // borders, so those subclasses opt out rather than stay on QLineEdit and
    // leave the library with two unrelated line-edit bases.
    //
    // Opt-IN, exactly like ICoreWidget::Surface::None (C1): the default is the
    // behaviour every existing call site already has, so adopting the component
    // somewhere new can never silently restyle it.
    enum class Chrome { Field, None };

    // Q1.2: one parent spelling. The QWidget* twin and the std::nullptr_t
    // delegate that broke their tie both went; with a single pointer
    // overload a literal nullptr is unambiguous and can carry the default.
    explicit ICoreLineEdit(ICoreNativeWidget *parent = nullptr, Chrome chrome = Chrome::Field);
    // Mirrors QLineEdit(text, parent) so call sites that were plain QLineEdits
    // swap over without splitting the construction into two lines.
    explicit ICoreLineEdit(const ICoreString &text, ICoreNativeWidget *parent = nullptr);

    [[nodiscard]] Chrome chrome() const;

    // Both spellings kept as members now that the `using QLineEdit::…`
    // re-export died with the base. The ICore enum values are pinned to the
    // toolkit's by the static_asserts in ICoreInputEnumsVerify.cpp.
    // Q3.2 deleted the Qt::FocusPolicy twin; this is the only spelling now.
    void setFocusPolicy(ICoreFocusPolicy policy);

    void setSizeBehavior(ICoreSizeBehavior horizontal, ICoreSizeBehavior vertical);

    // See a key BEFORE the field acts on it. Return true to consume it, false to
    // let the field have it -- the same "handled?" convention ICoreWidget's hooks
    // use.
    //
    // Runs from the Impl's event(), NOT keyPressEvent, which is the only level
    // that can see Tab: focus traversal eats Tab before keyPressEvent is ever
    // reached, so an interceptor installed lower could not implement
    // Tab-completion.
    //
    // This is what an owner reaches for instead of installing an event filter on
    // the field from outside the wrapper zone: a filter costs the owner a
    // QObject/QEvent signature it otherwise never needs, and it sees the key
    // only as an untyped QEvent it has to cast itself. The history recall and
    // the Ctrl+C interrupt in the Terminal panel are both this.
    void setKeyInterceptor(std::function<bool(const ICoreKeyEvent&)> interceptor);

    // Mirrors of the QLineEdit signals client code subscribes to.
    ICoreSignal<ICoreString> onTextChanged;
    // NOT the same as onTextChanged: this fires only for edits the USER made,
    // never for a programmatic setText(). Anything that reacts by re-deriving
    // state from the field -- a completion prefix, say -- wants this one, or a
    // setText() of its own re-enters it.
    ICoreSignal<ICoreString> onTextEdited;
    ICoreSignal<> onReturnPressed;
    ICoreSignal<> onEditingFinished;
    // NOT the same moment as onEditingFinished: that one also fires on Return,
    // while this is the caret genuinely leaving. The fields that commit their
    // value when the user clicks away subscribe here.
    ICoreSignal<> onFocusLost;

    double borderOpacity() const;
    void setBorderOpacity(double opacity);

    // The field's ground. Defaults to the field.background token and follows a
    // theme switch on its own; pass a colour to put this one field on a
    // different ground (the read-only cells do), or an invalid ICoreColor to hand
    // it back to the token.
    //
    // It is a colour rather than a style sheet because the ground is painted
    // here now: a style sheet background is a RECTANGLE, and this field's
    // border is rounded, so the fill's square corners sat outside the arc --
    // four little tabs of field colour poking out of every field in the app.
    // Painting it as the same rounded path the border strokes is the only way
    // the two can agree.
    void setFieldBackground(const ICoreColor& color);

    // ------------------------------------------------------------------
    // Facade members now that the QLineEdit base is gone. Seeded with the
    // text/selection/state operations the tier itself needs; the rest were
    // enumerated by the flip's harvest, exactly as ICoreLabel's were.
    // ------------------------------------------------------------------
    void setText(const ICoreString& text);
    [[nodiscard]] ICoreString text() const;
    void clear();
    void selectAll();
    void setPlaceholderText(const ICoreString& text);
    void setReadOnly(bool readOnly);
    [[nodiscard]] bool isReadOnly() const;
    [[nodiscard]] bool hasFocus() const;
    void setFocus();
    void setFocus(ICoreFocusReason reason);
    void update();
    void setEnabled(bool enabled);
    [[nodiscard]] bool isEnabled() const;
    // Q2.2: was setCursor(const QCursor&). Renamed rather than retyped to
    // ICoreCursor, because ICoreWidget, ICoreButton and ICoreGraphicsObject all
    // already publish this operation as setCursorShape() and §9 says take the
    // existing name. Same one-line body those three use.
    //
    // ⚠ A grep for `->setCursor(` found NO callers and that was WRONG: the one
    // caller is ICoreSpinBox::mouseMoved, which derives from this class and
    // calls it UNQUALIFIED, so the receiver never appears in the pattern. Only
    // the compiler found it. That is one of the five documented ways a
    // call-site survey lies at a wrapper seam -- do not size one of these swaps
    // from grep alone.
    void setCursorShape(ICoreCursorShape shape);
    void setToolTip(const ICoreString& tip);
    void setStyleSheet(const ICoreString& styleSheet);
    void setMinimumHeight(int height);
    void setVisible(bool visible);
    [[nodiscard]] int width() const;
    [[nodiscard]] int height() const;
    void setFixedHeight(int height);
    void setFixedWidth(int width);
    void setObjectName(const ICoreString& name);
    void setMinimumWidth(int width);
    void setTextMargins(int left, int top, int right, int bottom);
    // Where the text sits inside the field. Same enum and same spelling
    // ICoreLabel::setAlignment takes; the values are pinned to the toolkit's by
    // the static_asserts in ICoreInputEnumsVerify.cpp.
    void setAlignment(ICoreAlignment alignment);
    void setCursorPosition(int position);
    [[nodiscard]] int cursorPosition() const;
    void setClearButtonEnabled(bool enabled);
    [[nodiscard]] bool hasSelectedText() const;
    [[nodiscard]] ICoreFont font() const;

    // Unscoped on purpose, matching QLineEdit's spelling at the one call site
    // (ICoreCopilotConnectionSettings writes ICoreLineEdit::Password). Pinned
    // against the toolkit's values by static_asserts in the .cpp.
    enum EchoMode { Normal = 0, NoEcho = 1, Password = 2, PasswordEchoOnEdit = 3 };
    void setEchoMode(EchoMode mode);

    // Out of line: the unique_ptr member's deleter needs Impl complete, and
    // this header only forward-declares it.
    virtual ~ICoreLineEdit();

protected:
    // ------------------------------------------------------------------
    // Hook surface (P2.9d-2's shape): subclasses override THESE. The Qt
    // handlers that call them live in the Impl now -- a subclass cannot even
    // spell the Qt signatures. Contracts match ICoreWidget's hooks: the
    // bool hooks answer "handled?" (true consumes the event, false forwards
    // it to the toolkit), paintContent runs after the field chrome is drawn
    // (both Chrome modes), focusGained/focusLost run after the base handler
    // repaints and BEFORE the onFocusLost mirror fires -- ICoreSpinBox's
    // commit-on-blur depends on running ahead of the mirror's subscribers.
    // ------------------------------------------------------------------
    virtual void paintContent(ICorePainter& painter);
    virtual bool mousePressed(const ICoreMouseEvent& event);
    virtual bool mouseReleased(const ICoreMouseEvent& event);
    virtual bool mouseMoved(const ICoreMouseEvent& event);
    virtual bool mouseDoubleClicked(const ICoreMouseEvent& event);
    virtual void pointerLeft();
    virtual bool keyPressed(const ICoreKeyEvent& event);
    virtual bool wheelScrolled(const ICoreWheelEvent& event);
    virtual void focusGained(const ICoreFocusEvent& event);
    virtual void focusLost(const ICoreFocusEvent& event);

    // The Impl QLineEdit, for SUBCLASSES (all wrapper zone) whose behaviour
    // genuinely needs toolkit API the facade does not carry -- the validator,
    // style hints. Client code outside the zone never sees this.
    //
    // ⚠ H4.6 LEFT THIS ONE VIOLATION STANDING, DELIBERATELY, AND THE ROW LANDS
    // AT 1 RATHER THAN 0. It is a protected NON-VIRTUAL, which exemption 2 does
    // not cover, so the rule's only answers are publish or delete -- and unlike
    // ICoreTextEdit::nativeTextEdit(), ICoreRichTextEdit::nativeRichTextEdit()
    // and ICoreWindow::nativeWindow(), all of which had ZERO callers and were
    // deleted on their own rows, this one has SEVEN live callers in
    // ICoreSpinBox.cpp (the QIntValidator it installs, two SH_SpinBox style
    // hints, and a themed connect). Neither answer is available to one header:
    //
    //   - publishing it puts `QLineEdit*` on the PUBLIC contract of a wrapper
    //     whose whole purpose is that its header names no toolkit type;
    //   - deleting it means re-expressing those seven reaches as named
    //     operations, which is a redesign of ICoreSpinBox -- row H4.2, claimed
    //     by another session and mid-flight in this same directory.
    //
    // Making it `virtual` would buy exemption 2's silence without changing
    // anything real, which is exactly the exemption-shopping the guidelines
    // forbid, so it was not done. This is H4.45's shape at one-violation
    // scale: whoever owns ICoreSpinBox should bring the owner a choice rather
    // than pick one here. See the H4 notes on HEADER_SURFACE.md.
    QLineEdit* nativeLineEdit() const;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreListBox.h#

src/ICoreEssentials/UI/Widgets/ICoreListBox.h

ICoreListBoxItem#

ICoreListBox.h:44 · class · pImpl · 10 declaration(s)

A flat list of selectable rows, wrapping QListWidget.

class ICoreListBoxItem {
public:
    ICoreListBoxItem();
    explicit ICoreListBoxItem(const ICoreString& text);
    ~ICoreListBoxItem();

    ICoreListBoxItem(const ICoreListBoxItem&) = delete;
    ICoreListBoxItem& operator=(const ICoreListBoxItem&) = delete;

    void setLabel(const ICoreString& text);
    ICoreString label() const;

    void setIcon(const ICoreIcon& icon);

    void setTag(const ICoreString& tag);
    ICoreString tag() const;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreListBox#

ICoreListBox.h:74 · class · final · bases public ICoreNativeWidget · pImpl · 17 declaration(s)

class ICoreListBox final : public ICoreNativeWidget {
public:
    explicit ICoreListBox(ICoreNativeWidget* parent = nullptr);
    ~ICoreListBox() override;

    ICoreListBox(const ICoreListBox&) = delete;
    ICoreListBox& operator=(const ICoreListBox&) = delete;

    // Takes ownership of `item`'s toolkit half. Passing an item that is
    // already in a view does nothing -- it has no half left to give.
    void addRow(ICoreListBoxItem* item);
    void addRow(const ICoreString& text);

    // ⚠ Both may return nullptr: for an out-of-range index, and for a row this
    // library did not create. See the ownership note above.
    ICoreListBoxItem* row(int index) const;
    ICoreListBoxItem* currentRow() const;

    int rowCount() const;
    void clearRows();
    void setCurrentRow(int index);

    void setFont(const ICoreFont& font);
    void setStyleSheet(const ICoreString& styleSheet);
    void setHorizontalScrollBarVisibility(ICoreScrollBarPolicy policy);
    void setTextElideMode(ICoreTextElide mode);

    // Suppresses the ICoreSignals below while a caller repopulates the list.
    // It is the toolkit's blockSignals underneath, which is what the one call
    // site used: the signals here are fired from lambdas connected to the Qt
    // ones, so blocking those stops these too.
    void setSignalsBlocked(bool blocked);

    ICoreNativeHandle nativeWidgetHandle() const override;

    ICoreSignal<int> onCurrentRowChanged;
    ICoreSignal<ICoreListBoxItem*> onRowDoubleClicked;
    ICoreSignal<ICoreListBoxItem*> onRowClicked;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreListView.h#

src/ICoreEssentials/UI/Widgets/ICoreListView.h

ICoreListView#

ICoreListView.h:21 · class · bases public QListView · 1 declaration(s)

⚠ FROZEN QT LAYER (P8.5) — DO NOT EDIT, DO NOT ADD MEMBERS.

class ICoreListView : public QListView {
protected:
    // Base only — this layer is never instantiated bare.
    ICoreListView() = default;
};
};

ICoreProgressBar.h#

src/ICoreEssentials/UI/Widgets/ICoreProgressBar.h

ICoreProgressBar#

ICoreProgressBar.h:17 · class · final · bases public ICoreNativeWidget · pImpl · 12 declaration(s)

Determinate/indeterminate progress.

class ICoreProgressBar final : public ICoreNativeWidget {
public:
    explicit ICoreProgressBar(ICoreNativeWidget* parent = nullptr);
    ~ICoreProgressBar() override;

    ICoreProgressBar(const ICoreProgressBar&) = delete;
    ICoreProgressBar& operator=(const ICoreProgressBar&) = delete;

    void setRange(int minimum, int maximum);
    void setValue(int value);
    void setTextVisible(bool visible);

    void setIndeterminate(bool indeterminate);

    void setLabel(const ICoreString& format);

    void setFixedWidth(int width);
    void setFixedHeight(int height);

    ICoreNativeHandle nativeWidgetHandle() const override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreRadioButton.h#

src/ICoreEssentials/UI/Widgets/ICoreRadioButton.h

ICoreRadioButton#

ICoreRadioButton.h:21 · class · final · bases public ICoreNativeWidget · pImpl · 9 declaration(s)

A radio button that paints its own indicator from the theme tokens, the way ICoreLineEdit and ICoreSpinBox paint their field.

class ICoreRadioButton final : public ICoreNativeWidget {
public:
    explicit ICoreRadioButton(ICoreNativeWidget* parent = nullptr);
    explicit ICoreRadioButton(const ICoreString& text, ICoreNativeWidget* parent = nullptr);
    ~ICoreRadioButton() override;

    ICoreRadioButton(const ICoreRadioButton&) = delete;
    ICoreRadioButton& operator=(const ICoreRadioButton&) = delete;

    void setChecked(bool checked);
    [[nodiscard]] bool isChecked() const;

    void setText(const ICoreString& text);

    // Mirror of the Qt toggled signal, so client code subscribes without
    // QObject::connect: notchRadio->onToggled.connect(m_signals, [this](bool on){ ... });
    // Carries the new checked state, exactly as toggled(bool) did -- including
    // programmatic setChecked and the auto-uncheck of the sibling that just
    // lost the group.
    ICoreSignal<bool> onToggled;

    ICoreNativeHandle nativeWidgetHandle() const override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreRichTextEdit.h#

src/ICoreEssentials/UI/Widgets/ICoreRichTextEdit.h

Declares no class of its own — see the file.

ICoreRotatableArrowIcon.h#

src/ICoreEssentials/UI/Widgets/ICoreRotatableArrowIcon.h

Declares no class of its own — see the file.

ICoreScrollPane.h#

src/ICoreEssentials/UI/Widgets/ICoreScrollPane.h

ICoreScrollPane#

ICoreScrollPane.h:34 · class · final · bases public ICoreNativeWidget · pImpl · 21 declaration(s)

ICoreScrollPane -- the editor's scrolling container.

class ICoreScrollPane final : public ICoreNativeWidget {
public:
    explicit ICoreScrollPane(ICoreNativeWidget* parent);
    ~ICoreScrollPane() override;

    ICoreScrollPane(const ICoreScrollPane&) = delete;
    ICoreScrollPane& operator=(const ICoreScrollPane&) = delete;

    // The scrolled content. Takes ownership the way QScrollArea::setWidget
    // does: the pane deletes it, and a widget handed here must not also be
    // parented elsewhere.
    void setWidget(ICoreNativeWidget* content);

    // Whether the content is resized to fill the pane. On by default -- the
    // constructor sets it -- so the four call sites that spell it are either
    // turning it off or restating it.
    void setWidgetResizable(bool resizable);

    // Scrolls `child` into view. All five call sites pass both margins, so
    // neither has a default here; Qt's own 50/50 would be a number nobody in
    // this tree has ever asked for.
    void ensureWidgetVisible(ICoreNativeWidget* child, int xMargin, int yMargin);

    void disableHorizontalScrolling();
    void disableVerticalScrolling();

    // Forces the horizontal bar to exist even when the content fits. The tab
    // strip pairs this with setHorizontalScrollBarHidden(true): the bar has to
    // be present for the pane to scroll sideways, and invisible because a bar
    // under the tab row would be a second line under a row that already has
    // one. Spelled as its own method because "always on" and "off" are the two
    // policies this tree uses and neither is the Qt default.
    void keepHorizontalScrollBarEnabled();

    // Draws a themed hairline around the pane, using the same field border
    // token as ICoreLineEdit / ICoreTextEdit so a bordered pane and a bordered
    // field read as the same family. Off by default — most panes sit flush
    // inside a panel, where a border would only box in nothing.
    void setBordered(bool bordered);

    // Padding between the pane's edge and the scrolled content, in px. Set on
    // the viewport rather than the content widget's layout, so a caller does
    // not have to reach into whatever it happened to put inside.
    void setContentPadding(int padding);

    // Collapses the horizontal scrollbar to nothing while leaving it ENABLED,
    // so the pane still scrolls sideways by wheel or by keyboard.
    //
    // It lives here rather than in a stylesheet at the call site because
    // applyPaneStyle() rewrites the whole sheet on every theme switch (Qt
    // stylesheets replace, they do not merge) -- a caller's own rule would
    // survive exactly until the first Light/Dark switch.
    void setHorizontalScrollBarHidden(bool hidden);

    // Scrolls the content sideways by `pixels` (negative scrolls left), and
    // answers whether there was a horizontal bar to scroll. For the panes that
    // turn a vertical wheel into horizontal travel -- a tab strip, a filmstrip.
    bool scrollHorizontallyBy(int pixels);

    // Jump to the end of the content -- what a transcript does after an append.
    void scrollToBottom();

    // ---- what replaced viewport() -----------------------------------------

    // Gives the scrolled area an opaque ground in `color`.
    //
    // ⚠ PRESERVED DIVERGENCE, DO NOT "FIX": this sets the palette's Window
    // role, and a scroll area gives its viewport the Base role -- so on this
    // widget it paints nothing and always has. The three call sites have been
    // inert since they were written. That is exactly what the free helper they
    // used did, so it is what this does; making them suddenly take effect is a
    // visual change, not a port, and belongs to whoever owns that look.
    void fillViewportBackground(const ICoreColor& color);

    // Whether the scrolled area paints its own ground at all. One caller turns
    // it off so a themed frame behind the pane shows through.
    void setViewportAutoFill(bool autoFill);

    void setMinimumHeight(int height);
    void setFixedHeight(int height);
    void setVisible(bool visible);

    ICoreNativeHandle nativeWidgetHandle() const override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreSlider.h#

src/ICoreEssentials/UI/Widgets/ICoreSlider.h

ICoreSlider#

ICoreSlider.h:17 · class · final · bases public ICoreNativeWidget · pImpl · 8 declaration(s)

A value slider.

class ICoreSlider final : public ICoreNativeWidget {
public:
    explicit ICoreSlider(ICoreNativeWidget* parent = nullptr);
    ~ICoreSlider() override;

    ICoreSlider(const ICoreSlider&) = delete;
    ICoreSlider& operator=(const ICoreSlider&) = delete;

    void setRange(int minimum, int maximum);
    void setValue(int value);
    [[nodiscard]] int value() const;

    // Carries the new value, exactly as QSlider::valueChanged(int) did.
    ICoreSignal<int> onValueChanged;

    ICoreNativeHandle nativeWidgetHandle() const override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreSpinBox.h#

src/ICoreEssentials/UI/Widgets/ICoreSpinBox.h

ICoreSpinBox#

ICoreSpinBox.h:48 · class · bases public ICoreLineEdit · pImpl · 22 declaration(s)

An integer field with up/down chevrons, wearing the app's own field styling.

class ICoreSpinBox : public ICoreLineEdit {
public:
    // Q1.2: one parent spelling. The QWidget* twin and the std::nullptr_t
    // delegate that broke their tie both went; with a single pointer
    // overload a literal nullptr is unambiguous and can carry the default.
    explicit ICoreSpinBox(ICoreNativeWidget* parent = nullptr);
    ~ICoreSpinBox() override;

    [[nodiscard]] int value() const;
    [[nodiscard]] int minimum() const;
    [[nodiscard]] int maximum() const;
    [[nodiscard]] int singleStep() const;

    // No sizeHint() of its own: the chevrons live inside the right text margin,
    // and QLineEdit's hint already counts that margin in.

    // Same names and semantics as QSpinBox's, so call sites read unchanged.
    // (Were `public slots:` while the metaobject existed; nothing connected to
    // them by name, so the label was cost without a consumer.)
    // Out-of-range values are clamped, and valueChanged is emitted whenever the
    // value actually moves -- typed, stepped or set from code.
    void setValue(int value);
    void setRange(int minimum, int maximum);
    void setMinimum(int minimum);
    void setMaximum(int maximum);
    void setSingleStep(int step);
    void stepBy(int steps);

    // The one notification this class emits. Was a Qt signal + this mirror;
    // the audit at the base's flip found zero Qt-signal subscribers, so the
    // mirror is the whole mechanism now.
    ICoreSignal<int> onValueChanged;

protected:
    // P5.11 prep: these override ICoreLineEdit's HOOK surface, not the Qt
    // handlers -- the base translates and forwards, so the flip never touches
    // this class again.
    void paintContent(ICorePainter& painter) override;
    bool mousePressed(const ICoreMouseEvent& event) override;
    bool mouseReleased(const ICoreMouseEvent& event) override;
    bool mouseMoved(const ICoreMouseEvent& event) override;
    bool mouseDoubleClicked(const ICoreMouseEvent& event) override;
    void pointerLeft() override;
    bool keyPressed(const ICoreKeyEvent& event) override;
    bool wheelScrolled(const ICoreWheelEvent& event) override;
    void focusGained(const ICoreFocusEvent& event) override;
    void focusLost(const ICoreFocusEvent& event) override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreSplitter.h#

src/ICoreEssentials/UI/Widgets/ICoreSplitter.h

ICoreSplitter#

ICoreSplitter.h:26 · class · final · bases public ICoreNativeWidget · pImpl · 16 declaration(s)

User-resizable panes.

class ICoreSplitter final : public ICoreNativeWidget {
public:
    explicit ICoreSplitter(ICoreNativeWidget* parent = nullptr);
    ICoreSplitter(ICoreOrientation orientation, ICoreNativeWidget* parent = nullptr);
    ~ICoreSplitter() override;

    // Non-copyable: this owns a live toolkit object with a parent-child
    // lifetime, and there is no meaningful second one.
    ICoreSplitter(const ICoreSplitter&) = delete;
    ICoreSplitter& operator=(const ICoreSplitter&) = delete;

    // --- pane sizing -------------------------------------------------------

    // Sizes cross the boundary as std::vector<int> rather than QList<int>.
    void setPaneSizes(const std::vector<int>& sizes);
    std::vector<int> paneSizes() const;

    // How the pane at `index` shares out space the splitter gains as it grows.
    // 0 means "keep your width"; the call site uses that to pin an explorer
    // pane while the editor beside it takes the slack.
    void setStretchFactor(int index, int stretch);

    // --- children ----------------------------------------------------------

    // Append a pane. Takes ownership in the toolkit sense: the widget is
    // reparented to this splitter.
    void addWidget(ICoreNativeWidget* widget);

    // Insert a pane at `index`, shifting the rest right.
    void insertWidget(int index, ICoreNativeWidget* widget);

    // How many panes the splitter holds.
    int paneCount() const;

    // --- appearance --------------------------------------------------------

    void setStyleSheet(const ICoreString& styleSheet);

    void setVisible(bool visible);
    void show();
    void hide();

    // --- signals -----------------------------------------------------------

    ICoreSignal<> onPaneResized;

    // --- boundary ----------------------------------------------------------

    ICoreNativeHandle nativeWidgetHandle() const override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreStackedWidget.h#

src/ICoreEssentials/UI/Widgets/ICoreStackedWidget.h

ICoreStackedWidget#

ICoreStackedWidget.h:14 · class · final · bases public ICoreNativeWidget · pImpl · 8 declaration(s)

One-visible-at-a-time pages.

class ICoreStackedWidget final : public ICoreNativeWidget {
public:
    explicit ICoreStackedWidget(ICoreNativeWidget* parent = nullptr);
    ~ICoreStackedWidget() override;

    ICoreStackedWidget(const ICoreStackedWidget&) = delete;
    ICoreStackedWidget& operator=(const ICoreStackedWidget&) = delete;

    // Insert a page at `index`. The page is reparented onto this stack.
    void insertPage(int index, ICoreNativeWidget* page);

    void setCurrentIndex(int index);
    [[nodiscard]] int currentIndex() const;

    ICoreSignal<int> onCurrentChanged;

    ICoreNativeHandle nativeWidgetHandle() const override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreStandardItemImpl.h#

src/ICoreEssentials/UI/Widgets/ICoreStandardItemImpl.h

ICoreStandardItem's toolkit half, as an IMPL-SIDE header.

⚠ This is not part of the public surface and must not be included from one. It exists because TWO wrapper .cpp files need the Impl complete: ICoreTreeView.cpp defines and resolves it, and ICoreTreeViewModel.cpp has to upcast a released Impl* to QStandardItem* when appendRootRow() takes ownership. A private nested class defined inside a single .cpp cannot be upcast from another translation unit -- the type is incomplete there -- and that shows up as "no matching member function for call to appendRow", which reads like a signature problem rather than a visibility one.

Same precedent and same reasoning as ICoreAnimationAccess.h (P3.3): the cast lives in an impl-side header rather than in ICoreNativeHandleAccess.h, because nothing outside these two files needs it.

ICoreStandardItem#

ICoreStandardItemImpl.h:39 · class · bases :Impl : public QStandardItem · 6 declaration(s)

H4.11 moved every body from this header into ICoreTreeView.cpp, where the class is already resolved, and made m_owner public.

class ICoreStandardItem : :Impl : public QStandardItem {
public:
    static constexpr int kType = QStandardItem::UserType + 407;

    explicit Impl(ICoreStandardItem& owner);

    Impl(ICoreStandardItem& owner, const ICoreString& text);

    // ⚠ QStandardItem's type tag is a VIRTUAL, not a constructor argument --
    // unlike QListWidgetItem and QTreeWidgetItem, which take it. Overriding is
    // the only way to set it, and forgetting that is a SILENT failure: the
    // default would make ownerOf() reject every row this library made, so
    // childItem()/parentItem() would answer nullptr for rows that are ours.
    int type() const override;

    // The model (or the parent row) got here first: sever the link and take the
    // wrapper with us, because after insertion nothing else owns it.
    ~Impl() override;

    // Called from ~ICoreStandardItem so this destructor does not delete a
    // wrapper that is already destroying itself.
    void detachOwner();

    // The type-checked downcast, in one place. A row this library did not
    // create answers nullptr rather than being reinterpreted.
    static ICoreStandardItem* ownerOf(QStandardItem* raw);

    ICoreStandardItem* m_owner;
};
};

ICoreTable.h#

src/ICoreEssentials/UI/Widgets/ICoreTable.h

Hides every row whose visible cell text (labels, line edits, combo boxes) does not contain the query. An empty query shows everything again. The query is re-applied by the host panel after it rebuilds its rows.

ICoreTable#

ICoreTable.h:13 · class · bases public ICoreWidget · pImpl · 12 declaration(s)

class ICoreTable : public ICoreWidget {
public:
    explicit ICoreTable(ICoreNativeWidget* parent = nullptr, const std::vector<std::string>& columnsTitles = {});

    ICoreTableEntryRow* addRow(const std::vector<ICoreNativeWidget*>& entries);
    void deleteRow(ICoreTableEntryRow *entry);
    void clearAllRows();

    // Hides every row whose visible cell text (labels, line edits, combo boxes)
    // does not contain the query. An empty query shows everything again. The
    // query is re-applied by the host panel after it rebuilds its rows.
    void filterRows(const ICoreString& query);
    ICoreString getActiveFilter() const;
    int getVisibleRowsCount() const;

    void setColumnsWidthRatios(const std::vector<double> &newRatios);
    void setTitleBarHeight(const int& newHeight) const;
    void setRowsHeight(const int &newHeight);

    ~ICoreTable() override;

protected:
    void resized(const ICoreSizeF& newSize, const ICoreSizeF& oldSize) override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreTableEntryRow.h#

src/ICoreEssentials/UI/Widgets/ICoreTableEntryRow.h

⚠ Q1.6 SWAPPED THIS FROM std::vector<QWidget*>, AND THE SWAP FIXED A LIVE BUG RATHER THAN JUST RETYPING ONE. While the parameter was QWidget*, the body had to recover each cell's wrapper with icoreNativeWidgetOf(), which has returned nullptr for everything since P5.10 (see the ⚠⚠ note in ICoreNativeHandleAccess.h -- the dual base it relied on died with the conversion). So every cell handed to a table row was silently dropped instead of laid out. Taking the wrapper directly means there is nothing to recover.

ICoreTableEntryRow#

ICoreTableEntryRow.h:8 · class · bases public ICoreWidget · pImpl · 3 declaration(s)

class ICoreTableEntryRow : public ICoreWidget {
public:
    // ⚠ Q1.6 SWAPPED THIS FROM std::vector<QWidget*>, AND THE SWAP FIXED A LIVE
    // BUG RATHER THAN JUST RETYPING ONE. While the parameter was QWidget*, the
    // body had to recover each cell's wrapper with icoreNativeWidgetOf(), which
    // has returned nullptr for everything since P5.10 (see the ⚠⚠ note in
    // ICoreNativeHandleAccess.h -- the dual base it relied on died with the
    // conversion). So every cell handed to a table row was silently dropped
    // instead of laid out. Taking the wrapper directly means there is nothing
    // to recover.
    explicit ICoreTableEntryRow(const std::vector<ICoreNativeWidget*>& entries);

    void setColumnsWidths(const std::vector<double> &columnWidthRatios) const;

    ~ICoreTableEntryRow() override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreTableTitlesRow.h#

src/ICoreEssentials/UI/Widgets/ICoreTableTitlesRow.h

ICoreTableTitlesRow#

ICoreTableTitlesRow.h:11 · class · bases public ICoreWidget · 6 declaration(s)

class ICoreTableTitlesRow : public ICoreWidget {
public:
    explicit ICoreTableTitlesRow(ICoreTable* parent, const std::vector<std::string>& columnNames);

    void setColumnsWidths(std::vector<double> newColumnsWidths);

    std::vector<double> getColumnsWidths() const;

    void setHeight(const int &newHeight) const;

    qsizetype getSplitterIndex(const ICoreTableTitlesRowSplitter* splitter);

    ~ICoreTableTitlesRow() override;

};

ICoreTableTitlesRowSplitter.h#

src/ICoreEssentials/UI/Widgets/ICoreTableTitlesRowSplitter.h

ICoreTableTitlesRowSplitter#

ICoreTableTitlesRowSplitter.h:12 · class · bases public ICoreWidget · pImpl · 6 declaration(s)

class ICoreTableTitlesRowSplitter : public ICoreWidget {
public:
    explicit ICoreTableTitlesRowSplitter(ICoreTableTitlesRow* parentTitlesBar,
                        ICoreTable* grandParentTable);

    ~ICoreTableTitlesRowSplitter() override;

protected:
    void pointerEntered() override;
    void pointerLeft() override;

    bool mousePressed(const ICoreMouseEvent& event) override;
    bool mouseMoved(const ICoreMouseEvent& event) override;
    bool mouseReleased(const ICoreMouseEvent& event) override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreTextEdit.h#

src/ICoreEssentials/UI/Widgets/ICoreTextEdit.h

ICoreTextEdit#

ICoreTextEdit.h:50 · class · bases public ICoreNativeWidget · pImpl · 33 declaration(s)

The multi-line sibling of ICoreLineEdit: same themed field background, same rounded border, same hover fade.

class ICoreTextEdit : public ICoreNativeWidget {
public:

    // ⚠ Takes ICoreFont, and deliberately does NOT re-export a QFont overload.
    // P7.6 converted ICoreFont, so it no longer converts to QFont and every
    // call site passing one needs a sink that speaks the wrapper.
    void setFont(const ICoreFont& font);

    // The Impl QPlainTextEdit -- out of line because the header only
    // forward-declares Impl. Was `this` while the Qt base existed.
    ICoreNativeHandle nativeWidgetHandle() const override;

    // Which of the field's own chrome this instance wears -- the same opt-in
    // ICoreLineEdit::Chrome describes, and for the same reason. Field is the
    // default and is everything above; None styles and sizes NOTHING, so the
    // widget is behaviourally a plain QPlainTextEdit that happens to sit under
    // this class instead of beside it.
    //
    // None is what the read-only and console views need: they are given their
    // whole appearance by the panel that owns them, and they must NOT inherit
    // the field's border, its padding or -- the one that would actually break
    // them -- setVisibleLines(3)'s fixed height, since a console sizes itself
    // from the layout it is stretched into.
    enum class Chrome { Field, None };

    // Q1.2: one parent spelling. The QWidget* twin and the std::nullptr_t
    // delegate that broke their tie both went; with a single pointer
    // overload a literal nullptr is unambiguous and can carry the default.
    explicit ICoreTextEdit(ICoreNativeWidget* parent = nullptr, Chrome chrome = Chrome::Field);

    [[nodiscard]] Chrome chrome() const;

    double borderOpacity() const;
    void  setBorderOpacity(double opacity);

    // Sizes the field to a whole number of text lines, border and padding
    // included. A layout otherwise has to guess a pixel height that happens to
    // land on a line boundary, which then breaks whenever the theme's font or
    // padding changes.
    void setVisibleLines(int lines);

    // ------------------------------------------------------------------
    // Streaming coloured output (the console case).
    //
    // These exist so a client outside the wrapper zone never has to name
    // QTextCursor / QTextCharFormat / QTextBlockFormat. The whole document
    // manipulation stays in the .cpp here, which is the only place that
    // knows the chunk-vs-line distinction below matters.
    // ------------------------------------------------------------------

    // Append `text` at the very end in `colour` and pin the view to the bottom.
    //
    // Inserts rather than appends a paragraph: output arrives in chunks that do
    // not line up with line boundaries, and appending each one would break every
    // chunk onto a line of its own.
    void appendColouredChunk(const ICoreString& text, const ICoreColor& colour);

    // Same, but also marks the block the chunk STARTS in as the beginning of a
    // section, so visibleSectionTops() reports it. The mark lives on the block
    // format, so it survives the trimming maximumBlockCount does.
    //
    // The document's first block is never marked: there is nothing above it to
    // be separated from.
    void appendColouredChunkStartingSection(const ICoreString& text, const ICoreColor& colour);

    // Viewport-relative y of the top of every section-start block whose top
    // falls at or above `bottomY` -- for an owner drawing a rule between
    // sections. Walks only the blocks on screen and stops at the first one past
    // `bottomY`, so a long scrollback costs nothing.
    [[nodiscard]] std::vector<double> visibleSectionTops(double bottomY) const;

    // The width a decoration drawn in paintContent has to work with. Not the
    // widget's: a QPlainTextEdit paints into its VIEWPORT, which is narrower
    // whenever the vertical scroll bar is up.
    [[nodiscard]] double viewportWidth() const;

    // ------------------------------------------------------------------
    // Facade forwarders the flip's harvest enumerated (same treatment as
    // ICoreLabel/ICoreLineEdit).
    // ------------------------------------------------------------------
    void setPlainText(const ICoreString& text);
    [[nodiscard]] ICoreString toPlainText() const;
    void insertPlainText(const ICoreString& text);
    void appendPlainText(const ICoreString& text);
    void appendHtml(const ICoreString& html);
    void clear();
    void setReadOnly(bool readOnly);

    // Q5.1. Distinct from setReadOnly: a disabled edit is greyed and takes no
    // focus, a read-only one still looks and selects normally. The Git panel
    // wants disabled, and used to reach it by unwrapping to QWidget.
    void setEnabled(bool enabled);
    void setPlaceholderText(const ICoreString& text);
    void setStyleSheet(const ICoreString& styleSheet);
    void setFixedHeight(int height);
    void setMinimumHeight(int height);
    void setMaximumBlockCount(int count);
    // Named operations instead of document() for the SCANNED-zone callers --
    // P2.10b-6b's lesson: the caller wants the margin and the emptiness test,
    // never the document.
    void setDocumentMargin(double margin);
    [[nodiscard]] bool isDocumentEmpty() const;
    void update();
    [[nodiscard]] ICoreFont font() const;

    // Unscoped on purpose so existing `ICoreTextEdit::NoWrap` call sites read
    // unchanged; pinned to the toolkit's values by static_asserts in the .cpp.
    enum LineWrapMode { NoWrap = 0, WidgetWidth = 1 };
    void setLineWrapMode(LineWrapMode mode);

    // The document, for the panels that tune block limits and margins through
    // it. The pointer is the toolkit's; the call sites never NAME a Qt type,
    // which is what the boundary guard checks.
    [[nodiscard]] QTextDocument* document() const;

    // The same document as an opaque handle — what a language editor hands
    // its syntax highlighter's constructor (E6, STUDIO_QT_INDEPENDENCE.md §3).
    [[nodiscard]] ICoreTextDocumentHandle documentHandle() const;

    // Out of line: the unique_ptr member's deleter needs Impl complete, and
    // this header only forward-declares it.
    virtual ~ICoreTextEdit();

protected:
    // Called after the base class has painted, for owner-drawn decoration over
    // the viewport. `dirty` is the region being repainted, in viewport
    // coordinates. The painter is only valid for the duration of the call.
    virtual void paintContent(ICorePainter& painter, const ICoreRect& dirty);

    // H4.12 (header surface rule): `QPlainTextEdit* nativeTextEdit() const`
    // stood here, a protected non-virtual for wrapper-zone subclasses. It had
    // ZERO callers tree-wide -- declaration and definition only -- so it was
    // DELETED rather than published, the same call H4.24/H4.25 made for
    // ICoreWindow::nativeWindow and ICoreDialog::nativeDialog. A subclass that
    // genuinely needs the toolkit object again should take it back as a named
    // operation, not as a raw QPlainTextEdit*.

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreToggleButton.h#

src/ICoreEssentials/UI/Widgets/ICoreToggleButton.h

ICoreToggleButton#

ICoreToggleButton.h:32 · class · bases public ICoreWidget · pImpl · 12 declaration(s)

class ICoreToggleButton : public ICoreWidget {
public:
    // Mirror of the optionUpdated signal, for clients outside the wrapper zone.
    ICoreSignal<bool> onOptionUpdated;

    explicit ICoreToggleButton(ICoreNativeWidget* parent = nullptr);

    void setValueFromString(const std::string& stringValue);
    void onOptionUpdate();

    void setChecked(const bool& checked);

    bool isChecked() const;

    // 0 = knob fully left (off), 1 = knob fully right (on). The slide and the
    // colour are both derived from it, so they cannot disagree.
    [[nodiscard]] double knobPosition() const;
    void  setKnobPosition(double position);

    ~ICoreToggleButton() override;

protected:
    void paintContent(ICorePainter& painter) override;
    void pointerEntered() override;
    void pointerLeft() override;
    bool mousePressed(const ICoreMouseEvent& event) override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreTree.h#

src/ICoreEssentials/UI/Widgets/ICoreTree.h

ICoreTreeItem#

ICoreTree.h:41 · class · pImpl · 18 declaration(s)

The item-based tree (rows owned by the widget), wrapping QTreeWidget.

class ICoreTreeItem {
public:
    ICoreTreeItem();
    explicit ICoreTreeItem(const ICoreStringList& columnTexts);
    ~ICoreTreeItem();

    ICoreTreeItem(const ICoreTreeItem&) = delete;
    ICoreTreeItem& operator=(const ICoreTreeItem&) = delete;

    void setText(int column, const ICoreString& text);
    ICoreString text(int column) const;

    void setIcon(int column, const ICoreIcon& icon);

    void setForeground(int column, const ICoreColor& color);
    void setBackground(int column, const ICoreColor& color);

    void setToolTip(int column, const ICoreString& text);

    // Takes ownership of `child`'s toolkit half, exactly as ICoreTree's
    // addTopLevelRow does for a top-level row. Passing a row that is already in
    // a tree does nothing — it has no half left to give.
    void addChildRow(ICoreTreeItem* child);

    // ⚠ A caller-owned tag riding on the row, and it is a PLAIN MEMBER of this
    // wrapper rather than the Qt::UserRole data role ICoreListBoxItem uses.
    // That divergence is preserved deliberately, not overlooked: nothing reads
    // this tag through the model (the log delegate paints from the foreground
    // brush, not from a role), so moving it into a role would put a QVariant
    // round trip in front of a value the C++ side already owns. It also means
    // the tag does NOT survive into the toolkit item — which is correct, since
    // the toolkit item is not what callers hold.
    void setTag(const ICoreString& tag);
    ICoreString tag() const;

    // ⚠ All three may return nullptr — for a row this library did not create,
    // and for an out-of-range index. See the ownership note above.
    ICoreTreeItem* parentItem() const;
    ICoreTreeItem* childItem(int index) const;
    int childItemCount() const;

    bool isSelected() const;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreTree#

ICoreTree.h:108 · class · final · bases public ICoreNativeWidget · pImpl · 35 declaration(s)

class ICoreTree final : public ICoreNativeWidget {
public:
    explicit ICoreTree(ICoreNativeWidget* parent = nullptr);

    // Out of line, and required rather than stylistic: both m_itemDelegate and
    // the Impl are unique_ptrs to forward-declared types, so their deleters
    // have to be instantiated where those types are complete.
    ~ICoreTree() override;

    ICoreTree(const ICoreTree&) = delete;
    ICoreTree& operator=(const ICoreTree&) = delete;

    void setHeaderLabels(const ICoreStringList& labels);

    // Takes ownership of `item`'s toolkit half.
    void addTopLevelRow(ICoreTreeItem* item);

    // ⚠ Both may return nullptr — see the ownership note above.
    ICoreTreeItem* topLevelRow(int index) const;
    ICoreTreeItem* currentRow() const;

    int topLevelRowCount() const;
    void clearRows();

    // ---------------- behaviour
    //
    // None of these carry a using-declaration any more. Before the conversion
    // setSelectionMode and setTextElideMode needed one to keep the toolkit
    // overload reachable; this class no longer has a Qt base for them to hide,
    // which is P6.3's observation arriving here too — the transitional name
    // disappears the moment the Qt base does.

    void setSelectionMode(ICoreSelectionMode mode);

    // Whether a click takes the whole row or the single cell under it.
    void setSelectsWholeRows(bool wholeRows);

    // ⚠ THIS TREE TAKES OWNERSHIP, WHICH THE TOOLKIT'S setItemDelegate DOES
    // NOT — hence the unique_ptr, which says so in the signature instead of in
    // a comment nobody reads at the call site. The divergence is deliberate and
    // it is the safe direction:
    //
    //   - Qt documents only that it does not take ownership. It says nothing
    //     about a delegate destroyed BEFORE its view, which is exactly what a
    //     caller-held member produces: a QWidget's children are destroyed by
    //     ~QWidget, after every member of the class holding them, so any
    //     panel-owned delegate necessarily dies while its tree is still alive.
    //   - Owning it here inverts that. The delegate is a member of this class,
    //     so it dies in ~ICoreTree, before the Impl it paints for.
    //
    // It also removes the stack hazard: a unique_ptr parameter cannot be handed
    // an automatic object. Replacing a delegate deletes the previous one.
    void setItemDelegate(std::unique_ptr<ICoreItemDelegate> delegate);

    void setFocusBehavior(ICoreFocusPolicy policy);

    // Horizontal scrolling by pixel rather than by column, so a long line
    // slides instead of jumping a column at a time.
    void setSmoothHorizontalScrolling(bool smooth);

    void setHorizontalScrollBarVisibility(ICoreScrollBarPolicy policy);

    // Whether the last column swallows the width the others leave over.
    void setStretchLastColumn(bool stretch);

    void setColumnResizeMode(ICoreColumnResize mode);
    void setTextElideMode(ICoreTextElide mode);

    // ---------------- appearance and layout of the view itself
    //
    // These arrived free from QTreeWidget before the conversion and are
    // hand-written forwarders now. They are here because the ONE consumer
    // (ICoreRunDiagnosisPanel) calls every one of them — the count came from
    // reading the call site, not from QTreeWidget's method list, which is the
    // sizing lesson P4.1 wrote down.
    void setHeaderHidden(bool hidden);
    void setRootDecorated(bool decorated);
    void setExpandAnimated(bool animated);
    void setIndentation(int pixels);
    void setWordWrapEnabled(bool enabled);
    void setStyleSheet(const ICoreString& styleSheet);

    void resizeColumnToContents(int column);
    int columnWidth(int column) const;
    void setColumnWidth(int column, int width);

    // ⚠ Replaces viewport()->width() at the call site. The viewport is a
    // toolkit-created child with no wrapper of its own, so handing it out was
    // never an option — the same resolution P1.8 reached when it retired
    // ICoreScrollPane::viewport() in favour of named questions.
    int viewportWidth() const;

    void selectAllRows();
    void expandAllRows();
    void collapseAllRows();
    void collapseRow(ICoreTreeItem* item);
    void scrollToBottom();

    // Mirrors of the QTreeWidget signals client code subscribes to.
    //
    // ⚠ Each may deliver nullptr, for a row this library did not create. That
    // is new: before the conversion these carried an unchecked static_cast and
    // could not report "not mine", they could only be wrong about it.
    ICoreSignal<ICoreTreeItem*, int> onItemClicked;
    ICoreSignal<ICoreTreeItem*, int> onItemDoubleClicked;
    ICoreSignal<ICoreTreeItem*> onCurrentRowChanged;
    ICoreSignal<ICoreTreeItem*> onItemExpanded;
    ICoreSignal<ICoreTreeItem*> onItemCollapsed;

    // A right-click on the rows, carrying a SCREEN position -- which is what a
    // menu is popped up at, and what the press position on its own is not: the
    // press lands on the viewport, whose origin is not the view's.
    ICoreSignal<ICorePoint> onContextMenuRequested;

    // The scrolled area changed size. It is the viewport rather than the
    // widget because that is the width a column is sized against; the widget
    // also holds the header and the scroll bars, and one of those appearing is
    // itself a viewport resize.
    ICoreSignal<ICoreSizeF> onViewportResized;

    ICoreNativeHandle nativeWidgetHandle() const override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreTreeView.h#

src/ICoreEssentials/UI/Widgets/ICoreTreeView.h

The caller-owned data roles of an item view. A row carries its display text and icon in roles the toolkit owns; everything a call site attaches for its own use starts at User and counts up (User + 1, User + 2, ...).

The value is the toolkit's own first free role, and it MUST NOT move: roles are written into models by one class and read out by another (the subsystem entries are written by ICoreSubsystemTreeNode and read by ICoreNewTabPanel), so a shift here would not fail to compile -- it would silently read nothing. ICoreInputEnumsVerify.cpp pins it to the toolkit constant.

ICoreTreeRow#

ICoreTreeView.h:41 · class · pImpl · 11 declaration(s)

A row of a model-based tree, as an opaque handle.

class ICoreTreeRow {
public:
    // The opaque nested name only -- its definition is in the .cpp. Public so
    // the .cpp's buffer helpers can spell it, exactly as kNativeStorage* below
    // are public so they can be pinned (ICoreTextBlock's precedent).
    class Impl;

    ICoreTreeRow();
    ~ICoreTreeRow();

    // A row is a value: copied through tree walks and stored in containers.
    ICoreTreeRow(const ICoreTreeRow& other);
    ICoreTreeRow& operator=(const ICoreTreeRow& other);
    ICoreTreeRow(ICoreTreeRow&& other) noexcept;
    ICoreTreeRow& operator=(ICoreTreeRow&& other) noexcept;

    // Public only so the .cpp can pin them.
    static constexpr std::size_t kNativeStorageSize = sizeof(std::shared_ptr<void>);
    static constexpr std::size_t kNativeStorageAlign = alignof(std::shared_ptr<void>);

    bool isValid() const;
    ICoreTreeRow parent() const;

    // Two handles are the same row when they name the same row of the same
    // model -- what a call site comparing "is this the row I stored?" means.
    bool operator==(const ICoreTreeRow& other) const;
    bool operator!=(const ICoreTreeRow& other) const;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreStandardItem#

ICoreTreeView.h:122 · class · pImpl · 17 declaration(s)

The row type for models this library fills.

class ICoreStandardItem {
public:
    ICoreStandardItem();
    explicit ICoreStandardItem(const ICoreString& text);
    ~ICoreStandardItem();

    ICoreStandardItem(const ICoreStandardItem&) = delete;
    ICoreStandardItem& operator=(const ICoreStandardItem&) = delete;

    void setLabel(const ICoreString& text);
    ICoreString label() const;

    void setIcon(const ICoreIcon& icon);

    // Whether the row can be renamed in place.
    void setEditable(bool editable);

    // Caller-owned data on the row, off ICoreItemRoles::User. Two overloads
    // rather than a QVariant: those are the only two kinds this tree writes
    // (an entry-type enumerator and a registry path), and they are what
    // ICoreTreeView::rowData reads back. Unambiguous -- an enumerator converts
    // to int and never to ICoreString.
    void setData(int value, int role);
    void setData(const ICoreString& value, int role);

    // Caller-owned tag riding on the row (the ICoreItemRoles::User idiom).
    void setTag(const ICoreString& tag);
    ICoreString tag() const;

    // Takes ownership of `child`'s toolkit half.
    void appendChildRow(ICoreStandardItem* child);

    // The multi-column form: `cells` is one whole child row, left to right, and
    // ownership of every one of them transfers. cells[0] is the row proper --
    // the cell that carries the expand arrow, owns the children, and is the one
    // ICoreTreeView's row handles resolve to (see rowAt below).
    //
    // ⚠ Put the icon and any caller-owned roles on cells[0] and nowhere else.
    // A row handle always names column 0, so rowData() reads that cell; a role
    // written onto cells[1] is stored, costs memory, and can never be read back
    // through this API.
    void appendChildRow(const std::vector<ICoreStandardItem*>& cells);

    // ⚠ Both may return nullptr, for a row this library did not create.
    ICoreStandardItem* childItem(int row) const;
    ICoreStandardItem* parentItem() const;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreTreeView#

ICoreTreeView.h:190 · class · bases public ICoreNativeWidget · pImpl · 37 declaration(s)

The model-based tree.

class ICoreTreeView : public ICoreNativeWidget {
public:
    explicit ICoreTreeView(ICoreNativeWidget* parent = nullptr);
    ~ICoreTreeView() override;

    ICoreTreeView(const ICoreTreeView&) = delete;
    ICoreTreeView& operator=(const ICoreTreeView&) = delete;

    // Row activation/selection/clicks, delivered as a row handle. An invalid
    // handle means "no row" (the selection emptying, a click on empty space).
    ICoreSignal<ICoreTreeRow> onRowActivated;
    ICoreSignal<ICoreTreeRow> onCurrentRowChanged;
    ICoreSignal<ICoreTreeRow> onRowDoubleClicked;
    ICoreSignal<ICoreTreeRow> onRowClicked;

    // ---------------- the model
    //
    // ⚠ Returns the model this view was GIVEN, remembered. It is NOT a
    // dynamic_cast of the toolkit's model() and must not become one: P6.5's
    // finding, and now unavoidable -- after this conversion there is no
    // toolkit view for a call site to ask in the first place.
    void setModel(ICoreTreeViewModel* model);
    ICoreTreeViewModel* treeModel() const;

    // ---------------- rows
    //
    // The model's invisible root: the handle whose children are the top-level
    // rows. Invalid on purpose -- that is what "no parent" is.
    ICoreTreeRow rootRow() const;

    // The row under a point in the view's own coordinates. Invalid when the
    // point is not on a row.
    //
    // ⚠ ALWAYS COLUMN 0, whichever column the point actually fell in. A row
    // handle names a ROW -- the header says so, and operator== below compares
    // two handles on that basis -- so a click in a detail column has to resolve
    // to the same handle as a click on the name. Without that, rowData() would
    // read the clicked CELL: on a multi-column tree, double-clicking a date
    // column would find no entry-path role and do nothing, which reads as a
    // dead spot in the widget rather than as a bug. Every row handle this class
    // hands out is normalised the same way, including the four signals'.
    ICoreTreeRow rowAt(const ICorePoint& viewPos) const;

    // The same, for a point in screen coordinates -- which is what the
    // contextMenuRequested hook below is handed, and a context menu's first
    // question is always which row it was opened on.
    ICoreTreeRow rowAtGlobal(const ICorePoint& globalPos) const;

    int childRowCount(const ICoreTreeRow& row) const;
    ICoreTreeRow childRow(const ICoreTreeRow& row, int index) const;

    // The row's displayed text (the role with no name).
    ICoreString rowText(const ICoreTreeRow& row) const;

    // A caller-owned role off ICoreItemRoles::User, as text. Numbers written
    // into a role come back through ICoreString::toInt() -- the conversion is
    // the model's, so an int role round-trips.
    ICoreString rowData(const ICoreTreeRow& row, int role) const;

    // The row's position among its siblings.
    int rowNumber(const ICoreTreeRow& row) const;

    // The toolkit spells hiding as (row number, parent, hidden); a handle
    // already knows both halves. ⚠ No using-declaration any more -- there is
    // no Qt base left for a same-named member to hide, which is P6.3's
    // observation arriving here.
    void setRowHidden(const ICoreTreeRow& row, bool hidden);

    void expandRow(const ICoreTreeRow& row);
    void setCurrentRow(const ICoreTreeRow& row);
    void scrollToRow(const ICoreTreeRow& row);
    void collapseAllRows();

    // ---------------- behaviour and appearance
    //
    // Everything below arrived free from QTreeView before the conversion and is
    // a hand-written forwarder now. The list came from reading the one
    // subclass's constructor, not from QTreeView's method list -- P4.1's sizing
    // lesson, which P4.3 then had to re-learn.

    // How one column takes its width. The names are the toolkit's, but the
    // values are this class's own and are mapped by an explicit switch in the
    // .cpp -- nothing here is pinned to a toolkit constant.
    //
    //   Interactive      -- the user drags the header divider; setColumnWidth
    //                       gives the starting width.
    //   Stretch          -- shares the leftover width with the other Stretch
    //                       columns. This is how a tree's name column takes the
    //                       slack while its detail columns stay put.
    //   ResizeToContents -- as wide as its widest cell, and not draggable.
    //   Fixed            -- exactly setColumnWidth's width, never anything else.
    enum class ColumnSizing { Interactive, Stretch, ResizeToContents, Fixed };

    // ⚠ BOTH ONLY BITE ONCE THE MODEL HAS COLUMNS. The header has no sections
    // to size before setModel() -- calling either first is silently ignored, not
    // an error -- so a caller that rebuilds its model must re-apply them after
    // every setModel().
    void setColumnWidth(int column, int width);
    void setColumnSizing(int column, ColumnSizing sizing);

    // What a column is CURRENTLY laid out at, which is not the same as what it
    // was last set to: a stretch section, or one the user has dragged, answers
    // its real width. Zero for a column that does not exist yet, which is also
    // what a header with no sections answers -- callers remembering a width
    // across a model rebuild have to treat 0 as "nothing to remember".
    [[nodiscard]] int columnWidth(int column) const;

    // Whether the rightmost column absorbs leftover width. The toolkit's default
    // is ON, which fights any Stretch column to its left; a tree that sizes its
    // own columns wants it off.
    void setStretchLastColumn(bool stretch);

    // Whether a row can be renamed in place. Off means no edit trigger at all.
    void setEditingEnabled(bool enabled);

    void setSelectionMode(ICoreSelectionMode mode);

    void setStyleSheet(const ICoreString& styleSheet);
    void resize(int width, int height);
    void setIconSize(const ICoreSizeF& size);
    void setHeaderHidden(bool hidden);
    void setExpandAnimated(bool animated);
    void setMouseTracking(bool enabled);
    void setUniformRowHeights(bool uniform);
    void setAcceptDrops(bool accept);
    void setDropIndicatorShown(bool shown);

    ICoreNativeHandle nativeWidgetHandle() const override;

protected:
    // ------------------------------------------------------------------
    // The hook surface, mirroring ICoreWidget's. Both return "handled?":
    // true consumes the event, false forwards it to the base implementation,
    // so a subclass that overrides neither behaves exactly as it did before
    // the hooks existed.
    //
    // ⚠ The Qt handlers are GONE from this header -- they live on the Impl
    // now, so "kept overridable for the wrapper zone's own components" is no
    // longer true and no longer possible. Nothing used that route; a future
    // component needing one has to grow a hook, which is the same capability
    // P4.2 recorded losing for ICoreItemDelegate::initStyleOption.
    // ------------------------------------------------------------------
    virtual bool mouseDoubleClicked(const ICoreMouseEvent& event);
    virtual bool contextMenuRequested(const ICorePoint& globalPos);

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreTreeViewModel.h#

src/ICoreEssentials/UI/Widgets/ICoreTreeViewModel.h

ICoreTreeViewModel#

ICoreTreeViewModel.h:24 · class · final · bases public ICoreNativeObject · pImpl · 14 declaration(s)

The rows behind an ICoreTreeView, wrapping QStandardItemModel.

class ICoreTreeViewModel final : public ICoreNativeObject {
public:
    // ⚠ The parent is an ICoreNativeWidget, not an ICoreNativeObject, and that
    // is the "widget as object parent" decision this task existed to make.
    // Every model in the tree is parented to the VIEW that shows it -- a
    // widget -- and nothing parents one to a bare object. Taking the widget
    // interface and resolving it through icoreNativeObjectOfWidget() once,
    // inside, means no call site writes that step. Taking ICoreNativeObject*
    // instead would push an unwrap onto the one call site and buy nothing.
    explicit ICoreTreeViewModel(ICoreNativeWidget* parent = nullptr);
    ~ICoreTreeViewModel() override;

    ICoreTreeViewModel(const ICoreTreeViewModel&) = delete;
    ICoreTreeViewModel& operator=(const ICoreTreeViewModel&) = delete;

    // Empties the model. ⚠ This is the ONLY spelling -- the pre-conversion
    // class had resetToInitialState() AND an inherited clear(), which were the
    // same operation under two names, and the two call sites used one each
    // (§9: a second name for one thing is the P0.5 mistake).
    void resetToInitialState();

    // Takes the subsystem tree's root row. The item is owned by the model from
    // here, which is what QStandardItemModel::appendRow already meant.
    void appendRootRow(ICoreStandardItem* item);

    // The multi-column form -- one whole root row, left to right, all of it
    // owned by the model from here. cells[0] is the row proper; see
    // ICoreStandardItem::appendChildRow's note on where roles belong.
    void appendRootRow(const std::vector<ICoreStandardItem*>& cells);

    // The column titles, which also SET THE COLUMN COUNT. An empty list leaves
    // the model single-column.
    //
    // ⚠ resetToInitialState() clears these along with the rows, so a model that
    // is emptied and refilled has to be given them again.
    void setColumnHeaders(const std::vector<ICoreString>& labels);

    int rowCount() const;

    // Drops the parent link so the pool can outlive the view. Called by
    // ICoreStudioGarbageCollection before a model is recycled.
    void detachFromParent();

    void kill();
    void setAlive();
    bool isAlive() const;

    ICoreNativeHandle nativeObjectHandle() const override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreWidget.h#

src/ICoreEssentials/UI/Widgets/ICoreWidget.h

The ENUM header, not ICoreSurfaceGradient.h: that one's return type would drag <QLinearGradient> into all ~150 headers that name this class.

ICoreWidget#

ICoreWidget.h:73 · class · bases public ICoreNativeWidget · pImpl · 130 declaration(s)

The base every StudioObjects widget derives from (task C1).

class ICoreWidget : public ICoreNativeWidget {
public:

    // ⚠ Takes ICoreFont, and deliberately does NOT re-export the inherited
    // QWidget::setFont(const QFont&) with a `using`. P7.6 converted ICoreFont, so
    // it no longer converts to QFont and every call site passing one needs a
    // sink that speaks the wrapper. A `using` here would reopen exactly the
    // re-export hole §9 records neither guard being able to see, since the Qt
    // name would appear only at the call site. Hiding the base overload is
    // safe: QWidget::setFont is not virtual, and a caller still holding a raw
    // QFont converts through ICoreFont's implicit inbound constructor.
    void setFont(const ICoreFont& font);

    // The Impl QWidget -- out of line because the header only forward-declares
    // Impl. Was `this` while the Qt base existed.
    ICoreNativeHandle nativeWidgetHandle() const override;

    // Parent this widget to an already-converted wrapper.
    //
    // Deliberately a named setter and NOT a constructor overload. While this
    // class still derives from BOTH QWidget and ICoreNativeWidget, an
    // `ICoreWidget(ICoreNativeWidget*)` constructor would be ambiguous against
    // `ICoreWidget(QWidget*)` for every one of the ~96 call sites that passes an
    // ICoreWidget* as its parent -- both are derived-to-base pointer
    // conversions, so neither wins. A distinct name has no such problem. Once
    // this class is itself converted and QWidget is gone from the bases, the
    // ambiguity goes with it and this can fold back into the constructor.
    void setParentWidget(ICoreNativeWidget* parent);

    enum class Surface {
        None,
        Panel
    };

    explicit ICoreWidget(ICoreNativeWidget* parent = nullptr);
    ICoreWidget(Surface surface, ICoreNativeWidget* parent = nullptr);

    // ⚠ Q1.1 DELETED THE std::nullptr_t DELEGATE that used to sit here, and
    // that is the point rather than a side effect. It existed ONLY to break the
    // tie between the QWidget* and ICoreNativeWidget* overloads for a literal
    // `nullptr`; with one pointer overload left there is no tie, and the
    // defaults above are safe for the same reason. Do not re-add a QWidget*
    // overload without bringing the delegate back with it.

    // QWidget's (parent, flags) constructor. C1 needs it because a widget that
    // is its own top-level window passes Qt::Window here and has no other way
    // to say so -- ICoreDetachedPanelWindow is the one such widget today.
    // No default on `flags` on purpose: one would make ICoreWidget(parent)
    // ambiguous against the single-argument constructor above.
    //
    // Q1.1 swapped the parent, Q3.2 the flags. ICoreWindowFlags is Q0.1's
    // `unsigned int` flag set (ICoreMouseButtons' shape), unwrapped to
    // Qt::WindowFlags once at the Impl seam in the .cpp.
    ICoreWidget(ICoreNativeWidget* parent, ICoreWindowFlags flags);

    // Out of line: the unique_ptr<Impl> needs the complete type there. The
    // release-guard pairing with ~Impl is documented at the Impl's destructor.
    ~ICoreWidget() override;

    Surface surface() const;

    // Switching to Panel late is allowed; it applies the attributes and the
    // parent filter at that point, exactly as the constructor would have.
    void setSurface(Surface newSurface);

    // Panel-only appearance. Harmless in Surface::None -- nothing reads them.
    void setFillColor(const ICoreColor& newFillColor);

    // Spread the fill colour as ICoreSurfaceGradient's ramp -- lit at the corner
    // `direction` names, deepening toward the opposite one -- instead of one
    // flat wash. Off by default, and it is the SPREAD that changes: the fill
    // colour still names the surface, so a panel that already follows the theme
    // through setFillColor keeps following it with nothing else to subscribe to.
    //
    // The ramp is rebuilt from the body's bounds on every paint rather than
    // cached, which is what makes it survive a resize -- a stored gradient
    // carries absolute coordinates and would smear the moment the window
    // changed height. See ICoreSurfaceGradient.h for why it is sampled, and
    // ICoreGradientDirection.h for why a diagonal's angle follows the body's
    // aspect rather than holding 45 degrees.
    //
    // The two strengths scale how far each end of the ramp travels from the
    // fill colour, and they are separate so the lit end can be brought down
    // without the deep end coming up with it. A short body wants less of both,
    // since the same ramp across it is a far steeper slope. ICoreToolBar
    // carries the same four for its own body.
    void setGradientFill(bool gradient,
                         ICoreGradientDirection direction = ICoreGradientDirection::TopToBottom,
                         double litStrength = 1.0,
                         double deepStrength = 1.0);

    // The same treatment for the OUTLINE: borderColor() spread along the axis
    // `direction` names instead of drawn flat. Off by default, and like the
    // fill it changes only the spread -- borderColor() still names the colour,
    // so an override that follows the theme keeps following it.
    //
    // Meant to be given the direction the fill already runs, which is what
    // makes the body and its outline read as one lit surface rather than as a
    // gradient inside a flat frame. The ramp is border-tuned rather than the
    // fill's (ICoreSurfaceGradient::forBorder) because the same travel that
    // reads as material across a panel is invisible along a 2px line.
    void setGradientBorder(bool gradient,
                           ICoreGradientDirection direction = ICoreGradientDirection::TopToBottom,
                           double litStrength = 1.0,
                           double deepStrength = 1.0);

    // A widget that is its own top-level. Replaces passing toolkit window
    // flags to the constructor; FloatingCard also declines focus and shows
    // without activating, which is what a hover card needs.
    ICoreWidget(ICoreWindowNature nature, ICoreNativeWidget* parent = nullptr);

    // Turn an already-constructed widget into its own top-level window, frame
    // and all. The ICoreWindowNature constructor above is the way to say this
    // at construction; this is for the widgets that decide it in their own
    // body, after the base is built.
    void becomeTopLevelWindow();

    // The usable area of THIS widget's screen -- the one it is currently on,
    // excluding the OS bars. Not the primary screen's: a window dragged onto a
    // second monitor is placed against the monitor it is on, and reading the
    // primary one is how a card lands off-screen on a multi-monitor desk.
    ICoreRect screenAvailableGeometry() const;

    // Whether this widget will take keyboard focus at all.
    void setFocusable(bool focusable);

    // Let whatever is behind the widget show through where it does not paint.
    void setTranslucentBackground(bool translucent);

    // Fill the whole widget with one flat colour, opaquely. For the widgets that
    // ARE a block of colour -- rules, dividers, spacers -- rather than something
    // with a colour.
    //
    // Not a stylesheet: a stylesheet background here would be overridden by any
    // rule an ancestor sets for its child widgets, which is exactly what a
    // one-off divider inside a themed panel runs into. This paints through the
    // widget's own palette instead, which nothing else contends for. Independent
    // of Surface -- it works in None, where m_fillColor is not read.
    void setSolidBackground(const ICoreColor& color);

    // This widget's own area, origin at (0,0) -- what a paintContent() hook
    // draws into. The ICore spelling of rect(); paint hooks need it constantly
    // and ICoreRect's QRect constructor is explicit, so without this every hook
    // writes the conversion out by hand.
    [[nodiscard]] ICoreRect bounds() const;

    // This widget's coordinates <-> screen coordinates. The pair a popup needs
    // to place itself under a control that lives in a different parent chain.
    [[nodiscard]] ICorePoint mapToScreen(const ICorePoint& local) const;
    [[nodiscard]] ICorePoint mapFromScreen(const ICorePoint& screen) const;

    // The same mapping for a widget this code did not create -- an anchor it was
    // handed, or its own parentWidget(). Static and ICoreAnyWidget-taking because
    // neither of those is an ICoreWidget in general, which is exactly when a
    // popup needs the conversion.
    [[nodiscard]] static ICorePoint mapToScreenOf(const ICoreAnyWidget* widget,
                                                  const ICorePoint& local);
    [[nodiscard]] static ICorePoint mapFromScreenOf(const ICoreAnyWidget* widget,
                                                    const ICorePoint& screen);

    // The on-screen size of a widget this code did not create, for the same
    // reason the two statics above exist: an edge-anchored panel sizes itself
    // against a parent that is not an ICoreWidget.
    [[nodiscard]] static ICoreSizeF sizeOf(const ICoreAnyWidget* widget);

    // The widget's own palette background. The counterpart to
    // setSolidBackground -- NOT whatever a style sheet paints, which the
    // palette never learns about.
    [[nodiscard]] ICoreColor backgroundColor() const;

    // Let a style sheet's background/border actually paint on this widget.
    // A plain widget ignores both unless this is on; a widget that dresses
    // itself through the theme's style sheets needs it.
    void setStyledBackground(bool styled);

    // Q1.1: ICoreSizeF per Q0.2's decision (no integer ICoreSize). The member
    // stays a QSize and the setter rounds once -- every call site passes
    // integer literals, which are exact in a double.
    void setFilterCoefficient(const ICoreSizeF& coefficient);

    // How this widget wants its layout to treat its size hint, per axis.
    void setSizeBehavior(ICoreSizeBehavior horizontal, ICoreSizeBehavior vertical);

    // Watch `target` for pointer presses and report them to the
    // watchedPointerPressed hook below. The press still reaches `target`
    // untouched -- this only observes, which is what the panels that dismiss
    // a search or a popup on "user clicked over there" need.
    //
    // ⚠ ICoreNativeWidget* since Q5.1, and the history is worth keeping because
    // the type has now moved TWICE for the same underlying reason. P5.1 widened
    // it from ICoreWidget* to ICoreAnyWidget* (= QWidget*) because the dispatch
    // was a dynamic_cast to ICoreWidget* and a target that was not one -- an
    // ICoreButton, then a QPushButton subclass -- was silently unwatchable.
    // Post-conversion that argument is spent: ICoreButton and every other
    // wrapper implement ICoreNativeWidget, so the interface accepts everything
    // the QWidget* spelling did among wrappers, and every watcher in the tree
    // passes a wrapper. What it no longer accepts is a BARE toolkit widget that
    // no wrapper owns — nothing asks for that, and a site that needs it should
    // say so rather than have the whole surface stay Qt-typed for it.
    //
    // The win is at the other end: the hooks below now hand back the SAME
    // wrapper pointer the caller registered, so an overrider compares
    // `watched == closeButton` instead of unwrapping both sides.
    void watchPointerPressesOf(ICoreNativeWidget* target);

    // Watch `target` for resizes and report them to watchedResized below.
    void watchResizesOf(ICoreNativeWidget* target);

    // Watch `target` for KEY PRESSES and report them to watchedKeyPressed
    // below, which returns true to swallow the key.
    //
    // The fourth watch, added at P5.8 for the code editors: the editing surface
    // is an ICoreTextEdit, which is a QPlainTextEdit wrapper and so has none of
    // this class's hooks, and the base class that wants to reinterpret Tab is
    // not the widget the key is delivered to. Without this the only mechanism
    // was an eventFilter override -- which is precisely what stops being called
    // when ICoreWidget converts (P5.10) and is why P5.9 gates on zero of them.
    void watchKeyPressesOf(ICoreNativeWidget* target);

    // Watch `target` for pointer enter/leave and report them to
    // watchedPointerEntered/Left below. The counterpart of the press watch, for
    // a widget that must highlight while the pointer is over something else --
    // a row reacting to its own action button, a tooltip owner tracking its
    // anchor.
    void watchPointerCrossingsOf(ICoreNativeWidget* target);

    // Report this widget's PARENT changing size, to parentResized() below.
    //
    // Surface::Panel already watches its parent, but for its own purpose -- it
    // resizes itself to the parent minus a margin -- and that behaviour is
    // unchanged and stays automatic. This is the opt-in for a Surface::None
    // widget that needs to know without inheriting the snapping.
    void watchParentResizes(bool watch);

    // Report pointer MOVES anywhere in the application, to
    // applicationPointerMoved() below. The move twin of
    // watchOutsidePointerPresses, and it carries the same warning: an
    // application-wide filter sees every move in the app, so turn it off with
    // the gesture that needed it rather than leaving it installed.
    void watchApplicationPointerMoves(bool watch);

    // Watch for pointer presses ANYWHERE in the application and report the ones
    // that landed outside this widget to pointerPressedOutside() below.
    //
    // Distinct from watchPointerPressesOf, which needs a specific target. A
    // popup dismissing itself on "the user clicked away" has no such target:
    // the click can land on any widget in any window, including ones that did
    // not exist when the popup opened. Turn it OFF when the popup hides -- an
    // application-wide filter left installed sees every press in the app.
    void watchOutsidePointerPresses(bool watch);

    // Presses inside `widget` count as inside this one, so they do NOT reach
    // pointerPressedOutside(). For a popup whose trigger control sits outside
    // its own subtree -- a results panel under a search bar has to survive a
    // click on the bar that is driving it.
    void exemptFromOutsidePresses(ICoreNativeWidget* widget);

    // Let pointer events fall through to whatever is behind this widget --
    // for decorative children that must not steal their parent's hover.
    void setPointerTransparent(bool transparent);

    // Deliver enter/leave even when the widget is not tracking the mouse.
    void setHoverTracking(bool tracking);

    // Whether the style paints this widget's background at all. False leaves
    // whatever is behind it showing through wherever the widget does not paint.
    void setSystemBackground(bool paintSystemBackground);

    // Promise (or retract the promise) that paintContent covers every pixel,
    // which lets the toolkit skip erasing the area first. False is the safe
    // side for a widget with transparent regions.
    void setOpaquePaint(bool opaque);

    // Q5.1 group 3. A NAMED facade rather than a generic setAttribute, which
    // §9 refuses: this class publishes one method per attribute it actually
    // uses (setTranslucentBackground, setOpaquePaint, setPointerTransparent),
    // so a Studio caller never spells `Qt::WA_*`. Delete-on-close was the one
    // attribute with two callers and no facade.
    void setDeleteOnClose(bool deleteOnClose);

    // Q5.1. "Is the top-level I live in the one the OS has focused?"
    //
    // A PREDICATE rather than an accessor, and that is the whole point:
    // ICoreWindow.h refuses to hand back window() because the result is a raw
    // top-level with no wrapper to return. Every caller that reached for it was
    // asking this question and then comparing -- so the comparison moves in
    // here, where the raw pointer never escapes, and the refusal stands.
    [[nodiscard]] bool isInActiveWindow() const;

    // Q5.1. The ICoreWindow shell this widget lives inside, or nullptr if its
    // top-level is not one. Callers used to spell this
    // `icoreWindowOfNative(w->window())`, which needed BOTH the refused
    // window() accessor and an impl-side header at a non-sanctioned call
    // site. The raw top-level stays inside.
    [[nodiscard]] ICoreWindow* hostWindow() const;

    // setFocus with the reason spelled out. The reason is not cosmetic: a
    // field focused by Mouse does not select its contents, one focused by Tab
    // does, so the no-argument form would quietly change behaviour.
    void takeFocus(ICoreFocusReason reason = ICoreFocusReason::Mouse);

    // ------------------------------------------------------------------
    // Facade (P5.1). Everything below arrives from QWidget today and would
    // vanish at P5.10, so each one is declared here now -- while the Qt base
    // is still present and the forwarder is provably a no-op -- rather than
    // during the conversion, when a missing one is a compile error in ~96
    // subclasses at once.
    //
    // ⚠ setObjectName and setStyleSheet are the two that MUST be here: §2 R1
    // records that ICoreWidget has no QSS type selector of its own, so nothing
    // about the conversion looks like it touches styling -- and yet four #id
    // sheets go dark the moment either forwarder is missing, with no compile
    // error and no guard hit. They take ICoreString, which converts implicitly
    // from both a literal and a QString, so no call site changes.
    // ------------------------------------------------------------------

    void setObjectName(const ICoreString& name);
    void setStyleSheet(const ICoreString& sheet);

    // The pointer shape over this widget. ICoreCursorShape, NOT a new
    // ICorePointerShape -- P0.5 settled that this enum already exists and is
    // the vocabulary the tree speaks (§9).
    void setCursorShape(ICoreCursorShape shape);
    void clearCursorShape();

    // This widget's top-left within its parent. NOT covered by bounds(), which
    // is deliberately origin-relative because paint hooks want it that way.
    [[nodiscard]] ICorePoint position() const;

    // ⚠ Spelled requestRepaint(), not update(), because ICoreGraphicsView
    // already publishes requestRepaint() for exactly this operation
    // (ICoreGraphicsView.h:121). §9's rule, and the fifth time this check has
    // cancelled a second name after P0.5, P7.3, P3.4 and P2.7.
    void requestRepaint();

    // Repaint only `area` (widget coordinates). For a surface where redrawing
    // everything on every change is the cost worth avoiding -- the terminal
    // grid repaints the handful of lines the emulator marked dirty rather than
    // the whole screen, which is what keeps a fast writer from pinning the GUI
    // thread (TERMINAL_EMULATOR.md T3.2).
    //
    // An empty or invalid area is a no-op, not a full repaint: a caller that
    // computed "nothing changed" means it.
    void requestRepaint(const ICoreRect& area);

    // Take every keystroke, ahead of the application's shortcuts.
    //
    // A widget that IS a keyboard surface -- a terminal, a code editor's raw
    // mode -- needs the keys the application has bound at window scope:
    // Ctrl+C, Ctrl+V, Ctrl+Z, Tab. Window shortcuts are dispatched BEFORE the
    // focused widget's key handler, so without this those keys never arrive
    // and the widget silently ignores them, with nothing logged.
    //
    // Off by default. Turn it on only for a widget that genuinely consumes
    // raw keys, and expect the application's own shortcuts to stop working
    // while it has focus -- that is the point.
    void setClaimsKeyboard(bool claims);

    // Run `task` after `delayMs`, guarded by THIS WIDGET's lifetime: if the
    // widget dies first, the task never runs. The widget tier's twin of
    // ICoreGraphicsObject::deferToEventLoop (P2.9d-5c), replacing every
    // QMetaObject::invokeMethod(this, ...) -- those pass `this` as the QObject
    // context for exactly that guard, and dropping the context compiles and
    // then dangles. delayMs == 0 means "next event-loop turn". Safe to call
    // from a non-GUI thread: the task is marshalled to the GUI thread either
    // way, which is what the solver-thread callers in ICoreTimeLine rely on.
    // At the flip this body moves its context to the Impl; call sites stay.
    void deferToEventLoop(int delayMs, std::function<void()> task);

    // ---- P5.10 batch 1: the inherited geometry/visibility surface ----------
    //
    // These 22 are the operations subclasses reach through the QWidget base
    // today. MEASURED, not guessed: the probe (remove the Qt base in an
    // isolated export, -ferror-limit=0, compile the 182 TUs that can see
    // ICoreWidget or any of its 145 subclasses) reported 5 420 diagnostics with
    // ZERO "too many errors emitted", and these account for ~285 of the 495
    // no-member call sites.
    //
    // ⚠ ADDITIVE ON PURPOSE, AND THAT IS THE WHOLE POINT. Each one forwards to
    // QWidget:: today and becomes impl->… on the day the base is removed, so
    // the call sites never move. Landing them here shrinks the atomic step to
    // the base removal plus the constructor overloads, instead of one commit
    // that changes 495 call sites and the class shape together.
    //
    // ⚠ Only operations with NO existing ICore name are here. `update`,
    // `setSizePolicy`, `setFocus`, `setMouseTracking`, `setCursor`,
    // `mapToGlobal`, `mapFromGlobal`, `rect`, `pos`, `setAutoFillBackground`
    // and `setFocusPolicy` are all deliberately ABSENT: each already has a
    // facade twin (requestRepaint, setSizeBehavior, takeFocus, setHoverTracking,
    // setCursorShape, mapToScreen, mapFromScreen, bounds, position,
    // setStyledBackground, setFocusable) and adding the Qt spelling beside it
    // would be a second name for one thing -- §9's rule, which has now
    // cancelled a duplicate at P0.5, P7.3, P3.4, P2.7 and here. Those call
    // sites migrate to the existing name instead.
    //
    // ⚠ Absent for a different reason: setParent, setLayout, deleteLater,
    // findChild/findChildren, setGraphicsEffect/graphicsEffect. Each is an
    // OWNERSHIP or QObject-tree operation whose meaning changes when the wrapper
    // stops being a QObject -- deleteLater would delete the Impl and leave the
    // wrapper, and a findChildren tree walk stops seeing wrapper types at all.
    // They are decisions, not forwarders, and belong to the atomic step.

    void setFixedHeight(int height);
    void setFixedWidth(int width);
    void setFixedSize(int width, int height);
    void setMinimumWidth(int width);
    void setMinimumHeight(int height);
    void setMaximumWidth(int width);
    void setMaximumHeight(int height);
    [[nodiscard]] int maximumHeight() const;
    [[nodiscard]] int minimumHeight() const;
    [[nodiscard]] bool hasFocus() const;

    // The layout manages the Impl's children -- every child widget's QWidget
    // parent unwraps to the Impl -- so attaching it to the Impl is not a
    // relocation, it is where the layout always effectively lived. The
    // batch-1 list called setLayout an ownership decision; this is it,
    // decided: the Impl owns the layout, exactly as the QWidget base did.
    void setLayout(ICoreNativeLayout* layout);

    // The widget tier's deleteLater(), under a name that survives the flip --
    // the graphics tier's destroyDeferred() (P2.9d-5c), same contract: deletes
    // the WRAPPER (running the whole subclass destructor chain; the unique_ptr
    // takes the Impl with it), deferred a turn so it is safe from inside the
    // widget's own signal emissions. Never deleteLater on the Impl: that
    // deletes the toolkit object out from under the wrapper.
    void destroyDeferred();

    // Whether the pointer is currently over this widget.
    [[nodiscard]] bool underMouse() const;

    // Paint this widget (and children) into `target` -- the drag-preview path.
    // Q1.1: an ICorePixmap, not a bare paint device. Its one consumer is the
    // window-snapshot path, and icoreQt(ICorePixmap&) already has the MUTABLE
    // overload P7.4 added for exactly this write-into-the-storage case.
    void render(ICorePixmap& target);

    // The ICoreWindowNature constructor's switch, callable after construction
    // -- for the widgets that decide their window nature in their own body.
    // Supersedes ad-hoc setWindowFlags calls, which went with the Qt base.
    void adoptWindowNature(ICoreWindowNature nature);
    void resize(int width, int height);
    void adjustSize();
    void updateGeometry();
    void setContentsMargins(int left, int top, int right, int bottom);

    void move(int x, int y);
    void setGeometry(int x, int y, int width, int height);
    void setGeometry(const ICoreRect& rect);
    [[nodiscard]] int y() const;

    // ⚠ THESE TWO REVERSE A DECISION THIS FILE PREVIOUSLY RECORDED THE OTHER
    // WAY, and the reversal is the owner's, made 2026-08-12 with the trade in
    // front of them -- not an oversight and not a session quietly relitigating
    // §9. The note below about size() still stands; this is narrower than it.
    //
    // The board called the 115 `width()`/`height()` call sites "mechanical
    // migrations" onto bounds().width(). They are not, and the reason is a type
    // change: QWidget::width() returns int, ICoreRect::width() returns double
    // (ICoreRect.h:77 -- four plain doubles). The VALUE is identical, so most
    // sites would not care; but ~10 of them divide, and integer division
    // silently becomes floating-point division. ICoreRotatableArrowIcon.cpp:40
    // is the clearest -- ICorePoint(width() / 2, height() / 4) truncates today
    // and would not afterwards, moving the arrow half a pixel on odd sizes.
    // It compiles either way, so nothing would have reported it.
    //
    // Weighed against §9's "no second spelling" rule, the deciding fact is that
    // these are NOT a second spelling of bounds().width(): they differ in type
    // and in precision, which is exactly what the 10 dividing sites turn on.
    // Keeping them int leaves all 115 call sites untouched, which makes this
    // batch provably behaviour-neutral instead of 115 judgement calls.
    //
    // ⚠ Each declaration HIDES the inherited member of the same name, so the
    // bodies MUST be written QWidget:: qualified or they recurse -- the same
    // trap that already caught resize(int,int), move(int,int) and font().
    [[nodiscard]] int width() const;
    [[nodiscard]] int height() const;

    void show();
    void hide();
    void setVisible(bool visible);
    [[nodiscard]] bool isVisible() const;
    [[nodiscard]] bool isHidden() const;
    void raise();
    void activateWindow();

    void setEnabled(bool enabled);

    // ⚠ NOT setHoverTracking, and the two must never be folded together.
    // setHoverTracking sets Qt::WA_Hover, which asks the toolkit for
    // HoverEnter/HoverMove/HoverLeave. THIS asks for mouseMoveEvent to arrive
    // while NO button is held, which is what feeds the mouseMoved() hook on a
    // widget that tracks the pointer without a drag. Five classes rely on it
    // (ICoreMenu, ICoreMenuBar's titles, ICoreComboBox, the table splitter and
    // the global search dialog) and none of them also sets WA_Hover — so
    // "migrating" these to setHoverTracking would have compiled perfectly and
    // silently stopped their move handling. It looked like a second name for
    // one thing and is not; that is why it gets a forwarder rather than a
    // migration.
    void setMouseTracking(bool tracking);

    // ⚠ NOT setStyledBackground either. That one sets WA_StyledBackground, so
    // a stylesheet's background rule is honoured. THIS is Qt's
    // autoFillBackground, which fills with the palette's window role before
    // paintEvent runs. Same shape of near-miss as setMouseTracking above.
    void setAutoFillBackground(bool autoFill);

    // ---- P5.10 batch 2c: the rest of the inherited surface -----------------
    //
    // Re-measured at HEAD feb24cfd after batches 1/2/2b: the inherited bill
    // fell from 495 sites over 58 members to 150 over 28. These are the ones
    // with no facade twin to migrate to. Same contract as batch 1 -- each
    // forwards to QWidget:: today and becomes impl->... at the conversion.
    //
    // ⚠ ICoreAnyWidget (= QWidget) is the honest return type for window() and
    // parentWidget(), NOT ICoreWidget*. What comes back is whatever the toolkit
    // has up the parent chain, which is frequently a plain QWidget or a
    // not-yet-converted wrapper; narrowing the return to ICoreWidget* would be
    // a claim the tree cannot keep, and a dynamic_cast that silently yields
    // nullptr is P6.5's warning arriving early.
    [[nodiscard]] ICoreAnyWidget* window() const;
    [[nodiscard]] ICoreAnyWidget* parentWidget() const;
    [[nodiscard]] bool isAncestorOf(const ICoreAnyWidget* child) const;
    // Q5.1: the wrapper-taking twin, so a caller holding one stops unwrapping
    // just to ask. The ICoreAnyWidget form stays -- ICoreEventConversion and
    // the sanctioned zones genuinely start from a raw widget.
    [[nodiscard]] bool isAncestorOf(const ICoreWidget* child) const;

    // Returns Qt's "was it actually closed" answer; four of the nine call sites
    // read it.
    bool close();

    void setWindowTitle(const ICoreString& title);
    void setToolTip(const ICoreString& text);

    // The ratio the widget's screen is drawing at -- one caller, sizing a
    // pixmap. Named without the Qt suffix: QWidget has devicePixelRatio() (int,
    // deprecated) and devicePixelRatioF() (qreal), and only the second is
    // meaningful, so carrying the F across would preserve a distinction the
    // wrapper does not have.
    [[nodiscard]] double devicePixelRatio() const;

    [[nodiscard]] ICoreFont font() const;

    // Route Qt's two size questions through preferredSize/minimumPreferredSize,
    // falling back to the toolkit's answer when the hook declines. A subclass
    // that already overrides sizeHint() directly still wins -- these are
    // ordinary virtuals and it is further down the chain. That is why landing
    // this is additive even though wrapper-zone classes (ICoreMenu,
    // ICoreComboBox, and P5.6's three sites) still answer the Qt way.
    //
    // ⚠ PUBLIC, and it has to be. QWidget::sizeHint() is public and outside
    // code calls it on other widgets -- ICoreGlobalSearchDialog sums its
    // sections' hints to size itself. Declaring the override down in the
    // protected hook block, which is where it first went, does not just move a
    // declaration: it NARROWS the access of an inherited public member, and the
    // whole tree stops being able to ask a widget how big it wants to be.
    // Expect this for any Qt virtual that is also public API; the hooks are
    // protected, the overrides of public virtuals are not.
    // The toolkit's own answer, bypassing preferredSize -- for the wrapper
    // zone's fallback arithmetic (ICoreComboBox sizes off it).
    [[nodiscard]] QSize nativeSizeHint() const;

    [[nodiscard]] QSize sizeHint() const;
    [[nodiscard]] QSize minimumSizeHint() const;

    // ⚠ NO size() ACCESSOR, deliberately, though the P5.1 gap list asks for
    // one: bounds() already answers it. Its width()/height() ARE this widget's
    // size, and adding size() would leave two spellings of one value for the
    // next reader to choose between -- the trade §9 rejects. A caller wanting
    // an ICoreSizeF writes ICoreSizeF(bounds().width(), bounds().height()),
    // and no call site in the tree wants one today.

protected:
    // ------------------------------------------------------------------
    // The hook surface (task: Qt boundary). Subclasses OUTSIDE the wrapper
    // zone override these instead of the Qt handlers -- they cannot even
    // spell the Qt signatures without tripping tools/check_qt_boundary.sh.
    // Every hook receives ICore types only. The bool-returning hooks answer
    // "handled?": true consumes the event, false forwards it to the Qt base
    // class implementation, so an unhandled event behaves exactly as before.
    // ------------------------------------------------------------------

    // Called on every repaint, after the surface (None: nothing, Panel: the
    // rounded body) has been drawn. The painter is only valid for the call.
    virtual void paintContent(ICorePainter& painter);

    // The same call, plus the region Qt actually asked to be repainted. For a
    // widget whose paint is expensive enough to want clipping -- a long list,
    // a chart grid -- where redrawing everything on a two-pixel damage rect is
    // the cost worth avoiding.
    //
    // ⚠ These are ONE hook with two shapes, not two hooks: paintEvent calls
    // ONLY this one, and its default body calls the one-argument form above.
    // Override whichever you want; overriding both means the one-argument one
    // is never reached, because this default is what was calling it. That
    // arrangement is what keeps all 43 existing paintContent overriders working
    // untouched, which an additive task cannot do any other way.
    virtual void paintContent(ICorePainter& painter, const ICoreRect& dirty);

    // What this widget would like to be, and the smallest it can usefully be.
    //
    // ⚠ The default returns an INVALID ICoreSizeF, and that is the arming
    // mechanism rather than an oversight -- see ICoreSizeF::isValid(). Invalid
    // means "no opinion", and the toolkit's own sizeHint answers instead; a
    // widget that genuinely wants to collapse returns a valid 0x0, which is why
    // the test is isValid() and not isEmpty(). Value-returning virtuals need
    // this where the void handlers need nothing: there is no "did not handle it"
    // to return, so the sentinel has to be in the value.
    virtual ICoreSizeF preferredSize() const;
    virtual ICoreSizeF minimumPreferredSize() const;

    virtual bool mousePressed(const ICoreMouseEvent& event);
    virtual bool mouseReleased(const ICoreMouseEvent& event);
    virtual bool mouseMoved(const ICoreMouseEvent& event);
    virtual bool mouseDoubleClicked(const ICoreMouseEvent& event);
    virtual void pointerEntered();
    virtual void pointerLeft();
    virtual bool keyPressed(const ICoreKeyEvent& event);
    virtual bool keyReleased(const ICoreKeyEvent& event);
    virtual bool wheelScrolled(const ICoreWheelEvent& event);

    // ⚠ The old size is a PARAMETER, not a second hook. It used to be dropped
    // on the floor, and ICoreTable is the one place in the tree that reads it
    // (ICoreTable.cpp:52, comparing the old width to decide whether a column
    // re-layout is needed) -- P5.6's list has that site. The signature was
    // simply widened rather than overloaded because this hook had ZERO
    // overriders when P5.1 landed, so widening cost nothing and left one hook
    // where a second would have left two names for one event.
    //
    // ⚠ ICoreGraphicsView::resized(const ICoreRect& viewportBounds) keeps its
    // own different shape, and P2.11b asked for that divergence to be settled
    // here. Settled: they stay different, because they carry different VALUES
    // -- a scroll view's viewport bounds are not its widget size, and its one
    // overrider wants the viewport. Nothing ever sees both: ICoreGraphicsView
    // derives from ICoreNativeWidget, not from this class, so no subclass
    // inherits the pair and no reader has to choose between them.
    virtual void resized(const ICoreSizeF& newSize, const ICoreSizeF& oldSize);

    virtual void shown();
    virtual void hidden();

    // Focus arriving and leaving. The event carries the reason because losing
    // it is not the same as gaining it by mouse: see ICoreFocusEvent (P0.6),
    // which exists for ICoreSpinBox's select-on-Tab-but-not-on-click rule.
    virtual void focusGained(const ICoreFocusEvent& event);
    virtual void focusLost(const ICoreFocusEvent& event);

    // The widget was enabled or disabled -- for the ones that repaint
    // themselves greyed rather than letting the style do it.
    virtual void enabledChanged(bool enabled);

    // Return false to veto the close (the "unsaved changes" prompt lives in
    // an override of this).
    virtual bool closing();

    virtual bool contextMenuRequested(const ICorePoint& globalPos);

    // A widget registered with watchPointerPressesOf was just pressed.
    // ICoreNativeWidget* since Q5.1 -- and it is the SAME pointer the caller
    // handed watchPointerPressesOf, not a rediscovered one, so an overrider can
    // compare it directly against the wrapper it registered.
    virtual void watchedPointerPressed(ICoreNativeWidget* watched);

    // A widget registered with watchResizesOf just changed size.
    virtual void watchedResized(ICoreNativeWidget* watched, const ICoreSizeF& newSize);

    // A widget registered with watchPointerCrossingsOf was entered or left.
    virtual void watchedPointerEntered(ICoreNativeWidget* watched);
    virtual void watchedPointerLeft(ICoreNativeWidget* watched);

    // A widget registered with watchKeyPressesOf received a key press. Return
    // TRUE to consume it, which is the eventFilter `return true` this replaces;
    // false lets the key reach the watched widget unchanged.
    virtual bool watchedKeyPressed(ICoreNativeWidget* watched, const ICoreKeyEvent& event);

    // This widget's parent changed size. Only delivered after
    // watchParentResizes(true).
    virtual void parentResized(const ICoreSizeF& newParentSize);

    // The pointer moved anywhere in the application. Only delivered while
    // watchApplicationPointerMoves(true) is in force. The position is in SCREEN
    // coordinates, because the move that matters is usually over some other
    // widget and this one's local coordinates would be meaningless for it --
    // mapFromScreen() converts when the receiver does want its own.
    virtual void applicationPointerMoved(const ICorePoint& globalPos);

    // A pointer press landed outside this widget, everything inside it, and
    // everything handed to exemptFromOutsidePresses. Only delivered while
    // watchOutsidePointerPresses(true) is in force.
    virtual void pointerPressedOutside();

    // Drag & drop, delivered only after the subclass opts in with
    // setAcceptDrops(true). Returning true from dragEntered/dragMoved accepts
    // the drag; from dropped, the drop.
    virtual bool dragEntered(const ICoreDragEvent& event);
    virtual bool dragMoved(const ICoreDragEvent& event);
    virtual bool dropped(const ICoreDragEvent& event);

    // The drag left without dropping. No ICoreDragEvent and no bool: Qt's
    // QDragLeaveEvent carries neither position nor mime data, and there is
    // nothing to accept or decline once the drag is already gone. A widget
    // showing a drop highlight clears it here.
    virtual void dragLeft();

    // The Qt event handlers that stood here moved into the Impl at P5.10: the
    // Impl is the QWidget, so it is the object the toolkit delivers events to.
    // Each Impl override forwards to the hooks above, exactly as the handlers
    // here used to. P5.9 proved no subclass overrode any of them.

    // The outline drawn around the body. Read at paint time rather than cached,
    // so an override follows the theme with no work of its own.
    virtual ICoreColor borderColor() const;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

File-scope declarations#

// "Some widget, of a kind this API does not get to choose." The escape hatch
// for the handful of client signatures that genuinely cannot narrow to
// ICoreWidget*: a caller handing over the result of window(), or any widget it
// did not create, has nothing narrower to hand over. It is a spelling, not a
// wrapper -- there is no ICore behaviour behind it -- so a signature taking one
// should be read as "this parameter is not migrated yet", and a signature that
using ICoreAnyWidget = QWidget;

ICoreWidgetGrid.h#

src/ICoreEssentials/UI/Widgets/ICoreWidgetGrid.h

ICoreWidgetGrid#

ICoreWidgetGrid.h:12 · class · bases public ICoreWidget · pImpl · 7 declaration(s)

class ICoreWidgetGrid : public ICoreWidget {
public:
    explicit ICoreWidgetGrid(ICoreNativeWidget* parent = nullptr);

    void setColumns(int newColumns);
    void clearGrid();
    void removeWidget(ICoreWidget* widget);
    void addManagedWidget(ICoreWidget* widget);

    void enableAutoVerticalShrinking();

    ~ICoreWidgetGrid() override;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreWidgetPaintCommands.h#

src/ICoreEssentials/UI/Widgets/ICoreWidgetPaintCommands.h

Give a widget an opaque ground in color, for the widgets a client does not own and cannot subclass -- a scroll pane's viewport, most of all. Free function rather than a method because the target is any widget, and there is nothing else to hang it on.

Declares no class of its own — see the file.