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.
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.