Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,157 changes: 922 additions & 1,235 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ single_match_else = "warn"
zero_prefixed_literal = "allow"

[workspace.dependencies]
cairo = { package = "cairo-rs", version = "0.21.2", features = ["png"] }
gtk4 = { version = "0.10.2", features = ["blueprint"] }
cairo = { package = "cairo-rs", version = "0.22.0", features = ["png"] }
gtk4 = { version = "0.11.0", features = ["blueprint", "v4_18"] }
adw = { version = "0.9.1", package = "libadwaita", features = ["v1_8", "gtk_v4_18"] }
thiserror = "2.0.3"
tokio = { version = "1.25.0", features = ["rt-multi-thread"] }
tracing = "0.1.23"
Expand All @@ -45,13 +46,14 @@ kcshot-data = { path = "./kcshot-data" }

# UI-related dependencies
gtk4.workspace = true
adw.workspace = true
ksni = "0.3.1"

# Screenshot editing & capturing
kcshot-screenshot = { path = "./kcshot-screenshot" }
cairo.workspace = true
gdk4-x11 = "0.10.1"
pangocairo = "0.21.2"
gdk4-x11 = { version = "0.11.0", features = ["v4_18"] }
pangocairo = "0.22.0"
pulldown-cmark = { version = "0.13.0", default-features = false }
pulldown-cmark-escape = "0.11.0"
regex = "1.11.1"
Expand Down
3 changes: 2 additions & 1 deletion kcshot-screenshot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ workspace = true
kcshot-data = { path = "../kcshot-data" }

