Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Fix: use autosaveFilename format also for files exported via DnD or menu

Summary:
When exporting the current screenshot directly to applications via a
temporary file holding a copy of the screenshot, the very filename of the
temporary file is then picked up in those programs, e.g. when displaying
the file or creating a local copy. Additionally that name is also passed
in the x-kde-suggestedfilename property on DnD.
With the usage of QTemporaryFile this filename holds some random part, which
makes it less useful.
Switching to a QTemporaryDir instead for getting a non-conflicting
namespace in the temp dirs, and using a normal file with the configured
autosaveFilename format in that dir results in the expected naming of
screenshot files also on export to apps via menu or DnD.

BUG: 382718
FIXED-IN: 17.08.02

Reviewers: bgupta, alexeymin

Reviewed By: alexeymin

Subscribers: alexeymin, #kde_applications, #plasma

Differential Revision: https://phabricator.kde.org/D7725
parent 36f0b85e
......@@ -22,6 +22,7 @@
#include <QDir>
#include <QMimeDatabase>
#include <QImageWriter>
#include <QTemporaryDir>
#include <QTemporaryFile>
#include <QApplication>
#include <QClipboard>
......@@ -40,11 +41,14 @@
ExportManager::ExportManager(QObject *parent) :
QObject(parent),
mSavePixmap(QPixmap()),
mTempFile(QUrl())
mTempFile(QUrl()),
mTempDir(nullptr)
{}
ExportManager::~ExportManager()
{}
{
delete mTempDir;
}
ExportManager* ExportManager::instance()
{
......@@ -84,6 +88,7 @@ void ExportManager::setPixmap(const QPixmap &pixmap)
// reset our saved tempfile
if (mTempFile.isValid()) {
mUsedTempFileNames.append(mTempFile);
QFile file(mTempFile.toLocalFile());
file.remove();
mTempFile = QUrl();
......@@ -127,7 +132,8 @@ QUrl ExportManager::getAutosaveFilename()
const QDir baseDirPath(baseDir);
const QString filename = makeAutosaveFilename();
const QString fullpath = autoIncrementFilename(baseDirPath.filePath(filename),
SpectacleConfig::instance()->saveImageFormat());
SpectacleConfig::instance()->saveImageFormat(),
&ExportManager::isFileExists);
const QUrl fileNameUrl = QUrl::fromUserInput(fullpath);
if (fileNameUrl.isValid()) {
......@@ -154,15 +160,16 @@ QString ExportManager::makeAutosaveFilename()
.replace(QLatin1String("%S"), timestamp.toString(QStringLiteral("ss")));
}
QString ExportManager::autoIncrementFilename(const QString &baseName, const QString &extension)
QString ExportManager::autoIncrementFilename(const QString &baseName, const QString &extension,
FileNameAlreadyUsedCheck isFileNameUsed)
{
if (!(isFileExists(QUrl::fromUserInput(baseName + '.' + extension)))) {
if (!((this->*isFileNameUsed)(QUrl::fromUserInput(baseName + '.' + extension)))) {
return baseName + '.' + extension;
}
QString fileNameFmt(baseName + "-%1." + extension);
for (quint64 i = 1; i < std::numeric_limits<quint64>::max(); i++) {
if (!(isFileExists(QUrl::fromUserInput(fileNameFmt.arg(i))))) {
if (!((this->*isFileNameUsed)(QUrl::fromUserInput(fileNameFmt.arg(i))))) {
return fileNameFmt.arg(i);
}
}
......@@ -239,19 +246,30 @@ QUrl ExportManager::tempSave(const QString &mimetype)
}
}
QTemporaryFile tmpFile(QDir::tempPath() + QDir::separator() + "Spectacle.XXXXXX." + mimetype);
tmpFile.setAutoRemove(false);
tmpFile.setPermissions(QFile::ReadUser | QFile::WriteUser);
if (tmpFile.open()) {
if(!writeImage(&tmpFile, mimetype.toLatin1())) {
emit errorMessage(i18n("Cannot save screenshot. Error while writing temporary local file."));
return QUrl();
if (!mTempDir) {
mTempDir = new QTemporaryDir(QDir::tempPath() + QDir::separator() + "Spectacle.XXXXXX");
}
if (mTempDir && mTempDir->isValid()) {
// create the temporary file itself with normal file name and also unique one for this session
// supports the use-case of creating multiple screenshots in a row
// and exporting them to the same destination e.g. via clipboard,
// where the temp file name is used as filename suggestion
const QString baseFileName = mTempDir->path() + QDir::separator() + makeAutosaveFilename();
const QString fileName = autoIncrementFilename(baseFileName, mimetype,
&ExportManager::isTempFileAlreadyUsed);
QFile tmpFile(fileName);
if (tmpFile.open(QFile::WriteOnly)) {
if(writeImage(&tmpFile, mimetype.toLatin1())) {
mTempFile = QUrl::fromLocalFile(tmpFile.fileName());
// try to make sure 3rd-party which gets the url of the temporary file e.g. on export
// properly treats this as readonly, also hide from other users
tmpFile.setPermissions(QFile::ReadUser);
return mTempFile;
}
}
mTempFile = QUrl::fromLocalFile(tmpFile.fileName());
return mTempFile;
}
emit errorMessage(i18n("Cannot save screenshot. Error while writing temporary local file."));
return QUrl();
}
......@@ -269,7 +287,7 @@ bool ExportManager::save(const QUrl &url)
return remoteSave(url, mimetype);
}
bool ExportManager::isFileExists(const QUrl &url)
bool ExportManager::isFileExists(const QUrl &url) const
{
if (!(url.isValid())) {
return false;
......@@ -281,6 +299,11 @@ bool ExportManager::isFileExists(const QUrl &url)
return (existsJob->error() == KJob::NoError);
}
bool ExportManager::isTempFileAlreadyUsed(const QUrl &url) const
{
return mUsedTempFileNames.contains(url);
}
// save slots
void ExportManager::doSave(const QUrl &url, bool notify)
......
......@@ -26,6 +26,8 @@
#include <QPixmap>
#include <QUrl>
class QTemporaryDir;
class ExportManager : public QObject
{
Q_OBJECT
......@@ -78,16 +80,21 @@ class ExportManager : public QObject
private:
QString makeAutosaveFilename();
QString autoIncrementFilename(const QString &baseName, const QString &extension);
using FileNameAlreadyUsedCheck = bool (ExportManager::*)(const QUrl&) const;
QString autoIncrementFilename(const QString &baseName, const QString &extension,
FileNameAlreadyUsedCheck isFileNameUsed);
QString makeSaveMimetype(const QUrl &url);
bool writeImage(QIODevice *device, const QByteArray &format);
bool save(const QUrl &url);
bool localSave(const QUrl &url, const QString &mimetype);
bool remoteSave(const QUrl &url, const QString &mimetype);
bool isFileExists(const QUrl &url);
bool isFileExists(const QUrl &url) const;
bool isTempFileAlreadyUsed(const QUrl &url) const;
QPixmap mSavePixmap;
QUrl mTempFile;
QTemporaryDir *mTempDir;
QList<QUrl> mUsedTempFileNames;
};
#endif // EXPORTMANAGER_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment