image: Refresh file info after file rename
This commit is contained in:
parent
c0f435386d
commit
2fdfe5657c
5 changed files with 109 additions and 35 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
// Copyright (c) 2020-2022 Christopher Davis
|
// Copyright (c) 2020-2022 Christopher Davis
|
||||||
// Copyright (c) 2022-2023 Sophie Herold
|
// Copyright (c) 2023 Sophie Herold
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,20 @@
|
||||||
|
// Copyright (c) 2023 Sophie Herold
|
||||||
|
//
|
||||||
|
// 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 crate::deps::*;
|
use crate::deps::*;
|
||||||
|
|
||||||
pub struct FileInfo {
|
pub struct FileInfo {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,20 @@
|
||||||
|
// Copyright (c) 2023 Sophie Herold
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ImageFormat {
|
pub struct ImageFormat {
|
||||||
mime_type: glycin::MimeType,
|
mime_type: glycin::MimeType,
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ mod imp {
|
||||||
#[derive(Debug, Default, Properties)]
|
#[derive(Debug, Default, Properties)]
|
||||||
#[properties(wrapper_type = super::LpImage)]
|
#[properties(wrapper_type = super::LpImage)]
|
||||||
pub struct LpImage {
|
pub struct LpImage {
|
||||||
#[property(get, set = LpImage::set_file, explicit_notify)]
|
#[property(get, explicit_notify)]
|
||||||
pub(super) file: RefCell<Option<gio::File>>,
|
pub(super) file: RefCell<Option<gio::File>>,
|
||||||
#[property(get)]
|
#[property(get)]
|
||||||
pub(super) is_deleted: Cell<bool>,
|
pub(super) is_deleted: Cell<bool>,
|
||||||
|
|
@ -520,28 +520,6 @@ mod imp {
|
||||||
zoom_gesture.group_with(&rotation_gesture);
|
zoom_gesture.group_with(&rotation_gesture);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_file(&self, file: &gio::File) {
|
|
||||||
let obj = self.obj();
|
|
||||||
|
|
||||||
if obj.file().map_or(false, |x| file.equal(&x)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.file.replace(Some(file.clone()));
|
|
||||||
|
|
||||||
let monitor =
|
|
||||||
file.monitor_file(gio::FileMonitorFlags::WATCH_MOVES, gio::Cancellable::NONE);
|
|
||||||
if let Ok(m) = &monitor {
|
|
||||||
m.connect_changed(glib::clone!(@weak obj => move |_, file_a, file_b, event| {
|
|
||||||
obj.file_changed(event, file_a, file_b);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.file_monitor.replace(monitor.ok());
|
|
||||||
|
|
||||||
obj.notify_file();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_mirrored(&self, mirrored: bool) {
|
fn set_mirrored(&self, mirrored: bool) {
|
||||||
let obj = self.obj();
|
let obj = self.obj();
|
||||||
|
|
||||||
|
|
@ -813,20 +791,17 @@ glib::wrapper! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LpImage {
|
impl LpImage {
|
||||||
|
pub fn init(&self, file: &gio::File) {
|
||||||
|
self.imp().file.replace(Some(file.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn load(&self, file: &gio::File) {
|
pub async fn load(&self, file: &gio::File) {
|
||||||
let imp = self.imp();
|
let imp = self.imp();
|
||||||
log::debug!("Loading file {}", file.uri());
|
log::debug!("Loading file {}", file.uri());
|
||||||
|
|
||||||
self.set_file(file);
|
|
||||||
imp.metadata.replace(Metadata::default());
|
imp.metadata.replace(Metadata::default());
|
||||||
self.emmit_metadata_changed();
|
self.emmit_metadata_changed();
|
||||||
|
self.set_file_loaded(file).await;
|
||||||
let file_info = metadata::FileInfo::new(file).await;
|
|
||||||
match file_info {
|
|
||||||
Ok(file_info) => imp.metadata.borrow_mut().set_file_info(file_info),
|
|
||||||
Err(err) => log::warn!("Failed to load file information: {err}"),
|
|
||||||
}
|
|
||||||
self.emmit_metadata_changed();
|
|
||||||
|
|
||||||
let tiles = &self.imp().frame_buffer;
|
let tiles = &self.imp().frame_buffer;
|
||||||
// Delete all stored textures for reloads
|
// Delete all stored textures for reloads
|
||||||
|
|
@ -850,6 +825,68 @@ impl LpImage {
|
||||||
imp.decoder.replace(Some(Arc::new(decoder)));
|
imp.decoder.replace(Some(Arc::new(decoder)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set filename when (re)loading image
|
||||||
|
async fn set_file_loaded(&self, file: &gio::File) {
|
||||||
|
let imp = self.imp();
|
||||||
|
|
||||||
|
// Do not check if same file since it might be set via initialized with `Self::init` before
|
||||||
|
imp.file.replace(Some(file.clone()));
|
||||||
|
self.reload_file_info().await;
|
||||||
|
self.setup_file_monitor().await;
|
||||||
|
|
||||||
|
self.notify_file();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set filename after filename changed
|
||||||
|
async fn set_file_changed(&self, file: &gio::File) {
|
||||||
|
let imp = self.imp();
|
||||||
|
let prev_mime_type = self.metadata().mime_type();
|
||||||
|
|
||||||
|
imp.file.replace(Some(file.clone()));
|
||||||
|
self.reload_file_info().await;
|
||||||
|
|
||||||
|
// Reload if mime type changed since other decoding path might be responsible now
|
||||||
|
if self.metadata().mime_type() != prev_mime_type {
|
||||||
|
self.load(file).await;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setup_file_monitor().await;
|
||||||
|
|
||||||
|
self.notify_file();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn reload_file_info(&self) {
|
||||||
|
let imp = self.imp();
|
||||||
|
|
||||||
|
if let Some(file) = self.file() {
|
||||||
|
let file_info = metadata::FileInfo::new(&file).await;
|
||||||
|
match file_info {
|
||||||
|
Ok(file_info) => imp.metadata.borrow_mut().set_file_info(file_info),
|
||||||
|
Err(err) => log::warn!("Failed to load file information: {err}"),
|
||||||
|
}
|
||||||
|
self.emmit_metadata_changed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn setup_file_monitor(&self) {
|
||||||
|
let imp = self.imp();
|
||||||
|
|
||||||
|
if let Some(file) = self.file() {
|
||||||
|
let monitor =
|
||||||
|
file.monitor_file(gio::FileMonitorFlags::WATCH_MOVES, gio::Cancellable::NONE);
|
||||||
|
if let Ok(m) = &monitor {
|
||||||
|
m.connect_changed(
|
||||||
|
glib::clone!(@weak self as obj => move |_, file_a, file_b, event| {
|
||||||
|
obj.file_changed(event, file_a, file_b);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
imp.file_monitor.replace(monitor.ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Called when decoder sends update
|
/// Called when decoder sends update
|
||||||
pub fn update(&self, update: DecoderUpdate) {
|
pub fn update(&self, update: DecoderUpdate) {
|
||||||
let imp = self.imp();
|
let imp = self.imp();
|
||||||
|
|
@ -991,14 +1028,17 @@ impl LpImage {
|
||||||
log::debug!("Moved to {}", file.uri());
|
log::debug!("Moved to {}", file.uri());
|
||||||
// current file got replaced with a new one
|
// current file got replaced with a new one
|
||||||
let file_replace = self.file().map_or(false, |x| x.equal(&file));
|
let file_replace = self.file().map_or(false, |x| x.equal(&file));
|
||||||
self.set_file(&file);
|
let obj = self.clone();
|
||||||
if file_replace {
|
if file_replace {
|
||||||
log::debug!("Image got replaced {}", file.uri());
|
log::debug!("Image got replaced {}", file.uri());
|
||||||
let obj = self.clone();
|
|
||||||
// TODO: error handling is missing
|
// TODO: error handling is missing
|
||||||
glib::spawn_future_local(async move {
|
glib::spawn_future_local(async move {
|
||||||
obj.load(&file).await;
|
obj.load(&file).await;
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
glib::spawn_future_local(async move {
|
||||||
|
obj.set_file_changed(&file).await;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ impl LpImagePage {
|
||||||
pub fn from_file(file: &gio::File) -> Self {
|
pub fn from_file(file: &gio::File) -> Self {
|
||||||
let obj = glib::Object::new::<Self>();
|
let obj = glib::Object::new::<Self>();
|
||||||
|
|
||||||
obj.imp().image.set_file(file);
|
obj.imp().image.init(file);
|
||||||
|
|
||||||
glib::spawn_future_local(clone!(@weak obj, @strong file => async move {
|
glib::spawn_future_local(clone!(@weak obj, @strong file => async move {
|
||||||
let imp = obj.imp();
|
let imp = obj.imp();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue