Improve screenshot path handling (#1815)

* Make --path work correctly with relative paths

Relative paths are taken relative to the working directory of the calling
command, not relative to the daemon's working directory.

* Allow file paths in --path and refactor

* Remove some redundancy

These actions are already performed in the respective functions in
FlameshotDBusAdapter.

* Tweak --path error checker a bit more

* Rework FileNameHandler and update references

The class now has a much simpler interface.

- Screenshot paths are now universally determined by the function
  properScreenshotPath
- Some unreferenced methods have been removed
- The documentation of properScreenshotPath documents the changes well.

* Add crude tests for --path

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix failing build on Windows

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Add a test for invalid path

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Make tests clearer

Thanks to @mmahmoudian for his review and contribution.

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fix bug in properScreenshotPath

Auto-numeration did not work when the screenshot was automatically
saved when copied to clipboard.

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Fall back to default pictures location

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Revert "Remove some redundancy"

This was not redundancy. I had actually introduced a bug with this.

This reverts commit 011ef737564892e494518443e6b80ccf3d286ae1.

* Change default path only on interactive save

Previously, the default save path was changed every time a screenshot
was saved. Now, that only happens when it gets saved from the GUI.

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Change --path help text

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>

* Allow other image formats

Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>
This commit is contained in:
Haris Gušić
2021-08-20 20:10:12 +02:00
committed by GitHub
parent 584bcd7f6c
commit 41ca51bc10
14 changed files with 147 additions and 93 deletions

View File

@@ -5,7 +5,6 @@
#include "src/utils/confighandler.h"
#include "src/utils/strfparse.h"
#include <QDir>
#include <QStandardPaths>
#include <ctime>
#include <exception>
#include <locale>
@@ -52,65 +51,75 @@ QString FileNameHandler::parseFilename(const QString& name)
return res;
}
QString FileNameHandler::generateAbsolutePath(const QString& path)
/**
* @brief Generate a valid destination path from the possibly incomplete `path`.
* The input `path` can be one of:
* - empty string
* - an existing directory
* - a file in an existing directory
* In each case, the output path will be an absolute path to a file with a
* suffix matching the specified `format`.
* @note
* - If `path` points to a directory, the file name will be generated from the
* formatted file name from the user configuration
* - If `path` points to a file, its suffix will be changed to match `format`
* - If `format` is not given, the suffix will remain untouched, unless `path`
* has no suffix, in which case it will be given the "png" suffix
* - If the path generated by the previous steps points to an existing file,
* "_NUM" will be appended to its base name, where NUM is the first
* available number that produces a non-existent path (starting from 1).
* @param path Possibly incomplete file name to transform
* @param format Desired output file suffix (excluding an initial '.' character)
*/
QString FileNameHandler::properScreenshotPath(QString path,
const QString& format)
{
QString directory = path;
QString filename = parsedPattern();
fixPath(directory, filename);
return directory + filename;
}
// path a images si no existe, add numeration
void FileNameHandler::setPattern(const QString& pattern)
{
ConfigHandler().setFilenamePattern(pattern);
}
QFileInfo info(path);
QString suffix = info.suffix();
QString FileNameHandler::absoluteSavePath(QString& directory, QString& filename)
{
ConfigHandler config;
directory = config.savePath();
if (directory.isEmpty() || !QDir(directory).exists() ||
!QFileInfo(directory).isWritable()) {
directory =
QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
if (info.isDir()) {
// path is a directory => generate filename from configured pattern
path = QDir(QDir(path).absolutePath() + "/" + parsedPattern()).path();
} else {
// path points to a file => strip it of its suffix for now
path = QDir(info.dir().absolutePath() + "/" + info.completeBaseName())
.path();
}
filename = parsedPattern();
fixPath(directory, filename);
return directory + filename;
}
QString FileNameHandler::absoluteSavePath()
{
QString dir, file;
return absoluteSavePath(dir, file);
}
QString FileNameHandler::charArrToQString(const char* c)
{
return QString::fromLocal8Bit(c, MAX_CHARACTERS);
}
char* FileNameHandler::QStringToCharArr(const QString& s)
{
QByteArray ba = s.toLocal8Bit();
return const_cast<char*>(strdup(ba.constData()));
}
void FileNameHandler::fixPath(QString& directory, QString& filename)
{
// add '/' at the end of the directory
if (!directory.endsWith(QLatin1String("/"))) {
directory += QLatin1String("/");
if (!format.isEmpty()) {
// Override suffix to match format
path += "." + format;
} else if (!suffix.isEmpty()) {
// Leave the suffix as it was
path += "." + suffix;
} else {
path += ".png";
}
if (!QFileInfo::exists(path)) {
return path;
} else {
return autoNumerateDuplicate(path);
}
}
QString FileNameHandler::autoNumerateDuplicate(QString path)
{
// add numeration in case of repeated filename in the directory
// find unused name adding _n where n is a number
QFileInfo checkFile(directory + filename + ".png");
QFileInfo checkFile(path);
QString directory = checkFile.dir().absolutePath(),
filename = checkFile.completeBaseName(),
suffix = checkFile.suffix();
if (!suffix.isEmpty()) {
suffix = QStringLiteral(".") + suffix;
}
if (checkFile.exists()) {
filename += QLatin1String("_");
int i = 1;
while (true) {
checkFile.setFile(directory + filename + QString::number(i) +
".png");
checkFile.setFile(directory + "/" + filename + QString::number(i) +
suffix);
if (!checkFile.exists()) {
filename += QString::number(i);
break;
@@ -118,4 +127,5 @@ void FileNameHandler::fixPath(QString& directory, QString& filename)
++i;
}
}
return checkFile.filePath();
}