Compare commits
4 Commits
b5239e14b6
...
02120b3263
Author | SHA1 | Date | |
---|---|---|---|
02120b3263 | |||
a7ea7bd6d7 | |||
ac261f0761 | |||
4053fa70f4 |
41
Cargo.lock
generated
41
Cargo.lock
generated
@ -140,7 +140,7 @@ version = "4.4.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
|
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck 0.4.1",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.37",
|
"syn 2.0.37",
|
||||||
@ -379,7 +379,7 @@ version = "0.18.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72793962ceece3863c2965d7f10c8786323b17c7adea75a515809fa20ab799a5"
|
checksum = "72793962ceece3863c2965d7f10c8786323b17c7adea75a515809fa20ab799a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck 0.4.1",
|
||||||
"proc-macro-crate 2.0.0",
|
"proc-macro-crate 2.0.0",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@ -528,6 +528,12 @@ version = "0.4.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@ -608,6 +614,7 @@ dependencies = [
|
|||||||
"gtk4",
|
"gtk4",
|
||||||
"log",
|
"log",
|
||||||
"poppler-rs",
|
"poppler-rs",
|
||||||
|
"strum",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -798,6 +805,12 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.19"
|
version = "1.0.19"
|
||||||
@ -854,6 +867,28 @@ version = "0.10.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.26.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
||||||
|
dependencies = [
|
||||||
|
"strum_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.26.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.5.0",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn 2.0.37",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.109"
|
version = "1.0.109"
|
||||||
@ -883,7 +918,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3"
|
checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-expr",
|
"cfg-expr",
|
||||||
"heck",
|
"heck 0.4.1",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
"toml",
|
"toml",
|
||||||
"version-compare",
|
"version-compare",
|
||||||
|
@ -14,3 +14,4 @@ gtk = { version = "0.7.3", package = "gtk4", features = ["v4_8"] }
|
|||||||
anyhow = "1.0.75"
|
anyhow = "1.0.75"
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
env_logger = "0.10.1"
|
env_logger = "0.10.1"
|
||||||
|
strum = { version = "0.26.3", features = ["derive"] }
|
||||||
|
14
de.frajul.music-reader.gschema.xml
Normal file
14
de.frajul.music-reader.gschema.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- GTK settings schema / configuration. Deploy this e.g. to $HOME/.local/share/glib-2.0/schemas -->
|
||||||
|
<schemalist>
|
||||||
|
<schema id="de.frajul.music-reader" path="/de/frajul/music-reader/">
|
||||||
|
<key name="fullscreen" type="b">
|
||||||
|
<default>false</default>
|
||||||
|
<summary>Whether the application is in fullscreen mode</summary>
|
||||||
|
</key>
|
||||||
|
<key name="color-mode" type="s">
|
||||||
|
<default>'Normal'</default>
|
||||||
|
<summary>The color mode used to render the pdf pages</summary>
|
||||||
|
</key>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
11
flake.nix
11
flake.nix
@ -42,6 +42,10 @@
|
|||||||
|
|
||||||
mkdir -p $out/share/icons
|
mkdir -p $out/share/icons
|
||||||
cp ${./music-reader.png} $out/share/icons/music-reader.png
|
cp ${./music-reader.png} $out/share/icons/music-reader.png
|
||||||
|
|
||||||
|
mkdir -p $out/share/glib-2.0/schemas
|
||||||
|
cp ${./de.frajul.music-reader.gschema.xml} $out/share/glib-2.0/schemas/de.frajul.music-reader.gschema.xml
|
||||||
|
glib-compile-schemas $out/share/glib-2.0/schemas/
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
devShell =
|
devShell =
|
||||||
@ -53,6 +57,13 @@
|
|||||||
rustfmt
|
rustfmt
|
||||||
pre-commit
|
pre-commit
|
||||||
rustPackages.clippy
|
rustPackages.clippy
|
||||||
|
|
||||||
|
gtk4
|
||||||
|
cairo
|
||||||
|
glib
|
||||||
|
pkg-config
|
||||||
|
poppler
|
||||||
|
wrapGAppsHook
|
||||||
];
|
];
|
||||||
# Without inheriting nativeBuildinputs, cargo build will fail but that is good since we want to use only nix build
|
# Without inheriting nativeBuildinputs, cargo build will fail but that is good since we want to use only nix build
|
||||||
# inherit nativeBuildInputs;
|
# inherit nativeBuildInputs;
|
||||||
|
@ -1,12 +1,27 @@
|
|||||||
use cairo::ImageSurface;
|
use core::fmt;
|
||||||
|
|
||||||
#[derive(Clone)]
|
use cairo::ImageSurface;
|
||||||
|
use strum::EnumString;
|
||||||
|
|
||||||
|
#[derive(Clone, EnumString, Debug)]
|
||||||
pub enum ColorMode {
|
pub enum ColorMode {
|
||||||
Normal,
|
Normal,
|
||||||
Dark,
|
Dark,
|
||||||
Sepia,
|
Sepia,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ColorMode {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ColorMode {
|
||||||
|
fn default() -> Self {
|
||||||
|
ColorMode::Normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ColorMode {
|
impl ColorMode {
|
||||||
fn transform_color(&self, r: u8, g: u8, b: u8) -> (u8, u8, u8) {
|
fn transform_color(&self, r: u8, g: u8, b: u8) -> (u8, u8, u8) {
|
||||||
// l of black is 0.13 (approx 0x22)
|
// l of black is 0.13 (approx 0x22)
|
||||||
|
@ -5,9 +5,9 @@ mod ui;
|
|||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use env_logger::Env;
|
use env_logger::Env;
|
||||||
|
use gio::Settings;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Application;
|
use gtk::Application;
|
||||||
use log::debug;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -27,7 +27,8 @@ fn main() {
|
|||||||
let app = Application::builder().application_id(APP_ID).build();
|
let app = Application::builder().application_id(APP_ID).build();
|
||||||
|
|
||||||
app.connect_activate(move |app| {
|
app.connect_activate(move |app| {
|
||||||
let ui = build_ui(app);
|
let settings = Settings::new(APP_ID);
|
||||||
|
let ui = build_ui(app, settings);
|
||||||
if let Some(file) = cli.file.as_ref() {
|
if let Some(file) = cli.file.as_ref() {
|
||||||
ui::load_document(file, Rc::clone(&ui), 0);
|
ui::load_document(file, Rc::clone(&ui), 0);
|
||||||
}
|
}
|
||||||
@ -36,6 +37,6 @@ fn main() {
|
|||||||
app.run_with_args(&[] as &[&str]);
|
app.run_with_args(&[] as &[&str]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_ui(app: &Application) -> Rc<RefCell<Ui>> {
|
fn build_ui(app: &Application, settings: Settings) -> Rc<RefCell<Ui>> {
|
||||||
Ui::build(app)
|
Ui::build(app, settings)
|
||||||
}
|
}
|
||||||
|
63
src/ui.rs
63
src/ui.rs
@ -2,9 +2,11 @@ use std::{
|
|||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
str::FromStr,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use gio::Settings;
|
||||||
use gtk::{
|
use gtk::{
|
||||||
glib, Application, ApplicationWindow, Box, Button, FileChooserAction, FileChooserDialog,
|
glib, Application, ApplicationWindow, Box, Button, FileChooserAction, FileChooserDialog,
|
||||||
HeaderBar, Label, Overlay, Picture, ResponseType, ToggleButton,
|
HeaderBar, Label, Overlay, Picture, ResponseType, ToggleButton,
|
||||||
@ -19,6 +21,7 @@ use glib::clone;
|
|||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
|
||||||
pub struct Ui {
|
pub struct Ui {
|
||||||
|
settings: Settings,
|
||||||
window: ApplicationWindow,
|
window: ApplicationWindow,
|
||||||
bottom_bar: gtk::Box,
|
bottom_bar: gtk::Box,
|
||||||
header_bar: gtk::HeaderBar,
|
header_bar: gtk::HeaderBar,
|
||||||
@ -114,22 +117,24 @@ impl DocumentCanvas {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_fullscreen(ui: &Ui) {
|
pub fn set_fullscreen(ui: &Ui, fullscreen: bool) {
|
||||||
match !ui.window.is_fullscreen() {
|
match fullscreen {
|
||||||
true => {
|
true => {
|
||||||
ui.header_bar.hide();
|
ui.header_bar.hide();
|
||||||
ui.bottom_bar.hide();
|
ui.bottom_bar.hide();
|
||||||
ui.window.fullscreen();
|
ui.window.fullscreen();
|
||||||
|
|
||||||
let new_area_height = ui.image_container.height() + ui.header_bar.height();
|
let new_area_height = ui.image_container.height() + ui.header_bar.height();
|
||||||
ui.document_canvas
|
if ui.document_canvas.is_some() {
|
||||||
.as_ref()
|
ui.document_canvas
|
||||||
.unwrap()
|
.as_ref()
|
||||||
.priority_cache_current_pages(new_area_height);
|
.unwrap()
|
||||||
ui.document_canvas
|
.priority_cache_current_pages(new_area_height);
|
||||||
.as_ref()
|
ui.document_canvas
|
||||||
.unwrap()
|
.as_ref()
|
||||||
.cache_surrounding_pages(new_area_height);
|
.unwrap()
|
||||||
|
.cache_surrounding_pages(new_area_height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
false => {
|
false => {
|
||||||
ui.header_bar.show();
|
ui.header_bar.show();
|
||||||
@ -137,6 +142,11 @@ pub fn toggle_fullscreen(ui: &Ui) {
|
|||||||
ui.window.unfullscreen();
|
ui.window.unfullscreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ui.settings.set_boolean("fullscreen", fullscreen).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toggle_fullscreen(ui: &Ui) {
|
||||||
|
set_fullscreen(ui, !ui.window.is_fullscreen());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_page_status(ui: &Ui) {
|
fn update_page_status(ui: &Ui) {
|
||||||
@ -213,10 +223,11 @@ fn process_left_click(ui: &mut Ui, x: f64, y: f64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Ui {
|
impl Ui {
|
||||||
pub fn build(app: &Application) -> Rc<RefCell<Ui>> {
|
pub fn build(app: &Application, settings: Settings) -> Rc<RefCell<Ui>> {
|
||||||
debug!("building ui");
|
debug!("building ui");
|
||||||
let open_file_button = Button::from_icon_name("document-open");
|
let open_file_button = Button::from_icon_name("document-open");
|
||||||
let normal_color_mode_button = ToggleButton::builder().label("Std").active(true).build();
|
let fullscreen_button = Button::from_icon_name("view-fullscreen");
|
||||||
|
let normal_color_mode_button = ToggleButton::builder().label("Std").build();
|
||||||
let dark_color_mode_button = ToggleButton::builder()
|
let dark_color_mode_button = ToggleButton::builder()
|
||||||
.label("Dark")
|
.label("Dark")
|
||||||
.group(&normal_color_mode_button)
|
.group(&normal_color_mode_button)
|
||||||
@ -227,7 +238,7 @@ impl Ui {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
let button_container = Box::builder()
|
let button_container = Box::builder()
|
||||||
.spacing(5)
|
.spacing(10)
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.orientation(gtk::Orientation::Horizontal)
|
.orientation(gtk::Orientation::Horizontal)
|
||||||
.build();
|
.build();
|
||||||
@ -240,6 +251,7 @@ impl Ui {
|
|||||||
color_mode_button_container.append(&dark_color_mode_button);
|
color_mode_button_container.append(&dark_color_mode_button);
|
||||||
color_mode_button_container.append(&sepia_color_mode_button);
|
color_mode_button_container.append(&sepia_color_mode_button);
|
||||||
button_container.append(&open_file_button);
|
button_container.append(&open_file_button);
|
||||||
|
button_container.append(&fullscreen_button);
|
||||||
button_container.append(&color_mode_button_container);
|
button_container.append(&color_mode_button_container);
|
||||||
|
|
||||||
let image_container = Box::builder()
|
let image_container = Box::builder()
|
||||||
@ -281,7 +293,15 @@ impl Ui {
|
|||||||
.build();
|
.build();
|
||||||
window.present();
|
window.present();
|
||||||
|
|
||||||
|
let color_mode = ColorMode::from_str(&settings.string("color-mode")).unwrap_or_default();
|
||||||
|
match color_mode {
|
||||||
|
ColorMode::Normal => normal_color_mode_button.set_active(true),
|
||||||
|
ColorMode::Dark => dark_color_mode_button.set_active(true),
|
||||||
|
ColorMode::Sepia => sepia_color_mode_button.set_active(true),
|
||||||
|
};
|
||||||
|
|
||||||
let ui = Ui {
|
let ui = Ui {
|
||||||
|
settings,
|
||||||
window,
|
window,
|
||||||
app_wrapper,
|
app_wrapper,
|
||||||
bottom_bar: Box::builder()
|
bottom_bar: Box::builder()
|
||||||
@ -295,7 +315,7 @@ impl Ui {
|
|||||||
image_right,
|
image_right,
|
||||||
document_canvas: None,
|
document_canvas: None,
|
||||||
last_touch_time: None,
|
last_touch_time: None,
|
||||||
color_mode: ColorMode::Normal,
|
color_mode,
|
||||||
};
|
};
|
||||||
let ui = Rc::new(RefCell::new(ui));
|
let ui = Rc::new(RefCell::new(ui));
|
||||||
|
|
||||||
@ -327,6 +347,11 @@ impl Ui {
|
|||||||
choose_file(Rc::clone(&ui), &ui.borrow().window);
|
choose_file(Rc::clone(&ui), &ui.borrow().window);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
fullscreen_button.connect_clicked(
|
||||||
|
glib::clone!(@strong ui => @default-panic, move |_button| {
|
||||||
|
toggle_fullscreen(&ui.borrow());
|
||||||
|
}),
|
||||||
|
);
|
||||||
normal_color_mode_button.connect_clicked(
|
normal_color_mode_button.connect_clicked(
|
||||||
glib::clone!(@strong ui => @default-panic, move |_button| {
|
glib::clone!(@strong ui => @default-panic, move |_button| {
|
||||||
switch_color_mode(Rc::clone(&ui), ColorMode::Normal);
|
switch_color_mode(Rc::clone(&ui), ColorMode::Normal);
|
||||||
@ -344,11 +369,21 @@ impl Ui {
|
|||||||
);
|
);
|
||||||
|
|
||||||
ui.borrow().window.present();
|
ui.borrow().window.present();
|
||||||
|
|
||||||
|
if ui.borrow().settings.boolean("fullscreen") {
|
||||||
|
set_fullscreen(&ui.borrow(), true);
|
||||||
|
}
|
||||||
|
|
||||||
ui
|
ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn switch_color_mode(ui: Rc<RefCell<Ui>>, color_mode: ColorMode) {
|
fn switch_color_mode(ui: Rc<RefCell<Ui>>, color_mode: ColorMode) {
|
||||||
|
ui.borrow()
|
||||||
|
.settings
|
||||||
|
.set_string("color-mode", &color_mode.to_string())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
ui.borrow_mut().color_mode = color_mode;
|
ui.borrow_mut().color_mode = color_mode;
|
||||||
|
|
||||||
if ui.borrow().document_canvas.is_none() {
|
if ui.borrow().document_canvas.is_none() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user