Changeset View
Changeset View
Standalone View
Standalone View
src/ExportManager.cpp
Show All 13 Lines | |||||
14 | * You should have received a copy of the GNU Lesser General Public License | 14 | * You should have received a copy of the GNU Lesser General Public License | ||
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
17 | * Boston, MA 02110-1301, USA. | 17 | * Boston, MA 02110-1301, USA. | ||
18 | */ | 18 | */ | ||
19 | 19 | | |||
20 | #include "ExportManager.h" | 20 | #include "ExportManager.h" | ||
21 | 21 | | |||
22 | #include <QDir> | 22 | #include <QDir> | ||
23 | #include <QMimeDatabase> | 23 | #include <QMimeDatabase> | ||
24 | #include <QImageWriter> | 24 | #include <QImageWriter> | ||
25 | #include <QTemporaryDir> | 25 | #include <QTemporaryDir> | ||
26 | #include <QTemporaryFile> | 26 | #include <QTemporaryFile> | ||
27 | #include <QApplication> | 27 | #include <QApplication> | ||
28 | #include <QClipboard> | 28 | #include <QClipboard> | ||
29 | #include <QPainter> | 29 | #include <QPainter> | ||
rkflx: Unrelated change. | |||||
@rkflx, how should I fix unsorted #includes? If I do it with my normal changes combined, you are unsatisfied: "unrelated changes". Can I fix #includes in all files of Dolphin in a separate diff? rominf: @rkflx, how should I fix unsorted #includes? If I do it with my normal changes combined, you… | |||||
Reordering includes creates only very little value, but costs reviewer time, clutters the git history and will be imperfect again in no time. Nevertheless, removing unused includes across the code base has its value, but it would need to go into a separate Diff anyway. rkflx: Reordering includes creates only very little value, but costs reviewer time, clutters the git… | |||||
30 | #include <QFileDialog> | 30 | #include <QFileDialog> | ||
31 | #include <QBuffer> | 31 | #include <QBuffer> | ||
32 | #include <QRegularExpression> | ||||
32 | 33 | | |||
33 | #include <KLocalizedString> | 34 | #include <KLocalizedString> | ||
34 | #include <KSharedConfig> | 35 | #include <KSharedConfig> | ||
35 | #include <KConfigGroup> | 36 | #include <KConfigGroup> | ||
36 | #include <KIO/FileCopyJob> | 37 | #include <KIO/FileCopyJob> | ||
37 | #include <KIO/StatJob> | 38 | #include <KIO/StatJob> | ||
38 | 39 | | |||
39 | #include "SpectacleConfig.h" | 40 | #include "SpectacleConfig.h" | ||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Line(s) | 73 | { | |||
82 | } | 83 | } | ||
83 | 84 | | |||
84 | // compose the data uri and return it | 85 | // compose the data uri and return it | ||
85 | 86 | | |||
86 | QString uri = QStringLiteral("data:image/png;base64,") + QString::fromLatin1(imageData.toBase64()); | 87 | QString uri = QStringLiteral("data:image/png;base64,") + QString::fromLatin1(imageData.toBase64()); | ||
87 | return uri; | 88 | return uri; | ||
88 | } | 89 | } | ||
89 | 90 | | |||
91 | void ExportManager::setWindowTitle(const QString &windowTitle) | ||||
92 | { | ||||
93 | mWindowTitle = windowTitle; | ||||
94 | } | ||||
95 | | ||||
96 | QString ExportManager::windowTitle() const | ||||
97 | { | ||||
98 | return mWindowTitle; | ||||
99 | } | ||||
100 | | ||||
101 | ImageGrabber::GrabMode ExportManager::grabMode() const | ||||
102 | { | ||||
103 | return mGrabMode; | ||||
104 | } | ||||
105 | | ||||
106 | void ExportManager::setGrabMode(const ImageGrabber::GrabMode &grabMode) | ||||
107 | { | ||||
108 | mGrabMode = grabMode; | ||||
109 | } | ||||
110 | | ||||
90 | void ExportManager::setPixmap(const QPixmap &pixmap) | 111 | void ExportManager::setPixmap(const QPixmap &pixmap) | ||
91 | { | 112 | { | ||
92 | mSavePixmap = pixmap; | 113 | mSavePixmap = pixmap; | ||
93 | 114 | | |||
94 | // reset our saved tempfile | 115 | // reset our saved tempfile | ||
95 | if (mTempFile.isValid()) { | 116 | if (mTempFile.isValid()) { | ||
96 | mUsedTempFileNames.append(mTempFile); | 117 | mUsedTempFileNames.append(mTempFile); | ||
97 | QFile file(mTempFile.toLocalFile()); | 118 | QFile file(mTempFile.toLocalFile()); | ||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Line(s) | 161 | { | |||
148 | const QUrl fileNameUrl = QUrl::fromUserInput(fullpath); | 169 | const QUrl fileNameUrl = QUrl::fromUserInput(fullpath); | ||
149 | if (fileNameUrl.isValid()) { | 170 | if (fileNameUrl.isValid()) { | ||
150 | return fileNameUrl; | 171 | return fileNameUrl; | ||
151 | } else { | 172 | } else { | ||
152 | return QUrl(); | 173 | return QUrl(); | ||
153 | } | 174 | } | ||
154 | } | 175 | } | ||
155 | 176 | | |||
177 | QString ExportManager::truncatedFilename(QString const &filename) | ||||
178 | { | ||||
179 | QString result = filename; | ||||
180 | constexpr auto maxFilenameLength = 255; | ||||
181 | constexpr auto maxExtensionLength = 5; // For example, ".jpeg" | ||||
182 | constexpr auto maxCounterLength = 20; // std::numeric_limits<quint64>::max() == 18446744073709551615 | ||||
183 | constexpr auto maxLength = maxFilenameLength - maxCounterLength - maxExtensionLength; | ||||
184 | result.truncate(maxLength); | ||||
185 | return result; | ||||
186 | } | ||||
187 | | ||||
156 | QString ExportManager::makeAutosaveFilename() | 188 | QString ExportManager::makeAutosaveFilename() | ||
157 | { | 189 | { | ||
158 | KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("spectaclerc")); | 190 | KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("spectaclerc")); | ||
159 | KConfigGroup generalConfig = KConfigGroup(config, "General"); | 191 | KConfigGroup generalConfig = KConfigGroup(config, "General"); | ||
160 | 192 | | |||
161 | const QDateTime timestamp = QDateTime::currentDateTime(); | 193 | const QDateTime timestamp = QDateTime::currentDateTime(); | ||
162 | QString baseName = generalConfig.readEntry("save-filename-format", "Screenshot_%Y%M%D_%H%m%S"); | 194 | QString baseName = generalConfig.readEntry("save-filename-format", "Screenshot_%Y%M%D_%H%m%S"); | ||
163 | 195 | | |||
164 | return baseName.replace(QLatin1String("%Y"), timestamp.toString(QStringLiteral("yyyy"))) | 196 | QString title; | ||
197 | | ||||
198 | if (mGrabMode == ImageGrabber::GrabMode::ActiveWindow || | ||||
199 | mGrabMode == ImageGrabber::GrabMode::TransientWithParent || | ||||
200 | mGrabMode == ImageGrabber::GrabMode::WindowUnderCursor) { | ||||
201 | title = mWindowTitle; | ||||
202 | } else { | ||||
203 | // Remove '%T' with separators around it | ||||
rkflx: `const` | |||||
204 | const auto wordSymbol = QStringLiteral(R"(\p{L}\p{M}\p{N})"); | ||||
rkflx: Add comment about what the RegEx is for. | |||||
rkflx: Nice! | |||||
205 | const auto separator = QStringLiteral("([^%1]+)").arg(wordSymbol); | ||||
206 | const auto re = QRegularExpression(QStringLiteral("(.*?)(%1%T|%T%1)(.*?)").arg(separator)); | ||||
207 | baseName.replace(re, QStringLiteral(R"(\1\5)")); | ||||
208 | } | ||||
209 | | ||||
210 | QString result = baseName.replace(QLatin1String("%Y"), timestamp.toString(QStringLiteral("yyyy"))) | ||||
165 | .replace(QLatin1String("%y"), timestamp.toString(QStringLiteral("yy"))) | 211 | .replace(QLatin1String("%y"), timestamp.toString(QStringLiteral("yy"))) | ||
166 | .replace(QLatin1String("%M"), timestamp.toString(QStringLiteral("MM"))) | 212 | .replace(QLatin1String("%M"), timestamp.toString(QStringLiteral("MM"))) | ||
167 | .replace(QLatin1String("%D"), timestamp.toString(QStringLiteral("dd"))) | 213 | .replace(QLatin1String("%D"), timestamp.toString(QStringLiteral("dd"))) | ||
168 | .replace(QLatin1String("%H"), timestamp.toString(QStringLiteral("hh"))) | 214 | .replace(QLatin1String("%H"), timestamp.toString(QStringLiteral("hh"))) | ||
169 | .replace(QLatin1String("%m"), timestamp.toString(QStringLiteral("mm"))) | 215 | .replace(QLatin1String("%m"), timestamp.toString(QStringLiteral("mm"))) | ||
170 | .replace(QLatin1String("%S"), timestamp.toString(QStringLiteral("ss"))); | 216 | .replace(QLatin1String("%S"), timestamp.toString(QStringLiteral("ss"))) | ||
rkflx: `{}` | |||||
217 | .replace(QLatin1String("%T"), title) | ||||
218 | .replace(QLatin1String("/"), QLatin1String("_")); // POSIX doesn't allow "/" in filenames | ||||
219 | if (result.isEmpty()) { | ||||
220 | result = QStringLiteral("Screenshot"); | ||||
221 | } | ||||
222 | return truncatedFilename(result); | ||||
rkflx: Why do you need `= QStringLiteral();`? | |||||
rkflx: I still don't understand why a simple `QString title;` would not work. | |||||
171 | } | 223 | } | ||
172 | 224 | | |||
173 | QString ExportManager::autoIncrementFilename(const QString &baseName, const QString &extension, | 225 | QString ExportManager::autoIncrementFilename(const QString &baseName, const QString &extension, | ||
174 | FileNameAlreadyUsedCheck isFileNameUsed) | 226 | FileNameAlreadyUsedCheck isFileNameUsed) | ||
175 | { | 227 | { | ||
176 | if (!((this->*isFileNameUsed)(QUrl::fromUserInput(baseName + QLatin1Char('.') + extension)))) { | 228 | QString result = truncatedFilename(baseName) + QLatin1Literal(".") + extension; | ||
177 | return baseName + QLatin1Char('.') + extension; | 229 | if (!((this->*isFileNameUsed)(QUrl::fromUserInput(result)))) { | ||
230 | return result; | ||||
rkflx: `QLatin1Literal` | |||||
178 | } | 231 | } | ||
179 | 232 | | |||
180 | QString fileNameFmt(baseName + QStringLiteral("-%1.") + extension); | 233 | QString fileNameFmt = truncatedFilename(baseName) + QStringLiteral("-%1."); | ||
181 | for (quint64 i = 1; i < std::numeric_limits<quint64>::max(); i++) { | 234 | for (quint64 i = 1; i < std::numeric_limits<quint64>::max(); i++) { | ||
182 | if (!((this->*isFileNameUsed)(QUrl::fromUserInput(fileNameFmt.arg(i))))) { | 235 | result = fileNameFmt.arg(i) + extension; | ||
183 | return fileNameFmt.arg(i); | 236 | if (!((this->*isFileNameUsed)(QUrl::fromUserInput(result)))) { | ||
237 | return result; | ||||
184 | } | 238 | } | ||
185 | } | 239 | } | ||
186 | 240 | | |||
187 | // unlikely this will ever happen, but just in case we've run | 241 | // unlikely this will ever happen, but just in case we've run | ||
188 | // out of numbers | 242 | // out of numbers | ||
189 | 243 | | |||
190 | return fileNameFmt.arg(QStringLiteral("OVERFLOW-") + QString::number(qrand() % 10000)); | 244 | result = fileNameFmt.arg(QStringLiteral("OVERFLOW-") + QString::number(qrand() % 10000)); | ||
245 | return truncatedFilename(result) + extension; | ||||
191 | } | 246 | } | ||
192 | 247 | | |||
193 | QString ExportManager::makeSaveMimetype(const QUrl &url) | 248 | QString ExportManager::makeSaveMimetype(const QUrl &url) | ||
194 | { | 249 | { | ||
195 | QMimeDatabase mimedb; | 250 | QMimeDatabase mimedb; | ||
196 | QString type = mimedb.mimeTypeForUrl(url).preferredSuffix(); | 251 | QString type = mimedb.mimeTypeForUrl(url).preferredSuffix(); | ||
197 | 252 | | |||
198 | if (type.isEmpty()) { | 253 | if (type.isEmpty()) { | ||
▲ Show 20 Lines • Show All 206 Lines • Show Last 20 Lines |
Unrelated change.