Example #1
0
 def _changed_name(self, *obj):
     """
     callback to changes typed by user to the person name.
     Update the window title, and default name in name tab
     """
     self.update_title(self.get_menu_title())
     self.preview_name.set_markup(
         "<span size='x-large' weight='bold'>%s</span>" %
         markup_escape_text(self.get_preview_name(), -1))
     self.name_list.update_defname()
    def display_repo(self, repo):
        """
        Display details of the active repository.
        """
        self.name.set_markup("<span size='large' weight='bold'>%s</span>" %
                             markup_escape_text(repo.get_name(), -1))

        self.clear_grid()
        address_list = repo.get_address_list()
        if len(address_list) > 0:
            self.display_address(address_list[0])
            self.display_separator()
            phone = address_list[0].get_phone()
            if phone:
                self.add_row(_('Phone'), phone)

        self.display_url(repo, UrlType(UrlType.EMAIL))
        self.display_url(repo, UrlType(UrlType.WEB_HOME))
        self.display_url(repo, UrlType(UrlType.WEB_SEARCH))
        self.display_url(repo, UrlType(UrlType.WEB_FTP))
Example #3
0
 def display_person(self, active_person):
     """
     Display details of the active person.
     """
     self.load_person_image(active_person)
     self.name.set_markup(
         "<span size='large' weight='bold'>%s</span>" %
         markup_escape_text(name_displayer.display(active_person), -1))
     self.clear_grid()
     self.display_alternate_names(active_person)
     self.display_parents(active_person)
     self.display_separator()
     self.display_type(active_person, EventType(EventType.BIRTH))
     self.display_type(active_person, EventType(EventType.BAPTISM))
     self.display_type(active_person, EventType(EventType.DEATH))
     self.display_type(active_person, EventType(EventType.BURIAL))
     self.display_separator()
     self.display_attribute(active_person, _('Occupation'))
     self.display_attribute(active_person, _('Title'))
     self.display_attribute(active_person, _('Religion'))
Example #4
0
    def display_place(self, place):
        """
        Display details of the active place.
        """
        self.load_place_image(place)
        title = place_displayer.display(self.dbstate.db, place)
        self.title.set_markup("<span size='large' weight='bold'>%s</span>" %
                              markup_escape_text(title))

        self.clear_grid()
        self.add_row(_('Name'), place.get_name().get_value())
        self.add_row(_('Type'), place.get_type())
        self.display_separator()
        self.display_alt_names(place)
        self.display_separator()
        lat, lon = conv_lat_lon(place.get_latitude(),
                                place.get_longitude(),
                                format='DEG')
        if lat:
            self.add_row(_('Latitude'), lat)
        if lon:
            self.add_row(_('Longitude'), lon)
