예제 #1
0
 def get_bpw_for_planet(self, planet_id: int, typ: str='') -> BuildProgressWidget:
     if typ == '':
         if planet_id in self.bp_widgets:
             return self.bp_widgets[planet_id]
         # create BPW for planet
         bpw = BuildProgressWidget(self)
         bpw.requestCancelBuildWithPlanet.connect(self.on_request_build_cancel_with_planet)
         self._gb_builds.addWidget(bpw)
         self.bp_widgets[planet_id] = bpw
         bpw.hide()
         return bpw
     elif typ == BuildProgressWidget.BPW_TYPE_SHIPYARD:
         if planet_id in self.bp_widgets_sy:
             return self.bp_widgets_sy[planet_id]
         # create BPW for planet shipyard
         bpw = BuildProgressWidget(self)
         bpw.requestCancelBuildWithPlanet.connect(self.on_request_build_cancel_with_planet)
         self._gb_shipyard.addWidget(bpw)
         self.bp_widgets_sy[planet_id] = bpw
         bpw.hide()
         return bpw
     elif typ == BuildProgressWidget.BPW_TYPE_RESEARCH:
         if planet_id in self.bp_widgets_res:
             return self.bp_widgets_res[planet_id]
         # create BPW for planet shipyard
         bpw = BuildProgressWidget(self)
         bpw.requestCancelBuildWithPlanet.connect(self.on_request_build_cancel_with_planet)
         self._gb_research.addWidget(bpw)
         self.bp_widgets_res[planet_id] = bpw
         bpw.hide()
         return bpw
     else:
         logger.error('get_bpw_for_planet(): unknown typre requested: {0}'.format(typ))
예제 #2
0
 def get_bpw_for_planet(self,
                        planet_id: int,
                        typ: str = '') -> BuildProgressWidget:
     if typ == '':
         if planet_id in self.bp_widgets:
             return self.bp_widgets[planet_id]
         # create BPW for planet
         bpw = BuildProgressWidget(self)
         bpw.requestCancelBuildWithPlanet.connect(
             self.on_request_build_cancel_with_planet)
         self._gb_builds.addWidget(bpw)
         self.bp_widgets[planet_id] = bpw
         bpw.hide()
         return bpw
     elif typ == BuildProgressWidget.BPW_TYPE_SHIPYARD:
         if planet_id in self.bp_widgets_sy:
             return self.bp_widgets_sy[planet_id]
         # create BPW for planet shipyard
         bpw = BuildProgressWidget(self)
         bpw.requestCancelBuildWithPlanet.connect(
             self.on_request_build_cancel_with_planet)
         self._gb_shipyard.addWidget(bpw)
         self.bp_widgets_sy[planet_id] = bpw
         bpw.hide()
         return bpw
     elif typ == BuildProgressWidget.BPW_TYPE_RESEARCH:
         if planet_id in self.bp_widgets_res:
             return self.bp_widgets_res[planet_id]
         # create BPW for planet shipyard
         bpw = BuildProgressWidget(self)
         bpw.requestCancelBuildWithPlanet.connect(
             self.on_request_build_cancel_with_planet)
         self._gb_research.addWidget(bpw)
         self.bp_widgets_res[planet_id] = bpw
         bpw.hide()
         return bpw
     else:
         logger.error(
             'get_bpw_for_planet(): unknown typre requested: {0}'.format(
                 typ))
