Merge pull request #14027 from huffman/feat/deprecate-undo-stack

Remove UndoStack API
This commit is contained in:
Brad Hefta-Gaub 2018-10-01 17:13:48 -07:00 committed by GitHub
commit 7c9464572a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 102 additions and 143 deletions

View file

@ -976,7 +976,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
_window(new MainWindow(desktop())),
_sessionRunTimer(startupTimer),
_previousSessionCrashed(setupEssentials(argc, argv, runningMarkerExisted)),
_undoStackScriptingInterface(&_undoStack),
_entitySimulation(new PhysicalEntitySimulation()),
_physicsEngine(new PhysicsEngine(Vectors::ZERO)),
_entityClipboard(new EntityTree()),
@ -3095,7 +3094,6 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
surfaceContext->setContextProperty("AvatarManager", DependencyManager::get<AvatarManager>().data());
surfaceContext->setContextProperty("UndoStack", &_undoStackScriptingInterface);
surfaceContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
surfaceContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
@ -6767,8 +6765,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
scriptEngine->registerGlobalObject("AvatarManager", DependencyManager::get<AvatarManager>().data());
scriptEngine->registerGlobalObject("UndoStack", &_undoStackScriptingInterface);
scriptEngine->registerGlobalObject("LODManager", DependencyManager::get<LODManager>().data());
scriptEngine->registerGlobalObject("Paths", DependencyManager::get<PathUtils>().data());

View file

@ -23,7 +23,6 @@
#include <QtGui/QImage>
#include <QtWidgets/QApplication>
#include <QtWidgets/QUndoStack>
#include <ThreadHelpers.h>
#include <AbstractScriptingServicesInterface.h>
@ -70,7 +69,6 @@
#include "ui/OctreeStatsDialog.h"
#include "ui/OverlayConductor.h"
#include "ui/overlays/Overlays.h"
#include "UndoStackScriptingInterface.h"
#include "workload/GameWorkload.h"
@ -189,7 +187,6 @@ public:
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
QSharedPointer<EntityTreeRenderer> getEntities() const { return DependencyManager::get<EntityTreeRenderer>(); }
QUndoStack* getUndoStack() { return &_undoStack; }
MainWindow* getWindow() const { return _window; }
EntityTreePointer getEntityClipboard() const { return _entityClipboard; }
EntityEditPacketSender* getEntityEditPacketSender() { return &_entityEditSender; }
@ -571,9 +568,6 @@ private:
bool _activatingDisplayPlugin { false };
QUndoStack _undoStack;
UndoStackScriptingInterface _undoStackScriptingInterface;
uint32_t _renderFrameCount { 0 };
// Frame Rate Measurement

View file

