Compare commits

...

93 Commits

Author SHA1 Message Date
DarkPhoenix
2f57eb6ea6 Bump version 2024-06-08 03:01:13 +02:00
DarkPhoenix
3a7ee4699e Update effects and related things 2024-06-08 03:00:45 +02:00
DarkPhoenix
fa7f991fae Update icons 2024-06-08 01:37:13 +02:00
DarkPhoenix
0be8b429aa Add renames 2024-06-08 01:19:22 +02:00
DarkPhoenix
7d94e2de7d Update static data to 2604967 2024-06-08 00:57:34 +02:00
DarkPhoenix
0fbb318d8a Bump version 2024-04-30 04:10:53 +06:00
DarkPhoenix
cd013e8287 Add new effects 2024-04-30 04:10:33 +06:00
DarkPhoenix
e667453c1e Add new icons 2024-04-30 03:59:25 +06:00
DarkPhoenix
24e2db0f88 Update static data to 2563119 2024-04-30 03:55:34 +06:00
DarkPhoenix
3c47f8c6bb Add OS version comments to windows manifest 2024-04-17 02:42:42 +06:00
DarkPhoenix
42c2b3f253 Bundle extra library with appimage 2024-04-16 22:16:35 +06:00
DarkPhoenix
71d6830ac0 Bundle extra library with appimage 2024-04-16 22:03:25 +06:00
DarkPhoenix
ac2fb01a7c Update icons 2024-04-16 21:32:17 +06:00
DarkPhoenix
fc66c212fc Bump version 2024-04-16 21:31:29 +06:00
DarkPhoenix
9625fafda7 Merge remote-tracking branch 'origin/master' 2024-04-16 21:21:46 +06:00
DarkPhoenix
6b1aca4306 Update static data to 2550121 2024-04-16 21:21:33 +06:00
Anton Vorobyov
fd5a094304 Merge pull request #2597 from josephdouce/patch-2
Searchable exportHtml.py
2024-02-28 20:10:02 +04:00
Joseph Douce
a3142ff62f Update exportHtml.py 2024-02-28 15:36:02 +00:00
Joseph Douce
58ebfd3643 Searchable exportHtml.py
added searchable fits
2024-02-28 15:33:18 +00:00
Anton Vorobyov
e272267842 Merge pull request #2596 from josephdouce/patch-1
Fix exportHtml.py
2024-02-28 19:25:20 +04:00
Joseph Douce
b0256542bc Fix exportHtml.py 2024-02-28 13:17:23 +00:00
DarkPhoenix
9b8fd24987 Update pot 2024-02-27 16:30:06 +06:00
DarkPhoenix
9c68889a6d Call SelectAll() after Fit() since that's what seems to be causing issues under windows 2024-02-27 08:15:39 +06:00
DarkPhoenix
a4ed6e8066 Move select all call earlier, to see which call breaks it on windows 2024-02-27 07:38:01 +06:00
DarkPhoenix
9fe8163a69 Select all text even later 2024-02-27 05:54:55 +06:00
DarkPhoenix
9f9b496726 Select all text even later 2024-02-27 05:30:03 +06:00
DarkPhoenix
3b8fa68a4c Bump version 2024-02-27 04:11:02 +06:00
DarkPhoenix
9f5a649b04 Change migration to include newly added constraints 2024-02-27 04:05:19 +06:00
DarkPhoenix
fb45736c14 Extend UNIQUE constraint by new server column, to avoid possible collisions 2024-02-27 03:36:43 +06:00
Anton Vorobyov
b8a58fc7a6 Merge pull request #2590 from huangzheng2016/master
Update the SSO Login for Serenity and Singularity server's player
2024-02-26 23:35:31 +04:00
DarkPhoenix
b04c521805 Make sure not to crash character editor during SSO init when char editor is opened 2024-02-27 01:18:01 +06:00
DarkPhoenix
526695fa9a Try setting size for graph input boxes as a workaround for wx bug 2024-02-27 00:30:19 +06:00
Anton Vorobyov
d6be77d107 Merge pull request #2589 from pyfa-org/dependabot/pip/cryptography-42.0.4
Bump cryptography from 42.0.2 to 42.0.4
2024-02-26 22:22:33 +04:00
DarkPhoenix
907da343b1 Rework how progress dialog is used 2024-02-27 00:04:44 +06:00
DarkPhoenix
3fadccc715 Select all after setting focus as an attempt to fix input box not selecting everything under windows 2024-02-26 06:25:07 +06:00
DarkPhoenix
82a912858f Fix items in market's item view 2024-02-26 04:45:18 +06:00
正汰
cc1fdddc0a Merge branch 'pyfa-org:master' into master 2024-02-23 02:50:41 +08:00
正汰
e314ecf887 Fix the esi problem for Serenity when setting 2024-02-23 02:48:54 +08:00
正汰
94b1c8b029 Fix the esi problem for Serenity when setting 2024-02-23 02:47:59 +08:00
正汰
6e3b7ff132 Fix the esi problem for Serenity when setting 2024-02-23 02:47:47 +08:00
正汰
ff14855808 Fix the esi problem for Serenity when setting 2024-02-23 02:47:27 +08:00
dependabot[bot]
4761857b84 Bump cryptography from 42.0.2 to 42.0.4
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.2 to 42.0.4.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.2...42.0.4)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-21 20:48:49 +00:00
DarkPhoenix
bb53e75bfe Force light rack colors on windows regardless of OS theme 2024-02-21 03:04:36 +06:00
DarkPhoenix
cc146401b6 Bump version 2024-02-21 01:17:32 +06:00
DarkPhoenix
465e43ed45 Change how colors are defined and used 2024-02-21 00:28:21 +06:00
DarkPhoenix
f89a8a9f87 Make use of defined error color 2024-02-21 00:01:55 +06:00
DarkPhoenix
768c417c8e Add alternate colors for fitting pane (for dark mode on macos) 2024-02-21 00:00:44 +06:00
DarkPhoenix
494b6353b8 Fix icons script and update icons 2024-02-20 22:59:32 +06:00
DarkPhoenix
69ef7825af Add perl regexp lib to linux bundle 2024-02-20 22:20:52 +06:00
DarkPhoenix
e0a71754ce Merge remote-tracking branch 'origin/master' 2024-02-20 22:17:06 +06:00
DarkPhoenix
b959d9dd07 Fix mercoxit rig bonus 2024-02-20 22:15:54 +06:00
Anton Vorobyov
2c2455a644 Merge pull request #2573 from salartarium/master
update links
2024-02-20 20:09:39 +04:00
Anton Vorobyov
e2dbfb52e9 Merge pull request #2561 from m-sasha/abyssal-xml
Add mutation info to XML export/import.
2024-02-20 19:43:24 +04:00
Anton Vorobyov
612591b59b Merge pull request #2582 from pyfa-org/dependabot/pip/cryptography-42.0.2
Bump cryptography from 41.0.7 to 42.0.2
2024-02-20 19:36:03 +04:00
DarkPhoenix
3e00d5d4ae Add new effect 2024-02-20 21:18:37 +06:00
DarkPhoenix
539be1527b Clean up effects 2024-02-20 21:00:06 +06:00
DarkPhoenix
d00db1e167 Update static data to 2497879 2024-02-20 20:55:35 +06:00
dependabot[bot]
fc6d5fea48 Bump cryptography from 41.0.7 to 42.0.2
Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.7 to 42.0.2.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.7...42.0.2)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-17 00:47:08 +00:00
salartarium
ecf4d6c0de Update upgrade4.py
update link
2024-01-15 05:21:38 -08:00
salartarium
f5f7f92166 Update upgrade25.py
update link, typos in comments
2024-01-15 05:20:26 -08:00
salartarium
f5d7e754a6 Update upgrade1.py
update link
2024-01-15 05:18:33 -08:00
正汰
be85080d8d Merge branch 'pyfa-org:master' into master 2024-01-12 11:00:13 +08:00
Alexander Maryanovsky
6ed34be118 Merge branch 'master' into abyssal-xml 2023-12-25 06:39:51 +02:00
Anton Vorobyov
59dceadfee Merge pull request #2475 from pyfa-org/crowdin_master
New Crowdin updates
2023-12-25 05:08:01 +04:00
Anton Vorobyov
2a74c779c8 Merge pull request #2558 from fruitchewy/dark-style
Improve AutoListCtrl legibility in dark mode
2023-12-25 05:07:36 +04:00
Alexander Maryanovsky
f63331454b Merge branch 'master' into abyssal-xml 2023-12-22 10:36:35 +02:00
DarkPhoenix
d105748348 When importing skills, import their prerequisites as well 2023-12-22 03:43:47 +06:00
Alexander Maryanovsky
cdd7077346 Merge branch 'master' into abyssal-xml 2023-12-21 22:49:06 +02:00
DarkPhoenix
f965497186 Fix tooltip 2023-12-21 10:03:06 +06:00
Alexander Maryanovsky
6b06b5b46c Add mutation info to XML export/import. 2023-12-20 16:51:59 +02:00
akauble
d1e19406d0 Style AutoListCtrl highlighting manually in dark mode 2023-12-12 23:45:16 -06:00
DarkPhoenix
2a3c586be6 Add VTS as a jargon entry 2023-12-12 01:56:59 +06:00
DarkPhoenix
23f014c32e Do not use system theme for ListCtrl under windows 2023-12-09 17:46:31 +06:00
DarkPhoenix
0ac6a14ebb Show salvage chance next to salvage drones too 2023-12-09 17:24:35 +06:00
DarkPhoenix
0dc2632fc4 Bump version 2023-12-08 22:58:39 +06:00
DarkPhoenix
fc43691275 Revert pyinstaller to 6.0.0 for windows 2023-12-08 21:48:09 +06:00
Anton Vorobyov
128de58b83 New translations lang.pot (Japanese) 2022-11-05 01:34:48 +03:00
Anton Vorobyov
47eb8d422f New translations lang.pot (Japanese) 2022-11-04 00:10:59 +03:00
Anton Vorobyov
38ddf83da4 New translations lang.pot (Japanese) 2022-11-03 00:01:02 +03:00
Anton Vorobyov
58142a8641 New translations lang.pot (Japanese) 2022-11-02 00:03:26 +03:00
Anton Vorobyov
d86f0f40ac New translations lang.pot (Japanese) 2022-10-31 23:47:48 +03:00
Anton Vorobyov
62944e4ce3 New translations lang.pot (Japanese) 2022-10-30 23:14:52 +03:00
Anton Vorobyov
812201d8b3 New translations lang.pot (Japanese) 2022-10-29 22:53:28 +03:00
Anton Vorobyov
52abd5620f New translations lang.pot (Japanese) 2022-10-28 22:56:28 +03:00
Anton Vorobyov
e47112a1f2 New translations lang.pot (Japanese) 2022-10-23 22:57:24 +03:00
Anton Vorobyov
00a6835f50 New translations lang.pot (Japanese) 2022-10-22 21:46:14 +03:00
blitzmann
27101732ca Add a couple of bug fixes, and make the server option a checkbox 2022-05-08 13:48:38 -04:00
blitzmann
ed48a8b5d0 Re-work the exceptions related to logging a character in 2022-05-08 13:21:23 -04:00
blitzmann
5a6fe373f1 Merge branch 'master' into huangzheng2016-master
# Conflicts:
#	gui/builtinPreferenceViews/pyfaEsiPreferences.py
2022-05-08 12:35:46 -04:00
blitzmann
3c6eb6d054 Some updates to allow code / token paste regardless of server setting 2022-05-08 12:24:12 -04:00
blitzmann
dc997f0dc4 Various updates to support server-aware calls per character 2022-05-07 12:35:16 -04:00
blitzmann
14afc83e86 Fix client ID that is used 2022-04-30 10:17:51 -04:00
hz2016
216dd2a787 Update the SSO Login for Serenity and Singularity server's player 2022-04-28 15:58:33 +08:00
402 changed files with 91764 additions and 4669 deletions

View File

