Esempio n. 1
0
    def _show_panel(self, panel_name):
        """
        Helper function to switch between panels.

        @param panel_name: the name of the wanted panel. Choose between
                        "configuration" or "add"
        """
        if panel_name == "configuration":
            panel_to_remove = self.add_panel
            panel_to_add = self.config_panel
            side_is_enabled = True
        elif panel_name == "add":
            panel_to_remove = self.config_panel
            panel_to_add = self.add_panel
            side_is_enabled = False
        else:
            log.error("panel name unknown")
            return
        # Central pane
        # NOTE: self.central_pane is the Gtk.Container in which we load panels
        if panel_to_remove in self.central_pane:
            self.central_pane.remove(panel_to_remove)
        if panel_to_add not in self.central_pane:
            self.central_pane.add(panel_to_add)
        self.central_pane.show_all()
        # Side treeview
        # disabled if we're adding a new backend
        try:
            # when this is called upon initialization of this class, the
            # backends_tv object has not been created yet.
            self.add_button.set_sensitive(side_is_enabled)
            self.remove_button.set_sensitive(side_is_enabled)
            self.backends_tv.set_sensitive(side_is_enabled)
        except AttributeError:
            pass
Esempio n. 2
0
    def open_help(self, action, param):
        """Open help callback."""

        try:
            Gtk.show_uri(None, "help:gtg", Gdk.CURRENT_TIME)
        except GLib.Error:
            log.error('Could not open help')
Esempio n. 3
0
    def __init__(self):
        """
         Creates a dictionary of the currently available backend modules
        """
        super().__init__()
        if hasattr(self, "backend_modules"):
            # This object has already been constructed
            return
        self.backend_modules = {}
        backend_files = self._find_backend_files()
        # Create module names
        module_names = [f.replace(".py", "") for f in backend_files]
        log.debug("Backends found: " + str(module_names))
        # Load backend modules
        for module_name in module_names:
            extended_module_name = "GTG.backends." + module_name
            try:
                __import__(extended_module_name)
            except ImportError as exception:
                # Something is wrong with this backend, skipping
                log.warning("Backend %s could not be loaded: %s" %
                            (module_name, str(exception)))
                continue
            except Exception as exception:
                # Other exception log as errors
                log.error(f"Malformated backend {module_name}: {str(exception)}")
                continue

            self.backend_modules[module_name] = \
                sys.modules[extended_module_name]
Esempio n. 4
0
    def open_task(self, uid, new=False):
        """Open the task identified by 'uid'.

            If a Task editor is already opened for a given task, we present it.
            Otherwise, we create a new one.
        """

        if uid in self.open_tasks:
            editor = self.open_tasks[uid]
            editor.present()

        else:
            task = self.req.get_task(uid)
            editor = None

            if task:
                editor = TaskEditor(requester=self.req, app=self, task=task,
                                    thisisnew=new, clipboard=self.clipboard)

                editor.present()
                self.open_tasks[uid] = editor

                # Save open tasks to config
                open_tasks = self.config.get("opened_tasks")

                if uid not in open_tasks:
                    open_tasks.append(uid)

                self.config.set("opened_tasks", open_tasks)

            else:
                log.error(f'Task {uid} could not be found!')

        return editor
Esempio n. 5
0
 def get_configuration(self):
     try:
         return datetime.time(int(self.config.get('hour')),
                              int(self.config.get('min')))
     except(ValueError):
         log.error("Invalid time values: %s:%s", self.config.get('hour'),
                   self.config.get('min'))
         return datetime.time(0, 0)
Esempio n. 6
0
def create_dirs(filepath: str) -> None:
    """Create directory tree for filepath."""

    base_dir = os.path.dirname(filepath)
    try:
        os.makedirs(base_dir, exist_ok=True)
    except IOError as error:
        log.error("Error while creating directories:", error)
Esempio n. 7
0
 def _when_taking_too_long(self):
     """
     Function that is executed when the Dbus connection seems to be
     hanging. It disables the backend and signals the error to the user.
     """
     log.error("Dbus connection is taking too long for the Tomboy/Gnote"
               "backend!")
     BackendSignals().backend_failed(self.backend.get_id(),
                                     BackendSignals.ERRNO_DBUS)
     self.backend.quit(disable=True)
Esempio n. 8
0
    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()
Esempio n. 9
0
 def _login(self):
     """
     Tries to establish a connection to rtm with a token got from the
     authentication process
     """
     try:
         self.rtm = createRTM(self.PUBLIC_KEY, self.PRIVATE_KEY, self.token)
         self.timeline = self.rtm.timelines.create().timeline
         return True
     except (RTMError, RTMAPIError) as e:
         log.error("RTM ERROR" + str(e))
     return False
Esempio n. 10
0
    def callMethod(self, aname, rargs, oargs, **params):
        # Sanity checks
        for requiredArg in rargs:
            if requiredArg not in params:
                raise TypeError(f'Required parameter ({requiredArg}) missing')

        for param in params:
            if param not in rargs + oargs:
                log.error(f'Invalid parameter ({param})')

        return self.rtm.get(method=aname,
                            auth_token=self.rtm.authInfo.get('token'),
                            **params)
Esempio n. 11
0
    def __load_icon(self):
        """
        Loads emblem icons from the current icon theme

        Sometimes an icon can't be loaded because of a bug in system
        libraries, e.g. bug #1079587. Gracefuly degradate and skip
        the loading of a corrupted icon.
        """
        self.symbol_model = Gtk.ListStore(GdkPixbuf.Pixbuf, str)
        for icon in Gtk.IconTheme.get_default().list_icons(context="Emblems"):
            try:
                img = Gtk.IconTheme.get_default().load_icon(icon, 16, 0)
                self.symbol_model.append([img, icon])
            except GObject.GError:
                log.error(f"Failed to load icon '{icon}'")
        self.symbol_iv.set_model(self.symbol_model)
        self.loaded = True
Esempio n. 12
0
def save_file(filepath: str, root: etree.ElementTree) -> None:
    """Save an XML file."""

    temp_file = filepath + '__'

    if os.path.exists(filepath):
        os.rename(filepath, temp_file)

    try:
        write_xml(filepath, root)

        if os.path.exists(temp_file):
            os.remove(temp_file)

    except (IOError, FileNotFoundError):
        log.error(f'Could not write XML file at {filepath}')
        create_dirs(filepath)
Esempio n. 13
0
def write_backups(filepath: str) -> None:
    """Make backups for the file at filepath."""

    current_back = BACKUPS
    backup_name = get_backup_name(filepath, None)
    backup_dir = os.path.dirname(backup_name)

    # Make sure backup dir exists
    try:
        os.makedirs(backup_dir, exist_ok=True)

    except IOError:
        log.error(f'Backup dir {backup_dir} cannot be created!')
        return

    # Cycle backups
    while current_back > 0:
        older = f"{backup_name}.bak.{current_back}"
        newer = f"{backup_name}.bak.{current_back - 1}"

        if os.path.exists(newer):
            shutil.move(newer, older)

        current_back -= 1

    # bak.0 is always a fresh copy of the closed file
    # so that it's not touched in case of not opening next time
    bak_0 = f"{backup_name}.bak.0"
    shutil.copy(filepath, bak_0)

    # Add daily backup
    today = datetime.today().strftime('%Y-%m-%d')
    daily_backup = f'{backup_name}.{today}.bak'

    if not os.path.exists(daily_backup):
        shutil.copy(filepath, daily_backup)
Esempio n. 14
0
 def _load_module(self, module_paths):
     """Load the module containing this plugin."""
     try:
         # import the module containing the plugin
         f, pathname, desc = imp.find_module(self.module_name, module_paths)
         module = imp.load_module(self.module_name, f, pathname, desc)
         # find the class object for the actual plugin
         for key, item in module.__dict__.items():
             if isinstance(item, type):
                 self.plugin_class = item
                 self.class_name = item.__dict__['__module__'].split('.')[1]
                 break
     except ImportError as e:
         # load_module() failed, probably because of a module dependency
         if len(self.module_depends) > 0:
             self._check_module_depends()
         else:
             # no dependencies in info file; use the ImportError instead
             self.missing_modules.append(str(e).split(" ")[3])
         self.error = True
     except Exception as e:
         # load_module() failed for some other reason
         log.error(e)
         self.error = True
