@@ -423,7 +423,20 @@ void AscentDialog::handle_removeHikers()
423
423
*/
424
424
void AscentDialog::handle_addPhotos ()
425
425
{
426
- QStringList filepaths = openFileDialogForPhotosSelection (this );
426
+ // Determine path at which file dialog will open
427
+ int photoIndexForDir = -1 ;
428
+ QItemSelectionModel* selectionModel = photosListView->selectionModel ();
429
+ if (selectionModel->hasSelection ()) { // Use first selected photo if possible
430
+ photoIndexForDir = selectionModel->selectedRows ().first ().row ();
431
+ } else if (!photosModel.isEmpty ()) { // Otherwise, use first photo if it exists
432
+ photoIndexForDir = 0 ;
433
+ }
434
+ QString preSelectedDir = QString ();
435
+ if (photoIndexForDir >= 0 ) {
436
+ preSelectedDir = QFileInfo (photosModel.getFilepathAt (photoIndexForDir)).path ();
437
+ }
438
+
439
+ QStringList filepaths = openFileDialogForMultiPhotoSelection (this , preSelectedDir);
427
440
if (filepaths.isEmpty ()) return ;
428
441
429
442
QList<Photo> photos = QList<Photo>();
@@ -681,17 +694,106 @@ static BufferRowIndex openAscentDialogAndStore(QWidget* parent, Database* db, Di
681
694
682
695
683
696
/* *
684
- * Opens a file dialog for selecting photos .
697
+ * Opens a file dialog for selecting a single image file .
685
698
*
686
- * @param parent The parent window.
687
- * @return The selected filepaths.
699
+ * @param parent The parent window.
700
+ * @param preSelectedDir The directory to open the file dialog in initially, or an empty QString.
701
+ * @param overrideWindowTitle The window title to use, or an empty QString to use the default one.
702
+ * @return The selected filepath, or an empty QString if the dialog was cancelled.
703
+ */
704
+ QString openFileDialogForSinglePhotoSelection (QWidget* parent, QString preSelectedDir, QString overrideWindowTitle)
705
+ {
706
+ QString caption = AscentDialog::tr (" Select photo of ascent" );
707
+ if (!overrideWindowTitle.isEmpty ()) caption = overrideWindowTitle;
708
+ QString filter = getImageFileDialogFilterString ();
709
+ QString filepath = QFileDialog::getOpenFileName (parent, caption, preSelectedDir, filter);
710
+
711
+ QStringList checkedPath = checkFilepathsAndAskUser (parent, {filepath});
712
+ if (checkedPath.isEmpty ()) return QString ();
713
+ return checkedPath.first ();
714
+ }
715
+
716
+ /* *
717
+ * Opens a file dialog for selecting multiple image files.
718
+ *
719
+ * @param parent The parent window.
720
+ * @param preSelectedDir The directory to open the file dialog in initially, or an empty QString.
721
+ * @param overrideWindowTitle The window title to use, or an empty QString to use the default one.
722
+ * @return The selected filepaths, or an empty QStringList if the dialog was cancelled.
688
723
*/
689
- QStringList openFileDialogForPhotosSelection (QWidget* parent)
724
+ QStringList openFileDialogForMultiPhotoSelection (QWidget* parent, QString preSelectedDir, QString overrideWindowTitle )
690
725
{
691
726
QString caption = AscentDialog::tr (" Select photos of ascent" );
692
- QString preSelectedDir = QString ();
693
- QString filter = AscentDialog::tr (" Images" ) + " (*.jpg *.jpeg *.png *.bmp *.gif *.pbm *.pgm *.ppm *.xbm *.xpm);;"
694
- + AscentDialog::tr (" All files" ) + " (*.*)" ;
727
+ if (!overrideWindowTitle.isEmpty ()) caption = overrideWindowTitle;
728
+ QString filter = getImageFileDialogFilterString ();
695
729
QStringList filepaths = QFileDialog::getOpenFileNames (parent, caption, preSelectedDir, filter);
730
+
731
+ filepaths = checkFilepathsAndAskUser (parent, filepaths);
732
+
733
+ return filepaths;
734
+ }
735
+
736
+ /* *
737
+ * Returns the translated filter string to use for image file dialogs.
738
+ * @return The translated filter string.
739
+ */
740
+ QString getImageFileDialogFilterString ()
741
+ {
742
+ return AscentDialog::tr (" Images" ) + " (*.jpg *.jpeg *.png *.bmp *.gif *.pbm *.pgm *.ppm *.xbm *.xpm);;"
743
+ + AscentDialog::tr (" All files" ) + " (*.*)" ;
744
+ }
745
+
746
+ /* *
747
+ * Checks whether the given filepaths can be read as images and asks the user whether to add them
748
+ * anyway if they cannot.
749
+ *
750
+ * @param parent The parent window.
751
+ * @param filepaths The filepaths to check.
752
+ * @return The filepaths which are unproblematic or confirmed by the user. Empty if the user cancels.
753
+ */
754
+ QStringList checkFilepathsAndAskUser (QWidget* parent, QStringList filepaths)
755
+ {
756
+ bool noToAll = false ;
757
+
758
+ for (int i = 0 ; i < filepaths.size (); i++) {
759
+ QString filepath = filepaths.at (i);
760
+ QImageReader reader = QImageReader (filepath);
761
+ if (reader.canRead ()) continue ;
762
+
763
+ if (noToAll) {
764
+ filepaths.remove (i--); // Remove this path and skip the dialog
765
+ continue ;
766
+ }
767
+
768
+ QString title = AscentDialog::tr (" File error" );
769
+ QString message = AscentDialog::tr (" Image file cannot be read:\n %1"
770
+ " \n Reason: %2."
771
+ " \n\n Do you want to use it anyway?" )
772
+ .arg (filepath, reader.errorString ());
773
+ auto buttons = QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel;
774
+ if (filepaths.size () - 1 > i) {
775
+ buttons |= QMessageBox::YesToAll | QMessageBox::NoToAll;
776
+ }
777
+ auto pressedButton = QMessageBox::warning (parent, title, message, buttons);
778
+
779
+ if (pressedButton == QMessageBox::Yes) {
780
+ // Do nothing
781
+ }
782
+ else if (pressedButton == QMessageBox::YesToAll) {
783
+ break ; // Leave loop, no more paths need to be checked or removed
784
+ }
785
+ else if (pressedButton == QMessageBox::No) {
786
+ filepaths.remove (i--); // Remove this path
787
+ }
788
+ else if (pressedButton == QMessageBox::NoToAll) {
789
+ filepaths.remove (i--); // Remove this path and set flag
790
+ noToAll = true ;
791
+ }
792
+ else if (pressedButton == QMessageBox::Cancel) {
793
+ return QStringList (); // Return with empty list
794
+ }
795
+ else assert (false );
796
+ }
797
+
696
798
return filepaths;
697
799
}
0 commit comments