diff --git a/Makefile.common b/Makefile.common index 44d9185717..2152bae548 100644 --- a/Makefile.common +++ b/Makefile.common @@ -336,7 +336,8 @@ OBJ += ui/drivers/ui_qt.o \ ui/drivers/qt/flowlayout.o MOC_HEADERS += ui/drivers/ui_qt.h \ - ui/drivers/qt/ui_qt_load_core_window.h + ui/drivers/qt/ui_qt_load_core_window.h \ + ui/drivers/qt/flowlayout.h DEFINES += $(QT5CORE_CFLAGS) $(QT5GUI_CFLAGS) $(QT5WIDGETS_CFLAGS) $(QT5CONCURRENT_CFLAGS) -DHAVE_MAIN #DEFINES += $(QT5WEBENGINE_CFLAGS) diff --git a/ui/drivers/qt/flowlayout.cpp b/ui/drivers/qt/flowlayout.cpp index 6719c13f5c..8f8ba5333a 100644 --- a/ui/drivers/qt/flowlayout.cpp +++ b/ui/drivers/qt/flowlayout.cpp @@ -60,6 +60,8 @@ FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing) : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing) { setContentsMargins(margin, margin, margin, margin); + + connect(this, SIGNAL(signalAddWidgetDeferred(QWidget*)), this, SLOT(onAddWidgetDeferred(QWidget*)), Qt::QueuedConnection); } FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing) @@ -70,9 +72,9 @@ FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing) FlowLayout::~FlowLayout() { - QLayoutItem *item; + QLayoutItem *item = NULL; - while ((item = takeAt(0))) + while ((item = takeAt(0)) != NULL) delete item; } @@ -229,3 +231,13 @@ int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const else return static_cast(parentObj)->spacing(); } + +void FlowLayout::addWidgetDeferred(QWidget *widget) +{ + emit signalAddWidgetDeferred(widget); +} + +void FlowLayout::onAddWidgetDeferred(QWidget *widget) +{ + addWidget(widget); +} diff --git a/ui/drivers/qt/flowlayout.h b/ui/drivers/qt/flowlayout.h index 282a43df94..84dc349d51 100644 --- a/ui/drivers/qt/flowlayout.h +++ b/ui/drivers/qt/flowlayout.h @@ -65,6 +65,7 @@ class FlowLayout : public QLayout { + Q_OBJECT public: explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1); explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1); @@ -82,6 +83,13 @@ public: void setGeometry(const QRect &rect); QSize sizeHint() const; QLayoutItem* takeAt(int index); + void addWidgetDeferred(QWidget *widget); + +signals: + void signalAddWidgetDeferred(QWidget *widget); + +private slots: + void onAddWidgetDeferred(QWidget *widget); private: int doLayout(const QRect &rect, bool testOnly) const; diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index 00da8a0ac6..6a4d26e759 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -111,6 +111,10 @@ static void scan_finished_handler(void *task_data, void *user_data, const char * menu_environ.type = MENU_ENVIRON_RESET_HORIZONTAL_LIST; menu_environ.data = NULL; + (void)task_data; + (void)user_data; + (void)err; + menu_driver_ctl(RARCH_MENU_CTL_ENVIRONMENT, &menu_environ); if (!ui_window.qtWindow->settings()->value("scan_finish_confirm", true).toBool()) @@ -128,7 +132,6 @@ GridItem::GridItem() : ,image() ,pixmap() ,imageWatcher() - ,mutex() { } @@ -740,7 +743,6 @@ MainWindow::~MainWindow() inline void MainWindow::calcGridItemSize(GridItem *item, int zoomValue) { - QMutexLocker lock(&item->mutex); int newSize = 0; if (zoomValue < 50) @@ -850,12 +852,12 @@ void MainWindow::setCustomThemeString(QString qss) bool MainWindow::showMessageBox(QString msg, MessageBoxType msgType, Qt::WindowModality modality) { - QScopedPointer msgBoxPtr; + QPointer > msgBoxPtr; QMessageBox *msgBox = NULL; QCheckBox *checkBox = NULL; - msgBoxPtr.reset(new QMessageBox(this)); - msgBox = msgBoxPtr.data(); + msgBoxPtr.data()->reset(new QMessageBox(this)); + msgBox = msgBoxPtr.data()->data(); checkBox = new QCheckBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_DONT_SHOW_AGAIN), msgBox); msgBox->setWindowModality(modality); @@ -891,6 +893,9 @@ bool MainWindow::showMessageBox(QString msg, MessageBoxType msgType, Qt::WindowM msgBox->setText(msg); msgBox->exec(); + if (!msgBoxPtr) + return true; + if (checkBox->isChecked()) return false; @@ -904,7 +909,7 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) QScopedPointer associateMenu; QScopedPointer hiddenPlaylistsMenu; QScopedPointer hideAction; - QAction *selectedAction = NULL; + QPointer selectedAction; QPoint cursorPos = QCursor::pos(); QListWidgetItem *selectedItem = m_listWidget->itemAt(m_listWidget->viewport()->mapFromGlobal(cursorPos)); QDir playlistDir(settings->paths.directory_playlist); @@ -1103,7 +1108,7 @@ end: void MainWindow::onFileBrowserTreeContextMenuRequested(const QPoint&) { #ifdef HAVE_LIBRETRODB - QAction *action = NULL; + QPointer action; QList actions; QScopedPointer scanAction; QDir dir; @@ -1153,6 +1158,8 @@ void MainWindow::onGotStatusMessage(QString msg, unsigned priority, unsigned dur QScreen *screen = qApp->primaryScreen(); QStatusBar *status = statusBar(); + Q_UNUSED(priority) + if (msg.isEmpty()) return; @@ -2831,23 +2838,21 @@ void MainWindow::removeGridItems() { QMutableListIterator items(m_gridItems); + m_pendingItemUpdates.clear(); + while (items.hasNext()) { GridItem *item = items.next(); if (item) { - item->mutex.lock(); + item->imageWatcher.waitForFinished(); items.remove(); m_gridLayout->removeWidget(item->widget); - m_pendingItemUpdates.removeAll(item); delete item->widget; - - item->mutex.unlock(); - delete item; } } @@ -2867,15 +2872,14 @@ void MainWindow::onDeferredImageLoaded() if (!item) return; - item->mutex.lock(); - - if (!item->image.isNull()) + if (m_gridItems.contains(item)) { - m_pendingItemUpdates.append(item); - QTimer::singleShot(0, this, SLOT(onPendingItemUpdates())); + if (!item->image.isNull()) + { + m_pendingItemUpdates.append(item); + QTimer::singleShot(0, this, SLOT(onPendingItemUpdates())); + } } - - item->mutex.unlock(); } void MainWindow::onPendingItemUpdates() @@ -2889,7 +2893,8 @@ void MainWindow::onPendingItemUpdates() if (!item) continue; - onUpdateGridItemPixmapFromImage(item); + if (m_gridItems.contains(item)) + onUpdateGridItemPixmapFromImage(item); list.remove(); } @@ -2900,6 +2905,9 @@ void MainWindow::onUpdateGridItemPixmapFromImage(GridItem *item) if (!item) return; + if (!m_gridItems.contains(item)) + return; + item->label->setPixmap(QPixmap::fromImage(item->image)); item->label->update(); } @@ -2916,12 +2924,11 @@ GridItem* MainWindow::doDeferredImageLoad(GridItem *item, QString path) if (!item) return NULL; - item->mutex.lock(); - + /* While we are indeed writing across thread boundaries here, the image is never accessed until after + * its thread finishes, and the item is never deleted without first waiting for the thread to finish. + */ item->image = QImage(path); - item->mutex.unlock(); - return item; } @@ -2992,12 +2999,10 @@ void MainWindow::addPlaylistItemsToGrid(const QString &pathString) item->widget->layout()->addWidget(newLabel); qobject_cast(item->widget->layout())->setStretchFactor(label, 1); - m_gridLayout->addWidget(item->widget); + m_gridLayout->addWidgetDeferred(item->widget); m_gridItems.append(item); loadImageDeferred(item, imagePath); - - qApp->processEvents(); } } @@ -3178,12 +3183,6 @@ void MainWindow::addPlaylistItemsToTable(QString pathString) for (i = 0; i < items.count(); i++) { - const char *path = NULL; - const char *label = NULL; - const char *core_path = NULL; - const char *core_name = NULL; - const char *crc32 = NULL; - const char *db_name = NULL; QTableWidgetItem *labelItem = NULL; const QHash &hash = items.at(i); diff --git a/ui/drivers/ui_qt.h b/ui/drivers/ui_qt.h index 5344e2e842..7952fb3c14 100644 --- a/ui/drivers/ui_qt.h +++ b/ui/drivers/ui_qt.h @@ -75,7 +75,6 @@ struct GridItem QImage image; QPixmap pixmap; QFutureWatcher imageWatcher; - QMutex mutex; }; class ThumbnailWidget : public QWidget