Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ Paragraph tools in [`content.py`](plugin/modules/writer/content.py) are **`ToolB

**Writer Fields Specialized Tools**: Text fields in LibreOffice are implemented using `doc.createInstance("com.sun.star.text.textfield.<TYPE>")` (like `PageNumber`, `DateTime`). See `plugin/modules/writer/fields.py` for tools to insert, list, and delete fields natively using property reflection.

**Writer Track Changes Specialized Tools**: Track changes (redlines) tools are implemented in `plugin/modules/writer/tracking.py` using `XRedlinesSupplier` to enumerate changes, `RecordChanges` document property to start/stop tracking, and UNO dispatch commands (`.uno:AcceptTrackedChange`, etc.) against the selected text for accepting and rejecting modifications.

**Tool Compatibility**: `ToolRegistry` prioritizes `uno_services` matches (strict), but falls back to `doc_types` if no service match is found. This ensures tools remain accessible in test environments or across slightly different LibreOffice flavors.

**Shared tool names (Writer vs Calc/Draw)**: [`plugin/modules/writer/charts.py`](plugin/modules/writer/charts.py) and [`plugin/modules/writer/shapes.py`](plugin/modules/writer/shapes.py) register the same `name` as Calc/Draw tools; the last class registered wins. Those Writer subclasses must list a **union** of every document `uno_services` the inherited `execute()` supports (e.g. Text + Spreadsheet for chart tools, Text + Drawing + Presentation for shape tools), or `ToolRegistry.execute` will reject Calc/Draw documents.
Expand Down
6 changes: 3 additions & 3 deletions docs/writer-specialized-toolsets.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,9 +341,9 @@ The following items align with a fuller UNO/DevGuide coverage map; they are **no
- **Limits:** Tune `max_steps` / timeouts for the sub-agent; add telemetry on which domains are used.
- **Documentation:** Keep [`AGENTS.md`](../../AGENTS.md) in sync when behavior or entry points change.

### 5.10 Track changes (planned specialized toolset)
### 5.10 Track changes (specialized toolset)

**Status:** Not implemented. Treat this like other **specialized** domains: keep **record / review / accept-reject** operations off the default Writer tool list, and expose them only after `delegate_to_specialized_writer_toolset` enters a **track_changes** (or **review**) domain—same progressive-disclosure story as fields, indexes, tables, etc.
**Status:** Implemented (`plugin/modules/writer/tracking.py`). Treat this like other **specialized** domains: keep **record / review / accept-reject** operations off the default Writer tool list, and expose them only after `delegate_to_specialized_writer_toolset` enters a **track_changes** (or **review**) domain—same progressive-disclosure story as fields, indexes, tables, etc.

**Product fit:** Lets the model turn recording on before bulk edits, list or filter changes by author/type, accept or reject individually or in bulk, and toggle markup visibility—without bloating every chat turn with long schemas.

Expand All @@ -366,7 +366,7 @@ The following items align with a fuller UNO/DevGuide coverage map; they are **no
| `XChange` | `accept()` | Accept this change. |
| `XChange` | `reject()` | Reject this change. |

When implementing, align service names and includes with the installed LibreOffice SDK (e.g. `com.sun.star.text.*` track-changes interfaces) and add smoke tests against a doc with known revisions.
For specific UNO API implementation details used by WriterAgent, see [Writer Tracking API Reference](./writer-tracking-api-reference.md).

---

Expand Down
77 changes: 77 additions & 0 deletions docs/writer-tracking-api-reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Writer Tracking API Reference

## Introduction
The LibreOffice Writer Track Changes functionality (also known internally as "Redlines") allows users to record, review, accept, and reject modifications made to a document by various authors over time.

This document details the relevant UNO services, interfaces, properties, and Dispatch commands that WriterAgent uses to manage track changes.

## Document Properties

The `com.sun.star.text.TextDocument` service (and its underlying implementation `GenericTextDocument`) provides several important properties related to Track Changes.

### RecordChanges
- **Type:** `boolean`
- **Description:** Start or stop recording changes in the document. When `True`, any insertions, deletions, or formatting changes are tracked as Redlines.

## Redlines Collection (`XRedlinesSupplier`)

To access the changes made to a document, the document model provides the `com.sun.star.document.XRedlinesSupplier` interface.

### Methods
- `getRedlines()`: Returns a `com.sun.star.container.XEnumerationAccess` (or similar collection) containing all the redlines (tracked changes) in the document.

## Individual Redlines (`XRedline`)

When enumerating the collection returned by `getRedlines()`, each element represents an individual tracked change. A Redline typically exposes several properties:

### Key Properties
- `RedlineType` (string): The type of change, typically `"Insert"`, `"Delete"`, `"Format"`, or `"Move"`.
- `RedlineAuthor` (string): The name of the user who made the change.
- `RedlineDateTime` (`com.sun.star.util.DateTime`): The timestamp when the change was made (contains Year, Month, Day, Hours, Minutes, etc.).
- `RedlineComment` (string): An optional comment attached to the tracked change.
- `RedlineIdentifier` (string): An internal identifier for the redline.

## Dispatch Commands (.uno:)

Because the standard UNO `XRedline` objects in Python don't consistently expose direct `accept()` and `reject()` methods that are easily callable without complex text cursor manipulation, LibreOffice's Dispatch API is the most robust way to accept and reject changes, as well as toggle their visibility.

To use these, obtain a `com.sun.star.frame.DispatchHelper` and execute the command against the document's current frame (`doc.getCurrentController().getFrame()`).

### Available Commands
- `.uno:AcceptAllTrackedChanges`: Accepts all tracked changes in the document at once.
- `.uno:RejectAllTrackedChanges`: Rejects all tracked changes in the document at once.
- `.uno:AcceptTrackedChange`: Accepts the currently selected tracked change (requires navigating the view cursor to the change first).
- `.uno:RejectTrackedChange`: Rejects the currently selected tracked change (requires navigating the view cursor to the change first).
- `.uno:ShowTrackedChanges`: Toggles the visibility of the tracked changes markup in the document view.

## Example Usage (Python-UNO)

### Listing Tracked Changes

```python
doc = ctx.doc
redlines = doc.getRedlines()
enum = redlines.createEnumeration()

changes = []
while enum.hasMoreElements():
redline = enum.nextElement()
change = {
"author": redline.getPropertyValue("RedlineAuthor"),
"type": redline.getPropertyValue("RedlineType"),
# Extract DateTime fields
}
changes.append(change)
```

### Accepting All Changes

```python
smgr = ctx.ctx.ServiceManager
dispatcher = smgr.createInstanceWithContext(
"com.sun.star.frame.DispatchHelper", ctx.ctx
)
frame = ctx.doc.getCurrentController().getFrame()

dispatcher.executeDispatch(frame, ".uno:AcceptAllTrackedChanges", "", 0, ())
```
Loading
Loading