mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 16:45:27 +00:00
implement shared features as traits
This commit is contained in:
parent
6d49c79a0d
commit
725e764701
3 changed files with 118 additions and 98 deletions
|
|
@ -1,5 +1,13 @@
|
||||||
const DEFAULT: &str = "-";
|
mod display;
|
||||||
const DATE_TIME_FORMAT: &str = "%Y.%m.%d %H:%M:%S";
|
mod format;
|
||||||
|
|
||||||
|
use display::Display;
|
||||||
|
use format::Format;
|
||||||
|
|
||||||
|
use gtk::{
|
||||||
|
gio::FileInfo, pango::EllipsizeMode, Align, ColumnViewColumn, Label, ListItem,
|
||||||
|
SignalListItemFactory,
|
||||||
|
};
|
||||||
|
|
||||||
pub trait Column {
|
pub trait Column {
|
||||||
fn icon() -> Self;
|
fn icon() -> Self;
|
||||||
|
|
@ -11,10 +19,10 @@ pub trait Column {
|
||||||
fn access_date_time(width: i32) -> Self;
|
fn access_date_time(width: i32) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Column for gtk::ColumnViewColumn {
|
impl Column for ColumnViewColumn {
|
||||||
fn icon() -> Self {
|
fn icon() -> Self {
|
||||||
use gtk::{
|
use gtk::{
|
||||||
gio::{FileInfo, FileType},
|
gio::FileInfo,
|
||||||
prelude::{BoxExt, Cast, ListItemExt, WidgetExt},
|
prelude::{BoxExt, Cast, ListItemExt, WidgetExt},
|
||||||
Align, ColumnViewColumn, ListItem, SignalListItemFactory,
|
Align, ColumnViewColumn, ListItem, SignalListItemFactory,
|
||||||
};
|
};
|
||||||
|
|
@ -34,24 +42,15 @@ impl Column for gtk::ColumnViewColumn {
|
||||||
.symbolic_icon()
|
.symbolic_icon()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
image.set_tooltip_text(
|
image.set_tooltip_text(Some(
|
||||||
match list_item
|
list_item
|
||||||
.item()
|
.item()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.downcast_ref::<FileInfo>()
|
.downcast_ref::<FileInfo>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.file_type()
|
.file_type()
|
||||||
{
|
.as_str(),
|
||||||
FileType::Unknown => Some("Unknown"),
|
));
|
||||||
FileType::Regular => Some("File"),
|
|
||||||
FileType::Directory => Some("Directory"),
|
|
||||||
FileType::SymbolicLink => Some("SymbolicLink"),
|
|
||||||
FileType::Special => Some("Special"),
|
|
||||||
FileType::Shortcut => Some("Shortcut"),
|
|
||||||
FileType::Mountable => Some("Mountable"),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let container = gtk::Box::builder().halign(Align::Center).build(); // prevents `gtk::Image` blur
|
let container = gtk::Box::builder().halign(Align::Center).build(); // prevents `gtk::Image` blur
|
||||||
container.append(&image);
|
container.append(&image);
|
||||||
list_item.set_child(Some(&container));
|
list_item.set_child(Some(&container));
|
||||||
|
|
@ -62,21 +61,21 @@ impl Column for gtk::ColumnViewColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name(width: i32) -> Self {
|
fn name(width: i32) -> Self {
|
||||||
gtk::ColumnViewColumn::builder()
|
ColumnViewColumn::builder()
|
||||||
.fixed_width(width)
|
.fixed_width(width)
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
.title("Name")
|
.title("Name")
|
||||||
.factory(&{
|
.factory(&{
|
||||||
let factory = gtk::SignalListItemFactory::new();
|
let factory = SignalListItemFactory::new();
|
||||||
factory.connect_bind(|_, this| {
|
factory.connect_bind(|_, this| {
|
||||||
use gtk::prelude::{Cast, /*FileExt,*/ ListItemExt};
|
use gtk::prelude::{Cast, /*FileExt,*/ ListItemExt};
|
||||||
let list_item = this.downcast_ref::<gtk::ListItem>().unwrap();
|
let list_item = this.downcast_ref::<ListItem>().unwrap();
|
||||||
let item = list_item.item().unwrap();
|
let item = list_item.item().unwrap();
|
||||||
let file_info = item.downcast_ref::<gtk::gio::FileInfo>().unwrap();
|
let file_info = item.downcast_ref::<FileInfo>().unwrap();
|
||||||
list_item.set_child(Some(
|
list_item.set_child(Some(
|
||||||
>k::Label::builder()
|
&Label::builder()
|
||||||
.halign(gtk::Align::Start)
|
.halign(Align::Start)
|
||||||
.ellipsize(gtk::pango::EllipsizeMode::Middle)
|
.ellipsize(EllipsizeMode::Middle)
|
||||||
.label(file_info.display_name())
|
.label(file_info.display_name())
|
||||||
/*.tooltip_text(
|
/*.tooltip_text(
|
||||||
file_info
|
file_info
|
||||||
|
|
@ -98,22 +97,22 @@ impl Column for gtk::ColumnViewColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(width: i32) -> Self {
|
fn size(width: i32) -> Self {
|
||||||
gtk::ColumnViewColumn::builder()
|
ColumnViewColumn::builder()
|
||||||
.fixed_width(width)
|
.fixed_width(width)
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
.title("Size")
|
.title("Size")
|
||||||
.factory(&{
|
.factory(&{
|
||||||
let factory = gtk::SignalListItemFactory::new();
|
let factory = SignalListItemFactory::new();
|
||||||
factory.connect_bind(|_, this| {
|
factory.connect_bind(|_, this| {
|
||||||
use crate::tool::Format;
|
use crate::tool::Format;
|
||||||
use gtk::prelude::{Cast, ListItemExt};
|
use gtk::prelude::{Cast, ListItemExt};
|
||||||
let list_item = this.downcast_ref::<gtk::ListItem>().unwrap();
|
let list_item = this.downcast_ref::<ListItem>().unwrap();
|
||||||
let item = list_item.item().unwrap();
|
let item = list_item.item().unwrap();
|
||||||
let file_info = item.downcast_ref::<gtk::gio::FileInfo>().unwrap();
|
let file_info = item.downcast_ref::<FileInfo>().unwrap();
|
||||||
list_item.set_child(Some(
|
list_item.set_child(Some(
|
||||||
>k::Label::builder()
|
&Label::builder()
|
||||||
.halign(gtk::Align::Start)
|
.halign(Align::Start)
|
||||||
.ellipsize(gtk::pango::EllipsizeMode::Middle)
|
.ellipsize(EllipsizeMode::Middle)
|
||||||
.label((file_info.size() as usize).bytes())
|
.label((file_info.size() as usize).bytes())
|
||||||
.build(),
|
.build(),
|
||||||
));
|
));
|
||||||
|
|
@ -124,39 +123,22 @@ impl Column for gtk::ColumnViewColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content_type(width: i32) -> Self {
|
fn content_type(width: i32) -> Self {
|
||||||
gtk::ColumnViewColumn::builder()
|
ColumnViewColumn::builder()
|
||||||
.fixed_width(width)
|
.fixed_width(width)
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
.title("Content Type")
|
.title("Content Type")
|
||||||
.factory(&{
|
.factory(&{
|
||||||
let factory = gtk::SignalListItemFactory::new();
|
let factory = SignalListItemFactory::new();
|
||||||
factory.connect_bind(|_, this| {
|
factory.connect_bind(|_, this| {
|
||||||
use gtk::prelude::{Cast, ListItemExt};
|
use gtk::prelude::{Cast, ListItemExt};
|
||||||
let list_item = this.downcast_ref::<gtk::ListItem>().unwrap();
|
let list_item = this.downcast_ref::<ListItem>().unwrap();
|
||||||
let item = list_item.item().unwrap();
|
let item = list_item.item().unwrap();
|
||||||
let file_info = item.downcast_ref::<gtk::gio::FileInfo>().unwrap();
|
let file_info = item.downcast_ref::<FileInfo>().unwrap();
|
||||||
let content_type: gtk::glib::GString = match file_info.content_type() {
|
|
||||||
Some(content_type) => {
|
|
||||||
let display_name = file_info.display_name();
|
|
||||||
if content_type == "text/plain" {
|
|
||||||
if display_name.ends_with(".gmi")
|
|
||||||
|| display_name.ends_with(".gemini")
|
|
||||||
{
|
|
||||||
"text/gemini".into()
|
|
||||||
} else {
|
|
||||||
content_type
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
content_type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => DEFAULT.into(),
|
|
||||||
};
|
|
||||||
list_item.set_child(Some(
|
list_item.set_child(Some(
|
||||||
>k::Label::builder()
|
&Label::builder()
|
||||||
.halign(gtk::Align::Start)
|
.halign(Align::Start)
|
||||||
.ellipsize(gtk::pango::EllipsizeMode::Middle)
|
.ellipsize(EllipsizeMode::Middle)
|
||||||
.label(content_type)
|
.label(file_info.format_content_type())
|
||||||
.build(),
|
.build(),
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
@ -166,28 +148,22 @@ impl Column for gtk::ColumnViewColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn creation_date_time(width: i32) -> Self {
|
fn creation_date_time(width: i32) -> Self {
|
||||||
gtk::ColumnViewColumn::builder()
|
ColumnViewColumn::builder()
|
||||||
.fixed_width(width)
|
.fixed_width(width)
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
.title("Created")
|
.title("Created")
|
||||||
.factory(&{
|
.factory(&{
|
||||||
let factory = gtk::SignalListItemFactory::new();
|
let factory = SignalListItemFactory::new();
|
||||||
factory.connect_bind(|_, this| {
|
factory.connect_bind(|_, this| {
|
||||||
use gtk::prelude::{Cast, ListItemExt};
|
use gtk::prelude::{Cast, ListItemExt};
|
||||||
let list_item = this.downcast_ref::<gtk::ListItem>().unwrap();
|
let list_item = this.downcast_ref::<ListItem>().unwrap();
|
||||||
let item = list_item.item().unwrap();
|
let item = list_item.item().unwrap();
|
||||||
let file_info = item.downcast_ref::<gtk::gio::FileInfo>().unwrap();
|
let file_info = item.downcast_ref::<FileInfo>().unwrap();
|
||||||
list_item.set_child(Some(
|
list_item.set_child(Some(
|
||||||
>k::Label::builder()
|
&Label::builder()
|
||||||
.halign(gtk::Align::Start)
|
.halign(Align::Start)
|
||||||
.ellipsize(gtk::pango::EllipsizeMode::Middle)
|
.ellipsize(EllipsizeMode::Middle)
|
||||||
.label(
|
.label(file_info.format_date_time())
|
||||||
file_info
|
|
||||||
.creation_date_time()
|
|
||||||
.unwrap()
|
|
||||||
.format(DATE_TIME_FORMAT) // @TODO optional
|
|
||||||
.unwrap_or(DEFAULT.into()),
|
|
||||||
)
|
|
||||||
.build(),
|
.build(),
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
@ -197,28 +173,22 @@ impl Column for gtk::ColumnViewColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn modification_date_time(width: i32) -> Self {
|
fn modification_date_time(width: i32) -> Self {
|
||||||
gtk::ColumnViewColumn::builder()
|
ColumnViewColumn::builder()
|
||||||
.fixed_width(width)
|
.fixed_width(width)
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
.title("Modified")
|
.title("Modified")
|
||||||
.factory(&{
|
.factory(&{
|
||||||
let factory = gtk::SignalListItemFactory::new();
|
let factory = SignalListItemFactory::new();
|
||||||
factory.connect_bind(|_, this| {
|
factory.connect_bind(|_, this| {
|
||||||
use gtk::prelude::{Cast, ListItemExt};
|
use gtk::prelude::{Cast, ListItemExt};
|
||||||
let list_item = this.downcast_ref::<gtk::ListItem>().unwrap();
|
let list_item = this.downcast_ref::<ListItem>().unwrap();
|
||||||
let item = list_item.item().unwrap();
|
let item = list_item.item().unwrap();
|
||||||
let file_info = item.downcast_ref::<gtk::gio::FileInfo>().unwrap();
|
let file_info = item.downcast_ref::<FileInfo>().unwrap();
|
||||||
list_item.set_child(Some(
|
list_item.set_child(Some(
|
||||||
>k::Label::builder()
|
&Label::builder()
|
||||||
.halign(gtk::Align::Start)
|
.halign(Align::Start)
|
||||||
.ellipsize(gtk::pango::EllipsizeMode::Middle)
|
.ellipsize(EllipsizeMode::Middle)
|
||||||
.label(
|
.label(file_info.format_date_time())
|
||||||
file_info
|
|
||||||
.modification_date_time()
|
|
||||||
.unwrap()
|
|
||||||
.format(DATE_TIME_FORMAT) // @TODO optional
|
|
||||||
.unwrap_or(DEFAULT.into()),
|
|
||||||
)
|
|
||||||
.build(),
|
.build(),
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
@ -228,28 +198,22 @@ impl Column for gtk::ColumnViewColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn access_date_time(width: i32) -> Self {
|
fn access_date_time(width: i32) -> Self {
|
||||||
gtk::ColumnViewColumn::builder()
|
ColumnViewColumn::builder()
|
||||||
.fixed_width(width)
|
.fixed_width(width)
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
.title("Accessed")
|
.title("Accessed")
|
||||||
.factory(&{
|
.factory(&{
|
||||||
let factory = gtk::SignalListItemFactory::new();
|
let factory = SignalListItemFactory::new();
|
||||||
factory.connect_bind(|_, this| {
|
factory.connect_bind(|_, this| {
|
||||||
use gtk::prelude::{Cast, ListItemExt};
|
use gtk::prelude::{Cast, ListItemExt};
|
||||||
let list_item = this.downcast_ref::<gtk::ListItem>().unwrap();
|
let list_item = this.downcast_ref::<ListItem>().unwrap();
|
||||||
let item = list_item.item().unwrap();
|
let item = list_item.item().unwrap();
|
||||||
let file_info = item.downcast_ref::<gtk::gio::FileInfo>().unwrap();
|
let file_info = item.downcast_ref::<FileInfo>().unwrap();
|
||||||
list_item.set_child(Some(
|
list_item.set_child(Some(
|
||||||
>k::Label::builder()
|
&Label::builder()
|
||||||
.halign(gtk::Align::Start)
|
.halign(Align::Start)
|
||||||
.ellipsize(gtk::pango::EllipsizeMode::Middle)
|
.ellipsize(EllipsizeMode::Middle)
|
||||||
.label(
|
.label(file_info.format_date_time())
|
||||||
file_info
|
|
||||||
.access_date_time()
|
|
||||||
.unwrap()
|
|
||||||
.format(DATE_TIME_FORMAT) // @TODO optional
|
|
||||||
.unwrap_or(DEFAULT.into()),
|
|
||||||
)
|
|
||||||
.build(),
|
.build(),
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
use gtk::gio::FileType;
|
||||||
|
|
||||||
|
pub trait Display {
|
||||||
|
fn as_str(&self) -> &str;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for FileType {
|
||||||
|
fn as_str(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
FileType::Unknown => "Unknown",
|
||||||
|
FileType::Regular => "File",
|
||||||
|
FileType::Directory => "Directory",
|
||||||
|
FileType::SymbolicLink => "SymbolicLink",
|
||||||
|
FileType::Special => "Special",
|
||||||
|
FileType::Shortcut => "Shortcut",
|
||||||
|
FileType::Mountable => "Mountable",
|
||||||
|
_ => "Undefined",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
use gtk::{gio::FileInfo, glib::GString};
|
||||||
|
|
||||||
|
const DEFAULT: &str = "-";
|
||||||
|
|
||||||
|
pub trait Format {
|
||||||
|
fn format_content_type(&self) -> GString;
|
||||||
|
fn format_date_time(&self) -> GString;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format for FileInfo {
|
||||||
|
fn format_content_type(&self) -> GString {
|
||||||
|
match self.content_type() {
|
||||||
|
Some(content_type) => {
|
||||||
|
let display_name = self.display_name();
|
||||||
|
if content_type == "text/plain" {
|
||||||
|
if display_name.ends_with(".gmi") || display_name.ends_with(".gemini") {
|
||||||
|
"text/gemini".into()
|
||||||
|
} else {
|
||||||
|
content_type
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
content_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => DEFAULT.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn format_date_time(&self) -> GString {
|
||||||
|
match self.creation_date_time() {
|
||||||
|
Some(date_time) => date_time
|
||||||
|
.format("%Y.%m.%d %H:%M:%S") // @TODO optional
|
||||||
|
.unwrap_or(DEFAULT.into()),
|
||||||
|
None => DEFAULT.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue