376 lines
13 KiB
GDScript
376 lines
13 KiB
GDScript
class_name WordListElement
|
|
extends MarginContainer
|
|
|
|
signal delete_pressed()
|
|
signal new_gp_asked(i: int)
|
|
signal validated()
|
|
signal gps_updated()
|
|
|
|
const GP_LIST_BUTTON_SCENE: PackedScene = preload("res://sources/language_tool/gp_list_button.tscn")
|
|
const PLUS_BUTTON_SCENE: PackedScene = preload("res://sources/language_tool/plus_button.tscn")
|
|
|
|
@export var table: String = "Words"
|
|
@export var table_graph_column: String = "Word"
|
|
@export var sub_table: String = "GPs"
|
|
@export var sub_table_graph_column: String = "Grapheme"
|
|
@export var sub_table_phon_column: String = "Phoneme"
|
|
@export var relational_table: String = "GPsInWords"
|
|
@export var sub_table_id: String = "GPID"
|
|
|
|
var word: String = "":
|
|
set = set_word
|
|
var lesson: int = 0:
|
|
set = set_lesson
|
|
var undo_redo: UndoRedo:
|
|
get:
|
|
if not undo_redo:
|
|
undo_redo = UndoRedo.new()
|
|
return undo_redo
|
|
var id: int = -1
|
|
var gp_ids: Array[int] = []:
|
|
set = set_gp_ids
|
|
var unvalidated_gp_ids: Array[int] = []
|
|
var exception: int = 0:
|
|
set = set_exception
|
|
var reading: int = 0:
|
|
set = set_reading
|
|
var writing: int = 0:
|
|
set = set_writing
|
|
var sub_elements_list: Dictionary = {}
|
|
|
|
@onready var word_label: Label = %Word
|
|
@onready var graphemes_label: Label = %Graphemes
|
|
@onready var word_edit: LineEdit = %WordEdit
|
|
@onready var tab_container: TabContainer = $TabContainer
|
|
@onready var lesson_label: Label = %Lesson
|
|
@onready var exception_checkbox: CheckBox = %ExceptionCheckBox
|
|
@onready var exception_edit_checkbox: CheckBox = %ExceptionEditCheckBox
|
|
@onready var reading_checkbox: CheckBox = %ReadingCheckBox
|
|
@onready var writing_checkbox: CheckBox = %WritingCheckBox
|
|
@onready var reading_edit_checkbox: CheckBox = %ReadingEditCheckBox
|
|
@onready var writing_edit_checkbox: CheckBox = %WritingEditCheckBox
|
|
@onready var graphemes_edit_container: HBoxContainer = %GraphemesEditContainer
|
|
@onready var add_gp_button: MarginContainer = %AddGPButton
|
|
@onready var remove_gp_button: MarginContainer = %RemoveGPButton2
|
|
|
|
|
|
func set_exception(p_exception: bool) -> void:
|
|
exception = p_exception
|
|
if exception_checkbox:
|
|
exception_checkbox.button_pressed = bool(exception)
|
|
if exception_edit_checkbox:
|
|
exception_edit_checkbox.button_pressed = bool(exception)
|
|
|
|
|
|
func set_reading(p_reading: bool) -> void:
|
|
reading = p_reading
|
|
if reading_checkbox:
|
|
reading_checkbox.button_pressed = bool(reading)
|
|
if reading_edit_checkbox:
|
|
reading_edit_checkbox.button_pressed = bool(reading)
|
|
|
|
|
|
func set_writing(p_writing: bool) -> void:
|
|
writing = p_writing
|
|
if writing_checkbox:
|
|
writing_checkbox.button_pressed = bool(writing)
|
|
if writing_edit_checkbox:
|
|
writing_edit_checkbox.button_pressed = bool(writing)
|
|
|
|
|
|
func set_word(p_word: String) -> void:
|
|
word = p_word
|
|
if word_label:
|
|
word_label.text = word
|
|
if word_edit:
|
|
word_edit.text = word
|
|
|
|
|
|
func set_gp_ids(p_gp_ids: Array[int]) -> void:
|
|
gp_ids = p_gp_ids
|
|
if graphemes_label:
|
|
graphemes_label.text = get_gps(gp_ids)
|
|
|
|
|
|
func set_graphemes_edit(p_gp_ids: Array[int]) -> void:
|
|
if graphemes_edit_container:
|
|
for child: Node in graphemes_edit_container.get_children():
|
|
graphemes_edit_container.remove_child(child)
|
|
child.queue_free()
|
|
for ind_gp_id: int in range(p_gp_ids.size()):
|
|
var gp_id: int = p_gp_ids[ind_gp_id]
|
|
add_gp_list_button(gp_id, ind_gp_id)
|
|
|
|
|
|
func add_gp_list_button(gp_id: int, ind_gp_id: int) -> void:
|
|
var gp_list_button: GPListButton = GP_LIST_BUTTON_SCENE.instantiate()
|
|
gp_list_button.set_gp_list(sub_elements_list)
|
|
graphemes_edit_container.add_child(gp_list_button)
|
|
graphemes_edit_container.move_child(gp_list_button, 2 * ind_gp_id)
|
|
gp_list_button.select_id(gp_id)
|
|
gp_list_button.gp_selected.connect(_on_gp_list_button_selected.bind(gp_list_button))
|
|
gp_list_button.new_selected.connect(_on_gp_list_button_new_selected.bind(gp_list_button))
|
|
var plus_button: PlusButton = PLUS_BUTTON_SCENE.instantiate()
|
|
plus_button.size = Vector2(50, 50)
|
|
graphemes_edit_container.add_child(plus_button)
|
|
graphemes_edit_container.move_child(plus_button, 2 * ind_gp_id + 1)
|
|
plus_button.pressed.connect(_on_add_gp_button_pressed.bind(gp_list_button))
|
|
|
|
|
|
func _on_gp_list_button_selected(gp_id: int, element: Node) -> void:
|
|
var ind_gp_id: int = int(element.get_index() / 2.0)
|
|
unvalidated_gp_ids[ind_gp_id] = gp_id
|
|
word_edit.text = get_graphemes(unvalidated_gp_ids)
|
|
|
|
|
|
func _on_gp_list_button_new_selected(element: Node) -> void:
|
|
var ind_gp_id: int = int(element.get_index() / 2.0)
|
|
new_gp_asked.emit(ind_gp_id)
|
|
|
|
|
|
func get_graphemes(p_gp_ids: Array[int]) -> String:
|
|
var res: String = ""
|
|
for gp_id: int in p_gp_ids:
|
|
res += sub_elements_list[gp_id].grapheme
|
|
return res
|
|
|
|
|
|
func get_gps(p_gp_ids: Array[int]) -> String:
|
|
var res: String = ""
|
|
for gp_id: int in p_gp_ids:
|
|
res += sub_elements_list[gp_id].grapheme
|
|
res += "-"
|
|
res += sub_elements_list[gp_id].phoneme
|
|
res += " "
|
|
return res
|
|
|
|
|
|
func set_lesson(p_lesson: int) -> void:
|
|
lesson = p_lesson
|
|
if lesson_label:
|
|
lesson_label.text = str(p_lesson)
|
|
|
|
|
|
func _ready() -> void:
|
|
set_word(word)
|
|
set_gp_ids(gp_ids)
|
|
set_lesson(lesson)
|
|
set_exception(exception)
|
|
set_reading(reading)
|
|
set_writing(writing)
|
|
(%WordEditLabel as Label).text = table_graph_column + ": "
|
|
(%GPsEditLabel as Label).text = sub_table + ": "
|
|
|
|
|
|
func _on_edit_button_pressed() -> void:
|
|
edit_mode()
|
|
|
|
|
|
func edit_mode() -> void:
|
|
set_graphemes_edit(gp_ids)
|
|
tab_container.current_tab = 1
|
|
|
|
|
|
func _on_minus_button_pressed() -> void:
|
|
delete_pressed.emit()
|
|
|
|
|
|
func _on_validate_button_pressed() -> void:
|
|
undo_redo.create_action("validated")
|
|
undo_redo.add_do_property(self, "gp_ids", unvalidated_gp_ids.duplicate())
|
|
undo_redo.add_do_property(self, "word", word_edit.text)
|
|
undo_redo.add_do_property(self, "exception", int(exception_edit_checkbox.button_pressed))
|
|
undo_redo.add_do_property(self, "reading", int(reading_edit_checkbox.button_pressed))
|
|
undo_redo.add_do_property(self, "writing", int(writing_edit_checkbox.button_pressed))
|
|
undo_redo.add_undo_property(self, "gp_ids", gp_ids.duplicate())
|
|
undo_redo.add_undo_property(self, "word", word)
|
|
undo_redo.add_undo_property(self, "exception", int(exception_checkbox.button_pressed))
|
|
undo_redo.add_undo_property(self, "reading", int(reading_checkbox.button_pressed))
|
|
undo_redo.add_undo_property(self, "writing", int(writing_checkbox.button_pressed))
|
|
|
|
undo_redo.commit_action()
|
|
tab_container.current_tab = 0
|
|
update_lesson()
|
|
validated.emit()
|
|
|
|
|
|
func update_lesson() -> void:
|
|
var index: int = -1
|
|
for gp_id: int in gp_ids:
|
|
var min_index: int = Database.get_min_lesson_for_gp_id(gp_id)
|
|
if min_index < 0:
|
|
index = -1
|
|
break
|
|
index = maxi(index, min_index)
|
|
lesson = index
|
|
|
|
|
|
func gp_ids_from_string(p_gp_ids: String) -> Array[int]:
|
|
var res: Array[int] = []
|
|
var pack: PackedStringArray = p_gp_ids.split(" ")
|
|
res.resize(pack.size())
|
|
for index: int in range(pack.size()):
|
|
res[index] = int(pack[index])
|
|
return res
|
|
|
|
|
|
func set_gp_ids_from_string(p_gp_ids: String) -> void:
|
|
gp_ids = gp_ids_from_string(p_gp_ids)
|
|
unvalidated_gp_ids = gp_ids.duplicate()
|
|
|
|
|
|
func insert_in_database() -> void:
|
|
if id < 0:
|
|
Database.db.query_with_bindings("SELECT * FROM %s WHERE %s=?" % [table, table_graph_column], [word])
|
|
if not Database.db.query_result.is_empty():
|
|
id = Database.db.query_result[0].ID
|
|
|
|
if id >= 0:
|
|
var query: String = "SELECT %s, group_concat(%s, ' ') as %ss, group_concat(%s, ' ') as %ss, group_concat(%s.ID, ' ') as %sIDs, group_concat(%s.ID, ' ') as %sIDs, %s.Exception, %s.Reading, %s.Writing
|
|
FROM %s
|
|
INNER JOIN ( SELECT * FROM %s ORDER BY %s.Position ) %s ON %s.ID = %s.%sID
|
|
INNER JOIN %s ON %s.ID = %s.%s
|
|
WHERE %s.ID = ?
|
|
GROUP BY %s.ID" % [table_graph_column, sub_table_graph_column, sub_table_graph_column,
|
|
sub_table_phon_column, sub_table_phon_column,
|
|
relational_table, relational_table, sub_table, sub_table, table, table, table,
|
|
table,
|
|
relational_table, relational_table, relational_table, table, relational_table, table_graph_column,
|
|
sub_table, sub_table, relational_table, sub_table_id,
|
|
table,
|
|
table]
|
|
Database.db.query_with_bindings(query, [id])
|
|
Logger.trace("WordListElement: Sending query to insert in database: %s" % query)
|
|
if not Database.db.query_result.is_empty():
|
|
var element: Dictionary = Database.db.query_result[0]
|
|
if word != element[table_graph_column] or exception != element.Exception or reading != element.Reading or writing != element.Writing:
|
|
Database.db.update_rows(table, "ID=%s" % id, {table_graph_column: word, "Exception": exception, "Reading": reading, "Writing": writing})
|
|
if " ".join(gp_ids) != element[sub_table + "IDs"]:
|
|
var gps_in_words_ids: Array[String] = Array((element[relational_table + "IDs"] as String).split(" "))
|
|
while gps_in_words_ids.size() > gp_ids.size():
|
|
Database.db.delete_rows(relational_table, "ID=%s" % int(gps_in_words_ids.pop_back() as String))
|
|
for index: int in range(gps_in_words_ids.size()):
|
|
var gps_in_words_id: int = int(gps_in_words_ids[index])
|
|
Database.db.update_rows(relational_table, "ID=%s" % gps_in_words_id, {
|
|
table_graph_column + "ID": id,
|
|
sub_table_id: gp_ids[index],
|
|
"Position": index
|
|
})
|
|
for index: int in range(gps_in_words_ids.size(), gp_ids.size()):
|
|
Database.db.insert_row(relational_table, {
|
|
table_graph_column + "ID": id,
|
|
sub_table_id: gp_ids[index],
|
|
"Position": index
|
|
})
|
|
return
|
|
else:
|
|
Database.db.query_with_bindings("SELECT * FROM %s WHERE %s=?" % [table, table_graph_column], [word])
|
|
if not Database.db.query_result.is_empty():
|
|
var element: Dictionary = Database.db.query_result[0]
|
|
id = element.ID
|
|
if word != element[table_graph_column] or exception != element.Exception or reading != element.Reading or writing != element.writing:
|
|
Database.db.update_rows(table, "ID=%s" % id, {table_graph_column: word, "Exception": exception, "Reading": reading, "Writing": writing})
|
|
for index: int in range(gp_ids.size()):
|
|
Database.db.insert_row(relational_table, {
|
|
table_graph_column + "ID": id,
|
|
sub_table_id: gp_ids[index],
|
|
"Position": index
|
|
})
|
|
|
|
Database.db.query_with_bindings("SELECT * FROM %s WHERE %s=?" % [table, table_graph_column], [word])
|
|
if Database.db.query_result.is_empty():
|
|
Database.db.insert_row(table, {table_graph_column: word})
|
|
id = Database.db.last_insert_rowid
|
|
for index: int in range(gp_ids.size()):
|
|
Database.db.insert_row(relational_table, {
|
|
table_graph_column + "ID": id,
|
|
sub_table_id: gp_ids[index],
|
|
"Position": index
|
|
})
|
|
|
|
|
|
func _already_in_database(text: String) -> int:
|
|
var query: String = "SELECT %s.ID, %s, group_concat(%s, ' ') as %ss, group_concat(%s, ' ') as %ss, group_concat(%s.ID, ' ') as %sIDs
|
|
FROM %s
|
|
INNER JOIN ( SELECT * FROM %s ORDER BY %s.Position ) %s ON %s.ID = %s.%sID
|
|
INNER JOIN %s ON %s.ID = %s.%s
|
|
WHERE %s.%s = ?
|
|
GROUP BY %s.ID" % [table, table_graph_column, sub_table_graph_column, sub_table_graph_column,
|
|
sub_table_phon_column, sub_table_phon_column,
|
|
relational_table, relational_table,
|
|
table,
|
|
relational_table, relational_table, relational_table, table, relational_table, table_graph_column,
|
|
sub_table, sub_table, relational_table, sub_table_id,
|
|
table, table_graph_column,
|
|
table]
|
|
Database.db.query_with_bindings(query, [text])
|
|
if not Database.db.query_result.is_empty():
|
|
var element: Dictionary = Database.db.query_result[0]
|
|
id = element.ID
|
|
return id
|
|
return -1
|
|
|
|
|
|
func _add_from_additional_word_list(new_text: String) -> int:
|
|
if new_text in Database.additional_word_list:
|
|
var is_word: bool = table == "Words"
|
|
# res contains an int, followed by an array of int
|
|
var res: Array[Variant] = Database._import_word_from_csv(new_text, Database.additional_word_list[new_text].GPMATCH as String, is_word)
|
|
gps_updated.emit()
|
|
id = res[0]
|
|
gp_ids = res[1]
|
|
unvalidated_gp_ids = gp_ids
|
|
return id
|
|
return -1
|
|
|
|
|
|
func _try_to_complete_from_word(new_text: String) -> int:
|
|
var index: int = _already_in_database(new_text)
|
|
if index >= 0:
|
|
Logger.trace("WordListElement: Already in DB " + new_text)
|
|
return index
|
|
|
|
index = _add_from_additional_word_list(new_text)
|
|
if index >= 0:
|
|
return index
|
|
return -1
|
|
|
|
|
|
func _on_word_edit_text_submitted(new_text: String) -> void:
|
|
if _try_to_complete_from_word(new_text) >= 0:
|
|
_on_validate_button_pressed()
|
|
update_lesson()
|
|
|
|
|
|
func _on_remove_gp_button_2_pressed() -> void:
|
|
if graphemes_edit_container.get_child_count() < 2:
|
|
return
|
|
unvalidated_gp_ids.pop_back()
|
|
graphemes_edit_container.get_child(graphemes_edit_container.get_child_count() - 1).queue_free()
|
|
graphemes_edit_container.get_child(graphemes_edit_container.get_child_count() - 2).queue_free()
|
|
word_edit.text = get_graphemes(unvalidated_gp_ids)
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
add_gp_button.visible = graphemes_edit_container.get_child_count() <= 0
|
|
remove_gp_button.visible = graphemes_edit_container.get_child_count() > 0
|
|
|
|
|
|
func new_gp_asked_added(ind: int, gp_id: int) -> void:
|
|
unvalidated_gp_ids[ind] = gp_id
|
|
set_graphemes_edit(unvalidated_gp_ids)
|
|
word_edit.text = get_graphemes(unvalidated_gp_ids)
|
|
|
|
|
|
func _on_add_gp_button_pressed(element: Node) -> void:
|
|
var ind_gp_id: int = int(element.get_index() / 2.0)
|
|
var gp_id: int = sub_elements_list.keys()[0]
|
|
unvalidated_gp_ids.insert(ind_gp_id + 1, gp_id)
|
|
add_gp_list_button(gp_id, ind_gp_id + 1)
|
|
|
|
|
|
func _on_empty_add_gp_button_pressed() -> void:
|
|
var gp_id: int = sub_elements_list.keys()[0]
|
|
unvalidated_gp_ids.append(gp_id)
|
|
add_gp_list_button(gp_id, unvalidated_gp_ids.size() - 1)
|