add/remove cable by code: history?

Hi,

I’m adding/removing cable via code, on GUI thread, basically this way:

void addCable(int64_t inputModuleId, int64_t inputInputId, int64_t outputModuleId, int64_t outputInputId, int colorId) {
	rack::engine::Cable *cable = new rack::engine::Cable;
	cable->inputId = (int)inputInputId;
	cable->inputModule = APP->engine->getModule(inputModuleId);
	cable->outputId = (int)outputInputId;
	cable->outputModule = APP->engine->getModule(outputModuleId);
	APP->engine->addCable(cable);

	app::CableWidget *cableWidget = new app::CableWidget;
	cableWidget->setCable(cable);
	cableWidget->color = settings::cableColors[colorId];
	APP->scene->rack->addCable(cableWidget);
}
void removeCables(int64_t inputModuleId) {
	for (PortWidget *portWidget : getOutputs()) {
		for (CableWidget *cableWidget : APP->scene->rack->getCompleteCablesOnPort(portWidget)) {
			if (cableWidget->cable->inputModule->id == inputModuleId) {
				APP->scene->rack->removeCable(cableWidget);
				delete cableWidget;
			}
		}
	}
}

It seems to works nice. BUT: not able to push those “changes” in history. Which other context should I trigger/push to also insert those change int the history road? (so a CTRL+Z will undo the added/removed cables)?

Thanks

Some casual skimming of rack source suggest you will APP->history->push() a new CableAdd Action.

1 Like

Sorry for the big delay. Yes, it seems to works:

// history::CableAdd
history::CableAdd *h = new history::CableAdd;
h->setCable(cableWidget);
APP->history->push(h);

Should I just push CableWidget on history? No need to push also the Cable’s engine?

If I recall, Rack itself only pushes the CableAdd, but I didn’t go back to check. If you’re unsure, you can go read the Rack source yourself.

so It only add history for cablewidgets (gui side) and not engine?

Mmm… looks weirds…

This way, it visually remove it, but keep connection on CV mod in the audio thread?

Sorry, I don’t know enough about the logic of undo history to answer you. If you’re not getting the results you expect, then there’s more that must be done. Reading the Rack code and stepping through is one of the best ways to understand it. Maybe someone else with more experience will help more.

1 Like

Well, looking the source of Rack code, it seems I should call cableWidget->updateCable(), which will removeCable() from engine if cable exist: Rack/src/app/CableWidget.cpp at v2 · VCVRack/Rack · GitHub

But if I don’t call it, it seems it works anyway :open_mouth:

@Vortico can you clarify this please? Do we need to call cableWidget->updateCable(); before remove CableWidgets?

	cableWidget->updateCable(); // yes or no?
	APP->scene->rack->removeCable(cableWidget);
	delete cableWidget;

Thanks