Commit b5f8a25e authored by Fushan Wen's avatar Fushan Wen Committed by Nate Graham
Browse files

wallpapers/potd: Implement save action in the backend

To perform copy jobs.

CCBUG: 422934
parent 357b4ae5
......@@ -12,9 +12,11 @@ ecm_qt_declare_logging_category(potd_engine_SRCS
add_library(plasma_wallpaper_potdplugin SHARED ${potd_engine_SRCS})
target_link_libraries(plasma_wallpaper_potdplugin plasmapotdprovidercore
KF5::I18n
KF5::KIOCore
Qt::DBus
Qt::Qml
Qt::Widgets # QFileDialog
)
install(TARGETS plasma_wallpaper_potdplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/wallpapers/potd)
install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/wallpapers/potd)
......
......@@ -13,4 +13,5 @@ void PotdPlugin::registerTypes(const char *uri)
Q_ASSERT(uri == QByteArrayLiteral("org.kde.plasma.wallpapers.potd"));
qmlRegisterType<PotdProviderModel>(uri, 1, 0, "PotdProviderModel");
qmlRegisterUncreatableType<PotdProviderModel>(uri, 1, 0, "Global", QStringLiteral("Error: only enums"));
}
......@@ -12,8 +12,12 @@
#include <QDate>
#include <QDBusConnection>
#include <QDebug>
#include <QFileDialog>
#include <QStandardPaths> // For "Pictures" folder
#include <QThreadPool>
#include <KIO/CopyJob> // For "Save Image"
#include <KLocalizedString>
#include <KPluginFactory>
#include <KPluginMetaData>
......@@ -292,6 +296,85 @@ void PotdProviderModel::setAuthor(const QString &author)
Q_EMIT authorChanged();
}
void PotdProviderModel::saveImage()
{
if (m_data.wallpaperLocalUrl.isEmpty()) {
return;
}
auto sanitizeFileName = [](const QString &name){
if (name.isEmpty()) {
return name;
}
const char notAllowedChars[] = ",^@={}[]~!?:&*\"|#%<>$\"'();`'/\\";
QString sanitizedName(name);
for (const char *c = notAllowedChars; *c; c++) {
sanitizedName.replace(QLatin1Char(*c), QLatin1Char('-'));
}
return sanitizedName;
};
const QStringList &locations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
const QString path = locations.isEmpty() ? QStandardPaths::standardLocations(QStandardPaths::HomeLocation).at(0) : locations.at(0);
// clang-format off
QString defaultFileName = m_providers.at(m_currentIndex).name().trimmed();
if (!m_data.wallpaperTitle.isEmpty()) {
defaultFileName += QLatin1Char('-') + m_data.wallpaperTitle.trimmed();
if (!m_data.wallpaperAuthor.isEmpty()) {
defaultFileName += QLatin1Char('-') + m_data.wallpaperAuthor.trimmed();
}
} else {
// Use current date
if (!defaultFileName.isEmpty()) {
defaultFileName += QLatin1Char('-');
}
defaultFileName += QDate::currentDate().toString();
}
m_savedUrl = QUrl::fromLocalFile(
QFileDialog::getSaveFileName(
nullptr,
i18nc("@title:window", "Save Today's Picture"),
path + "/" + sanitizeFileName(defaultFileName) + ".jpg",
i18nc("@label:listbox Template for file dialog", "JPEG image (*.jpeg *.jpg *.jpe)"),
nullptr,
QFileDialog::DontConfirmOverwrite // KIO::CopyJob will show the confirmation dialog.
)
);
// clang-format on
if (m_savedUrl.isEmpty() || !m_savedUrl.isValid()) {
return;
}
m_savedFolder = QUrl::fromLocalFile(m_savedUrl.toLocalFile().section(QDir::separator(), 0, -2));
KIO::CopyJob *copyJob = KIO::copy(QUrl::fromLocalFile(m_data.wallpaperLocalUrl), m_savedUrl, KIO::HideProgressInfo);
connect(copyJob, &KJob::finished, this, [this](KJob *job) {
if (job->error()) {
m_saveStatusMessage = job->errorText();
if (m_saveStatusMessage.isEmpty()) {
m_saveStatusMessage = i18nc("@info:status after a save action", "The image was not saved.");
}
m_saveStatus = FileOperationStatus::Failed;
Q_EMIT saveStatusChanged();
} else {
m_saveStatusMessage = i18nc("@info:status after a save action %1 file path %2 basename",
"The image was saved as <a href=\"%1\">%2</a>",
m_savedUrl.toString(),
m_savedUrl.fileName());
m_saveStatus = FileOperationStatus::Successful;
Q_EMIT saveStatusChanged();
}
});
copyJob->start();
}
void PotdProviderModel::resetData()
{
setImage(QImage());
......
......@@ -11,6 +11,7 @@
#include <QAbstractListModel>
#include <QImage>
#include <QTimer>
#include <QUrl>
#include <KPluginMetaData>
......@@ -48,7 +49,34 @@ class PotdProviderModel : public QAbstractListModel
Q_PROPERTY(QString title READ title NOTIFY titleChanged)
Q_PROPERTY(QString author READ author NOTIFY authorChanged)
/**
* @return the result of the file operation.
*/
Q_PROPERTY(FileOperationStatus saveStatus MEMBER m_saveStatus NOTIFY saveStatusChanged)
/**
* @return the status message after a save operation.
*/
Q_PROPERTY(QString saveStatusMessage MEMBER m_saveStatusMessage CONSTANT)
/**
* @return the folder path of the saved image file.
*/
Q_PROPERTY(QUrl savedFolder MEMBER m_savedFolder CONSTANT)
/**
* @return the path of the saved image file.
*/
Q_PROPERTY(QUrl savedUrl MEMBER m_savedUrl CONSTANT)
public:
enum class FileOperationStatus {
None,
Successful,
Failed,
};
Q_ENUM(FileOperationStatus)
enum Roles {
Id = Qt::UserRole + 1,
};
......@@ -80,6 +108,12 @@ public:
QString title() const;
QString author() const;
/**
* Opens a Save dialog to choose the save location, and copies the source file to the
* selected destination.
*/
Q_INVOKABLE void saveImage();
Q_SIGNALS:
void runningChanged();
void identifierChanged();
......@@ -93,6 +127,8 @@ Q_SIGNALS:
void titleChanged();
void authorChanged();
void saveStatusChanged();
private Q_SLOTS:
void slotFinished(PotdProvider *);
void slotCachingFinished(const QString &source, const PotdProviderData &data);
......@@ -122,6 +158,11 @@ private:
bool m_loading;
QTimer m_checkDatesTimer;
QUrl m_savedFolder;
QUrl m_savedUrl;
FileOperationStatus m_saveStatus;
QString m_saveStatusMessage;
};
#endif
Supports Markdown
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