@@ -103,7 +103,7 @@ for:
# target Python version and architecture
- ps: echo("Install pip requirements:")
- cmd: "python -m pip install -r requirements.txt"
- cmd: "python -m pip install PyInstaller==6.1.0"
- cmd: "python -m pip install PyInstaller==6.0.0"
before_build:
# directory that will contain the built files
- ps: $env:PYFA_DIST_DIR = "c:\projects\$env:APPVEYOR_PROJECT_SLUG\dist"

View File

@@ -2,7 +2,7 @@
## Requirements
- Python 3.7
- Python 3.11
- Git CLI installed
- Python, pip and git are all available as command-line commands (add to the path if needed)

View File

@@ -9,6 +9,7 @@ import hashlib
from eos.const import FittingSlot
from cryptography.fernet import Fernet
from collections import namedtuple
pyfalog = Logger(__name__)
@@ -44,9 +45,16 @@ experimentalFeatures = None
version = None
language = None
API_CLIENT_ID = '095d8cd841ac40b581330919b49fe746'
ApiServer = namedtuple('ApiBase', ['name', 'sso', 'esi', 'client_id', 'callback', 'supports_auto_login'])
supported_servers = {
"Tranquility": ApiServer("Tranquility", "login.eveonline.com", "esi.evetech.net", '095d8cd841ac40b581330919b49fe746', 'https://pyfa-org.github.io/Pyfa/callback', True),
# No point having SISI: https://developers.eveonline.com/blog/article/removing-datasource-singularity
# "Singularity": ApiServer("Singularity", "sisilogin.testeveonline.com", "esi.evetech.net", 'b9c3cc79448f449ab17f3aebd018842e', 'https://pyfa-org.github.io/Pyfa/callback'),
"Serenity": ApiServer("Serenity", "login.evepc.163.com", "ali-esi.evepc.163.com", 'bc90aa496a404724a93f41b4f4e97761', 'https://ali-esi.evepc.163.com/ui/oauth2-redirect.html', False)
}
SSO_LOGOFF_SERENITY='https://login.evepc.163.com/account/logoff'
ESI_CACHE = 'esi_cache'
SSO_CALLBACK = 'https://pyfa-org.github.io/Pyfa/callback'
LOGLEVEL_MAP = {
"critical": CRITICAL,
@@ -58,13 +66,22 @@ LOGLEVEL_MAP = {
CATALOG = 'lang'
slotColourMapDark = {
FittingSlot.LOW: wx.Colour(44, 36, 19), # yellow = low slots 24/13
FittingSlot.MED: wx.Colour(28, 39, 51), # blue = mid slots 8.1/9.5
FittingSlot.HIGH: wx.Colour(53, 31, 34), # red = high slots 6.5/11.5
FittingSlot.RIG: '',
FittingSlot.SUBSYSTEM: ''}
errColorDark = wx.Colour(70, 20, 20)
slotColourMap = {
FittingSlot.LOW: wx.Colour(250, 235, 204), # yellow = low slots
FittingSlot.MED: wx.Colour(188, 215, 241), # blue = mid slots
FittingSlot.HIGH: wx.Colour(235, 204, 209), # red = high slots
FittingSlot.RIG: '',
FittingSlot.SUBSYSTEM: ''
}
FittingSlot.SUBSYSTEM: ''}
errColor = wx.Colour(204, 51, 51)
def getClientSecret():
return clientHash

View File

@@ -31,6 +31,10 @@ AppDir:
- libgtk-3-0
- librsvg2-common # GTK3 recommendation; without it, search in char editor crashes
- libwebkit2gtk-4.0-37 # Needed for wx's HTML lib
# Unknown
- libpcre2-32-0 # https://github.com/pyfa-org/Pyfa/issues/2572
- libnotify4 # https://github.com/pyfa-org/Pyfa/issues/2598
- libwayland-client0 # https://github.com/pyfa-org/Pyfa/issues/2600
exclude:
- hicolor-icon-theme
- humanity-icon-theme

View File

@@ -10,10 +10,15 @@
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 10 and Windows 11 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>

View File

@@ -7,7 +7,7 @@ Migration 1
loaded as they no longer exist in the database. We therefore replace these
modules with their new replacements
Based on http://community.eveonline.com/news/patch-notes/patch-notes-for-oceanus/
Based on https://www.eveonline.com/news/view/patch-notes-for-oceanus
and output of itemDiff.py
"""

View File

@@ -2,7 +2,7 @@
Migration 25
- Converts T3C fitting configurations based on the spreadsheet noted here:
https://community.eveonline.com/news/patch-notes/patch-notes-for-july-2017-release
https://www.eveonline.com/news/view/patch-notes-for-july-2017-release
(csv copies can be found on the pyfa repo in case the official documents are deleted)
@@ -4228,8 +4228,8 @@ def upgrade(saveddata_engine):
# We don't have a conversion for this. I don't think this will ever happen, but who knows
continue
# It doesn't actully matter which old module is replaced with which new module, so we don't have to worry
# about module position or anything like that. Just doe a straight up record UPDATE
# It doesn't actually matter which old module is replaced with which new module, so we don't have to worry
# about module position or anything like that. Just do a straight up record UPDATE
for i, old in enumerate(oldModules[:4]):
saveddata_engine.execute("UPDATE modules SET itemID = ? WHERE ID = ?", (newModules[i], old[0]))

View File

@@ -6,7 +6,7 @@ Migration 4
from database), which causes pyfa to crash. We therefore replace these
modules with their new replacements
Based on http://community.eveonline.com/news/patch-notes/patch-notes-for-proteus/
Based on https://www.eveonline.com/news/view/patch-notes-for-proteus
and output of itemDiff.py
"""

View File

@@ -0,0 +1,36 @@
"""
Migration 46
- add support for server selection for SSO characters
"""
import sqlalchemy
tmpTable = """
CREATE TABLE ssoCharacterTemp (
ID INTEGER NOT NULL,
client VARCHAR NOT NULL,
characterID INTEGER NOT NULL,
characterName VARCHAR NOT NULL,
refreshToken VARCHAR NOT NULL,
accessToken VARCHAR NOT NULL,
accessTokenExpires DATETIME NOT NULL,
created DATETIME,
modified DATETIME,
server VARCHAR,
PRIMARY KEY (ID),
CONSTRAINT "uix_client_server_characterID" UNIQUE (client, server, characterID),
CONSTRAINT "uix_client_server_characterName" UNIQUE (client, server, characterName)
)
"""
def upgrade(saveddata_engine):
try:
saveddata_engine.execute("SELECT server FROM ssoCharacter LIMIT 1")
except sqlalchemy.exc.DatabaseError:
saveddata_engine.execute(tmpTable)
saveddata_engine.execute(
"INSERT INTO ssoCharacterTemp (ID, client, characterID, characterName, refreshToken, accessToken, accessTokenExpires, created, modified, server) "
"SELECT ID, client, characterID, characterName, refreshToken, accessToken, accessTokenExpires, created, modified, 'Tranquility' "
"FROM ssoCharacter")
saveddata_engine.execute("DROP TABLE ssoCharacter")
saveddata_engine.execute("ALTER TABLE ssoCharacterTemp RENAME TO ssoCharacter")

View File

@@ -40,18 +40,18 @@ characters_table = Table("characters", saveddata_meta,
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now))
sso_table = Table("ssoCharacter", saveddata_meta,
Column("ID", Integer, primary_key=True),
Column("client", String, nullable=False),
Column("characterID", Integer, nullable=False),
Column("characterName", String, nullable=False),
Column("refreshToken", String, nullable=False),
Column("accessToken", String, nullable=False),
Column("accessTokenExpires", DateTime, nullable=False),
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
UniqueConstraint('client', 'characterID', name='uix_client_characterID'),
UniqueConstraint('client', 'characterName', name='uix_client_characterName')
)
Column("ID", Integer, primary_key=True),
Column("client", String, nullable=False),
Column("characterID", Integer, nullable=False),
Column("characterName", String, nullable=False),
Column("server", String, nullable=False),
Column("refreshToken", String, nullable=False),
Column("accessToken", String, nullable=False),
Column("accessTokenExpires", DateTime, nullable=False),
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
UniqueConstraint('client', 'server', 'characterID', name='uix_client_server_characterID'),
UniqueConstraint('client', 'server', 'characterName', name='uix_client_server_characterName'))
sso_character_map_table = Table("ssoCharacterMap", saveddata_meta,
Column("characterID", ForeignKey("characters.ID"), primary_key=True),

View File

@@ -493,9 +493,12 @@ def getSsoCharacters(clientHash, eager=None):
@cachedQuery(SsoCharacter, 1, "lookfor", "clientHash")
def getSsoCharacter(lookfor, clientHash, eager=None):
def getSsoCharacter(lookfor, clientHash, server=None, eager=None):
filter = SsoCharacter.client == clientHash
if server is not None:
filter = and_(filter, SsoCharacter.server == server)
if isinstance(lookfor, int):
filter = and_(filter, SsoCharacter.ID == lookfor)
elif isinstance(lookfor, str):

View File

@@ -396,7 +396,7 @@ class Effect59(BaseEffect):
cargoCapacityMultiply
Used by:
Modules from group: Expanded Cargohold (7 of 7)
Modules from group: Expanded Cargohold (8 of 8)
Modules from group: Overdrive Injector System (7 of 7)
Modules from group: Reinforced Bulkhead (8 of 8)
"""
@@ -966,8 +966,8 @@ class Effect272(BaseEffect):
Used by:
Implants named like: Inherent Implants 'Noble' Repair Systems RS (6 of 6)
Implants named like: Repairer Booster (4 of 4)
Modules named like: Nanobot Accelerator (8 of 8)
Implant: AIR Repairer Booster III
Implant: Numon Family Heirloom
Skill: Repair Systems
"""
@@ -1060,6 +1060,7 @@ class Effect290(BaseEffect):
Used by:
Implants named like: Frentix Booster (4 of 4)
Implants named like: Halcyon B Booster (5 of 5)
Implants named like: SoCT Turret Booster (3 of 3)
Implants named like: Zainou 'Deadeye' Sharpshooter ST (6 of 6)
Skill: Sharpshooter
"""
@@ -1169,6 +1170,7 @@ class Effect394(BaseEffect):
Implant: AIR Overclocker Booster II
Implant: Quafe Zero Classic
Implant: Serenity YC122.9 Season Booster - Max Velocity
Implant: Starsi Blast! Classic
Implant: Wisdom of Gheinok
Skill: Navigation
"""
@@ -1190,17 +1192,18 @@ class Effect395(BaseEffect):
Used by:
Modules from group: Rig Anchor (4 of 4)
Implants named like: Agility Booster (4 of 4)
Implants named like: Eifyr and Co. 'Rogue' Evasive Maneuvering EM (6 of 6)
Implants named like: Grand Prix Booster (4 of 6)
Implants named like: Halcyon G Booster (5 of 5)
Implants named like: Halcyon Y Booster (5 of 5)
Implants named like: grade Nomad (10 of 12)
Modules named like: Low Friction Nozzle Joints (8 of 8)
Implant: AIR Agility Booster II
Implant: AIR Overclocker Booster III
Implant: Genolution Core Augmentation CA-4
Implant: Quafe Zero Green Apple
Implant: Serenity YC122.9 Season Booster - Agility
Implant: Starsi Blast! Classic
Skill: Evasive Maneuvering
Skill: Spaceship Command
"""
@@ -1304,7 +1307,6 @@ class Effect446(BaseEffect):
Implants named like: Festival only 'Rock' SH Dose (4 of 4)
Implants named like: Halcyon G Booster (5 of 5)
Implants named like: Serenity Limited 'Hardshell' Dose (3 of 3)
Implants named like: Wightstorm Nirvana Booster (4 of 4)
Implants named like: Zainou 'Gnome' Shield Management SM (6 of 6)
Modules named like: Core Defense Field Extender (8 of 8)
Implant: AIR Nirvana Booster II
@@ -1329,7 +1331,6 @@ class Effect485(BaseEffect):
Implants named like: Halcyon G Booster (5 of 5)
Implants named like: Halcyon R Booster (5 of 5)
Implants named like: Inherent Implants 'Squire' Capacitor Systems Operation EO (6 of 6)
Implants named like: Wightstorm Rapture Booster (4 of 4)
Implants named like: grade Rapture (15 of 18)
Modules named like: Capacitor Control Circuit (8 of 8)
Implant: AIR Overclocker Booster III
@@ -1337,6 +1338,7 @@ class Effect485(BaseEffect):
Implant: Basic Capsuleer Engineering Augmentation Chip
Implant: Genolution Core Augmentation CA-2
Implant: Quafe Zero Green Apple
Implant: Starsi Blast! Orange
Skill: Capacitor Systems Operation
"""
@@ -1773,6 +1775,7 @@ class Effect584(BaseEffect):
Implants named like: 'Pyrolancea' Dose (7 of 7)
Implants named like: Eifyr and Co. 'Gunslinger' Surgical Strike SS (6 of 6)
Implants named like: Halcyon Y Booster (5 of 5)
Implants named like: SoCT Turret Booster (3 of 3)
Implant: AIR Pyrolancea Booster II
Implant: Standard Cerebral Accelerator
"""
@@ -2155,9 +2158,11 @@ class Effect699(BaseEffect):
Used by:
Implants named like: Halcyon B Booster (5 of 5)
Implants named like: Halcyon R Booster (5 of 5)
Implants named like: SoCT Scan Booster (3 of 3)
Implants named like: Zainou 'Gypsy' Signature Analysis SA (6 of 6)
Modules named like: Targeting System Subcontroller (8 of 8)
Implant: Quafe Zero Classic
Implant: Starsi Blast! Orange
Skill: Signature Analysis
"""
@@ -2504,6 +2509,7 @@ class Effect856(BaseEffect):
Implants named like: Grand Prix Booster (5 of 6)
Implants named like: Halcyon B Booster (5 of 5)
Implants named like: Serenity Limited 'Overclocker' Dose (3 of 3)
Implants named like: SoCT Agility Booster (3 of 3)
Implants named like: grade Ascendancy (10 of 12)
Modules named like: Hyperspatial Velocity Optimizer (8 of 8)
Implant: Serenity YC122.9 Season Booster - Warp Speed
@@ -3271,24 +3277,6 @@ class Effect1024(BaseEffect):
skill='Caldari Cruiser', **kwargs)
class Effect1025(BaseEffect):
"""
shipMissileLightVelocityBonusCC2
Used by:
Ship: Caracal
Ship: Osprey Navy Issue
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill('Light Missiles'),
'maxVelocity', ship.getModifiedItemAttr('shipBonusCC2'),
skill='Caldari Cruiser', **kwargs)
class Effect1030(BaseEffect):
"""
remoteArmorSystemsCapNeedBonusPostPercentCapacitorNeedLocationShipModulesRequiringRemoteArmorSystems
@@ -4837,7 +4825,7 @@ class Effect1615(BaseEffect):
shipAdvancedSpaceshipCommandAgilityBonus
Used by:
Items from market group: Ships > Capital Ships (50 of 50)
Items from market group: Ships > Capital Ships (51 of 51)
"""
type = 'passive'
@@ -4910,8 +4898,8 @@ class Effect1635(BaseEffect):
capitalRepairSystemsSkillDurationBonus
Used by:
Implants named like: Repairer Booster (4 of 4)
Modules named like: Nanobot Accelerator (8 of 8)
Implant: AIR Repairer Booster III
Skill: Capital Repair Systems
"""
@@ -4975,9 +4963,7 @@ class Effect1644(BaseEffect):
skirmishCommandMindlink
Used by:
Implant: Federation Navy Command Mindlink
Implant: Republic Fleet Command Mindlink
Implant: Skirmish Command Mindlink
Implants from group: Cyber Leadership (4 of 11)
"""
type = 'passive'
@@ -5001,7 +4987,7 @@ class Effect1645(BaseEffect):
shieldCommandMindlink
Used by:
Implants from group: Cyber Leadership (4 of 10)
Implants from group: Cyber Leadership (4 of 11)
"""
type = 'passive'
@@ -5025,9 +5011,7 @@ class Effect1646(BaseEffect):
informationCommandMindlink
Used by:
Implant: Caldari Navy Command Mindlink
Implant: Imperial Navy Command Mindlink
Implant: Information Command Mindlink
Implants from group: Cyber Leadership (4 of 11)
"""
type = 'passive'
@@ -6757,7 +6741,7 @@ class Effect2252(BaseEffect):
Used by:
Ships from group: Black Ops (5 of 5)
Ships from group: Blockade Runner (4 of 4)
Ships from group: Blockade Runner (5 of 5)
Ships from group: Covert Ops (8 of 8)
Ships from group: Expedition Frigate (2 of 2)
Ships from group: Force Recon Ship (9 of 9)
@@ -6806,8 +6790,8 @@ class Effect2255(BaseEffect):
tractorBeamCan
Used by:
Deployables from group: Mobile Tractor Unit (4 of 4)
Modules from group: Tractor Beam (4 of 4)
Deployables from group: Mobile Tractor Unit (5 of 5)
Modules from group: Tractor Beam (6 of 6)
"""
type = 'active'
@@ -6819,7 +6803,6 @@ class Effect2296(BaseEffect):
Used by:
Implants named like: Halcyon Y Booster (5 of 5)
Implants named like: Tetrimon Resistance Booster (4 of 4)
"""
type = 'passive'
@@ -7017,7 +7000,7 @@ class Effect2432(BaseEffect):
Implants named like: Halcyon Y Booster (5 of 5)
Implants named like: Inherent Implants 'Squire' Capacitor Management EM (6 of 6)
Implants named like: Mindflood Booster (4 of 4)
Implants named like: Tetrimon Capacitor Booster (4 of 4)
Implants named like: SoCT Capacitor Booster (3 of 3)
Modules named like: Semiconductor Memory Cell (8 of 8)
Implant: Antipharmakon Aeolis
Implant: Basic Capsuleer Engineering Augmentation Chip
@@ -7642,7 +7625,6 @@ class Effect2696(BaseEffect):
maxRangeBonusEffectLasers
Used by:
Implants named like: Tetrimon Precision Booster (4 of 4)
Modules named like: Energy Locus Coordinator (8 of 8)
"""
@@ -8393,8 +8375,6 @@ class Effect2803(BaseEffect):
energyWeaponDamageMultiplyPassive
Used by:
Implants named like: Harvest Damage Booster (4 of 4)
Implants named like: Wightstorm Vitarka Booster (4 of 4)
Modules named like: Energy Collision Accelerator (8 of 8)
Implant: Wisdom of Gheinok
"""
@@ -9515,7 +9495,7 @@ class Effect3046(BaseEffect):
modifyMaxVelocityOfShipPassive
Used by:
Modules from group: Expanded Cargohold (7 of 7)
Modules from group: Expanded Cargohold (8 of 8)
"""
type = 'offline'
@@ -9530,7 +9510,7 @@ class Effect3047(BaseEffect):
structureHPMultiplyPassive
Used by:
Modules from group: Expanded Cargohold (7 of 7)
Modules from group: Expanded Cargohold (8 of 8)
"""
type = 'passive'
@@ -9670,7 +9650,6 @@ class Effect3196(BaseEffect):
thermodynamicsSkillDamageBonus
Used by:
Implants named like: Wightstorm Sunyata Booster (4 of 4)
Skill: Thermodynamics
"""
@@ -10100,23 +10079,6 @@ class Effect3356(BaseEffect):
skill='Heavy Interdiction Cruisers', **kwargs)
class Effect3357(BaseEffect):
"""
eliteBonusHeavyInterdictorLightMissileVelocityBonus
Used by:
Ship: Onyx
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill('Light Missiles'),
'maxVelocity', ship.getModifiedItemAttr('eliteBonusHeavyInterdictors1'),
skill='Heavy Interdiction Cruisers', **kwargs)
class Effect3366(BaseEffect):
"""
shipRemoteSensorDampenerCapNeedGF
@@ -13527,6 +13489,7 @@ class Effect4162(BaseEffect):
Implants named like: Poteque 'Prospector' Astrometric Rangefinding AR (3 of 3)
Implants named like: Poteque 'Prospector' Sharpeye (2 of 2)
Implants named like: Serenity Limited 'Sharpeye' Dose (3 of 3)
Implants named like: SoCT Scan Booster (3 of 3)
Implants named like: grade Virtue (10 of 12)
Modules named like: Gravity Capacitor Upgrade (8 of 8)
Implant: AIR Astro-Rangefinding II Booster
@@ -16387,7 +16350,7 @@ class Effect4921(BaseEffect):
microJumpDrive
Used by:
Modules from group: Micro Jump Drive (2 of 2)
Modules named like: Micro Jump Drive (3 of 3)
"""
type = 'active'
@@ -16670,8 +16633,8 @@ class Effect4967(BaseEffect):
shieldBoosterDurationBonusShieldSkills
Used by:
Implants named like: Repairer Booster (4 of 4)
Modules named like: Core Defense Operational Solidifier (8 of 8)
Implant: AIR Repairer Booster III
"""
type = 'passive'
@@ -17365,9 +17328,10 @@ class Effect5069(BaseEffect):
@staticmethod
def handler(fit, module, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill('Mercoxit Processing'),
'specializationAsteroidYieldMultiplier',
module.getModifiedItemAttr('miningAmountBonus'), **kwargs)
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Mercoxit Ore Processing'),
'specializationAsteroidYieldMultiplier',
module.getModifiedItemAttr('miningAmountBonus'), **kwargs)
class Effect5079(BaseEffect):
@@ -18050,8 +18014,6 @@ class Effect5189(BaseEffect):
trackingSpeedBonusEffectLasers
Used by:
Implants named like: Tetrimon Precision Booster (4 of 4)
Implants named like: Wightstorm Manasikara Booster (4 of 4)
Modules named like: Energy Metastasis Adjuster (8 of 8)
"""
@@ -18701,7 +18663,7 @@ class Effect5266(BaseEffect):
blockadeRunnerCloakCpuPercentBonus
Used by:
Ships from group: Blockade Runner (4 of 4)
Ships from group: Blockade Runner (5 of 5)
"""
runTime = 'early'
@@ -20219,6 +20181,7 @@ class Effect5437(BaseEffect):
Used by:
Implants named like: Halcyon Y Booster (5 of 5)
Implants named like: SoCT Relic Coherence Booster (3 of 3)
Modules named like: Emission Scope Sharpener (8 of 8)
Implant: Poteque 'Prospector' Archaeology AC-905
Implant: Poteque 'Prospector' Environmental Analysis EY-1005
@@ -22467,7 +22430,7 @@ class Effect5869(BaseEffect):
eliteIndustrialWarpSpeedBonus1
Used by:
Ships from group: Blockade Runner (4 of 4)
Ships from group: Blockade Runner (5 of 5)
"""
type = 'passive'
@@ -22549,7 +22512,7 @@ class Effect5874(BaseEffect):
eliteIndustrialFleetCapacity1
Used by:
Ships from group: Deep Space Transport (4 of 4)
Ships from group: Deep Space Transport (5 of 5)
"""
type = 'passive'
@@ -22565,8 +22528,7 @@ class Effect5881(BaseEffect):
eliteIndustrialShieldResists2
Used by:
Ship: Bustard
Ship: Mastodon
Ships from group: Deep Space Transport (3 of 5)
"""
type = 'passive'
@@ -22601,7 +22563,7 @@ class Effect5889(BaseEffect):
eliteIndustrialABHeatBonus
Used by:
Ships from group: Deep Space Transport (4 of 4)
Ships from group: Deep Space Transport (5 of 5)
Ships from group: Interceptor (4 of 10)
"""
@@ -22618,7 +22580,7 @@ class Effect5890(BaseEffect):
eliteIndustrialMWDHeatBonus
Used by:
Ships from group: Deep Space Transport (4 of 4)
Ships from group: Deep Space Transport (5 of 5)
Ships from group: Interceptor (4 of 10)
"""
@@ -22635,7 +22597,7 @@ class Effect5891(BaseEffect):
eliteIndustrialArmorHardenerHeatBonus
Used by:
Ships from group: Deep Space Transport (4 of 4)
Ships from group: Deep Space Transport (5 of 5)
"""
type = 'passive'
@@ -22651,7 +22613,7 @@ class Effect5892(BaseEffect):
eliteIndustrialReactiveArmorHardenerHeatBonus
Used by:
Ships from group: Deep Space Transport (4 of 4)
Ships from group: Deep Space Transport (5 of 5)
"""
type = 'passive'
@@ -22667,7 +22629,7 @@ class Effect5893(BaseEffect):
eliteIndustrialShieldHardenerHeatBonus
Used by:
Ships from group: Deep Space Transport (4 of 4)
Ships from group: Deep Space Transport (5 of 5)
"""
type = 'passive'
@@ -22683,7 +22645,7 @@ class Effect5896(BaseEffect):
eliteIndustrialShieldBoosterHeatBonus
Used by:
Ships from group: Deep Space Transport (4 of 4)
Ships from group: Deep Space Transport (5 of 5)
"""
type = 'passive'
@@ -22701,7 +22663,7 @@ class Effect5899(BaseEffect):
eliteIndustrialArmorRepairHeatBonus
Used by:
Ships from group: Deep Space Transport (4 of 4)
Ships from group: Deep Space Transport (5 of 5)
"""
type = 'passive'
@@ -22734,7 +22696,7 @@ class Effect5901(BaseEffect):
roleBonusBulkheadCPU
Used by:
Ships from group: Freighter (4 of 5)
Ships from group: Freighter (4 of 6)
Ships from group: Jump Freighter (4 of 4)
"""
@@ -24911,7 +24873,7 @@ class Effect6208(BaseEffect):
microJumpPortalDrive
Used by:
Module: Micro Jump Field Generator
Modules named like: Micro Jump Field Generator (2 of 2)
"""
type = 'active'
@@ -26956,8 +26918,8 @@ class Effect6431(BaseEffect):
fighterAbilityMissiles
Used by:
Items from category: Fighter (48 of 82)
Fighters from group: Light Fighter (32 of 32)
Items from category: Fighter (56 of 94)
Fighters from group: Light Fighter (40 of 40)
"""
dealsDamage = True
@@ -26972,7 +26934,7 @@ class Effect6434(BaseEffect):
fighterAbilityEnergyNeutralizer
Used by:
Fighters named like: Cenobite (4 of 4)
Fighters named like: Cenobite (5 of 5)
"""
displayName = 'Energy Neutralizer'
@@ -27001,7 +26963,7 @@ class Effect6435(BaseEffect):
fighterAbilityStasisWebifier
Used by:
Fighters named like: Dromi (4 of 4)
Fighters named like: Dromi (5 of 5)
"""
displayName = 'Stasis Webifier'
@@ -27028,7 +26990,7 @@ class Effect6436(BaseEffect):
fighterAbilityWarpDisruption
Used by:
Fighters named like: Siren (4 of 4)
Fighters named like: Siren (5 of 5)
"""
displayName = 'Warp Disruption'
@@ -27055,7 +27017,7 @@ class Effect6437(BaseEffect):
fighterAbilityECM
Used by:
Fighters named like: Scarab (4 of 4)
Fighters named like: Scarab (5 of 5)
"""
displayName = 'ECM'
@@ -27085,7 +27047,7 @@ class Effect6439(BaseEffect):
fighterAbilityEvasiveManeuvers
Used by:
Fighters from group: Light Fighter (16 of 32)
Fighters from group: Light Fighter (20 of 40)
"""
displayName = 'Evasive Maneuvers'
@@ -27123,7 +27085,7 @@ class Effect6440(BaseEffect):
Used by:
Fighters named like: Shadow (2 of 2)
Fighters named like: Siren (4 of 4)
Fighters named like: Siren (5 of 5)
"""
displayName = 'Afterburner'
@@ -27142,7 +27104,7 @@ class Effect6441(BaseEffect):
fighterAbilityMicroWarpDrive
Used by:
Items from category: Fighter (44 of 82)
Items from category: Fighter (51 of 94)
"""
displayName = 'Microwarpdrive'
@@ -27236,7 +27198,7 @@ class Effect6465(BaseEffect):
fighterAbilityAttackM
Used by:
Items from category: Fighter (50 of 82)
Items from category: Fighter (54 of 94)
Fighters from group: Heavy Fighter (34 of 34)
"""
@@ -28396,6 +28358,9 @@ class Effect6567(BaseEffect):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups or
mod.item.requiresSkill('Propulsion Jamming'),
'capacitorNeed', src.getModifiedItemAttr('ewCapacitorNeedBonus'), **kwargs)
fit.modules.filteredItemIncrease(
lambda mod: mod.item.requiresSkill('Capital Micro Jump Drive Operation'), 'activationBlocked',
src.getModifiedItemAttr('networkedSensorArrayDisallowCapitalMicroJump'), **kwargs)
class Effect6570(BaseEffect):
@@ -31615,7 +31580,7 @@ class Effect6783(BaseEffect):
Used by:
Ships from group: Carrier (4 of 4)
Ships from group: Combat Battlecruiser (20 of 20)
Ships from group: Command Ship (4 of 8)
Ships from group: Command Ship (8 of 8)
Ships from group: Force Auxiliary (6 of 6)
Ships from group: Supercarrier (6 of 6)
Ships from group: Titan (8 of 8)
@@ -31661,9 +31626,9 @@ class Effect6789(BaseEffect):
industrialBonusDroneDamage
Used by:
Ships from group: Blockade Runner (4 of 4)
Ships from group: Deep Space Transport (4 of 4)
Ships from group: Hauler (17 of 17)
Ships from group: Blockade Runner (5 of 5)
Ships from group: Deep Space Transport (5 of 5)
Ships from group: Hauler (18 of 18)
Ships from group: Industrial Command Ship (2 of 2)
Ship: Hulk
Ship: Mackinaw
@@ -33600,7 +33565,7 @@ class Effect7009(BaseEffect):
Used by:
Structure Modules from group: Structure Citadel Service Module (2 of 2)
Structure Modules from group: Structure Engineering Service Module (6 of 6)
Structure Modules from group: Structure Navigation Service Module (3 of 3)
Structure Modules from group: Structure FLEX Service Module (3 of 3)
Structure Modules from group: Structure Resource Processing Service Module (4 of 4)
Structure Module: Standup Moon Drill I
"""
@@ -36712,7 +36677,7 @@ class Effect8108(BaseEffect):
signatureRadiusBonusOnline
Used by:
Module: Signature Radius Suppressor I
Modules from group: Signature Suppressor (5 of 5)
"""
type = 'passive'
@@ -36728,7 +36693,7 @@ class Effect8109(BaseEffect):
targetSpectrumBreakerBonus
Used by:
Module: Signature Radius Suppressor I
Modules from group: Signature Suppressor (5 of 5)
"""
type = 'active'
@@ -37692,64 +37657,12 @@ class Effect8264(BaseEffect):
skill='Industrial Command Ships', **kwargs)
class Effect8267(BaseEffect):
"""
weaponDisruptorResistanceBonusPassive
Used by:
Implants named like: Harvest Anti Disruptor Booster (4 of 4)
"""
type = 'passive'
@staticmethod
def handler(fit, container, context, projectionRange, **kwargs):
fit.ship.boostItemAttr(
'weaponDisruptionResistance',
container.getModifiedItemAttr('weaponDisruptionResistanceBonus'), **kwargs)
class Effect8268(BaseEffect):
"""
nosferatuDurationBonusPassive
Used by:
Implants named like: Harvest Nosferatu Booster (4 of 4)
"""
type = 'passive'
@staticmethod
def handler(fit, module, context, projectionRange, **kwargs):
fit.modules.filteredItemBoost(
lambda mod: mod.item.group.name == 'Energy Nosferatu', 'duration',
module.getModifiedItemAttr('durationBonus'), **kwargs)
class Effect8269(BaseEffect):
"""
stasisWebifierMaxRangeAddPassive
Used by:
Implants named like: Harvest Webifier Booster (4 of 4)
"""
type = 'passive'
@staticmethod
def handler(fit, module, context, projectionRange, **kwargs):
fit.modules.filteredItemIncrease(
lambda mod: mod.item.group.name == 'Stasis Web', 'maxRange',
module.getModifiedItemAttr('stasisWebRangeAdd'), **kwargs)
class Effect8270(BaseEffect):
"""
capacitorWarfareResistanceBonusPassive
Used by:
Implants named like: Halcyon Y Booster (5 of 5)
Implants named like: Tetrimon Anti Drain Booster (4 of 4)
"""
type = 'passive'
@@ -37812,23 +37725,6 @@ class Effect8279(BaseEffect):
skill='Industrial Command Ships', **kwargs)
class Effect8291(BaseEffect):
"""
afterburnerSpeedBoostBonusPassive
Used by:
Implants named like: Wightstorm Cetana Booster (4 of 4)
"""
type = 'passive'
@staticmethod
def handler(fit, booster, context, projectionRange, **kwargs):
fit.modules.filteredItemBoost(
lambda mod: mod.item.requiresSkill('Afterburner'), 'speedFactor',
booster.getModifiedItemAttr('speedFBonus'), **kwargs)
class Effect8294(BaseEffect):
"""
industrialCommandBonusDroneOreMiningYield
@@ -38117,6 +38013,40 @@ class Effect8323(BaseEffect):
skill='Gallente Hauler', **kwargs)
class Effect8327(BaseEffect):
"""
relicAnalyzerRangeBonusPassive
Used by:
Implants named like: SoCT Relic Range Booster (3 of 3)
"""
type = 'passive'
@staticmethod
def handler(fit, container, context, projectionRange, **kwargs):
fit.modules.filteredItemBoost(
lambda mod: mod.item.requiresSkill('Archaeology'), 'maxRange',
container.getModifiedItemAttr('rangeSkillBonus'), **kwargs)
class Effect8328(BaseEffect):
"""
relicVirusStrengthBonusPassive
Used by:
Implants named like: SoCT Relic Strength Booster (3 of 3)
"""
type = 'passive'
@staticmethod
def handler(fit, container, context, projectionRange, **kwargs):
fit.modules.filteredItemIncrease(
lambda mod: mod.item.requiresSkill('Archaeology'), 'virusStrength',
container.getModifiedItemAttr('virusStrengthBonus'), **kwargs)
class Effect8360(BaseEffect):
"""
shipBonusMissileReloadTimeGC2
@@ -38335,6 +38265,23 @@ class Effect8479(BaseEffect):
container.getModifiedItemAttr('falloffBonus'), **kwargs)
class Effect8594(BaseEffect):
"""
modifyArmorDamageResistanceBonusPostPercentPassive
Used by:
Implants named like: SoCT Armor Booster (3 of 3)
"""
type = 'passive'
@staticmethod
def handler(fit, booster, context, projectionRange, **kwargs):
for type in ('Em', 'Explosive', 'Kinetic', 'Thermal'):
fit.ship.boostItemAttr(f'armor{type}DamageResonance',
booster.getModifiedItemAttr('armorDamageResistanceBonus'), **kwargs)
class Effect11055(BaseEffect):
"""
shipBonusBattlecruiserHeavyMissileAoeVelocityMBC1
@@ -40539,3 +40486,306 @@ class Effect12003(BaseEffect):
fit.modules.filteredItemBoost(
lambda mod: mod.item.requiresSkill('Vorton Projector Operation'), 'speed',
booster.getModifiedItemAttr('turretSpeeBonus'), **kwargs)
class Effect12038(BaseEffect):
"""
shipBonusSPTFalloffMF3
Used by:
Ship: Republic Fleet Firetail
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredItemBoost(
lambda mod: mod.item.requiresSkill('Small Projectile Turret'), 'falloff',
ship.getModifiedItemAttr('shipBonus3MF'), skill='Minmatar Frigate', **kwargs)
class Effect12050(BaseEffect):
"""
shipBonusColonyResourcesHoldCapacityUH1
Used by:
Variations of ship: Squall (3 of 3)
"""
type = 'passive'
@staticmethod
def handler(fit, src, context, projectionRange, **kwargs):
fit.ship.boostItemAttr(
'specialColonyResourcesHoldCapacity', src.getModifiedItemAttr('shipBonusUH1'),
skill='Upwell Hauler', **kwargs)
class Effect12051(BaseEffect):
"""
shipMissileEMDamageUH2
Used by:
Variations of ship: Squall (3 of 3)
"""
type = 'passive'
@staticmethod
def handler(fit, container, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Missile Launcher Operation'),
'emDamage', container.getModifiedItemAttr('shipBonusUH2'),
skill='Upwell Hauler', **kwargs)
class Effect12052(BaseEffect):
"""
shipMissileThermalDamageUH2
Used by:
Variations of ship: Squall (3 of 3)
"""
type = 'passive'
@staticmethod
def handler(fit, container, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Missile Launcher Operation'),
'thermalDamage', container.getModifiedItemAttr('shipBonusUH2'),
skill='Upwell Hauler', **kwargs)
class Effect12053(BaseEffect):
"""
shipMissileExplosiveDamageUH2
Used by:
Variations of ship: Squall (3 of 3)
"""
type = 'passive'
@staticmethod
def handler(fit, container, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Missile Launcher Operation'),
'explosiveDamage', container.getModifiedItemAttr('shipBonusUH2'),
skill='Upwell Hauler', **kwargs)
class Effect12054(BaseEffect):
"""
shipMissileKineticDamageUH2
Used by:
Variations of ship: Squall (3 of 3)
"""
type = 'passive'
@staticmethod
def handler(fit, container, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Missile Launcher Operation'),
'kineticDamage', container.getModifiedItemAttr('shipBonusUH2'),
skill='Upwell Hauler', **kwargs)
class Effect12057(BaseEffect):
"""
shipBonusColonyResourcesHoldCapacityUFreighter1
Used by:
Ship: Avalanche
"""
type = 'passive'
@staticmethod
def handler(fit, src, context, projectionRange, **kwargs):
fit.ship.boostItemAttr(
'specialColonyResourcesHoldCapacity', src.getModifiedItemAttr('shipBonusUFreighter1'),
skill='Upwell Freighter', **kwargs)
class Effect12058(BaseEffect):
"""
shipMissileEMDamageUFreighter2
Used by:
Ship: Avalanche
"""
type = 'passive'
@staticmethod
def handler(fit, container, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Missile Launcher Operation'),
'emDamage', container.getModifiedItemAttr('shipBonusUFreighter2'),
skill='Upwell Freighter', **kwargs)
class Effect12060(BaseEffect):
"""
shipMissileThermalDamageUFreighter2
Used by:
Ship: Avalanche
"""
type = 'passive'
@staticmethod
def handler(fit, container, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Missile Launcher Operation'),
'thermalDamage', container.getModifiedItemAttr('shipBonusUFreighter2'),
skill='Upwell Freighter', **kwargs)
class Effect12061(BaseEffect):
"""
shipMissileExplosiveDamageUFreighter2
Used by:
Ship: Avalanche
"""
type = 'passive'
@staticmethod
def handler(fit, container, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Missile Launcher Operation'),
'explosiveDamage', container.getModifiedItemAttr('shipBonusUFreighter2'),
skill='Upwell Freighter', **kwargs)
class Effect12062(BaseEffect):
"""
shipMissileKineticDamageUFreighter2
Used by:
Ship: Avalanche
"""
type = 'passive'
@staticmethod
def handler(fit, container, context, projectionRange, **kwargs):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Missile Launcher Operation'),
'kineticDamage', container.getModifiedItemAttr('shipBonusUFreighter2'),
skill='Upwell Freighter', **kwargs)
class Effect12063(BaseEffect):
"""
shipRoleBonusUpwellFreighterCloakCPUPenalty
Used by:
Ship: Avalanche
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredItemIncrease(
lambda mod: mod.item.group.name == 'Cloaking Device',
'cpu', ship.getModifiedItemAttr('upwellFreightercloakCPUPenalty'), **kwargs)
class Effect12069(BaseEffect):
"""
shipBonusAutoTargetingMissilesUFreighter3
Used by:
Ship: Avalanche
"""
type = 'passive'
@staticmethod
def handler(fit, container, context, projectionRange, **kwargs):
damageTypes = ('em', 'explosive', 'kinetic', 'thermal')
for dmgType in damageTypes:
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Auto-Targeting Missiles'),
f'{dmgType}Damage', container.getModifiedItemAttr('shipBonusUFreighter3'),
skill='Upwell Freighter', **kwargs)
class Effect12071(BaseEffect):
"""
shipRoleBonusUpwellFreighterCapitalFlexHardenerFittingCapBonus
Used by:
Ship: Avalanche
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredItemMultiply(
lambda mod: mod.item.group.name == 'Flex Shield Hardener',
'power', ship.getModifiedItemAttr('upwellFreighterCapitalFlexHardenerFittingCapBonus'), **kwargs)
fit.modules.filteredItemMultiply(
lambda mod: mod.item.group.name == 'Flex Shield Hardener',
'capacitorNeed', ship.getModifiedItemAttr('upwellFreighterCapitalFlexHardenerFittingCapBonus'), **kwargs)
class Effect12072(BaseEffect):
"""
eliteIndustrialUpwellNeutNosHeatBonus
Used by:
Ship: Torrent
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredItemBoost(
lambda mod: mod.item.group.name in ('Energy Neutralizer', 'Energy Nosferatu'),
'overloadSelfDurationBonus', ship.getModifiedItemAttr('roleBonusOverheatDST'), **kwargs)
class Effect12098(BaseEffect):
"""
jumpPortalPassengerBonusPercentSkill
Used by:
Skill: Capital Jump Portal Generation
"""
type = 'passive'
@staticmethod
def handler(fit, skill, context, projectionRange, **kwargs):
fit.ship.boostItemAttr(
'conduitJumpPassengerCount',
skill.getModifiedItemAttr('conduitPassengerBonusPercent') * skill.level, **kwargs)
class Effect12102(BaseEffect):
"""
capitalMJDSkillCapReductionBonus
Used by:
Skill: Capital Micro Jump Drive Operation
"""
type = 'passive'
@staticmethod
def handler(fit, skill, context, projectionRange, **kwargs):
fit.modules.filteredItemBoost(
lambda mod: mod.item.requiresSkill('Capital Micro Jump Drive Operation'), 'capacitorNeed',
skill.getModifiedItemAttr('capitalMJDCapReductionBonus') * skill.level, **kwargs)

View File

@@ -377,7 +377,8 @@ class Item(EqBase):
16 : "jove",
32 : "sansha", # Incrusion Sansha
128: "ore",
135: "triglavian"
135: "triglavian",
168: "upwell",
}
# Race is None by default
race = None

View File

@@ -25,10 +25,11 @@ import time
class SsoCharacter:
def __init__(self, charID, name, client, accessToken=None, refreshToken=None):
def __init__(self, charID, name, client, server, accessToken=None, refreshToken=None):
self.characterID = charID
self.characterName = name
self.client = client
self.server = server
self.accessToken = accessToken
self.refreshToken = refreshToken
self.accessTokenExpires = None
@@ -37,6 +38,9 @@ class SsoCharacter:
def init(self):
pass
@property
def characterDisplay(self):
return "{} [{}]".format(self.characterName, self.server)
def is_token_expired(self):
if self.accessTokenExpires is None:
return True

View File

@@ -65,7 +65,6 @@ class DroneStackSplit(wx.Dialog):
self.input = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
self.input.SetValue(str(value))
self.input.SelectAll()
bSizer1.Add(self.input, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, 15)
@@ -75,12 +74,13 @@ class DroneStackSplit(wx.Dialog):
bSizer3.Add(self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND)
bSizer1.Add(bSizer3, 0, wx.ALL | wx.EXPAND, 10)
self.input.SetFocus()
self.input.Bind(wx.EVT_CHAR, self.onChar)
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
self.SetSizer(bSizer1)
self.CenterOnParent()
self.Fit()
self.CenterOnParent()
self.input.SetFocus()
self.input.SelectAll()
def processEnter(self, evt):
self.EndModal(wx.ID_OK)

View File

@@ -59,7 +59,6 @@ class NameDialog(wx.Dialog):
else:
value = str(value)
self.input.SetValue(value)
self.input.SelectAll()
bSizer1.Add(self.input, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, 15)
@@ -69,11 +68,12 @@ class NameDialog(wx.Dialog):
bSizer3.Add(self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND)
bSizer1.Add(bSizer3, 0, wx.ALL | wx.EXPAND, 10)
self.input.SetFocus()
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
self.SetSizer(bSizer1)
self.CenterOnParent()
self.Fit()
self.CenterOnParent()
self.input.SetFocus()
self.input.SelectAll()
def processEnter(self, evt):
self.EndModal(wx.ID_OK)

View File

@@ -108,7 +108,6 @@ class AmountChanger(wx.Dialog):
self.input = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
self.input.SetValue(str(value))
self.input.SelectAll()
bSizer1.Add(self.input, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, 15)
@@ -118,12 +117,13 @@ class AmountChanger(wx.Dialog):
bSizer3.Add(self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND)
bSizer1.Add(bSizer3, 0, wx.ALL | wx.EXPAND, 10)
self.input.SetFocus()
self.input.Bind(wx.EVT_CHAR, self.onChar)
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
self.SetSizer(bSizer1)
self.CenterOnParent()
self.Fit()
self.CenterOnParent()
self.input.SetFocus()
self.input.SelectAll()
def processEnter(self, evt):
self.EndModal(wx.ID_OK)

View File

@@ -94,7 +94,6 @@ class RangeChanger(wx.Dialog):
value = int(value)
value = str(value)
self.input.SetValue(value)
self.input.SelectAll()
bSizer1.Add(self.input, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, 15)
@@ -104,12 +103,13 @@ class RangeChanger(wx.Dialog):
bSizer3.Add(self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND)
bSizer1.Add(bSizer3, 0, wx.ALL | wx.EXPAND, 10)
self.input.SetFocus()
self.input.Bind(wx.EVT_CHAR, self.onChar)
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
self.SetSizer(bSizer1)
self.CenterOnParent()
self.Fit()
self.CenterOnParent()
self.input.SetFocus()
self.input.SelectAll()
def processEnter(self, evt):
self.EndModal(wx.ID_OK)

View File

@@ -72,6 +72,7 @@ AttrGroupDict = {
"specialAmmoHoldCapacity",
"specialCommandCenterHoldCapacity",
"specialPlanetaryCommoditiesHoldCapacity",
"specialColonyResourcesHoldCapacity",
"structureDamageLimit",
"specialSubsystemHoldCapacity",
"emDamageResonance",

View File

@@ -4,13 +4,18 @@ import wx
# noinspection PyPackageRequirements
import wx.lib.mixins.listctrl as listmix
from gui.utils.dark import isDark
class AutoListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ListRowHighlighter):
def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
listmix.ListCtrlAutoWidthMixin.__init__(self)
listmix.ListRowHighlighter.__init__(self)
if isDark():
listcol = wx.SystemSettings.GetColour(wx.SYS_COLOUR_LISTBOX)
highlight = listcol.ChangeLightness(110)
listmix.ListRowHighlighter.SetHighlightColor(self, highlight)
class AutoListCtrlNoHighlight(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ListRowHighlighter):
def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):

View File

@@ -2,12 +2,13 @@ import wx
from logbook import Logger
import gui.builtinMarketBrowser.pfSearchBox as SBox
from config import slotColourMap
from config import slotColourMap, slotColourMapDark
from eos.saveddata.module import Module
from gui.builtinMarketBrowser.events import ItemSelected, RECENTLY_USED_MODULES
from gui.contextMenu import ContextMenu
from gui.display import Display
from gui.utils.staticHelpers import DragDropHelper
from gui.utils.dark import isDark
from service.fit import Fit
from service.market import Market
@@ -243,6 +244,7 @@ class ItemView(Display):
def columnBackground(self, colItem, item):
if self.sFit.serviceFittingOptions["colorFitBySlot"]:
return slotColourMap.get(Module.calculateSlot(item)) or self.GetBackgroundColour()
colorMap = slotColourMapDark if isDark() else slotColourMap
return colorMap.get(Module.calculateSlot(item)) or self.GetBackgroundColour()
else:
return self.GetBackgroundColour()

View File

@@ -1,9 +1,11 @@
# noinspection PyPackageRequirements
import wx
import config
import gui.mainFrame
from gui.bitmap_loader import BitmapLoader
from gui.preferenceView import PreferenceView
from service.esi import Esi
from service.settings import EsiSettings
# noinspection PyPackageRequirements
@@ -41,38 +43,68 @@ class PFEsiPref(PreferenceView):
"due to 'Signature has expired' error")))
mainSizer.Add(self.enforceJwtExpiration, 0, wx.ALL | wx.EXPAND, 5)
self.ssoServer = wx.CheckBox(panel, wx.ID_ANY, _t("Auto-login (starts local server)"), wx.DefaultPosition,
wx.DefaultSize,
0)
self.ssoServer.SetToolTip(wx.ToolTip(_t("This allows the EVE SSO to callback to your local pyfa instance and complete the authentication process without manual intervention.")))
mainSizer.Add(self.ssoServer, 0, wx.ALL | wx.EXPAND, 5)
rbSizer = wx.BoxSizer(wx.HORIZONTAL)
self.rbMode = wx.RadioBox(panel, -1, _t("Login Authentication Method"), wx.DefaultPosition, wx.DefaultSize,
[_t('Local Server'), _t('Manual')], 1, wx.RA_SPECIFY_COLS)
self.rbMode.SetItemToolTip(0, _t("This option starts a local webserver that EVE SSO Server will call back to"
" with information about the character login."))
self.rbMode.SetItemToolTip(1, _t("This option prompts users to copy and paste information to allow for"
" character login. Use this if having issues with the local server."))
self.rbMode.SetSelection(self.settings.get('loginMode'))
self.enforceJwtExpiration.SetValue(self.settings.get("enforceJwtExpiration" or True))
self.enforceJwtExpiration.SetValue(self.settings.get("enforceJwtExpiration") or True)
self.ssoServer.SetValue(True if self.settings.get("loginMode") == 0 else False)
rbSizer.Add(self.rbMode, 1, wx.TOP | wx.RIGHT, 5)
mainSizer.Add(rbSizer, 0, wx.ALL | wx.EXPAND, 0)
self.rbMode.Bind(wx.EVT_RADIOBOX, self.OnModeChange)
esiSizer = wx.BoxSizer(wx.HORIZONTAL)
self.esiServer = wx.StaticText(panel, wx.ID_ANY, _t("Default SSO Server:"), wx.DefaultPosition, wx.DefaultSize, 0)
self.esiServer.Wrap(-1)
esiSizer.Add(self.esiServer, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.esiServer.SetToolTip(wx.ToolTip(_t('The source you choose will be used on connection.')))
self.chESIserver = wx.Choice(panel, choices=list(self.settings.keys()))
self.chESIserver.SetStringSelection(self.settings.get("server"))
esiSizer.Add(self.chESIserver, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 10)
mainSizer.Add(esiSizer, 0, wx.TOP | wx.RIGHT, 10)
self.chESIserver.Bind(wx.EVT_CHOICE, self.OnServerChange)
self.enforceJwtExpiration.Bind(wx.EVT_CHECKBOX, self.OnEnforceChange)
mainSizer.Add(rbSizer, 1, wx.ALL | wx.EXPAND, 0)
self.ssoServer.Bind(wx.EVT_CHECKBOX, self.OnModeChange)
panel.SetSizer(mainSizer)
panel.Layout()
def OnTimeoutChange(self, event):
self.settings.set('timeout', event.GetEventObject().GetValue())
event.Skip()
def OnModeChange(self, event):
self.settings.set('loginMode', event.GetInt())
self.settings.set('loginMode', 0 if self.ssoServer.GetValue() else 1)
event.Skip()
def OnEnforceChange(self, event):
self.settings.set('enforceJwtExpiration', self.enforceJwtExpiration.GetValue())
event.Skip()
def OnServerChange(self, event):
# pass
source = self.chESIserver.GetString(self.chESIserver.GetSelection())
esiService = Esi.getInstance()
# init servers
esiService.init(config.supported_servers[source])
self.settings.set("server", source)
event.Skip()
def getImage(self):
return BitmapLoader.getBitmap("eve", "gui")
PFEsiPref.register()
PFEsiPref.register()

View File

@@ -112,6 +112,7 @@ class TargetingMiscViewMinimal(StatsView):
cargoNamesOrder = OrderedDict((
("fleetHangarCapacity", _t("Fleet hangar")),
("shipMaintenanceBayCapacity", _t("Maintenance bay")),
("specialColonyResourcesHoldCapacity", _t("Infrastructure hold")),
("specialAmmoHoldCapacity", _t("Ammo hold")),
("specialFuelBayCapacity", _t("Fuel bay")),
("specialShipHoldCapacity", _t("Ship hold")),
@@ -134,6 +135,7 @@ class TargetingMiscViewMinimal(StatsView):
cargoValues = {
"main": lambda: fit.ship.getModifiedItemAttr("capacity"),
"fleetHangarCapacity": lambda: fit.ship.getModifiedItemAttr("fleetHangarCapacity"),
"specialColonyResourcesHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialColonyResourcesHoldCapacity"),
"shipMaintenanceBayCapacity": lambda: fit.ship.getModifiedItemAttr("shipMaintenanceBayCapacity"),
"specialAmmoHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialAmmoHoldCapacity"),
"specialFuelBayCapacity": lambda: fit.ship.getModifiedItemAttr("specialFuelBayCapacity"),

View File

@@ -167,7 +167,7 @@ class Miscellanea(ViewColumn):
text = "{0}/s".format(formatAmount(capPerSec, 3, 0, 3))
tooltip = "Energy neutralization per second"
return text, tooltip
elif itemGroup == "Salvager":
elif itemGroup in ("Salvager", "Salvage Drone"):
chance = stuff.getModifiedItemAttr("accessDifficultyBonus")
if not chance:
return "", None
@@ -590,7 +590,7 @@ class Miscellanea(ViewColumn):
text = "{0}/s".format(formatAmount(capPerSec, 3, 0, 3))
tooltip = "Energy neutralization per second"
return text, tooltip
elif itemGroup in ("Micro Jump Drive", "Micro Jump Field Generators"):
elif itemGroup in ("Micro Jump Drive", "Micro Jump Field Generators", "Capital Mobility Modules"):
cycleTime = stuff.getModifiedItemAttr("duration") / 1000
text = "{0}s".format(formatAmount(cycleTime, 3, 0, 3))
tooltip = "Spoolup time"

View File

@@ -39,9 +39,10 @@ from gui.builtinViewColumns.state import State
from gui.chrome_tabs import EVT_NOTEBOOK_PAGE_CHANGED
from gui.contextMenu import ContextMenu
from gui.utils.staticHelpers import DragDropHelper
from gui.utils.dark import isDark
from service.fit import Fit
from service.market import Market
from config import slotColourMap
from config import slotColourMap, slotColourMapDark, errColor, errColorDark
from gui.fitCommands.helpers import getSimilarModPositions
pyfalog = Logger(__name__)
@@ -729,7 +730,10 @@ class FittingView(d.Display):
event.Skip()
def slotColour(self, slot):
return slotColourMap.get(slot) or self.GetBackgroundColour()
if isDark():
return slotColourMapDark.get(slot) or self.GetBackgroundColour()
else:
return slotColourMap.get(slot) or self.GetBackgroundColour()
def refresh(self, stuff):
"""
@@ -774,7 +778,7 @@ class FittingView(d.Display):
if slotMap[mod.slot] or hasRestrictionOverriden: # Color too many modules as red
self.SetItemBackgroundColour(i, wx.Colour(204, 51, 51))
self.SetItemBackgroundColour(i, errColorDark if isDark() else errColor)
elif sFit.serviceFittingOptions["colorFitBySlot"]: # Color by slot it enabled
self.SetItemBackgroundColour(i, self.slotColour(mod.slot))

