Files
puzzle-quest/addons/godot_db_manager/table_editor.gd
T
Vaillant Jeremy 01ea3af253 Run godot --convert-3to4 (automated conversion)
Apply Godot 4.6 automated conversion: renames Spatial.translate->position,
margin_*->offset_*, tool->@tool, .empty()->.is_empty(), DynamicFont->FontFile,
onready->@onready, export()->@export, and many more.

127 files changed by the tool. Manual fixes still required for:
 - godot_db_manager plugin (incompatible APIs: WindowDialog, Tabs, etc.)
 - lod plugin (Spatial -> Node3D renames)
 - ResourceLoader.load_interactive removed -> load_threaded_request
 - OS.set_window_fullscreen removed -> DisplayServer
 - Viewport.set_size_override removed

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 19:18:27 +02:00

434 lines
17 KiB
GDScript

@tool
"""
class GDDBTableEditor
"""
class_name GDDBTableEditor
extends Control
signal set_dirty
var m_parent_table = null
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
$tabs/structure/header/new_property_btn.connect("pressed", Callable(self, "on_new_property_btn_pressed"))
$tabs/data/add_data_btn.connect("pressed", Callable(self, "on_add_row_data_btn_pressed"))
$tabs/data/add_data_btn.set_disabled(true)
$load_res_path_dlg.connect("file_selected", Callable(self, "on_select_res_path"))
$data_dlg.connect("select_data", Callable(self, "on_select_data"))
$edit_string_dlg.connect("string_edited", Callable(self, "on_text_edited"))
$delete_prop_dlg.connect("delete_prop", Callable(self, "on_confirm_delete_property"))
# called when resizing a property
func on_resize_property(prop_id : int, diff_x : float) -> void :
var current_prop = null
for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()):
var prop = $tabs/data/scroll/data_holder/data_header.get_child(idx)
if(prop.get_prop_id() == prop_id):
current_prop = prop
break
var prop_size : Vector2 = current_prop.get_child(0).get_size()
# print("diff_x: " + str(diff_x))
prop_size.x += diff_x
if(prop_size.x < gddb_constants.c_min_cell_width):
return
if(prop_size.x > gddb_constants.c_max_cell_width):
return
# print("prop_size.x = " + str(prop_size.x))
var prop_idx = -1
var data_size = $tabs/data/scroll.get_size()
data_size.x += diff_x
$tabs/data/scroll/data_holder/data_header.set_size(data_size)
for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()):
var prop = $tabs/data/scroll/data_holder/data_header.get_child(idx)
if(prop.get_prop_id() == prop_id):
var current_prop_size = prop.get_custom_minimum_size()
current_prop_size.x += diff_x
prop.set_custom_minimum_size(current_prop_size)
prop_idx = idx
if(prop_idx != -1 && idx > prop_idx):
var pos = prop.get_position()
pos.x += diff_x
prop.set_position(pos)
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
for jdx in range(0, row.get_child_count()):
var cell = row.get_child(jdx)
if(cell.get_prop_id() == prop_id):
cell.set_custom_minimum_size(prop_size)
if(jdx > prop_idx):
var pos = cell.get_position()
pos.x += diff_x
cell.set_position(pos)
# called when the new_property button is pressed
func on_new_property_btn_pressed() -> void:
# print("GDDBTableEditor::on_new_property_btn_pressed()")
if(null == m_parent_table):
print("ERROR: GDDBTableEditor::on_new_property_btn_pressed() - m_parent_table is null")
return
var prop_idx = m_parent_table.get_props_count()
var prop_type = gddb_types.e_prop_type_bool
var prop_name = "Property_" + str(prop_idx+1)
var prop_id = m_parent_table.add_prop(prop_type, prop_name)
add_prop_to_structure(prop_id, prop_type, prop_name)
add_prop_to_data(prop_id, prop_type, prop_name, false)
# enable add data btn
$tabs/data/add_data_btn.set_disabled(false)
emit_signal("set_dirty")
# adds a property to structure tab
func add_prop_to_structure(prop_id : int, prop_type : int, prop_name : String) -> void:
# print("GDDBTableEditor::add_prop_to_structure(" + str(prop_id) + ", " + str(prop_type) + ", " + prop_name + ")")
var prop = load(gddb_constants.c_addon_main_path + "table_property.tscn").instantiate()
$tabs/structure/scroll/properties.add_child(prop)
prop.set_parent_table(m_parent_table)
prop.setup(prop_id, prop_type, prop_name)
prop.connect("edit_property", Callable(self, "on_edit_property"))
prop.connect("delete_property", Callable(self, "on_delete_property"))
prop.connect("enable_autoincrement", Callable(self, "on_enable_prop_autoincrement"))
# adds a property to data tab
func add_prop_to_data(prop_id : int, prop_type : int, prop_name : String, has_autoincrement : bool) -> void:
var prop = load(gddb_constants.c_addon_main_path + "data_label.tscn").instantiate()
$tabs/data/scroll/data_holder/data_header.add_child(prop)
prop.set_prop_id(prop_id)
prop.set_text(prop_name)
prop.connect("resize_property", Callable(self, "on_resize_property"))
# add property to the existing rows
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
var cell = load(gddb_constants.c_addon_main_path + "table_cell.tscn").instantiate()
row.add_child(cell)
cell.set_prop_id(prop_id)
cell.set_row_idx(idx)
cell.set_prop_type(prop_type)
cell.set_text("")
cell.enable_autoincrement(has_autoincrement)
cell.connect("edit_data", Callable(self, "on_edit_data"))
cell.connect("choose_resource", Callable(self, "on_choose_resource"))
cell.connect("choose_data", Callable(self, "on_choose_data"))
cell.connect("edit_string", Callable(self, "on_edit_string"))
# called when the add data button is pressed
func on_add_row_data_btn_pressed() -> void:
# print("GDDBTableEditor::on_add_row_data_btn_pressed")
# add blank row in the table
var row_idx = m_parent_table.get_rows_count()
m_parent_table.add_blank_row()
# add row in the interface
var row = HBoxContainer.new()
$tabs/data/scroll/data_holder/data_container.add_child(row)
for idx in range(0, $tabs/structure/scroll/properties.get_child_count()):
var cell = load(gddb_constants.c_addon_main_path + "table_cell.tscn").instantiate()
var prop = $tabs/structure/scroll/properties.get_child(idx)
var db_prop = m_parent_table.get_prop_by_id(idx)
row.add_child(cell)
cell.set_prop_id(idx)
cell.set_row_idx(row_idx)
cell.set_prop_type(prop.get_prop_type())
var autoincrement = db_prop.has_autoincrement()
cell.enable_autoincrement(db_prop.has_autoincrement())
if(autoincrement):
cell.set_text(str(row_idx+1))
cell.connect("edit_data", Callable(self, "on_edit_data"))
cell.connect("choose_resource", Callable(self, "on_choose_resource"))
cell.connect("choose_data", Callable(self, "on_choose_data"))
cell.connect("edit_string", Callable(self, "on_edit_string"))
emit_signal("set_dirty")
# sets the table from database
func set_table(table : Object) -> void:
# print("GDDBTableEditor::set_table(" + table.get_table_name() + ")")
clear_current_layout()
m_parent_table = table
fill_properties()
fill_data()
# fills the interface with current table's properties
func fill_properties() -> void:
# print("GDDBTableEditor::fill_properties()")
var props_count = m_parent_table.get_props_count()
for idx in range(0, props_count):
var db_prop = m_parent_table.get_prop_at(idx)
add_prop_to_structure(db_prop.get_prop_id(), db_prop.get_prop_type(), db_prop.get_prop_name())
var prop = load(gddb_constants.c_addon_main_path + "data_label.tscn").instantiate()
$tabs/data/scroll/data_holder/data_header.add_child(prop)
prop.set_prop_id(db_prop.get_prop_id())
prop.set_prop_type(db_prop.get_prop_type())
prop.set_text(db_prop.get_prop_name())
prop.connect("resize_property", Callable(self, "on_resize_property"))
if(props_count > 0):
$tabs/data/add_data_btn.set_disabled(false)
# fills the interface with current table's data
func fill_data() -> void:
#print("GDDBTableEditor::fill_data()")
var rows_count = m_parent_table.get_rows_count()
#print("Table name: " + m_parent_table.get_table_name())
#print("rows_count: " + str(rows_count))
for idx in range(0, rows_count):
var row = HBoxContainer.new()
$tabs/data/scroll/data_holder/data_container.add_child(row)
var data_row = m_parent_table.get_data_at_row_idx(idx)
for jdx in range(0, data_row.size()):
var db_prop = m_parent_table.get_prop_at(jdx)
#print("Prop id: " + str(db_prop.get_prop_id()))
#print("Prop type: " + str(db_prop.get_prop_type()))
#print("Prop name: " + str(db_prop.get_prop_name()))
var cell = load(gddb_constants.c_addon_main_path + "table_cell.tscn").instantiate()
var cell_data = data_row[jdx].get_data()
var prop_type = db_prop.get_prop_type()
if(prop_type >= gddb_types.e_prop_types_count):
var db = m_parent_table.get_parent_database()
var table = db.get_table_by_id(prop_type - gddb_types.e_prop_types_count)
var data_row_idx = cell_data.to_int()
cell_data = gddb_globals.get_json_from_row(table, data_row_idx)
row.add_child(cell)
cell.set_prop_id(data_row[jdx].get_prop_id())
cell.set_row_idx(idx)
cell.set_prop_type(prop_type)
cell.set_text(cell_data)
cell.enable_autoincrement(db_prop.has_autoincrement())
cell.connect("edit_data", Callable(self, "on_edit_data"))
cell.connect("choose_resource", Callable(self, "on_choose_resource"))
cell.connect("choose_data", Callable(self, "on_choose_data"))
cell.connect("edit_string", Callable(self, "on_edit_string"))
# links properties
func link_props() -> void :
# print("GDDBTableEditor::link_props() for table with name: " + m_parent_table.get_table_name())
for idx in range(0, $tabs/structure/scroll/properties.get_child_count()):
var prop = $tabs/structure/scroll/properties.get_child(idx)
prop.link()
# refreshes autoincrement props
func refresh_autoincrement_props(prop_id, enable) -> void:
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
for jdx in range(0, row.get_child_count()):
var cell = row.get_child(jdx)
if(cell.get_prop_id() == prop_id):
cell.enable_autoincrement(enable)
# cleares current layout
func clear_current_layout() -> void:
# clear structure tab
for idx in range(0, $tabs/structure/scroll/properties.get_child_count()):
$tabs/structure/scroll/properties.get_child(idx).queue_free()
# clear data from data tab
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
for jdx in range(0, row.get_child_count()):
row.get_child(jdx).queue_free()
row.queue_free()
# clear properties from data tab
for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()):
$tabs/data/scroll/data_holder/data_header.get_child(idx).queue_free()
$tabs/data/add_data_btn.set_disabled(true)
# called when a property is edited
func on_edit_property(prop_id : int, prop_type : int, prop_name : String) -> void:
"""
print("GDDBTableEditor::on_edit_property(" + str(prop_id) + ", " + str(prop_type) + ", " + prop_name + ")")
if(prop_type >= gddb_types.e_prop_types_count):
var db = m_parent_table.get_parent_database()
var selected_table = db.get_table_by_id(gddb_types.e_prop_types_count - prop_type)
print("GDDBTableEditor::on_edit_property(" + str(prop_id) + ", " + selected_table.get_table_name() + ", " + prop_name + ")")
else:
print("GDDBTableEditor::on_edit_property(" + str(prop_id) + ", " + gddb_globals.get_data_name(prop_type) + ", " + prop_name + ")")
#"""
# edit prop in the table
m_parent_table.edit_prop(prop_id, prop_type, prop_name)
# refresh the prop name in data tab
for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()):
var prop = $tabs/data/scroll/data_holder/data_header.get_child(idx)
if(prop.get_prop_id() == prop_id):
prop.set_text(prop_name)
# update data type
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
for jdx in range(0, row.get_child_count()):
var cell = row.get_child(jdx)
if(cell.get_prop_id() == prop_id):
"""
if(prop_type < gddb_types.e_prop_types_count):
print("Prop type: " + gddb_globals.get_data_name(prop_type))
else:
print("Prop type: custom")
"""
cell.set_prop_type(prop_type)
emit_signal("set_dirty")
# called when a property is deleted
func on_delete_property(prop_id : int) -> void:
# print("GDDBTableEditor::on_delete_property(" + str(prop_id) + ")")
var prop = m_parent_table.get_prop_by_id(prop_id)
$delete_prop_dlg.set_prop_id(prop_id)
$delete_prop_dlg.set_prop_name(prop.get_prop_name())
$delete_prop_dlg.popup_centered()
# called when a property is deleted
func on_confirm_delete_property() -> void:
var prop_id = $delete_prop_dlg.get_prop_id()
# deletes a property from table; also all data by this property
m_parent_table.delete_prop(prop_id)
# delete cells from data tab
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
for jdx in range(0, row.get_child_count()):
var cell = row.get_child(jdx)
if(cell.get_prop_id() == prop_id):
cell.disconnect("edit_data", Callable(self, "on_edit_data"))
cell.queue_free()
break
# delete property from data tab
for idx in range(0, $tabs/data/scroll/data_holder/data_header.get_child_count()):
var prop = $tabs/data/scroll/data_holder/data_header.get_child(idx)
if(prop.get_prop_id() == prop_id):
prop.queue_free()
break
# delete prop from structure
for idx in range(0, $tabs/structure/scroll/properties.get_child_count()):
var prop = $tabs/structure/scroll/properties.get_child(idx)
if(prop.get_prop_id() == prop_id):
prop.queue_free()
break
# refresh the add data button
var props_count = m_parent_table.get_props_count()
if(props_count == 0):
$tabs/data/add_data_btn.set_disabled(true)
emit_signal("set_dirty")
# called when the property has autoincrement or not
func on_enable_prop_autoincrement(prop_id : int, enable : bool) -> void :
m_parent_table.enable_prop_autoincrement(prop_id, enable)
emit_signal("set_dirty")
refresh_autoincrement_props(prop_id, enable)
# reindex all data
if(enable):
for idx in range(0, $tabs/data/scroll/data_holder/data_container.get_child_count()):
var row = $tabs/data/scroll/data_holder/data_container.get_child(idx)
for jdx in range(0, row.get_child_count()):
var cell = row.get_child(jdx)
if(cell.get_prop_id() == prop_id):
cell.set_text(str(idx + 1))
# called when edit data
func on_edit_data(prop_id : int, row_idx : int, data : String) -> void:
m_parent_table.edit_data(prop_id, row_idx, data)
emit_signal("set_dirty")
# called when choosing a resource
func on_choose_resource(prop_id : int, row_idx : int) -> void:
# print("GDDBTableEditor::on_choose_resource(" + str(prop_id) + ", " + str(row_idx) + ")")
$load_res_path_dlg.set_prop_id(prop_id)
$load_res_path_dlg.set_row_idx(row_idx)
$load_res_path_dlg.popup_centered()
# called when choosing a data
func on_choose_data(prop_id : int, row_idx : int, prop_type : int) -> void:
# print("GDDBTableEditor::on_choose_data(" + str(prop_id) + ", " + str(row_idx) + ", " + str(prop_type) + ")")
$data_dlg.set_prop_id(prop_id)
$data_dlg.set_row_idx(row_idx)
var table_id = prop_type - gddb_types.e_prop_types_count
var db = m_parent_table.get_parent_database()
var tbl = db.get_table_by_id(table_id)
$data_dlg.set_table(tbl)
$data_dlg.popup_centered()
# called when choosing to edit string
func on_edit_string(prop_id : int, row_idx : int, text : String) -> void:
$edit_string_dlg.set_prop_id(prop_id)
$edit_string_dlg.set_row_idx(row_idx)
$edit_string_dlg.set_data_text(text)
$edit_string_dlg.popup_centered()
# called when selecting a resource filepath
func on_select_res_path(filepath : String) -> void:
# print("GDDBTableEditor::on_select_res_path(" + filepath + ")")
var prop_id = $load_res_path_dlg.get_prop_id()
var row_idx = $load_res_path_dlg.get_row_idx()
m_parent_table.edit_data(prop_id, row_idx, filepath)
var row = $tabs/data/scroll/data_holder/data_container.get_child(row_idx)
for idx in range(0, row.get_child_count()):
var cell = row.get_child(idx)
if(cell.get_prop_id() == prop_id):
cell.set_text(filepath)
emit_signal("set_dirty")
# called when data from a table is choosen
func on_select_data(prop_id : int, row_idx : int, data_row_idx : int, data : String) -> void:
# set the data in the databes / table
m_parent_table.edit_data(prop_id, row_idx, str(data_row_idx))
# fill in the interface cell with data
var row = $tabs/data/scroll/data_holder/data_container.get_child(row_idx)
for idx in range(0, row.get_child_count()):
var cell = row.get_child(idx)
if(cell.get_prop_id() == prop_id):
cell.set_text(data)
break
emit_signal("set_dirty")
# called when the text is edited
func on_text_edited():
var prop_id = $edit_string_dlg.get_prop_id()
var row_idx = $edit_string_dlg.get_row_idx()
var text_data = $edit_string_dlg.get_data_text()
var data = gddb_globals.handle_string(text_data)
# print("GDDBTableEditor::on_text_edited() - prop_id: " + str(prop_id) + ", row_idx: " + str(row_idx) + ", data: " + text_data)
m_parent_table.edit_data(prop_id, row_idx, data)
var row = $tabs/data/scroll/data_holder/data_container.get_child(row_idx)
for idx in range(0, row.get_child_count()):
var cell = row.get_child(idx)
if(cell.get_prop_id() == prop_id):
cell.set_text(text_data)
break
emit_signal("set_dirty")