[Development] New API design for file system operations

Vitaly Fanaskov vitaly.fanaskov at qt.io
Mon Feb 11 16:07:06 CET 2019


Hi Volker,
The question for me is: why would an application (that is not a file explorer) want to do any of this? I honestly don’t see the use case.
I think in order to provide a user some useful information or suggest to perform some actions. For example, "moveToTrash" operation might fail for some reason. If you don't have a separate class for trash bin you can only report this error to a user, but neither fix a cause nor do something useful. For example, what if there is not enough space in the trash bin, or what if the trash bin configured to remove files without keeping them and so on... Wouldn't this sort of API useful for a developer who wants to use move-to-trash operation?

On 2/11/19 1:22 PM, Volker Hilsheimer wrote:
Hey Vitaly,

See inline.

On 11 Feb 2019, at 11:42, Vitaly Fanaskov <vitaly.fanaskov at qt.io<mailto:vitaly.fanaskov at qt.io>> wrote:
Making QFile::remove(bool toTrash=false); is tempting, but I think Thiago has a valid point about providing a dedicated file system operation abstraction, rather than cramming a mix of simple and complex file operations into QFile and QDir.
I agree that creating separate abstraction for file operations is an acceptable option. Although, I don't think that there is should be any difference between "simple"/"complex" or "long"/"short" or "atomic"/"non-atomic" operation in terms of user. As an API user I want to just perform some actions and don't care what is the under the hood; I also want all available operations to be presented in one place based on global classification feature (e.g., "file operation"). Of course, some things like "this is potentially long operation..." should be mentioned in the documentation.


Indeed, I don’t want application developers to have to use fundamentally different approaches based on the under-the-hood complexity of the operation. Either do it synchronously, and accept that the calling thread will be blocked; or do it asynchronously, and provide whatever plumbing you might need to have control over the process.

I see how my statement above can be misleading; what I wanted to say is that adding an “asynchronous file operations” design to QFile and QDir is cluttery, and instead of adding it there, I’d rather move *all* file system ops into a new class.


I also think that we should have a look into some options for file operations from C++ 17: https://en.cppreference.com/w/cpp/filesystem/copy_options . Something similar is worth adding to the new API.

Yes, absolutely.


A dedicated operations interface that can work with both QFile and QDir (but essentially only cares about file paths) would be nice; that doens’t mean we can’t keep a QFIle API for the simple stuff, ideally one that doesn’t accidentially block your UI event loop because the user selected a 5 GB file for copying.
But in this case, QFile and QDir interfaces should be shorten by removing some unnecessary methods. Ideally this operations interface should depend on paths only and shouldn't have any knowledge about QFile and QDir classes.

Agree that duplicate functionality in QDir and QFile should become deprecated.

Perhaps; overloads that QDir might make sense, as QDir could be seen as a class that operates on a string implementing path semantics in the context of the actual file system (e.g “cdUp” removes the last segment; cd(“foo”) adds “/foo” if foo exists). So, it provides perhaps at least input validation.

Hard to make a point for using QFile in the APIs though, at least not as input.


For the last point: Moving a file to a trash is something an application would want to do (for previous versions of saved files, for instance; for old save-games; for old downloads; for deleted workspaces etc); I absolutely see the usecases here. But I see no value in an API that provides comprehensive access to the system trash. Unless you use Qt to build a desktop environment or a file manager, you don’t need any of this. If you do the former, then you have done this already; hello KDE. If you do the latter, then that code should be in your app, and not in everyone’s Qt library.
Ok, I see your point. But imagine the situation when you need to restore a file from the trash, or get list of files in the trash, or check a space in the trash, or cleanup the trash... Wouldn't it be more convenient to have a separate class for all of this operations? In might be useful even if you have a separate operation for moving files to the trash, because you can make an operation undoable but the thing is that your program is not an exclusive owner of files. The trash bin can be re-created/moved/removed and so on. How would you locate your files in this case?