Esempio n. 15
0
    def register_backend(self, backend_dic):
        """
        Registers a TaskSource as a backend for this DataStore

        @param backend_dic: Dictionary object containing all the
                            parameters to initialize the backend
                            (filename...). It should also contain the
                            backend class (under "backend"), and its
                            unique id (under "pid")
        """
        if "backend" in backend_dic:
            if "pid" not in backend_dic:
                log.error("registering a backend without pid.")
                return None
            backend = backend_dic["backend"]
            # Checking that is a new backend
            if backend.get_id() in self.backends:
                log.error("registering already registered backend")
                return None
            # creating the TaskSource which will wrap the backend,
            # filtering the tasks that should hit the backend.
            source = TaskSource(requester=self.requester,
                                backend=backend,
                                datastore=self.filtered_datastore)
            self.backends[backend.get_id()] = source
            # we notify that a new backend is present
            self._backend_signals.backend_added(backend.get_id())
            # saving the backend in the correct dictionary (backends for
            # enabled backends, disabled_backends for the disabled ones)
            # this is useful for retro-compatibility
            if GenericBackend.KEY_ENABLED not in backend_dic:
                source.set_parameter(GenericBackend.KEY_ENABLED, True)
            if GenericBackend.KEY_DEFAULT_BACKEND not in backend_dic:
                source.set_parameter(GenericBackend.KEY_DEFAULT_BACKEND, True)
            # if it's enabled, we initialize it
            if source.is_enabled() and \
                    (self.is_default_backend_loaded or source.is_default()):
                source.initialize(connect_signals=False)
                # Filling the backend
                # Doing this at start is more efficient than
                # after the GUI is launched
                source.start_get_tasks()
            return source
        else:
            log.error("Tried to register a backend without a  pid")
Esempio n. 16
0
    def _load_pickled_file(self, path, default_value=None):
        """
        A helper function to load some object from a file.

        @param path: the relative path of the file
        @param default_value: the value to return if the file is missing or
        corrupt
        @returns object: the needed object, or default_value
        """
        path = os.path.join(SYNC_DATA_DIR, path)
        if not os.path.exists(path):
            return default_value

        with open(path, 'rb') as file:
            try:
                return pickle.load(file)
            except Exception:
                log.error("Pickle file for backend '%s' is damaged" %
                          self.get_name())

        # Loading file failed, trying backups
        for i in range(1, PICKLE_BACKUP_NBR + 1):
            backup_file = f"{path}.bak.{i:d}"
            if os.path.exists(backup_file):
                with open(backup_file, 'rb') as file:
                    try:
                        data = pickle.load(file)
                        log.info("Succesfully restored backup #%d for '%s'" %
                                 (i, self.get_name()))
                        return data
                    except Exception:
                        log.error("Backup #%d for '%s' is damaged as well" %
                                  (i, self.get_name()))

        # Data could not be loaded, degrade to default data
        log.error(f"There is no suitable backup for '{self.get_name()}', "
                  "loading default data")
        return default_value
Esempio n. 17
0
    def do_render(self, cr, widget, background_area, cell_area, flags):

        vw_tags = self.__count_viewable_tags()
        count = 0

        # Select source
        if self.tag_list is not None:
            tags = self.tag_list
        elif self.tag is not None:
            tags = [self.tag]
        else:
            return

        # Drawing context
        gdkcontext = cr
        gdkcontext.set_antialias(cairo.ANTIALIAS_NONE)

        # Coordinates of the origin point
        x_align = self.get_property("xalign")
        y_align = self.get_property("yalign")
        padding = self.PADDING
        orig_x = cell_area.x + int((cell_area.width - 16 * vw_tags -
                                    padding * 2 * (vw_tags - 1)) * x_align)
        orig_y = cell_area.y + int((cell_area.height - 16) * y_align)

        # We draw the icons & squares
        for my_tag in tags:

            my_tag_icon = my_tag.get_attribute("icon")
            my_tag_color = my_tag.get_attribute("color")

            rect_x = orig_x + self.PADDING * 2 * count + 16 * count
            rect_y = orig_y

            if my_tag_icon:
                try:
                    pixbuf = Gtk.IconTheme.get_default().load_icon(
                        my_tag_icon, 16, 0)
                    Gdk.cairo_set_source_pixbuf(gdkcontext, pixbuf,
                                                rect_x, rect_y)
                    gdkcontext.paint()
                    count = count + 1
                except GLib.GError:
                    # In some rare cases an icon could not be found
                    # (e.g. wrong set icon path, missing icon)
                    # Raising an exception breaks UI and signal catcher badly
                    log.error(f"Can't load icon '{my_tag_icon}'")

            elif my_tag_color:

                # Draw rounded rectangle
                my_color = Gdk.color_parse(my_tag_color)
                Gdk.cairo_set_source_color(gdkcontext, my_color)
                self.__roundedrec(gdkcontext, rect_x, rect_y, 16, 16, 8)
                gdkcontext.fill()
                count = count + 1

                # Outer line
                Gdk.cairo_set_source_rgba(gdkcontext, Gdk.RGBA(0, 0, 0, 0.20))
                gdkcontext.set_line_width(1.0)
                self.__roundedrec(gdkcontext, rect_x, rect_y, 16, 16, 8)
                gdkcontext.stroke()

        if self.tag and my_tag:

            my_tag_icon = my_tag.get_attribute("icon")
            my_tag_color = my_tag.get_attribute("color")

            if not my_tag_icon and not my_tag_color:
                # Draw rounded rectangle
                Gdk.cairo_set_source_rgba(gdkcontext,
                                          Gdk.RGBA(0.95, 0.95, 0.95, 1))
                self.__roundedrec(gdkcontext, rect_x, rect_y, 16, 16, 8)
                gdkcontext.fill()

                # Outer line
                Gdk.cairo_set_source_rgba(gdkcontext, Gdk.RGBA(0, 0, 0, 0.20))
                gdkcontext.set_line_width(1.0)
                self.__roundedrec(gdkcontext, rect_x, rect_y, 16, 16, 8)
                gdkcontext.stroke()
