def fmt_time_period_abbr(t): """Get a localized abbreviated minutes+seconds string :param int t: A positive number of seconds :returns: short localized string :rtype: unicode The result looks like like "<minutes>m<seconds>s", or just "<seconds>s". """ if t < 0: raise ValueError("Parameter t cannot be negative") days = int(t / (24 * 60 * 60)) hours = int(t - days * 24 * 60 * 60) / (60 * 60) minutes = int(t - hours * 60 * 60) / 60 seconds = int(t - minutes * 60) # TRANSLATORS: I'm assuming that time periods in places where # TRANSLATORS: abbreviations make sense don't need ngettext() if t > 24 * 60 * 60: template = C_("Time period abbreviations", u"{days}d{hours}h") elif t > 60 * 60: template = C_("Time period abbreviations", u"{hours}h{minutes}m") elif t > 60: template = C_("Time period abbreviation", u"{minutes}m{seconds}s") else: template = C_("Time period abbreviation", u"{seconds}s") return template.format( days = days, hours = hours, minutes = minutes, seconds = seconds, )
def fmt_time_period_abbr(t): """Get a localized abbreviated minutes+seconds string :param int t: A positive number of seconds :returns: short localized string :rtype: unicode The result looks like like "<minutes>m<seconds>s", or just "<seconds>s". """ if t < 0: raise ValueError("Parameter t cannot be negative") days = int(t // (24 * 60 * 60)) hours = int(t - days * 24 * 60 * 60) // (60 * 60) minutes = int(t - hours * 60 * 60) // 60 seconds = int(t - minutes * 60) if t > 24 * 60 * 60: # TRANSLATORS: Assumption for all "Time period abbreviations": # TRANSLATORS: they don't need ngettext (to support plural/singular) template = C_("Time period abbreviations", u"{days}d{hours}h") elif t > 60 * 60: template = C_("Time period abbreviations", u"{hours}h{minutes}m") elif t > 60: template = C_("Time period abbreviation", u"{minutes}m{seconds}s") else: template = C_("Time period abbreviation", u"{seconds}s") return template.format( days = days, hours = hours, minutes = minutes, seconds = seconds, )
def _query_tooltip_cb(self, da, x, y, keyboard_mode, tooltip): s = self._TOOLTIP_ICON_SIZE scaled_pixbuf = self._get_scaled_pixbuf(s) tooltip.set_icon(scaled_pixbuf) template_params = {"brush_name": escape(self._brush_name)} markup_template = C_( "current brush indicator: tooltip (no-description case)", u"<b>{brush_name}</b>", ) if self._brush_desc: markup_template = C_( "current brush indicator: tooltip (description case)", u"<b>{brush_name}</b>\n{brush_desc}", ) template_params["brush_desc"] = escape(self._brush_desc) markup = markup_template.format(**template_params) tooltip.set_markup(markup) # TODO: summarize changes? return True
def _query_tooltip_cb(self, da, x, y, keyboard_mode, tooltip): s = self._TOOLTIP_ICON_SIZE scaled_pixbuf = self._get_scaled_pixbuf(s) tooltip.set_icon(scaled_pixbuf) template_params = {"brush_name": lib.xml.escape(self._brush_name)} markup_template = C_( "current brush indicator: tooltip (no-description case)", u"<b>{brush_name}</b>", ) if self._brush_desc: markup_template = C_( "current brush indicator: tooltip (description case)", u"<b>{brush_name}</b>\n{brush_desc}", ) template_params["brush_desc"] = lib.xml.escape(self._brush_desc) markup = markup_template.format(**template_params) tooltip.set_markup(markup) # TODO: summarize changes? return True
def _query_tooltip_cb(self, da, x, y, keyboard_mode, tooltip): s = self._TOOLTIP_ICON_SIZE scaled_pixbuf = self._get_scaled_pixbuf(s) tooltip.set_icon(scaled_pixbuf) brush_name = self._brush_name if not brush_name: brush_name = self._DEFAULT_BRUSH_DISPLAY_NAME # Rare cases, see https://github.com/mypaint/mypaint/issues/402. # Probably just after init. template_params = {"brush_name": lib.xml.escape(brush_name)} markup_template = C_("current brush indicator: tooltip (no-description case)", u"<b>{brush_name}</b>") if self._brush_desc: markup_template = C_( "current brush indicator: tooltip (description case)", u"<b>{brush_name}</b>\n{brush_desc}" ) template_params["brush_desc"] = lib.xml.escape(self._brush_desc) markup = markup_template.format(**template_params) tooltip.set_markup(markup) # TODO: summarize changes? return True
def _query_tooltip_cb(self, da, x, y, keyboard_mode, tooltip): s = self._TOOLTIP_ICON_SIZE scaled_pixbuf = self._get_scaled_pixbuf(s) tooltip.set_icon(scaled_pixbuf) brush_name = self._brush_name if not brush_name: brush_name = self._DEFAULT_BRUSH_DISPLAY_NAME # Rare cases, see https://github.com/mypaint/mypaint/issues/402. # Probably just after init. template_params = {"brush_name": lib.xml.escape(brush_name)} markup_template = C_( "current brush indicator: tooltip (no-description case)", u"<b>{brush_name}</b>", ) if self._brush_desc: markup_template = C_( "current brush indicator: tooltip (description case)", u"<b>{brush_name}</b>\n{brush_desc}", ) template_params["brush_desc"] = lib.xml.escape(self._brush_desc) markup = markup_template.format(**template_params) tooltip.set_markup(markup) # TODO: summarize changes? return True
def _save_doc_to_file(self, filename, doc, export=False, statusmsg=True, **options): """Saves a document to one or more files :param filename: The base filename to save :param gui.document.Document doc: Controller for the document to save :param bool export: True if exporting :param **options: Pass-through options This method handles logging, statusbar messages, and alerting the user to when the save failed. See also: `lib.document.Document.save()`. """ thumbnail_pixbuf = None prefs = self.app.preferences display_colorspace_setting = prefs["display.colorspace"] options['save_srgb_chunks'] = (display_colorspace_setting == "srgb") if statusmsg: statusbar = self.app.statusbar statusbar_cid = self._statusbar_context_id statusbar.remove_all(statusbar_cid) file_basename = os.path.basename(filename) if export: during_tmpl = C_( "file handling: during export (statusbar)", u"Exporting to “{file_basename}”…" ) else: during_tmpl = C_( "file handling: during save (statusbar)", u"Saving “{file_basename}”…" ) statusbar.push(statusbar_cid, during_tmpl.format( file_basename = file_basename, )) try: x, y, w, h = doc.model.get_bbox() if w == 0 and h == 0: w, h = tiledsurface.N, tiledsurface.N # TODO: Add support for other sizes thumbnail_pixbuf = doc.model.save( filename, feedback_cb=self.gtk_main_tick, **options ) self.lastsavefailed = False except (FileHandlingError, AllocationError, MemoryError) as e: if statusmsg: statusbar.remove_all(statusbar_cid) if export: failed_tmpl = C_( "file handling: export failure (statusbar)", u"Failed to export to “{file_basename}”.", ) else: failed_tmpl = C_( "file handling: save failure (statusbar)", u"Failed to save “{file_basename}”.", ) self.app.show_transient_message(failed_tmpl.format( file_basename = file_basename, )) self.lastsavefailed = True self.app.message_dialog(unicode(e), type=Gtk.MessageType.ERROR) else: if statusmsg: statusbar.remove_all(statusbar_cid) file_location = os.path.abspath(filename) multifile_info = '' if "multifile" in options: multifile_info = " (basis; used multiple .XXX.ext names)" if not export: logger.info('Saved to %r%s', file_location, multifile_info) else: logger.info('Exported to %r%s', file_location, multifile_info) if statusmsg: if export: success_tmpl = C_( "file handling: export success (statusbar)", u"Exported to “{file_basename}” successfully.", ) else: success_tmpl = C_( "file handling: save success (statusbar)", u"Saved “{file_basename}” successfully.", ) self.app.show_transient_message(success_tmpl.format( file_basename = file_basename, )) return thumbnail_pixbuf
def _layer_description_markup(layer): """GMarkup text description of a layer, used in the list.""" name_markup = None description = None if layer is None: name_markup = escape(lib.layer.PlaceholderLayer.DEFAULT_NAME) description = C_( "Layers: description: no layer (\"never happens\" condition!)", u"?layer", ) elif layer.name is None: name_markup = escape(layer.DEFAULT_NAME) else: name_markup = escape(layer.name) if layer is not None: desc_parts = [] if isinstance(layer, lib.layer.LayerStack): name_markup = "<i>{}</i>".format(name_markup) # Mode (if it's interesting) if layer.mode in lib.modes.MODE_STRINGS: if layer.mode != lib.modes.default_mode(): s, d = lib.modes.MODE_STRINGS[layer.mode] desc_parts.append(s) else: desc_parts.append( C_( "Layers: description parts: unknown mode (fallback str!)", u"?mode", )) # Visibility and opacity (if interesting) if not layer.visible: desc_parts.append( C_( "Layers: description parts: layer hidden", u"Hidden", )) elif layer.opacity < 1.0: desc_parts.append( C_("Layers: description parts: opacity percentage", u"%d%% opaque" % (round(layer.opacity * 100), ))) # Locked flag (locked is interesting) if layer.locked: desc_parts.append( C_( "Layers dockable: description parts: layer locked flag", u"Locked", )) # Description of the layer's type. # Currently always used, for visual rhythm reasons, but it goes # on the end since it's perhaps the least interesting info. if layer.TYPE_DESCRIPTION is not None: desc_parts.append(layer.TYPE_DESCRIPTION) else: desc_parts.append( C_( "Layers: description parts: unknown type (fallback str!)", u"?type", )) # Stitch it all together if desc_parts: description = C_( "Layers dockable: description parts joiner text", u", ", ).join(desc_parts) else: description = None if description is None: markup_template = C_( "Layers dockable: markup for a layer with no description", u"{layer_name}", ) else: markup_template = C_( "Layers dockable: markup for a layer with a description", '<span size="smaller">{layer_name}\n' '<span size="smaller">{layer_description}</span>' '</span>') markup = markup_template.format( layer_name=name_markup, layer_description=escape(description), ) return markup
def _save_doc_to_file(self, filename, doc, export=False, statusmsg=True, **options): """Saves a document to one or more files :param filename: The base filename to save :param gui.document.Document doc: Controller for the document to save :param bool export: True if exporting :param **options: Pass-through options This method handles logging, statusbar messages, and alerting the user to when the save failed. See also: `lib.document.Document.save()`. """ thumbnail_pixbuf = None prefs = self.app.preferences display_colorspace_setting = prefs["display.colorspace"] options['save_srgb_chunks'] = (display_colorspace_setting == "srgb") if statusmsg: statusbar = self.app.statusbar statusbar_cid = self._statusbar_context_id statusbar.remove_all(statusbar_cid) file_basename = os.path.basename(filename) if export: during_tmpl = C_("file handling: during export (statusbar)", u"Exporting to “{file_basename}”…") else: during_tmpl = C_("file handling: during save (statusbar)", u"Saving “{file_basename}”…") statusbar.push(statusbar_cid, during_tmpl.format(file_basename=file_basename, )) try: x, y, w, h = doc.model.get_bbox() if w == 0 and h == 0: w, h = tiledsurface.N, tiledsurface.N # TODO: Add support for other sizes thumbnail_pixbuf = doc.model.save(filename, feedback_cb=self.gtk_main_tick, **options) self.lastsavefailed = False except (FileHandlingError, AllocationError, MemoryError) as e: if statusmsg: statusbar.remove_all(statusbar_cid) if export: failed_tmpl = C_( "file handling: export failure (statusbar)", u"Failed to export to “{file_basename}”.", ) else: failed_tmpl = C_( "file handling: save failure (statusbar)", u"Failed to save “{file_basename}”.", ) self.app.show_transient_message( failed_tmpl.format(file_basename=file_basename, )) self.lastsavefailed = True self.app.message_dialog(unicode(e), type=gtk.MESSAGE_ERROR) else: if statusmsg: statusbar.remove_all(statusbar_cid) file_location = os.path.abspath(filename) multifile_info = '' if "multifile" in options: multifile_info = " (basis; used multiple .XXX.ext names)" if not export: logger.info('Saved to %r%s', file_location, multifile_info) else: logger.info('Exported to %r%s', file_location, multifile_info) if statusmsg: if export: success_tmpl = C_( "file handling: export success (statusbar)", u"Exported to “{file_basename}” successfully.", ) else: success_tmpl = C_( "file handling: save success (statusbar)", u"Saved “{file_basename}” successfully.", ) self.app.show_transient_message( success_tmpl.format(file_basename=file_basename, )) return thumbnail_pixbuf
>>> x2 = u'xyz 2' >>> make_unique_name(u"xyz", {}, start=2, always_number=u"xyz") == x2 True """ name = unicode(name) match = UNIQUE_NAME_REGEX.match(name) if match: base = match.group("name") num = int(match.group("number")) else: base = name num = max(0, int(start)) force_numbering = (name == always_number) while (name in existing) or force_numbering: name = UNIQUE_NAME_TEMPLATE.format(name=base, number=num) num += 1 force_numbering = False return name assert UNIQUE_NAME_REGEX.match( UNIQUE_NAME_TEMPLATE.format( name="testing", number=12, ) ), ( "Translation error: lib.naming.UNIQUE_NAME_REGEX " "must match UNIQUE_NAME_TEMPLATE." )
def _layer_description_markup(layer): """GMarkup text description of a layer, used in the list.""" name_markup = None description = None if layer is None: name_markup = escape(lib.layer.PlaceholderLayer.DEFAULT_NAME) description = C_( "Layers: description: no layer (\"never happens\" condition!)", u"?layer", ) elif layer.name is None: name_markup = escape(layer.DEFAULT_NAME) else: name_markup = escape(layer.name) if layer is not None: desc_parts = [] if isinstance(layer, lib.layer.LayerStack): name_markup = "<i>{}</i>".format(name_markup) # Mode (if it's interesting) if layer.mode in lib.modes.MODE_STRINGS: if layer.mode != lib.modes.DEFAULT_MODE: s, d = lib.modes.MODE_STRINGS[layer.mode] desc_parts.append(s) else: desc_parts.append(C_( "Layers: description parts: unknown mode (fallback str!)", u"?mode", )) # Visibility and opacity (if interesting) if not layer.visible: desc_parts.append(C_( "Layers: description parts: layer hidden", u"Hidden", )) elif layer.opacity < 1.0: desc_parts.append(C_( "Layers: description parts: opacity percentage", u"%d%% opaque" % (round(layer.opacity * 100),) )) # Locked flag (locked is interesting) if layer.locked: desc_parts.append(C_( "Layers dockable: description parts: layer locked flag", u"Locked", )) # Description of the layer's type. # Currently always used, for visual rhythm reasons, but it goes # on the end since it's perhaps the least interesting info. if layer.TYPE_DESCRIPTION is not None: desc_parts.append(layer.TYPE_DESCRIPTION) else: desc_parts.append(C_( "Layers: description parts: unknown type (fallback str!)", u"?type", )) # Stitch it all together if desc_parts: description = C_( "Layers dockable: description parts joiner text", u", ", ).join(desc_parts) else: description = None if description is None: markup_template = C_( "Layers dockable: markup for a layer with no description", u"{layer_name}", ) else: markup_template = C_( "Layers dockable: markup for a layer with a description", '<span size="smaller">{layer_name}\n' '<span size="smaller" alpha="50%">{layer_description}</span>' '</span>' ) markup = markup_template.format( layer_name=name_markup, layer_description=escape(description), ) return markup
item to be, for example, "Widget 1", not "Widget". >>> make_unique_name(u"xyz", {}, start=1, always_number=u"xyz") u'xyz 1' >>> make_unique_name(u"xyz", {}, start=2, always_number=u"xyz") u'xyz 2' """ name = unicode(name) match = UNIQUE_NAME_REGEX.match(name) if match: base = match.group("name") num = int(match.group("number")) else: base = name num = max(0, int(start)) force_numbering = (name == always_number) while (name in existing) or force_numbering: name = UNIQUE_NAME_TEMPLATE.format(name=base, number=num) num += 1 force_numbering = False return name assert UNIQUE_NAME_REGEX.match( UNIQUE_NAME_TEMPLATE.format( name="testing", number=12, )), ("Translation error: lib.naming.UNIQUE_NAME_REGEX " "must match UNIQUE_NAME_TEMPLATE.")