def run(self): """ Shows the settings dialog and processes settings changes. Doesn't return anything. """ gtk_settings = Gtk.Settings.get_default() # Discord enabled state discord_enabled_previous = self.settings.get_integration_discord_enabled() settings_discord_enable = self.builder.get_object('setting_discord_enable') settings_discord_enable.set_active(discord_enabled_previous) # Gtk Theme if not sys.platform.startswith('linux'): store: Gtk.ListStore = Gtk.ListStore.new([str]) cb: Gtk.ComboBox = self.builder.get_object('setting_gtk_theme') active = None for id, theme in enumerate(self._list_gtk_themes()): store.append([theme]) if theme == gtk_settings.get_property("gtk-theme-name"): active = id cb.set_model(store) if active is not None: cb.set_active(active) else: self.builder.get_object('frame_setting_gtk_theme').hide() # Languages cb: Gtk.ComboBox = self.builder.get_object('setting_language') store: Gtk.ListStore = self.builder.get_object('lang_store') store.clear() active = None for id, (code, name) in enumerate(LANGS): store.append([code, name]) if code == self.settings.get_locale(): active = id if active is not None: cb.set_active(active) response = self.window.run() have_to_restart = False if response == Gtk.ResponseType.ACCEPT: # Discord enabled state discord_enabled = settings_discord_enable.get_active() if discord_enabled != discord_enabled_previous: self.settings.set_integration_discord_enabled(discord_enabled) have_to_restart = True # Gtk Theme if not sys.platform.startswith('linux'): cb: Gtk.ComboBox = self.builder.get_object('setting_gtk_theme') iter = cb.get_active_iter() if (iter != None): theme_name = cb.get_model()[iter][0] gtk_settings.set_property("gtk-theme-name", theme_name) self.settings.set_gtk_theme(theme_name) # Languages cb: Gtk.ComboBox = self.builder.get_object('setting_language') lang_name = cb.get_model()[cb.get_active_iter()][0] before = self.settings.get_locale() if before != lang_name: self.settings.set_locale(lang_name) have_to_restart = True self.window.hide() if have_to_restart: md = SkyTempleMessageDialog(self.parent_window, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("You need to restart SkyTemple to " "apply some of the settings."), title="SkyTemple") md.run() md.destroy()
def on_import_clicked(self, *args): md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("To import, select a directory to import from. Files with the pattern 'XX.png'\n" "will be imported, where XX is a number between 0 and 99. The image dimensions must be a multiple of 8." ), title=_("Import Images")) md.run() md.destroy() dialog = Gtk.FileChooserNative.new(_("Import images from PNGs..."), MainController.window(), Gtk.FileChooserAction.SELECT_FOLDER, None, None) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: r = re.compile(rf"(\d+)\.png", re.IGNORECASE) imgs_dict = { int(match[1]): name for match, name in self._try_match_import(r, os.listdir(fn)) if match is not None } imgs = [] # Convert imgs to list for i in range(0, len(imgs_dict)): if i not in imgs_dict: display_error( None, f( _('Failed importing image "{i}":\nImage for number {i} missing.' )), _('Image for number {i} missing.')) return imgs.append(imgs_dict[i]) if len(imgs) == 0: display_error(None, _('No images found.'), _("No images found.")) return for index, image_fn in enumerate(imgs): try: with open(os.path.join(fn, image_fn), 'rb') as file: image = Image.open(file) if len(self.w16) > index: # Existing image, update self.w16[index].set(image) else: self.w16.append( W16AtImage.new(W16TocEntry(0, 0, 0, 0), image)) except Exception as err: logger.error(f(_("Failed importing image '{index}'.")), exc_info=err) display_error( sys.exc_info(), f(_('Failed importing image "{index}":\n{err}')), f(_("Error for '{index}'."))) # Re-render self._reset() for draw in self._draws: draw.queue_draw() # Mark as modified self.module.mark_w16_as_modified(self.item_id)
def convert(self, *args): mode_cb: Gtk.ComboBox = self.builder.get_object('tq_mode') mode = ImageConversionMode( mode_cb.get_model()[mode_cb.get_active_iter()][0]) dither_level = self.builder.get_object('tq_dither_level').get_value() has_first_image = self.builder.get_object( 'tq_input_file').get_filename() is not None has_second_image = self.builder.get_object( 'tq_second_file').get_filename() is not None if not has_first_image: self.error(_("Please select an input image.")) return if has_second_image: md = SkyTempleMessageDialog( self.window, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("Since you selected two images to convert, you will be " "asked for both images where to save them to.")) md.run() md.destroy() dialog = Gtk.FileChooserNative.new(_("Save first image as (PNG)..."), self.window, Gtk.FileChooserAction.SAVE, None, None) if self._previous_output_image is not None: dialog.set_filename(self._previous_output_image) add_dialog_png_filter(dialog) response = dialog.run() output_image = dialog.get_filename() if '.' not in output_image: output_image += '.png' self._previous_output_image = output_image dialog.destroy() if response != Gtk.ResponseType.ACCEPT: return if has_second_image: dialog = Gtk.FileChooserNative.new( _("Save second image as (PNG)..."), self.window, Gtk.FileChooserAction.SAVE, None, None) if self._previous_second_output_image is not None: dialog.set_filename(self._previous_second_output_image) else: dialog.set_filename(output_image) add_dialog_png_filter(dialog) response = dialog.run() second_output_image = dialog.get_filename() if '.' not in second_output_image: second_output_image += '.png' self._previous_second_output_image = second_output_image dialog.destroy() if response != Gtk.ResponseType.ACCEPT: return try: num_pals = int( self.builder.get_object('tq_number_palettes').get_text()) input_image = self.builder.get_object( 'tq_input_file').get_filename() second_input_file = self.builder.get_object( 'tq_second_file').get_filename() transparent_color = self.builder.get_object( 'tq_transparent_color').get_color() transparent_color = (int(transparent_color.red_float * 255), int(transparent_color.green_float * 255), int(transparent_color.blue_float * 255)) except ValueError: self.error(_("You entered invalid numbers.")) else: if not os.path.exists(input_image): self.error(_("The input image does not exist.")) return if has_second_image and not os.path.exists(second_input_file): self.error(_("The second input image does not exist.")) return with open(input_image, 'rb') as input_file: try: if not has_second_image: # Only one image image = Image.open(input_file) else: # Two images: Merge them. image1 = Image.open(input_file) image2 = Image.open(second_input_file) image = Image.new('RGBA', (max(image1.width, image2.width), image1.height + image2.height), transparent_color) image.paste(image1, (0, 0)) image.paste(image2, (0, image1.height)) except OSError: self.error(_("The input image is not a supported format.")) return try: img = self._convert(image, transparent_color, mode, num_pals, dither_level) if not has_second_image: # Only one image img.save(output_image) else: # Two images: Un-merge them. img.crop((0, 0, image1.width, image1.height)).save(output_image) img.crop( (0, image1.height, image2.width, image1.height + image2.height)).save(second_output_image) except BaseException as err: logger.error("Tilequant error.", exc_info=err) self.error(str(err)) else: md = SkyTempleMessageDialog( self.window, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("Image was converted."), is_success=True) md.run() md.destroy()
from skytemple.core.ui_utils import make_builder try: gi.require_foreign("cairo") except ImportError: from gi.repository import Gtk md = SkyTempleMessageDialog( None, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, _("PyGObject compiled without Cairo support. Can't start!"), title=_("SkyTemple - Error!")) md.set_position(Gtk.WindowPosition.CENTER) md.run() md.destroy() exit(1) from gi.repository import Gtk, Gdk, GLib from gi.repository.Gtk import Window from skytemple.controller.main import MainController SKYTEMPLE_LOGLEVEL = logging.INFO def run_main(settings: SkyTempleSettingsStore): # TODO: Gtk.Application: https://python-gtk-3-tutorial.readthedocs.io/en/latest/application.html path = os.path.abspath(os.path.dirname(__file__)) if sys.platform.startswith('win'): # Load theming under Windows