Пример #1
0
    def __init__(self,
                 parent,
                 size=(770, 460),
                 title=_('About GRASS GIS'),
                 **kwargs):
        wx.Frame.__init__(self,
                          parent=parent,
                          id=wx.ID_ANY,
                          title=title,
                          size=size,
                          **kwargs)

        self.panel = wx.Panel(parent=self, id=wx.ID_ANY)

        # icon
        self.SetIcon(
            wx.Icon(os.path.join(globalvar.ICONDIR, 'grass.ico'),
                    wx.BITMAP_TYPE_ICO))

        # notebook
        self.aboutNotebook = FormNotebook(self.panel, style=wx.BK_LEFT)

        for title, win in ((_("Info"),
                            self._pageInfo()), (_("Copyright"),
                                                self._pageCopyright()),
                           (_("License"),
                            self._pageLicense()), (_("Citation"),
                                                   self._pageCitation()),
                           (_("Authors"),
                            self._pageCredit()), (_("Contributors"),
                                                  self._pageContributors()),
                           (_("Extra contributors"),
                            self._pageContributors(extra=True)),
                           (_("Translators"),
                            self._pageTranslators()), (_("Translation status"),
                                                       self._pageStats())):
            self.aboutNotebook.AddPage(page=win, text=title)
        wx.CallAfter(self.aboutNotebook.SetSelection, 0)
        wx.CallAfter(self.aboutNotebook.Refresh)

        # buttons
        self.btnClose = Button(parent=self.panel, id=wx.ID_CLOSE)
        self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)

        self._doLayout()
