sidebar: Rename Entry to IconItem

Entry is confusing because GtkEntry is where we input text.
This commit is contained in:
Kévin Commaille 2023-11-19 17:58:22 +01:00
parent eeb9d6f5ae
commit d6d2c43c71
No known key found for this signature in database
GPG key ID: 29A48C1F03620416
13 changed files with 123 additions and 126 deletions

View file

@ -289,12 +289,12 @@ sidebar-row:not(.drop-mode) > *:hover {
background-color: alpha(currentColor, 0.19);
}
sidebar-row sidebar-entry {
sidebar-row icon-item {
background: none;
font-weight: bold;
}
sidebar-row sidebar-entry image {
sidebar-row icon-item image {
min-width: 24px; /* Same width as avatars, so the text is aligned */
}
@ -345,7 +345,7 @@ sidebar-row.drop-empty > * {
color: @accent_color;
}
sidebar-row entry.forget {
sidebar-row icon-item.forget {
color: @error_color;
background: none;
}

View file

@ -31,7 +31,7 @@ src/session/model/room/member_role.rs
src/session/model/room/mod.rs
src/session/model/room_list/mod.rs
src/session/model/sidebar/category/category_type.rs
src/session/model/sidebar/entry/entry_type.rs
src/session/model/sidebar/icon_item.rs
src/session/view/account_settings/devices_page/device_list.rs
src/session/view/account_settings/devices_page/device_row.rs
src/session/view/account_settings/devices_page/device_row.ui

View file

@ -21,7 +21,7 @@ pub use self::{
session::{Session, SessionState},
settings::SessionSettings,
sidebar::{
Category, CategoryType, Entry, EntryType, ItemList, Selection, SidebarItem,
Category, CategoryType, IconItem, ItemList, ItemType, Selection, SidebarItem,
SidebarItemImpl, SidebarListModel,
},
user::{User, UserActions, UserExt},

View file

@ -1,24 +0,0 @@
use std::fmt;
use gettextrs::gettext;
use gtk::glib;
#[derive(Debug, Default, Hash, Eq, PartialEq, Clone, Copy, glib::Enum)]
#[repr(u32)]
#[enum_type(name = "EntryType")]
pub enum EntryType {
#[default]
Explore = 0,
Forget = 1,
}
impl fmt::Display for EntryType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let label = match self {
EntryType::Explore => gettext("Explore"),
EntryType::Forget => gettext("Forget Room"),
};
f.write_str(&label)
}
}

View file

@ -1,33 +1,63 @@
use std::fmt;
use gettextrs::gettext;
use gtk::{glib, prelude::*, subclass::prelude::*};
mod entry_type;
pub use self::entry_type::EntryType;
use super::{CategoryType, SidebarItem, SidebarItemExt, SidebarItemImpl};
#[derive(Debug, Default, Hash, Eq, PartialEq, Clone, Copy, glib::Enum)]
#[repr(u32)]
#[enum_type(name = "ItemType")]
pub enum ItemType {
#[default]
Explore = 0,
Forget = 1,
}
impl ItemType {
/// The icon name for this item type.
pub fn icon_name(&self) -> &'static str {
match self {
Self::Explore => "explore-symbolic",
Self::Forget => "user-trash-symbolic",
}
}
}
impl fmt::Display for ItemType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let label = match self {
Self::Explore => gettext("Explore"),
Self::Forget => gettext("Forget Room"),
};
f.write_str(&label)
}
}
mod imp {
use std::cell::Cell;
use super::*;
#[derive(Debug, Default)]
pub struct Entry {
pub type_: Cell<EntryType>,
pub struct IconItem {
pub type_: Cell<ItemType>,
}
#[glib::object_subclass]
impl ObjectSubclass for Entry {
const NAME: &'static str = "Entry";
type Type = super::Entry;
impl ObjectSubclass for IconItem {
const NAME: &'static str = "IconItem";
type Type = super::IconItem;
type ParentType = SidebarItem;
}
impl ObjectImpl for Entry {
impl ObjectImpl for IconItem {
fn properties() -> &'static [glib::ParamSpec] {
use once_cell::sync::Lazy;
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
vec![
glib::ParamSpecEnum::builder::<EntryType>("type")
glib::ParamSpecEnum::builder::<ItemType>("type")
.construct_only()
.build(),
glib::ParamSpecString::builder("display-name")
@ -63,46 +93,40 @@ mod imp {
}
}
impl SidebarItemImpl for Entry {
impl SidebarItemImpl for IconItem {
fn update_visibility(&self, for_category: CategoryType) {
let obj = self.obj();
match obj.type_() {
EntryType::Explore => obj.set_visible(true),
EntryType::Forget => obj.set_visible(for_category == CategoryType::Left),
ItemType::Explore => obj.set_visible(true),
ItemType::Forget => obj.set_visible(for_category == CategoryType::Left),
}
}
}
}
glib::wrapper! {
/// A top-level row in the sidebar without children.
///
/// Entry is supposed to be used in a TreeListModel, but as it does not have
/// any children, implementing the ListModel interface is not required.
pub struct Entry(ObjectSubclass<imp::Entry>) @extends SidebarItem;
/// A top-level row in the sidebar with an icon.
pub struct IconItem(ObjectSubclass<imp::IconItem>) @extends SidebarItem;
}
impl Entry {
pub fn new(type_: EntryType) -> Self {
impl IconItem {
pub fn new(type_: ItemType) -> Self {
glib::Object::builder().property("type", type_).build()
}
/// The type of this entry.
pub fn type_(&self) -> EntryType {
/// The type of this item.
pub fn type_(&self) -> ItemType {
self.imp().type_.get()
}
/// The display name of this entry.
/// The display name of this item.
pub fn display_name(&self) -> String {
self.type_().to_string()
}
/// The icon name used for this entry.
pub fn icon_name(&self) -> Option<&str> {
match self.type_() {
EntryType::Explore => Some("explore-symbolic"),
EntryType::Forget => Some("user-trash-symbolic"),
}
/// The icon name used for this item.
pub fn icon_name(&self) -> &'static str {
self.type_().icon_name()
}
}

View file

@ -1,6 +1,6 @@
use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*};
use super::{Category, CategoryType, Entry, EntryType, SidebarItem, SidebarItemExt};
use super::{Category, CategoryType, IconItem, ItemType, SidebarItem, SidebarItemExt};
use crate::session::model::{RoomList, VerificationList};
mod imp {
@ -77,14 +77,14 @@ mod imp {
let verification_list = obj.verification_list();
let list: [SidebarItem; 8] = [
Entry::new(EntryType::Explore).upcast(),
IconItem::new(ItemType::Explore).upcast(),
Category::new(CategoryType::VerificationRequest, verification_list).upcast(),
Category::new(CategoryType::Invited, room_list).upcast(),
Category::new(CategoryType::Favorite, room_list).upcast(),
Category::new(CategoryType::Normal, room_list).upcast(),
Category::new(CategoryType::LowPriority, room_list).upcast(),
Category::new(CategoryType::Left, room_list).upcast(),
Entry::new(EntryType::Forget).upcast(),
IconItem::new(ItemType::Forget).upcast(),
];
self.list.set(list.clone()).unwrap();

View file

@ -1,5 +1,5 @@
mod category;
mod entry;
mod icon_item;
mod item;
mod item_list;
mod list_model;
@ -7,7 +7,7 @@ mod selection;
pub use self::{
category::{Category, CategoryType},
entry::{Entry, EntryType},
icon_item::{IconItem, ItemType},
item::{SidebarItem, SidebarItemExt, SidebarItemImpl},
item_list::ItemList,
list_model::SidebarListModel,

View file

@ -12,7 +12,7 @@ use self::{
verification::IdentityVerificationWidget,
};
use crate::session::model::{
Entry, EntryType, IdentityVerification, Room, RoomType, Session, VerificationMode,
IconItem, IdentityVerification, ItemType, Room, RoomType, Session, VerificationMode,
};
mod imp {
@ -252,8 +252,8 @@ impl Content {
}
}
Some(o)
if o.is::<Entry>()
&& o.downcast_ref::<Entry>().unwrap().type_() == EntryType::Explore =>
if o.downcast_ref::<IconItem>()
.is_some_and(|i| i.type_() == ItemType::Explore) =>
{
imp.explore.init();
imp.stack.set_visible_child(&*imp.explore);

View file

@ -1,7 +1,7 @@
use adw::subclass::prelude::BinImpl;
use gtk::{self, glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use crate::session::model::{Entry, EntryType};
use crate::session::model::{IconItem, ItemType};
mod imp {
use std::cell::RefCell;
@ -11,20 +11,20 @@ mod imp {
use super::*;
#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/org/gnome/Fractal/ui/session/view/sidebar/entry_row.ui")]
pub struct EntryRow {
pub entry: RefCell<Option<Entry>>,
#[template(resource = "/org/gnome/Fractal/ui/session/view/sidebar/icon_item_row.ui")]
pub struct IconItemRow {
pub icon_item: RefCell<Option<IconItem>>,
}
#[glib::object_subclass]
impl ObjectSubclass for EntryRow {
const NAME: &'static str = "SidebarEntryRow";
type Type = super::EntryRow;
impl ObjectSubclass for IconItemRow {
const NAME: &'static str = "SidebarIconItemRow";
type Type = super::IconItemRow;
type ParentType = adw::Bin;
fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass);
klass.set_css_name("sidebar-entry");
klass.set_css_name("icon-item");
}
fn instance_init(obj: &InitializingObject<Self>) {
@ -32,11 +32,11 @@ mod imp {
}
}
impl ObjectImpl for EntryRow {
impl ObjectImpl for IconItemRow {
fn properties() -> &'static [glib::ParamSpec] {
use once_cell::sync::Lazy;
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
vec![glib::ParamSpecObject::builder::<Entry>("entry")
vec![glib::ParamSpecObject::builder::<IconItem>("icon-item")
.explicit_notify()
.build()]
});
@ -46,54 +46,54 @@ mod imp {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"entry" => self.obj().set_entry(value.get().unwrap()),
"icon-item" => self.obj().set_icon_item(value.get().unwrap()),
_ => unimplemented!(),
}
}
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"entry" => self.obj().entry().to_value(),
"icon-item" => self.obj().icon_item().to_value(),
_ => unimplemented!(),
}
}
}
impl WidgetImpl for EntryRow {}
impl BinImpl for EntryRow {}
impl WidgetImpl for IconItemRow {}
impl BinImpl for IconItemRow {}
}
glib::wrapper! {
pub struct EntryRow(ObjectSubclass<imp::EntryRow>)
pub struct IconItemRow(ObjectSubclass<imp::IconItemRow>)
@extends gtk::Widget, adw::Bin, @implements gtk::Accessible;
}
impl EntryRow {
impl IconItemRow {
pub fn new() -> Self {
glib::Object::new()
}
/// The entry of this row.
pub fn entry(&self) -> Option<Entry> {
self.imp().entry.borrow().clone()
/// The [`IconItem`] of this row.
pub fn icon_item(&self) -> Option<IconItem> {
self.imp().icon_item.borrow().clone()
}
/// Set the entry of this row.
pub fn set_entry(&self, entry: Option<Entry>) {
if self.entry() == entry {
/// Set the [`IconItem`] of this row.
pub fn set_icon_item(&self, icon_item: Option<IconItem>) {
if self.icon_item() == icon_item {
return;
}
if entry
if icon_item
.as_ref()
.map_or(false, |e| e.type_() == EntryType::Forget)
.is_some_and(|i| i.type_() == ItemType::Forget)
{
self.add_css_class("forget");
} else {
self.remove_css_class("forget");
}
self.imp().entry.replace(entry);
self.notify("entry");
self.imp().icon_item.replace(icon_item);
self.notify("icon-item");
}
}

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="SidebarEntryRow" parent="AdwBin">
<template class="SidebarIconItemRow" parent="AdwBin">
<child>
<object class="GtkBox">
<property name="spacing">12</property>
<child>
<object class="GtkImage">
<binding name="icon-name">
<lookup name="icon-name" type="Entry">
<lookup name="entry">SidebarEntryRow</lookup>
<lookup name="icon-name" type="IconItem">
<lookup name="icon-item">SidebarIconItemRow</lookup>
</lookup>
</binding>
<property name="accessible-role">presentation</property>
@ -20,8 +20,8 @@
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<binding name="label">
<lookup name="display-name" type="Entry">
<lookup name="entry">SidebarEntryRow</lookup>
<lookup name="display-name" type="IconItem">
<lookup name="icon-item">SidebarIconItemRow</lookup>
</lookup>
</binding>
</object>

View file

@ -1,5 +1,5 @@
mod category_row;
mod entry_row;
mod icon_item_row;
mod room_row;
mod row;
mod verification_row;
@ -9,14 +9,14 @@ use gtk::{gio, glib, glib::clone, CompositeTemplate};
use tracing::error;
use self::{
category_row::CategoryRow, entry_row::EntryRow, room_row::RoomRow, row::Row,
category_row::CategoryRow, icon_item_row::IconItemRow, room_row::RoomRow, row::Row,
verification_row::VerificationRow,
};
use crate::{
components::Avatar,
prelude::*,
session::model::{
Category, CategoryType, Entry, IdentityVerification, Room, RoomType, Selection,
Category, CategoryType, IconItem, IdentityVerification, Room, RoomType, Selection,
SidebarListModel, User,
},
Window,
@ -162,7 +162,7 @@ mod imp {
match row.item() {
Some(o) if o.is::<Category>() => row.set_expanded(!row.is_expanded()),
Some(o) if o.is::<Room>() => model.set_selected(pos),
Some(o) if o.is::<Entry>() => model.set_selected(pos),
Some(o) if o.is::<IconItem>() => model.set_selected(pos),
Some(o) if o.is::<IdentityVerification>() => model.set_selected(pos),
_ => {}
}

View file

@ -2,10 +2,11 @@ use adw::{prelude::*, subclass::prelude::*};
use gettextrs::gettext;
use gtk::{gdk, glib, glib::clone};
use super::{CategoryRow, EntryRow, RoomRow, Sidebar, VerificationRow};
use super::{CategoryRow, IconItemRow, RoomRow, Sidebar, VerificationRow};
use crate::{
session::model::{
Category, CategoryType, Entry, EntryType, IdentityVerification, Room, RoomType, SidebarItem,
Category, CategoryType, IconItem, IdentityVerification, ItemType, Room, RoomType,
SidebarItem,
},
spawn, toast,
utils::{message_dialog, BoundObjectWeakRef},
@ -204,20 +205,16 @@ impl Row {
};
child.set_room(Some(room.clone()));
} else if let Some(entry) = item.downcast_ref::<Entry>() {
let child = if let Some(child) = self.child().and_downcast::<EntryRow>() {
} else if let Some(icon_item) = item.downcast_ref::<IconItem>() {
let child = if let Some(child) = self.child().and_downcast::<IconItemRow>() {
child
} else {
let child = EntryRow::new();
let child = IconItemRow::new();
self.set_child(Some(&child));
child
};
if entry.type_() == EntryType::Forget {
self.add_css_class("forget");
}
child.set_entry(Some(entry.clone()));
child.set_icon_item(Some(icon_item.clone()));
} else if let Some(verification) = item.downcast_ref::<IdentityVerification>() {
let child = if let Some(child) = self.child().and_downcast::<VerificationRow>() {
child
@ -255,13 +252,13 @@ impl Row {
}
}
/// Get the `EntryType` of this item.
/// Get the [`ItemType`] of this item.
///
/// If this is not a `Entry`, returns `None`.
pub fn entry_type(&self) -> Option<EntryType> {
/// If this is not an [`IconItem`], returns `None`.
pub fn item_type(&self) -> Option<ItemType> {
self.item()
.and_downcast_ref::<Entry>()
.map(|entry| entry.type_())
.and_downcast_ref::<IconItem>()
.map(|i| i.type_())
}
/// Handle the drag-n-drop hovering this row.
@ -278,8 +275,8 @@ impl Row {
.set_drop_active_target_type(Some(target_type));
return true;
}
} else if let Some(entry_type) = self.entry_type() {
if room.category() == RoomType::Left && entry_type == EntryType::Forget {
} else if let Some(item_type) = self.item_type() {
if room.category() == RoomType::Left && item_type == ItemType::Forget {
self.add_css_class("drop-active");
self.sidebar().set_drop_active_target_type(None);
return true;
@ -306,9 +303,9 @@ impl Row {
}));
ret = true;
}
} else if let Some(entry_type) = self.entry_type() {
if room.category() == RoomType::Left && entry_type == EntryType::Forget {
spawn!(clone!(@weak self as obj, @weak room => async move {
} else if let Some(item_type) = self.item_type() {
if room.category() == RoomType::Left && item_type == ItemType::Forget {
spawn!(clone!(@strong self as obj, @weak room => async move {
obj.forget_room(&room).await;
}));
ret = true;
@ -377,10 +374,10 @@ impl Row {
self.remove_css_class("drop-empty");
}
} else {
let is_forget_entry = self
.entry_type()
.map_or(false, |entry_type| entry_type == EntryType::Forget);
if is_forget_entry && source_type == RoomType::Left {
let is_forget_item = self
.item_type()
.is_some_and(|item_type| item_type == ItemType::Forget);
if is_forget_item && source_type == RoomType::Left {
self.remove_css_class("drop-disabled");
} else {
self.add_css_class("drop-disabled");

View file

@ -96,7 +96,7 @@
<file compressed="true" preprocess="xml-stripblanks">session/view/room_creation.ui</file>
<file compressed="true" preprocess="xml-stripblanks">session/view/session_view.ui</file>
<file compressed="true" preprocess="xml-stripblanks">session/view/sidebar/category_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">session/view/sidebar/entry_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">session/view/sidebar/icon_item_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">session/view/sidebar/mod.ui</file>
<file compressed="true" preprocess="xml-stripblanks">session/view/sidebar/room_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">session/view/sidebar/verification_row.ui</file>