@@ -134,20 +134,28 @@ def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None, defaultSa
134134 # Create Flag checkboxes list
135135 self .flagGroupBox = QGroupBox (self )
136136 self .flagGroupBox .setTitle ('Flags' )
137- flagslayout = QVBoxLayout (self )
138- self .flagGroupBox .setLayout (flagslayout )
139- self .flagButtons = []
140137
141- self .diffcButton = QCheckBox (getStr ('useDifficult' ))
142- self .diffcButton .setChecked (False )
143- # calling stateChanged is inappropriate!
144- self .diffcButton .clicked .connect (self .btnstate )
145- self .flagButtons .append (self .diffcButton )
138+ vbox = QVBoxLayout (self )
139+ self .flagslayout = QGridLayout (self )
140+ vbox .addLayout (self .flagslayout )
141+
142+ addflagLayout = QHBoxLayout (self )
143+ self .flaglineedit = QLineEdit ()
144+ self .flaglineedit .setPlaceholderText ('Flag name' )
145+ self .flaglineedit .returnPressed .connect (self .addflag_button_pushed )
146+ addflagLayout .addWidget (self .flaglineedit , 9 )
147+ self .addflag_button = QPushButton ('↑' )
148+ self .addflag_button .clicked .connect (self .addflag_button_pushed )
149+ addflagLayout .addWidget (self .addflag_button , 1 )
150+ vbox .addLayout (addflagLayout )
146151
147- self .truncButton = QCheckBox (getStr ('useTruncated' ))
148- self .truncButton .setChecked (False )
149- self .truncButton .clicked .connect (self .btnstate )
150- self .flagButtons .append (self .truncButton )
152+ self .flagGroupBox .setLayout (vbox )
153+ # list of tuple(checkbox, x button)
154+ self .flagWidgets = []
155+
156+ # add difficult and truncated flag by default
157+ self .addFlags (getStr ('useDifficult' ))
158+ self .addFlags (getStr ('useTruncated' ))
151159
152160 # *
153161 # * dhzs 2017-12-2 add copy button
@@ -157,13 +165,9 @@ def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None, defaultSa
157165 self .copy_prev_button .clicked .connect (self .copyPreviousBoundingBoxes )
158166 listLayout .addWidget (self .copy_prev_button )
159167
160- # add flag buttons to flagsGroupBox
161- for flagbtn in self .flagButtons :
162- flagslayout .addWidget (flagbtn )
163-
164168 # Add some of widgets to listLayout
165- listLayout .addWidget (self .editButton )
166169 listLayout .addWidget (self .flagGroupBox )
170+ listLayout .addWidget (self .editButton )
167171 listLayout .addWidget (useDefaultLabelContainer )
168172
169173 # Create and add combobox for showing unique labels in group
@@ -756,8 +760,64 @@ def flags(self):
756760 """
757761 return {flagbtn .text (): flagbtn .isChecked () for flagbtn in self .flagButtons }
758762
759- def setFlagsChecked (self , flags ):
760- pass
763+ def addflag_button_pushed (self ):
764+ # check whether the name is valid or not
765+ flagname = self .flaglineedit .text ()
766+ if flagname == '' :
767+ self .errorMessage ('Invalid flag name' , 'Input any texts!' )
768+ return
769+
770+ if flagname in [c .text () for c in self .flagButtons ]:
771+ self .errorMessage ('Invalid flag name' , 'Already exist!' )
772+ return
773+
774+ self .addFlags (flagname )
775+
776+ def addFlags (self , name ):
777+ column = len (self .flagWidgets )
778+
779+ newbtn = QCheckBox (name )
780+ newbtn .setChecked (False )
781+ # calling stateChanged is inappropriate!
782+ newbtn .clicked .connect (self .btnstate )
783+ self .flagslayout .addWidget (newbtn , * (column , 0 ))
784+ self .flagslayout .setColumnStretch (0 , 9 )
785+
786+ removebtn = QPushButton ('X' )
787+ widgets = (newbtn , removebtn )
788+ index = len (self .flagWidgets )
789+ removebtn .clicked .connect (lambda : self .removeFlags (index ))
790+ self .flagslayout .addWidget (removebtn , * (column , 1 ))
791+ self .flagslayout .setColumnStretch (1 , 1 )
792+ self .flagWidgets .append (widgets )
793+
794+
795+ def removeFlags (self , index ):
796+ # remove checkbox
797+ btn = self .flagWidgets [index ][0 ]
798+ self .flagslayout .removeWidget (btn )
799+
800+ # remove x button
801+ removebtn = self .flagWidgets [index ][1 ]
802+ self .flagslayout .removeWidget (removebtn )
803+
804+ btn .deleteLater ()
805+ removebtn .deleteLater ()
806+ del self .flagWidgets [index ]
807+
808+ # update argument of removeFlags
809+ for i , removeBtn in enumerate (self .flagRemoveButtons ):
810+ removebtn .clicked .connect (lambda : self .removeFlags (i ))
811+
812+ @property
813+ def flagButtons (self ):
814+ for widgets in self .flagWidgets :
815+ yield widgets [0 ]
816+
817+ @property
818+ def flagRemoveButtons (self ):
819+ for widgets in self .flagWidgets :
820+ yield widgets [1 ]
761821
762822 # Add chris
763823 def btnstate (self , item = None ):
@@ -826,6 +886,7 @@ def remLabel(self, shape):
826886
827887 def loadLabels (self , shapes ):
828888 s = []
889+ flaglist = [btn .text () for btn in self .flagButtons ]
829890 for label , points , line_color , fill_color , flags in shapes :
830891 shape = Shape (label = label )
831892 for x , y in points :
@@ -850,6 +911,11 @@ def loadLabels(self, shapes):
850911 else :
851912 shape .fill_color = generateColorByText (label )
852913
914+ # add flag if it doesn't exist
915+ for flagname in shape .flags .keys ():
916+ if flagname not in flaglist :
917+ self .addFlags (flagname )
918+
853919 self .addLabel (shape )
854920 self .updateComboBox ()
855921 self .canvas .loadShapes (s )
0 commit comments