@@ -1120,6 +1120,12 @@ def setup_ui(self):
11201120 add_images_btn .clicked .connect (self .add_images )
11211121 toolbar_layout .addWidget (add_images_btn )
11221122
1123+ # Process All button
1124+ process_all_btn = QPushButton ("🔄 Reprocess All" )
1125+ process_all_btn .clicked .connect (self .process_all_images )
1126+ process_all_btn .setToolTip ("Reprocess all loaded images with current SDK versions" )
1127+ toolbar_layout .addWidget (process_all_btn )
1128+
11231129 clear_btn = QPushButton ("🗑️ Clear All" )
11241130 clear_btn .clicked .connect (self .clear_all )
11251131 toolbar_layout .addWidget (clear_btn )
@@ -1290,11 +1296,12 @@ def update_sdk_versions(self, sdk_versions: List[SDKVersion]):
12901296 # Update results table headers
12911297 self .results_table .update_sdk_headers (sdk_versions )
12921298
1293- # Process the currently selected image if we have one
1299+ # Process the currently selected image if we have one and images are loaded
12941300 current_item = self .file_list .currentItem ()
1295- if current_item and len (sdk_versions ) >= 2 :
1301+ if (current_item and len (sdk_versions ) >= 2 and
1302+ len (self .image_files ) > 0 and len (self .new_files ) > 0 ):
12961303 image_path = current_item .data (Qt .ItemDataRole .UserRole )
1297- if image_path :
1304+ if image_path and image_path in self . image_files :
12981305 QTimer .singleShot (500 , lambda : self .process_selected_image (image_path ))
12991306
13001307 def add_images (self ):
@@ -1307,15 +1314,70 @@ def add_images(self):
13071314 self .new_files = [str (f ) for f in files ]
13081315 self .add_image_files (files )
13091316
1317+ def process_all_images (self ):
1318+ """Process all loaded images"""
1319+ if not self .image_files :
1320+ QMessageBox .information (self , "No Images" , "Please add images first." )
1321+ return
1322+
1323+ if len (self .sdk_versions ) < 2 :
1324+ QMessageBox .information (self , "SDK Configuration Required" ,
1325+ "Please configure at least 2 SDK versions first." )
1326+ return
1327+
1328+ # Stop any existing processing
1329+ if self .processing_thread and self .processing_thread .isRunning ():
1330+ self .processing_thread .terminate ()
1331+ self .processing_thread .wait (1000 )
1332+
1333+ # Clear existing results for fresh processing
1334+ self .results .clear ()
1335+ self .results_table .setRowCount (0 )
1336+
1337+ # Show progress
1338+ self .progress_bar .setVisible (True )
1339+ self .progress_bar .setRange (0 , len (self .sdk_versions ) * len (self .image_files ))
1340+ self .progress_bar .setValue (0 )
1341+
1342+ self .status_bar .showMessage (f"Reprocessing all { len (self .image_files )} images..." )
1343+
1344+ # Process all images
1345+ self .processing_thread = ProcessingThread (self .image_files , self .sdk_versions , self .current_detection_mode )
1346+
1347+ # Connect signals
1348+ self .processing_thread .result_ready .connect (
1349+ self .on_batch_result_ready , Qt .ConnectionType .QueuedConnection
1350+ )
1351+ self .processing_thread .processing_complete .connect (
1352+ self .on_batch_processing_complete , Qt .ConnectionType .QueuedConnection
1353+ )
1354+
1355+ self .processing_thread .start ()
1356+
1357+ def on_batch_result_ready (self , image_path : str , sdk_name : str , result : ProcessingResult ):
1358+ """Handle batch processing result"""
1359+ # Same as single result but for batch processing
1360+ self .on_single_result_ready (image_path , sdk_name , result )
1361+
1362+ def on_batch_processing_complete (self ):
1363+ """Handle batch processing completion"""
1364+ self .progress_bar .setVisible (False )
1365+ self .status_bar .showMessage (f"✅ Reprocessing complete! Processed { len (self .image_files )} images" )
1366+
1367+ # Auto-select first image if none selected
1368+ if self .file_list .count () > 0 and not self .file_list .currentItem ():
1369+ self .file_list .setCurrentRow (0 )
1370+
13101371 def add_image_files (self , files : List [str ]):
1311- """Add image files to the list"""
1372+ """Add image files to the list and process them immediately """
13121373 new_files_added = 0
13131374 last_added_item = None
1375+ newly_added_files = []
13141376
13151377 for file_path in files :
1316-
13171378 if file_path not in self .image_files :
13181379 self .image_files .append (str (file_path ))
1380+ newly_added_files .append (str (file_path ))
13191381
13201382 # Create list item with image path stored as data
13211383 item = QListWidgetItem (os .path .basename (file_path ))
@@ -1327,17 +1389,60 @@ def add_image_files(self, files: List[str]):
13271389
13281390 self .status_bar .showMessage (f"Added { new_files_added } images. Total: { len (self .image_files )} " )
13291391
1330- # Auto-select the last added image and process it
1331- if last_added_item and len (self .sdk_versions ) >= 2 :
1332- self .file_list .setCurrentItem (last_added_item )
1333- # Processing will be triggered by the selection change event
1392+ # Process all newly added files immediately if we have SDK versions configured
1393+ if newly_added_files and len (self .sdk_versions ) >= 2 :
1394+ self .process_new_images (newly_added_files )
13341395 elif last_added_item :
13351396 # Select the item but show SDK configuration message
13361397 self .file_list .setCurrentItem (last_added_item )
13371398 QTimer .singleShot (100 , lambda : QMessageBox .information (
13381399 self , "SDK Configuration Required" ,
1339- "Image selected ! Please configure SDK versions first to enable processing."
1400+ "Images added ! Please configure SDK versions first to enable processing."
13401401 ))
1402+ elif last_added_item :
1403+ # Just select the last item if no processing needed
1404+ self .file_list .setCurrentItem (last_added_item )
1405+
1406+ def process_new_images (self , image_files : List [str ]):
1407+ """Process newly added images immediately"""
1408+ if not image_files or len (self .sdk_versions ) < 2 :
1409+ return
1410+
1411+ # Stop any existing processing
1412+ if self .processing_thread and self .processing_thread .isRunning ():
1413+ self .processing_thread .terminate ()
1414+ self .processing_thread .wait (1000 )
1415+
1416+ # Show progress
1417+ self .progress_bar .setVisible (True )
1418+ self .progress_bar .setRange (0 , len (self .sdk_versions ) * len (image_files ))
1419+ self .progress_bar .setValue (0 )
1420+
1421+ self .status_bar .showMessage (f"Processing { len (image_files )} new images..." )
1422+
1423+ # Process the new images
1424+ self .processing_thread = ProcessingThread (image_files , self .sdk_versions , self .current_detection_mode )
1425+
1426+ # Connect signals
1427+ self .processing_thread .result_ready .connect (
1428+ self .on_single_result_ready , Qt .ConnectionType .QueuedConnection
1429+ )
1430+ self .processing_thread .processing_complete .connect (
1431+ self .on_new_images_processing_complete , Qt .ConnectionType .QueuedConnection
1432+ )
1433+
1434+ self .processing_thread .start ()
1435+
1436+ def on_new_images_processing_complete (self ):
1437+ """Handle completion of new images processing"""
1438+ self .progress_bar .setVisible (False )
1439+ self .status_bar .showMessage (f"✅ Processing complete! Total images: { len (self .image_files )} " )
1440+
1441+ # Auto-select the last added image to show results
1442+ if self .file_list .count () > 0 :
1443+ last_item = self .file_list .item (self .file_list .count () - 1 )
1444+ if last_item :
1445+ self .file_list .setCurrentItem (last_item )
13411446
13421447 def on_image_selected (self , current_item , previous_item ):
13431448 """Handle image selection from the file list"""
@@ -1359,8 +1464,15 @@ def on_image_selected(self, current_item, previous_item):
13591464
13601465 # Check if we have SDK versions configured
13611466 if len (self .sdk_versions ) >= 2 :
1362- # Process the selected image
1363- self .process_selected_image (image_path )
1467+ # Check if we already have results for this image
1468+ if (image_path in self .results and
1469+ len (self .results [image_path ]) == len (self .sdk_versions )):
1470+ # We already have results, just display them
1471+ self .update_single_image_display (image_path )
1472+ self .status_bar .showMessage (f"✅ Displaying results for { os .path .basename (image_path )} " )
1473+ else :
1474+ # No results yet, process the image
1475+ self .process_selected_image (image_path )
13641476 else :
13651477 # Clear the comparison view and show message
13661478 self .image_comparison .sdk1_scene .clear ()
@@ -1376,6 +1488,16 @@ def process_selected_image(self, image_path: str):
13761488 self .status_bar .showMessage ("❌ Image file not found" )
13771489 return
13781490
1491+ # Check if we have the necessary data (image files and SDK versions)
1492+ if not self .image_files or len (self .sdk_versions ) < 2 :
1493+ self .status_bar .showMessage ("❌ No images loaded or insufficient SDK versions configured" )
1494+ return
1495+
1496+ # Verify the image is still in our current image list (might have been cleared by mode change)
1497+ if image_path not in self .image_files :
1498+ self .status_bar .showMessage ("❌ Image no longer in current selection" )
1499+ return
1500+
13791501 # Check if already processing this image
13801502 if (self .processing_thread and
13811503 self .processing_thread .isRunning () and
@@ -1394,7 +1516,7 @@ def process_selected_image(self, image_path: str):
13941516
13951517 # Show progress
13961518 self .progress_bar .setVisible (True )
1397- self .progress_bar .setRange (0 , len (self .sdk_versions ) * len ( self . new_files ))
1519+ self .progress_bar .setRange (0 , len (self .sdk_versions )) # Only processing one image
13981520 self .progress_bar .setValue (0 )
13991521
14001522 self .status_bar .showMessage (f"Processing { os .path .basename (image_path )} ..." )
@@ -1404,8 +1526,8 @@ def process_selected_image(self, image_path: str):
14041526 self .processing_thread .terminate ()
14051527 self .processing_thread .wait (1000 )
14061528
1407- # Start processing the selected image
1408- self .processing_thread = ProcessingThread (self . new_files , self .sdk_versions , self .current_detection_mode )
1529+ # Start processing the selected image only (not all new_files)
1530+ self .processing_thread = ProcessingThread ([ image_path ] , self .sdk_versions , self .current_detection_mode )
14091531
14101532 # Connect signals
14111533 self .processing_thread .result_ready .connect (
@@ -1501,6 +1623,15 @@ def on_detection_mode_changed(self, mode: str):
15011623 self .current_detection_mode = mode
15021624 self .status_bar .showMessage (f"Detection mode changed to: { mode } " )
15031625
1626+ # Stop any running processing threads first to prevent processing with old mode
1627+ if hasattr (self , 'processing_thread' ) and self .processing_thread and self .processing_thread .isRunning ():
1628+ self .processing_thread .terminate ()
1629+ self .processing_thread .wait (1000 )
1630+ self .processing_thread = None
1631+
1632+ # Hide progress bar
1633+ self .progress_bar .setVisible (False )
1634+
15041635 # Clear existing results and image files when mode changes as they're no longer valid
15051636 self .results .clear ()
15061637 self .results_table .setRowCount (0 )
0 commit comments