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