Implement disk caching of album art (#360)
* Implement disk caching of album art This includes a button to clear the cache in the settings, as requested. Closes #358 * Make the cache size defaults match * Implement the review by jonaski * Fix more problems with the PR
This commit is contained in:
parent
ab7b65a30b
commit
691f5d99ca
|
@ -158,6 +158,7 @@ void SCollection::ResumeWatcher() { watcher_->SetRescanPausedAsync(false); }
|
|||
void SCollection::ReloadSettings() {
|
||||
|
||||
watcher_->ReloadSettingsAsync();
|
||||
model_->ReloadSettings();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -899,6 +899,10 @@ SongList CollectionBackend::GetCompilationSongs(const QString &album, const Quer
|
|||
|
||||
}
|
||||
|
||||
Song::Source CollectionBackend::Source() const {
|
||||
return source_;
|
||||
}
|
||||
|
||||
void CollectionBackend::UpdateCompilations() {
|
||||
|
||||
QMutexLocker l(db_->Mutex());
|
||||
|
|
|
@ -188,6 +188,8 @@ class CollectionBackend : public CollectionBackendInterface {
|
|||
SongList GetSongsBySongId(const QList<int> &song_ids);
|
||||
SongList GetSongsBySongId(const QStringList &song_ids);
|
||||
|
||||
Song::Source Source() const;
|
||||
|
||||
public slots:
|
||||
void Exit();
|
||||
void LoadDirectories();
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include <QImage>
|
||||
#include <QPixmapCache>
|
||||
#include <QSettings>
|
||||
#include <QStandardPaths>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/application.h"
|
||||
|
@ -63,6 +64,7 @@
|
|||
#include "playlist/playlistmanager.h"
|
||||
#include "playlist/songmimedata.h"
|
||||
#include "covermanager/albumcoverloader.h"
|
||||
#include "settings/collectionsettingspage.h"
|
||||
|
||||
using std::bind;
|
||||
using std::sort;
|
||||
|
@ -71,7 +73,9 @@ using std::placeholders::_2;
|
|||
|
||||
const char *CollectionModel::kSavedGroupingsSettingsGroup = "SavedGroupings";
|
||||
const int CollectionModel::kPrettyCoverSize = 32;
|
||||
const int CollectionModel::kPixmapCacheLimit = QPixmapCache::cacheLimit() * 8;
|
||||
const char *CollectionModel::kPixmapDiskCacheDir = "/pixmapcache";
|
||||
|
||||
QNetworkDiskCache *CollectionModel::sIconCache = nullptr;
|
||||
|
||||
static bool IsArtistGroupBy(const CollectionModel::GroupBy by) {
|
||||
return by == CollectionModel::GroupBy_Artist || by == CollectionModel::GroupBy_AlbumArtist;
|
||||
|
@ -96,7 +100,8 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
|
|||
playlist_icon_(IconLoader::Load("albums")),
|
||||
init_task_id_(-1),
|
||||
use_pretty_covers_(false),
|
||||
show_dividers_(true) {
|
||||
show_dividers_(true),
|
||||
use_disk_cache_(false) {
|
||||
|
||||
root_->lazy_loaded = true;
|
||||
|
||||
|
@ -115,6 +120,11 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
|
|||
no_cover_icon_ = nocover.pixmap(nocover.availableSizes().last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
//no_cover_icon_ = QPixmap(":/pictures/noalbumart.png").scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
// When running under gdb, all calls to this constructor came from the same thread.
|
||||
// If this ever changes, these two lines might need to be protected by a mutex.
|
||||
if (sIconCache == nullptr)
|
||||
sIconCache = new QNetworkDiskCache(this);
|
||||
|
||||
connect(backend_, SIGNAL(SongsDiscovered(SongList)), SLOT(SongsDiscovered(SongList)));
|
||||
connect(backend_, SIGNAL(SongsDeleted(SongList)), SLOT(SongsDeleted(SongList)));
|
||||
connect(backend_, SIGNAL(DatabaseReset()), SLOT(Reset()));
|
||||
|
@ -127,7 +137,9 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
|
|||
backend_->UpdateTotalArtistCountAsync();
|
||||
backend_->UpdateTotalAlbumCountAsync();
|
||||
|
||||
QPixmapCache::setCacheLimit(kPixmapCacheLimit);
|
||||
connect(app_, SIGNAL(ClearPixmapDiskCache()), SLOT(ClearDiskCache()));
|
||||
|
||||
ReloadSettings();
|
||||
|
||||
}
|
||||
|
||||
|
@ -165,6 +177,26 @@ void CollectionModel::SaveGrouping(QString name) {
|
|||
|
||||
}
|
||||
|
||||
void CollectionModel::ReloadSettings() {
|
||||
|
||||
QSettings s;
|
||||
|
||||
s.beginGroup(CollectionSettingsPage::kSettingsGroup);
|
||||
|
||||
use_disk_cache_ = s.value(CollectionSettingsPage::kSettingsDiskCacheEnable, false).toBool();
|
||||
|
||||
if (!use_disk_cache_) {
|
||||
sIconCache->clear();
|
||||
}
|
||||
|
||||
sIconCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + kPixmapDiskCacheDir);
|
||||
sIconCache->setMaximumCacheSize(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsDiskCacheSize, CollectionSettingsPage::kSettingsDiskCacheSizeUnit));
|
||||
|
||||
QPixmapCache::setCacheLimit(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsCacheSize, CollectionSettingsPage::kSettingsCacheSizeUnit) / 1024);
|
||||
|
||||
s.endGroup();
|
||||
}
|
||||
|
||||
void CollectionModel::Init(bool async) {
|
||||
|
||||
if (async) {
|
||||
|
@ -476,6 +508,7 @@ void CollectionModel::SongsDeleted(const SongList &songs) {
|
|||
// Remove from pixmap cache
|
||||
const QString cache_key = AlbumIconPixmapCacheKey(ItemToIndex(node));
|
||||
QPixmapCache::remove(cache_key);
|
||||
if (use_disk_cache_) sIconCache->remove(QUrl(cache_key));
|
||||
if (pending_cache_keys_.contains(cache_key)) {
|
||||
pending_cache_keys_.remove(cache_key);
|
||||
}
|
||||
|
@ -532,7 +565,7 @@ QString CollectionModel::AlbumIconPixmapCacheKey(const QModelIndex &idx) const {
|
|||
idx_copy = idx_copy.parent();
|
||||
}
|
||||
|
||||
return "collectionart:" + path.join("/");
|
||||
return Song::TextForSource(backend_->Source()) + path.join("/");
|
||||
|
||||
}
|
||||
|
||||
|
@ -549,6 +582,18 @@ QVariant CollectionModel::AlbumIcon(const QModelIndex &idx) {
|
|||
return cached_pixmap;
|
||||
}
|
||||
|
||||
// Try to load it from the disk cache
|
||||
if (use_disk_cache_) {
|
||||
std::unique_ptr<QIODevice> cache(sIconCache->data(QUrl(cache_key)));
|
||||
if (cache) {
|
||||
QImage cached_pixmap;
|
||||
if (cached_pixmap.load(cache.get(), "XPM")) {
|
||||
QPixmapCache::insert(cache_key, QPixmap::fromImage(cached_pixmap));
|
||||
return QPixmap::fromImage(cached_pixmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Maybe we're loading a pixmap already?
|
||||
if (pending_cache_keys_.contains(cache_key)) {
|
||||
return no_cover_icon_;
|
||||
|
@ -591,6 +636,21 @@ void CollectionModel::AlbumCoverLoaded(const quint64 id, const QUrl &cover_url,
|
|||
QPixmapCache::insert(cache_key, image_pixmap);
|
||||
}
|
||||
|
||||
// If we have a valid cover not already in the disk cache
|
||||
if (use_disk_cache_) {
|
||||
std::unique_ptr<QIODevice> cached_img(sIconCache->data(QUrl(cache_key)));
|
||||
if (!cached_img && !image.isNull()) {
|
||||
QNetworkCacheMetaData item_metadata;
|
||||
item_metadata.setSaveToDisk(true);
|
||||
item_metadata.setUrl(QUrl(cache_key));
|
||||
QIODevice* cache = sIconCache->prepare(item_metadata);
|
||||
if (cache) {
|
||||
image.save(cache, "XPM");
|
||||
sIconCache->insert(cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QModelIndex idx = ItemToIndex(item);
|
||||
if (!idx.isValid()) return;
|
||||
|
||||
|
@ -1479,6 +1539,19 @@ bool CollectionModel::CompareItems(const CollectionItem *a, const CollectionItem
|
|||
|
||||
}
|
||||
|
||||
int CollectionModel::MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id) const {
|
||||
|
||||
int size = s->value(size_id, 80).toInt();
|
||||
int unit = s->value(size_unit_id, CollectionSettingsPage::CacheSizeUnit::CacheSizeUnit_MB).toInt() + 1;
|
||||
|
||||
do {
|
||||
size *= 1024;
|
||||
unit -= 1;
|
||||
} while (unit > 0);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void CollectionModel::GetChildSongs(CollectionItem *item, QList<QUrl> *urls, SongList *songs, QSet<int> *song_ids) const {
|
||||
|
||||
switch (item->type) {
|
||||
|
@ -1606,6 +1679,10 @@ void CollectionModel::TotalAlbumCountUpdatedSlot(int count) {
|
|||
|
||||
}
|
||||
|
||||
void CollectionModel::ClearDiskCache() {
|
||||
sIconCache->clear();
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &s, const CollectionModel::Grouping &g) {
|
||||
s << quint32(g.first) << quint32(g.second) << quint32(g.third);
|
||||
return s;
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <QImage>
|
||||
#include <QIcon>
|
||||
#include <QPixmap>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QSettings>
|
||||
|
||||
#include "core/simpletreemodel.h"
|
||||
|
@ -69,7 +70,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
|||
static const char *kSavedGroupingsSettingsGroup;
|
||||
|
||||
static const int kPrettyCoverSize;
|
||||
static const int kPixmapCacheLimit;
|
||||
static const char *kPixmapDiskCacheDir;
|
||||
|
||||
enum Role {
|
||||
Role_Type = Qt::UserRole + 1,
|
||||
|
@ -162,6 +163,9 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
|||
// Save the current grouping
|
||||
void SaveGrouping(QString name);
|
||||
|
||||
// Reload settings.
|
||||
void ReloadSettings();
|
||||
|
||||
// Utility functions for manipulating text
|
||||
static QString TextOrUnknown(const QString &text);
|
||||
static QString PrettyYearAlbum(const int year, const QString &album);
|
||||
|
@ -203,6 +207,7 @@ signals:
|
|||
void TotalSongCountUpdatedSlot(int count);
|
||||
void TotalArtistCountUpdatedSlot(int count);
|
||||
void TotalAlbumCountUpdatedSlot(int count);
|
||||
void ClearDiskCache();
|
||||
|
||||
// Called after ResetAsync
|
||||
void ResetAsyncQueryFinished(QFuture<CollectionModel::QueryResult> future);
|
||||
|
@ -244,6 +249,7 @@ signals:
|
|||
QVariant AlbumIcon(const QModelIndex &idx);
|
||||
QVariant data(const CollectionItem *item, int role) const;
|
||||
bool CompareItems(const CollectionItem *a, const CollectionItem *b) const;
|
||||
int MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id) const;
|
||||
|
||||
private:
|
||||
CollectionBackend *backend_;
|
||||
|
@ -274,10 +280,13 @@ signals:
|
|||
QIcon playlists_dir_icon_;
|
||||
QIcon playlist_icon_;
|
||||
|
||||
static QNetworkDiskCache *sIconCache;
|
||||
|
||||
int init_task_id_;
|
||||
|
||||
bool use_pretty_covers_;
|
||||
bool show_dividers_;
|
||||
bool use_disk_cache_;
|
||||
|
||||
AlbumCoverLoaderOptions cover_loader_options_;
|
||||
|
||||
|
|
|
@ -126,6 +126,7 @@ signals:
|
|||
void SettingsChanged();
|
||||
void SettingsDialogRequested(SettingsDialog::Page page);
|
||||
void ExitFinished();
|
||||
void ClearPixmapDiskCache();
|
||||
|
||||
private:
|
||||
std::unique_ptr<ApplicationImpl> p_;
|
||||
|
|
|
@ -469,17 +469,17 @@ Song::Source Song::SourceFromURL(const QUrl &url) {
|
|||
QString Song::TextForSource(Source source) {
|
||||
|
||||
switch (source) {
|
||||
case Song::Source_LocalFile: return QObject::tr("File");
|
||||
case Song::Source_Collection: return QObject::tr("Collection");
|
||||
case Song::Source_CDDA: return QObject::tr("CD");
|
||||
case Song::Source_Device: return QObject::tr("Device");
|
||||
case Song::Source_Stream: return QObject::tr("Stream");
|
||||
case Song::Source_Tidal: return QObject::tr("Tidal");
|
||||
case Song::Source_Subsonic: return QObject::tr("subsonic");
|
||||
case Song::Source_Qobuz: return QObject::tr("qobuz");
|
||||
case Song::Source_Unknown: return QObject::tr("Unknown");
|
||||
case Song::Source_LocalFile: return "file";
|
||||
case Song::Source_Collection: return "collection";
|
||||
case Song::Source_CDDA: return "cd";
|
||||
case Song::Source_Device: return "device";
|
||||
case Song::Source_Stream: return "stream";
|
||||
case Song::Source_Tidal: return "tidal";
|
||||
case Song::Source_Subsonic: return "subsonic";
|
||||
case Song::Source_Qobuz: return "qobuz";
|
||||
case Song::Source_Unknown: return "unknown";
|
||||
}
|
||||
return QObject::tr("Unknown");
|
||||
return "unknown";
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <QPushButton>
|
||||
#include <QSettings>
|
||||
|
||||
#include "core/application.h"
|
||||
#include "core/iconloader.h"
|
||||
#include "collection/collectiondirectorymodel.h"
|
||||
#include "collectionsettingspage.h"
|
||||
|
@ -43,6 +44,13 @@
|
|||
#include "ui_collectionsettingspage.h"
|
||||
|
||||
const char *CollectionSettingsPage::kSettingsGroup = "Collection";
|
||||
const char *CollectionSettingsPage::kSettingsCacheSize = "cache_size";
|
||||
const char *CollectionSettingsPage::kSettingsCacheSizeUnit = "cache_size_unit";
|
||||
const char *CollectionSettingsPage::kSettingsDiskCacheEnable = "disk_cache_enable";
|
||||
const char *CollectionSettingsPage::kSettingsDiskCacheSize = "disk_cache_size";
|
||||
const char *CollectionSettingsPage::kSettingsDiskCacheSizeUnit = "disk_cache_size_unit";
|
||||
|
||||
const QStringList CollectionSettingsPage::cacheUnitNames = { "KB", "MB", "GB", "TB" };
|
||||
|
||||
CollectionSettingsPage::CollectionSettingsPage(SettingsDialog *dialog)
|
||||
: SettingsPage(dialog),
|
||||
|
@ -91,6 +99,14 @@ void CollectionSettingsPage::CurrentRowChanged(const QModelIndex& index) {
|
|||
ui_->remove->setEnabled(index.isValid());
|
||||
}
|
||||
|
||||
void CollectionSettingsPage::DiskCacheEnable(int state) {
|
||||
bool checked = state == Qt::Checked;
|
||||
ui_->button_disk_cache->setEnabled(checked);
|
||||
ui_->label_disk_cache_size->setEnabled(checked);
|
||||
ui_->spinbox_disk_cache_size->setEnabled(checked);
|
||||
ui_->combobox_disk_cache_size->setEnabled(checked);
|
||||
}
|
||||
|
||||
void CollectionSettingsPage::Load() {
|
||||
|
||||
if (!initialised_model_) {
|
||||
|
@ -130,6 +146,20 @@ void CollectionSettingsPage::Load() {
|
|||
ui_->checkbox_cover_lowercase->setChecked(s.value("cover_lowercase", true).toBool());
|
||||
ui_->checkbox_cover_replace_spaces->setChecked(s.value("cover_replace_spaces", true).toBool());
|
||||
|
||||
ui_->spinbox_cache_size->setValue(s.value(kSettingsCacheSize, 80).toInt());
|
||||
ui_->combobox_cache_size->addItems(cacheUnitNames);
|
||||
ui_->combobox_cache_size->setCurrentIndex(s.value(kSettingsCacheSizeUnit, (int) CacheSizeUnit_MB).toInt());
|
||||
ui_->checkbox_disk_cache->setChecked(s.value(kSettingsDiskCacheEnable, false).toBool());
|
||||
ui_->label_disk_cache_size->setEnabled(ui_->checkbox_disk_cache->isChecked());
|
||||
ui_->spinbox_disk_cache_size->setEnabled(ui_->checkbox_disk_cache->isChecked());
|
||||
ui_->spinbox_disk_cache_size->setValue(s.value(kSettingsDiskCacheSize, 80).toInt());
|
||||
ui_->combobox_disk_cache_size->setEnabled(ui_->checkbox_disk_cache->isChecked());
|
||||
ui_->combobox_disk_cache_size->addItems(cacheUnitNames);
|
||||
ui_->combobox_disk_cache_size->setCurrentIndex(s.value(kSettingsDiskCacheSizeUnit, (int) CacheSizeUnit_MB).toInt());
|
||||
|
||||
connect(ui_->checkbox_disk_cache, SIGNAL(stateChanged(int)), SLOT(DiskCacheEnable(int)));
|
||||
connect(ui_->button_disk_cache, SIGNAL(clicked()), dialog()->app(), SIGNAL(ClearPixmapDiskCache()));
|
||||
|
||||
s.endGroup();
|
||||
|
||||
}
|
||||
|
@ -161,6 +191,12 @@ void CollectionSettingsPage::Save() {
|
|||
s.setValue("cover_lowercase", ui_->checkbox_cover_lowercase->isChecked());
|
||||
s.setValue("cover_replace_spaces", ui_->checkbox_cover_replace_spaces->isChecked());
|
||||
|
||||
s.setValue(kSettingsCacheSize, ui_->spinbox_cache_size->value());
|
||||
s.setValue(kSettingsCacheSizeUnit, ui_->combobox_cache_size->currentIndex());
|
||||
s.setValue(kSettingsDiskCacheEnable, ui_->checkbox_disk_cache->isChecked());
|
||||
s.setValue(kSettingsDiskCacheSize, ui_->spinbox_disk_cache_size->value());
|
||||
s.setValue(kSettingsDiskCacheSizeUnit, ui_->combobox_disk_cache_size->currentIndex());
|
||||
|
||||
s.endGroup();
|
||||
|
||||
}
|
||||
|
|
|
@ -39,6 +39,18 @@ public:
|
|||
~CollectionSettingsPage();
|
||||
|
||||
static const char *kSettingsGroup;
|
||||
static const char *kSettingsCacheSize;
|
||||
static const char *kSettingsCacheSizeUnit;
|
||||
static const char *kSettingsDiskCacheEnable;
|
||||
static const char *kSettingsDiskCacheSize;
|
||||
static const char *kSettingsDiskCacheSizeUnit;
|
||||
|
||||
enum CacheSizeUnit {
|
||||
CacheSizeUnit_KB,
|
||||
CacheSizeUnit_MB,
|
||||
CacheSizeUnit_GB,
|
||||
CacheSizeUnit_TB,
|
||||
};
|
||||
|
||||
enum SaveCover {
|
||||
SaveCover_Hash = 1,
|
||||
|
@ -53,11 +65,14 @@ private slots:
|
|||
void Remove();
|
||||
|
||||
void CurrentRowChanged(const QModelIndex &index);
|
||||
void DiskCacheEnable(int state);
|
||||
void CoverSaveInAlbumDirChanged();
|
||||
|
||||
private:
|
||||
Ui_CollectionSettingsPage *ui_;
|
||||
bool initialised_model_;
|
||||
|
||||
static const QStringList cacheUnitNames;
|
||||
};
|
||||
|
||||
#endif // COLLECTIONSETTINGSPAGE_H
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>509</width>
|
||||
<height>746</height>
|
||||
<height>913</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -249,6 +249,99 @@ If there are no matches then it will use the largest image in the directory.</st
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="albumArtGroupBox">
|
||||
<property name="title">
|
||||
<string>Album art cache</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_cache_size">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinbox_cache_size">
|
||||
<property name="maximum">
|
||||
<number>1048576</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="combobox_cache_size">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkbox_disk_cache">
|
||||
<property name="text">
|
||||
<string>Enable Disk Cache</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_disk_cache">
|
||||
<property name="text">
|
||||
<string>Clear Disk Cache</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_disk_cache_size">
|
||||
<property name="text">
|
||||
<string>Disk Cache Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinbox_disk_cache_size">
|
||||
<property name="maximum">
|
||||
<number>1048576</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="combobox_disk_cache_size">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
Loading…
Reference in New Issue