| Total Complexity | 118 |
| Total Lines | 526 |
| Duplicated Lines | 0 % |
| Changes | 0 | ||
Complex classes like osci.dialog.ProblemsDlg often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # |
||
| 2 | # Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/] |
||
| 3 | # |
||
| 4 | # This file is part of Outer Space. |
||
| 5 | # |
||
| 6 | # Outer Space is free software; you can redistribute it and/or modify |
||
| 7 | # it under the terms of the GNU General Public License as published by |
||
| 8 | # the Free Software Foundation; either version 2 of the License, or |
||
| 9 | # (at your option) any later version. |
||
| 10 | # |
||
| 11 | # Outer Space is distributed in the hope that it will be useful, |
||
| 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 14 | # GNU General Public License for more details. |
||
| 15 | # |
||
| 16 | # You should have received a copy of the GNU General Public License |
||
| 17 | # along with Outer Space; if not, write to the Free Software |
||
| 18 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
||
| 19 | # |
||
| 20 | import copy |
||
| 21 | import math |
||
| 22 | import re |
||
| 23 | import string |
||
| 24 | |||
| 25 | import pygameui as ui |
||
| 26 | from osci import gdata, client, res |
||
| 27 | import ige.ospace.Const as Const |
||
| 28 | from ige.ospace import Utils, Rules |
||
| 29 | |||
| 30 | class ProblemsDlg: |
||
| 31 | """Displays 'Problem locator' dialog. |
||
| 32 | |||
| 33 | """ |
||
| 34 | def __init__(self, app): |
||
| 35 | self.app = app |
||
| 36 | self.createUI() |
||
| 37 | |||
| 38 | def display(self): |
||
| 39 | self.show() |
||
| 40 | self.win.show() |
||
| 41 | # register for updates |
||
| 42 | if self not in gdata.updateDlgs: |
||
| 43 | gdata.updateDlgs.append(self) |
||
| 44 | |||
| 45 | def hide(self): |
||
| 46 | self.win.setStatus(_("Ready.")) |
||
| 47 | self.win.hide() |
||
| 48 | # unregister updates |
||
| 49 | if self in gdata.updateDlgs: |
||
| 50 | gdata.updateDlgs.remove(self) |
||
| 51 | |||
| 52 | def update(self): |
||
| 53 | self.show() |
||
| 54 | |||
| 55 | class Problems: |
||
| 56 | def __init__(self, win): |
||
| 57 | self.items = [] |
||
| 58 | self.checkboxes = {gdata.CRI: win.vCritical.checked, |
||
| 59 | gdata.MAJ: win.vMajor.checked, |
||
| 60 | gdata.MIN: win.vMinor.checked, |
||
| 61 | gdata.INFO: win.vInfo.checked} |
||
| 62 | |||
| 63 | def append(self, severity, item): |
||
| 64 | if self.checkboxes[severity]: |
||
| 65 | item.foreground = gdata.sevColors[severity] |
||
| 66 | self.items.append(item) |
||
| 67 | |||
| 68 | def _addProblemsStructStatus(self, problems, struct, planet): |
||
| 69 | player = client.getPlayer() |
||
| 70 | status = struct[Const.STRUCT_IDX_STATUS] |
||
| 71 | tech = client.getFullTechInfo(struct[Const.STRUCT_IDX_TECHID]) |
||
| 72 | |||
| 73 | if hasattr(player, 'techs'): |
||
| 74 | techEff = Rules.techImprEff[player.techs.get(struct[Const.STRUCT_IDX_TECHID], Rules.techBaseImprovement)] |
||
| 75 | else: |
||
| 76 | techEff = Rules.techImprEff[Rules.techBaseImprovement] |
||
| 77 | |||
| 78 | HPturn = max(1, int(0.02 * tech.maxHP * techEff)) |
||
| 79 | turnsToDestroy = math.ceil(struct[Const.STRUCT_IDX_HP] / HPturn) |
||
| 80 | |||
| 81 | if turnsToDestroy < Rules.turnsPerDay * 2: |
||
| 82 | severity = gdata.MAJ |
||
| 83 | if turnsToDestroy < Rules.turnsPerDay: |
||
| 84 | severity = gdata.CRI |
||
| 85 | else: |
||
| 86 | severity = gdata.MIN |
||
| 87 | |||
| 88 | if not status & Const.STRUCT_STATUS_ON: |
||
| 89 | # structure is off |
||
| 90 | problems.append(severity, |
||
| 91 | ui.Item(planet.name, tOID=planet.oid, tType=Const.T_PLANET, |
||
| 92 | vDescription=_('Structure (%s) is off and will be destroyed in %s turns.') % (tech.name, res.formatTime(turnsToDestroy)))) |
||
| 93 | |||
| 94 | if status & Const.STRUCT_STATUS_DETER: |
||
| 95 | problems.append(gdata.MAJ, |
||
| 96 | ui.Item(planet.name, tOID=planet.oid, tType=Const.T_PLANET, |
||
| 97 | vDescription=_('Structure (%s) is deteriorating.') % (tech.name,))) |
||
| 98 | if status & Const.STRUCT_STATUS_NOBIO: |
||
| 99 | problems.append(gdata.INFO, |
||
| 100 | ui.Item(planet.name, tOID=planet.oid, tType=Const.T_PLANET, |
||
| 101 | vDescription=_('Structure (%s) has insufficient supply of biomatter.') % (tech.name,))) |
||
| 102 | if status & Const.STRUCT_STATUS_NOEN: |
||
| 103 | problems.append(gdata.INFO, |
||
| 104 | ui.Item(planet.name, tOID=planet.oid, tType=Const.T_PLANET, |
||
| 105 | vDescription=_('Structure (%s) has insufficient supply of energy.') % (tech.name,))) |
||
| 106 | if status & Const.STRUCT_STATUS_NOPOP: |
||
| 107 | problems.append(gdata.INFO, |
||
| 108 | ui.Item(planet.name, tOID=planet.oid, tType=Const.T_PLANET, |
||
| 109 | vDescription=_('Structure (%s) has insufficient supply of workers.') % (tech.name,))) |
||
| 110 | if status & Const.STRUCT_STATUS_REPAIRING: |
||
| 111 | problems.append(gdata.INFO, |
||
| 112 | ui.Item(planet.name, tOID=planet.oid, tType=Const.T_PLANET, |
||
| 113 | vDescription=_('Structure (%s) is repairing.') % (tech.name,))) |
||
| 114 | |||
| 115 | def _getSystemRefuel(self, system): |
||
| 116 | player = client.getPlayer() |
||
| 117 | maxRefuelMax = 0 |
||
| 118 | hasRefuel = False |
||
| 119 | for planetID in system.planets: |
||
| 120 | planet = client.get(planetID, noUpdate=1) |
||
| 121 | if hasattr(planet, 'owner'): |
||
| 122 | if hasattr(planet, 'hasRefuel'): |
||
| 123 | hasRefuel = hasRefuel or planet.hasRefuel |
||
| 124 | if hasattr(planet, 'refuelMax'): |
||
| 125 | if planet.owner == player.oid: |
||
| 126 | maxRefuelMax = max(maxRefuelMax, planet.refuelMax) |
||
| 127 | elif planet.owner in player.diplomacyRels: |
||
| 128 | dipl = client.getDiplomacyWith(planet.owner) |
||
| 129 | if Const.PACT_ALLOW_TANKING in dipl.pacts and dipl.pacts[Const.PACT_ALLOW_TANKING][0] == Const.PACT_ACTIVE: |
||
| 130 | maxRefuelMax = max(maxRefuelMax, planet.refuelMax) |
||
| 131 | elif hasattr(planet, 'hasRefuel'): |
||
| 132 | maxRefuelMax |
||
| 133 | return hasRefuel, maxRefuelMax |
||
| 134 | |||
| 135 | def _addProblemsFleets(self, problems, fleet): |
||
| 136 | energyReserve = fleet.storEn * 100 / fleet.maxEn |
||
| 137 | system = None |
||
| 138 | |||
| 139 | if hasattr(fleet, 'orbiting') and fleet.orbiting: |
||
| 140 | system = client.get(fleet.orbiting, noUpdate=1) |
||
| 141 | hasRefuel, maxRefuelMax = self._getSystemRefuel(system) |
||
| 142 | else: |
||
| 143 | # we do not report fleets in flight |
||
| 144 | return |
||
| 145 | |||
| 146 | systemName = res.getUnknownName() |
||
| 147 | if system and hasattr(system, "name"): |
||
| 148 | systemName = system.name |
||
| 149 | |||
| 150 | # is fleet named? |
||
| 151 | if hasattr(fleet, 'customname') and fleet.customname: |
||
| 152 | name = fleet.customname |
||
| 153 | else: |
||
| 154 | name = getattr(fleet, "name", None) |
||
| 155 | |||
| 156 | note = _(' and is NOT refueling') |
||
| 157 | if 0 < maxRefuelMax <= energyReserve: |
||
| 158 | severity = gdata.INFO |
||
| 159 | if maxRefuelMax <= energyReserve: |
||
| 160 | note = _(' and CAN refuel, but reached planet maximum refuel amount') |
||
| 161 | else: |
||
| 162 | note = _(' and IS refueling') |
||
| 163 | elif hasRefuel: |
||
| 164 | severity = gdata.MIN |
||
| 165 | note = _(' and utilizes unknown refueling capacities') |
||
| 166 | elif energyReserve < 25: |
||
| 167 | severity = gdata.CRI |
||
| 168 | elif energyReserve < 50: |
||
| 169 | severity = gdata.MAJ |
||
| 170 | elif energyReserve == 100: |
||
| 171 | problems.append(gdata.INFO, |
||
| 172 | ui.Item(systemName, tOID=fleet.oid, tType=Const.T_FLEET, |
||
| 173 | vDescription=_('Fleet "%s" has full fuel tanks.') % (name))) |
||
| 174 | return |
||
| 175 | else: |
||
| 176 | severity = gdata.INFO |
||
| 177 | problems.append(severity, |
||
| 178 | ui.Item(systemName, tOID=fleet.oid, tType=Const.T_FLEET, |
||
| 179 | vDescription=_('Fleet "%s" is low on fuel [%d %%]%s.') % (name, energyReserve, note))) |
||
| 180 | |||
| 181 | def _addProblemsMaterial(self, problems, system, mat, totalMat, material): |
||
| 182 | if mat >= 0: |
||
| 183 | return |
||
| 184 | surplusTurns = totalMat / (-mat) |
||
| 185 | if surplusTurns < Rules.turnsPerDay * 7: |
||
| 186 | severity = gdata.MAJ |
||
| 187 | elif surplusTurns < Rules.turnsPerDay * 2: |
||
| 188 | severity = gdata.CRI |
||
| 189 | else: |
||
| 190 | severity = gdata.MIN |
||
| 191 | |||
| 192 | if totalMat > 0: |
||
| 193 | note = _(' surplus %d (%s)' % (totalMat, res.formatTime(surplusTurns))) |
||
| 194 | else: |
||
| 195 | note = _(' with no surplus left!') |
||
| 196 | problems.append(severity, |
||
| 197 | ui.Item(system.name, tOID=system.oid, tType=Const.T_SYSTEM, |
||
| 198 | vDescription=_('%s decreasing - last turn change %d, %s.') % (material, mat, note))) |
||
| 199 | |||
| 200 | def _getTaskSciValue(self, task): |
||
| 201 | player = client.getPlayer() |
||
| 202 | fulltech = client.getFullTechInfo(task.techID) |
||
| 203 | researchSci = Utils.getTechRCost(player, task.techID, task.improvement) |
||
| 204 | maxImprovement = min(Rules.techMaxImprovement, fulltech.maxImprovement) |
||
| 205 | |||
| 206 | if task.improveToMax: |
||
| 207 | # account next levels |
||
| 208 | for impr in range(task.improvement + 1, maxImprovement + 1): |
||
| 209 | researchSci += Utils.getTechRCost(player, task.techID, impr) |
||
| 210 | return researchSci - task.currSci |
||
| 211 | |||
| 212 | def _addProblemsResearch(self, problems): |
||
| 213 | player = client.getPlayer() |
||
| 214 | sciProd = max(sum(task.changeSci for task in player.rsrchQueue), |
||
| 215 | player.effSciPoints) |
||
| 216 | if sciProd < 0: |
||
| 217 | problems.append(gdata.CRI, |
||
| 218 | ui.Item(_('Research'), tType=Const.T_TECHNOLOGY, |
||
| 219 | vDescription=_('We are losing our researched knowledge by %d pts per turn!') % (sciProd,))) |
||
| 220 | return |
||
| 221 | elif sciProd == 0: |
||
| 222 | return |
||
| 223 | elif len(player.rsrchQueue) == 0: |
||
| 224 | problems.append(gdata.CRI, |
||
| 225 | ui.Item(_('Research'), tType=Const.T_TECHNOLOGY, |
||
| 226 | vDescription=_('Research queue is empty.'))) |
||
| 227 | |||
| 228 | queueValue = sum(self._getTaskSciValue(task) for task in player.rsrchQueue) |
||
| 229 | totalEtc = math.ceil(float(queueValue) / sciProd) |
||
| 230 | |||
| 231 | # check short reseach queue |
||
| 232 | if totalEtc < Rules.turnsPerDay * 2: |
||
| 233 | severity = gdata.MIN |
||
| 234 | if totalEtc < Rules.turnsPerDay: |
||
| 235 | severity = gdata.MAJ |
||
| 236 | problems.append(severity, |
||
| 237 | ui.Item(_('Research'), tType=Const.T_TECHNOLOGY, |
||
| 238 | vDescription=_('Research queue ends in %s turns, %d item(s) on list.') % (res.formatTime(totalEtc), len(player.rsrchQueue)))) |
||
| 239 | |||
| 240 | def _addProblemsGlobalQueues(self, problems): |
||
| 241 | # go through all planets to understand the state of global queues |
||
| 242 | player = client.getPlayer() |
||
| 243 | # holder for (number , eff production) of planets set to each queue |
||
| 244 | globalQueueStats = [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)] |
||
| 245 | queConstValues = [0, 0, 0, 0, 0] |
||
| 246 | queEtc = [0, 0, 0, 0, 0] |
||
| 247 | |||
| 248 | for planetID in player.planets: |
||
| 249 | planet = client.get(planetID, noUpdate=1) |
||
| 250 | globalQueueStats[planet.globalQueue] = tuple([sum(x) for x in zip(globalQueueStats[planet.globalQueue], (1, planet.effProdProd))]) |
||
| 251 | |||
| 252 | # evaluate depletion rate of the global queue |
||
| 253 | for queue in range(5): |
||
| 254 | quePlanets, queEffProd = globalQueueStats[queue] |
||
| 255 | for task in player.prodQueues[queue]: |
||
| 256 | if task.isShip: |
||
| 257 | tech = player.shipDesigns[task.techID] |
||
| 258 | else: |
||
| 259 | tech = client.getFullTechInfo(task.techID) |
||
| 260 | queConstValues[queue] += task.quantity * tech.buildProd |
||
| 261 | if queEffProd > 0: |
||
| 262 | queEtc[queue] = math.ceil(float(queConstValues[queue])/queEffProd) |
||
| 263 | else: |
||
| 264 | queEtc[queue] = 99999 |
||
| 265 | |||
| 266 | # creation of items with global queue problems |
||
| 267 | for queue in range(1, 5): |
||
| 268 | queName = res.globalQueueName(queue) |
||
| 269 | quePlanets = globalQueueStats[queue][0] |
||
| 270 | # check empty global production queue with at least one planet [so its relevant] |
||
| 271 | if queConstValues[queue] == 0 and quePlanets > 0: |
||
| 272 | problems.append(gdata.CRI, |
||
| 273 | ui.Item(_('Global queue ' + queName), tType=Const.T_QUEUE, |
||
| 274 | vDescription=_('Global production queue {0} used by {1} planet(s) is empty.'.format(queName, quePlanets)))) |
||
| 275 | # check end of global production queue |
||
| 276 | elif queEtc[queue] < Rules.turnsPerDay * 2: |
||
| 277 | severity = gdata.MIN |
||
| 278 | if queEtc[queue] < Rules.turnsPerDay: |
||
| 279 | severity = gdata.MAJ |
||
| 280 | problems.append(severity, |
||
| 281 | ui.Item(_('Global queue ' + queName), tType=Const.T_QUEUE, |
||
| 282 | vDescription=_('Global production queue {0} used by {1} planet(s) runs out in {2} turns.'.format(queName, quePlanets, res.formatTime(queEtc[queue]))))) |
||
| 283 | return queEtc[0] # time of depletion of the default queue will be reused later |
||
| 284 | |||
| 285 | def _getTargetSlotDict(self, planetID): |
||
| 286 | assert planetID in client.getPlayer().planets |
||
| 287 | targets = {} |
||
| 288 | planet = client.get(planetID, noUpdate=1) |
||
| 289 | if planet.effProdProd <= 0: |
||
| 290 | return targets |
||
| 291 | |||
| 292 | nonShipTasks = (task for task in planet.prodQueue if not task.isShip) |
||
|
1 ignored issue
–
show
|
|||
| 293 | for task in nonShipTasks: |
||
| 294 | tech = client.getFullTechInfo(task.techID) |
||
| 295 | if tech.isStructure and task.demolishStruct == 0: |
||
| 296 | quantity = task.quantity |
||
| 297 | elif tech.isProject and tech.id == 3802: |
||
| 298 | # we are constructing Habitable Surface Expansion |
||
| 299 | # so after construction we will have new slot on the planet |
||
| 300 | quantity = -1 |
||
| 301 | else: |
||
| 302 | continue |
||
| 303 | assert quantity != 0 |
||
| 304 | |||
| 305 | try: |
||
| 306 | targets[task.targetID] += task.quantity |
||
| 307 | except KeyError: |
||
| 308 | targets[task.targetID] = task.quantity |
||
| 309 | return targets |
||
| 310 | |||
| 311 | |||
| 312 | def _addProblemsSlots(self, problems, system): |
||
| 313 | player = client.getPlayer() |
||
| 314 | playerPlanets = set(system.planets) & set(player.planets) |
||
| 315 | freeSlots = {} |
||
| 316 | structSources = dict.fromkeys(system.planets) |
||
| 317 | for planetID in system.planets: |
||
| 318 | planet = client.get(planetID, noUpdate=1) |
||
| 319 | freeSlots[planetID] = planet.plSlots - len(planet.slots) |
||
| 320 | |||
| 321 | for planetID in playerPlanets: |
||
| 322 | for targetID, quantity in self._getTargetSlotDict(planetID).items(): |
||
| 323 | freeSlots[targetID] -= quantity |
||
| 324 | if quantity > 0: |
||
| 325 | try: |
||
| 326 | structSources[targetID].add(planetID) |
||
| 327 | except AttributeError: |
||
| 328 | structSources[targetID] = set([planetID]) |
||
| 329 | |||
| 330 | for planetID, free in freeSlots.items(): |
||
| 331 | if free < 0: |
||
| 332 | # not enough space, report for every planet that builds on this one |
||
| 333 | planet = client.get(planetID, noUpdate=1) |
||
| 334 | for sourceID in structSources[planetID]: |
||
| 335 | source = client.get(sourceID, noUpdate=1) |
||
| 336 | problems.append(gdata.MAJ, |
||
| 337 | ui.Item(source.name, tOID=sourceID, tType=Const.T_PLANET, |
||
| 338 | vDescription=_('There is no space for all constructed buildings on %s.') % (planet.name))) |
||
| 339 | |||
| 340 | def _addProblemsDefaultQueue(self, problems, planet, defaultQueueEtc): |
||
| 341 | player = client.getPlayer() |
||
| 342 | if not planet.effProdProd > 0: |
||
| 343 | return |
||
| 344 | planetEtc = 0 |
||
| 345 | # compute length of production queue |
||
| 346 | for task in planet.prodQueue: |
||
| 347 | if task.isShip: |
||
| 348 | tech = player.shipDesigns[task.techID] |
||
| 349 | else: |
||
| 350 | tech = client.getFullTechInfo(task.techID) |
||
| 351 | modifier = Rules.buildOnAnotherPlanetMod if task.targetID != planet.oid else 1 |
||
| 352 | planetEtc += math.ceil(float(task.quantity * tech.buildProd * modifier - task.currProd) / planet.effProdProd) |
||
| 353 | |||
| 354 | etc = planetEtc + defaultQueueEtc |
||
| 355 | # check empty production queue |
||
| 356 | if not etc: |
||
| 357 | problems.append(gdata.CRI, |
||
| 358 | ui.Item(planet.name, tOID=planet.oid, tType=Const.T_PLANET, |
||
| 359 | vDescription=_('Production queue is empty.'))) |
||
| 360 | return |
||
| 361 | if etc < Rules.turnsPerDay: |
||
| 362 | severity = gdata.MAJ |
||
| 363 | elif etc < Rules.turnsPerDay * 2: |
||
| 364 | severity = gdata.MIN |
||
| 365 | else: |
||
| 366 | severity = gdata.INFO |
||
| 367 | |||
| 368 | problems.append(severity, |
||
| 369 | ui.Item(planet.name, tOID=planet.oid, tType=Const.T_PLANET, |
||
| 370 | vDescription=_('Production queue may end in {0} turns ({1} directly in planet queue).'.format(res.formatTime(etc), res.formatTime(planetEtc))))) |
||
| 371 | |||
| 372 | def show(self): |
||
| 373 | critical = self.win.vCritical.checked |
||
| 374 | major = self.win.vMajor.checked |
||
| 375 | minor = self.win.vMinor.checked |
||
| 376 | info = self.win.vInfo.checked |
||
| 377 | |||
| 378 | disp = 1 |
||
| 379 | |||
| 380 | player = client.getPlayer() |
||
| 381 | problems = self.Problems(self.win) |
||
| 382 | systems = set([]) |
||
| 383 | for planetID in player.planets: |
||
| 384 | planet = client.get(planetID, noUpdate=1) |
||
| 385 | systems.add(planet.compOf) |
||
| 386 | |||
| 387 | defaultQueueEtc = self._addProblemsGlobalQueues(problems) |
||
| 388 | |||
| 389 | for systemID in systems: |
||
| 390 | system = client.get(systemID, noUpdate=1) |
||
| 391 | bio = 0 |
||
| 392 | totalBio = 0 |
||
| 393 | en = 0 |
||
| 394 | totalEn = 0 |
||
| 395 | # holds modified planets |
||
| 396 | planetCopies = {} |
||
| 397 | |||
| 398 | for planetID in system.planets: |
||
| 399 | planet = client.get(planetID, noUpdate=1) |
||
| 400 | # copy of planet to change plSlots count |
||
| 401 | if hasattr(planet, 'owner') and planet.owner == player.oid: |
||
| 402 | # add planet to the global queue stats |
||
| 403 | # compute bio and en for system |
||
| 404 | bio += planet.changeBio |
||
| 405 | totalBio += max(0, planet.storBio - planet.minBio) |
||
| 406 | en += planet.changeEn |
||
| 407 | totalEn += max(0, planet.storEn - planet.minEn) |
||
| 408 | # the planet needs to have global queue 0 - the default one - to have its queue reported |
||
| 409 | if self.win.vPlanets.checked: |
||
| 410 | if not planet.globalQueue: |
||
| 411 | self._addProblemsDefaultQueue(problems, planet, defaultQueueEtc) |
||
| 412 | for struct in planet.slots: |
||
| 413 | self._addProblemsStructStatus(problems, struct, planet) |
||
| 414 | |||
| 415 | # free slots within the system |
||
| 416 | self._addProblemsSlots(problems, system) |
||
| 417 | # check bio for system |
||
| 418 | if self.win.vSystems.checked: |
||
| 419 | self._addProblemsMaterial(problems, system, bio, totalBio, 'Bio') |
||
| 420 | self._addProblemsMaterial(problems, system, en, totalEn, 'En') |
||
| 421 | |||
| 422 | # check fleets |
||
| 423 | if self.win.vFleets.checked: |
||
| 424 | for fleetID in player.fleets: |
||
| 425 | fleet = client.get(fleetID, noUpdate=1) |
||
| 426 | self._addProblemsFleets(problems, fleet) |
||
| 427 | |||
| 428 | # check research queue |
||
| 429 | if self.win.vResearch.checked: |
||
| 430 | self._addProblemsResearch(problems) |
||
| 431 | |||
| 432 | self.win.vProblems.items = problems.items |
||
| 433 | self.win.vProblems.itemsChanged() |
||
| 434 | |||
| 435 | def onClose(self, widget, action, data): |
||
| 436 | self.hide() |
||
| 437 | |||
| 438 | def onShowSource(self, widget, action, data): |
||
| 439 | item = self.win.vProblems.selection[0] |
||
| 440 | if item.tType == Const.T_FLEET: |
||
| 441 | object = client.get(item.tOID, noUpdate=1) |
||
| 442 | # center on map |
||
| 443 | if hasattr(object, "x"): |
||
| 444 | gdata.mainGameDlg.win.vStarMap.highlightPos = (object.x, object.y) |
||
| 445 | gdata.mainGameDlg.win.vStarMap.setPos(object.x, object.y) |
||
| 446 | self.hide() |
||
| 447 | return |
||
| 448 | elif item.tType in (Const.T_SYSTEM, Const.T_PLANET): |
||
| 449 | if item.tOID != Const.OID_NONE: |
||
| 450 | gdata.mainGameDlg.onSelectMapObj(None, None, item.tOID) |
||
| 451 | return |
||
| 452 | elif item.tType == Const.T_TECHNOLOGY: |
||
| 453 | gdata.mainGameDlg.researchDlg.display() |
||
| 454 | return |
||
| 455 | elif item.tType == Const.T_QUEUE: |
||
| 456 | gdata.mainGameDlg.globalQueuesDlg.display() |
||
| 457 | self.win.setStatus(_("Cannot show location.")) |
||
| 458 | |||
| 459 | def onShowLocation(self, widget, action, data): |
||
| 460 | item = self.win.vProblems.selection[0] |
||
| 461 | if item.tType in (Const.T_SYSTEM, Const.T_PLANET, Const.T_FLEET): |
||
| 462 | object = client.get(item.tOID, noUpdate=1) |
||
| 463 | # center on map |
||
| 464 | if hasattr(object, "x"): |
||
| 465 | gdata.mainGameDlg.win.vStarMap.highlightPos = (object.x, object.y) |
||
| 466 | gdata.mainGameDlg.win.vStarMap.setPos(object.x, object.y) |
||
| 467 | self.hide() |
||
| 468 | return |
||
| 469 | self.win.setStatus(_("Cannot show location.")) |
||
| 470 | |||
| 471 | def onToggleCondition(self, widget, action, data): |
||
| 472 | self.update() |
||
| 473 | |||
| 474 | def createUI(self): |
||
| 475 | screenWidth, screenHeight = gdata.scrnSize |
||
| 476 | # size of dialog in layout metrics (for SimpleGridLM) |
||
| 477 | cols = 40 |
||
| 478 | rows = 29 |
||
| 479 | # dialog width and height in pixels |
||
| 480 | isSmallWin = screenHeight == 600 and screenWidth == 800 |
||
| 481 | width = cols * 20 + 4 * (not isSmallWin) |
||
| 482 | height = rows * 20 + 4 * (not isSmallWin) |
||
| 483 | #creating dialog window |
||
| 484 | self.win = ui.Window(self.app, |
||
| 485 | modal=1, |
||
| 486 | escKeyClose=1, |
||
| 487 | movable=0, |
||
| 488 | title=_("Problems Locator"), |
||
| 489 | titleOnly=isSmallWin, |
||
| 490 | rect=ui.Rect((screenWidth - 800 - 4 * (not isSmallWin)) / 2, |
||
| 491 | (screenHeight - 600 - 4 * (not isSmallWin)) / 2, |
||
| 492 | width, |
||
| 493 | height), |
||
| 494 | layoutManager=ui.SimpleGridLM()) |
||
| 495 | self.win.subscribeAction('*', self) |
||
| 496 | # first row is window title |
||
| 497 | rows -= 1 |
||
| 498 | |||
| 499 | ui.Listbox(self.win, layout=(0, 0, cols, rows - 2), id='vProblems', |
||
| 500 | columns=[(_('Location'), 'text', 10, ui.ALIGN_W), |
||
| 501 | (_('Problem description'), 'vDescription', 30, ui.ALIGN_W)], |
||
| 502 | columnLabels=1, action='onShowSource', rmbAction='onShowLocation') |
||
| 503 | |||
| 504 | btnWidth = 4 |
||
| 505 | ui.Check(self.win, layout=(btnWidth * 0, rows - 2, btnWidth, 1), id='vSystems', |
||
| 506 | text=_('Systems'), action='onToggleCondition', checked=1) |
||
| 507 | ui.Check(self.win, layout=(btnWidth * 1, rows - 2, btnWidth, 1), id='vPlanets', |
||
| 508 | text=_('Planets'), action='onToggleCondition', checked=1) |
||
| 509 | ui.Check(self.win, layout=(btnWidth * 2, rows - 2, btnWidth, 1), id='vFleets', |
||
| 510 | text=_('Fleets'), action='onToggleCondition', checked=1) |
||
| 511 | ui.Check(self.win, layout=(btnWidth * 3, rows - 2, btnWidth, 1), id='vResearch', |
||
| 512 | text=_('Research'), action='onToggleCondition', checked=1) |
||
| 513 | |||
| 514 | ui.Check(self.win, layout=(btnWidth * 6, rows - 2, btnWidth, 1), id='vCritical', |
||
| 515 | text=_('Critical'), action='onToggleCondition', checked=1) |
||
| 516 | ui.Check(self.win, layout=(btnWidth * 7, rows - 2, btnWidth, 1), id='vMajor', |
||
| 517 | text=_('Major'), action='onToggleCondition', checked=1) |
||
| 518 | ui.Check(self.win, layout=(btnWidth * 8, rows - 2, btnWidth, 1), id='vMinor', |
||
| 519 | text=_('Minor'), action='onToggleCondition', checked=1) |
||
| 520 | ui.Check(self.win, layout=(btnWidth * 9, rows - 2, btnWidth, 1), id='vInfo', |
||
| 521 | text=_('Info'), action='onToggleCondition', checked=0) |
||
| 522 | |||
| 523 | # dialog bottom line |
||
| 524 | ui.Title(self.win, layout=(0, rows - 1, cols - 5, 1)) |
||
| 525 | ui.TitleButton(self.win, layout=(cols - 5, rows - 1, 5, 1), text=_("Close"), action='onClose') |
||
| 526 |