Skip to content

Commit 5dd99bf

Browse files
committed
add DownloadPage
1 parent c41723d commit 5dd99bf

File tree

6 files changed

+138
-38
lines changed

6 files changed

+138
-38
lines changed

data/resources/meson.build

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ blueprints = custom_target('blueprints',
22
input: files(
33
'ui/window.blp',
44
'ui/shortcuts.blp',
5-
'ui/input_page.blp'
5+
'ui/input_page.blp',
6+
'ui/download_page.blp'
67
),
78
output: '.',
89
command: [find_program('blueprint-compiler'), 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@'],

data/resources/resources.gresource.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
<file compressed="true" preprocess="xml-stripblanks" alias="gtk/help-overlay.ui">ui/shortcuts.ui</file>
66
<file compressed="true" preprocess="xml-stripblanks">ui/window.ui</file>
77
<file compressed="true" preprocess="xml-stripblanks">ui/input_page.ui</file>
8+
<file compressed="true" preprocess="xml-stripblanks">ui/download_page.ui</file>
89
</gresource>
910
</gresources>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using Gtk 4.0;
2+
using Adw 1;
3+
4+
template DownloadPage: Gtk.Box {
5+
margin-top: 8;
6+
margin-bottom: 8;
7+
margin-start: 8;
8+
margin-end: 8;
9+
orientation: vertical;
10+
valign: center;
11+
Gtk.Box {
12+
orientation: horizontal;
13+
spacing: 16;
14+
Gtk.Image {
15+
icon-name: "folder-download-symbolic";
16+
pixel-size: 48;
17+
valign: center;
18+
}
19+
Gtk.Box {
20+
orientation: vertical;
21+
valign: center;
22+
margin-top: 8;
23+
margin-bottom: 8;
24+
Gtk.Label label {
25+
styles ["heading"]
26+
label: "Text";
27+
xalign: 0.0;
28+
wrap: true;
29+
}
30+
Gtk.Label label_downloaded {
31+
label: "0KB";
32+
xalign: 0.0;
33+
}
34+
Gtk.ProgressBar progress_bar {
35+
margin-top: 8;
36+
pulse-step: 0.1;
37+
hexpand: true;
38+
}
39+
}
40+
}
41+
Gtk.Button open_btn {
42+
styles ["suggested-action", "pill"]
43+
label: "Open File";
44+
margin-top: 8;
45+
margin-bottom: 8;
46+
opacity: 0;
47+
}
48+
}

src/download_page.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use gtk::glib;
2+
use gtk::prelude::*;
3+
use gtk::subclass::prelude::*;
4+
use glib::subclass::prelude::*;
5+
use gtk::CompositeTemplate;
6+
use gtk::TemplateChild;
7+
8+
mod imp {
9+
pub use super::*;
10+
#[derive(CompositeTemplate, Default)]
11+
#[template(resource = "/com/ranfdev/Geopard/ui/download_page.ui")]
12+
pub struct DownloadPage {
13+
#[template_child]
14+
pub label: TemplateChild<gtk::Label>,
15+
#[template_child]
16+
pub label_downloaded: TemplateChild<gtk::Label>,
17+
#[template_child]
18+
pub progress_bar: TemplateChild<gtk::ProgressBar>,
19+
#[template_child]
20+
pub open_btn: TemplateChild<gtk::Button>,
21+
}
22+
23+
24+
#[glib::object_subclass]
25+
impl ObjectSubclass for DownloadPage {
26+
// `NAME` needs to match `class` attribute of template
27+
const NAME: &'static str = "DownloadPage";
28+
type Type = super::DownloadPage;
29+
type ParentType = gtk::Box;
30+
31+
fn class_init(klass: &mut Self::Class) {
32+
klass.bind_template();
33+
}
34+
35+
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
36+
obj.init_template();
37+
}
38+
}
39+
40+
impl ObjectImpl for DownloadPage {}
41+
impl WidgetImpl for DownloadPage {}
42+
impl BoxImpl for DownloadPage {}
43+
}
44+
45+
glib::wrapper! {
46+
pub struct DownloadPage(ObjectSubclass<imp::DownloadPage>)
47+
@extends gtk::Box, gtk::Widget;
48+
}
49+
50+
impl DownloadPage {
51+
pub fn new() -> Self {
52+
glib::Object::new(&[]).unwrap()
53+
}
54+
}

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ mod macros;
1818
mod tab;
1919
mod window;
2020
mod input_page;
21+
mod download_page;
2122

2223
use gtk::prelude::*;
2324

src/tab.rs

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ impl Tab {
497497
Self::display_text(&mut req.draw_ctx, buffered).await?;
498498
None
499499
} else {
500-
Self::display_download(&mut req.draw_ctx, req.url.clone(), buffered).await?;
500+
self.display_download(req.url.clone(), buffered).await?;
501501
None
502502
}
503503
}
@@ -515,13 +515,7 @@ impl Tab {
515515
Ok(link_url)
516516
}
517517

