API — ICoreSDK/ICoreModel
The public contract of 16 header(s) under src/ICoreSDK/ICoreModel — 15 class/struct definition(s), 509 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.
ICoreBlockFactory.h#
src/ICoreSDK/ICoreModel/ICoreBlockFactory.h
ICoreBlockFactory#
ICoreBlockFactory.h:7 · class · nested InitialPorts · 12 declaration(s)
class ICoreBlockFactory {
public:
// ====================[ Solver Environments ]======================
using SolverEnvCreator = std::function<std::unique_ptr<ICoreBlockSolverEnvironment>(ICoreBlock*)>;
static void registerBlockSolvEnv(const std::string& type, SolverEnvCreator creator);
static std::unique_ptr<ICoreBlockSolverEnvironment> createBlockSolverEnvironment(const std::string& type, ICoreBlock* block);
static std::unordered_map<std::string, SolverEnvCreator>& getSolverEnvRegistry();
// ====================[ Manager ]======================
static void setBlockUp(ICoreBlock* blockToSetUp);
static bool isBlockTypeValidSubsystem(const std::string &blockType);
// ====================[ Block Icons ]======================
static void registerIconSVG(const std::string &type, const char *svg);
static const char *getBlockIconSVG(const std::string &type);
// All registered block type strings (the keys of the icon catalog). The icon
// registry is populated by every block TU's static initializer, so this is the
// authoritative list of valid types. Used to validate a requested type and to
// resolve a leaf name (e.g. "Gain") to its full hierarchical type path.
static std::vector<std::string> getAllRegisteredTypes();
// ====================[ Block Descriptions ]======================
// The block's user-facing description, as HTML (see ADDING_NEW_BLOCKS.md).
// Registered by each block TU next to its icon, and handed to the block's
// configurator by its solver-environment constructor — which needs a live
// ICoreBlock. The library navigator has none: it lists TYPES, so it reads the
// description from here, exactly as it reads the icon and the port counts.
static void registerDescriptionHTML(const std::string& type, const std::string& html);
// Empty for an unregistered type, so a caller shows nothing rather than a
// placeholder. Returns a reference into the registry — valid for the process's
// lifetime, since nothing ever erases from it.
static const std::string& getBlockDescriptionHTML(const std::string& type);
// ====================[ Initial Ports ]======================
// How many ports a freshly created block of a type comes up with. Registered by
// each block TU next to its icon, and it must mirror the createNewPort() calls in
// that block's solver-environment constructor — which is where the real ports are
// born, and which needs a live ICoreBlock on a canvas inside a subsystem tree.
// A library preview has none of that, so it reads the counts from here instead.
struct InitialPorts {
int inputCount = 0;
int outputCount = 0;
};
static void registerInitialPorts(const std::string& type, int inputCount, int outputCount);
// Zeroed for an unregistered type, so a caller draws nothing rather than guessing.
static InitialPorts getInitialPorts(const std::string& type);
};
};
ICoreSubsystemTreeNode.h#
src/ICoreSDK/ICoreModel/ICoreSubsystemTreeNode.h
ICoreSubsystemTreeNode#
ICoreSubsystemTreeNode.h:17 · class · pImpl · 73 declaration(s)
class ICoreSubsystemTreeNode {
public:
// How getTreeWidgetItems() orders the entries it builds for one level of the
// navigator. The enum lives here rather than in the view because the ordering
// is applied while the items are built, and the builder is this class -- the
// view is L8 and this is L3, so the mode travels DOWN as an argument.
//
// Name -- every entry, subsystems and blocks alike, by name (A-Z).
// Kind -- subsystems first, then blocks; by name within each group.
// LastModified -- most recently modified first (see markModified()).
// DateCreated -- most recently created first.
//
// Blocks carry no timestamps of their own, so under the two date modes they
// sort after every subsystem, among themselves by name. Ties in every mode
// break on name, so the order is total and a rebuild never reshuffles.
enum class SortMode { Name, Kind, LastModified, DateCreated };
explicit ICoreSubsystemTreeNode(ICoreSubsystemTreeNode* parent = nullptr, const std::string& initName = "~auto");
ICoreBlock* createNewBlock(const std::string &type);
ICoreLink* createNewLink(std::string type);
ICoreCanvasArea* createNewCanvasArea();
ICoreCanvasTextBox* createNewTextbox();
ICoreImage* createNewImage();
void deleteBlock(ICoreBlock* block);
void deleteLink(ICoreLink* link);
void deleteCanvasArea(ICoreCanvasArea* area);
void deleteTextbox(ICoreCanvasTextBox* textbox);
void deleteImage(ICoreImage* image);
void giveOwnershipUp_Block(ICoreBlock* block);
void giveOwnershipUp_Link(ICoreLink* link);
void giveOwnershipUp_CanvasArea(ICoreCanvasArea* area);
void giveOwnershipUp_Textbox(ICoreCanvasTextBox* textbox);
void giveOwnershipUp_Image(ICoreImage* image);
void acquireOwnership_Block(ICoreBlock* block);
void acquireOwnership_Link(ICoreLink* link);
void acquireOwnership_CanvasArea(ICoreCanvasArea* area);
void acquireOwnership_Textbox(ICoreCanvasTextBox* textbox);
void acquireOwnership_Image(ICoreImage* image);
void moveLinksFromAllDescendentsToTrash() const;
void deleteLinksFromAllDescendentsPermanently() const;
bool isBlockNameAvailable(const std::string& newName, ICoreBlock* blockToExclude);
bool isLinkNameAvailable(const std::string& newName, const ICoreLink* linkToExclude) const;
bool isCanvasAreaNameAvailable(const std::string& newName, ICoreCanvasArea* areaToExclude) const;
bool isTextBoxNameAvailable(const std::string& newName, ICoreCanvasTextBox* noteToExclude);
bool isImageNameAvailable(const std::string& newName, const ICoreImage* imageToExclude) const;
void runLinkPathOptimizerToAllBlocks() const;
void deleteChildTreeNode(ICoreSubsystemTreeNode* nodeToDelete);
void permanentlyDeleteAllChildren();
void reArrangeAllChildrenZOrder() const;
ICoreRect calculateReqAreaOnCanvas() const;
ICoreSubsystemTreeNode* findTreeNodeByPath(const std::string& fullPath);
// This node as ONE navigator row, as the cells of that row left to right:
// [0] the name, with the subsystem icon and the entry-type / entry-path
// roles the view reads back -- the cell that owns the children;
// [1] last modified, formatted for display;
// [2] date created, likewise.
//
// Always three cells, even for a caller showing one column: a tree whose
// rows disagree about their cell count is a Qt model bug waiting to happen,
// and hiding a column is the view's job (ICoreTreeView::setColumnSizing),
// not the model's. Blocks appear as rows here too and have no timestamps of
// their own, so their detail cells are empty rather than invented.
//
// Ownership transfers to whatever the cells are appended to -- see
// ICoreStandardItem's Group B note.
[[nodiscard]] std::vector<ICoreStandardItem*> getTreeWidgetItems(SortMode sortMode = SortMode::Name) const;
// How the two detail cells above are rendered, and the ONE place that
// decision lives -- the navigator's column titles are written against it.
// Local time, seconds dropped: a diagram edit is not a stopwatch reading,
// and the narrow columns these sit in have no room for them.
[[nodiscard]] static std::string formatTimestampForDisplay(long long msSinceEpoch);
void pushBackChildTreeNode(ICoreSubsystemTreeNode *newChild);
void eraseChildTreeNode(const ICoreSubsystemTreeNode *childToErase);
void checkOutCanvasPointersBeforeDeletion(ICoreCanvas* canvasToCheckOut);
// ======================= Setters ==============================
void setParent(ICoreSubsystemTreeNode* parent);
void setName(const std::string& newName) const;
void reconstructPath();
void setLoadedToCanvas(ICoreCanvas* canvas);
// ---------------- The two timestamps every subsystem carries
//
// Milliseconds since the Unix epoch, in the same units ICoreDateTime takes
// (fromMSecsSinceEpoch), so a caller that wants to SHOW one hands it straight
// over. A plain integer rather than a formatted string on purpose: it sorts,
// it round-trips through the recipe without a parser, and it carries no
// locale.
//
// Both are stamped with "now" by the constructor and by resetToInitialState,
// so a node always has a real pair -- there is no invalid/zero state to guard
// at the call sites. The setters exist for ONE caller each: the recipe
// interpreter, restoring what ICoreRecipeSerializer wrote (`h.setTimes(...)`
// / `subsystemTimes(...)`). Everything else uses markModified().
void setCreatedTimeMs(long long msSinceEpoch);
void setLastModifiedTimeMs(long long msSinceEpoch);
// Stamps THIS node's last-modified with now, and every ancestor up to the
// root with it -- a change inside a subsystem is a change to each diagram
// that contains it.
//
// ⚠ What it does NOT cover: this is called from the structural edits that go
// through a tree node (an object created, deleted, renamed, or moved in or
// out of the level). Editing a block's own config or dragging it a few pixels
// never reaches this class and so does not stamp anything. That is the
// documented meaning of the property -- "when the contents of this subsystem
// last changed shape" -- not an oversight.
void markModified();
// ======================= Getters ==============================
ICoreSubsystemTreeNode* getParent() const;
std::string getPath() const;
std::string getName() const;
[[nodiscard]] long long getCreatedTimeMs() const;
[[nodiscard]] long long getLastModifiedTimeMs() const;
// int getMaxSolverOrder() const;
ICoreCanvasOriginAnchor* getCanvasOriginAnchor() const;
std::vector<ICoreSubsystemTreeNode*> getChildrenTreeNodes() const;
std::vector<ICoreBlock*> getChildrenBlocks() const;
std::vector<ICoreLink*> getChildrenLinks() const;
std::vector<ICoreCanvasArea*> getChildrenCanvasAreas() const;
std::vector<ICoreCanvasTextBox*> getChildrenTextBoxes() const;
std::vector<ICoreImage*> getChildrenImages() const;
ICoreCanvas* getCanvasLoadedTo() const;
ICoreBlock* getAssociatedSubsystemBlock() const;
std::vector<ICoreBlock*> getAllGateBlocks() const;
// std::unordered_map<int, std::vector<ICoreBlock*>> getBlocksToSolveMap() const;
// std::vector<ICoreBlock *> getMatchingOrderBlocksToSolveList(const int &order) const;
ICoreTreeNodeSolverEnvironment* getSolverEnvironment() const;
bool isHomeNode() const;
bool isRootNode() const;
bool isHomeDescendantsNode() const;
void printTree(const std::string& prefix) const;
void printLinksReport() const;
void moveAllChildrenToTrash();
void resetToInitialState(ICoreSubsystemTreeNode* parent = nullptr, const std::string& initName = "~auto");
void kill();
void setAlive();
bool isAlive() const;
~ICoreSubsystemTreeNode();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreSubsystemTreeNodeRegistry.h#
src/ICoreSDK/ICoreModel/ICoreSubsystemTreeNodeRegistry.h
======================= Path forms =========================== Tree paths are canonically rooted at the app name ("ICoreBlocks/Home/Motor"), but that first segment is noise to the user -- and hidden altogether while navigation-root access is off. These convert between the canonical form the lookups need and the form the UI shows and accepts. Every find*ByPath() below normalises through toCanonicalPath(), so callers may hand them either form.
ICoreSubsystemTreeNodeRegistry#
ICoreSubsystemTreeNodeRegistry.h:11 · class · 20 declaration(s)
class ICoreSubsystemTreeNodeRegistry {
public:
static long initializeSubsystemTreeNodeRegistry();
static ICoreSubsystemTreeNode* findTreeNodeByPath(const std::string& path);
static ICoreVariablesSpace* findVariablesSpaceByPath(const std::string& path);
static ICoreBlock* findBlockByPath(const std::string &path);
static ICorePort* findPortByPath(const std::string &path);
static const ICoreVariable* scanVariableSpacesForVariable(const ICoreBlock* parentBlock, const ICoreBlockConfigVariable *var);
// ======================= Path forms ===========================
// Tree paths are canonically rooted at the app name ("ICoreBlocks/Home/Motor"), but that
// first segment is noise to the user -- and hidden altogether while navigation-root access
// is off. These convert between the canonical form the lookups need and the form the UI
// shows and accepts. Every find*ByPath() below normalises through toCanonicalPath(), so
// callers may hand them either form.
// Adds the "<AppName>/" root segment when it is missing and trims stray outer slashes:
// "Home/Motor", "/Home/Motor" and "ICoreBlocks/Home/Motor" all canonicalise to the same
// path. An empty input stays empty, which resolves to nothing.
static std::string toCanonicalPath(const std::string& path);
// Drops the root segment while navigation-root access is off, so the user reads
// "Home/Motor". The Root node itself has no user-facing form and yields an empty string.
// With access on the canonical path is handed back untouched.
static std::string toDisplayPath(const std::string& path);
// ================= Navigation root access =====================
// Gates every user-facing route into the part of the tree that sits above Home: the Root
// node itself and its non-Home children (Temp / ClipBoard / Trash), which are internal
// staging areas for the clipboard and the recycle bin. Off by default, so the user only
// ever sees Home and its descendants. Switch it on to expose the full tree unchanged.
//
// These forward to ICoreUserPreferences, which is what stores the setting: it is reachable
// from Settings -> Advanced and from the console, and it survives a restart.
static bool isNavigationRootAccessAllowed();
static void setNavigationRootAccessAllowed(bool allowed);
// The node the navigation surfaces present as their top level: the Root node when access
// is allowed, Home otherwise.
static ICoreSubsystemTreeNode* getNavigationRootTreeNode();
// True when the node may be shown to, or navigated to by, the user. A null node is never
// visible, so callers can pass an unresolved lookup straight through.
static bool isTreeNodeUserVisible(const ICoreSubsystemTreeNode* node);
static bool isTreeNodePathUserVisible(const std::string& path);
// ======================= Getters ==============================
static ICoreSubsystemTreeNode* getRootTreeNode();
static ICoreSubsystemTreeNode* getHomeTreeNode();
static ICoreSubsystemTreeNode* getTempTreeNode();
static ICoreSubsystemTreeNode* getClipBoardTreeNode();
static ICoreSubsystemTreeNode* getTrashTreeNode();
static bool isDebugMode();
static void printGlobalTree();
};
};
ICoreBlock.h#
src/ICoreSDK/ICoreModel/Block/ICoreBlock.h
ICoreBlock#
ICoreBlock.h:15 · class · pImpl · 72 declaration(s)
class ICoreBlock {
public:
explicit ICoreBlock(ICoreSubsystemTreeNode* parent, const std::string &fullType);
std::string generateUniqueName(const std::string& prefix) const;
ICorePort* createNewPort(const std::string& portType, const std::string& initialPortDescription,
bool isOutputPort, const std::string& preferredFacing = "West");
void deletePort(ICorePort* port);
void deleteAllPorts();
void acquirePortOwnership(ICorePort* port);
void givePortOwnership(ICorePort* port);
ICoreCanvasObjectState* getState() const;
void updateToState(const ICoreCanvasObjectState* desiredState);
void assignClonedProperties(ICoreBlock* originalBlock, bool clonePorts);
void select();
void deSelect();
ICorePort* getPortByName(const std::string& portName) const;
// ======================= Helpers ==============================
bool checkNameValid(const std::string& nameToCheck);
// bool isNameAvailable(const std::string& newName);
// ======================= UI Manager ==============================
void addToCanvas(ICoreCanvas* canvas);
void freeFromCanvas();
// Layer 4: canonical "remove me from the live model graph" — detach from parent container +
// canvas/selection. Idempotent. Called by collectGarbage_Block so collection is self-sufficient.
void detachFromModel();
// ======================= Setters ==============================
// Interactive rename: validates, and reports a rejected name to the user in a modal dialog.
// Never call it for a name the code generated itself -- see setName_Raw_NoVerification.
bool setName(const std::string& name);
// Machine-set rename: no validation, no dialog. For names the code produced itself
// (generateUniqueName, a captured state) where a modal error would stall a load, an undo or a
// paste on a name the user never typed.
void setName_Raw_NoVerification(const std::string& newName);
void setCommentedOut(bool commentedOut);
// The name label under the block is per-block state, not a view setting: it is
// captured in the block's state and written to the recipe, so hiding it survives
// undo/redo and a save/reload.
void setNameLabelVisible(bool visible);
void setParent(ICoreSubsystemTreeNode* newParent);
void setAssociatedTreeNode(ICoreSubsystemTreeNode* ICoreSubsystemTreeNode);
// ======================= Appearance ==============================
//
// A block type's default look: how big it is, what shape its frame is, and
// whether the user may retype its port description labels. Every one of
// these is declared once, per type, from the block's solver-environment
// constructor in ICoreBlockLibrary.
//
// THEY LIVE HERE SO THE BLOCK LIBRARY DOES NOT HAVE TO NAME ICoreBlockView.
// That library is ~113k lines across 302 files that contain no Qt
// whatsoever -- until these calls, which reached through getBlockUI() into
// a toolkit scene object and dragged the whole widget stack in behind them, in
// 146 of those files, to say things as view-free as "a Terminator is 50x50".
// Routed through the model instead, the statement stays where it belongs
// and the dependency collapses to the one forwarding site in ICoreBlock.cpp.
//
// Forwarding, deliberately, not storage: setWidth() on the view also
// resizes the frame and re-attaches the config UI, so these have to reach
// it. What changed is who says the words, not what happens.
//
// double rather than the toolkit's real type because this header is
// toolkit-free and stays that way; the forwarding site converts.
void setWidth(double width);
void setHeight(double height);
void setRotation(double angleDegrees);
void setAllowUserEditingPortDescLabels(bool allow);
void setCircleFrame();
void setTriangleFrame();
void setFrameBackgroundColor(int red, int green, int blue);
void setFrameMinimumWidth(double width);
// Whether the block type's registered art is painted on this block's face.
// Turn it off when the face carries something else -- a live readout. The
// art stays REGISTERED either way: the library palette, the auto-inserter
// button and ICoreRecipeInterpreter's block-type check all read it from
// the factory, and a block type with no icon registered is not a valid
// block type as far as a recipe is concerned.
void setFaceIconVisible(bool visible);
// Whether this block carries a readout PLATE on its face -- the bordered
// ground setFaceText() writes into. Off by default: without this every
// block on the canvas would wear an empty one. A block type that shows a
// value turns it on once, and the plate then stays up for the block's whole
// life, EMPTY between runs rather than vanishing. An empty readout is still
// a readout; a block that loses its face looks broken.
void setFaceReadoutVisible(bool visible);
// ======================= Live face readout ==============================
//
// The text a block shows ON ITS OWN FACE, centred in the frame. Display is
// what wanted it -- Simulink paints the value on the block, and this tree
// had nowhere but the run log to put one -- and any block with a per-sample
// value to show reaches it the same way.
//
// ⚠ SAFE TO CALL FROM THE SOLVER THREAD, and that is the whole point of it
// being here rather than on the view. compute_h() runs on
// ICoreModelSimulator's worker thread and the label is a scene item, so the
// call stores the text and hops it to the GUI thread.
//
// Consecutive values COALESCE: at most one hop is ever in flight, and it
// delivers whatever the latest text is when it lands. A solver stepping
// thousands of times a second therefore costs the event loop a bounded
// number of updates instead of one per sample, and the label still settles
// on the final value of the run.
void setFaceText(const std::string& text);
// Hides the readout. Call it at the start of a run so a block does not open
// one showing the last sample of the previous one.
void clearFaceText();
// ======================= Getters ==============================
ICoreSubsystemTreeNode* getParent() const;
std::string getName() const;
std::string getType();
std::string getFullType();
std::string getPath() const;
ICoreBlockView* getBlockUI() const;
std::vector<ICorePort*> getPorts() const;
std::vector<ICorePort*> getInputPorts() const;
std::vector<ICorePort*> getOutputPorts() const;
void setGateBlock();
void setSubsystemBlock();
void setScopeBlock();
// A sink that consumes signals without charting them (Signal Recorder). Kept
// apart from setScopeBlock() because that one attaches a chart; what the two
// share is being a terminal the verifier has to record at "Output Gates and
// Sink Blocks", which is what isSinkBlock() answers for.
void setSinkBlock();
bool isGateBlock() const;
bool isSubsystemBlock() const;
bool isScopeBlock() const;
bool isSinkBlock() const;
bool isSelected() const;
bool isCommentedOut() const;
bool isNameLabelVisible() const;
bool isDebugActive() const;
std::string getClassID() const;
ICoreSubsystemTreeNode* getAssociatedTreeNode() const;
ICoreBlockSubsystemGate* getAssociatedSubsystemGate() const;
ICoreChart* getAttachedChart() const;
ICoreCanvas* getLoadedToCanvas() const;
ICoreBlockConfigurator* getBlockConfigurator() const;
ICoreBlockSolverEnvironment* getSolverEnvironment() const;
void assignSolverEnvironment(std::unique_ptr<ICoreBlockSolverEnvironment> newEnvironment);
void setTrashOrder(const int newTrashOrder);
int getTrashOrder() const;
void increaseTrashOrder();
void decreaseTrashOrder();
void resetToInitialState(ICoreSubsystemTreeNode* parent, const std::string &type);
void kill();
void setAlive();
bool isAlive() const;
~ICoreBlock();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreBlockConfigVariable.h#
src/ICoreSDK/ICoreModel/Block/BlockConfig/ICoreBlockConfigVariable.h
ICoreBlockConfigVariable deepCopy() const;
void linkToVariablesSpace(ICoreVariablesSpaceVariable* variablesSpaceVariable); void unlinkFromVariablesSpace();
ICoreVariablesSpaceVariable* getLinkedVariablesSpaceVariable() const;
Declares no class of its own — see the file.
ICoreBlockConfigurator.h#
src/ICoreSDK/ICoreModel/Block/BlockConfig/ICoreBlockConfigurator.h
Designates one (private) config variable as user-editable source code: the config dialog toolbar shows an "Edit Code" button bound to it, and the recipe serializer persists it (base64) despite it being private.
ICoreBlockConfigurator#
ICoreBlockConfigurator.h:7 · class · pImpl · 31 declaration(s)
class ICoreBlockConfigurator {
public:
explicit ICoreBlockConfigurator(ICoreBlock* parentBlock);
ICoreBlockConfigVariable* createNewVariable(const std::string& initName, const std::string& initValue, const bool& isPrivate = false);
bool isVarNameUnique(const std::string& nameToCheck) const;
void clearAllVariables_WithoutUIEntries();
void requestToShowConfigUI();
void hideConfigUI();
void deleteConfigUI();
void assignClonedProperties(ICoreBlockConfigurator* originalBlockConfigurator) const;
void setIsPinnedToCanvas(bool newIsPinned) const;
void setBlockDescription(const std::string& newBlockDescription);
void setAllowUserEditingNumberOfInputPorts(const bool& newProperty);
void setAllowUserEditingNumberOfOutputPorts(const bool& newProperty);
ICoreBlockConfigView* getConfigUI() const;
bool getIsInputPortsNumberPrivate() const;
bool getIsOutputPortsNumberPrivate() const;
void setDefaultOutputPortDescText(const std::string &newValue);
void setDefaultInputPortDescText(const std::string &newValue);
std::string getDefaultOutputPortDescText() const;
std::string getDefaultInputPortDescText() const;
// Designates one (private) config variable as user-editable source code:
// the config dialog toolbar shows an "Edit Code" button bound to it, and
// the recipe serializer persists it (base64) despite it being private.
void setCodeEditorVariableName(const std::string& configVarName);
std::string getCodeEditorVariableName() const; // "" = block has no code editor
// Which language the code editor window opens the variable in (editor
// widget + highlighter + window title). Python unless the block says so.
enum class CodeEditorLanguage { Python, C };
void setCodeEditorLanguage(CodeEditorLanguage newLanguage);
CodeEditorLanguage getCodeEditorLanguage() const;
std::string getDescriptionText() const;
std::vector<ICoreBlockConfigVariable*> getAllVariables();
ICoreBlock* getParentBlock() const;
ICoreBlockConfigVariable* getConfigVariable(const std::string& name) const;
void resetToInitialState(ICoreBlock* parentBlock);
void kill();
void setAlive();
bool isAlive() const;
~ICoreBlockConfigurator();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreBlockSubsystemGate.h#
src/ICoreSDK/ICoreModel/Block/GateBlock/ICoreBlockSubsystemGate.h
ICoreBlockSubsystemGate#
ICoreBlockSubsystemGate.h:8 · class · pImpl · 11 declaration(s)
class ICoreBlockSubsystemGate {
public:
explicit ICoreBlockSubsystemGate(ICoreBlock* parentBlock);
void deleteParentSubsystemLinkedPort(ICorePort* gateBlockPort);
void createParentSubsystemLinkedPort(ICorePort* gateBlockPort);
std::string getUniquePortDescLabelText(const bool& isOutputPort) const;
void regenerateAllParentSubsystemPortsAfterGateBlockMigration();
void deleteAllPortsAtBothBlocks();
void resetToInitialState(ICoreBlock* parentBlock);
void kill();
void setAlive();
bool isAlive() const;
~ICoreBlockSubsystemGate();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICorePort.h#
src/ICoreSDK/ICoreModel/Block/Port/ICorePort.h
ICorePort#
ICorePort.h:14 · class · pImpl · 37 declaration(s)
class ICorePort {
public:
// preferredPortFacing is not guaranteed. ICorePortsPosAligner will determine if possible! Default alignment follow rules sat in ICorePortsPosAligner
explicit ICorePort(ICoreBlock* parentBlock = nullptr, const std::string &type = "ICoreDouble",
const std::string &initialPortDescription = "", const bool isOutputPort = false, const std::string& preferredFacing = "West");
void setParentItem(ICoreBlockViewFrame* blockFrame) const;
void setWirelessPortPairedTo(ICorePort* pairingPort);
void clearWirelessPairing();
ICorePort* getWirelessPortPairedTo() const;
std::string getDescriptionLabelText() const;
void setDescriptionLabelText(const std::string& newDescText) const;
[[nodiscard]] std::string capturePortState() const;
void assignClonedProperties(const ICorePort* originalPort) const;
std::string getName();
[[nodiscard]] bool isOutputPort() const;
[[nodiscard]] int getSerializationNumber() const;
ICoreBlock* getParentBlock() const;
[[nodiscard]] std::string getType() const;
void enforceSettingPortSerializationNumber(const int& newSerializationNumber);
void overwriteSignalValue(const ICoreMatrix& newVal) const;
[[nodiscard]] ICorePortView* getPortUI() const;
// The two things the model bridge needed from the port's view, said by the
// port instead. Same reasoning as the appearance block in ICoreBlock.h:
// reaching through getPortUI() made ICorePortSolverEnvironment and
// ICoreModelVerification -- neither of which draws anything -- compile
// against the editor's widget stack to resize a label and read a position.
//
// ICorePoint rather than the view's own point type, so this header stays
// free of raw toolkit names; the forwarding site converts, and the one call
// site already assigned the result to an ICorePoint anyway.
void setSignalSizeLabel(int numOfRows, int numOfColumns) const;
[[nodiscard]] ICorePoint getCanvasBaseCoordinates() const;
std::string getPath() const;
void setIsConnected(bool newIsConnected);
void setConnectionLinkBranch(ICoreLinkBranch* newLinkBranch);
[[nodiscard]] bool getIsConnected() const;
[[nodiscard]] ICoreLinkBranch* getConnectionLinkBranch() const;
ICorePort* getConnectionSource() const;
bool isConnectedToAnyInputPort() const;
ICorePortSolverEnvironment* getSolverEnvironment() const;
ICorePort* isConnectedToValidOutputPort() const;
//const std::string& getConnectionThread() const;
//ICorePort* getConnectedToPort() const;
ICoreMatrix* getSignal() const;
// Layer 4: canonical "remove me from the live model graph" — sever the cross-references a port
// can dangle (link-branch connection + wireless gate pairing). Idempotent. Called by
// collectGarbage_Port. NOTE: ports-vector removal + gate-mirror teardown stay in
// ICoreBlock::givePortOwnership (single-shot, not idempotent), so detachFromModel does NOT route
// through it.
void detachFromModel();
// --- Clear connection ---
void clearConnection();
//void removeOtherSidePortConnectionProperty(ICorePort* otherSidePort);
void removePortConnection(ICorePort* portToRemove, ICoreLink* connectionLink);
ICoreSubsystemTreeNode* getGrandParentTreeNode() const;
void printConnectionDetails() const;
void resetToInitialState(ICoreBlock* parentBlock, const std::string &type, const std::string &initialPortDescription,
const bool isOutputPort, const std::string& preferredFacing);
void kill();
void setAlive();
bool isAlive() const;
~ICorePort();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreEditorHost.h#
src/ICoreSDK/ICoreModel/Host/ICoreEditorHost.h
ICoreEditorHost#
ICoreEditorHost.h:40 · class · nested ConsoleResult · 21 declaration(s)
ICoreEditorHost -- what the simulation kernel needs FROM whatever is hosting it, expressed as something the kernel owns.
class ICoreEditorHost {
public:
virtual ~ICoreEditorHost() = default;
// Matches the levels the run-diagnosis panel already understood, so the
// meaning of a level is unchanged by the move -- only who names it.
enum class DiagnosticLevel {
Log = 0,
Warning = 1,
Error = 2,
};
// Outcome of evaluating one console line. A plain value type so the kernel
// is not handed a widget's result struct.
struct ConsoleResult {
bool ok = false;
std::string output;
};
// --- run diagnostics ---------------------------------------------------
virtual void diagnosticLogged(const std::string& message, DiagnosticLevel level);
virtual void diagnosticsCleared();
// --- user-facing notifications -----------------------------------------
virtual void notifyFriendly(const std::string& title, const std::string& message);
virtual void notifyWarning(const std::string& title, const std::string& message);
virtual void notifyError(const std::string& title, const std::string& message);
// --- simulator lifecycle -----------------------------------------------
virtual void solverStarted();
virtual void solverPaused();
virtual void solverStopped(bool wasAborted);
virtual void debugModeStarted();
virtual void progressReset();
// A run that ends BEFORE the solver starts -- the build failed, or the canvas has
// nothing on it. NOT solverStopped: no solver ran, so there is no outcome to
// announce, and whoever aborted has already said why (a "Nothing to Simulate"
// notification, a build failure in the diagnostics). A host still has to hear it,
// because a run's controls go inert the moment the build starts and this is the
// only thing left that can put them back.
virtual void solverStartupAborted();
// --- model configuration ------------------------------------------------
virtual void startTimeChanged();
virtual void stopTimeChanged();
// --- model build lifecycle ----------------------------------------------
//
// modelBuildFinished is raised for BOTH outcomes, from the one place the build
// returns from. modelBuildFailed stays what it always was -- the failure-only
// hook the port signal-type tags key off -- so a host that wants "the build is
// over, whatever it did" has something to hang a busy indicator off, and one
// that only cares about failure is unchanged.
virtual void modelBuildStarted();
virtual void modelBuildFinished(bool succeeded);
virtual void modelBuildFailed();
// --- navigation policy ---------------------------------------------------
virtual void navigationAccessChanged();
// --- the one REQUEST rather than notification ----------------------------
//
// Everything above tells the host something happened. This asks it to do
// something and hands back the answer, because the console grammar the
// script runner needs lives in the panel that implements it. The default
// returns a failed result rather than pretending to have run the line: a
// host with no console genuinely cannot evaluate one, and silently
// reporting success would make a script look like it had worked.
virtual ConsoleResult evaluateConsoleLine(const std::string& line);
// The host in force. Never null -- with none registered this is a shared
// do-nothing instance, which is exactly right for a headless process.
static ICoreEditorHost& instance();
// Registers the host. Pass nullptr to go back to the do-nothing default,
// which is what a teardown should do rather than leave a dangling host
// behind for late kernel activity to call into.
static void setInstance(ICoreEditorHost* host);
};
};
ICoreLink.h#
src/ICoreSDK/ICoreModel/Link/ICoreLink.h
Layer 4: canonical "remove me from the live model graph" — detach from parent container + canvas/selection. Idempotent. Called by collectGarbage_Link so collection is self-sufficient.
ICoreLink#
ICoreLink.h:11 · class · pImpl · 38 declaration(s)
class ICoreLink {
public:
explicit ICoreLink(ICoreSubsystemTreeNode* parent, std::string type);
std::string generateUniqueName(const std::string& prefix) const;
ICoreLinkBranch* createNewBranch();
void giveBranchOwnershipUp(ICoreLinkBranch* branchToGiveUp, bool forceRootBranchRemoval);
void acquireBranchOwnership(ICoreLinkBranch* branchToAcquire);
void deleteBranch(ICoreLinkBranch* branchToDelete);
void clearAllBranches_IncludingRoot();
void addToCanvas(ICoreCanvas* canvas);
void freeFromCanvas();
// Layer 4: canonical "remove me from the live model graph" — detach from parent container +
// canvas/selection. Idempotent. Called by collectGarbage_Link so collection is self-sufficient.
void detachFromModel();
std::string parseRootBranchState() const;
static std::string parseNoneRootBranchState(const ICoreLinkBranch* branchToCaptureState);
ICoreCanvasObjectState* getState() const;
void updateToState(ICoreCanvasObjectState* desiredState);
void updateRootBranchToState(const ICoreCanvasObjectState* fullLinkDesiredState) const;
void updateNoneRootBranchesToState(const ICoreCanvasObjectState* fullLinkDesiredState);
static std::vector<std::string> splitByDollarSign(const std::string& input);
static std::vector<ICorePoint> parsePoints(const std::string& str);
void ensureAllBranchesSplitFromLinkRoot() const;
void setParent(ICoreSubsystemTreeNode* newParent);
void setName(const std::string& newName);
ICoreSubsystemTreeNode* getParent() const;
std::string getName();
std::string getType();
std::string getPath() const;
ICoreCanvas* getDrawnToCanvas() const;
std::string getClassID() const;
ICoreLinkBranch* getRootBranch() const;
std::vector<ICoreLinkBranch*> getAllBranches() const;
void setTrashOrder(const int newTrashOrder);
int getTrashOrder() const;
void increaseTrashOrder();
void decreaseTrashOrder();
void resetToInitialState(ICoreSubsystemTreeNode* parent, std::string type);
void kill();
void setAlive();
bool isAlive() const;
~ICoreLink();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreLinkBranch.h#
src/ICoreSDK/ICoreModel/Link/ICoreLinkBranch.h
Corners are MODEL coordinates. There used to be two overloads here -- one taking the toolkit's point vector and one taking ICorePoint -- because a std::vector does not convert between value types even when its elements do. Now that the branch stores ICorePoint, the two collapsed into this one; it does NOT touch the sign of y (these coordinates are already in the +y-down sense, same contract as ICoreRecipeStudioBridge's).
Taken BY VALUE because optimize_unusedPath rewrites the path in place.
ICoreLinkBranch#
ICoreLinkBranch.h:12 · class · pImpl · 81 declaration(s)
class ICoreLinkBranch {
public:
explicit ICoreLinkBranch(ICoreLink* parentLink = nullptr);
// Corners are MODEL coordinates. There used to be two overloads here -- one
// taking the toolkit's point vector and one taking ICorePoint -- because a
// std::vector does not convert between value types even when its elements
// do. Now that the branch stores ICorePoint, the two collapsed into this
// one; it does NOT touch the sign of y (these coordinates are already in
// the +y-down sense, same contract as ICoreRecipeStudioBridge's).
//
// Taken BY VALUE because optimize_unusedPath rewrites the path in place.
void setBranchCorners(std::vector<ICorePoint> newBranchCorners, bool allowUpdateUI);
void setBranchCorners_RelativeToCanvasOriginAnchor(const std::vector<ICorePoint> &newBranchCorners, bool allowUpdateUI);
void reRunPathPlannerOverUnusedPath(std::vector<ICorePoint>& pathToRecreate);
void updateCornerCoordinates(const int& index, const ICorePoint& newCorner);
void translateCorner(const int& index, const double& dx, double& dy);
void translateBranch(ICorePoint delta);
void offsetPosition(ICorePoint delta);
void ungrabMouse() const;
void assignBranchConnection(ICorePort* tailPortToAssign, ICoreLinkBranch* branchSplittingFrom,
ICorePort* headPortToAssign, bool moveBranchOwnership);
// Add new branch segments. Call from here
ICoreLinkBranchSegment* addSegmentAtStart();
ICoreLinkBranchSegment* addSegmentAtEnd();
ICoreLinkBranchSegment* addSegmentAtIndex(int index);
// ====== These three don't add the new segments to the corners list (Raw). Call them from addSegmentAt...
ICoreLinkBranchSegment* createNewSegment_insertAtBranchStart(ICorePoint startCorner, ICorePoint endCorner);
ICoreLinkBranchSegment* createNewSegment_insertAtBranchEnd(ICorePoint startCorner, ICorePoint endCorner);
ICoreLinkBranchSegment* createNewSegmentAtIndex(int index);
static double computeDirectionalCost(
const ICorePoint& point,
const ICorePoint& closestOnSegment,
const ICorePoint& segmentStart,
const ICorePoint& segmentEnd);
static ICorePoint computeVector(const ICorePoint& from, const ICorePoint& to);
void addCornerAtEnd(ICorePoint newCorner);
void clearAllSegments();
// void resetAllBranchSegment() const;
// void adjustNumberOfSegment(const int& newNumberOfSegment);
void assignClonedProperties(const ICoreLinkBranch* originalBranch);
void setTailPort(ICorePort* newTailPort);
void setHeadPort(ICorePort* newHeadPort);
ICorePort* getTailPort() const;
ICorePort* getHeadPort() const;
ICoreLinkBranchTail* getBranchTail() const;
ICoreLinkBranchHead* getBranchHead() const;
void addToCanvas(ICoreCanvas* canvas);
void freeFromCanvas();
ICorePoint getClosestPointOnBranch(const ICorePoint& PointToCheckTo) const;
ICoreLinkBranchSegment* getClosestSegmentToPoint(const ICorePoint& targetPoint) const;
void updateUI();
void updateHeadAndTailPosOrientation() const;
void setConnectedStyle() const;
void setUnconnectedStyle() const;
void optimize_unusedPath(std::vector<ICorePoint>& newBranchCorners);
void optimize_usedPath();
static int countCorners(const std::vector<ICorePoint>& pathToCount);
bool doesPointLayOnBranch(const ICorePoint& pointToCheck) const;
void minimizeCorners(std::vector<ICorePoint> &originalPath) const;
static ICorePoint tryUpdatingPerpendicularCorner(const ICorePoint& previousCorner, const ICorePoint& thisCorner, const ICorePoint& nextCorner);
std::vector<ICorePoint> getBranchCorners_RelativeToCanvasOriginAnchor() const;
static void printDirections(const std::vector<ICorePoint>& path);
bool isRootBranch() const;
void shiftBranchCorners_X(double delta_x);
void shiftBranchCorners_Y(double delta_y);
void shiftBranchToTailCoords(ICorePoint newTailCoords);
void select();
void deSelect();
bool isSelected() const;
void setSegUnderCursor(ICoreLinkBranchSegment* segment);
std::vector<ICoreLinkBranch*> getSplitToBranches() const;
std::vector<ICorePoint> getBranchCorners() const;
std::vector<ICoreLinkBranchSegment*>& getBranchUISegments();
ICoreLink* getParentLink() const;
ICorePoint getTailCoordinates() const;
ICorePoint getHeadCoordinates() const;
void setZValue(int minZOrder);
bool getIsSplittingFromAnotherBranch() const;
ICoreLinkBranch* getSplittingFromBranch() const;
ICoreLinkBranchSegment* getSegUnderCursor() const;
ICoreLinkBranchSegmentMover* getBranchSegmentMover() const;
void ensureBranchTailLaysOnBranchingLink();
static void mergeCollinear_pathUnusedYet(std::vector<ICorePoint>& path);
void mergeCollinear_currentUsedPath();
static bool isCollinear(const ICorePoint& a, const ICorePoint& b, const ICorePoint& c, double eps = 1e-8);
static bool segmentsIntersect(const ICorePoint& p1, const ICorePoint& p2,
const ICorePoint& q1, const ICorePoint& q2,
ICorePoint& intersection);
static void removeLoops(std::vector<ICorePoint>& path);
static void normalizeRadAngle(double& angle);
void setAllowOptimizationAtPortMove(const bool& newAllow);
bool isOptimizationAllowedAtPortMove() const;
void setIsBranchDirectPath(bool newIsBranchDirectPath);
void setParentLink(ICoreLink* newParentLink);
void resetBranchMigrationOrder();
void incrementBranchMigrationOrder();
int getMigrationOrder() const;
bool isPathFreeOfObstacles(const std::vector<ICorePoint>& originalPath) const;
static bool lineIntersectsRect(const ICoreRect& rect, const ICorePoint& p1, const ICorePoint& p2);
void printConnectionDetails() const;
void resetToInitialState(ICoreLink* parentLink = nullptr);
void kill();
void setAlive();
bool isAlive() const;
~ICoreLinkBranch();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreBlockSolverEnvironment.h#
src/ICoreSDK/ICoreModel/SolverEnvironments/ICoreBlockSolverEnvironment.h
ICoreBlockSolverEnvironment#
ICoreBlockSolverEnvironment.h:11 · class · pImpl · 59 declaration(s)
class ICoreBlockSolverEnvironment {
public:
// ------------------------------------------------------
// Constructor
// ------------------------------------------------------
explicit ICoreBlockSolverEnvironment(ICoreBlock* parentBlock);
// DECLARED here, DEFINED in the .cpp: the residue below is a unique_ptr to an
// incomplete Impl, and every one of the 286 derived blocks destroys this base.
virtual ~ICoreBlockSolverEnvironment();
// ------------------------------------------------------
// Solver Order Assignment (Recursive)
// ------------------------------------------------------
int assignSolverOrder();
// ------------------------------------------------------
// State Space
// ------------------------------------------------------
void initializeStateSpace_Continues(const ICoreMatrix& A, const ICoreMatrix& B, const ICoreMatrix& C, const ICoreMatrix& D);
void initializeStateSpace_Continues(const ICoreMatrix &A, const ICoreMatrix &Bu, const ICoreMatrix &Bf,
const ICoreMatrix &C, const ICoreMatrix &Du, const ICoreMatrix &Df);
void initializeStateSpace_Discrete(const ICoreMatrix &A, const ICoreMatrix &B, const ICoreMatrix &C,
const ICoreMatrix &D, const double &Ts);
void initializeStateSpace_Discrete(const ICoreMatrix &A, const ICoreMatrix &Bu, const ICoreMatrix &Bf,
const ICoreMatrix &C, const ICoreMatrix &Du, const ICoreMatrix &Df,
const double &Ts);
void discretize();
// Clears stateSpace_cont back to its default-constructed (empty) value and drops the
// valid flag. Needed by blocks whose state-space representability depends on a config
// that can change between runs -- Gain, whose "Multiplication Type" is only expressible
// as y = D*u in some modes -- because the flag is otherwise sticky: once a suitable
// config had set it, a later unsuitable one would leave callers merging stale matrices.
void clearStateSpace_cont();
// Virtual so a block can refuse to hand out a state space its current config does not
// actually satisfy (see the Gain override), rather than returning a stale or meaningless one.
[[nodiscard]] virtual ICoreStateSpace getStateSpace_cont() const;
[[nodiscard]] ICoreStateSpace getStateSpace_disc() const;
// True once initializeStateSpace_Continues has been called at least once. Blocks that never
// model continuous dynamics (Gain, Sum, Mux, ...) leave stateSpace_cont at its default-constructed
// 1x1 zero matrices, which is shape-valid but mathematically meaningless — callers reasoning about
// stateSpace_cont (e.g. series/parallel merging) must gate on this rather than inspecting matrix sizes.
[[nodiscard]] bool hasValidStateSpace_cont() const;
// ------------------------------------------------------
// Reset
// ------------------------------------------------------
void resetSolverOrder();
void clearVisitedBlocks();
void clearInternalStates();
void assignHomeTreeNodeSampling();
// ------------------------------------------------------
// Block Sampling
// ------------------------------------------------------
void assignSamplingTime();
// ------------------------------------------------------
// Solve Step
// ------------------------------------------------------
void setInitialState(const ICoreMatrix& initialState);
void solve(const double &tn);
// ------------------------------------------------------
// Ports signal size
// ------------------------------------------------------
virtual void initializePortSignalSize();
virtual bool verifyInitializedPortSignals();
// Port sizing runs as a convergence loop (ICoreModelBuild::initializePortsSignalMatrixSize),
// so the per-block line initializePortSignalSize() logs would otherwise be repeated once per
// block per pass. The build turns it off after the first pass and back on when it is done.
static void setPortSizingLogEnabled(const bool& enabled);
// For an override that logs its own sizing failures. Anything a block reports from
// initializePortSignalSize() is reported once per pass unless it asks this first --
// and a PERMANENT failure (no runtime, code that will not compile) is reported on
// every one of them, which is how the diagnostics panel came to receive thousands of
// copies of two lines and take the GUI thread down with it.
[[nodiscard]] static bool isPortSizingLogEnabled();
// ------------------------------------------------------
// Block Config
// ------------------------------------------------------
virtual void loadBlockConfig();
// ------------------------------------------------------
// Block Simulation
// ------------------------------------------------------
virtual ICoreMatrix compute_f(const ICoreMatrix& x, const std::vector<ICoreMatrix>& u, const double& t);
virtual std::vector<ICoreMatrix> compute_h(const ICoreMatrix& x, const std::vector<ICoreMatrix>& u, const double& t);
virtual ICoreMatrix compute_f_discrete(const ICoreMatrix& x, const std::vector<ICoreMatrix>& u, const double& t);
virtual std::vector<ICoreMatrix> compute_h_discrete(const ICoreMatrix& x, const std::vector<ICoreMatrix>& u, const double& t);
virtual void onSolverFinish();
// ------------------------------------------------------
// Coder
// ------------------------------------------------------
virtual std::string generateBodyCode_Python();
virtual std::string generateParamsCode_Python(const std::string& blockFuncName) const;
virtual std::string generateBodyCode_Matlab();
virtual std::string generateParamsCode_Matlab(const std::string& blockFuncName) const;
virtual std::string generateBodyCode_Java();
virtual std::string generateParamsCode_Java(const std::string& blockFuncName) const;
virtual std::string generateBodyCode_Rust();
virtual std::string generateParamsCode_Rust(const std::string& blockFuncName) const;
virtual std::string generateBodyCode_C();
virtual std::string generateParamsCode_C(const std::string& blockFuncName) const;
virtual std::string generateStateCode_C(const std::string& blockFuncName) const; // persistent C state fields
virtual std::string generateBodyCode_Cpp();
virtual std::string generateParamsCode_Cpp(const std::string& blockFuncName) const;
virtual std::string generateBodyCode_VHDL();
virtual std::string generateParamsCode_VHDL(const std::string& blockFuncName) const;
virtual std::string generateStateDeclCode_VHDL(const std::string& blockFuncName) const; // persistent architecture-scope state signals
virtual std::string generateStateResetCode_VHDL(const std::string& blockFuncName) const; // rst-branch seeding for the above
virtual std::string generateBodyCode_Verilog();
virtual std::string generateParamsCode_Verilog(const std::string& blockFuncName) const;
virtual std::string generateStateDeclCode_Verilog(const std::string& blockFuncName) const; // persistent module-scope state regs
virtual std::string generateStateResetCode_Verilog(const std::string& blockFuncName) const; // rst-branch seeding for the above
virtual std::string generateBodyCode_SystemVerilog();
virtual std::string generateParamsCode_SystemVerilog(const std::string& blockFuncName) const;
virtual std::string generateStateDeclCode_SystemVerilog(const std::string& blockFuncName) const; // persistent module-scope state regs
virtual std::string generateStateResetCode_SystemVerilog(const std::string& blockFuncName) const; // rst-branch seeding for the above
virtual std::string generateDeclCode_PLC_ST();
virtual std::string generateBodyCode_PLC_ST();
virtual std::string generateParamsCode_PLC_ST(const std::string& blockFuncName) const;
// ------------------------------------------------------
// Getters
// ------------------------------------------------------
void setDiscreteOnlyBlock(const bool& newDiscreteOnlyBlock);
[[nodiscard]] int getSolverOrder() const;
[[nodiscard]] double getSamplingTime() const;
[[nodiscard]] ICoreBlock* getParentBlock() const;
[[nodiscard]] ICoreMatrix& getConfig_matrix(const std::string& key);
[[nodiscard]] std::string& getConfig_string(const std::string& key);
[[nodiscard]] std::vector<ICorePort*> getInputPorts() const;
[[nodiscard]] std::vector<ICorePort*> getOutputPorts() const;
[[nodiscard]] double get_tn_1() const;
[[nodiscard]] double get_dt() const;
void printConfigMap_double() const;
void printConfigMap_string() const;
// The per-block rate config EVERY block carries (created in the constructor).
// Public because the Simulink bridge maps it onto Simulink's SampleTime for
// every block type rather than per entry — the two share a convention:
// <= 0 inherits the surrounding rate, > 0 is an explicit period.
static const std::string CONFIG_SAMPLING_TIME;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICorePortSolverEnvironment.h#
src/ICoreSDK/ICoreModel/SolverEnvironments/ICorePortSolverEnvironment.h
ICorePortSolverEnvironment#
ICorePortSolverEnvironment.h:8 · class · pImpl · 8 declaration(s)
class ICorePortSolverEnvironment {
public:
explicit ICorePortSolverEnvironment(ICorePort* parentPort);
void setPortSignalSize(const size_t& newNumOfRows, const size_t& newNumOfColumns);
void resetPortSignal();
size_t getPortSignalNumOfRows() const;
size_t getPortSignalNumOfColumns() const;
ICoreMatrix* getSignal() const;
void resetToInitialState();
~ICorePortSolverEnvironment();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreTreeNodeSolverEnvironment.h#
src/ICoreSDK/ICoreModel/SolverEnvironments/ICoreTreeNodeSolverEnvironment.h
ICoreTreeNodeSolverEnvironment#
ICoreTreeNodeSolverEnvironment.h:7 · class · pImpl · 8 declaration(s)
class ICoreTreeNodeSolverEnvironment {
public:
explicit ICoreTreeNodeSolverEnvironment();
void setMaxSolverOrder(const int &newMaxSolverOrder);
void addMatchedOrderBlocks(const int& order, const std::vector<ICoreBlock*>& blocks);
int getMaxSolverOrder() const;
std::unordered_map<int, std::vector<ICoreBlock *>> getBlocksToSolveMap() const;
std::vector<ICoreBlock *> getMatchingOrderBlocksToSolveList(const int &order) const;
void resetToInitialState();
~ ICoreTreeNodeSolverEnvironment();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreVariablesSpace.h#
src/ICoreSDK/ICoreModel/VariablesSpace/ICoreVariablesSpace.h
ICoreVariablesSpace#
ICoreVariablesSpace.h:17 · class · pImpl · 30 declaration(s)
Backend model: a storage of variables.
class ICoreVariablesSpace {
public:
explicit ICoreVariablesSpace(ICoreSubsystemTreeNode* parent);
// Layer 4: canonical "remove me from the live model graph". A variables space is held by its
// parent tree node via a single pointer (no children vector), and its UI now lives in the left
// fixed panel (not the canvas), so this is just a selection detach. Idempotent.
void detachFromModel();
// -------------------------------------------------------------------------------------------
// View registry. Each ICoreVariablesSpaceView attaches itself on construction and detaches on
// destruction. refreshAllUIs() tells every attached view to re-read the model.
// -------------------------------------------------------------------------------------------
void attachUI(ICoreVariablesSpaceView* ui);
void detachUI(ICoreVariablesSpaceView* ui);
void refreshAllUIs();
// Read access for views to render rows from the model.
[[nodiscard]] const std::vector<ICoreVariablesSpaceVariable*>& getAllVariables() const;
// Commit helpers called by a view when a cell loses focus. The model validates/writes the data
// and then re-syncs all views (so a rejected duplicate name is reverted everywhere). Returns
// true only when the stored data actually changed (so callers can autosave just on real edits;
// a no-op re-entry or a rejected duplicate name returns false).
bool commitVariableName(ICoreVariablesSpaceVariable* var, const std::string& candidate);
bool commitVariableValue(ICoreVariablesSpaceVariable* var, const std::string& value);
ICoreVariablesSpaceVariable* createNewVariable();
bool isVariableNameUnique(const std::string &nameToCheck, const ICoreVariablesSpaceVariable* variableToExclude = nullptr) const;
// Programmatic declaration (e.g. from the command console, not a table view). Upserts by name:
// updates the value if the name already exists, otherwise fills the first empty placeholder row
// or appends a new one. Re-syncs all attached views. Returns false only for an empty name.
bool declareVariable(const std::string& name, const std::string& value);
// Programmatic declaration of a recorded signal, the Signal Recorder block's
// way in. Same upsert-by-name semantics as declareVariable() -- it just
// serialises the series to its canonical timeseries(...) string first, so
// the stored entry is an ordinary variable that happens to type as
// "Time Series". Returns false for an empty name or an invalid series
// (mismatched time/value lengths), never storing a half-formed one.
//
// Not thread safe: it re-syncs the attached views, so it must be called on
// the GUI thread. A block recording from the solver thread has to marshal
// (see the Signal Recorder's onSolverFinish).
bool declareTimeSeries(const std::string& name, const ICoreTimeSeries& series);
void deleteVariable(ICoreVariablesSpaceVariable* varToDelete);
void clearAllVariables();
void autoAdjustNumOfRows();
// -------------------------------------------------------------------------------------------
// Read-only access for the rest of the backend.
//
// The variables space is a pure "space of variables": it is edited *only* through its views.
// Other modules must never mutate it; they may only read a variable's value/type by name
// through this API. Only variables with a non-empty name count as defined (empty placeholder
// rows are skipped).
// -------------------------------------------------------------------------------------------
[[nodiscard]] bool hasVariable(const std::string& name) const;
[[nodiscard]] std::string getVariableValue(const std::string& name) const; // "" if not found
[[nodiscard]] std::string getVariableType(const std::string& name) const; // "" if not found
[[nodiscard]] const ICoreVariable* getVariable(const std::string& name) const; // nullptr if not found
[[nodiscard]] std::vector<std::pair<std::string, std::string>> getAllDefinedVariables() const;
// Recorded-signal reads. getTimeSeries() returns false when the name is
// unknown, holds something that is not a time series, or holds one whose
// stored string no longer parses -- callers get an empty series in every
// failure case and never a partially filled one.
[[nodiscard]] bool getTimeSeries(const std::string& name, ICoreTimeSeries& out) const;
// Names of every entry currently typing as "Time Series", in table order.
// This is what the math tool windows list as their available signals.
[[nodiscard]] std::vector<std::string> getAllTimeSeriesNames() const;
[[nodiscard]] ICoreCanvasObjectState* getState() const;
void updateToState(ICoreCanvasObjectState *desiredState);
ICoreSubsystemTreeNode* getParent() const;
[[nodiscard]] std::string getName() const;
[[nodiscard]] std::string getPath() const;
void select();
void deSelect();
bool isEmpty() const;
bool isSelected() const;
const std::string& getClassID();
~ICoreVariablesSpace();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreVariablesSpaceVariable.h#
src/ICoreSDK/ICoreModel/VariablesSpace/ICoreVariablesSpaceVariable.h
ICoreVariablesSpaceVariable#
ICoreVariablesSpaceVariable.h:11 · class · pImpl · 8 declaration(s)
Pure data model for a single variables-space entry.
class ICoreVariablesSpaceVariable {
public:
explicit ICoreVariablesSpaceVariable(ICoreVariablesSpace* parentSpace);
// Data-only mutators (no UI). Type is derived from the value by the underlying ICoreVariable.
std::string setName(const std::string& newName) const;
std::string setValue(const std::string& newValue);
ICoreVariable* getSyntraVariable() const;
[[nodiscard]] std::string getName() const;
[[nodiscard]] std::string getValue() const;
[[nodiscard]] std::string getType() const;
~ICoreVariablesSpaceVariable();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};