The question for me is: why would an application (that is not a file explorer) want to do any of this? I honestly don’t see the use case.


Cheers,
Volker



On 2/8/19 11:08 PM, Volker Hilsheimer wrote:
On 8 Feb 2019, at 10:43, Vitaly Fanaskov <vitaly.fanaskov at qt.io<mailto:vitaly.fanaskov at qt.io>> wrote:

On 2/7/19 5:03 PM, Volker Hilsheimer wrote:

Hi all,


TL;DR; we are considering moving file system operations from QFile into a seperate class (or set of classes) for a more consistent and flexible way of moving, copying etc files and directories.


The conversation around the design and implementation of an API to move file or directory to the trash in https://bugreports.qt.io/browse/QTBUG-47703 has during the last days moved somewhat beyond that rather straight-forward task, and has become a broader discussion around making file operations accessible outside of the existing set of classes.



[…]

Hi,

I've read QTBUG-47703 very carefully and I think that adding some file managers is overkill in this particular case. I would suggest the following changes:

  1.  Extract an abstract class (i.e., interface) for common file operations
  2.  Both QFile and QDir should implement this interface
  3.  Unify QDir API, e.g.,  QDir::remove -> QDir::removeFile, in order to match newly-extracted interface
  4.  Add a separate class which represents system trash bin and contains appropriate methods (e.g., functionality to check files inside, restore files, empty trash etc.)

Also in my point of view, it's not necessary to introduce a new method like "moveToTrash". We can extend method "remove" adding a new parameter that might be either a bool flag or some enum.

Hi Vitaly and Tor Arne,

Making QFile::remove(bool toTrash=false); is tempting, but I think Thiago has a valid point about providing a dedicated file system operation abstraction, rather than cramming a mix of simple and complex file operations into QFile and QDir.

Looking at the documentation, QFile is an interface for reading from and writing to files; QDir provides access to directory structures and their contents. I’d like it if they were simple interfaces focusing on those specific tasks.

But in addition, they provide a mix of file path operations (ie purely string operations), and a subset of operations that affect the file system. There’s some duplication, and little consistency. IIRC these classes have changed very little since Qt 1.

Unifying QFile and QDir around a common baseclass seems difficult. QFile is a QObject via QFileDevice and QIODevice; QDir is a copyable value type. Since you can point a QDir to a file, it’s perhaps closer to a value representing a file system entry. Making them both inherit an “operations” interface just to be able to remove either a file or a directory in the same way seems cluttery, esp given the ambitions for such an “operations” interface I’m lining out above (get progress updates, cancelable, transactions, batch jobs, run in a thread etc).

Adding such an interface would clutter those APIs, and require duplication in a lot of places. A dedicated operations interface that can work with both QFile and QDir (but essentially only cares about file paths) would be nice; that doens’t mean we can’t keep a QFIle API for the simple stuff, ideally one that doesn’t accidentially block your UI event loop because the user selected a 5 GB file for copying.


For the last point: Moving a file to a trash is something an application would want to do (for previous versions of saved files, for instance; for old save-games; for old downloads; for deleted workspaces etc); I absolutely see the usecases here. But I see no value in an API that provides comprehensive access to the system trash. Unless you use Qt to build a desktop environment or a file manager, you don’t need any of this. If you do the former, then you have done this already; hello KDE. If you do the latter, then that code should be in your app, and not in everyone’s Qt library.

Happy to be convinced otherwise.


Cheers,
Volker




--
Best Regards,

Fanaskov Vitaly
Senior Software Engineer

The Qt Company / Qt Quick and Widgets Team

_______________________________________________
Development mailing list
Development at qt-project.org<mailto:Development at qt-project.org>
https://lists.qt-project.org/listinfo/development


--
Best Regards,

Fanaskov Vitaly
Senior Software Engineer

The Qt Company / Qt Quick and Widgets Team
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20190211/37bbabf6/attachment.html>


More information about the Development mailing list