built auto save extension for LibreOffice

This commit is contained in:
2026-05-31 21:32:16 -05:00
commit dc2cb7cbc7
17 changed files with 783 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Jobs" oor:package="org.openoffice.Office">
<node oor:name="Jobs">
<node oor:name="org.libreoffice.extensions.autosave.AutoSaveJob" oor:op="replace">
<prop oor:name="Service">
<value>org.libreoffice.extensions.autosave.AutoSaveJob</value>
</prop>
</node>
</node>
<node oor:name="Events">
<node oor:name="OnLoad" oor:op="fuse">
<node oor:name="JobList">
<node oor:name="org.libreoffice.extensions.autosave.AutoSaveJob" oor:op="replace"/>
</node>
</node>
<node oor:name="OnNew" oor:op="fuse">
<node oor:name="JobList">
<node oor:name="org.libreoffice.extensions.autosave.AutoSaveJob" oor:op="replace"/>
</node>
</node>
</node>
</oor:component-data>
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
<manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=Python" manifest:full-path="autosave.py"/>
<manifest:file-entry manifest:media-type="application/vnd.sun.star.configuration-data" manifest:full-path="Jobs.xcu"/>
</manifest:manifest>
Binary file not shown.
+107
View File
@@ -0,0 +1,107 @@
import os
import shutil
import traceback
from threading import Timer
from datetime import datetime
import uno
import unohelper
from com.sun.star.util import XModifyListener
from com.sun.star.task import XJob, XJobExecutor
LOG_FILE = "C:\\Users\\jasonross\\workspace\\LibreOfficeAutoSave\\autosave_debug.log"
def log_debug(msg):
try:
with open(LOG_FILE, "a") as f:
f.write(f"[{datetime.now().isoformat()}] {msg}\n")
except Exception:
pass
log_debug("autosave.py module is being loaded by LibreOffice!")
class AutoSaveListener(unohelper.Base, XModifyListener):
def __init__(self, doc, delay_seconds=1.0):
self.doc = doc
self.delay = delay_seconds
self.timer = None
log_debug(f"AutoSaveListener initialized for document: {doc}")
def modified(self, event):
if self.timer:
self.timer.cancel()
self.timer = Timer(self.delay, self.execute_safe_save)
self.timer.start()
def execute_safe_save(self):
try:
log_debug("Timer expired, attempting save...")
if self.doc.supportsService("com.sun.star.document.OfficeDocument"):
if self.doc.hasLocation() and not self.doc.isReadonly():
file_url = self.doc.getURL()
log_debug(f"File has location: {file_url}")
if file_url.startswith("file:///"):
system_path = uno.fileUrlToSystemPath(file_url)
bak_path = os.path.join(os.path.dirname(system_path), f".{os.path.basename(system_path)}.bak")
try:
if os.path.exists(system_path):
shutil.copy2(system_path, bak_path)
log_debug(f"Created backup at {bak_path}")
except Exception as e:
log_debug(f"Backup failed: {e}")
self.doc.store()
log_debug("Document successfully saved.")
else:
log_debug("Document is readonly or has no location (not saved yet).")
except Exception as e:
log_debug(f"Auto-save exception: {e}\n{traceback.format_exc()}")
def disposing(self, event):
if self.timer:
self.timer.cancel()
log_debug("Listener disposed.")
g_listeners = {}
class AutoSaveJob(unohelper.Base, XJob, XJobExecutor):
def __init__(self, ctx=None):
self.ctx = ctx
log_debug("AutoSaveJob instantiated!")
def execute(self, arguments):
log_debug(f"AutoSaveJob execute() called with args: {arguments}")
self._attach_listener()
return ()
def trigger(self, args):
log_debug(f"AutoSaveJob trigger() called with args: {args}")
self._attach_listener()
def _attach_listener(self):
try:
ctx = uno.getComponentContext()
smgr = ctx.ServiceManager
desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx)
doc = desktop.getCurrentComponent()
if doc:
if doc in g_listeners:
log_debug("Listener already attached to this document.")
return
listener = AutoSaveListener(doc, delay_seconds=1.0)
doc.addModifyListener(listener)
g_listeners[doc] = listener
log_debug("Successfully attached listener to current document.")
else:
log_debug("No active document found.")
except Exception as e:
log_debug(f"Error in AutoSaveJob attach: {e}\n{traceback.format_exc()}")
g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(
AutoSaveJob,
"org.libreoffice.extensions.autosave.AutoSaveJob",
("com.sun.star.task.Job",),
)
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<description xmlns="http://openoffice.org/extensions/description/2006" xmlns:d="http://openoffice.org/extensions/description/2006" xmlns:xlink="http://www.w3.org/1999/xlink">
<identifier value="org.libreoffice.extensions.autosave"/>
<version value="1.0.0"/>
<display-name>
<name lang="en-US">AutoSave</name>
</display-name>
</description>