File indexing completed on 2024-05-19 04:21:17
0001 // vim: set tabstop=4 shiftwidth=4 expandtab: 0002 /* 0003 Gwenview: an image viewer 0004 Copyright 2009 Aurélien Gâteau <agateau@kde.org> 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU General Public License 0008 as published by the Free Software Foundation; either version 2 0009 of the License, or (at your option) any later version. 0010 0011 This program is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 GNU General Public License for more details. 0015 0016 You should have received a copy of the GNU General Public License 0017 along with this program; if not, write to the Free Software 0018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA. 0019 0020 */ 0021 // Self 0022 #include "savejob.h" 0023 0024 // Qt 0025 #include <QApplication> 0026 #include <QFuture> 0027 #include <QFutureWatcher> 0028 #include <QSaveFile> 0029 #include <QScopedPointer> 0030 #include <QTemporaryFile> 0031 #include <QUrl> 0032 #include <QtConcurrentRun> 0033 0034 // KF 0035 #include <KIO/CopyJob> 0036 #include <KIO/JobUiDelegate> 0037 #include <KJobWidgets> 0038 #include <KLocalizedString> 0039 0040 // Local 0041 #include "documentloadedimpl.h" 0042 0043 namespace Gwenview 0044 { 0045 struct SaveJobPrivate { 0046 DocumentLoadedImpl *mImpl = nullptr; 0047 QUrl mOldUrl; 0048 QUrl mNewUrl; 0049 QByteArray mFormat; 0050 QScopedPointer<QTemporaryFile> mTemporaryFile; 0051 QScopedPointer<QSaveFile> mSaveFile; 0052 QScopedPointer<QFutureWatcher<void>> mInternalSaveWatcher; 0053 0054 bool mKillReceived; 0055 }; 0056 0057 SaveJob::SaveJob(DocumentLoadedImpl *impl, const QUrl &url, const QByteArray &format) 0058 : d(new SaveJobPrivate) 0059 { 0060 d->mImpl = impl; 0061 d->mOldUrl = impl->document()->url(); 0062 d->mNewUrl = url; 0063 d->mFormat = format; 0064 d->mKillReceived = false; 0065 setCapabilities(Killable); 0066 } 0067 0068 SaveJob::~SaveJob() 0069 { 0070 delete d; 0071 } 0072 0073 void SaveJob::saveInternal() 0074 { 0075 if (!d->mImpl->saveInternal(d->mSaveFile.data(), d->mFormat)) { 0076 d->mSaveFile->cancelWriting(); 0077 setError(UserDefinedError + 2); 0078 setErrorText(d->mImpl->document()->errorString()); 0079 } 0080 } 0081 0082 void SaveJob::doStart() 0083 { 0084 if (d->mKillReceived) { 0085 return; 0086 } 0087 QString fileName; 0088 0089 if (d->mNewUrl.isLocalFile()) { 0090 fileName = d->mNewUrl.toLocalFile(); 0091 } else { 0092 d->mTemporaryFile.reset(new QTemporaryFile); 0093 d->mTemporaryFile->setAutoRemove(true); 0094 d->mTemporaryFile->open(); 0095 fileName = d->mTemporaryFile->fileName(); 0096 } 0097 0098 d->mSaveFile.reset(new QSaveFile(fileName)); 0099 0100 if (!d->mSaveFile->open(QSaveFile::WriteOnly)) { 0101 QUrl dirUrl = d->mNewUrl; 0102 dirUrl = dirUrl.adjusted(QUrl::RemoveFilename); 0103 setError(UserDefinedError + 1); 0104 // Don't use xi18n* with markup substitution here, this is done in GvCore::slotSaveResult or SaveAllHelper::slotResult 0105 setErrorText(i18nc("@info", 0106 "Could not open file for writing, check that you have the necessary rights in <filename>%1</filename>.", 0107 dirUrl.toDisplayString(QUrl::PreferLocalFile))); 0108 uiDelegate()->setAutoErrorHandlingEnabled(false); 0109 uiDelegate()->setAutoWarningHandlingEnabled(false); 0110 emitResult(); 0111 return; 0112 } 0113 QFuture<void> future = QtConcurrent::run(&SaveJob::saveInternal, this); 0114 d->mInternalSaveWatcher.reset(new QFutureWatcher<void>(this)); 0115 connect(d->mInternalSaveWatcher.data(), &QFutureWatcherBase::finished, this, &SaveJob::finishSave); 0116 d->mInternalSaveWatcher->setFuture(future); 0117 } 0118 0119 void SaveJob::finishSave() 0120 { 0121 d->mInternalSaveWatcher.reset(nullptr); 0122 if (d->mKillReceived) { 0123 return; 0124 } 0125 0126 if (error()) { 0127 emitResult(); 0128 return; 0129 } 0130 0131 if (!d->mSaveFile->commit()) { 0132 setErrorText( 0133 xi18nc("@info", "Could not overwrite file, check that you have the necessary rights to write in <filename>%1</filename>.", d->mNewUrl.toString())); 0134 setError(UserDefinedError + 3); 0135 return; 0136 } 0137 0138 if (d->mNewUrl.isLocalFile()) { 0139 emitResult(); 0140 } else { 0141 KIO::Job *job = KIO::copy(QUrl::fromLocalFile(d->mTemporaryFile->fileName()), d->mNewUrl); 0142 KJobWidgets::setWindow(job, qApp->activeWindow()); 0143 addSubjob(job); 0144 } 0145 } 0146 0147 void SaveJob::slotResult(KJob *job) 0148 { 0149 DocumentJob::slotResult(job); 0150 if (!error()) { 0151 emitResult(); 0152 } 0153 } 0154 0155 QUrl SaveJob::oldUrl() const 0156 { 0157 return d->mOldUrl; 0158 } 0159 0160 QUrl SaveJob::newUrl() const 0161 { 0162 return d->mNewUrl; 0163 } 0164 0165 bool SaveJob::doKill() 0166 { 0167 d->mKillReceived = true; 0168 if (d->mInternalSaveWatcher) { 0169 d->mInternalSaveWatcher->waitForFinished(); 0170 } 0171 return true; 0172 } 0173 0174 } // namespace 0175 0176 #include "moc_savejob.cpp"