summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android
diff options
context:
space:
mode:
authorAssam Boudjelthia <assam.boudjelthia@qt.io>2022-11-22 14:06:33 +0200
committerAssam Boudjelthia <assam.boudjelthia@qt.io>2022-12-20 12:42:31 +0000
commitc1fa5d602c541b06e3e2fc2d02f5d62060c84504 (patch)
tree446e88c7271e9c30e5eacbf8e8d997fd92cf42f8 /src/plugins/platforms/android
parent30efb24d45e61f3329484c8dd416ee6cde25739b (diff)
Android: handle rename() operation with content uris
Allow renaming content uris if the destination is provided as a direct fileName (i.e. not full content scheme path), and if the destination has the same trailing path (or parent) which means a rename in the same folder structure. Pick-to: 6.5 6.4 6.2 Task-number: QTBUG-98974 Change-Id: Ibc4973366807dd5284c19912ab04ff90f2a573cb Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
Diffstat (limited to 'src/plugins/platforms/android')
-rw-r--r--src/plugins/platforms/android/androidcontentfileengine.cpp56
-rw-r--r--src/plugins/platforms/android/androidcontentfileengine.h2
2 files changed, 58 insertions, 0 deletions
diff --git a/src/plugins/platforms/android/androidcontentfileengine.cpp b/src/plugins/platforms/android/androidcontentfileengine.cpp
index 0f06e2bee1..73f910d511 100644
--- a/src/plugins/platforms/android/androidcontentfileengine.cpp
+++ b/src/plugins/platforms/android/androidcontentfileengine.cpp
@@ -112,6 +112,15 @@ bool AndroidContentFileEngine::remove()
return m_documentFile->remove();
}
+bool AndroidContentFileEngine::rename(const QString &newName)
+{
+ if (m_documentFile->rename(newName)) {
+ m_initialFile = m_documentFile->uri().toString();
+ return true;
+ }
+ return false;
+}
+
bool AndroidContentFileEngine::mkdir(const QString &dirName, bool createParentDirectories,
std::optional<QFileDevice::Permissions> permissions) const
{
@@ -433,6 +442,7 @@ const QLatin1String COLUMN_SIZE("_size");
constexpr int FLAG_DIR_SUPPORTS_CREATE = 0x00000008;
constexpr int FLAG_SUPPORTS_DELETE = 0x00000004;
+constexpr int FLAG_SUPPORTS_RENAME = 0x00000040;
constexpr int FLAG_SUPPORTS_WRITE = 0x00000002;
constexpr int FLAG_VIRTUAL_DOCUMENT = 0x00000200;
@@ -516,6 +526,19 @@ bool deleteDocument(const QJniObject &documentUri)
documentUri.object());
}
+QJniObject renameDocument(const QJniObject &documentUri, const QString &displayName)
+{
+ const int flags = Cursor::queryColumn(documentUri, Document::COLUMN_FLAGS).toInt();
+ if (!(flags & Document::FLAG_SUPPORTS_RENAME))
+ return {};
+
+ return QJniObject::callStaticObjectMethod("android/provider/DocumentsContract",
+ "renameDocument",
+ "(Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;)Landroid/net/Uri;",
+ contentResolverInstance().object(),
+ documentUri.object(),
+ QJniObject::fromString(displayName).object());
+}
} // End DocumentsContract namespace
// Start of DocumentFile
@@ -735,4 +758,37 @@ std::vector<DocumentFilePtr> DocumentFile::listFiles()
return res;
}
+bool DocumentFile::rename(const QString &newName)
+{
+ QJniObject uri;
+ if (newName.startsWith("content://"_L1)) {
+ auto lastSeparatorIndex = [](const QString &file) {
+ int posDecoded = file.lastIndexOf("/");
+ int posEncoded = file.lastIndexOf(QUrl::toPercentEncoding("/"));
+ return posEncoded > posDecoded ? posEncoded : posDecoded;
+ };
+
+ // first try to see if the new file is under the same tree and thus used rename only
+ const QString parent = m_uri.toString().left(lastSeparatorIndex(m_uri.toString()));
+ if (newName.contains(parent)) {
+ QString displayName = newName.mid(lastSeparatorIndex(newName));
+ if (displayName.startsWith('/'))
+ displayName.remove(0, 1);
+ else if (displayName.startsWith(QUrl::toPercentEncoding("/")))
+ displayName.remove(0, 3);
+
+ uri = renameDocument(m_uri, displayName);
+ }
+ } else {
+ uri = renameDocument(m_uri, newName);
+ }
+
+ if (uri.isValid()) {
+ m_uri = uri;
+ return true;
+ }
+
+ return false;
+}
+
// End of DocumentFile
diff --git a/src/plugins/platforms/android/androidcontentfileengine.h b/src/plugins/platforms/android/androidcontentfileengine.h
index 439a23a664..56d9bae8f7 100644
--- a/src/plugins/platforms/android/androidcontentfileengine.h
+++ b/src/plugins/platforms/android/androidcontentfileengine.h
@@ -19,6 +19,7 @@ public:
bool close() override;
qint64 size() const override;
bool remove() override;
+ bool rename(const QString &newName) override;
bool mkdir(const QString &dirName, bool createParentDirectories,
std::optional<QFile::Permissions> permissions = std::nullopt) const override;
bool rmdir(const QString &dirName, bool recurseParentDirectories) const override;
@@ -91,6 +92,7 @@ public:
bool remove();
bool exists() const;
std::vector<DocumentFilePtr> listFiles();
+ bool rename(const QString &newName);
protected:
DocumentFile(const QJniObject &uri, const std::shared_ptr<DocumentFile> &parent);