<commit_before>#!/usr/bin/env python
# encoding: utf-8

from operator import itemgetter

from cadnano import app
from cadnano import preferences as prefs
from cadnano import util
from cadnano.cnproxy import ProxySignal
from cadnano.cnobject import CNObject
from cadnano.cnproxy import UndoStack, UndoCommand

from cadnano.strand import Strand

from cadnano.part import Part
from cadnano.part.nucleicacidpart import NucleicAcidPart
from cadnano.objectinstance import ObjectInstance
from cadnano.addinstancecmd import AddInstanceCommand


class Document(CNObject):
    """
    The Document class is the root of the model. It has two main purposes:
    1. Serve as the parent all Part objects within the model.
    2. Track all sub-model actions on its undoStack.
    """

    def __init__(self, parent=None):
        super(Document, self).__init__(parent)

        self._undostack = UndoStack()
        self._children = []
        self._controller = None
        self._selected_instance = None
        # the dictionary maintains what is selected
        self._selection_dict = {}
        # the added list is what was recently selected or deselected
        self._selected_changed_dict = {}
        self.view_names = []
        app().documentWasCreatedSignal.emit(self)
    # end def

    ### SIGNALS ###
    documentPartAddedSignal =  ProxySignal(object,
                                        CNObject,
                                        name='documentPartAddedSignal') # doc, part
    documentAssemblyAddedSignal =  ProxySignal(object,
                                        CNObject,
                                        name='documentAssemblyAddedSignal') # doc, assembly

    # dict of tuples of objects using the reference as the key,
    # and the value is a tuple with meta data
    # in the case of strands the metadata would be which endpoints of selected
    # e.g. { objectRef: (value0, value1),  ...}
    documentSelectedChangedSignal = ProxySignal(dict,
                                         name='documentSelectedChangedSignal') # tuples of items + data
    documentSelectionFilterChangedSignal = ProxySignal(list,
                                  name='documentSelectionFilterChangedSignal')
    documentPreXoverFilterChangedSignal = ProxySignal(str,
                                   name='documentPreXoverFilterChangedSignal')

    documentViewResetSignal = ProxySignal(CNObject,
                                               name='documentViewResetSignal')
    documentClearSelectionsSignal = ProxySignal(CNObject,
                                         name='documentClearSelectionsSignal')

    ### SLOTS ###

    ### ACCESSORS ###
    def undoStack(self):
        """
        This is the actual undoStack to use for all commands. Any children
        needing to perform commands should just ask their parent for the
        undoStack, and eventually the request will get here.
        """
        return self._undostack

    def children(self):
        """Returns a list of parts associated with the document."""
        return self._children

    def getPartsDict(self):
        out = {}
        for item in self._children:
            if isinstance(item, Part):
                out[item.getName()] = item
        return out

    def addChild(self, child):
        self._children.append(child)

    def removeAllChildren(self):
        """Used to reset the document. Not undoable."""
        self.documentClearSelectionsSignal.emit(self)
        for child in self._children:
            child.remove(use_undostack=False)
    # end def

    def removeChild(self, child):
        self.documentClearSelectionsSignal.emit(self)
        self._children.remove(child)
    # end def

    # def assemblies(self):
    #     """Returns a list of assemblies associated with the document."""
    #     return self._assemblies

    ### PUBLIC METHODS FOR QUERYING THE MODEL ###
    def selectedInstance(self):
        return self._selected_instance

    def addToSelection(self, obj, value):
        self._selection_dict[obj] = value
        self._selected_changed_dict[obj] = value
    # end def

    def removeFromSelection(self, obj):
        if obj in self._selection_dict:
            del self._selection_dict[obj]
            self._selected_changed_dict[obj] = (False, False)
            return True
        else:
            return False
    # end def

    def clearSelections(self):
        """
        Only clear the dictionary
        """
        self._selection_dict = {}
    # end def

    def addStrandToSelection(self, strand, value):
        ss = strand.strandSet()
        if ss in self._selection_dict:
            self._selection_dict[ss][strand] = value
        else:
            self._selection_dict[ss] = {strand: value}
        self._selected_changed_dict[strand] = value
    # end def

    def removeStrandFromSelection(self, strand):
        ss = strand.strandSet()
        if ss in self._selection_dict:
            temp = self._selection_dict[ss]
            if strand in temp:
                del temp[strand]
                if len(temp) == 0:
                    del self._selection_dict[ss]
                self._selected_changed_dict[strand] = (False, False)
                return True
            else:
                return False
        else:
            return False
    # end def

    def selectionDict(self):
        return self._selection_dict
    # end def

    def selectedOligos(self):
        """
        as long as one endpoint of a strand is in the selection, then the oligo
        is considered selected
        """
        s_dict = self._selection_dict
        selected_oligos = set()
        for ss in s_dict.keys():
            for strand in ss:
                 selected_oligos.add(strand.oligo())
            # end for
        # end for
        return selected_oligos if len(selected_oligos) > 0 else None
    #end def

    def clearAllSelected(self):
        self._selection_dict = {}
        # the added list is what was recently selected or deselected
        self._selected_changed_dict = {}
        self.documentClearSelectionsSignal.emit(self)
    # end def

    def isModelSelected(self, obj):
        return obj in self._selection_dict
    # end def

    def isModelStrandSelected(self, strand):
        ss = strand.strandSet()
        if ss in self._selection_dict:
            if strand in self._selection_dict[ss]:
                return True
            else:
                return False
        else:
            return False
    # end def

    def getSelectedValue(self, obj):
        """
        obj is an objects to look up
        it is prevetted to be in the dictionary
        """
        return self._selection_dict[obj]

    def getSelectedStrandValue(self, strand):
        """
        strand is an objects to look up
        it is prevetted to be in the dictionary
        """
        return self._selection_dict[strand.strandSet()][strand]<commit_msg>ready to tackle building virtualhelix selection into the model and multi view selection<commit_after>#!/usr/bin/env python
