iOS: add undo/redo support

Enable the undo/redo buttons on the keyboard, as well as the
Cmd-Z/Cmd-Shift-Z shortcuts.

For UIKit to support this, we need to add undo actions to
first responders undo manager. Since we don't know if Qt
has anything to undo/redo, we just enable the shortcuts
all the time. To do that, we trick NSUndoManager to always
have both an undo operation and a redo operation in the
stack.

Change-Id: I3294a962cc24f56585e7e515856142f3dda56d0a
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>
bb10
Richard Moe Gustavsen 2015-08-21 15:39:35 +02:00 committed by Richard Moe Gustavsen
parent dbb24ce477
commit af5b62844c
1 changed files with 53 additions and 0 deletions

View File

@ -209,6 +209,9 @@
if (UIView *accessoryView = static_cast<UIView *>(platformData.value(kImePlatformDataInputAccessoryView).value<void *>()))
self.inputAccessoryView = [[[WrapperView alloc] initWithView:accessoryView] autorelease];
self.undoManager.groupsByEvent = NO;
[self rebuildUndoStack];
return self;
}
@ -380,6 +383,56 @@
// -------------------------------------------------------------------------
- (void)undo
{
[self sendKeyPressRelease:Qt::Key_Z modifiers:Qt::ControlModifier];
[self rebuildUndoStack];
}
- (void)redo
{
[self sendKeyPressRelease:Qt::Key_Z modifiers:Qt::ControlModifier|Qt::ShiftModifier];
[self rebuildUndoStack];
}
- (void)registerRedo
{
NSUndoManager *undoMgr = self.undoManager;
[undoMgr beginUndoGrouping];
[undoMgr registerUndoWithTarget:self selector:@selector(redo) object:nil];
[undoMgr endUndoGrouping];
}
- (void)rebuildUndoStack
{
dispatch_async(dispatch_get_main_queue (), ^{
// Register dummy undo/redo operations to enable Cmd-Z and Cmd-Shift-Z
// Ensure we do this outside any undo/redo callback since NSUndoManager
// will treat registerUndoWithTarget as registering a redo when called
// from within a undo callback.
NSUndoManager *undoMgr = self.undoManager;
[undoMgr removeAllActions];
[undoMgr beginUndoGrouping];
[undoMgr registerUndoWithTarget:self selector:@selector(undo) object:nil];
[undoMgr endUndoGrouping];
// Schedule an operation that we immediately pop off to be able to schedule a redo
[undoMgr beginUndoGrouping];
[undoMgr registerUndoWithTarget:self selector:@selector(registerRedo) object:nil];
[undoMgr endUndoGrouping];
[undoMgr undo];
// Note that, perhaps because of a bug in UIKit, the buttons on the shortcuts bar ends up
// disabled if a undo/redo callback doesn't lead to a [UITextInputDelegate textDidChange].
// And we only call that method if Qt made changes to the text. The effect is that the buttons
// become disabled when there is nothing more to undo (Qt didn't change anything upon receiving
// an undo request). This seems to be OK behavior, so we let it stay like that unless it shows
// to cause problems.
});
}
// -------------------------------------------------------------------------
- (void)keyCommandTriggered:(UIKeyCommand *)keyCommand
{
Qt::Key key = Qt::Key_unknown;