models: Use splice on initial loading

Avoids calling items-changed multiple times
This commit is contained in:
Bilal Elmoussaoui 2022-06-11 11:10:46 +02:00
parent 2d05b5057a
commit a13930ba65
5 changed files with 44 additions and 20 deletions

View file

@ -45,7 +45,7 @@ impl AccountsModel {
glib::Object::new(&[]).expect("Failed to create AccountsModel")
}
pub fn insert(&self, account: &Account) {
pub fn append(&self, account: &Account) {
let pos = {
let mut data = self.imp().0.borrow_mut();
data.push(account.clone());
@ -54,6 +54,17 @@ impl AccountsModel {
self.items_changed(pos, 0, 1);
}
pub fn splice(&self, accounts: &[Account]) {
let len = accounts.len();
let pos = {
let mut data = self.imp().0.borrow_mut();
let pos = data.len();
data.extend_from_slice(accounts);
pos as u32
};
self.items_changed(pos, 0, len as u32);
}
pub fn remove(&self, pos: u32) {
self.imp().0.borrow_mut().remove(pos as usize);
self.items_changed(pos, 1, 0);

View file

@ -343,7 +343,8 @@ impl Provider {
.into_iter()
.map(From::from)
.map(|p: Provider| {
Account::load(&p).unwrap().for_each(|a| p.add_account(&a));
let accounts = Account::load(&p).unwrap().collect::<Vec<_>>();
p.add_accounts(&accounts);
p
});
Ok(results)
@ -585,6 +586,9 @@ impl Provider {
}
fn setup_tick_callback(&self) {
if self.imp().tick_callback.borrow().is_some() || !self.method().is_time_based() {
return;
}
self.set_property("remaining-time", &(self.period() as u64));
match self.method() {
@ -611,19 +615,18 @@ impl Provider {
}
}
pub fn has_account(&self, account: &Account) -> Option<u32> {
self.imp().accounts.find_position_by_id(account.id())
}
pub fn has_accounts(&self) -> bool {
self.imp().accounts.n_items() != 0
}
fn add_accounts(&self, accounts: &[Account]) {
self.imp().accounts.splice(accounts);
self.setup_tick_callback();
}
pub fn add_account(&self, account: &Account) {
self.imp().accounts.insert(account);
if self.imp().tick_callback.borrow().is_none() && self.method().is_time_based() {
self.setup_tick_callback();
}
self.imp().accounts.append(account);
self.setup_tick_callback();
}
pub fn accounts_model(&self) -> &AccountsModel {

View file

@ -89,14 +89,14 @@ impl ProvidersModel {
help_url,
image_uri,
)?;
self.add_provider(&p);
self.append(&p);
p
}
};
Ok(provider)
}
pub fn find_by_name(&self, name: &str) -> Option<Provider> {
fn find_by_name(&self, name: &str) -> Option<Provider> {
for pos in 0..self.n_items() {
let obj = self.item(pos)?;
let provider = obj.downcast::<Provider>().unwrap();
@ -144,7 +144,7 @@ impl ProvidersModel {
store
}
pub fn add_provider(&self, provider: &Provider) {
pub fn append(&self, provider: &Provider) {
let pos = {
let mut data = self.imp().0.borrow_mut();
data.push(provider.clone());
@ -153,6 +153,17 @@ impl ProvidersModel {
self.items_changed(pos, 0, 1);
}
fn splice(&self, providers: &[Provider]) {
let len = providers.len();
let pos = {
let mut data = self.imp().0.borrow_mut();
let pos = data.len();
data.extend_from_slice(providers);
pos as u32
};
self.items_changed(pos, 0, len as u32);
}
pub fn delete_provider(&self, provider: &Provider) {
let mut provider_pos = None;
for pos in 0..self.n_items() {
@ -185,7 +196,7 @@ impl ProvidersModel {
}
if !found {
provider.add_account(account);
self.add_provider(provider);
self.append(provider);
}
}
@ -212,11 +223,10 @@ impl ProvidersModel {
}
tracing::info!("Loading providers");
// fill in the providers from the database
Provider::load()
let providers = Provider::load()
.expect("Failed to load providers from the database")
.for_each(|provider| {
self.add_provider(&provider);
});
.collect::<Vec<_>>();
self.splice(&providers);
self.imp().1.set(true);
}
}

View file

@ -292,7 +292,7 @@ impl AccountAddDialog {
imp.provider_page.connect_local("created", false, clone!(@weak dialog, @weak model => @default-panic, move |args| {
let provider = args[1].get::<Provider>().unwrap();
model.add_provider(&provider);
model.append(&provider);
dialog.imp().provider_completion
.set_model(Some(&model.completion_model()));

View file

@ -170,7 +170,7 @@ impl ProvidersDialog {
false,
clone!(@weak model, @weak self as dialog => @default-return None, move |args| {
let provider = args[1].get::<Provider>().unwrap();
model.add_provider(&provider);
model.append(&provider);
dialog.emit_by_name::<()>("changed", &[]);
dialog.imp().toast_overlay.add_toast(&adw::Toast::new(&gettext("Provider created successfully")));
dialog.set_view(View::Placeholder);