Example #5
0
    def __populate_reg_list(self):
        """ Build list of plugins"""
        self.addons = []
        new_addons_file = os.path.join(VERSION_DIR, "new_addons.txt")
        if not os.path.isfile(new_addons_file) and not static.check_done:
            if QuestionDialog2(TITLE,
                               _("3rd party addons are not shown until the "
                                 "addons update list is downloaded.  Would "
                                 "you like to check for updated addons now?"),
                               _("Yes"), _("No"),
                               parent=self.window).run():
                self._check_for_updates()
            else:
                static.check_done = True
        try:
            with open(new_addons_file,
                      encoding='utf-8') as filep:
                for line in filep:
                    try:
                        plugin_dict = safe_eval(line)
                        if not isinstance(plugin_dict, dict):
                            raise TypeError("Line with addon metadata is not "
                                            "a dictionary")
                    except:  # pylint: disable=bare-except
                        LOG.warning("Skipped a line in the addon listing: " +
                                    str(line))
                        continue
                    self.addons.append(plugin_dict)
        except FileNotFoundError:
            pass
        except Exception as err:  # pylint: disable=broad-except
            LOG.warning("Failed to open addon status file: %s", err)

        addons = []
        updateable = []
        for plugin_dict in self.addons:
            pid = plugin_dict["i"]
            plugin = self._pmgr.get_plugin(pid)
            if plugin:  # check for an already registered plugin
                LOG.debug("Comparing %s > %s",
                          version_str_to_tup(plugin_dict["v"], 3),
                          version_str_to_tup(plugin.version, 3))
                # Check for a update
                if (version_str_to_tup(plugin_dict["v"], 3) >
                        version_str_to_tup(plugin.version, 3)):
                    LOG.debug("Update for '%s'...", plugin_dict["z"])
                    updateable.append(pid)
                else:  # current plugin is up to date.
                    LOG.debug("   '%s' is up to date", plugin_dict["n"])
            else:  # new addon
                LOG.debug("   '%s' is not installed", plugin_dict["n"])
                hidden = pid in self.hidden
                status_str = _("*Available")
                status = AVAILABLE
                if hidden:
                    status_str = "<s>%s</s>" % status_str
                    status |= HIDDEN
                row = [_(plugin_dict["t"]), status_str,
                       markup_escape_text(plugin_dict["n"]),
                       markup_escape_text(plugin_dict["d"]),
                       plugin_dict["i"], status]
                addons.append(row)

        fail_list = self._pmgr.get_fail_list()
        for (_type, typestr) in PTYPE_STR.items():
            for pdata in self._preg.type_plugins(_type):
                #  model: plugintype, hidden, pluginname, plugindescr, pluginid
                if 'gramps/plugins' in pdata.fpath.replace('\\', '/'):
                    status_str = _("Built-in")
                    status = BUILTIN
                    if not self._show_builtins:
                        continue
                else:
                    status_str = _("*Installed")
                    status = INSTALLED
                # i = (filename, (exception-type, exception, traceback), pdata)
                for i in fail_list:
                    if pdata == i[2]:
                        status_str += ', ' + '<span color="red">%s</span>' % \
                            _("Failed")
                        break
                if pdata.id in updateable:
                    status_str += ', ' + _("Update Available")
                    status |= UPDATE
                hidden = pdata.id in self.hidden
                if hidden:
                    status_str = "<s>%s</s>" % status_str
                    status |= HIDDEN
                addons.append([typestr, status_str,
                               markup_escape_text(pdata.name),
                               markup_escape_text(pdata.description),
                               pdata.id, status])
        for row in sorted(addons, key=itemgetter(R_TYPE, R_NAME)):
            if self._show_hidden or (row[R_ID] not in self.hidden):
                self._model_reg.append(row)
        self._selection_reg.select_path('0')
Example #6
0
    def _get_preview_text(self, lines, query):
        max_lines = 200

        # check if the file is a Zim markup file and if so, skip header
        if lines[0] == 'Content-Type: text/x-zim-wiki':
            for i, line in enumerate(lines):
                if line == "":
                    lines = lines[i + 1:]
                    break

        if query.strip() == "":
            return "\n".join(line for line in lines[:max_lines])

        # searching for "a" cannot match "&a", since markup_escape_text("&") -> "&apos;"
        # Ignoring q == "b", it would interfere with multiple queries:
        # Ex: query "f b", text "foo", matched with "f" -> "<b>f</b>oo", matched with "b" -> "<<b>b</b>>f</<b>b</b>>"
        query_match = (re.compile("(" + re.escape(q) + ")", re.IGNORECASE)
                       for q in query.split(" ") if q != "b")
        # too long lines caused strange Gtk behaviour – monitor brightness set to maximum, without any logged warning
        # so that I decided to put just extract of such long lines in preview
        # This regex matches query chunk in the line, prepends characters before and after.
        # When there should be the same query chunk after the first, it stops.
        # Otherwise, the second chunk might be halved and thus not highlighted.
        # Ex: query "test", text: "lorem ipsum text dolor text text sit amet consectetur" ->
        #   ["ipsum text dolor ", "text ", "text sit amet"] (words "lorem" and "consectetur" are strip)
        line_extract = [
            re.compile(
                "(.{0,80}" + re.escape(q) + "(?:(?!" + re.escape(q) +
                ").){0,80})", re.IGNORECASE) for q in query.split(" ")
            if q != "b"
        ]

        # grep some lines
        keep_all = not self.plugin.preferences["preview_short"] and len(
            lines) < max_lines
        lines_iter = iter(lines)
        chosen = [
            next(lines_iter)
        ]  # always include header as the first line, even if it does not contain the query
        for line in lines_iter:
            if len(
                    chosen
            ) > max_lines:  # file is too long which would result the preview to not be smooth
                break
            elif keep_all or any(q in line.lower() for q in query.split(" ")):
                # keep this line since it contains a query chunk
                if len(line) > 100:
                    # however, this line is too long to display, try to extract query and its neighbourhood
                    s = "...".join("...".join(q.findall(line))
                                   for q in line_extract).strip(".")
                    if not s:  # no query chunk was find on this line, the keep_all is True for sure
                        chosen.append(line[:100] + "...")
                    else:
                        chosen.append("..." + s + "...")
                else:
                    chosen.append(line)
        if not keep_all or len(chosen) > max_lines:
            # note that query might not been found, ex: query "foo" would not find line with a bold 'o': "f**o**o"
            chosen.append("...")
        txt = markup_escape_text("\n".join(line for line in chosen))

        # bold query chunks in the text
        for q in query_match:
            txt = q.sub(r"<b>\g<1></b>", txt)

        # preserve markup_escape_text entities
        # correct ex: '&a<b>m</b>p;' -> '&amp;' if searching for 'm'
        bold_tag = re.compile("</?b>")
        broken_entity = re.compile("&[a-z]*<b[^;]*;")
        txt = broken_entity.sub(lambda m: bold_tag.sub("", m.group(0)), txt)
        return txt
Example #7
0
    def show_ink(self, ink, switchpage):
        inknamet = '...'
        inktagst = '-'
        inkdesct = ''
        inkavailt = '-'
        inkstatust = '-'
        inkcolordesc = '-' # тут когда-нибудь будет человекочитаемое описание цвета
        inkcolor = None
        inkmaincolor = '-'
        inkusagecnt = '...'

        self.chosenInk = ink

        self.randominkusageview.refresh_begin()

        if not ink:
            inknamet = 'ничего подходящего не нашлось'
        else:
            inkName, inkTags, inkDescription, inkAvailability = self.stats.get_ink_description(ink)

            inknamet = inkName
            inktagst = markup_escape_text(inkTags) if inkTags else '-'
            inkdesct = inkDescription
            inkavailt = markup_escape_text(inkAvailability)

            if ink.done is None:
                inkstatust = 'не нужны'
            elif ink.done:
                inkstatust = 'испытаны'
            else:
                inkstatust = 'планируется покупка'

            if ink.color:
                inkcolor = ColorValue.get_rgb32_value(ink.color)
                inkcolordesc = ColorValue.new_from_rgb24(ink.color).get_description()

            if ink.maincolor:
                inkmaincolor = self.stats.tagNames.get(ink.maincolor, ink.maincolor)

            dnow = datetime.datetime.now().date()

            inkusagecnt = 'заправок: %d' % len(ink.usage)

            for unfo in ink.usage:
                _dd = dnow - unfo.date

                self.randominkusageview.store.append((str(unfo.date),
                    'сегодня' if _dd.days <= 1 else '%d дн. назад' % _dd.days,
                    unfo.comment))

        self.randominkusageview.refresh_end()

        self.randominkname.set_text(inknamet)
        self.randominktags.set_markup(inktagst)
        self.randominkdescbuf.set_text(inkdesct)
        self.randominkavail.set_markup(inkavailt)
        self.randominkstatus.set_text(inkstatust)
        self.randominkcolordesc.set_text(inkcolordesc)
        self.randominkmaincolor.set_text(inkmaincolor)

        self.randominkusagecnt.set_text(inkusagecnt)

        if inkcolor is None:
            self.randominkcolorimg.set_from_pixbuf(self.nocoloricon)
        else:
            self.randominkColorPixbuf.fill(inkcolor)
            self.randominkcolorimg.set_from_pixbuf(self.randominkColorPixbuf)

        if switchpage:
            self.pages.set_visible_child(self.pageChooser)
