@@ -325,6 +325,45 @@ def view_eurostat_indicator(self, index):
325
325
QMessageBox .critical (self , "Error" , "Failed to load {}" .format (code ))
326
326
327
327
328
+ def handle_search (self , text ):
329
+
330
+ def search_term_filter_df (df , text ):
331
+ terms = text .split ()
332
+ mask = None
333
+
334
+ # First time loop generates a sequence of booleans (lenght = nrows of df)
335
+ # Second time it takes 'boolean intersection' with previous search result(s)
336
+ for term in terms :
337
+ term_mask = (df ['Code' ].str .contains (term , case = False , na = False )) | (df ['Title' ].str .contains (term , case = False , na = False ))
338
+ if mask is None :
339
+ mask = term_mask
340
+ else :
341
+ mask &= term_mask
342
+ return df [mask ]
343
+
344
+ if text :
345
+ # when text is entered, then hide the treeview and show (new) search results
346
+ self .tree .hide ()
347
+ self .search_results_list .clear ()
348
+
349
+ # filter dataframe based on search term(s)
350
+ filtered_df = search_term_filter_df (self .df , text )
351
+
352
+ # drop duplicates in search result (i.e. same code, originating from different locations tree)
353
+ filtered_df = filtered_df .drop_duplicates (subset = 'Code' )
354
+
355
+ # reduce dataframe to list of strings (only retain 'title' and 'code')
356
+ results = [f"{ row ['Title' ]} ({ row ['Code' ]} )" for _ , row in filtered_df .iterrows ()]
357
+
358
+ self .search_results_list .addItems (results )
359
+ self .search_results_list .show ()
360
+
361
+ else : # if search field is empty
362
+ self .tree .show ()
363
+ self .search_results_list .hide ()
364
+
365
+
366
+
328
367
def showAdvancedPopup (self ):
329
368
popup = AdvancedPopup (self )
330
369
# Next Line takes into account 'finished signal' of the AdvancedPopup instance and links it to closeDialog.
0 commit comments