518-
fn download_path(url: &Url) -> anyhow::Result<std::path::PathBuf> {
519-
let file_name = url
520-
.path_segments()
521-
.context("Can't divide url in segments")?
522-
.last()
523-
.context("Can't get last url segment")?;
524-
518+
fn download_path(file_name: &str) -> anyhow::Result<std::path::PathBuf> {
525519
let mut file_name = std::path::PathBuf::from(file_name);
526520
loop {
527521
let mut d_path = common::DOWNLOAD_PATH.join(&file_name);
@@ -544,29 +538,32 @@ impl Tab {
544538
}
545539
}
546540
async fn display_download<T: AsyncRead + Unpin>(
547-
ctx: &mut DrawCtx,
541+
&self,
548542
url: Url,
549543
mut stream: T,
550544
) -> anyhow::Result<()> {
551-
let d_path = Self::download_path(&url)?;
545+
let imp = self.imp();
546+
547+
let file_name = url
548+
.path_segments()
549+
.context("Can't divide url in segments")?
550+
.last()
551+
.context("Can't get last url segment")?;
552+
let d_path = Self::download_path(file_name)?;
553+
554+
let page = crate::download_page::DownloadPage::new();
555+
page.imp().label.set_label(file_name);
556+
imp.stack.add_child(&page);
557+
imp.stack.set_visible_child(&page);
558+
559+
552560

553561
let mut buffer = Vec::with_capacity(8192);
554562
buffer.extend_from_slice(&[0; 8192]);
555563

556564
let mut read = 0;
557-
let mut text_iter = ctx.text_buffer.end_iter();
558-
ctx.insert_paragraph(
559-
&mut text_iter,
560-
&format!("writing to {:?}\n", d_path.as_os_str()),
561-
);
562-
ctx.insert_paragraph(
563-
&mut text_iter,
564-
"to interrupt the download, leave this page\n",
565-
);
566-
567-
let mark = ctx.text_buffer.create_mark(None, &text_iter, true);
568-
569-
ctx.insert_paragraph(&mut text_iter, "downloaded\t KB\n");
565+
let mut last_update_time = glib::real_time();
566+
const THROTTLE_TIME: i64 = 300_000; // 0.3s
570567

571568
let mut file = File::create(&d_path).await?;
572569
loop {
@@ -575,30 +572,28 @@ impl Tab {
575572
Ok(n) => {
576573
file.write_all(&buffer[..n]).await?;
577574
read += n;
578-
debug!("lines {}", ctx.text_buffer.line_count());
579-
let mut progress_info_iter = ctx.text_buffer.iter_at_mark(&mark);
580-
ctx.text_buffer
581-
.delete(&mut progress_info_iter, &mut ctx.text_buffer.end_iter());
582-
ctx.insert_paragraph(
583-
&mut progress_info_iter,
584-
&format!("downloaded\t {}KB\n", read / 1000),
585-
);
575+
576+
let t = glib::real_time();
577+
if t - last_update_time > THROTTLE_TIME {
578+
page.imp().progress_bar.pulse();
579+
page.imp().label_downloaded.set_text(&format!("{}KB", read / 1000));
580+
last_update_time = t;
581+
}
586582
}
587583
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => {
588584
continue;
589585
}
590586
Err(e) => return Err(e.into()),
591587
}
592588
}
593-
let mut text_iter = ctx.text_buffer.end_iter();
594-
ctx.insert_paragraph(&mut text_iter, "download finished!\n");
589+
page.imp().label_downloaded.set_text(&format!("{}KB", read / 1000));
590+
page.imp().progress_bar.set_fraction(1.0);
591+
page.imp().open_btn.set_opacity(1.0);
592+
595593
let downloaded_file_url = format!("file://{}", d_path.as_os_str().to_str().unwrap());
596-
let button = gtk::Button::with_label("Open With Default Program");
597-
button.add_css_class("suggested-action");
598-
button.connect_clicked(move |_| {
594+
page.imp().open_btn.connect_clicked(move |_| {
599595
gtk::show_uri(None::<&gtk::Window>, &downloaded_file_url, 0);
600596
});
601-
ctx.insert_widget(&mut text_iter, &button);
602597

603598
Ok(())
604599
}

0 commit comments

Comments
 (0)