View File

@@ -371,7 +371,7 @@ class SkillTreeView(wx.Panel):
bSizerButtons.AddStretchSpacer()
importExport = ((_t("Import skills from clipboard"), wx.ART_FILE_OPEN, "import"),
(_t("Export skills from clipboard"), wx.ART_FILE_SAVE_AS, "export"))
(_t("Export skills to clipboard"), wx.ART_FILE_SAVE_AS, "export"))
for tooltip, art, attr in importExport:
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
@@ -446,6 +446,7 @@ class SkillTreeView(wx.Panel):
text = fromClipboard().strip()
if text:
sCharacter = Character.getInstance()
char = self.charEditor.entityEditor.getActiveEntity()
try:
lines = text.splitlines()
@@ -455,7 +456,7 @@ class SkillTreeView(wx.Panel):
skill, level = s.rsplit(None, 1)[0], arabicOrRomanToInt(s.rsplit(None, 1)[1])
skill = char.getSkill(skill)
if skill:
skill.setLevel(level, ignoreRestrict=True)
sCharacter.changeLevel(char.ID, skill.item.ID, level)
except (KeyboardInterrupt, SystemExit):
raise
@@ -806,7 +807,12 @@ class APIView(wx.Panel):
self.SetSizer(pmainSizer)
self.Layout()
self.ssoListChanged(None)
try:
self.ssoListChanged(None)
except (KeyboardInterrupt, SystemExit):
raise
except:
pass
def ssoCharChanged(self, event):
sChar = Character.getInstance()
@@ -858,7 +864,7 @@ class APIView(wx.Panel):
noneID = self.charChoice.Append(_t("None"), None)
for char in ssoChars:
currId = self.charChoice.Append(char.characterName, char.ID)
currId = self.charChoice.Append(char.characterDisplay, char.ID)
if sso is not None and char.ID == sso.ID:
self.charChoice.SetSelection(currId)

View File

@@ -29,8 +29,9 @@ class Display(wx.ListCtrl):
DEFAULT_COLS = None
def __init__(self, parent, size=wx.DefaultSize, style=0):
wx.ListCtrl.__init__(self, parent, size=size, style=wx.LC_REPORT | style)
wx.ListCtrl.__init__(self)
self.EnableSystemTheme(False)
self.Create(parent, size=size, style=wx.LC_REPORT | style)
self.imageList = CachingImageList(16, 16)
self.SetImageList(self.imageList, wx.IMAGE_LIST_SMALL)
self.activeColumns = []

View File

@@ -96,7 +96,7 @@ class EveFittings(AuxiliaryFrame):
self.charChoice.Clear()
for char in chars:
self.charChoice.Append(char.characterName, char.ID)
self.charChoice.Append(char.characterDisplay, char.ID)
if len(chars) > 0:
self.charChoice.SetSelection(0)
@@ -227,21 +227,6 @@ class EveFittings(AuxiliaryFrame):
self.fitView.update([])
class ESIServerExceptionHandler:
def __init__(self, parentWindow, ex):
pyfalog.error(ex)
with wx.MessageDialog(
parentWindow,
_t("There was an issue starting up the localized server, try setting "
"Login Authentication Method to Manual by going to Preferences -> EVE SS0 -> "
"Login Authentication Method. If this doesn't fix the problem please file an "
"issue on Github."),
_t("Add Character Error"),
wx.OK | wx.ICON_ERROR
) as dlg:
dlg.ShowModal()
class ESIExceptionHandler:
# todo: make this a generate excetpion handler for all calls
def __init__(self, ex):
@@ -348,7 +333,7 @@ class ExportToEve(AuxiliaryFrame):
self.charChoice.Clear()
for char in chars:
self.charChoice.Append(char.characterName, char.ID)
self.charChoice.Append(char.characterDisplay, char.ID)
if len(chars) > 0:
self.charChoice.SetSelection(0)
@@ -434,6 +419,7 @@ class SsoCharacterMgmt(AuxiliaryFrame):
self.lcCharacters.InsertColumn(0, heading=_t('Character'))
self.lcCharacters.InsertColumn(1, heading=_t('Character ID'))
self.lcCharacters.InsertColumn(2, heading=_t('Server'))
self.popCharList()
@@ -496,9 +482,11 @@ class SsoCharacterMgmt(AuxiliaryFrame):
self.lcCharacters.InsertItem(index, char.characterName)
self.lcCharacters.SetItem(index, 1, str(char.characterID))
self.lcCharacters.SetItemData(index, char.ID)
self.lcCharacters.SetItem(index, 2, char.server or "<unknown>")
self.lcCharacters.SetColumnWidth(0, wx.LIST_AUTOSIZE)
self.lcCharacters.SetColumnWidth(1, wx.LIST_AUTOSIZE)
self.lcCharacters.SetColumnWidth(2, wx.LIST_AUTOSIZE)
def addChar(self, event):
try:
@@ -506,8 +494,6 @@ class SsoCharacterMgmt(AuxiliaryFrame):
sEsi.login()
except (KeyboardInterrupt, SystemExit):
raise
except Exception as ex:
ESIServerExceptionHandler(self, ex)
def delChar(self, event):
item = self.lcCharacters.GetFirstSelected()