Esempio n. 18
0
def openxmlfile(zefile, root):
    """ Open an XML file in a robust way

    If file could not be opened, try:
        - file__
        - file.bak.0
        - file.bak.1
        - .... until BACKUP_NBR

    If file doesn't exist, create a new file """

    # reset _USED_BACKUP and _BACKUP_FILE_INFO
    global _USED_BACKUP
    global _BACKUP_FILE_INFO
    _USED_BACKUP = False
    _BACKUP_FILE_INFO = ""
    tmpfile = zefile + '__'
    try:
        if os.path.exists(zefile):
            return _try_openxmlfile(zefile, root)
        elif os.path.exists(tmpfile):
            log.warning(f"Something happened to {zefile}. Using backup")
            os.rename(tmpfile, zefile)
            _USED_BACKUP = True
            _BACKUP_FILE_INFO = "Recovered from backup made on: " + \
                datetime.datetime.fromtimestamp(
                    os.path.getmtime(tmpfile)).strftime('%Y-%m-%d')
            return _try_openxmlfile(zefile, root)

    except IOError as msg:
        print(msg)
        sys.exit(1)

    except xml.parsers.expat.ExpatError as msg:
        errormsg = f"Error parsing XML file {zefile}: {msg}"
        log.error(errormsg)
        if os.path.exists(tmpfile):
            log.warning(f"Something happened to {zefile}. Using backup")
            os.rename(tmpfile, zefile)
            _USED_BACKUP = True
            _BACKUP_FILE_INFO = "Recovered from backup made on: " + \
                datetime.datetime.fromtimestamp(
                    os.path.getmtime(tmpfile)).strftime('%Y-%m-%d')
            # Ok, try one more time now
            try:
                return _try_openxmlfile(zefile, root)
            except Exception as msg:
                log.warning(f'Failed with reason: {msg}')

    # Try to revert to backup
    backup_name = _get_backup_name(zefile)
    for i in range(BACKUP_NBR):
        backup_file = f"{backup_name}.bak.{i:d}"
        if os.path.exists(backup_file):
            log.info(f"Trying to restore backup file {backup_file}")
            _USED_BACKUP = True
            _BACKUP_FILE_INFO = "Recovered from backup made on: " + \
                datetime.datetime.fromtimestamp(
                    os.path.getmtime(backup_file)).strftime('%Y-%m-%d')
            try:
                return _try_openxmlfile(backup_file, root)
            except Exception as msg:
                log.warning(f'Failed with reason: {msg}')

    log.info("No suitable backup was found")

    # Creating empty file
    doc, xmlproject = emptydoc(root)
    newfile = savexml(zefile, doc)
    if not newfile:
        log.error(f"Could not create a new file {zefile}")
        sys.exit(1)
    # set _USED_BACKUP even if there's a failure to notify about the same
    _USED_BACKUP = True
    _BACKUP_FILE_INFO = "No backups found. Created a new file"
    return _try_openxmlfile(zefile, root)

    # exit if execution reached this statement
    sys.exit(1)