Commit 43ea0fe5 authored by Bilal Elmoussaoui's avatar Bilal Elmoussaoui

reduce IO operations

store the Handle on the project itself
instead of re-reading the file each time
parent 96ce0056
Pipeline #201043 passed with stage
in 15 minutes and 27 seconds
......@@ -11,7 +11,7 @@ use crate::config;
use crate::widgets::Window;
pub enum Action {
OpenProject(Project),
OpenProject(Rc<Project>),
NewProject(gio::File),
}
......
......@@ -38,11 +38,8 @@ pub fn create_tmp(filename: &str) -> anyhow::Result<PathBuf> {
Ok(temp_path)
}
pub fn render(file: &gio::File, output_size: f64, dest: Option<PathBuf>) -> anyhow::Result<(gio::File, cairo::SvgSurface)> {
let stream = file.read(gio::NONE_CANCELLABLE)?.upcast::<gio::InputStream>();
let handle = Handle::from_stream(&LoadOptions::new(None), &stream, gio::NONE_CANCELLABLE)?;
let dest = dest.unwrap_or(create_tmp(&format!("#hicolor-{}-{}", output_size, file.get_basename().unwrap().to_str().unwrap()))?);
pub fn render(handle: &Handle, basename: &str, output_size: f64, dest: Option<PathBuf>) -> anyhow::Result<(gio::File, cairo::SvgSurface)> {
let dest = dest.unwrap_or(create_tmp(&format!("#hicolor-{}-{}", output_size, basename))?);
let mut surface = cairo::SvgSurface::new(output_size, output_size, Some(dest.clone())).unwrap();
surface.set_document_unit(cairo::SvgUnit::Px);
......@@ -64,13 +61,9 @@ pub fn render(file: &gio::File, output_size: f64, dest: Option<PathBuf>) -> anyh
Ok((gio::File::new_for_path(dest), surface))
}
pub fn render_by_id(file: &gio::File, id: &str, output_size: f64, dest: Option<PathBuf>) -> anyhow::Result<(gio::File, cairo::SvgSurface)> {
let stream = file.read(gio::NONE_CANCELLABLE)?.upcast::<gio::InputStream>();
let mut handle = Handle::from_stream(&LoadOptions::new(None), &stream, gio::NONE_CANCELLABLE)?;
let dest = dest.unwrap_or(create_tmp(&format!("{}-{}-{}", id, output_size, file.get_basename().unwrap().to_str().unwrap()))?);
pub fn render_by_id(handle: &Handle, basename: &str, id: &str, output_size: f64, dest: Option<PathBuf>) -> anyhow::Result<(gio::File, cairo::SvgSurface)> {
let dest = dest.unwrap_or(create_tmp(&format!("{}-{}-{}", id, output_size, basename))?);
handle.set_stylesheet("#layer3,#layer2 {visibility: hidden}")?;
if handle.has_sub(id)? {
let viewport = {
let doc = handle.get_dimensions(Dpi::default(), &SizeCallback::default(), false)?;
......
use super::common;
use anyhow::anyhow;
use gettextrs::gettext;
use gio::prelude::FileExt;
use gtk::prelude::*;
use librsvg::{CairoRenderer, Loader};
use rsvg_internals::{Dpi, Handle, LoadOptions, SizeCallback};
use std::rc::Rc;
#[derive(PartialEq, Debug, Clone)]
pub enum ProjectType {
......@@ -11,14 +11,14 @@ pub enum ProjectType {
Preview, // A 128px SVG found
}
#[derive(Debug, Clone)]
pub struct Project {
pub file: gio::File,
pub project_type: ProjectType,
handle: Handle,
}
impl Project {
pub fn from_template(dest: gio::File) -> anyhow::Result<Self> {
pub fn from_template(dest: gio::File) -> anyhow::Result<Rc<Self>> {
let template = gio::File::new_for_uri("resource://org/gnome/design/AppIconPreview/templates/empty_project.svg");
// Creates the parent directory tree if it does not already exist
dest.get_parent().map(|parent| parent.make_directory_with_parents(gio::NONE_CANCELLABLE));
......@@ -27,27 +27,30 @@ impl Project {
Project::parse(dest)
}
pub fn parse(file: gio::File) -> anyhow::Result<Self> {
let path = file.get_path().ok_or_else(|| anyhow!("Failed to get the path"))?;
pub fn parse(file: gio::File) -> anyhow::Result<Rc<Self>> {
let stream = file.read(gio::NONE_CANCELLABLE)?.upcast::<gio::InputStream>();
let mut handle = Handle::from_stream(&LoadOptions::new(None), &stream, gio::NONE_CANCELLABLE)?;
handle.set_stylesheet("#layer3,#layer2 {visibility: hidden}")?;
let handle = Loader::new().read_path(&path)?;
let renderer = CairoRenderer::new(&handle);
let dimensions = renderer.intrinsic_dimensions();
let width = dimensions.width.unwrap().length;
let height = dimensions.height.unwrap().length;
let dimensions = handle.get_dimensions(Dpi::default(), &SizeCallback::default(), false)?;
let width = dimensions.width as f64;
let height = dimensions.height as f64;
if (width - 128.0).abs() < std::f64::EPSILON && (height - 128.0).abs() < std::f64::EPSILON {
return Ok(Self {
return Ok(Rc::new(Self {
project_type: ProjectType::Preview,
file,
});
handle,
}));
}
if handle.has_element_with_id("#hicolor")? && handle.has_element_with_id("#symbolic")? {
return Ok(Self {
if handle.has_sub("#hicolor")? && handle.has_sub("#symbolic")? {
return Ok(Rc::new(Self {
file,
project_type: ProjectType::Icon,
});
handle,
}));
}
anyhow::bail!("not found")
}
......@@ -128,8 +131,8 @@ impl Project {
pub fn get_hicolor(&self, dest: Option<std::path::PathBuf>) -> anyhow::Result<(gio::File, cairo::SvgSurface)> {
match self.project_type {
ProjectType::Icon => common::render_by_id(&self.file, "#hicolor", 128.0, dest),
ProjectType::Preview => common::render(&self.file, 128.0, dest),
ProjectType::Icon => common::render_by_id(&self.handle, &self.name(), "#hicolor", 128.0, dest),
ProjectType::Preview => common::render(&self.handle, &self.name(), 128.0, dest),
}
}
......@@ -137,7 +140,7 @@ impl Project {
match self.project_type {
ProjectType::Icon => {
let dest = common::create_tmp(&format!("#symblic-16-{}-symbolic.svg", self.name()))?;
common::render_by_id(&self.file, "#symbolic", 16.0, Some(dest))
common::render_by_id(&self.handle, &self.name(), "#symbolic", 16.0, Some(dest))
}
ProjectType::Preview => anyhow::bail!("No symbolic support for Preview icons"),
}
......
use gtk::prelude::*;
use crate::project::Project;
use std::rc::Rc;
#[derive(Clone, Serialize, Deserialize)]
pub struct RecentItem {
......@@ -10,11 +11,11 @@ pub struct RecentItem {
pub struct RecentItemRow {
pub widget: gtk::FlowBoxChild,
pub event_box: gtk::EventBox,
project: Project,
project: Rc<Project>,
}
impl RecentItemRow {
pub fn new(project: Project) -> Self {
pub fn new(project: Rc<Project>) -> Self {
let widget = gtk::FlowBoxChild::new();
let event_box = gtk::EventBox::new();
......
......@@ -21,7 +21,7 @@ pub struct Window {
builder: gtk::Builder,
sender: glib::Sender<Action>,
previewer: ProjectPreviewer,
open_project: Rc<RefCell<Option<Project>>>,
open_project: RefCell<Option<Rc<Project>>>,
exporter: ExportPopover,
monitor: RefCell<Option<gio::FileMonitor>>,
}
......@@ -38,7 +38,7 @@ impl Window {
sender,
previewer,
exporter: ExportPopover::new(),
open_project: Rc::new(RefCell::new(None)),
open_project: RefCell::new(None),
monitor: RefCell::new(None),
});
......@@ -49,7 +49,7 @@ impl Window {
window_widget
}
pub fn set_open_project(&self, project: Project) {
pub fn set_open_project(&self, project: Rc<Project>) {
self.set_view(View::Previewer);
self.previewer.preview(&project);
self.exporter.set_project(&project);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment