Compare commits
270 Commits
v2.55.0dev
...
v2.58.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0fbb318d8a | ||
|
|
cd013e8287 | ||
|
|
e667453c1e | ||
|
|
24e2db0f88 | ||
|
|
3c47f8c6bb | ||
|
|
42c2b3f253 | ||
|
|
71d6830ac0 | ||
|
|
ac2fb01a7c | ||
|
|
fc66c212fc | ||
|
|
9625fafda7 | ||
|
|
6b1aca4306 | ||
|
|
fd5a094304 | ||
|
|
a3142ff62f | ||
|
|
58ebfd3643 | ||
|
|
e272267842 | ||
|
|
b0256542bc | ||
|
|
9b8fd24987 | ||
|
|
9c68889a6d | ||
|
|
a4ed6e8066 | ||
|
|
9fe8163a69 | ||
|
|
9f9b496726 | ||
|
|
3b8fa68a4c | ||
|
|
9f5a649b04 | ||
|
|
fb45736c14 | ||
|
|
b8a58fc7a6 | ||
|
|
b04c521805 | ||
|
|
526695fa9a | ||
|
|
d6be77d107 | ||
|
|
907da343b1 | ||
|
|
3fadccc715 | ||
|
|
82a912858f | ||
|
|
cc1fdddc0a | ||
|
|
e314ecf887 | ||
|
|
94b1c8b029 | ||
|
|
6e3b7ff132 | ||
|
|
ff14855808 | ||
|
|
4761857b84 | ||
|
|
bb53e75bfe | ||
|
|
cc146401b6 | ||
|
|
465e43ed45 | ||
|
|
f89a8a9f87 | ||
|
|
768c417c8e | ||
|
|
494b6353b8 | ||
|
|
69ef7825af | ||
|
|
e0a71754ce | ||
|
|
b959d9dd07 | ||
|
|
2c2455a644 | ||
|
|
e2dbfb52e9 | ||
|
|
612591b59b | ||
|
|
3e00d5d4ae | ||
|
|
539be1527b | ||
|
|
d00db1e167 | ||
|
|
fc6d5fea48 | ||
|
|
ecf4d6c0de | ||
|
|
f5f7f92166 | ||
|
|
f5d7e754a6 | ||
|
|
be85080d8d | ||
|
|
6ed34be118 | ||
|
|
59dceadfee | ||
|
|
2a74c779c8 | ||
|
|
f63331454b | ||
|
|
d105748348 | ||
|
|
cdd7077346 | ||
|
|
f965497186 | ||
|
|
6b06b5b46c | ||
|
|
d1e19406d0 | ||
|
|
2a3c586be6 | ||
|
|
23f014c32e | ||
|
|
0ac6a14ebb | ||
|
|
0dc2632fc4 | ||
|
|
fc43691275 | ||
|
|
21a9b779f3 | ||
|
|
b8dc55a3a6 | ||
|
|
b7a5b33ff6 | ||
|
|
3593d16bd1 | ||
|
|
57830fd5a5 | ||
|
|
313d793175 | ||
|
|
f8e20e23bb | ||
|
|
1959681250 | ||
|
|
0192c77df1 | ||
|
|
b709629d7b | ||
|
|
3071aead5c | ||
|
|
3f2df69022 | ||
|
|
e9a48817a7 | ||
|
|
ed19ea5f2f | ||
|
|
19366a09b4 | ||
|
|
f8f01cd63c | ||
|
|
21a0e2b9c5 | ||
|
|
0ba8ba33ef | ||
|
|
346184d06a | ||
|
|
46fc9e65bb | ||
|
|
2d51da4d02 | ||
|
|
b5e77415cf | ||
|
|
4c75daf36c | ||
|
|
4a120b8abf | ||
|
|
fc43510fbc | ||
|
|
28c7ff54aa | ||
|
|
89f1e0a126 | ||
|
|
b6ff1cada9 | ||
|
|
cc0d6465d6 | ||
|
|
c49a914584 | ||
|
|
e6e6568571 | ||
|
|
7120000202 | ||
|
|
c3f7078053 | ||
|
|
b70f02fa3e | ||
|
|
8d893ce648 | ||
|
|
c230480464 | ||
|
|
da7a4a2df0 | ||
|
|
62bde4b8c9 | ||
|
|
43967b70ae | ||
|
|
782c007200 | ||
|
|
5812d333d9 | ||
|
|
c461bf469e | ||
|
|
d5c8c92b48 | ||
|
|
1abffd6c5d | ||
|
|
a824cc5e48 | ||
|
|
db7afffd65 | ||
|
|
4d02a1292f | ||
|
|
00f72294d4 | ||
|
|
0d45be0597 | ||
|
|
f60090fc79 | ||
|
|
713807df13 | ||
|
|
c020bd8898 | ||
|
|
39ee8586d4 | ||
|
|
653a1585dc | ||
|
|
2dcf011020 | ||
|
|
555e72a27a | ||
|
|
85e740d75a | ||
|
|
d604ed300a | ||
|
|
3aea4e5f23 | ||
|
|
a54adddc74 | ||
|
|
dda397fea3 | ||
|
|
3cd718350e | ||
|
|
e87860a700 | ||
|
|
451d21eaa0 | ||
|
|
718f9ef859 | ||
|
|
193adc4ba5 | ||
|
|
cdfa52e9ed | ||
|
|
2752b288ad | ||
|
|
8dce968780 | ||
|
|
b889da7e68 | ||
|
|
0dd7dea708 | ||
|
|
8af1c8da7d | ||
|
|
8d4f83156d | ||
|
|
798bdf3fe0 | ||
|
|
a7cf4aab76 | ||
|
|
d910e324f3 | ||
|
|
d800db5ccb | ||
|
|
6c5d0a3e4f | ||
|
|
9389a0421f | ||
|
|
6f3ab6cee8 | ||
|
|
258dcd49a0 | ||
|
|
5f0320d1e3 | ||
|
|
54052899f9 | ||
|
|
eda53e9318 | ||
|
|
4d8a891fd8 | ||
|
|
2d4b97afe6 | ||
|
|
49d1ec17e8 | ||
|
|
cfecacacf9 | ||
|
|
a9112c04a3 | ||
|
|
5f2a74691c | ||
|
|
17c22df0f4 | ||
|
|
c53bc82929 | ||
|
|
7113f41b9a | ||
|
|
aa66d63085 | ||
|
|
140ee70dc3 | ||
|
|
5023a6cbae | ||
|
|
aafa77baed | ||
|
|
16dabd57ca | ||
|
|
8668d2dd55 | ||
|
|
5c5f37a9ae | ||
|
|
621c36f1cd | ||
|
|
be2cc523c2 | ||
|
|
bd83c403a1 | ||
|
|
043f533a10 | ||
|
|
57a23affd0 | ||
|
|
b678152ac6 | ||
|
|
747bbc8200 | ||
|
|
871cf42d88 | ||
|
|
28533d60d3 | ||
|
|
ca12b3c94f | ||
|
|
81e449dd83 | ||
|
|
368f2c33a9 | ||
|
|
c445bb4423 | ||
|
|
9b216b5d48 | ||
|
|
4b932d210f | ||
|
|
a1ca29fb30 | ||
|
|
876c85ee19 | ||
|
|
ac1d935712 | ||
|
|
2ccc829d3b | ||
|
|
061ab27286 | ||
|
|
d127dd9a7e | ||
|
|
6d13ab8bcb | ||
|
|
e5d95dd4d8 | ||
|
|
08c5c9a4b7 | ||
|
|
115ea9a36c | ||
|
|
a484698a9d | ||
|
|
bafaed1d81 | ||
|
|
c56f274a5f | ||
|
|
02f7fbf1b1 | ||
|
|
96214eaa27 | ||
|
|
2fef60eaaa | ||
|
|
807622a1ec | ||
|
|
d126b62d63 | ||
|
|
9e50de96f3 | ||
|
|
e67083a79b | ||
|
|
b103e576d2 | ||
|
|
b472adb404 | ||
|
|
7e5150be8c | ||
|
|
261d510ccb | ||
|
|
858b0b243a | ||
|
|
53385f2458 | ||
|
|
7d3371c379 | ||
|
|
d94116ea1c | ||
|
|
5d95663f63 | ||
|
|
128de58b83 | ||
|
|
47eb8d422f | ||
|
|
38ddf83da4 | ||
|
|
58142a8641 | ||
|
|
d86f0f40ac | ||
|
|
62944e4ce3 | ||
|
|
812201d8b3 | ||
|
|
52abd5620f | ||
|
|
b21b756fa6 | ||
|
|
492adb4dfd | ||
|
|
e47112a1f2 | ||
|
|
5fa7b2c86a | ||
|
|
f6120f09ac | ||
|
|
00a6835f50 | ||
|
|
4995c7994f | ||
|
|
620ce89a05 | ||
|
|
73dc056e61 | ||
|
|
97625d11ab | ||
|
|
21bd4272d9 | ||
|
|
332c91d661 | ||
|
|
719125657f | ||
|
|
9621a54257 | ||
|
|
bfc580cf7c | ||
|
|
fd2f76ee41 | ||
|
|
9e01d15e60 | ||
|
|
23ee164a76 | ||
|
|
99ddc36027 | ||
|
|
a33f48a83b | ||
|
|
11c060103a | ||
|
|
ac6b6f70eb | ||
|
|
baf10b24d6 | ||
|
|
0ab485115c | ||
|
|
27101732ca | ||
|
|
ed48a8b5d0 | ||
|
|
5a6fe373f1 | ||
|
|
3c6eb6d054 | ||
|
|
dc997f0dc4 | ||
|
|
f8895a14c5 | ||
|
|
22eabcea8d | ||
|
|
ccd3498594 | ||
|
|
14afc83e86 | ||
|
|
216dd2a787 | ||
|
|
71d088b90a | ||
|
|
17712d8b7d | ||
|
|
4a224ea9a5 | ||
|
|
6664b5620a | ||
|
|
a98e898bd8 | ||
|
|
e98ae5de39 | ||
|
|
a51fbbc238 | ||
|
|
f9b4c7b5ea | ||
|
|
4e83f52532 | ||
|
|
ec0b543393 | ||
|
|
cff94a12ee | ||
|
|
da39975ba8 | ||
|
|
82515343ee |
104
.appveyor.yml
@@ -1,75 +1,48 @@
|
|||||||
image:
|
image:
|
||||||
- Visual Studio 2019
|
- Ubuntu2204
|
||||||
- Ubuntu
|
- Visual Studio 2022
|
||||||
- macos
|
- macos-catalina
|
||||||
clone_depth: 1
|
|
||||||
for:
|
for:
|
||||||
-
|
-
|
||||||
matrix:
|
matrix:
|
||||||
only:
|
only:
|
||||||
- image: Ubuntu
|
- image: Ubuntu2204
|
||||||
environment:
|
environment:
|
||||||
APPVEYOR_SSH_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJDW/+oYNGOiPvwuwAL9tc/LQgg58aosIVpMYfepQZ20V+VZnHpZh8IRDA8Jo5xht19p2PksA+hFgqA0kpKtrSkuiWdE8rATQItfk4gf7yB0yGasJGGQZYazy9k/9XtmYkq2HHOOeEqdxvrICddJQ88MLCLT9lJENSUP/YS/yGcjZFXVxE11pTeIcqlCRU+3eYa1v7BeNvXIKNhZoK5orXWrtuH3cy8jrSns/u70aYfJ6B2jA8CnWnDbuvpeQtEY61SQqlKUsSArNa8NAsXj41wr3Ar9gAG9330w7EMTqlutk8HZO35uHI0q5qinUhaQYufPPrVkb2L/N+ZCfu0fnh appveyor"
|
APPVEYOR_SSH_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDhb96UEXy8yOy/f+riX/8kKbNx/lOfIZ4pP4Cw3Gj3DmnTwEnxtRtyc+xtaxOsKbt+7+EAXFpCzYX+jHMhtd0QtWB7dbey8DBg31g0f8C5EPquqROibVbhzr/F3f6/d52FFfq6Y/CWaAvLjezvipr+zOOsIFcVusqtXdPJQ/LtUJ0LS5d4lFiw5ELHSxHIpqwGwyb7PbR3ufEFoqbr8eYiCH+vlBob72ArPfo2f3u0sMvpGYmjVVu2jj4FEY2h89sLrGyFdNWBoyumRhkb38+WSAuyPa/Y21+g+S8sRzIlkwbxicGNMtrMIi6zHEIGAgA06Sw2psP807h730PPOVaWjUcU3ojNW8hH3nPizF74pT82+iP7/fFC4PXLP+tBa+8OoHC5yiO7QKUKprMSqVa1qOm8fHbrzglplKJXfzSfUtSE+AQ+HtHhuUWKI+0LBLDrsOJwI5hbsPOAuiZ5I3VfqfAOck6SH9TcmlapVmQEypc7d7oeeUtZSOuIWKXp068= dfx@aw"
|
||||||
APPIMAGE_TOOL: appimagetool-x86_64.AppImage
|
APPIMAGE_TOOL: appimage-builder-x86_64.AppImage
|
||||||
PYTHON_APPIMAGE: python3.7.17-cp37-cp37m-manylinux2014_x86_64.AppImage
|
|
||||||
DEPLOY_DIR: AppDir/opt/pyfa
|
DEPLOY_DIR: AppDir/opt/pyfa
|
||||||
# APPVEYOR_SSH_BLOCK: true
|
# APPVEYOR_SSH_BLOCK: true
|
||||||
cache:
|
cache:
|
||||||
- /home/appveyor/.cache/pip -> requirements.txt
|
- /home/appveyor/.cache/pip -> requirements.txt
|
||||||
init:
|
# init:
|
||||||
- sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -
|
# - sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -
|
||||||
install:
|
install:
|
||||||
- sh: git fetch --prune --unshallow # to fix the version dump issues
|
|
||||||
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y update
|
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y update
|
||||||
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y install python3.7-dev libgtk-3-dev python3-pip libwebkit2gtk-4.0-dev
|
# AppImage dependencies
|
||||||
|
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y install libfuse2
|
||||||
|
# Preparation script dependencies
|
||||||
|
- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get -y install python3-wxgtk4.0 python3-sqlalchemy python3-logbook
|
||||||
before_build:
|
before_build:
|
||||||
- sh: mkdir build && cd build
|
# Prepare pyfa data
|
||||||
- sh: curl -LO https://github.com/AppImage/AppImageKit/releases/download/13/$APPIMAGE_TOOL && chmod +x $APPIMAGE_TOOL
|
|
||||||
- sh: curl -LO https://github.com/niess/python-appimage/releases/download/python3.7/$PYTHON_APPIMAGE && chmod +x $PYTHON_APPIMAGE
|
|
||||||
build_script:
|
|
||||||
# Prepare Python base AppImage, stripping Python metadata
|
|
||||||
- sh: ./$PYTHON_APPIMAGE --appimage-extract
|
|
||||||
- sh: mv squashfs-root AppDir
|
|
||||||
- sh: rm AppDir/python*.desktop
|
|
||||||
- sh: rm AppDir/usr/share/applications/*.desktop
|
|
||||||
- sh: rm AppDir/usr/share/metainfo/*.appdata.xml
|
|
||||||
- sh: unlink AppDir/AppRun
|
|
||||||
- sh: mkdir -p $DEPLOY_DIR
|
|
||||||
# run install pyfa packages and any other requirements
|
|
||||||
|
|
||||||
- sh: AppDir/usr/bin/python -s -m pip install -U pip setuptools==41.6.0 wheel pathlib2
|
|
||||||
- sh: AppDir/usr/bin/python -s -m pip install -r ../requirements.txt
|
|
||||||
# Speedup, but causes runtime incompatiblities
|
|
||||||
#- sh: AppDir/usr/bin/python -s -m pip install -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04 -r ../requirements.txt
|
|
||||||
|
|
||||||
# Run scripts to prep pyfa data and build database
|
|
||||||
- sh: cd ../
|
|
||||||
- sh: find locale/ -type f -name "*.po" -exec msgen "{}" -o "{}" \;
|
- sh: find locale/ -type f -name "*.po" -exec msgen "{}" -o "{}" \;
|
||||||
- sh: build/AppDir/usr/bin/python scripts/compile_lang.py
|
- sh: python3 -B scripts/compile_lang.py
|
||||||
- sh: build/AppDir/usr/bin/python scripts/dump_crowdin_progress.py
|
- sh: python3 -B scripts/dump_crowdin_progress.py
|
||||||
- sh: build/AppDir/usr/bin/python db_update.py
|
- sh: python3 -B db_update.py
|
||||||
- sh: export PYFA_VERSION="$(python3.7 scripts/dump_version.py)"
|
- sh: export PYFA_VERSION="$(python3 -B scripts/dump_version.py)"
|
||||||
|
- sh: mkdir build
|
||||||
# Copy pyfa files to host
|
# Download packaging tool
|
||||||
- sh: cp -r eos graphs gui imgs locale service utils eve.db config.py pyfa.py db_update.py README.md LICENSE version.yml ./build/$DEPLOY_DIR
|
- sh: curl -o $APPIMAGE_TOOL -L https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage
|
||||||
- sh: find ./build/$DEPLOY_DIR | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
|
- sh: chmod +x $APPIMAGE_TOOL
|
||||||
|
build_script:
|
||||||
# Copy static AppImage files
|
- sh: mkdir -p AppDir/opt/pyfa
|
||||||
- sh: cd dist_assets/linux
|
- sh: cp -r eos graphs gui imgs locale service utils eve.db config.py pyfa.py db_update.py README.md LICENSE version.yml AppDir/opt/pyfa/
|
||||||
- sh: chmod +x AppRun
|
- sh: mkdir -p AppDir/usr/share/icons/hicolor/64x64/apps/
|
||||||
- sh: cp AppRun pyfa.desktop ../../build/AppDir/
|
- sh: cp imgs/gui/pyfa64.png AppDir/usr/share/icons/hicolor/64x64/apps/pyfa.png
|
||||||
- sh: cp pyfa.desktop ../../build/AppDir/usr/share/applications/
|
- sh: ./$APPIMAGE_TOOL --recipe dist_assets/linux/AppImageBuilder.yml
|
||||||
- sh: cp pyfa.appdata.xml ../../build/AppDir/usr/share/metainfo/
|
|
||||||
- sh: chmod +x pyfa && cp pyfa ../../build/AppDir/usr/bin
|
|
||||||
- sh: cd ../../
|
|
||||||
|
|
||||||
# Package it all up
|
|
||||||
- sh: mkdir dist
|
|
||||||
- sh: ./build/$APPIMAGE_TOOL build/AppDir dist/pyfa-$PYFA_VERSION-linux.AppImage
|
|
||||||
after_build:
|
after_build:
|
||||||
- sh: ls -la build
|
- sh: ls -la
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: dist/pyfa-$PYFA_VERSION-linux.AppImage
|
- path: pyfa-$PYFA_VERSION-linux.AppImage
|
||||||
deploy:
|
deploy:
|
||||||
tag: $PYFA_VERSION
|
tag: $PYFA_VERSION
|
||||||
release: pyfa $PYFA_VERSION
|
release: pyfa $PYFA_VERSION
|
||||||
@@ -85,17 +58,15 @@ for:
|
|||||||
-
|
-
|
||||||
matrix:
|
matrix:
|
||||||
only:
|
only:
|
||||||
- image: Visual Studio 2019
|
- image: Visual Studio 2022
|
||||||
environment:
|
environment:
|
||||||
PYTHON: "C:\\Python37-x64"
|
PYTHON: "C:\\Python311-x64"
|
||||||
# Should be enabled only for build process debugging
|
# Should be enabled only for build process debugging
|
||||||
# init:
|
# init:
|
||||||
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||||
cache:
|
cache:
|
||||||
- C:\users\appveyor\appdata\local\pip\cache\ -> requirements.txt
|
- C:\users\appveyor\appdata\local\pip\cache\ -> requirements.txt
|
||||||
install:
|
install:
|
||||||
- cmd: git fetch --prune --unshallow # to fix the version dump issues
|
|
||||||
|
|
||||||
- ps: echo("OS version:")
|
- ps: echo("OS version:")
|
||||||
- ps: "[System.Environment]::OSVersion.Version"
|
- ps: "[System.Environment]::OSVersion.Version"
|
||||||
|
|
||||||
@@ -131,10 +102,8 @@ for:
|
|||||||
# pip will build them from source using the MSVC compiler matching the
|
# pip will build them from source using the MSVC compiler matching the
|
||||||
# target Python version and architecture
|
# target Python version and architecture
|
||||||
- ps: echo("Install pip requirements:")
|
- ps: echo("Install pip requirements:")
|
||||||
# This one is needed to build wxpython 4.0.6 on windows
|
|
||||||
- cmd: "python -m pip install pathlib2"
|
|
||||||
- cmd: "python -m pip install -r requirements.txt"
|
- cmd: "python -m pip install -r requirements.txt"
|
||||||
- cmd: "python -m pip install PyInstaller==3.6"
|
- cmd: "python -m pip install PyInstaller==6.0.0"
|
||||||
before_build:
|
before_build:
|
||||||
# directory that will contain the built files
|
# directory that will contain the built files
|
||||||
- ps: $env:PYFA_DIST_DIR = "c:\projects\$env:APPVEYOR_PROJECT_SLUG\dist"
|
- ps: $env:PYFA_DIST_DIR = "c:\projects\$env:APPVEYOR_PROJECT_SLUG\dist"
|
||||||
@@ -150,7 +119,7 @@ for:
|
|||||||
# Build gamedata DB
|
# Build gamedata DB
|
||||||
- cmd: "python db_update.py"
|
- cmd: "python db_update.py"
|
||||||
# Build command for PyInstaller
|
# Build command for PyInstaller
|
||||||
- cmd: "python -m PyInstaller --noupx --clean --windowed --noconsole -y pyfa.spec"
|
- cmd: "python -m PyInstaller --clean -y pyfa.spec"
|
||||||
# Copy over manifest (See pyfa-org/pyfa#1622)
|
# Copy over manifest (See pyfa-org/pyfa#1622)
|
||||||
- ps: xcopy /y dist_assets\win\pyfa.exe.manifest $env:PYFA_DIST_DIR\pyfa\
|
- ps: xcopy /y dist_assets\win\pyfa.exe.manifest $env:PYFA_DIST_DIR\pyfa\
|
||||||
# InnoScript EXE building. This is in a separate script because I don't feel like copying over the logic to AppVeyor script right now...
|
# InnoScript EXE building. This is in a separate script because I don't feel like copying over the logic to AppVeyor script right now...
|
||||||
@@ -177,16 +146,15 @@ for:
|
|||||||
-
|
-
|
||||||
matrix:
|
matrix:
|
||||||
only:
|
only:
|
||||||
- image: macos
|
- image: macos-catalina
|
||||||
environment:
|
environment:
|
||||||
APPVEYOR_SSH_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJDW/+oYNGOiPvwuwAL9tc/LQgg58aosIVpMYfepQZ20V+VZnHpZh8IRDA8Jo5xht19p2PksA+hFgqA0kpKtrSkuiWdE8rATQItfk4gf7yB0yGasJGGQZYazy9k/9XtmYkq2HHOOeEqdxvrICddJQ88MLCLT9lJENSUP/YS/yGcjZFXVxE11pTeIcqlCRU+3eYa1v7BeNvXIKNhZoK5orXWrtuH3cy8jrSns/u70aYfJ6B2jA8CnWnDbuvpeQtEY61SQqlKUsSArNa8NAsXj41wr3Ar9gAG9330w7EMTqlutk8HZO35uHI0q5qinUhaQYufPPrVkb2L/N+ZCfu0fnh appveyor"
|
APPVEYOR_SSH_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJDW/+oYNGOiPvwuwAL9tc/LQgg58aosIVpMYfepQZ20V+VZnHpZh8IRDA8Jo5xht19p2PksA+hFgqA0kpKtrSkuiWdE8rATQItfk4gf7yB0yGasJGGQZYazy9k/9XtmYkq2HHOOeEqdxvrICddJQ88MLCLT9lJENSUP/YS/yGcjZFXVxE11pTeIcqlCRU+3eYa1v7BeNvXIKNhZoK5orXWrtuH3cy8jrSns/u70aYfJ6B2jA8CnWnDbuvpeQtEY61SQqlKUsSArNa8NAsXj41wr3Ar9gAG9330w7EMTqlutk8HZO35uHI0q5qinUhaQYufPPrVkb2L/N+ZCfu0fnh appveyor"
|
||||||
cache:
|
cache:
|
||||||
- /Users/appveyor/Library/Caches/pip/ -> requirements.txt
|
- /Users/appveyor/Library/Caches/pip/ -> requirements.txt
|
||||||
init:
|
init:
|
||||||
# - sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -
|
# - sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e -
|
||||||
- sh: source ~/venv3.7/bin/activate
|
- sh: source ~/venv3.11/bin/activate
|
||||||
install:
|
install:
|
||||||
- sh: git fetch --prune --unshallow # to fix the version dump issues
|
|
||||||
- sh: bash scripts/osx-setup.sh
|
- sh: bash scripts/osx-setup.sh
|
||||||
build_script:
|
build_script:
|
||||||
- sh: bash scripts/osx-translations.sh
|
- sh: bash scripts/osx-translations.sh
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- Python 3.7
|
- Python 3.11
|
||||||
- Git CLI installed
|
- Git CLI installed
|
||||||
- Python, pip and git are all available as command-line commands (add to the path if needed)
|
- Python, pip and git are all available as command-line commands (add to the path if needed)
|
||||||
|
|
||||||
|
|||||||
25
config.py
@@ -9,6 +9,7 @@ import hashlib
|
|||||||
from eos.const import FittingSlot
|
from eos.const import FittingSlot
|
||||||
|
|
||||||
from cryptography.fernet import Fernet
|
from cryptography.fernet import Fernet
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
pyfalog = Logger(__name__)
|
pyfalog = Logger(__name__)
|
||||||
|
|
||||||
@@ -44,9 +45,16 @@ experimentalFeatures = None
|
|||||||
version = None
|
version = None
|
||||||
language = 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'
|
ESI_CACHE = 'esi_cache'
|
||||||
SSO_CALLBACK = 'https://pyfa-org.github.io/Pyfa/callback'
|
|
||||||
|
|
||||||
LOGLEVEL_MAP = {
|
LOGLEVEL_MAP = {
|
||||||
"critical": CRITICAL,
|
"critical": CRITICAL,
|
||||||
@@ -58,13 +66,22 @@ LOGLEVEL_MAP = {
|
|||||||
|
|
||||||
CATALOG = 'lang'
|
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 = {
|
slotColourMap = {
|
||||||
FittingSlot.LOW: wx.Colour(250, 235, 204), # yellow = low slots
|
FittingSlot.LOW: wx.Colour(250, 235, 204), # yellow = low slots
|
||||||
FittingSlot.MED: wx.Colour(188, 215, 241), # blue = mid slots
|
FittingSlot.MED: wx.Colour(188, 215, 241), # blue = mid slots
|
||||||
FittingSlot.HIGH: wx.Colour(235, 204, 209), # red = high slots
|
FittingSlot.HIGH: wx.Colour(235, 204, 209), # red = high slots
|
||||||
FittingSlot.RIG: '',
|
FittingSlot.RIG: '',
|
||||||
FittingSlot.SUBSYSTEM: ''
|
FittingSlot.SUBSYSTEM: ''}
|
||||||
}
|
errColor = wx.Colour(204, 51, 51)
|
||||||
|
|
||||||
|
|
||||||
def getClientSecret():
|
def getClientSecret():
|
||||||
return clientHash
|
return clientHash
|
||||||
|
|||||||
@@ -794,8 +794,8 @@ def update_db():
|
|||||||
_hardcodeAttribs(cybeleTypeID, attrMap)
|
_hardcodeAttribs(cybeleTypeID, attrMap)
|
||||||
_hardcodeEffects(cybeleTypeID, effectMap)
|
_hardcodeEffects(cybeleTypeID, effectMap)
|
||||||
|
|
||||||
hardcodeShapash()
|
# hardcodeShapash()
|
||||||
hardcodeCybele()
|
# hardcodeCybele()
|
||||||
|
|
||||||
eos.db.gamedata_session.commit()
|
eos.db.gamedata_session.commit()
|
||||||
eos.db.gamedata_engine.execute('VACUUM')
|
eos.db.gamedata_engine.execute('VACUUM')
|
||||||
|
|||||||
74
dist_assets/linux/AppImageBuilder.yml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
version: 1
|
||||||
|
|
||||||
|
AppDir:
|
||||||
|
path: ./AppDir
|
||||||
|
|
||||||
|
app_info:
|
||||||
|
id: pyfa
|
||||||
|
name: pyfa
|
||||||
|
icon: pyfa
|
||||||
|
version: '{{PYFA_VERSION}}'
|
||||||
|
exec: usr/bin/python3.11
|
||||||
|
exec_args: "-s $APPDIR/opt/pyfa/pyfa.py $@"
|
||||||
|
|
||||||
|
apt:
|
||||||
|
arch: [ amd64 ]
|
||||||
|
sources:
|
||||||
|
- sourceline: 'deb http://us.archive.ubuntu.com/ubuntu jammy main restricted universe multiverse'
|
||||||
|
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920d1991bc93c'
|
||||||
|
- sourceline: 'deb http://us.archive.ubuntu.com/ubuntu jammy-updates main restricted universe multiverse'
|
||||||
|
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920d1991bc93c'
|
||||||
|
- sourceline: 'deb http://us.archive.ubuntu.com/ubuntu jammy-backports main restricted universe multiverse'
|
||||||
|
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920d1991bc93c'
|
||||||
|
- sourceline: 'deb http://us.archive.ubuntu.com/ubuntu jammy-security main restricted universe multiverse'
|
||||||
|
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920d1991bc93c'
|
||||||
|
- sourceline: 'deb https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu jammy main'
|
||||||
|
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xf23c5a6cf475977595c89f51ba6932366a755776'
|
||||||
|
|
||||||
|
include:
|
||||||
|
- python3.11
|
||||||
|
# wx dependencies
|
||||||
|
- 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
|
||||||
|
- ubuntu-mono
|
||||||
|
|
||||||
|
after_bundle:
|
||||||
|
# Install python dependencies to bundled interpreter
|
||||||
|
- export PYTHONHOME="AppDir/usr"
|
||||||
|
- export PYTHONPATH="AppDir/usr/lib/python3.11/site-packages"
|
||||||
|
- curl -L https://bootstrap.pypa.io/get-pip.py -o get-pip.py
|
||||||
|
- AppDir/usr/bin/python3.11 get-pip.py
|
||||||
|
# Just to bundle certificates with AppImage
|
||||||
|
- AppDir/usr/bin/python3.11 -s -m pip install certifi
|
||||||
|
- AppDir/usr/bin/python3.11 -s -m pip install -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-22.04 -r requirements.txt
|
||||||
|
|
||||||
|
files:
|
||||||
|
exclude:
|
||||||
|
- usr/lib/x86_64-linux-gnu/gconv
|
||||||
|
- usr/share/man
|
||||||
|
- usr/share/doc/*/README.*
|
||||||
|
- usr/share/doc/*/changelog.*
|
||||||
|
- usr/share/doc/*/NEWS.*
|
||||||
|
- usr/share/doc/*/TODO.*
|
||||||
|
- usr/include
|
||||||
|
|
||||||
|
runtime:
|
||||||
|
env:
|
||||||
|
PYTHONHOME: '${APPDIR}/usr'
|
||||||
|
PYTHONPATH: '${APPDIR}/usr/lib/python3.11/site-packages'
|
||||||
|
SSL_CERT_FILE: '${APPDIR}/usr/local/lib/python3.11/dist-packages/certifi/cacert.pem'
|
||||||
|
# Workaround for https://github.com/AppImageCrafters/appimage-builder/issues/336
|
||||||
|
XDG_DATA_DIRS: '${APPDIR}/usr/local/share:${APPDIR}/usr/share:/usr/local/share:/usr/share:$XDG_DATA_DIRS'
|
||||||
|
|
||||||
|
AppImage:
|
||||||
|
sign-key: None
|
||||||
|
arch: x86_64
|
||||||
|
file_name: 'pyfa-{{PYFA_VERSION}}-linux.AppImage'
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#! /bin/bash -i
|
|
||||||
|
|
||||||
# Export APPRUN if running from an extracted image
|
|
||||||
self="$(readlink -f -- $0)"
|
|
||||||
here="${self%/*}"
|
|
||||||
APPDIR="${APPDIR:-${here}}"
|
|
||||||
|
|
||||||
# Export TCl/Tk
|
|
||||||
export TCL_LIBRARY="${APPDIR}/usr/share/tcltk/tcl8.4"
|
|
||||||
export TK_LIBRARY="${APPDIR}/usr/share/tcltk/tk8.4"
|
|
||||||
export TKPATH="${TK_LIBRARY}"
|
|
||||||
|
|
||||||
# Export SSL certificate
|
|
||||||
export SSL_CERT_FILE="${APPDIR}/opt/_internal/certs.pem"
|
|
||||||
|
|
||||||
# Call the entry point
|
|
||||||
#! /bin/bash -i
|
|
||||||
|
|
||||||
${APPDIR}/usr/bin/pyfa "$@"
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#! /bin/bash
|
|
||||||
|
|
||||||
${APPDIR}/usr/bin/python3.7 -s "${APPDIR}/opt/pyfa/pyfa.py" "$@"
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<component type="desktop-application">
|
|
||||||
<id>org.pyfa.pyfa</id>
|
|
||||||
<metadata_license>MIT</metadata_license>
|
|
||||||
<project_license>GPL-3</project_license>
|
|
||||||
<name>Pyfa</name>
|
|
||||||
<summary>Pyfa </summary>
|
|
||||||
<description>
|
|
||||||
<p> Python Fitting Assitant for EVE Online
|
|
||||||
</p>
|
|
||||||
</description>
|
|
||||||
<launchable type="desktop-id">pyfa.desktop</launchable>
|
|
||||||
<url type="homepage">https://github.com/pyfa-org/Pyfa</url>
|
|
||||||
<provides>
|
|
||||||
<binary>pyfa</binary>
|
|
||||||
</provides>
|
|
||||||
</component>
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
[Desktop Entry]
|
|
||||||
Type=Application
|
|
||||||
Name=Pyfa
|
|
||||||
Exec=pyfa
|
|
||||||
Comment=Python Fitting Assistant for EVE: Online
|
|
||||||
Icon=python
|
|
||||||
Categories=Game;
|
|
||||||
@@ -80,6 +80,7 @@ exe = EXE(pyz,
|
|||||||
app = BUNDLE(
|
app = BUNDLE(
|
||||||
exe,
|
exe,
|
||||||
name='pyfa.app',
|
name='pyfa.app',
|
||||||
|
version=os.getenv('PYFA_VERSION'),
|
||||||
icon=icon,
|
icon=icon,
|
||||||
bundle_identifier=None,
|
bundle_identifier=None,
|
||||||
info_plist={
|
info_plist={
|
||||||
@@ -88,5 +89,7 @@ app = BUNDLE(
|
|||||||
'CFBundleName': 'pyfa',
|
'CFBundleName': 'pyfa',
|
||||||
'CFBundleDisplayName': 'pyfa',
|
'CFBundleDisplayName': 'pyfa',
|
||||||
'CFBundleIdentifier': 'org.pyfaorg.pyfa',
|
'CFBundleIdentifier': 'org.pyfaorg.pyfa',
|
||||||
|
'CFBundleVersion': os.getenv('PYFA_VERSION'),
|
||||||
|
'CFBundleShortVersionString': os.getenv('PYFA_VERSION'),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ CloseApplications=yes
|
|||||||
DefaultDirName={pf}\{#MyAppName}
|
DefaultDirName={pf}\{#MyAppName}
|
||||||
DefaultGroupName={#MyAppName}
|
DefaultGroupName={#MyAppName}
|
||||||
AllowNoIcons=yes
|
AllowNoIcons=yes
|
||||||
LicenseFile={#MyAppDir}\LICENSE
|
LicenseFile={#MyAppDir}\app\LICENSE
|
||||||
OutputDir={#MyOutputDir}
|
OutputDir={#MyOutputDir}
|
||||||
OutputBaseFilename={#MyOutputFile}
|
OutputBaseFilename={#MyOutputFile}
|
||||||
SetupIconFile={#MyAppDir}\pyfa.ico
|
SetupIconFile={#MyAppDir}\app\pyfa.ico
|
||||||
SolidCompression=yes
|
SolidCompression=yes
|
||||||
|
|
||||||
[Languages]
|
[Languages]
|
||||||
|
|||||||
@@ -10,10 +10,15 @@
|
|||||||
</trustInfo>
|
</trustInfo>
|
||||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
<application>
|
<application>
|
||||||
|
<!-- Windows Vista -->
|
||||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||||
|
<!-- Windows 7 -->
|
||||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||||
|
<!-- Windows 8 -->
|
||||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||||
|
<!-- Windows 8.1 -->
|
||||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||||
|
<!-- Windows 10 and Windows 11 -->
|
||||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||||
</application>
|
</application>
|
||||||
</compatibility>
|
</compatibility>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ mapper(DynamicItemAttribute, dynamicAttributes_table,
|
|||||||
properties={"info": relation(AttributeInfo, lazy=False)})
|
properties={"info": relation(AttributeInfo, lazy=False)})
|
||||||
|
|
||||||
mapper(DynamicItemItem, dynamicApplicable_table, properties={
|
mapper(DynamicItemItem, dynamicApplicable_table, properties={
|
||||||
"mutaplasmid": relation(DynamicItem),
|
"mutaplasmid": relation(DynamicItem, viewonly=True),
|
||||||
})
|
})
|
||||||
|
|
||||||
DynamicItemAttribute.ID = association_proxy("info", "attributeID")
|
DynamicItemAttribute.ID = association_proxy("info", "attributeID")
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ props = {
|
|||||||
primaryjoin=dynamicApplicable_table.c.applicableTypeID == items_table.c.typeID,
|
primaryjoin=dynamicApplicable_table.c.applicableTypeID == items_table.c.typeID,
|
||||||
secondaryjoin=dynamicApplicable_table.c.typeID == DynamicItem.typeID,
|
secondaryjoin=dynamicApplicable_table.c.typeID == DynamicItem.typeID,
|
||||||
secondary=dynamicApplicable_table,
|
secondary=dynamicApplicable_table,
|
||||||
backref="applicableItems"
|
backref="applicableItems",
|
||||||
|
viewonly=True
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Migration 1
|
|||||||
loaded as they no longer exist in the database. We therefore replace these
|
loaded as they no longer exist in the database. We therefore replace these
|
||||||
modules with their new replacements
|
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
|
and output of itemDiff.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
Migration 25
|
Migration 25
|
||||||
|
|
||||||
- Converts T3C fitting configurations based on the spreadsheet noted here:
|
- 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)
|
(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
|
# We don't have a conversion for this. I don't think this will ever happen, but who knows
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# It doesn't actully matter which old module is replaced with which new module, so we don't have to worry
|
# 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 doe a straight up record UPDATE
|
# about module position or anything like that. Just do a straight up record UPDATE
|
||||||
for i, old in enumerate(oldModules[:4]):
|
for i, old in enumerate(oldModules[:4]):
|
||||||
saveddata_engine.execute("UPDATE modules SET itemID = ? WHERE ID = ?", (newModules[i], old[0]))
|
saveddata_engine.execute("UPDATE modules SET itemID = ? WHERE ID = ?", (newModules[i], old[0]))
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Migration 4
|
|||||||
from database), which causes pyfa to crash. We therefore replace these
|
from database), which causes pyfa to crash. We therefore replace these
|
||||||
modules with their new replacements
|
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
|
and output of itemDiff.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
36
eos/db/migrations/upgrade47.py
Normal 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")
|
||||||
@@ -40,18 +40,18 @@ characters_table = Table("characters", saveddata_meta,
|
|||||||
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now))
|
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now))
|
||||||
|
|
||||||
sso_table = Table("ssoCharacter", saveddata_meta,
|
sso_table = Table("ssoCharacter", saveddata_meta,
|
||||||
Column("ID", Integer, primary_key=True),
|
Column("ID", Integer, primary_key=True),
|
||||||
Column("client", String, nullable=False),
|
Column("client", String, nullable=False),
|
||||||
Column("characterID", Integer, nullable=False),
|
Column("characterID", Integer, nullable=False),
|
||||||
Column("characterName", String, nullable=False),
|
Column("characterName", String, nullable=False),
|
||||||
Column("refreshToken", String, nullable=False),
|
Column("server", String, nullable=False),
|
||||||
Column("accessToken", String, nullable=False),
|
Column("refreshToken", String, nullable=False),
|
||||||
Column("accessTokenExpires", DateTime, nullable=False),
|
Column("accessToken", String, nullable=False),
|
||||||
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
|
Column("accessTokenExpires", DateTime, nullable=False),
|
||||||
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
|
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
|
||||||
UniqueConstraint('client', 'characterID', name='uix_client_characterID'),
|
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
|
||||||
UniqueConstraint('client', 'characterName', name='uix_client_characterName')
|
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,
|
sso_character_map_table = Table("ssoCharacterMap", saveddata_meta,
|
||||||
Column("characterID", ForeignKey("characters.ID"), primary_key=True),
|
Column("characterID", ForeignKey("characters.ID"), primary_key=True),
|
||||||
|
|||||||
@@ -175,12 +175,13 @@ mapper(es_Fit, fits_table,
|
|||||||
collection_class=HandledModuleList,
|
collection_class=HandledModuleList,
|
||||||
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False), # noqa
|
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False), # noqa
|
||||||
order_by=modules_table.c.position,
|
order_by=modules_table.c.position,
|
||||||
|
overlaps='owner',
|
||||||
cascade='all, delete, delete-orphan'),
|
cascade='all, delete, delete-orphan'),
|
||||||
"_Fit__projectedModules": relation(
|
"_Fit__projectedModules": relation(
|
||||||
Module,
|
Module,
|
||||||
collection_class=HandledProjectedModList,
|
collection_class=HandledProjectedModList,
|
||||||
|
overlaps='owner, _Fit__modules',
|
||||||
cascade='all, delete, delete-orphan',
|
cascade='all, delete, delete-orphan',
|
||||||
single_parent=True,
|
|
||||||
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)), # noqa
|
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)), # noqa
|
||||||
"owner": relation(
|
"owner": relation(
|
||||||
User,
|
User,
|
||||||
@@ -190,37 +191,37 @@ mapper(es_Fit, fits_table,
|
|||||||
"_Fit__boosters": relation(
|
"_Fit__boosters": relation(
|
||||||
Booster,
|
Booster,
|
||||||
collection_class=HandledBoosterList,
|
collection_class=HandledBoosterList,
|
||||||
cascade='all, delete, delete-orphan',
|
overlaps='owner',
|
||||||
single_parent=True),
|
cascade='all, delete, delete-orphan'),
|
||||||
"_Fit__drones": relation(
|
"_Fit__drones": relation(
|
||||||
Drone,
|
Drone,
|
||||||
collection_class=HandledDroneCargoList,
|
collection_class=HandledDroneCargoList,
|
||||||
|
overlaps='owner',
|
||||||
cascade='all, delete, delete-orphan',
|
cascade='all, delete, delete-orphan',
|
||||||
single_parent=True,
|
|
||||||
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)), # noqa
|
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)), # noqa
|
||||||
"_Fit__fighters": relation(
|
"_Fit__fighters": relation(
|
||||||
Fighter,
|
Fighter,
|
||||||
collection_class=HandledDroneCargoList,
|
collection_class=HandledDroneCargoList,
|
||||||
|
overlaps='owner',
|
||||||
cascade='all, delete, delete-orphan',
|
cascade='all, delete, delete-orphan',
|
||||||
single_parent=True,
|
|
||||||
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)), # noqa
|
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)), # noqa
|
||||||
"_Fit__cargo": relation(
|
"_Fit__cargo": relation(
|
||||||
Cargo,
|
Cargo,
|
||||||
collection_class=HandledDroneCargoList,
|
collection_class=HandledDroneCargoList,
|
||||||
|
overlaps='owner',
|
||||||
cascade='all, delete, delete-orphan',
|
cascade='all, delete, delete-orphan',
|
||||||
single_parent=True,
|
|
||||||
primaryjoin=and_(cargo_table.c.fitID == fits_table.c.ID)),
|
primaryjoin=and_(cargo_table.c.fitID == fits_table.c.ID)),
|
||||||
"_Fit__projectedDrones": relation(
|
"_Fit__projectedDrones": relation(
|
||||||
Drone,
|
Drone,
|
||||||
collection_class=HandledProjectedDroneList,
|
collection_class=HandledProjectedDroneList,
|
||||||
|
overlaps='owner, _Fit__drones',
|
||||||
cascade='all, delete, delete-orphan',
|
cascade='all, delete, delete-orphan',
|
||||||
single_parent=True,
|
|
||||||
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)), # noqa
|
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)), # noqa
|
||||||
"_Fit__projectedFighters": relation(
|
"_Fit__projectedFighters": relation(
|
||||||
Fighter,
|
Fighter,
|
||||||
collection_class=HandledProjectedDroneList,
|
collection_class=HandledProjectedDroneList,
|
||||||
|
overlaps='owner, _Fit__fighters',
|
||||||
cascade='all, delete, delete-orphan',
|
cascade='all, delete, delete-orphan',
|
||||||
single_parent=True,
|
|
||||||
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)), # noqa
|
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)), # noqa
|
||||||
"_Fit__implants": relation(
|
"_Fit__implants": relation(
|
||||||
Implant,
|
Implant,
|
||||||
|
|||||||
@@ -493,9 +493,12 @@ def getSsoCharacters(clientHash, eager=None):
|
|||||||
|
|
||||||
|
|
||||||
@cachedQuery(SsoCharacter, 1, "lookfor", "clientHash")
|
@cachedQuery(SsoCharacter, 1, "lookfor", "clientHash")
|
||||||
def getSsoCharacter(lookfor, clientHash, eager=None):
|
def getSsoCharacter(lookfor, clientHash, server=None, eager=None):
|
||||||
filter = SsoCharacter.client == clientHash
|
filter = SsoCharacter.client == clientHash
|
||||||
|
|
||||||
|
if server is not None:
|
||||||
|
filter = and_(filter, SsoCharacter.server == server)
|
||||||
|
|
||||||
if isinstance(lookfor, int):
|
if isinstance(lookfor, int):
|
||||||
filter = and_(filter, SsoCharacter.ID == lookfor)
|
filter = and_(filter, SsoCharacter.ID == lookfor)
|
||||||
elif isinstance(lookfor, str):
|
elif isinstance(lookfor, str):
|
||||||
|
|||||||
480
eos/effects.py
@@ -966,8 +966,8 @@ class Effect272(BaseEffect):
|
|||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Implants named like: Inherent Implants 'Noble' Repair Systems RS (6 of 6)
|
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)
|
Modules named like: Nanobot Accelerator (8 of 8)
|
||||||
Implant: AIR Repairer Booster III
|
|
||||||
Implant: Numon Family Heirloom
|
Implant: Numon Family Heirloom
|
||||||
Skill: Repair Systems
|
Skill: Repair Systems
|
||||||
"""
|
"""
|
||||||
@@ -1060,6 +1060,7 @@ class Effect290(BaseEffect):
|
|||||||
Used by:
|
Used by:
|
||||||
Implants named like: Frentix Booster (4 of 4)
|
Implants named like: Frentix Booster (4 of 4)
|
||||||
Implants named like: Halcyon B Booster (5 of 5)
|
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)
|
Implants named like: Zainou 'Deadeye' Sharpshooter ST (6 of 6)
|
||||||
Skill: Sharpshooter
|
Skill: Sharpshooter
|
||||||
"""
|
"""
|
||||||
@@ -1169,6 +1170,7 @@ class Effect394(BaseEffect):
|
|||||||
Implant: AIR Overclocker Booster II
|
Implant: AIR Overclocker Booster II
|
||||||
Implant: Quafe Zero Classic
|
Implant: Quafe Zero Classic
|
||||||
Implant: Serenity YC122.9 Season Booster - Max Velocity
|
Implant: Serenity YC122.9 Season Booster - Max Velocity
|
||||||
|
Implant: Starsi Blast! Classic
|
||||||
Implant: Wisdom of Gheinok
|
Implant: Wisdom of Gheinok
|
||||||
Skill: Navigation
|
Skill: Navigation
|
||||||
"""
|
"""
|
||||||
@@ -1190,17 +1192,18 @@ class Effect395(BaseEffect):
|
|||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Modules from group: Rig Anchor (4 of 4)
|
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: Eifyr and Co. 'Rogue' Evasive Maneuvering EM (6 of 6)
|
||||||
Implants named like: Grand Prix Booster (4 of 6)
|
Implants named like: Grand Prix Booster (4 of 6)
|
||||||
Implants named like: Halcyon G Booster (5 of 5)
|
Implants named like: Halcyon G Booster (5 of 5)
|
||||||
Implants named like: Halcyon Y Booster (5 of 5)
|
Implants named like: Halcyon Y Booster (5 of 5)
|
||||||
Implants named like: grade Nomad (10 of 12)
|
Implants named like: grade Nomad (10 of 12)
|
||||||
Modules named like: Low Friction Nozzle Joints (8 of 8)
|
Modules named like: Low Friction Nozzle Joints (8 of 8)
|
||||||
Implant: AIR Agility Booster II
|
|
||||||
Implant: AIR Overclocker Booster III
|
Implant: AIR Overclocker Booster III
|
||||||
Implant: Genolution Core Augmentation CA-4
|
Implant: Genolution Core Augmentation CA-4
|
||||||
Implant: Quafe Zero Green Apple
|
Implant: Quafe Zero Green Apple
|
||||||
Implant: Serenity YC122.9 Season Booster - Agility
|
Implant: Serenity YC122.9 Season Booster - Agility
|
||||||
|
Implant: Starsi Blast! Classic
|
||||||
Skill: Evasive Maneuvering
|
Skill: Evasive Maneuvering
|
||||||
Skill: Spaceship Command
|
Skill: Spaceship Command
|
||||||
"""
|
"""
|
||||||
@@ -1335,6 +1338,7 @@ class Effect485(BaseEffect):
|
|||||||
Implant: Basic Capsuleer Engineering Augmentation Chip
|
Implant: Basic Capsuleer Engineering Augmentation Chip
|
||||||
Implant: Genolution Core Augmentation CA-2
|
Implant: Genolution Core Augmentation CA-2
|
||||||
Implant: Quafe Zero Green Apple
|
Implant: Quafe Zero Green Apple
|
||||||
|
Implant: Starsi Blast! Orange
|
||||||
Skill: Capacitor Systems Operation
|
Skill: Capacitor Systems Operation
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -1511,6 +1515,7 @@ class Effect512(BaseEffect):
|
|||||||
Ship: Atron
|
Ship: Atron
|
||||||
Ship: Federation Navy Comet
|
Ship: Federation Navy Comet
|
||||||
Ship: Pacifier
|
Ship: Pacifier
|
||||||
|
Ship: Shapash
|
||||||
Ship: Taranis
|
Ship: Taranis
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -1712,6 +1717,7 @@ class Effect562(BaseEffect):
|
|||||||
Variations of ship: Vexor (3 of 4)
|
Variations of ship: Vexor (3 of 4)
|
||||||
Ship: Adrestia
|
Ship: Adrestia
|
||||||
Ship: Arazu
|
Ship: Arazu
|
||||||
|
Ship: Cybele
|
||||||
Ship: Deimos
|
Ship: Deimos
|
||||||
Ship: Enforcer
|
Ship: Enforcer
|
||||||
Ship: Exequror Navy Issue
|
Ship: Exequror Navy Issue
|
||||||
@@ -1769,6 +1775,7 @@ class Effect584(BaseEffect):
|
|||||||
Implants named like: 'Pyrolancea' Dose (7 of 7)
|
Implants named like: 'Pyrolancea' Dose (7 of 7)
|
||||||
Implants named like: Eifyr and Co. 'Gunslinger' Surgical Strike SS (6 of 6)
|
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: Halcyon Y Booster (5 of 5)
|
||||||
|
Implants named like: SoCT Turret Booster (3 of 3)
|
||||||
Implant: AIR Pyrolancea Booster II
|
Implant: AIR Pyrolancea Booster II
|
||||||
Implant: Standard Cerebral Accelerator
|
Implant: Standard Cerebral Accelerator
|
||||||
"""
|
"""
|
||||||
@@ -2151,9 +2158,11 @@ class Effect699(BaseEffect):
|
|||||||
Used by:
|
Used by:
|
||||||
Implants named like: Halcyon B Booster (5 of 5)
|
Implants named like: Halcyon B Booster (5 of 5)
|
||||||
Implants named like: Halcyon R 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)
|
Implants named like: Zainou 'Gypsy' Signature Analysis SA (6 of 6)
|
||||||
Modules named like: Targeting System Subcontroller (8 of 8)
|
Modules named like: Targeting System Subcontroller (8 of 8)
|
||||||
Implant: Quafe Zero Classic
|
Implant: Quafe Zero Classic
|
||||||
|
Implant: Starsi Blast! Orange
|
||||||
Skill: Signature Analysis
|
Skill: Signature Analysis
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -2500,6 +2509,7 @@ class Effect856(BaseEffect):
|
|||||||
Implants named like: Grand Prix Booster (5 of 6)
|
Implants named like: Grand Prix Booster (5 of 6)
|
||||||
Implants named like: Halcyon B Booster (5 of 5)
|
Implants named like: Halcyon B Booster (5 of 5)
|
||||||
Implants named like: Serenity Limited 'Overclocker' Dose (3 of 3)
|
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)
|
Implants named like: grade Ascendancy (10 of 12)
|
||||||
Modules named like: Hyperspatial Velocity Optimizer (8 of 8)
|
Modules named like: Hyperspatial Velocity Optimizer (8 of 8)
|
||||||
Implant: Serenity YC122.9 Season Booster - Warp Speed
|
Implant: Serenity YC122.9 Season Booster - Warp Speed
|
||||||
@@ -3267,24 +3277,6 @@ class Effect1024(BaseEffect):
|
|||||||
skill='Caldari Cruiser', **kwargs)
|
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):
|
class Effect1030(BaseEffect):
|
||||||
"""
|
"""
|
||||||
remoteArmorSystemsCapNeedBonusPostPercentCapacitorNeedLocationShipModulesRequiringRemoteArmorSystems
|
remoteArmorSystemsCapNeedBonusPostPercentCapacitorNeedLocationShipModulesRequiringRemoteArmorSystems
|
||||||
@@ -4906,8 +4898,8 @@ class Effect1635(BaseEffect):
|
|||||||
capitalRepairSystemsSkillDurationBonus
|
capitalRepairSystemsSkillDurationBonus
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
|
Implants named like: Repairer Booster (4 of 4)
|
||||||
Modules named like: Nanobot Accelerator (8 of 8)
|
Modules named like: Nanobot Accelerator (8 of 8)
|
||||||
Implant: AIR Repairer Booster III
|
|
||||||
Skill: Capital Repair Systems
|
Skill: Capital Repair Systems
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -5630,8 +5622,8 @@ class Effect1882(BaseEffect):
|
|||||||
miningYieldMultiplyPercent
|
miningYieldMultiplyPercent
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
|
Modules from group: Mining Upgrade (7 of 12)
|
||||||
Variations of module: Mining Laser Upgrade I (5 of 5)
|
Variations of module: Mining Laser Upgrade I (5 of 5)
|
||||||
Module: Frostline 'Omnivore' Harvester Upgrade
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type = 'passive'
|
type = 'passive'
|
||||||
@@ -6802,8 +6794,8 @@ class Effect2255(BaseEffect):
|
|||||||
tractorBeamCan
|
tractorBeamCan
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Deployables from group: Mobile Tractor Unit (4 of 4)
|
Deployables from group: Mobile Tractor Unit (5 of 5)
|
||||||
Modules from group: Tractor Beam (4 of 4)
|
Modules from group: Tractor Beam (6 of 6)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type = 'active'
|
type = 'active'
|
||||||
@@ -6815,7 +6807,6 @@ class Effect2296(BaseEffect):
|
|||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Implants named like: Halcyon Y Booster (5 of 5)
|
Implants named like: Halcyon Y Booster (5 of 5)
|
||||||
Implants named like: Tetrimon Resistance Booster (4 of 4)
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type = 'passive'
|
type = 'passive'
|
||||||
@@ -7013,7 +7004,7 @@ class Effect2432(BaseEffect):
|
|||||||
Implants named like: Halcyon Y Booster (5 of 5)
|
Implants named like: Halcyon Y Booster (5 of 5)
|
||||||
Implants named like: Inherent Implants 'Squire' Capacitor Management EM (6 of 6)
|
Implants named like: Inherent Implants 'Squire' Capacitor Management EM (6 of 6)
|
||||||
Implants named like: Mindflood Booster (4 of 4)
|
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)
|
Modules named like: Semiconductor Memory Cell (8 of 8)
|
||||||
Implant: Antipharmakon Aeolis
|
Implant: Antipharmakon Aeolis
|
||||||
Implant: Basic Capsuleer Engineering Augmentation Chip
|
Implant: Basic Capsuleer Engineering Augmentation Chip
|
||||||
@@ -7034,8 +7025,8 @@ class Effect2444(BaseEffect):
|
|||||||
minerCpuUsageMultiplyPercent2
|
minerCpuUsageMultiplyPercent2
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
|
Modules from group: Mining Upgrade (7 of 12)
|
||||||
Variations of module: Mining Laser Upgrade I (5 of 5)
|
Variations of module: Mining Laser Upgrade I (5 of 5)
|
||||||
Module: Frostline 'Omnivore' Harvester Upgrade
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type = 'passive'
|
type = 'passive'
|
||||||
@@ -7638,7 +7629,6 @@ class Effect2696(BaseEffect):
|
|||||||
maxRangeBonusEffectLasers
|
maxRangeBonusEffectLasers
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Implants named like: Tetrimon Precision Booster (4 of 4)
|
|
||||||
Modules named like: Energy Locus Coordinator (8 of 8)
|
Modules named like: Energy Locus Coordinator (8 of 8)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -8389,7 +8379,6 @@ class Effect2803(BaseEffect):
|
|||||||
energyWeaponDamageMultiplyPassive
|
energyWeaponDamageMultiplyPassive
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Implants named like: Harvest Damage Booster (4 of 4)
|
|
||||||
Modules named like: Energy Collision Accelerator (8 of 8)
|
Modules named like: Energy Collision Accelerator (8 of 8)
|
||||||
Implant: Wisdom of Gheinok
|
Implant: Wisdom of Gheinok
|
||||||
"""
|
"""
|
||||||
@@ -10094,23 +10083,6 @@ class Effect3356(BaseEffect):
|
|||||||
skill='Heavy Interdiction Cruisers', **kwargs)
|
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):
|
class Effect3366(BaseEffect):
|
||||||
"""
|
"""
|
||||||
shipRemoteSensorDampenerCapNeedGF
|
shipRemoteSensorDampenerCapNeedGF
|
||||||
@@ -13521,6 +13493,7 @@ class Effect4162(BaseEffect):
|
|||||||
Implants named like: Poteque 'Prospector' Astrometric Rangefinding AR (3 of 3)
|
Implants named like: Poteque 'Prospector' Astrometric Rangefinding AR (3 of 3)
|
||||||
Implants named like: Poteque 'Prospector' Sharpeye (2 of 2)
|
Implants named like: Poteque 'Prospector' Sharpeye (2 of 2)
|
||||||
Implants named like: Serenity Limited 'Sharpeye' Dose (3 of 3)
|
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)
|
Implants named like: grade Virtue (10 of 12)
|
||||||
Modules named like: Gravity Capacitor Upgrade (8 of 8)
|
Modules named like: Gravity Capacitor Upgrade (8 of 8)
|
||||||
Implant: AIR Astro-Rangefinding II Booster
|
Implant: AIR Astro-Rangefinding II Booster
|
||||||
@@ -14883,6 +14856,7 @@ class Effect4473(BaseEffect):
|
|||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Ship: Adrestia
|
Ship: Adrestia
|
||||||
|
Ship: Cybele
|
||||||
Ship: Mimir
|
Ship: Mimir
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -15443,6 +15417,7 @@ class Effect4620(BaseEffect):
|
|||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Ship: Garmur
|
Ship: Garmur
|
||||||
|
Ship: Shapash
|
||||||
Ship: Utu
|
Ship: Utu
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -15461,6 +15436,7 @@ class Effect4621(BaseEffect):
|
|||||||
Used by:
|
Used by:
|
||||||
Ship: Cambion
|
Ship: Cambion
|
||||||
Ship: Etana
|
Ship: Etana
|
||||||
|
Ship: Shapash
|
||||||
Ship: Utu
|
Ship: Utu
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -15542,6 +15518,7 @@ class Effect4626(BaseEffect):
|
|||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Ship: Adrestia
|
Ship: Adrestia
|
||||||
|
Ship: Cybele
|
||||||
Ship: Orthrus
|
Ship: Orthrus
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -16660,8 +16637,8 @@ class Effect4967(BaseEffect):
|
|||||||
shieldBoosterDurationBonusShieldSkills
|
shieldBoosterDurationBonusShieldSkills
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
|
Implants named like: Repairer Booster (4 of 4)
|
||||||
Modules named like: Core Defense Operational Solidifier (8 of 8)
|
Modules named like: Core Defense Operational Solidifier (8 of 8)
|
||||||
Implant: AIR Repairer Booster III
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type = 'passive'
|
type = 'passive'
|
||||||
@@ -17355,9 +17332,10 @@ class Effect5069(BaseEffect):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handler(fit, module, context, projectionRange, **kwargs):
|
def handler(fit, module, context, projectionRange, **kwargs):
|
||||||
fit.modules.filteredChargeBoost(lambda mod: mod.charge.requiresSkill('Mercoxit Processing'),
|
fit.modules.filteredChargeBoost(
|
||||||
'specializationAsteroidYieldMultiplier',
|
lambda mod: mod.charge.requiresSkill('Mercoxit Ore Processing'),
|
||||||
module.getModifiedItemAttr('miningAmountBonus'), **kwargs)
|
'specializationAsteroidYieldMultiplier',
|
||||||
|
module.getModifiedItemAttr('miningAmountBonus'), **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Effect5079(BaseEffect):
|
class Effect5079(BaseEffect):
|
||||||
@@ -18040,7 +18018,6 @@ class Effect5189(BaseEffect):
|
|||||||
trackingSpeedBonusEffectLasers
|
trackingSpeedBonusEffectLasers
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Implants named like: Tetrimon Precision Booster (4 of 4)
|
|
||||||
Modules named like: Energy Metastasis Adjuster (8 of 8)
|
Modules named like: Energy Metastasis Adjuster (8 of 8)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -20208,6 +20185,7 @@ class Effect5437(BaseEffect):
|
|||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Implants named like: Halcyon Y Booster (5 of 5)
|
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)
|
Modules named like: Emission Scope Sharpener (8 of 8)
|
||||||
Implant: Poteque 'Prospector' Archaeology AC-905
|
Implant: Poteque 'Prospector' Archaeology AC-905
|
||||||
Implant: Poteque 'Prospector' Environmental Analysis EY-1005
|
Implant: Poteque 'Prospector' Environmental Analysis EY-1005
|
||||||
@@ -24749,7 +24727,7 @@ class Effect6185(BaseEffect):
|
|||||||
srcFalloffRange=module.getModifiedItemAttr('falloffEffectiveness'),
|
srcFalloffRange=module.getModifiedItemAttr('falloffEffectiveness'),
|
||||||
distance=projectionRange)
|
distance=projectionRange)
|
||||||
duration = module.getModifiedItemAttr('duration') / 1000.0
|
duration = module.getModifiedItemAttr('duration') / 1000.0
|
||||||
fit.extraAttributes.increase('hullRepair', bonus / duration, **kwargs)
|
fit._hullRr.append((bonus, duration))
|
||||||
|
|
||||||
|
|
||||||
class Effect6186(BaseEffect):
|
class Effect6186(BaseEffect):
|
||||||
@@ -24774,7 +24752,7 @@ class Effect6186(BaseEffect):
|
|||||||
srcFalloffRange=container.getModifiedItemAttr('falloffEffectiveness'),
|
srcFalloffRange=container.getModifiedItemAttr('falloffEffectiveness'),
|
||||||
distance=projectionRange)
|
distance=projectionRange)
|
||||||
duration = container.getModifiedItemAttr('duration') / 1000.0
|
duration = container.getModifiedItemAttr('duration') / 1000.0
|
||||||
fit.extraAttributes.increase('shieldRepair', bonus / duration, **kwargs)
|
fit._shieldRr.append((bonus, duration))
|
||||||
|
|
||||||
|
|
||||||
class Effect6187(BaseEffect):
|
class Effect6187(BaseEffect):
|
||||||
@@ -24828,10 +24806,9 @@ class Effect6188(BaseEffect):
|
|||||||
srcFalloffRange=container.getModifiedItemAttr('falloffEffectiveness'),
|
srcFalloffRange=container.getModifiedItemAttr('falloffEffectiveness'),
|
||||||
distance=projectionRange)
|
distance=projectionRange)
|
||||||
duration = container.getModifiedItemAttr('duration') / 1000.0
|
duration = container.getModifiedItemAttr('duration') / 1000.0
|
||||||
rps = bonus / duration
|
fit._armorRr.append((bonus, duration))
|
||||||
fit.extraAttributes.increase('armorRepair', rps, **kwargs)
|
fit._armorRrPreSpool.append((bonus, duration))
|
||||||
fit.extraAttributes.increase('armorRepairPreSpool', rps, **kwargs)
|
fit._armorRrFullSpool.append((bonus, duration))
|
||||||
fit.extraAttributes.increase('armorRepairFullSpool', rps, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Effect6195(BaseEffect):
|
class Effect6195(BaseEffect):
|
||||||
@@ -29788,10 +29765,9 @@ class Effect6651(BaseEffect):
|
|||||||
srcFalloffRange=module.getModifiedItemAttr('falloffEffectiveness'),
|
srcFalloffRange=module.getModifiedItemAttr('falloffEffectiveness'),
|
||||||
distance=projectionRange)
|
distance=projectionRange)
|
||||||
speed = module.getModifiedItemAttr('duration') / 1000.0
|
speed = module.getModifiedItemAttr('duration') / 1000.0
|
||||||
rps = amount / speed
|
fit._armorRr.append((amount, speed))
|
||||||
fit.extraAttributes.increase('armorRepair', rps, **kwargs)
|
fit._armorRrPreSpool.append((amount, speed))
|
||||||
fit.extraAttributes.increase('armorRepairPreSpool', rps, **kwargs)
|
fit._armorRrFullSpool.append((amount, speed))
|
||||||
fit.extraAttributes.increase('armorRepairFullSpool', rps, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Effect6652(BaseEffect):
|
class Effect6652(BaseEffect):
|
||||||
@@ -29817,7 +29793,7 @@ class Effect6652(BaseEffect):
|
|||||||
srcFalloffRange=module.getModifiedItemAttr('falloffEffectiveness'),
|
srcFalloffRange=module.getModifiedItemAttr('falloffEffectiveness'),
|
||||||
distance=projectionRange)
|
distance=projectionRange)
|
||||||
speed = module.getModifiedItemAttr('duration') / 1000.0
|
speed = module.getModifiedItemAttr('duration') / 1000.0
|
||||||
fit.extraAttributes.increase('shieldRepair', amount / speed, **kwargs)
|
fit._shieldRr.append((amount, speed))
|
||||||
|
|
||||||
|
|
||||||
class Effect6653(BaseEffect):
|
class Effect6653(BaseEffect):
|
||||||
@@ -30446,10 +30422,9 @@ class Effect6687(BaseEffect):
|
|||||||
return
|
return
|
||||||
bonus = container.getModifiedItemAttr('armorDamageAmount')
|
bonus = container.getModifiedItemAttr('armorDamageAmount')
|
||||||
duration = container.getModifiedItemAttr('duration') / 1000.0
|
duration = container.getModifiedItemAttr('duration') / 1000.0
|
||||||
rps = bonus / duration
|
fit._armorRr.append((bonus, duration))
|
||||||
fit.extraAttributes.increase('armorRepair', rps, **kwargs)
|
fit._armorRrPreSpool.append((bonus, duration))
|
||||||
fit.extraAttributes.increase('armorRepairPreSpool', rps, **kwargs)
|
fit._armorRrFullSpool.append((bonus, duration))
|
||||||
fit.extraAttributes.increase('armorRepairFullSpool', rps, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Effect6688(BaseEffect):
|
class Effect6688(BaseEffect):
|
||||||
@@ -30472,7 +30447,7 @@ class Effect6688(BaseEffect):
|
|||||||
return
|
return
|
||||||
bonus = container.getModifiedItemAttr('shieldBonus')
|
bonus = container.getModifiedItemAttr('shieldBonus')
|
||||||
duration = container.getModifiedItemAttr('duration') / 1000.0
|
duration = container.getModifiedItemAttr('duration') / 1000.0
|
||||||
fit.extraAttributes.increase('shieldRepair', bonus / duration, **kwargs)
|
fit._shieldRr.append((bonus, duration))
|
||||||
|
|
||||||
|
|
||||||
class Effect6689(BaseEffect):
|
class Effect6689(BaseEffect):
|
||||||
@@ -30496,7 +30471,7 @@ class Effect6689(BaseEffect):
|
|||||||
return
|
return
|
||||||
bonus = module.getModifiedItemAttr('structureDamageAmount')
|
bonus = module.getModifiedItemAttr('structureDamageAmount')
|
||||||
duration = module.getModifiedItemAttr('duration') / 1000.0
|
duration = module.getModifiedItemAttr('duration') / 1000.0
|
||||||
fit.extraAttributes.increase('hullRepair', bonus / duration, **kwargs)
|
fit._hullRr.append((bonus, duration))
|
||||||
|
|
||||||
|
|
||||||
class Effect6690(BaseEffect):
|
class Effect6690(BaseEffect):
|
||||||
@@ -31607,7 +31582,7 @@ class Effect6783(BaseEffect):
|
|||||||
Used by:
|
Used by:
|
||||||
Ships from group: Carrier (4 of 4)
|
Ships from group: Carrier (4 of 4)
|
||||||
Ships from group: Combat Battlecruiser (20 of 20)
|
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: Force Auxiliary (6 of 6)
|
||||||
Ships from group: Supercarrier (6 of 6)
|
Ships from group: Supercarrier (6 of 6)
|
||||||
Ships from group: Titan (8 of 8)
|
Ships from group: Titan (8 of 8)
|
||||||
@@ -35047,12 +35022,12 @@ class Effect7166(BaseEffect):
|
|||||||
repSpoolPerCycle = container.getModifiedItemAttr('repairMultiplierBonusPerCycle')
|
repSpoolPerCycle = container.getModifiedItemAttr('repairMultiplierBonusPerCycle')
|
||||||
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
|
defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
|
||||||
spoolType, spoolAmount = resolveSpoolOptions(SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False), container)
|
spoolType, spoolAmount = resolveSpoolOptions(SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False), container)
|
||||||
rps = repAmountBase * (1 + calculateSpoolup(repSpoolMax, repSpoolPerCycle, cycleTime, spoolType, spoolAmount)[0]) / cycleTime
|
amount = repAmountBase * (1 + calculateSpoolup(repSpoolMax, repSpoolPerCycle, cycleTime, spoolType, spoolAmount)[0])
|
||||||
rpsPreSpool = repAmountBase * (1 + calculateSpoolup(repSpoolMax, repSpoolPerCycle, cycleTime, SpoolType.SPOOL_SCALE, 0)[0]) / cycleTime
|
amountPreSpool = repAmountBase * (1 + calculateSpoolup(repSpoolMax, repSpoolPerCycle, cycleTime, SpoolType.SPOOL_SCALE, 0)[0])
|
||||||
rpsFullSpool = repAmountBase * (1 + calculateSpoolup(repSpoolMax, repSpoolPerCycle, cycleTime, SpoolType.SPOOL_SCALE, 1)[0]) / cycleTime
|
amountFullSpool = repAmountBase * (1 + calculateSpoolup(repSpoolMax, repSpoolPerCycle, cycleTime, SpoolType.SPOOL_SCALE, 1)[0])
|
||||||
fit.extraAttributes.increase('armorRepair', rps, **kwargs)
|
fit._armorRr.append((amount, cycleTime))
|
||||||
fit.extraAttributes.increase('armorRepairPreSpool', rpsPreSpool, **kwargs)
|
fit._armorRrPreSpool.append((amountPreSpool, cycleTime))
|
||||||
fit.extraAttributes.increase('armorRepairFullSpool', rpsFullSpool, **kwargs)
|
fit._armorRrFullSpool.append((amountFullSpool, cycleTime))
|
||||||
|
|
||||||
|
|
||||||
class Effect7167(BaseEffect):
|
class Effect7167(BaseEffect):
|
||||||
@@ -36009,6 +35984,7 @@ class Effect8039(BaseEffect):
|
|||||||
upwellSkillaoeVelocityaoeCloudSizeBonus
|
upwellSkillaoeVelocityaoeCloudSizeBonus
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
|
Implants named like: Halcyon G Booster (5 of 5)
|
||||||
Skill: Vorton Arc Guidance
|
Skill: Vorton Arc Guidance
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -36258,12 +36234,30 @@ class Effect8065(BaseEffect):
|
|||||||
'maxRange', skill.getModifiedItemAttr('rangeSkillBonus') * skill.level, **kwargs)
|
'maxRange', skill.getModifiedItemAttr('rangeSkillBonus') * skill.level, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class Effect8064(BaseEffect):
|
||||||
|
"""
|
||||||
|
vortonProjectorOptimalRangeBonus
|
||||||
|
|
||||||
|
Used by:
|
||||||
|
Implants named like: Halcyon B Booster (5 of 5)
|
||||||
|
"""
|
||||||
|
|
||||||
|
type = 'passive'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def handler(fit, booster, context, projectionRange, **kwargs):
|
||||||
|
fit.modules.filteredItemBoost(
|
||||||
|
lambda mod: mod.item.requiresSkill('Vorton Projector Operation'), 'maxRange',
|
||||||
|
booster.getModifiedItemAttr('rangeSkillBonus'), **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Effect8066(BaseEffect):
|
class Effect8066(BaseEffect):
|
||||||
"""
|
"""
|
||||||
vortonProjectorDamageBonus
|
vortonProjectorDamageBonus
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Implants named like: Agency 'Pyrolancea' DB Dose (4 of 4)
|
Implants named like: Agency 'Pyrolancea' DB Dose (4 of 4)
|
||||||
|
Implants named like: Halcyon Y Booster (5 of 5)
|
||||||
Implant: AIR Pyrolancea Booster II
|
Implant: AIR Pyrolancea Booster II
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -37665,64 +37659,12 @@ class Effect8264(BaseEffect):
|
|||||||
skill='Industrial Command Ships', **kwargs)
|
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):
|
class Effect8270(BaseEffect):
|
||||||
"""
|
"""
|
||||||
capacitorWarfareResistanceBonusPassive
|
capacitorWarfareResistanceBonusPassive
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Implants named like: Halcyon Y Booster (5 of 5)
|
Implants named like: Halcyon Y Booster (5 of 5)
|
||||||
Implants named like: Tetrimon Anti Drain Booster (4 of 4)
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type = 'passive'
|
type = 'passive'
|
||||||
@@ -38073,6 +38015,40 @@ class Effect8323(BaseEffect):
|
|||||||
skill='Gallente Hauler', **kwargs)
|
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):
|
class Effect8360(BaseEffect):
|
||||||
"""
|
"""
|
||||||
shipBonusMissileReloadTimeGC2
|
shipBonusMissileReloadTimeGC2
|
||||||
@@ -38291,6 +38267,23 @@ class Effect8479(BaseEffect):
|
|||||||
container.getModifiedItemAttr('falloffBonus'), **kwargs)
|
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):
|
class Effect11055(BaseEffect):
|
||||||
"""
|
"""
|
||||||
shipBonusBattlecruiserHeavyMissileAoeVelocityMBC1
|
shipBonusBattlecruiserHeavyMissileAoeVelocityMBC1
|
||||||
@@ -40101,6 +40094,23 @@ class Effect11764(BaseEffect):
|
|||||||
'speed', ship.getModifiedItemAttr('shipBonusRole7'), **kwargs)
|
'speed', ship.getModifiedItemAttr('shipBonusRole7'), **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class Effect11767(BaseEffect):
|
||||||
|
"""
|
||||||
|
shipBonusHybridTrackingATC3
|
||||||
|
|
||||||
|
Used by:
|
||||||
|
Ship: Cybele
|
||||||
|
"""
|
||||||
|
|
||||||
|
type = 'passive'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def handler(fit, src, context, projectionRange, **kwargs):
|
||||||
|
fit.modules.filteredItemBoost(
|
||||||
|
lambda mod: mod.item.requiresSkill('Medium Hybrid Turret'), 'trackingSpeed',
|
||||||
|
src.getModifiedItemAttr('eliteBonusHeavyGunship1'), skill='Heavy Assault Cruisers', **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Effect11919(BaseEffect):
|
class Effect11919(BaseEffect):
|
||||||
"""
|
"""
|
||||||
shipBonusDestroyerMD1Falloff
|
shipBonusDestroyerMD1Falloff
|
||||||
@@ -40326,11 +40336,12 @@ class Effect11953(BaseEffect):
|
|||||||
stackingPenalties=True, penaltyGroup='postMul', **kwargs)
|
stackingPenalties=True, penaltyGroup='postMul', **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Effect100100(BaseEffect):
|
class Effect11992(BaseEffect):
|
||||||
"""
|
"""
|
||||||
pyfaCustomShapashAfArAmount
|
shipBonusArmorPlateMassAT
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
|
Ship: Cybele
|
||||||
Ship: Shapash
|
Ship: Shapash
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -40339,13 +40350,47 @@ class Effect100100(BaseEffect):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
def handler(fit, ship, context, projectionRange, **kwargs):
|
||||||
fit.modules.filteredItemBoost(
|
fit.modules.filteredItemBoost(
|
||||||
lambda mod: mod.item.requiresSkill('Repair Systems'),
|
lambda mod: mod.item.group.name == 'Armor Plate', 'massAddition',
|
||||||
'armorDamageAmount', 10, skill='Assault Frigates', **kwargs)
|
ship.getModifiedItemAttr('shipBonusATF3'), **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Effect100101(BaseEffect):
|
class Effect11993(BaseEffect):
|
||||||
"""
|
"""
|
||||||
pyfaCustomShapashAfShtTrackingOptimal
|
shipBonusRepairSystemsBonusATC3
|
||||||
|
|
||||||
|
Used by:
|
||||||
|
Ship: Cybele
|
||||||
|
"""
|
||||||
|
|
||||||
|
type = 'passive'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def handler(fit, src, context, projectionRange, **kwargs):
|
||||||
|
fit.modules.filteredItemBoost(
|
||||||
|
lambda mod: mod.item.requiresSkill('Repair Systems'), 'armorDamageAmount',
|
||||||
|
src.getModifiedItemAttr('shipBonusGC3'), skill='Gallente Cruiser', **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class Effect11994(BaseEffect):
|
||||||
|
"""
|
||||||
|
shipBonusHybridFalloffATC3
|
||||||
|
|
||||||
|
Used by:
|
||||||
|
Ship: Cybele
|
||||||
|
"""
|
||||||
|
|
||||||
|
type = 'passive'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def handler(fit, src, context, projectionRange, **kwargs):
|
||||||
|
fit.modules.filteredItemBoost(
|
||||||
|
lambda mod: mod.item.requiresSkill('Medium Hybrid Turret'), 'falloff',
|
||||||
|
src.getModifiedItemAttr('eliteBonusHeavyGunship2'), skill='Heavy Assault Cruisers', **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class Effect11995(BaseEffect):
|
||||||
|
"""
|
||||||
|
shipBonusHeatAfterburnerATGF
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Ship: Shapash
|
Ship: Shapash
|
||||||
@@ -40354,18 +40399,15 @@ class Effect100101(BaseEffect):
|
|||||||
type = 'passive'
|
type = 'passive'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
def handler(fit, src, context, projectionRange, **kwargs):
|
||||||
fit.modules.filteredItemBoost(
|
fit.modules.filteredItemBoost(
|
||||||
lambda mod: mod.item.requiresSkill('Small Hybrid Turret'),
|
lambda mod: mod.item.requiresSkill('Afterburner'), 'overloadSpeedFactorBonus',
|
||||||
'maxRange', 10, skill='Assault Frigates', **kwargs)
|
src.getModifiedItemAttr('shipBonusGF2'), skill='Gallente Frigate', **kwargs)
|
||||||
fit.modules.filteredItemBoost(
|
|
||||||
lambda mod: mod.item.requiresSkill('Small Hybrid Turret'),
|
|
||||||
'trackingSpeed', 10, skill='Assault Frigates', **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Effect100102(BaseEffect):
|
class Effect11996(BaseEffect):
|
||||||
"""
|
"""
|
||||||
pyfaCustomShapashGfShtDamage
|
shipBonusMWDHeatATGF
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Ship: Shapash
|
Ship: Shapash
|
||||||
@@ -40374,15 +40416,15 @@ class Effect100102(BaseEffect):
|
|||||||
type = 'passive'
|
type = 'passive'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
def handler(fit, src, context, projectionRange, **kwargs):
|
||||||
fit.modules.filteredItemBoost(
|
fit.modules.filteredItemBoost(
|
||||||
lambda mod: mod.item.requiresSkill('Small Hybrid Turret'),
|
lambda mod: mod.item.requiresSkill('High Speed Maneuvering'), 'overloadSpeedFactorBonus',
|
||||||
'damageMultiplier', 10, skill='Gallente Frigate', **kwargs)
|
src.getModifiedItemAttr('shipBonusGF2'), skill='Gallente Frigate', **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Effect100103(BaseEffect):
|
class Effect11997(BaseEffect):
|
||||||
"""
|
"""
|
||||||
pyfaCustomShapashGfPointRange
|
shipBonusArmorRepATGF
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Ship: Shapash
|
Ship: Shapash
|
||||||
@@ -40391,15 +40433,15 @@ class Effect100103(BaseEffect):
|
|||||||
type = 'passive'
|
type = 'passive'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
def handler(fit, src, context, projectionRange, **kwargs):
|
||||||
fit.modules.filteredItemBoost(
|
fit.modules.filteredItemBoost(
|
||||||
lambda mod: mod.item.group.name == 'Warp Scrambler',
|
lambda mod: mod.item.requiresSkill('Repair Systems'), 'armorDamageAmount',
|
||||||
'maxRange', 10, skill='Gallente Frigate', **kwargs)
|
src.getModifiedItemAttr('eliteBonusGunship1'), skill='Assault Frigates', **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Effect100104(BaseEffect):
|
class Effect11998(BaseEffect):
|
||||||
"""
|
"""
|
||||||
pyfaCustomShapashGfPropOverheat
|
shipBonusSmallHybridMaxRangeATF3
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Ship: Shapash
|
Ship: Shapash
|
||||||
@@ -40408,15 +40450,15 @@ class Effect100104(BaseEffect):
|
|||||||
type = 'passive'
|
type = 'passive'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
def handler(fit, src, context, projectionRange, **kwargs):
|
||||||
fit.modules.filteredItemBoost(
|
fit.modules.filteredItemBoost(
|
||||||
lambda mod: mod.item.requiresSkill('Afterburner') or mod.item.requiresSkill('High Speed Maneuvering'),
|
lambda mod: mod.item.requiresSkill('Small Hybrid Turret'), 'maxRange',
|
||||||
'overloadSpeedFactorBonus', 10, skill='Gallente Frigate', **kwargs)
|
src.getModifiedItemAttr('eliteBonusGunship2'), skill='Assault Frigates', **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Effect100105(BaseEffect):
|
class Effect11999(BaseEffect):
|
||||||
"""
|
"""
|
||||||
pyfaCustomShapashRolePlateMass
|
shipBonusSmallHybridTrackingSpeedATF3
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Ship: Shapash
|
Ship: Shapash
|
||||||
@@ -40425,31 +40467,35 @@ class Effect100105(BaseEffect):
|
|||||||
type = 'passive'
|
type = 'passive'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
def handler(fit, src, context, projectionRange, **kwargs):
|
||||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == 'Armor Plate', 'massAddition', -100, **kwargs)
|
fit.modules.filteredItemBoost(
|
||||||
|
lambda mod: mod.item.requiresSkill('Small Hybrid Turret'), 'trackingSpeed',
|
||||||
|
src.getModifiedItemAttr('eliteBonusGunship2'), skill='Assault Frigates', **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Effect100106(BaseEffect):
|
class Effect12003(BaseEffect):
|
||||||
"""
|
"""
|
||||||
pyfaCustomShapashRoleHeat
|
vortonTurretSpeeBonusPostPercentSpeedLocationShipModulesRequiringVortonProjectorOperation
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Ship: Shapash
|
Implants named like: Halcyon R Booster (5 of 5)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type = 'passive'
|
type = 'passive'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
def handler(fit, booster, context, projectionRange, **kwargs):
|
||||||
fit.modules.filteredItemBoost(lambda mod: True, 'heatDamage', -50, **kwargs)
|
fit.modules.filteredItemBoost(
|
||||||
|
lambda mod: mod.item.requiresSkill('Vorton Projector Operation'), 'speed',
|
||||||
|
booster.getModifiedItemAttr('turretSpeeBonus'), **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Effect100200(BaseEffect):
|
class Effect12038(BaseEffect):
|
||||||
"""
|
"""
|
||||||
pyfaCustomCybeleHacMhtFalloff
|
shipBonusSPTFalloffMF3
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
Ship: Cybele
|
Ship: Republic Fleet Firetail
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type = 'passive'
|
type = 'passive'
|
||||||
@@ -40457,103 +40503,5 @@ class Effect100200(BaseEffect):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
def handler(fit, ship, context, projectionRange, **kwargs):
|
||||||
fit.modules.filteredItemBoost(
|
fit.modules.filteredItemBoost(
|
||||||
lambda mod: mod.item.requiresSkill('Medium Hybrid Turret'),
|
lambda mod: mod.item.requiresSkill('Small Projectile Turret'), 'falloff',
|
||||||
'falloff', 10, skill='Heavy Assault Cruisers', **kwargs)
|
ship.getModifiedItemAttr('shipBonus3MF'), skill='Minmatar Frigate', **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Effect100201(BaseEffect):
|
|
||||||
"""
|
|
||||||
pyfaCustomCybeleHacMhtTracking
|
|
||||||
|
|
||||||
Used by:
|
|
||||||
Ship: Cybele
|
|
||||||
"""
|
|
||||||
|
|
||||||
type = 'passive'
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
|
||||||
fit.modules.filteredItemBoost(
|
|
||||||
lambda mod: mod.item.requiresSkill('Medium Hybrid Turret'),
|
|
||||||
'trackingSpeed', 7.5, skill='Heavy Assault Cruisers', **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Effect100202(BaseEffect):
|
|
||||||
"""
|
|
||||||
pyfaCustomCybeleGcMhtDamage
|
|
||||||
|
|
||||||
Used by:
|
|
||||||
Ship: Cybele
|
|
||||||
"""
|
|
||||||
|
|
||||||
type = 'passive'
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
|
||||||
fit.modules.filteredItemBoost(
|
|
||||||
lambda mod: mod.item.requiresSkill('Medium Hybrid Turret'),
|
|
||||||
'damageMultiplier', 20, skill='Gallente Cruiser', **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Effect100203(BaseEffect):
|
|
||||||
"""
|
|
||||||
pyfaCustomCybeleGcArAmount
|
|
||||||
|
|
||||||
Used by:
|
|
||||||
Ship: Cybele
|
|
||||||
"""
|
|
||||||
|
|
||||||
type = 'passive'
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
|
||||||
fit.modules.filteredItemBoost(
|
|
||||||
lambda mod: mod.item.requiresSkill('Repair Systems'),
|
|
||||||
'armorDamageAmount', 10, skill='Gallente Cruiser', **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Effect100204(BaseEffect):
|
|
||||||
"""
|
|
||||||
pyfaCustomCybeleGcPointRange
|
|
||||||
|
|
||||||
Used by:
|
|
||||||
Ship: Cybele
|
|
||||||
"""
|
|
||||||
|
|
||||||
type = 'passive'
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
|
||||||
fit.modules.filteredItemBoost(
|
|
||||||
lambda mod: mod.item.group.name == 'Warp Scrambler',
|
|
||||||
'maxRange', 25, skill='Gallente Cruiser', **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Effect100205(BaseEffect):
|
|
||||||
"""
|
|
||||||
pyfaCustomCybeleRoleVelocity
|
|
||||||
|
|
||||||
Used by:
|
|
||||||
Ship: Cybele
|
|
||||||
"""
|
|
||||||
|
|
||||||
type = 'passive'
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
|
||||||
fit.ship.boostItemAttr('maxVelocity', 30, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Effect100206(BaseEffect):
|
|
||||||
"""
|
|
||||||
pyfaCustomCybeleRolePlateMass
|
|
||||||
|
|
||||||
Used by:
|
|
||||||
Ship: Cybele
|
|
||||||
"""
|
|
||||||
|
|
||||||
type = 'passive'
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def handler(fit, ship, context, projectionRange, **kwargs):
|
|
||||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == 'Armor Plate', 'massAddition', -100, **kwargs)
|
|
||||||
|
|||||||
@@ -159,6 +159,12 @@ class Fit:
|
|||||||
self.gangBoosts = None
|
self.gangBoosts = None
|
||||||
self.__ecmProjectedList = []
|
self.__ecmProjectedList = []
|
||||||
self.commandBonuses = {}
|
self.commandBonuses = {}
|
||||||
|
# Reps received, as a list of (amount, cycle time in seconds)
|
||||||
|
self._hullRr = []
|
||||||
|
self._armorRr = []
|
||||||
|
self._armorRrPreSpool = []
|
||||||
|
self._armorRrFullSpool = []
|
||||||
|
self._shieldRr = []
|
||||||
|
|
||||||
def clearFactorReloadDependentData(self):
|
def clearFactorReloadDependentData(self):
|
||||||
# Here we clear all data known to rely on cycle parameters
|
# Here we clear all data known to rely on cycle parameters
|
||||||
@@ -550,6 +556,12 @@ class Fit:
|
|||||||
if stuff is not None and stuff != self:
|
if stuff is not None and stuff != self:
|
||||||
stuff.clear()
|
stuff.clear()
|
||||||
|
|
||||||
|
self._hullRr.clear()
|
||||||
|
self._armorRr.clear()
|
||||||
|
self._armorRrPreSpool.clear()
|
||||||
|
self._armorRrFullSpool.clear()
|
||||||
|
self._shieldRr.clear()
|
||||||
|
|
||||||
# If this is the active fit that we are clearing, not a projected fit,
|
# If this is the active fit that we are clearing, not a projected fit,
|
||||||
# then this will run and clear the projected ships and flag the next
|
# then this will run and clear the projected ships and flag the next
|
||||||
# iteration to skip this part to prevent recursion.
|
# iteration to skip this part to prevent recursion.
|
||||||
@@ -621,7 +633,7 @@ class Fit:
|
|||||||
"duration", value)
|
"duration", value)
|
||||||
|
|
||||||
if warfareBuffID == 12: # Shield Burst: Shield Extension: Shield HP
|
if warfareBuffID == 12: # Shield Burst: Shield Extension: Shield HP
|
||||||
self.ship.boostItemAttr("shieldCapacity", value, stackingPenalties=True)
|
self.ship.boostItemAttr("shieldCapacity", value)
|
||||||
|
|
||||||
if warfareBuffID == 13: # Armor Burst: Armor Energizing: Armor Resistance
|
if warfareBuffID == 13: # Armor Burst: Armor Energizing: Armor Resistance
|
||||||
for damageType in ("Em", "Thermal", "Explosive", "Kinetic"):
|
for damageType in ("Em", "Thermal", "Explosive", "Kinetic"):
|
||||||
@@ -640,7 +652,7 @@ class Fit:
|
|||||||
"duration", value)
|
"duration", value)
|
||||||
|
|
||||||
if warfareBuffID == 15: # Armor Burst: Armor Reinforcement: Armor HP
|
if warfareBuffID == 15: # Armor Burst: Armor Reinforcement: Armor HP
|
||||||
self.ship.boostItemAttr("armorHP", value, stackingPenalties=True)
|
self.ship.boostItemAttr("armorHP", value)
|
||||||
|
|
||||||
if warfareBuffID == 16: # Information Burst: Sensor Optimization: Scan Resolution
|
if warfareBuffID == 16: # Information Burst: Sensor Optimization: Scan Resolution
|
||||||
self.ship.boostItemAttr("scanResolution", value, stackingPenalties=True)
|
self.ship.boostItemAttr("scanResolution", value, stackingPenalties=True)
|
||||||
@@ -734,7 +746,7 @@ class Fit:
|
|||||||
self.ship.boostItemAttr(attr, value, stackingPenalties=True)
|
self.ship.boostItemAttr(attr, value, stackingPenalties=True)
|
||||||
|
|
||||||
if warfareBuffID == 42: # Erebus Effect Generator : Armor HP bonus
|
if warfareBuffID == 42: # Erebus Effect Generator : Armor HP bonus
|
||||||
self.ship.boostItemAttr("armorHP", value, stackingPenalties=True)
|
self.ship.boostItemAttr("armorHP", value)
|
||||||
|
|
||||||
if warfareBuffID == 43: # Erebus Effect Generator : Explosive resistance bonus
|
if warfareBuffID == 43: # Erebus Effect Generator : Explosive resistance bonus
|
||||||
for attr in ("armorExplosiveDamageResonance", "shieldExplosiveDamageResonance", "explosiveDamageResonance"):
|
for attr in ("armorExplosiveDamageResonance", "shieldExplosiveDamageResonance", "explosiveDamageResonance"):
|
||||||
@@ -756,7 +768,7 @@ class Fit:
|
|||||||
self.ship.boostItemAttr(attr, value, stackingPenalties=True)
|
self.ship.boostItemAttr(attr, value, stackingPenalties=True)
|
||||||
|
|
||||||
if warfareBuffID == 48: # Leviathan Effect Generator : Shield HP bonus
|
if warfareBuffID == 48: # Leviathan Effect Generator : Shield HP bonus
|
||||||
self.ship.boostItemAttr("shieldCapacity", value, stackingPenalties=True)
|
self.ship.boostItemAttr("shieldCapacity", value)
|
||||||
|
|
||||||
if warfareBuffID == 49: # Leviathan Effect Generator : EM resistance bonus
|
if warfareBuffID == 49: # Leviathan Effect Generator : EM resistance bonus
|
||||||
for attr in ("armorEmDamageResonance", "shieldEmDamageResonance", "emDamageResonance"):
|
for attr in ("armorEmDamageResonance", "shieldEmDamageResonance", "emDamageResonance"):
|
||||||
@@ -870,6 +882,14 @@ class Fit:
|
|||||||
if warfareBuffID == 100: # Weather_caustic_toxin_scan_resolution_bonus
|
if warfareBuffID == 100: # Weather_caustic_toxin_scan_resolution_bonus
|
||||||
self.ship.boostItemAttr("scanResolution", value, stackingPenalties=True)
|
self.ship.boostItemAttr("scanResolution", value, stackingPenalties=True)
|
||||||
|
|
||||||
|
if warfareBuffID == 2405: # Insurgency Suppression Bonus: Interdiction Range
|
||||||
|
self.modules.filteredItemBoost(
|
||||||
|
lambda mod: mod.item.requiresSkill("Navigation"),
|
||||||
|
"maxRange", value, stackingPenalties=True)
|
||||||
|
self.modules.filteredItemBoost(
|
||||||
|
lambda mod: mod.item.group.name == "Stasis Web",
|
||||||
|
"maxRange", value, stackingPenalties=True)
|
||||||
|
|
||||||
del self.commandBonuses[warfareBuffID]
|
del self.commandBonuses[warfareBuffID]
|
||||||
|
|
||||||
def __resetDependentCalcs(self):
|
def __resetDependentCalcs(self):
|
||||||
@@ -1478,11 +1498,11 @@ class Fit:
|
|||||||
def tank(self):
|
def tank(self):
|
||||||
reps = {
|
reps = {
|
||||||
"passiveShield": self.calculateShieldRecharge(),
|
"passiveShield": self.calculateShieldRecharge(),
|
||||||
"shieldRepair": self.extraAttributes["shieldRepair"],
|
"shieldRepair": self.extraAttributes["shieldRepair"] + self._getAppliedShieldRr(),
|
||||||
"armorRepair": self.extraAttributes["armorRepair"],
|
"armorRepair": self.extraAttributes["armorRepair"] + self._getAppliedArmorRr(),
|
||||||
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"],
|
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"] + self._getAppliedArmorPreSpoolRr(),
|
||||||
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"],
|
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"] + self._getAppliedArmorFullSpoolRr(),
|
||||||
"hullRepair": self.extraAttributes["hullRepair"]
|
"hullRepair": self.extraAttributes["hullRepair"] + self._getAppliedHullRr()
|
||||||
}
|
}
|
||||||
return reps
|
return reps
|
||||||
|
|
||||||
@@ -1519,11 +1539,11 @@ class Fit:
|
|||||||
if self.__sustainableTank is None:
|
if self.__sustainableTank is None:
|
||||||
sustainable = {
|
sustainable = {
|
||||||
"passiveShield": self.calculateShieldRecharge(),
|
"passiveShield": self.calculateShieldRecharge(),
|
||||||
"shieldRepair": self.extraAttributes["shieldRepair"],
|
"shieldRepair": self.extraAttributes["shieldRepair"] + self._getAppliedShieldRr(),
|
||||||
"armorRepair": self.extraAttributes["armorRepair"],
|
"armorRepair": self.extraAttributes["armorRepair"] + self._getAppliedArmorRr(),
|
||||||
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"],
|
"armorRepairPreSpool": self.extraAttributes["armorRepairPreSpool"] + self._getAppliedArmorPreSpoolRr(),
|
||||||
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"],
|
"armorRepairFullSpool": self.extraAttributes["armorRepairFullSpool"] + self._getAppliedArmorFullSpoolRr(),
|
||||||
"hullRepair": self.extraAttributes["hullRepair"]
|
"hullRepair": self.extraAttributes["hullRepair"] + self._getAppliedHullRr()
|
||||||
}
|
}
|
||||||
if not self.capStable or self.factorReload:
|
if not self.capStable or self.factorReload:
|
||||||
# Map a local repairer type to the attribute it uses
|
# Map a local repairer type to the attribute it uses
|
||||||
@@ -1760,6 +1780,38 @@ class Fit:
|
|||||||
mults.setdefault(stackingGroup, []).append((1 + strength / 100, None))
|
mults.setdefault(stackingGroup, []).append((1 + strength / 100, None))
|
||||||
return calculateMultiplier(mults)
|
return calculateMultiplier(mults)
|
||||||
|
|
||||||
|
def _getAppliedHullRr(self):
|
||||||
|
return self.__getAppliedRr(self._hullRr)
|
||||||
|
|
||||||
|
def _getAppliedArmorRr(self):
|
||||||
|
return self.__getAppliedRr(self._armorRr)
|
||||||
|
|
||||||
|
def _getAppliedArmorPreSpoolRr(self):
|
||||||
|
return self.__getAppliedRr(self._armorRrPreSpool)
|
||||||
|
|
||||||
|
def _getAppliedArmorFullSpoolRr(self):
|
||||||
|
return self.__getAppliedRr(self._armorRrFullSpool)
|
||||||
|
|
||||||
|
def _getAppliedShieldRr(self):
|
||||||
|
return self.__getAppliedRr(self._shieldRr)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def __getAppliedRr(rrList):
|
||||||
|
totalRaw = 0
|
||||||
|
for amount, cycleTime in rrList:
|
||||||
|
# That's right, for considerations of RR diminishing returns cycle time is rounded this way
|
||||||
|
totalRaw += amount / int(cycleTime)
|
||||||
|
RR_ADDITION = 7000
|
||||||
|
RR_MULTIPLIER = 10
|
||||||
|
appliedRr = 0
|
||||||
|
for amount, cycleTime in rrList:
|
||||||
|
rrps = amount / int(cycleTime)
|
||||||
|
modified_rrps = RR_ADDITION + (rrps * RR_MULTIPLIER)
|
||||||
|
rrps_mult = 1 - (((rrps + modified_rrps) / (totalRaw + modified_rrps)) - 1) ** 2
|
||||||
|
appliedRr += rrps_mult * amount / cycleTime
|
||||||
|
return appliedRr
|
||||||
|
|
||||||
|
|
||||||
def __deepcopy__(self, memo=None):
|
def __deepcopy__(self, memo=None):
|
||||||
fitCopy = Fit()
|
fitCopy = Fit()
|
||||||
# Character and owner are not copied
|
# Character and owner are not copied
|
||||||
|
|||||||
@@ -25,10 +25,11 @@ import time
|
|||||||
|
|
||||||
|
|
||||||
class SsoCharacter:
|
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.characterID = charID
|
||||||
self.characterName = name
|
self.characterName = name
|
||||||
self.client = client
|
self.client = client
|
||||||
|
self.server = server
|
||||||
self.accessToken = accessToken
|
self.accessToken = accessToken
|
||||||
self.refreshToken = refreshToken
|
self.refreshToken = refreshToken
|
||||||
self.accessTokenExpires = None
|
self.accessTokenExpires = None
|
||||||
@@ -37,6 +38,9 @@ class SsoCharacter:
|
|||||||
def init(self):
|
def init(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def characterDisplay(self):
|
||||||
|
return "{} [{}]".format(self.characterName, self.server)
|
||||||
def is_token_expired(self):
|
def is_token_expired(self):
|
||||||
if self.accessTokenExpires is None:
|
if self.accessTokenExpires is None:
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class GraphFrame(AuxiliaryFrame):
|
|||||||
newW = max(curW, bestW)
|
newW = max(curW, bestW)
|
||||||
newH = max(curH, bestH)
|
newH = max(curH, bestH)
|
||||||
if newW > curW or newH > curH:
|
if newW > curW or newH > curH:
|
||||||
newSize = wx.Size(newW, newH)
|
newSize = wx.Size(round(newW), round(newH))
|
||||||
self.SetSize(newSize)
|
self.SetSize(newSize)
|
||||||
self.SetMinSize(newSize)
|
self.SetMinSize(newSize)
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class VectorPicker(wx.Window):
|
|||||||
self._directionOnly = kwargs.pop('directionOnly', False)
|
self._directionOnly = kwargs.pop('directionOnly', False)
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._fontsize = max(1, float(kwargs.pop('fontsize', 8 / self.GetContentScaleFactor())))
|
self._fontsize = max(1, float(kwargs.pop('fontsize', 8 / self.GetContentScaleFactor())))
|
||||||
self._font = wx.Font(self._fontsize, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False)
|
self._font = wx.Font(round(self._fontsize), wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False)
|
||||||
self._angle = 0
|
self._angle = 0
|
||||||
self.__length = 1
|
self.__length = 1
|
||||||
self._left = False
|
self._left = False
|
||||||
@@ -76,7 +76,7 @@ class VectorPicker(wx.Window):
|
|||||||
self.__length = newLength
|
self.__length = newLength
|
||||||
|
|
||||||
def DoGetBestSize(self):
|
def DoGetBestSize(self):
|
||||||
return wx.Size(self._size, self._size)
|
return wx.Size(round(self._size), round(self._size))
|
||||||
|
|
||||||
def AcceptsFocusFromKeyboard(self):
|
def AcceptsFocusFromKeyboard(self):
|
||||||
return False
|
return False
|
||||||
@@ -121,35 +121,37 @@ class VectorPicker(wx.Window):
|
|||||||
|
|
||||||
radius = min(width, height) / 2 - 2
|
radius = min(width, height) / 2 - 2
|
||||||
dc.SetBrush(wx.WHITE_BRUSH)
|
dc.SetBrush(wx.WHITE_BRUSH)
|
||||||
dc.DrawCircle(radius + 2, radius + 2, radius)
|
dc.DrawCircle(round(radius + 2), round(radius + 2), round(radius))
|
||||||
a = math.radians(self._angle + self._offset)
|
a = math.radians(self._angle + self._offset)
|
||||||
x = math.cos(a) * radius
|
x = math.cos(a) * radius
|
||||||
y = math.sin(a) * radius
|
y = math.sin(a) * radius
|
||||||
# See PR #2260 on why this is needed
|
# See PR #2260 on why this is needed
|
||||||
pointRadius = 2 / self.GetContentScaleFactor() if 'wxGTK' in wx.PlatformInfo else 2
|
pointRadius = 2 / self.GetContentScaleFactor() if 'wxGTK' in wx.PlatformInfo else 2
|
||||||
dc.DrawLine(radius + 2, radius + 2, radius + 2 + x * self._length, radius + 2 - y * self._length)
|
dc.DrawLine(
|
||||||
|
round(radius + 2), round(radius + 2),
|
||||||
|
round(radius + 2 + x * self._length), round(radius + 2 - y * self._length))
|
||||||
dc.SetBrush(wx.BLACK_BRUSH)
|
dc.SetBrush(wx.BLACK_BRUSH)
|
||||||
dc.DrawCircle(radius + 2 + x * self._length, radius + 2 - y * self._length, pointRadius)
|
dc.DrawCircle(round(radius + 2 + x * self._length), round(radius + 2 - y * self._length), round(pointRadius))
|
||||||
|
|
||||||
if self._label:
|
if self._label:
|
||||||
labelText = self._label
|
labelText = self._label
|
||||||
labelTextW, labelTextH = dc.GetTextExtent(labelText)
|
labelTextW, labelTextH = dc.GetTextExtent(labelText)
|
||||||
labelTextX = (radius * 2 + 4 - labelTextW) if (self._labelpos & 1) else 0
|
labelTextX = (radius * 2 + 4 - labelTextW) if (self._labelpos & 1) else 0
|
||||||
labelTextY = (radius * 2 + 4 - labelTextH) if (self._labelpos & 2) else 0
|
labelTextY = (radius * 2 + 4 - labelTextH) if (self._labelpos & 2) else 0
|
||||||
dc.DrawText(labelText, labelTextX, labelTextY)
|
dc.DrawText(labelText, round(labelTextX), round(labelTextY))
|
||||||
|
|
||||||
if not self._directionOnly:
|
if not self._directionOnly:
|
||||||
lengthText = '%d%%' % (100 * self._length,)
|
lengthText = '%d%%' % (100 * self._length,)
|
||||||
lengthTextW, lengthTextH = dc.GetTextExtent(lengthText)
|
lengthTextW, lengthTextH = dc.GetTextExtent(lengthText)
|
||||||
lengthTextX = radius + 2 + x / 2 - y / 3 - lengthTextW / 2
|
lengthTextX = radius + 2 + x / 2 - y / 3 - lengthTextW / 2
|
||||||
lengthTextY = radius + 2 - y / 2 - x / 3 - lengthTextH / 2
|
lengthTextY = radius + 2 - y / 2 - x / 3 - lengthTextH / 2
|
||||||
dc.DrawText(lengthText, lengthTextX, lengthTextY)
|
dc.DrawText(lengthText, round(lengthTextX), round(lengthTextY))
|
||||||
|
|
||||||
angleText = '%d\u00B0' % (self._angle,)
|
angleText = '%d\u00B0' % (self._angle,)
|
||||||
angleTextW, angleTextH = dc.GetTextExtent(angleText)
|
angleTextW, angleTextH = dc.GetTextExtent(angleText)
|
||||||
angleTextX = radius + 2 - x / 2 - angleTextW / 2
|
angleTextX = radius + 2 - x / 2 - angleTextW / 2
|
||||||
angleTextY = radius + 2 + y / 2 - angleTextH / 2
|
angleTextY = radius + 2 + y / 2 - angleTextH / 2
|
||||||
dc.DrawText(angleText, angleTextX, angleTextY)
|
dc.DrawText(angleText, round(angleTextX), round(angleTextY))
|
||||||
|
|
||||||
def OnEraseBackground(self, event):
|
def OnEraseBackground(self, event):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ class AttributeGauge(wx.Window):
|
|||||||
for x in range(1, 20):
|
for x in range(1, 20):
|
||||||
dc.SetBrush(wx.Brush(wx.LIGHT_GREY))
|
dc.SetBrush(wx.Brush(wx.LIGHT_GREY))
|
||||||
dc.SetPen(wx.Pen(wx.LIGHT_GREY))
|
dc.SetPen(wx.Pen(wx.LIGHT_GREY))
|
||||||
dc.DrawRectangle(x * 10, 1, 1, rect.height)
|
dc.DrawRectangle(round(x * 10), 1, 1, round(rect.height))
|
||||||
|
|
||||||
dc.SetBrush(wx.Brush(colour))
|
dc.SetBrush(wx.Brush(colour))
|
||||||
dc.SetPen(wx.Pen(colour))
|
dc.SetPen(wx.Pen(colour))
|
||||||
@@ -222,19 +222,19 @@ class AttributeGauge(wx.Window):
|
|||||||
|
|
||||||
if value >= 0:
|
if value >= 0:
|
||||||
padding = (half if is_even else math.ceil(half - 1)) + 1
|
padding = (half if is_even else math.ceil(half - 1)) + 1
|
||||||
dc.DrawRectangle(padding, 1, w, rect.height)
|
dc.DrawRectangle(round(padding), 1, round(w), round(rect.height))
|
||||||
else:
|
else:
|
||||||
padding = half - w + 1 if is_even else math.ceil(half) - (w - 1)
|
padding = half - w + 1 if is_even else math.ceil(half) - (w - 1)
|
||||||
dc.DrawRectangle(padding, 1, w, rect.height)
|
dc.DrawRectangle(round(padding), 1, round(w), round(rect.height))
|
||||||
|
|
||||||
if self.leading_edge and (self.edge_on_neutral or value != 0):
|
if self.leading_edge and (self.edge_on_neutral or value != 0):
|
||||||
dc.SetPen(wx.Pen(wx.WHITE))
|
dc.SetPen(wx.Pen(wx.WHITE))
|
||||||
dc.SetBrush(wx.Brush(wx.WHITE))
|
dc.SetBrush(wx.Brush(wx.WHITE))
|
||||||
|
|
||||||
if value > 0:
|
if value > 0:
|
||||||
dc.DrawRectangle(min(padding + w, rect.width), 1, 1, rect.height)
|
dc.DrawRectangle(round(min(padding + w, rect.width)), 1, 1, round(rect.height))
|
||||||
else:
|
else:
|
||||||
dc.DrawRectangle(max(padding - 1, 1), 1, 1, rect.height)
|
dc.DrawRectangle(round(max(padding - 1, 1)), 1, 1, round(rect.height))
|
||||||
|
|
||||||
def OnTimer(self, event):
|
def OnTimer(self, event):
|
||||||
old_value = self._old_percentage
|
old_value = self._old_percentage
|
||||||
|
|||||||
@@ -103,10 +103,9 @@ class BitmapLoader:
|
|||||||
pyfalog.warning("Missing icon file: {0}/{1}".format(location, filename))
|
pyfalog.warning("Missing icon file: {0}/{1}".format(location, filename))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
bmp: wx.Bitmap = img.ConvertToBitmap()
|
|
||||||
if scale > 1:
|
if scale > 1:
|
||||||
bmp.SetSize((bmp.GetWidth() // scale, bmp.GetHeight() // scale))
|
return img.Scale(round(img.GetWidth() // scale), round(img.GetHeight() // scale)).ConvertToBitmap()
|
||||||
return bmp
|
return img.ConvertToBitmap()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def loadScaledBitmap(cls, name, location, scale=0):
|
def loadScaledBitmap(cls, name, location, scale=0):
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ class DroneStackSplit(wx.Dialog):
|
|||||||
|
|
||||||
self.input = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
|
self.input = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
|
||||||
self.input.SetValue(str(value))
|
self.input.SetValue(str(value))
|
||||||
self.input.SelectAll()
|
|
||||||
|
|
||||||
bSizer1.Add(self.input, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, 15)
|
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)
|
bSizer3.Add(self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND)
|
||||||
bSizer1.Add(bSizer3, 0, wx.ALL | wx.EXPAND, 10)
|
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_CHAR, self.onChar)
|
||||||
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
|
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
|
||||||
self.SetSizer(bSizer1)
|
self.SetSizer(bSizer1)
|
||||||
self.CenterOnParent()
|
|
||||||
self.Fit()
|
self.Fit()
|
||||||
|
self.CenterOnParent()
|
||||||
|
self.input.SetFocus()
|
||||||
|
self.input.SelectAll()
|
||||||
|
|
||||||
def processEnter(self, evt):
|
def processEnter(self, evt):
|
||||||
self.EndModal(wx.ID_OK)
|
self.EndModal(wx.ID_OK)
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
|
|||||||
data.groups[_t('Sansha Incursion')] = self.getEffectBeacons(
|
data.groups[_t('Sansha Incursion')] = self.getEffectBeacons(
|
||||||
_t('ContextMenu|ProjectedEffectManipulation|Sansha Incursion'))
|
_t('ContextMenu|ProjectedEffectManipulation|Sansha Incursion'))
|
||||||
data.groups[_t('Triglavian Invasion')] = self.getInvasionBeacons()
|
data.groups[_t('Triglavian Invasion')] = self.getInvasionBeacons()
|
||||||
|
# data.groups[_t('Pirate Insurgency')] = self.getEffectBeacons(
|
||||||
|
# _t('ContextMenu|ProjectedEffectManipulation|Insurgency'))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def getEffectBeacons(self, *groups, extra_garbage=()):
|
def getEffectBeacons(self, *groups, extra_garbage=()):
|
||||||
@@ -238,5 +240,12 @@ class AddEnvironmentEffect(ContextMenuUnconditional):
|
|||||||
data.items.append(Entry(item.ID, item.name, item.name))
|
data.items.append(Entry(item.ID, item.name, item.name))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def getInsurgencyBeacons(self):
|
||||||
|
data = self.getDestructibleBeacons()
|
||||||
|
# Suppression Interdiction Range Beacon
|
||||||
|
item = Market.getInstance().getItem(79839)
|
||||||
|
data.items.append(Entry(item.ID, item.name, item.name))
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
AddEnvironmentEffect.register()
|
AddEnvironmentEffect.register()
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ class NameDialog(wx.Dialog):
|
|||||||
else:
|
else:
|
||||||
value = str(value)
|
value = str(value)
|
||||||
self.input.SetValue(value)
|
self.input.SetValue(value)
|
||||||
self.input.SelectAll()
|
|
||||||
|
|
||||||
bSizer1.Add(self.input, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, 15)
|
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)
|
bSizer3.Add(self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND)
|
||||||
bSizer1.Add(bSizer3, 0, wx.ALL | wx.EXPAND, 10)
|
bSizer1.Add(bSizer3, 0, wx.ALL | wx.EXPAND, 10)
|
||||||
|
|
||||||
self.input.SetFocus()
|
|
||||||
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
|
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
|
||||||
self.SetSizer(bSizer1)
|
self.SetSizer(bSizer1)
|
||||||
self.CenterOnParent()
|
|
||||||
self.Fit()
|
self.Fit()
|
||||||
|
self.CenterOnParent()
|
||||||
|
self.input.SetFocus()
|
||||||
|
self.input.SelectAll()
|
||||||
|
|
||||||
def processEnter(self, evt):
|
def processEnter(self, evt):
|
||||||
self.EndModal(wx.ID_OK)
|
self.EndModal(wx.ID_OK)
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ class AmountChanger(wx.Dialog):
|
|||||||
|
|
||||||
self.input = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
|
self.input = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
|
||||||
self.input.SetValue(str(value))
|
self.input.SetValue(str(value))
|
||||||
self.input.SelectAll()
|
|
||||||
|
|
||||||
bSizer1.Add(self.input, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, 15)
|
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)
|
bSizer3.Add(self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND)
|
||||||
bSizer1.Add(bSizer3, 0, wx.ALL | wx.EXPAND, 10)
|
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_CHAR, self.onChar)
|
||||||
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
|
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
|
||||||
self.SetSizer(bSizer1)
|
self.SetSizer(bSizer1)
|
||||||
self.CenterOnParent()
|
|
||||||
self.Fit()
|
self.Fit()
|
||||||
|
self.CenterOnParent()
|
||||||
|
self.input.SetFocus()
|
||||||
|
self.input.SelectAll()
|
||||||
|
|
||||||
def processEnter(self, evt):
|
def processEnter(self, evt):
|
||||||
self.EndModal(wx.ID_OK)
|
self.EndModal(wx.ID_OK)
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ class RangeChanger(wx.Dialog):
|
|||||||
value = int(value)
|
value = int(value)
|
||||||
value = str(value)
|
value = str(value)
|
||||||
self.input.SetValue(value)
|
self.input.SetValue(value)
|
||||||
self.input.SelectAll()
|
|
||||||
|
|
||||||
bSizer1.Add(self.input, 0, wx.LEFT | wx.RIGHT | wx.EXPAND, 15)
|
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)
|
bSizer3.Add(self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND)
|
||||||
bSizer1.Add(bSizer3, 0, wx.ALL | wx.EXPAND, 10)
|
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_CHAR, self.onChar)
|
||||||
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
|
self.input.Bind(wx.EVT_TEXT_ENTER, self.processEnter)
|
||||||
self.SetSizer(bSizer1)
|
self.SetSizer(bSizer1)
|
||||||
self.CenterOnParent()
|
|
||||||
self.Fit()
|
self.Fit()
|
||||||
|
self.CenterOnParent()
|
||||||
|
self.input.SetFocus()
|
||||||
|
self.input.SelectAll()
|
||||||
|
|
||||||
def processEnter(self, evt):
|
def processEnter(self, evt):
|
||||||
self.EndModal(wx.ID_OK)
|
self.EndModal(wx.ID_OK)
|
||||||
|
|||||||
@@ -4,13 +4,18 @@ import wx
|
|||||||
# noinspection PyPackageRequirements
|
# noinspection PyPackageRequirements
|
||||||
import wx.lib.mixins.listctrl as listmix
|
import wx.lib.mixins.listctrl as listmix
|
||||||
|
|
||||||
|
from gui.utils.dark import isDark
|
||||||
|
|
||||||
|
|
||||||
class AutoListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ListRowHighlighter):
|
class AutoListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ListRowHighlighter):
|
||||||
def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
|
def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
|
||||||
wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
|
wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
|
||||||
listmix.ListCtrlAutoWidthMixin.__init__(self)
|
listmix.ListCtrlAutoWidthMixin.__init__(self)
|
||||||
listmix.ListRowHighlighter.__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):
|
class AutoListCtrlNoHighlight(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ListRowHighlighter):
|
||||||
def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
|
def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ import wx
|
|||||||
from logbook import Logger
|
from logbook import Logger
|
||||||
|
|
||||||
import gui.builtinMarketBrowser.pfSearchBox as SBox
|
import gui.builtinMarketBrowser.pfSearchBox as SBox
|
||||||
from config import slotColourMap
|
from config import slotColourMap, slotColourMapDark
|
||||||
from eos.saveddata.module import Module
|
from eos.saveddata.module import Module
|
||||||
from gui.builtinMarketBrowser.events import ItemSelected, RECENTLY_USED_MODULES
|
from gui.builtinMarketBrowser.events import ItemSelected, RECENTLY_USED_MODULES
|
||||||
from gui.contextMenu import ContextMenu
|
from gui.contextMenu import ContextMenu
|
||||||
from gui.display import Display
|
from gui.display import Display
|
||||||
from gui.utils.staticHelpers import DragDropHelper
|
from gui.utils.staticHelpers import DragDropHelper
|
||||||
|
from gui.utils.dark import isDark
|
||||||
from service.fit import Fit
|
from service.fit import Fit
|
||||||
from service.market import Market
|
from service.market import Market
|
||||||
|
|
||||||
@@ -243,6 +244,7 @@ class ItemView(Display):
|
|||||||
|
|
||||||
def columnBackground(self, colItem, item):
|
def columnBackground(self, colItem, item):
|
||||||
if self.sFit.serviceFittingOptions["colorFitBySlot"]:
|
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:
|
else:
|
||||||
return self.GetBackgroundColour()
|
return self.GetBackgroundColour()
|
||||||
|
|||||||
@@ -253,8 +253,8 @@ class PFSearchBox(wx.Window):
|
|||||||
else:
|
else:
|
||||||
spad = 0
|
spad = 0
|
||||||
|
|
||||||
dc.DrawBitmap(self.searchBitmapShadow, self.searchButtonX + 1, self.searchButtonY + 1)
|
dc.DrawBitmap(self.searchBitmapShadow, round(self.searchButtonX + 1), round(self.searchButtonY + 1))
|
||||||
dc.DrawBitmap(self.searchBitmap, self.searchButtonX + spad, self.searchButtonY + spad)
|
dc.DrawBitmap(self.searchBitmap, round(self.searchButtonX + spad), round(self.searchButtonY + spad))
|
||||||
|
|
||||||
if self.isCancelButtonVisible:
|
if self.isCancelButtonVisible:
|
||||||
if self.cancelBitmap:
|
if self.cancelBitmap:
|
||||||
@@ -262,8 +262,8 @@ class PFSearchBox(wx.Window):
|
|||||||
cpad = 1
|
cpad = 1
|
||||||
else:
|
else:
|
||||||
cpad = 0
|
cpad = 0
|
||||||
dc.DrawBitmap(self.cancelBitmapShadow, self.cancelButtonX + 1, self.cancelButtonY + 1)
|
dc.DrawBitmap(self.cancelBitmapShadow, round(self.cancelButtonX + 1), round(self.cancelButtonY + 1))
|
||||||
dc.DrawBitmap(self.cancelBitmap, self.cancelButtonX + cpad, self.cancelButtonY + cpad)
|
dc.DrawBitmap(self.cancelBitmap, round(self.cancelButtonX + cpad), round(self.cancelButtonY + cpad))
|
||||||
|
|
||||||
dc.SetPen(wx.Pen(sepColor, 1))
|
dc.SetPen(wx.Pen(sepColor, 1))
|
||||||
dc.DrawLine(0, rect.height - 1, rect.width, rect.height - 1)
|
dc.DrawLine(0, rect.height - 1, rect.width, rect.height - 1)
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
# noinspection PyPackageRequirements
|
# noinspection PyPackageRequirements
|
||||||
import wx
|
import wx
|
||||||
|
|
||||||
|
import config
|
||||||
import gui.mainFrame
|
import gui.mainFrame
|
||||||
from gui.bitmap_loader import BitmapLoader
|
from gui.bitmap_loader import BitmapLoader
|
||||||
from gui.preferenceView import PreferenceView
|
from gui.preferenceView import PreferenceView
|
||||||
|
from service.esi import Esi
|
||||||
from service.settings import EsiSettings
|
from service.settings import EsiSettings
|
||||||
|
|
||||||
# noinspection PyPackageRequirements
|
# noinspection PyPackageRequirements
|
||||||
@@ -41,38 +43,68 @@ class PFEsiPref(PreferenceView):
|
|||||||
"due to 'Signature has expired' error")))
|
"due to 'Signature has expired' error")))
|
||||||
mainSizer.Add(self.enforceJwtExpiration, 0, wx.ALL | wx.EXPAND, 5)
|
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)
|
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)
|
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.SetSizer(mainSizer)
|
||||||
|
|
||||||
panel.Layout()
|
panel.Layout()
|
||||||
|
|
||||||
def OnTimeoutChange(self, event):
|
def OnTimeoutChange(self, event):
|
||||||
self.settings.set('timeout', event.GetEventObject().GetValue())
|
self.settings.set('timeout', event.GetEventObject().GetValue())
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
def OnModeChange(self, event):
|
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):
|
def OnEnforceChange(self, event):
|
||||||
self.settings.set('enforceJwtExpiration', self.enforceJwtExpiration.GetValue())
|
self.settings.set('enforceJwtExpiration', self.enforceJwtExpiration.GetValue())
|
||||||
event.Skip()
|
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):
|
def getImage(self):
|
||||||
return BitmapLoader.getBitmap("eve", "gui")
|
return BitmapLoader.getBitmap("eve", "gui")
|
||||||
|
|
||||||
|
|
||||||
PFEsiPref.register()
|
PFEsiPref.register()
|
||||||
@@ -40,7 +40,7 @@ class PFGeneralPref(PreferenceView):
|
|||||||
|
|
||||||
langSizer = wx.BoxSizer(wx.HORIZONTAL)
|
langSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
|
|
||||||
self.langChoices = sorted([langInfo for lang, langInfo in LocaleSettings.supported_langauges().items()], key=lambda x: x.Description)
|
self.langChoices = sorted([langInfo for lang, langInfo in LocaleSettings.supported_languages().items()], key=lambda x: x.Description)
|
||||||
pyfaLangsEnabled = bool(self.langChoices)
|
pyfaLangsEnabled = bool(self.langChoices)
|
||||||
|
|
||||||
if pyfaLangsEnabled:
|
if pyfaLangsEnabled:
|
||||||
@@ -64,7 +64,7 @@ class PFGeneralPref(PreferenceView):
|
|||||||
langBox.Add(hl.HyperLinkCtrl(panel, -1,
|
langBox.Add(hl.HyperLinkCtrl(panel, -1,
|
||||||
_t("Interested in helping with translations?"),
|
_t("Interested in helping with translations?"),
|
||||||
URL="https://github.com/pyfa-org/Pyfa/blob/master/locale/README.md"
|
URL="https://github.com/pyfa-org/Pyfa/blob/master/locale/README.md"
|
||||||
), 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 15)
|
), 0, wx.LEFT, 15)
|
||||||
else:
|
else:
|
||||||
self.stLangLabel = wx.StaticText(panel, wx.ID_ANY, _t("Pyfa language selection disabled. Please check if .mo files have been generated.\nRefer to locale/README.md for info."), wx.DefaultPosition, wx.DefaultSize, 0)
|
self.stLangLabel = wx.StaticText(panel, wx.ID_ANY, _t("Pyfa language selection disabled. Please check if .mo files have been generated.\nRefer to locale/README.md for info."), wx.DefaultPosition, wx.DefaultSize, 0)
|
||||||
self.stLangLabel.Wrap(-1)
|
self.stLangLabel.Wrap(-1)
|
||||||
@@ -93,7 +93,7 @@ class PFGeneralPref(PreferenceView):
|
|||||||
langBox.Add(wx.StaticText(panel, wx.ID_ANY,
|
langBox.Add(wx.StaticText(panel, wx.ID_ANY,
|
||||||
_t("Auto will use the same language pyfa uses if available, otherwise English"),
|
_t("Auto will use the same language pyfa uses if available, otherwise English"),
|
||||||
wx.DefaultPosition,
|
wx.DefaultPosition,
|
||||||
wx.DefaultSize, 0), 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 15)
|
wx.DefaultSize, 0), 0, wx.LEFT, 15)
|
||||||
|
|
||||||
self.cbGlobalChar = wx.CheckBox(panel, wx.ID_ANY, _t("Use global character"), wx.DefaultPosition, wx.DefaultSize,
|
self.cbGlobalChar = wx.CheckBox(panel, wx.ID_ANY, _t("Use global character"), wx.DefaultPosition, wx.DefaultSize,
|
||||||
0)
|
0)
|
||||||
|
|||||||
@@ -104,14 +104,14 @@ class CategoryItem(SFBrowserItem):
|
|||||||
textColor = colorUtils.GetSuitable(windowColor, 1)
|
textColor = colorUtils.GetSuitable(windowColor, 1)
|
||||||
|
|
||||||
mdc.SetTextForeground(textColor)
|
mdc.SetTextForeground(textColor)
|
||||||
mdc.DrawBitmap(self.dropShadowBitmap, self.shipBmpx + 1, self.shipBmpy + 1)
|
mdc.DrawBitmap(self.dropShadowBitmap, round(self.shipBmpx + 1), round(self.shipBmpy + 1))
|
||||||
mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0)
|
mdc.DrawBitmap(self.shipBmp, round(self.shipBmpx), round(self.shipBmpy), 0)
|
||||||
|
|
||||||
mdc.SetFont(self.fontBig)
|
mdc.SetFont(self.fontBig)
|
||||||
|
|
||||||
categoryName, fittings = self.fittingInfo
|
categoryName, fittings = self.fittingInfo
|
||||||
|
|
||||||
mdc.DrawText(categoryName, self.catx, self.caty)
|
mdc.DrawText(categoryName, round(self.catx), round(self.caty))
|
||||||
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|||||||
@@ -416,9 +416,18 @@ class FitItem(SFItem.SFBrowserItem):
|
|||||||
if self.dragging:
|
if self.dragging:
|
||||||
if not self.dragged:
|
if not self.dragged:
|
||||||
if self.dragMotionTrigger < 0:
|
if self.dragMotionTrigger < 0:
|
||||||
|
if not self.dragTLFBmp:
|
||||||
|
tdc = wx.MemoryDC()
|
||||||
|
bmpWidth = self.toolbarx if self.toolbarx < 200 else 200
|
||||||
|
self.dragTLFBmp = wx.Bitmap(round(bmpWidth), round(self.GetRect().height))
|
||||||
|
tdc.SelectObject(self.dragTLFBmp)
|
||||||
|
tdc.SetBrush(wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)))
|
||||||
|
tdc.DrawRectangle(0, 0, bmpWidth, self.GetRect().height)
|
||||||
|
self.DrawItem(tdc)
|
||||||
|
tdc.SelectObject(wx.NullBitmap)
|
||||||
if not self.HasCapture():
|
if not self.HasCapture():
|
||||||
self.CaptureMouse()
|
self.CaptureMouse()
|
||||||
self.dragWindow = PFBitmapFrame(self, pos, self.dragTLFBmp)
|
self.dragWindow = PFBitmapFrame(self, pos, self.dragTLFBmp)
|
||||||
self.dragWindow.Show()
|
self.dragWindow.Show()
|
||||||
self.dragged = True
|
self.dragged = True
|
||||||
self.dragMotionTrigger = self.dragMotionTrail
|
self.dragMotionTrigger = self.dragMotionTrail
|
||||||
@@ -493,9 +502,9 @@ class FitItem(SFItem.SFBrowserItem):
|
|||||||
else:
|
else:
|
||||||
shipEffBk = self.shipEffBk
|
shipEffBk = self.shipEffBk
|
||||||
|
|
||||||
mdc.DrawBitmap(shipEffBk, self.shipEffx, self.shipEffy, 0)
|
mdc.DrawBitmap(shipEffBk, round(self.shipEffx), round(self.shipEffy), 0)
|
||||||
|
|
||||||
mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0)
|
mdc.DrawBitmap(self.shipBmp, round(self.shipBmpx), round(self.shipBmpy), 0)
|
||||||
|
|
||||||
mdc.SetFont(self.fontNormal)
|
mdc.SetFont(self.fontNormal)
|
||||||
|
|
||||||
@@ -504,26 +513,21 @@ class FitItem(SFItem.SFBrowserItem):
|
|||||||
pfdate = drawUtils.GetPartialText(mdc, fitLocalDate,
|
pfdate = drawUtils.GetPartialText(mdc, fitLocalDate,
|
||||||
self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
|
self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
|
||||||
|
|
||||||
mdc.DrawText(pfdate, self.textStartx, self.timestampy)
|
mdc.DrawText(pfdate, round(self.textStartx), round(self.timestampy))
|
||||||
|
|
||||||
mdc.SetFont(self.fontSmall)
|
mdc.SetFont(self.fontSmall)
|
||||||
mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery)
|
mdc.DrawText(self.toolbar.hoverLabel, round(self.thoverx), round(self.thovery))
|
||||||
|
|
||||||
mdc.SetFont(self.fontBig)
|
mdc.SetFont(self.fontBig)
|
||||||
|
|
||||||
psname = drawUtils.GetPartialText(mdc, self.fitName,
|
psname = drawUtils.GetPartialText(mdc, self.fitName,
|
||||||
self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
|
self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
|
||||||
|
|
||||||
mdc.DrawText(psname, self.textStartx, self.fitNamey)
|
mdc.DrawText(psname, round(self.textStartx), round(self.fitNamey))
|
||||||
|
|
||||||
if self.tcFitName.IsShown():
|
if self.tcFitName.IsShown():
|
||||||
self.AdjustControlSizePos(self.tcFitName, self.textStartx, self.toolbarx - self.editWidth - self.padding)
|
self.AdjustControlSizePos(self.tcFitName, self.textStartx, self.toolbarx - self.editWidth - self.padding)
|
||||||
|
|
||||||
tdc = wx.MemoryDC()
|
|
||||||
self.dragTLFBmp = wx.Bitmap((self.toolbarx if self.toolbarx < 200 else 200), rect.height, 24)
|
|
||||||
tdc.SelectObject(self.dragTLFBmp)
|
|
||||||
tdc.Blit(0, 0, (self.toolbarx if self.toolbarx < 200 else 200), rect.height, mdc, 0, 0, wx.COPY)
|
|
||||||
tdc.SelectObject(wx.NullBitmap)
|
|
||||||
|
|
||||||
def AdjustControlSizePos(self, editCtl, start, end):
|
def AdjustControlSizePos(self, editCtl, start, end):
|
||||||
fnEditSize = editCtl.GetSize()
|
fnEditSize = editCtl.GetSize()
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ class NavigationPanel(SFItem.SFBrowserItem):
|
|||||||
|
|
||||||
self.toolbar.SetPosition((self.toolbarx, self.toolbary))
|
self.toolbar.SetPosition((self.toolbarx, self.toolbary))
|
||||||
mdc.SetFont(self.fontSmall)
|
mdc.SetFont(self.fontSmall)
|
||||||
mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery)
|
mdc.DrawText(self.toolbar.hoverLabel, round(self.thoverx), round(self.thovery))
|
||||||
mdc.SetPen(wx.Pen(sepColor, 1))
|
mdc.SetPen(wx.Pen(sepColor, 1))
|
||||||
mdc.DrawLine(0, rect.height - 1, rect.width, rect.height - 1)
|
mdc.DrawLine(0, rect.height - 1, rect.width, rect.height - 1)
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class PFBitmapFrame(wx.Frame):
|
|||||||
# todo: evaluate wx.DragImage, might make this class obsolete, however might also lose our customizations
|
# todo: evaluate wx.DragImage, might make this class obsolete, however might also lose our customizations
|
||||||
# (like the sexy fade-in animation)
|
# (like the sexy fade-in animation)
|
||||||
rect = self.GetRect()
|
rect = self.GetRect()
|
||||||
canvas = wx.Bitmap(rect.width, rect.height)
|
canvas = wx.Bitmap(round(rect.width), round(rect.height))
|
||||||
# todo: convert to context manager after updating to wxPython >v4.0.1 (4.0.1 has a bug, see #1421)
|
# todo: convert to context manager after updating to wxPython >v4.0.1 (4.0.1 has a bug, see #1421)
|
||||||
# See #1418 for discussion
|
# See #1418 for discussion
|
||||||
mdc = wx.BufferedPaintDC(self)
|
mdc = wx.BufferedPaintDC(self)
|
||||||
@@ -63,4 +63,4 @@ class PFBitmapFrame(wx.Frame):
|
|||||||
mdc.DrawBitmap(self.bitmap, 0, 0)
|
mdc.DrawBitmap(self.bitmap, 0, 0)
|
||||||
mdc.SetPen(wx.Pen("#000000", width=1))
|
mdc.SetPen(wx.Pen("#000000", width=1))
|
||||||
mdc.SetBrush(wx.TRANSPARENT_BRUSH)
|
mdc.SetBrush(wx.TRANSPARENT_BRUSH)
|
||||||
mdc.DrawRectangle(0, 0, rect.width, rect.height)
|
mdc.DrawRectangle(0, 0, round(rect.width), round(rect.height))
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class PFListPane(wx.ScrolledWindow):
|
|||||||
|
|
||||||
posy = self.GetScrollPos(wx.VERTICAL)
|
posy = self.GetScrollPos(wx.VERTICAL)
|
||||||
posy -= self.itemsHeight
|
posy -= self.itemsHeight
|
||||||
self.Scroll(0, posy)
|
self.Scroll(0, round(posy))
|
||||||
|
|
||||||
event.Skip()
|
event.Skip()
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ class PFListPane(wx.ScrolledWindow):
|
|||||||
|
|
||||||
posy = self.GetScrollPos(wx.VERTICAL)
|
posy = self.GetScrollPos(wx.VERTICAL)
|
||||||
posy += self.itemsHeight
|
posy += self.itemsHeight
|
||||||
self.Scroll(0, posy)
|
self.Scroll(0, round(posy))
|
||||||
|
|
||||||
event.Skip()
|
event.Skip()
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ class PFListPane(wx.ScrolledWindow):
|
|||||||
|
|
||||||
# if we need to adjust
|
# if we need to adjust
|
||||||
if new_vs_x != -1 or new_vs_y != -1:
|
if new_vs_x != -1 or new_vs_y != -1:
|
||||||
self.Scroll(new_vs_x, new_vs_y)
|
self.Scroll(round(new_vs_x), round(new_vs_y))
|
||||||
|
|
||||||
def AddWidget(self, widget):
|
def AddWidget(self, widget):
|
||||||
widget.Reparent(self)
|
widget.Reparent(self)
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ class RaceSelector(wx.Window):
|
|||||||
img = img.Rotate90(False)
|
img = img.Rotate90(False)
|
||||||
img.Replace(0, 0, 0, sysTextColour[0], sysTextColour[1], sysTextColour[2])
|
img.Replace(0, 0, 0, sysTextColour[0], sysTextColour[1], sysTextColour[2])
|
||||||
if layout == wx.VERTICAL:
|
if layout == wx.VERTICAL:
|
||||||
img = img.Scale(self.minWidth, 8, wx.IMAGE_QUALITY_HIGH)
|
img = img.Scale(round(self.minWidth), 8, wx.IMAGE_QUALITY_HIGH)
|
||||||
|
|
||||||
self.bmpArrow = wx.Bitmap(img)
|
self.bmpArrow = wx.Bitmap(img)
|
||||||
|
|
||||||
@@ -194,25 +194,25 @@ class RaceSelector(wx.Window):
|
|||||||
bmp = wx.Bitmap(img)
|
bmp = wx.Bitmap(img)
|
||||||
|
|
||||||
if self.layout == wx.VERTICAL:
|
if self.layout == wx.VERTICAL:
|
||||||
mdc.DrawBitmap(dropShadow, rect.width - self.buttonsPadding - bmp.GetWidth() + 1, y + 1)
|
mdc.DrawBitmap(dropShadow, round(rect.width - self.buttonsPadding - bmp.GetWidth() + 1), round(y + 1))
|
||||||
mdc.DrawBitmap(bmp, rect.width - self.buttonsPadding - bmp.GetWidth(), y)
|
mdc.DrawBitmap(bmp, round(rect.width - self.buttonsPadding - bmp.GetWidth()), round(y))
|
||||||
y += raceBmp.GetHeight() + self.buttonsPadding
|
y += raceBmp.GetHeight() + self.buttonsPadding
|
||||||
mdc.SetPen(wx.Pen(sepColor, 1))
|
mdc.SetPen(wx.Pen(sepColor, 1))
|
||||||
mdc.DrawLine(rect.width - 1, 0, rect.width - 1, rect.height)
|
mdc.DrawLine(rect.width - 1, 0, rect.width - 1, rect.height)
|
||||||
else:
|
else:
|
||||||
mdc.DrawBitmap(dropShadow, x + 1, self.buttonsPadding + 1)
|
mdc.DrawBitmap(dropShadow, round(x + 1), round(self.buttonsPadding + 1))
|
||||||
mdc.DrawBitmap(bmp, x, self.buttonsPadding)
|
mdc.DrawBitmap(bmp, round(x), round(self.buttonsPadding))
|
||||||
x += raceBmp.GetWidth() + self.buttonsPadding
|
x += raceBmp.GetWidth() + self.buttonsPadding
|
||||||
mdc.SetPen(wx.Pen(sepColor, 1))
|
mdc.SetPen(wx.Pen(sepColor, 1))
|
||||||
mdc.DrawLine(0, 0, rect.width, 0)
|
mdc.DrawLine(0, 0, rect.width, 0)
|
||||||
|
|
||||||
if self.direction < 1:
|
if self.direction < 1:
|
||||||
if self.layout == wx.VERTICAL:
|
if self.layout == wx.VERTICAL:
|
||||||
mdc.DrawBitmap(self.bmpArrow, -2, (rect.height - self.bmpArrow.GetHeight()) / 2)
|
mdc.DrawBitmap(self.bmpArrow, -2, round((rect.height - self.bmpArrow.GetHeight()) / 2))
|
||||||
else:
|
else:
|
||||||
mdc.SetPen(wx.Pen(sepColor, 1))
|
mdc.SetPen(wx.Pen(sepColor, 1))
|
||||||
mdc.DrawLine(0, 0, rect.width, 0)
|
mdc.DrawLine(0, 0, rect.width, 0)
|
||||||
mdc.DrawBitmap(self.bmpArrow, (rect.width - self.bmpArrow.GetWidth()) / 2, -2)
|
mdc.DrawBitmap(self.bmpArrow, round((rect.width - self.bmpArrow.GetWidth()) / 2), -2)
|
||||||
|
|
||||||
def OnTimer(self, event):
|
def OnTimer(self, event):
|
||||||
if event.GetId() == self.animTimerID:
|
if event.GetId() == self.animTimerID:
|
||||||
|
|||||||
@@ -233,8 +233,8 @@ class PFToolbar:
|
|||||||
|
|
||||||
bmpWidth = bmp.GetWidth()
|
bmpWidth = bmp.GetWidth()
|
||||||
|
|
||||||
pdc.DrawBitmap(dropShadowBmp, bx + self.padding / 2, self.toolbarY + self.padding / 2)
|
pdc.DrawBitmap(dropShadowBmp, round(bx + self.padding / 2), round(self.toolbarY + self.padding / 2))
|
||||||
pdc.DrawBitmap(bmp, tbx, by)
|
pdc.DrawBitmap(bmp, round(tbx), round(by))
|
||||||
|
|
||||||
bx += bmpWidth + self.padding
|
bx += bmpWidth + self.padding
|
||||||
|
|
||||||
|
|||||||
@@ -247,12 +247,12 @@ class ShipItem(SFItem.SFBrowserItem):
|
|||||||
else:
|
else:
|
||||||
shipEffBk = self.shipEffBk
|
shipEffBk = self.shipEffBk
|
||||||
|
|
||||||
mdc.DrawBitmap(shipEffBk, self.shipEffx, self.shipEffy, 0)
|
mdc.DrawBitmap(shipEffBk, round(self.shipEffx), round(self.shipEffy), 0)
|
||||||
|
|
||||||
mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0)
|
mdc.DrawBitmap(self.shipBmp, round(self.shipBmpx), round(self.shipBmpy), 0)
|
||||||
|
|
||||||
mdc.DrawBitmap(self.raceDropShadowBmp, self.raceBmpx + 1, self.raceBmpy + 1)
|
mdc.DrawBitmap(self.raceDropShadowBmp, round(self.raceBmpx + 1), round(self.raceBmpy + 1))
|
||||||
mdc.DrawBitmap(self.raceBmp, self.raceBmpx, self.raceBmpy)
|
mdc.DrawBitmap(self.raceBmp, round(self.raceBmpx), round(self.raceBmpy))
|
||||||
|
|
||||||
shipName, shipTrait, fittings = self.shipFittingInfo
|
shipName, shipTrait, fittings = self.shipFittingInfo
|
||||||
|
|
||||||
@@ -264,17 +264,17 @@ class ShipItem(SFItem.SFBrowserItem):
|
|||||||
fformat = "%d fits"
|
fformat = "%d fits"
|
||||||
|
|
||||||
mdc.SetFont(self.fontNormal)
|
mdc.SetFont(self.fontNormal)
|
||||||
mdc.DrawText(fformat % fittings if fittings > 0 else fformat, self.textStartx, self.fittingsy)
|
mdc.DrawText(fformat % fittings if fittings > 0 else fformat, round(self.textStartx), round(self.fittingsy))
|
||||||
|
|
||||||
mdc.SetFont(self.fontSmall)
|
mdc.SetFont(self.fontSmall)
|
||||||
mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery)
|
mdc.DrawText(self.toolbar.hoverLabel, round(self.thoverx), round(self.thovery))
|
||||||
|
|
||||||
mdc.SetFont(self.fontBig)
|
mdc.SetFont(self.fontBig)
|
||||||
|
|
||||||
psname = drawUtils.GetPartialText(mdc, shipName,
|
psname = drawUtils.GetPartialText(mdc, shipName,
|
||||||
self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
|
self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
|
||||||
|
|
||||||
mdc.DrawText(psname, self.textStartx, self.shipNamey)
|
mdc.DrawText(psname, round(self.textStartx), round(self.shipNamey))
|
||||||
|
|
||||||
if self.tcFitName.IsShown():
|
if self.tcFitName.IsShown():
|
||||||
self.AdjustControlSizePos(self.tcFitName, self.textStartx, self.toolbarx - self.editWidth - self.padding)
|
self.AdjustControlSizePos(self.tcFitName, self.textStartx, self.toolbarx - self.editWidth - self.padding)
|
||||||
|
|||||||
@@ -146,8 +146,8 @@ class ResistancesViewFull(StatsView):
|
|||||||
|
|
||||||
lbl = PyGauge(contentPanel, font, 100)
|
lbl = PyGauge(contentPanel, font, 100)
|
||||||
lbl.SetMinSize((48, 16))
|
lbl.SetMinSize((48, 16))
|
||||||
lbl.SetBackgroundColour(wx.Colour(bc[0], bc[1], bc[2]))
|
lbl.SetBackgroundColour(wx.Colour(round(bc[0]), round(bc[1]), round(bc[2])))
|
||||||
lbl.SetBarColour(wx.Colour(fc[0], fc[1], fc[2]))
|
lbl.SetBarColour(wx.Colour(round(fc[0]), round(fc[1]), round(fc[2])))
|
||||||
lbl.SetBarGradient()
|
lbl.SetBarGradient()
|
||||||
lbl.SetFractionDigits(1)
|
lbl.SetFractionDigits(1)
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ class Miscellanea(ViewColumn):
|
|||||||
text = "{0}/s".format(formatAmount(capPerSec, 3, 0, 3))
|
text = "{0}/s".format(formatAmount(capPerSec, 3, 0, 3))
|
||||||
tooltip = "Energy neutralization per second"
|
tooltip = "Energy neutralization per second"
|
||||||
return text, tooltip
|
return text, tooltip
|
||||||
elif itemGroup == "Salvager":
|
elif itemGroup in ("Salvager", "Salvage Drone"):
|
||||||
chance = stuff.getModifiedItemAttr("accessDifficultyBonus")
|
chance = stuff.getModifiedItemAttr("accessDifficultyBonus")
|
||||||
if not chance:
|
if not chance:
|
||||||
return "", None
|
return "", None
|
||||||
|
|||||||
@@ -39,9 +39,10 @@ from gui.builtinViewColumns.state import State
|
|||||||
from gui.chrome_tabs import EVT_NOTEBOOK_PAGE_CHANGED
|
from gui.chrome_tabs import EVT_NOTEBOOK_PAGE_CHANGED
|
||||||
from gui.contextMenu import ContextMenu
|
from gui.contextMenu import ContextMenu
|
||||||
from gui.utils.staticHelpers import DragDropHelper
|
from gui.utils.staticHelpers import DragDropHelper
|
||||||
|
from gui.utils.dark import isDark
|
||||||
from service.fit import Fit
|
from service.fit import Fit
|
||||||
from service.market import Market
|
from service.market import Market
|
||||||
from config import slotColourMap
|
from config import slotColourMap, slotColourMapDark, errColor, errColorDark
|
||||||
from gui.fitCommands.helpers import getSimilarModPositions
|
from gui.fitCommands.helpers import getSimilarModPositions
|
||||||
|
|
||||||
pyfalog = Logger(__name__)
|
pyfalog = Logger(__name__)
|
||||||
@@ -729,7 +730,10 @@ class FittingView(d.Display):
|
|||||||
event.Skip()
|
event.Skip()
|
||||||
|
|
||||||
def slotColour(self, slot):
|
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):
|
def refresh(self, stuff):
|
||||||
"""
|
"""
|
||||||
@@ -774,7 +778,7 @@ class FittingView(d.Display):
|
|||||||
|
|
||||||
|
|
||||||
if slotMap[mod.slot] or hasRestrictionOverriden: # Color too many modules as red
|
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
|
elif sFit.serviceFittingOptions["colorFitBySlot"]: # Color by slot it enabled
|
||||||
self.SetItemBackgroundColour(i, self.slotColour(mod.slot))
|
self.SetItemBackgroundColour(i, self.slotColour(mod.slot))
|
||||||
|
|
||||||
@@ -895,7 +899,7 @@ class FittingView(d.Display):
|
|||||||
opts.m_labelText = name
|
opts.m_labelText = name
|
||||||
|
|
||||||
if imgId != -1:
|
if imgId != -1:
|
||||||
opts.m_labelBitmap = wx.Bitmap(isize, isize)
|
opts.m_labelBitmap = wx.Bitmap(round(isize), round(isize))
|
||||||
|
|
||||||
width = render.DrawHeaderButton(self, tdc, (0, 0, 16, 16), sortArrow=wx.HDR_SORT_ICON_NONE, params=opts)
|
width = render.DrawHeaderButton(self, tdc, (0, 0, 16, 16), sortArrow=wx.HDR_SORT_ICON_NONE, params=opts)
|
||||||
|
|
||||||
@@ -911,7 +915,7 @@ class FittingView(d.Display):
|
|||||||
maxWidth += columnsWidths[i]
|
maxWidth += columnsWidths[i]
|
||||||
|
|
||||||
mdc = wx.MemoryDC()
|
mdc = wx.MemoryDC()
|
||||||
mbmp = wx.Bitmap(maxWidth, maxRowHeight * rows + padding * 4 + headerSize)
|
mbmp = wx.Bitmap(round(maxWidth), round(maxRowHeight * rows + padding * 4 + headerSize))
|
||||||
|
|
||||||
mdc.SelectObject(mbmp)
|
mdc.SelectObject(mbmp)
|
||||||
|
|
||||||
@@ -956,7 +960,7 @@ class FittingView(d.Display):
|
|||||||
cx = padding
|
cx = padding
|
||||||
|
|
||||||
if slotMap[st.slot]:
|
if slotMap[st.slot]:
|
||||||
mdc.DrawRectangle(cx, cy, maxWidth - cx, maxRowHeight)
|
mdc.DrawRectangle(round(cx), round(cy), round(maxWidth - cx), round(maxRowHeight))
|
||||||
|
|
||||||
for i, col in enumerate(self.activeColumns):
|
for i, col in enumerate(self.activeColumns):
|
||||||
if i > maxColumns:
|
if i > maxColumns:
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ class SkillTreeView(wx.Panel):
|
|||||||
bSizerButtons.AddStretchSpacer()
|
bSizerButtons.AddStretchSpacer()
|
||||||
|
|
||||||
importExport = ((_t("Import skills from clipboard"), wx.ART_FILE_OPEN, "import"),
|
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:
|
for tooltip, art, attr in importExport:
|
||||||
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
|
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
|
||||||
@@ -446,6 +446,7 @@ class SkillTreeView(wx.Panel):
|
|||||||
|
|
||||||
text = fromClipboard().strip()
|
text = fromClipboard().strip()
|
||||||
if text:
|
if text:
|
||||||
|
sCharacter = Character.getInstance()
|
||||||
char = self.charEditor.entityEditor.getActiveEntity()
|
char = self.charEditor.entityEditor.getActiveEntity()
|
||||||
try:
|
try:
|
||||||
lines = text.splitlines()
|
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, level = s.rsplit(None, 1)[0], arabicOrRomanToInt(s.rsplit(None, 1)[1])
|
||||||
skill = char.getSkill(skill)
|
skill = char.getSkill(skill)
|
||||||
if skill:
|
if skill:
|
||||||
skill.setLevel(level, ignoreRestrict=True)
|
sCharacter.changeLevel(char.ID, skill.item.ID, level)
|
||||||
|
|
||||||
except (KeyboardInterrupt, SystemExit):
|
except (KeyboardInterrupt, SystemExit):
|
||||||
raise
|
raise
|
||||||
@@ -516,7 +517,10 @@ class SkillTreeView(wx.Panel):
|
|||||||
def populateSkillTreeSkillSearch(self, event=None):
|
def populateSkillTreeSkillSearch(self, event=None):
|
||||||
sChar = Character.getInstance()
|
sChar = Character.getInstance()
|
||||||
char = self.charEditor.entityEditor.getActiveEntity()
|
char = self.charEditor.entityEditor.getActiveEntity()
|
||||||
search = self.searchInput.GetLineText(0)
|
try:
|
||||||
|
search = self.searchInput.GetLineText(0)
|
||||||
|
except AttributeError:
|
||||||
|
search = self.searchInput.GetValue()
|
||||||
|
|
||||||
root = self.root
|
root = self.root
|
||||||
tree = self.skillTreeListCtrl
|
tree = self.skillTreeListCtrl
|
||||||
@@ -530,7 +534,7 @@ class SkillTreeView(wx.Panel):
|
|||||||
iconId = self.skillBookDirtyImageId
|
iconId = self.skillBookDirtyImageId
|
||||||
|
|
||||||
childId = tree.AppendItem(root, name, iconId, data=('skill', id))
|
childId = tree.AppendItem(root, name, iconId, data=('skill', id))
|
||||||
tree.SetItemText(childId, 1, _t("Level {}d").format(int(level)) if isinstance(level, float) else level)
|
tree.SetItemText(childId, 1, _t("Level {}").format(int(level)) if isinstance(level, float) else level)
|
||||||
|
|
||||||
def populateSkillTree(self, event=None):
|
def populateSkillTree(self, event=None):
|
||||||
sChar = Character.getInstance()
|
sChar = Character.getInstance()
|
||||||
@@ -588,7 +592,6 @@ class SkillTreeView(wx.Panel):
|
|||||||
iconId = self.skillBookDirtyImageId
|
iconId = self.skillBookDirtyImageId
|
||||||
|
|
||||||
childId = tree.AppendItem(root, name, iconId, data=('skill', id))
|
childId = tree.AppendItem(root, name, iconId, data=('skill', id))
|
||||||
|
|
||||||
tree.SetItemText(childId, 1, _t("Level {}").format(int(level)) if isinstance(level, float) else level)
|
tree.SetItemText(childId, 1, _t("Level {}").format(int(level)) if isinstance(level, float) else level)
|
||||||
|
|
||||||
def spawnMenu(self, event):
|
def spawnMenu(self, event):
|
||||||
@@ -804,7 +807,12 @@ class APIView(wx.Panel):
|
|||||||
|
|
||||||
self.SetSizer(pmainSizer)
|
self.SetSizer(pmainSizer)
|
||||||
self.Layout()
|
self.Layout()
|
||||||
self.ssoListChanged(None)
|
try:
|
||||||
|
self.ssoListChanged(None)
|
||||||
|
except (KeyboardInterrupt, SystemExit):
|
||||||
|
raise
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def ssoCharChanged(self, event):
|
def ssoCharChanged(self, event):
|
||||||
sChar = Character.getInstance()
|
sChar = Character.getInstance()
|
||||||
@@ -856,7 +864,7 @@ class APIView(wx.Panel):
|
|||||||
noneID = self.charChoice.Append(_t("None"), None)
|
noneID = self.charChoice.Append(_t("None"), None)
|
||||||
|
|
||||||
for char in ssoChars:
|
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:
|
if sso is not None and char.ID == sso.ID:
|
||||||
self.charChoice.SetSelection(currId)
|
self.charChoice.SetSelection(currId)
|
||||||
|
|||||||
@@ -514,7 +514,7 @@ class _TabRenderer:
|
|||||||
Creates the tab background bitmap based upon calculated dimension values
|
Creates the tab background bitmap based upon calculated dimension values
|
||||||
and modified bitmaps via InitBitmaps()
|
and modified bitmaps via InitBitmaps()
|
||||||
"""
|
"""
|
||||||
bk_bmp = wx.Bitmap(self.tab_width, self.tab_height)
|
bk_bmp = wx.Bitmap(round(self.tab_width), round(self.tab_height))
|
||||||
|
|
||||||
mdc = wx.MemoryDC()
|
mdc = wx.MemoryDC()
|
||||||
mdc.SelectObject(bk_bmp)
|
mdc.SelectObject(bk_bmp)
|
||||||
@@ -525,16 +525,16 @@ class _TabRenderer:
|
|||||||
|
|
||||||
# convert middle bitmap and scale to tab width
|
# convert middle bitmap and scale to tab width
|
||||||
cm = self.ctab_middle_bmp.ConvertToImage()
|
cm = self.ctab_middle_bmp.ConvertToImage()
|
||||||
mimg = cm.Scale(self.content_width, self.ctab_middle.GetHeight(),
|
mimg = cm.Scale(round(self.content_width), round(self.ctab_middle.GetHeight()),
|
||||||
wx.IMAGE_QUALITY_NORMAL)
|
wx.IMAGE_QUALITY_NORMAL)
|
||||||
mbmp = wx.Bitmap(mimg)
|
mbmp = wx.Bitmap(mimg)
|
||||||
|
|
||||||
# draw middle bitmap, offset by left
|
# draw middle bitmap, offset by left
|
||||||
mdc.DrawBitmap(mbmp, self.left_width, 0)
|
mdc.DrawBitmap(mbmp, round(self.left_width), 0)
|
||||||
|
|
||||||
# draw right bitmap offset by left + middle
|
# draw right bitmap offset by left + middle
|
||||||
mdc.DrawBitmap(self.ctab_right_bmp,
|
mdc.DrawBitmap(self.ctab_right_bmp,
|
||||||
self.content_width + self.left_width, 0)
|
round(self.content_width + self.left_width), 0)
|
||||||
|
|
||||||
mdc.SelectObject(wx.NullBitmap)
|
mdc.SelectObject(wx.NullBitmap)
|
||||||
|
|
||||||
@@ -555,7 +555,7 @@ class _TabRenderer:
|
|||||||
+ self.left_width \
|
+ self.left_width \
|
||||||
- self.ctab_close_bmp.GetWidth() / 2
|
- self.ctab_close_bmp.GetWidth() / 2
|
||||||
y_offset = (self.tab_height - self.ctab_close_bmp.GetHeight()) / 2
|
y_offset = (self.tab_height - self.ctab_close_bmp.GetHeight()) / 2
|
||||||
self.close_region.Offset(x_offset, y_offset)
|
self.close_region.Offset(round(x_offset), round(y_offset))
|
||||||
|
|
||||||
def InitColors(self):
|
def InitColors(self):
|
||||||
"""Determines colors used for tab, based on system settings"""
|
"""Determines colors used for tab, based on system settings"""
|
||||||
@@ -573,7 +573,7 @@ class _TabRenderer:
|
|||||||
|
|
||||||
height = self.tab_height
|
height = self.tab_height
|
||||||
|
|
||||||
canvas = wx.Bitmap(self.tab_width, self.tab_height, 24)
|
canvas = wx.Bitmap(round(self.tab_width), round(self.tab_height), 24)
|
||||||
|
|
||||||
mdc = wx.MemoryDC()
|
mdc = wx.MemoryDC()
|
||||||
|
|
||||||
@@ -590,8 +590,8 @@ class _TabRenderer:
|
|||||||
# Draw tab icon
|
# Draw tab icon
|
||||||
mdc.DrawBitmap(
|
mdc.DrawBitmap(
|
||||||
bmp,
|
bmp,
|
||||||
self.left_width + self.padding - bmp.GetWidth() / 2,
|
round(self.left_width + self.padding - bmp.GetWidth() / 2),
|
||||||
(height - bmp.GetHeight()) / 2)
|
round((height - bmp.GetHeight()) / 2))
|
||||||
|
|
||||||
# draw close button
|
# draw close button
|
||||||
if self.closeable:
|
if self.closeable:
|
||||||
@@ -604,8 +604,8 @@ class _TabRenderer:
|
|||||||
|
|
||||||
mdc.DrawBitmap(
|
mdc.DrawBitmap(
|
||||||
cbmp,
|
cbmp,
|
||||||
self.content_width + self.left_width - cbmp.GetWidth() / 2,
|
round(self.content_width + self.left_width - cbmp.GetWidth() / 2),
|
||||||
(height - cbmp.GetHeight()) / 2)
|
round((height - cbmp.GetHeight()) / 2))
|
||||||
|
|
||||||
mdc.SelectObject(wx.NullBitmap)
|
mdc.SelectObject(wx.NullBitmap)
|
||||||
|
|
||||||
@@ -640,7 +640,7 @@ class _TabRenderer:
|
|||||||
# draw text (with no ellipses)
|
# draw text (with no ellipses)
|
||||||
text = draw.GetPartialText(dc, self.text, maxsize, "")
|
text = draw.GetPartialText(dc, self.text, maxsize, "")
|
||||||
tx, ty = dc.GetTextExtent(text)
|
tx, ty = dc.GetTextExtent(text)
|
||||||
dc.DrawText(text, text_start + self.padding, height / 2 - ty / 2)
|
dc.DrawText(text, round(text_start + self.padding), round(height / 2 - ty / 2))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "_TabRenderer(text={}, disabled={}) at {}".format(
|
return "_TabRenderer(text={}, disabled={}) at {}".format(
|
||||||
@@ -1005,7 +1005,7 @@ class _TabsContainer(wx.Panel):
|
|||||||
|
|
||||||
region = tab.GetCloseButtonRegion()
|
region = tab.GetCloseButtonRegion()
|
||||||
posx, posy = tab.GetPosition()
|
posx, posy = tab.GetPosition()
|
||||||
region.Offset(posx, posy)
|
region.Offset(round(posx), round(posy))
|
||||||
|
|
||||||
if region.Contains(x, y):
|
if region.Contains(x, y):
|
||||||
index = self.tabs.index(tab)
|
index = self.tabs.index(tab)
|
||||||
@@ -1036,7 +1036,7 @@ class _TabsContainer(wx.Panel):
|
|||||||
|
|
||||||
region = self.add_button.GetRegion()
|
region = self.add_button.GetRegion()
|
||||||
ax, ay = self.add_button.GetPosition()
|
ax, ay = self.add_button.GetPosition()
|
||||||
region.Offset(ax, ay)
|
region.Offset(round(ax), round(ay))
|
||||||
|
|
||||||
if region.Contains(x, y):
|
if region.Contains(x, y):
|
||||||
ev = PageAdding()
|
ev = PageAdding()
|
||||||
@@ -1058,7 +1058,7 @@ class _TabsContainer(wx.Panel):
|
|||||||
for tab in self.tabs:
|
for tab in self.tabs:
|
||||||
region = tab.GetCloseButtonRegion()
|
region = tab.GetCloseButtonRegion()
|
||||||
posx, posy = tab.GetPosition()
|
posx, posy = tab.GetPosition()
|
||||||
region.Offset(posx, posy)
|
region.Offset(round(posx), round(posy))
|
||||||
|
|
||||||
if region.Contains(x, y):
|
if region.Contains(x, y):
|
||||||
if not tab.GetCloseButtonHoverStatus():
|
if not tab.GetCloseButtonHoverStatus():
|
||||||
@@ -1093,7 +1093,7 @@ class _TabsContainer(wx.Panel):
|
|||||||
tabRegion = tab.GetTabRegion()
|
tabRegion = tab.GetTabRegion()
|
||||||
tabPos = tab.GetPosition()
|
tabPos = tab.GetPosition()
|
||||||
tabPosX, tabPosY = tabPos
|
tabPosX, tabPosY = tabPos
|
||||||
tabRegion.Offset(tabPosX, tabPosY)
|
tabRegion.Offset(round(tabPosX), round(tabPosY))
|
||||||
|
|
||||||
if tabRegion.Contains(x, y):
|
if tabRegion.Contains(x, y):
|
||||||
return True
|
return True
|
||||||
@@ -1166,7 +1166,7 @@ class _TabsContainer(wx.Panel):
|
|||||||
|
|
||||||
region = self.add_button.GetRegion()
|
region = self.add_button.GetRegion()
|
||||||
ax, ay = self.add_button.GetPosition()
|
ax, ay = self.add_button.GetPosition()
|
||||||
region.Offset(ax, ay)
|
region.Offset(round(ax), round(ay))
|
||||||
|
|
||||||
if region.Contains(x, y):
|
if region.Contains(x, y):
|
||||||
if not self.add_button.IsHighlighted():
|
if not self.add_button.IsHighlighted():
|
||||||
@@ -1198,7 +1198,7 @@ class _TabsContainer(wx.Panel):
|
|||||||
|
|
||||||
if self.show_add_button:
|
if self.show_add_button:
|
||||||
ax, ay = self.add_button.GetPosition()
|
ax, ay = self.add_button.GetPosition()
|
||||||
mdc.DrawBitmap(self.add_button.Render(), ax, ay, True)
|
mdc.DrawBitmap(self.add_button.Render(), round(ax), round(ay), True)
|
||||||
|
|
||||||
for i in range(len(self.tabs) - 1, -1, -1):
|
for i in range(len(self.tabs) - 1, -1, -1):
|
||||||
tab = self.tabs[i]
|
tab = self.tabs[i]
|
||||||
@@ -1206,14 +1206,14 @@ class _TabsContainer(wx.Panel):
|
|||||||
|
|
||||||
if not tab.IsSelected():
|
if not tab.IsSelected():
|
||||||
# drop shadow first
|
# drop shadow first
|
||||||
mdc.DrawBitmap(self.fxBmps[tab], posx, posy, True)
|
mdc.DrawBitmap(self.fxBmps[tab], round(posx), (posy), True)
|
||||||
bmp = tab.Render()
|
bmp = tab.Render()
|
||||||
img = bmp.ConvertToImage()
|
img = bmp.ConvertToImage()
|
||||||
img = img.AdjustChannels(1, 1, 1, 0.85)
|
img = img.AdjustChannels(1, 1, 1, 0.85)
|
||||||
bmp = wx.Bitmap(img)
|
bmp = wx.Bitmap(img)
|
||||||
mdc.DrawBitmap(bmp, posx, posy, True)
|
mdc.DrawBitmap(bmp, round(posx), (posy), True)
|
||||||
|
|
||||||
mdc.SetDeviceOrigin(posx, posy)
|
mdc.SetDeviceOrigin(round(posx), round(posy))
|
||||||
tab.DrawText(mdc)
|
tab.DrawText(mdc)
|
||||||
mdc.SetDeviceOrigin(0, 0)
|
mdc.SetDeviceOrigin(0, 0)
|
||||||
else:
|
else:
|
||||||
@@ -1224,7 +1224,7 @@ class _TabsContainer(wx.Panel):
|
|||||||
if selected:
|
if selected:
|
||||||
posx, posy = selected.GetPosition()
|
posx, posy = selected.GetPosition()
|
||||||
# drop shadow first
|
# drop shadow first
|
||||||
mdc.DrawBitmap(self.fxBmps[selected], posx, posy, True)
|
mdc.DrawBitmap(self.fxBmps[selected], round(posx), round(posy), True)
|
||||||
|
|
||||||
bmp = selected.Render()
|
bmp = selected.Render()
|
||||||
|
|
||||||
@@ -1233,9 +1233,9 @@ class _TabsContainer(wx.Panel):
|
|||||||
img = img.AdjustChannels(1.2, 1.2, 1.2, 0.7)
|
img = img.AdjustChannels(1.2, 1.2, 1.2, 0.7)
|
||||||
bmp = wx.Bitmap(img)
|
bmp = wx.Bitmap(img)
|
||||||
|
|
||||||
mdc.DrawBitmap(bmp, posx, posy, True)
|
mdc.DrawBitmap(bmp, round(posx), round(posy), True)
|
||||||
|
|
||||||
mdc.SetDeviceOrigin(posx, posy)
|
mdc.SetDeviceOrigin(round(posx), round(posy))
|
||||||
selected.DrawText(mdc)
|
selected.DrawText(mdc)
|
||||||
mdc.SetDeviceOrigin(0, 0)
|
mdc.SetDeviceOrigin(0, 0)
|
||||||
|
|
||||||
@@ -1501,7 +1501,7 @@ class PFNotebookPagePreview(wx.Frame):
|
|||||||
|
|
||||||
def OnWindowPaint(self, event):
|
def OnWindowPaint(self, event):
|
||||||
rect = self.GetRect()
|
rect = self.GetRect()
|
||||||
canvas = wx.Bitmap(rect.width, rect.height)
|
canvas = wx.Bitmap(round(rect.width), round(rect.height))
|
||||||
mdc = wx.BufferedPaintDC(self)
|
mdc = wx.BufferedPaintDC(self)
|
||||||
mdc.SelectObject(canvas)
|
mdc.SelectObject(canvas)
|
||||||
color = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
|
color = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
|
||||||
@@ -1514,7 +1514,7 @@ class PFNotebookPagePreview(wx.Frame):
|
|||||||
x, y = mdc.GetTextExtent(self.title)
|
x, y = mdc.GetTextExtent(self.title)
|
||||||
|
|
||||||
mdc.SetBrush(wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)))
|
mdc.SetBrush(wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)))
|
||||||
mdc.DrawRectangle(0, 0, rect.width, 16)
|
mdc.DrawRectangle(0, 0, round(rect.width), 16)
|
||||||
|
|
||||||
mdc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
mdc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||||
|
|
||||||
@@ -1523,4 +1523,4 @@ class PFNotebookPagePreview(wx.Frame):
|
|||||||
mdc.SetPen(wx.Pen("#000000", width=1))
|
mdc.SetPen(wx.Pen("#000000", width=1))
|
||||||
mdc.SetBrush(wx.TRANSPARENT_BRUSH)
|
mdc.SetBrush(wx.TRANSPARENT_BRUSH)
|
||||||
|
|
||||||
mdc.DrawRectangle(0, 16, rect.width, rect.height - 16)
|
mdc.DrawRectangle(0, 16, round(rect.width), round(rect.height - 16))
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ class CopySelectDialog(wx.Dialog):
|
|||||||
|
|
||||||
def exportEsi(self, options, callback):
|
def exportEsi(self, options, callback):
|
||||||
fit = getFit(self.mainFrame.getActiveFit())
|
fit = getFit(self.mainFrame.getActiveFit())
|
||||||
Port.exportESI(fit, True, callback)
|
Port.exportESI(fit, False, False, False, callback)
|
||||||
|
|
||||||
def exportXml(self, options, callback):
|
def exportXml(self, options, callback):
|
||||||
fit = getFit(self.mainFrame.getActiveFit())
|
fit = getFit(self.mainFrame.getActiveFit())
|
||||||
|
|||||||
@@ -29,8 +29,9 @@ class Display(wx.ListCtrl):
|
|||||||
DEFAULT_COLS = None
|
DEFAULT_COLS = None
|
||||||
|
|
||||||
def __init__(self, parent, size=wx.DefaultSize, style=0):
|
def __init__(self, parent, size=wx.DefaultSize, style=0):
|
||||||
|
wx.ListCtrl.__init__(self)
|
||||||
wx.ListCtrl.__init__(self, parent, size=size, style=wx.LC_REPORT | style)
|
self.EnableSystemTheme(False)
|
||||||
|
self.Create(parent, size=size, style=wx.LC_REPORT | style)
|
||||||
self.imageList = CachingImageList(16, 16)
|
self.imageList = CachingImageList(16, 16)
|
||||||
self.SetImageList(self.imageList, wx.IMAGE_LIST_SMALL)
|
self.SetImageList(self.imageList, wx.IMAGE_LIST_SMALL)
|
||||||
self.activeColumns = []
|
self.activeColumns = []
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ class EveFittings(AuxiliaryFrame):
|
|||||||
|
|
||||||
self.charChoice.Clear()
|
self.charChoice.Clear()
|
||||||
for char in chars:
|
for char in chars:
|
||||||
self.charChoice.Append(char.characterName, char.ID)
|
self.charChoice.Append(char.characterDisplay, char.ID)
|
||||||
if len(chars) > 0:
|
if len(chars) > 0:
|
||||||
self.charChoice.SetSelection(0)
|
self.charChoice.SetSelection(0)
|
||||||
|
|
||||||
@@ -227,21 +227,6 @@ class EveFittings(AuxiliaryFrame):
|
|||||||
self.fitView.update([])
|
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:
|
class ESIExceptionHandler:
|
||||||
# todo: make this a generate excetpion handler for all calls
|
# todo: make this a generate excetpion handler for all calls
|
||||||
def __init__(self, ex):
|
def __init__(self, ex):
|
||||||
@@ -283,7 +268,7 @@ class ExportToEve(AuxiliaryFrame):
|
|||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
parent, id=wx.ID_ANY, title=_t("Export fit to EVE"), pos=wx.DefaultPosition,
|
parent, id=wx.ID_ANY, title=_t("Export fit to EVE"), pos=wx.DefaultPosition,
|
||||||
size=wx.Size(400, 140) if "wxGTK" in wx.PlatformInfo else wx.Size(350, 115), resizeable=True)
|
size=wx.Size(400, 175) if "wxGTK" in wx.PlatformInfo else wx.Size(350, 145), resizeable=True)
|
||||||
|
|
||||||
self.mainFrame = parent
|
self.mainFrame = parent
|
||||||
|
|
||||||
@@ -305,6 +290,16 @@ class ExportToEve(AuxiliaryFrame):
|
|||||||
self.exportChargesCb.Bind(wx.EVT_CHECKBOX, self.OnChargeExportChange)
|
self.exportChargesCb.Bind(wx.EVT_CHECKBOX, self.OnChargeExportChange)
|
||||||
mainSizer.Add(self.exportChargesCb, 0, 0, 5)
|
mainSizer.Add(self.exportChargesCb, 0, 0, 5)
|
||||||
|
|
||||||
|
self.exportImplantsCb = wx.CheckBox(self, wx.ID_ANY, _t('Export Implants'), wx.DefaultPosition, wx.DefaultSize, 0)
|
||||||
|
self.exportImplantsCb.SetValue(EsiSettings.getInstance().get('exportImplants'))
|
||||||
|
self.exportImplantsCb.Bind(wx.EVT_CHECKBOX, self.OnImplantsExportChange)
|
||||||
|
mainSizer.Add(self.exportImplantsCb, 0, 0, 5)
|
||||||
|
|
||||||
|
self.exportBoostersCb = wx.CheckBox(self, wx.ID_ANY, _t('Export Boosters'), wx.DefaultPosition, wx.DefaultSize, 0)
|
||||||
|
self.exportBoostersCb.SetValue(EsiSettings.getInstance().get('exportBoosters'))
|
||||||
|
self.exportBoostersCb.Bind(wx.EVT_CHECKBOX, self.OnBoostersExportChange)
|
||||||
|
mainSizer.Add(self.exportBoostersCb, 0, 0, 5)
|
||||||
|
|
||||||
self.exportBtn.Bind(wx.EVT_BUTTON, self.exportFitting)
|
self.exportBtn.Bind(wx.EVT_BUTTON, self.exportFitting)
|
||||||
|
|
||||||
self.statusbar = wx.StatusBar(self)
|
self.statusbar = wx.StatusBar(self)
|
||||||
@@ -324,13 +319,21 @@ class ExportToEve(AuxiliaryFrame):
|
|||||||
EsiSettings.getInstance().set('exportCharges', self.exportChargesCb.GetValue())
|
EsiSettings.getInstance().set('exportCharges', self.exportChargesCb.GetValue())
|
||||||
event.Skip()
|
event.Skip()
|
||||||
|
|
||||||
|
def OnImplantsExportChange(self, event):
|
||||||
|
EsiSettings.getInstance().set('exportImplants', self.exportImplantsCb.GetValue())
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
|
def OnBoostersExportChange(self, event):
|
||||||
|
EsiSettings.getInstance().set('exportBoosters', self.exportBoostersCb.GetValue())
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
def updateCharList(self):
|
def updateCharList(self):
|
||||||
sEsi = Esi.getInstance()
|
sEsi = Esi.getInstance()
|
||||||
chars = sEsi.getSsoCharacters()
|
chars = sEsi.getSsoCharacters()
|
||||||
|
|
||||||
self.charChoice.Clear()
|
self.charChoice.Clear()
|
||||||
for char in chars:
|
for char in chars:
|
||||||
self.charChoice.Append(char.characterName, char.ID)
|
self.charChoice.Append(char.characterDisplay, char.ID)
|
||||||
|
|
||||||
if len(chars) > 0:
|
if len(chars) > 0:
|
||||||
self.charChoice.SetSelection(0)
|
self.charChoice.SetSelection(0)
|
||||||
@@ -360,8 +363,10 @@ class ExportToEve(AuxiliaryFrame):
|
|||||||
|
|
||||||
sFit = Fit.getInstance()
|
sFit = Fit.getInstance()
|
||||||
exportCharges = self.exportChargesCb.GetValue()
|
exportCharges = self.exportChargesCb.GetValue()
|
||||||
|
exportImplants = self.exportImplantsCb.GetValue()
|
||||||
|
exportBoosters = self.exportBoostersCb.GetValue()
|
||||||
try:
|
try:
|
||||||
data = sPort.exportESI(sFit.getFit(fitID), exportCharges)
|
data = sPort.exportESI(sFit.getFit(fitID), exportCharges, exportImplants, exportBoosters)
|
||||||
except ESIExportException as e:
|
except ESIExportException as e:
|
||||||
msg = str(e)
|
msg = str(e)
|
||||||
if not msg:
|
if not msg:
|
||||||
@@ -414,6 +419,7 @@ class SsoCharacterMgmt(AuxiliaryFrame):
|
|||||||
|
|
||||||
self.lcCharacters.InsertColumn(0, heading=_t('Character'))
|
self.lcCharacters.InsertColumn(0, heading=_t('Character'))
|
||||||
self.lcCharacters.InsertColumn(1, heading=_t('Character ID'))
|
self.lcCharacters.InsertColumn(1, heading=_t('Character ID'))
|
||||||
|
self.lcCharacters.InsertColumn(2, heading=_t('Server'))
|
||||||
|
|
||||||
self.popCharList()
|
self.popCharList()
|
||||||
|
|
||||||
@@ -476,9 +482,11 @@ class SsoCharacterMgmt(AuxiliaryFrame):
|
|||||||
self.lcCharacters.InsertItem(index, char.characterName)
|
self.lcCharacters.InsertItem(index, char.characterName)
|
||||||
self.lcCharacters.SetItem(index, 1, str(char.characterID))
|
self.lcCharacters.SetItem(index, 1, str(char.characterID))
|
||||||
self.lcCharacters.SetItemData(index, char.ID)
|
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(0, wx.LIST_AUTOSIZE)
|
||||||
self.lcCharacters.SetColumnWidth(1, wx.LIST_AUTOSIZE)
|
self.lcCharacters.SetColumnWidth(1, wx.LIST_AUTOSIZE)
|
||||||
|
self.lcCharacters.SetColumnWidth(2, wx.LIST_AUTOSIZE)
|
||||||
|
|
||||||
def addChar(self, event):
|
def addChar(self, event):
|
||||||
try:
|
try:
|
||||||
@@ -486,8 +494,6 @@ class SsoCharacterMgmt(AuxiliaryFrame):
|
|||||||
sEsi.login()
|
sEsi.login()
|
||||||
except (KeyboardInterrupt, SystemExit):
|
except (KeyboardInterrupt, SystemExit):
|
||||||
raise
|
raise
|
||||||
except Exception as ex:
|
|
||||||
ESIServerExceptionHandler(self, ex)
|
|
||||||
|
|
||||||
def delChar(self, event):
|
def delChar(self, event):
|
||||||
item = self.lcCharacters.GetFirstSelected()
|
item = self.lcCharacters.GetFirstSelected()
|
||||||
|
|||||||
164
gui/mainFrame.py
@@ -61,10 +61,11 @@ from gui.statsPane import StatsPane
|
|||||||
from gui.targetProfileEditor import TargetProfileEditor
|
from gui.targetProfileEditor import TargetProfileEditor
|
||||||
from gui.updateDialog import UpdateDialog
|
from gui.updateDialog import UpdateDialog
|
||||||
from gui.utils.clipboard import fromClipboard
|
from gui.utils.clipboard import fromClipboard
|
||||||
|
from gui.utils.progressHelper import ProgressHelper
|
||||||
from service.character import Character
|
from service.character import Character
|
||||||
from service.esi import Esi
|
from service.esi import Esi
|
||||||
from service.fit import Fit
|
from service.fit import Fit
|
||||||
from service.port import IPortUser, Port
|
from service.port import Port
|
||||||
from service.price import Price
|
from service.price import Price
|
||||||
from service.settings import HTMLExportSettings, SettingsProvider
|
from service.settings import HTMLExportSettings, SettingsProvider
|
||||||
from service.update import Update
|
from service.update import Update
|
||||||
@@ -130,7 +131,6 @@ class OpenFitsThread(threading.Thread):
|
|||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
|
|
||||||
# todo: include IPortUser again
|
|
||||||
class MainFrame(wx.Frame):
|
class MainFrame(wx.Frame):
|
||||||
__instance = None
|
__instance = None
|
||||||
|
|
||||||
@@ -845,14 +845,15 @@ class MainFrame(wx.Frame):
|
|||||||
style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE
|
style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE
|
||||||
) as dlg:
|
) as dlg:
|
||||||
if dlg.ShowModal() == wx.ID_OK:
|
if dlg.ShowModal() == wx.ID_OK:
|
||||||
self.progressDialog = wx.ProgressDialog(
|
# set some arbitrary spacing to create width in window
|
||||||
_t("Importing fits"),
|
progress = ProgressHelper(message=" " * 100, callback=self._openAfterImport)
|
||||||
" " * 100, # set some arbitrary spacing to create width in window
|
call = (Port.importFitsThreaded, [dlg.GetPaths(), progress], {})
|
||||||
parent=self,
|
self.handleProgress(
|
||||||
style=wx.PD_CAN_ABORT | wx.PD_SMOOTH | wx.PD_ELAPSED_TIME | wx.PD_APP_MODAL
|
title=_t("Importing fits"),
|
||||||
)
|
style=wx.PD_CAN_ABORT | wx.PD_SMOOTH | wx.PD_APP_MODAL | wx.PD_AUTO_HIDE,
|
||||||
Port.importFitsThreaded(dlg.GetPaths(), self)
|
call=call,
|
||||||
self.progressDialog.ShowModal()
|
progress=progress,
|
||||||
|
errMsgLbl=_t("Import Error"))
|
||||||
|
|
||||||
def backupToXml(self, event):
|
def backupToXml(self, event):
|
||||||
""" Back up all fits to EVE XML file """
|
""" Back up all fits to EVE XML file """
|
||||||
@@ -863,32 +864,30 @@ class MainFrame(wx.Frame):
|
|||||||
_t("Save Backup As..."),
|
_t("Save Backup As..."),
|
||||||
wildcard=_t("EVE XML fitting file") + " (*.xml)|*.xml",
|
wildcard=_t("EVE XML fitting file") + " (*.xml)|*.xml",
|
||||||
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT,
|
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT,
|
||||||
defaultFile=defaultFile,
|
defaultFile=defaultFile) as fileDlg:
|
||||||
) as dlg:
|
if fileDlg.ShowModal() == wx.ID_OK:
|
||||||
if dlg.ShowModal() == wx.ID_OK:
|
filePath = fileDlg.GetPath()
|
||||||
filePath = dlg.GetPath()
|
|
||||||
if '.' not in os.path.basename(filePath):
|
if '.' not in os.path.basename(filePath):
|
||||||
filePath += ".xml"
|
filePath += ".xml"
|
||||||
|
|
||||||
sFit = Fit.getInstance()
|
fitAmount = Fit.getInstance().countAllFits()
|
||||||
max_ = sFit.countAllFits()
|
progress = ProgressHelper(
|
||||||
|
message=_t("Backing up {} fits to: {}").format(fitAmount, filePath),
|
||||||
self.progressDialog = wx.ProgressDialog(
|
maximum=fitAmount + 1)
|
||||||
_t("Backup fits"),
|
call = (Port.backupFits, [filePath, progress], {})
|
||||||
_t("Backing up {} fits to: {}").format(max_, filePath),
|
self.handleProgress(
|
||||||
maximum=max_,
|
title=_t("Backup fits"),
|
||||||
parent=self,
|
style=wx.PD_CAN_ABORT | wx.PD_SMOOTH | wx.PD_ELAPSED_TIME | wx.PD_APP_MODAL | wx.PD_AUTO_HIDE,
|
||||||
style=wx.PD_CAN_ABORT | wx.PD_SMOOTH | wx.PD_ELAPSED_TIME | wx.PD_APP_MODAL
|
call=call,
|
||||||
)
|
progress=progress,
|
||||||
Port.backupFits(filePath, self)
|
errMsgLbl=_t("Export Error"))
|
||||||
self.progressDialog.ShowModal()
|
|
||||||
|
|
||||||
def exportHtml(self, event):
|
def exportHtml(self, event):
|
||||||
from gui.utils.exportHtml import exportHtml
|
from gui.utils.exportHtml import exportHtml
|
||||||
|
|
||||||
sFit = Fit.getInstance()
|
sFit = Fit.getInstance()
|
||||||
settings = HTMLExportSettings.getInstance()
|
settings = HTMLExportSettings.getInstance()
|
||||||
|
|
||||||
max_ = sFit.countAllFits()
|
|
||||||
path = settings.getPath()
|
path = settings.getPath()
|
||||||
|
|
||||||
if not os.path.isdir(os.path.dirname(path)):
|
if not os.path.isdir(os.path.dirname(path)):
|
||||||
@@ -903,82 +902,44 @@ class MainFrame(wx.Frame):
|
|||||||
) as dlg:
|
) as dlg:
|
||||||
if dlg.ShowModal() == wx.ID_OK:
|
if dlg.ShowModal() == wx.ID_OK:
|
||||||
return
|
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(
|
def handleProgress(self, title, style, call, progress, errMsgLbl=None):
|
||||||
_t("Backup fits"),
|
extraArgs = {}
|
||||||
_t("Generating HTML file at: {}").format(path),
|
if progress.maximum is not None:
|
||||||
maximum=max_, parent=self,
|
extraArgs['maximum'] = progress.maximum
|
||||||
style=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME)
|
with wx.ProgressDialog(
|
||||||
|
parent=self,
|
||||||
exportHtml.getInstance().refreshFittingHtml(True, self.backupCallback)
|
title=title,
|
||||||
self.progressDialog.ShowModal()
|
message=progress.message,
|
||||||
|
style=style,
|
||||||
def backupCallback(self, info):
|
**extraArgs
|
||||||
if info == -1:
|
) as dlg:
|
||||||
self.closeProgressDialog()
|
func, args, kwargs = call
|
||||||
else:
|
func(*args, **kwargs)
|
||||||
self.progressDialog.Update(info)
|
while progress.working:
|
||||||
|
wx.MilliSleep(250)
|
||||||
def on_port_process_start(self):
|
wx.Yield()
|
||||||
# flag for progress dialog.
|
(progress.dlgWorking, skip) = dlg.Update(progress.current, progress.message)
|
||||||
self.__progress_flag = True
|
if progress.error and errMsgLbl:
|
||||||
|
|
||||||
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")
|
|
||||||
with wx.MessageDialog(
|
with wx.MessageDialog(
|
||||||
self,
|
self,
|
||||||
_t("The following error was generated") +
|
_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"),
|
_t("Be aware that already processed fits were not saved"),
|
||||||
_message, wx.OK | wx.ICON_ERROR
|
errMsgLbl, wx.OK | wx.ICON_ERROR
|
||||||
) as dlg:
|
) as dlg:
|
||||||
dlg.ShowModal()
|
dlg.ShowModal()
|
||||||
return
|
elif progress.callback:
|
||||||
|
progress.callback(*progress.cbArgs)
|
||||||
# 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])
|
|
||||||
|
|
||||||
def _openAfterImport(self, fits):
|
def _openAfterImport(self, fits):
|
||||||
if len(fits) > 0:
|
if len(fits) > 0:
|
||||||
@@ -988,6 +949,8 @@ class MainFrame(wx.Frame):
|
|||||||
wx.PostEvent(self.shipBrowser, Stage3Selected(shipID=fit.shipID, back=True))
|
wx.PostEvent(self.shipBrowser, Stage3Selected(shipID=fit.shipID, back=True))
|
||||||
else:
|
else:
|
||||||
fits.sort(key=lambda _fit: (_fit.ship.item.name, _fit.name))
|
fits.sort(key=lambda _fit: (_fit.ship.item.name, _fit.name))
|
||||||
|
# Show 100 fits max
|
||||||
|
fits = fits[:100]
|
||||||
results = []
|
results = []
|
||||||
for fit in fits:
|
for fit in fits:
|
||||||
results.append((
|
results.append((
|
||||||
@@ -999,15 +962,6 @@ class MainFrame(wx.Frame):
|
|||||||
))
|
))
|
||||||
wx.PostEvent(self.shipBrowser, ImportSelected(fits=results, back=True))
|
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):
|
def importCharacter(self, event):
|
||||||
""" Imports character XML file from EVE API """
|
""" Imports character XML file from EVE API """
|
||||||
with wx.FileDialog(
|
with wx.FileDialog(
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class DmgPatternNameValidator(BaseValidator):
|
|||||||
return DmgPatternNameValidator()
|
return DmgPatternNameValidator()
|
||||||
|
|
||||||
def Validate(self, win):
|
def Validate(self, win):
|
||||||
entityEditor = win.parent
|
entityEditor = win.Parent.parent
|
||||||
textCtrl = self.GetWindow()
|
textCtrl = self.GetWindow()
|
||||||
text = textCtrl.GetValue().strip()
|
text = textCtrl.GetValue().strip()
|
||||||
|
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ class PyGauge(wx.Window):
|
|||||||
else:
|
else:
|
||||||
w = rect.width * (float(value) / 100)
|
w = rect.width * (float(value) / 100)
|
||||||
r = copy.copy(rect)
|
r = copy.copy(rect)
|
||||||
r.width = w
|
r.width = round(w)
|
||||||
dc.DrawRectangle(r)
|
dc.DrawRectangle(r)
|
||||||
else:
|
else:
|
||||||
# if bar color is not set, then we use pre-defined transitions
|
# if bar color is not set, then we use pre-defined transitions
|
||||||
@@ -269,7 +269,7 @@ class PyGauge(wx.Window):
|
|||||||
else:
|
else:
|
||||||
w = rect.width * (float(value) / 100)
|
w = rect.width * (float(value) / 100)
|
||||||
r = copy.copy(rect)
|
r = copy.copy(rect)
|
||||||
r.width = w
|
r.width = round(w)
|
||||||
|
|
||||||
# determine transition range number and calculate xv (which is the
|
# determine transition range number and calculate xv (which is the
|
||||||
# progress between the two transition ranges)
|
# progress between the two transition ranges)
|
||||||
@@ -317,7 +317,7 @@ class PyGauge(wx.Window):
|
|||||||
gradient_color
|
gradient_color
|
||||||
)
|
)
|
||||||
if gradient_bitmap is not None:
|
if gradient_bitmap is not None:
|
||||||
dc.DrawBitmap(gradient_bitmap, r.left, r.top)
|
dc.DrawBitmap(gradient_bitmap, round(r.left), round(r.top))
|
||||||
|
|
||||||
# font stuff begins here
|
# font stuff begins here
|
||||||
dc.SetFont(self.font)
|
dc.SetFont(self.font)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class ImplantTextValidor(BaseValidator):
|
|||||||
return ImplantTextValidor()
|
return ImplantTextValidor()
|
||||||
|
|
||||||
def Validate(self, win):
|
def Validate(self, win):
|
||||||
entityEditor = win.parent
|
entityEditor = win.Parent.parent
|
||||||
textCtrl = self.GetWindow()
|
textCtrl = self.GetWindow()
|
||||||
text = textCtrl.GetValue().strip()
|
text = textCtrl.GetValue().strip()
|
||||||
|
|
||||||
|
|||||||
@@ -2,30 +2,48 @@ import wx
|
|||||||
import gui.mainFrame
|
import gui.mainFrame
|
||||||
import webbrowser
|
import webbrowser
|
||||||
import gui.globalEvents as GE
|
import gui.globalEvents as GE
|
||||||
|
import config
|
||||||
|
import time
|
||||||
|
|
||||||
|
from service.settings import EsiSettings
|
||||||
|
|
||||||
_t = wx.GetTranslation
|
_t = wx.GetTranslation
|
||||||
|
|
||||||
|
|
||||||
class SsoLogin(wx.Dialog):
|
class SsoLogin(wx.Dialog):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, server: config.ApiServer, start_local_server=True):
|
||||||
mainFrame = gui.mainFrame.MainFrame.getInstance()
|
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||||
|
from service.esi import Esi
|
||||||
super().__init__(
|
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))
|
size=wx.Size(450, 240) if "wxGTK" in wx.PlatformInfo else wx.Size(400, 240))
|
||||||
|
|
||||||
bSizer1 = wx.BoxSizer(wx.VERTICAL)
|
bSizer1 = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
|
||||||
text = wx.StaticText(self, wx.ID_ANY, _t("Copy and paste the block of text provided by pyfa.io"))
|
if start_local_server:
|
||||||
bSizer1.Add(text, 0, wx.ALL | wx.EXPAND, 10)
|
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 = 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.SetFont(wx.Font(8, wx.FONTFAMILY_TELETYPE, wx.NORMAL, wx.NORMAL))
|
||||||
self.ssoInfoCtrl.Layout()
|
self.ssoInfoCtrl.Layout()
|
||||||
|
self.ssoInfoCtrl.Bind(wx.EVT_TEXT, self.OnTextEnter)
|
||||||
|
|
||||||
bSizer1.Add(self.ssoInfoCtrl, 1, wx.LEFT | wx.RIGHT | wx.EXPAND, 10)
|
bSizer1.Add(self.ssoInfoCtrl, 1, wx.LEFT | wx.RIGHT | wx.EXPAND, 10)
|
||||||
|
|
||||||
|
self.Esisettings = EsiSettings.getInstance()
|
||||||
|
|
||||||
bSizer3 = wx.BoxSizer(wx.VERTICAL)
|
bSizer3 = wx.BoxSizer(wx.VERTICAL)
|
||||||
bSizer3.Add(wx.StaticLine(self, wx.ID_ANY), 0, wx.BOTTOM | wx.EXPAND, 10)
|
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.SetSizer(bSizer1)
|
||||||
self.Center()
|
self.Center()
|
||||||
|
|
||||||
from service.esi import Esi
|
|
||||||
|
|
||||||
self.sEsi = Esi.getInstance()
|
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)
|
uri = self.sEsi.get_login_uri(serverAddr)
|
||||||
|
|
||||||
bSizer1 = wx.BoxSizer(wx.VERTICAL)
|
if server.name == "Serenity":
|
||||||
self.mainFrame.Bind(GE.EVT_SSO_LOGIN, self.OnLogin)
|
webbrowser.open(config.SSO_LOGOFF_SERENITY)
|
||||||
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
|
time.sleep(1)
|
||||||
|
|
||||||
text = wx.StaticText(self, wx.ID_ANY, _t("Waiting for character login through EVE Single Sign-On."))
|
self.okBtn = self.FindWindow(wx.ID_OK)
|
||||||
bSizer1.Add(text, 0, wx.ALL | wx.EXPAND, 10)
|
self.okBtn.Enable(False)
|
||||||
|
# Ensure we clean up once they hit the "OK" button
|
||||||
bSizer3 = wx.BoxSizer(wx.VERTICAL)
|
self.okBtn.Bind(wx.EVT_BUTTON, self.OnDestroy)
|
||||||
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()
|
|
||||||
|
|
||||||
webbrowser.open(uri)
|
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):
|
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()
|
event.Skip()
|
||||||
|
|
||||||
def OnDestroy(self, event):
|
def OnDestroy(self, event):
|
||||||
|
# Clean up by unbinding some events and stopping the server
|
||||||
self.mainFrame.Unbind(GE.EVT_SSO_LOGIN, handler=self.OnLogin)
|
self.mainFrame.Unbind(GE.EVT_SSO_LOGIN, handler=self.OnLogin)
|
||||||
|
if self:
|
||||||
|
self.Unbind(wx.EVT_WINDOW_DESTROY, handler=self.OnDestroy)
|
||||||
self.sEsi.stopServer()
|
self.sEsi.stopServer()
|
||||||
event.Skip()
|
event.Skip()
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class TargetProfileNameValidator(BaseValidator):
|
|||||||
return TargetProfileNameValidator()
|
return TargetProfileNameValidator()
|
||||||
|
|
||||||
def Validate(self, win):
|
def Validate(self, win):
|
||||||
entityEditor = win.parent
|
entityEditor = win.Parent.parent
|
||||||
textCtrl = self.GetWindow()
|
textCtrl = self.GetWindow()
|
||||||
text = textCtrl.GetValue().strip()
|
text = textCtrl.GetValue().strip()
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ class LoadAnimation(wx.Window):
|
|||||||
bh = rect.height
|
bh = rect.height
|
||||||
y = 0
|
y = 0
|
||||||
|
|
||||||
dc.DrawRectangle(x, y, barWidth, bh)
|
dc.DrawRectangle(round(x), round(y), round(barWidth), round(bh))
|
||||||
x += barWidth
|
x += barWidth
|
||||||
|
|
||||||
textColor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
|
textColor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ def Brighten(color, factor):
|
|||||||
b += (255 - b) * factor
|
b += (255 - b) * factor
|
||||||
g += (255 - g) * factor
|
g += (255 - g) * factor
|
||||||
|
|
||||||
return wx.Colour(r, g, b, a)
|
return wx.Colour(round(r), round(g), round(b), round(a))
|
||||||
|
|
||||||
|
|
||||||
def Darken(color, factor):
|
def Darken(color, factor):
|
||||||
@@ -30,7 +30,7 @@ def Darken(color, factor):
|
|||||||
b = min(max(b, 0), 255)
|
b = min(max(b, 0), 255)
|
||||||
g = min(max(g, 0), 255)
|
g = min(max(g, 0), 255)
|
||||||
|
|
||||||
return wx.Colour(r, g, b, a)
|
return wx.Colour(round(r), round(g), round(b), round(a))
|
||||||
|
|
||||||
|
|
||||||
def _getBrightness(color):
|
def _getBrightness(color):
|
||||||
@@ -70,4 +70,4 @@ def CalculateTransition(s_color, e_color, delta):
|
|||||||
tG = sG + (eG - sG) * delta
|
tG = sG + (eG - sG) * delta
|
||||||
tB = sB + (eB - sB) * delta
|
tB = sB + (eB - sB) * delta
|
||||||
|
|
||||||
return wx.Colour(tR, tG, tB, (sA + eA) / 2)
|
return wx.Colour(round(tR), round(tG), round(tB), round((sA + eA) / 2))
|
||||||
|
|||||||
12
gui/utils/dark.py
Normal 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
|
||||||
@@ -21,7 +21,7 @@ def RenderGradientBar(windowColor, width, height, sFactor, eFactor, mFactor=None
|
|||||||
|
|
||||||
|
|
||||||
def DrawFilledBitmap(width, height, color):
|
def DrawFilledBitmap(width, height, color):
|
||||||
canvas = wx.Bitmap(width, height)
|
canvas = wx.Bitmap(round(width), round(height))
|
||||||
|
|
||||||
mdc = wx.MemoryDC()
|
mdc = wx.MemoryDC()
|
||||||
mdc.SelectObject(canvas)
|
mdc.SelectObject(canvas)
|
||||||
@@ -37,20 +37,20 @@ def DrawFilledBitmap(width, height, color):
|
|||||||
def DrawGradientBar(width, height, gStart, gEnd, gMid=None, fillRatio=4):
|
def DrawGradientBar(width, height, gStart, gEnd, gMid=None, fillRatio=4):
|
||||||
if width == 0 or height == 0:
|
if width == 0 or height == 0:
|
||||||
return None
|
return None
|
||||||
canvas = wx.Bitmap(width, height)
|
canvas = wx.Bitmap(round(width), round(height))
|
||||||
|
|
||||||
mdc = wx.MemoryDC()
|
mdc = wx.MemoryDC()
|
||||||
mdc.SelectObject(canvas)
|
mdc.SelectObject(canvas)
|
||||||
|
|
||||||
r = wx.Rect(0, 0, width, height)
|
r = wx.Rect(0, 0, width, height)
|
||||||
r.SetHeight(height / fillRatio)
|
r.SetHeight(round(height / fillRatio))
|
||||||
|
|
||||||
if gMid is None:
|
if gMid is None:
|
||||||
gMid = gStart
|
gMid = gStart
|
||||||
|
|
||||||
mdc.GradientFillLinear(r, gStart, gMid, wx.SOUTH)
|
mdc.GradientFillLinear(r, gStart, gMid, wx.SOUTH)
|
||||||
r.SetTop(r.GetHeight())
|
r.SetTop(r.GetHeight())
|
||||||
r.SetHeight(height * (fillRatio - 1) / fillRatio + (1 if height % fillRatio != 0 else 0))
|
r.SetHeight(round(height * (fillRatio - 1) / fillRatio + (1 if height % fillRatio != 0 else 0)))
|
||||||
|
|
||||||
mdc.GradientFillLinear(r, gMid, gEnd, wx.SOUTH)
|
mdc.GradientFillLinear(r, gMid, gEnd, wx.SOUTH)
|
||||||
|
|
||||||
|
|||||||
@@ -26,20 +26,20 @@ class exportHtml:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.thread = exportHtmlThread()
|
self.thread = exportHtmlThread()
|
||||||
|
|
||||||
def refreshFittingHtml(self, force=False, callback=False):
|
def refreshFittingHtml(self, force=False, progress=None):
|
||||||
settings = HTMLExportSettings.getInstance()
|
settings = HTMLExportSettings.getInstance()
|
||||||
|
|
||||||
if force or settings.getEnabled():
|
if force or settings.getEnabled():
|
||||||
self.thread.stop()
|
self.thread.stop()
|
||||||
self.thread = exportHtmlThread(callback)
|
self.thread = exportHtmlThread(progress)
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
|
||||||
|
|
||||||
class exportHtmlThread(threading.Thread):
|
class exportHtmlThread(threading.Thread):
|
||||||
def __init__(self, callback=False):
|
def __init__(self, progress=False):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.name = "HTMLExport"
|
self.name = "HTMLExport"
|
||||||
self.callback = callback
|
self.progress = progress
|
||||||
self.stopRunning = False
|
self.stopRunning = False
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
@@ -72,11 +72,13 @@ class exportHtmlThread(threading.Thread):
|
|||||||
pass
|
pass
|
||||||
except (KeyboardInterrupt, SystemExit):
|
except (KeyboardInterrupt, SystemExit):
|
||||||
raise
|
raise
|
||||||
except Exception as ex:
|
except Exception as e:
|
||||||
pass
|
if self.progress:
|
||||||
|
self.progress.error = f'{e}'
|
||||||
if self.callback:
|
finally:
|
||||||
wx.CallAfter(self.callback, -1)
|
if self.progress:
|
||||||
|
self.progress.current += 1
|
||||||
|
self.progress.workerWorking = False
|
||||||
|
|
||||||
def generateFullHTML(self, sMkt, sFit, dnaUrl):
|
def generateFullHTML(self, sMkt, sFit, dnaUrl):
|
||||||
""" Generate the complete HTML with styling and javascript """
|
""" Generate the complete HTML with styling and javascript """
|
||||||
@@ -171,13 +173,13 @@ class exportHtmlThread(threading.Thread):
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="canvas" data-role="page">
|
<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">
|
<div data-role="header">
|
||||||
<h1>Pyfa fits</h1>
|
<h1>Pyfa fits by Group</h1>
|
||||||
</div>
|
</div>
|
||||||
<div data-role="content">
|
<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)
|
""" % (time.time(), dnaUrl, localDate)
|
||||||
|
|
||||||
HTML += ' <ul data-role="listview" class="ui-listview-outer" data-inset="true" data-filter="true">\n'
|
HTML += ' <ul data-role="listview" class="ui-listview-outer" data-inset="true" data-filter="true">\n'
|
||||||
categoryList = list(sMkt.getShipRoot())
|
categoryList = list(sMkt.getShipRoot())
|
||||||
categoryList.sort(key=lambda _ship: _ship.name)
|
categoryList.sort(key=lambda _ship: _ship.name)
|
||||||
@@ -214,7 +216,9 @@ class exportHtmlThread(threading.Thread):
|
|||||||
eftFit = Port.exportEft(getFit(fit[0]), options={
|
eftFit = Port.exportEft(getFit(fit[0]), options={
|
||||||
PortEftOptions.IMPLANTS: True,
|
PortEftOptions.IMPLANTS: True,
|
||||||
PortEftOptions.MUTATIONS: True,
|
PortEftOptions.MUTATIONS: True,
|
||||||
PortEftOptions.LOADED_CHARGES: True})
|
PortEftOptions.LOADED_CHARGES: True,
|
||||||
|
PortEftOptions.BOOSTERS: True,
|
||||||
|
PortEftOptions.CARGO: True})
|
||||||
|
|
||||||
HTMLfit = (
|
HTMLfit = (
|
||||||
' <li data-role="collapsible" data-iconpos="right" data-shadow="false" '
|
' <li data-role="collapsible" data-iconpos="right" data-shadow="false" '
|
||||||
@@ -234,8 +238,8 @@ class exportHtmlThread(threading.Thread):
|
|||||||
pyfalog.warning("Failed to export line")
|
pyfalog.warning("Failed to export line")
|
||||||
continue
|
continue
|
||||||
finally:
|
finally:
|
||||||
if self.callback:
|
if self.progress:
|
||||||
wx.CallAfter(self.callback, count)
|
self.progress.current = count
|
||||||
count += 1
|
count += 1
|
||||||
HTMLgroup += HTMLship + (' </ul>\n'
|
HTMLgroup += HTMLship + (' </ul>\n'
|
||||||
' </li>\n')
|
' </li>\n')
|
||||||
@@ -244,7 +248,7 @@ class exportHtmlThread(threading.Thread):
|
|||||||
# Market group header
|
# Market group header
|
||||||
HTML += (
|
HTML += (
|
||||||
' <li data-role="collapsible" data-iconpos="right" data-shadow="false" data-corners="false">\n'
|
' <li data-role="collapsible" data-iconpos="right" data-shadow="false" data-corners="false">\n'
|
||||||
' <h2>' + group.groupName + ' <span class="ui-li-count">' + str(groupFits) + '</span></h2>\n'
|
' <h2>' + group.name + ' <span class="ui-li-count">' + str(groupFits) + '</span></h2>\n'
|
||||||
' <ul data-role="listview" data-shadow="false" data-inset="true" data-corners="false">\n' +
|
' <ul data-role="listview" data-shadow="false" data-inset="true" data-corners="false">\n' +
|
||||||
HTMLgroup +
|
HTMLgroup +
|
||||||
' </ul>\n'
|
' </ul>\n'
|
||||||
@@ -254,6 +258,68 @@ class exportHtmlThread(threading.Thread):
|
|||||||
HTML += """
|
HTML += """
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>"""
|
</html>"""
|
||||||
@@ -291,7 +357,7 @@ class exportHtmlThread(threading.Thread):
|
|||||||
pyfalog.error("Failed to export line")
|
pyfalog.error("Failed to export line")
|
||||||
continue
|
continue
|
||||||
finally:
|
finally:
|
||||||
if self.callback:
|
if self.progress:
|
||||||
wx.CallAfter(self.callback, count)
|
self.progress.current = count
|
||||||
count += 1
|
count += 1
|
||||||
return HTML
|
return HTML
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ class InputValidator(metaclass=ABCMeta):
|
|||||||
class FloatBox(wx.TextCtrl):
|
class FloatBox(wx.TextCtrl):
|
||||||
|
|
||||||
def __init__(self, parent, value, id=wx.ID_ANY, style=0, validator=None, **kwargs):
|
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)
|
super().__init__(parent=parent, id=id, style=style, **kwargs)
|
||||||
self.Bind(wx.EVT_TEXT, self.OnText)
|
self.Bind(wx.EVT_TEXT, self.OnText)
|
||||||
self._storedValue = ''
|
self._storedValue = ''
|
||||||
@@ -107,6 +110,9 @@ class FloatBox(wx.TextCtrl):
|
|||||||
class FloatRangeBox(wx.TextCtrl):
|
class FloatRangeBox(wx.TextCtrl):
|
||||||
|
|
||||||
def __init__(self, parent, value, id=wx.ID_ANY, style=0, **kwargs):
|
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)
|
super().__init__(parent=parent, id=id, style=style, **kwargs)
|
||||||
self.Bind(wx.EVT_TEXT, self.OnText)
|
self.Bind(wx.EVT_TEXT, self.OnText)
|
||||||
self._storedValue = ''
|
self._storedValue = ''
|
||||||
|
|||||||
19
gui/utils/progressHelper.py
Normal 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
|
After Width: | Height: | Size: 673 B |
BIN
imgs/icons/10848@2x.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
imgs/icons/24603@1x.png
Normal file
|
After Width: | Height: | Size: 915 B |
BIN
imgs/icons/24603@2x.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 741 B After Width: | Height: | Size: 724 B |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 724 B After Width: | Height: | Size: 741 B |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 887 B After Width: | Height: | Size: 863 B |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 863 B After Width: | Height: | Size: 887 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 795 B After Width: | Height: | Size: 787 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 787 B After Width: | Height: | Size: 795 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 908 B After Width: | Height: | Size: 893 B |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 893 B After Width: | Height: | Size: 908 B |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 783 B After Width: | Height: | Size: 760 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 760 B After Width: | Height: | Size: 783 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 861 B After Width: | Height: | Size: 847 B |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 847 B After Width: | Height: | Size: 861 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.5 KiB |
BIN
imgs/icons/25235@1x.png
Normal file
|
After Width: | Height: | Size: 780 B |
BIN
imgs/icons/25235@2x.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
imgs/icons/25236@1x.png
Normal file
|
After Width: | Height: | Size: 829 B |
BIN
imgs/icons/25236@2x.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
imgs/icons/25237@1x.png
Normal file
|
After Width: | Height: | Size: 821 B |