Fixed handling of burst image selected/key/default, closes #401 (again)
This commit is contained in:
@@ -209,4 +209,11 @@ EXTENDED_ATTRIBUTE_NAMES = [
|
||||
EXTENDED_ATTRIBUTE_NAMES_QUOTED = [f"'{x}'" for x in EXTENDED_ATTRIBUTE_NAMES]
|
||||
|
||||
# name of export DB
|
||||
OSXPHOTOS_EXPORT_DB = ".osxphotos_export.db"
|
||||
OSXPHOTOS_EXPORT_DB = ".osxphotos_export.db"
|
||||
|
||||
# bit flags for burst images ("burstPickType")
|
||||
BURST_NOT_SELECTED = 0b10 # 2: burst image is not selected
|
||||
BURST_DEFAULT_PICK = 0b100 # 4: burst image is the one Photos picked to be key image before any selections made
|
||||
BURST_SELECTED = 0b1000 # 8: burst image is selected
|
||||
BURST_KEY = 0b10000 # 16: burst image is the key photo (top of burst stack)
|
||||
BURST_UNKNOWN = 0b100000 # 32: this is almost always set with BURST_DEFAULT_PICK and never if BURST_DEFAULT_PICK is not set. I think this has something to do with what algorithm Photos used to pick the default image
|
||||
@@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.42.10"
|
||||
__version__ = "0.42.11"
|
||||
|
||||
@@ -26,6 +26,10 @@ from .._constants import (
|
||||
_PHOTOS_5_SHARED_ALBUM_KIND,
|
||||
_PHOTOS_5_SHARED_PHOTO_PATH,
|
||||
_PHOTOS_5_VERSION,
|
||||
BURST_DEFAULT_PICK,
|
||||
BURST_KEY,
|
||||
BURST_NOT_SELECTED,
|
||||
BURST_SELECTED,
|
||||
)
|
||||
from ..adjustmentsinfo import AdjustmentsInfo
|
||||
from ..albuminfo import AlbumInfo, ImportInfo
|
||||
@@ -455,16 +459,14 @@ class PhotoInfo:
|
||||
|
||||
@property
|
||||
def burst_albums(self):
|
||||
"""If photo is non-selected burst photo, list of albums any other images in the same burst set are contained in, otherwise returns self.albums"""
|
||||
if self.burst_selected or not self.burst:
|
||||
return self.albums
|
||||
|
||||
"""If photo is burst photo, list of albums it is contained in as well as any albums the key photo is contained in, otherwise returns self.albums """
|
||||
try:
|
||||
return self._burst_albums
|
||||
except AttributeError:
|
||||
burst_albums = []
|
||||
burst_albums = list(self.albums)
|
||||
for photo in self.burst_photos:
|
||||
burst_albums.extend(photo.albums)
|
||||
if photo.burst_key:
|
||||
burst_albums.extend(photo.albums)
|
||||
self._burst_albums = list(set(burst_albums))
|
||||
return self._burst_albums
|
||||
|
||||
@@ -482,16 +484,14 @@ class PhotoInfo:
|
||||
|
||||
@property
|
||||
def burst_album_info(self):
|
||||
""" If photo is a non-selected burst photo, returns list of AlbumInfo objects representing albums any other photos in the same burst set are contained in, otherwise returns self.album_info """
|
||||
if self.burst_selected or not self.burst:
|
||||
return self.album_info
|
||||
|
||||
""" If photo is a burst photo, returns list of AlbumInfo objects representing albums the photo is contained in as well as albums the burst key photo is contained in, otherwise returns self.album_info. """
|
||||
try:
|
||||
return self._burst_album_info
|
||||
except AttributeError:
|
||||
burst_album_info = []
|
||||
burst_album_info = list(self.album_info)
|
||||
for photo in self.burst_photos:
|
||||
burst_album_info.extend(photo.album_info)
|
||||
if photo.burst_key:
|
||||
burst_album_info.extend(photo.album_info)
|
||||
self._burst_album_info = list(set(burst_album_info))
|
||||
return self._burst_album_info
|
||||
|
||||
@@ -713,7 +713,17 @@ class PhotoInfo:
|
||||
@property
|
||||
def burst_selected(self):
|
||||
""" Returns True if photo is a burst photo and has been selected from the burst set by the user, otherwise False """
|
||||
return self._info["burst_key"]
|
||||
return bool(self._info["burstPickType"] & BURST_SELECTED)
|
||||
|
||||
@property
|
||||
def burst_key(self):
|
||||
""" Returns True if photo is a burst photo and is the key image for the burst set (the image that Photos shows on top of the burst stack), otherwise False """
|
||||
return bool(self._info["burstPickType"] & BURST_KEY)
|
||||
|
||||
@property
|
||||
def burst_default_pick(self):
|
||||
""" Returns True if photo is a burst image and is the photo that Photos selected as the default image for the burst set, otherwise False """
|
||||
return bool(self._info["burstPickType"] & BURST_DEFAULT_PICK)
|
||||
|
||||
@property
|
||||
def burst_photos(self):
|
||||
|
||||
@@ -1227,7 +1227,7 @@ class PhotoLibrary:
|
||||
|
||||
Args:
|
||||
burstid: str, burst UUID
|
||||
all: return all burst assets; if False returns only those selected by the user
|
||||
all: return all burst assets; if False returns only those selected by the user (including the "key photo" even if user hasn't manually selected it)
|
||||
|
||||
Returns:
|
||||
list of PhotoAsset objects
|
||||
|
||||
@@ -33,6 +33,8 @@ from .._constants import (
|
||||
_PHOTOS_5_SHARED_ALBUM_KIND,
|
||||
_TESTED_OS_VERSIONS,
|
||||
_UNKNOWN_PERSON,
|
||||
BURST_KEY,
|
||||
BURST_SELECTED,
|
||||
TIME_DELTA,
|
||||
)
|
||||
from .._version import __version__
|
||||
@@ -41,6 +43,7 @@ from ..datetime_utils import datetime_has_tz, datetime_naive_to_local
|
||||
from ..fileutil import FileUtil
|
||||
from ..personinfo import PersonInfo
|
||||
from ..photoinfo import PhotoInfo
|
||||
from ..queryoptions import QueryOptions
|
||||
from ..utils import (
|
||||
_check_file_exists,
|
||||
_db_is_locked,
|
||||
@@ -51,7 +54,6 @@ from ..utils import (
|
||||
noop,
|
||||
normalize_unicode,
|
||||
)
|
||||
from ..queryoptions import QueryOptions
|
||||
from .photosdb_utils import get_db_model_version, get_db_version
|
||||
|
||||
# TODO: Add test for imageTimeZoneOffsetSeconds = None
|
||||
@@ -1067,18 +1069,9 @@ class PhotosDB:
|
||||
if burst_uuid not in self._dbphotos_burst:
|
||||
self._dbphotos_burst[burst_uuid] = set()
|
||||
self._dbphotos_burst[burst_uuid].add(uuid)
|
||||
if row[24] != 2 and row[24] != 4:
|
||||
self._dbphotos[uuid][
|
||||
"burst_key"
|
||||
] = True # it's a key photo (selected from the burst)
|
||||
else:
|
||||
self._dbphotos[uuid][
|
||||
"burst_key"
|
||||
] = False # it's a burst photo but not one that's selected
|
||||
else:
|
||||
# not a burst photo
|
||||
self._dbphotos[uuid]["burst"] = False
|
||||
self._dbphotos[uuid]["burst_key"] = None
|
||||
|
||||
# RKVersion.specialType
|
||||
# 1 == panorama
|
||||
@@ -2010,18 +2003,9 @@ class PhotosDB:
|
||||
if burst_uuid not in self._dbphotos_burst:
|
||||
self._dbphotos_burst[burst_uuid] = set()
|
||||
self._dbphotos_burst[burst_uuid].add(uuid)
|
||||
if row[20] != 2 and row[20] != 4:
|
||||
info[
|
||||
"burst_key"
|
||||
] = True # it's a key photo (selected from the burst)
|
||||
else:
|
||||
info[
|
||||
"burst_key"
|
||||
] = False # it's a burst photo but not one that's selected
|
||||
else:
|
||||
# not a burst photo
|
||||
info["burst"] = False
|
||||
info["burst_key"] = None
|
||||
|
||||
# Info on sub-type (live photo, panorama, etc)
|
||||
# ZGENERICASSET.ZKINDSUBTYPE
|
||||
@@ -2787,7 +2771,10 @@ class PhotosDB:
|
||||
# get the intersection of each argument/search criteria
|
||||
for p in set.intersection(*photos_sets):
|
||||
# filter for non-selected burst photos
|
||||
if self._dbphotos[p]["burst"] and not self._dbphotos[p]["burst_key"]:
|
||||
if self._dbphotos[p]["burst"] and not (
|
||||
self._dbphotos[p]["burstPickType"] & BURST_SELECTED
|
||||
or self._dbphotos[p]["burstPickType"] & BURST_KEY
|
||||
):
|
||||
# not a key/selected burst photo, don't include in returned results
|
||||
continue
|
||||
|
||||
@@ -3234,4 +3221,3 @@ def _get_photos_by_attribute(photos, attribute, values, ignore_case):
|
||||
for x in values:
|
||||
photos_search.extend(p for p in photos if x in getattr(p, attribute))
|
||||
return photos_search
|
||||
|
||||
|
||||
Reference in New Issue
Block a user