23#include <kconfiggroup.h>
24#include <ksharedconfig.h>
35 : QAbstractTableModel(parent)
57 if (parent.isValid()) {
60 return d->storages.size();
66 if (parent.isValid()) {
75 const QString storageLocation = query.value(
"location").toString();
76 const QString storageType = query.value(
"storage_type").toString();
77 const QString storageIdAsString = query.value(
"id").toString();
83 const int storageId = query.value(
"id").toInt();
88 result = thumbQuery.prepare(
"SELECT thumbnail FROM storages WHERE id = :id");
90 qWarning() <<
"Failed to prepare query for thumbnail of" << storageId << thumbQuery.lastError();
94 thumbQuery.bindValue(
":id", storageId);
96 result = thumbQuery.exec();
99 qWarning() <<
"Failed to execute query for thumbnail of" << storageId << thumbQuery.lastError();
103 if (!thumbQuery.next()) {
104 qWarning() <<
"Failed to find thumbnail of" << storageId;
108 QByteArray ba = thumbQuery.value(
"thumbnail").toByteArray();
110 buf.open(QBuffer::ReadOnly);
111 img.load(&buf,
"PNG");
121 if (!index.isValid())
return v;
123 if (index.column() > (
int)
MetaData)
return v;
125 if (role == Qt::FontRole) {
129 QString location =
d->storages.at(index.row());
133 bool r = query.prepare(
134 "SELECT storages.id as id\n"
135 ", storage_types.name as storage_type\n"
142 "WHERE storages.storage_type_id = storage_types.id\n"
143 "AND location = :location");
146 qWarning() <<
"Could not prepare KisStorageModel data query" << query.lastError();
150 query.bindValue(
":location", location);
155 qWarning() <<
"Could not execute KisStorageModel data query" << query.lastError() << query.boundValues();
159 if (!query.first()) {
160 qWarning() <<
"KisStorageModel data query did not return anything";
164 if ((role == Qt::DisplayRole || role == Qt::EditRole) && index.column() ==
Active) {
165 return query.value(
"active");
168 case Qt::DisplayRole:
170 switch(index.column()) {
172 return query.value(
"id");
174 return query.value(
"storage_type");
176 return query.value(
"location");
178 return QDateTime::fromSecsSinceEpoch(query.value(
"timestamp").value<
int>()).toString();
180 return query.value(
"pre_installed");
182 return query.value(
"active");
190 QVariant name = query.value(
"location");
208 case Qt::CheckStateRole: {
209 switch (index.column()) {
211 if (query.value(
"pre_installed").toInt() == 0) {
212 return Qt::Unchecked;
217 if (query.value(
"active").toInt() == 0) {
218 return Qt::Unchecked;
226 case Qt::DecorationRole: {
232 case Qt::UserRole +
Id:
233 return query.value(
"id");
237 QVariant name = query.value(
"location");
247 return query.value(
"storage_type");
249 return query.value(
"location");
251 return query.value(
"timestamp");
253 return query.value(
"pre_installed");
254 case Qt::UserRole +
Active:
255 return query.value(
"active");
274 if (index.isValid()) {
276 if (role == Qt::CheckStateRole) {
278 bool r = query.prepare(
"UPDATE storages\n"
279 "SET active = :active\n"
281 query.bindValue(
":active",
value);
282 query.bindValue(
":id", index.data(Qt::UserRole +
Id));
285 qWarning() <<
"Could not prepare KisStorageModel update query" << query.lastError();
292 qWarning() <<
"Could not execute KisStorageModel update query" << query.lastError();
298 Q_EMIT dataChanged(index, index, {role});
300 if (
value.toBool()) {
313 if (!index.isValid()) {
314 return Qt::NoItemFlags;
316 return QAbstractTableModel::flags(index) | Qt::ItemIsEditable | Qt::ItemNeverHasChildren;
322 if (!index.isValid())
return 0;
323 if (index.row() >
rowCount())
return 0;
324 if (index.column() > (
int)
MetaData)
return 0;
326 QString location =
d->storages.at(index.row());
335 bool r = query.prepare(
"SELECT location\n"
337 "WHERE storages.id = :storageId");
340 qWarning() <<
"Could not prepare KisStorageModel data query" << query.lastError();
344 query.bindValue(
":storageId", storageId);
349 qWarning() <<
"Could not execute KisStorageModel data query" << query.lastError() << query.boundValues();
353 if (!query.first()) {
354 qWarning() <<
"KisStorageModel data query did not return anything";
366 QFileInfo info = QFileInfo(location +
"/" + filename);
367 if (!info.exists()) {
371 QString extension = info.suffix();
372 QString filenameNoExtension = filename.left(filename.length() - extension.length());
375 QDir dir = QDir(location);
379 int maxVersionUsed = -1;
380 for (
int i = 0; i < similarEntries.count(); i++) {
381 QString entry = similarEntries[i];
383 if (!entry.endsWith(extension)) {
386 QString versionStr = entry.right(entry.length() - filenameNoExtension.length());
387 versionStr = versionStr.left(versionStr.length() - extension.length());
388 if (!versionStr.startsWith(
"_")) {
391 versionStr = versionStr.right(versionStr.length() - 1);
394 int version = versionStr.toInt(&ok);
398 if (version > maxVersionUsed) {
399 maxVersionUsed = version;
403 int versionToUse = maxVersionUsed > -1 ? maxVersionUsed + 1 : 1;
404 int versionStringLength = 3;
405 QString baseNewVersion = QString::number(versionToUse);
406 while (baseNewVersion.length() < versionStringLength) {
407 baseNewVersion.prepend(
"0");
410 QString newFilename = filenameNoExtension +
"_" + QString::number(versionToUse) + extension;
411 bool success = !QFileInfo(location +
"/" + newFilename).exists();
414 qCritical() <<
"The new filename for the bundle does exist." << newFilename;
428 const QByteArray &data)
const
441 const QByteArray &data)
444 QFileInfo oldFileInfo(filename);
446 QString newName = oldFileInfo.fileName();
447 QString newLocation = newDir +
'/' + newName;
449 QFileInfo newFileInfo(newLocation);
450 if (newFileInfo.exists()) {
454 }
else if (importOption ==
Rename) {
456 newLocation = newDir +
'/' + newName;
457 newFileInfo = QFileInfo(newLocation);
468 if (
data.isEmpty()) {
469 QFile::copy(filename, newLocation);
471 QSaveFile f(newLocation);
472 f.setDirectWriteFallback(
false);
474 if (!f.open(QIODevice::WriteOnly) || f.write(
data) !=
data.size() || !f.flush()) {
475 qWarning() <<
"Error writing" <<
data.size() <<
"bytes to" << newLocation <<
"storage:" << f.errorString();
485 if (storage.isNull()) {
return false; }
487 qWarning() <<
"Could not add bundle to the storages" << newLocation;
495 QVariant
v = QVariant();
496 if (role != Qt::DisplayRole) {
499 if (orientation == Qt::Horizontal) {
506 return i18n(
"Location");
508 return i18n(
"Creation Date");
510 return i18n(
"Preinstalled");
512 return i18n(
"Active");
514 return i18n(
"Thumbnail");
518 v = QString::number(section);
522 return QAbstractTableModel::headerData(section, orientation, role);
528 d->storages.append(location);
534 int row =
d->storages.indexOf(QFileInfo(location).fileName());
535 beginRemoveRows(QModelIndex(), row, row);
536 d->storages.removeAt(row);
553 bool r = query.prepare(
558 qWarning() <<
"Could not prepare KisStorageModel query" << query.lastError();
564 qWarning() <<
"Could not execute KisStorageModel query" << query.lastError();
568 while (query.next()) {
569 d->storages << query.value(0).toString();
float value(const T *src, size_t ch)
QList< QString > QStringList
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
QString findUnusedName(QString location, QString filename)
QMap< QString, QVariant > metaDataForStorage(const QString &storageLocation) const
metaDataForStorage
KisResourceStorageSP storageByLocation(const QString &location) const
void storageRemoved(const QString &location)
Emitted whenever a storage is removed.
void storageAdded(const QString &location)
Emitted whenever a storage is added.
void storagesBulkSynchronizationFinished()
void storageResynchronized(const QString &storage, bool isBulkResynchronization)
static KisResourceLocator * instance()
static const QString s_meta_title
static const QString s_meta_name
void insert(const QString &storageLocation, const QString &resourceType, const QString &filename, const QImage &image)
static KisResourceThumbnailCache * instance()
QImage originalImage(const QString &storageLocation, const QString &resourceType, const QString &filename) const
static KisStorageModel * instance()
void storageDisabled(const QString &storage)
~KisStorageModel() override
bool importStorage(const QString &filename, StorageImportOption importOption) const
static QImage getThumbnailFromQuery(const QSqlQuery &query)
bool setData(const QModelIndex &index, const QVariant &value, int role) override
Enable and disable the storage represented by index.
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
KisStorageModel(QObject *parent=0)
void removeStorage(const QString &location)
This is called when a storage really is deleted both from database and anywhere else.
QScopedPointer< Private > d
int columnCount(const QModelIndex &parent=QModelIndex()) const override
void addStorage(const QString &location)
Called whenever a storage is added.
void storageEnabled(const QString &storage)
void storageResynchronized(const QString &storage, bool isBulkResynchronization)
Emitted when an individual storage is initialized.
KisResourceStorageSP storageForIndex(const QModelIndex &index) const
int rowCount(const QModelIndex &parent=QModelIndex()) const override
KisResourceStorageSP storageForId(const int storageId) const
Qt::ItemFlags flags(const QModelIndex &index) const override
QVariant data(const QModelIndex &index, int role) const override
static bool importStorageInternal(const QString &filename, StorageImportOption importOption, bool dryRun, const QByteArray &data)
void slotStoragesBulkSynchronizationFinished()
called when storages finished synchronization process
bool importStorageData(const QString &filename, StorageImportOption importOption, const QByteArray &data) const
void storagesBulkSynchronizationFinished()
Emitted on loading when all the storages are finished initialization.
bool canImportStorage(const QString &filename) const
static QString getAppDataLocation()
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
QList< QString > storages