Commands

Editing is done through the QUndoStack mechanism for redo/undo-ing actions. All changes to a transcript, including style changes, should be done through a QUndoCommand.

The qcommands module should contain all available QUndoCommand classes and classes/functions relating to generating any QUndoCommand.

The two main functions are steno_insert and steno_remove, which insert and remove elements from the userData slot of the block in the QTextEdit.

class qcommands.BlockUserData(*args: Any, **kwargs: Any)

Bases: QTextBlockUserData

Representation of the data for a block.

This was adapted from ninja-ide by using a default dict as attrs in the class. An empty element_collection is set in self.attr["strokes"] so every block will have an element_collection set.

qcommands.update_user_data(block_dict, key, value=None)

Update BlockUserData key with default value (time) if not provided in a new instance.

Parameters:
  • block_dict – a BlockUserData from a QTextBlock

  • key (str) – attribute to be updated

Value str:

value of attribute, automatically insert time if None

Returns:

updated BlockUserData

class qcommands.element_actions

Bases: object

QCommand factory for mass insertions.

This is necessary because images are inserted differently than other “text” elements.

Parameters:
  • document – reference to QTextEdit instance

  • block (int) – block number

  • position_in_block (int) – position within block

  • element – element to be inserted

Returns:

QUndoCommand that should be pushed into a QUndoStack

class qcommands.steno_insert(*args: Any, **kwargs: Any)

Bases: QUndoCommand

Inserts text and steno data into editor.

Parameters:
  • cursor – a QTextCursor instance

  • document – a QTextDocument to act upon

  • block (int) – blockNumber of the QTextDocument to act upon

  • position_in_block (int) – position in the block to act upon

  • steno – elements or element_collection to insert

class qcommands.steno_remove(*args: Any, **kwargs: Any)

Bases: QUndoCommand

Removes text and steno data from editor.

Parameters:
  • cursor – a QTextCursor instance

  • document – a QTextDocument to act upon

  • block (int) – blockNumber of the QTextDocument to act upon

  • position_in_block (int) – position in the block to act upon

  • length (int) – number of characters to remove

  • steno – holder of removed data

class qcommands.image_insert(*args: Any, **kwargs: Any)

Bases: QUndoCommand

Insert image into editor.

Parameters:
  • cursor – a QTextCursor instance

  • document – a QTextDocument to act upon

  • block (int) – blockNumber of the QTextDocument to act upon

  • position_in_block (int) – position in the block to act upon

  • image_element – an image_text element to insert

class qcommands.split_steno_par(*args: Any, **kwargs: Any)

Bases: QUndoCommand

Splits a paragraph at position in block, and puts steno properly with new paragraph.

Warning

Use cursor movements, and not insertText and removeSelectedText as otherwise image elements are replaced by the text equivalent.

Parameters:
  • cursor – a QTextCursor instance

  • document – a QTextDocument to act upon

  • block (int) – blockNumber of the QTextDocument to act upon

  • position_in_block (int) – position in the block to act upon

  • space_placement (str) – from Plover config, whether space is before/after output

  • new_line_stroke – a stroke_text element containing custom data to insert in the split

  • remove_space (bool) – trim space from start of new paragraph after split, default True

  • space_removed (bool) – tracks whether a space was removed from start of new paragraph

class qcommands.merge_steno_par(*args: Any, **kwargs: Any)

Bases: QUndoCommand

Combine two paragraphs into one in editor.

Warning

Use cursor movements, and not insertText and removeSelectedText as otherwise image elements are replaced by the text equivalent.

Parameters:
  • cursor – a QTextCursor instance

  • document – a QTextDocument to act upon

  • block (int) – blockNumber of the QTextDocument to act upon

  • position_in_block (int) – position in the block to act upon

  • space_placement (str) – from Plover config, whether space is before/after output

  • add_space (bool) – whether to add space between the two paragraphs at merging

class qcommands.set_par_style(*args: Any, **kwargs: Any)

Bases: QUndoCommand

Set paragraph style.

Character formats have to be applied through the iterator of QTextBlock on individual QTextFragment elements to avoid applying a format on an image, over-riding its format, and causing it to revert to an object replacement charater.

Parameters:
  • cursor – a QTextCursor instance

  • document – a QTextDocument to act upon

  • block (int) – blockNumber of the QTextDocument to act upon

  • style (str) – name of style to set

  • par_formatsdict containing block-level formats

  • txt_formatsdict containing char-level formats

class qcommands.set_par_property(*args: Any, **kwargs: Any)

Bases: QUndoCommand

Set a paragraph’s property.

Parameters:
  • document – a QTextDocument to act upon

  • block (int) – blockNumber of the QTextDocument to act upon

  • prop (str) – property key

  • value – value to set for property

class qcommands.update_style(*args: Any, **kwargs: Any)

Bases: QUndoCommand

Update entire style.

Parameters:
  • document – a QTextDocument to act upon

  • styles – dict of styles

  • style_name – name of style to update

  • new_style_dict – dict of new style parameters

class qcommands.update_config_value(*args: Any, **kwargs: Any)

Bases: QUndoCommand

Update transcript config value.

Parameters:
  • key (str) – config key

  • value (str) – config value

  • config (dict) – transcript config

class qcommands.update_field(*args: Any, **kwargs: Any)

Bases: QUndoCommand

Update transcript fields with new values.

When fields change values, the underlying text_field will be updated when called again, but the text in the QTextEdit will not. This command updates the text_field element, then removes the old field value and inserts the new one into text.

The original dict that has to be updated is outside the command and has to be passed in by reference. But a copy each of the old and the new dicts are needed to perform redo/undos properly.

Parameters:
  • cursor – a QTextCursor instance

  • document – a QTextDocument to act upon

  • block (int) – blockNumber of the QTextDocument to act upon

  • position_in_block (int) – position in the block to act upon

  • old_dict (dict) – dict with existing field values

  • new_dict – dict with new field values

class qcommands.update_entries(*args: Any, **kwargs: Any)

Bases: QUndoCommand

Update index entries with new values.

Parameters:
  • cursor – a QTextCursor instance

  • document – a QTextDocument to act upon

  • block (int) – blockNumber of the QTextDocument to act upon

  • position_in_block (int) – position in the block to act upon

  • old_dict (dict) – dict with existing index data

  • new_dict – dict with new index data

Constructing a new QUndoCommand

Each command has to subclass QUndoCommand

Each subclass of QUndoCommand that acts on the transcript text must have the following parameters, regardless of whether they are used in redo or undo functions. This is to maintain consistency for action generation (future proof).

  • cursor: reference to copy of present QTextCursor, such as QTextEdit.textCursor(), should be earliest position if cursor has selection

  • document: reference to QTextEdit transcript

  • block: integer, blockNumber in editor (do not take direct block reference in case it gets destroyed)

Commands that act only on GUI style or data do not need to.

block_state is an attribute that is set within the QUndoCommands to indicate a block has been changed. For safety, even if an action is undone, the block’s state is not reverted.

The userState attribute of each paragraph in the QtextEdit will be set to 1 (ie, is modified? True) if any QUndoCommand acted on it. Right now, this is to signify that the paragraph has been modified for use in saving the transcript, and it is not reset back to 0 even if the command is undone. This may change in the future.

The QTextBlock where edits are made within the QUndoCommand should be retried with findBlockByNumber and not directly with the current QTextCursor, in both redo and undo. This is especially important in undo. Then the cursor position should be set with position_in_block and block coordinates.