mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2026-08-17 16:34:54 -05:00
fix: memory leaks in multiple dialogs due to reference cycles (#855)
This commit is contained in:
@@ -9,7 +9,8 @@ use gtk::{
|
|||||||
gdk,
|
gdk,
|
||||||
glib::{subclass::types::ObjectSubclassIsExt, types::StaticType, value::ToValue},
|
glib::{subclass::types::ObjectSubclassIsExt, types::StaticType, value::ToValue},
|
||||||
prelude::{
|
prelude::{
|
||||||
AdjustmentExt, BoxExt, ButtonExt, CheckButtonExt, OrientableExt, PopoverExt, WidgetExt,
|
AdjustmentExt, BoxExt, ButtonExt, CheckButtonExt, ObjectExt, OrientableExt, PopoverExt,
|
||||||
|
WidgetExt,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use i18n_embed_fl::fl;
|
use i18n_embed_fl::fl;
|
||||||
@@ -108,17 +109,23 @@ impl relm4::factory::FactoryComponent for PlotComponent {
|
|||||||
set_actions: gdk::DragAction::MOVE,
|
set_actions: gdk::DragAction::MOVE,
|
||||||
set_types: &[DynamicIndexValue::static_type()],
|
set_types: &[DynamicIndexValue::static_type()],
|
||||||
|
|
||||||
connect_enter[root] => move |_, _, _| {
|
connect_enter[root = root.downgrade()] => move |_, _, _| {
|
||||||
root.set_opacity(0.5);
|
if let Some(root) = root.upgrade() {
|
||||||
|
root.set_opacity(0.5);
|
||||||
|
}
|
||||||
gdk::DragAction::MOVE
|
gdk::DragAction::MOVE
|
||||||
},
|
},
|
||||||
|
|
||||||
connect_leave[root] => move |_| {
|
connect_leave[root = root.downgrade()] => move |_| {
|
||||||
root.set_opacity(1.0);
|
if let Some(root) = root.upgrade() {
|
||||||
|
root.set_opacity(1.0);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
connect_drop[root, index, sender] => move |_, value, _, _| {
|
connect_drop[root = root.downgrade(), index, sender] => move |_, value, _, _| {
|
||||||
root.set_opacity(1.0);
|
if let Some(root) = root.upgrade() {
|
||||||
|
root.set_opacity(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
if let Ok(DynamicIndexValue(source_index)) = value.get::<DynamicIndexValue>() {
|
if let Ok(DynamicIndexValue(source_index)) = value.get::<DynamicIndexValue>() {
|
||||||
sender.output(GraphsWindowMsg::SwapPlots(index.clone(), source_index)).unwrap();
|
sender.output(GraphsWindowMsg::SwapPlots(index.clone(), source_index)).unwrap();
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ use relm4::{
|
|||||||
factory::FactoryVecDeque,
|
factory::FactoryVecDeque,
|
||||||
prelude::DynamicIndex,
|
prelude::DynamicIndex,
|
||||||
typed_view::list::{RelmListItem, TypedListView},
|
typed_view::list::{RelmListItem, TypedListView},
|
||||||
Component, ComponentController, ComponentParts, ComponentSender, RelmIterChildrenExt,
|
Component, ComponentParts, ComponentSender, RelmIterChildrenExt, RelmWidgetExt,
|
||||||
RelmWidgetExt,
|
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
@@ -35,6 +34,8 @@ pub struct Header {
|
|||||||
selector_label: String,
|
selector_label: String,
|
||||||
system_info: SystemInfo,
|
system_info: SystemInfo,
|
||||||
device_flags: Vec<DeviceFlag>,
|
device_flags: Vec<DeviceFlag>,
|
||||||
|
|
||||||
|
new_profile_diag: Option<relm4::Controller<NewProfileDialog>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -302,6 +303,7 @@ impl Component for Header {
|
|||||||
profiles_info: ProfilesInfo::default(),
|
profiles_info: ProfilesInfo::default(),
|
||||||
system_info,
|
system_info,
|
||||||
device_flags: Vec::new(),
|
device_flags: Vec::new(),
|
||||||
|
new_profile_diag: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let gpu_selector = &model.gpu_selector.view;
|
let gpu_selector = &model.gpu_selector.view;
|
||||||
@@ -395,12 +397,13 @@ impl Component for Header {
|
|||||||
HeaderMsg::CreateProfile => {
|
HeaderMsg::CreateProfile => {
|
||||||
sender.input(HeaderMsg::ClosePopover);
|
sender.input(HeaderMsg::ClosePopover);
|
||||||
|
|
||||||
let mut diag_controller = NewProfileDialog::builder()
|
let diag_controller = NewProfileDialog::builder()
|
||||||
.launch(self.custom_profiles())
|
.launch(self.custom_profiles())
|
||||||
.forward(sender.output_sender(), |(name, base)| {
|
.forward(sender.output_sender(), |(name, base)| {
|
||||||
AppMsg::CreateProfile(name, base)
|
AppMsg::CreateProfile(name, base)
|
||||||
});
|
});
|
||||||
diag_controller.detach_runtime();
|
|
||||||
|
self.new_profile_diag = Some(diag_controller);
|
||||||
}
|
}
|
||||||
HeaderMsg::RenameProfile(index) => {
|
HeaderMsg::RenameProfile(index) => {
|
||||||
sender.input(HeaderMsg::ClosePopover);
|
sender.input(HeaderMsg::ClosePopover);
|
||||||
|
|||||||
@@ -67,8 +67,10 @@ impl Component for NewProfileDialog {
|
|||||||
set_label: &fl!(I18N, "cancel"),
|
set_label: &fl!(I18N, "cancel"),
|
||||||
set_hexpand: true,
|
set_hexpand: true,
|
||||||
|
|
||||||
connect_clicked[root] => move |_| {
|
connect_clicked[root = root.downgrade()] => move |_| {
|
||||||
root.hide();
|
if let Some(root) = root.upgrade() {
|
||||||
|
root.close();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -122,7 +124,7 @@ impl Component for NewProfileDialog {
|
|||||||
.output((self.name_buffer.text().to_string(), base))
|
.output((self.name_buffer.text().to_string(), base))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
root.hide();
|
root.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ pub mod profile_row;
|
|||||||
|
|
||||||
use crate::app::{msg::AppMsg, APP_BROKER};
|
use crate::app::{msg::AppMsg, APP_BROKER};
|
||||||
use crate::I18N;
|
use crate::I18N;
|
||||||
|
use gtk::prelude::ObjectExt;
|
||||||
use gtk::{
|
use gtk::{
|
||||||
pango,
|
pango,
|
||||||
prelude::{
|
prelude::{
|
||||||
@@ -64,14 +65,16 @@ impl relm4::Component for ProfileRuleWindow {
|
|||||||
set_default_size: (600, 300),
|
set_default_size: (600, 300),
|
||||||
set_title: Some(&fl!(I18N, "profile-rules")),
|
set_title: Some(&fl!(I18N, "profile-rules")),
|
||||||
set_transient_for: Some(&root_window),
|
set_transient_for: Some(&root_window),
|
||||||
connect_response[root, sender] => move |_, response| {
|
connect_response[root = root.downgrade(), sender] => move |_, response| {
|
||||||
match response {
|
if let Some(root) = root.upgrade() {
|
||||||
gtk::ResponseType::Accept => {
|
match response {
|
||||||
sender.input(ProfileRuleWindowMsg::Save);
|
gtk::ResponseType::Accept => {
|
||||||
root.close();
|
sender.input(ProfileRuleWindowMsg::Save);
|
||||||
|
root.close();
|
||||||
|
}
|
||||||
|
gtk::ResponseType::Cancel => root.close(),
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
gtk::ResponseType::Cancel => root.close(),
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ pub struct SoftwarePage {
|
|||||||
|
|
||||||
vulkan_driver_selector: relm4::Controller<SimpleComboBox<String>>,
|
vulkan_driver_selector: relm4::Controller<SimpleComboBox<String>>,
|
||||||
opencl_platform_selector: relm4::Controller<SimpleComboBox<String>>,
|
opencl_platform_selector: relm4::Controller<SimpleComboBox<String>>,
|
||||||
|
|
||||||
|
vulkan_window: Option<relm4::Controller<VulkanFeaturesWindow>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -250,6 +252,7 @@ impl relm4::SimpleComponent for SoftwarePage {
|
|||||||
device_info: None,
|
device_info: None,
|
||||||
vulkan_driver_selector,
|
vulkan_driver_selector,
|
||||||
opencl_platform_selector,
|
opencl_platform_selector,
|
||||||
|
vulkan_window: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut daemon_version = format!("{}-{}", system_info.version, system_info.profile);
|
let mut daemon_version = format!("{}-{}", system_info.version, system_info.profile);
|
||||||
@@ -329,12 +332,18 @@ impl relm4::SimpleComponent for SoftwarePage {
|
|||||||
}
|
}
|
||||||
SoftwarePageMsg::ShowVulkanFeatures => {
|
SoftwarePageMsg::ShowVulkanFeatures => {
|
||||||
if let Some(vulkan_info) = &self.selected_vulkan_info() {
|
if let Some(vulkan_info) = &self.selected_vulkan_info() {
|
||||||
show_features_window("Vulkan Features", &vulkan_info.features);
|
self.vulkan_window = Some(show_features_window(
|
||||||
|
"Vulkan Features",
|
||||||
|
&vulkan_info.features,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SoftwarePageMsg::ShowVulkanExtensions => {
|
SoftwarePageMsg::ShowVulkanExtensions => {
|
||||||
if let Some(vulkan_info) = self.selected_vulkan_info() {
|
if let Some(vulkan_info) = self.selected_vulkan_info() {
|
||||||
show_features_window("Vulkan Extensions", &vulkan_info.extensions);
|
self.vulkan_window = Some(show_features_window(
|
||||||
|
"Vulkan Extensions",
|
||||||
|
&vulkan_info.extensions,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SoftwarePageMsg::SelectionChanged => (),
|
SoftwarePageMsg::SelectionChanged => (),
|
||||||
@@ -366,7 +375,10 @@ impl SoftwarePage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_features_window(title: &str, values: &IndexMap<String, bool>) {
|
fn show_features_window(
|
||||||
|
title: &str,
|
||||||
|
values: &IndexMap<String, bool>,
|
||||||
|
) -> relm4::Controller<VulkanFeaturesWindow> {
|
||||||
let values = values
|
let values = values
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(name, &supported)| VulkanFeature {
|
.map(|(name, &supported)| VulkanFeature {
|
||||||
@@ -375,9 +387,9 @@ fn show_features_window(title: &str, values: &IndexMap<String, bool>) {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut window_controller = VulkanFeaturesWindow::builder()
|
let window_controller = VulkanFeaturesWindow::builder()
|
||||||
.launch((values, title.to_owned()))
|
.launch((values, title.to_owned()))
|
||||||
.detach();
|
.detach();
|
||||||
window_controller.detach_runtime();
|
|
||||||
window_controller.widget().present();
|
window_controller.widget().present();
|
||||||
|
window_controller
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use gtk::{
|
use gtk::{
|
||||||
glib::GString,
|
glib::GString,
|
||||||
prelude::{EditableExt, GtkWindowExt, OrientableExt, WidgetExt},
|
prelude::{EditableExt, GtkWindowExt, ObjectExt, OrientableExt, WidgetExt},
|
||||||
NoSelection,
|
NoSelection,
|
||||||
};
|
};
|
||||||
use relm4::{
|
use relm4::{
|
||||||
@@ -39,8 +39,10 @@ impl SimpleComponent for VulkanFeaturesWindow {
|
|||||||
sender.input(AppMsg::FilterChanged(entry.text()));
|
sender.input(AppMsg::FilterChanged(entry.text()));
|
||||||
},
|
},
|
||||||
|
|
||||||
connect_stop_search[root] => move |_| {
|
connect_stop_search[root = root.downgrade()] => move |_| {
|
||||||
root.close();
|
if let Some(root) = root.upgrade() {
|
||||||
|
root.close();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user