View File

@@ -61,10 +61,11 @@ from gui.statsPane import StatsPane
from gui.targetProfileEditor import TargetProfileEditor
from gui.updateDialog import UpdateDialog
from gui.utils.clipboard import fromClipboard
from gui.utils.progressHelper import ProgressHelper
from service.character import Character
from service.esi import Esi
from service.fit import Fit
from service.port import IPortUser, Port
from service.port import Port
from service.price import Price
from service.settings import HTMLExportSettings, SettingsProvider
from service.update import Update
@@ -130,7 +131,6 @@ class OpenFitsThread(threading.Thread):
self.running = False
# todo: include IPortUser again
class MainFrame(wx.Frame):
__instance = None
@@ -845,14 +845,15 @@ class MainFrame(wx.Frame):
style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE
) as dlg:
if dlg.ShowModal() == wx.ID_OK:
self.progressDialog = wx.ProgressDialog(
_t("Importing fits"),
" " * 100, # set some arbitrary spacing to create width in window
parent=self,
style=wx.PD_CAN_ABORT | wx.PD_SMOOTH | wx.PD_ELAPSED_TIME | wx.PD_APP_MODAL
)
Port.importFitsThreaded(dlg.GetPaths(), self)
self.progressDialog.ShowModal()
# set some arbitrary spacing to create width in window
progress = ProgressHelper(message=" " * 100, callback=self._openAfterImport)
call = (Port.importFitsThreaded, [dlg.GetPaths(), progress], {})
self.handleProgress(
title=_t("Importing fits"),
style=wx.PD_CAN_ABORT | wx.PD_SMOOTH | wx.PD_APP_MODAL | wx.PD_AUTO_HIDE,
call=call,
progress=progress,
errMsgLbl=_t("Import Error"))
def backupToXml(self, event):
""" Back up all fits to EVE XML file """
@@ -863,32 +864,30 @@ class MainFrame(wx.Frame):
_t("Save Backup As..."),
wildcard=_t("EVE XML fitting file") + " (*.xml)|*.xml",
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT,
defaultFile=defaultFile,
) as dlg:
if dlg.ShowModal() == wx.ID_OK:
filePath = dlg.GetPath()
defaultFile=defaultFile) as fileDlg:
if fileDlg.ShowModal() == wx.ID_OK:
filePath = fileDlg.GetPath()
if '.' not in os.path.basename(filePath):
filePath += ".xml"
sFit = Fit.getInstance()
max_ = sFit.countAllFits()
self.progressDialog = wx.ProgressDialog(
_t("Backup fits"),
_t("Backing up {} fits to: {}").format(max_, filePath),
maximum=max_,
parent=self,
style=wx.PD_CAN_ABORT | wx.PD_SMOOTH | wx.PD_ELAPSED_TIME | wx.PD_APP_MODAL
)
Port.backupFits(filePath, self)
self.progressDialog.ShowModal()
fitAmount = Fit.getInstance().countAllFits()
progress = ProgressHelper(
message=_t("Backing up {} fits to: {}").format(fitAmount, filePath),
maximum=fitAmount + 1)
call = (Port.backupFits, [filePath, progress], {})
self.handleProgress(
title=_t("Backup fits"),
style=wx.PD_CAN_ABORT | wx.PD_SMOOTH | wx.PD_ELAPSED_TIME | wx.PD_APP_MODAL | wx.PD_AUTO_HIDE,
call=call,
progress=progress,
errMsgLbl=_t("Export Error"))
def exportHtml(self, event):
from gui.utils.exportHtml import exportHtml
sFit = Fit.getInstance()
settings = HTMLExportSettings.getInstance()
max_ = sFit.countAllFits()
path = settings.getPath()
if not os.path.isdir(os.path.dirname(path)):
@@ -903,82 +902,44 @@ class MainFrame(wx.Frame):
) as dlg:
if dlg.ShowModal() == wx.ID_OK:
return
progress = ProgressHelper(
message=_t("Generating HTML file at: {}").format(path),
maximum=sFit.countAllFits() + 1)
call = (exportHtml.getInstance().refreshFittingHtml, [True, progress], {})
self.handleProgress(
title=_t("Backup fits"),
style=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME,
call=call,
progress=progress)
self.progressDialog = wx.ProgressDialog(
_t("Backup fits"),
_t("Generating HTML file at: {}").format(path),
maximum=max_, parent=self,
style=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME)
exportHtml.getInstance().refreshFittingHtml(True, self.backupCallback)
self.progressDialog.ShowModal()
def backupCallback(self, info):
if info == -1:
self.closeProgressDialog()
else:
self.progressDialog.Update(info)
def on_port_process_start(self):
# flag for progress dialog.
self.__progress_flag = True
def on_port_processing(self, action, data=None):
# 2017/03/29 NOTE: implementation like interface
wx.CallAfter(
self._on_port_processing, action, data
)
return self.__progress_flag
def _on_port_processing(self, action, data):
"""
While importing fits from file, the logic calls back to this function to
update progress bar to show activity. XML files can contain multiple
ships with multiple fits, whereas EFT cfg files contain many fits of
a single ship. When iterating through the files, we update the message
when we start a new file, and then Pulse the progress bar with every fit
that is processed.
action : a flag that lets us know how to deal with :data
None: Pulse the progress bar
1: Replace message with data
other: Close dialog and handle based on :action (-1 open fits, -2 display error)
"""
_message = None
if action & IPortUser.ID_ERROR:
self.closeProgressDialog()
_message = _t("Import Error") if action & IPortUser.PROCESS_IMPORT else _t("Export Error")
def handleProgress(self, title, style, call, progress, errMsgLbl=None):
extraArgs = {}
if progress.maximum is not None:
extraArgs['maximum'] = progress.maximum
with wx.ProgressDialog(
parent=self,
title=title,
message=progress.message,
style=style,
**extraArgs
) as dlg:
func, args, kwargs = call
func(*args, **kwargs)
while progress.working:
wx.MilliSleep(250)
wx.Yield()
(progress.dlgWorking, skip) = dlg.Update(progress.current, progress.message)
if progress.error and errMsgLbl:
with wx.MessageDialog(
self,
_t("The following error was generated") +
f"\n\n{data}\n\n" +
f"\n\n{progress.error}\n\n" +
_t("Be aware that already processed fits were not saved"),
_message, wx.OK | wx.ICON_ERROR
errMsgLbl, wx.OK | wx.ICON_ERROR
) as dlg:
dlg.ShowModal()
return
# data is str
if action & IPortUser.PROCESS_IMPORT:
if action & IPortUser.ID_PULSE:
_message = ()
# update message
elif action & IPortUser.ID_UPDATE: # and data != self.progressDialog.message:
_message = data
if _message is not None:
self.__progress_flag, _unuse = self.progressDialog.Pulse(_message)
else:
self.closeProgressDialog()
if action & IPortUser.ID_DONE:
self._openAfterImport(data)
# data is tuple(int, str)
elif action & IPortUser.PROCESS_EXPORT:
if action & IPortUser.ID_DONE:
self.closeProgressDialog()
else:
self.__progress_flag, _unuse = self.progressDialog.Update(data[0], data[1])
elif progress.callback:
progress.callback(*progress.cbArgs)
def _openAfterImport(self, fits):
if len(fits) > 0:
@@ -988,6 +949,8 @@ class MainFrame(wx.Frame):
wx.PostEvent(self.shipBrowser, Stage3Selected(shipID=fit.shipID, back=True))
else:
fits.sort(key=lambda _fit: (_fit.ship.item.name, _fit.name))
# Show 100 fits max
fits = fits[:100]
results = []
for fit in fits:
results.append((
@@ -999,15 +962,6 @@ class MainFrame(wx.Frame):
))
wx.PostEvent(self.shipBrowser, ImportSelected(fits=results, back=True))
def closeProgressDialog(self):
# Windows apparently handles ProgressDialogs differently. We can
# simply Destroy it here, but for other platforms we must Close it
if 'wxMSW' in wx.PlatformInfo:
self.progressDialog.Destroy()
else:
self.progressDialog.EndModal(wx.ID_OK)
self.progressDialog.Close()
def importCharacter(self, event):
""" Imports character XML file from EVE API """
with wx.FileDialog(

View File

@@ -2,30 +2,48 @@ import wx
import gui.mainFrame
import webbrowser
import gui.globalEvents as GE
import config
import time
from service.settings import EsiSettings
_t = wx.GetTranslation
class SsoLogin(wx.Dialog):
def __init__(self):
mainFrame = gui.mainFrame.MainFrame.getInstance()
def __init__(self, server: config.ApiServer, start_local_server=True):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
from service.esi import Esi
super().__init__(
mainFrame, id=wx.ID_ANY, title=_t("SSO Login"), style=wx.DEFAULT_DIALOG_STYLE,
self.mainFrame, id=wx.ID_ANY, title=_t("SSO Login"), style=wx.DEFAULT_DIALOG_STYLE,
size=wx.Size(450, 240) if "wxGTK" in wx.PlatformInfo else wx.Size(400, 240))
bSizer1 = wx.BoxSizer(wx.VERTICAL)
text = wx.StaticText(self, wx.ID_ANY, _t("Copy and paste the block of text provided by pyfa.io"))
bSizer1.Add(text, 0, wx.ALL | wx.EXPAND, 10)
if start_local_server:
text = wx.StaticText(self, wx.ID_ANY, _t("Waiting for character login through EVE Single Sign-On."))
bSizer1.Add(text, 0, wx.ALL | wx.EXPAND, 10)
bSizer1.Add(wx.StaticLine(self, wx.ID_ANY), 0, wx.EXPAND, 15)
text = wx.StaticText(self, wx.ID_ANY, _t("If auto-login fails, copy and paste the token provided by pyfa.io"))
bSizer1.Add(text, 0, wx.ALL | wx.EXPAND, 10)
elif server.name == "Serenity":
text = wx.StaticText(self, wx.ID_ANY, _t("Please copy and paste the url when your authorization is completed"))
bSizer1.Add(text, 0, wx.ALL | wx.EXPAND, 10)
else:
text = wx.StaticText(self, wx.ID_ANY, _t("Please copy and paste the token provided by pyfa.io"))
bSizer1.Add(text, 0, wx.ALL | wx.EXPAND, 10)
self.ssoInfoCtrl = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, (-1, -1), style=wx.TE_MULTILINE)
self.ssoInfoCtrl.SetFont(wx.Font(8, wx.FONTFAMILY_TELETYPE, wx.NORMAL, wx.NORMAL))
self.ssoInfoCtrl.Layout()
self.ssoInfoCtrl.Bind(wx.EVT_TEXT, self.OnTextEnter)
bSizer1.Add(self.ssoInfoCtrl, 1, wx.LEFT | wx.RIGHT | wx.EXPAND, 10)
self.Esisettings = EsiSettings.getInstance()
bSizer3 = wx.BoxSizer(wx.VERTICAL)
bSizer3.Add(wx.StaticLine(self, wx.ID_ANY), 0, wx.BOTTOM | wx.EXPAND, 10)
@@ -34,51 +52,43 @@ class SsoLogin(wx.Dialog):
self.SetSizer(bSizer1)
self.Center()
from service.esi import Esi
self.sEsi = Esi.getInstance()
uri = self.sEsi.get_login_uri(None)
webbrowser.open(uri)
class SsoLoginServer(wx.Dialog):
def __init__(self, port):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
super().__init__(self.mainFrame, id=wx.ID_ANY, title=_t("SSO Login"), size=(-1, -1), style=wx.DEFAULT_DIALOG_STYLE)
from service.esi import Esi
self.sEsi = Esi.getInstance()
serverAddr = self.sEsi.startServer(port)
serverAddr = self.sEsi.startServer(0) if start_local_server else None
uri = self.sEsi.get_login_uri(serverAddr)
bSizer1 = wx.BoxSizer(wx.VERTICAL)
self.mainFrame.Bind(GE.EVT_SSO_LOGIN, self.OnLogin)
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
if server.name == "Serenity":
webbrowser.open(config.SSO_LOGOFF_SERENITY)
time.sleep(1)
text = wx.StaticText(self, wx.ID_ANY, _t("Waiting for character login through EVE Single Sign-On."))
bSizer1.Add(text, 0, wx.ALL | wx.EXPAND, 10)
bSizer3 = wx.BoxSizer(wx.VERTICAL)
bSizer3.Add(wx.StaticLine(self, wx.ID_ANY), 0, wx.BOTTOM | wx.EXPAND, 10)
bSizer3.Add(self.CreateStdDialogButtonSizer(wx.CANCEL), 0, wx.EXPAND)
bSizer1.Add(bSizer3, 0, wx.BOTTOM | wx.RIGHT | wx.LEFT | wx.EXPAND, 10)
self.SetSizer(bSizer1)
self.Fit()
self.Center()
self.okBtn = self.FindWindow(wx.ID_OK)
self.okBtn.Enable(False)
# Ensure we clean up once they hit the "OK" button
self.okBtn.Bind(wx.EVT_BUTTON, self.OnDestroy)
webbrowser.open(uri)
self.mainFrame.Bind(GE.EVT_SSO_LOGIN, self.OnLogin)
# Ensure we clean up if ESC is pressed
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
def OnTextEnter(self, event):
t = event.String.strip()
if t == "":
self.okBtn.Enable(False)
else:
self.okBtn.Enable(True)
event.Skip()
def OnLogin(self, event):
self.EndModal(wx.ID_OK)
# This would normally happen if it was logged in via server auto-login. In this case, the modal is done, we effectively want to cancel out
self.EndModal(wx.ID_CANCEL)
event.Skip()
def OnDestroy(self, event):
# Clean up by unbinding some events and stopping the server
self.mainFrame.Unbind(GE.EVT_SSO_LOGIN, handler=self.OnLogin)
if self:
self.Unbind(wx.EVT_WINDOW_DESTROY, handler=self.OnDestroy)
self.sEsi.stopServer()
event.Skip()

