# vim: set fileencoding=utf-8 : ############################################################################### # # # Copyright (c) 2019 Idiap Research Institute, http://www.idiap.ch/ # # Contact: beat.support@idiap.ch # # # # This file is part of the beat.editor module of the BEAT platform. # # # # Commercial License Usage # # Licensees holding valid commercial BEAT licenses may use this file in # # accordance with the terms contained in a written agreement between you # # and Idiap. For further information contact tto@idiap.ch # # # # Alternatively, this file may be used under the terms of the GNU Affero # # Public License version 3 as published by the Free Software and appearing # # in the file LICENSE.AGPL included in the packaging of this file. # # The BEAT platform is distributed in the hope that it will be useful, but # # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # # or FITNESS FOR A PARTICULAR PURPOSE. # # # # You should have received a copy of the GNU Affero Public License along # # with the BEAT platform. If not, see http://www.gnu.org/licenses/. # # # ############################################################################### import os from PyQt5.QtCore import pyqtSignal from PyQt5.QtCore import pyqtSlot from PyQt5.QtCore import pyqtProperty from PyQt5.QtCore import QStringListModel from ..utils import dataformat_basetypes from .asset import AssetType class AssetModel(QStringListModel): """The asset model present a list of available asset from a given type""" assetTypeChanged = pyqtSignal(AssetType) prefixPathChanged = pyqtSignal(str) def __init__(self, parent=None): """Constructor""" super(QStringListModel, self).__init__(parent) self.__latest_only = True self.__prefix_path = None self.__asset_type = AssetType.UNKNOWN def setLatestOnlyEnabled(self, enabled): if self.__latest_only == enabled: return self.__latest_only = enabled self.reload() @pyqtSlot() def reload(self): """Loads the content regarding the asset property from the prefix""" if not self.__prefix_path or self.__asset_type == AssetType.UNKNOWN: return def _find_json_files(path): """Return all json files from folder sorted""" asset_items = os.scandir(path) json_files = sorted( [ item.name for item in asset_items if item.is_file() and item.name.endswith("json") ] ) return json_files assets_list = [] if self.asset_type in [AssetType.DATABASE, AssetType.PROTOCOLTEMPLATE]: # These assets have no user associated with them for asset_folder in os.scandir(self.asset_folder): json_files = _find_json_files(asset_folder) if json_files: if self.__latest_only: json_files = json_files[-1:] for json_file in json_files: assets_list.append( "{name}/{version}".format( name=asset_folder.name, version=json_file.split(".")[0] ) ) else: # Assets belonging to a user asset_users = os.scandir(self.asset_folder) for asset_user in asset_users: for asset_folder in os.scandir(asset_user): if self.asset_type == AssetType.EXPERIMENT: for root, dirs, files in os.walk(asset_folder, topdown=False): if dirs: continue anchor = "experiments/" position = root.index(anchor) + len(anchor) experiment_path = root[position:] for json_file in [ file for file in files if file.endswith("json") ]: assets_list.append( "{experiment_path}/{name}".format( experiment_path=experiment_path, name=json_file.split(".")[0], ) ) else: json_files = _find_json_files(asset_folder) if json_files: if self.__latest_only: json_files = json_files[-1:] for json_file in json_files: assets_list.append( "{user}/{name}/{version}".format( user=asset_user.name, name=asset_folder.name, version=json_file.split(".")[0], ) ) assets_list = sorted(assets_list) if self.asset_type == AssetType.DATAFORMAT: assets_list = dataformat_basetypes() + assets_list self.setStringList(assets_list) def assetType(self): """Returns the asset type of this model :return: Asset type of this model """ return self.__asset_type def setAssetType(self, type_): """Set the asset type of this model :param AssetType type_: Asset type this model should show """ if self.__asset_type == type_: return self.__asset_type = type_ self.reload() self.assetTypeChanged.emit(type_) asset_type = pyqtProperty( AssetType, fget=assetType, fset=setAssetType, notify=assetTypeChanged ) def prefixPath(self): """Returns the prefix path use by this model :return: the prefix path used """ return self.__prefix_path def setPrefixPath(self, path): """Set the prefix path use by this model :param str path: Path to prefix """ if self.__prefix_path == path: return self.__prefix_path = path self.reload() self.prefixPathChanged.emit(path) prefix_path = pyqtProperty( str, fget=prefixPath, fset=setPrefixPath, notify=prefixPathChanged ) @property def asset_folder(self): """Returns the folder matching this model asset type""" return os.path.join(self.prefix_path, self.asset_type.path) def json_path(self, asset_name): """Returns the full path to the json file matching the asset given :param asset_name str: fully qualified asset name """ asset_path = self.asset_type.declaration_path(self.prefix_path, asset_name) if not os.path.exists(asset_path): raise RuntimeError("Invalid asset {}".format(asset_name)) return asset_path