Skip to content

Commit

Permalink
models: Add LogListModel list model for exposing backend logs to UI
Browse files Browse the repository at this point in the history
The model implements the backend::Log trait
The LogItem GObject is also provided as the model object type
  • Loading branch information
rafaelmardojai committed Mar 6, 2023
1 parent 53fee05 commit 2021c8f
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 0 deletions.
43 changes: 43 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ edition = "2018"
adw = { package = "libadwaita", version = "0.3", features = ["v1_2"] }
image = "0.24"
log = "0.4"
im-rc = "15.1.0"
pretty_env_logger = "0.4"
gettext-rs = { version = "0.6", features = ["gettext-system"] }
gtk = { package = "gtk4", version = "0.6", features = ["v4_8"] }
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod application;
mod backend;
#[rustfmt::skip]
mod config;
mod models;
mod widgets;
mod window;

Expand Down
3 changes: 3 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ sources = files(
'backend/mod.rs',
'backend/scraper.rs',
'backend/social.rs',
'models/log_item.rs',
'models/log_model.rs',
'models/mod.rs',
'widgets/card.rs',
'widgets/image.rs',
'widgets/metadata_item.rs',
Expand Down
65 changes: 65 additions & 0 deletions src/models/log_item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2023 Rafael Mardojai CM
// SPDX-License-Identifier: GPL-3.0-or-later

use std::cell::RefCell;
use std::convert::TryFrom;

use glib::subclass::prelude::*;
use gtk::{
glib::{self, ParamSpec, Properties, Value},
prelude::*,
};

use crate::backend::LogLevel;

mod imp {
use super::*;

#[derive(Default, Properties)]
#[properties(wrapper_type = super::LogItem)]
pub struct LogItem {
pub level: RefCell<LogLevel>,
#[property(get, set)]
text: RefCell<Option<String>>,
}

#[glib::object_subclass]
impl ObjectSubclass for LogItem {
const NAME: &'static str = "LogItem";
type Type = super::LogItem;
}

impl ObjectImpl for LogItem {
fn properties() -> &'static [ParamSpec] {
Self::derived_properties()
}

fn set_property(&self, id: usize, value: &Value, pspec: &ParamSpec) {
self.derived_set_property(id, value, pspec)
}

fn property(&self, id: usize, pspec: &ParamSpec) -> Value {
self.derived_property(id, pspec)
}
}
}

glib::wrapper! {
pub struct LogItem(ObjectSubclass<imp::LogItem>);
}

impl LogItem {
pub fn new(level: LogLevel, text: &str) -> LogItem {
let item: LogItem = glib::Object::builder()
.property("text", text)
.build();

*item.imp().level.borrow_mut() = level;

item
}

pub fn level(&self) -> LogLevel {
*self.imp().level.borrow()
}
}
86 changes: 86 additions & 0 deletions src/models/log_model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright 2023 Rafael Mardojai CM
// SPDX-License-Identifier: GPL-3.0-or-later

use std::cell::RefCell;

use gio::subclass::prelude::*;
use gtk::{gio, glib, prelude::*};

use im_rc::Vector;

use crate::backend::{Log, LogLevel};
use super::LogItem;

mod imp {
use super::*;

#[derive(Debug, Default)]
pub struct LogListModel(pub(super) RefCell<Vector<LogItem>>);

#[glib::object_subclass]
impl ObjectSubclass for LogListModel {
const NAME: &'static str = "LogListModel";
type Type = super::LogListModel;
type Interfaces = (gio::ListModel,);
}

impl ObjectImpl for LogListModel {}

impl ListModelImpl for LogListModel {
fn item_type(&self) -> glib::Type {
LogItem::static_type()
}

fn n_items(&self) -> u32 {
self.0.borrow().len() as u32
}

fn item(&self, position: u32) -> Option<glib::Object> {
self.0
.borrow()
.get(position as usize)
.map(|o| o.clone().upcast::<glib::Object>())
}
}
}

glib::wrapper! {
pub struct LogListModel(ObjectSubclass<imp::LogListModel>) @implements gio::ListModel;
}

impl LogListModel {
pub fn new() -> LogListModel {
glib::Object::new()
}

pub fn append(&self, obj: &LogItem) {
let index = {
let mut data = self.imp().0.borrow_mut();
data.push_back(obj.clone());
data.len() - 1
};

// Emit change signal
self.items_changed(index as u32, 0, 1);
}

pub fn clear(&self) {
let length: u32 = self.imp().n_items();

// Clear inner vector
self.imp().0.borrow_mut().clear();
// Emit change signal
self.items_changed(0, length, 0);
}
}

impl Log for LogListModel {
fn log(&self, level: LogLevel, text: String) {
let item = LogItem::new(level, &text);
self.append(&item);
}

fn flush(&self) {
self.clear();
}
}
7 changes: 7 additions & 0 deletions src/models/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub mod log_item;
pub mod log_model;

pub use self::{
log_item::LogItem,
log_model::LogListModel,
};

0 comments on commit 2021c8f

Please sign in to comment.