# encoding: utf-8

from operator import itemgetter

from cadnano import app
from cadnano import preferences as prefs
from cadnano import util
from cadnano.cnproxy import ProxySignal
from cadnano.cnobject import CNObject
from cadnano.cnproxy import UndoStack, UndoCommand

from cadnano.strand import Strand

from cadnano.part import Part
from cadnano.part.nucleicacidpart import NucleicAcidPart
from cadnano.objectinstance import ObjectInstance
from cadnano.addinstancecmd import AddInstanceCommand


class Document(CNObject):
    """
    The Document class is the root of the model. It has two main purposes:
    1. Serve as the parent all Part objects within the model.
    2. Track all sub-model actions on its undoStack.
    """

    def __init__(self, parent=None):
        super(Document, self).__init__(parent)

        self._undostack = UndoStack()
        self._children = []
        self._controller = None
        self._selected_instance = None
        # the dictionary maintains what is selected
        self._selection_dict = {}
        # the added list is what was recently selected or deselected
        self._selected_changed_dict = {}
        self.view_names = []
        app().documentWasCreatedSignal.emit(self)
    # end def

    ### SIGNALS ###
    documentPartAddedSignal =  ProxySignal(object,
                                        CNObject,
                                        name='documentPartAddedSignal') # doc, part
    documentAssemblyAddedSignal =  ProxySignal(object,
                                        CNObject,
                                        name='documentAssemblyAddedSignal') # doc, assembly

    # dict of tuples of objects using the reference as the key,
    # and the value is a tuple with meta data
    # in the case of strands the metadata would be which endpoints of selected
    # e.g. { objectRef: (value0, value1),  ...}
    documentSelectedChangedSignal = ProxySignal(dict,
                                         name='documentSelectedChangedSignal') # tuples of items + data
    documentSelectionFilterChangedSignal = ProxySignal(list,
                                  name='documentSelectionFilterChangedSignal')
    documentPreXoverFilterChangedSignal = ProxySignal(str,
                                   name='documentPreXoverFilterChangedSignal')

    documentViewResetSignal = ProxySignal(CNObject,
                                               name='documentViewResetSignal')
    documentClearSelectionsSignal = ProxySignal(CNObject,
                                         name='documentClearSelectionsSignal')

    ### SLOTS ###

    ### ACCESSORS ###
    def undoStack(self):
        """
        This is the actual undoStack to use for all commands. Any children
        needing to perform commands should just ask their parent for the
        undoStack, and eventually the request will get here.
        """
        return self._undostack

    def children(self):
        """Returns a list of parts associated with the document."""
        return self._children

    def getPartsDict(self):
        out = {}
        for item in self._children:
            if isinstance(item, Part):
                out[item.getName()] = item
        return out

    def addChild(self, child):
        self._children.append(child)

    def removeAllChildren(self):
        """Used to reset the document. Not undoable."""
        self.documentClearSelectionsSignal.emit(self)
        for child in self._children:
            child.remove(use_undostack=False)
    # end def

    def removeChild(self, child):
        self.documentClearSelectionsSignal.emit(self)
        self._children.remove(child)
    # end def

    # def assemblies(self):
    #     """Returns a list of assemblies associated with the document."""
    #     return self._assemblies

    ### PUBLIC METHODS FOR QUERYING THE MODEL ###
    # def selectedInstance(self):
    #     return self._selected_instance

    # def addToSelection(self, obj, value):
    #     self._selection_dict[obj] = value
    #     self._selected_changed_dict[obj] = value
    # # end def

    # def removeFromSelection(self, obj):
    #     if obj in self._selection_dict:
    #         del self._selection_dict[obj]
    #         self._selected_changed_dict[obj] = (False, False)
    #         return True
    #     else:
    #         return False
    # # end def

    # def clearSelections(self):
    #     """
    #     Only clear the dictionary
    #     """
    #     self._selection_dict = {}
    # # end def

    def addStrandToSelection(self, strand, value):
        ss = strand.strandSet()
        if ss in self._selection_dict:
            self._selection_dict[ss][strand] = value
        else:
            self._selection_dict[ss] = {strand: value}
        self._selected_changed_dict[strand] = value
    # end def

    def removeStrandFromSelection(self, strand):
        ss = strand.strandSet()
        if ss in self._selection_dict:
            temp = self._selection_dict[ss]
            if strand in temp:
                del temp[strand]
                if len(temp) == 0:
                    del self._selection_dict[ss]
                self._selected_changed_dict[strand] = (False, False)
                return True
            else:
                return False
        else:
            return False
    # end def

    def selectionDict(self):
        return self._selection_dict
    # end def

    def selectedOligos(self):
        """
        as long as one endpoint of a strand is in the selection, then the oligo
        is considered selected
        """
        s_dict = self._selection_dict
        selected_oligos = set()
        for ss in s_dict.keys():
            for strand in ss:
                 selected_oligos.add(strand.oligo())
            # end for
        # end for
        return selected_oligos if len(selected_oligos) > 0 else None
    #end def

    def clearAllSelected(self):
        self._selection_dict = {}
        # the added list is what was recently selected or deselected
        self._selected_changed_dict = {}
        self.documentClearSelectionsSignal.emit(self)
    # end def

    # def isModelSelected(self, obj):
    #     return obj in self._selection_dict
    # # end def

    def isModelStrandSelected(self, strand):
        ss = strand.strandSet()
        if ss in self._selection_dict:
            if strand in self._selection_dict[ss]:
                return True
            else:
                return False
        else:
            return False
    # end def

    def getSelectedValue(self, obj):
        """
        obj is an objects to look up
        it is prevetted to be in the dictionary
        """
        return self._selection_dict[obj]

    def getSelectedStrandValue(self, strand):
        """
        strand is an objects to look up
        it is prevetted to be in the dictionary
        """
        return self._selection_dict[strand.strandSet()][strand]
{'fraction_non_alphanumeric': 0.07306814941545481, 'fraction_numerical': 0.000998003992015968, 'mean_word_length': 2.0365800865800865, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4358733', 'n_tokens_mistral': 3689, 'n_tokens_neox': 3484, 'n_words': 1095}