Catching document close event

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Catching document close event

Post by wmayer »

flachyjoe wrote: Thu Dec 02, 2021 10:10 am So even if they are exposed soon my workbench won't be retro-compatible
A workaround is to implement an event filter class that inherits from QtCore.QObject. Inside the overridden function eventFilter() you check for close events and a receiver that inherits from Gui::View3DInventor. If both criterions match return True to filter the close event.

Code: Select all

from PySide2 import QtCore
class DocumentFilter(QtCore.QObject):
  def eventFilter(self, obj, ev):
    if ev.type() == QtCore.QEvent.Close and obj.inherits("Gui::View3DInventor"):
      ev.ignore()
      return True
    return False

Code: Select all

filter = DocumentFilter()
app = QtCore.QCoreApplication.instance()
app.installEventFilter(filter)

Code: Select all

app.removeEventFilter(filter)
User avatar
flachyjoe
Veteran
Posts: 1869
Joined: Sat Mar 31, 2012 12:00 pm
Location: Limoges, France

Re: Catching document close event

Post by flachyjoe »

openBrain wrote: Thu Dec 02, 2021 10:42 am

Code: Select all

    /** Called when a document is about to be saved*/
    void slotStartSaveDocument(const App::Document&, const std::string&);
I'm not sure I can ask the external to save the FC included file, it could need a user action. I've to look further.
wmayer wrote: Thu Dec 02, 2021 10:47 am git commit 526dc1a030
:)
wmayer wrote: Thu Dec 02, 2021 10:53 am A workaround is to implement an event filter
Looks great !
- Flachy Joe -
Image
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Catching document close event

Post by openBrain »

flachyjoe wrote: Thu Dec 02, 2021 11:18 am
wmayer wrote: Thu Dec 02, 2021 10:53 am A workaround is to implement an event filter
Looks great !
There can be some limitations though. A same document can have several 3D views open, in which case you probably want to catch only when the last one is closed. Also a document can have no ViewInventor open, for example if only a spreadsheet is open. ;)
User avatar
flachyjoe
Veteran
Posts: 1869
Joined: Sat Mar 31, 2012 12:00 pm
Location: Limoges, France

Re: Catching document close event

Post by flachyjoe »

openBrain wrote: Thu Dec 02, 2021 10:42 am

Code: Select all

    /** Called when a document is about to be saved*/
    void slotStartSaveDocument(const App::Document&, const std::string&);
I can send a message to Pure-Data to ask the file save, it works well BUT I can't get the file back in FreeCAD.
Objects properties change are not validate while slotStartSaveDocument stops the main loop.

Code: Select all

class PDInclude:
    def __init__(self, obj):
        obj.Proxy = self
        self.object = obj
        self.Type = "PDInclude"
        obj.addProperty('App::PropertyFileIncluded', 'PDFile', '', '')
        self.isOpen = False
        self.docObserver = None

    def startEdit(self):
        if not self.isOpen:
            sFile = self.object.PDFile
            FCPD = locator.getFCPDCore()
            self.pdServer = FCPD.pdServer
            if sFile:
                if not self.pdServer.isAvailable():
                    self.pdServer.run()
                    FCPD.runPD()

                _, self.tmpFile = tempfile.mkstemp()
                shutil.copyfile(sFile, self.tmpFile)
                dirName, fileName = os.path.split(self.tmpFile)
                self.pdServer.send('0 pd open %s %s' % (fileName, dirName))

                # TODO fix close detection
                # self.isOpen = True

                # watch for file change
                self.fs_watcher = QtCore.QFileSystemWatcher([self.tmpFile])
                self.fs_watcher.fileChanged.connect(self.fileChanged)

                # auto save pd file when document is saved
                class MyObserver(object):
                    def __init__(self):
                        self.target_doc = None
                        self.caller = None
                        self.fileName = None

                    def slotStartSaveDocument(self, doc, label):
                        if doc == self.target_doc:
                            Log('Ask PD to save\n')
                            self.caller.pdServer.send('0 pd-%s menusave;' % self.fileName)
                            # give PD 500ms to save
                            time.sleep(0.5)
                            # store the file back
                            self.caller.object.PDFile = self.caller.tmpFile
                            App.ActiveDocument.recompute() # BUG Doesn't work as main loop is stopped!


                self.docObserver = MyObserver()
                self.docObserver.target_doc = App.ActiveDocument
                self.docObserver.caller = self
                self.docObserver.fileName = fileName
                App.addDocumentObserver(self.docObserver)

    def fileChanged(self, filename):
        Log("%s has changed\n" % filename)
        if self.tmpFile:
            self.object.PDFile = self.tmpFile
            App.ActiveDocument.recompute()

    def endEdit(self):
        os.remove(self.tmpFile)
        self.isOpen = False
        App.removeDocumentObserver(self.docObserver)

    def onDocumentRestored(self, obj):
        self.object = obj
        self.isOpen = False

    def __getstate__(self):
        return None
- Flachy Joe -
Image
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Catching document close event

Post by openBrain »

flachyjoe wrote: Fri Dec 03, 2021 7:53 am Objects properties change are not validate while slotStartSaveDocument stops the main loop.
Sorry I don't have much time to look at the code right now.
Maybe you can try

Code: Select all

Gui.updateGui()
to process the events then

Code: Select all

App.ActiveDocument.recompute()
:?
User avatar
flachyjoe
Veteran
Posts: 1869
Joined: Sat Mar 31, 2012 12:00 pm
Location: Limoges, France

Re: Catching document close event

Post by flachyjoe »

Hi,
I got the save working : I was abused by Log which was obviously shown only after App.ActiveDocument.recompute()
I thunk Pure-Data got the message and save but it only got it after FC saved (server run in the main loop).
So I updateGui after server.send, message go to PD, file is saved and after 500ms delay FC save the change well.

A question is still in suspend (I have to try) does FreeCAD autosave triggers the slotStartSaveDocument ? If it does I will have a problem as I don't want to save the PD change in this case.
- Flachy Joe -
Image
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Catching document close event

Post by wmayer »

A question is still in suspend (I have to try) does FreeCAD autosave triggers the slotStartSaveDocument ?
No, it doesn't.
User avatar
flachyjoe
Veteran
Posts: 1869
Joined: Sat Mar 31, 2012 12:00 pm
Location: Limoges, France

Re: Catching document close event

Post by flachyjoe »

wmayer, openBrain
Thank you! :)

My next task is to catch the file close but it's mainly on the Pure-Data side.
- Flachy Joe -
Image
Post Reply