Пример #2
0
class AboutWindow(wx.Frame):
    """Create custom About Window
    """
    def __init__(self,
                 parent,
                 size=(770, 460),
                 title=_('About GRASS GIS'),
                 **kwargs):
        wx.Frame.__init__(self,
                          parent=parent,
                          id=wx.ID_ANY,
                          title=title,
                          size=size,
                          **kwargs)

        self.panel = wx.Panel(parent=self, id=wx.ID_ANY)

        # icon
        self.SetIcon(
            wx.Icon(os.path.join(globalvar.ICONDIR, 'grass.ico'),
                    wx.BITMAP_TYPE_ICO))

        # notebook
        self.aboutNotebook = FormNotebook(self.panel, style=wx.BK_LEFT)

        for title, win in ((_("Info"),
                            self._pageInfo()), (_("Copyright"),
                                                self._pageCopyright()),
                           (_("License"),
                            self._pageLicense()), (_("Citation"),
                                                   self._pageCitation()),
                           (_("Authors"),
                            self._pageCredit()), (_("Contributors"),
                                                  self._pageContributors()),
                           (_("Extra contributors"),
                            self._pageContributors(extra=True)),
                           (_("Translators"),
                            self._pageTranslators()), (_("Translation status"),
                                                       self._pageStats())):
            self.aboutNotebook.AddPage(page=win, text=title)
        wx.CallAfter(self.aboutNotebook.SetSelection, 0)
        wx.CallAfter(self.aboutNotebook.Refresh)

        # buttons
        self.btnClose = Button(parent=self.panel, id=wx.ID_CLOSE)
        self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)

        self._doLayout()

    def _doLayout(self):
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.Add(self.btnClose, proportion=0, flag=wx.ALL, border=5)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.aboutNotebook,
                  proportion=1,
                  flag=wx.EXPAND | wx.ALL,
                  border=1)
        sizer.Add(btnSizer,
                  proportion=0,
                  flag=wx.ALL | wx.ALIGN_RIGHT,
                  border=1)

        self.SetMinSize((400, 400))

        self.panel.SetSizer(sizer)
        sizer.Fit(self.panel)

        self.Layout()

    def _pageInfo(self):
        """Info page"""
        # get version and web site
        vInfo = grass.version()
        if not vInfo:
            sys.stderr.write(_("Unable to get GRASS version\n"))

        infoTxt = ScrolledPanel(self.aboutNotebook)
        infoTxt.SetBackgroundColour('WHITE')
        infoTxt.SetupScrolling()
        infoSizer = wx.BoxSizer(wx.VERTICAL)
        infoGridSizer = wx.GridBagSizer(vgap=5, hgap=5)
        logo = os.path.join(globalvar.ICONDIR, "grass-64x64.png")
        logoBitmap = wx.StaticBitmap(
            infoTxt, wx.ID_ANY, wx.Bitmap(name=logo, type=wx.BITMAP_TYPE_PNG))
        infoSizer.Add(logoBitmap,
                      proportion=0,
                      flag=wx.ALL | wx.ALIGN_CENTER,
                      border=20)

        infoLabel = 'GRASS GIS %s' % vInfo.get('version', _('unknown version'))
        if 'x86_64' in vInfo.get('build_platform', ''):
            infoLabel += ' (64bit)'
        info = StaticText(parent=infoTxt,
                          id=wx.ID_ANY,
                          label=infoLabel + os.linesep)
        info.SetFont(wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
        info.SetForegroundColour(wx.Colour(35, 142, 35))
        infoSizer.Add(info,
                      proportion=0,
                      flag=wx.BOTTOM | wx.ALIGN_CENTER,
                      border=1)

        team = StaticText(parent=infoTxt, label=_grassDevTeam(1999) + '\n')
        infoSizer.Add(team,
                      proportion=0,
                      flag=wx.BOTTOM | wx.ALIGN_CENTER,
                      border=1)

        row = 0
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label=_('Official GRASS site:')),
                          pos=(row, 0),
                          flag=wx.ALIGN_RIGHT)

        infoGridSizer.Add(HyperLinkCtrl(parent=infoTxt,
                                        id=wx.ID_ANY,
                                        label='https://grass.osgeo.org'),
                          pos=(row, 1),
                          flag=wx.ALIGN_LEFT)

        row += 2
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label='%s:' % _('Code Revision')),
                          pos=(row, 0),
                          flag=wx.ALIGN_RIGHT)

        infoGridSizer.Add(HyperLinkCtrl(
            parent=infoTxt,
            id=wx.ID_ANY,
            label=vInfo.get('revision', '?'),
            URL='https://github.com/OSGeo/grass.git'),
                          pos=(row, 1),
                          flag=wx.ALIGN_LEFT)

        row += 1
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label='%s:' % _('Build Date')),
                          pos=(row, 0),
                          flag=wx.ALIGN_RIGHT)

        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label=vInfo.get('build_date', '?')),
                          pos=(row, 1),
                          flag=wx.ALIGN_LEFT)

        # show only basic info
        # row += 1
        # infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
        #                                        label = '%s:' % _('GIS Library Revision')),
        #                   pos = (row, 0),
        #                   flag = wx.ALIGN_RIGHT)

        # infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
        #                                        label = vInfo['libgis_revision'] + ' (' +
        #                                        vInfo['libgis_date'].split(' ')[0] + ')'),
        #                   pos = (row, 1),
        #                   flag = wx.ALIGN_LEFT)

        row += 2
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label='Python:'),
                          pos=(row, 0),
                          flag=wx.ALIGN_RIGHT)

        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label=platform.python_version()),
                          pos=(row, 1),
                          flag=wx.ALIGN_LEFT)

        row += 1
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label='wxPython:'),
                          pos=(row, 0),
                          flag=wx.ALIGN_RIGHT)

        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label=wx.__version__),
                          pos=(row, 1),
                          flag=wx.ALIGN_LEFT)

        infoGridSizer.AddGrowableCol(0)
        infoGridSizer.AddGrowableCol(1)
        infoSizer.Add(infoGridSizer, proportion=1, flag=wx.EXPAND)

        row += 2
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label="%s:" % _('Language')),
                          pos=(row, 0),
                          flag=wx.ALIGN_RIGHT)
        self.langUsed = grass.gisenv().get('LANG', None)
        if not self.langUsed:
            import locale
            loc = locale.getdefaultlocale()
            if loc == (None, None):
                self.langUsed = _('unknown')
            else:
                self.langUsed = u'%s.%s' % (loc[0], loc[1])
        infoGridSizer.Add(StaticText(parent=infoTxt,
                                     id=wx.ID_ANY,
                                     label=self.langUsed),
                          pos=(row, 1),
                          flag=wx.ALIGN_LEFT)

        infoTxt.SetSizer(infoSizer)
        infoSizer.Fit(infoTxt)

        return infoTxt

    def _pageCopyright(self):
        """Copyright information"""
        copyfile = os.path.join(os.getenv("GISBASE"), "COPYING")
        if os.path.exists(copyfile):
            copyrightFile = open(copyfile, 'r')
            copytext = copyrightFile.read()
            copyrightFile.close()
        else:
            copytext = _('%s file missing') % 'COPYING'

        # put text into a scrolling panel
        copyrightwin = ScrolledPanel(self.aboutNotebook)
        copyrighttxt = TextCtrl(copyrightwin,
                                id=wx.ID_ANY,
                                value=copytext,
                                style=wx.TE_MULTILINE | wx.TE_READONLY)
        copyrightwin.SetAutoLayout(True)
        copyrightwin.sizer = wx.BoxSizer(wx.VERTICAL)
        copyrightwin.sizer.Add(copyrighttxt,
                               proportion=1,
                               flag=wx.EXPAND | wx.ALL,
                               border=3)
        copyrightwin.SetSizer(copyrightwin.sizer)
        copyrightwin.Layout()
        copyrightwin.SetupScrolling()

        return copyrightwin

    def _pageLicense(self):
        """Licence about"""
        licfile = os.path.join(os.getenv("GISBASE"), "GPL.TXT")
        if os.path.exists(licfile):
            licenceFile = open(licfile, 'r')
            license = ''.join(licenceFile.readlines())
            licenceFile.close()
        else:
            license = _('%s file missing') % 'GPL.TXT'
        # put text into a scrolling panel
        licensewin = ScrolledPanel(self.aboutNotebook)
        licensetxt = TextCtrl(licensewin,
                              id=wx.ID_ANY,
                              value=license,
                              style=wx.TE_MULTILINE | wx.TE_READONLY)
        licensewin.SetAutoLayout(True)
        licensewin.sizer = wx.BoxSizer(wx.VERTICAL)
        licensewin.sizer.Add(licensetxt,
                             proportion=1,
                             flag=wx.EXPAND | wx.ALL,
                             border=3)
        licensewin.SetSizer(licensewin.sizer)
        licensewin.Layout()
        licensewin.SetupScrolling()

        return licensewin

    def _pageCitation(self):
        """Citation information"""
        try:
            # import only when needed
            import grass.script as gscript
            text = gscript.read_command('g.version', flags='x')
        except CalledModuleError as error:
            text = _("Unable to provide citation suggestion,"
                     " see GRASS GIS website instead."
                     " The error was: {0}").format(error)

        # put text into a scrolling panel
        window = ScrolledPanel(self.aboutNotebook)
        stat_text = TextCtrl(window,
                             id=wx.ID_ANY,
                             value=text,
                             style=wx.TE_MULTILINE | wx.TE_READONLY)
        window.SetAutoLayout(True)
        window.sizer = wx.BoxSizer(wx.VERTICAL)
        window.sizer.Add(stat_text,
                         proportion=1,
                         flag=wx.EXPAND | wx.ALL,
                         border=3)
        window.SetSizer(window.sizer)
        window.Layout()
        window.SetupScrolling()

        return window

    def _pageCredit(self):
        """Credit about"""
        # credits
        authfile = os.path.join(os.getenv("GISBASE"), "AUTHORS")
        if os.path.exists(authfile):
            with codecs.open(authfile, encoding='utf-8',
                             mode='r') as authorsFile:
                authors = ''.join(authorsFile.readlines())
        else:
            authors = _('%s file missing') % 'AUTHORS'
        authorwin = ScrolledPanel(self.aboutNotebook)
        authortxt = TextCtrl(authorwin,
                             id=wx.ID_ANY,
                             value=authors,
                             style=wx.TE_MULTILINE | wx.TE_READONLY)
        authorwin.SetAutoLayout(True)
        authorwin.SetupScrolling()
        authorwin.sizer = wx.BoxSizer(wx.VERTICAL)
        authorwin.sizer.Add(authortxt,
                            proportion=1,
                            flag=wx.EXPAND | wx.ALL,
                            border=3)
        authorwin.SetSizer(authorwin.sizer)
        authorwin.Layout()

        return authorwin

    def _pageContributors(self, extra=False):
        """Contributors info"""
        if extra:
            contribfile = os.path.join(os.getenv("GISBASE"),
                                       "contributors_extra.csv")
        else:
            contribfile = os.path.join(os.getenv("GISBASE"),
                                       "contributors.csv")
        if os.path.exists(contribfile):
            contribFile = codecs.open(contribfile, encoding='utf-8', mode='r')
            contribs = list()
            errLines = list()
            for line in contribFile.readlines()[1:]:
                line = line.rstrip('\n')
                try:
                    if extra:
                        name, email, country, rfc2_agreed = line.split(',')
                    else:
                        cvs_id, name, email, country, osgeo_id, rfc2_agreed = line.split(
                            ',')
                except ValueError:
                    errLines.append(line)
                    continue
                if extra:
                    contribs.append((name, email, country))
                else:
                    contribs.append((name, email, country, osgeo_id))

            contribFile.close()

            if errLines:
                GError(
                    parent=self,
                    message=_("Error when reading file '%s'.") % contribfile +
                    "\n\n" + _("Lines:") +
                    " %s" % os.linesep.join(map(DecodeString, errLines)))
        else:
            contribs = None

        contribwin = ScrolledPanel(self.aboutNotebook)
        contribwin.SetAutoLayout(True)
        contribwin.SetupScrolling()
        contribwin.sizer = wx.BoxSizer(wx.VERTICAL)

        if not contribs:
            contribtxt = StaticText(contribwin,
                                    id=wx.ID_ANY,
                                    label=_('%s file missing') % contribfile)
            contribwin.sizer.Add(contribtxt,
                                 proportion=1,
                                 flag=wx.EXPAND | wx.ALL,
                                 border=3)
        else:
            if extra:
                items = (_('Name'), _('E-mail'), _('Country'))
            else:
                items = (_('Name'), _('E-mail'), _('Country'), _('OSGeo_ID'))
            contribBox = wx.FlexGridSizer(cols=len(items), vgap=5, hgap=5)
            for item in items:
                text = StaticText(parent=contribwin, id=wx.ID_ANY, label=item)
                text.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0,
                                     ""))
                contribBox.Add(text)
            for vals in sorted(contribs, key=lambda x: x[0]):
                for item in vals:
                    contribBox.Add(
                        StaticText(parent=contribwin, id=wx.ID_ANY,
                                   label=item))
            contribwin.sizer.Add(contribBox,
                                 proportion=1,
                                 flag=wx.EXPAND | wx.ALL,
                                 border=3)

        contribwin.SetSizer(contribwin.sizer)
        contribwin.Layout()

        return contribwin

    def _pageTranslators(self):
        """Translators info"""
        translatorsfile = os.path.join(os.getenv("GISBASE"), "translators.csv")
        if os.path.exists(translatorsfile):
            translatorsFile = codecs.open(translatorsfile,
                                          encoding='utf-8',
                                          mode='r')
            translators = dict()
            errLines = list()
            for line in translatorsFile.readlines()[1:]:
                line = line.rstrip('\n')
                try:
                    name, email, languages = line.split(',')
                except ValueError:
                    errLines.append(line)
                    continue
                for language in languages.split(' '):
                    if language not in translators:
                        translators[language] = list()
                    translators[language].append((name, email))
            translatorsFile.close()

            if errLines:
                GError(parent=self,
                       message=_("Error when reading file '%s'.") %
                       translatorsfile + "\n\n" + _("Lines:") +
                       " %s" % os.linesep.join(map(DecodeString, errLines)))
        else:
            translators = None

        translatorswin = ScrolledPanel(self.aboutNotebook)
        translatorswin.SetBackgroundColour('WHITE')
        translatorswin.SetAutoLayout(True)
        translatorswin.SetupScrolling()
        translatorswin.sizer = wx.BoxSizer(wx.VERTICAL)

        if not translators:
            translatorstxt = StaticText(translatorswin,
                                        id=wx.ID_ANY,
                                        label=_('%s file missing') %
                                        'translators.csv')
            translatorswin.sizer.Add(translatorstxt,
                                     proportion=1,
                                     flag=wx.EXPAND | wx.ALL,
                                     border=3)
        else:
            translatorsBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
            languages = sorted(translators.keys())
            tname = StaticText(parent=translatorswin,
                               id=wx.ID_ANY,
                               label=_('Name'))
            tname.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
            translatorsBox.Add(tname)
            temail = StaticText(parent=translatorswin,
                                id=wx.ID_ANY,
                                label=_('E-mail'))
            temail.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
            translatorsBox.Add(temail)
            tlang = StaticText(parent=translatorswin,
                               id=wx.ID_ANY,
                               label=_('Language'))
            tlang.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
            translatorsBox.Add(tlang)
            tnat = StaticText(parent=translatorswin,
                              id=wx.ID_ANY,
                              label=_('Nation'))
            tnat.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
            translatorsBox.Add(tnat)
            for lang in languages:
                for translator in translators[lang]:
                    name, email = translator
                    translatorsBox.Add(
                        StaticText(parent=translatorswin,
                                   id=wx.ID_ANY,
                                   label=name))
                    translatorsBox.Add(
                        StaticText(parent=translatorswin,
                                   id=wx.ID_ANY,
                                   label=email))
                    translatorsBox.Add(
                        StaticText(parent=translatorswin,
                                   id=wx.ID_ANY,
                                   label=lang))
                    flag = os.path.join(globalvar.ICONDIR, "flags",
                                        "%s.png" % lang.lower())
                    if os.path.exists(flag):
                        flagBitmap = wx.StaticBitmap(
                            translatorswin, wx.ID_ANY,
                            wx.Bitmap(name=flag, type=wx.BITMAP_TYPE_PNG))
                        translatorsBox.Add(flagBitmap)
                    else:
                        translatorsBox.Add(
                            StaticText(parent=translatorswin,
                                       id=wx.ID_ANY,
                                       label=lang))

            translatorswin.sizer.Add(translatorsBox,
                                     proportion=1,
                                     flag=wx.EXPAND | wx.ALL,
                                     border=3)

        translatorswin.SetSizer(translatorswin.sizer)
        translatorswin.Layout()

        return translatorswin

    def _langString(self, k, v):
        """Return string for the status of translation"""
        allStr = "%s :" % k.upper()
        try:
            allStr += _("   %d translated" % v['good'])
        except:
            pass
        try:
            allStr += _("   %d fuzzy" % v['fuzzy'])
        except:
            pass
        try:
            allStr += _("   %d untranslated" % v['bad'])
        except:
            pass
        return allStr

    def _langBox(self, par, k, v):
        """Return box"""
        langBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
        tkey = StaticText(parent=par, id=wx.ID_ANY, label=k.upper())
        langBox.Add(tkey)
        try:
            tgood = StaticText(parent=par,
                               id=wx.ID_ANY,
                               label=_("%d translated" % v['good']))
            tgood.SetForegroundColour(wx.Colour(35, 142, 35))
            langBox.Add(tgood)
        except:
            tgood = StaticText(parent=par, id=wx.ID_ANY, label="")
            langBox.Add(tgood)
        try:
            tfuzzy = StaticText(parent=par,
                                id=wx.ID_ANY,
                                label=_("   %d fuzzy" % v['fuzzy']))
            tfuzzy.SetForegroundColour(wx.Colour(255, 142, 0))
            langBox.Add(tfuzzy)
        except:
            tfuzzy = StaticText(parent=par, id=wx.ID_ANY, label="")
            langBox.Add(tfuzzy)
        try:
            tbad = StaticText(parent=par,
                              id=wx.ID_ANY,
                              label=_("   %d untranslated" % v['bad']))
            tbad.SetForegroundColour(wx.Colour(255, 0, 0))
            langBox.Add(tbad)
        except:
            tbad = StaticText(parent=par, id=wx.ID_ANY, label="")
            langBox.Add(tbad)
        return langBox

    def _langPanel(self, lang, js):
        """Create panel for each languages"""
        text = self._langString(lang, js['total'])
        panel = wx.CollapsiblePane(self.statswin,
                                   -1,
                                   label=text,
                                   style=wx.CP_DEFAULT_STYLE
                                   | wx.CP_NO_TLW_RESIZE)
        panel.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.OnPaneChanged)
        win = panel.GetPane()
        # TODO IT DOESN'T WORK
        # TO ADD ONLY WHEN TAB IS OPENED
        # if lang == self.langUsed.split('_')[0]:
        # panel.Collapse(False)
        # else:
        # panel.Collapse(True)
        pageSizer = wx.BoxSizer(wx.VERTICAL)
        for k, v in six.iteritems(js):
            if k != 'total' and k != 'name':
                box = self._langBox(win, k, v)
                pageSizer.Add(box,
                              proportion=1,
                              flag=wx.EXPAND | wx.ALL,
                              border=3)

        win.SetSizer(pageSizer)
        pageSizer.SetSizeHints(win)

        return panel

    def OnPaneChanged(self, evt):
        """Redo the layout"""
        # TODO better to test on Windows
        self.statswin.SetupScrolling(scrollToTop=False)

    def _pageStats(self):
        """Translation statistics info"""
        fname = "translation_status.json"
        statsfile = os.path.join(os.getenv("GISBASE"), fname)
        if os.path.exists(statsfile):
            statsFile = open(statsfile)
            import json
            jsStats = json.load(statsFile)
        else:
            jsStats = None
        self.statswin = ScrolledPanel(self.aboutNotebook)
        self.statswin.SetBackgroundColour('WHITE')
        self.statswin.SetAutoLayout(True)

        if not jsStats:
            Debug.msg(5, _("File <%s> not found") % fname)
            statsSizer = wx.BoxSizer(wx.VERTICAL)
            statstext = StaticText(self.statswin,
                                   id=wx.ID_ANY,
                                   label=_('%s file missing') % fname)
            statsSizer.Add(statstext,
                           proportion=1,
                           flag=wx.EXPAND | wx.ALL,
                           border=3)
        else:
            languages = sorted(jsStats['langs'].keys())

            statsSizer = wx.BoxSizer(wx.VERTICAL)
            for lang in languages:
                v = jsStats['langs'][lang]
                panel = self._langPanel(lang, v)
                statsSizer.Add(panel)

        self.statswin.SetSizer(statsSizer)
        self.statswin.SetupScrolling(scroll_x=False, scroll_y=True)
        self.statswin.Layout()
        self.statswin.Fit()
        return self.statswin

    def OnCloseWindow(self, event):
        """Close window"""
        self.Close()