Adds a Duplicate feature to Dolphin, showing up as a menu item in the File menu that appears when one or more items are selected and the directory is writable. Duplicated items receive the names of the original files with " copy" appended before the file extension, if any.
Details
- Delete or temporarily move aside ~/.local/share/kxmlgui5/dolphin/dolphinui.rc
- Launch Dolphin
- Select one item
- Ctrl+D or file > Duplicate Here or > right-click > Duplicate Here
- Try the above with multiple files selected
- Do it all again with different combinations of single and multiple files with various filename extensions
Diff Detail
- Repository
- R318 Dolphin
- Branch
- arcpatch-D8208
- Lint
No Linters Available - Unit
No Unit Test Coverage - Build Status
Buildable 20984 Build 21002: arc lint + arc unit
src/views/dolphinview.cpp | ||
---|---|---|
719 | using QFileInfo will break if the url is not a local file |
I think I could live without a warning message, if the item is named 'Duplicate here' (or 'Duplicate Here'?) to clarify that you shouldn't use it to get a duplicate elsewhere.
- Don't use QFileInfo
- Improve reliability of "copy" text appending with unusual filenames
- Add the action to the context menu
src/views/dolphinview.cpp | ||
---|---|---|
722 | Note that this returns a null QString if the extension isn't known and also doesn't preserve case. So currently this would happen: "test.foo" -> "test.foo"/ ""` -> "test.foo copy" |
@fvogt "test.foo" becoming "test.foo copy" is intentional because .foo isn't a known valid extension, and it's valid for files to have dots in their names. In general the approach of using QMimeDatabase supports this, solves the problems of using QFileInfo that @pino pointed out, and also allows seamless support for filename extensions with two dots in them (e.g. tar.gz).
If I go back to using QFileInfo to chop up the file into filename + extension, then there's the difficult choice of what kind of file to fail on: If I use QFileInfo::suffix(), it will fail for extensions with two dots like .tar.gz; if I use QFileInfo::completeSuffix(), that fails for files with dots in their names outside of the extension.
Each approach has drawbacks. Which would you find acceptable?
The case preserving issue is more severe than the issue with unknown extensions, so if that's fixed, using QMimeDatabase is IMO fine. Maybe with a fallback to completeSuffix if it didn't have an entry.
Why trying to append 'copy' in the base name whith possible headaches while you could simply do something like 'Copy N#1 of /original file name/' ?
The only thing to test would be if the filename starts with a dot and and keep it as first.
I can do that, sure. But IMO there's a UX problem when you append "Copy of" to the beginning rather than the end. Imagine that you have a file that starts with a Z and you duplicate it. The duplicate appears near the top of the window because it begins with C. If the current view is scrollable, view scrolls up to the top to show you the newly duplicated file. This causes you to lose your place in the view, which could be annoying if you were planning to do something else with another adjacent file or perform another operation on the original file (perhaps to duplicate it a second time to perform some A/B testing on two duplicates with slightly different changes, for example). For this reason, I prefer the macOS behavior of appending "copy" to the end of the filename, not to the beginning.
- Fix bug with copy being put in the wrong place for filenames with extensions
- Preserve existing filename extension casing
Hmm I don't think I should change the behaviour of QMimeDatabase after all.
https://lxr.kde.org/source/kde/kdeutils/ark/kerfuffle/createdialog.cpp#0106 does
const QString detectedSuffix = QMimeDatabase().suffixForFileName(fileName); if (currentMimeType().suffixes().contains(detectedSuffix)) {
which would break if case was preserved.
fileName.right(extension.size()) is exactly the way I almost-fixed this in Qt, so it's the right thing to do here instead :)
http://www.davidfaure.fr/kde/qt_preserve_case.diff for the record.
src/views/dolphinview.cpp | ||
---|---|---|
721 | This will behave wrong on /home/dfaure/Documents/dfaure You could just do const QString fileLocation = originalURL.path(QUrl::RemoveFilename); (I'd call it directoryPath btw, in QUrl terms it's a path) | |
726 | move it out of the loop | |
737 | It would be simpler to keep the dot here (then both this line and the previous one become simpler). |
src/views/dolphinview.cpp | ||
---|---|---|
733 ↗ | (On Diff #73304) | path(), not toString(). Or if you really want a full URL in there then call it directoryURL. It means reparsing the whole URL though, I thought we'd just copy the URL and change the path. |
738 ↗ | (On Diff #73304) | Why not just put the "." in the format string here? |
src/views/dolphinview.cpp | ||
---|---|---|
738 ↗ | (On Diff #73304) | Because then originalFileName.chopped(extension.size() includes the dot from the extension because extension doesn't already include it. |
Well, that depends on the current sorting mode, right? If I have sort-by-modified then the duplicate file will jump to the top of the view even if it has the "copy" suffix rather than the "Copy of" prefix, no?
Normally this shouldn't happen, since this uses CopyJob which preserves the mtime of the file.
If you prepend "Copy of," then it jumps around when you're sorting by Name or Creation Date.
If you append "copy," then it only jumps around when you're sorting by Creation Date.
Fair enough ;)
src/views/dolphinview.cpp | ||
---|---|---|
728 | Please add context for translators, explaining that %1 is a path. | |
732 | QLatin1String if you want to concatenate, QStringLiteral(".%1").arg(extension) otherwise. | |
735–737 | I'd call this variable originalExtension. | |
751 | What's this needed for? | |
753–754 | What's this connection needed for? | |
src/views/dolphinview.h | ||
374–375 | Where is the rename operation in this patch? |
src/views/dolphinview.cpp | ||
---|---|---|
751 | To make sure the new file(s) get selected after creation. |
I can't figure out how to make the rename operation work right now; see the FIXME: in the code. We can do it later in another patch, or else maybe someone could help me with it here.
I don't get why we want to start a rename operation at all, tbf.
Anyway, it doesn't seems to work for me. Can you update the test plan?
I'd say it's time to merge this patch since the 20.04 feature freeze is close.
Just a minor thing (see inline) and then you can push it.
src/views/dolphinview.cpp | ||
---|---|---|
752–757 ↗ | (On Diff #73304) | Since this doesn't work, I'd just remove it. (I still think that we don't need to trigger renaming in the first place). |