Example #8
0
    def load_db(self):
        self.totalstatview.set_model(None)
        self.totalstatlstore.clear()

        self.detailstats.view.set_model(None)
        self.detailstats.store.clear()

        expand = []

        def __bool_s(b, clr=None):
            st = '√' if clr is None else '<span color="%s"><b>√</b></span>' % clr
            return st if b else ''

        CTODO = '#fd0'
        CNODO = '#c00'
        CDONE = '#0f0'

        try:
            self.db = load_ink_db(self.cfg.databaseFileName)
            self.stats = get_ink_stats(self.db)
            self.rndchooser = None

            # статистика
            if self.stats:
                dfname = os.path.split(self.cfg.databaseFileName)[-1]

                #
                # общая статистика
                #
                totals = self.stats.get_total_result_table()

                for row in totals:
                    self.totalstatlstore.append(row)

                #
                # детали
                #
                for tagstat in self.stats.tagStats:
                    itr = self.detailstats.store.append(None,
                            (None, tagstat.title, '', '', '', '', None, None))

                    expand.append(self.detailstats.store.get_path(itr))

                    _items = tagstat.stats.items()

                    # мелкий костылинг: сортироваться должны только списки,
                    # полученные обработкой директив TAGSTATS

                    if tagstat.issortable:
                        # порядок сортировки: название метки, наличие
                        # на кой чорт питонщики сделали key вместо cmp?
                        # в случае cmp не пришлось бы тратить память на
                        # значение временного ключа сортировки
                        # и фрагментировать кучу
                        def __group_key_f(r):
                            return '%5d%s' % (r[1].available,
                                              self.stats.get_tag_display_name(r[0]).lower())

                        _items = sorted(_items, key=__group_key_f, reverse=True)

                    for tag, nfo in _items:
                        row = (None, self.stats.get_tag_display_name(tag),
                            *nfo.counter_strs(), None,
                            None)

                        subitr = self.detailstats.store.append(itr, row)

                        # конкретные марки чернил сортируем уже по названию в алфавитном порядке
                        for ink in sorted(nfo.inks, key=lambda i: i.text.lower()):
                            if ink.color:
                                pbuf = Pixbuf.new(GdkPixbuf.Colorspace.RGB, False, 8, self.samplePixbufSize, self.samplePixbufSize)
                                pbuf.fill(int(ColorValue.get_rgb32_value(ink.color)))
                            else:
                                pbuf = self.nocoloricon

                            # 'название', 'отсортированный список человекочитаемых меток', 'описание', 'наличие'
                            _inkname, _inktags, _inkdesc, _inkavail = self.stats.get_ink_description(ink)

                            hint = ['<b>%s</b>' % markup_escape_text(_inkname)]

                            if ink.color:
                                hint.append('Цвет: <span color="#%.6x">██</span> %s' % (ink.color,
                                    markup_escape_text(ColorValue.new_from_rgb24(ink.color).get_description())))

                            if _inkdesc:
                                hint.append(markup_escape_text(_inkdesc))

                            if _inkavail:
                                hint.append('В наличии: %s' % markup_escape_text(_inkavail))

                            if ink.done == False:
                                hint.append('Запланирована покупка этих чернил')

                            if ink.missing:
                                hint.append('Отсутствуют данные: %s' % self.stats.get_ink_missing_data_str(ink))

                            bunwanted = ink.done is None
                            self.detailstats.store.append(subitr,
                                    (ink,
                                    ink.text,
                                    # avail
                                    __bool_s(ink.avail, CDONE),
                                    # unavail
                                    __bool_s(not ink.avail, None if bunwanted else CTODO),
                                    # wanted
                                    __bool_s(ink.done == False, CTODO), # прямое сравнение, т.к. иначе None будет воспринято тоже как False
                                    # unwanted
                                    __bool_s(bunwanted, CNODO),
                                    pbuf,
                                    '\n\n'.join(hint)))

                self.rndchooser = RandomInkChooser(self.stats, None, None)

            else:
                dfname = ''

            #
            # метки
            #
            self.tagchecklistbox.clear_items()

            def __add_tag(tagname):
                tagdisp = tagname if tagname not in self.stats.tagNames else self.stats.tagNames[tagname]
                self.tagchecklistbox.add_item(False, tagdisp, tagname)

            # в первую очередь используем только метки, учитываемые в статистике
            ntags = 0

            for tsinfo in self.stats.tagStats:
                for tagname in sorted(tsinfo.tags):
                    __add_tag(tagname)
                    ntags += 1

            # ...а вот если там меток не было - берём весь список меток
            if not ntags:
                for tagname in sorted(self.stats.tags):
                    __add_tag(tagname)

            self.includetags.clear() # пустое множество - выбирать все
            self.excludetags.clear() # пустое множество - не исключать ничего

            self.includetagstxt.set_text(self.INCLUDE_ANY)
            self.excludetagstxt.set_text(self.EXCLUDE_NOTHING)

            #

            self.openorgfiledlg.select_filename(self.cfg.databaseFileName)
            self.headerbar.set_subtitle(dfname)

            self.cfg.add_recent_file(self.cfg.databaseFileName)
            self.update_recent_files_menu()

        finally:
            self.detailstats.view.set_model(self.detailstats.store)

            for path in expand:
                self.detailstats.view.expand_row(path, False)

            self.totalstatview.set_model(self.totalstatlstore)

        self.choose_random_ink()
Example #9
0
    def view_encode(self, string, limit=25):
        if (len(string)) > limit:
            string = string[:limit] + '…'

        string = markup_escape_text(string)
        return string