# Actually taking the screeenshot
ashpd = { version = "0.12.0", default-features = false, features = [
ashpd = { version = "0.13.0", default-features = false, features = [
"gtk4",
"tokio",
"tracing",
"screenshot"
] }
xcb = { version = "1.2.2", features = [
"debug_atom_names",
Expand Down
172 changes: 99 additions & 73 deletions src/appwindow.blp
Original file line number Diff line number Diff line change
@@ -1,95 +1,121 @@
using Gtk 4.0;
using Adw 1;

template $KCShotAppWindow : Gtk.ApplicationWindow {
hide-on-close: true;
menu main-menu {
section {
item {
label: 'Preferences';
action: "app.settings";
}

Gtk.Box {
orientation: horizontal;
item {
label: 'About';
action: "app.about";
}
}
}

Gtk.Frame {
Gtk.Box {
orientation: vertical;
spacing: 0;
template $KCShotAppWindow : Adw.ApplicationWindow {
hide-on-close: true;
default-width: 800;
default-height: 800;
title: 'kcshot';

Gtk.Button {
child: Gtk.Label {
label: 'Capture';
halign: start;
};
Adw.Breakpoint {
condition ("max-width: 400sp")

clicked => $on_capture_clicked() swapped;
setters {
split_view.collapsed: true;
}
}

content: Adw.ToolbarView {
content: Adw.OverlaySplitView split_view {
sidebar: Adw.ToolbarView {
[top]
Adw.HeaderBar {
[end]
Gtk.MenuButton {
menu-model: main-menu;
icon-name: 'open-menu-symbolic';
}
}

Gtk.Button {
child: Gtk.Label {
label: 'Settings';
halign: start;
};
Gtk.Box {
orientation: vertical;
spacing: 4;
margin-start: 4;
margin-end: 4;
margin-top: 4;
margin-bottom: 4;

Gtk.Button {
child: Adw.ButtonContent {
halign: start;
label: 'Capture';
icon-name: 'camera-photo-symbolic';
};

clicked => $on_settings_clicked() swapped;
}
clicked => $on_capture_clicked() swapped;
}

Gtk.Button {
child: Gtk.Label {
label: 'Screenshots folder';
halign: start;
};
Gtk.Button {
child: Adw.ButtonContent {
halign: start;
label: 'Screenshots folder';
icon-name: 'folder-open-symbolic';
};

clicked => $on_screenshots_folder_clicked() swapped;
}
clicked => $on_screenshots_folder_clicked() swapped;
}

Gtk.Button history_button {
child: Gtk.Label {
label: 'History';
halign: start;
};
Gtk.Button history_button {
child: Adw.ButtonContent {
halign: start;
label: 'History';
icon-name: 'document-open-recent-symbolic';
};

clicked => $on_history_clicked() swapped;
clicked => $on_history_clicked() swapped;
}
}
};

Gtk.Button {
child: Gtk.Label {
label: 'Quit kcshot';
halign: start;
content: Adw.ToolbarView {
[top]
Adw.HeaderBar {
title-widget: Adw.WindowTitle {
title: 'History';
};

clicked => $on_quit_clicked() swapped;
}
}
}

Gtk.Frame {
Gtk.Stack stack {
Gtk.StackPage {
name: 'message';
child: Gtk.Box {
orientation: vertical;
spacing: 2;

Gtk.Label {
label: '(´• ω •`)';
styles [ 'kc-label-emoji' ]
content: Adw.NavigationPage {
title: 'Content';

Gtk.Stack stack {
Gtk.StackPage {
name: 'message';
child: Adw.StatusPage {
title: '(´• ω •`)';
description: 'The history is disabled';
icon-name: 'action-unavailable-symbolic';
};
}

Gtk.Label {
label: 'The history is disabled';
styles [ 'kc-history-disabled-note' ]
}
};
}

Gtk.StackPage {
name: 'image-grid';
child: Gtk.ScrolledWindow {
propagate-natural-width: true;
min-content-height: 600;
Gtk.StackPage {
name: 'image-grid';
child: Gtk.ScrolledWindow {
propagate-natural-width: true;
min-content-height: 600;

child: Gtk.GridView image_grid {
min-columns: 3;
};
};
}
}
}
}
child: Gtk.GridView image_grid {
min-columns: 3;
};
};
}
}
};
};
};
};
}
44 changes: 34 additions & 10 deletions src/appwindow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use crate::{history::HistoryModel, kcshot::KCShot};

glib::wrapper! {
pub struct AppWindow(ObjectSubclass<underlying::AppWindow>)
@extends gtk4::Widget, gtk4::Window, gtk4::ApplicationWindow,
@extends gtk4::Widget, adw::Window, gtk4::ApplicationWindow, adw::ApplicationWindow,
@implements gtk4::ConstraintTarget, gtk4::Buildable, gtk4::Accessible,
gtk4::ShortcutManager, gtk4::Root, gtk4::Native, gio::ActionMap, gio::ActionGroup;
gtk4::ShortcutManager, gtk4::Root, gtk4::Native, gtk4::Window, gio::ActionMap, gio::ActionGroup;
}

impl AppWindow {
Expand All @@ -21,8 +21,12 @@ impl AppWindow {
mod underlying {
use std::{cell::RefCell, process::Command};

use adw::{
prelude::AdwDialogExt,
subclass::{prelude::AdwApplicationWindowImpl, window::AdwWindowImpl},
};
use gtk4::{
CompositeTemplate, gdk,
CompositeTemplate, gdk, gio,
glib::{self, Properties, clone},
prelude::*,
subclass::{application_window::ApplicationWindowImpl, prelude::*},
Expand Down Expand Up @@ -67,7 +71,7 @@ mod underlying {
impl ObjectSubclass for AppWindow {
const NAME: &'static str = "KCShotAppWindow";
type Type = super::AppWindow;
type ParentType = gtk4::ApplicationWindow;
type ParentType = adw::ApplicationWindow;

fn class_init(klass: &mut Self::Class) {
klass.set_css_name("kcshot-app-window");
Expand Down Expand Up @@ -117,6 +121,8 @@ mod underlying {
self.settings
.bind_is_history_enabled(&self.history_button.get(), "visible")
.build();

self.setup_actions();
}

fn dispose(&self) {
Expand All @@ -125,19 +131,34 @@ mod underlying {
}

impl WindowImpl for AppWindow {}
impl AdwWindowImpl for AppWindow {}

#[gtk4::template_callbacks]
impl AppWindow {
#[template_callback]
fn on_capture_clicked(&self, _: &gtk4::Button) {
let editing_starts_with_cropping = self.settings.editing_starts_with_cropping();
fn setup_actions(&self) {
let window = self.obj();

// Add action "close" to `window` taking no parameter
let action_preferences = gio::ActionEntry::builder("settings")
.activate(clone!(
#[weak]
window,
move |_, _, _| {
SettingsWindow::default()
.present(Some(window.upcast_ref::<gtk4::Widget>()));
}
))
.build();

EditorWindow::show(KCShot::the().upcast_ref(), editing_starts_with_cropping);
let actions = gio::SimpleActionGroup::new();
actions.add_action_entries([action_preferences]);
window.insert_action_group("app", Some(&actions));
}

#[template_callback]
fn on_settings_clicked(&self, _: &gtk4::Button) {
SettingsWindow::default().show();
fn on_capture_clicked(&self, _: &gtk4::Button) {
let editing_starts_with_cropping = self.settings.editing_starts_with_cropping();
EditorWindow::show(KCShot::the().upcast_ref(), editing_starts_with_cropping);
}

#[template_callback]
Expand Down Expand Up @@ -170,10 +191,12 @@ mod underlying {
.width_request(300)
.build();

let list_item = list_item.downcast_ref::<gtk4::ListItem>().unwrap();
list_item.set_child(Some(&picture));
});

factory.connect_bind(move |_this, list_item| {
let list_item = list_item.downcast_ref::<gtk4::ListItem>().unwrap();
let object = list_item
.item()
.and_downcast::<RowData>()
Expand Down Expand Up @@ -224,5 +247,6 @@ mod underlying {
}

impl WidgetImpl for AppWindow {}
impl AdwApplicationWindowImpl for AppWindow {}
impl ApplicationWindowImpl for AppWindow {}
}
4 changes: 2 additions & 2 deletions src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ glib::wrapper! {
}

impl EditorWindow {
pub fn new(app: &gtk4::Application, editing_starts_with_cropping: bool) -> Self {
pub fn new(app: &adw::Application, editing_starts_with_cropping: bool) -> Self {
glib::Object::builder::<Self>()
.property("application", app)
.property("editing-starts-with-cropping", editing_starts_with_cropping)
.build()
}

pub fn show(app: &gtk4::Application, editing_starts_with_cropping: bool) {
pub fn show(app: &adw::Application, editing_starts_with_cropping: bool) {
let window = Self::new(app, editing_starts_with_cropping);
window.set_decorated(false);
window.show();
Expand Down
8 changes: 5 additions & 3 deletions src/kcshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use crate::{

glib::wrapper! {
pub struct KCShot(ObjectSubclass<underlying::KCShot>)
@extends gio::Application, gtk4::Application,
@implements gio::ActionGroup, gio::ActionMap;
@extends gio::Application, adw::Application,
@implements gio::ActionGroup, gio::ActionMap, gtk4::Application;
}

impl Default for KCShot {
Expand Down Expand Up @@ -81,6 +81,7 @@ mod underlying {
ops::ControlFlow,
};

use adw::subclass::prelude::AdwApplicationImpl;
use diesel::SqliteConnection;
use gtk4::{
gdk,
Expand Down Expand Up @@ -203,7 +204,7 @@ mod underlying {
impl ObjectSubclass for KCShot {
const NAME: &'static str = "KCShot";
type Type = super::KCShot;
type ParentType = gtk4::Application;
type ParentType = adw::Application;
}

impl ObjectImpl for KCShot {
Expand Down Expand Up @@ -351,4 +352,5 @@ mod underlying {
}

impl GtkApplicationImpl for KCShot {}
impl AdwApplicationImpl for KCShot {}
}
Loading