Exemplo n.º 1
0
def set_user_count(normal, ops):
    """ sets the amount of users in the current channel. """

    m_users = gettext.ngettext("%d User", "%d Users", normal) % (normal)
    m_ops = gettext.ngettext("%d Operator", "%d Operators", ops) % (ops)

    widgets.get_object("nick_stats_label").set_text("%(users)s – %(ops)s" % {"users": m_users, "ops": m_ops})
    def __updateStatusbar(self):
        """ Update the status bar """
        # Tracklist
        count = len(self.tracklist)
        if count == 0:
            self.status1.set_label('')
        else:
            self.status1.set_label(ngettext('One track in playlist  [%(length)s]', '%(count)u tracks in playlist  [%(length)s]', count) \
                                      % {'count': count, 'length': tools.sec2str(self.playtime)})

        # Selected tracks
        count = len(self.selTracks)
        if count == 0:
            self.status2.set_label('')
        else:
            selection = ngettext('One track selected', '%(count)u tracks selected', count) % {'count': count}

            audioType = self.selTracks[0].getType()
            for track in self.selTracks[1:]:
                if track.getType() != audioType:
                    audioType = _('various')
                    break

            bitrate = self.selTracks[0].getBitrate()
            for track in self.selTracks[1:]:
                if track.getBitrate() != bitrate:
                    bitrate = _('various')
                    break

            self.status2.set_label(_('%(selection)s (Type: %(type)s, Bitrate: %(bitrate)s)') % {'selection': selection, 'type': audioType, 'bitrate': bitrate})
Exemplo n.º 3
0
def beautify_time_delta(seconds):
    """
    Converts the given time in seconds to a human-readable estimate.

    This is intended for "Unsaved changes" and "Backup file found" dialogs.
    """
    mins = seconds / 60
    sec = int(seconds % 60)
    hours = mins / 60
    mins = int(mins % 60)
    days = int(hours / 24)
    hours = int(hours % 24)

    parts = []
    if days > 0:
        parts.append(ngettext("%d day", "%d days", days) % days)
    if hours > 0:
        parts.append(ngettext("%d hour", "%d hours", hours) % hours)

    if days == 0 and mins > 0:
        parts.append(ngettext("%d minute", "%d minutes", mins) % mins)

    if hours == 0 and mins < 2 and sec:
        parts.append(ngettext("%d second", "%d seconds", sec) % sec)

    return ", ".join(parts)
 def secs_to_readable(self, seconds):
     '''Convert seconds to a more friendly format.'''
     if seconds >= 60:
         minutes = seconds / 60
         return ngettext("%d minute", "%d minutes", minutes) % (minutes,)
     else:
         return ngettext("%d second", "%d seconds", seconds) % (seconds,)
Exemplo n.º 5
0
    def _sourcesStoppedImportingCb(self, unused_project):
        self.debug("Importing took %.3f seconds",
                   time.time() - self.import_start_time)
        self._flushPendingRows()
        self._progressbar.hide()
        if self._errors:
            errors_amount = len(self._errors)
            btn_text = ngettext("View error", "View errors", errors_amount)
            # Translators: {0:d} is just like %d (integer number variable)
            text = ngettext("An error occurred while importing.",
                            "{0:d} errors occurred while importing.",
                            errors_amount)
            # Do the {0:d} (aka "%d") substitution using "format" instead of %,
            # avoiding tracebacks as %d would be missing in the singular form:
            text = text.format(errors_amount)

            self._view_error_button.set_label(btn_text)
            self._warning_label.set_text(text)
            self._import_warning_infobar.show_all()

        missing_thumbs = self._missing_thumbs
        self._missing_thumbs = []
        if missing_thumbs:
            self.info("Generating missing thumbnails: %d", len(missing_thumbs))
            self._thumbs_process = threading.Thread(
                target=MediaLibraryWidget._generateThumbnailsThread, args=(self, missing_thumbs))
            self._thumbs_process.start()

        self._selectLastImportedUris()
Exemplo n.º 6
0
def make_status_info(status_lines, toplevel):
    """Return a GtkLabel with a summary of changed/untracked files.

    Also, a tooltip reveals the project's toplevel path and all changed/
    untracked files with their git status code.
    """
    status_lines = status_lines.rstrip("\x00")
    tooltip_text = _("Toplevel path") + ":\n   %s" % toplevel
    if not status_lines:
        status_info = _("Everything up-to-date.")
    else:
        status_array = status_lines.split("\x00")
        untracked = [status.lstrip("?? ") for status in status_array
                     if status.startswith("?")]
        changed = [status for status in status_array
                   if status.lstrip("?? ") not in untracked]
        num_untracked = len(untracked)
        num_changed = len(changed)
        status_info = ""

        if num_changed > 0:
            status_info = gettext.ngettext("%d change", "%d changes",
                                           num_changed) % num_changed
            tooltip_text += "\n\n" + _("Changes") + ":\n   " + "\n   ".join(changed)

        if num_untracked > 0:
            if num_changed:
                status_info += ", "
            status_info += gettext.ngettext("%d untracked", "%d untracked",
                                            num_untracked) % num_untracked
            tooltip_text += "\n\n" + _("Untracked") + ":\n   " + "\n   ".join(untracked)

    widget = Gtk.Label(status_info)
    widget.set_tooltip_text(tooltip_text)
    return widget
Exemplo n.º 7
0
 def get_info_markup(self, info = None):
     seasons = len(self.get_seasons())
     if seasons:
         episodes_info = info or self.get_episodes_info()
         episodes_to_watch = episodes_info['episodes_to_watch']
         next_episode = episodes_info['next_episode']
         show_info = gettext.ngettext('%s season', '%s seasons', seasons) \
                      % seasons
         if self.is_completely_watched():
             show_info += '<br/>' + _('Completely watched')
             if self.status and self.status == 'Ended':
                 show_info += '<br/>' + _('Show has ended')
         else:
             if episodes_to_watch:
                 n_episodes_to_watch = len(episodes_to_watch)
                 show_info += '<br/>' + gettext.ngettext('%s episode not watched',
                                                       '%s episodes not watched',
                                                       n_episodes_to_watch) \
                                                       % n_episodes_to_watch
             else:
                 show_info += '<br/>' + _('No episodes to watch')
             if next_episode:
                 next_air_date = next_episode.air_date
                 if next_air_date:
                     show_info += '<br/>' + _('<i>Next:</i> %s, %s') % \
                                  (next_episode.get_episode_show_number(), \
                                  next_episode.get_air_date_text())
                 else:
                     show_info += '<br/>' + _('<i>Next:</i> %s') % \
                                  next_episode.get_episode_show_number()
     else:
         show_info = ''
     return show_info
Exemplo n.º 8
0
    def statstext(self, stats):
        # XXX translate expressions, not words
        statslabel = '%s %s\n.' % (stats['songs'],
                                   gettext.ngettext('song', 'songs',
                                                    int(stats['songs'])))
        statslabel += '%s %s\n.' % (stats['albums'],
                                    gettext.ngettext('album', 'albums',
                                                     int(stats['albums'])))
        statslabel += '%s %s\n.' % (stats['artists'],
                                   gettext.ngettext('artist', 'artists',
                                                    int(stats['artists'])))
        try:
            db_playtime = float(stats['db_playtime'])
            hours_of_playtime = misc.convert_time(db_playtime).split(':')[-3]
        except:
            hours_of_playtime = '0'
        if int(hours_of_playtime) >= 24:
            days_of_playtime = str(int(hours_of_playtime) / 24)
            statslabel += '%s %s.' % (days_of_playtime,
                                      gettext.ngettext('day of bliss',
                                                       'days of bliss',
                                                       int(days_of_playtime)))
        else:
            statslabel += '%s %s.' % (hours_of_playtime,
                                      gettext.ngettext('hour of bliss',
                                                       'hours of bliss',
                                                       int(hours_of_playtime)))

        return statslabel
Exemplo n.º 9
0
	def _create_unhide_item(self, files, hidden_path, hidden):
		"""Creates the 'Unhide file(s)' menu item."""
		item = Nemo.MenuItem(name="NemoHide::UnhideFile",
		                         label=ngettext("Un_hide File", "Un_hide Files", len(files)),
		                         tip=ngettext("Unhide this file", "Unhide these files", len(files)))
		item.connect("activate", self._unhide_run, files, hidden_path, hidden)
		return item
 def check_status(self):
     changed = False
     countInstall = 0
     countRemove = 0
     for (lang, langInfo) in self._langlist:
         if langInfo.changes:
             changed = True
             for item in langInfo.languagePkgList.values():
                 if item.doChange:
                     if item.installed:
                         countRemove = countRemove + 1
                     else:
                         countInstall = countInstall + 1
     #print "%(INSTALL)d to install, %(REMOVE)d to remove" % (countInstall, countRemove)
     # Translators: %(INSTALL)d is parsed; either keep it exactly as is or remove it entirely, but don't translate "INSTALL".
     textInstall = gettext.ngettext("%(INSTALL)d to install", "%(INSTALL)d to install", countInstall) % {'INSTALL': countInstall}
     # Translators: %(REMOVE)d is parsed; either keep it exactly as is or remove it entirely, but don't translate "REMOVE".
     textRemove = gettext.ngettext("%(REMOVE)d to remove", "%(REMOVE)d to remove", countRemove) % {'REMOVE': countRemove}
     if countRemove == 0 and countInstall == 0: 
         self.label_install_remove.set_text("")
     elif countRemove == 0: 
         self.label_install_remove.set_text(textInstall)
     elif countInstall == 0: 
         self.label_install_remove.set_text(textRemove)
     else: 
         # Translators: this string will concatenate the "%n to install" and "%n to remove" strings, you can replace the comma if you need to.
         self.label_install_remove.set_text(_("%s, %s") % (textInstall, textRemove))
     
     if changed:
         self.button_apply.set_sensitive(True)
     else:
         self.button_apply.set_sensitive(False)
Exemplo n.º 11
0
 def you_win_callback (self, grid):
     if hasattr(self, 'dancer'):
         return
     self.won = True
     # increase difficulty for next time.
     self.mateconf['difficulty'] = self.mateconf['difficulty'] + 0.1
     self.timer.finish_timing()
     self.sudoku_tracker.finish_game(self)
     sublabel = _("You completed the puzzle in %(totalTime)s (%(activeTime)s active)") % {'totalTime': self.timer.total_time_string(),
     'activeTime': self.timer.active_time_string()
             }
     sublabel += "\n"
     sublabel += ngettext("You got %(n)s hint", "You got %(n)s hints", self.gsd.hints) % {'n':self.gsd.hints}
     sublabel += "\n"
     if self.gsd.impossible_hints:
         sublabel += ngettext("You had %(n)s impossibility pointed out.",
                              "You had %(n)s impossibilities pointed out.",
                              self.gsd.impossible_hints) % {'n':self.gsd.impossible_hints}
         sublabel += "\n"
     if self.gsd.auto_fills:
         sublabel += ngettext("You used the auto-fill %(n)s time",
                              "You used the auto-fill %(n)s times",
                              self.gsd.auto_fills) % {'n':self.gsd.auto_fills}
     import dancer
     self.dancer = dancer.GridDancer(self.gsd)
     self.dancer.start_dancing()
     dialog_extras.show_message(_("You win!"), label = _("You win!"),
                                sublabel = sublabel
                                )
Exemplo n.º 12
0
	def _create_hide_item(self, files, hidden_path, hidden):
		"""Creates the 'Hide file(s)' menu item."""
		item = Nautilus.MenuItem(name="NautilusHide::HideFile",
		                         label=ngettext("_Hide File", "_Hide Files", len(files)),
		                         tip=ngettext("Hide this file", "Hide these files", len(files)))
		item.connect("activate", self._hide_run, files, hidden_path, hidden)
		return item
Exemplo n.º 13
0
 def get_status_text(self):
     """return user readable status text suitable for a status bar"""
     # no status text in the details page
     if self.notebook.get_current_page() == self.PAGE_APP_DETAILS:
         return ""
     # otherwise, show status based on search or not
     model = self.app_view.get_model()
     if not model:
         return ""
     length = len(self.app_view.get_model())
     if self.channel.installed_only:
         if len(self.searchentry.get_text()) > 0:
             return gettext.ngettext("%(amount)s matching item",
                                     "%(amount)s matching items",
                                     length) % {'amount': length}
         else:
             return gettext.ngettext("%(amount)s item installed",
                                     "%(amount)s items installed",
                                     length) % {'amount': length}
     else:
         if len(self.searchentry.get_text()) > 0:
             return gettext.ngettext("%(amount)s matching item",
                                     "%(amount)s matching items",
                                     length) % {'amount': length}
         else:
             return gettext.ngettext("%(amount)s item available",
                                     "%(amount)s items available",
                                     length) % {'amount': length}
Exemplo n.º 14
0
def format_friendly_date (tim):
    local_tim = time.localtime(tim)
    diff = int(time.time() - tim)
    curr_hour, curr_min = time.localtime()[3:5]
    now_to_yesterday = curr_hour * 60 * 60 + curr_min * 60
    if diff < now_to_yesterday:
        # Then we're today
        if diff < 60: # within the minute
            return ngettext("%(n)s second ago",
                            "%(n)s seconds ago", diff) % {'n': diff}
        elif diff < (60 * 60): # within the hour...
            minute = int(diff / 60)
            return ngettext("%(n)s minute ago",
                            "%(n)s minutes ago", minute) % {'n': minute}
        else:
            # Translators, see strftime manual in order to translate %? format strings
            return time.strftime(_("at %I:%M %p"), local_tim)
    elif diff < now_to_yesterday + (60 * 60 * 24):
        # Translators, see strftime manual in order to translate %? format strings
        return time.strftime(_("yesterday at %I:%M %p"), local_tim)
    elif diff < now_to_yesterday + (60 * 60 * 24) * 6:
        # Translators, see strftime manual in order to translate %? format strings
        return time.strftime(_("%A %I:%M %p"), local_tim)
    else:
        # Translators, see strftime manual in order to translate %? format strings
        return time.strftime(_("%B %e"), local_tim)
Exemplo n.º 15
0
def get_nice_date_string(cur_t):
    """ return a "nice" human readable date, like "2 minutes ago"  """
    import datetime

    dt = datetime.datetime.utcnow() - cur_t
    days = dt.days
    secs = dt.seconds

    if days < 1:
        if secs < 120:   # less than 2 minute ago
            s = _('a few minutes ago')   # dont be fussy

        elif secs < 3600:   # less than an hour ago
            s = gettext.ngettext("%(min)i minute ago",
                                 "%(min)i minutes ago",
                                 (secs / 60)) % {'min': (secs / 60)}

        else:   # less than a day ago
            s = gettext.ngettext("%(hours)i hour ago",
                                 "%(hours)i hours ago",
                                 (secs / 3600)) % {'hours': (secs / 3600)}
    elif days <= 5:  # less than a week ago
        s = gettext.ngettext("%(days)i day ago",
                             "%(days)i days ago",
                             days) % {'days': days}
    else:   # any timedelta greater than 5 days old
        # YYYY-MM-DD
        s = cur_t.isoformat().split('T')[0]
    return s
Exemplo n.º 16
0
def get_last_synced(folder):
    try:
        timestamp = open(os.path.join(folder, 'synced')).read()
        now = time.time()

        o_delta = datetime.timedelta(seconds=float(timestamp))
        n_delta = datetime.timedelta(seconds=now)

        difference = n_delta - o_delta

        weeks, days = divmod(difference.days, 7)

        minutes, seconds = divmod(difference.seconds, 60)
        hours, minutes = divmod(minutes, 60)

        if weeks:
            return ngettext('%d week ago', '%d weeks ago', weeks) % weeks
        if days:
            return ngettext('%d day ago', '%d days ago', days) % days
        if hours:
            return ngettext('%d hour ago', '%d hours ago', hours) % hours
        if minutes:
            return ngettext('%d minute ago', '%d minutes ago', minutes) % minutes
        return _('Just Now')
    except:
        return _('Never')
Exemplo n.º 17
0
 def __disabled_pubs_info(self, disabled_pubs):
         if len(disabled_pubs) == 0:
                 return
         num = len(disabled_pubs)       
         msg = ngettext(
             "The following publisher is disabled:\n",
             "The following publishers are disabled:\n", num)
                 
         for pub in disabled_pubs:
                 msg += _("\t<b>%s</b>\n") % pub
                 
         msg += ngettext(
             "\nClicking OK will enable the publisher before proceeding with "
             "install. On completion it will be disabled again.",
             "\nClicking OK will enable the publishers before proceeding with "
             "install.\nOn completion they will be disabled again.",
             num)
                 
         msgbox = gtk.MessageDialog(
             parent = self.w_webinstall_dialog,
             buttons = gtk.BUTTONS_OK_CANCEL,
             flags = gtk.DIALOG_MODAL, type = gtk.MESSAGE_INFO,
             message_format = None)
         msgbox.set_markup(msg)
         title = ngettext("Disabled Publisher", "Disabled Publishers", 
             len(disabled_pubs))
         msgbox.set_title(title)
         msgbox.set_default_response(gtk.RESPONSE_OK)               
         
         response = msgbox.run()
         if response == gtk.RESPONSE_OK:
                 gobject.idle_add(self.__proceed)
         msgbox.destroy()
         return
Exemplo n.º 18
0
 def _about(self, action, param):
     """
         Setup about dialog
         @param action as Gio.SimpleAction
         @param param as GLib.Variant
     """
     builder = Gtk.Builder()
     builder.add_from_resource('/org/gnome/Lollypop/AboutDialog.ui')
     if self.scanner.is_locked():
         builder.get_object('button').set_sensitive(False)
     builder.get_object('button').connect('clicked',
                                          self._on_reset_clicked,
                                          builder.get_object('progress'))
     artists = self.artists.count()
     albums = self.albums.count()
     tracks = self.tracks.count()
     builder.get_object('artists').set_text(
                     ngettext("%d artist", "%d artists", artists) % artists)
     builder.get_object('albums').set_text(
                         ngettext("%d album", "%d albums", albums) % albums)
     builder.get_object('tracks').set_text(
                         ngettext("%d track", "%d tracks", tracks) % tracks)
     about = builder.get_object('about_dialog')
     about.set_transient_for(self.window)
     about.connect("response", self._about_response)
     about.show()
