cancel build right mouse button
This commit is contained in:
305
addons/kanban_tasks/data/board.gd
Normal file
305
addons/kanban_tasks/data/board.gd
Normal file
@@ -0,0 +1,305 @@
|
||||
@tool
|
||||
extends "kanban_resource.gd"
|
||||
|
||||
## Manages the loading and saving of other data.
|
||||
|
||||
|
||||
const __UUID := preload("../uuid/uuid.gd")
|
||||
const __Category := preload("category.gd")
|
||||
const __Layout := preload("layout.gd")
|
||||
const __Stage := preload("stage.gd")
|
||||
const __Task := preload("task.gd")
|
||||
const __KanbanResource := preload("kanban_resource.gd")
|
||||
|
||||
var layout: __Layout:
|
||||
set(value):
|
||||
if layout:
|
||||
layout.changed.disconnect(__notify_changed)
|
||||
layout = value
|
||||
layout.changed.connect(__notify_changed)
|
||||
|
||||
var __categories: Dictionary
|
||||
var __stages: Dictionary
|
||||
var __tasks: Dictionary
|
||||
|
||||
|
||||
## Generates a json representation of the board.
|
||||
func to_json() -> Dictionary:
|
||||
var dict := {}
|
||||
|
||||
var category_data := __propagate_uuid_dict(__categories)
|
||||
dict["categories"] = category_data
|
||||
|
||||
var stage_data := __propagate_uuid_dict(__stages)
|
||||
dict["stages"] = stage_data
|
||||
|
||||
var task_data := __propagate_uuid_dict(__tasks)
|
||||
dict["tasks"] = task_data
|
||||
|
||||
dict["layout"] = layout.to_json()
|
||||
|
||||
return dict
|
||||
|
||||
|
||||
## Save the board at `path`.
|
||||
func save(path: String) -> void:
|
||||
var file = FileAccess.open(path, FileAccess.WRITE)
|
||||
if not file:
|
||||
push_error("Error " + str(FileAccess.get_open_error()) + " while opening file for saving board data at " + path)
|
||||
file.close()
|
||||
return
|
||||
|
||||
var string := JSON.stringify(to_json(), "\t", false)
|
||||
file.store_string(string)
|
||||
file.close()
|
||||
|
||||
|
||||
## Initializes the board state from json data.
|
||||
func from_json(json: Dictionary) -> void:
|
||||
__instantiate_uuid_array(json.get("categories", null), __Category, __add_category)
|
||||
__instantiate_uuid_array(json.get("stages", null), __Stage, __add_stage)
|
||||
__instantiate_uuid_array(json.get("tasks", null), __Task, __add_task)
|
||||
|
||||
layout = __Layout.new([])
|
||||
if json.get("layout", null) is Dictionary:
|
||||
layout.from_json(json["layout"])
|
||||
else:
|
||||
push_warning("Loading incomplete board data which is missing layout data.")
|
||||
|
||||
|
||||
## Loads the data from `path` into the current instance.
|
||||
func load(path: String) -> void:
|
||||
var file = FileAccess.open(path, FileAccess.READ)
|
||||
if not file:
|
||||
push_error("Error " + str(FileAccess.get_open_error()) + " while opening file for loading board data at " + path)
|
||||
file.close()
|
||||
return
|
||||
|
||||
var json = JSON.new()
|
||||
var err = json.parse(file.get_as_text())
|
||||
file.close()
|
||||
if err != OK:
|
||||
push_error("Error " + str(err) + " while parsing board at " + path + " to json. At line " + str(json.get_error_line()) + " the following problem occured:\n" + json.get_error_message())
|
||||
return
|
||||
|
||||
if json.data.has("columns"):
|
||||
__from_legacy_file(json.data)
|
||||
else:
|
||||
from_json(json.data)
|
||||
|
||||
|
||||
## Adds a category and returns the uuid which is associated with it.
|
||||
func add_category(category: __Category, silent: bool = false) -> String:
|
||||
var res := __add_category(category)
|
||||
if not silent:
|
||||
__notify_changed()
|
||||
return res
|
||||
|
||||
## Returns the category associated with the given uuid or `null` if there is none.
|
||||
func get_category(uuid: String) -> __Category:
|
||||
if not __categories.has(uuid) and uuid != "":
|
||||
push_warning('There is no category with the uuid "' + uuid + '".')
|
||||
return __categories.get(uuid, null)
|
||||
|
||||
## Returns the count of categories.
|
||||
func get_category_count() -> int:
|
||||
return len(__categories)
|
||||
|
||||
## Returns the uuid's of all categories.
|
||||
func get_categories() -> Array[String]:
|
||||
var temp: Array[String] = []
|
||||
temp.assign(__categories.keys())
|
||||
return temp
|
||||
|
||||
## Removes a category by uuid.
|
||||
func remove_category(uuid: String, silent: bool = false) -> void:
|
||||
if __categories.has(uuid):
|
||||
__categories[uuid].changed.disconnect(__notify_changed)
|
||||
__categories.erase(uuid)
|
||||
if not silent:
|
||||
__notify_changed()
|
||||
else:
|
||||
push_warning("Trying to remove uuid wich is not associated with a category.")
|
||||
|
||||
|
||||
## Adds a stage and returns the uuid which is associated with it.
|
||||
func add_stage(stage: __Stage, silent: bool = false) -> String:
|
||||
var res := __add_stage(stage)
|
||||
if not silent:
|
||||
__notify_changed()
|
||||
return res
|
||||
|
||||
## Returns the stage associated with the given uuid or `null` if there is none.
|
||||
func get_stage(uuid: String) -> __Stage:
|
||||
if not __stages.has(uuid) and uuid != "":
|
||||
push_warning('There is no stage with the uuid "' + uuid + '".')
|
||||
return __stages.get(uuid, null)
|
||||
|
||||
## Returns the count of stages.
|
||||
func get_stage_count() -> int:
|
||||
return len(__stages)
|
||||
|
||||
## Returns the uuid's of all stages.
|
||||
func get_stages() -> Array[String]:
|
||||
var temp: Array[String] = []
|
||||
temp.assign(__stages.keys())
|
||||
return temp
|
||||
|
||||
## Removes a stage by uuid.
|
||||
func remove_stage(uuid: String, silent: bool = false) -> void:
|
||||
if __stages.has(uuid):
|
||||
__stages[uuid].changed.disconnect(__notify_changed)
|
||||
__stages.erase(uuid)
|
||||
if not silent:
|
||||
__notify_changed()
|
||||
else:
|
||||
push_warning("Trying to remove uuid wich is not associated with a stage.")
|
||||
|
||||
|
||||
## Adds a task and returns the uuid which is associated with it.
|
||||
func add_task(task: __Task, silent: bool = false) -> String:
|
||||
var res := __add_task(task)
|
||||
if not silent:
|
||||
__notify_changed()
|
||||
return res
|
||||
|
||||
## Returns the task associated with the given uuid or `null` if there is none.
|
||||
func get_task(uuid: String) -> __Task:
|
||||
if not __tasks.has(uuid) and uuid != "":
|
||||
push_warning('There is no task with the uuid "' + uuid + '".')
|
||||
return __tasks.get(uuid, null)
|
||||
|
||||
## Returns the count of tasks.
|
||||
func get_task_count() -> int:
|
||||
return len(__tasks)
|
||||
|
||||
## Returns the uuid's of all tasks.
|
||||
func get_tasks() -> Array[String]:
|
||||
var temp: Array[String] = []
|
||||
temp.assign(__tasks.keys())
|
||||
return temp
|
||||
|
||||
## Removes a task by uuid.
|
||||
func remove_task(uuid: String, silent: bool = false) -> void:
|
||||
if __tasks.has(uuid):
|
||||
if __tasks[uuid].changed.is_connected(__notify_changed):
|
||||
__tasks[uuid].changed.disconnect(__notify_changed)
|
||||
__tasks.erase(uuid)
|
||||
if not silent:
|
||||
__notify_changed()
|
||||
else:
|
||||
push_warning("Trying to remove uuid wich is not associated with a task.")
|
||||
|
||||
|
||||
# Internal version of `add_category` which can be provided with an uuid suggestion.
|
||||
# The uuid that is passed can be altered by the board if it is already used by
|
||||
# an other category. Therefore always use the returned uuid.
|
||||
func __add_category(category: __Category, uuid: String = "") -> String:
|
||||
category.changed.connect(__notify_changed)
|
||||
|
||||
if __categories.has(uuid):
|
||||
push_warning("The uuid " + uuid + ' is already used. A new one will be generated for the category "' + category.title + '".')
|
||||
|
||||
if uuid == "":
|
||||
uuid = __UUID.v4()
|
||||
|
||||
while uuid in __categories.keys():
|
||||
uuid = __UUID.v4()
|
||||
|
||||
__categories[uuid] = category
|
||||
return uuid
|
||||
|
||||
|
||||
# Internal version of `add_stage` which can be provided with an uuid suggestion.
|
||||
func __add_stage(stage: __Stage, uuid: String = "") -> String:
|
||||
stage.changed.connect(__notify_changed)
|
||||
|
||||
if __stages.has(uuid):
|
||||
push_warning("The uuid " + uuid + ' is already used. A new one will be generated for the stage "' + stage.title + '".')
|
||||
|
||||
if uuid == "":
|
||||
uuid = __UUID.v4()
|
||||
|
||||
while uuid in __stages.keys():
|
||||
uuid = __UUID.v4()
|
||||
|
||||
__stages[uuid] = stage
|
||||
return uuid
|
||||
|
||||
|
||||
# Internal version of `add_task` which can be provided with an uuid suggestion.
|
||||
func __add_task(task: __Task, uuid: String = "") -> String:
|
||||
task.changed.connect(__notify_changed)
|
||||
|
||||
if __tasks.has(uuid):
|
||||
push_warning("The uuid " + uuid + ' is already used. A new one will be generated for the task "' + task.title + '".')
|
||||
|
||||
if uuid == "":
|
||||
uuid = __UUID.v4()
|
||||
|
||||
while uuid in __tasks.keys():
|
||||
uuid = __UUID.v4()
|
||||
|
||||
__tasks[uuid] = task
|
||||
return uuid
|
||||
|
||||
|
||||
# HACK: `array` should have the type `Array` but then `null` could not be passed.
|
||||
func __instantiate_uuid_array(array, type: Script, add_callback: Callable) -> void:
|
||||
if array == null:
|
||||
push_warning("Loading incomplete board data which is missing data for '" + type.resource_path + "'.")
|
||||
return
|
||||
|
||||
for data in array:
|
||||
var instance: __KanbanResource = type.new()
|
||||
instance.from_json(data)
|
||||
add_callback.call(instance, data.get("uuid", ""))
|
||||
|
||||
|
||||
# Converts a dictionary with (uuid, kanban_resource) pairs into a list
|
||||
# json representations with the uuid added.
|
||||
func __propagate_uuid_dict(dict: Dictionary) -> Array:
|
||||
var res := []
|
||||
for key in dict.keys():
|
||||
var json: Dictionary = {"uuid": key}
|
||||
json.merge(dict[key].to_json())
|
||||
res.append(json)
|
||||
return res
|
||||
|
||||
|
||||
# TODO: Remove this sometime in the future.
|
||||
## Loads a board from the old file format.
|
||||
func __from_legacy_file(data: Dictionary) -> void:
|
||||
var categories: Array[String] = []
|
||||
var tasks: Array[String] = []
|
||||
var stages: Array[String] = []
|
||||
|
||||
for c in data["categories"]:
|
||||
categories.append(
|
||||
__add_category(__Category.new(c["title"], c["color"])),
|
||||
)
|
||||
|
||||
for t in data["tasks"]:
|
||||
tasks.append(
|
||||
__add_task(
|
||||
__Task.new(t["title"], t["details"], categories[t["category"]]),
|
||||
),
|
||||
)
|
||||
|
||||
for s in data["stages"]:
|
||||
var contained_tasks: Array[String] = []
|
||||
for t in s["tasks"]:
|
||||
contained_tasks.append(tasks[t])
|
||||
stages.append(
|
||||
__add_stage(
|
||||
__Stage.new(s["title"], contained_tasks),
|
||||
),
|
||||
)
|
||||
|
||||
var columns: Array[PackedStringArray] = []
|
||||
for c in data["columns"]:
|
||||
var column = PackedStringArray([])
|
||||
for s in c["stages"]:
|
||||
column.append(stages[s])
|
||||
columns.append(column)
|
||||
layout = __Layout.new(columns)
|
||||
1
addons/kanban_tasks/data/board.gd.uid
Normal file
1
addons/kanban_tasks/data/board.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://csd0qg7nc4p7m
|
||||
43
addons/kanban_tasks/data/category.gd
Normal file
43
addons/kanban_tasks/data/category.gd
Normal file
@@ -0,0 +1,43 @@
|
||||
@tool
|
||||
extends "kanban_resource.gd"
|
||||
|
||||
## Data of a category.
|
||||
|
||||
|
||||
var title: String:
|
||||
set(value):
|
||||
title = value
|
||||
__notify_changed()
|
||||
|
||||
var color: Color:
|
||||
set(value):
|
||||
color = value
|
||||
__notify_changed()
|
||||
|
||||
|
||||
func _init(p_title: String = "", p_color: Color = Color()) -> void:
|
||||
title = p_title
|
||||
color = p_color
|
||||
super._init()
|
||||
|
||||
|
||||
func to_json() -> Dictionary:
|
||||
return {
|
||||
"title": title,
|
||||
"color": color.to_html(false),
|
||||
}
|
||||
|
||||
|
||||
func from_json(json: Dictionary) -> void:
|
||||
title = "Missing data."
|
||||
color = Color.CORNFLOWER_BLUE
|
||||
|
||||
if json.has("title"):
|
||||
title = json["title"]
|
||||
else:
|
||||
push_warning("Loading incomplete json data which is missing a title.")
|
||||
|
||||
if json.has("color"):
|
||||
color = Color.html(json["color"])
|
||||
else:
|
||||
push_warning("Loading incomplete json data which is missing a color.")
|
||||
1
addons/kanban_tasks/data/category.gd.uid
Normal file
1
addons/kanban_tasks/data/category.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bymg657d5rk55
|
||||
30
addons/kanban_tasks/data/kanban_resource.gd
Normal file
30
addons/kanban_tasks/data/kanban_resource.gd
Normal file
@@ -0,0 +1,30 @@
|
||||
@tool
|
||||
extends RefCounted
|
||||
|
||||
## Base class for kanban tasks data structures.
|
||||
|
||||
|
||||
## Emitted when the resource changed. The properties are updated before emitting.
|
||||
signal changed()
|
||||
|
||||
var __emit_changed := true
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
pass
|
||||
|
||||
|
||||
## Serializes the object as json.
|
||||
func to_json() -> Dictionary:
|
||||
push_error("Method to_json not implemented.")
|
||||
return {}
|
||||
|
||||
|
||||
## Deserializes the object from json.
|
||||
func from_json(json: Dictionary) -> void:
|
||||
push_error("Method from_json not implemented.")
|
||||
|
||||
|
||||
func __notify_changed() -> void:
|
||||
if __emit_changed:
|
||||
changed.emit()
|
||||
1
addons/kanban_tasks/data/kanban_resource.gd.uid
Normal file
1
addons/kanban_tasks/data/kanban_resource.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dwbcvxus65wau
|
||||
49
addons/kanban_tasks/data/layout.gd
Normal file
49
addons/kanban_tasks/data/layout.gd
Normal file
@@ -0,0 +1,49 @@
|
||||
@tool
|
||||
extends "kanban_resource.gd"
|
||||
|
||||
## Layout data.
|
||||
|
||||
|
||||
# Use `PackedStringArray` because nested typed collections are not supported.
|
||||
var columns: Array[PackedStringArray] = []:
|
||||
get:
|
||||
return columns.duplicate()
|
||||
set(value):
|
||||
columns = value
|
||||
__notify_changed()
|
||||
|
||||
|
||||
func _init(p_columns: Array[PackedStringArray] = []) -> void:
|
||||
columns = p_columns
|
||||
super._init()
|
||||
|
||||
|
||||
func to_json() -> Dictionary:
|
||||
var cols := []
|
||||
for c in columns:
|
||||
var col = []
|
||||
for uuid in c:
|
||||
col.append(uuid)
|
||||
cols.append(col)
|
||||
return {
|
||||
"columns": cols,
|
||||
}
|
||||
|
||||
|
||||
func from_json(json: Dictionary) -> void:
|
||||
if json.has("columns"):
|
||||
if json["columns"] is Array:
|
||||
var cols: Array[PackedStringArray] = []
|
||||
for c in json["columns"]:
|
||||
var arr := PackedStringArray()
|
||||
if c is Array:
|
||||
for id in c:
|
||||
arr.append(id)
|
||||
else:
|
||||
push_warning("Layout data is corrupted.")
|
||||
cols.append(arr)
|
||||
columns = cols
|
||||
else:
|
||||
push_warning("Layout data is corrupted.")
|
||||
else:
|
||||
push_warning("Loading incomplete json data which is missing a list of columns.")
|
||||
1
addons/kanban_tasks/data/layout.gd.uid
Normal file
1
addons/kanban_tasks/data/layout.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://rt5utu17k4q4
|
||||
159
addons/kanban_tasks/data/settings.gd
Normal file
159
addons/kanban_tasks/data/settings.gd
Normal file
@@ -0,0 +1,159 @@
|
||||
@tool
|
||||
extends "kanban_resource.gd"
|
||||
|
||||
## Contains settings that are not bound to a board.
|
||||
|
||||
|
||||
const DEFAULT_EDITOR_DATA_PATH: String = "res://kanban_tasks_data.kanban"
|
||||
|
||||
enum DescriptionOnBoard {
|
||||
FULL,
|
||||
FIRST_LINE,
|
||||
UNTIL_FIRST_BLANK_LINE,
|
||||
}
|
||||
|
||||
enum StepsOnBoard {
|
||||
ONLY_OPEN,
|
||||
ALL_OPEN_FIRST,
|
||||
ALL_IN_ORDER
|
||||
}
|
||||
|
||||
## Whether the first line of the description is shown on the board.
|
||||
var show_description_preview: bool = true:
|
||||
set(value):
|
||||
show_description_preview = value
|
||||
__notify_changed()
|
||||
|
||||
var show_steps_preview: bool = true:
|
||||
set(value):
|
||||
show_steps_preview = value
|
||||
__notify_changed()
|
||||
|
||||
var show_category_on_board: bool = false:
|
||||
set(value):
|
||||
show_category_on_board = value
|
||||
__notify_changed()
|
||||
|
||||
var edit_step_details_exclusively: bool = false:
|
||||
set(value):
|
||||
edit_step_details_exclusively = value
|
||||
__notify_changed()
|
||||
|
||||
var max_displayed_lines_in_description: int = 0:
|
||||
set(value):
|
||||
max_displayed_lines_in_description = value
|
||||
__notify_changed()
|
||||
|
||||
var description_on_board := DescriptionOnBoard.FIRST_LINE:
|
||||
set(value):
|
||||
description_on_board = value
|
||||
__notify_changed()
|
||||
|
||||
var steps_on_board := StepsOnBoard.ONLY_OPEN:
|
||||
set(value):
|
||||
steps_on_board = value
|
||||
__notify_changed()
|
||||
|
||||
var max_steps_on_board: int = 2:
|
||||
set(value):
|
||||
max_steps_on_board = value
|
||||
__notify_changed()
|
||||
|
||||
var stages_width: int = 200:
|
||||
set(value):
|
||||
stages_width = value
|
||||
__notify_changed()
|
||||
|
||||
var editor_data_file_path: String = DEFAULT_EDITOR_DATA_PATH:
|
||||
set(value):
|
||||
editor_data_file_path = value
|
||||
__notify_changed()
|
||||
|
||||
var warn_about_empty_deletion: bool = false:
|
||||
set(value):
|
||||
warn_about_empty_deletion = value
|
||||
__notify_changed()
|
||||
|
||||
var recent_file_count: int = 5:
|
||||
set(value):
|
||||
recent_file_count = value
|
||||
recent_files.resize(value)
|
||||
__notify_changed()
|
||||
|
||||
var recent_files: PackedStringArray = []:
|
||||
get:
|
||||
return recent_files.duplicate()
|
||||
set(value):
|
||||
recent_files = value
|
||||
__notify_changed()
|
||||
|
||||
# Here such settings can come, which is own responsibiity of a user control.
|
||||
# When it just want to persist its own state, but the setting is not used by anything else.
|
||||
# In this case there is no need to mess up this class with bolerplate code
|
||||
# E.g. the splitter position in the details editor window
|
||||
# Set via set_internal_state to trigger notification
|
||||
# (As no clean-up, during develolpment some mess can remain in it.
|
||||
# Use clear or erase in your code in such cases, just don't forget there)
|
||||
var internal_states: Dictionary = { }
|
||||
|
||||
|
||||
func set_internal_state(property: String, value: Variant) -> void:
|
||||
internal_states[property] = value
|
||||
__notify_changed()
|
||||
|
||||
|
||||
func to_json() -> Dictionary:
|
||||
var res := {
|
||||
"show_description_preview": show_description_preview,
|
||||
"warn_about_empty_deletion": warn_about_empty_deletion,
|
||||
"edit_step_details_exclusively": edit_step_details_exclusively,
|
||||
"max_displayed_lines_in_description": max_displayed_lines_in_description,
|
||||
"description_on_board": description_on_board,
|
||||
"show_steps_preview": show_steps_preview,
|
||||
"show_category_on_board": show_category_on_board,
|
||||
"steps_on_board": steps_on_board,
|
||||
"max_steps_on_board": max_steps_on_board,
|
||||
"stages_width": stages_width,
|
||||
}
|
||||
|
||||
if not Engine.is_editor_hint():
|
||||
res["recent_file_count"] = recent_file_count
|
||||
res["recent_files"] = recent_files
|
||||
else:
|
||||
res["editor_data_file_path"] = editor_data_file_path
|
||||
|
||||
res["internal_states"] = internal_states
|
||||
|
||||
return res
|
||||
|
||||
|
||||
func from_json(json: Dictionary) -> void:
|
||||
if json.has("show_description_preview"):
|
||||
show_description_preview = json["show_description_preview"]
|
||||
if json.has("warn_about_empty_deletion"):
|
||||
warn_about_empty_deletion = json["warn_about_empty_deletion"]
|
||||
if json.has("edit_step_details_exclusively"):
|
||||
edit_step_details_exclusively = json["edit_step_details_exclusively"]
|
||||
if json.has("max_displayed_lines_in_description"):
|
||||
max_displayed_lines_in_description = json["max_displayed_lines_in_description"]
|
||||
if json.has("description_on_board"):
|
||||
description_on_board = json["description_on_board"]
|
||||
if json.has("editor_data_file_path"):
|
||||
editor_data_file_path = json["editor_data_file_path"]
|
||||
if json.has("recent_file_count"):
|
||||
recent_file_count = json["recent_file_count"]
|
||||
if json.has("recent_files"):
|
||||
recent_files = PackedStringArray(json["recent_files"])
|
||||
if json.has("show_steps_preview"):
|
||||
show_steps_preview = json["show_steps_preview"]
|
||||
if json.has("steps_on_board"):
|
||||
steps_on_board = json["steps_on_board"]
|
||||
if json.has("max_steps_on_board"):
|
||||
max_steps_on_board = json["max_steps_on_board"]
|
||||
if json.has("stages_width"):
|
||||
stages_width = json["stages_width"]
|
||||
if json.has("show_category_on_board"):
|
||||
show_category_on_board = json["show_category_on_board"]
|
||||
if json.has("internal_states"):
|
||||
internal_states = json["internal_states"]
|
||||
__notify_changed()
|
||||
1
addons/kanban_tasks/data/settings.gd.uid
Normal file
1
addons/kanban_tasks/data/settings.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://l6lfl3k3qwxw
|
||||
48
addons/kanban_tasks/data/stage.gd
Normal file
48
addons/kanban_tasks/data/stage.gd
Normal file
@@ -0,0 +1,48 @@
|
||||
@tool
|
||||
extends "kanban_resource.gd"
|
||||
|
||||
## Data of a stage.
|
||||
|
||||
|
||||
var title: String:
|
||||
set(value):
|
||||
title = value
|
||||
__notify_changed()
|
||||
|
||||
var tasks: Array[String] = []:
|
||||
get:
|
||||
# Pass by value to avoid appending without emitting `changed`.
|
||||
return tasks.duplicate()
|
||||
set(value):
|
||||
tasks = value
|
||||
__notify_changed()
|
||||
|
||||
|
||||
func _init(p_title: String = "", p_tasks: Array[String] = []) -> void:
|
||||
title = p_title
|
||||
tasks = p_tasks
|
||||
super._init()
|
||||
|
||||
|
||||
func to_json() -> Dictionary:
|
||||
return {
|
||||
"title": title,
|
||||
"tasks": tasks,
|
||||
}
|
||||
|
||||
|
||||
func from_json(json: Dictionary) -> void:
|
||||
if json.has("title"):
|
||||
title = json["title"]
|
||||
else:
|
||||
push_warning("Loading incomplete json data which is missing a title.")
|
||||
|
||||
if json.has("tasks"):
|
||||
# HACK: Workaround for casting to typed array.
|
||||
var s: Array[String] = []
|
||||
for i in json["tasks"]:
|
||||
s.append(i)
|
||||
|
||||
tasks = s
|
||||
else:
|
||||
push_warning("Loading incomplete json data which is missing a list of tasks.")
|
||||
1
addons/kanban_tasks/data/stage.gd.uid
Normal file
1
addons/kanban_tasks/data/stage.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ciuqm01ng1wfq
|
||||
40
addons/kanban_tasks/data/step.gd
Normal file
40
addons/kanban_tasks/data/step.gd
Normal file
@@ -0,0 +1,40 @@
|
||||
@tool
|
||||
extends "kanban_resource.gd"
|
||||
|
||||
## Data of a step.
|
||||
|
||||
|
||||
var details: String:
|
||||
set(value):
|
||||
details = value
|
||||
__notify_changed()
|
||||
|
||||
var done: bool:
|
||||
set(value):
|
||||
done = value
|
||||
__notify_changed()
|
||||
|
||||
|
||||
func _init(p_details: String = "", p_done: bool = false) -> void:
|
||||
details = p_details
|
||||
done = p_done
|
||||
super._init()
|
||||
|
||||
|
||||
func to_json() -> Dictionary:
|
||||
return {
|
||||
"details": details,
|
||||
"done": done,
|
||||
}
|
||||
|
||||
|
||||
func from_json(json: Dictionary) -> void:
|
||||
if json.has("details"):
|
||||
details = json["details"]
|
||||
else:
|
||||
push_warning("Loading incomplete json data which is missing details.")
|
||||
|
||||
if json.has("done"):
|
||||
done = json["done"]
|
||||
else:
|
||||
push_warning("Loading incomplete json data which is missing 'done'.")
|
||||
1
addons/kanban_tasks/data/step.gd.uid
Normal file
1
addons/kanban_tasks/data/step.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cvg6hllieqvxj
|
||||
86
addons/kanban_tasks/data/task.gd
Normal file
86
addons/kanban_tasks/data/task.gd
Normal file
@@ -0,0 +1,86 @@
|
||||
@tool
|
||||
extends "kanban_resource.gd"
|
||||
|
||||
## Data of a task.
|
||||
|
||||
|
||||
const __Step := preload("step.gd")
|
||||
|
||||
var title: String:
|
||||
set(value):
|
||||
title = value
|
||||
__notify_changed()
|
||||
|
||||
var description: String:
|
||||
set(value):
|
||||
description = value
|
||||
__notify_changed()
|
||||
|
||||
var category: String:
|
||||
set(value):
|
||||
category = value
|
||||
__notify_changed()
|
||||
|
||||
var steps: Array[__Step]:
|
||||
get:
|
||||
return steps.duplicate()
|
||||
set(value):
|
||||
steps = value
|
||||
__notify_changed()
|
||||
|
||||
|
||||
func _init(p_title: String = "", p_description: String = "", p_category: String = "", p_steps: Array[__Step] = []) -> void:
|
||||
title = p_title
|
||||
description = p_description
|
||||
category = p_category
|
||||
steps = p_steps
|
||||
super._init()
|
||||
|
||||
|
||||
func add_step(step: __Step, silent: bool = false) -> void:
|
||||
var new_steps = steps
|
||||
new_steps.append(step)
|
||||
steps = new_steps
|
||||
step.changed.connect(__notify_changed)
|
||||
if not silent:
|
||||
__notify_changed()
|
||||
|
||||
|
||||
func to_json() -> Dictionary:
|
||||
var s: Array[Dictionary] = []
|
||||
for step in steps:
|
||||
s.append(step.to_json())
|
||||
|
||||
return {
|
||||
"title": title,
|
||||
"description": description,
|
||||
"category": category,
|
||||
"steps": s,
|
||||
}
|
||||
|
||||
|
||||
func from_json(json: Dictionary) -> void:
|
||||
if json.has("title"):
|
||||
title = json["title"]
|
||||
else:
|
||||
push_warning("Loading incomplete json data which is missing a title.")
|
||||
|
||||
if json.has("description"):
|
||||
description = json["description"]
|
||||
else:
|
||||
push_warning("Loading incomplete json data which is missing a description.")
|
||||
|
||||
if json.has("category"):
|
||||
category = json["category"]
|
||||
else:
|
||||
push_warning("Loading incomplete json data which is missing a category.")
|
||||
|
||||
if json.has("steps"):
|
||||
var s: Array[__Step] = []
|
||||
for step in json["steps"]:
|
||||
s.append(__Step.new())
|
||||
s[-1].from_json(step)
|
||||
s[-1].changed.connect(__notify_changed)
|
||||
steps = s
|
||||
else:
|
||||
push_warning("Loading incomplete json data which is missing steps.")
|
||||
1
addons/kanban_tasks/data/task.gd.uid
Normal file
1
addons/kanban_tasks/data/task.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b1j5opcoegc6y
|
||||
Reference in New Issue
Block a user