feat: intial work
This commit is contained in:
parent
be1d5b0fb3
commit
bac018672a
35 changed files with 3060 additions and 311 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,3 +9,4 @@
|
|||
/.flatpak/
|
||||
/vendor
|
||||
/.vscode
|
||||
/src/config.rs
|
2024
Cargo.lock
generated
Normal file
2024
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
10
Cargo.toml
10
Cargo.toml
|
@ -9,6 +9,14 @@ lto = true
|
|||
|
||||
[dependencies]
|
||||
gettext-rs = { version = "0.7", features = ["gettext-system"] }
|
||||
gtk = { version = "0.7", package = "gtk4", features = ["v4_8"] }
|
||||
gtk = { version = "0.7", package = "gtk4", features = ["v4_10"] }
|
||||
tracing = "0.1.37"
|
||||
tracing-subscriber = "0.3"
|
||||
reqwest = { version = "0.11", features = ["json", "blocking"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
gsettings-macro = "0.1.20"
|
||||
|
||||
[dependencies.adw]
|
||||
package = "libadwaita"
|
||||
version = "0.5"
|
||||
features = ["v1_4"]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "dev.mnts.ModManager.Devel",
|
||||
"runtime": "org.gnome.Platform",
|
||||
"runtime-version": "44",
|
||||
"runtime-version": "45",
|
||||
"sdk": "org.gnome.Sdk",
|
||||
"sdk-extensions": [
|
||||
"org.freedesktop.Sdk.Extension.rust-stable",
|
||||
|
@ -19,9 +19,7 @@
|
|||
],
|
||||
"build-options": {
|
||||
"append-path": "/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm16/bin",
|
||||
"build-args": [
|
||||
"--share=network"
|
||||
],
|
||||
"build-args": ["--share=network"],
|
||||
"env": {
|
||||
"CARGO_REGISTRIES_CRATES_IO_PROTOCOL": "sparse",
|
||||
"CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER": "clang",
|
||||
|
@ -29,19 +27,37 @@
|
|||
"CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER": "clang",
|
||||
"CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS": "-C link-arg=-fuse-ld=/usr/lib/sdk/rust-stable/bin/mold"
|
||||
},
|
||||
"test-args": [
|
||||
"--socket=x11",
|
||||
"--share=network"
|
||||
]
|
||||
"test-args": ["--socket=x11", "--share=network"]
|
||||
},
|
||||
"cleanup": [
|
||||
"/include",
|
||||
"/lib/pkgconfig",
|
||||
"/man",
|
||||
"/share/doc",
|
||||
"/share/gtk-doc",
|
||||
"/share/man",
|
||||
"/share/pkgconfig",
|
||||
"*.la",
|
||||
"*.a"
|
||||
],
|
||||
"modules": [
|
||||
{
|
||||
"name": "blueprint-compiler",
|
||||
"buildsystem": "meson",
|
||||
"cleanup": ["*"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://gitlab.gnome.org/jwestman/blueprint-compiler",
|
||||
"tag": "v0.10.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mod-manager",
|
||||
"buildsystem": "meson",
|
||||
"run-tests": true,
|
||||
"config-opts": [
|
||||
"-Dprofile=development"
|
||||
],
|
||||
"config-opts": ["-Dprofile=development"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "dir",
|
||||
|
@ -51,4 +67,3 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -13,5 +13,10 @@
|
|||
<default>false</default>
|
||||
<summary>Window maximized state</summary>
|
||||
</key>
|
||||
<key name="games" type="{ss}">
|
||||
<default>{}</default>
|
||||
<summary>Dictionary of games being managed. First string is game name second is path to mods
|
||||
folder.</summary>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
||||
</schemalist>
|
|
@ -1,8 +1,20 @@
|
|||
# Resources
|
||||
blueprints = custom_target('blueprints',
|
||||
input: files(
|
||||
'ui/windows/main/main.blp',
|
||||
'ui/windows/main/pages/welcome.blp',
|
||||
'ui/windows/main/pages/games_and_mods.blp',
|
||||
'ui/windows/add_new_game/add_new_game.blp',
|
||||
'ui/components/mods_list.blp',
|
||||
),
|
||||
output: '.',
|
||||
command: [find_program('blueprint-compiler'), 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@'],
|
||||
)
|
||||
resources = gnome.compile_resources(
|
||||
'resources',
|
||||
'resources.gresource.xml',
|
||||
gresource_bundle: true,
|
||||
dependencies: blueprints,
|
||||
source_dir: meson.current_build_dir(),
|
||||
install: true,
|
||||
install_dir: pkgdatadir,
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
<gresources>
|
||||
<gresource prefix="/dev/mnts/ModManager/">
|
||||
<!-- see https://gtk-rs.org/gtk4-rs/git/docs/gtk4/struct.Application.html#automatic-resources -->
|
||||
<file compressed="true" preprocess="xml-stripblanks" alias="gtk/help-overlay.ui">ui/shortcuts.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">ui/window.ui</file>
|
||||
<file compressed="true">ui/windows/main/main.ui</file>
|
||||
<file compressed="true">ui/windows/main/pages/welcome.ui</file>
|
||||
<file compressed="true">ui/windows/main/pages/games_and_mods.ui</file>
|
||||
<file compressed="true">ui/windows/add_new_game/add_new_game.ui</file>
|
||||
<file compressed="true">ui/components/mods_list.ui</file>
|
||||
<file compressed="true">style.css</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
.title-header{
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
}
|
135
data/resources/ui/components/mods_list.blp
Normal file
135
data/resources/ui/components/mods_list.blp
Normal file
|
@ -0,0 +1,135 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $ModsList : Adw.NavigationPage {
|
||||
title: _("Main");
|
||||
|
||||
Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar header_bar {
|
||||
show-back-button: true;
|
||||
}
|
||||
|
||||
content: Box {
|
||||
orientation: vertical;
|
||||
valign: center;
|
||||
halign: center;
|
||||
|
||||
Image {
|
||||
name: "logo";
|
||||
icon-name: "re.sonny.Workbench";
|
||||
pixel-size: 196;
|
||||
margin-bottom: 30;
|
||||
|
||||
styles [
|
||||
"icon-dropshadow"
|
||||
]
|
||||
}
|
||||
|
||||
Label {
|
||||
label: _("Welcome to Mod Manager");
|
||||
margin-bottom: 30;
|
||||
|
||||
styles [
|
||||
"title-1"
|
||||
]
|
||||
}
|
||||
|
||||
Box subtitle {
|
||||
orientation: vertical;
|
||||
halign: center;
|
||||
margin-bottom: 30;
|
||||
|
||||
Label {
|
||||
label: "Learn and prototype with\nGNOME technologies";
|
||||
justify: center;
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
orientation: vertical;
|
||||
homogeneous: true;
|
||||
halign: center;
|
||||
|
||||
Box {
|
||||
margin-bottom: 6;
|
||||
|
||||
Image {
|
||||
icon-name: "update-symbolic";
|
||||
margin-end: 12;
|
||||
icon-size: normal;
|
||||
}
|
||||
|
||||
Label {
|
||||
label: _("Edit Style or UI to update the Preview");
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
margin-bottom: 6;
|
||||
|
||||
Image {
|
||||
icon-name: "media-playback-start-symbolic";
|
||||
margin-end: 12;
|
||||
icon-size: normal;
|
||||
}
|
||||
|
||||
Label {
|
||||
label: _("Hit");
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
accelerator: "<Control>Return";
|
||||
margin-start: 12;
|
||||
}
|
||||
|
||||
Label {
|
||||
label: _("to format and run Code");
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
margin-bottom: 6;
|
||||
|
||||
Image {
|
||||
icon-name: "media-floppy-symbolic";
|
||||
margin-end: 12;
|
||||
icon-size: normal;
|
||||
}
|
||||
|
||||
Label {
|
||||
label: _("Changes are automatically saved and restored");
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
margin-bottom: 6;
|
||||
|
||||
Image {
|
||||
icon-name: "library-symbolic";
|
||||
margin-end: 12;
|
||||
icon-size: normal;
|
||||
}
|
||||
|
||||
Label {
|
||||
label: _("Browse the Library for demos and examples");
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
margin-bottom: 6;
|
||||
|
||||
Image {
|
||||
icon-name: "user-bookmarks-symbolic";
|
||||
margin-end: 12;
|
||||
icon-size: normal;
|
||||
}
|
||||
|
||||
Label {
|
||||
label: _("Checkout the Bookmarks menu to learn and get help");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkShortcutsWindow" id="help_overlay">
|
||||
<property name="modal">True</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsSection">
|
||||
<property name="section-name">shortcuts</property>
|
||||
<property name="max-height">10</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="title" translatable="yes" context="shortcut window">General</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes" context="shortcut window">Show Shortcuts</property>
|
||||
<property name="action-name">win.show-help-overlay</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="title" translatable="yes" context="shortcut window">Quit</property>
|
||||
<property name="action-name">app.quit</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -1,41 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<menu id="primary_menu">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Preferences</attribute>
|
||||
<attribute name="action">app.preferences</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
|
||||
<attribute name="action">win.show-help-overlay</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_About Mod Manager</attribute>
|
||||
<attribute name="action">app.about</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
<template class="ExampleApplicationWindow" parent="GtkApplicationWindow">
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="headerbar">
|
||||
<child type="end">
|
||||
<object class="GtkMenuButton" id="appmenu_button">
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
<property name="menu-model">primary_menu</property>
|
||||
<property name="primary">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Main Menu</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label">
|
||||
<property name="label" translatable="yes">Hello world!</property>
|
||||
<style>
|
||||
<class name="title-header"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
46
data/resources/ui/windows/add_new_game/add_new_game.blp
Normal file
46
data/resources/ui/windows/add_new_game/add_new_game.blp
Normal file
|
@ -0,0 +1,46 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $ModManagerWindowAddNewGame : Adw.ApplicationWindow {
|
||||
default-width: 600;
|
||||
default-height: 400;
|
||||
title: _("Add a new game");
|
||||
|
||||
content: Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar header_bar {
|
||||
show-back-button: true;
|
||||
}
|
||||
|
||||
content: Box {
|
||||
orientation: vertical;
|
||||
halign: center;
|
||||
valign: center;
|
||||
|
||||
Label {
|
||||
label: _("Chose a game to manage mods for");
|
||||
margin-bottom: 30;
|
||||
justify: center;
|
||||
wrap: true;
|
||||
styles ["title-1"]
|
||||
}
|
||||
|
||||
DropDown games_dropdown {
|
||||
margin-bottom: 30;
|
||||
}
|
||||
|
||||
FileDialog mods_folder {
|
||||
title: _("Chose a location where to install the mods");
|
||||
}
|
||||
|
||||
Button chose_button {
|
||||
label: _("Chose the location");
|
||||
margin-bottom: 30;
|
||||
}
|
||||
|
||||
Button complete_button {
|
||||
label: _("Add game");
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
25
data/resources/ui/windows/main/main.blp
Normal file
25
data/resources/ui/windows/main/main.blp
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Copyright (c) 2023 Tine Jozelj
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $ModManagerWindowMain : Adw.ApplicationWindow {
|
||||
default-width: 1000;
|
||||
default-height: 800;
|
||||
title: _("Mod Manager");
|
||||
}
|
45
data/resources/ui/windows/main/pages/games_and_mods.blp
Normal file
45
data/resources/ui/windows/main/pages/games_and_mods.blp
Normal file
|
@ -0,0 +1,45 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $GamesAndMods: Adw.Bin {
|
||||
Adw.NavigationSplitView {
|
||||
sidebar: Adw.NavigationPage {
|
||||
title: "Games";
|
||||
tag: "sidebar";
|
||||
|
||||
Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
}
|
||||
|
||||
content: Box {
|
||||
Label {
|
||||
label: "The Sims 4";
|
||||
}
|
||||
Label {
|
||||
label: "The Sims 3";
|
||||
}
|
||||
Label {
|
||||
label: "The Sims 2";
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
content: Adw.NavigationPage{
|
||||
title: "Mods";
|
||||
tag: "content";
|
||||
|
||||
Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
}
|
||||
|
||||
content: Box {
|
||||
Label {
|
||||
label: "Mods";
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
28
data/resources/ui/windows/main/pages/welcome.blp
Normal file
28
data/resources/ui/windows/main/pages/welcome.blp
Normal file
|
@ -0,0 +1,28 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $Welcome: Adw.Bin {
|
||||
Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
}
|
||||
|
||||
content: Box {
|
||||
orientation: vertical;
|
||||
halign: center;
|
||||
valign: center;
|
||||
|
||||
Label {
|
||||
label: "No games added yet!";
|
||||
justify: center;
|
||||
wrap: true;
|
||||
styles ["title-1"]
|
||||
margin-bottom: 30;
|
||||
}
|
||||
Button add_new_game {
|
||||
label: "Add new game";
|
||||
styles ["suggested-action", "pill"]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
15
src/api/base.rs
Normal file
15
src/api/base.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
pub const API_URL: &str = "https://api.curseforge.com";
|
||||
|
||||
pub fn get_curse_forge_client() -> Result<reqwest::blocking::Client, reqwest::Error> {
|
||||
let mut api_key_header =
|
||||
reqwest::header::HeaderValue::from_str(crate::config::API_KEY).unwrap();
|
||||
api_key_header.set_sensitive(true);
|
||||
|
||||
let mut headers = reqwest::header::HeaderMap::new();
|
||||
headers.insert("x-api-key", api_key_header);
|
||||
|
||||
reqwest::blocking::Client::builder()
|
||||
.user_agent(format!("dev.mnts.ModManager/{}", crate::config::VERSION))
|
||||
.default_headers(headers)
|
||||
.build()
|
||||
}
|
46
src/api/games.rs
Normal file
46
src/api/games.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
use crate::api::*;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Response {
|
||||
data: Vec<Game>,
|
||||
pagination: Pagination,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Game {
|
||||
id: u32,
|
||||
name: String,
|
||||
slug: String,
|
||||
dateModified: String,
|
||||
assets: Assets,
|
||||
status: u32,
|
||||
apiStatus: u32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Assets {
|
||||
iconUrl: Option<String>,
|
||||
tileUrl: String,
|
||||
coverUrl: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Pagination {
|
||||
index: u32,
|
||||
pageSize: u32,
|
||||
resultCount: u32,
|
||||
totalCount: u32,
|
||||
}
|
||||
|
||||
pub fn get_games() -> Vec<String> {
|
||||
let client = base::get_curse_forge_client().unwrap();
|
||||
let response = client
|
||||
.get(&format!("{}/v1/games", base::API_URL))
|
||||
.send()
|
||||
.unwrap();
|
||||
let json: Response = response.json().unwrap();
|
||||
|
||||
return json.data.iter().map(|game| game.name.clone()).collect();
|
||||
}
|
5
src/api/mod.rs
Normal file
5
src/api/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
mod base;
|
||||
pub use base::*;
|
||||
|
||||
pub mod games;
|
||||
pub use games::*;
|
|
@ -1,54 +1,87 @@
|
|||
use gettextrs::gettext;
|
||||
/* application.rs
|
||||
*
|
||||
* Copyright 2023 Tine
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
use adw::subclass::prelude::*;
|
||||
use gtk::{gdk, prelude::*};
|
||||
use gtk::{gio, glib};
|
||||
use tracing::{debug, info};
|
||||
|
||||
use gtk::prelude::*;
|
||||
use gtk::subclass::prelude::*;
|
||||
use gtk::{gdk, gio, glib};
|
||||
|
||||
use crate::config::{APP_ID, PKGDATADIR, PROFILE, VERSION};
|
||||
use crate::window::ExampleApplicationWindow;
|
||||
use crate::config::VERSION;
|
||||
use crate::config::{APP_ID, PKGDATADIR, PROFILE};
|
||||
use crate::windows::main::ModManagerWindowMain;
|
||||
use crate::windows::main::Welcome;
|
||||
|
||||
mod imp {
|
||||
|
||||
use super::*;
|
||||
use glib::WeakRef;
|
||||
use std::cell::OnceCell;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ExampleApplication {
|
||||
pub window: OnceCell<WeakRef<ExampleApplicationWindow>>,
|
||||
}
|
||||
pub struct ModManagerApplication {}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for ExampleApplication {
|
||||
const NAME: &'static str = "ExampleApplication";
|
||||
type Type = super::ExampleApplication;
|
||||
type ParentType = gtk::Application;
|
||||
impl ObjectSubclass for ModManagerApplication {
|
||||
const NAME: &'static str = "ModManagerApplication";
|
||||
type Type = super::ModManagerApplication;
|
||||
type ParentType = adw::Application;
|
||||
}
|
||||
|
||||
impl ObjectImpl for ExampleApplication {}
|
||||
impl ObjectImpl for ModManagerApplication {
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
let obj = self.obj();
|
||||
obj.set_accels_for_action("app.quit", &["<primary>q"]);
|
||||
|
||||
impl ApplicationImpl for ExampleApplication {
|
||||
//let settings = ModManagerSettings::default();
|
||||
// let games = settings.games();
|
||||
|
||||
//let settings = gio::Settings::new(APP_ID);
|
||||
//let games = settings.string("games");
|
||||
|
||||
//println!("Games: {:?}", games);
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplicationImpl for ModManagerApplication {
|
||||
// We connect to the activate callback to create a window when the application
|
||||
// has been launched. Additionally, this callback notifies us when the user
|
||||
// tries to launch a "second instance" of the application. When they try
|
||||
// to do that, we'll just present any existing window.
|
||||
fn activate(&self) {
|
||||
debug!("GtkApplication<ExampleApplication>::activate");
|
||||
self.parent_activate();
|
||||
let app = self.obj();
|
||||
debug!("GtkApplication<ModManager>::activate");
|
||||
let application = self.obj();
|
||||
// Get the current window or create one if necessary
|
||||
let window = if let Some(window) = application.active_window() {
|
||||
window
|
||||
} else {
|
||||
// TODO: Figure our if show welcome or games_and_mods.
|
||||
let welcome = Welcome::new();
|
||||
let window = ModManagerWindowMain::new(&*application, &welcome.upcast());
|
||||
window.upcast()
|
||||
};
|
||||
|
||||
if let Some(window) = self.window.get() {
|
||||
let window = window.upgrade().unwrap();
|
||||
window.present();
|
||||
return;
|
||||
}
|
||||
|
||||
let window = ExampleApplicationWindow::new(&app);
|
||||
self.window
|
||||
.set(window.downgrade())
|
||||
.expect("Window already set.");
|
||||
|
||||
app.main_window().present();
|
||||
// Ask the window manager/compositor to present the window
|
||||
window.present();
|
||||
}
|
||||
|
||||
fn startup(&self) {
|
||||
debug!("GtkApplication<ExampleApplication>::startup");
|
||||
debug!("GtkApplication<ModManager>::startup");
|
||||
self.parent_startup();
|
||||
let app = self.obj();
|
||||
|
||||
|
@ -57,47 +90,43 @@ mod imp {
|
|||
|
||||
app.setup_css();
|
||||
app.setup_gactions();
|
||||
app.setup_accels();
|
||||
}
|
||||
}
|
||||
|
||||
impl GtkApplicationImpl for ExampleApplication {}
|
||||
impl GtkApplicationImpl for ModManagerApplication {}
|
||||
impl AdwApplicationImpl for ModManagerApplication {}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct ExampleApplication(ObjectSubclass<imp::ExampleApplication>)
|
||||
@extends gio::Application, gtk::Application,
|
||||
@implements gio::ActionMap, gio::ActionGroup;
|
||||
pub struct ModManagerApplication(ObjectSubclass<imp::ModManagerApplication>)
|
||||
@extends gio::Application, gtk::Application, adw::Application,
|
||||
@implements gio::ActionGroup, gio::ActionMap;
|
||||
}
|
||||
|
||||
impl ExampleApplication {
|
||||
fn main_window(&self) -> ExampleApplicationWindow {
|
||||
self.imp().window.get().unwrap().upgrade().unwrap()
|
||||
impl ModManagerApplication {
|
||||
pub fn new(flags: &gio::ApplicationFlags) -> Self {
|
||||
glib::Object::builder()
|
||||
.property("application-id", APP_ID)
|
||||
.property("flags", flags)
|
||||
.build()
|
||||
}
|
||||
|
||||
pub fn run(&self) -> glib::ExitCode {
|
||||
info!("Mod Manager ({})", APP_ID);
|
||||
info!("Version: {} ({})", VERSION, PROFILE);
|
||||
info!("Datadir: {}", PKGDATADIR);
|
||||
|
||||
ApplicationExtManual::run(self)
|
||||
}
|
||||
|
||||
fn setup_gactions(&self) {
|
||||
// Quit
|
||||
let action_quit = gio::ActionEntry::builder("quit")
|
||||
.activate(move |app: &Self, _, _| {
|
||||
// This is needed to trigger the delete event and saving the window state
|
||||
app.main_window().close();
|
||||
app.quit();
|
||||
})
|
||||
let quit_action = gio::ActionEntry::builder("quit")
|
||||
.activate(move |app: &Self, _, _| app.quit())
|
||||
.build();
|
||||
|
||||
// About
|
||||
let action_about = gio::ActionEntry::builder("about")
|
||||
.activate(|app: &Self, _, _| {
|
||||
app.show_about_dialog();
|
||||
})
|
||||
let about_action = gio::ActionEntry::builder("about")
|
||||
.activate(move |app: &Self, _, _| app.show_about())
|
||||
.build();
|
||||
self.add_action_entries([action_quit, action_about]);
|
||||
}
|
||||
|
||||
// Sets up keyboard shortcuts
|
||||
fn setup_accels(&self) {
|
||||
self.set_accels_for_action("app.quit", &["<Control>q"]);
|
||||
self.set_accels_for_action("window.close", &["<Control>w"]);
|
||||
self.add_action_entries([quit_action, about_action]);
|
||||
}
|
||||
|
||||
fn setup_css(&self) {
|
||||
|
@ -112,38 +141,18 @@ impl ExampleApplication {
|
|||
}
|
||||
}
|
||||
|
||||
fn show_about_dialog(&self) {
|
||||
let dialog = gtk::AboutDialog::builder()
|
||||
.logo_icon_name(APP_ID)
|
||||
// Insert your license of choice here
|
||||
// .license_type(gtk::License::MitX11)
|
||||
// Insert your website here
|
||||
// .website("https://gitlab.gnome.org/bilelmoussaoui/mod-manager/")
|
||||
fn show_about(&self) {
|
||||
let window = self.active_window().unwrap();
|
||||
let about = adw::AboutWindow::builder()
|
||||
.transient_for(&window)
|
||||
.application_name("mod-manager")
|
||||
.application_icon(APP_ID)
|
||||
.developer_name("Tine Jozelj")
|
||||
.version(VERSION)
|
||||
.transient_for(&self.main_window())
|
||||
.translator_credits(gettext("translator-credits"))
|
||||
.modal(true)
|
||||
.authors(vec!["Tine Jozelj"])
|
||||
.artists(vec!["Tine Jozelj"])
|
||||
.developers(vec!["Tine Jozelj <tine@tjo.space>"])
|
||||
.copyright("© 2023 Tine Jozelj and other developers")
|
||||
.build();
|
||||
|
||||
dialog.present();
|
||||
}
|
||||
|
||||
pub fn run(&self) -> glib::ExitCode {
|
||||
info!("Mod Manager ({})", APP_ID);
|
||||
info!("Version: {} ({})", VERSION, PROFILE);
|
||||
info!("Datadir: {}", PKGDATADIR);
|
||||
|
||||
ApplicationExtManual::run(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ExampleApplication {
|
||||
fn default() -> Self {
|
||||
glib::Object::builder()
|
||||
.property("application-id", APP_ID)
|
||||
.property("resource-base-path", "/dev/mnts/ModManager/")
|
||||
.build()
|
||||
about.present();
|
||||
}
|
||||
}
|
||||
|
|
2
src/components/mod.rs
Normal file
2
src/components/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod mods_list;
|
||||
pub use mods_list::*;
|
64
src/components/mods_list.rs
Normal file
64
src/components/mods_list.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* welcome.rs
|
||||
*
|
||||
* Copyright 2023 Tine
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
use adw::subclass::prelude::*;
|
||||
use gtk::{gio, glib};
|
||||
use gtk::{glib::clone, prelude::*};
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default, gtk::CompositeTemplate)]
|
||||
#[template(resource = "/dev/mnts/ModManager/ui/components/mods_list.ui")]
|
||||
pub struct ModsList {}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for ModsList {
|
||||
const NAME: &'static str = "ModsList";
|
||||
type Type = super::ModsList;
|
||||
type ParentType = adw::NavigationPage;
|
||||
|
||||
fn class_init(klass: &mut Self::Class) {
|
||||
klass.bind_template();
|
||||
}
|
||||
|
||||
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
|
||||
obj.init_template();
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for ModsList {
|
||||
fn constructed(&self) {}
|
||||
}
|
||||
impl WidgetImpl for ModsList {}
|
||||
impl NavigationPageImpl for ModsList {}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct ModsList(ObjectSubclass<imp::ModsList>)
|
||||
@extends gtk::Widget, gtk::Buildable, adw::NavigationPage,
|
||||
@implements gio::ActionGroup, gio::ActionMap;
|
||||
}
|
||||
|
||||
impl ModsList {
|
||||
pub fn new() -> Self {
|
||||
glib::Object::builder().build()
|
||||
}
|
||||
}
|
|
@ -5,3 +5,5 @@ pub const PKGDATADIR: &str = @PKGDATADIR@;
|
|||
pub const PROFILE: &str = @PROFILE@;
|
||||
pub const RESOURCES_FILE: &str = concat!(@PKGDATADIR@, "/resources.gresource");
|
||||
pub const VERSION: &str = @VERSION@;
|
||||
|
||||
pub const API_KEY: &str = @API_KEY@;
|
48
src/main.rs
48
src/main.rs
|
@ -1,32 +1,56 @@
|
|||
mod config {
|
||||
#![allow(dead_code)]
|
||||
/*
|
||||
Copyright (c) 2023 Tine Jozelj
|
||||
|
||||
include!(concat!(env!("CODEGEN_BUILD_DIR"), "/config.rs"));
|
||||
}
|
||||
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/>.
|
||||
*/
|
||||
|
||||
mod api;
|
||||
mod application;
|
||||
mod window;
|
||||
mod components;
|
||||
mod config;
|
||||
mod windows;
|
||||
|
||||
use self::application::ModManagerApplication;
|
||||
|
||||
use config::{GETTEXT_PACKAGE, LOCALEDIR, RESOURCES_FILE};
|
||||
use gettextrs::{gettext, LocaleCategory};
|
||||
use gtk::prelude::*;
|
||||
use gtk::{gio, glib};
|
||||
|
||||
use self::application::ExampleApplication;
|
||||
use self::config::{GETTEXT_PACKAGE, LOCALEDIR, RESOURCES_FILE};
|
||||
|
||||
fn main() -> glib::ExitCode {
|
||||
// Initialize logger
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
// Prepare i18n
|
||||
// Set up gettext translations
|
||||
gettextrs::setlocale(LocaleCategory::LcAll, "");
|
||||
gettextrs::bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR).expect("Unable to bind the text domain");
|
||||
gettextrs::textdomain(GETTEXT_PACKAGE).expect("Unable to switch to the text domain");
|
||||
|
||||
glib::set_application_name(&gettext("Mod Manager"));
|
||||
|
||||
let res = gio::Resource::load(RESOURCES_FILE).expect("Could not load gresource file");
|
||||
gio::resources_register(&res);
|
||||
// Load resources
|
||||
let resources = gio::Resource::load(RESOURCES_FILE).expect("Could not load resources");
|
||||
gio::resources_register(&resources);
|
||||
|
||||
let app = ExampleApplication::default();
|
||||
// Create a new GtkApplication. The application manages our main loop,
|
||||
// application windows, integration with the window manager/compositor, and
|
||||
// desktop features such as file opening and single-instance applications.
|
||||
let app = ModManagerApplication::new(&gio::ApplicationFlags::empty());
|
||||
|
||||
// Run the application. This function will block until the application
|
||||
// exits. Upon return, we have our exit code to return to the shell. (This
|
||||
// is the code you see when you do `echo $?` after running a command in a
|
||||
// terminal.
|
||||
app.run()
|
||||
}
|
||||
|
|
|
@ -5,12 +5,21 @@ global_conf.set_quoted('PROFILE', profile)
|
|||
global_conf.set_quoted('VERSION', version + version_suffix)
|
||||
global_conf.set_quoted('GETTEXT_PACKAGE', gettext_package)
|
||||
global_conf.set_quoted('LOCALEDIR', localedir)
|
||||
global_conf.set_quoted('API_KEY', '$2a$10$AtaQ/fkWxMoVHVhO.6PMoOHQq7ERdSdpmegqJ09.2Mgj5iTQP3r.2')
|
||||
config = configure_file(
|
||||
input: 'config.rs.in',
|
||||
output: 'config.rs',
|
||||
configuration: global_conf
|
||||
)
|
||||
|
||||
# Copy the config.rs output to the source directory.
|
||||
run_command(
|
||||
'cp',
|
||||
meson.project_build_root() / 'src' / 'config.rs',
|
||||
meson.project_source_root() / 'src' / 'config.rs',
|
||||
check: true
|
||||
)
|
||||
|
||||
cargo_options = [ '--manifest-path', meson.project_source_root() / 'Cargo.toml' ]
|
||||
cargo_options += [ '--target-dir', meson.project_build_root() / 'src' ]
|
||||
|
||||
|
|
66
src/mods_list.rs
Normal file
66
src/mods_list.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* welcome.rs
|
||||
*
|
||||
* Copyright 2023 Tine
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
use adw::subclass::prelude::*;
|
||||
use gtk::{gio, glib};
|
||||
use gtk::{glib::clone, prelude::*};
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default, gtk::CompositeTemplate)]
|
||||
#[template(resource = "/dev/mnts/ModManager/components/mods_list.ui")]
|
||||
pub struct ModsList {
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for ModsList {
|
||||
const NAME: &'static str = "ModsList";
|
||||
type Type = super::ModsList;
|
||||
type ParentType = adw::NavigationPage;
|
||||
|
||||
fn class_init(klass: &mut Self::Class) {
|
||||
klass.bind_template();
|
||||
}
|
||||
|
||||
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
|
||||
obj.init_template();
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for ModsList {
|
||||
fn constructed(&self) {
|
||||
}
|
||||
}
|
||||
impl WidgetImpl for ModsList {}
|
||||
impl NavigationPageImpl for ModsList {}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct ModsList(ObjectSubclass<imp::ModsList>)
|
||||
@extends gtk::Widget, gtk::Buildable, adw::NavigationPage,
|
||||
@implements gio::ActionGroup, gio::ActionMap;
|
||||
}
|
||||
|
||||
impl ModsList {
|
||||
pub fn new() -> Self {
|
||||
glib::Object::builder().build()
|
||||
}
|
||||
}
|
20
src/settings.rs
Normal file
20
src/settings.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
use gio::glib;
|
||||
use gsettings_macro::gen_settings;
|
||||
use gtk::gio;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::config::APP_ID;
|
||||
|
||||
#[gen_settings(file = "./data/dev.mnts.ModManager.gschema.xml.in")]
|
||||
#[gen_settings_define(
|
||||
key_name = "games",
|
||||
arg_type = "HashMap<String, String>",
|
||||
ret_type = "HashMap<String, String>"
|
||||
)]
|
||||
pub struct ModManagerSettings;
|
||||
|
||||
impl Default for ModManagerSettings {
|
||||
fn default() -> Self {
|
||||
Self::new(APP_ID)
|
||||
}
|
||||
}
|
117
src/window.rs
117
src/window.rs
|
@ -1,117 +0,0 @@
|
|||
use gtk::prelude::*;
|
||||
use gtk::subclass::prelude::*;
|
||||
use gtk::{gio, glib};
|
||||
|
||||
use crate::application::ExampleApplication;
|
||||
use crate::config::{APP_ID, PROFILE};
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, gtk::CompositeTemplate)]
|
||||
#[template(resource = "/dev/mnts/ModManager/ui/window.ui")]
|
||||
pub struct ExampleApplicationWindow {
|
||||
#[template_child]
|
||||
pub headerbar: TemplateChild<gtk::HeaderBar>,
|
||||
pub settings: gio::Settings,
|
||||
}
|
||||
|
||||
impl Default for ExampleApplicationWindow {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
headerbar: TemplateChild::default(),
|
||||
settings: gio::Settings::new(APP_ID),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for ExampleApplicationWindow {
|
||||
const NAME: &'static str = "ExampleApplicationWindow";
|
||||
type Type = super::ExampleApplicationWindow;
|
||||
type ParentType = gtk::ApplicationWindow;
|
||||
|
||||
fn class_init(klass: &mut Self::Class) {
|
||||
klass.bind_template();
|
||||
}
|
||||
|
||||
// You must call `Widget`'s `init_template()` within `instance_init()`.
|
||||
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
|
||||
obj.init_template();
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for ExampleApplicationWindow {
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
let obj = self.obj();
|
||||
|
||||
// Devel Profile
|
||||
if PROFILE == "Devel" {
|
||||
obj.add_css_class("devel");
|
||||
}
|
||||
|
||||
// Load latest window state
|
||||
obj.load_window_size();
|
||||
}
|
||||
|
||||
fn dispose(&self) {
|
||||
self.dispose_template();
|
||||
}
|
||||
}
|
||||
|
||||
impl WidgetImpl for ExampleApplicationWindow {}
|
||||
impl WindowImpl for ExampleApplicationWindow {
|
||||
// Save window state on delete event
|
||||
fn close_request(&self) -> glib::Propagation {
|
||||
if let Err(err) = self.obj().save_window_size() {
|
||||
tracing::warn!("Failed to save window state, {}", &err);
|
||||
}
|
||||
|
||||
// Pass close request on to the parent
|
||||
self.parent_close_request()
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplicationWindowImpl for ExampleApplicationWindow {}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct ExampleApplicationWindow(ObjectSubclass<imp::ExampleApplicationWindow>)
|
||||
@extends gtk::Widget, gtk::Window, gtk::ApplicationWindow,
|
||||
@implements gio::ActionMap, gio::ActionGroup, gtk::Root;
|
||||
}
|
||||
|
||||
impl ExampleApplicationWindow {
|
||||
pub fn new(app: &ExampleApplication) -> Self {
|
||||
glib::Object::builder().property("application", app).build()
|
||||
}
|
||||
|
||||
fn save_window_size(&self) -> Result<(), glib::BoolError> {
|
||||
let imp = self.imp();
|
||||
|
||||
let (width, height) = self.default_size();
|
||||
|
||||
imp.settings.set_int("window-width", width)?;
|
||||
imp.settings.set_int("window-height", height)?;
|
||||
|
||||
imp.settings
|
||||
.set_boolean("is-maximized", self.is_maximized())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_window_size(&self) {
|
||||
let imp = self.imp();
|
||||
|
||||
let width = imp.settings.int("window-width");
|
||||
let height = imp.settings.int("window-height");
|
||||
let is_maximized = imp.settings.boolean("is-maximized");
|
||||
|
||||
self.set_default_size(width, height);
|
||||
|
||||
if is_maximized {
|
||||
self.maximize();
|
||||
}
|
||||
}
|
||||
}
|
96
src/windows/add_new_game/add_new_game.rs
Normal file
96
src/windows/add_new_game/add_new_game.rs
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* welcome.rs
|
||||
*
|
||||
* Copyright 2023 Tine
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
use adw::subclass::prelude::*;
|
||||
use glib::clone;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{gio, glib};
|
||||
|
||||
use crate::api::*;
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default, gtk::CompositeTemplate)]
|
||||
#[template(resource = "/dev/mnts/ModManager/ui/windows/add_new_game/add_new_game.ui")]
|
||||
pub struct ModManagerWindowAddNewGame {
|
||||
#[template_child]
|
||||
pub complete_button: TemplateChild<gtk::Button>,
|
||||
|
||||
#[template_child]
|
||||
pub games_dropdown: TemplateChild<gtk::DropDown>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for ModManagerWindowAddNewGame {
|
||||
const NAME: &'static str = "ModManagerWindowAddNewGame";
|
||||
type Type = super::ModManagerWindowAddNewGame;
|
||||
type ParentType = adw::ApplicationWindow;
|
||||
|
||||
fn class_init(klass: &mut Self::Class) {
|
||||
klass.bind_template();
|
||||
}
|
||||
|
||||
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
|
||||
obj.init_template();
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for ModManagerWindowAddNewGame {}
|
||||
impl WidgetImpl for ModManagerWindowAddNewGame {}
|
||||
impl WindowImpl for ModManagerWindowAddNewGame {}
|
||||
impl ApplicationWindowImpl for ModManagerWindowAddNewGame {}
|
||||
impl AdwApplicationWindowImpl for ModManagerWindowAddNewGame {}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct ModManagerWindowAddNewGame(ObjectSubclass<imp::ModManagerWindowAddNewGame>)
|
||||
@extends gtk::Widget, gtk::Window, gtk::ApplicationWindow, adw::ApplicationWindow,
|
||||
@implements gio::ActionGroup, gio::ActionMap;
|
||||
}
|
||||
|
||||
impl ModManagerWindowAddNewGame {
|
||||
pub fn new() -> Self {
|
||||
glib::Object::builder().build()
|
||||
}
|
||||
|
||||
pub fn setup(&self) {
|
||||
let games = games::get_games();
|
||||
let games_strs: Vec<&str> = games.iter().map(|s| s.as_str()).collect();
|
||||
let games_list = >k::StringList::new(&games_strs);
|
||||
|
||||
let complete_button = &imp::ModManagerWindowAddNewGame::from_obj(self).complete_button;
|
||||
let games_dropdown = &imp::ModManagerWindowAddNewGame::from_obj(self).games_dropdown;
|
||||
|
||||
games_dropdown.set_property("model", games_list);
|
||||
|
||||
let instance = self;
|
||||
|
||||
complete_button.connect_clicked(clone!(@strong instance => move |_| {
|
||||
//let selected_game = games_dropdown.selected_item();
|
||||
|
||||
println!("complete button clicked");
|
||||
|
||||
//if let Some(selected_game) = selected_game {
|
||||
instance.hide()
|
||||
//}
|
||||
}));
|
||||
}
|
||||
}
|
2
src/windows/add_new_game/mod.rs
Normal file
2
src/windows/add_new_game/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod add_new_game;
|
||||
pub use add_new_game::*;
|
82
src/windows/main/main.rs
Normal file
82
src/windows/main/main.rs
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
Copyright (c) 2023 Tine Jozelj
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
use adw::subclass::prelude::*;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{gio, glib};
|
||||
|
||||
use crate::config::PROFILE;
|
||||
|
||||
mod imp {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default, gtk::CompositeTemplate)]
|
||||
#[template(resource = "/dev/mnts/ModManager/ui/windows/main/main.ui")]
|
||||
pub struct ModManagerWindowMain {}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for ModManagerWindowMain {
|
||||
const NAME: &'static str = "ModManagerWindowMain";
|
||||
type Type = super::ModManagerWindowMain;
|
||||
type ParentType = adw::ApplicationWindow;
|
||||
|
||||
fn class_init(klass: &mut Self::Class) {
|
||||
klass.bind_template();
|
||||
}
|
||||
|
||||
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
|
||||
obj.init_template();
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for ModManagerWindowMain {
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
let obj = self.obj();
|
||||
|
||||
// Devel Profile
|
||||
if PROFILE == "Devel" {
|
||||
obj.add_css_class("devel");
|
||||
}
|
||||
}
|
||||
|
||||
fn dispose(&self) {
|
||||
self.dispose_template();
|
||||
}
|
||||
}
|
||||
|
||||
impl WidgetImpl for ModManagerWindowMain {}
|
||||
impl WindowImpl for ModManagerWindowMain {}
|
||||
impl ApplicationWindowImpl for ModManagerWindowMain {}
|
||||
impl AdwApplicationWindowImpl for ModManagerWindowMain {}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct ModManagerWindowMain(ObjectSubclass<imp::ModManagerWindowMain>)
|
||||
@extends gtk::Widget, gtk::Window, gtk::ApplicationWindow, adw::ApplicationWindow,
|
||||
@implements gio::ActionGroup, gio::ActionMap;
|
||||
}
|
||||
|
||||
impl ModManagerWindowMain {
|
||||
pub fn new<P: glib::IsA<gtk::Application>>(application: &P, content: >k::Widget) -> Self {
|
||||
glib::Object::builder()
|
||||
.property("application", application)
|
||||
.property("content", content)
|
||||
.build()
|
||||
}
|
||||
}
|
5
src/windows/main/mod.rs
Normal file
5
src/windows/main/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
pub mod main;
|
||||
pub use main::*;
|
||||
|
||||
pub mod pages;
|
||||
pub use pages::*;
|
60
src/windows/main/pages/games_and_mods.rs
Normal file
60
src/windows/main/pages/games_and_mods.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
Copyright (c) 2023 Tine Jozelj
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
use adw::subclass::prelude::*;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{gio, glib};
|
||||
|
||||
mod imp {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default, gtk::CompositeTemplate)]
|
||||
#[template(resource = "/dev/mnts/ModManager/ui/windows/main/pages/games_and_mods.ui")]
|
||||
pub struct GamesAndMods {}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for GamesAndMods {
|
||||
const NAME: &'static str = "GamesAndMods";
|
||||
type Type = super::GamesAndMods;
|
||||
type ParentType = adw::Bin;
|
||||
|
||||
fn class_init(klass: &mut Self::Class) {
|
||||
klass.bind_template();
|
||||
}
|
||||
|
||||
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
|
||||
obj.init_template();
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for GamesAndMods {}
|
||||
impl WidgetImpl for GamesAndMods {}
|
||||
impl BinImpl for GamesAndMods {}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct GamesAndMods(ObjectSubclass<imp::GamesAndMods>)
|
||||
@extends gtk::Widget, adw::NavigationSplitView,
|
||||
@implements gio::ActionGroup, gio::ActionMap;
|
||||
}
|
||||
|
||||
impl GamesAndMods {
|
||||
pub fn new() -> Self {
|
||||
glib::Object::builder().build()
|
||||
}
|
||||
}
|
5
src/windows/main/pages/mod.rs
Normal file
5
src/windows/main/pages/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
pub mod games_and_mods;
|
||||
pub use games_and_mods::*;
|
||||
|
||||
pub mod welcome;
|
||||
pub use welcome::*;
|
76
src/windows/main/pages/welcome.rs
Normal file
76
src/windows/main/pages/welcome.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
Copyright (c) 2023 Tine Jozelj
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
use adw::subclass::prelude::*;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{gio, glib};
|
||||
|
||||
use crate::windows::ModManagerWindowAddNewGame;
|
||||
|
||||
mod imp {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default, gtk::CompositeTemplate)]
|
||||
#[template(resource = "/dev/mnts/ModManager/ui/windows/main/pages/welcome.ui")]
|
||||
pub struct Welcome {
|
||||
#[template_child]
|
||||
pub add_new_game: gtk::TemplateChild<gtk::Button>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for Welcome {
|
||||
const NAME: &'static str = "Welcome";
|
||||
type Type = super::Welcome;
|
||||
type ParentType = adw::Bin;
|
||||
|
||||
fn class_init(klass: &mut Self::Class) {
|
||||
klass.bind_template();
|
||||
}
|
||||
|
||||
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
|
||||
obj.init_template();
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for Welcome {
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
|
||||
self.add_new_game.connect_clicked(|_| {
|
||||
let welcome = ModManagerWindowAddNewGame::new();
|
||||
welcome.setup();
|
||||
welcome.set_modal(true);
|
||||
welcome.present();
|
||||
});
|
||||
}
|
||||
}
|
||||
impl WidgetImpl for Welcome {}
|
||||
impl BinImpl for Welcome {}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct Welcome(ObjectSubclass<imp::Welcome>)
|
||||
@extends gtk::Widget, adw::ToolbarView,
|
||||
@implements gio::ActionGroup, gio::ActionMap;
|
||||
}
|
||||
|
||||
impl Welcome {
|
||||
pub fn new() -> Self {
|
||||
glib::Object::builder().build()
|
||||
}
|
||||
}
|
5
src/windows/mod.rs
Normal file
5
src/windows/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
pub mod main;
|
||||
pub use main::*;
|
||||
|
||||
pub mod add_new_game;
|
||||
pub use add_new_game::*;
|
Loading…
Reference in a new issue