12
gui/utils/dark.py Normal file
View File

@@ -0,0 +1,12 @@
import wx
def isDark():
if 'wxMSW' in wx.PlatformInfo:
return False
try:
return wx.SystemSettings.GetAppearance().IsDark()
except (KeyboardInterrupt, SystemExit):
raise
except:
return False

View File

@@ -26,20 +26,20 @@ class exportHtml:
def __init__(self):
self.thread = exportHtmlThread()
def refreshFittingHtml(self, force=False, callback=False):
def refreshFittingHtml(self, force=False, progress=None):
settings = HTMLExportSettings.getInstance()
if force or settings.getEnabled():
self.thread.stop()
self.thread = exportHtmlThread(callback)
self.thread = exportHtmlThread(progress)
self.thread.start()
class exportHtmlThread(threading.Thread):
def __init__(self, callback=False):
def __init__(self, progress=False):
threading.Thread.__init__(self)
self.name = "HTMLExport"
self.callback = callback
self.progress = progress
self.stopRunning = False
def stop(self):
@@ -72,11 +72,13 @@ class exportHtmlThread(threading.Thread):
pass
except (KeyboardInterrupt, SystemExit):
raise
except Exception as ex:
pass
if self.callback:
wx.CallAfter(self.callback, -1)
except Exception as e:
if self.progress:
self.progress.error = f'{e}'
finally:
if self.progress:
self.progress.current += 1
self.progress.workerWorking = False
def generateFullHTML(self, sMkt, sFit, dnaUrl):
""" Generate the complete HTML with styling and javascript """
@@ -171,13 +173,13 @@ class exportHtmlThread(threading.Thread):
</head>
<body>
<div id="canvas" data-role="page">
<div style="text-align: center;"><strong>Last updated:</strong> %s <small>(<span class="timer"></span>)</small></div>
<div data-role="header">
<h1>Pyfa fits</h1>
<h1>Pyfa fits by Group</h1>
</div>
<div data-role="content">
<div style="text-align: center;"><strong>Last updated:</strong> %s <small>(<span class="timer"></span>)</small></div>
""" % (time.time(), dnaUrl, localDate)
HTML += ' <ul data-role="listview" class="ui-listview-outer" data-inset="true" data-filter="true">\n'
categoryList = list(sMkt.getShipRoot())
categoryList.sort(key=lambda _ship: _ship.name)
@@ -214,7 +216,9 @@ class exportHtmlThread(threading.Thread):
eftFit = Port.exportEft(getFit(fit[0]), options={
PortEftOptions.IMPLANTS: True,
PortEftOptions.MUTATIONS: True,
PortEftOptions.LOADED_CHARGES: True})
PortEftOptions.LOADED_CHARGES: True,
PortEftOptions.BOOSTERS: True,
PortEftOptions.CARGO: True})
HTMLfit = (
' <li data-role="collapsible" data-iconpos="right" data-shadow="false" '
@@ -234,8 +238,8 @@ class exportHtmlThread(threading.Thread):
pyfalog.warning("Failed to export line")
continue
finally:
if self.callback:
wx.CallAfter(self.callback, count)
if self.progress:
self.progress.current = count
count += 1
HTMLgroup += HTMLship + (' </ul>\n'
' </li>\n')
@@ -254,6 +258,68 @@ class exportHtmlThread(threading.Thread):
HTML += """
</ul>
</div>
<div data-role="header">
<h1>Pyfa fits by Name</h1>
</div>
<div data-role="content">
"""
HTML += ' <ul data-role="listview" class="ui-listview-outer" data-inset="true" data-filter="true">\n'
categoryList = list(sMkt.getShipRoot())
categoryList.sort(key=lambda _ship: _ship.name)
count = 0
for group in categoryList:
# init market group string to give ships something to attach to
HTMLgroup = ''
ships = list(sMkt.getShipList(group.ID))
ships.sort(key=lambda _ship: _ship.name)
# Keep track of how many ships per group
groupFits = 0
for ship in ships:
fits = sFit.getFitsWithShip(ship.ID)
if len(fits) > 0:
groupFits += len(fits)
for fit in fits:
if self.stopRunning:
return
try:
eftFit = Port.exportEft(getFit(fit[0]), options={
PortEftOptions.IMPLANTS: True,
PortEftOptions.MUTATIONS: True,
PortEftOptions.LOADED_CHARGES: True,
PortEftOptions.BOOSTERS: True,
PortEftOptions.CARGO: True})
HTMLfit = (
' <li data-role="collapsible" data-iconpos="right" data-shadow="false" '
'data-corners="false">\n'
' <h2>' + ship.name + " - " + fit[1] + '</h2>\n'
' <ul data-role="listview" data-shadow="false" data-inset="true" '
'data-corners="false">\n'
)
HTMLfit += ' <li><pre>' + eftFit + '\n </pre></li>\n'
HTMLfit += ' </ul>\n </li>\n'
HTML += HTMLfit
except (KeyboardInterrupt, SystemExit):
raise
except:
pyfalog.warning("Failed to export line")
continue
finally:
if self.progress:
self.progress.current = count
count += 1
HTML += """
</ul>
</div>
</div>
</body>
</html>"""
@@ -291,7 +357,7 @@ class exportHtmlThread(threading.Thread):
pyfalog.error("Failed to export line")
continue
finally:
if self.callback:
wx.CallAfter(self.callback, count)
if self.progress:
self.progress.current = count
count += 1
return HTML

View File

@@ -58,6 +58,9 @@ class InputValidator(metaclass=ABCMeta):
class FloatBox(wx.TextCtrl):
def __init__(self, parent, value, id=wx.ID_ANY, style=0, validator=None, **kwargs):
# Workaround for #2591
if 'wxMac' in wx.PlatformInfo and 'size' not in kwargs:
kwargs['size'] = wx.Size(97, 26)
super().__init__(parent=parent, id=id, style=style, **kwargs)
self.Bind(wx.EVT_TEXT, self.OnText)
self._storedValue = ''
@@ -107,6 +110,9 @@ class FloatBox(wx.TextCtrl):
class FloatRangeBox(wx.TextCtrl):
def __init__(self, parent, value, id=wx.ID_ANY, style=0, **kwargs):
# Workaround for #2591
if 'wxMac' in wx.PlatformInfo and 'size' not in kwargs:
kwargs['size'] = wx.Size(97, 26)
super().__init__(parent=parent, id=id, style=style, **kwargs)
self.Bind(wx.EVT_TEXT, self.OnText)
self._storedValue = ''

View File

@@ -0,0 +1,19 @@
class ProgressHelper:
def __init__(self, message, maximum=None, callback=None):
self.message = message
self.current = 0
self.maximum = maximum
self.workerWorking = True
self.dlgWorking = True
self.error = None
self.callback = callback
self.cbArgs = []
@property
def working(self):
return self.workerWorking and self.dlgWorking and not self.error
@property
def userCancelled(self):
return not self.dlgWorking

BIN
imgs/icons/10848@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

BIN
imgs/icons/10848@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
imgs/icons/24603@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 B

BIN
imgs/icons/24603@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 741 B

After

Width:  |  Height:  |  Size: 724 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 724 B

After

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 887 B

After

Width:  |  Height:  |  Size: 863 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 863 B

After

Width:  |  Height:  |  Size: 887 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 795 B

After

Width:  |  Height:  |  Size: 787 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 787 B

After

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 908 B

After

Width:  |  Height:  |  Size: 893 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 893 B

After

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 783 B

After

Width:  |  Height:  |  Size: 760 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 760 B

After

Width:  |  Height:  |  Size: 783 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 861 B

After

Width:  |  Height:  |  Size: 847 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 847 B

After

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 833 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 814 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

BIN
imgs/icons/25994@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 918 B

BIN
imgs/icons/25994@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
imgs/icons/26002@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 B

BIN
imgs/icons/26002@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
imgs/icons/26004@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 B

BIN
imgs/icons/26004@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
imgs/icons/26005@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 B

BIN
imgs/icons/26005@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
imgs/icons/26016@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 B

BIN
imgs/icons/26016@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
imgs/icons/26017@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

BIN
imgs/icons/26017@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
imgs/icons/26018@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

BIN
imgs/icons/26018@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
imgs/icons/26019@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

BIN
imgs/icons/26019@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
imgs/icons/26038@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 980 B

BIN
imgs/icons/26038@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
imgs/icons/26039@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 B

BIN
imgs/icons/26039@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
imgs/icons/26040@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 B

BIN
imgs/icons/26040@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
imgs/icons/26041@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

BIN
imgs/icons/26041@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
imgs/icons/26042@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 B

BIN
imgs/icons/26042@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
imgs/icons/26043@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 961 B

BIN
imgs/icons/26043@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
imgs/icons/26044@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

BIN
imgs/icons/26044@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Some files were not shown because too many files have changed in this diff Show More