Exemplo n.º 19
0
def pithy_timesince(d, preposition=''):
    '''
        Concise timesince.
        Modified from Pownce pithy_timesince and django timesince.
    '''
    if d is None:
        return None
    chunks = (
      (60 * 60 * 24 * 365, lambda n, d: _('%(prep)s %(date)s') % { 'prep': preposition, 'date': defaultfilters.date(d, 'M j, Y') }), # 1 year+
      (60 * 60 * 24 * 7, lambda n, d: _('%(prep)s %(date)s') % { 'prep': preposition, 'date': defaultfilters.date(d, 'M jS') }), # 1 week+
      (60 * 60 * 24, lambda n, d: ngettext('%d day ago', '%d days ago', n // (60 * 60 * 24)) % (n // (60 * 60 * 24),)), # 1 day+
      (60 * 60, lambda n, d: ngettext('%d hour ago', '%d hours ago', n // (60 * 60)) % (n // (60 * 60),)), # 1 hour+
      (60 * 2, lambda n, d: ngettext('%d minute ago', '%d minutes ago', n // 60) % (n // 60,)), # 2 minutes+
      (1, lambda n, d: _('just now')) # under 2 mins ago
    )
    t = time.localtime()
    if d.tzinfo:
        tz = LocalTimezone(d)
    else:
        tz = None
    now = datetime.datetime(t[0], t[1], t[2], t[3], t[4], t[5], tzinfo=tz)
    # ignore microsecond part of 'd' since we removed it from 'now'
    delta = now - (d - datetime.timedelta(0, 0, d.microsecond))
    since = delta.days * 24 * 60 * 60 + delta.seconds

    for i, (seconds, label) in enumerate(chunks):
        count = since // seconds # truncated division
        if count != 0:
            break
    return label(since, d)
Exemplo n.º 20
0
 def _get_last_apt_get_update_text(self):
     """
     return a human readable string with the information when
     the last apt-get update was run
     """
     ago_hours = self._get_last_apt_get_update_hours()
     if ago_hours is None:
         return _("It is unknown when the package information was "
                  "updated last. Please try clicking on the 'Check' "
                  "button to update the information.")
     ago_days = int( ago_hours / 24 )
     if ago_days > self.NO_UPDATE_WARNING_DAYS:
         return _("The package information was last updated %(days_ago)s "
                  "days ago.\n"
                  "Press the 'Check' button below to check for new software "
                  "updates.") % { "days_ago" : ago_days, }
     elif ago_days > 0:
         return ngettext("The package information was last updated %(days_ago)s day ago.",
                         "The package information was last updated %(days_ago)s days ago.",
                         ago_days) % { "days_ago" : ago_days, }
     elif ago_hours > 0:
         return ngettext("The package information was last updated %(hours_ago)s hour ago.",
                         "The package information was last updated %(hours_ago)s hours ago.",
                         ago_hours) % { "hours_ago" : ago_hours, }
     else:
         return _("The package information was last updated less than one hour ago.")
     return None
Exemplo n.º 21
0
def ldnp(td, ctxt, id, idp, n, *args):
    if not dir or nolocales: _die("please set a locale directory with l_dir() before using other translate functions")

    if idp: args = (n,) + args
    out = None
    if dry:
        if not nowrite:
            save = []
            if td: save.push(' # domain: '+td)
            if ctxt: save.push('msgctxt: "'+gettext_escape(ctxt)+'"')
            save.push('msgid "'+gettext_escape(id)+'"')
            if idp: save.push('msgid_plural "'+gettext_escape(idp)+'"')
            wd(save)
        out = (idp if idp and n != 1 else id) % args
    else:
        if       td and not ctxt and id and     idp and     n: out = sprintf(dngettext(td, id, idp, n), *args)
        elif not td and not ctxt and id and     idp and     n: out = sprintf(ngettext(id, idp, n), *args)
        elif not td and not ctxt and id and not idp and not n: out = sprintf(gettext(id), *args)
        elif     td and not ctxt and id and not idp and not n: out = sprintf(dgettext(td, id), *args)

        # with context magic
        if       td and     ctxt and id and     idp and     n: out = sprintf(dngettext(td, ctxt+'\x04'+id, ctxt+'\x04'+idp, n), *args)
        elif not td and     ctxt and id and     idp and     n: out = sprintf(ngettext(ctxt+'\x04'+id, ctxt+'\x04'+idp, n), *args)
        elif not td and     ctxt and id and not idp and not n: out = sprintf(gettext(ctxt+'\x04'+id), *args)
        elif     td and     ctxt and id and not idp and not n: out = sprintf(dgettext(td, ctxt+'\x04'+id), *args)
    return out
Exemplo n.º 22
0
 def __set_updates_str(self, str_fmt):
         if self.n_updates == 0:
                 updates_str = ""
         else:
                 updates_fmt = ngettext("%d Update,", "%d Updates,",
                     self.n_updates)
                 updates_str = updates_fmt % self.n_updates
         if self.n_installs == 0:
                 installs_str = ""
         else:
                 installs_fmt = ngettext("%d Install,", "%d Installs,",
                     self.n_installs)
                 installs_str = installs_fmt % self.n_installs
         if self.n_removes == 0:
                 removes_str = ""
         else:
                 removes_fmt = ngettext("%d Remove", "%d Removes",
                     self.n_removes)
                 removes_str = removes_fmt % self.n_removes
         updates_str = str_fmt % \
             {"updates": updates_str,
             "installs": installs_str,
             "removes": removes_str}
         updates_str = updates_str.rstrip(', ')
         return updates_str
Exemplo n.º 23
0
 def update_progress_bar (self):
     if self.generateForTargetRadio.get_active():
         tot = int(self.newSudokusSpinButton.get_value())
         self.prog.set_fraction(
             float(self.generated())/tot
             )
         try:
             txt = ngettext('Generated %(n)s out of %(total)s puzzle',
                            'Generated %(n)s out of %(total)s puzzles',
                            tot) % {'n':self.generated(), 'total':tot}
         except TypeError:
             # Allow for fuzzy translation badness caused by a
             # previous version having this done the wrong way
             # (i.e. the previous version didn't use the dictionary
             # method for the format string, which meant
             # translators couldn't change the word order here.
             try:
                 txt = ngettext('Generated %(n)s out of %(total)s puzzle',
                                'Generated %(n)s out of %(total)s puzzles',
                                tot) % (self.generated(), tot)
             except:
                 # Fallback to English
                 txt = 'Generated %s out of %s puzzles' % (self.generated(), tot)
     else:
         self.prog.pulse()
         txt = ngettext('Generated %(n)s puzzle', 'Generated %(n)s puzzles', self.generated()) % {'n':self.generated()}
     if self.paused:
         txt = txt + ' (' + _('Paused') + ')'
     self.prog.set_text(txt)
Exemplo n.º 24
0
 def can_close(self):
     if self._force_close:
         return True
     elif downloadmanager.can_quit():
         return True
     else:
         alert = Alert()
         alert.props.title = ngettext('Download in progress',
                                      'Downloads in progress',
                                      downloadmanager.num_downloads())
         message = ngettext('Stopping now will erase your download',
                            'Stopping now will erase your downloads',
                            downloadmanager.num_downloads())
         alert.props.msg = message
         cancel_icon = Icon(icon_name='dialog-cancel')
         cancel_label = ngettext('Continue download', 'Continue downloads',
                                 downloadmanager.num_downloads())
         alert.add_button(Gtk.ResponseType.CANCEL, cancel_label,
                          cancel_icon)
         stop_icon = Icon(icon_name='dialog-ok')
         alert.add_button(Gtk.ResponseType.OK, _('Stop'), stop_icon)
         stop_icon.show()
         self.add_alert(alert)
         alert.connect('response', self.__inprogress_response_cb)
         alert.show()
         self.present()
         return False
Exemplo n.º 25
0
def timestamp_diff(timestamp, reference_time):
    """
    Takes as input the timestamp and outputs a text representing the time
    difference of the timestamp from a reference_time.

    :param timestamp:      Timestamp for which difference is calculated.
    :param reference_time: Reference time for difference to be calculated.
    """
    timediff = time.mktime(reference_time)-time.mktime(timestamp)
    d = datetime.timedelta(seconds=timediff)
    total_secs = d.total_seconds()
    if total_secs < 60:
        return "Just Now"
    elif total_secs < 3600:
        minutes = d.seconds // 60
        return ngettext("A minute ago", "{minutes} minutes ago",
                        minutes).format(minutes=minutes)
    elif total_secs <= 43200:
        hours = d.seconds // 3600
        return ngettext("An hour ago",
                        "{hours} hours ago",
                        hours).format(hours=hours)
    elif d.days == 0:
        return "Today"
    elif d.days == 1:
        return "Yesterday"
    elif total_secs // 3600 < 7 * 24 - reference_time.tm_hour:
        return time.strftime("%A", timestamp)
    elif d.days < 14:
        return "1 week ago"
    elif d.days <= reference_time.tm_yday:
        return time.strftime("%B", timestamp)
    else:
        return time.strftime("%Y", timestamp)
Exemplo n.º 26
0
def beautify_length(length):
    """Converts the specified duration to a human readable string.

    Args:
        length (int): The duration in nanoseconds.
    """
    if length == Gst.CLOCK_TIME_NONE:
        return ""

    sec = length / Gst.SECOND
    mins = int(sec / 60)
    sec = int(sec % 60)
    hours = int(mins / 60)
    mins = int(mins % 60)

    parts = []
    if hours:
        parts.append(ngettext("%d hour", "%d hours", hours) % hours)

    if mins:
        parts.append(ngettext("%d minute", "%d minutes", mins) % mins)

    if not hours and sec:
        parts.append(ngettext("%d second", "%d seconds", sec) % sec)

    return ", ".join(parts)
Exemplo n.º 27
0
    def on_transfer_progress(self, _transfer, progress):
        self.transferred = progress
        if self._last_bytes == 0:
            self.total_transferred += progress
        else:
            self.total_transferred += (progress - self._last_bytes)

        self._last_bytes = progress

        tm = time.time()
        if tm - self._last_update > 0.5:
            spd = self.speed.calc(self.total_transferred)
            (size, units) = format_bytes(spd)
            try:
                x = ((self.total_bytes - self.total_transferred) / spd) + 1
                if x > 60:
                    x /= 60
                    eta = ngettext("%.0f Minute", "%.0f Minutes", round(x)) % x
                else:
                    eta = ngettext("%.0f Second", "%.0f Seconds", round(x)) % x
            except ZeroDivisionError:
                eta = "∞"

            self.pb.props.text = _("Sending File") + (" %(0)s/%(1)s (%(2).2f %(3)s/s) " + _("ETA:") + " %(4)s") % {
                "1": self.num_files,
                "0": (self.num_files - len(self.files) + 1),
                "2": size,
                "3": units,
                "4": eta}
            self._last_update = tm

        self.pb.props.fraction = float(self.total_transferred) / self.total_bytes
Exemplo n.º 28
0
 def _fail_feature(self):
     failed_msg = ngettext('{} scenario failed', '{} scenarios failed', self._scenarios_failed)
     passed_msg = ngettext('{} scenario passed', '{} scenarios passed', self._scenarios_passed)
     msg = u'{}, {}'.format(failed_msg, passed_msg).format(self._scenarios_failed, self._scenarios_passed)
     prefix = '-' * 66
     for step_line, tb, exc in self._exceptions:
         msg += u'\n{}{}\n{}{}'.format(prefix, step_line, tb, exc).replace(u'\n', u'\n    ')
     assert self._scenarios_failed == 0, msg
Exemplo n.º 29
0
def _formatClientCount(value):
    if isinstance(value, (int, long)):
        template = gettext.ngettext(
            N_("%d client"), N_("%d clients"), value)
    else:
        template = gettext.ngettext(
            N_("%.2f client"), N_("%.2f clients"), value)
    return template % value
Exemplo n.º 30
0
 def _str_time(self, seconds):
     if seconds < 0:
         return _('unknown time')
    
     minutes = seconds / 60
     hours = minutes / 60
     minutes = minutes % 60                    
    
     return gettext.ngettext('%d Hour', '%d Hours', hours) + " " + gettext.ngettext('%d Minutes', '%d Minutes', minutes)
Exemplo n.º 31
0
    def convert(self, value: t.Any, param: t.Optional["Parameter"],
                ctx: t.Optional["Context"]) -> t.Any:
        # Match through normalization and case sensitivity
        # first do token_normalize_func, then lowercase
        # preserve original `value` to produce an accurate message in
        # `self.fail`
        normed_value = value
        normed_choices = {choice: choice for choice in self.choices}

        if ctx is not None and ctx.token_normalize_func is not None:
            normed_value = ctx.token_normalize_func(value)
            normed_choices = {
                ctx.token_normalize_func(normed_choice): original
                for normed_choice, original in normed_choices.items()
            }

        if not self.case_sensitive:
            normed_value = normed_value.casefold()
            normed_choices = {
                normed_choice.casefold(): original
                for normed_choice, original in normed_choices.items()
            }

        if normed_value in normed_choices:
            return normed_choices[normed_value]

        choices_str = ", ".join(map(repr, self.choices))
        self.fail(
            ngettext(
                "{value!r} is not {choice}.",
                "{value!r} is not one of {choices}.",
                len(self.choices),
            ).format(value=value, choice=choices_str, choices=choices_str),
            param,
            ctx,
        )
Exemplo n.º 32
0
def wait_for_flatpak_steam(timeout=99):
    """Wait for Flatpak version of Steam to be running."""
    loginvdf = os.path.expanduser("~/.local/share/Steam/config/loginusers.vdf")
    try:
        stat = os.stat(loginvdf)
        loginvdf_timestamp = stat.st_mtime
    except OSError:
        loginvdf_timestamp = 0

    waittime = timeout
    while waittime > 0:
        # "\r" can't be used here because this helper is subprocess
        print(ngettext("Waiting {} second for steam to start up.",
                       "Waiting {} seconds for steam to start up.",
                       waittime).format(waittime),
              flush=True)
        time.sleep(1)
        waittime -= 1
        try:
            stat = os.stat(loginvdf)
            if stat.st_mtime > loginvdf_timestamp:
                break
        except OSError:
            pass
Exemplo n.º 33
0
def main():
    files = do_options()

    # should parse files[] to read \version?
    if global_options.show_rules:
        show_rules(sys.stdout, global_options.from_version,
                   global_options.to_version)
        sys.exit(0)

    identify()

    errors = 0
    for f in files:
        if f == '-':
            f = ''
        elif not os.path.isfile(f):
            ly.error(_("%s: Unable to open file") % f)
            errors += 1
            continue
        try:
            errors += do_one_file(f)
        except UnknownVersion:
            ly.error(_("%s: Unable to determine version.  Skipping") % f)
            errors += 1
        except InvalidVersion as v:
            ly.error(
                _("%s: Invalid version string `%s' \n"
                  "Valid version strings consist of three numbers, "
                  "separated by dots, e.g. `2.8.12'") % (f, v.version))
            errors += 1

    if errors:
        ly.warning(
            gettext.ngettext("There was %d error.", "There were %d errors.",
                             errors) % errors)
        sys.exit(1)
Exemplo n.º 34
0
 def ngettext(self, singular, plural, n):
     """
     Return the unicode translated singular/plural string.
     
     The translation of singular/plural is returned unless the translation is
     not available and the singular contains the separator. In that case,
     the returned value is the portion of singular following the last
     separator. Default separator is '|'.
 
     :param singular: The singular form of the string to be translated.
                       may contain a context separator
     :type singular: unicode
     :param plural: The plural form of the string to be translated.
     :type plural: unicode
     :param n: the amount for which to decide the translation
     :type n: int
     :returns: The translated singular/plural message
     :rtype: unicode
 
     """
     if self.__trans is None:
         return unicode(gettext.ngettext(singular, plural, n))
     else:
         return self.__trans.ungettext(singular, plural, n)
Exemplo n.º 35
0
    def get_unsupported_suggestion_text(self, term, category, state):
        if state.filter is None:
            return None
        supported_only = state.filter.get_supported_only()
        if not supported_only:
            return None

        state.filter.set_supported_only(False)

        #if category:
        #    category_query = category.query
        #else:
        #    category_query = None

        enq = self.enquirer
        enq.set_query(enq.search_query,
                      limit=self.pane.get_app_items_limit(),
                      sortmode=self.pane.get_sort_mode(),
                      nonapps_visible=True,
                      filter=state.filter,
                      nonblocking_load=False)

        state.filter.set_supported_only(True)

        if enq.nr_apps > 0:
            text = self.BULLET % gettext.ngettext(
                "Try "
                "<a href=\"search-unsupported:\">the %(amount)d item "
                "that matches</a> in software not maintained by Canonical",
                "Try <a href=\"search-unsupported:\">the %(amount)d items "
                "that match</a> in software not maintained by Canonical",
                enq.nr_apps) % {
                    'amount': enq.nr_apps
                }
            return text
        return None
Exemplo n.º 36
0
    def _execute_status(self):
        state_map = {
                'play': _('Playing'),
                'pause': _('Paused'),
                'stop': _('Stopped')
                }
        aprint(3, '%s: %s' % (_('State'),
                state_map[self.status['state']]))

        aprint(3, '%s %s' % (_('Repeat:'), _('On') if self.status['repeat'] == '1'\
                else _('Off')))

        aprint(3, '%s %s' % (_('Random:'), _('On') if self.status['random'] == '1'\
                else _('Off')))

        aprint(3, '%s %s' % (_('Single:'), _('On') if self.status['single'] == '1'\
                else _('Off')))

        aprint(3, '%s %s' % (_('Consume:'), _('On')\
                if self.status['consume'] == '1' else _('Off')))
        aprint(3, '%s: %s/100' % (_('Volume'), self.status['volume']))
        aprint(3, '%s: %s %s' % (_('Crossfade'), self.status['xfade'],
                    gettext.ngettext('second', 'seconds',
                             int(self.status['xfade']))))
Exemplo n.º 37
0
def format_time (time, round_at=None):
    time = int(time)
    time_strings = []
    units = [(int(365.25*24*60*60),
              lambda years: ngettext("%s year","%s years",years)%years),
             (31*24*60*60,
              lambda months: ngettext("%s month","%s months",months)%months),
             (7*24*60*60,
              lambda weeks: ngettext("%s week","%s weeks",weeks)%weeks),
             (24*60*60,
              lambda days: ngettext("%s day","%s days",days)%days),
             (60*60,
              lambda hours: ngettext("%s hour","%s hours",hours)%hours),
             (60,
              lambda minutes: ngettext("%s minute","%s minutes",minutes)%minutes),
             (1,
              lambda seconds: ngettext("%s second","%s seconds",seconds)%seconds)]
    for divisor,unit_formatter in units:
        time_covered = time / divisor
        if time_covered:
            if round_at and len(time_strings)+1>=round_at:
                time_covered = int(round(float(time)/divisor))
                time_strings.append(unit_formatter(time_covered))
                break
            else:
                time_strings.append(unit_formatter(time_covered))
                time = time - time_covered * divisor
    if len(time_strings)>2:
        # Translators... this is a messay way of concatenating
        # lists. In English we do lists this way: 1, 2, 3, 4, 5
        # and 6. This set-up allows for the English system only.
        # You can of course make your language only use commas or
        # ands or spaces or whatever you like by translating both
        # ", " and " and " with the same string.
        return _(" and ").join([_(", ").join(time_strings[0:-1]),time_strings[-1]])
    else:
        return _(" and ").join(time_strings)
Exemplo n.º 38
0
    def validate(self):
        """
        Validates the state of this Library Content Module Instance. This
        is the override of the general XBlock method, and it will also ask
        its superclass to validate.
        """
        validation = super(LibraryContentDescriptor, self).validate()
        if not isinstance(validation, StudioValidation):
            validation = StudioValidation.copy(validation)
        library_tools = self.runtime.service(self, "library_tools")
        if not (library_tools and library_tools.can_use_library_content(self)):
            validation.set_summary(
                StudioValidationMessage(
                    StudioValidationMessage.ERROR,
                    _(u"This course does not support content libraries. "
                      u"Contact your system administrator for more information."
                      )))
            return validation
        if not self.source_library_id:
            validation.set_summary(
                StudioValidationMessage(
                    StudioValidationMessage.NOT_CONFIGURED,
                    _(u"A library has not yet been selected."),
                    action_class='edit-button',
                    action_label=_(u"Select a Library.")))
            return validation
        lib_tools = self.runtime.service(self, 'library_tools')
        self._validate_library_version(validation, lib_tools,
                                       self.source_library_version,
                                       self.source_library_key)

        # Note: we assume refresh_children() has been called
        # since the last time fields like source_library_id or capa_types were changed.
        matching_children_count = len(self.children)  # pylint: disable=no-member
        if matching_children_count == 0:
            self._set_validation_error_if_empty(
                validation,
                StudioValidationMessage(
                    StudioValidationMessage.WARNING,
                    _(u'There are no matching problem types in the specified libraries.'
                      ),
                    action_class='edit-button',
                    action_label=_(u"Select another problem type.")))

        if matching_children_count < self.max_count:
            self._set_validation_error_if_empty(
                validation,
                StudioValidationMessage(
                    StudioValidationMessage.WARNING,
                    (ngettext(
                        u'The specified library is configured to fetch {count} problem, ',
                        u'The specified library is configured to fetch {count} problems, ',
                        self.max_count) + ngettext(
                            u'but there is only {actual} matching problem.',
                            u'but there are only {actual} matching problems.',
                            matching_children_count)).format(
                                count=self.max_count,
                                actual=matching_children_count),
                    action_class='edit-button',
                    action_label=_(u"Edit the library configuration.")))

        return validation
Exemplo n.º 39
0
 def test_plural_forms1(self):
     eq = self.assertEqual
     x = gettext.ngettext('There is %s file', 'There are %s files', 1)
     eq(x, 'Hay %s fichero')
     x = gettext.ngettext('There is %s file', 'There are %s files', 2)
     eq(x, 'Hay %s ficheros')
Exemplo n.º 40
0
Arquivo: i18n.py Projeto: saue0/Solaar
    del _sys

    from glob import glob as _glob

    for location in prefix_share, src_share:
        mo_files = _glob(_path.join(location, 'locale', '*', 'LC_MESSAGES', lc_domain + '.mo'))
        if mo_files:
            return _path.join(location, 'locale')

    # del _path


locale.setlocale(locale.LC_ALL, '')
language, encoding = locale.getlocale()
del locale

_LOCALE_DOMAIN = _NAME.lower()
path = _find_locale_path(_LOCALE_DOMAIN)

_gettext.bindtextdomain(_LOCALE_DOMAIN, path)
_gettext.textdomain(_LOCALE_DOMAIN)
_gettext.install(_LOCALE_DOMAIN)

try:
    unicode  # noqa: F821
    _ = lambda x: _gettext.gettext(x).decode('UTF-8')
    ngettext = lambda *x: _gettext.ngettext(*x).decode('UTF-8')
except Exception:
    _ = _gettext.gettext
    ngettext = _gettext.ngettext
Exemplo n.º 41
0
	def extras_tab(self, cbs):
		"""Construct and layout the extras tab"""
		if not self.scrobbler.imported():
			self.config.as_enabled = False
		extraslabel = ui.label(markup='<b>' + _('Extras') + '</b>')
		frame = gtk.Frame()
		frame.set_label_widget(extraslabel)
		frame.set_shadow_type(gtk.SHADOW_NONE)

		as_checkbox = gtk.CheckButton(_("_Audioscrobbling (Last.fm)"))
		as_checkbox.set_active(self.config.as_enabled)
		as_user_label = ui.label(textmn=_("_Username:"******"_Password:"******"Popup _notification on song changes"))
		display_notification.set_active(self.config.show_notification)

		time_names = ["%s %s" %
			(i , gettext.ngettext('second', 'seconds', int(i)))
			for i in cbs.popuptimes if i != _('Entire song')]
		time_names.append(_('Entire song'))
		notification_options = ui.combo(items=time_names,
			active=self.config.popup_option,
			changed_cb=self._notiftime_changed)
		notification_locs = ui.combo(items=cbs.popuplocations,
			active=self.config.traytips_notifications_location,
			changed_cb=self._notiflocation_changed)
		notifhbox = gtk.HBox(spacing=6)
		notifhbox.pack_end(notification_locs, False, False)
		notifhbox.pack_end(notification_options, False, False)
		display_notification.connect('toggled', cbs.notif_toggled,
			notifhbox)
		if not self.config.show_notification:
			notifhbox.set_sensitive(False)
		crossfadespin = gtk.SpinButton()
		crossfadespin.set_range(1, 30)
		crossfadespin.set_value(self.config.xfade)
		crossfadespin.set_numeric(True)
		crossfadespin.set_increments(1, 5)
		crossfadespin.connect('value-changed', cbs.crossfade_changed)
		crossfadelabel2 = ui.label(textmn=_("_Fade length:"))
		crossfadelabel2.set_mnemonic_widget(crossfadespin)
		crossfadelabel3 = ui.label(text=_("sec"))
		crossfadebox = gtk.HBox(spacing=12)
		crossfadebox.pack_end(crossfadelabel3, False, False)
		crossfadebox.pack_end(crossfadespin, False, False)
		crossfadebox.pack_end(crossfadelabel2, False, False)
		crossfadecheck = gtk.CheckButton(_("C_rossfade"))
		crossfadecheck.connect('toggled',
			self._crossfadecheck_toggled, crossfadespin,
			crossfadelabel2, crossfadelabel3)
		crossfadecheck.connect('toggled', cbs.crossfade_toggled,
			crossfadespin)
		crossfadecheck.set_active(self.config.xfade_enabled)
		crossfadecheck.toggled() # Force the toggled callback

		widgets = (as_checkbox, as_entries, display_notification,
			notifhbox, crossfadecheck, crossfadebox)
		table = gtk.Table(len(widgets), 1)
		table.set_col_spacings(12)
		table.set_row_spacings(6)
		for i, widget in enumerate(widgets):
			table.attach(widget, 0, 1, i, i+1,
				gtk.FILL|gtk.EXPAND, gtk.FILL)
		alignment = gtk.Alignment(0.5, 0.5, 1.0, 1.0)
		alignment.set_padding(12, 0, 12, 0)
		alignment.add(table)
		frame.add(alignment)
		tab = gtk.Alignment(0.5, 0.5, 1.0, 1.0)
		tab.set_padding(12, 12, 12, 12)
		tab.add(frame)

		as_checkbox.connect('toggled', self._as_enabled_toggled,
			as_user_entry, as_pass_entry, as_user_label,
			as_pass_label)
		if not self.config.as_enabled or not self.scrobbler.imported():
			for widget in (as_user_entry, as_pass_entry,
					as_user_label, as_pass_label):
				widget.set_sensitive(False)
		return tab
Exemplo n.º 42
0
 def _on_duration_changed(self, coredisc, duration):
     mins = (coredisc.props.duration // 60) + 1
     self._running_info_label.props.label = ngettext(
         "{} minute", "{} minutes", mins).format(mins)
Exemplo n.º 43
0
 def __str__(self):
     count = len(self._receiver)
     return (_("No paired devices.") if count == 0 else ngettext(
         "%(count)s paired device.", "%(count)s paired devices.", count) % {
             'count': count
         })
Exemplo n.º 44
0
    def __init__(self):
        """
            Init dialog
        """
        self.__choosers = []
        self.__cover_tid = None
        self.__mix_tid = None
        self.__popover = None

        builder = Gtk.Builder()
        builder.add_from_resource("/org/gnome/Lollypop/SettingsDialog.ui")
        self.__progress = builder.get_object("progress")
        self.__infobar = builder.get_object("infobar")
        self.__reset_button = builder.get_object("reset_button")
        if Lp().lastfm is None or Lp().lastfm.is_goa:
            builder.get_object("lastfm_grid").hide()
        if Lp().scanner.is_locked():
            builder.get_object("reset_button").set_sensitive(False)
        artists = Lp().artists.count()
        albums = Lp().albums.count()
        tracks = Lp().tracks.count()
        builder.get_object("artists").set_text(
            ngettext("%d artist", "%d artists", artists) % artists)
        builder.get_object("albums").set_text(
            ngettext("%d album", "%d albums", albums) % albums)
        builder.get_object("tracks").set_text(
            ngettext("%d track", "%d tracks", tracks) % tracks)

        self.__popover_content = builder.get_object("popover")
        duration = builder.get_object("duration")
        duration.set_range(1, 20)
        duration.set_value(Lp().settings.get_value("mix-duration").get_int32())

        self.__settings_dialog = builder.get_object("settings_dialog")
        self.__settings_dialog.set_transient_for(Lp().window)

        if Lp().settings.get_value("disable-csd"):
            self.__settings_dialog.set_title(_("Preferences"))
        else:
            headerbar = builder.get_object("header_bar")
            headerbar.set_title(_("Preferences"))
            self.__settings_dialog.set_titlebar(headerbar)

        switch_scan = builder.get_object("switch_scan")
        switch_scan.set_state(Lp().settings.get_value("auto-update"))

        switch_view = builder.get_object("switch_dark")
        if Lp().gtk_application_prefer_dark_theme:
            switch_view.set_sensitive(False)
        else:
            switch_view.set_state(Lp().settings.get_value("dark-ui"))

        switch_background = builder.get_object("switch_background")
        switch_background.set_state(Lp().settings.get_value("background-mode"))

        switch_state = builder.get_object("switch_state")
        switch_state.set_state(Lp().settings.get_value("save-state"))

        switch_mix = builder.get_object("switch_mix")
        switch_mix.set_state(Lp().settings.get_value("mix"))

        self._switch_song_notifications = builder.get_object(
            "switch_song_notifications", )

        self._switch_song_notifications.set_state(
            not Lp().settings.get_value("disable-song-notifications"), )

        self._switch_song_notifications.set_sensitive(
            not Lp().settings.get_value("disable-notifications"), )

        Lp().settings.connect(
            "changed::disable-notifications",
            self._on_notifications_setting_changed,
        )

        self.__helper = TouchHelper(switch_mix, None, None)
        self.__helper.set_long_func(self.__mix_long_func, switch_mix)
        self.__helper.set_short_func(self.__mix_short_func, switch_mix)

        switch_mix_party = builder.get_object("switch_mix_party")
        switch_mix_party.set_state(Lp().settings.get_value("party-mix"))

        switch_artwork_tags = builder.get_object("switch_artwork_tags")
        grid_behaviour = builder.get_object("grid_behaviour")
        # Check portal for kid3-cli
        dbus_helper = DBusHelper()
        dbus_helper.call("CanSetCover", None, self.__on_can_set_cover,
                         (switch_artwork_tags, grid_behaviour))

        if GLib.find_program_in_path("youtube-dl") is None or\
                not Lp().settings.get_value("network-access"):
            builder.get_object("charts_grid").hide()
        else:
            switch_charts = builder.get_object("switch_charts")
            switch_charts.set_state(Lp().settings.get_value("show-charts"))

        switch_genres = builder.get_object("switch_genres")
        switch_genres.set_state(Lp().settings.get_value("show-genres"))

        switch_compilations = builder.get_object("switch_compilations")
        switch_compilations.set_state(
            Lp().settings.get_value("show-compilations"))

        switch_artwork = builder.get_object("switch_artwork")
        switch_artwork.set_state(Lp().settings.get_value("artist-artwork"))

        switch_spotify = builder.get_object("switch_spotify")
        switch_spotify.set_state(Lp().settings.get_value("search-spotify"))

        switch_itunes = builder.get_object("switch_itunes")
        switch_itunes.set_state(Lp().settings.get_value("search-itunes"))

        if GLib.find_program_in_path("youtube-dl") is None:
            builder.get_object("yt-dl").show()

        combo_orderby = builder.get_object("combo_orderby")
        combo_orderby.set_active(Lp().settings.get_enum(("orderby")))

        combo_preview = builder.get_object("combo_preview")

        scale_coversize = builder.get_object("scale_coversize")
        scale_coversize.set_range(150, 300)
        scale_coversize.set_value(
            Lp().settings.get_value("cover-size").get_int32())
        self.__settings_dialog.connect("destroy", self.__edit_settings_close)

        builder.connect_signals(self)

        main_chooser_box = builder.get_object("main_chooser_box")
        self.__chooser_box = builder.get_object("chooser_box")

        self.__set_outputs(combo_preview)

        #
        # Music tab
        #
        dirs = []
        for directory in Lp().settings.get_value("music-uris"):
            dirs.append(directory)

        # Main chooser
        self.__main_chooser = ChooserWidget()
        image = Gtk.Image.new_from_icon_name("list-add-symbolic",
                                             Gtk.IconSize.MENU)
        self.__main_chooser.set_icon(image)
        self.__main_chooser.set_action(self.__add_chooser)
        main_chooser_box.pack_start(self.__main_chooser, False, True, 0)
        if len(dirs) > 0:
            uri = dirs.pop(0)
        else:
            filename = GLib.get_user_special_dir(
                GLib.UserDirectory.DIRECTORY_MUSIC)
            if filename:
                uri = GLib.filename_to_uri(filename)
            else:
                uri = ""

        self.__main_chooser.set_dir(uri)

        # Others choosers
        for directory in dirs:
            self.__add_chooser(directory)

        #
        # Google tab
        #
        key = Lp().settings.get_value("cs-api-key").get_string() or\
            Lp().settings.get_default_value("cs-api-key").get_string()
        builder.get_object("cs-entry").set_text(key)

        from lollypop.helper_passwords import PasswordsHelper
        helper = PasswordsHelper()
        #
        # Last.fm tab
        #
        if Lp().lastfm is not None:
            self.__lastfm_test_image = builder.get_object("lastfm_test_image")
            self.__lastfm_login = builder.get_object("lastfm_login")
            self.__lastfm_password = builder.get_object("lastfm_password")
            helper.get("lastfm", self.__on_get_password)
            builder.get_object("lastfm_grid").set_sensitive(True)
            builder.get_object("lastfm_error_label").hide()
        #
        # Libre.fm tab
        #
        if Lp().librefm is not None:
            self.__librefm_test_image = builder.get_object(
                "librefm_test_image")
            self.__librefm_login = builder.get_object("librefm_login")
            self.__librefm_password = builder.get_object("librefm_password")
            helper.get("librefm", self.__on_get_password)
            builder.get_object("librefm_grid").set_sensitive(True)
            builder.get_object("librefm_error_label").hide()
Exemplo n.º 45
0
    def delete(self, rogue):
        for cert in rogue:
            try:
                cert.delete()
                self.report.rogue.append(cert)
            except OSError, er:
                log.exception(er)
                log.warn("Failed to delete cert")

        # If we just deleted certs, we need to refresh the now stale
        # entitlement directory before we go to delete expired certs.
        rogue_count = len(self.report.rogue)
        if rogue_count > 0:
            print gettext.ngettext("%s local certificate has been deleted.",
                                   "%s local certificates have been deleted.",
                                   rogue_count) % rogue_count
            self.ent_dir.refresh()


class EntitlementCertBundlesInstaller(object):
    """Install a list of entitlement cert bundles.

    pre_install() is triggered before any of the ent cert
    bundles are installed. post_install() is triggered after
    all of the ent cert bundles are installed.
    """
    def __init__(self, report):
        self.exceptions = []
        self.report = report
Exemplo n.º 46
0
    def search(self, text, format):
        """Execute the search process (to be executed in a dedicated thread)"""
        self.searchRunning = True

        symbols = self.vocabularyController.getCurrentProject().getVocabulary(
        ).getSymbols()
        # Reset the progress bar
        GObject.idle_add(self._view.searchProgressBar.show)
        GObject.idle_add(self._view.searchProgressBar.set_fraction, 0.0)

        # create a task for the text
        searcher = Searcher(self.vocabularyController.getCurrentProject(),
                            self.updateProgessBar)
        # generate variations for each provided format (see glade file)
        if format == "string":
            searchTasks = searcher.getSearchedDataForString(text)
        elif format == "hexa":
            searchTasks = searcher.getSearchedDataForHexadecimal(text)
        elif format == "decimal":
            searchTasks = searcher.getSearchedDataForDecimal(text)
        elif format == "octal":
            searchTasks = searcher.getSearchedDataForOctal(text)
        elif format == "binary":
            searchTasks = searcher.getSearchedDataForBinary(text)
        elif format == "ipv4":
            searchTasks = searcher.getSearchedDataForIP(text)
        else:
            searchTasks = None
            self.log.error(
                "Cannot search for data if provided with type {0}".format(
                    format))

        if searchTasks is not None and len(searchTasks) > 0:
            self.executedSearchTasks = searcher.search(searchTasks)
            self.idResult = -1
            self.nbResult = 0
            for searchTask in self.executedSearchTasks:
                self.nbResult += len(searchTask.getResults())

            if self.nbResult == 0:
                GObject.idle_add(self._view.imageWarning.show)
                GObject.idle_add(self._view.numberOfResultLabel.show)
                GObject.idle_add(self._view.numberOfResultLabel.set_label,
                                 _("No occurrence found."))
            else:
                GObject.idle_add(self._view.imageWarning.hide)
                GObject.idle_add(self._view.numberOfResultLabel.show)

                label = ngettext("{0} occurrence found.",
                                 "{0} occurrences found.",
                                 self.nbResult).format(self.nbResult)
                GObject.idle_add(self._view.numberOfResultLabel.set_label,
                                 label)

            if not self.stopFlag and self.nbResult > 0:
                # if search has completed (not stopped), nav. is allowed
                GObject.idle_add(self._view.research_previous.set_sensitive,
                                 False)
                GObject.idle_add(self._view.research_next.set_sensitive, True)
            else:
                self.executedSearchTasks = None
                self.idResult = 0

        self.searchRunning = False
        self.stopFlag = False
        GObject.idle_add(self._view.searchProgressBar.hide)
    def __init__(self, parent, sourceslist, source_renderer, get_comparable,
                 datadir, file):
        print(file)
        self.parent = parent
        self.source_renderer = source_renderer
        self.sourceslist = sourceslist
        self.get_comparable = get_comparable
        self.file = self.format_uri(file)

        setup_ui(self,
                 os.path.join(datadir, "gtkbuilder",
                              "dialog-add-sources-list.ui"),
                 domain="software-properties")

        self.dialog = self.dialog_add_sources_list
        self.label = self.label_sources
        self.treeview = self.treeview_sources
        self.scrolled = self.scrolled_window
        self.image = self.image_sources_list

        self.dialog.realize()
        if self.parent != None:
            self.dialog.set_transient_for(parent)
        else:
            self.dialog.set_title(_("Add Software Channels"))
        self.dialog.get_window().set_functions(Gdk.WMFunction.MOVE)

        # Setup the treeview
        self.store = Gtk.ListStore(GObject.TYPE_STRING)
        self.treeview.set_model(self.store)
        cell = Gtk.CellRendererText()
        cell.set_property("xpad", 2)
        cell.set_property("ypad", 2)
        column = Gtk.TreeViewColumn("Software Channel", cell, markup=0)
        column.set_max_width(500)
        self.treeview.append_column(column)

        # Parse the source.list file
        try:
            self.new_sources = SingleSourcesList(self.file)
        except:
            self.error()
            return

        # show the found channels or an error message
        if len(self.new_sources.list) > 0:
            counter = 0

            for source in self.new_sources.list:
                if source.invalid or source.disabled:
                    continue
                self.new_sources.matcher.match(source)
            # sort the list
            self.new_sources.list.sort(key=self.get_comparable)

            for source in self.new_sources.list:
                if source.invalid or source.disabled:
                    continue
                counter = counter + 1
                line = self.source_renderer(source)
                self.store.append([line])
            if counter == 0:
                self.error()
                return

            header = gettext.ngettext(
                "Install software additionally or "
                "only from this source?", "Install software additionally or "
                "only from these sources?", counter)
            body = _(
                "You can either add the following sources or replace your "
                "current sources by them. Only install software from "
                "trusted sources.")
            self.label.set_markup("<big><b>%s</b></big>\n\n%s" %
                                  (header, body))
        else:
            self.error()
            return
 def _update_countdown_message(self):
     self._second_message = gettext.ngettext("Settings will be reverted in %d second",
                                             "Settings will be reverted in %d seconds",
                                             self._countdown)
Exemplo n.º 49
0
 def get_comment(self):
     return ngettext("%d item", "%d items", trash_monitor.get_count()) \
            % trash_monitor.get_count()
Exemplo n.º 50
0
def _builtin_field_metadata():
    # This is a function so that changing the UI language allows newly created
    # field metadata objects to have correctly translated labels for builtin
    # fields.
    return [
        ('authors', {
            'table': 'authors',
            'column': 'name',
            'link_column': 'author',
            'category_sort': 'sort',
            'datatype': 'text',
            'is_multiple': {
                'cache_to_list': ',',
                'ui_to_list': '&',
                'list_to_ui': ' & '
            },
            'kind': 'field',
            'name': _('Authors'),
            'search_terms': ['authors', 'author'],
            'is_custom': False,
            'is_category': True,
            'is_csp': False
        }),
        ('languages', {
            'table': 'languages',
            'column': 'lang_code',
            'link_column': 'lang_code',
            'category_sort': 'lang_code',
            'datatype': 'text',
            'is_multiple': {
                'cache_to_list': ',',
                'ui_to_list': ',',
                'list_to_ui': ', '
            },
            'kind': 'field',
            'name': _('Languages'),
            'search_terms': ['languages', 'language'],
            'is_custom': False,
            'is_category': True,
            'is_csp': False
        }),
        ('series', {
            'table': 'series',
            'column': 'name',
            'link_column': 'series',
            'category_sort': '(title_sort(name))',
            'datatype': 'series',
            'is_multiple': {},
            'kind': 'field',
            'name': ngettext('Series', 'Series', 1),
            'search_terms': ['series'],
            'is_custom': False,
            'is_category': True,
            'is_csp': False
        }),
        ('formats', {
            'table': None,
            'column': None,
            'datatype': 'text',
            'is_multiple': {
                'cache_to_list': ',',
                'ui_to_list': ',',
                'list_to_ui': ', '
            },
            'kind': 'field',
            'name': _('Formats'),
            'search_terms': ['formats', 'format'],
            'is_custom': False,
            'is_category': True,
            'is_csp': False
        }),
        ('publisher', {
            'table': 'publishers',
            'column': 'name',
            'link_column': 'publisher',
            'category_sort': 'name',
            'datatype': 'text',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Publisher'),
            'search_terms': ['publisher'],
            'is_custom': False,
            'is_category': True,
            'is_csp': False
        }),
        ('rating', {
            'table': 'ratings',
            'column': 'rating',
            'link_column': 'rating',
            'category_sort': 'rating',
            'datatype': 'rating',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Rating'),
            'search_terms': ['rating'],
            'is_custom': False,
            'is_category': True,
            'is_csp': False
        }),
        ('news', {
            'table': 'news',
            'column': 'name',
            'category_sort': 'name',
            'datatype': None,
            'is_multiple': {},
            'kind': 'category',
            'name': _('News'),
            'search_terms': [],
            'is_custom': False,
            'is_category': True,
            'is_csp': False
        }),
        ('tags', {
            'table': 'tags',
            'column': 'name',
            'link_column': 'tag',
            'category_sort': 'name',
            'datatype': 'text',
            'is_multiple': {
                'cache_to_list': ',',
                'ui_to_list': ',',
                'list_to_ui': ', '
            },
            'kind': 'field',
            'name': _('Tags'),
            'search_terms': ['tags', 'tag'],
            'is_custom': False,
            'is_category': True,
            'is_csp': False
        }),
        ('identifiers', {
            'table': None,
            'column': None,
            'datatype': 'text',
            'is_multiple': {
                'cache_to_list': ',',
                'ui_to_list': ',',
                'list_to_ui': ', '
            },
            'kind': 'field',
            'name': _('Identifiers'),
            'search_terms': ['identifiers', 'identifier', 'isbn'],
            'is_custom': False,
            'is_category': True,
            'is_csp': True
        }),
        ('author_sort', {
            'table': None,
            'column': None,
            'datatype': 'text',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Author Sort'),
            'search_terms': ['author_sort'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('au_map', {
            'table': None,
            'column': None,
            'datatype': 'text',
            'is_multiple': {
                'cache_to_list': ',',
                'ui_to_list': None,
                'list_to_ui': None
            },
            'kind': 'field',
            'name': None,
            'search_terms': [],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('comments', {
            'table': None,
            'column': None,
            'datatype': 'text',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Comments'),
            'search_terms': ['comments', 'comment'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('cover', {
            'table': None,
            'column': None,
            'datatype': 'int',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Cover'),
            'search_terms': ['cover'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('id', {
            'table': None,
            'column': None,
            'datatype': 'int',
            'is_multiple': {},
            'kind': 'field',
            'name': None,
            'search_terms': ['id'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('last_modified', {
            'table': None,
            'column': None,
            'datatype': 'datetime',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Modified'),
            'search_terms': ['last_modified'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('ondevice', {
            'table': None,
            'column': None,
            'datatype': 'text',
            'is_multiple': {},
            'kind': 'field',
            'name': _('On Device'),
            'search_terms': ['ondevice'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('path', {
            'table': None,
            'column': None,
            'datatype': 'text',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Path'),
            'search_terms': [],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('pubdate', {
            'table': None,
            'column': None,
            'datatype': 'datetime',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Published'),
            'search_terms': ['pubdate'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('marked', {
            'table': None,
            'column': None,
            'datatype': 'text',
            'is_multiple': {},
            'kind': 'field',
            'name': None,
            'search_terms': ['marked'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('series_index', {
            'table': None,
            'column': None,
            'datatype': 'float',
            'is_multiple': {},
            'kind': 'field',
            'name': None,
            'search_terms': ['series_index'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('series_sort', {
            'table': None,
            'column': None,
            'datatype': 'text',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Series Sort'),
            'search_terms': ['series_sort'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('sort', {
            'table': None,
            'column': None,
            'datatype': 'text',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Title Sort'),
            'search_terms': ['title_sort'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('size', {
            'table': None,
            'column': None,
            'datatype': 'float',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Size'),
            'search_terms': ['size'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('timestamp', {
            'table': None,
            'column': None,
            'datatype': 'datetime',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Date'),
            'search_terms': ['date'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('title', {
            'table': None,
            'column': None,
            'datatype': 'text',
            'is_multiple': {},
            'kind': 'field',
            'name': _('Title'),
            'search_terms': ['title'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
        ('uuid', {
            'table': None,
            'column': None,
            'datatype': 'text',
            'is_multiple': {},
            'kind': 'field',
            'name': None,
            'search_terms': ['uuid'],
            'is_custom': False,
            'is_category': False,
            'is_csp': False
        }),
    ]
Exemplo n.º 51
0
 def _get_confirmation_alert_message(self, entries_len):
     return ngettext('Do you want to copy %d entry?',
                     'Do you want to copy %d entries?',
                     entries_len) % (entries_len)
Exemplo n.º 52
0
def ngettext(singular, plural, n):
    t = gettext.dngettext("YouTube", singular, plural, n)
    if t in (singular, plural):
        t = gettext.ngettext(singular, plural, n)
    return t
Exemplo n.º 53
0
def main(args):
    """
    Handles the command line arguments
    args is the list of arguments passed
    return (int): value to return to the OS as program exit code
    """
    # arguments handling
    parser = argparse.ArgumentParser(description="File format conversion utility")

    parser.add_argument('--version', dest="version", action='store_true',
                        help="show program's version number and exit")
    parser.add_argument("--input", "-i", dest="input",
                        help="name of the input file")
    parser.add_argument("--tiles", "-t", dest="tiles", nargs="+",
                        help="list of files acquired in tiles to re-assemble")
    parser.add_argument("--effcomp", dest="effcomp",
                        help="name of a spectrum efficiency compensation table (in CSV format)")
    fmts = dataio.get_available_formats(os.O_WRONLY)
    parser.add_argument("--output", "-o", dest="output",
            help="name of the output file. "
            "The file format is derived from the extension (%s are supported)." %
            (" and ".join(fmts)))
    # TODO: automatically select pyramidal format if image > 4096px?
    parser.add_argument("--pyramid", "-p", dest="pyramid", action='store_true',
                        help="Export the data in pyramidal format. "
                        "It takes about 2x more space, but allows to visualise large images. "
                        "Currently, only the TIFF format supports this option.")
    parser.add_argument("--minus", "-m", dest="minus", action='append',
            help="name of an acquisition file whose data is subtracted from the input file.")
    parser.add_argument("--weaver", "-w", dest="weaver",
            help="name of weaver to be used during stitching. Options: 'mean': MeanWeaver " 
            "(blend overlapping regions of adjacent tiles), 'collage': CollageWeaver "
            "(paste tiles as-is at calculated position)", choices=("mean", "collage", "collage_reverse"),
            default='mean')
    parser.add_argument("--registrar", "-r", dest="registrar",
            help="name of registrar to be used during stitching. Options: 'identity': IdentityRegistrar "
            "(place tiles at original position), 'shift': ShiftRegistrar (use cross-correlation "
            "algorithm to correct for suboptimal stage movement), 'global_shift': GlobalShiftRegistrar "
            "(uses cross-correlation algorithm with global optimization)",
            choices=("identity", "shift", "global_shift"), default="global_shift")

    # TODO: --export (spatial) image that defaults to a HFW corresponding to the
    # smallest image, and can be overridden by --hfw xxx (in µm).
    # TODO: --range parameter to select which image to select from the input
    #      (like: 1-4,5,6-10,12)

    options = parser.parse_args(args[1:])

    # Cannot use the internal feature, because it doesn't support multi-line
    if options.version:
        print(odemis.__fullname__ + " " + odemis.__version__ + "\n" +
              odemis.__copyright__ + "\n" +
              "Licensed under the " + odemis.__license__)
        return 0

    infn = options.input
    tifns = options.tiles
    ecfn = options.effcomp
    outfn = options.output

    if not (infn or tifns or ecfn) or not outfn:
        raise ValueError("--input/--tiles/--effcomp and --output arguments must be provided.")

    if sum(not not o for o in (infn, tifns, ecfn)) != 1:
        raise ValueError("--input, --tiles, --effcomp cannot be provided simultaneously.")

    if infn:
        data, thumbs = open_acq(infn)
        logging.info("File contains %d %s (and %d %s)",
                     len(data), ngettext("image", "images", len(data)),
                     len(thumbs), ngettext("thumbnail", "thumbnails", len(thumbs)))
    elif tifns:
        registration_method = {"identity": REGISTER_IDENTITY, "shift": REGISTER_SHIFT,
                               "global_shift": REGISTER_GLOBAL_SHIFT}[options.registrar]
        weaving_method = {"collage": WEAVER_COLLAGE, "mean": WEAVER_MEAN,
                  "collage_reverse": WEAVER_COLLAGE_REVERSE}[options.weaver]
        data = stitch(tifns, registration_method, weaving_method)
        thumbs = []
        logging.info("File contains %d %s",
                     len(data), ngettext("stream", "streams", len(data)))
    elif ecfn:
        data = open_ec(ecfn)
        thumbs = []
        logging.info("File contains %d coefficients", data[0].shape[0])

    if options.minus:
        if thumbs:
            logging.info("Dropping thumbnail due to subtraction")
            thumbs = []
        for fn in options.minus:
            sdata, _ = open_acq(fn)
            data = minus(data, sdata)

    save_acq(outfn, data, thumbs, options.pyramid)

    logging.info("Successfully generated file %s", outfn)
Exemplo n.º 54
0
import gettext

n = 5
ng1 = gettext.ngettext("ngettext1", "ngettext1-plural", n)
dng1 = gettext.dngettext("test-domain", "dngettext1", "dngettext1-plural", n)
dng2 = gettext.dngettext("some-other-domain", "dngettext2",
                         "dngettext2-plural", n)
Exemplo n.º 55
0
def foo():
    # Note: This will have the TRANSLATOR: tag but shouldn't
    # be included on the extracted stuff
    print ngettext('FooBar', 'FooBars', 1)
Exemplo n.º 56
0
    def show(self, tids=None):
        self.tids_todelete = tids or self.tids_todelete

        if not self.tids_todelete:
            # We must at least have something to delete!
            return []

        # Get full task list to delete
        tasklist = []
        self.update_tags = []

        for tid in self.tids_todelete:
            task = self.req.get_task(tid)
            self.recursive_list_tasks(tasklist, task)

        # Prepare Labels
        singular = len(tasklist)
        cancel_text = ngettext("Keep selected task",
                               "Keep selected tasks",
                                singular)

        delete_text = ngettext("Permanently remove task",
                               "Permanently remove tasks",
                                singular)

        label_text = ngettext("Deleting a task cannot be undone, "
                              "and will delete the following task: ",
                              "Deleting a task cannot be undone, "
                              "and will delete the following tasks: ",
                              singular)

        label_text = label_text[0:label_text.find(":") + 1]

        missing_titles_count = len(tasklist) - self.MAXIMUM_TIDS_TO_SHOW

        if missing_titles_count >= 2:
            tasks = tasklist[: self.MAXIMUM_TIDS_TO_SHOW]
            titles_suffix = _(f"\nAnd {missing_titles_count:d} more tasks")
        else:
            tasks = tasklist
            titles_suffix = ""

        titles = "".join("\n• " + task.get_title() for task in tasks)


        # Build and run dialog
        dialog = Gtk.MessageDialog(transient_for=self.window, modal=True)
        dialog.add_button(cancel_text, Gtk.ResponseType.CANCEL)

        delete_btn = dialog.add_button(delete_text, Gtk.ResponseType.YES)
        delete_btn.get_style_context().add_class("destructive-action")

        dialog.props.use_markup = True
        dialog.props.text = "<span weight=\"bold\">" + label_text + "</span>"

        dialog.props.secondary_text = titles + titles_suffix

        response = dialog.run()
        dialog.destroy()

        if response == Gtk.ResponseType.YES:
            self.on_delete_confirm()
        elif response == Gtk.ResponseType.CANCEL:
            tasklist = []

        return tasklist
Exemplo n.º 57
0
def main():

    global config, options

    # Parse command line...
    parser = ArgumentParser(usage="%(prog)s [options] "
                            "[APPID[:VERCODE] [APPID[:VERCODE] ...]]")
    common.setup_global_opts(parser)
    parser.add_argument("appid", nargs='*', help=_("applicationId with optional versionCode in the form APPID[:VERCODE]"))
    metadata.add_metadata_arguments(parser)
    options = parser.parse_args()
    metadata.warnings_action = options.W

    config = common.read_config(options)

    if not ('jarsigner' in config and 'keytool' in config):
        logging.critical(_('Java JDK not found! Install in standard location or set java_paths!'))
        sys.exit(1)

    common.assert_config_keystore(config)

    log_dir = 'logs'
    if not os.path.isdir(log_dir):
        logging.info(_("Creating log directory"))
        os.makedirs(log_dir)

    tmp_dir = 'tmp'
    if not os.path.isdir(tmp_dir):
        logging.info(_("Creating temporary directory"))
        os.makedirs(tmp_dir)

    output_dir = 'repo'
    if not os.path.isdir(output_dir):
        logging.info(_("Creating output directory"))
        os.makedirs(output_dir)

    unsigned_dir = 'unsigned'
    if not os.path.isdir(unsigned_dir):
        logging.warning(_("No unsigned directory - nothing to do"))
        sys.exit(1)

    if not os.path.exists(config['keystore']):
        logging.error("Config error - missing '{0}'".format(config['keystore']))
        sys.exit(1)

    # It was suggested at
    #    https://dev.guardianproject.info/projects/bazaar/wiki/FDroid_Audit
    # that a package could be crafted, such that it would use the same signing
    # key as an existing app. While it may be theoretically possible for such a
    # colliding package ID to be generated, it seems virtually impossible that
    # the colliding ID would be something that would be a) a valid package ID,
    # and b) a sane-looking ID that would make its way into the repo.
    # Nonetheless, to be sure, before publishing we check that there are no
    # collisions, and refuse to do any publishing if that's the case...
    allapps = metadata.read_metadata()
    vercodes = common.read_pkg_args(options.appid, True)
    allaliases = []
    for appid in allapps:
        m = hashlib.md5()
        m.update(appid.encode('utf-8'))
        keyalias = m.hexdigest()[:8]
        if keyalias in allaliases:
            logging.error(_("There is a keyalias collision - publishing halted"))
            sys.exit(1)
        allaliases.append(keyalias)
    logging.info(ngettext('{0} app, {1} key aliases',
                          '{0} apps, {1} key aliases', len(allapps)).format(len(allapps), len(allaliases)))

    # Process any APKs or ZIPs that are waiting to be signed...
    for apkfile in sorted(glob.glob(os.path.join(unsigned_dir, '*.apk'))
                          + glob.glob(os.path.join(unsigned_dir, '*.zip'))):

        appid, vercode = common.publishednameinfo(apkfile)
        apkfilename = os.path.basename(apkfile)
        if vercodes and appid not in vercodes:
            continue
        if appid in vercodes and vercodes[appid]:
            if vercode not in vercodes[appid]:
                continue
        logging.info(_("Processing {apkfilename}").format(apkfilename=apkfile))

        # There ought to be valid metadata for this app, otherwise why are we
        # trying to publish it?
        if appid not in allapps:
            logging.error("Unexpected {0} found in unsigned directory"
                          .format(apkfilename))
            sys.exit(1)
        app = allapps[appid]

        if app.Binaries:

            # It's an app where we build from source, and verify the apk
            # contents against a developer's binary, and then publish their
            # version if everything checks out.
            # The binary should already have been retrieved during the build
            # process.
            srcapk = re.sub(r'.apk$', '.binary.apk', apkfile)

            # Compare our unsigned one with the downloaded one...
            compare_result = common.verify_apks(srcapk, apkfile, tmp_dir)
            if compare_result:
                logging.error("...verification failed - publish skipped : "
                              + compare_result)
            else:

                # Success! So move the downloaded file to the repo, and remove
                # our built version.
                shutil.move(srcapk, os.path.join(output_dir, apkfilename))
                os.remove(apkfile)

                publish_source_tarball(apkfilename, unsigned_dir, output_dir)
                logging.info('Published ' + apkfilename)

        elif apkfile.endswith('.zip'):

            # OTA ZIPs built by fdroid do not need to be signed by jarsigner,
            # just to be moved into place in the repo
            shutil.move(apkfile, os.path.join(output_dir, apkfilename))
            publish_source_tarball(apkfilename, unsigned_dir, output_dir)
            logging.info('Published ' + apkfilename)

        else:

            # It's a 'normal' app, i.e. we sign and publish it...
            skipsigning = False

            # First we handle signatures for this app from local metadata
            signingfiles = common.metadata_find_developer_signing_files(appid, vercode)
            if signingfiles:
                # There's a signature of the app developer present in our
                # metadata. This means we're going to prepare both a locally
                # signed APK and a version signed with the developers key.

                signaturefile, signedfile, manifest = signingfiles

                with open(signaturefile, 'rb') as f:
                    devfp = common.signer_fingerprint_short(f.read())
                devsigned = '{}_{}_{}.apk'.format(appid, vercode, devfp)
                devsignedtmp = os.path.join(tmp_dir, devsigned)
                shutil.copy(apkfile, devsignedtmp)

                common.apk_implant_signatures(devsignedtmp, signaturefile,
                                              signedfile, manifest)
                if common.verify_apk_signature(devsignedtmp):
                    shutil.move(devsignedtmp, os.path.join(output_dir, devsigned))
                else:
                    os.remove(devsignedtmp)
                    logging.error('...verification failed - skipping: %s', devsigned)
                    skipsigning = True

            # Now we sign with the F-Droid key.

            # Figure out the key alias name we'll use. Only the first 8
            # characters are significant, so we'll use the first 8 from
            # the MD5 of the app's ID and hope there are no collisions.
            # If a collision does occur later, we're going to have to
            # come up with a new alogrithm, AND rename all existing keys
            # in the keystore!
            if not skipsigning:
                if appid in config['keyaliases']:
                    # For this particular app, the key alias is overridden...
                    keyalias = config['keyaliases'][appid]
                    if keyalias.startswith('@'):
                        m = hashlib.md5()
                        m.update(keyalias[1:].encode('utf-8'))
                        keyalias = m.hexdigest()[:8]
                else:
                    m = hashlib.md5()
                    m.update(appid.encode('utf-8'))
                    keyalias = m.hexdigest()[:8]
                logging.info("Key alias: " + keyalias)

                # See if we already have a key for this application, and
                # if not generate one...
                env_vars = {
                    'FDROID_KEY_STORE_PASS': config['keystorepass'],
                    'FDROID_KEY_PASS': config['keypass'],
                }
                p = FDroidPopen([config['keytool'], '-list',
                                 '-alias', keyalias, '-keystore', config['keystore'],
                                 '-storepass:env', 'FDROID_KEY_STORE_PASS'], envs=env_vars)
                if p.returncode != 0:
                    logging.info("Key does not exist - generating...")
                    p = FDroidPopen([config['keytool'], '-genkey',
                                     '-keystore', config['keystore'],
                                     '-alias', keyalias,
                                     '-keyalg', 'RSA', '-keysize', '2048',
                                     '-validity', '10000',
                                     '-storepass:env', 'FDROID_KEY_STORE_PASS',
                                     '-keypass:env', 'FDROID_KEY_PASS',
                                     '-dname', config['keydname']], envs=env_vars)
                    if p.returncode != 0:
                        raise BuildException("Failed to generate key", p.output)

                signed_apk_path = os.path.join(output_dir, apkfilename)
                if os.path.exists(signed_apk_path):
                    raise BuildException("Refusing to sign '{0}' file exists in both "
                                         "{1} and {2} folder.".format(apkfilename,
                                                                      unsigned_dir,
                                                                      output_dir))

                # TODO replace below with common.sign_apk() once it has proven stable
                # Sign the application...
                p = FDroidPopen([config['jarsigner'], '-keystore', config['keystore'],
                                 '-storepass:env', 'FDROID_KEY_STORE_PASS',
                                 '-keypass:env', 'FDROID_KEY_PASS', '-sigalg',
                                 'SHA1withRSA', '-digestalg', 'SHA1',
                                 apkfile, keyalias], envs=env_vars)
                if p.returncode != 0:
                    raise BuildException(_("Failed to sign application"), p.output)

                # Zipalign it...
                p = SdkToolsPopen(['zipalign', '-v', '4', apkfile,
                                   os.path.join(output_dir, apkfilename)])
                if p.returncode != 0:
                    raise BuildException(_("Failed to align application"))
                os.remove(apkfile)

                publish_source_tarball(apkfilename, unsigned_dir, output_dir)
                logging.info('Published ' + apkfilename)

    store_stats_fdroid_signing_key_fingerprints(allapps.keys())
    logging.info('published list signing-key fingerprints')
Exemplo n.º 58
0
def ngettext(singular, plural, n):
    t = gettext.dngettext('EPGRefresh', singular, plural, n)
    if t in (singular, plural):
        t = gettext.ngettext(singular, plural, n)
    return t
Exemplo n.º 59
0
    def __init__(self):
        """
            Init dialog
        """
        self.__choosers = []
        self.__cover_tid = None
        self.__mix_tid = None
        self.__popover = None

        cs_api_key = Lp().settings.get_value('cs-api-key').get_string()
        default_cs_api_key = Lp().settings.get_default_value(
            'cs-api-key').get_string()
        if (not cs_api_key or
            cs_api_key == default_cs_api_key) and\
                get_network_available() and\
                Lp().notify is not None:
            Lp().notify.send(
                _("Google Web Services need a custom API key"),
                _("Lollypop needs this to search artwork and music."))

        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Lollypop/SettingsDialog.ui')
        self.__progress = builder.get_object('progress')
        self.__infobar = builder.get_object('infobar')
        self.__reset_button = builder.get_object('reset_button')
        if Lp().lastfm is None or Lp().lastfm.is_goa:
            builder.get_object('lastfm_grid').hide()
        if Lp().scanner.is_locked():
            builder.get_object('reset_button').set_sensitive(False)
        artists = Lp().artists.count()
        albums = Lp().albums.count()
        tracks = Lp().tracks.count()
        builder.get_object('artists').set_text(
            ngettext("%d artist", "%d artists", artists) % artists)
        builder.get_object('albums').set_text(
            ngettext("%d album", "%d albums", albums) % albums)
        builder.get_object('tracks').set_text(
            ngettext("%d track", "%d tracks", tracks) % tracks)

        self.__popover_content = builder.get_object('popover')
        duration = builder.get_object('duration')
        duration.set_range(1, 20)
        duration.set_value(Lp().settings.get_value('mix-duration').get_int32())

        self.__settings_dialog = builder.get_object('settings_dialog')
        self.__settings_dialog.set_transient_for(Lp().window)

        if Lp().settings.get_value('disable-csd'):
            self.__settings_dialog.set_title(_("Preferences"))
        else:
            headerbar = builder.get_object('header_bar')
            headerbar.set_title(_("Preferences"))
            self.__settings_dialog.set_titlebar(headerbar)

        switch_scan = builder.get_object('switch_scan')
        switch_scan.set_state(Lp().settings.get_value('auto-update'))

        switch_view = builder.get_object('switch_dark')
        if Lp().gtk_application_prefer_dark_theme:
            switch_view.set_sensitive(False)
        else:
            switch_view.set_state(Lp().settings.get_value('dark-ui'))

        switch_background = builder.get_object('switch_background')
        switch_background.set_state(Lp().settings.get_value('background-mode'))

        switch_state = builder.get_object('switch_state')
        switch_state.set_state(Lp().settings.get_value('save-state'))

        switch_mix = builder.get_object('switch_mix')
        switch_mix.set_state(Lp().settings.get_value('mix'))
        self.__helper = TouchHelper(switch_mix, None, None)
        self.__helper.set_long_func(self.__mix_long_func, switch_mix)
        self.__helper.set_short_func(self.__mix_short_func, switch_mix)

        switch_mix_party = builder.get_object('switch_mix_party')
        switch_mix_party.set_state(Lp().settings.get_value('party-mix'))

        switch_librefm = builder.get_object('switch_librefm')
        switch_librefm.set_state(Lp().settings.get_value('use-librefm'))

        switch_artwork_tags = builder.get_object('switch_artwork_tags')
        # Check portal for kid3-cli
        can_set_cover = False
        try:
            bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
            proxy = Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None,
                                           'org.gnome.Lollypop.Portal',
                                           '/org/gnome/LollypopPortal',
                                           'org.gnome.Lollypop.Portal', None)
            can_set_cover = proxy.call_sync('CanSetCover', None,
                                            Gio.DBusCallFlags.NO_AUTO_START,
                                            500, None)[0]
        except Exception as e:
            print(
                "You are missing lollypop-portal: "
                "https://github.com/gnumdk/lollypop-portal", e)
        if not can_set_cover:
            grid = builder.get_object('grid_behaviour')
            h = grid.child_get_property(switch_artwork_tags, 'height')
            w = grid.child_get_property(switch_artwork_tags, 'width')
            l = grid.child_get_property(switch_artwork_tags, 'left-attach')
            t = grid.child_get_property(switch_artwork_tags, 'top-attach')
            switch_artwork_tags.destroy()
            label = Gtk.Label.new(_("You need to install kid3-cli"))
            label.get_style_context().add_class('dim-label')
            label.set_property('halign', Gtk.Align.END)
            label.show()
            grid.attach(label, l, t, w, h)
        else:
            switch_artwork_tags.set_state(
                Lp().settings.get_value('save-to-tags'))

        if GLib.find_program_in_path("youtube-dl") is None:
            builder.get_object('charts_grid').hide()
        else:
            switch_charts = builder.get_object('switch_charts')
            switch_charts.set_state(Lp().settings.get_value('show-charts'))

        switch_genres = builder.get_object('switch_genres')
        switch_genres.set_state(Lp().settings.get_value('show-genres'))

        switch_compilations = builder.get_object('switch_compilations')
        switch_compilations.set_state(
            Lp().settings.get_value('show-compilations'))

        switch_artwork = builder.get_object('switch_artwork')
        switch_artwork.set_state(Lp().settings.get_value('artist-artwork'))

        switch_spotify = builder.get_object('switch_spotify')
        switch_spotify.set_state(Lp().settings.get_value('search-spotify'))

        switch_itunes = builder.get_object('switch_itunes')
        switch_itunes.set_state(Lp().settings.get_value('search-itunes'))

        if GLib.find_program_in_path("youtube-dl") is None:
            builder.get_object('yt-dl').show()

        combo_orderby = builder.get_object('combo_orderby')
        combo_orderby.set_active(Lp().settings.get_enum(('orderby')))

        combo_preview = builder.get_object('combo_preview')

        scale_coversize = builder.get_object('scale_coversize')
        scale_coversize.set_range(150, 300)
        scale_coversize.set_value(
            Lp().settings.get_value('cover-size').get_int32())
        self.__settings_dialog.connect('destroy', self.__edit_settings_close)

        builder.connect_signals(self)

        main_chooser_box = builder.get_object('main_chooser_box')
        self.__chooser_box = builder.get_object('chooser_box')

        self.__set_outputs(combo_preview)

        #
        # Music tab
        #
        dirs = []
        for directory in Lp().settings.get_value('music-uris'):
            dirs.append(directory)

        # Main chooser
        self.__main_chooser = ChooserWidget()
        image = Gtk.Image.new_from_icon_name("list-add-symbolic",
                                             Gtk.IconSize.MENU)
        self.__main_chooser.set_icon(image)
        self.__main_chooser.set_action(self.__add_chooser)
        main_chooser_box.pack_start(self.__main_chooser, False, True, 0)
        if len(dirs) > 0:
            uri = dirs.pop(0)
        else:
            filename = GLib.get_user_special_dir(
                GLib.UserDirectory.DIRECTORY_MUSIC)
            if filename:
                uri = GLib.filename_to_uri(filename)
            else:
                uri = ""

        self.__main_chooser.set_dir(uri)

        # Others choosers
        for directory in dirs:
            self.__add_chooser(directory)

        #
        # Google tab
        #
        builder.get_object('cs-entry').set_text(
            Lp().settings.get_value('cs-api-key').get_string())
        #
        # Last.fm tab
        #
        if Lp().lastfm is not None and Secret is not None:
            self.__test_img = builder.get_object('test_img')
            self.__login = builder.get_object('login')
            self.__password = builder.get_object('password')
            schema = Secret.Schema.new("org.gnome.Lollypop",
                                       Secret.SchemaFlags.NONE, SecretSchema)
            Secret.password_lookup(schema, SecretAttributes, None,
                                   self.__on_password_lookup)
            builder.get_object('lastfm_grid').set_sensitive(True)
            builder.get_object('lastfm_error').hide()
            self.__login.set_text(
                Lp().settings.get_value('lastfm-login').get_string())
Exemplo n.º 60
0
        def rebuild_oneconfview():

            # FIXME for P: hide the search entry
            self.searchentry.hide()

            self.cat_docid_map = {}
            enq = self.enquirer
            query = xapian.Query("")
            if self.state.channel and self.state.channel.query:
                query = xapian.Query(xapian.Query.OP_AND, query,
                                     self.state.channel.query)

            i = 0

            # First search: missing apps only
            xfilter = AppFilter(self.db, self.cache)
            xfilter.set_restricted_list(self.oneconf_additional_pkg)
            xfilter.set_not_installed_only(True)

            enq.set_query(
                query,
                sortmode=SortMethods.BY_ALPHABET,
                nonapps_visible=self.nonapps_visible,
                filter=xfilter,
                nonblocking_load=True,  # we don't block this one for
                # better oneconf responsiveness
                persistent_duplicate_filter=(i > 0))

            L = len(enq.matches)

            if L:
                cat_title = utf8(
                    ngettext(
                        u'%(amount)s item on “%(machine)s” not on this computer',
                        u'%(amount)s items on “%(machine)s” not on this computer',
                        L)) % {
                            'amount': L,
                            'machine': utf8(self.current_hostname)
                        }
                i += L
                docs = enq.get_documents()
                self.cat_docid_map["missingpkg"] = set(
                    [doc.get_docid() for doc in docs])
                model.set_nocategory_documents(
                    docs,
                    untranslated_name="additionalpkg",
                    display_name=cat_title)

            # Second search: additional apps
            xfilter.set_restricted_list(self.oneconf_missing_pkg)
            xfilter.set_not_installed_only(False)
            xfilter.set_installed_only(True)
            enq.set_query(query,
                          sortmode=SortMethods.BY_ALPHABET,
                          nonapps_visible=self.nonapps_visible,
                          filter=xfilter,
                          nonblocking_load=False,
                          persistent_duplicate_filter=(i > 0))

            L = len(enq.matches)
            if L:
                cat_title = utf8(
                    ngettext(
                        u'%(amount)s item on this computer not on “%(machine)s”',
                        '%(amount)s items on this computer not on “%(machine)s”',
                        L)) % {
                            'amount': L,
                            'machine': utf8(self.current_hostname)
                        }
                i += L
                docs = enq.get_documents()
                self.cat_docid_map["additionalpkg"] = set(
                    [doc.get_docid() for doc in docs])
                model.set_nocategory_documents(
                    docs,
                    untranslated_name="additionalpkg",
                    display_name=cat_title)

            if i:
                self.app_view.tree_view.set_cursor(Gtk.TreePath(), None, False)
                if i <= 10:
                    self.app_view.tree_view.expand_all()

            # cache the installed app count
            self.installed_count = i
            self.app_view._append_appcount(self.installed_count,
                                           mode=AppView.DIFF_MODE)

            self.app_view.set_model(self.treefilter)
            if keep_state:
                self._restore_treeview_state(treeview_state)

            # hide the local spinner
            self.hide_installed_view_spinner()

            if window:
                window.set_cursor(None)

            self.emit("app-list-changed", i)
            return