Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b11176015 | |||
| 154837d411 | |||
| c1acd2dfcb |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
subprojects/blueprint-compiler
|
||||
_build
|
||||
18
README.md
18
README.md
@@ -5,10 +5,10 @@ This is a companion-app for Warframe players on Linux, written in phython and GT
|
||||
## Features
|
||||
|
||||
- Manage a persistent list of which Basic and Prime warframes you own to help you plan what to get next!
|
||||
- Wishlist missing frames and track which parts you own and where to get the missing ones!
|
||||
|
||||
## Planned
|
||||
|
||||
- Overview of needed parts, with ability to select which are already acquired, what is needed to craft them, and where/how to optain them.
|
||||
- Overview of which frames have been subsumed.
|
||||
- Overview of which relics to prioritize based on which frames are missing or a wishlist of priority frames. (Potentially also integrate market data?)
|
||||
- Support for weapons.
|
||||
@@ -21,7 +21,21 @@ Ideally, cloning the repo and opening with GNOME Builder will have the best resu
|
||||
$ git clone https://git.valhrafnaz.gay/valhrafnaz/VoidManifest.git
|
||||
```
|
||||
|
||||
Alternatively, you can run ninja yourself.
|
||||
Alternatively, you can build the project yourself.
|
||||
|
||||
```
|
||||
$ cd VoidManifest
|
||||
$ meson setup builddir
|
||||
$ meson compile -C builddir
|
||||
```
|
||||
|
||||
To be able to run the executable `./builddir/src/voidmanifest`, you must install the project with meson:
|
||||
|
||||
```
|
||||
$ meson install -C builddir
|
||||
```
|
||||
|
||||
Note that only the flatpak version of the program is supported, all issues referencing local installations will be deleted.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -24,11 +24,11 @@ template $ChecklistPage: Box {
|
||||
}
|
||||
|
||||
Label {
|
||||
label: _("List of all Warframes available as of Dec 10 '25");
|
||||
label: _("List of all Warframes available as of today");
|
||||
margin-bottom: 12;
|
||||
|
||||
styles [
|
||||
"dim-label",
|
||||
"dimmed",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ template $ChecklistPage: Box {
|
||||
}
|
||||
|
||||
ToggleButton cyte09 {
|
||||
name: "cyte09";
|
||||
name: "cyte-09";
|
||||
label: _("Cyte-09");
|
||||
margin-bottom: 4;
|
||||
}
|
||||
@@ -622,7 +622,7 @@ template $ChecklistPage: Box {
|
||||
}
|
||||
|
||||
ToggleButton cyte09_prime {
|
||||
name: "cyte09_prime";
|
||||
name: "cyte-09_prime";
|
||||
label: _("Cyte-09 Prime");
|
||||
margin-bottom: 4;
|
||||
can-target: false;
|
||||
|
||||
@@ -32,10 +32,10 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">List of all Warframes available as of Dec 10 '25</property>
|
||||
<property name="label" translatable="yes">List of all Warframes available as of today</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
<class name="dimmed"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
@@ -189,7 +189,7 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="cyte09">
|
||||
<property name="name">cyte09</property>
|
||||
<property name="name">cyte-09</property>
|
||||
<property name="label" translatable="yes">Cyte-09</property>
|
||||
<property name="margin-bottom">4</property>
|
||||
</object>
|
||||
@@ -740,7 +740,7 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="cyte09_prime">
|
||||
<property name="name">cyte09_prime</property>
|
||||
<property name="name">cyte-09_prime</property>
|
||||
<property name="label" translatable="yes">Cyte-09 Prime</property>
|
||||
<property name="margin-bottom">4</property>
|
||||
<property name="can-target">false</property>
|
||||
|
||||
@@ -5,12 +5,17 @@ template $HomePage: Box {
|
||||
orientation: vertical;
|
||||
baseline-position: center;
|
||||
Adw.Clamp {
|
||||
Adw.PreferencesGroup {
|
||||
ScrolledWindow {
|
||||
hexpand: true;
|
||||
vexpand: true;
|
||||
child: Adw.PreferencesGroup {
|
||||
margin-start:20;
|
||||
margin-end: 20;
|
||||
title: _("Welcome back, Tenno");
|
||||
styles [
|
||||
'list-title'
|
||||
]
|
||||
Adw.ActionRow {
|
||||
Adw.ExpanderRow owned_frames_row {
|
||||
title: _("Owned Unique Frames:");
|
||||
title-selectable: false;
|
||||
activatable: false;
|
||||
@@ -19,7 +24,7 @@ template $HomePage: Box {
|
||||
Label owned_frames {
|
||||
}
|
||||
}
|
||||
Adw.ActionRow {
|
||||
Adw.ExpanderRow owned_basics_row {
|
||||
title: _("Owned Basic Frames:");
|
||||
title-selectable: false;
|
||||
activatable: false;
|
||||
@@ -29,7 +34,7 @@ template $HomePage: Box {
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.ExpanderRow missing_basics_row {
|
||||
title: _("Missing Basic Frames:");
|
||||
title-selectable: false;
|
||||
activatable: false;
|
||||
@@ -39,7 +44,7 @@ template $HomePage: Box {
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.ExpanderRow owned_primes_row {
|
||||
title: _("Owned Prime Frames:");
|
||||
title-selectable: false;
|
||||
activatable: false;
|
||||
@@ -49,7 +54,7 @@ template $HomePage: Box {
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
Adw.ExpanderRow missing_primes_row {
|
||||
title: _("Missing Prime Frames:");
|
||||
title-selectable: false;
|
||||
activatable: false;
|
||||
@@ -58,6 +63,7 @@ template $HomePage: Box {
|
||||
Label missing_primes {
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,13 +12,19 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
<child>
|
||||
<object class="AdwClamp">
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hexpand">true</property>
|
||||
<property name="vexpand">true</property>
|
||||
<property name="child">
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="margin-start">20</property>
|
||||
<property name="margin-end">20</property>
|
||||
<property name="title" translatable="yes">Welcome back, Tenno</property>
|
||||
<style>
|
||||
<class name="list-title"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<object class="AdwExpanderRow" id="owned_frames_row">
|
||||
<property name="title" translatable="yes">Owned Unique Frames:</property>
|
||||
<property name="title-selectable">false</property>
|
||||
<property name="activatable">false</property>
|
||||
@@ -28,7 +34,7 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<object class="AdwExpanderRow" id="owned_basics_row">
|
||||
<property name="title" translatable="yes">Owned Basic Frames:</property>
|
||||
<property name="title-selectable">false</property>
|
||||
<property name="activatable">false</property>
|
||||
@@ -38,7 +44,7 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<object class="AdwExpanderRow" id="missing_basics_row">
|
||||
<property name="title" translatable="yes">Missing Basic Frames:</property>
|
||||
<property name="title-selectable">false</property>
|
||||
<property name="activatable">false</property>
|
||||
@@ -48,7 +54,7 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<object class="AdwExpanderRow" id="owned_primes_row">
|
||||
<property name="title" translatable="yes">Owned Prime Frames:</property>
|
||||
<property name="title-selectable">false</property>
|
||||
<property name="activatable">false</property>
|
||||
@@ -58,7 +64,7 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<object class="AdwExpanderRow" id="missing_primes_row">
|
||||
<property name="title" translatable="yes">Missing Prime Frames:</property>
|
||||
<property name="title-selectable">false</property>
|
||||
<property name="activatable">false</property>
|
||||
@@ -68,6 +74,8 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
@@ -35,7 +35,7 @@ template $VoidmanifestWindow: Adw.ApplicationWindow {
|
||||
// Main View
|
||||
content:
|
||||
Adw.ViewStack viewstack {
|
||||
|
||||
notify::visible-child => $on_page_changed();
|
||||
};
|
||||
[bottom]
|
||||
ActionBar {
|
||||
|
||||
@@ -39,7 +39,9 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
</object>
|
||||
</child>
|
||||
<property name="content">
|
||||
<object class="AdwViewStack" id="viewstack"></object>
|
||||
<object class="AdwViewStack" id="viewstack">
|
||||
<signal name="notify::visible-child" handler="on_page_changed"/>
|
||||
</object>
|
||||
</property>
|
||||
<child type="bottom">
|
||||
<object class="GtkActionBar">
|
||||
|
||||
@@ -5,7 +5,11 @@ template $WishlistPage: Gtk.Box {
|
||||
orientation: vertical;
|
||||
baseline-position: center;
|
||||
Adw.Clamp {
|
||||
ScrolledWindow {
|
||||
hexpand: true;
|
||||
vexpand: true;
|
||||
Adw.PreferencesGroup wishlist {
|
||||
margin-end:20;
|
||||
header-suffix: Button btn_wishlist_add {
|
||||
icon-name: 'plus-circle-outline-symbolic';
|
||||
styles [
|
||||
@@ -21,4 +25,5 @@ template $WishlistPage: Gtk.Box {
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,13 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
<property name="baseline-position">1</property>
|
||||
<child>
|
||||
<object class="AdwClamp">
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hexpand">true</property>
|
||||
<property name="vexpand">true</property>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup" id="wishlist">
|
||||
<property name="margin-end">20</property>
|
||||
<property name="header-suffix">
|
||||
<object class="GtkButton" id="btn_wishlist_add">
|
||||
<property name="icon-name">plus-circle-outline-symbolic</property>
|
||||
@@ -32,5 +37,7 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@@ -6,7 +6,7 @@ EXISTING_FRAMES_BASIC = [
|
||||
"caliban",
|
||||
"chroma",
|
||||
"citrine",
|
||||
"cyte09",
|
||||
"cyte-09",
|
||||
"dagath",
|
||||
"dante",
|
||||
"ember",
|
||||
@@ -52,7 +52,6 @@ EXISTING_FRAMES_BASIC = [
|
||||
"temple",
|
||||
"titania",
|
||||
"trinity",
|
||||
"uriel",
|
||||
"valkyr",
|
||||
"vauban",
|
||||
"volt",
|
||||
@@ -79,7 +78,6 @@ EXISTING_FRAMES_PRIME = [
|
||||
"garuda_prime",
|
||||
"gauss_prime",
|
||||
"grendel_prime",
|
||||
"gyre_prime",
|
||||
"harrow_prime",
|
||||
"hildryn_prime",
|
||||
"hydroid_prime",
|
||||
@@ -119,7 +117,6 @@ EXISTING_FRAMES_PRIME = [
|
||||
ID_TO_NAME: dict[str, str] = dict()
|
||||
NAME_TO_ID: dict[str, str] = dict()
|
||||
# warframe counts
|
||||
# TODO Update via API/wiki
|
||||
BASIC_WARFRAMES = 63
|
||||
PRIME_WARFRAMES = 49
|
||||
CURRENT_UPDATE = 41
|
||||
|
||||
@@ -125,7 +125,7 @@ class VoidmanifestApplication(Adw.Application):
|
||||
|
||||
def _refresh_metadata(self):
|
||||
url = 'https://api.warframestat.us/warframes'
|
||||
params = 'only=name,isPrime'
|
||||
params = 'only=name,isPrime,category'
|
||||
resp = requests.get(url, params)
|
||||
base_frames_list: list[str] = list()
|
||||
prime_frames_list: list[str] = list()
|
||||
@@ -135,6 +135,9 @@ class VoidmanifestApplication(Adw.Application):
|
||||
else:
|
||||
print('CRITICAL ERROR: Could not refresh metadata from https://api.warframestat.us/')
|
||||
for warframe in resp_data:
|
||||
# skip every non-warframe
|
||||
if warframe['category'] != 'Warframes':
|
||||
continue
|
||||
name = warframe['name']
|
||||
# skip these two frames since they cannot be acquired anymore and break symmetry in the list
|
||||
if name == 'Excalibur Umbra Prime' or name == 'Excalibur Prime':
|
||||
@@ -145,12 +148,23 @@ class VoidmanifestApplication(Adw.Application):
|
||||
prime_frames_list.append(frame_id)
|
||||
else:
|
||||
base_frames_list.append(frame_id)
|
||||
# TODO REMOVE
|
||||
# only needed until API is finally updated
|
||||
base_frames_list.append('uriel')
|
||||
prime_frames_list.append('gyre_prime')
|
||||
base_frames_list = sorted(list(set(base_frames_list)))
|
||||
prime_frames_list = sorted(list(set(prime_frames_list)))
|
||||
EXISTING_FRAMES_BASIC = base_frames_list.copy()
|
||||
EXISTING_FRAMES_PRIME = prime_frames_list.copy()
|
||||
BASIC_WARFRAMES = len(EXISTING_FRAMES_BASIC)
|
||||
PRIME_WARFRAMES = len(EXISTING_FRAMES_PRIME)
|
||||
# dictionary that translates ids to names for better responsiveness on UI
|
||||
ID_TO_NAME[frame_id] = name
|
||||
# TODO REMOVE
|
||||
# only needed until API is finally updated
|
||||
ID_TO_NAME['gyre_prime'] = 'Gyre Prime'
|
||||
ID_TO_NAME['uriel'] = 'Uriel'
|
||||
|
||||
NAME_TO_ID = dict((v,k) for k,v in ID_TO_NAME.items())
|
||||
|
||||
|
||||
@@ -170,7 +184,7 @@ class VoidmanifestApplication(Adw.Application):
|
||||
json.dump(profile.to_dict(), f, indent=2)
|
||||
|
||||
def reset_frames(self, param):
|
||||
self.profile.owned_frames = {}
|
||||
self.profile.owned_frames = []
|
||||
button = self.checklist_page.btns_basic.get_first_child()
|
||||
while button is not None:
|
||||
if isinstance(button, Gtk.ToggleButton):
|
||||
@@ -188,7 +202,7 @@ class VoidmanifestApplication(Adw.Application):
|
||||
basic_count = 0
|
||||
missing_basics: list[str] = []
|
||||
for basic_frame in EXISTING_FRAMES_BASIC:
|
||||
if self.profile.owned_frames.get(basic_frame, False):
|
||||
if basic_frame in self.profile.owned_frames:
|
||||
basic_count = basic_count + 1
|
||||
else:
|
||||
missing_basics.append(basic_frame)
|
||||
@@ -196,18 +210,18 @@ class VoidmanifestApplication(Adw.Application):
|
||||
prime_count = 0
|
||||
missing_primes: list[str] = []
|
||||
for prime_frame in EXISTING_FRAMES_PRIME:
|
||||
if self.profile.owned_frames.get(prime_frame, False):
|
||||
if prime_frame in self.profile.owned_frames:
|
||||
prime_count = prime_count + 1
|
||||
else:
|
||||
missing_primes.append(prime_frame)
|
||||
# count unique
|
||||
unique_frames: set[str] = set()
|
||||
for owned_frame, is_owned in self.profile.owned_frames.items():
|
||||
if is_owned:
|
||||
for owned_frame in self.profile.owned_frames:
|
||||
_name = owned_frame.removesuffix("_prime")
|
||||
_name = _name.removesuffix("_umbra")
|
||||
unique_frames.add(_name)
|
||||
|
||||
self.profile.unique_frames_list = list(unique_frames)
|
||||
self.profile.missing_basics_count = len(missing_basics)
|
||||
self.profile.missing_primes_count = len(missing_primes)
|
||||
self.profile.unique_frames_owned = len(unique_frames)
|
||||
|
||||
@@ -44,14 +44,14 @@ class ChecklistPage(Gtk.Box):
|
||||
while button is not None:
|
||||
if isinstance(button, Gtk.ToggleButton):
|
||||
btn_id = button.get_name()
|
||||
button.set_active(self.app.profile.owned_frames.get(btn_id, False))
|
||||
button.set_active((btn_id in self.app.profile.owned_frames))
|
||||
button.connect("toggled", self._on_button_toggled)
|
||||
button = button.get_next_sibling()
|
||||
button = self.btns_prime.get_first_child()
|
||||
while button is not None:
|
||||
if isinstance(button, Gtk.ToggleButton):
|
||||
btn_id = button.get_name()
|
||||
button.set_active(self.app.profile.owned_frames.get(btn_id, False))
|
||||
button.set_active((btn_id in self.app.profile.owned_frames))
|
||||
button.connect("toggled", self._on_button_toggled)
|
||||
button = button.get_next_sibling()
|
||||
|
||||
@@ -90,7 +90,12 @@ class ChecklistPage(Gtk.Box):
|
||||
if btn_id == "GtkToggleButton":
|
||||
print("what")
|
||||
return
|
||||
self.app.profile.owned_frames[btn_id] = btn.get_active()
|
||||
if btn.get_active():
|
||||
self.app.profile.owned_frames.append(btn_id)
|
||||
if btn_id in self.app.profile.wishlist(btn_id):
|
||||
self.app.profile.wishlist.remove(btn_id)
|
||||
else:
|
||||
self.app.profile.owned_frames.remove(btn_id)
|
||||
self.app.save_profile(self.app.profile)
|
||||
self._calc_frames()
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import gi
|
||||
|
||||
from ..constants import BASIC_WARFRAMES, PRIME_WARFRAMES
|
||||
from ..constants import BASIC_WARFRAMES, PRIME_WARFRAMES, ID_TO_NAME
|
||||
|
||||
gi.require_version('Gtk', '4.0')
|
||||
gi.require_version('Adw', '1')
|
||||
@@ -12,29 +12,80 @@ from gi.repository import Gtk, Adw, GObject, GLib # noqa: E402
|
||||
class HomePage(Gtk.Box):
|
||||
__gtype_name__ = "HomePage"
|
||||
|
||||
app = None
|
||||
|
||||
owned_frames = Gtk.Template.Child()
|
||||
owned_frames_row = Gtk.Template.Child()
|
||||
owned_basics = Gtk.Template.Child()
|
||||
owned_basics_row = Gtk.Template.Child()
|
||||
missing_basics = Gtk.Template.Child()
|
||||
missing_basics_row = Gtk.Template.Child()
|
||||
owned_primes = Gtk.Template.Child()
|
||||
owned_primes_row = Gtk.Template.Child()
|
||||
missing_primes = Gtk.Template.Child()
|
||||
missing_primes_row = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, *, parent: Adw.ViewStack):
|
||||
"""
|
||||
`parent` is the ViewStack that will host this page.
|
||||
By passing it to the superclass constructor we tell GTK to
|
||||
insert the newly created page into that stack automatically.
|
||||
"""
|
||||
super().__init__()
|
||||
parent.add_titled(self, "home", "Home")
|
||||
wrapper = parent.get_page(self)
|
||||
wrapper.set_icon_name("compass2-symbolic")
|
||||
self.app = self.get_root().get_application()
|
||||
self.app.profile._on_change = self.refresh
|
||||
self._unique_rows: dict[str, Adw.ActionRow] = {}
|
||||
self._missing_basics_rows: dict[str, Adw.ActionRow] = {}
|
||||
self._missing_primes_rows: dict[str, Adw.ActionRow] = {}
|
||||
self._basic_rows: dict[str, Adw.ActionRow] = {}
|
||||
self._prime_rows: dict[str, Adw.ActionRow] = {}
|
||||
self.refresh()
|
||||
|
||||
def refresh(self):
|
||||
# Prevents race condition where refresh is called before __init__
|
||||
if self.app is None:
|
||||
return
|
||||
|
||||
self.app.profile.owned_frames = sorted(list(set(self.app.profile.owned_frames)))
|
||||
|
||||
# set labels
|
||||
self.owned_frames.set_label(str (self.app.profile.unique_frames_owned))
|
||||
self.owned_basics.set_label(str (BASIC_WARFRAMES - self.app.profile.missing_basics_count))
|
||||
self.owned_primes.set_label(str (PRIME_WARFRAMES - self.app.profile.missing_primes_count))
|
||||
self.missing_basics.set_label(str(self.app.profile.missing_basics_count))
|
||||
self.missing_primes.set_label(str(self.app.profile.missing_primes_count))
|
||||
# populate dropdowns
|
||||
for frame in self.app.profile.owned_frames:
|
||||
if "_prime" in frame or "_umbra" in frame:
|
||||
row = Adw.ActionRow(
|
||||
title=ID_TO_NAME[frame]
|
||||
)
|
||||
if not self._prime_rows.get(frame, False):
|
||||
self._prime_rows[frame] = row
|
||||
self.owned_primes_row.add_row(row)
|
||||
else:
|
||||
row = Adw.ActionRow(
|
||||
title=ID_TO_NAME[frame]
|
||||
)
|
||||
if not self._basic_rows.get(frame, False):
|
||||
self._basic_rows[frame] = row
|
||||
self.owned_basics_row.add_row(row)
|
||||
|
||||
frame = frame.replace('_prime', '')
|
||||
row = Adw.ActionRow(
|
||||
title=ID_TO_NAME[frame]
|
||||
)
|
||||
if not self._unique_rows.get(frame, False):
|
||||
self._unique_rows[frame] = row
|
||||
self.owned_frames_row.add_row(row)
|
||||
for prime in self.app.profile.missing_primes:
|
||||
row = Adw.ActionRow(
|
||||
title=ID_TO_NAME[prime]
|
||||
)
|
||||
if not self._missing_primes_rows.get(prime, False):
|
||||
self._missing_primes_rows[prime] = row
|
||||
self.missing_primes_row.add_row(row)
|
||||
for basic in self.app.profile.missing_basics:
|
||||
row = Adw.ActionRow(
|
||||
title=ID_TO_NAME[basic]
|
||||
)
|
||||
if not self._missing_basics_rows.get(basic, False):
|
||||
self._missing_basics_rows[basic] = row
|
||||
self.missing_basics_row.add_row(row)
|
||||
|
||||
@@ -25,9 +25,10 @@ class WishlistPage(Gtk.Box):
|
||||
wrapper.set_icon_name("logs-symbolic")
|
||||
self.btn_wishlist_add.connect('clicked', self._open_wishlist_dialogue)
|
||||
self._wishlist_rows: dict[str, Adw.ActionRow] = {}
|
||||
self.refresh_wishlist()
|
||||
|
||||
def _open_wishlist_dialogue(self, button):
|
||||
dialog = FramePickerDialog(missing_frames=self.app.profile.missing_basics + self.app.profile.missing_primes)
|
||||
dialog = FramePickerDialog(missing_frames=self.app.profile.missing_basics + self.app.profile.missing_primes, app=self.app)
|
||||
dialog.connect('frame-selected', self.add_frame_to_wishlist)
|
||||
dialog.present(self.get_root())
|
||||
|
||||
@@ -52,7 +53,7 @@ class WishlistPage(Gtk.Box):
|
||||
self.wishlist.add(row)
|
||||
self.app.profile.wishlist.append(frame_id)
|
||||
self.app.profile.wishlist = sorted(self.app.profile.wishlist)
|
||||
self._refresh_wishlist
|
||||
self.refresh_wishlist
|
||||
|
||||
def btn_remove(self, button):
|
||||
self.remove_frame_from_wishlist(button.frame_id)
|
||||
@@ -61,14 +62,24 @@ class WishlistPage(Gtk.Box):
|
||||
if frame_id in self._wishlist_rows:
|
||||
row = self._wishlist_rows.pop(frame_id)
|
||||
self.wishlist.remove(row)
|
||||
if frame_id in self.app.profile.wishlist:
|
||||
self.app.profile.wishlist.remove(frame_id)
|
||||
|
||||
def has_frame(self, frame_id) -> bool:
|
||||
return frame_id in self._wishlist_rows
|
||||
|
||||
def _refresh_wishlist(self):
|
||||
def refresh_wishlist(self):
|
||||
# deduplicate
|
||||
self.app.profile.wishlist = list(set(self.app.profile.wishlist))
|
||||
|
||||
for frame_id in self.app.profile.wishlist:
|
||||
if frame_id not in self._wishlist_rows:
|
||||
self.add_frame_to_wishlist(Adw.Dialog.new(),frame_id)
|
||||
for frame_id in list(self._wishlist_rows):
|
||||
to_delete: list[str] = []
|
||||
for frame_id in self._wishlist_rows:
|
||||
if frame_id not in self.app.profile.wishlist:
|
||||
to_delete.append(frame_id)
|
||||
if frame_id in self.app.profile.owned_frames:
|
||||
to_delete.append(frame_id)
|
||||
for frame_id in to_delete:
|
||||
self.remove_frame_from_wishlist(frame_id)
|
||||
|
||||
@@ -5,22 +5,15 @@ from .constants import BASIC_WARFRAMES, PRIME_WARFRAMES
|
||||
# pseudo struct that contains the profile data that gets serialized into the .json profile.
|
||||
@dataclass
|
||||
class Profile:
|
||||
owned_frames: dict[str, bool] = field(default_factory=dict)
|
||||
owned_frames: list[str] = field(default_factory=list)
|
||||
unique_frames_owned: int = 0
|
||||
unique_frames_list: list[str] = field(default_factory=list)
|
||||
missing_basics: list[str] = field(default_factory=list)
|
||||
missing_basics_count: int = BASIC_WARFRAMES
|
||||
missing_primes: list[str] = field(default_factory=list)
|
||||
missing_primes_count: int = PRIME_WARFRAMES
|
||||
wishlist: list[str] = field(default_factory=list)
|
||||
|
||||
_on_change: Callable | None = field(default=None, repr=False, compare=False)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
super().__setattr__(name, value)
|
||||
# Notify on change (skip private attributes)
|
||||
if not name.startswith('_') and hasattr(self, '_on_change') and self._on_change:
|
||||
self._on_change()
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
"""Convert to dict, excluding private fields"""
|
||||
return {
|
||||
|
||||
@@ -16,9 +16,9 @@ class FramePickerDialog(Adw.Dialog):
|
||||
search_entry = Gtk.Template.Child()
|
||||
frame_list = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, missing_frames: list[str], **kwargs):
|
||||
def __init__(self, app: Adw.ApplicationWindow, missing_frames: list[str], **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.app = app
|
||||
self.missing_frames = missing_frames
|
||||
self._populate_list()
|
||||
|
||||
@@ -26,6 +26,7 @@ class FramePickerDialog(Adw.Dialog):
|
||||
|
||||
def _populate_list(self):
|
||||
for frame_name in sorted(self.missing_frames):
|
||||
if frame_name not in self.app.profile.wishlist:
|
||||
row = Adw.ActionRow(title=frame_name.replace("_", " ").title(),
|
||||
activatable=True
|
||||
)
|
||||
|
||||
@@ -56,4 +56,16 @@ class VoidmanifestWindow(Adw.ApplicationWindow):
|
||||
self.app.save_profile(self.app.profile)
|
||||
return False
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def on_page_changed(self, stack, param):
|
||||
self.app.refresh_profile()
|
||||
visible_child = stack.get_visible_child()
|
||||
visible_name = stack.get_visible_child_name()
|
||||
match visible_name:
|
||||
case 'home':
|
||||
visible_child.refresh()
|
||||
case 'wishlist':
|
||||
visible_child.refresh_wishlist()
|
||||
case _:
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user