def __init__(self):
     super().__init__()
     self.other_data_context_was_added = Signal(BaseViewModel)
     self.other_data_context_was_removed = Signal(BaseViewModel)
     self.data_context_container = DataContexts()
     self._other_data_contexts = None
     self.other_data_contexts = ObservableList()
Esempio n. 2
0
class BaseViewModel(object):
    """
    This is the base view model class to be implemented by all data context classes
    """

    name = 'data_context'

    def __init__(self):
        self.property_changed = Signal(str)

    def notify_change(self, name):
        """
        Send notification that a variable has been changed that the binding enabled widgets can update accordingly
        :param name: variable name
        """
        self.property_changed.emit(name)

    def save_configuration(self):
        """
        This method can be overwritten to enable the automatic saving of the data-context data when it is used inside
        a modular application.

        NOTE: There is now save system in place, this method will just by called once the application terminates
        """
        pass
Esempio n. 3
0
class BindingEnabledWidget(object):
    """
    This class is not a visual widget but enables a widget that inherits it along with a Qt widget to do data binding.
    """

    data_context_changed = Signal(BaseViewModel)
    data_context_removed = Signal(BaseViewModel)

    @property
    def data_context(self):
        """
        Gets the data context of this frame
        """
        return self._data_context

    @data_context.setter
    def data_context(self, value):
        """
        Sets the data context of this frame
        """
        # alert that the old data context will be removed
        self.data_context_removed.emit(self._data_context)

        self._data_context = value
        self.bindings.destroy(
        )  # destroy the bindings manager to remove any previous binding relationships
        self.bindings = BindingManager(
            self._data_context)  # create a new bindings manager

        # alert listeners that the data context of this frame was changed
        self.data_context_changed.emit(self._data_context)

    def __init__(self):
        self._data_context = None
        self.bindings = BindingManager(None)

    def __del__(self):
        self.bindings.destroy()
Esempio n. 4
0
 def __init__(self):
     self._data_context = None
     self.data_context_changed = Signal(BaseViewModel)
     self.data_context_removed = Signal(BaseViewModel)
     self.bindings = BindingManager(None)
Esempio n. 5
0
class ExperimentOverviewViewModel(BaseContextAwareViewModel):
    """
    This is the data-context for the experiment frame. It stores the data-contexts of single experiment boxes.
    """

    name = 'experiments'

    add_experiment_request = Signal(bool)

    @property
    def experiment_folder(self):
        """
        Gets the path of the folder where the python scripts containing experiments are
        """
        return self._experiment_folder

    @experiment_folder.setter
    def experiment_folder(self, value):
        """
        Sets the path of the folder where the python scripts containing experiments are
        :param value: path
        """
        self._experiment_folder = value
        for experiment in self.experiments:
            experiment.experiment_folder = value

    def __init__(self, experiment_folder=None):
        super().__init__()
        self.experiments = ObservableList(
        )  # list that contains the experiment data-contexts
        self.experiments.item_added.connect(
            self._experiment_added_)  # listen for experiments which are added
        self._experiment_folder = experiment_folder  # member for storing the experiment folder path
        self.other_data_contexts.item_added.connect(
            self._data_contexts_changed_
        )  # listen for data contexts that appear in the application
        self.other_data_contexts.item_removed.connect(
            self._data_contexts_changed_
        )  # listen for data contexts that disappear from the application

    def add_experiment(self, cannot_be_removed=False):
        """
        Add experiment box
        :param cannot_be_removed: If set to true no remove button will be added
        """
        self.add_experiment_request.emit(cannot_be_removed)

    def save_configuration(self):
        """
        Save experiment configuration
        """
        experiment_list = list()
        for experiment in self.experiments:
            experiment_data = {'experiment_name': experiment.experiment_name}
            experiment_list.append(experiment_data)

        data = {
            'experiments': experiment_list,
            'experiment_folder': self.experiment_folder
        }
        with open(EXPERIMENT_CONFIG, 'w') as file:
            file.write(json.dumps(data))

    def load_configuration(self):
        """
        Load experiment configuration
        """
        if os.path.isfile(EXPERIMENT_CONFIG):
            with open(EXPERIMENT_CONFIG, 'r') as file:
                data = json.loads(file.read())
                self.experiment_folder = data['experiment_folder']
                while len(self.experiments) < len(data['experiments']):
                    self.add_experiment(
                        cannot_be_removed=len(self.experiments) == 0)

                for i in range(len(self.experiments)):
                    experiment_name = data['experiments'][i]['experiment_name']
                    if experiment_name in self.experiments[
                            i].available_experiments:
                        index = self.experiments[
                            i].available_experiments.index(experiment_name)
                        self.experiments[i].selected_experiment = index

    def change_experiment_folder(self):
        """
        Opens a dialog to select a new folder to look for experiment python scripts
        :return:
        """
        path = QFileDialog.getExistingDirectory(
            None, "Select folder containing experiment scripts")
        if path != '':
            self.experiment_folder = path

    def _data_contexts_changed_(self, vm):
        """
        Callback for handling changes in the available other data contexts.
        This method updates the experiments that they can access these contexts
        :param vm: data context that caused the signal
        """
        for experiment in self.experiments:
            experiment.other_data_contexts = self.other_data_contexts

    def _experiment_added_(self, experiment: BaseContextAwareViewModel):
        """
        Callback for handling an experiment being added
        :param experiment: experiment which was added
        """
        experiment.other_data_contexts = self.other_data_contexts  # make other data contexts available to newly added experiment
