Parcourir la source

- added a new feature, project auto-saving controlled from Edit -> Preferences -> General -> APP. Preferences -> Enable Auto Save checkbox

Marius Stanciu il y a 5 ans
Parent
commit
f690c2b09d
3 fichiers modifiés avec 92 ajouts et 12 suppressions
  1. 4 0
      CHANGELOG.md
  2. 52 2
      FlatCAMApp.py
  3. 36 10
      flatcamGUI/PreferencesUI.py

+ 4 - 0
CHANGELOG.md

@@ -7,6 +7,10 @@ CHANGELOG for FlatCAM beta
 
 =================================================
 
+22.04.2020 
+
+- added a new feature, project auto-saving controlled from Edit -> Preferences -> General -> APP. Preferences -> Enable Auto Save checkbox
+
 20.04.2020
 
 - made the Grid icon in the status bar clickable and it will toggle the snap to grid function

+ 52 - 2
FlatCAMApp.py

@@ -437,6 +437,8 @@ class App(QtCore.QObject):
             "global_tpdf_bmargin": 10.0,
             "global_tpdf_lmargin": 20.0,
             "global_tpdf_rmargin": 20.0,
+            "global_autosave": False,
+            "global_autosave_timeout": 300000,
 
             # General
             "global_graphic_engine": '3D',
@@ -1197,6 +1199,8 @@ class App(QtCore.QObject):
 
             "global_compression_level": self.ui.general_defaults_form.general_app_group.compress_spinner,
             "global_save_compressed": self.ui.general_defaults_form.general_app_group.save_type_cb,
+            "global_autosave": self.ui.general_defaults_form.general_app_group.autosave_cb,
+            "global_autosave_timeout": self.ui.general_defaults_form.general_app_group.autosave_entry,
 
             "global_tpdf_tmargin": self.ui.general_defaults_form.general_app_group.tmargin_entry,
             "global_tpdf_bmargin": self.ui.general_defaults_form.general_app_group.bmargin_entry,
@@ -1956,6 +1960,15 @@ class App(QtCore.QObject):
         self.worker_task.connect(self.workers.add_task)
         self.log.debug("Finished creating Workers crew.")
 
+        # #############################################################################
+        # ################################ AUTOSAVE SETUP #############################
+        # #############################################################################
+
+        self.block_autosave = False
+        self.autosave_timer = QtCore.QTimer(self)
+        self.save_project_auto_update()
+        self.autosave_timer.timeout.connect(self.save_project_auto)
+
         # #############################################################################
         # ################################# Activity Monitor ##########################
         # #############################################################################
@@ -5161,6 +5174,9 @@ class App(QtCore.QObject):
         if not silent:
             self.inform.emit('[success] %s' % _("Preferences saved."))
 
+        # update the autosave timer
+        self.save_project_auto_update()
+
     def save_toolbar_view(self):
         """
         Will save the toolbar view state to the defaults
@@ -11651,6 +11667,9 @@ class App(QtCore.QObject):
         """
         App.log.debug("Opening project: " + filename)
 
+        # block autosaving while a project is loaded
+        self.block_autosave = True
+
         # for some reason, setting ui_title does not work when this method is called from Tcl Shell
         # it's because the TclCommand is run in another thread (it inherit TclCommandSignaled)
         if cli is None:
@@ -11739,6 +11758,9 @@ class App(QtCore.QObject):
         self.should_we_save = False
         self.file_opened.emit("project", filename)
 
+        # restore autosaving after a project was loaded
+        self.block_autosave = False
+
         # for some reason, setting ui_title does not work when this method is called from Tcl Shell
         # it's because the TclCommand is run in another thread (it inherit TclCommandSignaled)
         if cli is None:
@@ -12920,8 +12942,7 @@ class App(QtCore.QObject):
 
                 if silent is False:
                     if 'version' in saved_d:
-                        self.inform.emit('[success] %s: %s' %
-                                         (_("Project saved to"), filename))
+                        self.inform.emit('[success] %s: %s' % (_("Project saved to"), filename))
                     else:
                         self.inform.emit('[ERROR_NOTCL] %s: %s %s' %
                                          (_("Failed to parse saved project file"), filename, _("Retry to save it.")))
@@ -12969,7 +12990,36 @@ class App(QtCore.QObject):
         except Exception:
             traceback.print_exc()
 
