Hi,
I would like my users to have an option of an Autosave… I would like to use an async task to kick in and save the doc at a user defined time.
My code all seems to run fine apart from the sleep part… I’ve done various versions, this one has Sleep in it, others using DispatchTimer. Seemingly i am getting a bit caught between ironpython and cpython with some bits working in some and not in others… Would anyone have a suggestion as to why it isn’t working?
(I am saving a little file to help the code know whether to start or stop, I would prefer to pull the current icon state, but it didn’t seem available to me).
Any thoughts welcome!
Mark
import os
from Autodesk.Revit.UI import TaskDialog
from pyrevit import forms, revit, HOST_APP, script
from Autodesk.Revit.UI import IExternalEventHandler, ExternalEvent
import clr
clr.AddReference('System')
from System.Threading import Timer, TimerCallback
# Define the file path for storing the auto-save state
STATE_FILE_PATH = os.path.join(os.path.dirname(__file__), 'auto_save_state.txt')
# Function to read the auto-save state from the file
def read_auto_save_state():
if os.path.exists(STATE_FILE_PATH):
with open(STATE_FILE_PATH, 'r') as file:
return file.read().strip() == 'True'
return False
# Function to write the auto-save state to the file
def write_auto_save_state(state):
with open(STATE_FILE_PATH, 'w') as file:
file.write('True' if state else 'False')
# Flag to track auto-save status (only for this session)
auto_save_on = read_auto_save_state()
auto_save_timer = None
uiapp = HOST_APP.uiapp
doc = revit.doc
button = None
# External event handler for performing auto-save
class AutoSaveHandler(IExternalEventHandler):
def __init__(self, doc):
self.doc = doc
def Execute(self, app):
try:
self.doc.Save()
TaskDialog.Show('AutoSave', 'Document saved!')
except Exception as e:
TaskDialog.Show('Error', str(e))
def GetName(self):
return "AutoSaveHandler"
# Create an instance of the handler and external event
auto_save_handler = AutoSaveHandler(doc)
external_event = ExternalEvent.Create(auto_save_handler)
# Function to initialize button icon based on auto-save state
def __selfinit__(script_cmp, ui_button_cmp, __rvt__):
global auto_save_on
global button
button = ui_button_cmp
button_icon = script_cmp.get_bundle_file('on.png' if auto_save_on else 'off.png')
ui_button_cmp.set_icon(button_icon, icon_size=script.ICON_MEDIUM)
# Function to handle the timer callback (this replaces the Elapsed event)
def on_timer_elapsed(state):
external_event.Raise() # Raise external event to save the document
# Function to start the timer for auto-saving
def start_auto_save_timer(interval_minutes):
global auto_save_timer
interval_ms = interval_minutes * 60 * 1000 # Convert minutes to milliseconds
auto_save_timer = Timer(TimerCallback(on_timer_elapsed), None, interval_ms, interval_ms)
# Function to stop the auto-save timer
def stop_auto_save_timer():
global auto_save_timer
if auto_save_timer is not None:
auto_save_timer.Dispose()
auto_save_timer = None
# Function to toggle the save process
def toggle_auto_save():
global auto_save_on
auto_save_on = not auto_save_on # Toggle the state
write_auto_save_state(auto_save_on) # Save the state to the file
if auto_save_on:
# Get the time interval in minutes from the user
text = forms.ask_for_string(default='15', prompt='Enter time in minutes:', title='Autosave Set Interval')
if text is not None and text.isdigit():
minutes = int(text)
else:
TaskDialog.Show('Error', 'Invalid input. Please enter a number.')
return False
TaskDialog.Show('AutoSave', 'Auto-save is now ON.')
start_auto_save_timer(minutes) # Start the timer
return True # Returning True when auto-save is ON
else:
TaskDialog.Show('AutoSave', 'Auto-save is now OFF.')
stop_auto_save_timer() # Stop the timer
return False # Returning False when auto-save is OFF
# Main execution - Runs only when the script is executed (button clicked)
if __name__ == '__main__':
# Toggle auto-save and update button icon based on the new state
is_active = toggle_auto_save()
# Update button icon to reflect the new state
script.toggle_icon(is_active)