class MapPreview(object): """Semiprivate class dealing with the map preview icon""" def __init__(self, get_widget): """ @param get_widget: returns the current widget (self.current) """ self.minimap = None self.calc_proc = None # handle to background calculation process self.get_widget = get_widget def update_map(self, map_file): """Direct map preview update. Only use for existing maps, it's too slow for random maps""" if self.minimap is not None: self.minimap.end() world = self._load_raw_world(map_file) self.minimap = Minimap(self._get_map_preview_icon(), session=None, view=None, world=world, targetrenderer=horizons.main.fife.targetrenderer, imagemanager=horizons.main.fife.imagemanager, cam_border=False, use_rotation=False, tooltip=None, on_click=None, preview=True) self.minimap.draw() def update_random_map(self, map_params, on_click): """Called when a random map parameter has changed. @param map_params: _get_random_map() output @param on_click: handler for clicks""" def check_calc_process(): # checks up on calc process (see below) if self.calc_proc is not None: state = self.calc_proc.poll() if state is None: # not finished ExtScheduler().add_new_object(check_calc_process, self, 0.1) elif state != 0: self._set_map_preview_status(u"An unknown error occured while generating the map preview") else: # done data = open(self.calc_proc.output_filename, "r").read() os.unlink(self.calc_proc.output_filename) self.calc_proc = None icon = self._get_map_preview_icon() if icon is None: return # dialog already gone tooltip = _("Click to generate a different random map") if self.minimap is not None: self.minimap.end() self.minimap = Minimap(icon, session=None, view=None, world=None, targetrenderer=horizons.main.fife.targetrenderer, imagemanager=horizons.main.fife.imagemanager, cam_border=False, use_rotation=False, tooltip=tooltip, on_click=on_click, preview=True) self.minimap.draw_data( data ) icon.show() self._set_map_preview_status(u"") if self.calc_proc is not None: self.calc_proc.kill() # process exists, therefore up is scheduled already else: ExtScheduler().add_new_object(check_calc_process, self, 0.5) # launch process in background to calculate minimap data minimap_icon = self._get_map_preview_icon() params = json.dumps(((minimap_icon.width, minimap_icon.height), map_params)) args = (sys.executable, sys.argv[0], "--generate-minimap", params) handle, outfilename = tempfile.mkstemp() os.close(handle) self.calc_proc = subprocess.Popen(args=args, stdout=open(outfilename, "w")) self.calc_proc.output_filename = outfilename # attach extra info self._set_map_preview_status(u"Generating preview...") @classmethod def generate_minimap(cls, size, parameters): """Called as subprocess, calculates minimap data and passes it via string via stdout""" # called as standalone basically, so init everything we need from horizons.main import _create_main_db from horizons.entities import Entities from horizons.ext.dummy import Dummy db = _create_main_db() Entities.load_grounds(db, load_now=False) # create all references map_file = SingleplayerMenu._generate_random_map( parameters ) world = cls._load_raw_world(map_file) location = Rect.init_from_topleft_and_size_tuples( (0, 0), size) minimap = Minimap(location, session=None, view=None, world=world, targetrenderer=Dummy(), imagemanager=Dummy(), cam_border=False, use_rotation=False, preview=True) # communicate via stdout print minimap.dump_data() @classmethod def _load_raw_world(cls, map_file): WorldObject.reset() world = World(session=None) world.inited = True world.load_raw_map( SavegameAccessor( map_file ), preview=True ) return world def _get_map_preview_icon(self): """Returns pychan icon for map preview""" return self.get_widget().findChild(name="map_preview_minimap") def _set_map_preview_status(self, text): """Sets small status label next to map preview""" wdg = self.get_widget().findChild(name="map_preview_status_label") if wdg: # might show next dialog already wdg.text = text
class MapPreview(object): """Semiprivate class dealing with the map preview icon""" def __init__(self, get_widget): """ @param get_widget: returns the current widget (self.current) """ self.minimap = None self.calc_proc = None # handle to background calculation process self.get_widget = get_widget self._last_random_map_params = None def update_map(self, map_file): """Direct map preview update. Only use for existing maps, it's too slow for random maps""" if self.minimap is not None: self.minimap.end() world = self._load_raw_world(map_file) self.minimap = Minimap( self._get_map_preview_icon(), session=None, view=None, world=world, targetrenderer=horizons.globals.fife.targetrenderer, imagemanager=horizons.globals.fife.imagemanager, cam_border=False, use_rotation=False, tooltip=None, on_click=None, preview=True) self.minimap.draw() def update_random_map(self, map_params, on_click): """Called when a random map parameter has changed. @param map_params: _get_random_map() output @param on_click: handler for clicks""" if self._last_random_map_params == map_params: return # we already display this, happens on spurious slider events such as hover self._last_random_map_params = map_params def check_calc_process(): # checks up on calc process (see below) if self.calc_proc is not None: state = self.calc_proc.poll() if state is None: # not finished ExtScheduler().add_new_object(check_calc_process, self, 0.1) elif state != 0: self._set_map_preview_status( u"An unknown error occured while generating the map preview" ) else: # done data = open(self.calc_proc.output_filename, "r").read() os.unlink(self.calc_proc.output_filename) self.calc_proc = None icon = self._get_map_preview_icon() if icon is None: return # dialog already gone tooltip = _("Click to generate a different random map") if self.minimap is not None: self.minimap.end() self.minimap = Minimap( icon, session=None, view=None, world=None, targetrenderer=horizons.globals.fife.targetrenderer, imagemanager=horizons.globals.fife.imagemanager, cam_border=False, use_rotation=False, tooltip=tooltip, on_click=on_click, preview=True) self.minimap.draw_data(data) icon.show() self._set_map_preview_status(u"") if self.calc_proc is not None: self.calc_proc.kill( ) # process exists, therefore up is scheduled already else: ExtScheduler().add_new_object(check_calc_process, self, 0.5) # launch process in background to calculate minimap data minimap_icon = self._get_map_preview_icon() params = json.dumps( ((minimap_icon.width, minimap_icon.height), map_params)) args = (sys.executable, sys.argv[0], "--generate-minimap", params) handle, outfilename = tempfile.mkstemp() os.close(handle) self.calc_proc = subprocess.Popen(args=args, stdout=open(outfilename, "w")) self.calc_proc.output_filename = outfilename # attach extra info self._set_map_preview_status(u"Generating preview...") @classmethod def generate_minimap(cls, size, parameters): """Called as subprocess, calculates minimap data and passes it via string via stdout""" # called as standalone basically, so init everything we need from horizons.main import _create_main_db from horizons.entities import Entities from horizons.ext.dummy import Dummy db = _create_main_db() Entities.load_grounds(db, load_now=False) # create all references map_file = SingleplayerMenu._generate_random_map(parameters) world = cls._load_raw_world(map_file) location = Rect.init_from_topleft_and_size_tuples((0, 0), size) minimap = Minimap(location, session=None, view=None, world=world, targetrenderer=Dummy(), imagemanager=Dummy(), cam_border=False, use_rotation=False, preview=True) # communicate via stdout print minimap.dump_data() @classmethod def _load_raw_world(cls, map_file): WorldObject.reset() world = World(session=None) world.inited = True world.load_raw_map(SavegameAccessor(map_file, True), preview=True) return world def _get_map_preview_icon(self): """Returns pychan icon for map preview""" return self.get_widget().findChild(name="map_preview_minimap") def _set_map_preview_status(self, text): """Sets small status label next to map preview""" wdg = self.get_widget().findChild(name="map_preview_status_label") if wdg: # might show next dialog already wdg.text = text