class FlightsWidget(QWidget): requestShowSettings = pyqtSignal() requestShowMessages = pyqtSignal() def __init__(self, parent=None): super(FlightsWidget, self).__init__(parent) # state vars self.uifile = 'ui/flights_widget.ui' # objects, sub-windows self.ui = None self._btn_newmsg = ButtonTextOverIcon(self) self._btn_settings = QPushButton(self) # world reference self.world = XNovaWorld_instance() # columns indexes self.COL_TIME = 0 self.COL_MISSION = 1 self.COL_FROM = 2 self.COL_TO = 3 self.COL_PLAYER = 4 self.COL_SHIPS_RES = 5 def load_ui(self): self.ui = uic.loadUi(self.uifile, self) # new messages button self._btn_newmsg.setText('') self._btn_newmsg.setIcon(QIcon(':/i/message.png')) self._btn_newmsg.setIconSize(QSize(24, 16)) self._btn_newmsg.setMinimumSize(QSize(30, 22)) self._btn_newmsg.setMaximumSize(QSize(30, 22)) self.ui.horizontalLayout.insertWidget(0, self._btn_newmsg, 0) # settings button self._btn_settings.setText('') self._btn_settings.setIcon(QIcon(':/i/settings_32.png')) self._btn_settings.setIconSize(QSize(16, 16)) self._btn_settings.setMaximumWidth(32) self._btn_settings.clicked.connect(self.on_btn_settings) self.ui.horizontalLayout.addWidget(self._btn_settings, 0) # configure table widget self.ui.tw_flights.setColumnCount(6) self.ui.tw_flights.setRowCount(0) # timer | mission | src | dst | ships (res) self.ui.tw_flights.setHorizontalHeaderLabels([ self.tr('Timer'), self.tr('Mission'), self.tr('From'), self.tr('To'), self.tr('Player'), self.tr('Ships/Res')]) self.ui.tw_flights.setColumnWidth(self.COL_TIME, 120) self.ui.tw_flights.setColumnWidth(self.COL_MISSION, 90) self.ui.tw_flights.setColumnWidth(self.COL_FROM, 120) self.ui.tw_flights.setColumnWidth(self.COL_TO, 120) self.ui.tw_flights.setColumnWidth(self.COL_PLAYER, 100) self.ui.tw_flights.setColumnWidth(self.COL_SHIPS_RES, 350) # wider, wider self.ui.tw_flights.hide() # connections self.btn_show.clicked.connect(self.on_showhide_fleets) self._btn_newmsg.clicked.connect(self.on_messages_clicked) def set_online_state(self, st: bool = True): self._btn_newmsg.setEnabled(st) self.ui.btn_show.setEnabled(st) #def minimize_height(self): # print(self.parent()) # num_rows = self.ui.tw_flights.rowCount() # total_heights = 0 # for i in range(num_rows): # total_heights += self.ui.tw_flights.rowHeight(i) # if total_heights < 10: # total_heights = 10 # # add vertical header height # header_view = self.ui.tw_flights.verticalHeader() # if header_view is not None: # total_heights += header_view.height() # self.ui.tw_flights.setMaximumHeight(total_heights) @pyqtSlot() def on_showhide_fleets(self): if self.ui.tw_flights.isVisible(): self.ui.tw_flights.hide() self.setMinimumHeight(22) self.parent().setMinimumHeight(22) self.btn_show.setArrowType(Qt.RightArrow) else: self.ui.tw_flights.show() base_h = 22 + 22 grow_h = 100 self.setMinimumHeight(base_h + grow_h) self.parent().setMinimumHeight(base_h + grow_h + 1) self.btn_show.setArrowType(Qt.DownArrow) # self.minimize_height() self.update_button_fleet_count() def update_button_fleet_count(self): flights = self.world.get_flights() flights_cnt = self.world.get_fleets_count() # fleets_count_str = '{0} / {1}'.format(flights_cnt[0], flights_cnt[1]) # if self.ui.tw_flights.isVisible(): self.ui.btn_show.setText(self.tr('Fleets: {0}').format(fleets_count_str)) else: closest_fleet_str = '' if len(flights) > 0: fl = flights[0] secs = self.world.get_flight_remaining_time_secs(fl) if secs == -1: # ignore, this should not happen but possible secs = 0 hours = secs // 3600 secs -= (hours * 3600) minutes = secs // 60 secs -= (minutes * 60) return_str = self.tr(' (return)') if fl.direction == 'return' else '' closest_fleet_str = self.tr('{0:02}:{1:02}:{2:02} ||| {3}{4}: {5} => {6}, {7} ship(s)').format( hours, minutes, secs, flight_mission_for_humans(fl.mission), return_str, fl.src, fl.dst, len(fl.ships)) self.ui.btn_show.setText(self.tr('Fleets: {0} ||| {1}').format( fleets_count_str, closest_fleet_str)) def update_new_messages_count(self): nmc = self.world.get_new_messages_count() txt = '' if nmc > 0: txt = str(nmc) self._btn_newmsg.setText(txt) self._btn_newmsg.update() @staticmethod def _get_flight_bgcolor(fl: XNFlight) -> QColor: ret = QColor(255, 255, 255) mis = fl.mission if mis == 'ownharvest': ret = QColor(255, 255, 200) elif mis == 'owndeploy': ret = QColor(200, 200, 255) elif mis == 'ownattack': ret = QColor(255, 200, 230) elif mis == 'owntransport': ret = QColor(200, 255, 200) elif mis == 'ownespionage': ret = QColor(255, 220, 150) elif mis == 'owncolony': ret = QColor(190, 210, 255) elif mis == 'ownmissile': ret = QColor(165, 255, 255) elif mis == 'ownbase': ret = QColor(153, 200, 255) elif mis == 'attack': ret = QColor(255, 230, 230) if fl.direction == 'return': # darken -20% ret.setRed(ret.red() * 0.8) ret.setGreen(ret.green() * 0.8) ret.setBlue(ret.blue() * 0.8) return ret @staticmethod def _get_flight_fgcolor(fl: XNFlight) -> QColor: ret = QColor(0, 0, 0) if fl.mission == 'attack': ret = QColor(200, 0, 0) return ret def _set_twi(self, row, col, text, bg_color=None, fg_color=None): twi = QTableWidgetItem(str(text)) if bg_color is not None: bgb = QBrush(QColor(bg_color), Qt.SolidPattern) twi.setBackground(bgb) if fg_color is not None: fgb = QBrush(QColor(fg_color), Qt.SolidPattern) twi.setForeground(fgb) self.ui.tw_flights.setItem(row, col, twi) def _fl_timer_str(self, fl: XNFlight) -> str: seconds_left = self.world.get_flight_remaining_time_secs(fl) if seconds_left == -1: raise ValueError('Flight seconds left == -1: {0}'.format(str(fl))) hours_left = seconds_left // 3600 seconds_left -= (hours_left * 3600) minutes_left = seconds_left // 60 seconds_left -= (minutes_left * 60) hours_str = '{0:02}:'.format(hours_left) if hours_left > 0 else '' minutes_str = '{0:02}:'.format(minutes_left) if minutes_left > 0 else '' seconds_str = '{0:02}'.format(seconds_left) time_arr_s = str(fl.arrive_datetime) timer_str = '{0}{1}{2}\n{3}'.format(hours_str, minutes_str, seconds_str, time_arr_s) return timer_str def update_flights(self): # clear widget # prev_row = self.ui.tw_flights.currentRow() # prev_col = self.ui.tw_flights.currentColumn() self.ui.tw_flights.setUpdatesEnabled(False) self.ui.tw_flights.clearContents() # self.ui.tw_flights.setRowCount(0) # nope, resets current scroll position # get data flights = self.world.get_flights() self.ui.tw_flights.setRowCount(len(flights)) # iterate irow = 0 for fl in flights: # format data # fleet timer timer_str = self._fl_timer_str(fl) # fleet mission fldir_str = self.tr('\nreturn') if fl.direction == 'return' else '' mis_str_h = flight_mission_for_humans(fl.mission) mis_str = '{0}{1}'.format(mis_str_h, fldir_str) # resources res_str = '' if len(fl.res) > 0: res_str = '\n' + self.tr('Res: {0} m / {1} c {2} d').format( number_format(fl.res.met), number_format(fl.res.cry), number_format(fl.res.deit)) # insert row # timer | mission | src | dst | ships (res) # self.ui.tw_flights.insertRow(irow) self._set_twi(irow, self.COL_TIME, timer_str) self._set_twi(irow, self.COL_MISSION, mis_str, self._get_flight_bgcolor(fl), self._get_flight_fgcolor(fl)) self._set_twi(irow, self.COL_FROM, str(fl.src)) self._set_twi(irow, self.COL_TO, str(fl.dst)) self._set_twi(irow, self.COL_PLAYER, str(fl.enemy_name)) self._set_twi(irow, self.COL_SHIPS_RES, str(fl.ships) + res_str) # self.ui.tw_flights.setRowHeight(irow, 40) irow += 1 self.ui.tw_flights.setUpdatesEnabled(True) # self.ui.tw_flights.setCurrentCell(prev_row, prev_col) self.ui.tw_flights.horizontalHeader().setStretchLastSection(True) self.ui.tw_flights.verticalHeader().resizeSections(QHeaderView.ResizeToContents) # upadte button text self.update_button_fleet_count() self.update_new_messages_count() @pyqtSlot() def on_messages_clicked(self): self.requestShowMessages.emit() @pyqtSlot() def on_btn_settings(self): self.requestShowSettings.emit()