11import math
22import itertools
3+
4+ from PyQt4 .QtCore import Qt
35from collections import defaultdict
46
57from PyQt4 import QtGui
68import numpy
79
810import Orange
9- from Orange .widgets import widget
10- from Orange .widgets import gui
11+ from Orange .widgets import widget , gui , settings
1112from Orange .widgets .utils import itemmodels
1213from Orange .widgets .utils .sql import check_sql_input
1314
1415
15- INSTANCEID = "Same source "
16- INDEX = "Index "
16+ INSTANCEID = "Source position (index) "
17+ INDEX = "Position (index) "
1718
1819class OWMergeData (widget .OWWidget ):
1920 name = "Merge Data"
@@ -26,6 +27,9 @@ class OWMergeData(widget.OWWidget):
2627 outputs = [("Merged Data A+B" , Orange .data .Table , ),
2728 ("Merged Data B+A" , Orange .data .Table , )]
2829
30+ attr_a = settings .Setting ('' , schema_only = True )
31+ attr_b = settings .Setting ('' , schema_only = True )
32+
2933 want_main_area = False
3034
3135 def __init__ (self ):
@@ -45,30 +49,24 @@ def __init__(self):
4549 # attribute A selection
4650 boxAttrA = gui .vBox (self , self .tr ("Attribute A" ), addToLayout = False )
4751 grid .addWidget (boxAttrA , 0 , 0 )
48- self .attrViewA = QtGui .QListView (
49- selectionMode = QtGui .QListView .SingleSelection
50- )
5152
53+ self .attrViewA = gui .comboBox (boxAttrA , self , 'attr_a' ,
54+ orientation = Qt .Horizontal ,
55+ sendSelectedValue = True ,
56+ callback = self ._invalidate )
5257 self .attrModelA = itemmodels .VariableListModel ()
5358 self .attrViewA .setModel (self .attrModelA )
54- self .attrViewA .selectionModel ().selectionChanged .connect (
55- self ._selectedAttrAChanged )
56-
57- boxAttrA .layout ().addWidget (self .attrViewA )
5859
5960 # attribute B selection
6061 boxAttrB = gui .vBox (self , self .tr ("Attribute B" ), addToLayout = False )
6162 grid .addWidget (boxAttrB , 0 , 1 )
62- self .attrViewB = QtGui .QListView (
63- selectionMode = QtGui .QListView .SingleSelection
64- )
6563
64+ self .attrViewB = gui .comboBox (boxAttrB , self , 'attr_b' ,
65+ orientation = Qt .Horizontal ,
66+ sendSelectedValue = True ,
67+ callback = self ._invalidate )
6668 self .attrModelB = itemmodels .VariableListModel ()
6769 self .attrViewB .setModel (self .attrModelB )
68- self .attrViewB .selectionModel ().selectionChanged .connect (
69- self ._selectedAttrBChanged )
70-
71- boxAttrB .layout ().addWidget (self .attrViewB )
7270
7371 # info A
7472 boxDataA = gui .vBox (self , self .tr ("Data A Input" ), addToLayout = False )
@@ -80,36 +78,43 @@ def __init__(self):
8078 grid .addWidget (boxDataB , 1 , 1 )
8179 self .infoBoxDataB = gui .widgetLabel (boxDataB , self .dataInfoText (None ))
8280
83- gui .rubber (self .buttonsArea )
84- # resize
85- self .resize (400 , 500 )
81+ gui .rubber (self )
8682
87- def setAttrs (self ):
88- add = ()
89- if self .dataA is not None and self .dataB is not None \
90- and len (numpy .intersect1d (self .dataA .ids , self .dataB .ids )):
91- add = (INSTANCEID ,)
92- if self .dataA is not None :
93- self .attrModelA [:] = add + allvars (self .dataA )
94- else :
95- self .attrModelA [:] = []
96- if self .dataB is not None :
97- self .attrModelB [:] = add + allvars (self .dataB )
98- else :
99- self .attrModelB [:] = []
83+ def _setAttrs (self , model , data , othermodel , otherdata ):
84+ model [:] = allvars (data ) if data is not None else []
85+
86+ if data is not None and otherdata is not None and \
87+ len (numpy .intersect1d (data .ids , otherdata .ids )):
88+ for model_ in (model , othermodel ):
89+ if len (model_ ) and model_ [0 ] != INSTANCEID :
90+ model_ .insert (0 , INSTANCEID )
10091
10192 @check_sql_input
10293 def setDataA (self , data ):
103- #self.closeContext()
10494 self .dataA = data
105- self .setAttrs ()
95+ self ._setAttrs (self .attrModelA , data , self .attrModelB , self .dataB )
96+ curr_index = - 1
97+ if self .attr_a :
98+ curr_index = next ((i for i , val in enumerate (self .attrModelA )
99+ if str (val ) == self .attr_a ), - 1 )
100+ if curr_index != - 1 :
101+ self .attrViewA .setCurrentIndex (curr_index )
102+ else :
103+ self .attr_a = INDEX
106104 self .infoBoxDataA .setText (self .dataInfoText (data ))
107105
108106 @check_sql_input
109107 def setDataB (self , data ):
110- #self.closeContext()
111108 self .dataB = data
112- self .setAttrs ()
109+ self ._setAttrs (self .attrModelB , data , self .attrModelA , self .dataA )
110+ curr_index = - 1
111+ if self .attr_b :
112+ curr_index = next ((i for i , val in enumerate (self .attrModelB )
113+ if str (val ) == self .attr_b ), - 1 )
114+ if curr_index != - 1 :
115+ self .attrViewB .setCurrentIndex (curr_index )
116+ else :
117+ self .attr_b = INDEX
113118 self .infoBoxDataB .setText (self .dataInfoText (data ))
114119
115120 def handleNewSignals (self ):
@@ -126,50 +131,40 @@ def dataInfoText(self, data):
126131 attributes = self .tr ("%n variable(s)" , None , nvariables )
127132 return "\n " .join ([instances , attributes ])
128133
129- def selectedIndexA (self ):
130- return selected_row (self .attrViewA )
131-
132- def selectedIndexB (self ):
133- return selected_row (self .attrViewB )
134-
135134 def commit (self ):
136- indexA = self .selectedIndexA ()
137- indexB = self .selectedIndexB ()
138135 AB , BA = None , None
139- if indexA is not None and indexB is not None :
140- varA = self .attrModelA [indexA ]
141- varB = self .attrModelB [indexB ]
136+ if (self .attr_a and self .attr_b and
137+ self .dataA is not None and
138+ self .dataB is not None ):
139+ varA = (self .attr_a if self .attr_a in (INDEX , INSTANCEID ) else
140+ self .dataA .domain [self .attr_a ])
141+ varB = (self .attr_b if self .attr_b in (INDEX , INSTANCEID ) else
142+ self .dataB .domain [self .attr_b ])
142143 AB = merge (self .dataA , varA , self .dataB , varB )
143144 BA = merge (self .dataB , varB , self .dataA , varA )
144145 self .send ("Merged Data A+B" , AB )
145146 self .send ("Merged Data B+A" , BA )
146147
147- def _selectedAttrAChanged (self , * args ):
148- self ._invalidate ()
149-
150- def _selectedAttrBChanged (self , * args ):
151- self ._invalidate ()
152-
153148 def _invalidate (self ):
154149 self .commit ()
155150
156151 def send_report (self ):
157- attr_a = self .selectedIndexA ()
158- attr_b = self .selectedIndexB ()
152+ attr_a = None
153+ attr_b = None
154+ if self .dataA is not None :
155+ attr_a = self .attr_a
156+ if attr_a in self .dataA .domain :
157+ attr_a = self .dataA .domain [attr_a ]
158+ if self .dataB is not None :
159+ attr_b = self .attr_b
160+ if attr_b in self .dataB .domain :
161+ attr_b = self .dataB .domain [attr_b ]
159162 self .report_items ((
160- ("Attribute A" , attr_a and self . attrModelA [ attr_a ] ),
161- ("Attribute B" , attr_b and self . attrModelB [ attr_b ])
163+ ("Attribute A" , attr_a ),
164+ ("Attribute B" , attr_b ),
162165 ))
163166
164167
165- def selected_row (view ):
166- rows = view .selectionModel ().selectedRows ()
167- if rows :
168- return rows [0 ].row ()
169- else :
170- return None
171-
172-
173168def allvars (data ):
174169 return (INDEX ,) + data .domain .attributes + data .domain .class_vars + data .domain .metas
175170
0 commit comments