"""
This module contains the ModelConfigApps class, which handles the management of configuration files
used by MoilApp. It includes methods for loading, saving, resetting, and updating configuration settings,
as well as managing recent project configurations.
"""
from datetime import datetime
import os
import json
[docs]
class ModelConfigApps:
"""
The ModelConfigApps class manages configuration files for MoilApp.
Attributes:
_model: The ModelApps instance for accessing application data and functionalities.
_path_file (str): The path to the directory containing configuration files.
_config_file (str): The path to the main configuration file.
_config_project_file (str): The path to the recent project configuration file.
_recent_config_dir (str): The path to the directory containing recent project configuration files.
Methods:
- get_config_file: Manages the main configuration file for MoilApp.
- save_update_main_config: Saves updated configuration data to the main configuration file.
- reset_value_main_config: Resets the configuration view to its default values.
- read_recent_config_path: Reads recent project configuration files from the specified directory.
- get_timestamp: Extracts the timestamp from a filename to sort recent project configurations.
- load_json_file: Loads a JSON file from the specified path and returns its content.
- load_json_file_project: Loads a 'recent__.json' file from the specified directory and returns its content.
- remove_json_file_project: Removes a specific 'recent__.json' file from the recent configuration directory.
- create_config_recent: Creates a new recent configuration file with a unique name based on the current timestamp.
- create_new_data_recent: Creates a new 'recent__.json' file for the recent open project.
- update_main_config_from_recent: Updates the main configuration from the recent configuration.
"""
def __init__(self, model):
self._model = model
self._path_file = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
self._config_file = self._path_file + "/models/cached/main_config.json"
self._config_project_file = self._path_file + "/models/cached/recent_main.json"
self._recent_config_dir = self._path_file + "/models/cached/"
[docs]
def get_config_file(self):
"""
Manages the main configuration file for MoilApp.
This method checks if the main configuration file exists. If the file exists, it loads its content.
If the file doesn't exist or encounters an error during loading, it resets the configuration to default values.
Return:
str: The path to the main configuration file.
"""
try:
if self._model.debug_mode:
self._model.activity_logger.info("ModelConfigApps: get_config_file(), "
"Create config_main file if not exist on path and load the config if exist")
if not os.path.exists(self._config_file):
self.reset_value_main_config()
else:
try:
data = self.load_json_file(self._config_file)
if not data:
self.reset_value_main_config()
except (json.decoder.JSONDecodeError, FileNotFoundError):
with open(self._config_file, 'w', encoding='utf-8') as f:
json.dump({}, f)
self.reset_value_main_config()
return self._config_file
except Exception as e:
self._model.activity_logger.error(f"ModelConfigApps.get_config_file(): Error: {str(e)}")
[docs]
def save_update_main_config(self, data):
"""
Save updated configuration data to the main configuration file for MoilApp.
This method writes the provided configuration data to the main configuration file.
The configuration file is formatted with an indentation of 5 spaces for better readability.
Arg:
data (dict): The updated configuration data to be saved.
Return:
None
"""
try:
if self._model.debug_mode:
self._model.activity_logger.info("ModelConfigApps: save_update_main_config(), "
"Save config that updated on program with argument data(config)")
with open(self._config_file, 'w', encoding='utf-8') as json_file:
json.dump(data, json_file, indent=5)
self.create_config_recent()
except Exception as e:
self._model.activity_logger.error(f"ModelConfigApps.save_update_main_config(): Error: {str(e)}")
# Reset config to the default value ++++++
[docs]
def reset_value_main_config(self):
"""
Reset the configuration view to its default values.
This function sets all the fields of the configuration view to their default values,
and saves the new configuration to the config file.
"""
try:
if self._model.debug_mode:
self._model.activity_logger.info("ModelConfigApps: reset_value_main_config(), Reset all value of "
"main_config in dictionary data type")
config = {
"Debug_mode": False,
"Plugin_run": None,
"Github_config": {
"active_branch": None,
"list_branch": [None, None],
"origin_url": "Can't found remote repository URL!",
"token": None,
"error": None,
"user_name": None
},
"Media_path": None,
"Cam_type": None,
"Parameter_name": None,
"Source_type": None,
"Zoom_size": 1000,
"Recent_view": "FisheyeView",
"Recenter_view": False,
"Active_view": None,
"Rotate_result": 0,
"Image_original": {
"rotate": 0,
"width": None,
"height": None,
"center_coord": [0, 0],
"pointer": [None, None]
},
"Image_recenter": {
"Recenter_coordinate": [None, None],
"pointer": [None, None],
"alpha": 0,
"beta": 0
},
"Mode_1": {
"coord": [0, 0],
"alpha": 0,
"beta": 0,
"zoom": 4
},
"Mode_2": {
"coord": [0, 0],
"pitch": 0,
"yaw": 0,
"roll": 0,
"zoom": 4
},
"Pano_tube": {
"alpha_min": 8,
"alpha_max": 110,
"crop_top": 0,
"crop_bottom": 1
},
"Pano_car": {
"coord": [0, 0],
"alpha_max": 110,
"flip": False,
"alpha": 0,
"beta": 0,
"crop_left": 0,
"crop_right": 1,
"crop_top": 0,
"crop_bottom": 1
},
"Image_saved": {},
"Open_directory": None
}
with open(self._config_file, "w", encoding="utf-8") as write_file:
json.dump(config, write_file, indent=5)
except Exception as e:
self._model.activity_logger.error(f"ModelConfigApps.reset_value_main_config(): Error: {str(e)}")
[docs]
def read_recent_config_path(self):
"""
Read the recent project configuration files from the specified directory.
This method scans the directory for files with names starting with 'recent_' and ending with '.json'.
It reads each file and checks if it contains a valid 'Media_path' key. If valid, the file name
is added to the list of recent project configurations; otherwise, the file is removed.
Return:
None
"""
try:
if self._model.debug_mode:
self._model.activity_logger.info("ModelConfigApps: read_recent_config_path(), "
"Read all file recent'__'.json for recent open project")
self._model.recent_project_list = []
for recent_file in os.listdir(self._recent_config_dir):
if recent_file.startswith("recent_") and recent_file.endswith(".json"):
config = self.load_json_file_project(recent_file)
if config["Media_path"] is not None:
self._model.recent_project_list.append(recent_file)
else:
self.remove_json_file_project(recent_file)
self._model.recent_project_list = sorted(self._model.recent_project_list, key=self.get_timestamp,
reverse=True)
except Exception as e:
self._model.activity_logger.error(f"ModelConfigApps.read_recent_config_path(): Error: {str(e)}")
[docs]
def get_timestamp(self, filename):
"""
Extract the timestamp from a filename to sort recent project configurations.
This method parses the given filename to extract the timestamp embedded in the format 'recent_[timestamp].json'.
The extracted timestamp is returned for sorting the recent project configurations by their creation time.
Arg:
filename (str): The name of the recent project configuration file.
Return:
str: The extracted timestamp from the filename.
"""
try:
if self._model.debug_mode:
self._model.activity_logger.info("ModelConfigApps: get_timestamp(), "
"Split name of 'recent__.json' for get newest and oldest project")
return filename.split('_')[2].split('.')[0]
except Exception as e:
self._model.activity_logger.error(f"ModelConfigApps.get_timestamp(): Error: {str(e)}")
[docs]
def load_json_file(self, path):
"""
Load a JSON file from the specified path and returns its content.
This method reads the JSON file located at the given path and parses its content into a Python dictionary.
The parsed content is then returned to the caller.
Arg:
path (str): The path to the JSON file to be loaded.
Return:
dict: The parsed content of the JSON file as a dictionary.
"""
try:
if self._model.debug_mode:
self._model.activity_logger.info("ModelConfigApps: load_json_file(), "
"Load '.json' file in path and return in variable")
with open(path, 'r', encoding='utf-8') as file:
content = json.load(file)
return content
except Exception as e:
self._model.activity_logger.error(f"ModelConfigApps.load_json_file(): Error: {str(e)}")
[docs]
def load_json_file_project(self, path):
"""
Load a 'recent__.json' file from the specified directory and returns its content.
This method constructs the full path to the 'recent__.json' file using the provided path and the directory where
recent configuration files are stored. It then calls the `load_json_file` method to read and parse the JSON content.
Arg:
path (str): The filename of the 'recent__.json' file to be loaded.
Return:
dict: The parsed content of the 'recent__.json' file as a dictionary.
"""
try:
if self._model.debug_mode:
self._model.activity_logger.info("ModelConfigApps: load_json_file_project(), "
"Load 'recent__.json' file in path and return in variable")
return self.load_json_file(self._recent_config_dir + path)
except Exception as e:
self._model.activity_logger.error(f"ModelConfigApps.load_json_file_project(): Error: {str(e)}")
[docs]
def remove_json_file_project(self, path):
"""
Remove a specific 'recent__.json' file from the recent configuration directory.
This method constructs the full path to the 'recent__.json' file using the provided filename and the directory
where recent configuration files are stored. It then deletes the file from the file system.
Arg:
path (str): The filename of the 'recent__.json' file to be removed.
Return:
None
"""
try:
if self._model.debug_mode:
self._model.activity_logger.info("ModelConfigApps: remove_json_file_project(), Remove specific "
"'recent__.json' file in path")
os.remove(self._recent_config_dir + path)
except Exception as e:
self._model.activity_logger.error(f"ModelConfigApps.remove_json_file_project(): Error: {str(e)}")
[docs]
def create_config_recent(self):
"""
Create a new recent configuration file with a unique name based on the current timestamp.
This method generates a unique filename for the new recent configuration file using the current date and time.
It then checks the existing recent configuration files to ensure that there are no duplicates or overlaps
with the current project's media path. If a duplicate is found, it removes the old recent configuration file
and creates a new one.
Arg:
None
Return:
None
"""
try:
if self._model.debug_mode:
self._model.activity_logger.info("ModelConfigApps: create_config_recent(), "
"Create config recent with deference name and logic to not "
"overlap with other project")
filename = f"{self._recent_config_dir}recent_" + datetime.now().strftime('%Y%m%d_%H%M%S%f') + ".json"
for recent_file in os.listdir(self._recent_config_dir):
if recent_file.startswith("recent_") and recent_file.endswith(".json"):
config_recent = self.load_json_file_project(recent_file)
if config_recent["Media_path"] == self._model.main_config["Media_path"]:
# self.update_main_config_from_recent(config_recent, load=False)
self.create_new_data_recent(filename)
self.remove_json_file_project(recent_file)
else:
self.create_new_data_recent(filename)
self.read_recent_config_path()
except Exception as e:
self._model.activity_logger.error(f"ModelConfigApps.create_config_recent(): Error: {str(e)}")
[docs]
def create_new_data_recent(self, filename):
"""
Create a new 'recent__.json' file for the recent open project.
This method constructs a new recent configuration data based on the main configuration data of the current project.
It gathers essential parameters such as source type, camera type, media path, and various mode settings from the
main configuration. This data is then saved into a new 'recent__.json' file with the specified filename.
Arg:
filename (str): The filename for the new recent configuration file.
Return:
None
"""
try:
if self._model.debug_mode:
self._model.activity_logger.info("ModelConfigApps: create_new_data_recent(), "
"Create new file 'recent__.json' for recent open project with argument "
"filename to make sure not overlap")
main_config = self._model.main_config
new_data_recent = {
"Source_type": main_config["Source_type"],
"Cam_type": main_config["Cam_type"],
"Media_path": main_config["Media_path"],
"Parameter_name": main_config["Parameter_name"],
"Recent_view": main_config["Recent_view"],
"Recenter_view": main_config["Recenter_view"],
"Active_view": main_config["Active_view"],
"Rotate_result": main_config["Rotate_result"],
"Image_original": main_config["Image_original"],
"Image_recenter": main_config["Image_recenter"],
"Mode_1": main_config["Mode_1"],
"Mode_2": main_config["Mode_2"],
"Pano_car": main_config["Pano_car"],
"Pano_tube": main_config["Pano_tube"],
}
with open(filename, "w", encoding="utf-8") as write_file:
json.dump(new_data_recent, write_file, indent=5)
except Exception as e:
self._model.activity_logger.error(f"ModelConfigApps.create_new_data_recent(): Error: {str(e)}")
[docs]
def update_main_config_from_recent(self, config, load=True):
"""
Update the main configuration from the recent configuration.
Updates the main configuration attributes based on the values provided in the recent configuration.
Optionally, saves the updated main configuration to the configuration file.
Args:
config (dict): The recent configuration dictionary.
load (bool, optional): Whether to load the updated main configuration. Defaults to True.
Return:
None
"""
try:
self._model.main_config["Source_type"] = config["Source_type"]
self._model.main_config["Cam_type"] = config["Cam_type"]
self._model.main_config["Media_path"] = config["Media_path"]
self._model.main_config["Parameter_name"] = config["Parameter_name"]
self._model.main_config["Recent_view"] = config["Recent_view"]
self._model.main_config["Recenter_view"] = config["Recenter_view"]
self._model.main_config["Active_view"] = config["Active_view"]
self._model.main_config["Rotate_result"] = config["Rotate_result"]
self._model.main_config["Image_original"] = config["Image_original"]
self._model.main_config["Image_recenter"] = config["Image_recenter"]
self._model.main_config["Mode_1"] = config["Mode_1"]
self._model.main_config["Mode_2"] = config["Mode_2"]
self._model.main_config["Pano_car"] = config["Pano_car"]
self._model.main_config["Pano_tube"] = config["Pano_tube"]
if load:
# pass
# self._model.main_config = self.get_config_file()
self.save_update_main_config(self._model.main_config)
except Exception as e:
self._model.activity_logger.error(f"ModelConfigApps.update_main_config_from_recent(): Error: {str(e)}")