built auto save extension for LibreOffice
This commit is contained in:
@@ -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>
|
||||
@@ -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
@@ -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",),
|
||||
)
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user