class BaseContextAwareViewModel(BaseViewModel):
    """
    Context aware view models have the ability that they can access other view models which are present in the application.
    This enables the context aware view model to control other view models.

    Important: This only works if the control is embedded in the lab master main window which handles the dependency injection!
    """

    other_data_context_was_added = Signal(BaseViewModel)
    other_data_context_was_removed = Signal(BaseViewModel)

    @property
    def other_data_contexts(self):
        """
        Gets all the available data contexts
        """
        return self._other_data_contexts

    @other_data_contexts.setter
    def other_data_contexts(self, value: ObservableList):
        """
        Sets the data contexts of other view models. Makes view models available
        """
        if type(self._other_data_contexts) == ObservableList:   # check if old data context list is observable
            # de-register change events
            self._other_data_contexts.item_added.disconnect(self._other_data_context_added_)
            self._other_data_contexts.item_removed.disconnect(self._other_data_context_removed_)

        if type(value) == ObservableList:   # check if new data context list is observable
            # register change events
            self._other_data_contexts = value
            self._other_data_contexts.item_added.connect(self._other_data_context_added_)
            self._other_data_contexts.item_removed.connect(self._other_data_context_removed_)

            # add existing data contexts
            for data_context in self._other_data_contexts:
                self._other_data_context_added_(data_context)

    def __init__(self):
        super().__init__()
        self.data_context_container = DataContexts()
        self._other_data_contexts = None
        self.other_data_contexts = ObservableList()

    def _count_instances_(self, data_context):
        """
        Counts how many view models of this type are present
        :param data_context: view model
        :return: view model count
        """
        count = 0
        for dc in self._other_data_contexts:
            if is_non_strict_type(type(dc), type(data_context)):
                count += 1
        return count

    def _other_data_context_added_(self, data_context):
        """
        Callback for handling newly added view model
        :param data_context: newly added view model
        """
        count = self._count_instances_(data_context)
        data_context_name = str(data_context).replace(' ', '')

        if hasattr(data_context, 'name'):
            data_context_name = getattr(data_context, 'name').replace(' ', '')

        if count > 1:
            data_context_name += str(count)
        self.data_context_container.__dict__[data_context_name] = data_context
        self.other_data_context_was_added.emit(data_context)

    def _other_data_context_removed_(self, data_context):
        """
        Callback for handling the removal of a view model
        :param data_context: view model that has been removed
        """
        remove_key = None
        for key in self.data_context_container.__dict__:
            if self.data_context_container.__dict__[key] == data_context:
                remove_key = key
                break
        if remove_key is not None:
            del self.data_context_container.__dict__[remove_key]
            self.other_data_context_was_removed.emit(data_context)
Esempio n. 7
0
 def __init__(self):
     self.property_changed = Signal(str)