@ -90,19 +90,6 @@ Menu::Menu() {
// Edit menu ----------------------------------
MenuWrapper* editMenu = addMenu("Edit");
// Edit > Undo
QUndoStack* undoStack = qApp->getUndoStack();
QAction* undoAction = undoStack->createUndoAction(editMenu);
undoAction->setShortcut(Qt::CTRL | Qt::Key_Z);
addActionToQMenuAndActionHash(editMenu, undoAction);
// Edit > Redo
QAction* redoAction = undoStack->createRedoAction(editMenu);
redoAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_Z);
addActionToQMenuAndActionHash(editMenu, redoAction);
editMenu->addSeparator();
// Edit > Cut
auto cutAction = addActionToQMenuAndActionHash(editMenu, "Cut", QKeySequence::Cut);
connect(cutAction, &QAction::triggered, [] {

View file

@ -1,66 +0,0 @@
//
// UndoStackScriptingInterface.cpp
// libraries/script-engine/src
//
// Created by Ryan Huffman on 10/22/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "UndoStackScriptingInterface.h"
#include <QDebug>
#include <QScriptValue>
#include <QScriptValueList>
#include <QScriptEngine>
UndoStackScriptingInterface::UndoStackScriptingInterface(QUndoStack* undoStack) : _undoStack(undoStack) {
}
void UndoStackScriptingInterface::pushCommand(QScriptValue undoFunction, QScriptValue undoData,
QScriptValue redoFunction, QScriptValue redoData) {
if (undoFunction.engine()) {
ScriptUndoCommand* undoCommand = new ScriptUndoCommand(undoFunction, undoData, redoFunction, redoData);
undoCommand->moveToThread(undoFunction.engine()->thread());
_undoStack->push(undoCommand);
}
}
ScriptUndoCommand::ScriptUndoCommand(QScriptValue undoFunction, QScriptValue undoData,
QScriptValue redoFunction, QScriptValue redoData) :
_hasRedone(false),
_undoFunction(undoFunction),
_undoData(undoData),
_redoFunction(redoFunction),
_redoData(redoData) {
}
void ScriptUndoCommand::undo() {
QMetaObject::invokeMethod(this, "doUndo");
}
void ScriptUndoCommand::redo() {
// QUndoStack will call `redo()` when adding a command to the stack. This
// makes it difficult to work with commands that span a period of time - for instance,
// the entity duplicate + move command that duplicates an entity and then moves it.
// A better implementation might be to properly implement `mergeWith()` and `id()`
// so that the two actions in the example would be merged.
if (_hasRedone) {
QMetaObject::invokeMethod(this, "doRedo");
}
_hasRedone = true;
}
void ScriptUndoCommand::doUndo() {
QScriptValueList args;
args << _undoData;
_undoFunction.call(QScriptValue(), args);
}
void ScriptUndoCommand::doRedo() {
QScriptValueList args;
args << _redoData;
_redoFunction.call(QScriptValue(), args);
}

View file

@ -1,53 +0,0 @@
//
// UndoStackScriptingInterface.h
// libraries/script-engine/src
//
// Created by Ryan Huffman on 10/22/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_UndoStackScriptingInterface_h
#define hifi_UndoStackScriptingInterface_h
#include <QUndoCommand>
#include <QUndoStack>
#include <QScriptValue>
class UndoStackScriptingInterface : public QObject {
Q_OBJECT
public:
UndoStackScriptingInterface(QUndoStack* undoStack);
public slots:
void pushCommand(QScriptValue undoFunction, QScriptValue undoData, QScriptValue redoFunction, QScriptValue redoData);
private:
QUndoStack* _undoStack;
};
class ScriptUndoCommand : public QObject, public QUndoCommand {
Q_OBJECT
public:
ScriptUndoCommand(QScriptValue undoFunction, QScriptValue undoData, QScriptValue redoFunction, QScriptValue redoData);
virtual void undo() override;
virtual void redo() override;
virtual bool mergeWith(const QUndoCommand* command) override { return false; }
virtual int id() const override { return -1; }
public slots:
void doUndo();
void doRedo();
private:
bool _hasRedone;
QScriptValue _undoFunction;
QScriptValue _undoData;
QScriptValue _redoFunction;
QScriptValue _redoData;
};
#endif // hifi_UndoStackScriptingInterface_h

View file

@ -850,6 +850,7 @@ var toolBar = (function () {
}));
isActive = active;
activeButton.editProperties({isActive: isActive});
undoHistory.setEnabled(isActive);
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
@ -1237,6 +1238,19 @@ var originalLightsArePickable = Entities.getLightsArePickable();
function setupModelMenus() {
// adj our menuitems
Menu.addMenuItem({
menuName: "Edit",
menuItemName: "Undo",
shortcutKey: 'Ctrl+Z',
position: 0,
});
Menu.addMenuItem({
menuName: "Edit",
menuItemName: "Redo",
shortcutKey: 'Ctrl+Shift+Z',
position: 1,
});
Menu.addMenuItem({
menuName: "Edit",
menuItemName: "Entities",
@ -1356,6 +1370,9 @@ function setupModelMenus() {
setupModelMenus(); // do this when first running our script.
function cleanupModelMenus() {
Menu.removeMenuItem("Edit", "Undo");
Menu.removeMenuItem("Edit", "Redo");
Menu.removeSeparator("Edit", "Entities");
if (modelMenuAddedDelete) {
// delete our menuitems
@ -1698,6 +1715,10 @@ function handeMenuEvent(menuItem) {
Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights"));
} else if (menuItem === "Delete") {
deleteSelectedEntities();
} else if (menuItem === "Undo") {
undoHistory.undo();
} else if (menuItem === "Redo") {
undoHistory.redo();
} else if (menuItem === "Parent Entity to Last") {
parentSelectedEntities();
} else if (menuItem === "Unparent Entity") {
@ -1924,6 +1945,86 @@ function recursiveAdd(newParentID, parentData) {
}
}
var UndoHistory = function(onUpdate) {
this.history = [];
// The current position is the index of the last executed action in the history array.
//
// -1 0 1 2 3 <- position
// A B C D <- actions in history
//
// If our lastExecutedIndex is 1, the last executed action is B.
// If we undo, we undo B (index 1). If we redo, we redo C (index 2).
this.lastExecutedIndex = -1;
this.enabled = true;
this.onUpdate = onUpdate;
};
UndoHistory.prototype.pushCommand = function(undoFn, undoArgs, redoFn, redoArgs) {
if (!this.enabled) {
return;
}
// Delete any history following the last executed action.
this.history.splice(this.lastExecutedIndex + 1);
this.history.push({
undoFn: undoFn,
undoArgs: undoArgs,
redoFn: redoFn,
redoArgs: redoArgs
});
this.lastExecutedIndex++;
if (this.onUpdate) {
this.onUpdate();
}
};
UndoHistory.prototype.setEnabled = function(enabled) {
this.enabled = enabled;
if (this.onUpdate) {
this.onUpdate();
}
};
UndoHistory.prototype.canUndo = function() {
return this.enabled && this.lastExecutedIndex >= 0;
};
UndoHistory.prototype.canRedo = function() {
return this.enabled && this.lastExecutedIndex < this.history.length - 1;
};
UndoHistory.prototype.undo = function() {
if (!this.canUndo()) {
console.warn("Cannot undo action");
return;
}
var command = this.history[this.lastExecutedIndex];
command.undoFn(command.undoArgs);
this.lastExecutedIndex--;
if (this.onUpdate) {
this.onUpdate();
}
};
UndoHistory.prototype.redo = function() {
if (!this.canRedo()) {
console.warn("Cannot redo action");
return;
}
var command = this.history[this.lastExecutedIndex + 1];
command.redoFn(command.redoArgs);
this.lastExecutedIndex++;
if (this.onUpdate) {
this.onUpdate();
}
};
function updateUndoRedoMenuItems() {
Menu.setMenuEnabled("Edit > Undo", undoHistory.canUndo());
Menu.setMenuEnabled("Edit > Redo", undoHistory.canRedo());
}
var undoHistory = new UndoHistory(updateUndoRedoMenuItems);
updateUndoRedoMenuItems();
// When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently
// possible to create an entity with a specific id, earlier undo commands to the deleted entity
// will fail if there isn't a way to find the new entity id.
@ -2011,7 +2112,7 @@ function pushCommandForSelections(createdEntityData, deletedEntityData, doNotSav
properties: currentProperties
});
}
UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData);
undoHistory.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData);
}
var ServerScriptStatusMonitor = function(entityID, statusCallback) {