<s> from __future__ import absolute_import , division , print_function <EOL> from glue . external . qt . QtCore import Qt <EOL> from glue . external . qt import QtGui , QtCore , is_pyqt5 <EOL> from glue . core . hub import HubListener <EOL> from glue . core import message as m <EOL> from glue . core . decorators import memoize <EOL> from glue import core <EOL> from glue . core . qt . mime import LAYERS_MIME_TYPE <EOL> from glue . icons . qt import layer_icon <EOL> from glue . core . qt . style_dialog import StyleDialog <EOL> from glue . utils import nonpartial <EOL> from glue . utils . qt import PyMimeData <EOL> from glue . utils . qt . helpers import CUSTOM_QWIDGETS <EOL> DATA_IDX = <NUM_LIT:0> <EOL> SUBSET_IDX = <NUM_LIT:1> <EOL> def full_edit_factory ( item , pos ) : <EOL> StyleDialog . dropdown_editor ( item , pos ) <EOL> def restricted_edit_factory ( item , pos ) : <EOL> StyleDialog . dropdown_editor ( item , pos , edit_label = False ) <EOL> class Item ( object ) : <EOL> edit_factory = None <EOL> glue_data = None <EOL> flags = Qt . ItemIsEnabled <EOL> tooltip = None <EOL> def font ( self ) : <EOL> return QtGui . QFont ( ) <EOL> def icon ( self ) : <EOL> return None <EOL> @ property <EOL> def label ( self ) : <EOL> return self . _label <EOL> class DataCollectionItem ( Item ) : <EOL> def __init__ ( self , dc ) : <EOL> self . dc = dc <EOL> self . row = <NUM_LIT:0> <EOL> self . column = <NUM_LIT:0> <EOL> self . parent = None <EOL> self . _label = '<STR_LIT>' <EOL> self . children_count = <NUM_LIT:2> <EOL> @ memoize <EOL> def child ( self , row ) : <EOL> if row == DATA_IDX : <EOL> return DataListItem ( self . dc , self ) <EOL> if row == SUBSET_IDX : <EOL> return SubsetListItem ( self . dc , self ) <EOL> return None <EOL> class DataListItem ( Item ) : <EOL> def __init__ ( self , dc , parent ) : <EOL> self . dc = dc <EOL> self . parent = parent <EOL> self . row = DATA_IDX <EOL> self . column = <NUM_LIT:0> <EOL> self . _label = '<STR_LIT>' <EOL> @ memoize <EOL> def child ( self , row ) : <EOL> if row < len ( self . dc ) : <EOL> return DataItem ( self . dc , row , self ) <EOL> @ property <EOL> def children_count ( self ) : <EOL> return len ( self . dc ) <EOL> def font ( self ) : <EOL> result = QtGui . QFont ( ) <EOL> result . setBold ( True ) <EOL> return result <EOL> class DataItem ( Item ) : <EOL> edit_factory = full_edit_factory <EOL> flags = ( Qt . ItemIsSelectable | Qt . ItemIsEnabled | <EOL> Qt . ItemIsDragEnabled ) <EOL> def __init__ ( self , dc , row , parent ) : <EOL> self . dc = dc <EOL> self . row = row <EOL> self . parent = parent <EOL> self . column = <NUM_LIT:0> <EOL> self . children_count = <NUM_LIT:0> <EOL> @ property <EOL> def data ( self ) : <EOL> return self . dc [ self . row ] <EOL> @ property <EOL> def glue_data ( self ) : <EOL> return self . data <EOL> @ property <EOL> def label ( self ) : <EOL> return self . data . label <EOL> @ label . setter <EOL> def label ( self , value ) : <EOL> self . data . label = value <EOL> @ property <EOL> def tooltip ( self ) : <EOL> return self . label <EOL> @ property <EOL> def style ( self ) : <EOL> return self . data . style <EOL> def icon ( self ) : <EOL> return layer_icon ( self . data ) <EOL> class SubsetListItem ( Item ) : <EOL> def __init__ ( self , dc , parent ) : <EOL> self . dc = dc <EOL> self . parent = parent <EOL> self . row = SUBSET_IDX <EOL> self . _label = '<STR_LIT>' <EOL> self . column = <NUM_LIT:0> <EOL> @ memoize <EOL> def child ( self , row ) : <EOL> if row < len ( self . dc . subset_groups ) : <EOL> return SubsetGroupItem ( self . dc , row , self ) <EOL> @ property <EOL> def children_count ( self ) : <EOL> return len ( self . dc . subset_groups ) <EOL> def font ( self ) : <EOL> result = QtGui . QFont ( ) <EOL> result . setBold ( True ) <EOL> return result <EOL> class SubsetGroupItem ( Item ) : <EOL> edit_factory = full_edit_factory <EOL> flags = Qt . ItemIsSelectable | Qt . ItemIsEnabled | Qt . ItemIsEditable <EOL> def __init__ ( self , dc , row , parent ) : <EOL> self . parent = parent <EOL> self . dc = dc <EOL> self . row = row <EOL> self . column = <NUM_LIT:0> <EOL> @ property <EOL> def subset_group ( self ) : <EOL> return self . dc . subset_groups [ self . row ] <EOL> @ property <EOL> def glue_data ( self ) : <EOL> return self . subset_group <EOL> @ property <EOL> def label ( self ) : <EOL> return self . subset_group . label <EOL> @ label . setter <EOL> def label ( self , value ) : <EOL> self . subset_group . label = value <EOL> @ property <EOL> def tooltip ( self ) : <EOL> if type ( self . subset_group . subset_state ) == core . subset . SubsetState : <EOL> return "<STR_LIT>" <EOL> atts = self . subset_group . subset_state . attributes <EOL> atts = [ a for a in atts if isinstance ( a , core . ComponentID ) ] <EOL> if len ( atts ) > <NUM_LIT:0> : <EOL> lbl = '<STR_LIT:U+002CU+0020>' . join ( a . label for a in atts ) <EOL> return "<STR_LIT>" % lbl <EOL> @ property <EOL> def style ( self ) : <EOL> return self . subset_group . style <EOL> @ property <EOL> def children_count ( self ) : <EOL> return len ( self . subset_group . subsets ) <EOL> @ memoize <EOL> def child ( self , row ) : <EOL> return SubsetItem ( self . dc , self . subset_group , row , self ) <EOL> def icon ( self ) : <EOL> return layer_icon ( self . subset_group ) <EOL> class SubsetItem ( Item ) : <EOL> edit_factory = restricted_edit_factory <EOL> flags = Qt . ItemIsSelectable | Qt . ItemIsEnabled | Qt . ItemIsDragEnabled <EOL> def __init__ ( self , dc , subset_group , subset_idx , parent ) : <EOL> self . parent = parent <EOL> self . subset_group = subset_group <EOL> self . row = subset_idx <EOL> self . parent = parent <EOL> self . children_count = <NUM_LIT:0> <EOL> self . column = <NUM_LIT:0> <EOL> @ property <EOL> def subset ( self ) : <EOL> return self . subset_group . subsets [ self . row ] <EOL> @ property <EOL> def label ( self ) : <EOL> return self . subset . verbose_label <EOL> def icon ( self ) : <EOL> return layer_icon ( self . subset ) <EOL> @ property <EOL> def style ( self ) : <EOL> return self . subset . style <EOL> @ property <EOL> def glue_data ( self ) : <EOL> return self . subset <EOL> class DataCollectionModel ( QtCore . QAbstractItemModel , HubListener ) : <EOL> new_item = QtCore . Signal ( QtCore . QModelIndex ) <EOL> def __init__ ( self , data_collection , parent = None ) : <EOL> QtCore . QAbstractItemModel . __init__ ( self , parent ) <EOL> HubListener . __init__ ( self ) <EOL> self . data_collection = data_collection <EOL> self . root = DataCollectionItem ( data_collection ) <EOL> self . _items = { } <EOL> self . register_to_hub ( self . data_collection . hub ) <EOL> if not is_pyqt5 ( ) : <EOL> self . setSupportedDragActions ( Qt . CopyAction ) <EOL> def supportedDragActions ( self ) : <EOL> return Qt . CopyAction <EOL> def index ( self , row , column , parent = QtCore . QModelIndex ( ) ) : <EOL> if column != <NUM_LIT:0> : <EOL> return QtCore . QModelIndex ( ) <EOL> if not parent . isValid ( ) : <EOL> parent_item = self . root <EOL> else : <EOL> parent_item = self . _get_item ( parent ) <EOL> if parent_item is None : <EOL> return QtCore . QModelIndex ( ) <EOL> child_item = parent_item . child ( row ) <EOL> if child_item : <EOL> return self . _make_index ( row , column , child_item ) <EOL> else : <EOL> return QtCore . QModelIndex ( ) <EOL> def _get_item ( self , index ) : <EOL> if not index . isValid ( ) : <EOL> return None <EOL> return self . _items . get ( id ( index . internalPointer ( ) ) , None ) <EOL> def _make_index ( self , row , column , item ) : <EOL> if item is not None : <EOL> result = self . createIndex ( row , column , item ) <EOL> self . _items [ id ( result . internalPointer ( ) ) ] = item <EOL> assert result . internalPointer ( ) is item <EOL> return result <EOL> return self . createIndex ( row , column ) <EOL> def to_indices ( self , items ) : <EOL> """<STR_LIT>""" <EOL> result = [ ] <EOL> for item in items : <EOL> if isinstance ( item , core . Data ) : <EOL> idx = self . data_index ( list ( self . data_collection ) . index ( item ) ) <EOL> elif isinstance ( item , core . SubsetGroup ) : <EOL> idx = self . subsets_index ( <EOL> self . data_collection . subset_groups . index ( item ) ) <EOL> elif isinstance ( item , core . subset_group . GroupedSubset ) : <EOL> grp = item . group <EOL> idx = self . subsets_index ( <EOL> self . data_collection . subset_groups . index ( grp ) ) <EOL> row = list ( self . data_collection ) . index ( item . data ) <EOL> idx = self . index ( row , idx ) <EOL> else : <EOL> raise NotImplementedError ( type ( item ) ) <EOL> result . append ( idx ) <EOL> return result <EOL> def flags ( self , index = QtCore . QModelIndex ( ) ) : <EOL> item = self . _get_item ( index ) <EOL> if item is None : <EOL> return Qt . NoItemFlags <EOL> else : <EOL> return item . flags <EOL> def data ( self , index , role ) : <EOL> if not index . isValid ( ) : <EOL> return <EOL> dispatch = { <EOL> Qt . DisplayRole : self . _display_data , <EOL> Qt . FontRole : self . _font_data , <EOL> Qt . DecorationRole : self . _icon_data , <EOL> Qt . UserRole : self . _user_data , <EOL> Qt . ToolTipRole : self . _tooltip_data } <EOL> if role in dispatch : <EOL> return dispatch [ role ] ( index ) <EOL> def setData ( self , index , value , role = Qt . EditRole ) : <EOL> if role != Qt . EditRole : <EOL> return False <EOL> try : <EOL> self . _get_item ( index ) . label = value <EOL> return True <EOL> except AttributeError : <EOL> return False <EOL> def _tooltip_data ( self , index ) : <EOL> tooltip = self . _get_item ( index ) . tooltip <EOL> return tooltip <EOL> def _user_data ( self , index ) : <EOL> return self . _get_item ( index ) <EOL> def _display_data ( self , index ) : <EOL> return self . _get_item ( index ) . label <EOL> def _font_data ( self , index ) : <EOL> item = self . _get_item ( index ) <EOL> return item . font ( ) <EOL> def _icon_data ( self , index ) : <EOL> return self . _get_item ( index ) . icon ( ) <EOL> def headerData ( self , section , orientation , role = Qt . DisplayRole ) : <EOL> return '<STR_LIT>' <EOL> def data_index ( self , data_number = None ) : <EOL> """<STR_LIT>""" <EOL> base = self . index ( DATA_IDX , <NUM_LIT:0> ) <EOL> if data_number is None : <EOL> return base <EOL> return self . index ( data_number , <NUM_LIT:0> , base ) <EOL> def subsets_index ( self , subset_number = None ) : <EOL> """<STR_LIT>""" <EOL> base = self . index ( SUBSET_IDX , <NUM_LIT:0> ) <EOL> assert isinstance ( self . _get_item ( base ) , SubsetListItem ) <EOL> if subset_number is None : <EOL> return base <EOL> return self . index ( subset_number , <NUM_LIT:0> , base ) <EOL> def rowCount ( self , index = QtCore . QModelIndex ( ) ) : <EOL> item = self . _get_item ( index ) <EOL> if item is None : <EOL> return self . root . children_count <EOL> return item . children_count <EOL> def parent ( self , index = None ) : <EOL> if index is None : <EOL> return QtCore . QObject . parent ( self ) <EOL> item = self . _get_item ( index ) <EOL> if item is None : <EOL> return QtCore . QModelIndex ( ) <EOL> return self . _make_index ( item . row , item . column , item . parent ) <EOL> def columnCount ( self , index ) : <EOL> return <NUM_LIT:1> <EOL> def register_to_hub ( self , hub ) : <EOL> for msg in [ m . DataCollectionDeleteMessage , <EOL> m . SubsetDeleteMessage ] : <EOL> hub . subscribe ( self , msg , lambda x : self . invalidate ( ) ) <EOL> hub . subscribe ( self , m . DataCollectionAddMessage , self . _on_add_data ) <EOL> hub . subscribe ( self , m . SubsetCreateMessage , self . _on_add_subset ) <EOL> def _on_add_data ( self , message ) : <EOL> self . invalidate ( ) <EOL> idx = self . data_index ( len ( self . data_collection ) - <NUM_LIT:1> ) <EOL> self . new_item . emit ( idx ) <EOL> def _on_add_subset ( self , message ) : <EOL> self . invalidate ( ) <EOL> idx = self . subsets_index ( len ( self . data_collection . subset_groups ) - <NUM_LIT:1> ) <EOL> self . new_item . emit ( idx ) <EOL> def invalidate ( self ) : <EOL> self . root = DataCollectionItem ( self . data_collection ) <EOL> self . _items . clear ( ) <EOL> if not is_pyqt5 ( ) : <EOL> self . reset ( ) <EOL> self . layoutChanged . emit ( ) <EOL> def glue_data ( self , indices ) : <EOL> """<STR_LIT>""" <EOL> items = [ self . _get_item ( idx ) for idx in indices ] <EOL> items = [ item . glue_data for item in items ] <EOL> return items <EOL> def mimeData ( self , indices ) : <EOL> data = self . glue_data ( indices ) <EOL> result = PyMimeData ( data , ** { LAYERS_MIME_TYPE : data } ) <EOL> self . _mime = result <EOL> return result <EOL> def mimeTypes ( self ) : <EOL> return [ LAYERS_MIME_TYPE ] <EOL> class DataCollectionView ( QtGui . QTreeView ) : <EOL> selection_changed = QtCore . Signal ( ) <EOL> def __init__ ( self , parent = None ) : <EOL> super ( DataCollectionView , self ) . __init__ ( parent ) <EOL> self . doubleClicked . connect ( self . _edit ) <EOL> self . pressed . connect ( nonpartial ( self . _update_viewport ) ) <EOL> self . setItemDelegate ( LabeledDelegate ( ) ) <EOL> self . setEditTriggers ( self . NoEditTriggers ) <EOL> self . _timer = QtCore . QTimer ( self ) <EOL> self . _timer . timeout . connect ( nonpartial ( self . _update_viewport ) ) <EOL> self . _timer . start ( <NUM_LIT:1000> ) <EOL> def _update_viewport ( self ) : <EOL> self . viewport ( ) . update ( ) <EOL> def selected_layers ( self ) : <EOL> idxs = self . selectedIndexes ( ) <EOL> return self . _model . glue_data ( idxs ) <EOL> def set_selected_layers ( self , layers ) : <EOL> sm = self . selectionModel ( ) <EOL> idxs = self . _model . to_indices ( layers ) <EOL> self . select_indices ( * idxs ) <EOL> def select_indices ( self , * indices ) : <EOL> sm = self . selectionModel ( ) <EOL> sm . clearSelection ( ) <EOL> for idx in indices : <EOL> sm . select ( idx , sm . Select ) <EOL> def set_data_collection ( self , data_collection ) : <EOL> self . _model = DataCollectionModel ( data_collection ) <EOL> self . setModel ( self . _model ) <EOL> sm = QtGui . QItemSelectionModel ( self . _model ) <EOL> sm . selectionChanged . connect ( lambda * args : <EOL> self . selection_changed . emit ( ) ) <EOL> self . setSelectionModel ( sm ) <EOL> self . setRootIsDecorated ( False ) <EOL> self . setExpandsOnDoubleClick ( False ) <EOL> self . expandToDepth ( <NUM_LIT:0> ) <EOL> self . _model . layoutChanged . connect ( lambda : self . expandToDepth ( <NUM_LIT:0> ) ) <EOL> self . _model . layoutChanged . connect ( self . selection_changed . emit ) <EOL> self . _model . new_item . connect ( self . select_indices ) <EOL> self . _model . new_item . connect ( self . edit_label ) <EOL> self . setSelectionBehavior ( QtGui . QAbstractItemView . SelectRows ) <EOL> self . setSelectionMode ( QtGui . QAbstractItemView . ExtendedSelection ) <EOL> self . setDragEnabled ( True ) <EOL> self . setDropIndicatorShown ( True ) <EOL> self . setDragDropMode ( QtGui . QAbstractItemView . DragOnly ) <EOL> def edit_label ( self , index ) : <EOL> if not ( self . _model . flags ( index ) & Qt . ItemIsEditable ) : <EOL> return <EOL> self . edit ( index ) <EOL> def _edit ( self , index ) : <EOL> item = self . _model . data ( index , role = Qt . UserRole ) <EOL> if item is None or item . edit_factory is None : <EOL> return <EOL> rect = self . visualRect ( index ) <EOL> pos = self . mapToGlobal ( rect . bottomLeft ( ) ) <EOL> pos . setY ( pos . y ( ) + <NUM_LIT:1> ) <EOL> item . edit_factory ( pos ) <EOL> CUSTOM_QWIDGETS . append ( DataCollectionView ) <EOL> class LabeledDelegate ( QtGui . QStyledItemDelegate ) : <EOL> """<STR_LIT>""" <EOL> def setEditorData ( self , editor , index ) : <EOL> super ( LabeledDelegate , self ) . setEditorData ( editor , index ) <EOL> label = index . model ( ) . data ( index , role = Qt . DisplayRole ) <EOL> editor . selectAll ( ) <EOL> editor . setText ( label ) <EOL> if __name__ == "<STR_LIT:__main__>" : <EOL> from glue . external . qt import get_qapp <EOL> from glue . external . qt import QtGui <EOL> from glue . core import Data , DataCollection <EOL> app = get_qapp ( ) <EOL> dc = DataCollection ( ) <EOL> dc . append ( Data ( label = '<STR_LIT:w>' ) ) <EOL> view = DataCollectionView ( ) <EOL> view . set_data_collection ( dc ) <EOL> view . show ( ) <EOL> view . raise_ ( ) <EOL> dc . extend ( [ Data ( label = '<STR_LIT:x>' , x = [ <NUM_LIT:1> , <NUM_LIT:2> , <NUM_LIT:3> ] ) , <EOL> Data ( label = '<STR_LIT:y>' , y = [ <NUM_LIT:1> , <NUM_LIT:2> , <NUM_LIT:3> ] ) , <EOL> Data ( label = '<STR_LIT:z>' , z = [ <NUM_LIT:1> , <NUM_LIT:2> , <NUM_LIT:3> ] ) ] ) <EOL> app . exec_ ( ) </s>
