Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdcded93f3 | ||
|
|
b3a65c3d23 | ||
|
|
06730248a9 | ||
|
|
b46faa951f | ||
|
|
43a04e7d44 | ||
|
|
d74c8aba1a |
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -73,11 +73,11 @@ jobs:
|
|||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
brew install meson pygobject3 libadwaita adwaita-icon-theme desktop-file-utils pyinstaller pillow
|
brew install meson pygobject3 libadwaita adwaita-icon-theme desktop-file-utils pyinstaller pillow
|
||||||
pip3 install --break-system-packages requests PyYAML
|
pip3 install --break-system-packages requests PyYAML pyobjc
|
||||||
|
|
||||||
- name: Meson Build
|
- name: Meson Build
|
||||||
run: |
|
run: |
|
||||||
meson setup _build
|
meson setup _build -Dtiff_compression=jpeg
|
||||||
ninja install -C _build
|
ninja install -C _build
|
||||||
|
|
||||||
- name: PyInstaller
|
- name: PyInstaller
|
||||||
|
|||||||
120
cartridges/application_delegate.py
Normal file
120
cartridges/application_delegate.py
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
# application_delegate.py
|
||||||
|
#
|
||||||
|
# Copyright 2024 kramo
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
"""A set of methods that manage your app’s life cycle and its interaction
|
||||||
|
with common system services."""
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from AppKit import NSApp, NSApplication, NSMenu, NSMenuItem # type: ignore
|
||||||
|
from Foundation import NSObject # type: ignore
|
||||||
|
from gi.repository import Gio # type: ignore
|
||||||
|
from showtime import shared
|
||||||
|
|
||||||
|
|
||||||
|
class ApplicationDelegate(NSObject): # type: ignore
|
||||||
|
"""A set of methods that manage your app’s life cycle and its interaction
|
||||||
|
with common system services."""
|
||||||
|
|
||||||
|
def applicationDidFinishLaunching_(self, *_args: Any) -> None:
|
||||||
|
main_menu = NSApp.mainMenu()
|
||||||
|
|
||||||
|
add_game_menu_item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
|
||||||
|
"Add Game", "add:", "n"
|
||||||
|
)
|
||||||
|
|
||||||
|
import_menu_item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
|
||||||
|
"Import", "import:", "i"
|
||||||
|
)
|
||||||
|
|
||||||
|
file_menu = NSMenu.alloc().init()
|
||||||
|
file_menu.addItem_(add_game_menu_item)
|
||||||
|
file_menu.addItem_(import_menu_item)
|
||||||
|
|
||||||
|
file_menu_item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
|
||||||
|
"File", None, ""
|
||||||
|
)
|
||||||
|
file_menu_item.setSubmenu_(file_menu)
|
||||||
|
main_menu.addItem_(file_menu_item)
|
||||||
|
|
||||||
|
show_hidden_menu_item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
|
||||||
|
"Show Hidden", "hidden:", "h"
|
||||||
|
)
|
||||||
|
|
||||||
|
windows_menu = NSMenu.alloc().init()
|
||||||
|
|
||||||
|
view_menu = NSMenu.alloc().init()
|
||||||
|
view_menu.addItem_(show_hidden_menu_item)
|
||||||
|
|
||||||
|
view_menu_item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
|
||||||
|
"View", None, ""
|
||||||
|
)
|
||||||
|
view_menu_item.setSubmenu_(view_menu)
|
||||||
|
main_menu.addItem_(view_menu_item)
|
||||||
|
|
||||||
|
windows_menu = NSMenu.alloc().init()
|
||||||
|
|
||||||
|
windows_menu_item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
|
||||||
|
"Window", None, ""
|
||||||
|
)
|
||||||
|
windows_menu_item.setSubmenu_(windows_menu)
|
||||||
|
main_menu.addItem_(windows_menu_item)
|
||||||
|
|
||||||
|
NSApp.setWindowsMenu_(windows_menu)
|
||||||
|
|
||||||
|
keyboard_shortcuts_menu_item = (
|
||||||
|
NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
|
||||||
|
"Keyboard Shortcuts", "shortcuts:", "?"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
help_menu = NSMenu.alloc().init()
|
||||||
|
help_menu.addItem_(keyboard_shortcuts_menu_item)
|
||||||
|
|
||||||
|
help_menu_item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
|
||||||
|
"Help", None, ""
|
||||||
|
)
|
||||||
|
help_menu_item.setSubmenu_(help_menu)
|
||||||
|
main_menu.addItem_(help_menu_item)
|
||||||
|
|
||||||
|
NSApp.setHelpMenu_(help_menu)
|
||||||
|
|
||||||
|
def add_(self, *_args: Any) -> None:
|
||||||
|
if (not shared.win) or (not (app := shared.win.get_application())):
|
||||||
|
return
|
||||||
|
|
||||||
|
app.lookup_action("add_game").activate()
|
||||||
|
|
||||||
|
def import_(self, *_args: Any) -> None:
|
||||||
|
if (not shared.win) or (not (app := shared.win.get_application())):
|
||||||
|
return
|
||||||
|
|
||||||
|
app.lookup_action("import").activate()
|
||||||
|
|
||||||
|
def hidden_(self, *_args: Any) -> None:
|
||||||
|
if not shared.win:
|
||||||
|
return
|
||||||
|
|
||||||
|
shared.win.lookup_action("show_hidden").activate()
|
||||||
|
|
||||||
|
def shortcuts_(self, *_args: Any) -> None:
|
||||||
|
if (not shared.win) or (not (overlay := shared.win.get_help_overlay())):
|
||||||
|
return
|
||||||
|
|
||||||
|
overlay.present()
|
||||||
@@ -59,8 +59,15 @@ class DetailsDialog(Adw.Dialog):
|
|||||||
|
|
||||||
cover_changed: bool = False
|
cover_changed: bool = False
|
||||||
|
|
||||||
|
is_open = False
|
||||||
|
|
||||||
def __init__(self, game: Optional[Game] = None, **kwargs: Any):
|
def __init__(self, game: Optional[Game] = None, **kwargs: Any):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
# Make it so only one dialog can be open at a time
|
||||||
|
self.__class__.is_open = True
|
||||||
|
self.connect("closed", lambda *_: self.set_is_open(False))
|
||||||
|
|
||||||
self.game: Game = game
|
self.game: Game = game
|
||||||
self.game_cover: GameCover = GameCover({self.cover})
|
self.game_cover: GameCover = GameCover({self.cover})
|
||||||
|
|
||||||
@@ -325,3 +332,6 @@ class DetailsDialog(Adw.Dialog):
|
|||||||
|
|
||||||
def choose_cover(self, *_args: Any) -> None:
|
def choose_cover(self, *_args: Any) -> None:
|
||||||
self.image_file_dialog.open(self.get_root(), None, self.set_cover)
|
self.image_file_dialog.open(self.get_root(), None, self.set_cover)
|
||||||
|
|
||||||
|
def set_is_open(self, is_open: bool) -> None:
|
||||||
|
self.__class__.is_open = is_open
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import shlex
|
|||||||
import sys
|
import sys
|
||||||
from time import time
|
from time import time
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
@@ -57,6 +58,12 @@ from cartridges.store.store import Store
|
|||||||
from cartridges.utils.run_executable import run_executable
|
from cartridges.utils.run_executable import run_executable
|
||||||
from cartridges.window import CartridgesWindow
|
from cartridges.window import CartridgesWindow
|
||||||
|
|
||||||
|
if sys.platform == "darwin":
|
||||||
|
from AppKit import NSApp # type: ignore
|
||||||
|
from PyObjCTools import AppHelper
|
||||||
|
|
||||||
|
from cartridges.application_delegate import ApplicationDelegate
|
||||||
|
|
||||||
|
|
||||||
class CartridgesApplication(Adw.Application):
|
class CartridgesApplication(Adw.Application):
|
||||||
state = shared.AppState.DEFAULT
|
state = shared.AppState.DEFAULT
|
||||||
@@ -87,9 +94,16 @@ class CartridgesApplication(Adw.Application):
|
|||||||
|
|
||||||
self.add_main_option_entries((search, launch))
|
self.add_main_option_entries((search, launch))
|
||||||
|
|
||||||
if sys.platform == "darwin" and (settings := Gtk.Settings.get_default()):
|
if sys.platform == "darwin":
|
||||||
|
if settings := Gtk.Settings.get_default():
|
||||||
settings.props.gtk_decoration_layout = "close,minimize,maximize:"
|
settings.props.gtk_decoration_layout = "close,minimize,maximize:"
|
||||||
|
|
||||||
|
def setup_app_delegate() -> None:
|
||||||
|
NSApp.setDelegate_(ApplicationDelegate.alloc().init()) # type: ignore
|
||||||
|
AppHelper.runEventLoop() # type: ignore
|
||||||
|
|
||||||
|
GLib.Thread.new(None, setup_app_delegate)
|
||||||
|
|
||||||
def do_activate(self) -> None: # pylint: disable=arguments-differ
|
def do_activate(self) -> None: # pylint: disable=arguments-differ
|
||||||
"""Called on app creation"""
|
"""Called on app creation"""
|
||||||
|
|
||||||
@@ -287,7 +301,7 @@ class CartridgesApplication(Adw.Application):
|
|||||||
_parameter: Any = None,
|
_parameter: Any = None,
|
||||||
page_name: Optional[str] = None,
|
page_name: Optional[str] = None,
|
||||||
expander_row: Optional[str] = None,
|
expander_row: Optional[str] = None,
|
||||||
) -> CartridgesWindow:
|
) -> Optional[CartridgesPreferences]:
|
||||||
if CartridgesPreferences.is_open:
|
if CartridgesPreferences.is_open:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -310,6 +324,9 @@ class CartridgesApplication(Adw.Application):
|
|||||||
DetailsDialog(shared.win.active_game).present(shared.win)
|
DetailsDialog(shared.win.active_game).present(shared.win)
|
||||||
|
|
||||||
def on_add_game_action(self, *_args: Any) -> None:
|
def on_add_game_action(self, *_args: Any) -> None:
|
||||||
|
if DetailsDialog.is_open:
|
||||||
|
return
|
||||||
|
|
||||||
DetailsDialog().present(shared.win)
|
DetailsDialog().present(shared.win)
|
||||||
|
|
||||||
def on_import_action(self, *_args: Any) -> None:
|
def on_import_action(self, *_args: Any) -> None:
|
||||||
@@ -352,7 +369,7 @@ class CartridgesApplication(Adw.Application):
|
|||||||
self.on_remove_game_action()
|
self.on_remove_game_action()
|
||||||
|
|
||||||
def search(self, uri: str) -> None:
|
def search(self, uri: str) -> None:
|
||||||
Gio.AppInfo.launch_default_for_uri(f"{uri}{shared.win.active_game.name}")
|
Gio.AppInfo.launch_default_for_uri(f"{uri}{quote(shared.win.active_game.name)}")
|
||||||
|
|
||||||
def on_igdb_search_action(self, *_args: Any) -> None:
|
def on_igdb_search_action(self, *_args: Any) -> None:
|
||||||
self.search("https://www.igdb.com/search?type=1&q=")
|
self.search("https://www.igdb.com/search?type=1&q=")
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ install_subdir('logging', install_dir: moduledir)
|
|||||||
install_subdir('errors', install_dir: moduledir)
|
install_subdir('errors', install_dir: moduledir)
|
||||||
install_data(
|
install_data(
|
||||||
[
|
[
|
||||||
|
'application_delegate.py',
|
||||||
'main.py',
|
'main.py',
|
||||||
'window.py',
|
'window.py',
|
||||||
'preferences.py',
|
'preferences.py',
|
||||||
|
|||||||
@@ -450,6 +450,9 @@ class CartridgesWindow(Adw.ApplicationWindow):
|
|||||||
self.navigation_view.pop_to_page(self.library_page)
|
self.navigation_view.pop_to_page(self.library_page)
|
||||||
|
|
||||||
def on_show_hidden_action(self, *_args: Any) -> None:
|
def on_show_hidden_action(self, *_args: Any) -> None:
|
||||||
|
if self.navigation_view.get_visible_page() == self.hidden_library_page:
|
||||||
|
return
|
||||||
|
|
||||||
self.navigation_view.push(self.hidden_library_page)
|
self.navigation_view.push(self.hidden_library_page)
|
||||||
|
|
||||||
def on_sort_action(self, action: Gio.SimpleAction, state: GLib.Variant) -> None:
|
def on_sort_action(self, action: Gio.SimpleAction, state: GLib.Variant) -> None:
|
||||||
|
|||||||
@@ -54,6 +54,14 @@
|
|||||||
</screenshots>
|
</screenshots>
|
||||||
<content_rating type="oars-1.1" />
|
<content_rating type="oars-1.1" />
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="2.9.1" date="2024-07-11">
|
||||||
|
<description translate="no">
|
||||||
|
<ul>
|
||||||
|
<li>Cartridges now utilizes the menu bar on macOS</li>
|
||||||
|
<li>Various bug fixes</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
<release version="2.9" date="2024-07-10">
|
<release version="2.9" date="2024-07-10">
|
||||||
<description translate="no">
|
<description translate="no">
|
||||||
<ul>
|
<ul>
|
||||||
@@ -62,13 +70,6 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</description>
|
</description>
|
||||||
</release>
|
</release>
|
||||||
<release version="2.8.5" date="2024-05-25">
|
|
||||||
<description translate="no">
|
|
||||||
<ul>
|
|
||||||
<li>Steam runtimes and Proton should stop being imported again</li>
|
|
||||||
</ul>
|
|
||||||
</description>
|
|
||||||
</release>
|
|
||||||
<release version="2.8" date="2024-03-20">
|
<release version="2.8" date="2024-03-20">
|
||||||
<description translate="no">
|
<description translate="no">
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
project(
|
project(
|
||||||
'cartridges',
|
'cartridges',
|
||||||
version: '2.9',
|
version: '2.9.1',
|
||||||
meson_version: '>= 0.59.0',
|
meson_version: '>= 0.59.0',
|
||||||
default_options: [
|
default_options: [
|
||||||
'warning_level=2',
|
'warning_level=2',
|
||||||
|
|||||||
Reference in New Issue
Block a user