def this_is_the_first_run(self, _) -> None: """ Called upon the very first GTG startup. This function is needed only in this backend, because it can be used as default one. The xml parameter is an object containing GTG default tasks. It will be saved to a file, and the backend will be set as default. @param xml: an xml object containing the default tasks. """ filepath = self.get_path() if versioning.is_required(filepath): log.warning('Found old file. Running versioning code.') old_path = os.path.join(DATA_DIR, 'gtg_tasks.xml') tree = versioning.convert(old_path, self.datastore) xml.save_file(filepath, tree) else: root = firstrun_tasks.generate() xml.create_dirs(self.get_path()) xml.save_file(self.get_path(), root) self._parameters[self.KEY_DEFAULT_BACKEND] = True # Load the newly created file self.data_tree = xml.open_file(self.get_path(), 'gtgData') self.task_tree = self.data_tree.find('tasklist') self.tag_tree = self.data_tree.find('taglist') xml.backup_used = None
def save_tags(self, tagnames, tagstore) -> None: """Save changes to tags and saved searches.""" already_saved = [] self.search_tree.clear() self.tag_tree.clear() for tagname in tagnames: if tagname in already_saved: continue tag = tagstore.get_node(tagname) attributes = tag.get_all_attributes(butname=True, withparent=True) if "special" in attributes: continue if tag.is_search_tag(): root = self.search_tree tag_type = 'savedSearch' else: root = self.tag_tree tag_type = 'tag' tid = str(tag.tid) element = root.findall(f'{tag_type}[@id="{tid}"]') if len(element) == 0: element = et.SubElement(self.task_tree, tag_type) root.append(element) else: element = element[0] # Don't save the @ in the name element.set('id', tid) element.set('name', tag.get_friendly_name()) # Remove these and don't re-add them if not needed element.attrib.pop('icon', None) element.attrib.pop('color', None) element.attrib.pop('parent', None) for attr in attributes: # skip labels for search tags if tag.is_search_tag() and attr == 'label': continue value = tag.get_attribute(attr) if value: if attr == 'color': value = value[1:] element.set(attr, value) already_saved.append(tagname) xml.save_file(self.get_path(), self.data_tree)
def remove_task(self, tid: str) -> None: """ This function is called from GTG core whenever a task must be removed from the backend. Note that the task could be not present here. @param tid: the id of the task to delete """ element = self.task_tree.findall(f"task[@id='{tid}']") if element: element[0].getparent().remove(element[0]) xml.save_file(self.get_path(), True)
def save(self, quit=False): """ Saves the backends parameters. @param quit: If quit is true, backends are shut down """ try: self.start_get_tasks_thread.join() except Exception: pass doc = etree.Element('config') # we ask all the backends to quit first. if quit: # we quit backends in parallel threads_dic = {} for b in self.get_all_backends(): thread = threading.Thread(target=b.quit) threads_dic[b.get_id()] = thread thread.start() for backend_id, thread in threads_dic.items(): # after 20 seconds, we give up thread.join(20) if thread.isAlive(): log.error("The %s backend stalled while quitting", backend_id) # we save the parameters for b in self.get_all_backends(disabled=True): t_xml = etree.SubElement(doc, 'backend') for key, value in b.get_parameters().items(): if key in ["backend", "xmlobject"]: # We don't want parameters, backend, xmlobject: # we'll create them at next startup continue param_type = b.get_parameter_type(key) value = b.cast_param_type_to_string(param_type, value) t_xml.set(str(key), value) # Saving all the projects at close doc.append(t_xml) xml.save_file(PROJECTS_XMLFILE, etree.ElementTree(doc)) xml.write_backups(PROJECTS_XMLFILE) # Saving the tagstore self.save_tagtree()
def initialize(self): """ This is called when a backend is enabled """ super(Backend, self).initialize() filepath = self.get_path() if versioning.is_required(filepath): log.warning('Found old file. Running versioning code.') old_path = os.path.join(DATA_DIR, 'gtg_tasks.xml') tree = versioning.convert(old_path, self.datastore) xml.save_file(filepath, tree) elif not os.path.isfile(filepath): root = firstrun_tasks.generate() xml.create_dirs(self.get_path()) xml.save_file(self.get_path(), root) self.data_tree = xml.open_file(filepath, 'gtgData') self.task_tree = self.data_tree.find('tasklist') self.tag_tree = self.data_tree.find('taglist') self.search_tree = self.data_tree.find('searchlist') self.datastore.load_tag_tree(self.tag_tree) self.datastore.load_search_tree(self.search_tree) # Make safety daily backup after loading xml.save_file(self.get_path(), self.data_tree) xml.write_backups(self.get_path())
def __init__(self, parameters: Dict): """ Instantiates a new backend. @param parameters: A dictionary of parameters, generated from _static_parameters. A few parameters are added to those, the list of these is in the "DefaultBackend" class, look for the KEY_* constants. The backend should take care if one expected value is None or does not exist in the dictionary. """ super().__init__(parameters) if self.KEY_DEFAULT_BACKEND not in parameters: parameters[self.KEY_DEFAULT_BACKEND] = True self.task_tree = xml.open_file(self.get_path(), 'project') self.backup_used = None # Make safety daily backup after loading xml.save_file(self.get_path(), self.task_tree) xml.write_backups(self.get_path())
def set_task(self, task) -> None: """ This function is called from GTG core whenever a task should be saved, either because it's a new one or it has been modified. This function will look into the loaded XML object if the task is present, and if it's not, it will create it. Then, it will save the task data in the XML object. @param task: the task object to save """ tid = task.get_id() element = xml.task_to_element(task) existing = self.task_tree.findall(f"task[@id='{tid}']") if existing and element != existing[0]: existing[0].getparent().replace(existing[0], element) else: self.task_tree.getroot().append(element) # Write the xml xml.save_file(self.get_path(), self.task_tree)
def save_tagtree(self): """ Saves the tag tree to an XML file """ if not self.tagfile_loaded: return xmlroot = etree.Element(TAG_XMLROOT) tags = self._tagstore.get_main_view().get_all_nodes() already_saved = [] for tagname in tags: if tagname in already_saved: continue tag = self._tagstore.get_node(tagname) attributes = tag.get_all_attributes(butname=True, withparent=True) if "special" in attributes or len(attributes) == 0: continue t_xml = etree.SubElement(xmlroot, 'tag') t_xml.set('name', tagname) for attr in attributes: # skip labels for search tags if tag.is_search_tag() and attr == 'label': continue value = tag.get_attribute(attr) if value: t_xml.set(attr, value) xmlroot.append(t_xml) already_saved.append(tagname) xml.save_file(TAGS_XMLFILE, etree.ElementTree(xmlroot)) xml.write_backups(TAGS_XMLFILE)