Merge pull request #7737 from CozmoP/modelview
Qt: custom playlist model and playlist view
This commit is contained in:
commit
ad3e66dcb0
|
@ -340,7 +340,7 @@ ifeq ($(HAVE_QT), 1)
|
||||||
ui/drivers/qt/ui_qt_browser_window.o \
|
ui/drivers/qt/ui_qt_browser_window.o \
|
||||||
ui/drivers/qt/ui_qt_load_core_window.o \
|
ui/drivers/qt/ui_qt_load_core_window.o \
|
||||||
ui/drivers/qt/ui_qt_msg_window.o \
|
ui/drivers/qt/ui_qt_msg_window.o \
|
||||||
ui/drivers/qt/flowlayout.o \
|
ui/drivers/qt/gridview.o \
|
||||||
ui/drivers/qt/shaderparamsdialog.o \
|
ui/drivers/qt/shaderparamsdialog.o \
|
||||||
ui/drivers/qt/coreoptionsdialog.o \
|
ui/drivers/qt/coreoptionsdialog.o \
|
||||||
ui/drivers/qt/filedropwidget.o \
|
ui/drivers/qt/filedropwidget.o \
|
||||||
|
@ -355,7 +355,7 @@ ifeq ($(HAVE_QT), 1)
|
||||||
|
|
||||||
MOC_HEADERS += ui/drivers/ui_qt.h \
|
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 \
|
ui/drivers/qt/gridview.h \
|
||||||
ui/drivers/qt/shaderparamsdialog.h \
|
ui/drivers/qt/shaderparamsdialog.h \
|
||||||
ui/drivers/qt/coreoptionsdialog.h \
|
ui/drivers/qt/coreoptionsdialog.h \
|
||||||
ui/drivers/qt/filedropwidget.h \
|
ui/drivers/qt/filedropwidget.h \
|
||||||
|
|
|
@ -43,7 +43,7 @@ UI
|
||||||
#include "../ui/drivers/qt/ui_qt_browser_window.cpp"
|
#include "../ui/drivers/qt/ui_qt_browser_window.cpp"
|
||||||
#include "../ui/drivers/qt/ui_qt_msg_window.cpp"
|
#include "../ui/drivers/qt/ui_qt_msg_window.cpp"
|
||||||
#include "../ui/drivers/qt/ui_qt_application.cpp"
|
#include "../ui/drivers/qt/ui_qt_application.cpp"
|
||||||
#include "../ui/drivers/qt/flowlayout.cpp"
|
#include "../ui/drivers/qt/gridview.cpp"
|
||||||
#include "../ui/drivers/qt/shaderparamsdialog.cpp"
|
#include "../ui/drivers/qt/shaderparamsdialog.cpp"
|
||||||
#include "../ui/drivers/qt/coreoptionsdialog.cpp"
|
#include "../ui/drivers/qt/coreoptionsdialog.cpp"
|
||||||
#include "../ui/drivers/qt/filedropwidget.cpp"
|
#include "../ui/drivers/qt/filedropwidget.cpp"
|
||||||
|
@ -59,7 +59,7 @@ UI
|
||||||
#include "../ui/drivers/qt/moc_coreinfodialog.cpp"
|
#include "../ui/drivers/qt/moc_coreinfodialog.cpp"
|
||||||
#include "../ui/drivers/qt/moc_coreoptionsdialog.cpp"
|
#include "../ui/drivers/qt/moc_coreoptionsdialog.cpp"
|
||||||
#include "../ui/drivers/qt/moc_filedropwidget.cpp"
|
#include "../ui/drivers/qt/moc_filedropwidget.cpp"
|
||||||
#include "../ui/drivers/qt/moc_flowlayout.cpp"
|
#include "../ui/drivers/qt/moc_gridview.cpp"
|
||||||
#include "../ui/drivers/qt/moc_playlistentrydialog.cpp"
|
#include "../ui/drivers/qt/moc_playlistentrydialog.cpp"
|
||||||
#include "../ui/drivers/qt/moc_shaderparamsdialog.cpp"
|
#include "../ui/drivers/qt/moc_shaderparamsdialog.cpp"
|
||||||
#include "../ui/drivers/qt/moc_ui_qt_load_core_window.cpp"
|
#include "../ui/drivers/qt/moc_ui_qt_load_core_window.cpp"
|
||||||
|
|
|
@ -7679,6 +7679,14 @@ MSG_HASH(
|
||||||
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_STARTUP_PLAYLIST,
|
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_STARTUP_PLAYLIST,
|
||||||
"Start on playlist:"
|
"Start on playlist:"
|
||||||
)
|
)
|
||||||
|
MSG_HASH(
|
||||||
|
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THUMBNAIL_TYPE,
|
||||||
|
"Icon view thumbnail type:"
|
||||||
|
)
|
||||||
|
MSG_HASH(
|
||||||
|
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THUMBNAIL_CACHE_LIMIT,
|
||||||
|
"Thumbnail cache limit:"
|
||||||
|
)
|
||||||
MSG_HASH(
|
MSG_HASH(
|
||||||
MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALL_THUMBNAILS,
|
MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALL_THUMBNAILS,
|
||||||
"Download All Thumbnails"
|
"Download All Thumbnails"
|
||||||
|
|
|
@ -1988,6 +1988,8 @@ enum msg_hash_enums
|
||||||
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_LIST_MAX_COUNT,
|
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_LIST_MAX_COUNT,
|
||||||
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_GRID_MAX_COUNT,
|
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_GRID_MAX_COUNT,
|
||||||
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_STARTUP_PLAYLIST,
|
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_STARTUP_PLAYLIST,
|
||||||
|
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THUMBNAIL_TYPE,
|
||||||
|
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THUMBNAIL_CACHE_LIMIT,
|
||||||
MENU_ENUM_LABEL_VALUE_QT_MENU_TOOLS,
|
MENU_ENUM_LABEL_VALUE_QT_MENU_TOOLS,
|
||||||
MENU_ENUM_LABEL_VALUE_QT_MENU_HELP,
|
MENU_ENUM_LABEL_VALUE_QT_MENU_HELP,
|
||||||
MENU_ENUM_LABEL_VALUE_QT_MENU_DOCK_CONTENT_BROWSER,
|
MENU_ENUM_LABEL_VALUE_QT_MENU_DOCK_CONTENT_BROWSER,
|
||||||
|
|
|
@ -41,7 +41,12 @@ void FileDropWidget::paintEvent(QPaintEvent *event)
|
||||||
|
|
||||||
void FileDropWidget::keyPressEvent(QKeyEvent *event)
|
void FileDropWidget::keyPressEvent(QKeyEvent *event)
|
||||||
{
|
{
|
||||||
if (event->key() == Qt::Key_Delete)
|
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
|
||||||
|
{
|
||||||
|
event->accept();
|
||||||
|
emit enterPressed();
|
||||||
|
}
|
||||||
|
else if (event->key() == Qt::Key_Delete)
|
||||||
{
|
{
|
||||||
event->accept();
|
event->accept();
|
||||||
emit deletePressed();
|
emit deletePressed();
|
||||||
|
|
|
@ -15,6 +15,7 @@ public:
|
||||||
FileDropWidget(QWidget *parent = 0);
|
FileDropWidget(QWidget *parent = 0);
|
||||||
signals:
|
signals:
|
||||||
void filesDropped(QStringList files);
|
void filesDropped(QStringList files);
|
||||||
|
void enterPressed();
|
||||||
void deletePressed();
|
void deletePressed();
|
||||||
protected:
|
protected:
|
||||||
void dragEnterEvent(QDragEnterEvent *event);
|
void dragEnterEvent(QDragEnterEvent *event);
|
||||||
|
|
|
@ -1,248 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of the examples of the Qt Toolkit.
|
|
||||||
**
|
|
||||||
** $QT_BEGIN_LICENSE:BSD$
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** BSD License Usage
|
|
||||||
** Alternatively, you may use this file under the terms of the BSD license
|
|
||||||
** as follows:
|
|
||||||
**
|
|
||||||
** "Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions are
|
|
||||||
** met:
|
|
||||||
** * Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in
|
|
||||||
** the documentation and/or other materials provided with the
|
|
||||||
** distribution.
|
|
||||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
|
||||||
** contributors may be used to endorse or promote products derived
|
|
||||||
** from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
|
||||||
**
|
|
||||||
** $QT_END_LICENSE$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/* Original work Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
* Modified work Copyright (C) 2018 - Brad Parker
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <QtWidgets>
|
|
||||||
|
|
||||||
#include "flowlayout.h"
|
|
||||||
#include "../ui_qt.h"
|
|
||||||
|
|
||||||
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(QPointer<ThumbnailWidget>)), this, SLOT(onAddWidgetDeferred(QPointer<ThumbnailWidget>)), Qt::QueuedConnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
|
|
||||||
: m_hSpace(hSpacing), m_vSpace(vSpacing)
|
|
||||||
{
|
|
||||||
setContentsMargins(margin, margin, margin, margin);
|
|
||||||
}
|
|
||||||
|
|
||||||
FlowLayout::~FlowLayout()
|
|
||||||
{
|
|
||||||
QLayoutItem *item = NULL;
|
|
||||||
|
|
||||||
while ((item = takeAt(0)) != NULL)
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlowLayout::addItem(QLayoutItem *item)
|
|
||||||
{
|
|
||||||
itemList.append(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
int FlowLayout::horizontalSpacing() const
|
|
||||||
{
|
|
||||||
if (m_hSpace >= 0)
|
|
||||||
return m_hSpace;
|
|
||||||
else
|
|
||||||
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
int FlowLayout::verticalSpacing() const
|
|
||||||
{
|
|
||||||
if (m_vSpace >= 0)
|
|
||||||
return m_vSpace;
|
|
||||||
else
|
|
||||||
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
int FlowLayout::count() const
|
|
||||||
{
|
|
||||||
return itemList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
QLayoutItem* FlowLayout::itemAt(int index) const
|
|
||||||
{
|
|
||||||
return itemList.value(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
QLayoutItem* FlowLayout::takeAt(int index)
|
|
||||||
{
|
|
||||||
if (index >= 0 && index < itemList.size())
|
|
||||||
return itemList.takeAt(index);
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::Orientations FlowLayout::expandingDirections() const
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FlowLayout::hasHeightForWidth() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FlowLayout::heightForWidth(int width) const
|
|
||||||
{
|
|
||||||
int height = doLayout(QRect(0, 0, width, 0), true);
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlowLayout::setGeometry(const QRect &rect)
|
|
||||||
{
|
|
||||||
QLayout::setGeometry(rect);
|
|
||||||
doLayout(rect, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize FlowLayout::sizeHint() const
|
|
||||||
{
|
|
||||||
return minimumSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize FlowLayout::minimumSize() const
|
|
||||||
{
|
|
||||||
QSize size;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (itemList.isEmpty())
|
|
||||||
return size;
|
|
||||||
|
|
||||||
for (i = 0; i < itemList.count(); i++)
|
|
||||||
{
|
|
||||||
const QLayoutItem *item = itemList.at(i);
|
|
||||||
size = size.expandedTo(item->minimumSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
size += QSize(2 * margin(), 2 * margin());
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
|
|
||||||
{
|
|
||||||
QRect effectiveRect;
|
|
||||||
int left = 0, top = 0, right = 0, bottom = 0;
|
|
||||||
int x = 0;
|
|
||||||
int y = 0;
|
|
||||||
int lineHeight = 0;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
getContentsMargins(&left, &top, &right, &bottom);
|
|
||||||
effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
|
|
||||||
x = effectiveRect.x();
|
|
||||||
y = effectiveRect.y();
|
|
||||||
|
|
||||||
if (itemList.isEmpty())
|
|
||||||
return y + lineHeight - rect.y() + bottom;
|
|
||||||
|
|
||||||
for (i = 0; i < itemList.count(); i++)
|
|
||||||
{
|
|
||||||
QLayoutItem *item = itemList.at(i);
|
|
||||||
const QWidget *wid = item->widget();
|
|
||||||
int spaceX = horizontalSpacing();
|
|
||||||
int spaceY = 0;
|
|
||||||
int nextX = 0;
|
|
||||||
|
|
||||||
if (spaceX == -1)
|
|
||||||
spaceX = wid->style()->layoutSpacing(
|
|
||||||
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
|
|
||||||
|
|
||||||
spaceY = verticalSpacing();
|
|
||||||
|
|
||||||
if (spaceY == -1)
|
|
||||||
spaceY = wid->style()->layoutSpacing(
|
|
||||||
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
|
|
||||||
|
|
||||||
nextX = x + item->sizeHint().width() + spaceX;
|
|
||||||
|
|
||||||
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0)
|
|
||||||
{
|
|
||||||
x = effectiveRect.x();
|
|
||||||
y = y + lineHeight + spaceY;
|
|
||||||
nextX = x + item->sizeHint().width() + spaceX;
|
|
||||||
lineHeight = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!testOnly)
|
|
||||||
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
|
|
||||||
|
|
||||||
x = nextX;
|
|
||||||
lineHeight = qMax(lineHeight, item->sizeHint().height());
|
|
||||||
}
|
|
||||||
|
|
||||||
return y + lineHeight - rect.y() + bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
|
|
||||||
{
|
|
||||||
const QObject *parentObj = parent();
|
|
||||||
|
|
||||||
if (!parentObj)
|
|
||||||
return -1;
|
|
||||||
else if (parentObj->isWidgetType())
|
|
||||||
{
|
|
||||||
const QWidget *pw = static_cast<const QWidget*>(parentObj);
|
|
||||||
return pw->style()->pixelMetric(pm, NULL, pw);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return static_cast<const QLayout*>(parentObj)->spacing();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlowLayout::addWidgetDeferred(QPointer<ThumbnailWidget> widget)
|
|
||||||
{
|
|
||||||
emit signalAddWidgetDeferred(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlowLayout::onAddWidgetDeferred(QPointer<ThumbnailWidget> widget)
|
|
||||||
{
|
|
||||||
/* widget might have been deleted before we got to it since this uses a queued connection, hence the guarded QPointer */
|
|
||||||
if (!widget)
|
|
||||||
return;
|
|
||||||
|
|
||||||
addWidget(widget);
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of the examples of the Qt Toolkit.
|
|
||||||
**
|
|
||||||
** $QT_BEGIN_LICENSE:BSD$
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** BSD License Usage
|
|
||||||
** Alternatively, you may use this file under the terms of the BSD license
|
|
||||||
** as follows:
|
|
||||||
**
|
|
||||||
** "Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions are
|
|
||||||
** met:
|
|
||||||
** * Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in
|
|
||||||
** the documentation and/or other materials provided with the
|
|
||||||
** distribution.
|
|
||||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
|
||||||
** contributors may be used to endorse or promote products derived
|
|
||||||
** from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
|
||||||
**
|
|
||||||
** $QT_END_LICENSE$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/* Original work Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
* Modified work Copyright (C) 2018 - Brad Parker
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* bparker: Removed C++11 override keyword from original source
|
|
||||||
* Changed QList to QVector
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FLOWLAYOUT_H
|
|
||||||
#define FLOWLAYOUT_H
|
|
||||||
|
|
||||||
#include <QLayout>
|
|
||||||
#include <QRect>
|
|
||||||
#include <QStyle>
|
|
||||||
|
|
||||||
class ThumbnailWidget;
|
|
||||||
|
|
||||||
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);
|
|
||||||
~FlowLayout();
|
|
||||||
|
|
||||||
void addItem(QLayoutItem *item);
|
|
||||||
int horizontalSpacing() const;
|
|
||||||
int verticalSpacing() const;
|
|
||||||
Qt::Orientations expandingDirections() const;
|
|
||||||
bool hasHeightForWidth() const;
|
|
||||||
int heightForWidth(int) const;
|
|
||||||
int count() const;
|
|
||||||
QLayoutItem* itemAt(int index) const;
|
|
||||||
QSize minimumSize() const;
|
|
||||||
void setGeometry(const QRect &rect);
|
|
||||||
QSize sizeHint() const;
|
|
||||||
QLayoutItem* takeAt(int index);
|
|
||||||
void addWidgetDeferred(QPointer<ThumbnailWidget> widget);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void signalAddWidgetDeferred(QPointer<ThumbnailWidget> widget);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onAddWidgetDeferred(QPointer<ThumbnailWidget> widget);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int doLayout(const QRect &rect, bool testOnly) const;
|
|
||||||
int smartSpacing(QStyle::PixelMetric pm) const;
|
|
||||||
|
|
||||||
QVector<QLayoutItem*> itemList;
|
|
||||||
int m_hSpace;
|
|
||||||
int m_vSpace;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // FLOWLAYOUT_H
|
|
|
@ -0,0 +1,481 @@
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
#include "gridview.h"
|
||||||
|
#include "../ui_qt.h"
|
||||||
|
|
||||||
|
/* http://www.informit.com/articles/article.aspx?p=1613548 */
|
||||||
|
|
||||||
|
ThumbnailDelegate::ThumbnailDelegate(const GridItem &gridItem, QObject* parent) :
|
||||||
|
QStyledItemDelegate(parent), m_style(gridItem)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void ThumbnailDelegate::paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
QStyleOptionViewItem opt = option;
|
||||||
|
const QWidget *widget = opt.widget;
|
||||||
|
QStyle *style = widget->style();
|
||||||
|
int padding = m_style.padding;
|
||||||
|
int textTopMargin = 4; /* Qt seemingly reports -4 the actual line height. */
|
||||||
|
int textHeight = painter->fontMetrics().height() + padding + padding;
|
||||||
|
QRect rect = opt.rect;
|
||||||
|
QRect adjusted = rect.adjusted(padding, padding, -padding, -textHeight + textTopMargin);
|
||||||
|
QPixmap pixmap = index.data(PlaylistModel::THUMBNAIL).value<QPixmap>();
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
|
||||||
|
initStyleOption(&opt, index);
|
||||||
|
|
||||||
|
/* draw the background */
|
||||||
|
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, widget);
|
||||||
|
|
||||||
|
/* draw the image */
|
||||||
|
if (!pixmap.isNull())
|
||||||
|
{
|
||||||
|
QPixmap pixmapScaled = pixmap.scaled(adjusted.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
|
style->drawItemPixmap(painter, adjusted, Qt::AlignHCenter | m_style.thumbnailVerticalAlignmentFlag, pixmapScaled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* draw the text */
|
||||||
|
if (!opt.text.isEmpty())
|
||||||
|
{
|
||||||
|
QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
|
||||||
|
QRect textRect = QRect(rect.x() + padding, rect.y() + adjusted.height() - textTopMargin + padding, rect.width() - 2 * padding, textHeight);
|
||||||
|
QString elidedText = painter->fontMetrics().elidedText(opt.text, opt.textElideMode, textRect.width(), Qt::TextShowMnemonic);
|
||||||
|
|
||||||
|
if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active))
|
||||||
|
cg = QPalette::Inactive;
|
||||||
|
|
||||||
|
if (opt.state & QStyle::State_Selected)
|
||||||
|
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
|
||||||
|
else
|
||||||
|
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||||
|
|
||||||
|
painter->setFont(opt.font);
|
||||||
|
painter->drawText(textRect, Qt::AlignCenter, elidedText);
|
||||||
|
}
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
GridView::GridView(QWidget *parent) : QAbstractItemView(parent), m_idealHeight(0), m_hashIsDirty(false)
|
||||||
|
{
|
||||||
|
setFocusPolicy(Qt::WheelFocus);
|
||||||
|
horizontalScrollBar()->setRange(0, 0);
|
||||||
|
verticalScrollBar()->setRange(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::setModel(QAbstractItemModel *newModel)
|
||||||
|
{
|
||||||
|
if (model())
|
||||||
|
disconnect(model(), SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(rowsRemoved(QModelIndex, int, int)));
|
||||||
|
|
||||||
|
QAbstractItemView::setModel(newModel);
|
||||||
|
|
||||||
|
connect(newModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(rowsRemoved(QModelIndex, int, int)));
|
||||||
|
|
||||||
|
m_hashIsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::setviewMode(ViewMode mode)
|
||||||
|
{
|
||||||
|
m_viewMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::calculateRectsIfNecessary() const
|
||||||
|
{
|
||||||
|
if (!m_hashIsDirty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int x = m_spacing;
|
||||||
|
int y = m_spacing;
|
||||||
|
int row;
|
||||||
|
int nextX;
|
||||||
|
|
||||||
|
const int maxWidth = viewport()->width();
|
||||||
|
|
||||||
|
switch (m_viewMode)
|
||||||
|
{
|
||||||
|
case Anchored:
|
||||||
|
{
|
||||||
|
int columns = (maxWidth - m_spacing) / (m_size + m_spacing);
|
||||||
|
if (columns > 0)
|
||||||
|
{
|
||||||
|
const int actualSpacing = (maxWidth - m_spacing - m_size - (columns - 1) * m_size) / columns;
|
||||||
|
for (row = 0; row < model()->rowCount(); ++row)
|
||||||
|
{
|
||||||
|
nextX = x + m_size + actualSpacing;
|
||||||
|
if (nextX > maxWidth)
|
||||||
|
{
|
||||||
|
x = m_spacing;
|
||||||
|
y += m_size + m_spacing;
|
||||||
|
nextX = x + m_size + actualSpacing;
|
||||||
|
}
|
||||||
|
m_rectForRow[row] = QRectF(x, y, m_size, m_size);
|
||||||
|
x = nextX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Centered:
|
||||||
|
{
|
||||||
|
int columns = (maxWidth - m_spacing) / (m_size + m_spacing);
|
||||||
|
if (columns > 0)
|
||||||
|
{
|
||||||
|
const int actualSpacing = (maxWidth - columns * m_size) / (columns + 1);
|
||||||
|
x = actualSpacing;
|
||||||
|
for (row = 0; row < model()->rowCount(); ++row)
|
||||||
|
{
|
||||||
|
nextX = x + m_size + actualSpacing;
|
||||||
|
if (nextX > maxWidth)
|
||||||
|
{
|
||||||
|
x = actualSpacing;
|
||||||
|
y += m_size + m_spacing;
|
||||||
|
nextX = x + m_size + actualSpacing;
|
||||||
|
}
|
||||||
|
m_rectForRow[row] = QRectF(x, y, m_size, m_size);
|
||||||
|
x = nextX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Simple:
|
||||||
|
for (row = 0; row < model()->rowCount(); ++row)
|
||||||
|
{
|
||||||
|
nextX = x + m_size + m_spacing;
|
||||||
|
if (nextX > maxWidth)
|
||||||
|
{
|
||||||
|
x = m_spacing;
|
||||||
|
y += m_size + m_spacing;
|
||||||
|
nextX = x + m_size + m_spacing;
|
||||||
|
}
|
||||||
|
m_rectForRow[row] = QRectF(x, y, m_size, m_size);
|
||||||
|
x = nextX;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_idealHeight = y + m_size + m_spacing;
|
||||||
|
m_hashIsDirty = false;
|
||||||
|
viewport()->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect GridView::visualRect(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
QRect rect;
|
||||||
|
if (index.isValid())
|
||||||
|
rect = viewportRectForRow(index.row()).toRect();
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF GridView::viewportRectForRow(int row) const
|
||||||
|
{
|
||||||
|
QRectF rect;
|
||||||
|
calculateRectsIfNecessary();
|
||||||
|
rect = m_rectForRow.value(row).toRect();
|
||||||
|
if (!rect.isValid())
|
||||||
|
return rect;
|
||||||
|
return QRectF(rect.x() - horizontalScrollBar()->value(), rect.y() - verticalScrollBar()->value(), rect.width(), rect.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::scrollTo(const QModelIndex &index, QAbstractItemView::ScrollHint)
|
||||||
|
{
|
||||||
|
QRect viewRect = viewport()->rect();
|
||||||
|
QRect itemRect = visualRect(index);
|
||||||
|
|
||||||
|
if (itemRect.left() < viewRect.left())
|
||||||
|
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + itemRect.left() - viewRect.left());
|
||||||
|
else if (itemRect.right() > viewRect.right())
|
||||||
|
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + qMin(itemRect.right() - viewRect.right(), itemRect.left() - viewRect.left()));
|
||||||
|
if (itemRect.top() < viewRect.top())
|
||||||
|
verticalScrollBar()->setValue(verticalScrollBar()->value() + itemRect.top() - viewRect.top());
|
||||||
|
else if (itemRect.bottom() > viewRect.bottom())
|
||||||
|
verticalScrollBar()->setValue(verticalScrollBar()->value() + qMin(itemRect.bottom() - viewRect.bottom(), itemRect.top() - viewRect.top()));
|
||||||
|
viewport()->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Make this more efficient by changing m_rectForRow for another data structure. Look at how Qt's own views do it. */
|
||||||
|
QModelIndex GridView::indexAt(const QPoint &point_) const
|
||||||
|
{
|
||||||
|
QPoint point(point_);
|
||||||
|
QHash<int, QRectF>::const_iterator i;
|
||||||
|
point.rx() += horizontalScrollBar()->value();
|
||||||
|
point.ry() += verticalScrollBar()->value();
|
||||||
|
|
||||||
|
calculateRectsIfNecessary();
|
||||||
|
|
||||||
|
i = m_rectForRow.constBegin();
|
||||||
|
|
||||||
|
while (i != m_rectForRow.constEnd())
|
||||||
|
{
|
||||||
|
if (i.value().contains(point))
|
||||||
|
return model()->index(i.key(), 0, rootIndex());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
|
||||||
|
{
|
||||||
|
m_hashIsDirty = true;
|
||||||
|
QAbstractItemView::dataChanged(topLeft, bottomRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::refresh()
|
||||||
|
{
|
||||||
|
m_hashIsDirty = true;
|
||||||
|
calculateRectsIfNecessary();
|
||||||
|
updateGeometries();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::rowsInserted(const QModelIndex &parent, int start, int end)
|
||||||
|
{
|
||||||
|
QAbstractItemView::rowsInserted(parent, start, end);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::rowsRemoved(const QModelIndex &parent, int start, int end)
|
||||||
|
{
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::setGridSize(const int newSize)
|
||||||
|
{
|
||||||
|
if (newSize != m_size)
|
||||||
|
{
|
||||||
|
m_size = newSize;
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::resizeEvent(QResizeEvent*)
|
||||||
|
{
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::reset()
|
||||||
|
{
|
||||||
|
m_visibleIndexes.clear();
|
||||||
|
QAbstractItemView::reset();
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex GridView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers)
|
||||||
|
{
|
||||||
|
QModelIndex index = currentIndex();
|
||||||
|
if (index.isValid())
|
||||||
|
{
|
||||||
|
if ((cursorAction == MoveLeft && index.row() > 0) || (cursorAction == MoveRight && index.row() + 1 < model()->rowCount()))
|
||||||
|
{
|
||||||
|
const int offset = (cursorAction == MoveLeft ? -1 : 1);
|
||||||
|
index = model()->index(index.row() + offset, index.column(), index.parent());
|
||||||
|
}
|
||||||
|
else if ((cursorAction == MoveUp && index.row() > 0) || (cursorAction == MoveDown && index.row() + 1 < model()->rowCount()))
|
||||||
|
{
|
||||||
|
const int offset = ((m_size + m_spacing) * (cursorAction == MoveUp ? -1 : 1));
|
||||||
|
QRect rect = viewportRectForRow(index.row()).toRect();
|
||||||
|
QPoint point(rect.center().x(), rect.center().y() + offset);
|
||||||
|
index = indexAt(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GridView::horizontalOffset() const
|
||||||
|
{
|
||||||
|
return horizontalScrollBar()->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GridView::verticalOffset() const
|
||||||
|
{
|
||||||
|
return verticalScrollBar()->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::scrollContentsBy(int dx, int dy)
|
||||||
|
{
|
||||||
|
scrollDirtyRegion(dx, dy);
|
||||||
|
viewport()->scroll(dx, dy);
|
||||||
|
emit(visibleItemsChangedMaybe());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Maybe add a way to get the previous/next visible indexes. */
|
||||||
|
QVector<QModelIndex> GridView::visibleIndexes() const {
|
||||||
|
return m_visibleIndexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::setSelection(const QRect &rect, QFlags<QItemSelectionModel::SelectionFlag> flags)
|
||||||
|
{
|
||||||
|
QRect rectangle;
|
||||||
|
QHash<int, QRectF>::const_iterator i;
|
||||||
|
int firstRow = model()->rowCount();
|
||||||
|
int lastRow = -1;
|
||||||
|
|
||||||
|
calculateRectsIfNecessary();
|
||||||
|
|
||||||
|
rectangle = rect.translated(horizontalScrollBar()->value(), verticalScrollBar()->value()).normalized();
|
||||||
|
|
||||||
|
i = m_rectForRow.constBegin();
|
||||||
|
while (i != m_rectForRow.constEnd())
|
||||||
|
{
|
||||||
|
if (i.value().intersects(rectangle))
|
||||||
|
{
|
||||||
|
firstRow = firstRow < i.key() ? firstRow : i.key();
|
||||||
|
lastRow = lastRow > i.key() ? lastRow : i.key();
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (firstRow != model()->rowCount() && lastRow != -1)
|
||||||
|
{
|
||||||
|
QItemSelection selection(model()->index(firstRow, 0, rootIndex()), model()->index(lastRow, 0, rootIndex()));
|
||||||
|
selectionModel()->select(selection, flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QModelIndex invalid;
|
||||||
|
QItemSelection selection(invalid, invalid);
|
||||||
|
selectionModel()->select(selection, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QRegion GridView::visualRegionForSelection(const QItemSelection &selection) const
|
||||||
|
{
|
||||||
|
QRegion region;
|
||||||
|
QItemSelectionRange range;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < selection.size(); i++)
|
||||||
|
{
|
||||||
|
range = selection.at(i);
|
||||||
|
int row;
|
||||||
|
for (row = range.top(); row <= range.bottom(); row++)
|
||||||
|
{
|
||||||
|
int column;
|
||||||
|
for (column = range.left(); column < range.right(); column++)
|
||||||
|
{
|
||||||
|
QModelIndex index = model()->index(row, column, rootIndex());
|
||||||
|
region += visualRect(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::paintEvent(QPaintEvent*)
|
||||||
|
{
|
||||||
|
QPainter painter(viewport());
|
||||||
|
int row;
|
||||||
|
|
||||||
|
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||||
|
m_visibleIndexes.clear();
|
||||||
|
|
||||||
|
for (row = 0; row < model()->rowCount(rootIndex()); ++row)
|
||||||
|
{
|
||||||
|
QModelIndex index = model()->index(row, 0, rootIndex());
|
||||||
|
QRectF rect = viewportRectForRow(row);
|
||||||
|
QStyleOptionViewItem option = viewOptions();
|
||||||
|
|
||||||
|
if (!rect.isValid() || rect.bottom() < 0 || rect.y() > viewport()->height())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m_visibleIndexes.append(index);
|
||||||
|
option.rect = rect.toRect();
|
||||||
|
|
||||||
|
if (selectionModel()->isSelected(index))
|
||||||
|
option.state |= QStyle::State_Selected;
|
||||||
|
|
||||||
|
if (currentIndex() == index)
|
||||||
|
option.state |= QStyle::State_HasFocus;
|
||||||
|
|
||||||
|
itemDelegate()->paint(&painter, option, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::updateGeometries()
|
||||||
|
{
|
||||||
|
const int RowHeight = m_size + m_spacing;
|
||||||
|
|
||||||
|
QAbstractItemView::updateGeometries();
|
||||||
|
|
||||||
|
verticalScrollBar()->setSingleStep(RowHeight);
|
||||||
|
verticalScrollBar()->setPageStep(viewport()->height());
|
||||||
|
verticalScrollBar()->setRange(0, qMax(0, m_idealHeight - viewport()->height()));
|
||||||
|
|
||||||
|
horizontalScrollBar()->setPageStep(viewport()->width());
|
||||||
|
horizontalScrollBar()->setRange(0, qMax(0, RowHeight - viewport()->width()));
|
||||||
|
|
||||||
|
emit(visibleItemsChangedMaybe());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GridView::getLayout() const
|
||||||
|
{
|
||||||
|
switch (m_viewMode)
|
||||||
|
{
|
||||||
|
case Simple:
|
||||||
|
return "simple";
|
||||||
|
case Anchored:
|
||||||
|
return "anchored";
|
||||||
|
case Centered:
|
||||||
|
default:
|
||||||
|
return "centered";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::setLayout(QString layout)
|
||||||
|
{
|
||||||
|
if (layout == "anchored")
|
||||||
|
m_viewMode = Anchored;
|
||||||
|
else if (layout == "centered")
|
||||||
|
m_viewMode = Centered;
|
||||||
|
else if (layout == "fixed")
|
||||||
|
m_viewMode = Simple;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GridView::getSpacing() const
|
||||||
|
{
|
||||||
|
return m_spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridView::setSpacing(const int spacing)
|
||||||
|
{
|
||||||
|
m_spacing = spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
GridItem::GridItem(QWidget* parent) : QWidget(parent)
|
||||||
|
, thumbnailVerticalAlignmentFlag(Qt::AlignBottom)
|
||||||
|
, padding(11)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int GridItem::getPadding() const
|
||||||
|
{
|
||||||
|
return padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridItem::setPadding(const int value)
|
||||||
|
{
|
||||||
|
padding = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GridItem::getThumbnailVerticalAlign() const
|
||||||
|
{
|
||||||
|
switch (thumbnailVerticalAlignmentFlag)
|
||||||
|
{
|
||||||
|
case Qt::AlignTop:
|
||||||
|
return "top";
|
||||||
|
case Qt::AlignVCenter:
|
||||||
|
return "center";
|
||||||
|
case Qt::AlignBottom:
|
||||||
|
default:
|
||||||
|
return "bottom";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridItem::setThumbnailVerticalAlign(const QString valign)
|
||||||
|
{
|
||||||
|
if (valign == "top")
|
||||||
|
thumbnailVerticalAlignmentFlag = Qt::AlignTop;
|
||||||
|
else if (valign == "center")
|
||||||
|
thumbnailVerticalAlignmentFlag = Qt::AlignVCenter;
|
||||||
|
else if (valign == "bottom")
|
||||||
|
thumbnailVerticalAlignmentFlag = Qt::AlignBottom;
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
#ifndef GRIDVIEW_H
|
||||||
|
#define GRIDVIEW_H
|
||||||
|
|
||||||
|
#include <QAbstractItemView>
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
|
||||||
|
#define DEFAULT_GRID_ITEM_MARGIN 11
|
||||||
|
#define DEFAULT_GRID_ITEM_THUMBNAIL_ALIGNMENT "bottom"
|
||||||
|
#define DEFAULT_GRID_SPACING 7
|
||||||
|
#define DEFAULT_GRID_LAYOUT "centered"
|
||||||
|
|
||||||
|
class GridItem;
|
||||||
|
|
||||||
|
class ThumbnailDelegate : public QStyledItemDelegate
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ThumbnailDelegate(const GridItem &gridItem, QObject* parent = 0);
|
||||||
|
void paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex& index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const GridItem &m_style;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GridView : public QAbstractItemView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QString layout READ getLayout WRITE setLayout DESIGNABLE true SCRIPTABLE true)
|
||||||
|
Q_PROPERTY(int spacing READ getSpacing WRITE setSpacing DESIGNABLE true SCRIPTABLE true)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum ViewMode
|
||||||
|
{
|
||||||
|
Simple,
|
||||||
|
Centered,
|
||||||
|
Anchored
|
||||||
|
};
|
||||||
|
|
||||||
|
GridView(QWidget *parent = 0);
|
||||||
|
~GridView() {}
|
||||||
|
|
||||||
|
QModelIndex indexAt(const QPoint &point_) const;
|
||||||
|
QVector<QModelIndex> visibleIndexes() const;
|
||||||
|
QRect visualRect(const QModelIndex &index) const;
|
||||||
|
void setModel(QAbstractItemModel *model);
|
||||||
|
void scrollTo(const QModelIndex &index, QAbstractItemView::ScrollHint);
|
||||||
|
void setGridSize(const int newSize);
|
||||||
|
void setviewMode(ViewMode mode);
|
||||||
|
QString getLayout() const;
|
||||||
|
void setLayout(QString layout);
|
||||||
|
int getSpacing() const;
|
||||||
|
void setSpacing(const int spacing);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void visibleItemsChangedMaybe() const;
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
|
||||||
|
void rowsInserted(const QModelIndex &parent, int start, int end);
|
||||||
|
void rowsRemoved(const QModelIndex &parent, int start, int end);
|
||||||
|
void updateGeometries();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers);
|
||||||
|
QRegion visualRegionForSelection(const QItemSelection &selection) const;
|
||||||
|
bool isIndexHidden(const QModelIndex&) const { return false; }
|
||||||
|
int horizontalOffset() const;
|
||||||
|
int verticalOffset() const;
|
||||||
|
void scrollContentsBy(int dx, int dy);
|
||||||
|
void setSelection(const QRect &rect, QFlags<QItemSelectionModel::SelectionFlag> flags);
|
||||||
|
void paintEvent(QPaintEvent*);
|
||||||
|
void resizeEvent(QResizeEvent*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QRectF viewportRectForRow(int row) const;
|
||||||
|
void calculateRectsIfNecessary() const;
|
||||||
|
void refresh();
|
||||||
|
|
||||||
|
int m_size = 255;
|
||||||
|
int m_spacing = DEFAULT_GRID_SPACING;
|
||||||
|
QVector<QModelIndex> m_visibleIndexes;
|
||||||
|
ViewMode m_viewMode = Centered;
|
||||||
|
mutable int m_idealHeight;
|
||||||
|
mutable QHash<int, QRectF> m_rectForRow;
|
||||||
|
mutable bool m_hashIsDirty;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -9,9 +9,10 @@
|
||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QImageReader>
|
||||||
|
#include <QtConcurrent>
|
||||||
|
|
||||||
#include "../ui_qt.h"
|
#include "../ui_qt.h"
|
||||||
#include "flowlayout.h"
|
|
||||||
#include "playlistentrydialog.h"
|
#include "playlistentrydialog.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -28,6 +29,213 @@ extern "C" {
|
||||||
#include "../../../verbosity.h"
|
#include "../../../verbosity.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlaylistModel::PlaylistModel(QObject *parent)
|
||||||
|
: QAbstractListModel(parent)
|
||||||
|
{
|
||||||
|
m_imageFormats = QVector<QByteArray>::fromList(QImageReader::supportedImageFormats());
|
||||||
|
m_fileSanitizerRegex = QRegularExpression("[&*/:`<>?\\|]");
|
||||||
|
setThumbnailCacheLimit(500);
|
||||||
|
connect(this, &PlaylistModel::imageLoaded, this, &PlaylistModel::onImageLoaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PlaylistModel::rowCount(const QModelIndex & /* parent */) const
|
||||||
|
{
|
||||||
|
return m_contents.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int PlaylistModel::columnCount(const QModelIndex & /* parent */) const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant PlaylistModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (index.column() == 0)
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if (index.row() >= m_contents.size() || index.row() < 0)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
switch (role)
|
||||||
|
{
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case Qt::EditRole:
|
||||||
|
case Qt::ToolTipRole:
|
||||||
|
return m_contents.at(index.row())["label_noext"];
|
||||||
|
case HASH:
|
||||||
|
return QVariant::fromValue(m_contents.at(index.row()));
|
||||||
|
case THUMBNAIL:
|
||||||
|
{
|
||||||
|
QPixmap *cachedPreview = m_cache.object(getCurrentTypeThumbnailPath(index));
|
||||||
|
if (cachedPreview)
|
||||||
|
return *cachedPreview;
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags PlaylistModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return Qt::ItemIsEnabled;
|
||||||
|
|
||||||
|
return QAbstractListModel::flags(index) | Qt::ItemIsEditable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlaylistModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
|
{
|
||||||
|
if (index.isValid() && role == Qt::EditRole) {
|
||||||
|
QHash<QString, QString> hash = m_contents.at(index.row());
|
||||||
|
|
||||||
|
hash["label"] = value.toString();
|
||||||
|
hash["label_noext"] = QFileInfo(value.toString()).completeBaseName();
|
||||||
|
|
||||||
|
m_contents.replace(index.row(), hash);
|
||||||
|
emit dataChanged(index, index, { role });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant PlaylistModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (role != Qt::DisplayRole)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if (orientation == Qt::Horizontal)
|
||||||
|
return msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NAME);
|
||||||
|
else
|
||||||
|
return section + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaylistModel::setThumbnailType(const ThumbnailType type)
|
||||||
|
{
|
||||||
|
m_thumbnailType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaylistModel::setThumbnailCacheLimit(int limit)
|
||||||
|
{
|
||||||
|
m_cache.setMaxCost(limit * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PlaylistModel::getThumbnailPath(const QModelIndex &index, QString type) const
|
||||||
|
{
|
||||||
|
QByteArray extension;
|
||||||
|
QString extensionStr;
|
||||||
|
|
||||||
|
QString thumbnailFileNameNoExt;
|
||||||
|
int lastIndex = -1;
|
||||||
|
|
||||||
|
const QHash<QString, QString> &hash = m_contents.at(index.row());
|
||||||
|
lastIndex = hash["path"].lastIndexOf('.');
|
||||||
|
|
||||||
|
if (lastIndex >= 0)
|
||||||
|
{
|
||||||
|
extensionStr = hash["path"].mid(lastIndex + 1);
|
||||||
|
|
||||||
|
if (!extensionStr.isEmpty())
|
||||||
|
{
|
||||||
|
extension = extensionStr.toLower().toUtf8();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!extension.isEmpty() && m_imageFormats.contains(extension))
|
||||||
|
{
|
||||||
|
/* use thumbnail widgets to show regular image files */
|
||||||
|
return hash["path"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thumbnailFileNameNoExt = hash["label_noext"];
|
||||||
|
thumbnailFileNameNoExt.replace(m_fileSanitizerRegex, "_");
|
||||||
|
return QDir::cleanPath(QString(config_get_ptr()->paths.directory_thumbnails)) + "/" + hash.value("db_name") + "/" + type + "/" + thumbnailFileNameNoExt + ".png";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PlaylistModel::getCurrentTypeThumbnailPath(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
switch (m_thumbnailType)
|
||||||
|
{
|
||||||
|
case THUMBNAIL_TYPE_BOXART:
|
||||||
|
return getThumbnailPath(index, THUMBNAIL_BOXART);
|
||||||
|
case THUMBNAIL_TYPE_SCREENSHOT:
|
||||||
|
return getThumbnailPath(index, THUMBNAIL_SCREENSHOT);
|
||||||
|
case THUMBNAIL_TYPE_TITLE_SCREEN:
|
||||||
|
return getThumbnailPath(index, THUMBNAIL_TITLE);
|
||||||
|
default:
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaylistModel::reloadThumbnail(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
if (index.isValid()) {
|
||||||
|
reloadThumbnailPath(getCurrentTypeThumbnailPath(index));
|
||||||
|
loadThumbnail(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaylistModel::reloadSystemThumbnails(const QString system)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
QString key;
|
||||||
|
QString path = QDir::cleanPath(QString(config_get_ptr()->paths.directory_thumbnails)) + "/" + system;
|
||||||
|
QList<QString> keys = m_cache.keys();
|
||||||
|
QList<QString> pending = m_pendingImages.values();
|
||||||
|
|
||||||
|
for (i = 0; i < keys.size(); i++)
|
||||||
|
{
|
||||||
|
key = keys.at(i);
|
||||||
|
if (key.startsWith(path))
|
||||||
|
m_cache.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < pending.size(); i++)
|
||||||
|
{
|
||||||
|
key = pending.at(i);
|
||||||
|
if (key.startsWith(path))
|
||||||
|
m_pendingImages.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaylistModel::reloadThumbnailPath(const QString path)
|
||||||
|
{
|
||||||
|
m_cache.remove(path);
|
||||||
|
m_pendingImages.remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaylistModel::loadThumbnail(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
QString path = getCurrentTypeThumbnailPath(index);
|
||||||
|
|
||||||
|
if (!m_pendingImages.contains(path) && !m_cache.contains(path))
|
||||||
|
{
|
||||||
|
m_pendingImages.insert(path);
|
||||||
|
QtConcurrent::run(this, &PlaylistModel::loadImage, index, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaylistModel::loadImage(const QModelIndex &index, const QString &path)
|
||||||
|
{
|
||||||
|
const QImage image = QImage(path);
|
||||||
|
if (!image.isNull())
|
||||||
|
emit imageLoaded(image, index, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaylistModel::onImageLoaded(const QImage image, const QModelIndex &index, const QString &path)
|
||||||
|
{
|
||||||
|
QPixmap *pixmap = new QPixmap(QPixmap::fromImage(image));
|
||||||
|
const int cost = pixmap->width() * pixmap->height() * pixmap->depth() / (8 * 1024);
|
||||||
|
m_cache.insert(path, pixmap, cost);
|
||||||
|
if (index.isValid())
|
||||||
|
emit dataChanged(index, index, { THUMBNAIL });
|
||||||
|
m_pendingImages.remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
inline static bool comp_hash_name_key_lower(const QHash<QString, QString> &lhs, const QHash<QString, QString> &rhs)
|
inline static bool comp_hash_name_key_lower(const QHash<QString, QString> &lhs, const QHash<QString, QString> &rhs)
|
||||||
{
|
{
|
||||||
return lhs.value("name").toLower() < rhs.value("name").toLower();
|
return lhs.value("name").toLower() < rhs.value("name").toLower();
|
||||||
|
@ -38,7 +246,6 @@ inline static bool comp_hash_label_key_lower(const QHash<QString, QString> &lhs,
|
||||||
return lhs.value("label").toLower() < rhs.value("label").toLower();
|
return lhs.value("label").toLower() < rhs.value("label").toLower();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* https://stackoverflow.com/questions/7246622/how-to-create-a-slider-with-a-non-linear-scale */
|
|
||||||
bool MainWindow::addDirectoryFilesToList(QProgressDialog *dialog, QStringList &list, QDir &dir, QStringList &extensions)
|
bool MainWindow::addDirectoryFilesToList(QProgressDialog *dialog, QStringList &list, QDir &dir, QStringList &extensions)
|
||||||
{
|
{
|
||||||
PlaylistEntryDialog *playlistDialog = playlistEntryDialog();
|
PlaylistEntryDialog *playlistDialog = playlistEntryDialog();
|
||||||
|
@ -834,9 +1041,6 @@ void MainWindow::reloadPlaylists()
|
||||||
|
|
||||||
getPlaylistFiles();
|
getPlaylistFiles();
|
||||||
|
|
||||||
/* block this signal because setData() would trigger an infinite loop */
|
|
||||||
disconnect(m_listWidget, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(onCurrentListItemDataChanged(QListWidgetItem*)));
|
|
||||||
|
|
||||||
m_listWidget->clear();
|
m_listWidget->clear();
|
||||||
m_listWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
m_listWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
m_listWidget->setSelectionMode(QAbstractItemView::SingleSelection);
|
m_listWidget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
@ -968,13 +1172,11 @@ void MainWindow::reloadPlaylists()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(m_listWidget, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(onCurrentListItemDataChanged(QListWidgetItem*)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MainWindow::getCurrentPlaylistPath()
|
QString MainWindow::getCurrentPlaylistPath()
|
||||||
{
|
{
|
||||||
QListWidgetItem *playlistItem = m_listWidget->currentItem();
|
QListWidgetItem *playlistItem = m_listWidget->currentItem();
|
||||||
QHash<QString, QString> contentHash;
|
|
||||||
QString playlistPath;
|
QString playlistPath;
|
||||||
|
|
||||||
if (!playlistItem)
|
if (!playlistItem)
|
||||||
|
@ -1116,151 +1318,15 @@ void MainWindow::getPlaylistFiles()
|
||||||
m_playlistFiles = playlistDir.entryList(QDir::NoDotAndDotDot | QDir::Readable | QDir::Files, QDir::Name);
|
m_playlistFiles = playlistDir.entryList(QDir::NoDotAndDotDot | QDir::Readable | QDir::Files, QDir::Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::addPlaylistItemsToGrid(const QStringList &paths, bool add)
|
void PlaylistModel::getPlaylistItems(QString path)
|
||||||
{
|
|
||||||
QVector<QHash<QString, QString> > items;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (paths.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < paths.size(); i++)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
QVector<QHash<QString, QString> > vec = getPlaylistItems(paths.at(i));
|
|
||||||
/* QVector::append() wasn't added until 5.5, so just do it the old fashioned way */
|
|
||||||
for (j = 0; j < vec.size(); j++)
|
|
||||||
{
|
|
||||||
if (add && m_allPlaylistsGridMaxCount > 0 && items.size() >= m_allPlaylistsGridMaxCount)
|
|
||||||
goto finish;
|
|
||||||
|
|
||||||
items.append(vec.at(j));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finish:
|
|
||||||
std::sort(items.begin(), items.end(), comp_hash_label_key_lower);
|
|
||||||
|
|
||||||
addPlaylistHashToGrid(items);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::addPlaylistHashToGrid(const QVector<QHash<QString, QString> > &items)
|
|
||||||
{
|
|
||||||
QScreen *screen = qApp->primaryScreen();
|
|
||||||
QSize screenSize = screen->size();
|
|
||||||
QListWidgetItem *currentItem = m_listWidget->currentItem();
|
|
||||||
settings_t *settings = config_get_ptr();
|
|
||||||
int i = 0;
|
|
||||||
int zoomValue = m_zoomSlider->value();
|
|
||||||
|
|
||||||
m_gridProgressBar->setMinimum(0);
|
|
||||||
m_gridProgressBar->setMaximum(qMax(0, items.count() - 1));
|
|
||||||
m_gridProgressBar->setValue(0);
|
|
||||||
|
|
||||||
for (i = 0; i < items.count(); i++)
|
|
||||||
{
|
|
||||||
const QHash<QString, QString> &hash = items.at(i);
|
|
||||||
QPointer<GridItem> item;
|
|
||||||
QPointer<ThumbnailLabel> label;
|
|
||||||
QString thumbnailFileNameNoExt;
|
|
||||||
QLabel *newLabel = NULL;
|
|
||||||
QSize thumbnailWidgetSizeHint(screenSize.width() / 8, screenSize.height() / 8);
|
|
||||||
QByteArray extension;
|
|
||||||
QString extensionStr;
|
|
||||||
QString imagePath;
|
|
||||||
int lastIndex = -1;
|
|
||||||
|
|
||||||
if (m_listWidget->currentItem() != currentItem)
|
|
||||||
{
|
|
||||||
/* user changed the current playlist before we finished loading... abort */
|
|
||||||
m_gridProgressWidget->hide();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
item = new GridItem();
|
|
||||||
|
|
||||||
lastIndex = hash["path"].lastIndexOf('.');
|
|
||||||
|
|
||||||
if (lastIndex >= 0)
|
|
||||||
{
|
|
||||||
extensionStr = hash["path"].mid(lastIndex + 1);
|
|
||||||
|
|
||||||
if (!extensionStr.isEmpty())
|
|
||||||
{
|
|
||||||
extension = extensionStr.toLower().toUtf8();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!extension.isEmpty() && m_imageFormats.contains(extension))
|
|
||||||
{
|
|
||||||
/* use thumbnail widgets to show regular image files */
|
|
||||||
imagePath = hash["path"];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
thumbnailFileNameNoExt = hash["label_noext"];
|
|
||||||
thumbnailFileNameNoExt.replace(m_fileSanitizerRegex, "_");
|
|
||||||
imagePath = QString(settings->paths.directory_thumbnails) + "/" + hash.value("db_name") + "/" + THUMBNAIL_BOXART + "/" + thumbnailFileNameNoExt + ".png";
|
|
||||||
}
|
|
||||||
|
|
||||||
item->hash = hash;
|
|
||||||
item->widget = new ThumbnailWidget();
|
|
||||||
item->widget->setSizeHint(thumbnailWidgetSizeHint);
|
|
||||||
item->widget->setFixedSize(item->widget->sizeHint());
|
|
||||||
item->widget->setLayout(new QVBoxLayout());
|
|
||||||
item->widget->setObjectName("thumbnailWidget");
|
|
||||||
item->widget->setProperty("hash", QVariant::fromValue<QHash<QString, QString> >(hash));
|
|
||||||
item->widget->setProperty("image_path", imagePath);
|
|
||||||
|
|
||||||
connect(item->widget, SIGNAL(mouseDoubleClicked()), this, SLOT(onGridItemDoubleClicked()));
|
|
||||||
connect(item->widget, SIGNAL(mousePressed()), this, SLOT(onGridItemClicked()));
|
|
||||||
|
|
||||||
label = new ThumbnailLabel(item->widget);
|
|
||||||
label->setObjectName("thumbnailGridLabel");
|
|
||||||
|
|
||||||
item->label = label;
|
|
||||||
item->labelText = hash.value("label");
|
|
||||||
|
|
||||||
newLabel = new QLabel(item->labelText, item->widget);
|
|
||||||
newLabel->setObjectName("thumbnailQLabel");
|
|
||||||
newLabel->setAlignment(Qt::AlignCenter);
|
|
||||||
newLabel->setToolTip(item->labelText);
|
|
||||||
|
|
||||||
calcGridItemSize(item, zoomValue);
|
|
||||||
|
|
||||||
item->widget->layout()->addWidget(label);
|
|
||||||
|
|
||||||
item->widget->layout()->addWidget(newLabel);
|
|
||||||
qobject_cast<QVBoxLayout*>(item->widget->layout())->setStretchFactor(label, 1);
|
|
||||||
|
|
||||||
m_gridLayout->addWidgetDeferred(item->widget);
|
|
||||||
m_gridItems.append(item);
|
|
||||||
|
|
||||||
loadImageDeferred(item, imagePath);
|
|
||||||
|
|
||||||
if (i % 25 == 0)
|
|
||||||
{
|
|
||||||
/* Needed to update progress dialog while doing a lot of stuff on the main thread. */
|
|
||||||
qApp->processEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_gridProgressBar->setValue(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there's only one entry, a min/max/value of all zero would make an indeterminate progress bar that never ends... so just hide it when we are done. */
|
|
||||||
if (m_gridProgressBar->value() == m_gridProgressBar->maximum())
|
|
||||||
m_gridProgressWidget->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<QHash<QString, QString> > MainWindow::getPlaylistItems(QString pathString)
|
|
||||||
{
|
{
|
||||||
QByteArray pathArray;
|
QByteArray pathArray;
|
||||||
QVector<QHash<QString, QString> > items;
|
|
||||||
const char *pathData = NULL;
|
const char *pathData = NULL;
|
||||||
playlist_t *playlist = NULL;
|
playlist_t *playlist = NULL;
|
||||||
unsigned playlistSize = 0;
|
unsigned playlistSize = 0;
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
|
|
||||||
pathArray.append(pathString);
|
pathArray.append(path);
|
||||||
pathData = pathArray.constData();
|
pathData = pathArray.constData();
|
||||||
|
|
||||||
playlist = playlist_init(pathData, COLLECTION_SIZE);
|
playlist = playlist_init(pathData, COLLECTION_SIZE);
|
||||||
|
@ -1313,58 +1379,67 @@ QVector<QHash<QString, QString> > MainWindow::getPlaylistItems(QString pathStrin
|
||||||
hash["db_name"].remove(file_path_str(FILE_PATH_LPL_EXTENSION));
|
hash["db_name"].remove(file_path_str(FILE_PATH_LPL_EXTENSION));
|
||||||
}
|
}
|
||||||
|
|
||||||
items.append(hash);
|
m_contents.append(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist_free(playlist);
|
playlist_free(playlist);
|
||||||
playlist = NULL;
|
playlist = NULL;
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::addPlaylistItemsToTable(const QStringList &paths, bool add)
|
void PlaylistModel::addPlaylistItems(const QStringList &paths, bool add)
|
||||||
{
|
{
|
||||||
QVector<QHash<QString, QString> > items;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (paths.isEmpty())
|
if (paths.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
beginResetModel();
|
||||||
|
|
||||||
|
m_contents.clear();
|
||||||
|
|
||||||
for (i = 0; i < paths.size(); i++)
|
for (i = 0; i < paths.size(); i++)
|
||||||
{
|
{
|
||||||
int j;
|
getPlaylistItems(paths.at(i));
|
||||||
QVector<QHash<QString, QString> > vec = getPlaylistItems(paths.at(i));
|
|
||||||
/* QVector::append() wasn't added until 5.5, so just do it the old fashioned way */
|
|
||||||
for (j = 0; j < vec.size(); j++)
|
|
||||||
{
|
|
||||||
if (add && m_allPlaylistsListMaxCount > 0 && items.size() >= m_allPlaylistsListMaxCount)
|
|
||||||
goto finish;
|
|
||||||
|
|
||||||
items.append(vec.at(j));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finish:
|
|
||||||
addPlaylistHashToTable(items);
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::addPlaylistHashToTable(const QVector<QHash<QString, QString> > &items)
|
void PlaylistModel::addDir(QString path, QFlags<QDir::Filter> showHidden)
|
||||||
{
|
{
|
||||||
|
QDir dir = path;
|
||||||
|
QStringList dirList;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int oldRowCount = m_tableWidget->rowCount();
|
|
||||||
|
|
||||||
m_tableWidget->setRowCount(oldRowCount + items.count());
|
dirList = dir.entryList(QDir::NoDotAndDotDot |
|
||||||
|
QDir::Readable |
|
||||||
|
QDir::Files |
|
||||||
|
showHidden,
|
||||||
|
QDir::Name);
|
||||||
|
|
||||||
for (i = 0; i < items.count(); i++)
|
if (dirList.count() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
beginResetModel();
|
||||||
|
|
||||||
|
m_contents.clear();
|
||||||
|
|
||||||
|
for (i = 0; i < dirList.count(); i++)
|
||||||
{
|
{
|
||||||
QTableWidgetItem *labelItem = NULL;
|
QString fileName = dirList.at(i);
|
||||||
const QHash<QString, QString> &hash = items.at(i);
|
QHash<QString, QString> hash;
|
||||||
|
QString filePath(QDir::toNativeSeparators(dir.absoluteFilePath(fileName)));
|
||||||
|
QFileInfo fileInfo(filePath);
|
||||||
|
|
||||||
labelItem = new QTableWidgetItem(hash.value("label"));
|
hash["path"] = filePath;
|
||||||
labelItem->setData(Qt::UserRole, QVariant::fromValue<QHash<QString, QString> >(hash));
|
hash["label"] = hash["path"];
|
||||||
labelItem->setFlags(labelItem->flags() | Qt::ItemIsEditable);
|
hash["label_noext"] = fileInfo.completeBaseName();
|
||||||
|
hash["db_name"] = fileInfo.dir().dirName();
|
||||||
|
|
||||||
m_tableWidget->setItem(oldRowCount + i, 0, labelItem);
|
m_contents.append(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::setAllPlaylistsListMaxCount(int count)
|
void MainWindow::setAllPlaylistsListMaxCount(int count)
|
||||||
|
@ -1382,4 +1457,3 @@ void MainWindow::setAllPlaylistsGridMaxCount(int count)
|
||||||
|
|
||||||
m_allPlaylistsGridMaxCount = count;
|
m_allPlaylistsGridMaxCount = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,14 +150,14 @@ void MainWindow::onPlaylistThumbnailDownloadFinished()
|
||||||
emit showErrorMessageDeferred(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR)) + ": Code " + QString::number(code) + ": " + errorData);*/
|
emit showErrorMessageDeferred(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR)) + ": Code " + QString::number(code) + ": " + errorData);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_playlistModel->reloadThumbnailPath(m_playlistThumbnailDownloadFile.fileName());
|
||||||
|
|
||||||
if (!m_playlistThumbnailDownloadWasCanceled && m_pendingPlaylistThumbnails.count() > 0)
|
if (!m_playlistThumbnailDownloadWasCanceled && m_pendingPlaylistThumbnails.count() > 0)
|
||||||
{
|
{
|
||||||
QHash<QString, QString> nextThumbnail = m_pendingPlaylistThumbnails.takeAt(0);
|
QHash<QString, QString> nextThumbnail = m_pendingPlaylistThumbnails.takeAt(0);
|
||||||
ViewType viewType = getCurrentViewType();
|
ViewType viewType = getCurrentViewType();
|
||||||
|
|
||||||
if (viewType == VIEW_TYPE_ICONS)
|
updateVisibleItems();
|
||||||
emit gridItemChanged(reply->property("title").toString());
|
|
||||||
|
|
||||||
downloadNextPlaylistThumbnail(nextThumbnail.value("db_name"), nextThumbnail.value("label_noext"), nextThumbnail.value("type"));
|
downloadNextPlaylistThumbnail(nextThumbnail.value("db_name"), nextThumbnail.value("label_noext"), nextThumbnail.value("type"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -236,7 +236,7 @@ void MainWindow::downloadNextPlaylistThumbnail(QString system, QString title, QS
|
||||||
if (!m_playlistThumbnailDownloadFile.open(QIODevice::WriteOnly))
|
if (!m_playlistThumbnailDownloadFile.open(QIODevice::WriteOnly))
|
||||||
{
|
{
|
||||||
m_failedThumbnails++;
|
m_failedThumbnails++;
|
||||||
|
|
||||||
RARCH_ERR("[Qt]: Could not open file for writing: %s\n", fileNameData);
|
RARCH_ERR("[Qt]: Could not open file for writing: %s\n", fileNameData);
|
||||||
|
|
||||||
if (m_pendingPlaylistThumbnails.count() > 0)
|
if (m_pendingPlaylistThumbnails.count() > 0)
|
||||||
|
@ -290,9 +290,9 @@ void MainWindow::downloadPlaylistThumbnails(QString playlistPath)
|
||||||
QString system;
|
QString system;
|
||||||
QString title;
|
QString title;
|
||||||
QString type;
|
QString type;
|
||||||
QVector<QHash<QString, QString> > playlistItems = getPlaylistItems(playlistPath);
|
|
||||||
settings_t *settings = config_get_ptr();
|
settings_t *settings = config_get_ptr();
|
||||||
int i;
|
int i;
|
||||||
|
int count;
|
||||||
|
|
||||||
if (!settings || !playlistFile.exists())
|
if (!settings || !playlistFile.exists())
|
||||||
return;
|
return;
|
||||||
|
@ -302,12 +302,14 @@ void MainWindow::downloadPlaylistThumbnails(QString playlistPath)
|
||||||
m_failedThumbnails = 0;
|
m_failedThumbnails = 0;
|
||||||
m_playlistThumbnailDownloadWasCanceled = false;
|
m_playlistThumbnailDownloadWasCanceled = false;
|
||||||
|
|
||||||
if (playlistItems.count() == 0)
|
count = m_playlistModel->rowCount();
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < playlistItems.count(); i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
const QHash<QString, QString> &itemHash = playlistItems.at(i);
|
const QHash<QString, QString> &itemHash = m_playlistModel->index(i, 0).data(PlaylistModel::HASH).value< QHash<QString, QString> >();
|
||||||
QHash<QString, QString> hash;
|
QHash<QString, QString> hash;
|
||||||
QHash<QString, QString> hash2;
|
QHash<QString, QString> hash2;
|
||||||
QHash<QString, QString> hash3;
|
QHash<QString, QString> hash3;
|
||||||
|
|
|
@ -154,6 +154,8 @@ void MainWindow::onThumbnailDownloadFinished()
|
||||||
{
|
{
|
||||||
RARCH_LOG("[Qt]: Thumbnail download finished successfully.\n");
|
RARCH_LOG("[Qt]: Thumbnail download finished successfully.\n");
|
||||||
/* reload thumbnail image */
|
/* reload thumbnail image */
|
||||||
|
m_playlistModel->reloadThumbnailPath(m_thumbnailDownloadFile.fileName());
|
||||||
|
updateVisibleItems();
|
||||||
emit itemChanged();
|
emit itemChanged();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -191,7 +191,6 @@ void MainWindow::onThumbnailPackDownloadFinished()
|
||||||
|
|
||||||
reply->disconnect();
|
reply->disconnect();
|
||||||
reply->close();
|
reply->close();
|
||||||
reply->deleteLater();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onThumbnailPackDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
void MainWindow::onThumbnailPackDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||||
|
@ -309,6 +308,11 @@ void MainWindow::onThumbnailPackExtractFinished(bool success)
|
||||||
|
|
||||||
emit showInfoMessageDeferred(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_PACK_DOWNLOADED_SUCCESSFULLY));
|
emit showInfoMessageDeferred(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_PACK_DOWNLOADED_SUCCESSFULLY));
|
||||||
|
|
||||||
|
QNetworkReply *reply = m_thumbnailPackDownloadReply.data();
|
||||||
|
|
||||||
|
m_playlistModel->reloadSystemThumbnails(reply->property("system").toString());
|
||||||
|
reply->deleteLater();
|
||||||
|
updateVisibleItems();
|
||||||
/* reload thumbnail image */
|
/* reload thumbnail image */
|
||||||
emit itemChanged();
|
emit itemChanged();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ extern "C" {
|
||||||
#include <string/stdstring.h>
|
#include <string/stdstring.h>
|
||||||
#include <file/file_path.h>
|
#include <file/file_path.h>
|
||||||
#include <retro_miscellaneous.h>
|
#include <retro_miscellaneous.h>
|
||||||
};
|
}
|
||||||
|
|
||||||
#define CORE_NAME_COLUMN 0
|
#define CORE_NAME_COLUMN 0
|
||||||
#define CORE_VERSION_COLUMN 1
|
#define CORE_VERSION_COLUMN 1
|
||||||
|
|
|
@ -313,7 +313,7 @@ static const QString qt_theme_dark_stylesheet = QStringLiteral(R"(
|
||||||
padding-left:5px;
|
padding-left:5px;
|
||||||
padding-right:5px;
|
padding-right:5px;
|
||||||
}
|
}
|
||||||
QTableWidget {
|
QTableView {
|
||||||
background-color:rgb(25,25,25);
|
background-color:rgb(25,25,25);
|
||||||
alternate-background-color:rgb(40,40,40);
|
alternate-background-color:rgb(40,40,40);
|
||||||
}
|
}
|
||||||
|
@ -422,14 +422,18 @@ static const QString qt_theme_dark_stylesheet = QStringLiteral(R"(
|
||||||
QSizeGrip {
|
QSizeGrip {
|
||||||
background-color:solid;
|
background-color:solid;
|
||||||
}
|
}
|
||||||
ThumbnailWidget#thumbnailWidget, ThumbnailLabel#thumbnailGridLabel, QLabel#thumbnailQLabel {
|
GridView::item {
|
||||||
background-color:rgb(40,40,40);
|
background-color:rgb(40,40,40);
|
||||||
}
|
}
|
||||||
ThumbnailWidget#thumbnailWidgetSelected {
|
GridView::item:selected {
|
||||||
background-color:rgb(40,40,40);
|
|
||||||
border:3px solid %1;
|
border:3px solid %1;
|
||||||
}
|
}
|
||||||
QWidget#gridLayoutWidget {
|
GridView {
|
||||||
background-color:rgb(25,25,25);
|
background-color:rgb(25,25,25);
|
||||||
|
selection-color: white;
|
||||||
|
qproperty-layout: "fixed";
|
||||||
|
}
|
||||||
|
GridItem {
|
||||||
|
qproperty-thumbnailvalign: "center";
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -19,7 +19,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewOptionsDialog::ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent) :
|
ViewOptionsDialog::ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent) :
|
||||||
QDialog(parent)
|
QDialog(mainwindow)
|
||||||
,m_mainwindow(mainwindow)
|
,m_mainwindow(mainwindow)
|
||||||
,m_settings(mainwindow->settings())
|
,m_settings(mainwindow->settings())
|
||||||
,m_saveGeometryCheckBox(new QCheckBox(this))
|
,m_saveGeometryCheckBox(new QCheckBox(this))
|
||||||
|
@ -27,6 +27,8 @@ ViewOptionsDialog::ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent) :
|
||||||
,m_saveLastTabCheckBox(new QCheckBox(this))
|
,m_saveLastTabCheckBox(new QCheckBox(this))
|
||||||
,m_showHiddenFilesCheckBox(new QCheckBox(this))
|
,m_showHiddenFilesCheckBox(new QCheckBox(this))
|
||||||
,m_themeComboBox(new QComboBox(this))
|
,m_themeComboBox(new QComboBox(this))
|
||||||
|
,m_thumbnailComboBox(new QComboBox(this))
|
||||||
|
,m_thumbnailCacheSpinBox(new QSpinBox(this))
|
||||||
,m_startupPlaylistComboBox(new QComboBox(this))
|
,m_startupPlaylistComboBox(new QComboBox(this))
|
||||||
,m_highlightColorPushButton(new QPushButton(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CHOOSE), this))
|
,m_highlightColorPushButton(new QPushButton(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CHOOSE), this))
|
||||||
,m_highlightColor()
|
,m_highlightColor()
|
||||||
|
@ -45,6 +47,13 @@ ViewOptionsDialog::ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent) :
|
||||||
m_themeComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_DARK), MainWindow::THEME_DARK);
|
m_themeComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_DARK), MainWindow::THEME_DARK);
|
||||||
m_themeComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_CUSTOM), MainWindow::THEME_CUSTOM);
|
m_themeComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_CUSTOM), MainWindow::THEME_CUSTOM);
|
||||||
|
|
||||||
|
m_thumbnailComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_BOXART), THUMBNAIL_TYPE_BOXART);
|
||||||
|
m_thumbnailComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_SCREENSHOT), THUMBNAIL_TYPE_SCREENSHOT);
|
||||||
|
m_thumbnailComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_TITLE_SCREEN), THUMBNAIL_TYPE_TITLE_SCREEN);
|
||||||
|
|
||||||
|
m_thumbnailCacheSpinBox->setSuffix(" MB");
|
||||||
|
m_thumbnailCacheSpinBox->setRange(0, 99999);
|
||||||
|
|
||||||
m_allPlaylistsListMaxCountSpinBox->setRange(0, 99999);
|
m_allPlaylistsListMaxCountSpinBox->setRange(0, 99999);
|
||||||
m_allPlaylistsGridMaxCountSpinBox->setRange(0, 99999);
|
m_allPlaylistsGridMaxCountSpinBox->setRange(0, 99999);
|
||||||
|
|
||||||
|
@ -67,6 +76,8 @@ ViewOptionsDialog::ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent) :
|
||||||
form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_LIST_MAX_COUNT), m_allPlaylistsListMaxCountSpinBox);
|
form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_LIST_MAX_COUNT), m_allPlaylistsListMaxCountSpinBox);
|
||||||
form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_GRID_MAX_COUNT), m_allPlaylistsGridMaxCountSpinBox);
|
form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_GRID_MAX_COUNT), m_allPlaylistsGridMaxCountSpinBox);
|
||||||
form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_STARTUP_PLAYLIST), m_startupPlaylistComboBox);
|
form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_STARTUP_PLAYLIST), m_startupPlaylistComboBox);
|
||||||
|
form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THUMBNAIL_TYPE), m_thumbnailComboBox);
|
||||||
|
form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THUMBNAIL_CACHE_LIMIT), m_thumbnailCacheSpinBox);
|
||||||
form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME), m_themeComboBox);
|
form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME), m_themeComboBox);
|
||||||
form->addRow(m_highlightColorLabel, m_highlightColorPushButton);
|
form->addRow(m_highlightColorLabel, m_highlightColorPushButton);
|
||||||
|
|
||||||
|
@ -77,9 +88,16 @@ ViewOptionsDialog::ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent) :
|
||||||
loadViewOptions();
|
loadViewOptions();
|
||||||
|
|
||||||
connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onThemeComboBoxIndexChanged(int)));
|
connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onThemeComboBoxIndexChanged(int)));
|
||||||
|
connect(m_thumbnailComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onThumbnailComboBoxIndexChanged(int)));
|
||||||
connect(m_highlightColorPushButton, SIGNAL(clicked()), this, SLOT(onHighlightColorChoose()));
|
connect(m_highlightColorPushButton, SIGNAL(clicked()), this, SLOT(onHighlightColorChoose()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewOptionsDialog::onThumbnailComboBoxIndexChanged(int index)
|
||||||
|
{
|
||||||
|
ThumbnailType type = static_cast<ThumbnailType>(m_thumbnailComboBox->currentData().value<int>());
|
||||||
|
m_mainwindow->setCurrentThumbnailType(type);
|
||||||
|
}
|
||||||
|
|
||||||
void ViewOptionsDialog::onThemeComboBoxIndexChanged(int)
|
void ViewOptionsDialog::onThemeComboBoxIndexChanged(int)
|
||||||
{
|
{
|
||||||
MainWindow::Theme theme = static_cast<MainWindow::Theme>(m_themeComboBox->currentData(Qt::UserRole).toInt());
|
MainWindow::Theme theme = static_cast<MainWindow::Theme>(m_themeComboBox->currentData(Qt::UserRole).toInt());
|
||||||
|
@ -138,6 +156,7 @@ void ViewOptionsDialog::loadViewOptions()
|
||||||
QVector<QPair<QString, QString> > playlists = m_mainwindow->getPlaylists();
|
QVector<QPair<QString, QString> > playlists = m_mainwindow->getPlaylists();
|
||||||
QString initialPlaylist = m_settings->value("initial_playlist", m_mainwindow->getSpecialPlaylistPath(SPECIAL_PLAYLIST_HISTORY)).toString();
|
QString initialPlaylist = m_settings->value("initial_playlist", m_mainwindow->getSpecialPlaylistPath(SPECIAL_PLAYLIST_HISTORY)).toString();
|
||||||
int themeIndex = 0;
|
int themeIndex = 0;
|
||||||
|
int thumbnailIndex = 0;
|
||||||
int playlistIndex = 0;
|
int playlistIndex = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -148,12 +167,18 @@ void ViewOptionsDialog::loadViewOptions()
|
||||||
m_suggestLoadedCoreFirstCheckBox->setChecked(m_settings->value("suggest_loaded_core_first", false).toBool());
|
m_suggestLoadedCoreFirstCheckBox->setChecked(m_settings->value("suggest_loaded_core_first", false).toBool());
|
||||||
m_allPlaylistsListMaxCountSpinBox->setValue(m_settings->value("all_playlists_list_max_count", 0).toInt());
|
m_allPlaylistsListMaxCountSpinBox->setValue(m_settings->value("all_playlists_list_max_count", 0).toInt());
|
||||||
m_allPlaylistsGridMaxCountSpinBox->setValue(m_settings->value("all_playlists_grid_max_count", 5000).toInt());
|
m_allPlaylistsGridMaxCountSpinBox->setValue(m_settings->value("all_playlists_grid_max_count", 5000).toInt());
|
||||||
|
m_thumbnailCacheSpinBox->setValue(m_settings->value("thumbnail_cache_limit", 512).toInt());
|
||||||
|
|
||||||
themeIndex = m_themeComboBox->findData(m_mainwindow->getThemeFromString(m_settings->value("theme", "default").toString()));
|
themeIndex = m_themeComboBox->findData(m_mainwindow->getThemeFromString(m_settings->value("theme", "default").toString()));
|
||||||
|
|
||||||
if (m_themeComboBox->count() > themeIndex)
|
if (m_themeComboBox->count() > themeIndex)
|
||||||
m_themeComboBox->setCurrentIndex(themeIndex);
|
m_themeComboBox->setCurrentIndex(themeIndex);
|
||||||
|
|
||||||
|
thumbnailIndex = m_thumbnailComboBox->findData(m_mainwindow->getThumbnailTypeFromString(m_settings->value("icon_view_thumbnail_type", "boxart").toString()));
|
||||||
|
|
||||||
|
if (m_thumbnailComboBox->count() > thumbnailIndex)
|
||||||
|
m_thumbnailComboBox->setCurrentIndex(thumbnailIndex);
|
||||||
|
|
||||||
if (highlightColor.isValid())
|
if (highlightColor.isValid())
|
||||||
{
|
{
|
||||||
m_highlightColor = highlightColor;
|
m_highlightColor = highlightColor;
|
||||||
|
@ -204,12 +229,15 @@ void ViewOptionsDialog::saveViewOptions()
|
||||||
m_settings->setValue("all_playlists_list_max_count", m_allPlaylistsListMaxCountSpinBox->value());
|
m_settings->setValue("all_playlists_list_max_count", m_allPlaylistsListMaxCountSpinBox->value());
|
||||||
m_settings->setValue("all_playlists_grid_max_count", m_allPlaylistsGridMaxCountSpinBox->value());
|
m_settings->setValue("all_playlists_grid_max_count", m_allPlaylistsGridMaxCountSpinBox->value());
|
||||||
m_settings->setValue("initial_playlist", m_startupPlaylistComboBox->currentData(Qt::UserRole).toString());
|
m_settings->setValue("initial_playlist", m_startupPlaylistComboBox->currentData(Qt::UserRole).toString());
|
||||||
|
m_settings->setValue("icon_view_thumbnail_type", m_mainwindow->getCurrentThumbnailTypeString());
|
||||||
|
m_settings->setValue("thumbnail_cache_limit", m_thumbnailCacheSpinBox->value());
|
||||||
|
|
||||||
if (!m_mainwindow->customThemeString().isEmpty())
|
if (!m_mainwindow->customThemeString().isEmpty())
|
||||||
m_settings->setValue("custom_theme", m_customThemePath);
|
m_settings->setValue("custom_theme", m_customThemePath);
|
||||||
|
|
||||||
m_mainwindow->setAllPlaylistsListMaxCount(m_allPlaylistsListMaxCountSpinBox->value());
|
m_mainwindow->setAllPlaylistsListMaxCount(m_allPlaylistsListMaxCountSpinBox->value());
|
||||||
m_mainwindow->setAllPlaylistsGridMaxCount(m_allPlaylistsGridMaxCountSpinBox->value());
|
m_mainwindow->setAllPlaylistsGridMaxCount(m_allPlaylistsGridMaxCountSpinBox->value());
|
||||||
|
m_mainwindow->setThumbnailCacheLimit(m_thumbnailCacheSpinBox->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewOptionsDialog::onAccepted()
|
void ViewOptionsDialog::onAccepted()
|
||||||
|
@ -229,11 +257,12 @@ void ViewOptionsDialog::onRejected()
|
||||||
void ViewOptionsDialog::showDialog()
|
void ViewOptionsDialog::showDialog()
|
||||||
{
|
{
|
||||||
loadViewOptions();
|
loadViewOptions();
|
||||||
|
setWindowFlags(windowFlags() | Qt::Tool);
|
||||||
show();
|
show();
|
||||||
|
activateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewOptionsDialog::hideDialog()
|
void ViewOptionsDialog::hideDialog()
|
||||||
{
|
{
|
||||||
reject();
|
reject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ public slots:
|
||||||
void onRejected();
|
void onRejected();
|
||||||
private slots:
|
private slots:
|
||||||
void onThemeComboBoxIndexChanged(int index);
|
void onThemeComboBoxIndexChanged(int index);
|
||||||
|
void onThumbnailComboBoxIndexChanged(int index);
|
||||||
void onHighlightColorChoose();
|
void onHighlightColorChoose();
|
||||||
private:
|
private:
|
||||||
void loadViewOptions();
|
void loadViewOptions();
|
||||||
|
@ -37,6 +38,8 @@ private:
|
||||||
QCheckBox *m_saveLastTabCheckBox;
|
QCheckBox *m_saveLastTabCheckBox;
|
||||||
QCheckBox *m_showHiddenFilesCheckBox;
|
QCheckBox *m_showHiddenFilesCheckBox;
|
||||||
QComboBox *m_themeComboBox;
|
QComboBox *m_themeComboBox;
|
||||||
|
QComboBox *m_thumbnailComboBox;
|
||||||
|
QSpinBox *m_thumbnailCacheSpinBox;
|
||||||
QComboBox *m_startupPlaylistComboBox;
|
QComboBox *m_startupPlaylistComboBox;
|
||||||
QPushButton *m_highlightColorPushButton;
|
QPushButton *m_highlightColorPushButton;
|
||||||
QColor m_highlightColor;
|
QColor m_highlightColor;
|
||||||
|
|
|
@ -293,11 +293,12 @@ static void* ui_companion_qt_init(void)
|
||||||
widget->setContextMenuPolicy(Qt::CustomContextMenu);
|
widget->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
|
||||||
QObject::connect(widget, SIGNAL(filesDropped(QStringList)), mainwindow, SLOT(onPlaylistFilesDropped(QStringList)));
|
QObject::connect(widget, SIGNAL(filesDropped(QStringList)), mainwindow, SLOT(onPlaylistFilesDropped(QStringList)));
|
||||||
|
QObject::connect(widget, SIGNAL(enterPressed()), mainwindow, SLOT(onDropWidgetEnterPressed()));
|
||||||
QObject::connect(widget, SIGNAL(deletePressed()), mainwindow, SLOT(deleteCurrentPlaylistItem()));
|
QObject::connect(widget, SIGNAL(deletePressed()), mainwindow, SLOT(deleteCurrentPlaylistItem()));
|
||||||
QObject::connect(widget, SIGNAL(customContextMenuRequested(const QPoint&)), mainwindow, SLOT(onFileDropWidgetContextMenuRequested(const QPoint&)));
|
QObject::connect(widget, SIGNAL(customContextMenuRequested(const QPoint&)), mainwindow, SLOT(onFileDropWidgetContextMenuRequested(const QPoint&)));
|
||||||
|
|
||||||
layout = new QVBoxLayout();
|
layout = new QVBoxLayout();
|
||||||
layout->addWidget(mainwindow->contentTableWidget());
|
layout->addWidget(mainwindow->contentTableView());
|
||||||
layout->addWidget(mainwindow->contentGridWidget());
|
layout->addWidget(mainwindow->contentGridWidget());
|
||||||
|
|
||||||
widget->setLayout(layout);
|
widget->setLayout(layout);
|
||||||
|
@ -513,6 +514,11 @@ static void* ui_companion_qt_init(void)
|
||||||
if (qsettings->contains("all_playlists_grid_max_count"))
|
if (qsettings->contains("all_playlists_grid_max_count"))
|
||||||
mainwindow->setAllPlaylistsGridMaxCount(qsettings->value("all_playlists_grid_max_count", 5000).toInt());
|
mainwindow->setAllPlaylistsGridMaxCount(qsettings->value("all_playlists_grid_max_count", 5000).toInt());
|
||||||
|
|
||||||
|
if (qsettings->contains("thumbnail_cache_limit"))
|
||||||
|
mainwindow->setThumbnailCacheLimit(qsettings->value("thumbnail_cache_limit", 500).toInt());
|
||||||
|
else
|
||||||
|
mainwindow->setThumbnailCacheLimit(500);
|
||||||
|
|
||||||
if (qsettings->contains("geometry"))
|
if (qsettings->contains("geometry"))
|
||||||
if (qsettings->contains("save_geometry"))
|
if (qsettings->contains("save_geometry"))
|
||||||
mainwindow->restoreGeometry(qsettings->value("geometry").toByteArray());
|
mainwindow->restoreGeometry(qsettings->value("geometry").toByteArray());
|
||||||
|
@ -555,6 +561,25 @@ static void* ui_companion_qt_init(void)
|
||||||
else
|
else
|
||||||
mainwindow->setCurrentViewType(MainWindow::VIEW_TYPE_LIST);
|
mainwindow->setCurrentViewType(MainWindow::VIEW_TYPE_LIST);
|
||||||
|
|
||||||
|
if (qsettings->contains("icon_view_thumbnail_type"))
|
||||||
|
{
|
||||||
|
QString thumbnailType = qsettings->value("icon_view_thumbnail_type", "boxart").toString();
|
||||||
|
|
||||||
|
if (thumbnailType == "boxart")
|
||||||
|
mainwindow->setCurrentThumbnailType(THUMBNAIL_TYPE_BOXART);
|
||||||
|
else if (thumbnailType == "screenshot")
|
||||||
|
mainwindow->setCurrentThumbnailType(THUMBNAIL_TYPE_SCREENSHOT);
|
||||||
|
else if (thumbnailType == "title")
|
||||||
|
mainwindow->setCurrentThumbnailType(THUMBNAIL_TYPE_TITLE_SCREEN);
|
||||||
|
else
|
||||||
|
mainwindow->setCurrentThumbnailType(THUMBNAIL_TYPE_BOXART);
|
||||||
|
|
||||||
|
/* we set it to the same thing a second time so that m_lastThumbnailType is also equal to the startup view type */
|
||||||
|
mainwindow->setCurrentThumbnailType(mainwindow->getCurrentThumbnailType());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mainwindow->setCurrentViewType(MainWindow::VIEW_TYPE_LIST);
|
||||||
|
|
||||||
/* We make sure to hook up the tab widget callback only after the tabs themselves have been added,
|
/* We make sure to hook up the tab widget callback only after the tabs themselves have been added,
|
||||||
* but before changing to a specific one, to avoid the callback firing before the view type is set.
|
* but before changing to a specific one, to avoid the callback firing before the view type is set.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QTableWidget>
|
#include <QTableView>
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
@ -38,6 +38,10 @@
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#include <QSslError>
|
#include <QSslError>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
#include <QCache>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <retro_assert.h>
|
#include <retro_assert.h>
|
||||||
|
@ -84,7 +88,7 @@ class LoadCoreWindow;
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
class ThumbnailWidget;
|
class ThumbnailWidget;
|
||||||
class ThumbnailLabel;
|
class ThumbnailLabel;
|
||||||
class FlowLayout;
|
class GridView;
|
||||||
class ShaderParamsDialog;
|
class ShaderParamsDialog;
|
||||||
class CoreOptionsDialog;
|
class CoreOptionsDialog;
|
||||||
class CoreInfoDialog;
|
class CoreInfoDialog;
|
||||||
|
@ -96,19 +100,58 @@ enum SpecialPlaylist
|
||||||
SPECIAL_PLAYLIST_HISTORY
|
SPECIAL_PLAYLIST_HISTORY
|
||||||
};
|
};
|
||||||
|
|
||||||
class GridItem : public QObject
|
enum ThumbnailType
|
||||||
|
{
|
||||||
|
THUMBNAIL_TYPE_BOXART,
|
||||||
|
THUMBNAIL_TYPE_SCREENSHOT,
|
||||||
|
THUMBNAIL_TYPE_TITLE_SCREEN,
|
||||||
|
};
|
||||||
|
|
||||||
|
class PlaylistModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
|
||||||
GridItem();
|
|
||||||
|
|
||||||
QPointer<ThumbnailWidget> widget;
|
public:
|
||||||
QPointer<ThumbnailLabel> label;
|
enum Roles
|
||||||
QHash<QString, QString> hash;
|
{
|
||||||
QImage image;
|
HASH = Qt::UserRole + 1,
|
||||||
QPixmap pixmap;
|
THUMBNAIL
|
||||||
QFutureWatcher<GridItem*> imageWatcher;
|
};
|
||||||
QString labelText;
|
|
||||||
|
PlaylistModel(QObject *parent = 0);
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
void addPlaylistItems(const QStringList &paths, bool add = false);
|
||||||
|
void addDir(QString path, QFlags<QDir::Filter> showHidden);
|
||||||
|
void setThumbnailType(const ThumbnailType type);
|
||||||
|
void loadThumbnail(const QModelIndex &index);
|
||||||
|
void reloadThumbnail(const QModelIndex &index);
|
||||||
|
void reloadThumbnailPath(const QString path);
|
||||||
|
void reloadSystemThumbnails(const QString system);
|
||||||
|
void setThumbnailCacheLimit(int limit);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void imageLoaded(const QImage image, const QModelIndex &index, const QString &path);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onImageLoaded(const QImage image, const QModelIndex &index, const QString &path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<QHash<QString, QString> > m_contents;
|
||||||
|
QCache<QString, QPixmap> m_cache;
|
||||||
|
QSet<QString> m_pendingImages;
|
||||||
|
QVector<QByteArray> m_imageFormats;
|
||||||
|
QRegularExpression m_fileSanitizerRegex;
|
||||||
|
ThumbnailType m_thumbnailType = THUMBNAIL_TYPE_BOXART;
|
||||||
|
QString getThumbnailPath(const QModelIndex &index, QString type) const;
|
||||||
|
QString getCurrentTypeThumbnailPath(const QModelIndex &index) const;
|
||||||
|
void getPlaylistItems(QString path);
|
||||||
|
void loadImage(const QModelIndex &index, const QString &path);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThumbnailWidget : public QFrame
|
class ThumbnailWidget : public QFrame
|
||||||
|
@ -164,17 +207,12 @@ protected slots:
|
||||||
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TableWidget : public QTableWidget
|
class TableView : public QTableView
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
TableWidget(QWidget *parent = 0);
|
TableView(QWidget *parent = 0);
|
||||||
bool isEditorOpen();
|
bool isEditorOpen();
|
||||||
signals:
|
|
||||||
void enterPressed();
|
|
||||||
void deletePressed();
|
|
||||||
protected:
|
|
||||||
void keyPressEvent(QKeyEvent *event);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ListWidget : public QListWidget
|
class ListWidget : public QListWidget
|
||||||
|
@ -233,6 +271,26 @@ public slots:
|
||||||
void appendMessage(const QString& text);
|
void appendMessage(const QString& text);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Used to store styling since delegates don't inherit QWidget. */
|
||||||
|
class GridItem : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QString thumbnailvalign READ getThumbnailVerticalAlign WRITE setThumbnailVerticalAlign)
|
||||||
|
Q_PROPERTY(int padding READ getPadding WRITE setPadding)
|
||||||
|
|
||||||
|
public:
|
||||||
|
GridItem(QWidget* parent);
|
||||||
|
|
||||||
|
Qt::AlignmentFlag thumbnailVerticalAlignmentFlag;
|
||||||
|
int padding;
|
||||||
|
|
||||||
|
int getPadding() const;
|
||||||
|
void setPadding(const int value);
|
||||||
|
QString getThumbnailVerticalAlign() const;
|
||||||
|
void setThumbnailVerticalAlign(const QString valign);
|
||||||
|
};
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -263,9 +321,10 @@ public:
|
||||||
MainWindow(QWidget *parent = NULL);
|
MainWindow(QWidget *parent = NULL);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
TreeView* dirTreeView();
|
TreeView* dirTreeView();
|
||||||
|
PlaylistModel* playlistModel();
|
||||||
ListWidget* playlistListWidget();
|
ListWidget* playlistListWidget();
|
||||||
TableWidget* contentTableWidget();
|
TableView* contentTableView();
|
||||||
FlowLayout* contentGridLayout();
|
GridView* contentGridView();
|
||||||
QWidget* contentGridWidget();
|
QWidget* contentGridWidget();
|
||||||
QWidget* searchWidget();
|
QWidget* searchWidget();
|
||||||
QLineEdit* searchLineEdit();
|
QLineEdit* searchLineEdit();
|
||||||
|
@ -289,20 +348,26 @@ public:
|
||||||
bool setCustomThemeFile(QString filePath);
|
bool setCustomThemeFile(QString filePath);
|
||||||
void setCustomThemeString(QString qss);
|
void setCustomThemeString(QString qss);
|
||||||
const QString& customThemeString() const;
|
const QString& customThemeString() const;
|
||||||
GridItem* doDeferredImageLoad(GridItem *item, QString path);
|
|
||||||
void setCurrentViewType(ViewType viewType);
|
void setCurrentViewType(ViewType viewType);
|
||||||
QString getCurrentViewTypeString();
|
QString getCurrentViewTypeString();
|
||||||
ViewType getCurrentViewType();
|
ViewType getCurrentViewType();
|
||||||
|
void setCurrentThumbnailType(ThumbnailType thumbnailType);
|
||||||
|
QString getCurrentThumbnailTypeString();
|
||||||
|
ThumbnailType getCurrentThumbnailType();
|
||||||
|
ThumbnailType getThumbnailTypeFromString(QString thumbnailType);
|
||||||
void setAllPlaylistsListMaxCount(int count);
|
void setAllPlaylistsListMaxCount(int count);
|
||||||
void setAllPlaylistsGridMaxCount(int count);
|
void setAllPlaylistsGridMaxCount(int count);
|
||||||
|
void setThumbnailCacheLimit(int count);
|
||||||
PlaylistEntryDialog* playlistEntryDialog();
|
PlaylistEntryDialog* playlistEntryDialog();
|
||||||
void addFilesToPlaylist(QStringList files);
|
void addFilesToPlaylist(QStringList files);
|
||||||
QString getCurrentPlaylistPath();
|
QString getCurrentPlaylistPath();
|
||||||
|
QModelIndex getCurrentContentIndex();
|
||||||
QHash<QString, QString> getCurrentContentHash();
|
QHash<QString, QString> getCurrentContentHash();
|
||||||
static double lerp(double x, double y, double a, double b, double d);
|
static double lerp(double x, double y, double a, double b, double d);
|
||||||
QString getSpecialPlaylistPath(SpecialPlaylist playlist);
|
QString getSpecialPlaylistPath(SpecialPlaylist playlist);
|
||||||
QVector<QPair<QString, QString> > getPlaylists();
|
QVector<QPair<QString, QString> > getPlaylists();
|
||||||
QString getScrubbedString(QString str);
|
QString getScrubbedString(QString str);
|
||||||
|
void setDefaultCustomProperties();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void thumbnailChanged(const QPixmap &pixmap);
|
void thumbnailChanged(const QPixmap &pixmap);
|
||||||
|
@ -317,6 +382,7 @@ signals:
|
||||||
void showInfoMessageDeferred(QString msg);
|
void showInfoMessageDeferred(QString msg);
|
||||||
void extractArchiveDeferred(QString path, QString extractionDir, QString tempExtension, retro_task_callback_t cb);
|
void extractArchiveDeferred(QString path, QString extractionDir, QString tempExtension, retro_task_callback_t cb);
|
||||||
void itemChanged();
|
void itemChanged();
|
||||||
|
void updateThumbnails();
|
||||||
void gridItemChanged(QString title);
|
void gridItemChanged(QString title);
|
||||||
void gotThumbnailDownload(QString system, QString title);
|
void gotThumbnailDownload(QString system, QString title);
|
||||||
void scrollToDownloads(QString path);
|
void scrollToDownloads(QString path);
|
||||||
|
@ -327,15 +393,13 @@ public slots:
|
||||||
void onBrowserUpClicked();
|
void onBrowserUpClicked();
|
||||||
void onBrowserStartClicked();
|
void onBrowserStartClicked();
|
||||||
void initContentTableWidget();
|
void initContentTableWidget();
|
||||||
void initContentGridLayout();
|
|
||||||
void onViewClosedDocksAboutToShow();
|
void onViewClosedDocksAboutToShow();
|
||||||
void onShowHiddenDockWidgetAction();
|
void onShowHiddenDockWidgetAction();
|
||||||
void setCoreActions();
|
void setCoreActions();
|
||||||
void onRunClicked();
|
void onRunClicked();
|
||||||
void loadContent(const QHash<QString, QString> &contentHash);
|
void loadContent(const QHash<QString, QString> &contentHash);
|
||||||
void onStartCoreClicked();
|
void onStartCoreClicked();
|
||||||
void onTableWidgetEnterPressed();
|
void onDropWidgetEnterPressed();
|
||||||
void onTableWidgetDeletePressed();
|
|
||||||
void selectBrowserDir(QString path);
|
void selectBrowserDir(QString path);
|
||||||
void resizeThumbnails(bool one, bool two, bool three);
|
void resizeThumbnails(bool one, bool two, bool three);
|
||||||
void onResizeThumbnailOne();
|
void onResizeThumbnailOne();
|
||||||
|
@ -365,24 +429,20 @@ public slots:
|
||||||
void downloadAllThumbnails(QString system, QUrl url = QUrl());
|
void downloadAllThumbnails(QString system, QUrl url = QUrl());
|
||||||
void downloadPlaylistThumbnails(QString playlistPath);
|
void downloadPlaylistThumbnails(QString playlistPath);
|
||||||
void downloadNextPlaylistThumbnail(QString system, QString title, QString type, QUrl url = QUrl());
|
void downloadNextPlaylistThumbnail(QString system, QString title, QString type, QUrl url = QUrl());
|
||||||
|
void changeThumbnailType(ThumbnailType type);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onLoadCoreClicked(const QStringList &extensionFilters = QStringList());
|
void onLoadCoreClicked(const QStringList &extensionFilters = QStringList());
|
||||||
void onUnloadCoreMenuAction();
|
void onUnloadCoreMenuAction();
|
||||||
void onTimeout();
|
void onTimeout();
|
||||||
void onCoreLoaded();
|
void onCoreLoaded();
|
||||||
|
void onCurrentTableItemDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
|
||||||
void onCurrentListItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
|
void onCurrentListItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
|
||||||
void onCurrentTableItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous);
|
|
||||||
void onCurrentTableItemDataChanged(QTableWidgetItem *item);
|
|
||||||
void onCurrentListItemDataChanged(QListWidgetItem *item);
|
void onCurrentListItemDataChanged(QListWidgetItem *item);
|
||||||
void currentItemChanged(const QHash<QString, QString> &hash);
|
void currentItemChanged(const QModelIndex &index);
|
||||||
void onSearchEnterPressed();
|
void onSearchEnterPressed();
|
||||||
void onSearchLineEditEdited(const QString &text);
|
void onSearchLineEditEdited(const QString &text);
|
||||||
void addPlaylistItemsToTable(const QStringList &paths, bool all = false);
|
void onContentItemDoubleClicked(const QModelIndex &index);
|
||||||
void addPlaylistHashToTable(const QVector<QHash<QString, QString> > &items);
|
|
||||||
void addPlaylistItemsToGrid(const QStringList &paths, bool all = false);
|
|
||||||
void addPlaylistHashToGrid(const QVector<QHash<QString, QString> > &items);
|
|
||||||
void onContentItemDoubleClicked(QTableWidgetItem *item);
|
|
||||||
void onCoreLoadWindowClosed();
|
void onCoreLoadWindowClosed();
|
||||||
void onTreeViewItemsSelected(QModelIndexList selectedIndexes);
|
void onTreeViewItemsSelected(QModelIndexList selectedIndexes);
|
||||||
void onSearchResetClicked();
|
void onSearchResetClicked();
|
||||||
|
@ -390,13 +450,7 @@ private slots:
|
||||||
void onFileBrowserTreeContextMenuRequested(const QPoint &pos);
|
void onFileBrowserTreeContextMenuRequested(const QPoint &pos);
|
||||||
void onPlaylistWidgetContextMenuRequested(const QPoint &pos);
|
void onPlaylistWidgetContextMenuRequested(const QPoint &pos);
|
||||||
void onStopClicked();
|
void onStopClicked();
|
||||||
void onDeferredImageLoaded();
|
|
||||||
void onZoomValueChanged(int value);
|
void onZoomValueChanged(int value);
|
||||||
void onContentGridInited();
|
|
||||||
void onUpdateGridItemPixmapFromImage(GridItem *item);
|
|
||||||
void onPendingItemUpdates();
|
|
||||||
void onGridItemDoubleClicked();
|
|
||||||
void onGridItemClicked(ThumbnailWidget *thumbnailWidget = NULL);
|
|
||||||
void onPlaylistFilesDropped(QStringList files);
|
void onPlaylistFilesDropped(QStringList files);
|
||||||
void onShaderParamsClicked();
|
void onShaderParamsClicked();
|
||||||
void onCoreOptionsClicked();
|
void onCoreOptionsClicked();
|
||||||
|
@ -404,7 +458,6 @@ private slots:
|
||||||
void onShowInfoMessage(QString msg);
|
void onShowInfoMessage(QString msg);
|
||||||
void onContributorsClicked();
|
void onContributorsClicked();
|
||||||
void onItemChanged();
|
void onItemChanged();
|
||||||
void onGridItemChanged(QString title);
|
|
||||||
void onFileSystemDirLoaded(const QString &path);
|
void onFileSystemDirLoaded(const QString &path);
|
||||||
void onDownloadScroll(QString path);
|
void onDownloadScroll(QString path);
|
||||||
void onDownloadScrollAgain(QString path);
|
void onDownloadScrollAgain(QString path);
|
||||||
|
@ -439,14 +492,14 @@ private slots:
|
||||||
void onPlaylistThumbnailDownloadReadyRead();
|
void onPlaylistThumbnailDownloadReadyRead();
|
||||||
void onPlaylistThumbnailDownloadCanceled();
|
void onPlaylistThumbnailDownloadCanceled();
|
||||||
|
|
||||||
|
void startTimer();
|
||||||
|
void updateVisibleItems();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setCurrentCoreLabel();
|
void setCurrentCoreLabel();
|
||||||
void getPlaylistFiles();
|
void getPlaylistFiles();
|
||||||
bool isCoreLoaded();
|
bool isCoreLoaded();
|
||||||
bool isContentLessCore();
|
bool isContentLessCore();
|
||||||
void removeGridItems();
|
|
||||||
void loadImageDeferred(GridItem *item, QString path);
|
|
||||||
void calcGridItemSize(GridItem *item, int zoomValue);
|
|
||||||
bool updateCurrentPlaylistEntry(const QHash<QString, QString> &contentHash);
|
bool updateCurrentPlaylistEntry(const QHash<QString, QString> &contentHash);
|
||||||
int extractArchive(QString path);
|
int extractArchive(QString path);
|
||||||
void removeUpdateTempFiles();
|
void removeUpdateTempFiles();
|
||||||
|
@ -454,8 +507,9 @@ private:
|
||||||
void renamePlaylistItem(QListWidgetItem *item, QString newName);
|
void renamePlaylistItem(QListWidgetItem *item, QString newName);
|
||||||
bool currentPlaylistIsSpecial();
|
bool currentPlaylistIsSpecial();
|
||||||
bool currentPlaylistIsAll();
|
bool currentPlaylistIsAll();
|
||||||
QVector<QHash<QString, QString> > getPlaylistItems(QString pathString);
|
|
||||||
|
|
||||||
|
PlaylistModel *m_playlistModel;
|
||||||
|
QSortFilterProxyModel *m_proxyModel;
|
||||||
LoadCoreWindow *m_loadCoreWindow;
|
LoadCoreWindow *m_loadCoreWindow;
|
||||||
QTimer *m_timer;
|
QTimer *m_timer;
|
||||||
QString m_currentCore;
|
QString m_currentCore;
|
||||||
|
@ -464,7 +518,7 @@ private:
|
||||||
TreeView *m_dirTree;
|
TreeView *m_dirTree;
|
||||||
QFileSystemModel *m_dirModel;
|
QFileSystemModel *m_dirModel;
|
||||||
ListWidget *m_listWidget;
|
ListWidget *m_listWidget;
|
||||||
TableWidget *m_tableWidget;
|
TableView *m_tableView;
|
||||||
QWidget *m_searchWidget;
|
QWidget *m_searchWidget;
|
||||||
QLineEdit *m_searchLineEdit;
|
QLineEdit *m_searchLineEdit;
|
||||||
QDockWidget *m_searchDock;
|
QDockWidget *m_searchDock;
|
||||||
|
@ -496,19 +550,19 @@ private:
|
||||||
QListWidgetItem *m_historyPlaylistsItem;
|
QListWidgetItem *m_historyPlaylistsItem;
|
||||||
QIcon m_folderIcon;
|
QIcon m_folderIcon;
|
||||||
QString m_customThemeString;
|
QString m_customThemeString;
|
||||||
FlowLayout *m_gridLayout;
|
GridView *m_gridView;
|
||||||
QWidget *m_gridWidget;
|
QWidget *m_gridWidget;
|
||||||
QScrollArea *m_gridScrollArea;
|
QScrollArea *m_gridScrollArea;
|
||||||
QVector<QPointer<GridItem> > m_gridItems;
|
|
||||||
QWidget *m_gridLayoutWidget;
|
QWidget *m_gridLayoutWidget;
|
||||||
QSlider *m_zoomSlider;
|
QSlider *m_zoomSlider;
|
||||||
int m_lastZoomSliderValue;
|
int m_lastZoomSliderValue;
|
||||||
QList<GridItem*> m_pendingItemUpdates;
|
|
||||||
ViewType m_viewType;
|
ViewType m_viewType;
|
||||||
|
ThumbnailType m_thumbnailType;
|
||||||
QProgressBar *m_gridProgressBar;
|
QProgressBar *m_gridProgressBar;
|
||||||
QWidget *m_gridProgressWidget;
|
QWidget *m_gridProgressWidget;
|
||||||
QHash<QString, QString> m_currentGridHash;
|
QHash<QString, QString> m_currentGridHash;
|
||||||
ViewType m_lastViewType;
|
ViewType m_lastViewType;
|
||||||
|
ThumbnailType m_lastThumbnailType;
|
||||||
QPointer<ThumbnailWidget> m_currentGridWidget;
|
QPointer<ThumbnailWidget> m_currentGridWidget;
|
||||||
int m_allPlaylistsListMaxCount;
|
int m_allPlaylistsListMaxCount;
|
||||||
int m_allPlaylistsGridMaxCount;
|
int m_allPlaylistsGridMaxCount;
|
||||||
|
@ -540,6 +594,9 @@ private:
|
||||||
bool m_playlistThumbnailDownloadWasCanceled;
|
bool m_playlistThumbnailDownloadWasCanceled;
|
||||||
QString m_pendingDirScrollPath;
|
QString m_pendingDirScrollPath;
|
||||||
|
|
||||||
|
QTimer *m_thumbnailTimer;
|
||||||
|
GridItem m_gridItem;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
void keyPressEvent(QKeyEvent *event);
|
void keyPressEvent(QKeyEvent *event);
|
||||||
|
|
Loading…
Reference in New Issue