+    def save_project_auto(self):
+        """
+        Called periodically to save the project.
+        It will save if there is no block on the save, if the project was saved at least once and if there is no save in
+        # progress.
+
+        :return:
+        """
+
+        if self.block_autosave is False and self.should_we_save is True and self.save_in_progress is False:
+            self.on_file_saveproject()
+
+    def save_project_auto_update(self):
+        """
+        Update the auto save time interval value.
+        :return:
+        """
+        log.debug("App.save_project_auto_update() --> updated the interval timeout.")
+        if self.autosave_timer.isActive():
+            self.autosave_timer.stop()
+        if self.defaults['global_autosave'] is True:
+            self.autosave_timer.setInterval(int(self.defaults['global_autosave_timeout']))
+            self.autosave_timer.start()
+
     def on_plotarea_tab_closed(self, tab_idx):
+        """
+
+        :param tab_idx: Index of the Tab from the plotarea that was closed
+        :return:
+        """
         widget = self.ui.plot_tab_area.widget(tab_idx)
 
         if widget is not None:

+ 36 - 10
flatcamGUI/PreferencesUI.py

@@ -1818,16 +1818,42 @@ class GeneralAppPrefGroupUI(OptionsGroupUI):
 
         self.proj_ois = OptionalInputSection(self.save_type_cb, [self.compress_label, self.compress_spinner], True)
 
+        # Auto save CB
+        self.autosave_cb = FCCheckBox(_('Enable Auto Save'))
+        self.autosave_cb.setToolTip(
+            _("Check to enable the autosave feature.\n"
+              "When enabled, the application will try to save a project\n"
+              "at the set interval.")
+        )
+
+        grid0.addWidget(self.autosave_cb, 31, 0, 1, 2)
+
+        # Auto Save Timeout Interval
+        self.autosave_entry = FCSpinner()
+        self.autosave_entry.set_range(0, 9999999)
+        self.autosave_label = QtWidgets.QLabel('%s:' % _('Interval'))
+        self.autosave_label.setToolTip(
+            _("Time interval for autosaving. In milliseconds.\n"
+              "The application will try to save periodically but only\n"
+              "if the project was saved manually at least once.\n"
+              "While active, some operations may block this feature.")
+        )
+
+        grid0.addWidget(self.autosave_label, 32, 0)
+        grid0.addWidget(self.autosave_entry, 32, 1)
+
+        # self.as_ois = OptionalInputSection(self.autosave_cb, [self.autosave_label, self.autosave_entry], True)
+
         separator_line = QtWidgets.QFrame()
         separator_line.setFrameShape(QtWidgets.QFrame.HLine)
         separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
-        grid0.addWidget(separator_line, 31, 0, 1, 2)
+        grid0.addWidget(separator_line, 33, 0, 1, 2)
 
         self.pdf_param_label = QtWidgets.QLabel('<B>%s:</b>' % _("Text to PDF parameters"))
         self.pdf_param_label.setToolTip(
             _("Used when saving text in Code Editor or in FlatCAM Document objects.")
         )
-        grid0.addWidget(self.pdf_param_label, 32, 0, 1, 2)
+        grid0.addWidget(self.pdf_param_label, 34, 0, 1, 2)
 
         # Top Margin value
         self.tmargin_entry = FCDoubleSpinner()
@@ -1839,8 +1865,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI):
             _("Distance between text body and the top of the PDF file.")
         )
 
-        grid0.addWidget(self.tmargin_label, 33, 0)
-        grid0.addWidget(self.tmargin_entry, 33, 1)
+        grid0.addWidget(self.tmargin_label, 35, 0)
+        grid0.addWidget(self.tmargin_entry, 35, 1)
 
         # Bottom Margin value
         self.bmargin_entry = FCDoubleSpinner()
@@ -1852,8 +1878,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI):
             _("Distance between text body and the bottom of the PDF file.")
         )
 
-        grid0.addWidget(self.bmargin_label, 34, 0)
-        grid0.addWidget(self.bmargin_entry, 34, 1)
+        grid0.addWidget(self.bmargin_label, 36, 0)
+        grid0.addWidget(self.bmargin_entry, 36, 1)
 
         # Left Margin value
         self.lmargin_entry = FCDoubleSpinner()
@@ -1865,8 +1891,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI):
             _("Distance between text body and the left of the PDF file.")
         )
 
-        grid0.addWidget(self.lmargin_label, 35, 0)
-        grid0.addWidget(self.lmargin_entry, 35, 1)
+        grid0.addWidget(self.lmargin_label, 37, 0)
+        grid0.addWidget(self.lmargin_entry, 37, 1)
 
         # Right Margin value
         self.rmargin_entry = FCDoubleSpinner()
@@ -1878,8 +1904,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI):
             _("Distance between text body and the right of the PDF file.")
         )
 
-        grid0.addWidget(self.rmargin_label, 36, 0)
-        grid0.addWidget(self.rmargin_entry, 36, 1)
+        grid0.addWidget(self.rmargin_label, 38, 0)
+        grid0.addWidget(self.rmargin_entry, 38, 1)
 
         self.layout.addStretch()