mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-03 23:21:15 +00:00 
			
		
		
		
	Addded methods to propagate checks & refactored classes to use new methods.
This commit is contained in:
		
							parent
							
								
									deefce7bb5
								
							
						
					
					
						commit
						a4bac268c9
					
				
					 10 changed files with 132 additions and 161 deletions
				
			
		| 
						 | 
					@ -357,6 +357,13 @@
 | 
				
			||||||
				Emitted when a cell is selected.
 | 
									Emitted when a cell is selected.
 | 
				
			||||||
			</description>
 | 
								</description>
 | 
				
			||||||
		</signal>
 | 
							</signal>
 | 
				
			||||||
 | 
							<signal name="check_propagated_to_item">
 | 
				
			||||||
 | 
								<argument index="0" name="item" type="TreeItem" />
 | 
				
			||||||
 | 
								<argument index="1" name="column" type="int" />
 | 
				
			||||||
 | 
								<description>
 | 
				
			||||||
 | 
									Emitted when [method TreeItem.propagate_check] is called. Connect to this signal to process the items that are affected when [method TreeItem.propagate_check] is invoked. The order that the items affected will be processed is as follows: the item that invoked the method, children of that item, and finally parents of that item.
 | 
				
			||||||
 | 
								</description>
 | 
				
			||||||
 | 
							</signal>
 | 
				
			||||||
		<signal name="column_title_pressed">
 | 
							<signal name="column_title_pressed">
 | 
				
			||||||
			<argument index="0" name="column" type="int" />
 | 
								<argument index="0" name="column" type="int" />
 | 
				
			||||||
			<description>
 | 
								<description>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -385,6 +385,14 @@
 | 
				
			||||||
				[b]Note:[/b] You can't move to the root or move the root.
 | 
									[b]Note:[/b] You can't move to the root or move the root.
 | 
				
			||||||
			</description>
 | 
								</description>
 | 
				
			||||||
		</method>
 | 
							</method>
 | 
				
			||||||
 | 
							<method name="propagate_check">
 | 
				
			||||||
 | 
								<return type="void" />
 | 
				
			||||||
 | 
								<argument index="0" name="column" type="int" />
 | 
				
			||||||
 | 
								<argument index="1" name="emit_signal" type="bool" default="true" />
 | 
				
			||||||
 | 
								<description>
 | 
				
			||||||
 | 
									Propagates this item's checked status to its children and parents for the given [code]column[/code]. It is possible to process the items affected by this method call by connecting to [signal Tree.check_propagated_to_item]. The order that the items affected will be processed is as follows: the item invoking this method, children of that item, and finally parents of that item. If [code]emit_signal[/code] is set to false, then [signal Tree.check_propagated_to_item] will not be emitted.
 | 
				
			||||||
 | 
								</description>
 | 
				
			||||||
 | 
							</method>
 | 
				
			||||||
		<method name="remove_child">
 | 
							<method name="remove_child">
 | 
				
			||||||
			<return type="void" />
 | 
								<return type="void" />
 | 
				
			||||||
			<argument index="0" name="child" type="Object" />
 | 
								<argument index="0" name="child" type="Object" />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,45 +36,6 @@
 | 
				
			||||||
#include "editor_node.h"
 | 
					#include "editor_node.h"
 | 
				
			||||||
