Compare commits

..

No commits in common. "de81283ae4ff585676260fff3b76816578804d0d" and "d1ec3a858524442357fc0c04cc6535118b1b22e6" have entirely different histories.

6 changed files with 49 additions and 317 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 KiB

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 76 76" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" enable-background="new 0 0 76.00 76.00" xml:space="preserve">
<path fill="#000000" fill-opacity="1" stroke-width="0.2" stroke-linejoin="round" d="M 19,35L 19,43L 27,43L 27,35L 19,35 Z M 30.9999,35L 30.9999,43L 56.9998,43L 56.9999,35L 30.9999,35 Z M 31,32L 57,32L 57,24L 31,24L 31,32 Z M 32,31L 32,25L 56,25L 56,31L 32,31 Z M 21,33L 25,33L 25,30L 28,30L 28,26L 25,26L 25,23L 21,23L 21,26L 18,26L 18,30L 21,30L 21,33 Z M 22,32L 22,29L 19,29L 19,27L 22,27L 22,24L 24,24L 24,27L 27,27L 27,29L 24,29L 24,32L 22,32 Z M 19.0001,46L 19.0001,54L 27.0001,54L 27.0001,46L 19.0001,46 Z M 31.0001,46L 31.0001,54L 57,54L 57,46L 31.0001,46 Z "/>
</svg>

Before

Width:  |  Height:  |  Size: 1,022 B

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 76 76" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" enable-background="new 0 0 76.00 76.00" xml:space="preserve">
<path fill="#000000" fill-opacity="1" stroke-width="0.2" stroke-linejoin="round" d="M 19,42L 19,34L 27,34L 27,42L 19,42 Z M 30.9999,42L 30.9999,34L 56.9999,34L 56.9999,42L 30.9999,42 Z M 31,45L 57,45L 57,53L 31,53L 31,45 Z M 32,46L 32,52L 56,52L 56,46L 32,46 Z M 21,44L 25,44L 25,47L 28,47L 28,51L 25,51L 25,54L 21,54L 21,51L 18,51L 18,47L 21,47L 21,44 Z M 22,45L 22,48L 19,48L 19,50L 22,50L 22,53L 24,53L 24,50L 27,50L 27,48L 24,48L 24,45L 22,45 Z M 19.0001,31L 19.0001,23L 27.0001,23L 27.0001,31L 19.0001,31 Z M 31.0001,31L 31.0001,23L 57,23L 57,31L 31.0001,31 Z "/>
</svg>

Before

Width:  |  Height:  |  Size: 1,022 B

View file

@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
width="800px"
height="800px"
viewBox="0 0 76 76"
version="1.1"
enable-background="new 0 0 76.00 76.00"
xml:space="preserve"
id="svg1"
sodipodi:docname="split-above.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1" /><sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="0.74629807"
inkscape:cx="252.58004"
inkscape:cy="447.54236"
inkscape:window-width="1463"
inkscape:window-height="909"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg1" />
<path
fill="#000000"
fill-opacity="1"
stroke-width="0.404256"
stroke-linejoin="round"
d="M 3.8256403,28.314338 V 46.261937 H 18.394593 V 28.314338 Z m 21.8532467,0 v 17.947599 h 47.348916 l 1.82e-4,-17.947599 z m 1.83e-4,-6.730349 H 73.028167 V 3.6363892 H 25.67907 Z m 1.821118,-2.243451 V 5.8798398 h 43.70686 V 19.340538 Z M 3.8258225,52.992286 V 70.939887 H 18.394774 V 52.992286 Z m 21.8534285,0 V 70.939887 H 73.028167 V 52.992286 Z"
id="path1"
sodipodi:nodetypes="cccccccccccccccccccccccccccccc" />
<path
d="M 3.5834285,21.523408 H 18.345395 V 3.5758086 H 3.5834285 Z M 5.3255032,19.102699 V 5.7129051 L 16.732439,5.5582305 16.783963,19.315409 Z"
style="fill:#000000;fill-opacity:1;stroke-width:0.225723;stroke-linejoin:round"
id="path1-2"
sodipodi:nodetypes="cccccccccc" /><rect
style="fill:#000000;stroke-width:0.11759"
id="rect1"
width="72.699356"
height="1.642724"
x="1.9440452"
y="24.184471" /></svg>

Before

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,60 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
width="800px"
height="800px"
viewBox="0 0 76 76"
version="1.1"
enable-background="new 0 0 76.00 76.00"
xml:space="preserve"
id="svg1"
sodipodi:docname="split-below.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1" /><sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="0.76425252"
inkscape:cx="252.53433"
inkscape:cy="367.67952"
inkscape:window-width="1463"
inkscape:window-height="909"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg1" />
<path
fill="#000000"
fill-opacity="1"
stroke-width="0.404256"
stroke-linejoin="round"
d="M 3.8256403,28.314338 V 46.261937 H 18.394593 V 28.314338 Z m 21.8532467,0 v 17.947599 h 47.348916 l 1.82e-4,-17.947599 z"
id="path1"
sodipodi:nodetypes="cccccccccc" />
<path
d="M 3.8,71.717599 H 18.561966 V 53.77 H 3.8 Z M 5.5420747,69.29689 V 55.907096 L 16.94901,55.752421 17.00053,69.5096 Z"
style="fill:#000000;fill-opacity:1;stroke-width:0.225723;stroke-linejoin:round"
id="path1-2"
sodipodi:nodetypes="cccccccccc" /><rect
style="fill:#000000;stroke-width:0.11759"
id="rect1"
width="72.699356"
height="1.642724"
x="1.9440452"
y="49.006992" /><path
d="M 3.8,3.924661 V 21.872262 H 18.368951 V 3.924661 Z m 21.853428,0 V 21.872262 H 73.002344 V 3.924661 Z"
style="fill:#000000;fill-opacity:1;stroke-width:0.404256;stroke-linejoin:round"
id="path1-7" /><path
d="M 25.65,71.7176 H 72.999097 V 53.77 H 25.65 Z m 1.821118,-2.243451 V 56.013451 h 43.70686 v 13.460698 z"
style="fill:#000000;fill-opacity:1;stroke-width:0.404256;stroke-linejoin:round"
id="path1-6" /></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -1,20 +1,15 @@
use std::{
collections::HashMap,
io,
path::{Path, PathBuf},
};
use std::{io, path::Path, path::PathBuf};
use crate::core::presentations::Presentation;
use cosmic::{
Element, Task,
dialog::file_chooser::{FileFilter, open::Dialog},
iced::{Background, ContentFit, Length, alignment::Vertical},
iced::{ContentFit, Length, alignment::Vertical},
iced_widget::{column, row},
theme,
widget::{
self, Space, button, container, context_menu,
horizontal_space, icon, image::Handle, menu, mouse_area,
scrollable, text, text_input,
self, Space, button, container, horizontal_space, icon,
image::Handle, scrollable, text, text_input,
},
};
use miette::IntoDiagnostic;
@ -31,8 +26,6 @@ pub struct PresentationEditor {
current_slide_index: Option<i32>,
title: String,
editing: bool,
hovered_slide: Option<i32>,
context_menu_id: Option<i32>,
}
pub enum Action {
@ -53,28 +46,6 @@ pub enum Message {
None,
ChangePresentationFile(Presentation),
AddSlides(Option<Vec<Handle>>),
ChangeSlide(usize),
HoverSlide(Option<i32>),
ContextMenu(usize),
SplitBefore,
SplitAfter,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum MenuAction {
SplitBefore,
SplitAfter,
}
impl menu::Action for MenuAction {
type Message = Message;
fn message(&self) -> Self::Message {
match self {
MenuAction::SplitBefore => Message::SplitBefore,
MenuAction::SplitAfter => Message::SplitAfter,
}
}
}
impl PresentationEditor {
@ -88,8 +59,6 @@ impl PresentationEditor {
current_slide_index: None,
page_count: None,
slides: None,
hovered_slide: None,
context_menu_id: None,
}
}
pub fn update(&mut self, message: Message) -> Action {
@ -210,15 +179,21 @@ impl PresentationEditor {
doc.load_page(previous_index).ok()?;
let matrix = Matrix::IDENTITY;
let colorspace = Colorspace::device_rgb();
let pixmap = page
let Ok(pixmap) = page
.to_pixmap(
&matrix,
&colorspace,
true,
true,
)
.ok()?;
.into_diagnostic()
else {
error!(
"Can't turn this page into pixmap"
);
return None;
};
debug!(?pixmap);
Some(Handle::from_rgba(
pixmap.width(),
pixmap.height(),
@ -227,50 +202,6 @@ impl PresentationEditor {
});
self.current_slide_index = Some(previous_index);
}
Message::ChangeSlide(index) => {
self.current_slide =
self.document.as_ref().and_then(|doc| {
let page =
doc.load_page(index as i32).ok()?;
let matrix = Matrix::IDENTITY;
let colorspace = Colorspace::device_rgb();
let pixmap = page
.to_pixmap(
&matrix,
&colorspace,
true,
true,
)
.ok()?;
Some(Handle::from_rgba(
pixmap.width(),
pixmap.height(),
pixmap.samples().to_vec(),
))
});
self.current_slide_index = Some(index as i32);
}
Message::HoverSlide(slide) => {
self.hovered_slide = slide;
}
Message::ContextMenu(index) => {
self.context_menu_id = Some(index as i32);
}
Message::SplitBefore => {
if let Some(index) = self.context_menu_id {
debug!("split before {index}");
} else {
error!("split before no index");
}
}
Message::SplitAfter => {
if let Some(index) = self.context_menu_id {
debug!("split after {index}");
} else {
error!("split after no index");
}
}
}
Action::None
}
@ -281,75 +212,32 @@ impl PresentationEditor {
widget::image(slide)
.content_fit(ContentFit::ScaleDown),
)
.style(|_| {
container::background(Background::Color(
cosmic::iced::Color::WHITE,
))
})
} else {
container(Space::new(0, 0))
};
let pdf_pages: Vec<Element<Message>> = if let Some(pages) =
&self.slides
{
let pdf_pages: Vec<Element<Message>> =
if let Some(pages) = &self.slides {
pages
.iter()
.enumerate()
.map(|(index, page)| {
.map(|page| {
let image = widget::image(page)
.height(theme::spacing().space_xxxl * 3)
.content_fit(ContentFit::ScaleDown);
let slide = container(image).style(|_| {
container::background(Background::Color(
cosmic::iced::Color::WHITE,
))
});
let clickable_slide = container(
mouse_area(slide)
.on_enter(Message::HoverSlide(Some(
index as i32,
)))
.on_exit(Message::HoverSlide(None))
.on_right_press(Message::ContextMenu(
index,
))
.on_press(Message::ChangeSlide(index)),
)
.padding(theme::spacing().space_m)
.clip(true)
.class(
if let Some(hovered_index) =
self.hovered_slide
{
if index as i32 == hovered_index {
theme::Container::Primary
} else {
theme::Container::Card
}
} else {
theme::Container::Card
},
);
clickable_slide.into()
container(image).into()
})
.collect()
} else {
vec![horizontal_space().into()]
};
let pages_column = container(
self.context_menu(
scrollable(
let pages_column = container(scrollable(
column(pdf_pages)
.spacing(theme::active().cosmic().space_xs())
.padding(theme::spacing().space_xs),
)
.into(),
),
)
.padding(theme::spacing().space_l),
))
.class(theme::Container::Card);
let main_row = row![
pages_column,
container(presentation).center(Length::FillPortion(2))
presentation.center(Length::FillPortion(2))
]
.spacing(theme::spacing().space_xxl);
let control_buttons = row![
@ -391,44 +279,6 @@ impl PresentationEditor {
self.editing
}
fn context_menu<'b>(
&self,
items: Element<'b, Message>,
) -> Element<'b, Message> {
if self.context_menu_id.is_some() {
let before_icon =
icon::from_path("./res/split-above.svg".into())
.symbolic(true);
let after_icon =
icon::from_path("./res/split-below.svg".into())
.symbolic(true);
let menu_items = vec![
menu::Item::Button(
"Spit Before",
Some(before_icon),
MenuAction::SplitBefore,
),
menu::Item::Button(
"Split After",
Some(after_icon),
MenuAction::SplitAfter,
),
];
let context_menu = context_menu(
items,
self.context_menu_id.map_or_else(
|| None,
|_| {
Some(menu::items(&HashMap::new(), menu_items))
},
),
);
Element::from(context_menu)
} else {
items
}
}
fn update_entire_presentation(
&mut self,
presentation: &Presentation,
@ -446,13 +296,17 @@ impl PresentationEditor {
let page = doc.load_page(0).ok()?;
let matrix = Matrix::IDENTITY;
let colorspace = Colorspace::device_rgb();
let pixmap = page
let Ok(pixmap) = page
.to_pixmap(&matrix, &colorspace, true, true)
.ok()?;
.into_diagnostic()
else {
error!("Can't turn this page into pixmap");
return None;
};
debug!(?pixmap);
Some(Handle::from_rgba(
pixmap.width(),
pixmap.height(),
pixmap.width() / 3,
pixmap.height() / 3,
pixmap.samples().to_vec(),
))
});
@ -475,12 +329,16 @@ async fn get_all_pages(
pages
.filter_map(|page| {
let page = page.ok()?;
let matrix = Matrix::IDENTITY;
let colorspace = Colorspace::device_rgb();
let pixmap = page
let Ok(pixmap) = page
.to_pixmap(&matrix, &colorspace, true, true)
.ok()?;
.into_diagnostic()
else {
error!("Can't turn this page into pixmap");
return None;
};
Some(Handle::from_rgba(
pixmap.width(),
pixmap.height(),