예제 #3
0
 def __init__(self, parent: QWidget):
     super(PlanetWidget, self).__init__(parent)
     #
     self.world = XNovaWorld_instance()
     self._planet = XNPlanet()
     # setup frame
     self.setFrameShape(QFrame.StyledPanel)
     self.setFrameShadow(QFrame.Raised)
     # layout
     self._layout = QVBoxLayout()
     self._layout.setContentsMargins(0, 0, 0, 0)
     self._layout.setSpacing(3)
     self.setLayout(self._layout)
     # basic info panel
     self._bipanel = Planet_BasicInfoPanel(self)
     self._bipanel.requestOpenGalaxy.connect(self.on_request_open_galaxy)
     self._bipanel.requestRefreshPlanet.connect(
         self.on_request_refresh_planet)
     self._bipanel.requestRenamePlanet.connect(
         self.on_request_rename_planet)
     # build progress widgets
     self._bpw_buildings = BuildProgressWidget(self)
     self._bpw_buildings.hide()
     self._bpw_buildings.hide_planet_name()
     self._bpw_buildings.layout().setContentsMargins(5, 2, 5, 2)
     self._bpw_shipyard = BuildProgressWidget(self)
     self._bpw_shipyard.hide()
     self._bpw_shipyard.hide_planet_name()
     self._bpw_shipyard.layout().setContentsMargins(5, 2, 5, 2)
     self._bpw_research = BuildProgressWidget(self)
     self._bpw_research.hide()
     self._bpw_research.hide_planet_name()
     self._bpw_research.layout().setContentsMargins(5, 2, 5, 2)
     # buildings
     self._cf_buildings = CollapsibleFrame(self)
     self._cf_buildings.setTitle(self.tr('Buildings'))
     self._sa_buildings = QScrollArea(self._cf_buildings)
     self._bip_buildings = Planet_BuildItemsPanel(self._sa_buildings)
     self._bip_buildings.set_type(Planet_BuildItemsPanel.TYPE_BUILDINGS)
     self._bip_buildings.show()
     self._sa_buildings.setWidget(self._bip_buildings)
     self._cf_buildings.addWidget(self._sa_buildings)
     # shipyard
     self._cf_shipyard = CollapsibleFrame(self)
     self._cf_shipyard.setTitle(self.tr('Shipyard'))
     self._sa_shipyard = QScrollArea(self._cf_shipyard)
     self._bip_shipyard = Planet_BuildItemsPanel(self._cf_shipyard)
     self._bip_shipyard.set_type(Planet_BuildItemsPanel.TYPE_SHIPYARD)
     self._sa_shipyard.setWidget(self._bip_shipyard)
     self._cf_shipyard.addWidget(self._sa_shipyard)
     # research
     self._cf_research = CollapsibleFrame(self)
     self._cf_research.setTitle(self.tr('Research'))
     self._sa_research = QScrollArea(self._cf_research)
     self._bip_research = Planet_BuildItemsPanel(self._cf_research)
     self._bip_research.set_type(Planet_BuildItemsPanel.TYPE_RESEARCHES)
     self._sa_research.setWidget(self._bip_research)
     self._cf_research.addWidget(self._sa_research)
     # layout finalize
     self._layout.addWidget(self._bipanel)
     self._layout.addWidget(self._bpw_buildings)
     self._layout.addWidget(self._bpw_shipyard)
     self._layout.addWidget(self._bpw_research)
     self._layout.addWidget(self._cf_buildings)
     self._layout.addWidget(self._cf_shipyard)
     self._layout.addWidget(self._cf_research)
     # expand buildings frame by default
     self._cf_buildings.expand()
     #
     # connect signals
     self._cf_buildings.expanded.connect(self.on_frame_buildings_expanded)
     self._cf_buildings.collapsed.connect(self.on_frame_buildings_collapsed)
     self._cf_shipyard.expanded.connect(self.on_frame_shipyard_expanded)
     self._cf_shipyard.collapsed.connect(self.on_frame_shipyard_collapsed)
     self._cf_research.expanded.connect(self.on_frame_research_expanded)
     self._cf_research.collapsed.connect(self.on_frame_research_collapsed)
     #
     self._bpw_buildings.requestCancelBuild.connect(
         self.on_request_cancel_build)
     self._bpw_research.requestCancelBuild.connect(
         self.on_request_cancel_build)
     #
     self._bip_buildings.requestBuildItem.connect(
         self.on_request_build_item)
     self._bip_buildings.requestDowngradeItem.connect(
         self.on_request_downgrade_item)
     self._bip_shipyard.requestBuildItem.connect(self.on_request_build_item)
     self._bip_research.requestBuildItem.connect(self.on_request_build_item)
     #
     # create timer
     self._timer = QTimer(self)
     self._timer.timeout.connect(self.on_timer)
예제 #4
0
class PlanetWidget(QFrame):
    """
    Provides view of galaxy/solarsystem contents as table widget
    """

    requestOpenGalaxy = pyqtSignal(XNCoords)

    def __init__(self, parent: QWidget):
        super(PlanetWidget, self).__init__(parent)
        #
        self.world = XNovaWorld_instance()
        self._planet = XNPlanet()
        # setup frame
        self.setFrameShape(QFrame.StyledPanel)
        self.setFrameShadow(QFrame.Raised)
        # layout
        self._layout = QVBoxLayout()
        self._layout.setContentsMargins(0, 0, 0, 0)
        self._layout.setSpacing(3)
        self.setLayout(self._layout)
        # basic info panel
        self._bipanel = Planet_BasicInfoPanel(self)
        self._bipanel.requestOpenGalaxy.connect(self.on_request_open_galaxy)
        self._bipanel.requestRefreshPlanet.connect(
            self.on_request_refresh_planet)
        self._bipanel.requestRenamePlanet.connect(
            self.on_request_rename_planet)
        # build progress widgets
        self._bpw_buildings = BuildProgressWidget(self)
        self._bpw_buildings.hide()
        self._bpw_buildings.hide_planet_name()
        self._bpw_buildings.layout().setContentsMargins(5, 2, 5, 2)
        self._bpw_shipyard = BuildProgressWidget(self)
        self._bpw_shipyard.hide()
        self._bpw_shipyard.hide_planet_name()
        self._bpw_shipyard.layout().setContentsMargins(5, 2, 5, 2)
        self._bpw_research = BuildProgressWidget(self)
        self._bpw_research.hide()
        self._bpw_research.hide_planet_name()
        self._bpw_research.layout().setContentsMargins(5, 2, 5, 2)
        # buildings
        self._cf_buildings = CollapsibleFrame(self)
        self._cf_buildings.setTitle(self.tr('Buildings'))
        self._sa_buildings = QScrollArea(self._cf_buildings)
        self._bip_buildings = Planet_BuildItemsPanel(self._sa_buildings)
        self._bip_buildings.set_type(Planet_BuildItemsPanel.TYPE_BUILDINGS)
        self._bip_buildings.show()
        self._sa_buildings.setWidget(self._bip_buildings)
        self._cf_buildings.addWidget(self._sa_buildings)
        # shipyard
        self._cf_shipyard = CollapsibleFrame(self)
        self._cf_shipyard.setTitle(self.tr('Shipyard'))
        self._sa_shipyard = QScrollArea(self._cf_shipyard)
        self._bip_shipyard = Planet_BuildItemsPanel(self._cf_shipyard)
        self._bip_shipyard.set_type(Planet_BuildItemsPanel.TYPE_SHIPYARD)
        self._sa_shipyard.setWidget(self._bip_shipyard)
        self._cf_shipyard.addWidget(self._sa_shipyard)
        # research
        self._cf_research = CollapsibleFrame(self)
        self._cf_research.setTitle(self.tr('Research'))
        self._sa_research = QScrollArea(self._cf_research)
        self._bip_research = Planet_BuildItemsPanel(self._cf_research)
        self._bip_research.set_type(Planet_BuildItemsPanel.TYPE_RESEARCHES)
        self._sa_research.setWidget(self._bip_research)
        self._cf_research.addWidget(self._sa_research)
        # layout finalize
        self._layout.addWidget(self._bipanel)
        self._layout.addWidget(self._bpw_buildings)
        self._layout.addWidget(self._bpw_shipyard)
        self._layout.addWidget(self._bpw_research)
        self._layout.addWidget(self._cf_buildings)
        self._layout.addWidget(self._cf_shipyard)
        self._layout.addWidget(self._cf_research)
        # expand buildings frame by default
        self._cf_buildings.expand()
        #
        # connect signals
        self._cf_buildings.expanded.connect(self.on_frame_buildings_expanded)
        self._cf_buildings.collapsed.connect(self.on_frame_buildings_collapsed)
        self._cf_shipyard.expanded.connect(self.on_frame_shipyard_expanded)
        self._cf_shipyard.collapsed.connect(self.on_frame_shipyard_collapsed)
        self._cf_research.expanded.connect(self.on_frame_research_expanded)
        self._cf_research.collapsed.connect(self.on_frame_research_collapsed)
        #
        self._bpw_buildings.requestCancelBuild.connect(
            self.on_request_cancel_build)
        self._bpw_research.requestCancelBuild.connect(
            self.on_request_cancel_build)
        #
        self._bip_buildings.requestBuildItem.connect(
            self.on_request_build_item)
        self._bip_buildings.requestDowngradeItem.connect(
            self.on_request_downgrade_item)
        self._bip_shipyard.requestBuildItem.connect(self.on_request_build_item)
        self._bip_research.requestBuildItem.connect(self.on_request_build_item)
        #
        # create timer
        self._timer = QTimer(self)
        self._timer.timeout.connect(self.on_timer)

    def get_tab_type(self) -> str:
        return 'planet'

    def setPlanet(self, planet: XNPlanet):
        self._planet = planet
        # setup basic info panel
        self._bipanel.setup_from_planet(self._planet)
        # setup build progress widgets
        self._bpw_buildings.update_from_planet(planet, typ='')
        self._bpw_shipyard.update_from_planet(
            planet, typ=BuildProgressWidget.BPW_TYPE_SHIPYARD)
        self._bpw_research.update_from_planet(
            planet, typ=BuildProgressWidget.BPW_TYPE_RESEARCH)
        # setup build items panels (in collapsible frames)
        self._bip_buildings.set_planet(planet)
        self._bip_shipyard.set_planet(planet)
        self._bip_research.set_planet(planet)
        #
        # start/restart timer
        self._timer.stop()
        self._timer.setInterval(1000)
        self._timer.setSingleShot(False)
        self._timer.start()

    def planet(self) -> XNPlanet:
        return self._planet

    @pyqtSlot()
    def on_timer(self):
        # update basic info panel - refresh resources
        self._bipanel.update_resources()
        # update build progress widgets - tick builds
        self._bpw_buildings.update_from_planet(self._planet)
        self._bpw_shipyard.update_from_planet(
            self._planet, BuildProgressWidget.BPW_TYPE_SHIPYARD)
        self._bpw_research.update_from_planet(
            self._planet, BuildProgressWidget.BPW_TYPE_RESEARCH)

    @pyqtSlot(XNCoords)
    def on_request_open_galaxy(self, coords: XNCoords):
        self.requestOpenGalaxy.emit(coords)

    @pyqtSlot()
    def on_request_refresh_planet(self):
        self.world.signal(self.world.SIGNAL_RELOAD_PLANET,
                          planet_id=self._planet.planet_id)

    @pyqtSlot(int, str)
    def on_request_rename_planet(self, planet_id: int, planet_name: str):
        self.world.signal(self.world.SIGNAL_RENAME_PLANET,
                          planet_id=planet_id,
                          new_name=planet_name)

    @pyqtSlot(XNPlanetBuildingItem)
    def on_request_cancel_build(self, bitem: XNPlanetBuildingItem):
        if bitem is None:
            return
        if (bitem.remove_link is None) or (bitem.remove_link == ''):
            return
        self.world.signal(XNovaWorld.SIGNAL_BUILD_CANCEL,
                          planet_id=self._planet.planet_id,
                          bitem=bitem)

    @pyqtSlot(XNPlanetBuildingItem, int)
    def on_request_build_item(self, bitem: XNPlanetBuildingItem,
                              quantity: int):
        if bitem is None:
            return
        self.world.signal(XNovaWorld.SIGNAL_BUILD_ITEM,
                          planet_id=self._planet.planet_id,
                          bitem=bitem,
                          quantity=quantity)

    @pyqtSlot(XNPlanetBuildingItem)
    def on_request_downgrade_item(self, bitem: XNPlanetBuildingItem):
        if bitem is None:
            return
        if not bitem.is_building_item:
            logger.warn('Cannot dismantle item that is '
                        'not building: {0}'.format(bitem))
            return
        downgrade_price = '{0} {3},  {1} {4},  {2} {5}'.format(
            self.tr('Metal'), self.tr('Crystal'), self.tr('Deit'),
            int(bitem.cost_met // 2), int(bitem.cost_cry // 2),
            int(bitem.cost_deit // 2))
        btn = QMessageBox.question(
            self, self.tr('Downgrade building'),
            self.tr('Are you sure you want to downgrade this building?') +
            '\n' + '{0} {1} {2}\n{3}: {4}'.format(
                bitem.name, self.tr('lv.'), bitem.level, self.tr('Cost'),
                downgrade_price), QMessageBox.Yes | QMessageBox.No)
        if btn == QMessageBox.Yes:
            self.world.signal(XNovaWorld.SIGNAL_BUILD_DISMANTLE,
                              planet_id=self._planet.planet_id,
                              bitem=bitem)

    @pyqtSlot()
    def on_frame_buildings_collapsed(self):
        pass

    @pyqtSlot()
    def on_frame_buildings_expanded(self):
        # collapse other frames
        self._cf_shipyard.collapse()
        self._cf_research.collapse()

    @pyqtSlot()
    def on_frame_shipyard_collapsed(self):
        pass

    @pyqtSlot()
    def on_frame_shipyard_expanded(self):
        # collapse other frames
        self._cf_buildings.collapse()
        self._cf_research.collapse()

    @pyqtSlot()
    def on_frame_research_collapsed(self):
        pass

    @pyqtSlot()
    def on_frame_research_expanded(self):
        # collapse other frames
        self._cf_buildings.collapse()
        self._cf_shipyard.collapse()
예제 #5
0
 def __init__(self, parent: QWidget):
     super(PlanetWidget, self).__init__(parent)
     #
     self.world = XNovaWorld_instance()
     self._planet = XNPlanet()
     # setup frame
     self.setFrameShape(QFrame.StyledPanel)
     self.setFrameShadow(QFrame.Raised)
     # layout
     self._layout = QVBoxLayout()
     self._layout.setContentsMargins(0, 0, 0, 0)
     self._layout.setSpacing(3)
     self.setLayout(self._layout)
     # basic info panel
     self._bipanel = Planet_BasicInfoPanel(self)
     self._bipanel.requestOpenGalaxy.connect(self.on_request_open_galaxy)
     self._bipanel.requestRefreshPlanet.connect(
             self.on_request_refresh_planet)
     self._bipanel.requestRenamePlanet.connect(self.on_request_rename_planet)
     # build progress widgets
     self._bpw_buildings = BuildProgressWidget(self)
     self._bpw_buildings.hide()
     self._bpw_buildings.hide_planet_name()
     self._bpw_buildings.layout().setContentsMargins(5, 2, 5, 2)
     self._bpw_shipyard = BuildProgressWidget(self)
     self._bpw_shipyard.hide()
     self._bpw_shipyard.hide_planet_name()
     self._bpw_shipyard.layout().setContentsMargins(5, 2, 5, 2)
     self._bpw_research = BuildProgressWidget(self)
     self._bpw_research.hide()
     self._bpw_research.hide_planet_name()
     self._bpw_research.layout().setContentsMargins(5, 2, 5, 2)
     # buildings
     self._cf_buildings = CollapsibleFrame(self)
     self._cf_buildings.setTitle(self.tr('Buildings'))
     self._sa_buildings = QScrollArea(self._cf_buildings)
     self._bip_buildings = Planet_BuildItemsPanel(self._sa_buildings)
     self._bip_buildings.set_type(Planet_BuildItemsPanel.TYPE_BUILDINGS)
     self._bip_buildings.show()
     self._sa_buildings.setWidget(self._bip_buildings)
     self._cf_buildings.addWidget(self._sa_buildings)
     # shipyard
     self._cf_shipyard = CollapsibleFrame(self)
     self._cf_shipyard.setTitle(self.tr('Shipyard'))
     self._sa_shipyard = QScrollArea(self._cf_shipyard)
     self._bip_shipyard = Planet_BuildItemsPanel(self._cf_shipyard)
     self._bip_shipyard.set_type(Planet_BuildItemsPanel.TYPE_SHIPYARD)
     self._sa_shipyard.setWidget(self._bip_shipyard)
     self._cf_shipyard.addWidget(self._sa_shipyard)
     # research
     self._cf_research = CollapsibleFrame(self)
     self._cf_research.setTitle(self.tr('Research'))
     self._sa_research = QScrollArea(self._cf_research)
     self._bip_research = Planet_BuildItemsPanel(self._cf_research)
     self._bip_research.set_type(Planet_BuildItemsPanel.TYPE_RESEARCHES)
     self._sa_research.setWidget(self._bip_research)
     self._cf_research.addWidget(self._sa_research)
     # layout finalize
     self._layout.addWidget(self._bipanel)
     self._layout.addWidget(self._bpw_buildings)
     self._layout.addWidget(self._bpw_shipyard)
     self._layout.addWidget(self._bpw_research)
     self._layout.addWidget(self._cf_buildings)
     self._layout.addWidget(self._cf_shipyard)
     self._layout.addWidget(self._cf_research)
     # expand buildings frame by default
     self._cf_buildings.expand()
     #
     # connect signals
     self._cf_buildings.expanded.connect(self.on_frame_buildings_expanded)
     self._cf_buildings.collapsed.connect(self.on_frame_buildings_collapsed)
     self._cf_shipyard.expanded.connect(self.on_frame_shipyard_expanded)
     self._cf_shipyard.collapsed.connect(self.on_frame_shipyard_collapsed)
     self._cf_research.expanded.connect(self.on_frame_research_expanded)
     self._cf_research.collapsed.connect(self.on_frame_research_collapsed)
     #
     self._bpw_buildings.requestCancelBuild.connect(
             self.on_request_cancel_build)
     self._bpw_research.requestCancelBuild.connect(
             self.on_request_cancel_build)
     #
     self._bip_buildings.requestBuildItem.connect(self.on_request_build_item)
     self._bip_buildings.requestDowngradeItem.connect(
             self.on_request_downgrade_item)
     self._bip_shipyard.requestBuildItem.connect(self.on_request_build_item)
     self._bip_research.requestBuildItem.connect(self.on_request_build_item)
     #
     # create timer
     self._timer = QTimer(self)
     self._timer.timeout.connect(self.on_timer)
예제 #6
0
class PlanetWidget(QFrame):
    """
    Provides view of galaxy/solarsystem contents as table widget
    """

    requestOpenGalaxy = pyqtSignal(XNCoords)

    def __init__(self, parent: QWidget):
        super(PlanetWidget, self).__init__(parent)
        #
        self.world = XNovaWorld_instance()
        self._planet = XNPlanet()
        # setup frame
        self.setFrameShape(QFrame.StyledPanel)
        self.setFrameShadow(QFrame.Raised)
        # layout
        self._layout = QVBoxLayout()
        self._layout.setContentsMargins(0, 0, 0, 0)
        self._layout.setSpacing(3)
        self.setLayout(self._layout)
        # basic info panel
        self._bipanel = Planet_BasicInfoPanel(self)
        self._bipanel.requestOpenGalaxy.connect(self.on_request_open_galaxy)
        self._bipanel.requestRefreshPlanet.connect(
                self.on_request_refresh_planet)
        self._bipanel.requestRenamePlanet.connect(self.on_request_rename_planet)
        # build progress widgets
        self._bpw_buildings = BuildProgressWidget(self)
        self._bpw_buildings.hide()
        self._bpw_buildings.hide_planet_name()
        self._bpw_buildings.layout().setContentsMargins(5, 2, 5, 2)
        self._bpw_shipyard = BuildProgressWidget(self)
        self._bpw_shipyard.hide()
        self._bpw_shipyard.hide_planet_name()
        self._bpw_shipyard.layout().setContentsMargins(5, 2, 5, 2)
        self._bpw_research = BuildProgressWidget(self)
        self._bpw_research.hide()
        self._bpw_research.hide_planet_name()
        self._bpw_research.layout().setContentsMargins(5, 2, 5, 2)
        # buildings
        self._cf_buildings = CollapsibleFrame(self)
        self._cf_buildings.setTitle(self.tr('Buildings'))
        self._sa_buildings = QScrollArea(self._cf_buildings)
        self._bip_buildings = Planet_BuildItemsPanel(self._sa_buildings)
        self._bip_buildings.set_type(Planet_BuildItemsPanel.TYPE_BUILDINGS)
        self._bip_buildings.show()
        self._sa_buildings.setWidget(self._bip_buildings)
        self._cf_buildings.addWidget(self._sa_buildings)
        # shipyard
        self._cf_shipyard = CollapsibleFrame(self)
        self._cf_shipyard.setTitle(self.tr('Shipyard'))
        self._sa_shipyard = QScrollArea(self._cf_shipyard)
        self._bip_shipyard = Planet_BuildItemsPanel(self._cf_shipyard)
        self._bip_shipyard.set_type(Planet_BuildItemsPanel.TYPE_SHIPYARD)
        self._sa_shipyard.setWidget(self._bip_shipyard)
        self._cf_shipyard.addWidget(self._sa_shipyard)
        # research
        self._cf_research = CollapsibleFrame(self)
        self._cf_research.setTitle(self.tr('Research'))
        self._sa_research = QScrollArea(self._cf_research)
        self._bip_research = Planet_BuildItemsPanel(self._cf_research)
        self._bip_research.set_type(Planet_BuildItemsPanel.TYPE_RESEARCHES)
        self._sa_research.setWidget(self._bip_research)
        self._cf_research.addWidget(self._sa_research)
        # layout finalize
        self._layout.addWidget(self._bipanel)
        self._layout.addWidget(self._bpw_buildings)
        self._layout.addWidget(self._bpw_shipyard)
        self._layout.addWidget(self._bpw_research)
        self._layout.addWidget(self._cf_buildings)
        self._layout.addWidget(self._cf_shipyard)
        self._layout.addWidget(self._cf_research)
        # expand buildings frame by default
        self._cf_buildings.expand()
        #
        # connect signals
        self._cf_buildings.expanded.connect(self.on_frame_buildings_expanded)
        self._cf_buildings.collapsed.connect(self.on_frame_buildings_collapsed)
        self._cf_shipyard.expanded.connect(self.on_frame_shipyard_expanded)
        self._cf_shipyard.collapsed.connect(self.on_frame_shipyard_collapsed)
        self._cf_research.expanded.connect(self.on_frame_research_expanded)
        self._cf_research.collapsed.connect(self.on_frame_research_collapsed)
        #
        self._bpw_buildings.requestCancelBuild.connect(
                self.on_request_cancel_build)
        self._bpw_research.requestCancelBuild.connect(
                self.on_request_cancel_build)
        #
        self._bip_buildings.requestBuildItem.connect(self.on_request_build_item)
        self._bip_buildings.requestDowngradeItem.connect(
                self.on_request_downgrade_item)
        self._bip_shipyard.requestBuildItem.connect(self.on_request_build_item)
        self._bip_research.requestBuildItem.connect(self.on_request_build_item)
        #
        # create timer
        self._timer = QTimer(self)
        self._timer.timeout.connect(self.on_timer)

    def get_tab_type(self) -> str:
        return 'planet'

    def setPlanet(self, planet: XNPlanet):
        self._planet = planet
        # setup basic info panel
        self._bipanel.setup_from_planet(self._planet)
        # setup build progress widgets
        self._bpw_buildings.update_from_planet(planet, typ='')
        self._bpw_shipyard.update_from_planet(planet,
                typ=BuildProgressWidget.BPW_TYPE_SHIPYARD)
        self._bpw_research.update_from_planet(planet,
                typ=BuildProgressWidget.BPW_TYPE_RESEARCH)
        # setup build items panels (in collapsible frames)
        self._bip_buildings.set_planet(planet)
        self._bip_shipyard.set_planet(planet)
        self._bip_research.set_planet(planet)
        #
        # start/restart timer
        self._timer.stop()
        self._timer.setInterval(1000)
        self._timer.setSingleShot(False)
        self._timer.start()

    def planet(self) -> XNPlanet:
        return self._planet

    @pyqtSlot()
    def on_timer(self):
        # update basic info panel - refresh resources
        self._bipanel.update_resources()
        # update build progress widgets - tick builds
        self._bpw_buildings.update_from_planet(self._planet)
        self._bpw_shipyard.update_from_planet(self._planet,
                BuildProgressWidget.BPW_TYPE_SHIPYARD)
        self._bpw_research.update_from_planet(self._planet,
                BuildProgressWidget.BPW_TYPE_RESEARCH)

    @pyqtSlot(XNCoords)
    def on_request_open_galaxy(self, coords: XNCoords):
        self.requestOpenGalaxy.emit(coords)

    @pyqtSlot()
    def on_request_refresh_planet(self):
        self.world.signal(self.world.SIGNAL_RELOAD_PLANET,
                planet_id=self._planet.planet_id)

    @pyqtSlot(int, str)
    def on_request_rename_planet(self, planet_id: int, planet_name: str):
        self.world.signal(self.world.SIGNAL_RENAME_PLANET,
                planet_id=planet_id, new_name=planet_name)

    @pyqtSlot(XNPlanetBuildingItem)
    def on_request_cancel_build(self, bitem: XNPlanetBuildingItem):
        if bitem is None:
            return
        if (bitem.remove_link is None) or (bitem.remove_link == ''):
            return
        self.world.signal(XNovaWorld.SIGNAL_BUILD_CANCEL,
                          planet_id=self._planet.planet_id,
                          bitem=bitem)

    @pyqtSlot(XNPlanetBuildingItem, int)
    def on_request_build_item(self, bitem: XNPlanetBuildingItem,
                              quantity: int):
        if bitem is None:
            return
        self.world.signal(XNovaWorld.SIGNAL_BUILD_ITEM,
                          planet_id=self._planet.planet_id,
                          bitem=bitem,
                          quantity=quantity)

    @pyqtSlot(XNPlanetBuildingItem)
    def on_request_downgrade_item(self, bitem: XNPlanetBuildingItem):
        if bitem is None:
            return
        if not bitem.is_building_item:
            logger.warn('Cannot dismantle item that is '
                    'not building: {0}'.format(bitem))
            return
        downgrade_price = '{0} {3},  {1} {4},  {2} {5}'.format(
                self.tr('Metal'), self.tr('Crystal'), self.tr('Deit'),
                int(bitem.cost_met//2),
                int(bitem.cost_cry // 2),
                int(bitem.cost_deit // 2))
        btn = QMessageBox.question(self,
                self.tr('Downgrade building'),
                self.tr('Are you sure you want to downgrade this building?')
                        + '\n' + '{0} {1} {2}\n{3}: {4}'.format(
                        bitem.name,
                        self.tr('lv.'),
                        bitem.level,
                        self.tr('Cost'),
                        downgrade_price),
                QMessageBox.Yes | QMessageBox.No)
        if btn == QMessageBox.Yes:
            self.world.signal(XNovaWorld.SIGNAL_BUILD_DISMANTLE,
                              planet_id=self._planet.planet_id,
                              bitem=bitem)

    @pyqtSlot()
    def on_frame_buildings_collapsed(self):
        pass

    @pyqtSlot()
    def on_frame_buildings_expanded(self):
        # collapse other frames
        self._cf_shipyard.collapse()
        self._cf_research.collapse()

    @pyqtSlot()
    def on_frame_shipyard_collapsed(self):
        pass

    @pyqtSlot()
    def on_frame_shipyard_expanded(self):
        # collapse other frames
        self._cf_buildings.collapse()
        self._cf_research.collapse()

    @pyqtSlot()
    def on_frame_research_collapsed(self):
        pass

    @pyqtSlot()
    def on_frame_research_expanded(self):
        # collapse other frames
        self._cf_buildings.collapse()
        self._cf_shipyard.collapse()