Members of the KDE Community are recommended to subscribe to the kde-community mailing list at 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

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:
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) :
delete mTempDir;
ExportManager* ExportManager::instance()
......@@ -84,6 +88,7 @@ void ExportManager::setPixmap(const QPixmap &pixmap)
// reset our saved tempfile
if (mTempFile.isValid()) {
QFile file(mTempFile.toLocalFile());
mTempFile = QUrl();
......@@ -127,7 +132,8 @@ QUrl ExportManager::getAutosaveFilename()
const QDir baseDirPath(baseDir);
const QString filename = makeAutosaveFilename();
const QString fullpath = autoIncrementFilename(baseDirPath.filePath(filename),
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.setPermissions(QFile::ReadUser | QFile::WriteUser);
if ( {
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,
QFile tmpFile(fileName);
if ( {
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
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
......@@ -78,16 +80,21 @@ class ExportManager : public QObject
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;
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