class UpdateDialog: """ Base dialog for update satellites, transponders and services from the web.""" def __init__(self, transient, settings, title=None): handlers = { "on_update_satellites_list": self.on_update_satellites_list, "on_receive_data": self.on_receive_data, "on_cancel_receive": self.on_cancel_receive, "on_satellite_toggled": self.on_satellite_toggled, "on_transponder_toggled": self.on_transponder_toggled, "on_info_bar_close": self.on_info_bar_close, "on_filter_toggled": self.on_filter_toggled, "on_find_toggled": self.on_find_toggled, "on_popup_menu": on_popup_menu, "on_select_all": self.on_select_all, "on_unselect_all": self.on_unselect_all, "on_filter": self.on_filter, "on_search": self.on_search, "on_search_down": self.on_search_down, "on_search_up": self.on_search_up, "on_quit": self.on_quit } self._settings = settings self._download_task = False self._parser = None self._size_name = "{}_window_size".format("_".join( re.findall("[A-Z][^A-Z]*", self.__class__.__name__))).lower() builder = Gtk.Builder() builder.set_translation_domain(TEXT_DOMAIN) builder.add_objects_from_file( UI_RESOURCES_PATH + "satellites_dialog.glade", ("satellites_update_window", "update_source_store", "update_sat_list_store", "update_sat_list_model_filter", "update_sat_list_model_sort", "side_store", "pos_adjustment", "pos_adjustment2", "satellites_update_popup_menu", "remove_selection_image", "update_transponder_store", "update_service_store")) builder.connect_signals(handlers) self._window = builder.get_object("satellites_update_window") self._window.set_transient_for(transient) if title: self._window.set_title(title) self._transponder_paned = builder.get_object("sat_update_tr_paned") self._sat_view = builder.get_object("sat_update_tree_view") self._transponder_view = builder.get_object("sat_update_tr_view") self._service_view = builder.get_object("sat_update_srv_view") self._source_box = builder.get_object("source_combo_box") self._sat_update_expander = builder.get_object("sat_update_expander") self._text_view = builder.get_object("text_view") self._receive_button = builder.get_object("receive_data_button") self._sat_update_info_bar = builder.get_object("sat_update_info_bar") self._info_bar_message_label = builder.get_object( "info_bar_message_label") self._receive_button.bind_property( "visible", builder.get_object("cancel_data_button"), "visible", 4) # Filter self._filter_bar = builder.get_object("sat_update_filter_bar") self._from_pos_button = builder.get_object("from_pos_button") self._to_pos_button = builder.get_object("to_pos_button") self._filter_from_combo_box = builder.get_object( "filter_from_combo_box") self._filter_to_combo_box = builder.get_object("filter_to_combo_box") self._filter_model = builder.get_object("update_sat_list_model_filter") self._filter_model.set_visible_func(self.filter_function) self._filter_positions = (0, 0) # Search self._search_bar = builder.get_object("sat_update_search_bar") self._search_provider = SearchProvider( (self._sat_view, ), builder.get_object("sat_update_search_down_button"), builder.get_object("sat_update_search_up_button")) window_size = self._settings.get(self._size_name) if window_size: self._window.resize(*window_size) def show(self): self._window.show() @property def is_download(self): return self._download_task @is_download.setter def is_download(self, value): self._download_task = value self._receive_button.set_visible(not value) @run_idle def on_update_satellites_list(self, item): if self.is_download: show_dialog(DialogType.ERROR, self._window, "The task is already running!") return model = get_base_model(self._sat_view.get_model()) model.clear() self.is_download = True src = self._source_box.get_active() if not self._parser: self._parser = SatellitesParser() self.get_sat_list(src, self.append_satellites) @run_task def get_sat_list(self, src, callback): sat_src = SatelliteSource.FLYSAT if src == 1: sat_src = SatelliteSource.LYNGSAT elif src == 2: sat_src = SatelliteSource.KINGOFSAT sats = self._parser.get_satellites_list(sat_src) if sats: callback(sats) self.is_download = False @run_idle def append_satellites(self, sats): model = get_base_model(self._sat_view.get_model()) for sat in sats: model.append(sat) @run_idle def on_receive_data(self, item): if self.is_download: show_dialog(DialogType.ERROR, self._window, "The task is already running!") return @run_idle def update_expander(self): self._sat_update_expander.set_expanded(True) self._text_view.get_buffer().set_text("", 0) def append_output(self): @run_idle def append(t): append_text_to_tview(t, self._text_view) while True: text = yield append(text) def on_cancel_receive(self, item=None): self._download_task = False def on_satellite_toggled(self, toggle, path): model = self._sat_view.get_model() self.update_state(model, path, not toggle.get_active()) self.update_receive_button_state(self._filter_model) def on_transponder_toggled(self, toggle, path): model = self._transponder_view.get_model() model.set_value(model.get_iter(path), 2, not toggle.get_active()) @run_idle def update_receive_button_state(self, model): self._receive_button.set_sensitive((any(r[4] for r in model))) @run_idle def show_info_message(self, text, message_type): self._sat_update_info_bar.set_visible(True) self._sat_update_info_bar.set_message_type(message_type) self._info_bar_message_label.set_text(text) def on_info_bar_close(self, bar=None, resp=None): self._sat_update_info_bar.set_visible(False) def on_find_toggled(self, button: Gtk.ToggleToolButton): self._search_bar.set_search_mode(button.get_active()) def on_filter_toggled(self, button: Gtk.ToggleToolButton): self._filter_bar.set_search_mode(button.get_active()) @run_idle def on_filter(self, item): self._filter_positions = self.get_positions() self._filter_model.refilter() def filter_function(self, model, itr, data): if self._filter_model is None or self._filter_model == "None": return True from_pos, to_pos = self._filter_positions if from_pos == 0 and to_pos == 0: return True if from_pos > to_pos: from_pos, to_pos = to_pos, from_pos return from_pos <= float( self._parser.get_position(model.get(itr, 1)[0])) <= to_pos def get_positions(self): from_pos = round(self._from_pos_button.get_value(), 1) * ( -1 if self._filter_from_combo_box.get_active() else 1) to_pos = round(self._to_pos_button.get_value(), 1) * ( -1 if self._filter_to_combo_box.get_active() else 1) return from_pos, to_pos def on_search(self, entry): self._search_provider.search(entry.get_text()) def on_search_down(self, item): self._search_provider.on_search_down() def on_search_up(self, item): self._search_provider.on_search_up() def on_select_all(self, view): self.update_selection(view, True) def on_unselect_all(self, view): self.update_selection(view, False) def update_selection(self, view, select): model = view.get_model() view.get_model().foreach( lambda mod, path, itr: self.update_state(model, path, select)) self.update_receive_button_state(self._filter_model) def update_state(self, model, path, select): """ Updates checkbox state by given path in the list """ itr = self._filter_model.convert_iter_to_child_iter( model.convert_iter_to_child_iter(model.get_iter(path))) self._filter_model.get_model().set_value(itr, 4, select) def on_quit(self, window, event): self._settings.add(self._size_name, window.get_size()) self.is_download = False
class SatellitesUpdateDialog: """ Dialog for update satellites over internet """ def __init__(self, transient, main_model): handlers = { "on_update_satellites_list": self.on_update_satellites_list, "on_receive_satellites_list": self.on_receive_satellites_list, "on_cancel_receive": self.on_cancel_receive, "on_selected_toggled": self.on_selected_toggled, "on_info_bar_close": self.on_info_bar_close, "on_filter_toggled": self.on_filter_toggled, "on_find_toggled": self.on_find_toggled, "on_popup_menu": on_popup_menu, "on_select_all": self.on_select_all, "on_unselect_all": self.on_unselect_all, "on_filter": self.on_filter, "on_search": self.on_search, "on_search_down": self.on_search_down, "on_search_up": self.on_search_up, "on_quit": self.on_quit } builder = Gtk.Builder() builder.set_translation_domain(TEXT_DOMAIN) builder.add_objects_from_file( UI_RESOURCES_PATH + "satellites_dialog.glade", ("satellites_update_window", "update_source_store", "update_sat_list_store", "update_sat_list_model_filter", "update_sat_list_model_sort", "side_store", "pos_adjustment", "pos_adjustment2", "satellites_update_popup_menu", "remove_selection_image")) builder.connect_signals(handlers) self._window = builder.get_object("satellites_update_window") self._window.set_transient_for(transient) self._main_model = main_model # self._dialog.get_content_area().set_border_width(0) self._sat_view = builder.get_object("sat_update_tree_view") self._source_box = builder.get_object("source_combo_box") self._sat_update_expander = builder.get_object("sat_update_expander") self._text_view = builder.get_object("text_view") self._receive_button = builder.get_object( "receive_sat_list_tool_button") self._sat_update_info_bar = builder.get_object("sat_update_info_bar") self._info_bar_message_label = builder.get_object( "info_bar_message_label") # Filter self._filter_bar = builder.get_object("sat_update_filter_bar") self._from_pos_button = builder.get_object("from_pos_button") self._to_pos_button = builder.get_object("to_pos_button") self._filter_from_combo_box = builder.get_object( "filter_from_combo_box") self._filter_to_combo_box = builder.get_object("filter_to_combo_box") self._filter_model = builder.get_object("update_sat_list_model_filter") self._filter_model.set_visible_func(self.filter_function) self._filter_positions = (0, 0) # Search self._search_bar = builder.get_object("sat_update_search_bar") self._search_provider = SearchProvider( (self._sat_view, ), builder.get_object("sat_update_search_down_button"), builder.get_object("sat_update_search_up_button")) self._download_task = False self._parser = None def show(self): self._window.show() @run_idle def on_update_satellites_list(self, item): if self._download_task: show_dialog(DialogType.ERROR, self._window, "The task is already running!") return model = get_base_model(self._sat_view.get_model()) model.clear() self._download_task = True src = self._source_box.get_active() if not self._parser: self._parser = SatellitesParser() self.get_sat_list(src, self.append_satellites) @run_task def get_sat_list(self, src, callback): sats = self._parser.get_satellites_list( SatelliteSource.FLYSAT if src == 0 else SatelliteSource.LYNGSAT) if sats: callback(sats) self._download_task = False @run_idle def append_satellites(self, sats): model = get_base_model(self._sat_view.get_model()) for sat in sats: model.append(sat) @run_idle def on_receive_satellites_list(self, item): if self._download_task: show_dialog(DialogType.ERROR, self._window, "The task is already running!") return self.receive_satellites() @run_task def receive_satellites(self): self._download_task = True self.update_expander() model = self._sat_view.get_model() start = time.time() with concurrent.futures.ProcessPoolExecutor(max_workers=4) as executor: text = "Processing: {}\n" sats = [] appender = self.append_output() next(appender) futures = { executor.submit(self._parser.get_satellite, sat[:-1]): sat for sat in [r for r in model if r[4]] } for future in concurrent.futures.as_completed(futures): if not self._download_task: self._download_task = True executor.shutdown() appender.send("\nCanceled\n") appender.close() self._download_task = False return data = future.result() appender.send(text.format(data[0])) sats.append(data) appender.send("-" * 75 + "\n") appender.send( "Consumed : {:0.0f}s, {} satellites received.".format( start - time.time(), len(sats))) appender.close() sats = {s[2]: s for s in sats} # key = position, v = satellite for row in self._main_model: pos = row[-1] if pos in sats: sat = sats.pop(pos) itr = row.iter self.update_satellite(itr, row, sat) for sat in sats.values(): append_satellite(self._main_model, sat) self._download_task = False @run_idle def update_expander(self): self._sat_update_expander.set_expanded(True) self._text_view.get_buffer().set_text("", 0) @run_idle def update_satellite(self, itr, row, sat): if self._main_model.iter_has_child(itr): children = row.iterchildren() for ch in children: self._main_model.remove(ch.iter) for tr in sat[3]: self._main_model.append(itr, ["Transponder:", *tr, None, None]) def append_output(self): @run_idle def append(t): append_text_to_tview(t, self._text_view) while True: text = yield append(text) def on_cancel_receive(self, item=None): self._download_task = False def on_selected_toggled(self, toggle, path): model = self._sat_view.get_model() self.update_state(model, path, not toggle.get_active()) self.update_receive_button_state(self._filter_model) @run_idle def update_receive_button_state(self, model): self._receive_button.set_sensitive((any(r[4] for r in model))) @run_idle def show_info_message(self, text, message_type): self._sat_update_info_bar.set_visible(True) self._sat_update_info_bar.set_message_type(message_type) self._info_bar_message_label.set_text(text) def on_info_bar_close(self, bar=None, resp=None): self._sat_update_info_bar.set_visible(False) def on_find_toggled(self, button: Gtk.ToggleToolButton): self._search_bar.set_search_mode(button.get_active()) def on_filter_toggled(self, button: Gtk.ToggleToolButton): self._filter_bar.set_search_mode(button.get_active()) @run_idle def on_filter(self, item): self._filter_positions = self.get_positions() self._filter_model.refilter() def filter_function(self, model, iter, data): if self._filter_model is None or self._filter_model == "None": return True from_pos, to_pos = self._filter_positions if from_pos == 0 and to_pos == 0: return True if from_pos > to_pos: from_pos, to_pos = to_pos, from_pos return from_pos <= float( self._parser.get_position(model.get(iter, 1)[0])) <= to_pos def get_positions(self): from_pos = round(self._from_pos_button.get_value(), 1) * ( -1 if self._filter_from_combo_box.get_active() else 1) to_pos = round(self._to_pos_button.get_value(), 1) * ( -1 if self._filter_to_combo_box.get_active() else 1) return from_pos, to_pos def on_search(self, entry): self._search_provider.search(entry.get_text()) def on_search_down(self, item): self._search_provider.on_search_down() def on_search_up(self, item): self._search_provider.on_search_up() def on_select_all(self, view): self.update_selection(view, True) def on_unselect_all(self, view): self.update_selection(view, False) def update_selection(self, view, select): model = view.get_model() view.get_model().foreach( lambda mod, path, itr: self.update_state(model, path, select)) self.update_receive_button_state(self._filter_model) def update_state(self, model, path, select): """ Updates checkbox state by given path in the list """ itr = self._filter_model.convert_iter_to_child_iter( model.convert_iter_to_child_iter(model.get_iter(path))) self._filter_model.get_model().set_value(itr, 4, select) def on_quit(self, window, event): self._download_task = False