mirror of
https://github.com/aclist/dztui.git
synced 2026-08-31 12:16:55 +02:00
Compare commits
24 Commits
881b0b3008
...
adf8a62e8a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adf8a62e8a | ||
|
|
46a54cef12 | ||
|
|
321384dc7b | ||
|
|
e02f02b775 | ||
|
|
de524bd2a5 | ||
|
|
edee9b6234 | ||
|
|
cefd041e08 | ||
|
|
5ab18d0796 | ||
|
|
23e3d34947 | ||
|
|
b86dd37b50 | ||
|
|
59fdd30236 | ||
|
|
a35bfda5f1 | ||
|
|
5393bf1f5f | ||
|
|
90b3aa8663 | ||
|
|
728e4daf7c | ||
|
|
7a210c7f39 | ||
|
|
459dd69359 | ||
|
|
fbd1a355d5 | ||
|
|
82d2afb1f2 | ||
|
|
8193980878 | ||
|
|
f75ef947c9 | ||
|
|
6dc9a719ee | ||
|
|
785df28f66 | ||
|
|
66e114a400 |
41
CHANGELOG.md
41
CHANGELOG.md
@ -1,18 +1,51 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [5.6.6] 2024-02-09
|
## [5.8.0] 2025-07-06
|
||||||
|
## Added
|
||||||
|
- Filter servers by official/unofficial status
|
||||||
|
- Automatically fetch geolocation records
|
||||||
|
## Changed
|
||||||
|
- Updated internal versioning of helper files
|
||||||
|
## Fixed
|
||||||
|
- Corrected erroneous 2024 date in prior changelog entries
|
||||||
|
|
||||||
|
## [5.7.0] 2025-04-17
|
||||||
|
## Added
|
||||||
|
- Save application dimensions when quitting and restore on subsequent boot
|
||||||
|
## Fixed
|
||||||
|
- Issues with the window exceeding the bounds of the screen when displaying some table contexts
|
||||||
|
## Changed
|
||||||
|
- More direct server ping query method that should return marginally more accurate times
|
||||||
|
|
||||||
|
## [5.6.7] 2025-04-04
|
||||||
|
## Dropped
|
||||||
|
- Removed extraneous pre-boot API checks that could cause error messages to be printed if the user had not set up an API key yet
|
||||||
|
|
||||||
|
## [5.6.6] 2025-03-16
|
||||||
|
## Changed
|
||||||
|
- Update IP database records for 2025-03
|
||||||
|
|
||||||
|
## [5.6.5] 2025-03-04
|
||||||
|
## Fixed
|
||||||
|
- Livonia server results being dropped from batch queries
|
||||||
|
|
||||||
|
## [5.6.4] 2025-02-10
|
||||||
|
### Changed
|
||||||
|
- Drop launch flag and check for invocation through Steam automatically
|
||||||
|
|
||||||
|
## [5.6.3] 2025-02-09
|
||||||
### Changed
|
### Changed
|
||||||
- Update IP database records for 2025-02
|
- Update IP database records for 2025-02
|
||||||
|
|
||||||
## [5.6.2] 2024-01-22
|
## [5.6.2] 2025-01-22
|
||||||
### Fixed
|
### Fixed
|
||||||
- Resolve regression introduced with IP resolution feature in 5.6.0 (restores functionality of right-click action: Add to My Servers)
|
- Resolve regression introduced with IP resolution feature in 5.6.0 (restores functionality of right-click action: Add to My Servers)
|
||||||
|
|
||||||
## [5.6.1] 2024-01-10
|
## [5.6.1] 2025-01-10
|
||||||
### Fixed
|
### Fixed
|
||||||
- Add fallback support for jq 1.6
|
- Add fallback support for jq 1.6
|
||||||
|
|
||||||
## [5.6.0] 2024-01-06
|
## [5.6.0] 2025-01-06
|
||||||
### Added
|
### Added
|
||||||
- Application header bar and controls
|
- Application header bar and controls
|
||||||
- Menu context subtitle in header bar
|
- Menu context subtitle in header bar
|
||||||
|
|||||||
71
CONTRIBUTING.md
Normal file
71
CONTRIBUTING.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# Introduction
|
||||||
|
|
||||||
|
Thank you for your interest in DZGUI!
|
||||||
|
|
||||||
|
This guide goes over development conventions and best practices for contributors.
|
||||||
|
If you are a developer, you can skip to the end.
|
||||||
|
|
||||||
|
# Requesting help
|
||||||
|
|
||||||
|
If you encounter a problem with DZGUI, you can submit tickets on the GitHub
|
||||||
|
(issue tracker)[https://github.com/aclist/dzgui-devel/issues] under the
|
||||||
|
`troubleshooting` tag.
|
||||||
|
|
||||||
|
# How can I help the project?
|
||||||
|
|
||||||
|
There are several ways to help this project.
|
||||||
|
1. Report bugs that you find
|
||||||
|
2. Request features that you would like
|
||||||
|
3. Contribute features and fixes to the codebase
|
||||||
|
4. Contribute documentation to the project
|
||||||
|
|
||||||
|
Before making any contribution, please read the `CODE_OF_CONDUCT.md` and act
|
||||||
|
accordingly.
|
||||||
|
|
||||||
|
## Submitting a ticket
|
||||||
|
|
||||||
|
Navigate to the GitHub (issue tracker)[https://github.com/aclist/dzgui-devel/issues].
|
||||||
|
From there, follow the onscreen prompts. You will be asked questions such as:
|
||||||
|
|
||||||
|
- What version are you using?
|
||||||
|
- What distribution are you using?
|
||||||
|
- What is the issue that you found?
|
||||||
|
- How can we reproduce the issue?
|
||||||
|
|
||||||
|
You can also attach screenshots, logs, or other data that can help us.
|
||||||
|
|
||||||
|
## Requesting a feature
|
||||||
|
|
||||||
|
You can also request features via the same issue tracker. It is good practice to
|
||||||
|
first search for your idea to see if a similar one has already been posted.
|
||||||
|
If not, open a ticket where you describe your feature and its possible benefits.
|
||||||
|
|
||||||
|
Please note that this is a community project, so it takes time for us to develop
|
||||||
|
features. Putting in a feature request does not mean that it will be implemented,
|
||||||
|
but we will do our best to support as many cool ideas as possible.
|
||||||
|
|
||||||
|
## Contributing code or documentation
|
||||||
|
|
||||||
|
If you would like to take ownership or assist with an issue on the issue tracker, or
|
||||||
|
contribute a new change, please follow the guidelines below.
|
||||||
|
|
||||||
|
Fork this repository and check out the code up to `prerelease/<latest-version>`.
|
||||||
|
If there is no pending prerelease PR, you can base your changes off of
|
||||||
|
the `testing` branch. You may later be asked to retarget your PR to the prerelease
|
||||||
|
branch once a new one is made. This is because out-of-band PRs are consolidated into
|
||||||
|
the next release before merging.
|
||||||
|
|
||||||
|
The following naming conventions apply for PRs:
|
||||||
|
- fix/<your-fix> - patch/hotfix branches
|
||||||
|
- feat/<your-feature> - feature branches
|
||||||
|
- doc/<your-doc-branch> - documentation branches
|
||||||
|
- infra/<your-infra-branch> - infrastructure branches
|
||||||
|
|
||||||
|
Implement your changes and test them locally. If they work you may
|
||||||
|
open a merge request, and then we review your changes. If everything is OK, it
|
||||||
|
will be merged to `prerelease/<latest-version>`, then `testing`, and after a live
|
||||||
|
testing phase, to `stable` as well.
|
||||||
|
|
||||||
|
It is recommended to follow
|
||||||
|
(Conventional Commits)[https://www.conventionalcommits.org/en/v1.0.0/], as this
|
||||||
|
integrates well with tooling and helps the project review your code.
|
||||||
148
dzgui.sh
148
dzgui.sh
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
version=5.6.3
|
version=5.8.0
|
||||||
|
|
||||||
#CONSTANTS
|
#CONSTANTS
|
||||||
aid=221100
|
aid=221100
|
||||||
@ -49,10 +49,9 @@ freedesktop_path="$HOME/.local/share/applications"
|
|||||||
|
|
||||||
#HELPERS
|
#HELPERS
|
||||||
ui_helper="$helpers_path/ui.py"
|
ui_helper="$helpers_path/ui.py"
|
||||||
geo_file="$helpers_path/ips.csv"
|
|
||||||
km_helper="$helpers_path/latlon"
|
km_helper="$helpers_path/latlon"
|
||||||
sums_path="$helpers_path/sums.md5"
|
|
||||||
func_helper="$helpers_path/funcs"
|
func_helper="$helpers_path/funcs"
|
||||||
|
geo_helper="$helpers_path/ips.csv"
|
||||||
|
|
||||||
#REMOTE
|
#REMOTE
|
||||||
remote_host=gh
|
remote_host=gh
|
||||||
@ -63,7 +62,6 @@ stable_url="$url_prefix/dzgui"
|
|||||||
testing_url="$url_prefix/testing"
|
testing_url="$url_prefix/testing"
|
||||||
releases_url="https://github.com/$author/$repo/releases/download/browser"
|
releases_url="https://github.com/$author/$repo/releases/download/browser"
|
||||||
km_helper_url="$releases_url/latlon"
|
km_helper_url="$releases_url/latlon"
|
||||||
geo_file_url="$releases_url/ips.csv.gz"
|
|
||||||
|
|
||||||
|
|
||||||
set_im_module(){
|
set_im_module(){
|
||||||
@ -587,10 +585,10 @@ fetch_helpers_by_sum(){
|
|||||||
[[ -f "$config_file" ]] && source "$config_file"
|
[[ -f "$config_file" ]] && source "$config_file"
|
||||||
declare -A sums
|
declare -A sums
|
||||||
sums=(
|
sums=(
|
||||||
["ui.py"]="5a876efacf208d12b5fe761996425412"
|
["ui.py"]="f128a97e744e9e11036d707198feb8a8"
|
||||||
["query_v2.py"]="55d339ba02512ac69de288eb3be41067"
|
["query_v2.py"]="55d339ba02512ac69de288eb3be41067"
|
||||||
["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397"
|
["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397"
|
||||||
["funcs"]="417bd5eaffbefc905a843985c691dc64"
|
["funcs"]="94287c75a5ae0a06a95dd439711e6fba"
|
||||||
["lan"]="c62e84ddd1457b71a85ad21da662b9af"
|
["lan"]="c62e84ddd1457b71a85ad21da662b9af"
|
||||||
)
|
)
|
||||||
local author="aclist"
|
local author="aclist"
|
||||||
@ -637,18 +635,8 @@ fetch_helpers_by_sum(){
|
|||||||
done
|
done
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
fetch_geo_file(){
|
fetch_km_helper(){
|
||||||
# for binary releases
|
|
||||||
local geo_sum="9824e9b9a75a4830a2423932cc188b06"
|
|
||||||
local km_sum="b038fdb8f655798207bd28de3a004706"
|
local km_sum="b038fdb8f655798207bd28de3a004706"
|
||||||
local gzip="$helpers_path/ips.csv.gz"
|
|
||||||
if [[ ! -f $geo_file ]] || [[ $(get_hash $geo_file) != $geo_sum ]]; then
|
|
||||||
local res=$(get_response_code "$geo_file_url")
|
|
||||||
[[ $res -ne 200 ]] && raise_error_and_quit "Remote resource unavailable: '$geo_file_url'"
|
|
||||||
curl -Ls "$geo_file_url" > "$gzip"
|
|
||||||
#force overwrite
|
|
||||||
gunzip -f "$gzip"
|
|
||||||
fi
|
|
||||||
if [[ ! -f $km_helper ]] || [[ $(get_hash $km_helper) != $km_sum ]]; then
|
if [[ ! -f $km_helper ]] || [[ $(get_hash $km_helper) != $km_sum ]]; then
|
||||||
local res=$(get_response_code "$km_helper_url")
|
local res=$(get_response_code "$km_helper_url")
|
||||||
[[ $res -ne 200 ]] && raise_error_and_quit "Remote resource unavailable: '$km_helper_url'"
|
[[ $res -ne 200 ]] && raise_error_and_quit "Remote resource unavailable: '$km_helper_url'"
|
||||||
@ -656,10 +644,119 @@ fetch_geo_file(){
|
|||||||
chmod +x "$km_helper"
|
chmod +x "$km_helper"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
get_response_code(){
|
||||||
|
local url="$1"
|
||||||
|
curl -Ls -I -o /dev/null -w "%{http_code}" "$url"
|
||||||
|
}
|
||||||
|
raise_error_and_quit(){
|
||||||
|
echo "$1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
fetch_ip_db(){
|
||||||
|
parse_dl_url(){
|
||||||
|
curl -Ls "$url" \
|
||||||
|
| grep "csv.gz" \
|
||||||
|
| awk -F"['']" '{print $2}'
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_dl_url_date(){
|
||||||
|
local url="$1"
|
||||||
|
<<< "$url" \
|
||||||
|
awk -F/ '{print $5}' \
|
||||||
|
| awk -F"dbip-city-lite-" '{print $2}' \
|
||||||
|
| awk -F'.csv.gz' '{print $1}'
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(){
|
||||||
|
logger INFO "Triggering fetch routine"
|
||||||
|
local url="$1"
|
||||||
|
|
||||||
|
curl -Ls "$url" > "$base_file"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
logger WARN "Abnormal exit while accessing '$url'"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
gunzip -f "$base_file"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
rm "$base_file"
|
||||||
|
logger WARN "Abnormal exit while unpacking gzip '$base_file'"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
< "$extracted_file" grep -vE "^[a-z0-9]{4}:" | grep -v "::" > "$ip_file"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
logger WARN "Abnormal exit while parsing IPs"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
rm "${state_path}/${month}.csv"
|
||||||
|
|
||||||
|
readarray -t records < <(cat $ip_file | awk -F, 'NR==1 {print $1} END {print $1}')
|
||||||
|
if [[ ${records[0]} != "0.0.0.0" ]] && [[ ${records[1]} != "224.0.0.0" ]]; then
|
||||||
|
logger WARN "Anchor records missing in '$ip_file', possibly malformed"
|
||||||
|
rm "$ip_file"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv "$ip_file" "$geo_helper"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
logger WARN "Abnormal exit while moving '$ip_file' to '$helpers_path'"
|
||||||
|
rm "$ip_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$month" > "$month_file"
|
||||||
|
logger INFO "Wrote '$month' to stub '$month_file'"
|
||||||
|
logger INFO "Updated '$ip_file'"
|
||||||
|
}
|
||||||
|
|
||||||
|
local url="https://db-ip.com/db/download/ip-to-city-lite"
|
||||||
|
local month_file="${state_path}/.month"
|
||||||
|
local ip_file="${state_path}/ips.csv"
|
||||||
|
|
||||||
|
# test main url
|
||||||
|
local res=$(get_response_code "$url")
|
||||||
|
if [[ $res -ne 200 ]]; then
|
||||||
|
logger WARN "Failed to retrieve remote resource: '$url' ($res)"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
logger INFO "Resolved remote URL: '$url'"
|
||||||
|
|
||||||
|
# test dl url
|
||||||
|
local dl_url="$(parse_dl_url)"
|
||||||
|
local res=$(get_response_code "$dl_url")
|
||||||
|
if [[ $res -ne 200 ]]; then
|
||||||
|
logger WARN "Remote resource unavailable: '$dl_url' ($res)"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
logger INFO "Resolved download URL: '$dl_url'"
|
||||||
|
|
||||||
|
local month=$(parse_dl_url_date "$dl_url")
|
||||||
|
local base_file="${state_path}/${month}.csv.gz"
|
||||||
|
local extracted_file="${state_path}/${month}.csv"
|
||||||
|
|
||||||
|
# no stub file
|
||||||
|
if [[ ! -f $month_file ]]; then
|
||||||
|
logger WARN "No stub file '$month_file' present"
|
||||||
|
fetch "$dl_url"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# local needs update
|
||||||
|
local last_month=$(< "$month_file")
|
||||||
|
if [[ $last_month != "$month" ]]; then
|
||||||
|
logger WARN "Local stub '$last_month' does not match remote stub '$month'"
|
||||||
|
fetch "$dl_url"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# if stub is same date, abort
|
||||||
|
logger INFO "Local stub '$last_month' is identical to remote, skipping"
|
||||||
|
}
|
||||||
fetch_helpers(){
|
fetch_helpers(){
|
||||||
fetch_a2s
|
fetch_a2s
|
||||||
fetch_dzq
|
fetch_dzq
|
||||||
fetch_geo_file
|
fetch_km_helper
|
||||||
|
fetch_ip_db
|
||||||
fetch_helpers_by_sum
|
fetch_helpers_by_sum
|
||||||
[[ ! -f $share_path/icon.png ]] && freedesktop_dirs
|
[[ ! -f $share_path/icon.png ]] && freedesktop_dirs
|
||||||
fetch_icons
|
fetch_icons
|
||||||
@ -876,21 +973,14 @@ get_response_code(){
|
|||||||
curl -Ls -I -o /dev/null -w "%{http_code}" "$url"
|
curl -Ls -I -o /dev/null -w "%{http_code}" "$url"
|
||||||
}
|
}
|
||||||
test_connection(){
|
test_connection(){
|
||||||
source "$config_file"
|
|
||||||
declare -A hr
|
declare -A hr
|
||||||
local res1
|
local res1
|
||||||
local res2
|
local res2
|
||||||
local str="No connection could be established to the remote server"
|
local str="No connection could be established to the remote server"
|
||||||
hr=(
|
hr=(
|
||||||
["steampowered.com"]="https://api.steampowered.com/IGameServersService/GetServerList/v1/?key=$steam_api"
|
|
||||||
["github.com"]="https://github.com/$author"
|
["github.com"]="https://github.com/$author"
|
||||||
["codeberg.org"]="https://codeberg.org/$author"
|
["codeberg.org"]="https://codeberg.org/$author"
|
||||||
)
|
)
|
||||||
# steam API is mandatory, except on initial setup
|
|
||||||
if [[ -n $steam_api ]]; then
|
|
||||||
res=$(get_response_code "${hr["steampowered.com"]}")
|
|
||||||
[[ $res -ne 200 ]] && raise_error_and_quit "$str ("steampowered.com")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
res=$(get_response_code "${hr["github.com"]}")
|
res=$(get_response_code "${hr["github.com"]}")
|
||||||
if [[ $res -ne 200 ]]; then
|
if [[ $res -ne 200 ]]; then
|
||||||
@ -906,7 +996,6 @@ test_connection(){
|
|||||||
stable_url="$url_prefix/dzgui"
|
stable_url="$url_prefix/dzgui"
|
||||||
testing_url="$url_prefix/testing"
|
testing_url="$url_prefix/testing"
|
||||||
km_helper_url="$releases_url/latlon"
|
km_helper_url="$releases_url/latlon"
|
||||||
geo_file_url="$releases_url/ips.csv.gz"
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
legacy_cols(){
|
legacy_cols(){
|
||||||
@ -922,14 +1011,14 @@ stale_mod_signatures(){
|
|||||||
readarray -t old_mod_ids < <(awk -F, '{print $1}' $versions_file)
|
readarray -t old_mod_ids < <(awk -F, '{print $1}' $versions_file)
|
||||||
for ((i=0; i<${#old_mod_ids[@]}; ++i)); do
|
for ((i=0; i<${#old_mod_ids[@]}; ++i)); do
|
||||||
if [[ ! -d $workshop_dir/${old_mod_ids[$i]} ]]; then
|
if [[ ! -d $workshop_dir/${old_mod_ids[$i]} ]]; then
|
||||||
"$HOME/.local/share/$app_name/helpers/funcs" "align_local" "${old_mod_ids[$i]}"
|
"$func_helper" "align_local" "${old_mod_ids[$i]}"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
create_new_links(){
|
create_new_links(){
|
||||||
"$HOME/.local/share/$app_name/helpers/funcs" "update_symlinks"
|
"$func_helper" "update_symlinks"
|
||||||
}
|
}
|
||||||
initial_setup(){
|
initial_setup(){
|
||||||
setup_dirs
|
setup_dirs
|
||||||
@ -1007,9 +1096,6 @@ main(){
|
|||||||
uninstall &&
|
uninstall &&
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
if [[ $1 == "--steam" ]] || [[ $1 == "-s" ]]; then
|
|
||||||
export STEAM_LAUNCH=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
set_im_module
|
set_im_module
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
version=5.6.0
|
version="5.8.0"
|
||||||
|
|
||||||
#CONSTANTS
|
#CONSTANTS
|
||||||
aid=221100
|
aid=221100
|
||||||
@ -59,7 +59,6 @@ geo_file="$helpers_path/ips.csv"
|
|||||||
km_helper="$helpers_path/latlon"
|
km_helper="$helpers_path/latlon"
|
||||||
sums_path="$helpers_path/sums.md5"
|
sums_path="$helpers_path/sums.md5"
|
||||||
query_helper="$helpers_path/query_v2.py"
|
query_helper="$helpers_path/query_v2.py"
|
||||||
func_helper="$helpers_path/funcs"
|
|
||||||
lan_helper="$helpers_path/lan"
|
lan_helper="$helpers_path/lan"
|
||||||
|
|
||||||
#STEAM PATHS
|
#STEAM PATHS
|
||||||
@ -453,10 +452,15 @@ get_dist(){
|
|||||||
}
|
}
|
||||||
get_remote_servers(){
|
get_remote_servers(){
|
||||||
params=(
|
params=(
|
||||||
"\\nor\1\map\chernarusplus\\nor\1\map\sakhal"
|
"\\nor\1\map\chernarusplus\\nor\1\map\sakhal\\nor\1\map\enoch\empty\1\\nor\1\map\namalsk"
|
||||||
|
"\map\namalsk\empty\1"
|
||||||
|
"\map\namalsk\noplayers\1"
|
||||||
"\map\chernarusplus\empty\1"
|
"\map\chernarusplus\empty\1"
|
||||||
"\map\chernarusplus\noplayers\1"
|
"\map\chernarusplus\noplayers\1"
|
||||||
"\map\\sakhal"
|
"\map\\sakhal\empty\1"
|
||||||
|
"\map\\sakhal\noplayers\1"
|
||||||
|
"\map\\enoch\empty\1"
|
||||||
|
"\map\\enoch\noplayers\1"
|
||||||
)
|
)
|
||||||
local limit=10000
|
local limit=10000
|
||||||
local url="https://api.steampowered.com/IGameServersService/GetServerList/v1/?"
|
local url="https://api.steampowered.com/IGameServersService/GetServerList/v1/?"
|
||||||
@ -601,6 +605,20 @@ filter_servers(){
|
|||||||
<<< "$filtered" awk -F$separator '!seen[$1]++'
|
<<< "$filtered" awk -F$separator '!seen[$1]++'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
filter_official(){
|
||||||
|
if [[ ${filters[*]} =~ Official ]]; then
|
||||||
|
echo -n "$filtered"
|
||||||
|
else
|
||||||
|
<<< "$filtered" awk -F$separator '$10 == "Community"'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
filter_community(){
|
||||||
|
if [[ ${filters[*]} =~ Unoffic ]]; then
|
||||||
|
echo -n "$filtered"
|
||||||
|
else
|
||||||
|
<<< "$filtered" awk -F$separator '$10 == "Official"'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
filtered=$(filter_perspective)
|
filtered=$(filter_perspective)
|
||||||
filtered=$(filter_full)
|
filtered=$(filter_full)
|
||||||
@ -611,6 +629,8 @@ filter_servers(){
|
|||||||
filtered=$(filter_ascii)
|
filtered=$(filter_ascii)
|
||||||
filtered=$(filter_duplicates)
|
filtered=$(filter_duplicates)
|
||||||
filtered=$(filter_keyword)
|
filtered=$(filter_keyword)
|
||||||
|
filtered=$(filter_official)
|
||||||
|
filtered=$(filter_community)
|
||||||
|
|
||||||
if [[ -z "$filtered" ]]; then
|
if [[ -z "$filtered" ]]; then
|
||||||
logger WARN "Filter result is empty"
|
logger WARN "Filter result is empty"
|
||||||
@ -648,7 +668,8 @@ parse_server_json(){
|
|||||||
"\(.max_players)␞" +
|
"\(.max_players)␞" +
|
||||||
"\(if .gametype == null then "0" elif .gametype|split("lqs")[1] == null then "0" else .gametype|split("lqs")[1]|split(",")[0] end)␞" +
|
"\(if .gametype == null then "0" elif .gametype|split("lqs")[1] == null then "0" else .gametype|split("lqs")[1]|split(",")[0] end)␞" +
|
||||||
"\(.addr|split(":")[0]):\(if .gameport == null then "XXXX" else .gameport end)␞" +
|
"\(.addr|split(":")[0]):\(if .gameport == null then "XXXX" else .gameport end)␞" +
|
||||||
"\(.addr|split(":")[1])"
|
"\(.addr|split(":")[1])␞" +
|
||||||
|
"\(if .gametype == null then "null" else (.gametype|split(",")|if any(. == "external") then "Community" else "Official" end) end)"
|
||||||
' | sort -k1
|
' | sort -k1
|
||||||
}
|
}
|
||||||
align_versions_file(){
|
align_versions_file(){
|
||||||
@ -780,12 +801,17 @@ logger(){
|
|||||||
}
|
}
|
||||||
test_ping(){
|
test_ping(){
|
||||||
shift
|
shift
|
||||||
|
local time
|
||||||
|
local res
|
||||||
local ip="$1"
|
local ip="$1"
|
||||||
local qport="$2"
|
local qport="$2"
|
||||||
local res
|
res=$(a2s $ip $qport info)
|
||||||
res=$(ping -c1 -4 -W0.5 $1 | grep time= | awk -F= '{print $4}')
|
if [[ -z $res ]]; then
|
||||||
[[ ! $? -eq 0 ]] && res="Timed out"
|
time="Timed out"
|
||||||
printf "%s" "$res"
|
else
|
||||||
|
time=$(<<< "$res" jq -r '.[].ping')
|
||||||
|
fi
|
||||||
|
printf "%s" "$time"
|
||||||
}
|
}
|
||||||
show_server_modlist(){
|
show_server_modlist(){
|
||||||
shift
|
shift
|
||||||
@ -1271,7 +1297,7 @@ symlinks(){
|
|||||||
link="@$encoded_id"
|
link="@$encoded_id"
|
||||||
mod="${arr[$i]}"
|
mod="${arr[$i]}"
|
||||||
logger INFO "Creating link '$game_dir/$link' for '$workshop_dir/$mod'"
|
logger INFO "Creating link '$game_dir/$link' for '$workshop_dir/$mod'"
|
||||||
[[ $STEAM_LAUNCH -eq 1 ]] && echo "# Creating mod link $((i+1))/${#arr[@]}"
|
[[ -n $STEAMSCRIPT ]] && echo "# Creating mod link $((i+1))/${#arr[@]}"
|
||||||
ln -s "$workshop_dir/$mod" "$game_dir/$link"
|
ln -s "$workshop_dir/$mod" "$game_dir/$link"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@ -1286,7 +1312,7 @@ symlinks(){
|
|||||||
|
|
||||||
if [[ ${#links[@]} -eq 0 ]]; then
|
if [[ ${#links[@]} -eq 0 ]]; then
|
||||||
logger INFO "No symlinks present in '$game_dir', creating them"
|
logger INFO "No symlinks present in '$game_dir', creating them"
|
||||||
if [[ $STEAM_LAUNCH -eq 1 ]]; then
|
if [[ -n $STEAMSCRIPT ]]; then
|
||||||
_create_links "${mods[@]}" > >(_pulse)
|
_create_links "${mods[@]}" > >(_pulse)
|
||||||
else
|
else
|
||||||
_create_links "${mods[@]}"
|
_create_links "${mods[@]}"
|
||||||
@ -1304,7 +1330,7 @@ symlinks(){
|
|||||||
|
|
||||||
# update missing targets
|
# update missing targets
|
||||||
logger INFO "Found ${#hits[@]} unlinked mods"
|
logger INFO "Found ${#hits[@]} unlinked mods"
|
||||||
if [[ $STEAM_LAUNCH -eq 1 ]]; then
|
if [[ -n $STEAMSCRIPT ]]; then
|
||||||
_create_links "${hits[@]}" > >(_pulse)
|
_create_links "${hits[@]}" > >(_pulse)
|
||||||
else
|
else
|
||||||
_create_links "${hits[@]}"
|
_create_links "${hits[@]}"
|
||||||
|
|||||||
141
helpers/ui.py
141
helpers/ui.py
@ -17,7 +17,6 @@ import gi
|
|||||||
gi.require_version("Gtk", "3.0")
|
gi.require_version("Gtk", "3.0")
|
||||||
from gi.repository import Gtk, GLib, Gdk, GObject, Pango
|
from gi.repository import Gtk, GLib, Gdk, GObject, Pango
|
||||||
|
|
||||||
# 5.6.0
|
|
||||||
app_name = "DZGUI"
|
app_name = "DZGUI"
|
||||||
|
|
||||||
cache = {}
|
cache = {}
|
||||||
@ -38,7 +37,7 @@ mod_store = Gtk.ListStore(str, str, str, float, str)
|
|||||||
#cf. log_cols
|
#cf. log_cols
|
||||||
log_store = Gtk.ListStore(str, str, str, str)
|
log_store = Gtk.ListStore(str, str, str, str)
|
||||||
#cf. browser_cols
|
#cf. browser_cols
|
||||||
server_store = Gtk.ListStore(str, str, str, str, int, int, int, str, int)
|
server_store = Gtk.ListStore(str, str, str, str, int, int, int, str, int, str)
|
||||||
|
|
||||||
default_tooltip = "Select a row to see its detailed description"
|
default_tooltip = "Select a row to see its detailed description"
|
||||||
server_tooltip = [None, None]
|
server_tooltip = [None, None]
|
||||||
@ -50,6 +49,7 @@ helpers_path = '%s/.local/share/dzgui/helpers' %(user_path)
|
|||||||
log_path = '%s/logs' %(state_path)
|
log_path = '%s/logs' %(state_path)
|
||||||
changelog_path = '%s/CHANGELOG.md' %(state_path)
|
changelog_path = '%s/CHANGELOG.md' %(state_path)
|
||||||
geometry_path = '%s/dzg.cols.json' %(state_path)
|
geometry_path = '%s/dzg.cols.json' %(state_path)
|
||||||
|
res_path = '%s/dzg.res.json' %(state_path)
|
||||||
funcs = '%s/funcs' %(helpers_path)
|
funcs = '%s/funcs' %(helpers_path)
|
||||||
mods_temp_file = '%s/dzg.mods_temp' %(cache_path)
|
mods_temp_file = '%s/dzg.mods_temp' %(cache_path)
|
||||||
stale_mods_temp_file = '%s/dzg.stale_mods_temp' %(cache_path)
|
stale_mods_temp_file = '%s/dzg.stale_mods_temp' %(cache_path)
|
||||||
@ -88,14 +88,16 @@ log_cols = [
|
|||||||
]
|
]
|
||||||
filters = {
|
filters = {
|
||||||
"1PP": True,
|
"1PP": True,
|
||||||
"3PP": True,
|
|
||||||
"Day": True,
|
"Day": True,
|
||||||
"Night": True,
|
|
||||||
"Empty": False,
|
"Empty": False,
|
||||||
|
"3PP": True,
|
||||||
|
"Night": True,
|
||||||
"Full": False,
|
"Full": False,
|
||||||
"Low pop": True,
|
"Low pop": True,
|
||||||
"Non-ASCII": False,
|
"Non-ASCII": False,
|
||||||
"Duplicate": False
|
"Duplicate": False,
|
||||||
|
"Official": True,
|
||||||
|
"Unoffic.": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -552,7 +554,7 @@ def parse_server_rows(data):
|
|||||||
lines = data.stdout.splitlines()
|
lines = data.stdout.splitlines()
|
||||||
reader = csv.reader(lines, delimiter=delimiter)
|
reader = csv.reader(lines, delimiter=delimiter)
|
||||||
try:
|
try:
|
||||||
rows = [[row[0], row[1], row[2], row[3], int(row[4]), int(row[5]), int(row[6]), row[7], int(row[8])] for row in reader if row]
|
rows = [[row[0], row[1], row[2], row[3], int(row[4]), int(row[5]), int(row[6]), row[7], int(row[8]), row[9]] for row in reader if row]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return 1
|
return 1
|
||||||
for row in rows:
|
for row in rows:
|
||||||
@ -685,7 +687,7 @@ def process_shell_return_code(transient_parent, msg, code, original_input):
|
|||||||
process_tree_option([treeview.view, RowType.HANDSHAKE], treeview)
|
process_tree_option([treeview.view, RowType.HANDSHAKE], treeview)
|
||||||
case 255:
|
case 255:
|
||||||
spawn_dialog(transient_parent, "Update complete. Please close DZGUI and restart.", Popup.NOTIFY)
|
spawn_dialog(transient_parent, "Update complete. Please close DZGUI and restart.", Popup.NOTIFY)
|
||||||
Gtk.main_quit()
|
save_res_and_quit(transient_parent)
|
||||||
|
|
||||||
|
|
||||||
def process_tree_option(input, treeview):
|
def process_tree_option(input, treeview):
|
||||||
@ -874,19 +876,36 @@ class OuterWindow(Gtk.Window):
|
|||||||
self.add(self.grid)
|
self.add(self.grid)
|
||||||
if is_game_mode is True:
|
if is_game_mode is True:
|
||||||
self.fullscreen()
|
self.fullscreen()
|
||||||
|
elif query_config(None, "fullscreen")[0] == "true":
|
||||||
|
logger.info("User preference for 'fullscreen' is 'true'")
|
||||||
|
self.maximize()
|
||||||
else:
|
else:
|
||||||
if query_config(None, "fullscreen")[0] == "true":
|
if os.path.isfile(res_path):
|
||||||
self.maximize()
|
with open(res_path, "r") as infile:
|
||||||
|
try:
|
||||||
|
data = json.load(infile)
|
||||||
|
valid_json = True
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
logger.critical("JSON decode error in '%s'" %(res_path))
|
||||||
|
valid_json = False
|
||||||
|
else:
|
||||||
|
valid_json = False
|
||||||
|
if valid_json:
|
||||||
|
res = data["res"]
|
||||||
|
w = res["width"]
|
||||||
|
h = res["height"]
|
||||||
|
logger.info("Restoring window size to %s,%s" %(w,h))
|
||||||
|
self.set_default_size(w, h)
|
||||||
|
|
||||||
# Hide FilterPanel on main menu
|
|
||||||
self.show_all()
|
self.show_all()
|
||||||
|
# Hide FilterPanel on main menu
|
||||||
self.grid.right_panel.set_filter_visibility(False)
|
self.grid.right_panel.set_filter_visibility(False)
|
||||||
self.grid.sel_panel.set_visible(False)
|
self.grid.sel_panel.set_visible(False)
|
||||||
self.grid.scrollable_treelist.treeview.grab_focus()
|
self.grid.scrollable_treelist.treeview.grab_focus()
|
||||||
|
|
||||||
def halt_proc_and_quit(self, window, event):
|
def halt_proc_and_quit(self, window, event):
|
||||||
self.grid.terminate_treeview_process()
|
self.grid.terminate_treeview_process()
|
||||||
Gtk.main_quit()
|
save_res_and_quit(window)
|
||||||
|
|
||||||
|
|
||||||
class ScrollableTree(Gtk.ScrolledWindow):
|
class ScrollableTree(Gtk.ScrolledWindow):
|
||||||
@ -896,7 +915,6 @@ class ScrollableTree(Gtk.ScrolledWindow):
|
|||||||
self.treeview = TreeView(is_steam_deck)
|
self.treeview = TreeView(is_steam_deck)
|
||||||
self.add(self.treeview)
|
self.add(self.treeview)
|
||||||
|
|
||||||
|
|
||||||
class RightPanel(Gtk.Box):
|
class RightPanel(Gtk.Box):
|
||||||
def __init__(self, is_steam_deck):
|
def __init__(self, is_steam_deck):
|
||||||
super().__init__(spacing=6)
|
super().__init__(spacing=6)
|
||||||
@ -925,8 +943,7 @@ class RightPanel(Gtk.Box):
|
|||||||
self.question_button.connect("clicked", self._on_button_clicked)
|
self.question_button.connect("clicked", self._on_button_clicked)
|
||||||
|
|
||||||
self.pack_start(self.debug_toggle, False, True, 0)
|
self.pack_start(self.debug_toggle, False, True, 0)
|
||||||
if is_steam_deck is False:
|
self.pack_start(self.question_button, False, True, 0)
|
||||||
self.pack_start(self.question_button, False, True, 0)
|
|
||||||
|
|
||||||
def _on_button_toggled(self, button, command):
|
def _on_button_toggled(self, button, command):
|
||||||
grid = self.get_parent()
|
grid = self.get_parent()
|
||||||
@ -971,7 +988,7 @@ class ButtonBox(Gtk.Box):
|
|||||||
button.set_opacity(0.6)
|
button.set_opacity(0.6)
|
||||||
self.buttons.append(button)
|
self.buttons.append(button)
|
||||||
button.connect("clicked", self._on_selection_button_clicked)
|
button.connect("clicked", self._on_selection_button_clicked)
|
||||||
self.pack_start(button, False, False, True)
|
self.pack_start(button, False, False, 0)
|
||||||
|
|
||||||
self.buttons[0].set_opacity(1.0)
|
self.buttons[0].set_opacity(1.0)
|
||||||
|
|
||||||
@ -1043,7 +1060,9 @@ class ButtonBox(Gtk.Box):
|
|||||||
|
|
||||||
if context == ButtonType.EXIT:
|
if context == ButtonType.EXIT:
|
||||||
logger.info("Normal user exit")
|
logger.info("Normal user exit")
|
||||||
Gtk.main_quit()
|
widgets = relative_widget(self)
|
||||||
|
window = widgets["outer"]
|
||||||
|
save_res_and_quit(window)
|
||||||
return
|
return
|
||||||
cols = treeview.get_columns()
|
cols = treeview.get_columns()
|
||||||
|
|
||||||
@ -1073,12 +1092,13 @@ class ButtonBox(Gtk.Box):
|
|||||||
|
|
||||||
|
|
||||||
class CalcDist(multiprocessing.Process):
|
class CalcDist(multiprocessing.Process):
|
||||||
def __init__(self, widget, addr, result_queue, cache):
|
def __init__(self, widget, addr, qport, result_queue, cache):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.widget = widget
|
self.widget = widget
|
||||||
self.result_queue = result_queue
|
self.result_queue = result_queue
|
||||||
self.addr = addr
|
self.addr = addr
|
||||||
|
self.qport = str(qport)
|
||||||
self.ip = addr.split(':')[0]
|
self.ip = addr.split(':')[0]
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@ -1087,7 +1107,7 @@ class CalcDist(multiprocessing.Process):
|
|||||||
self.result_queue.put([self.addr, cache[self.addr][0], cache[self.addr][1]])
|
self.result_queue.put([self.addr, cache[self.addr][0], cache[self.addr][1]])
|
||||||
return
|
return
|
||||||
proc = call_out(self.widget, "get_dist", self.ip)
|
proc = call_out(self.widget, "get_dist", self.ip)
|
||||||
proc2 = call_out(self.widget, "test_ping", self.ip)
|
proc2 = call_out(self.widget, "test_ping", self.ip, self.qport)
|
||||||
km = proc.stdout
|
km = proc.stdout
|
||||||
ping = proc2.stdout
|
ping = proc2.stdout
|
||||||
self.result_queue.put([self.addr, km, ping])
|
self.result_queue.put([self.addr, km, ping])
|
||||||
@ -1314,6 +1334,7 @@ class TreeView(Gtk.TreeView):
|
|||||||
|
|
||||||
if self.view == WindowContext.TABLE_API or self.view == WindowContext.TABLE_SERVER:
|
if self.view == WindowContext.TABLE_API or self.view == WindowContext.TABLE_SERVER:
|
||||||
addr = self.get_column_at_index(7)
|
addr = self.get_column_at_index(7)
|
||||||
|
qport = self.get_column_at_index(8)
|
||||||
if addr is None:
|
if addr is None:
|
||||||
server_tooltip[0] = format_tooltip()
|
server_tooltip[0] = format_tooltip()
|
||||||
grid.update_statusbar(server_tooltip[0])
|
grid.update_statusbar(server_tooltip[0])
|
||||||
@ -1327,7 +1348,7 @@ class TreeView(Gtk.TreeView):
|
|||||||
grid.update_statusbar(tooltip)
|
grid.update_statusbar(tooltip)
|
||||||
return
|
return
|
||||||
self.emit("on_distcalc_started")
|
self.emit("on_distcalc_started")
|
||||||
self.current_proc = CalcDist(self, addr, self.queue, cache)
|
self.current_proc = CalcDist(self, addr, qport, self.queue, cache)
|
||||||
self.current_proc.start()
|
self.current_proc.start()
|
||||||
else:
|
else:
|
||||||
tooltip = format_metadata(row_sel)
|
tooltip = format_metadata(row_sel)
|
||||||
@ -1582,13 +1603,15 @@ class TreeView(Gtk.TreeView):
|
|||||||
column_title = "Name"
|
column_title = "Name"
|
||||||
saved_size = data["cols"][column_title]
|
saved_size = data["cols"][column_title]
|
||||||
column.set_fixed_width(saved_size)
|
column.set_fixed_width(saved_size)
|
||||||
|
column.set_expand(True)
|
||||||
else:
|
else:
|
||||||
if ("Name" in column_title):
|
if ("Name" in column_title):
|
||||||
column.set_fixed_width(800)
|
column.set_fixed_width(800)
|
||||||
if (column_title == "Map"):
|
if (column_title == "Map"):
|
||||||
column.set_fixed_width(300)
|
column.set_fixed_width(300)
|
||||||
|
|
||||||
self.append_column(column)
|
if i != 10:
|
||||||
|
self.append_column(column)
|
||||||
|
|
||||||
self.update_first_col(mode.dict["label"])
|
self.update_first_col(mode.dict["label"])
|
||||||
|
|
||||||
@ -2330,12 +2353,8 @@ class Grid(Gtk.Grid):
|
|||||||
self._version = "%s %s" %(app_name, sys.argv[2])
|
self._version = "%s %s" %(app_name, sys.argv[2])
|
||||||
|
|
||||||
self.scrollable_treelist = ScrollableTree(is_steam_deck)
|
self.scrollable_treelist = ScrollableTree(is_steam_deck)
|
||||||
if is_steam_deck is True:
|
self.scrollable_treelist.set_hexpand(False)
|
||||||
self.scrollable_treelist.set_hexpand(False)
|
self.scrollable_treelist.set_vexpand(True)
|
||||||
self.scrollable_treelist.set_vexpand(True)
|
|
||||||
else:
|
|
||||||
self.scrollable_treelist.set_hexpand(True)
|
|
||||||
self.scrollable_treelist.set_vexpand(True)
|
|
||||||
|
|
||||||
self.right_panel = RightPanel(is_steam_deck)
|
self.right_panel = RightPanel(is_steam_deck)
|
||||||
self.sel_panel = ModSelectionPanel()
|
self.sel_panel = ModSelectionPanel()
|
||||||
@ -2352,14 +2371,9 @@ class Grid(Gtk.Grid):
|
|||||||
self.bar.add(self.status_right_label)
|
self.bar.add(self.status_right_label)
|
||||||
self.update_right_statusbar()
|
self.update_right_statusbar()
|
||||||
|
|
||||||
if is_steam_deck is True:
|
self.attach(self.scrollable_treelist, 0, 0, 3, 1)
|
||||||
self.attach(self.scrollable_treelist, 0, 0, 4, 1)
|
self.attach_next_to(self.bar, self.scrollable_treelist, Gtk.PositionType.BOTTOM, 3, 1)
|
||||||
self.attach_next_to(self.bar, self.scrollable_treelist, Gtk.PositionType.BOTTOM, 4, 1)
|
self.attach_next_to(self.right_panel, self.scrollable_treelist, Gtk.PositionType.RIGHT, 1, 1)
|
||||||
self.attach_next_to(self.right_panel, self.scrollable_treelist, Gtk.PositionType.RIGHT, 1, 1)
|
|
||||||
else:
|
|
||||||
self.attach(self.scrollable_treelist, 0, 0, 7, 5)
|
|
||||||
self.attach_next_to(self.bar, self.scrollable_treelist, Gtk.PositionType.BOTTOM, 7, 1)
|
|
||||||
self.attach_next_to(self.right_panel, self.scrollable_treelist, Gtk.PositionType.RIGHT, 1, 1)
|
|
||||||
|
|
||||||
def update_right_statusbar(self):
|
def update_right_statusbar(self):
|
||||||
config_vals.clear()
|
config_vals.clear()
|
||||||
@ -2438,16 +2452,50 @@ class App(Gtk.Application):
|
|||||||
self.win = OuterWindow(is_steam_deck, is_game_mode)
|
self.win = OuterWindow(is_steam_deck, is_game_mode)
|
||||||
self.win.set_icon_name("dzgui")
|
self.win.set_icon_name("dzgui")
|
||||||
|
|
||||||
|
|
||||||
accel = Gtk.AccelGroup()
|
accel = Gtk.AccelGroup()
|
||||||
accel.connect(Gdk.KEY_q, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE, self._halt_window_subprocess)
|
accel.connect(Gdk.KEY_q, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE, self._halt_window_subprocess)
|
||||||
self.win.add_accel_group(accel)
|
self.win.add_accel_group(accel)
|
||||||
|
|
||||||
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, Gtk.main_quit)
|
|
||||||
|
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self._catch_sigint)
|
||||||
Gtk.main()
|
Gtk.main()
|
||||||
|
|
||||||
def _halt_window_subprocess(self, accel_group, window, code, flag):
|
def _catch_sigint(self):
|
||||||
self.win.halt_proc_and_quit(self, None)
|
self.win.halt_proc_and_quit(self.win, None)
|
||||||
|
|
||||||
|
def _halt_window_subprocess(self, accel_group, window, code, flag):
|
||||||
|
self.win.halt_proc_and_quit(self.win, None)
|
||||||
|
|
||||||
|
|
||||||
|
def save_res_and_quit(window):
|
||||||
|
if window.props.is_maximized:
|
||||||
|
Gtk.main_quit()
|
||||||
|
return
|
||||||
|
rect = window.get_size()
|
||||||
|
|
||||||
|
def write_json(rect):
|
||||||
|
data = {"res": { "width": rect.width, "height": rect.height } }
|
||||||
|
j = json.dumps(data, indent=2)
|
||||||
|
with open(res_path, "w") as outfile:
|
||||||
|
outfile.write(j)
|
||||||
|
logger.info("Wrote initial window size to '%s'" %(res_path))
|
||||||
|
|
||||||
|
if os.path.isfile(res_path):
|
||||||
|
with open(res_path, "r") as infile:
|
||||||
|
try:
|
||||||
|
data = json.load(infile)
|
||||||
|
data["res"]["width"] = rect.width
|
||||||
|
data["res"]["height"] = rect.height
|
||||||
|
with open(res_path, "w") as outfile:
|
||||||
|
outfile.write(json.dumps(data, indent=2))
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
logger.critical("JSON decode error in '%s'" %(res_path))
|
||||||
|
write_json(rect)
|
||||||
|
else:
|
||||||
|
write_json(rect)
|
||||||
|
|
||||||
|
Gtk.main_quit()
|
||||||
|
|
||||||
class ModSelectionPanel(Gtk.Box):
|
class ModSelectionPanel(Gtk.Box):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -2471,7 +2519,6 @@ class ModSelectionPanel(Gtk.Box):
|
|||||||
button.connect("clicked", self._on_button_clicked)
|
button.connect("clicked", self._on_button_clicked)
|
||||||
self.pack_start(button, False, True, 0)
|
self.pack_start(button, False, True, 0)
|
||||||
|
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
l = len(self.get_children())
|
l = len(self.get_children())
|
||||||
last = self.get_children()[l-1]
|
last = self.get_children()[l-1]
|
||||||
@ -2483,7 +2530,6 @@ class ModSelectionPanel(Gtk.Box):
|
|||||||
case "Unhighlight stale":
|
case "Unhighlight stale":
|
||||||
i.set_label("Highlight stale")
|
i.set_label("Highlight stale")
|
||||||
|
|
||||||
|
|
||||||
def _on_button_clicked(self, button):
|
def _on_button_clicked(self, button):
|
||||||
self.active_button = button
|
self.active_button = button
|
||||||
label = button.get_label()
|
label = button.get_label()
|
||||||
@ -2512,7 +2558,6 @@ class ModSelectionPanel(Gtk.Box):
|
|||||||
path = Gtk.TreePath(i)
|
path = Gtk.TreePath(i)
|
||||||
treeview.get_selection().select_path(path)
|
treeview.get_selection().select_path(path)
|
||||||
|
|
||||||
|
|
||||||
def _remove_last_button(self):
|
def _remove_last_button(self):
|
||||||
children = self.get_children()
|
children = self.get_children()
|
||||||
l = len(children)
|
l = len(children)
|
||||||
@ -2637,12 +2682,20 @@ class FilterPanel(Gtk.Box):
|
|||||||
self.maps_combo.connect("changed", self._on_map_changed)
|
self.maps_combo.connect("changed", self._on_map_changed)
|
||||||
self.maps_combo.connect("key-press-event", self._on_esc_pressed)
|
self.maps_combo.connect("key-press-event", self._on_esc_pressed)
|
||||||
|
|
||||||
self.pack_start(self.filters_label, False, False, True)
|
self.pack_start(self.filters_label, False, False, 0)
|
||||||
self.pack_start(self.keyword_entry, False, False, True)
|
self.pack_start(self.keyword_entry, False, False, 0)
|
||||||
self.pack_start(self.maps_combo, False, False, True)
|
self.pack_start(self.maps_combo, False, False, 0)
|
||||||
|
|
||||||
|
button_grid = Gtk.Grid()
|
||||||
|
row = 1
|
||||||
|
col = 0
|
||||||
for i, check in enumerate(checks[0:]):
|
for i, check in enumerate(checks[0:]):
|
||||||
self.pack_start(checks[i], False, False, True)
|
col = col + 1
|
||||||
|
if (col > 3):
|
||||||
|
row = row + 1
|
||||||
|
col = 1
|
||||||
|
button_grid.attach(checks[i], col, row, 1, 1)
|
||||||
|
self.pack_start(button_grid, False, False, 0)
|
||||||
|
|
||||||
def _on_map_entry_keypress(self, entry, event):
|
def _on_map_entry_keypress(self, entry, event):
|
||||||
match event.keyval:
|
match event.keyval:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user