API — ICoreBlocks/ICoreStudio/StudioObjects/Panels/ICoreAccount
The public contract of 4 header(s) under src/ICoreBlocks/ICoreStudio/StudioObjects/Panels/ICoreAccount — 4 class/struct definition(s), 52 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.
| Header | Defines | Declarations | Bases |
|---|---|---|---|
ICoreAccountPanel.h | ICoreAccountPanel | 12 | public ICoreWidget |
ICoreLicenseBanner.h | ICoreLicenseBanner | 13 | public ICoreWidget |
ICoreLicenseStateLabel.h | ICoreLicenseStateLabel | 6 | public ICoreWidget |
ICoreSignInDialog.h | ICoreSignInDialog | 21 | public ICoreDialog |
ICoreAccountPanel.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/Panels/ICoreAccount/ICoreAccountPanel.h
ICoreAccountPanel#
ICoreAccountPanel.h:42 · class · final · bases public ICoreWidget · pImpl · 12 declaration(s)
ICoreAccountPanel — who is signed in, what this copy is allowed to do, and what THIS MACHINE is holding.
class ICoreAccountPanel final : public ICoreWidget {
public:
explicit ICoreAccountPanel(ICoreWidget* parent = nullptr);
~ICoreAccountPanel() override;
// The gate this panel reads and deactivates through. NOT OWNED. Display
// facts come from icore::License, which needs nothing bound; the two
// ACTIONS (refresh, deactivate this machine) need the gate itself.
void setGate(ICoreLicenseGate* gate);
// Re-reads everything. Call it when the licence state moves; the panel does
// not subscribe to icore::License, because that view carries one callback
// and a widget taking it would unhook the shell's.
void refresh();
// ---- what it currently says, so a suite can assert sentences ----------
[[nodiscard]] ICoreString identityText() const;
[[nodiscard]] ICoreString licenceText() const;
[[nodiscard]] ICoreString machineText() const;
[[nodiscard]] ICoreString vaultDisclosureText() const;
// The provisioning sentence, or EMPTY when this session resolved a licence
// the ordinary way. Non-empty means ICoreLicenseGate::resolvedFromEnvironment()
// — the MACHINE is licensed, by a signed ICORE_LICENSE_TOKEN in the
// environment, and nobody signed in.
//
// ⚠ THE PANEL SAID NOTHING ABOUT THIS UNTIL A3.4, and it is what made a
// sign-out look broken: the panel showed a licence for an account nobody
// had signed into, sign-out emptied it, and the next launch put it back.
// The gate had answered the question all along and no caller in src/ asked.
[[nodiscard]] ICoreString provisioningText() const;
// What the session button currently offers — "Sign out" while signed in,
// "Sign in" when not. Exposed for the same reason the sentences above are:
// so a suite can assert the flip instead of a human noticing it.
[[nodiscard]] ICoreString sessionActionText() const;
// The portal, spelled once. The panel's link and any "manage seats" text
// both read this.
//
// ⚠ IT IS ITS OWN HOST — `portal.systemsicore.com`, a separate Cloudflare
// Worker — and NOT a path on the marketing site. `systemsicore.com/account`
// is not a route and never was; this link pointed at it until 2026-08-24.
[[nodiscard]] static ICoreString portalUrl();
// The same one place with the scheme trimmed, for PROSE that names where to
// go ("release a machine from your account on …"). A sentence spelling the
// host itself would be a second copy of this fact, and the second copy is
// the one that does not get changed.
[[nodiscard]] static ICoreString portalHost();
// Sign-out completed. ⚠ THE HOST MUST PUT THE WALL BACK UP — this session
// is now Unlicensed, and until 2026-08-24 nothing did: the panel reported a
// released seat and the editor carried on fully functional until the next
// launch, with no way to sign in as anybody else. ICorePrimaryWindow raises
// the sign-in dialog from here.
//
// Was `onDeactivated` while the button said "Deactivate this machine".
ICoreSignal<> onSignedOut;
// The session button was pressed while signed OUT. ⚠ The host raises the
// LOCAL sign-in dialog — not the portal. Signing in is something this
// application does over the gate it already holds; the portal is where the
// things this panel deliberately does not show live (seats, invoices, org
// admin), and sending a user there to get back into the app they are
// already looking at would be a detour with a browser in it.
//
// It goes through the host for the same reason onSignedOut does: the wall
// belongs to the window, which knows to refresh the banner afterwards, and
// two places constructing it is two places to keep in step.
ICoreSignal<> onSignInRequested;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreLicenseBanner.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/Panels/ICoreAccount/ICoreLicenseBanner.h
ICoreLicenseBanner#
ICoreLicenseBanner.h:42 · class · final · bases public ICoreWidget · pImpl · 13 declaration(s)
ICoreLicenseBanner — the one thing the licence is allowed to put in front of a user who is working.
class ICoreLicenseBanner final : public ICoreWidget {
public:
explicit ICoreLicenseBanner(ICoreWidget* parent = nullptr);
~ICoreLicenseBanner() override;
// The height the host should reserve when the banner is visible. It is
// ICoreBannerStrip::HEIGHT, spelled through that constant rather than
// repeated, so the two banners cannot end up different heights.
static const int BANNER_HEIGHT;
// Reads icore::License::instance() and re-decides. Cheap; call it from
// wherever the shell learns the state changed.
void refreshFromLicense();
// The same decision with the values handed in — what a test drives, and
// what a host with its own state already in hand should call.
void setState(icore::LicenseState state, int graceDaysRemaining);
// Whether this state is one of the two that show anything. A host can ask
// before it makes room, and a test can assert it without a screen.
[[nodiscard]] static bool isBannerState(icore::LicenseState state);
// What the strip currently says, so a suite can assert the sentence rather
// than a screenshot. Empty when the banner is not showing.
[[nodiscard]] ICoreString message() const;
// Grace only, and only until the next state change.
void dismissForThisSession();
[[nodiscard]] bool isDismissed() const;
// "Account…" was pressed. The host opens ICoreAccountPanel; the banner
// deliberately does not know how to.
ICoreSignal<> onAccountRequested;
// The strip showed or hid itself; the host re-stacks the strips under the
// top panel (ICoreStudioSurface::relayoutStripsUnderTopPanel), so the
// update banner below it moves up or down (2026-09-28).
ICoreSignal<> onVisibilityChanged;
protected:
void paintContent(ICorePainter& painter) override;
// ⚠ IT FLOATS OVER THE CANVAS NOW (owner, 2026-09-25: under the top panel,
// not under the title bar -- ICoreStudioSurface::addStripUnderTopPanel), so
// a gesture on its bare ground is swallowed, for the reason
// ICoreTopFixedPanel gives: a declined press or wheel walks on and pans,
// zooms or deselects the diagram underneath. Its buttons are children and
// are offered the gesture first, so they answer as before.
bool mousePressed(const ICoreMouseEvent& event) override;
bool mouseReleased(const ICoreMouseEvent& event) override;
bool mouseDoubleClicked(const ICoreMouseEvent& event) override;
bool wheelScrolled(const ICoreWheelEvent& event) override;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreLicenseStateLabel.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/Panels/ICoreAccount/ICoreLicenseStateLabel.h
ICoreLicenseStateLabel#
ICoreLicenseStateLabel.h:39 · class · final · bases public ICoreWidget · pImpl · 6 declaration(s)
ICoreLicenseStateLabel — the one-word licence badge at the foot of the primary window's left rail (owner, 2026-09-25).
class ICoreLicenseStateLabel final : public ICoreWidget {
public:
explicit ICoreLicenseStateLabel(ICoreWidget* parent = nullptr);
~ICoreLicenseStateLabel() override;
// The height it takes when showing: the badge plus the gap above it.
static const int LABEL_HEIGHT;
// Reads icore::License::instance() and re-decides.
void refreshFromLicense();
// The same decision with the values handed in -- what a test drives.
void setState(icore::LicenseState state, const std::string& tierId);
// What it currently says; empty when it is not showing.
[[nodiscard]] ICoreString text() const;
protected:
void paintContent(ICorePainter& painter) override;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreSignInDialog.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/Panels/ICoreAccount/ICoreSignInDialog.h
ICoreSignInDialog#
ICoreSignInDialog.h:47 · class · final · bases public ICoreDialog · pImpl · 21 declaration(s)
ICoreSignInDialog — the wall's face.
class ICoreSignInDialog final : public ICoreDialog {
public:
explicit ICoreSignInDialog(ICoreWidget* parent = nullptr);
~ICoreSignInDialog() override;
// Which of the two forms is showing. THE EMAIL AND PASSWORD ARE THE
// DEFAULT (owner, 2026-08-25): it is what somebody who has just bought has
// to hand, and the account route can reach a licence the person never
// copied anywhere. The key route stays one click away for the boxed or
// invoiced customer, and it is still the only one that can be checked
// before the network is touched.
//
// ⚠ A CASE THAT DRIVES THE KEY ROUTE MUST SAY SO. submit() reads this
// member, not the field that happens to be filled, so a suite that sets a
// licence key and submits without calling setMethod() now sends an empty
// credentials form and is refused for the wrong reason.
enum class Method { LicenseKey, EmailAndPassword };
void setMethod(Method method);
[[nodiscard]] Method method() const;
// What the method picker READS, as a user sees it.
//
// ⚠ IT EXISTS BECAUSE THE DEFAULT HAS TWO HALVES: the member above decides
// which form is visible, the combo's own selection decides what the control
// says, and they are set on two different lines. Change one and the window
// opens showing a form the picker does not name — a mismatch every case
// driving this dialog through method() would call correct.
[[nodiscard]] ICoreString methodLabel() const;
// The gate the dialog activates through. NOT OWNED, and may be null: with
// no gate the button reports that licensing is not running in this build
// instead of silently doing nothing.
void setGate(ICoreLicenseGate* gate);
// ---- the fields, so a suite can drive this with no screen -------------
void setLicenseKey(const ICoreString& key);
void setEmail(const ICoreString& email);
void setPassword(const ICoreString& password);
[[nodiscard]] ICoreString licenseKey() const;
[[nodiscard]] ICoreString email() const;
// What "Sign in" does. False means nothing was sent — the offline check
// refused, a field is empty, or there is no gate — and statusText() says
// which. True means a request is in flight; onSignedIn fires if it lands.
bool submit();
// The sentence under the form. Never empty after a failed submit().
[[nodiscard]] ICoreString statusText() const;
// WHICH BUTTON RETURN PRESSES. "Sign in", in every step and from any field.
//
// ⚠ IT EXISTS BECAUSE NOBODY DECLARED ONE. No button asked to be the
// default, so the answer was settled at SHOW time, by Qt, from the child
// order -- and "Create an account" is built first because it must sit left
// of the stretch, so Enter on a filled-in form opened a browser at the
// registration page and sent no activation. The footer's layout position and
// the meaning of the Return key are two different decisions, and nothing in
// this dialog's API could see the second one until this seam.
//
// ⚠ IT READS THE DECLARED DEFAULT, NOT A SIMULATED KEY PRESS -- the GuiLab
// has no way to send one. Measured 2026-08-26 with the three calls in the
// footer removed: this answered EMPTY on a dialog that had never been shown,
// which is the shape of the defect (nothing claimed it) rather than the
// symptom (Qt handed it to the first button). A case that wanted the symptom
// would need a shown dialog and a Return event, and would still be asserting
// Qt's rule rather than this dialog's decision.
[[nodiscard]] ICoreString defaultButtonText() const;
// Where the licence picker sits inside the dialog, in pixels from the top,
// or -1 when it is not showing.
//
// ⚠ IT EXISTS BECAUSE IT SHIPPED AT ZERO. The picker was added to the page
// layout on a line that ran BEFORE the line that constructed it, so the
// layout was handed a null pointer, the widget was parented to the dialog
// and never positioned, and it drew itself over the heading at (0,0).
// `addWidget(nullptr)` says nothing, and every case in the suite drives
// this dialog through its API rather than its geometry — so nothing in the
// tree could see it and a person had to notice. This is the seam that
// makes it visible to a test.
[[nodiscard]] int licenseChoiceTop() const;
// Where "Create an account" sends a user who has nothing to type into this
// dialog yet. Registration, payment and the licence key that comes out of
// it are the portal's, exactly as seats and invoices are — the dialog links
// to it rather than growing a second copy of it.
//
// ⚠ IT DELEGATES TO ICoreAccountPanel::portalUrl() AND SPELLS NOTHING
// ITSELF. A "/signup" path here would be a second spelling of the portal
// AND an invented route: the portal Worker serves its root and answers 404
// at /signup, /register and /sign-up (probed 2026-08-24), which is the same
// defect as the `systemsicore.com/account` link this dialog's messages
// carried until that day — a control that leads nowhere.
[[nodiscard]] static ICoreString registrationUrl();
// Opens registrationUrl() in the user's browser and writes the status line
// saying so. Exposed so a suite can drive the button's whole effect; the
// browser is the platform's and nothing here waits on it.
void openRegistrationPage();
// The seat fingerprint as a HUMAN reads it: the salted hash, truncated, with
// the ellipsis already on it. Never the raw platform id.
//
// ⚠ ONE SPELLING OF THE TRUNCATION, deliberately. Two places show this — the
// wall's dialog and the account panel — and a fingerprint shown 12 characters
// long in one and 16 in the other is a support call where neither end can
// tell whether they are looking at the same machine. The salt already lives
// in exactly one place for the same reason; this is the display half of it.
[[nodiscard]] static std::string elidedSeatFingerprint();
// Everything about THIS MACHINE that an activation carries, filled in.
// Credentials are the caller's half; this is the half that must never
// contain the raw machine id.
[[nodiscard]] static ICoreActivationRequest describeThisMachine();
// One sentence per error code the Worker and the gate can answer with, and
// NO TWO ARE THE SAME — collapsing "seat limit reached" into "sign-in
// failed" is the defect this exists to prevent, and it is invisible in
// review. An unknown code is not an error to hide: it is reported as
// itself, because a build that has not learned a code is still able to
// tell the user what the server said.
[[nodiscard]] static ICoreString errorText(const std::string& errorCode);
// Every code errorText() knows, for the case that asserts distinctness.
[[nodiscard]] static std::vector<std::string> knownErrorCodes();
// The licence was accepted and stored. The wall's host closes on this.
ICoreSignal<> onSignedIn;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};