@@ -445,146 +445,158 @@ void GameSummaryWidget::onComputeHashClicked()
445445 return ;
446446 }
447447
448- Error error;
449- std::unique_ptr<CDImage> image = CDImage::Open (m_path.c_str (), false , &error);
450- if (!image)
451- {
452- QtUtils::MessageBoxCritical (QtUtils::GetRootWidget (this ), tr (" Image Open Failed" ),
453- QString::fromStdString (error.GetDescription ()));
454- return ;
455- }
448+ m_ui.computeHashes ->setEnabled (false );
449+
450+ QtAsyncTaskWithProgress::create (this , TRANSLATE_SV (" GameSummaryWidget" , " Verifying Image" ), {}, true , 1 , 0 , 0 .0f ,
451+ [this , path = m_path](ProgressCallback* progress) {
452+ Error error;
453+ CDImageHasher::TrackHashes track_hashes;
454+ const bool result = computeImageHash (path, track_hashes, progress, &error);
455+ const bool cancelled = (!result && progress->IsCancelled ());
456+ return
457+ [this , track_hashes = std::move (track_hashes), error = std::move (error), result,
458+ cancelled]() { processHashResults (track_hashes, result, cancelled, error); };
459+ });
460+ }
456461
457- QtModalProgressCallback progress_callback (this );
458- progress_callback.SetCancellable (true );
459- progress_callback.SetProgressRange (image->GetTrackCount ());
460- progress_callback.MakeVisible ();
462+ bool GameSummaryWidget::computeImageHash (const std::string& path, CDImageHasher::TrackHashes& track_hashes,
463+ ProgressCallback* const progress, Error* const error) const
464+ {
465+ std::unique_ptr<CDImage> image = CDImage::Open (m_path.c_str (), false , error);
466+ if (!image)
467+ return false ;
461468
462- std::vector<CDImageHasher::Hash> track_hashes;
463469 track_hashes.reserve (image->GetTrackCount ());
470+ progress->SetProgressRange (image->GetTrackCount ());
464471
465- // Calculate hashes
466- bool calculate_hash_success = true ;
467- for (u8 track = 1 ; track <= image->GetTrackCount (); track++)
472+ for (u32 track = 0 ; track < image->GetTrackCount (); track++)
468473 {
469- progress_callback. SetProgressValue (track - 1 );
470- progress_callback. PushState ();
474+ progress-> SetProgressValue (track);
475+ progress-> PushState ();
471476
472477 CDImageHasher::Hash hash;
473- if (!CDImageHasher::GetTrackHash (image.get (), track, &hash, &progress_callback, & error))
478+ if (!CDImageHasher::GetTrackHash (image.get (), static_cast < u8 >( track + 1 ) , &hash, progress, error))
474479 {
475- progress_callback.PopState ();
476-
477- if (progress_callback.IsCancelled ())
478- return ;
479-
480- QtUtils::MessageBoxCritical (QtUtils::GetRootWidget (this ), tr (" Hash Calculation Failed" ),
481- QString::fromStdString (error.GetDescription ()));
482- calculate_hash_success = false ;
483- break ;
480+ progress->PopState ();
481+ return false ;
484482 }
483+
485484 track_hashes.emplace_back (hash);
485+ progress->PopState ();
486+ }
486487
487- QTreeWidgetItem* const row = m_ui.tracks ->topLevelItem (track - 1 );
488- row->setText (4 , QString::fromStdString (CDImageHasher::HashToString (hash)));
488+ return true ;
489+ }
490+
491+ void GameSummaryWidget::processHashResults (const CDImageHasher::TrackHashes& track_hashes, bool result, bool cancelled,
492+ const Error& error)
493+ {
494+ m_ui.computeHashes ->setEnabled (true );
495+
496+ if (!result)
497+ {
498+ if (!cancelled)
499+ {
500+ QtUtils::AsyncMessageBox (this , QMessageBox::Critical, tr (" Hash Calculation Failed" ),
501+ QString::fromStdString (error.GetDescription ()));
502+ }
489503
490- progress_callback. PopState () ;
504+ return ;
491505 }
492506
493507 // Verify hashes against gamedb
494- std::vector<bool > verification_results (image->GetTrackCount (), false );
495- if (calculate_hash_success)
508+ std::vector<bool > verification_results (track_hashes.size (), false );
509+
510+ std::string found_revision;
511+ std::string found_serial;
512+ m_redump_search_keyword = CDImageHasher::HashToString (track_hashes.front ());
513+
514+ // Verification strategy used:
515+ // 1. First, find all matches for the data track
516+ // If none are found, fail verification for all tracks
517+ // 2. For each data track match, try to match all audio tracks
518+ // If all match, assume this revision. Else, try other revisions,
519+ // and accept the one with the most matches.
520+ const GameDatabase::TrackHashesMap& hashes_map = GameDatabase::GetTrackHashesMap ();
521+
522+ auto data_track_matches = hashes_map.equal_range (track_hashes[0 ]);
523+ if (data_track_matches.first != data_track_matches.second )
496524 {
497- std::string found_revision;
498- std::string found_serial;
499- m_redump_search_keyword = CDImageHasher::HashToString (track_hashes.front ());
500-
501- progress_callback.SetStatusText (TRANSLATE (" GameSummaryWidget" , " Verifying hashes..." ));
502- progress_callback.SetProgressValue (image->GetTrackCount ());
503-
504- // Verification strategy used:
505- // 1. First, find all matches for the data track
506- // If none are found, fail verification for all tracks
507- // 2. For each data track match, try to match all audio tracks
508- // If all match, assume this revision. Else, try other revisions,
509- // and accept the one with the most matches.
510- const GameDatabase::TrackHashesMap& hashes_map = GameDatabase::GetTrackHashesMap ();
511-
512- auto data_track_matches = hashes_map.equal_range (track_hashes[0 ]);
513- if (data_track_matches.first != data_track_matches.second )
525+ auto best_data_match = data_track_matches.second ;
526+ for (auto iter = data_track_matches.first ; iter != data_track_matches.second ; ++iter)
514527 {
515- auto best_data_match = data_track_matches.second ;
516- for (auto iter = data_track_matches.first ; iter != data_track_matches.second ; ++iter)
517- {
518- std::vector<bool > current_verification_results (image->GetTrackCount (), false );
519- const auto & data_track_attribs = iter->second ;
520- current_verification_results[0 ] = true ; // Data track already matched
528+ std::vector<bool > current_verification_results (track_hashes.size (), false );
529+ const auto & data_track_attribs = iter->second ;
530+ current_verification_results[0 ] = true ; // Data track already matched
521531
522- for (auto audio_tracks_iter = std::next (track_hashes.begin ()); audio_tracks_iter != track_hashes.end ();
523- ++audio_tracks_iter)
532+ for (auto audio_tracks_iter = std::next (track_hashes.begin ()); audio_tracks_iter != track_hashes.end ();
533+ ++audio_tracks_iter)
534+ {
535+ auto audio_track_matches = hashes_map.equal_range (*audio_tracks_iter);
536+ for (auto audio_iter = audio_track_matches.first ; audio_iter != audio_track_matches.second ; ++audio_iter)
524537 {
525- auto audio_track_matches = hashes_map. equal_range (*audio_tracks_iter);
526- for ( auto audio_iter = audio_track_matches. first ; audio_iter != audio_track_matches. second ; ++audio_iter )
538+ // If audio track comes from the same revision and code as the data track, "pass" it
539+ if ( audio_iter-> second == data_track_attribs )
527540 {
528- // If audio track comes from the same revision and code as the data track, "pass" it
529- if (audio_iter->second == data_track_attribs)
530- {
531- current_verification_results[std::distance (track_hashes.begin (), audio_tracks_iter)] = true ;
532- break ;
533- }
541+ current_verification_results[std::distance (track_hashes.begin (), audio_tracks_iter)] = true ;
542+ break ;
534543 }
535544 }
545+ }
536546
537- const auto old_matches_count = std::count (verification_results.begin (), verification_results.end (), true );
538- const auto new_matches_count =
539- std::count (current_verification_results.begin (), current_verification_results.end (), true );
547+ const auto old_matches_count = std::count (verification_results.begin (), verification_results.end (), true );
548+ const auto new_matches_count =
549+ std::count (current_verification_results.begin (), current_verification_results.end (), true );
540550
541- if (new_matches_count > old_matches_count)
551+ if (new_matches_count > old_matches_count)
552+ {
553+ best_data_match = iter;
554+ verification_results = current_verification_results;
555+ // If all elements got matched, early out
556+ if (new_matches_count >= static_cast <ptrdiff_t >(verification_results.size ()))
542557 {
543- best_data_match = iter;
544- verification_results = current_verification_results;
545- // If all elements got matched, early out
546- if (new_matches_count >= static_cast <ptrdiff_t >(verification_results.size ()))
547- {
548- break ;
549- }
558+ break ;
550559 }
551560 }
552-
553- found_revision = best_data_match->second .revision_str ;
554- found_serial = best_data_match->second .serial ;
555561 }
556562
557- QString text;
563+ found_revision = best_data_match->second .revision_str ;
564+ found_serial = best_data_match->second .serial ;
565+ }
558566
559- if (!found_revision.empty ())
560- text = tr (" Revision: %1" ).arg (found_revision.empty () ? tr (" N/A" ) : QString::fromStdString (found_revision));
567+ QString text;
561568
562- if (found_serial != m_dialog->getGameSerial ())
569+ if (!found_revision.empty ())
570+ text = tr (" Revision: %1" ).arg (found_revision.empty () ? tr (" N/A" ) : QString::fromStdString (found_revision));
571+
572+ if (found_serial != m_dialog->getGameSerial ())
573+ {
574+ if (found_serial.empty ())
563575 {
564- if (found_serial.empty ())
565- {
566- text = tr (" No known dump found that matches this hash." );
567- }
576+ text = tr (" No known dump found that matches this hash." );
577+ }
578+ else
579+ {
580+ const QString mismatch_str = tr (" Serial Mismatch: %1 vs %2" )
581+ .arg (QString::fromStdString (found_serial))
582+ .arg (QString::fromStdString (m_dialog->getGameSerial ()));
583+ if (!text.isEmpty ())
584+ text = QStringLiteral (" %1 | %2" ).arg (mismatch_str).arg (text);
568585 else
569- {
570- const QString mismatch_str = tr (" Serial Mismatch: %1 vs %2" )
571- .arg (QString::fromStdString (found_serial))
572- .arg (QString::fromStdString (m_dialog->getGameSerial ()));
573- if (!text.isEmpty ())
574- text = QStringLiteral (" %1 | %2" ).arg (mismatch_str).arg (text);
575- else
576- text = mismatch_str;
577- }
586+ text = mismatch_str;
578587 }
579-
580- setRevisionText (text);
581588 }
582589
583- for (u8 track = 0 ; track < image->GetTrackCount (); track++)
590+ setRevisionText (text);
591+
592+ // update in ui
593+ for (size_t i = 0 ; i < track_hashes.size (); i++)
584594 {
585- QTreeWidgetItem* const row = m_ui.tracks ->topLevelItem (track);
595+ QTreeWidgetItem* const row = m_ui.tracks ->topLevelItem (static_cast <int >(i));
596+ row->setText (4 , QString::fromStdString (CDImageHasher::HashToString (track_hashes[i])));
597+
586598 QBrush brush;
587- if (verification_results[track ])
599+ if (verification_results[i ])
588600 {
589601 brush = QColor (0 , 200 , 0 );
590602 row->setText (5 , QString::fromUtf8 (u8" \u2713 " ));
0 commit comments