From 5ecfcf693510696eeccb13a04cbc63635a299dd6 Mon Sep 17 00:00:00 2001 From: Gary Wang Date: Tue, 30 Jul 2019 20:19:53 +0800 Subject: [PATCH] feat: file iterator async support ( #8 ) --- gio-qt/include/dgiofile.h | 4 +++ gio-qt/include/dgiofileiterator.h | 42 ++++++++++++++++++++++++++++++ gio-qt/source/dgiofile.cpp | 31 ++++++++++++++++++++-- gio-qt/source/dgiofileiterator.cpp | 40 +++++++++++++++++++++++++++- qgio-tools/main.cpp | 33 +++++++++++++++++++++++ 5 files changed, 147 insertions(+), 3 deletions(-) diff --git a/gio-qt/include/dgiofile.h b/gio-qt/include/dgiofile.h index 1bcac53..6bb8041 100644 --- a/gio-qt/include/dgiofile.h +++ b/gio-qt/include/dgiofile.h @@ -34,6 +34,10 @@ public: QString uri() const; QExplicitlySharedDataPointer createFileSystemInfo(); QExplicitlySharedDataPointer createFileIterator(QString attr = "*", DGioFileQueryInfoFlags queryInfoFlags = FILE_QUERY_INFO_NONE); + void createFileIteratorAsync(QString attr = "*", DGioFileQueryInfoFlags queryInfoFlags = FILE_QUERY_INFO_NONE); + +Q_SIGNALS: + void createFileIteratorReady(QExplicitlySharedDataPointer iter); private: QScopedPointer d_ptr; diff --git a/gio-qt/include/dgiofileiterator.h b/gio-qt/include/dgiofileiterator.h index 08006af..0232971 100644 --- a/gio-qt/include/dgiofileiterator.h +++ b/gio-qt/include/dgiofileiterator.h @@ -8,6 +8,43 @@ namespace Gio { class FileEnumerator; } +enum DGioIOPriority +{ + /*! Use this for high priority event sources. It is not used within + * GLib or GTK+.

+ */ + PRIORITY_HIGH = -100, + + /*! Use this for default priority event sources. In glibmm this + * priority is used by default when installing timeout handlers with + * SignalTimeout::connect(). In GDK this priority is used for events + * from the X server.

+ */ + PRIORITY_DEFAULT = 0, + + /*! Use this for high priority idle functions. GTK+ uses + * PRIORITY_HIGH_IDLE + 10 for resizing operations, and + * PRIORITY_HIGH_IDLE + 20 for redrawing operations. + * (This is done to ensure that any pending resizes are processed before + * any pending redraws, so that widgets are not redrawn twice unnecessarily.) + *

+ */ + PRIORITY_HIGH_IDLE = 100, + + /*! Use this for default priority idle functions. In glibmm this priority is + * used by default when installing idle handlers with SignalIdle::connect(). + *

+ */ + PRIORITY_DEFAULT_IDLE = 200, + + /*! Use this for very low priority background tasks. It is not used within + * GLib or GTK+. + */ + PRIORITY_LOW = 300 +}; + +Q_ENUMS(DGioIOPriority); + class DGioFileInfo; class DGioFileIteratorPrivate; class DGioFileIterator : public QObject, public QSharedData @@ -18,6 +55,11 @@ public: ~DGioFileIterator(); QExplicitlySharedDataPointer nextFile(); + void nextFilesAsync(int numberOfFiles = 1, DGioIOPriority io_priority = PRIORITY_DEFAULT); + +Q_SIGNALS: + void nextFilesReady(QList > fileInfoList); + void nextFilesCancelled(); private: QScopedPointer d_ptr; diff --git a/gio-qt/source/dgiofile.cpp b/gio-qt/source/dgiofile.cpp index 31ea5f6..a995a13 100644 --- a/gio-qt/source/dgiofile.cpp +++ b/gio-qt/source/dgiofile.cpp @@ -26,6 +26,8 @@ private: DGioFile *q_ptr; + void slot_enumerateChildrenAsyncResult(const Glib::RefPtr& result); + Q_DECLARE_PUBLIC(DGioFile) }; @@ -46,6 +48,20 @@ QString DGioFilePrivate::uri() const return QString::fromStdString(m_gmmFilePtr->get_uri()); } +void DGioFilePrivate::slot_enumerateChildrenAsyncResult(const Glib::RefPtr &result) +{ + Q_Q(DGioFile); + + try { + Glib::RefPtr iter = m_gmmFilePtr->enumerate_children_finish(result); + QExplicitlySharedDataPointer fileIterPtr(new DGioFileIterator(iter.release())); + + Q_EMIT q->createFileIteratorReady(fileIterPtr); + } catch (const Glib::Error & error) { + qDebug() << QString::fromStdString(error.what().raw()); + } +} + // ------------------------------------------------------------- DGioFile::DGioFile(File* gmmFilePtr, QObject *parent) @@ -168,9 +184,10 @@ QExplicitlySharedDataPointer DGioFile::createFileIterator(QStr { Q_D(DGioFile); + unsigned int flagValue = queryInfoFlags; + FileQueryInfoFlags flags = static_cast(flagValue); + try { - unsigned int flagValue = queryInfoFlags; - FileQueryInfoFlags flags = static_cast(flagValue); Glib::RefPtr gmmFileEnumerator = d->getGmmFileInstance()->enumerate_children(attr.toStdString(), flags); QExplicitlySharedDataPointer fileIterPtr(new DGioFileIterator(gmmFileEnumerator.release())); @@ -181,3 +198,13 @@ QExplicitlySharedDataPointer DGioFile::createFileIterator(QStr return QExplicitlySharedDataPointer(nullptr); } + +void DGioFile::createFileIteratorAsync(QString attr, DGioFileQueryInfoFlags queryInfoFlags) +{ + Q_D(DGioFile); + + unsigned int flagValue = queryInfoFlags; + FileQueryInfoFlags flags = static_cast(flagValue); + d->getGmmFileInstance()->enumerate_children_async(sigc::mem_fun(d, &DGioFilePrivate::slot_enumerateChildrenAsyncResult), + attr.toStdString(), flags); +} diff --git a/gio-qt/source/dgiofileiterator.cpp b/gio-qt/source/dgiofileiterator.cpp index 43f9b26..063eb0f 100644 --- a/gio-qt/source/dgiofileiterator.cpp +++ b/gio-qt/source/dgiofileiterator.cpp @@ -1,6 +1,7 @@ -#include "dgiofileiterator.h" +#include "dgiofileiterator.h" #include "dgiofileinfo.h" +#include #include #include @@ -22,6 +23,8 @@ private: DGioFileIterator *q_ptr; + void slot_nextFileAsyncResult(const Glib::RefPtr& result); + Q_DECLARE_PUBLIC(DGioFileIterator) }; @@ -37,6 +40,32 @@ Glib::RefPtr DGioFileIteratorPrivate::getGmmFileEnumeratorInstan return m_gmmFileEnumeratorPtr; } +void DGioFileIteratorPrivate::slot_nextFileAsyncResult(const Glib::RefPtr &result) +{ + Q_Q(DGioFileIterator); + + try { + Glib::ListHandle< Glib::RefPtr > files = m_gmmFileEnumeratorPtr->next_files_finish(result); + QList > fileInfoList; + + for (auto gmmFileInfoPtr : files) { + QExplicitlySharedDataPointer info(new DGioFileInfo(gmmFileInfoPtr.release())); + fileInfoList.append(info); + } + + Q_EMIT q->nextFilesReady(fileInfoList); + } catch (const Gio::Error& error) { + if (error.code() != Gio::Error::CANCELLED) { + Q_EMIT q->nextFilesCancelled(); + } else { + // should we add an error signal? + qDebug() << QString::fromStdString(error.what().raw()); + } + } catch (const Glib::Error& error) { + // should we add an error signal? + qDebug() << QString::fromStdString(error.what().raw()); + } +} // ------------------------------------------------------------- @@ -70,3 +99,12 @@ QExplicitlySharedDataPointer DGioFileIterator::nextFile() return QExplicitlySharedDataPointer(nullptr); } + +void DGioFileIterator::nextFilesAsync(int numberOfFiles, DGioIOPriority io_priority) +{ + Q_D(DGioFileIterator); + + + d->getGmmFileEnumeratorInstance()->next_files_async(sigc::mem_fun(d, &DGioFileIteratorPrivate::slot_nextFileAsyncResult), + numberOfFiles, io_priority); +} diff --git a/qgio-tools/main.cpp b/qgio-tools/main.cpp index a55d1bf..8f43f1c 100644 --- a/qgio-tools/main.cpp +++ b/qgio-tools/main.cpp @@ -26,6 +26,39 @@ int main(int argc, char * argv[]) } } } + delete networkFile; + } + +// // Can't do asynchronous next_files() on a file enumerator created synchronously +// DGioFile *recentFile1 = DGioFile::createFromUri("recent:///"); +// QExplicitlySharedDataPointer iter1; +// if (recentFile1) { +// iter1 = recentFile1->createFileIterator("standard::*"); +// if (iter1) { +// iter1->nextFilesAsync(5); +// QObject::connect(iter1.data(), &DGioFileIterator::nextFilesReady, [](QList > fileInfoList){ +// for (auto fi : fileInfoList) { +// qDebug() << "xxxxxx" << fi->displayName() << fi->fileType(); +// } +// }); +// } +// } + + DGioFile *recentFile = DGioFile::createFromUri("recent:///"); + QExplicitlySharedDataPointer iter; + if (recentFile) { + recentFile->createFileIteratorAsync("standard::*"); + QObject::connect(recentFile, &DGioFile::createFileIteratorReady, [&iter](QExplicitlySharedDataPointer iterr){ + iter = iterr; + if (iter) { + iter->nextFilesAsync(5); + QObject::connect(iter.data(), &DGioFileIterator::nextFilesReady, [](QList > fileInfoList){ + for (auto fi : fileInfoList) { + qDebug() << "under recent:" << fi->displayName() << fi->fileType(); + } + }); + } + }); } qDebug() << "----------------------";