summaryrefslogtreecommitdiff
path: root/src/camera/ImportPage.vala
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff.email>2023-06-14 20:36:37 +0200
committerJörg Frings-Fürst <debian@jff.email>2023-06-14 20:36:37 +0200
commitbb80d3feebdc9acc52e3f4ad24084d8425f043a2 (patch)
tree2084a84c39f159c6aea254775dc0880d52579d45 /src/camera/ImportPage.vala
parentb26ff0798252a1a8072dd2c7a67f6205de9fde11 (diff)
parent31804433d72460cbe0a39f9f8ea5e76058d84cda (diff)
Merge branch 'feature/upstream' into develop
Diffstat (limited to 'src/camera/ImportPage.vala')
-rw-r--r--src/camera/ImportPage.vala162
1 files changed, 71 insertions, 91 deletions
diff --git a/src/camera/ImportPage.vala b/src/camera/ImportPage.vala
index 84d7cbe..a5d3b4e 100644
--- a/src/camera/ImportPage.vala
+++ b/src/camera/ImportPage.vala
@@ -21,13 +21,13 @@ abstract class ImportSource : ThumbnailSource, Indexable {
private string folder;
private string filename;
private ulong file_size;
- private time_t modification_time;
+ private DateTime modification_time;
private Gdk.Pixbuf? preview = null;
private string? indexable_keywords = null;
protected ImportSource(string camera_name, GPhoto.Camera camera, int fsid, string folder,
- string filename, ulong file_size, time_t modification_time) {
- this.camera_name = camera_name;
+ string filename, ulong file_size, DateTime modification_time) {
+ this.camera_name =camera_name;
this.camera = camera;
this.fsid = fsid;
this.folder = folder;
@@ -65,7 +65,7 @@ abstract class ImportSource : ThumbnailSource, Indexable {
return file_size;
}
- public time_t get_modification_time() {
+ public DateTime get_modification_time() {
return modification_time;
}
@@ -73,7 +73,7 @@ abstract class ImportSource : ThumbnailSource, Indexable {
return preview;
}
- public virtual time_t get_exposure_time() {
+ public virtual DateTime get_exposure_time() {
return get_modification_time();
}
@@ -110,7 +110,7 @@ abstract class ImportSource : ThumbnailSource, Indexable {
class VideoImportSource : ImportSource {
public VideoImportSource(string camera_name, GPhoto.Camera camera, int fsid, string folder,
- string filename, ulong file_size, time_t modification_time) {
+ string filename, ulong file_size, DateTime modification_time) {
base(camera_name, camera, fsid, folder, filename, file_size, modification_time);
}
@@ -159,7 +159,7 @@ class PhotoImportSource : ImportSource {
private PhotoImportSource? associated = null; // JPEG source for RAW+JPEG
public PhotoImportSource(string camera_name, GPhoto.Camera camera, int fsid, string folder,
- string filename, ulong file_size, time_t modification_time, PhotoFileFormat file_format) {
+ string filename, ulong file_size, DateTime modification_time, PhotoFileFormat file_format) {
base(camera_name, camera, fsid, folder, filename, file_size, modification_time);
this.file_format = file_format;
}
@@ -200,7 +200,7 @@ class PhotoImportSource : ImportSource {
this.exif_md5 = exif_md5;
}
- public override time_t get_exposure_time() {
+ public override DateTime get_exposure_time() {
if (metadata == null)
return get_modification_time();
@@ -340,10 +340,10 @@ class ImportPreview : MediaSourceItem {
if (duplicated_photo_id.is_valid()) {
// Check exposure timestamp
LibraryPhoto duplicated_photo = LibraryPhoto.global.fetch(duplicated_photo_id);
- time_t photo_exposure_time = photo_import_source.get_exposure_time();
- time_t duplicated_photo_exposure_time = duplicated_photo.get_exposure_time();
+ DateTime photo_exposure_time = photo_import_source.get_exposure_time();
+ DateTime duplicated_photo_exposure_time = duplicated_photo.get_exposure_time();
- if (photo_exposure_time == duplicated_photo_exposure_time) {
+ if (photo_exposure_time.equal(duplicated_photo_exposure_time)) {
duplicated_file = DuplicatedFile.create_from_photo_id(
LibraryPhoto.global.get_basename_filesize_duplicate(
get_import_source().get_filename(), (int64) filesize));
@@ -485,7 +485,7 @@ public class ImportPage : CheckerboardPage {
private string filename;
private uint64 filesize;
private PhotoMetadata metadata;
- private time_t exposure_time;
+ private DateTime exposure_time;
private CameraImportJob? associated = null;
private BackingPhotoRow? associated_file = null;
private DuplicatedFile? duplicated_file;
@@ -503,12 +503,13 @@ public class ImportPage : CheckerboardPage {
assert(fulldir != null);
filename = import_file.get_filename();
filesize = import_file.get_filesize();
- metadata = (import_file is PhotoImportSource) ?
- (import_file as PhotoImportSource).get_metadata() : null;
+ var photo_import_source = import_file as PhotoImportSource;
+ metadata = (photo_import_source != null) ?
+ photo_import_source.get_metadata() : null;
exposure_time = import_file.get_exposure_time();
}
- public time_t get_exposure_time() {
+ public DateTime get_exposure_time() {
return exposure_time;
}
@@ -516,8 +517,8 @@ public class ImportPage : CheckerboardPage {
return duplicated_file;
}
- public override time_t get_exposure_time_override() {
- return (import_file is VideoImportSource) ? get_exposure_time() : 0;
+ public override DateTime? get_exposure_time_override() {
+ return (import_file is VideoImportSource) ? get_exposure_time() : null;
}
public override string get_dest_identifier() {
@@ -682,16 +683,13 @@ public class ImportPage : CheckerboardPage {
private Gtk.Label camera_label = new Gtk.Label(null);
private Gtk.CheckButton hide_imported;
private Gtk.ProgressBar progress_bar = new Gtk.ProgressBar();
- private GPhoto.Camera camera;
- private string uri;
+ private DiscoveredCamera dcamera;
private bool busy = false;
private bool refreshed = false;
private GPhoto.Result refresh_result = GPhoto.Result.OK;
private string refresh_error = null;
- private string camera_name;
private VolumeMonitor volume_monitor = null;
private ImportPage? local_ref = null;
- private string? icon;
private ImportPageSearchViewFilter search_filter = new ImportPageSearchViewFilter();
private HideImportedViewFilter hide_imported_filter = new HideImportedViewFilter();
private CameraViewTracker tracker;
@@ -707,28 +705,15 @@ public class ImportPage : CheckerboardPage {
LIBRARY_ERROR
}
- public ImportPage(GPhoto.Camera camera, string uri, string? display_name = null, string? icon = null) {
+ public ImportPage(DiscoveredCamera dcamera) {
base(_("Camera"));
- this.camera = camera;
- this.uri = uri;
- this.import_sources = new ImportSourceCollection("ImportSources for %s".printf(uri));
- this.icon = icon;
+ this.dcamera = dcamera;
+ this.import_sources = new ImportSourceCollection("ImportSources for %s".printf(dcamera.uri));
tracker = new CameraViewTracker(get_view());
- // Get camera name.
- if (null != display_name) {
- camera_name = display_name;
- } else {
- GPhoto.CameraAbilities abilities;
- GPhoto.Result res = camera.get_abilities(out abilities);
- if (res != GPhoto.Result.OK) {
- debug("Unable to get camera abilities: %s", res.to_full_string());
- camera_name = _("Camera");
- }
- }
- camera_label.set_text(camera_name);
- set_page_name(camera_name);
+ camera_label.set_text(dcamera.display_name);
+ set_page_name(dcamera.display_name);
// Mount.unmounted signal is *only* fired when a VolumeMonitor has been instantiated.
this.volume_monitor = VolumeMonitor.get();
@@ -846,6 +831,14 @@ public class ImportPage : CheckerboardPage {
return tracker;
}
+ protected override string get_view_empty_icon() {
+ if (this.dcamera.icon != null) {
+ return this.dcamera.icon;
+ }
+
+ return "camera-photo-symbolic";
+ }
+
protected override string get_view_empty_message() {
return _("The camera seems to be empty. No photos/videos found to import");
}
@@ -855,8 +848,8 @@ public class ImportPage : CheckerboardPage {
}
private static int64 preview_comparator(void *a, void *b) {
- return ((ImportPreview *) a)->get_import_source().get_exposure_time()
- - ((ImportPreview *) b)->get_import_source().get_exposure_time();
+ return nullsafe_date_time_comperator(((ImportPreview *) a)->get_import_source().get_exposure_time(),
+ ((ImportPreview *) b)->get_import_source().get_exposure_time());
}
private static bool preview_comparator_predicate(DataObject object, Alteration alteration) {
@@ -864,7 +857,7 @@ public class ImportPage : CheckerboardPage {
}
private int64 import_job_comparator(void *a, void *b) {
- return ((CameraImportJob *) a)->get_exposure_time() - ((CameraImportJob *) b)->get_exposure_time();
+ return nullsafe_date_time_comperator(((CameraImportJob *) a)->get_exposure_time(), ((CameraImportJob *) b)->get_exposure_time());
}
protected override void init_collect_ui_filenames(Gee.List<string> ui_filenames) {
@@ -896,11 +889,11 @@ public class ImportPage : CheckerboardPage {
}
public GPhoto.Camera get_camera() {
- return camera;
+ return dcamera.gcamera;
}
public string get_uri() {
- return uri;
+ return dcamera.uri;
}
public bool is_busy() {
@@ -998,27 +991,9 @@ public class ImportPage : CheckerboardPage {
}
// if locked because it's mounted, offer to unmount
- debug("Checking if %s is mounted…", uri);
+ debug("Checking if %s is mounted…", dcamera.uri);
- File uri = File.new_for_uri(uri);
-
- Mount mount = null;
- try {
- mount = uri.find_enclosing_mount(null);
- } catch (Error err) {
- // error means not mounted
- }
-
- // Could not find mount for gphoto2://, re-try with mtp://
- // It seems some devices are mounted using MTP and not gphoto2 daemon
- if (mount == null && this.uri.has_prefix("gphoto2")) {
- uri = File.new_for_uri("mtp" + this.uri.substring(7));
- try {
- mount = uri.find_enclosing_mount(null);
- } catch (Error err) {
- // error means not mounted
- }
- }
+ var mount = dcamera.get_mount();
if (mount != null) {
// it's mounted, offer to unmount for the user
@@ -1128,7 +1103,7 @@ public class ImportPage : CheckerboardPage {
* @param search_target The name of the directory to look for.
*/
private bool check_directory_exists(int fsid, string dir, string search_target) {
- string? fulldir = get_fulldir(camera, camera_name, fsid, dir);
+ string? fulldir = get_fulldir(dcamera.gcamera, dcamera.display_name, fsid, dir);
GPhoto.Result result;
GPhoto.CameraList folders;
@@ -1138,7 +1113,7 @@ public class ImportPage : CheckerboardPage {
return false;
}
- result = camera.list_folders(fulldir, folders, spin_idle_context.context);
+ result = dcamera.gcamera.list_folders(fulldir, folders, spin_idle_context.context);
if (result != GPhoto.Result.OK) {
// fetching the list failed - can't determine whether specified dir is present
return false;
@@ -1167,7 +1142,7 @@ public class ImportPage : CheckerboardPage {
update_status(busy, false);
refresh_error = null;
- refresh_result = camera.init(spin_idle_context.context);
+ refresh_result = dcamera.gcamera.init(spin_idle_context.context);
// If we fail to claim the device, we might have run into a conflict
// with gvfs-gphoto2-volume-monitor. Back off, try again after
@@ -1209,7 +1184,7 @@ public class ImportPage : CheckerboardPage {
Gee.ArrayList<ImportSource> import_list = new Gee.ArrayList<ImportSource>();
GPhoto.CameraStorageInformation[] sifs = null;
- refresh_result = camera.get_storageinfo(out sifs, spin_idle_context.context);
+ refresh_result = dcamera.gcamera.get_storageinfo(out sifs, spin_idle_context.context);
if (refresh_result == GPhoto.Result.OK) {
for (int fsid = 0; fsid < sifs.length; fsid++) {
// Check well-known video and image paths first to prevent accidental
@@ -1302,7 +1277,7 @@ public class ImportPage : CheckerboardPage {
progress_bar.set_text("");
progress_bar.set_fraction(0.0);
- GPhoto.Result res = camera.exit(spin_idle_context.context);
+ GPhoto.Result res = dcamera.gcamera.exit(spin_idle_context.context);
if (res != GPhoto.Result.OK) {
// log but don't fail
warning("Unable to unlock camera: %s", res.to_full_string());
@@ -1386,7 +1361,7 @@ public class ImportPage : CheckerboardPage {
}
private bool enumerate_files(int fsid, string dir, Gee.ArrayList<ImportSource> import_list) {
- string? fulldir = get_fulldir(camera, camera_name, fsid, dir);
+ string? fulldir = get_fulldir(dcamera.gcamera, dcamera.display_name, fsid, dir);
if (fulldir == null) {
warning("Skipping enumerating %s: invalid folder name", dir);
@@ -1401,7 +1376,7 @@ public class ImportPage : CheckerboardPage {
return false;
}
- refresh_result = camera.list_files(fulldir, files, spin_idle_context.context);
+ refresh_result = dcamera.gcamera.list_files(fulldir, files, spin_idle_context.context);
if (refresh_result != GPhoto.Result.OK) {
warning("Unable to list files in %s: %s", fulldir, refresh_result.to_full_string());
@@ -1424,7 +1399,7 @@ public class ImportPage : CheckerboardPage {
try {
GPhoto.CameraFileInfo info;
- if (!GPhoto.get_info(spin_idle_context.context, camera, fulldir, filename, out info)) {
+ if (!GPhoto.get_info(spin_idle_context.context, dcamera.gcamera, fulldir, filename, out info)) {
warning("Skipping import of %s/%s: name too long", fulldir, filename);
continue;
@@ -1438,8 +1413,8 @@ public class ImportPage : CheckerboardPage {
}
if (VideoReader.is_supported_video_filename(filename)) {
- VideoImportSource video_source = new VideoImportSource(camera_name, camera,
- fsid, dir, filename, info.file.size, info.file.mtime);
+ VideoImportSource video_source = new VideoImportSource(dcamera.display_name, dcamera.gcamera,
+ fsid, dir, filename, info.file.size, new DateTime.from_unix_utc(info.file.mtime));
import_list.add(video_source);
} else {
// determine file format from type, and then from file extension
@@ -1454,8 +1429,8 @@ public class ImportPage : CheckerboardPage {
continue;
}
}
- import_list.add(new PhotoImportSource(camera_name, camera, fsid, dir, filename,
- info.file.size, info.file.mtime, file_format));
+ import_list.add(new PhotoImportSource(dcamera.display_name, dcamera.gcamera, fsid, dir, filename,
+ info.file.size, new DateTime.from_unix_utc(info.file.mtime), file_format));
}
progress_bar.pulse();
@@ -1479,7 +1454,7 @@ public class ImportPage : CheckerboardPage {
return false;
}
- refresh_result = camera.list_folders(fulldir, folders, spin_idle_context.context);
+ refresh_result = dcamera.gcamera.list_folders(fulldir, folders, spin_idle_context.context);
if (refresh_result != GPhoto.Result.OK) {
warning("Unable to list folders in %s: %s", fulldir, refresh_result.to_full_string());
@@ -1498,8 +1473,12 @@ public class ImportPage : CheckerboardPage {
return false;
}
- if (!enumerate_files(fsid, append_path(dir, subdir), import_list))
- return false;
+ if (subdir.has_prefix(".")) {
+ debug("Skipping hidden sub-folder %s in %s", subdir, dir);
+ } else {
+ if (!enumerate_files(fsid, append_path(dir, subdir), import_list))
+ return false;
+ }
}
return true;
@@ -1575,7 +1554,7 @@ public class ImportPage : CheckerboardPage {
PhotoMetadata? metadata = null;
if (!VideoReader.is_supported_video_filename(filename)) {
try {
- metadata = GPhoto.load_metadata(spin_idle_context.context, camera, fulldir,
+ metadata = GPhoto.load_metadata(spin_idle_context.context, dcamera.gcamera, fulldir,
filename);
} catch (Error err) {
warning("Unable to fetch metadata for %s/%s: %s", fulldir, filename,
@@ -1604,7 +1583,7 @@ public class ImportPage : CheckerboardPage {
preview_fulldir = associated.get_fulldir();
preview_filename = associated.get_filename();
}
- preview = GPhoto.load_preview(spin_idle_context.context, camera, preview_fulldir,
+ preview = GPhoto.load_preview(spin_idle_context.context, dcamera.gcamera, preview_fulldir,
preview_filename, out preview_md5);
} catch (Error err) {
// only issue the warning message if we're not reading a video. GPhoto is capable
@@ -1621,17 +1600,18 @@ public class ImportPage : CheckerboardPage {
debug("camera MD5 %s: exif=%s preview=%s", filename, exif_only_md5, preview_md5);
#endif
- if (import_source is VideoImportSource)
- (import_source as VideoImportSource).update(preview);
+ var video_import_source = import_source as VideoImportSource;
+ if (video_import_source != null)
+ video_import_source.update(preview);
- if (import_source is PhotoImportSource)
- (import_source as PhotoImportSource).update(preview, preview_md5, metadata,
- exif_only_md5);
+ var photo_import_source = import_source as PhotoImportSource;
+ if (photo_import_source != null)
+ photo_import_source.update(preview, preview_md5, metadata, exif_only_md5);
if (associated != null) {
try {
PhotoMetadata? associated_metadata = GPhoto.load_metadata(spin_idle_context.context,
- camera, associated.get_fulldir(), associated.get_filename());
+ dcamera.gcamera, associated.get_fulldir(), associated.get_filename());
associated.update(preview, preview_md5, associated_metadata, null);
} catch (Error err) {
warning("Unable to fetch metadata for %s/%s: %s", associated.get_fulldir(),
@@ -1671,7 +1651,7 @@ public class ImportPage : CheckerboardPage {
}
private void import(Gee.Iterable<DataObject> items) {
- GPhoto.Result res = camera.init(spin_idle_context.context);
+ GPhoto.Result res = dcamera.gcamera.init(spin_idle_context.context);
if (res != GPhoto.Result.OK) {
AppWindow.error_message(_("Unable to lock camera: %s").printf(res.to_full_string()));
@@ -1712,14 +1692,14 @@ public class ImportPage : CheckerboardPage {
jobs.add(import_job);
}
- debug("Importing %d files from %s", jobs.size, camera_name);
+ debug("Importing %d files from %s", jobs.size, dcamera.display_name);
if (jobs.size > 0) {
// see import_reporter() to see why this is held during the duration of the import
assert(local_ref == null);
local_ref = this;
- BatchImport batch_import = new BatchImport(jobs, camera_name, import_reporter,
+ BatchImport batch_import = new BatchImport(jobs, dcamera.display_name, import_reporter,
null, already_imported);
batch_import.import_job_failed.connect(on_import_job_failed);
batch_import.import_complete.connect(close_import);
@@ -1811,7 +1791,7 @@ public class ImportPage : CheckerboardPage {
}
private void close_import() {
- GPhoto.Result res = camera.exit(spin_idle_context.context);
+ GPhoto.Result res = dcamera.gcamera.exit(spin_idle_context.context);
if (res != GPhoto.Result.OK) {
// log but don't fail
message("Unable to unlock camera: %s", res.to_full_string());