7#import <AssetsLibrary/AssetsLibrary.h>
9#include <QtCore/QTimer>
10#include <QtCore/private/qcoreapplication_p.h>
11#include <QtCore/qurl.h>
12#include <QtCore/qset.h>
13#include <QtCore/qthreadstorage.h>
14#include <QtCore/qfileselector.h>
28 if ([ALAssetsLibrary authorizationStatus] != ALAuthorizationStatusNotDetermined)
34 if ([NSThread isMainThread]) {
44 NSLog(
@"QIOSFileEngine: unable to show assets authorization dialog from non-gui thread before QApplication is executing.");
57 : m_semWriteAsset(dispatch_semaphore_create(
kBufferSize))
58 , m_semReadAsset(dispatch_semaphore_create(0))
60 , m_assetsLibrary([assetsLibrary retain])
65 , m_nextAssetReady(
false)
84 dispatch_semaphore_signal(m_semWriteAsset);
85 dispatch_release(m_semReadAsset);
86 dispatch_release(m_semWriteAsset);
88 [m_assetsLibrary autorelease];
93 if (!m_nextAssetReady) {
94 dispatch_semaphore_wait(m_semReadAsset, DISPATCH_TIME_FOREVER);
95 m_nextAssetReady =
true;
97 return m_buffer[m_readIndex] !=
kNoAsset;
105 ALAsset *asset = [m_buffer[m_readIndex] autorelease];
106 dispatch_semaphore_signal(m_semWriteAsset);
109 m_nextAssetReady =
false;
114 dispatch_semaphore_t m_semWriteAsset;
115 dispatch_semaphore_t m_semReadAsset;
116 std::atomic_bool m_stop;
118 ALAssetsLibrary *m_assetsLibrary;
119 ALAssetsGroupType m_type;
123 bool m_nextAssetReady;
125 void writeAsset(ALAsset *asset)
127 dispatch_semaphore_wait(m_semWriteAsset, DISPATCH_TIME_FOREVER);
128 m_buffer[m_writeIndex] = [asset retain];
129 dispatch_semaphore_signal(m_semReadAsset);
133 void startEnumerate()
135 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
136 [m_assetsLibrary enumerateGroupsWithTypes:m_type usingBlock:^(ALAssetsGroup *
group, BOOL *stopEnumerate) {
144 *stopEnumerate =
true;
150 if (!asset || ![[asset valueForProperty:ALAssetPropertyType]
isEqual:ALAssetTypePhoto])
154 *stopEnumerate = m_stop;
156 } failureBlock:^(NSError *
error) {
157 NSLog(
@"QIOSFileEngine: %@",
error);
172 , m_assetUrl(assetUrl)
183 if (assetData->m_assetUrl == assetUrl) {
184 m_assetLibrary = [assetData->m_assetLibrary retain];
185 m_asset = [assetData->m_asset retain];
195 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
197 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
198 NSURL *
url = [NSURL URLWithString:assetUrl.toNSString()];
199 m_assetLibrary = [[ALAssetsLibrary alloc]
init];
200 [m_assetLibrary assetForURL:
url resultBlock:^(ALAsset *asset) {
208 while (
e.hasNext()) {
209 ALAsset *
a =
e.next();
211 if (
url == assetUrl) {
222 dispatch_semaphore_signal(semaphore);
223 } failureBlock:^(NSError *
error) {
225 dispatch_semaphore_signal(semaphore);
229 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
230 dispatch_release(semaphore);
247 ALAssetsLibrary *m_assetLibrary;
252#ifndef QT_NO_FILESYSTEMITERATOR
279 QString url = QUrl::fromNSURL([asset valueForProperty:ALAssetPropertyAssetURL]).
toString();
316ALAsset *QIOSFileEngineAssetsLibrary::loadAsset()
const
324 std::optional<QFile::Permissions> permissions)
346 QAbstractFileEngine::FileFlags
flags;
347 const bool isDir = (m_assetUrl ==
"assets-library://"_L1);
350 static const auto selectors = fileSelector.
allSelectors();
351 if (m_assetUrl.
startsWith(
"assets-library://"_L1)) {
352 for (
const auto &
selector : selectors) {
367 ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
368 if (status != ALAuthorizationStatusRestricted && status != ALAuthorizationStatusDenied)
379 if (ALAsset *asset = loadAsset())
380 return [[asset defaultRepresentation]
size];
386 ALAsset *asset = loadAsset();
394 NSError *
error =
nullptr;
395 [[asset defaultRepresentation] getBytes:(uint8_t *)
data fromOffset:m_offset
length:bytesRead
error:&
error];
402 m_offset += bytesRead;
435 m_assetUrl =
"assets-library://"_L1;
437 m_assetUrl =
"assets-library:/"_L1 +
file.mid(
index);
440#ifndef QT_NO_FILESYSTEMITERATOR
static bool isEqual(const aiUVTransform &a, const aiUVTransform &b)
The QAbstractFileEngineIterator class provides an iterator interface for custom file engines.
QDir::Filters filters() const
Returns the entry filters for this iterator.
virtual QString next()=0
This pure virtual function advances the iterator to the next directory entry, and returns the file pa...
virtual bool hasNext() const =0
This pure virtual function returns true if there is at least one more entry in the current directory ...
virtual QString currentFileName() const =0
This pure virtual function returns the name of the current directory entry, excluding the path.
QStringList nameFilters() const
Returns the name filters for this iterator.
virtual QFileInfo currentFileInfo() const
The virtual function returns a QFileInfo for the current directory entry.
FileName
These values are used to request a file name in a particular format.
QFile::FileError error() const
Returns the QFile::FileError that resulted from the last failed operation.
int exec(ProcessEventsFlags flags=AllEvents)
Enters the main event loop and waits until exit() is called.
void quit()
Tells the event loop to exit normally.
\inmodule QtCore \reentrant
QStringList allSelectors() const
Returns the complete, ordered list of selectors used by this instance.
QIOSAssetData(const QString &assetUrl, QIOSFileEngineAssetsLibrary *engine)
QIOSAssetEnumerator(ALAssetsLibrary *assetsLibrary, ALAssetsGroupType type)
~QIOSFileEngineAssetsLibrary()
QString fileName(FileName file) const override
Return the file engine's current file name in the format specified by file.
void setError(QFile::FileError error, const QString &str)
bool open(QIODevice::OpenMode openMode, std::optional< QFile::Permissions > permissions) override
Opens the file in the specified mode.
qint64 pos() const override
Returns the current file position.
void setFileName(const QString &file) override
Sets the file engine's file name to file.
Iterator * beginEntryList(QDir::Filters filters, const QStringList &filterNames) override
Returns an instance of a QAbstractFileEngineIterator using filters for entry filtering and filterName...
Iterator * endEntryList() override
bool seek(qint64 pos) override
Sets the file position to the given offset.
FileFlags fileFlags(FileFlags type) const override
This function should return the set of OR'd flags that are true for the file engine's file,...
qint64 read(char *data, qint64 maxlen) override
Reads a number of characters from the file into data.
qint64 size() const override
Returns the size of the file.
QIOSFileEngineAssetsLibrary(const QString &fileName)
bool close() override
Closes the file, returning true if successful; otherwise returns false.
QIOSAssetEnumerator * m_enumerator
static QObjectPrivate * get(QObject *o)
void deleteLater()
\threadsafe
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
bool singleShot
whether the timer is a single-shot timer
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
static bool ensureAuthorizationDialogNotBlocked()
static const int kBufferSize
static QThreadStorage< QString > g_iteratorCurrentUrl
static QThreadStorage< QPointer< QIOSAssetData > > g_assetDataCache
static ALAsset * kNoAsset
constexpr const T & qMin(const T &a, const T &b)
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLenum GLsizei length
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
QFileSelector selector
[1]
QUrl url("example.com")
[constructor-url-reference]
const QStringList filters({"Image files (*.png *.xpm *.jpg)", "Text files (*.txt)", "Any files (*)" })
[6]
char * toString(const MyType &t)
[31]