#include "progress_dialog.h"
 | 
					#include "progress_dialog.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void EditorAssetInstaller::_update_subitems(TreeItem *p_item, bool p_check, bool p_first) {
 | 
					 | 
				
			||||||
	if (p_check) {
 | 
					 | 
				
			||||||
		if (p_item->get_custom_color(0) == Color()) {
 | 
					 | 
				
			||||||
			p_item->set_checked(0, true);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		p_item->set_checked(0, false);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (p_item->get_first_child()) {
 | 
					 | 
				
			||||||
		_update_subitems(p_item->get_first_child(), p_check);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!p_first && p_item->get_next()) {
 | 
					 | 
				
			||||||
		_update_subitems(p_item->get_next(), p_check);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void EditorAssetInstaller::_uncheck_parent(TreeItem *p_item) {
 | 
					 | 
				
			||||||
	if (!p_item) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool any_checked = false;
 | 
					 | 
				
			||||||
	TreeItem *item = p_item->get_first_child();
 | 
					 | 
				
			||||||
	while (item) {
 | 
					 | 
				
			||||||
		if (item->is_checked(0)) {
 | 
					 | 
				
			||||||
			any_checked = true;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		item = item->get_next();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!any_checked) {
 | 
					 | 
				
			||||||
		p_item->set_checked(0, false);
 | 
					 | 
				
			||||||
		_uncheck_parent(p_item->get_parent());
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void EditorAssetInstaller::_item_edited() {
 | 
					void EditorAssetInstaller::_item_edited() {
 | 
				
			||||||
	if (updating) {
 | 
						if (updating) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -85,22 +46,17 @@ void EditorAssetInstaller::_item_edited() {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	String path = item->get_metadata(0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	updating = true;
 | 
						updating = true;
 | 
				
			||||||
	if (path.is_empty() || item == tree->get_root()) { //a dir or root
 | 
						item->propagate_check(0);
 | 
				
			||||||
		_update_subitems(item, item->is_checked(0), true);
 | 
						updating = false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (item->is_checked(0)) {
 | 
					void EditorAssetInstaller::_check_propagated_to_item(Object *p_obj, int column) {
 | 
				
			||||||
		while (item) {
 | 
						TreeItem *affected_item = Object::cast_to<TreeItem>(p_obj);
 | 
				
			||||||
			item->set_checked(0, true);
 | 
						if (affected_item && affected_item->get_custom_color(0) != Color()) {
 | 
				
			||||||
			item = item->get_parent();
 | 
							affected_item->set_checked(0, false);
 | 
				
			||||||
 | 
							affected_item->propagate_check(0, false);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		_uncheck_parent(item->get_parent());
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	updating = false;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void EditorAssetInstaller::open(const String &p_path, int p_depth) {
 | 
					void EditorAssetInstaller::open(const String &p_path, int p_depth) {
 | 
				
			||||||
| 
						 | 
					@ -260,6 +216,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
 | 
				
			||||||
				ti->set_custom_color(0, tree->get_theme_color(SNAME("error_color"), SNAME("Editor")));
 | 
									ti->set_custom_color(0, tree->get_theme_color(SNAME("error_color"), SNAME("Editor")));
 | 
				
			||||||
				ti->set_tooltip(0, vformat(TTR("%s (already exists)"), res_path));
 | 
									ti->set_tooltip(0, vformat(TTR("%s (already exists)"), res_path));
 | 
				
			||||||
				ti->set_checked(0, false);
 | 
									ti->set_checked(0, false);
 | 
				
			||||||
 | 
									ti->propagate_check(0);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				ti->set_tooltip(0, res_path);
 | 
									ti->set_tooltip(0, res_path);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -305,7 +262,7 @@ void EditorAssetInstaller::ok_pressed() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		String name = fname;
 | 
							String name = fname;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (status_map.has(name) && status_map[name]->is_checked(0)) {
 | 
							if (status_map.has(name) && (status_map[name]->is_checked(0) || status_map[name]->is_indeterminate(0))) {
 | 
				
			||||||
			String path = status_map[name]->get_metadata(0);
 | 
								String path = status_map[name]->get_metadata(0);
 | 
				
			||||||
			if (path.is_empty()) { // a dir
 | 
								if (path.is_empty()) { // a dir
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -393,6 +350,7 @@ EditorAssetInstaller::EditorAssetInstaller() {
 | 
				
			||||||
	tree = memnew(Tree);
 | 
						tree = memnew(Tree);
 | 
				
			||||||
	tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 | 
						tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 | 
				
			||||||
	tree->connect("item_edited", callable_mp(this, &EditorAssetInstaller::_item_edited));
 | 
						tree->connect("item_edited", callable_mp(this, &EditorAssetInstaller::_item_edited));
 | 
				
			||||||
 | 
						tree->connect("check_propagated_to_item", callable_mp(this, &EditorAssetInstaller::_check_propagated_to_item));
 | 
				
			||||||
	vb->add_child(tree);
 | 
						vb->add_child(tree);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = memnew(AcceptDialog);
 | 
						error = memnew(AcceptDialog);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,9 +43,8 @@ class EditorAssetInstaller : public ConfirmationDialog {
 | 
				
			||||||
	AcceptDialog *error;
 | 
						AcceptDialog *error;
 | 
				
			||||||
	Map<String, TreeItem *> status_map;
 | 
						Map<String, TreeItem *> status_map;
 | 
				
			||||||
	bool updating;
 | 
						bool updating;
 | 
				
			||||||
	void _update_subitems(TreeItem *p_item, bool p_check, bool p_first = false);
 | 
					 | 
				
			||||||
	void _uncheck_parent(TreeItem *p_item);
 | 
					 | 
				
			||||||
	void _item_edited();
 | 
						void _item_edited();
 | 
				
			||||||
 | 
						void _check_propagated_to_item(Object *p_obj, int column);
 | 
				
			||||||
	virtual void ok_pressed() override;
 | 
						virtual void ok_pressed() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,8 +81,6 @@ void ThemeItemImportTree::_update_items_tree() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool is_matching_filter = (filter_text.is_empty() || type_name.findn(filter_text) > -1);
 | 
							bool is_matching_filter = (filter_text.is_empty() || type_name.findn(filter_text) > -1);
 | 
				
			||||||
		bool has_filtered_items = false;
 | 
							bool has_filtered_items = false;
 | 
				
			||||||
		bool any_checked = false;
 | 
					 | 
				
			||||||
		bool any_checked_with_data = false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) {
 | 
							for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) {
 | 
				
			||||||
			Theme::DataType dt = (Theme::DataType)i;
 | 
								Theme::DataType dt = (Theme::DataType)i;
 | 
				
			||||||
| 
						 | 
					@ -178,9 +176,6 @@ void ThemeItemImportTree::_update_items_tree() {
 | 
				
			||||||
					break; // Can't happen, but silences warning.
 | 
										break; // Can't happen, but silences warning.
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			bool data_type_any_checked = false;
 | 
					 | 
				
			||||||
			bool data_type_any_checked_with_data = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			filtered_names.sort_custom<StringName::AlphCompare>();
 | 
								filtered_names.sort_custom<StringName::AlphCompare>();
 | 
				
			||||||
			for (const StringName &F : filtered_names) {
 | 
								for (const StringName &F : filtered_names) {
 | 
				
			||||||
				TreeItem *item_node = import_items_tree->create_item(data_type_node);
 | 
									TreeItem *item_node = import_items_tree->create_item(data_type_node);
 | 
				
			||||||
| 
						 | 
					@ -194,20 +189,11 @@ void ThemeItemImportTree::_update_items_tree() {
 | 
				
			||||||
				item_node->set_editable(IMPORT_ITEM_DATA, true);
 | 
									item_node->set_editable(IMPORT_ITEM_DATA, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				_restore_selected_item(item_node);
 | 
									_restore_selected_item(item_node);
 | 
				
			||||||
				if (item_node->is_checked(IMPORT_ITEM)) {
 | 
									item_node->propagate_check(IMPORT_ITEM, false);
 | 
				
			||||||
					data_type_any_checked = true;
 | 
									item_node->propagate_check(IMPORT_ITEM_DATA, false);
 | 
				
			||||||
					any_checked = true;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (item_node->is_checked(IMPORT_ITEM_DATA)) {
 | 
					 | 
				
			||||||
					data_type_any_checked_with_data = true;
 | 
					 | 
				
			||||||
					any_checked_with_data = true;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				item_list->push_back(item_node);
 | 
									item_list->push_back(item_node);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					 | 
				
			||||||
			data_type_node->set_checked(IMPORT_ITEM, data_type_any_checked);
 | 
					 | 
				
			||||||
			data_type_node->set_checked(IMPORT_ITEM_DATA, data_type_any_checked && data_type_any_checked_with_data);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Remove the item if it doesn't match the filter in any way.
 | 
							// Remove the item if it doesn't match the filter in any way.
 | 
				
			||||||
| 
						 | 
					@ -221,9 +207,6 @@ void ThemeItemImportTree::_update_items_tree() {
 | 
				
			||||||
		if (!filter_text.is_empty() && has_filtered_items) {
 | 
							if (!filter_text.is_empty() && has_filtered_items) {
 | 
				
			||||||
			type_node->set_collapsed(false);
 | 
								type_node->set_collapsed(false);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		type_node->set_checked(IMPORT_ITEM, any_checked);
 | 
					 | 
				
			||||||
		type_node->set_checked(IMPORT_ITEM_DATA, any_checked && any_checked_with_data);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (color_amount > 0) {
 | 
						if (color_amount > 0) {
 | 
				
			||||||
| 
						 | 
					@ -471,23 +454,26 @@ void ThemeItemImportTree::_tree_item_edited() {
 | 
				
			||||||
	if (is_checked) {
 | 
						if (is_checked) {
 | 
				
			||||||
		if (edited_column == IMPORT_ITEM_DATA) {
 | 
							if (edited_column == IMPORT_ITEM_DATA) {
 | 
				
			||||||
			edited_item->set_checked(IMPORT_ITEM, true);
 | 
								edited_item->set_checked(IMPORT_ITEM, true);
 | 
				
			||||||
 | 
								edited_item->propagate_check(IMPORT_ITEM);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		_select_all_subitems(edited_item, (edited_column == IMPORT_ITEM_DATA));
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		if (edited_column == IMPORT_ITEM) {
 | 
							if (edited_column == IMPORT_ITEM) {
 | 
				
			||||||
			edited_item->set_checked(IMPORT_ITEM_DATA, false);
 | 
								edited_item->set_checked(IMPORT_ITEM_DATA, false);
 | 
				
			||||||
 | 
								edited_item->propagate_check(IMPORT_ITEM_DATA);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		_deselect_all_subitems(edited_item, (edited_column == IMPORT_ITEM));
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						edited_item->propagate_check(edited_column);
 | 
				
			||||||
	_update_parent_items(edited_item);
 | 
					 | 
				
			||||||
	_store_selected_item(edited_item);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	updating_tree = false;
 | 
						updating_tree = false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ThemeItemImportTree::_check_propagated_to_tree_item(Object *p_obj, int p_column) {
 | 
				
			||||||
 | 
						TreeItem *item = Object::cast_to<TreeItem>(p_obj);
 | 
				
			||||||
 | 
						// Skip "category" tree items by checking for children.
 | 
				
			||||||
 | 
						if (item && !item->get_first_child()) {
 | 
				
			||||||
 | 
							_store_selected_item(item);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ThemeItemImportTree::_select_all_subitems(TreeItem *p_root_item, bool p_select_with_data) {
 | 
					void ThemeItemImportTree::_select_all_subitems(TreeItem *p_root_item, bool p_select_with_data) {
 | 
				
			||||||
	TreeItem *child_item = p_root_item->get_first_child();
 | 
						TreeItem *child_item = p_root_item->get_first_child();
 | 
				
			||||||
	while (child_item) {
 | 
						while (child_item) {
 | 
				
			||||||
| 
						 | 
					@ -516,32 +502,6 @@ void ThemeItemImportTree::_deselect_all_subitems(TreeItem *p_root_item, bool p_d
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ThemeItemImportTree::_update_parent_items(TreeItem *p_root_item) {
 | 
					 | 
				
			||||||
	TreeItem *parent_item = p_root_item->get_parent();
 | 
					 | 
				
			||||||
	if (!parent_item) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool any_checked = false;
 | 
					 | 
				
			||||||
	bool any_checked_with_data = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	TreeItem *child_item = parent_item->get_first_child();
 | 
					 | 
				
			||||||
	while (child_item) {
 | 
					 | 
				
			||||||
		if (child_item->is_checked(IMPORT_ITEM)) {
 | 
					 | 
				
			||||||
			any_checked = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (child_item->is_checked(IMPORT_ITEM_DATA)) {
 | 
					 | 
				
			||||||
			any_checked_with_data = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		child_item = child_item->get_next();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	parent_item->set_checked(IMPORT_ITEM, any_checked);
 | 
					 | 
				
			||||||
	parent_item->set_checked(IMPORT_ITEM_DATA, any_checked && any_checked_with_data);
 | 
					 | 
				
			||||||
	_update_parent_items(parent_item);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ThemeItemImportTree::_select_all_items_pressed() {
 | 
					void ThemeItemImportTree::_select_all_items_pressed() {
 | 
				
			||||||
	if (updating_tree) {
 | 
						if (updating_tree) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -629,7 +589,7 @@ void ThemeItemImportTree::_select_all_data_type_pressed(int p_data_type) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		child_item->set_checked(IMPORT_ITEM, true);
 | 
							child_item->set_checked(IMPORT_ITEM, true);
 | 
				
			||||||
		_update_parent_items(child_item);
 | 
							child_item->propagate_check(IMPORT_ITEM, false);
 | 
				
			||||||
		_store_selected_item(child_item);
 | 
							_store_selected_item(child_item);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -685,7 +645,8 @@ void ThemeItemImportTree::_select_full_data_type_pressed(int p_data_type) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		child_item->set_checked(IMPORT_ITEM, true);
 | 
							child_item->set_checked(IMPORT_ITEM, true);
 | 
				
			||||||
		child_item->set_checked(IMPORT_ITEM_DATA, true);
 | 
							child_item->set_checked(IMPORT_ITEM_DATA, true);
 | 
				
			||||||
		_update_parent_items(child_item);
 | 
							child_item->propagate_check(IMPORT_ITEM, false);
 | 
				
			||||||
 | 
							child_item->propagate_check(IMPORT_ITEM_DATA, false);
 | 
				
			||||||
		_store_selected_item(child_item);
 | 
							_store_selected_item(child_item);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -741,7 +702,8 @@ void ThemeItemImportTree::_deselect_all_data_type_pressed(int p_data_type) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		child_item->set_checked(IMPORT_ITEM, false);
 | 
							child_item->set_checked(IMPORT_ITEM, false);
 | 
				
			||||||
		child_item->set_checked(IMPORT_ITEM_DATA, false);
 | 
							child_item->set_checked(IMPORT_ITEM_DATA, false);
 | 
				
			||||||
		_update_parent_items(child_item);
 | 
							child_item->propagate_check(IMPORT_ITEM, false);
 | 
				
			||||||
 | 
							child_item->propagate_check(IMPORT_ITEM_DATA, false);
 | 
				
			||||||
		_store_selected_item(child_item);
 | 
							_store_selected_item(child_item);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -937,6 +899,7 @@ ThemeItemImportTree::ThemeItemImportTree() {
 | 
				
			||||||
	import_items_tree->set_h_size_flags(Control::SIZE_EXPAND_FILL);
 | 
						import_items_tree->set_h_size_flags(Control::SIZE_EXPAND_FILL);
 | 
				
			||||||
	import_main_hb->add_child(import_items_tree);
 | 
						import_main_hb->add_child(import_items_tree);
 | 
				
			||||||
	import_items_tree->connect("item_edited", callable_mp(this, &ThemeItemImportTree::_tree_item_edited));
 | 
						import_items_tree->connect("item_edited", callable_mp(this, &ThemeItemImportTree::_tree_item_edited));
 | 
				
			||||||
 | 
						import_items_tree->connect("check_propagated_to_item", callable_mp(this, &ThemeItemImportTree::_check_propagated_to_tree_item));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	import_items_tree->set_columns(3);
 | 
						import_items_tree->set_columns(3);
 | 
				
			||||||
	import_items_tree->set_column_titles_visible(true);
 | 
						import_items_tree->set_column_titles_visible(true);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,9 +149,9 @@ class ThemeItemImportTree : public VBoxContainer {
 | 
				
			||||||
	void _update_total_selected(Theme::DataType p_data_type);
 | 
						void _update_total_selected(Theme::DataType p_data_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void _tree_item_edited();
 | 
						void _tree_item_edited();
 | 
				
			||||||
 | 
						void _check_propagated_to_tree_item(Object *p_obj, int p_column);
 | 
				
			||||||
	void _select_all_subitems(TreeItem *p_root_item, bool p_select_with_data);
 | 
						void _select_all_subitems(TreeItem *p_root_item, bool p_select_with_data);
 | 
				
			||||||
	void _deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely);
 | 
						void _deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely);
 | 
				
			||||||
	void _update_parent_items(TreeItem *p_root_item);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void _select_all_items_pressed();
 | 
						void _select_all_items_pressed();
 | 
				
			||||||
	void _select_full_items_pressed();
 | 
						void _select_full_items_pressed();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -737,12 +737,10 @@ bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem
 | 
				
			||||||
	p_item->set_metadata(0, p_dir->get_path());
 | 
						p_item->set_metadata(0, p_dir->get_path());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool used = false;
 | 
						bool used = false;
 | 
				
			||||||
	bool checked = true;
 | 
					 | 
				
			||||||
	for (int i = 0; i < p_dir->get_subdir_count(); i++) {
 | 
						for (int i = 0; i < p_dir->get_subdir_count(); i++) {
 | 
				
			||||||
		TreeItem *subdir = include_files->create_item(p_item);
 | 
							TreeItem *subdir = include_files->create_item(p_item);
 | 
				
			||||||
		if (_fill_tree(p_dir->get_subdir(i), subdir, current, p_only_scenes)) {
 | 
							if (_fill_tree(p_dir->get_subdir(i), subdir, current, p_only_scenes)) {
 | 
				
			||||||
			used = true;
 | 
								used = true;
 | 
				
			||||||
			checked = checked && subdir->is_checked(0);
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			memdelete(subdir);
 | 
								memdelete(subdir);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -767,12 +765,10 @@ bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem
 | 
				
			||||||
		file->set_editable(0, true);
 | 
							file->set_editable(0, true);
 | 
				
			||||||
		file->set_checked(0, current->has_export_file(path));
 | 
							file->set_checked(0, current->has_export_file(path));
 | 
				
			||||||
		file->set_metadata(0, path);
 | 
							file->set_metadata(0, path);
 | 
				
			||||||
		checked = checked && file->is_checked(0);
 | 
							file->propagate_check(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		used = true;
 | 
							used = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	p_item->set_checked(0, checked);
 | 
					 | 
				
			||||||
	return used;
 | 
						return used;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -791,54 +787,24 @@ void ProjectExportDialog::_tree_changed() {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	String path = item->get_metadata(0);
 | 
						item->propagate_check(0);
 | 
				
			||||||
	bool added = item->is_checked(0);
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (path.ends_with("/")) {
 | 
					void ProjectExportDialog::_check_propagated_to_item(Object *p_obj, int column) {
 | 
				
			||||||
		_check_dir_recursive(item, added);
 | 
						Ref<EditorExportPreset> current = get_current_preset();
 | 
				
			||||||
	} else {
 | 
						if (current.is_null()) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						TreeItem *item = Object::cast_to<TreeItem>(p_obj);
 | 
				
			||||||
 | 
						String path = item->get_metadata(0);
 | 
				
			||||||
 | 
						if (item && !path.ends_with("/")) {
 | 
				
			||||||
 | 
							bool added = item->is_checked(0);
 | 
				
			||||||
		if (added) {
 | 
							if (added) {
 | 
				
			||||||
			current->add_export_file(path);
 | 
								current->add_export_file(path);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			current->remove_export_file(path);
 | 
								current->remove_export_file(path);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	_refresh_parent_checks(item); // Makes parent folder checked if all files/folders are checked.
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ProjectExportDialog::_check_dir_recursive(TreeItem *p_dir, bool p_checked) {
 | 
					 | 
				
			||||||
	for (TreeItem *child = p_dir->get_first_child(); child; child = child->get_next()) {
 | 
					 | 
				
			||||||
		String path = child->get_metadata(0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		child->set_checked(0, p_checked);
 | 
					 | 
				
			||||||
		if (path.ends_with("/")) {
 | 
					 | 
				
			||||||
			_check_dir_recursive(child, p_checked);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			if (p_checked) {
 | 
					 | 
				
			||||||
				get_current_preset()->add_export_file(path);
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				get_current_preset()->remove_export_file(path);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ProjectExportDialog::_refresh_parent_checks(TreeItem *p_item) {
 | 
					 | 
				
			||||||
	TreeItem *parent = p_item->get_parent();
 | 
					 | 
				
			||||||
	if (!parent) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool checked = true;
 | 
					 | 
				
			||||||
	for (TreeItem *child = parent->get_first_child(); child; child = child->get_next()) {
 | 
					 | 
				
			||||||
		checked = checked && child->is_checked(0);
 | 
					 | 
				
			||||||
		if (!checked) {
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	parent->set_checked(0, checked);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_refresh_parent_checks(parent);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ProjectExportDialog::_export_pck_zip() {
 | 
					void ProjectExportDialog::_export_pck_zip() {
 | 
				
			||||||
| 
						 | 
					@ -1111,6 +1077,7 @@ ProjectExportDialog::ProjectExportDialog() {
 | 
				
			||||||
	include_files = memnew(Tree);
 | 
						include_files = memnew(Tree);
 | 
				
			||||||
	include_margin->add_child(include_files);
 | 
						include_margin->add_child(include_files);
 | 
				
			||||||
	include_files->connect("item_edited", callable_mp(this, &ProjectExportDialog::_tree_changed));
 | 
						include_files->connect("item_edited", callable_mp(this, &ProjectExportDialog::_tree_changed));
 | 
				
			||||||
 | 
						include_files->connect("check_propagated_to_item", callable_mp(this, &ProjectExportDialog::_check_propagated_to_item));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	include_filters = memnew(LineEdit);
 | 
						include_filters = memnew(LineEdit);
 | 
				
			||||||
	resources_vb->add_margin_child(
 | 
						resources_vb->add_margin_child(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,8 +123,7 @@ private:
 | 
				
			||||||
	void _fill_resource_tree();
 | 
						void _fill_resource_tree();
 | 
				
			||||||
	bool _fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> ¤t, bool p_only_scenes);
 | 
						bool _fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> ¤t, bool p_only_scenes);
 | 
				
			||||||
	void _tree_changed();
 | 
						void _tree_changed();
 | 
				
			||||||
	void _check_dir_recursive(TreeItem *p_dir, bool p_checked);
 | 
						void _check_propagated_to_item(Object *p_obj, int column);
 | 
				
			||||||
	void _refresh_parent_checks(TreeItem *p_item);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
 | 
						Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
 | 
				
			||||||
	bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
 | 
						bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -198,6 +198,65 @@ bool TreeItem::is_indeterminate(int p_column) const {
 | 
				
			||||||
	return cells[p_column].indeterminate;
 | 
						return cells[p_column].indeterminate;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void TreeItem::propagate_check(int p_column, bool p_emit_signal) {
 | 
				
			||||||
 | 
						bool ch = cells[p_column].checked;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (p_emit_signal) {
 | 
				
			||||||
 | 
							tree->emit_signal("check_propagated_to_item", this, p_column);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_propagate_check_through_children(p_column, ch, p_emit_signal);
 | 
				
			||||||
 | 
						_propagate_check_through_parents(p_column, p_emit_signal);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void TreeItem::_propagate_check_through_children(int p_column, bool p_checked, bool p_emit_signal) {
 | 
				
			||||||
 | 
						TreeItem *current = get_first_child();
 | 
				
			||||||
 | 
						while (current) {
 | 
				
			||||||
 | 
							current->set_checked(p_column, p_checked);
 | 
				
			||||||
 | 
							if (p_emit_signal) {
 | 
				
			||||||
 | 
								current->tree->emit_signal("check_propagated_to_item", current, p_column);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							current->_propagate_check_through_children(p_column, p_checked, p_emit_signal);
 | 
				
			||||||
 | 
							current = current->get_next();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void TreeItem::_propagate_check_through_parents(int p_column, bool p_emit_signal) {
 | 
				
			||||||
 | 
						TreeItem *current = get_parent();
 | 
				
			||||||
 | 
						if (!current) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool all_unchecked_and_not_indeterminate = true;
 | 
				
			||||||
 | 
						bool any_unchecked_or_indeterminate = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						TreeItem *child_item = current->get_first_child();
 | 
				
			||||||
 | 
						while (child_item) {
 | 
				
			||||||
 | 
							if (!child_item->is_checked(p_column)) {
 | 
				
			||||||
 | 
								any_unchecked_or_indeterminate = true;
 | 
				
			||||||
 | 
								if (child_item->is_indeterminate(p_column)) {
 | 
				
			||||||
 | 
									all_unchecked_and_not_indeterminate = false;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								all_unchecked_and_not_indeterminate = false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							child_item = child_item->get_next();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (all_unchecked_and_not_indeterminate) {
 | 
				
			||||||
 | 
							current->set_checked(p_column, false);
 | 
				
			||||||
 | 
						} else if (any_unchecked_or_indeterminate) {
 | 
				
			||||||
 | 
							current->set_indeterminate(p_column, true);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							current->set_checked(p_column, true);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (p_emit_signal) {
 | 
				
			||||||
 | 
							current->tree->emit_signal("check_propagated_to_item", current, p_column);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						current->_propagate_check_through_parents(p_column, p_emit_signal);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TreeItem::set_text(int p_column, String p_text) {
 | 
					void TreeItem::set_text(int p_column, String p_text) {
 | 
				
			||||||
	ERR_FAIL_INDEX(p_column, cells.size());
 | 
						ERR_FAIL_INDEX(p_column, cells.size());
 | 
				
			||||||
	cells.write[p_column].text = p_text;
 | 
						cells.write[p_column].text = p_text;
 | 
				
			||||||
| 
						 | 
					@ -1141,6 +1200,8 @@ void TreeItem::_bind_methods() {
 | 
				
			||||||
	ClassDB::bind_method(D_METHOD("is_checked", "column"), &TreeItem::is_checked);
 | 
						ClassDB::bind_method(D_METHOD("is_checked", "column"), &TreeItem::is_checked);
 | 
				
			||||||
	ClassDB::bind_method(D_METHOD("is_indeterminate", "column"), &TreeItem::is_indeterminate);
 | 
						ClassDB::bind_method(D_METHOD("is_indeterminate", "column"), &TreeItem::is_indeterminate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ClassDB::bind_method(D_METHOD("propagate_check", "column", "emit_signal"), &TreeItem::propagate_check, DEFVAL(true));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ClassDB::bind_method(D_METHOD("set_text", "column", "text"), &TreeItem::set_text);
 | 
						ClassDB::bind_method(D_METHOD("set_text", "column", "text"), &TreeItem::set_text);
 | 
				
			||||||
	ClassDB::bind_method(D_METHOD("get_text", "column"), &TreeItem::get_text);
 | 
						ClassDB::bind_method(D_METHOD("get_text", "column"), &TreeItem::get_text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4848,6 +4909,7 @@ void Tree::_bind_methods() {
 | 
				
			||||||
	ADD_SIGNAL(MethodInfo("item_custom_button_pressed"));
 | 
						ADD_SIGNAL(MethodInfo("item_custom_button_pressed"));
 | 
				
			||||||
	ADD_SIGNAL(MethodInfo("item_double_clicked"));
 | 
						ADD_SIGNAL(MethodInfo("item_double_clicked"));
 | 
				
			||||||
	ADD_SIGNAL(MethodInfo("item_collapsed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem")));
 | 
						ADD_SIGNAL(MethodInfo("item_collapsed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem")));
 | 
				
			||||||
 | 
						ADD_SIGNAL(MethodInfo("check_propagated_to_item", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column")));
 | 
				
			||||||
	//ADD_SIGNAL( MethodInfo("item_double_clicked" ) );
 | 
						//ADD_SIGNAL( MethodInfo("item_double_clicked" ) );
 | 
				
			||||||
	ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::INT, "id")));
 | 
						ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::INT, "id")));
 | 
				
			||||||
	ADD_SIGNAL(MethodInfo("custom_popup_edited", PropertyInfo(Variant::BOOL, "arrow_clicked")));
 | 
						ADD_SIGNAL(MethodInfo("custom_popup_edited", PropertyInfo(Variant::BOOL, "arrow_clicked")));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,6 +212,14 @@ public:
 | 
				
			||||||
	bool is_checked(int p_column) const;
 | 
						bool is_checked(int p_column) const;
 | 
				
			||||||
	bool is_indeterminate(int p_column) const;
 | 
						bool is_indeterminate(int p_column) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void propagate_check(int p_column, bool p_emit_signal = true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						// Check helpers.
 | 
				
			||||||
 | 
						void _propagate_check_through_children(int p_column, bool p_checked, bool p_emit_signal);
 | 
				
			||||||
 | 
						void _propagate_check_through_parents(int p_column, bool p_emit_signal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
	void set_text(int p_column, String p_text);
 | 
						void set_text(int p_column, String p_text);
 | 
				
			||||||
	String get_text(int p_column) const;
 | 
						String get_text(int p_column) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue