PDA

View Full Version : Using QTimer to install an autosave feature



dennisvz
18th May 2019, 01:32
I want to install an autosave feature and was considering using QTimer. I looked at the docs, but most are in C, so I am having trouble getting it correct. So far, I have:


timer = QtCore.QTimer()
timer.timeout(self.savefile)
timer.start(600000)


1. Is QTimer the way to get what I want? If so, what is the correct code (Line 2 above is not correct)
2. If QTimer is the way to get what I want, where does the above code go? in the init of the module that contains self.savefile? If not, where?
3. If QTimer is not correct, what is the better way?
Thanks

ChrisW67
18th May 2019, 03:06
1. Is QTimer the way to get what I want? If so, what is the correct code (Line 2 above is not correct)
Seems reasonable. You need to connect the timeout signal correctly (line 2) and probably make sure that savefile only does something if the "document" is dirty.

2. If QTimer is the way to get what I want, where does the above code go? in the init of the module that contains self.savefile? If not, where?
Create the timer and connect it in the constructor/init.
Start the timer when a "document" is opened and stop it when the "document" is closed.
[/LIST]

3. If QTimer is not correct, what is the better way?
You could call savefile() when the "document" is modified and and clear the modified flag when it is saved. This could impose an unacceptable load depending on how modifications occur.

Example opens a document and closes it 5 seconds later, with a save every 2 seconds. App will terminate after 10 seconds.


#!/usr/bin/env python3

import sys
from PyQt5.QtCore import QCoreApplication, QObject, QTimer

class Foo(QObject):
def __init__(self, *args, **kwargs):
super(Foo, self).__init__(*args, **kwargs)
self.autosaveTimer = QTimer()
self.autosaveTimer.setInterval(2000)
self.autosaveTimer.timeout.connect(self.saveFile)

def openFile(self):
# Open the document
print ("Open...")
self.autosaveTimer.start()

def closeFile(self):
# Close the document
print ("Close...")
self.autosaveTimer.stop()

def saveFile(self):
# Save the document if it is dirty
print ("Saving...")

if __name__ == '__main__':
app = QCoreApplication(sys.argv)
QTimer.singleShot(10000, app.quit)

foo = Foo()
foo.openFile()
QTimer.singleShot(5000, foo.closeFile)

app.exec_();

dennisvz
18th May 2019, 14:34
One last question. Does autosaving interfere with anything else going on within the program, like if the program is running some loop, or whether the user is in the process of entering data in the UI or whether the user just manually clicked the same "Save" button?

ChrisW67
19th May 2019, 00:55
One last question. Does autosaving interfere with anything else going on within the program, like if the program is running some loop, or whether the user is in the process of entering data in the UI or whether the user just manually clicked the same "Save" button?

In a straightforward single-threaded Qt program the timer will go off, and the auto-save called, only when the program returns to the Qt event loop. If your program is busy doing some processing that does not return to the event loop, e.g. a 5 minute computation, then it will not be interrupted. While the save is occurring the program not be doing anything else, which can be a problem if that takes a long time.

You probably also need to be defensive and auto-save to somewhere other than the real file, and only overwrite the real file if the user selects Save deliberately. On file open look for the matching auto-save and, if found (because the program crashed last time), offer to use that instead. Depends on your application though.