diff --git a/data/gtk/properties_view.ui b/data/gtk/properties_view.ui
index fd5b31d2241129bcb09028cce02653dc141aa8fa..15e7c359982b457314ccfe46cf9aaeebb6b71c2b 100644
--- a/data/gtk/properties_view.ui
+++ b/data/gtk/properties_view.ui
@@ -113,19 +113,31 @@
- Location
- location_button
+ Originally Created
-
+
LpPropertiesView
-
+
LpPropertiesView
-
-
- center
- properties.open-location
- mark-location-symbolic
- Open Location
-
-
-
@@ -245,15 +245,15 @@
- Camera
+ Maker, Model
-
+
LpPropertiesView
-
+
LpPropertiesView
diff --git a/src/image_metadata/gps.rs b/src/image_metadata/gps.rs
index 93f30285cebfc4ce24965595597ad2e2be1059a8..35cdea5ec5593e025be5c779c74c28212c9eaedc 100644
--- a/src/image_metadata/gps.rs
+++ b/src/image_metadata/gps.rs
@@ -1,3 +1,5 @@
+use crate::i18n::*;
+
#[derive(Debug, Clone, Copy)]
pub struct GPSLocation {
pub latitude: GPSCoord,
@@ -53,10 +55,24 @@ impl GPSCoord {
}
fn position_exif(position: &[exif::Rational]) -> Option<(f64, Option, Option)> {
+ let (deg, mut min, mut sec) = (position.get(0)?, position.get(1), position.get(2));
+
+ if let (Some(min_), Some(sec_)) = (min, sec) {
+ if min_.denom > 1 && sec_.num == 0 {
+ sec = None;
+ }
+ }
+
+ if let Some(min_) = min {
+ if deg.denom > 1 && min_.num == 0 {
+ min = None;
+ }
+ }
+
Some((
- position.get(0).map(exif::Rational::to_f64)?,
- position.get(1).map(exif::Rational::to_f64),
- position.get(2).map(exif::Rational::to_f64),
+ deg.to_f64(),
+ min.map(exif::Rational::to_f64),
+ sec.map(exif::Rational::to_f64),
))
}
}
@@ -93,8 +109,19 @@ impl GPSLocation {
pub fn display(&self) -> String {
if let Some(world) = libgweather::Location::world() {
let location = world.find_nearest_city(self.latitude.to_f64(), self.longitude.to_f64());
- if let (Some(city), Some(country)) = (location.city_name(), location.country_name()) {
- return format!("{city}, {country}");
+ let location_exact = libgweather::Location::new_detached(
+ "",
+ None,
+ self.latitude.to_f64(),
+ self.longitude.to_f64(),
+ );
+
+ // do not use city if more than 100 km away
+ if location.distance(&location_exact) < 100. {
+ if let (Some(city), Some(country)) = (location.city_name(), location.country_name())
+ {
+ return format!("{city}, {country}");
+ }
}
}
@@ -104,16 +131,28 @@ impl GPSLocation {
pub fn latitude_display(&self) -> String {
let coord = self.latitude;
- let reference = if coord.sing { "N" } else { "S" };
+ let reference = if coord.sing {
+ // Translators: short for "north" in GPS coordiante
+ i18n("N")
+ } else {
+ // Translators: short for "south" in GPS coordiante
+ i18n("S")
+ };
- coord.display(reference)
+ coord.display(&reference)
}
pub fn longitude_display(&self) -> String {
let coord = self.longitude;
- let reference = if coord.sing { "E" } else { "W" };
+ let reference = if coord.sing {
+ // Translators: short for "east" in GPS coordiante
+ i18n("E")
+ } else {
+ // Translators: short for "west" in GPS coordiante
+ i18n("W")
+ };
- coord.display(reference)
+ coord.display(&reference)
}
pub fn geo_uri(&self) -> String {
diff --git a/src/image_metadata/mod.rs b/src/image_metadata/mod.rs
index c4c9d1c20fb4caab521f42b07d213d3777b8849f..6f760a027d8b56e42b1f96c50df4605a47b06070 100644
--- a/src/image_metadata/mod.rs
+++ b/src/image_metadata/mod.rs
@@ -162,7 +162,25 @@ impl ImageMetadata {
None
}
- pub fn camera_model(&self) -> Option {
+ /// Combined maker and model info
+ pub fn maker_model(&self) -> Option {
+ if let Some(mut model) = self.model() {
+ if let Some(maker) = self.maker() {
+ // This is to avoid doubling the maker name
+ // Canon for example also puts "Canon" in the model as well
+ // NIKON sometimes puts "NIKON" in model and "NIKON CORPORATION" in maker
+ if model.split_whitespace().next() != maker.split_whitespace().next() {
+ model = format!("{maker} {model}");
+ }
+ }
+
+ Some(model)
+ } else {
+ self.maker()
+ }
+ }
+
+ pub fn model(&self) -> Option {
if let Self::Exif(exif) = self {
if let Some(field) = exif.get_field(exif::Tag::Model, exif::In::PRIMARY) {
if let exif::Value::Ascii(value) = &field.value {
@@ -176,6 +194,20 @@ impl ImageMetadata {
None
}
+ pub fn maker(&self) -> Option {
+ if let Self::Exif(exif) = self {
+ if let Some(field) = exif.get_field(exif::Tag::Make, exif::In::PRIMARY) {
+ if let exif::Value::Ascii(value) = &field.value {
+ if let Some(entry) = value.first() {
+ return Some(String::from_utf8_lossy(entry).to_string());
+ }
+ }
+ }
+ }
+
+ None
+ }
+
pub fn gps_location(&self) -> Option {
if let Self::Exif(exif) = self {
if let (Some(latitude), Some(latitude_ref), Some(longitude), Some(longitude_ref)) = (
diff --git a/src/image_metadata/obj.rs b/src/image_metadata/obj.rs
index 434943a1db3ac89b9b9488cef0501ccb3100d538..8c961e2f4ef98aa3788b86830208c4f252f6e544 100644
--- a/src/image_metadata/obj.rs
+++ b/src/image_metadata/obj.rs
@@ -75,7 +75,7 @@ mod imp {
"exposure-time",
"iso",
"focal-length",
- "camera-model",
+ "maker-model",
]
.iter()
.map(|name| glib::ParamSpecString::builder(name).read_only().build())
@@ -99,7 +99,7 @@ mod imp {
"exposure-time" => metadata.exposure_time().to_value(),
"iso" => metadata.iso().to_value(),
"focal-length" => metadata.focal_length().to_value(),
- "camera-model" => metadata.camera_model().to_value(),
+ "maker-model" => metadata.maker_model().to_value(),
name => unimplemented!("property {name}"),
}
}