mirror of https://github.com/mgba-emu/mgba.git
Qt: Begin library view
This commit is contained in:
parent
480415c51e
commit
91fd2c6b47
|
@ -23,3 +23,7 @@ ArchiveInspector::ArchiveInspector(const QString& filename, QWidget* parent)
|
|||
VFile* ArchiveInspector::selectedVFile() const {
|
||||
return m_ui.archiveView->selectedVFile();
|
||||
}
|
||||
|
||||
QPair<QString, QString> ArchiveInspector::selectedPath() const {
|
||||
return m_ui.archiveView->selectedPath();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ public:
|
|||
ArchiveInspector(const QString& filename, QWidget* parent = nullptr);
|
||||
|
||||
VFile* selectedVFile() const;
|
||||
QPair<QString, QString> selectedPath() const;
|
||||
|
||||
private:
|
||||
Ui::ArchiveInspector m_ui;
|
||||
|
|
|
@ -164,6 +164,10 @@ QString ConfigController::getOption(const char* key) const {
|
|||
return QString(mCoreConfigGetValue(&m_config, key));
|
||||
}
|
||||
|
||||
QString ConfigController::getOption(const QString& key) const {
|
||||
return getOption(key.toUtf8().constData());
|
||||
}
|
||||
|
||||
QVariant ConfigController::getQtOption(const QString& key, const QString& group) const {
|
||||
if (!group.isNull()) {
|
||||
m_settings->beginGroup(group);
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
void updateOption(const char* key);
|
||||
|
||||
QString getOption(const char* key) const;
|
||||
QString getOption(const QString& key) const;
|
||||
|
||||
QVariant getQtOption(const QString& key, const QString& group = QString()) const;
|
||||
|
||||
|
|
|
@ -145,7 +145,11 @@ GameController::GameController(QObject* parent)
|
|||
controller->m_multiplayer->attachGame(controller);
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(controller, "gameStarted", Q_ARG(mCoreThread*, context), Q_ARG(const QString&, controller->m_fname));
|
||||
QString path = controller->m_fname;
|
||||
if (!controller->m_fsub.isEmpty()) {
|
||||
path += QDir::separator() + controller->m_fsub;
|
||||
}
|
||||
QMetaObject::invokeMethod(controller, "gameStarted", Q_ARG(mCoreThread*, context), Q_ARG(const QString&, path));
|
||||
QMetaObject::invokeMethod(controller, "startAudio");
|
||||
};
|
||||
|
||||
|
@ -369,17 +373,48 @@ void GameController::loadGame(const QString& path) {
|
|||
closeGame();
|
||||
QFileInfo info(path);
|
||||
if (!info.isReadable()) {
|
||||
LOG(QT, ERROR) << tr("Failed to open game file: %1").arg(path);
|
||||
QString fname = info.fileName();
|
||||
QString base = info.path();
|
||||
if (base.endsWith("/") || base.endsWith(QDir::separator())) {
|
||||
base.chop(1);
|
||||
}
|
||||
VDir* dir = VDirOpenArchive(base.toUtf8().constData());
|
||||
if (dir) {
|
||||
VFile* vf = dir->openFile(dir, fname.toUtf8().constData(), O_RDONLY);
|
||||
if (vf) {
|
||||
struct VFile* vfclone = VFileMemChunk(NULL, vf->size(vf));
|
||||
uint8_t buffer[2048];
|
||||
ssize_t read;
|
||||
while ((read = vf->read(vf, buffer, sizeof(buffer))) > 0) {
|
||||
vfclone->write(vfclone, buffer, read);
|
||||
}
|
||||
vf->close(vf);
|
||||
vf = vfclone;
|
||||
}
|
||||
dir->close(dir);
|
||||
loadGame(vf, fname, base);
|
||||
} else {
|
||||
LOG(QT, ERROR) << tr("Failed to open game file: %1").arg(path);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
m_fname = info.canonicalFilePath();
|
||||
m_fsub = QString();
|
||||
}
|
||||
m_fname = info.canonicalFilePath();
|
||||
m_vf = nullptr;
|
||||
openGame();
|
||||
}
|
||||
|
||||
void GameController::loadGame(VFile* vf, const QString& base) {
|
||||
void GameController::loadGame(VFile* vf, const QString& path, const QString& base) {
|
||||
closeGame();
|
||||
m_fname = base;
|
||||
QFileInfo info(base);
|
||||
if (info.isDir()) {
|
||||
m_fname = base + QDir::separator() + path;
|
||||
m_fsub = QString();
|
||||
} else {
|
||||
m_fname = base;
|
||||
m_fsub = path;
|
||||
}
|
||||
m_vf = vf;
|
||||
openGame();
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ signals:
|
|||
|
||||
public slots:
|
||||
void loadGame(const QString& path);
|
||||
void loadGame(VFile* vf, const QString& base);
|
||||
void loadGame(VFile* vf, const QString& path, const QString& base);
|
||||
void loadBIOS(int platform, const QString& path);
|
||||
void loadSave(const QString& path, bool temporary = true);
|
||||
void yankPak();
|
||||
|
@ -198,6 +198,7 @@ private:
|
|||
bool m_gameOpen;
|
||||
|
||||
QString m_fname;
|
||||
QString m_fsub;
|
||||
VFile* m_vf;
|
||||
QString m_bios;
|
||||
bool m_useBios;
|
||||
|
|
|
@ -23,7 +23,7 @@ LibraryModel::LibraryModel(const QString& path, QObject* parent)
|
|||
s_columns["filename"] = {
|
||||
tr("Filename"),
|
||||
[](const mLibraryEntry& e) -> QString {
|
||||
return e.filename;
|
||||
return QString::fromUtf8(e.filename);
|
||||
}
|
||||
};
|
||||
s_columns["size"] = {
|
||||
|
@ -60,6 +60,12 @@ LibraryModel::LibraryModel(const QString& path, QObject* parent)
|
|||
}
|
||||
}
|
||||
};
|
||||
s_columns["location"] = {
|
||||
tr("Location"),
|
||||
[](const mLibraryEntry& e) -> QString {
|
||||
return QString::fromUtf8(e.base);
|
||||
}
|
||||
};
|
||||
}
|
||||
if (!path.isNull()) {
|
||||
if (s_handles.contains(path)) {
|
||||
|
@ -75,6 +81,7 @@ LibraryModel::LibraryModel(const QString& path, QObject* parent)
|
|||
memset(&m_constraints, 0, sizeof(m_constraints));
|
||||
m_constraints.platform = PLATFORM_NONE;
|
||||
m_columns.append(s_columns["filename"]);
|
||||
m_columns.append(s_columns["location"]);
|
||||
m_columns.append(s_columns["platform"]);
|
||||
m_columns.append(s_columns["size"]);
|
||||
|
||||
|
@ -114,6 +121,22 @@ VFile* LibraryModel::openVFile(const QModelIndex& index) const {
|
|||
return mLibraryOpenVFile(m_library->library, &entry);
|
||||
}
|
||||
|
||||
QString LibraryModel::filename(const QModelIndex& index) const {
|
||||
mLibraryEntry entry;
|
||||
if (!entryAt(index.row(), &entry)) {
|
||||
return QString();
|
||||
}
|
||||
return QString::fromUtf8(entry.filename);
|
||||
}
|
||||
|
||||
QString LibraryModel::location(const QModelIndex& index) const {
|
||||
mLibraryEntry entry;
|
||||
if (!entryAt(index.row(), &entry)) {
|
||||
return QString();
|
||||
}
|
||||
return QString::fromUtf8(entry.base);
|
||||
}
|
||||
|
||||
QVariant LibraryModel::data(const QModelIndex& index, int role) const {
|
||||
if (!index.isValid()) {
|
||||
return QVariant();
|
||||
|
|
|
@ -29,6 +29,8 @@ public:
|
|||
|
||||
bool entryAt(int row, mLibraryEntry* out) const;
|
||||
VFile* openVFile(const QModelIndex& index) const;
|
||||
QString filename(const QModelIndex& index) const;
|
||||
QString location(const QModelIndex& index) const;
|
||||
|
||||
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
|
|
@ -29,6 +29,10 @@ void LibraryView::setDirectory(const QString& filename) {
|
|||
m_model.constrainBase(filename);
|
||||
}
|
||||
|
||||
void LibraryView::addDirectory(const QString& filename) {
|
||||
m_model.loadDirectory(filename);
|
||||
}
|
||||
|
||||
VFile* LibraryView::selectedVFile() const {
|
||||
QModelIndex index = m_ui.listing->selectionModel()->currentIndex();
|
||||
if (!index.isValid()) {
|
||||
|
@ -37,6 +41,14 @@ VFile* LibraryView::selectedVFile() const {
|
|||
return m_model.openVFile(index);
|
||||
}
|
||||
|
||||
QPair<QString, QString> LibraryView::selectedPath() const {
|
||||
QModelIndex index = m_ui.listing->selectionModel()->currentIndex();
|
||||
if (!index.isValid()) {
|
||||
return qMakePair(QString(), QString());
|
||||
}
|
||||
return qMakePair(m_model.filename(index), m_model.location(index));
|
||||
}
|
||||
|
||||
void LibraryView::resizeColumns() {
|
||||
m_ui.listing->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
LibraryView(QWidget* parent = nullptr);
|
||||
|
||||
VFile* selectedVFile() const;
|
||||
QPair<QString, QString> selectedPath() const;
|
||||
|
||||
signals:
|
||||
void doneLoading();
|
||||
|
@ -28,6 +29,7 @@ signals:
|
|||
|
||||
public slots:
|
||||
void setDirectory(const QString&);
|
||||
void addDirectory(const QString&);
|
||||
|
||||
private slots:
|
||||
void resizeColumns();
|
||||
|
|
|
@ -13,7 +13,10 @@
|
|||
<property name="windowTitle">
|
||||
<string>Library</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<layout class="QGridLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTableView" name="listing">
|
||||
<property name="editTriggers">
|
||||
|
@ -34,6 +37,9 @@
|
|||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderDefaultSectionSize">
|
||||
<number>20</number>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderMinimumSectionSize">
|
||||
<number>0</number>
|
||||
</attribute>
|
||||
|
|
|
@ -202,6 +202,7 @@ void SettingsView::updateConfig() {
|
|||
saveSetting("savestatePath", m_ui.savestatePath);
|
||||
saveSetting("screenshotPath", m_ui.screenshotPath);
|
||||
saveSetting("patchPath", m_ui.patchPath);
|
||||
saveSetting("showLibrary", m_ui.showLibrary);
|
||||
|
||||
if (m_ui.fastForwardUnbounded->isChecked()) {
|
||||
saveSetting("fastForwardRatio", "-1");
|
||||
|
@ -279,6 +280,7 @@ void SettingsView::reloadConfig() {
|
|||
loadSetting("savestatePath", m_ui.savestatePath);
|
||||
loadSetting("screenshotPath", m_ui.screenshotPath);
|
||||
loadSetting("patchPath", m_ui.patchPath);
|
||||
loadSetting("showLibrary", m_ui.showLibrary);
|
||||
|
||||
double fastForwardRatio = loadSetting("fastForwardRatio").toDouble();
|
||||
if (fastForwardRatio <= 0) {
|
||||
|
|
|
@ -45,6 +45,11 @@
|
|||
<string>Audio/Video</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Interface</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Emulation</string>
|
||||
|
@ -72,7 +77,7 @@
|
|||
<item row="1" column="1">
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="av">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
|
@ -384,6 +389,65 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="interface_2">
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="allowOpposingDirections">
|
||||
<property name="text">
|
||||
<string>Allow opposing input directions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="suspendScreensaver">
|
||||
<property name="text">
|
||||
<string>Suspend screensaver</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="pauseOnFocusLost">
|
||||
<property name="text">
|
||||
<string>Pause when inactive</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Library:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="showLibrary">
|
||||
<property name="text">
|
||||
<string>Show when no game open</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="Line" name="line_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="clearCache">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear cache</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="emulation">
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
|
@ -478,38 +542,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="allowOpposingDirections">
|
||||
<property name="text">
|
||||
<string>Allow opposing input directions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QCheckBox" name="suspendScreensaver">
|
||||
<property name="text">
|
||||
<string>Suspend screensaver</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="pauseOnFocusLost">
|
||||
<property name="text">
|
||||
<string>Pause when inactive</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Idle loops:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="idleOptimization">
|
||||
<item>
|
||||
<property name="text">
|
||||
|
@ -528,21 +568,21 @@
|
|||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Savestate extra data:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="saveStateScreenshot">
|
||||
<property name="text">
|
||||
<string>Screenshot</string>
|
||||
|
@ -552,7 +592,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<item row="8" column="1">
|
||||
<widget class="QCheckBox" name="saveStateSave">
|
||||
<property name="text">
|
||||
<string>Save data</string>
|
||||
|
@ -562,7 +602,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<item row="9" column="1">
|
||||
<widget class="QCheckBox" name="saveStateCheats">
|
||||
<property name="text">
|
||||
<string>Cheat codes</string>
|
||||
|
@ -572,14 +612,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>Load extra data:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<item row="11" column="1">
|
||||
<widget class="QCheckBox" name="loadStateScreenshot">
|
||||
<property name="text">
|
||||
<string>Screenshot</string>
|
||||
|
@ -589,20 +629,27 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<item row="12" column="1">
|
||||
<widget class="QCheckBox" name="loadStateSave">
|
||||
<property name="text">
|
||||
<string>Save data</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<item row="13" column="1">
|
||||
<widget class="QCheckBox" name="loadStateCheats">
|
||||
<property name="text">
|
||||
<string>Cheat codes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
<widget class="Line" name="line_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="bios">
|
||||
|
|
|
@ -103,7 +103,30 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
|
|||
m_savedScale = multiplier.toInt();
|
||||
i = m_savedScale;
|
||||
}
|
||||
#ifdef M_CORE_GBA
|
||||
#ifdef USE_SQLITE3
|
||||
m_libraryView = new LibraryView(this);
|
||||
ConfigOption* showLibrary = m_config->addOption("showLibrary");
|
||||
showLibrary->connect([this](const QVariant& value) {
|
||||
if (value.toBool()) {
|
||||
if (m_controller->isLoaded()) {
|
||||
m_screenWidget->layout()->addWidget(m_libraryView);
|
||||
} else {
|
||||
attachWidget(m_libraryView);
|
||||
}
|
||||
} else {
|
||||
detachWidget(m_libraryView);
|
||||
}
|
||||
}, this);
|
||||
m_config->updateOption("showLibrary");
|
||||
|
||||
connect(m_libraryView, &LibraryView::accepted, [this]() {
|
||||
VFile* output = m_libraryView->selectedVFile();
|
||||
QPair<QString, QString> path = m_libraryView->selectedPath();
|
||||
if (output) {
|
||||
m_controller->loadGame(output, path.first, path.second);
|
||||
}
|
||||
});
|
||||
#elif defined(M_CORE_GBA)
|
||||
m_screenWidget->setSizeHint(QSize(VIDEO_HORIZONTAL_PIXELS * i, VIDEO_VERTICAL_PIXELS * i));
|
||||
#endif
|
||||
m_screenWidget->setPixmap(m_logo);
|
||||
|
@ -367,16 +390,25 @@ void Window::selectROMInArchive() {
|
|||
return;
|
||||
}
|
||||
ArchiveInspector* archiveInspector = new ArchiveInspector(filename);
|
||||
connect(archiveInspector, &QDialog::accepted, [this, archiveInspector, filename]() {
|
||||
connect(archiveInspector, &QDialog::accepted, [this, archiveInspector]() {
|
||||
VFile* output = archiveInspector->selectedVFile();
|
||||
QPair<QString, QString> path = archiveInspector->selectedPath();
|
||||
if (output) {
|
||||
m_controller->loadGame(output, filename);
|
||||
m_controller->loadGame(output, path.second, path.first);
|
||||
}
|
||||
archiveInspector->close();
|
||||
});
|
||||
archiveInspector->setAttribute(Qt::WA_DeleteOnClose);
|
||||
archiveInspector->show();
|
||||
}
|
||||
|
||||
void Window::addDirToLibrary() {
|
||||
QString filename = GBAApp::app()->getOpenDirectoryName(this, tr("Select folder"));
|
||||
if (filename.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
m_libraryView->addDirectory(filename);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Window::replaceROM() {
|
||||
|
@ -886,8 +918,12 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
installEventFilter(m_shortcutController);
|
||||
addControlledAction(fileMenu, fileMenu->addAction(tr("Load &ROM..."), this, SLOT(selectROM()), QKeySequence::Open),
|
||||
"loadROM");
|
||||
#ifdef USE_SQLITE3
|
||||
addControlledAction(fileMenu, fileMenu->addAction(tr("Load ROM in archive..."), this, SLOT(selectROMInArchive())),
|
||||
"loadROMInArchive");
|
||||
addControlledAction(fileMenu, fileMenu->addAction(tr("Add folder to library..."), this, SLOT(addDirToLibrary())),
|
||||
"addDirToLibrary");
|
||||
#endif
|
||||
|
||||
QAction* loadTemporarySave = new QAction(tr("Load temporary save..."), fileMenu);
|
||||
connect(loadTemporarySave, &QAction::triggered, [this]() { this->selectSave(true); });
|
||||
|
|
|
@ -28,6 +28,7 @@ class Display;
|
|||
class GameController;
|
||||
class GDBController;
|
||||
class GIFView;
|
||||
class LibraryView;
|
||||
class LogView;
|
||||
class ShaderSelector;
|
||||
class ShortcutController;
|
||||
|
@ -59,6 +60,7 @@ public slots:
|
|||
void selectROM();
|
||||
#ifdef USE_SQLITE3
|
||||
void selectROMInArchive();
|
||||
void addDirToLibrary();
|
||||
#endif
|
||||
void selectSave(bool temporary);
|
||||
void selectPatch();
|
||||
|
@ -191,6 +193,10 @@ private:
|
|||
#ifdef USE_GDB_STUB
|
||||
GDBController* m_gdbController;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SQLITE3
|
||||
LibraryView* m_libraryView;
|
||||
#endif
|
||||
};
|
||||
|
||||
class WindowBackground : public QLabel {
|
||||
|
|
Loading…
Reference in New Issue