mirror of
https://github.com/libretro/RetroArch
synced 2025-03-03 04:14:00 +00:00
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_load_core_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/coreoptionsdialog.o \
|
||||
ui/drivers/qt/filedropwidget.o \
|
||||
@ -355,7 +355,7 @@ ifeq ($(HAVE_QT), 1)
|
||||
|
||||
MOC_HEADERS += ui/drivers/ui_qt.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/coreoptionsdialog.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_msg_window.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/coreoptionsdialog.cpp"
|
||||
#include "../ui/drivers/qt/filedropwidget.cpp"
|
||||
@ -59,7 +59,7 @@ UI
|
||||
#include "../ui/drivers/qt/moc_coreinfodialog.cpp"
|
||||
#include "../ui/drivers/qt/moc_coreoptionsdialog.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_shaderparamsdialog.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,
|
||||
"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(
|
||||
MENU_ENUM_LABEL_VALUE_QT_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_GRID_MAX_COUNT,
|
||||
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_HELP,
|
||||
MENU_ENUM_LABEL_VALUE_QT_MENU_DOCK_CONTENT_BROWSER,
|
||||
|
@ -41,7 +41,12 @@ void FileDropWidget::paintEvent(QPaintEvent *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();
|
||||
emit deletePressed();
|
||||
|
@ -15,6 +15,7 @@ public:
|
||||
FileDropWidget(QWidget *parent = 0);
|
||||
signals:
|
||||
void filesDropped(QStringList files);
|
||||
void enterPressed();
|
||||
void deletePressed();
|
||||
protected:
|
||||
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
|
481
ui/drivers/qt/gridview.cpp
Normal file
481
ui/drivers/qt/gridview.cpp
Normal file
@ -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;
|
||||
}
|
91
ui/drivers/qt/gridview.h
Normal file
91
ui/drivers/qt/gridview.h
Normal file
@ -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 <QScreen>
|
||||
#include <QRegularExpression>
|
||||
#include <QImageReader>
|
||||
#include <QtConcurrent>
|
||||
|
||||
#include "../ui_qt.h"
|
||||
#include "flowlayout.h"
|
||||
#include "playlistentrydialog.h"
|
||||
|
||||
extern "C" {
|
||||
@ -28,6 +29,213 @@ extern "C" {
|
||||
#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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
PlaylistEntryDialog *playlistDialog = playlistEntryDialog();
|
||||
@ -834,9 +1041,6 @@ void MainWindow::reloadPlaylists()
|
||||
|
||||
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->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
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()
|
||||
{
|
||||
QListWidgetItem *playlistItem = m_listWidget->currentItem();
|
||||
QHash<QString, QString> contentHash;
|
||||
QString playlistPath;
|
||||
|
||||
if (!playlistItem)
|
||||
@ -1116,151 +1318,15 @@ void MainWindow::getPlaylistFiles()
|
||||
m_playlistFiles = playlistDir.entryList(QDir::NoDotAndDotDot | QDir::Readable | QDir::Files, QDir::Name);
|
||||
}
|
||||
|
||||
void MainWindow::addPlaylistItemsToGrid(const QStringList &paths, bool add)
|
||||
{
|
||||
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)
|
||||
void PlaylistModel::getPlaylistItems(QString path)
|
||||
{
|
||||
QByteArray pathArray;
|
||||
QVector<QHash<QString, QString> > items;
|
||||
const char *pathData = NULL;
|
||||
playlist_t *playlist = NULL;
|
||||
unsigned playlistSize = 0;
|
||||
unsigned i = 0;
|
||||
|
||||
pathArray.append(pathString);
|
||||
pathArray.append(path);
|
||||
pathData = pathArray.constData();
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
items.append(hash);
|
||||
m_contents.append(hash);
|
||||
}
|
||||
|
||||
playlist_free(playlist);
|
||||
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;
|
||||
|
||||
if (paths.isEmpty())
|
||||
return;
|
||||
|
||||
beginResetModel();
|
||||
|
||||
m_contents.clear();
|
||||
|
||||
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_allPlaylistsListMaxCount > 0 && items.size() >= m_allPlaylistsListMaxCount)
|
||||
goto finish;
|
||||
|
||||
items.append(vec.at(j));
|
||||
}
|
||||
getPlaylistItems(paths.at(i));
|
||||
}
|
||||
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 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;
|
||||
const QHash<QString, QString> &hash = items.at(i);
|
||||
QString fileName = dirList.at(i);
|
||||
QHash<QString, QString> hash;
|
||||
QString filePath(QDir::toNativeSeparators(dir.absoluteFilePath(fileName)));
|
||||
QFileInfo fileInfo(filePath);
|
||||
|
||||
labelItem = new QTableWidgetItem(hash.value("label"));
|
||||
labelItem->setData(Qt::UserRole, QVariant::fromValue<QHash<QString, QString> >(hash));
|
||||
labelItem->setFlags(labelItem->flags() | Qt::ItemIsEditable);
|
||||
hash["path"] = filePath;
|
||||
hash["label"] = hash["path"];
|
||||
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)
|
||||
@ -1382,4 +1457,3 @@ void MainWindow::setAllPlaylistsGridMaxCount(int 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);*/
|
||||
}
|
||||
|
||||
m_playlistModel->reloadThumbnailPath(m_playlistThumbnailDownloadFile.fileName());
|
||||
|
||||
if (!m_playlistThumbnailDownloadWasCanceled && m_pendingPlaylistThumbnails.count() > 0)
|
||||
{
|
||||
QHash<QString, QString> nextThumbnail = m_pendingPlaylistThumbnails.takeAt(0);
|
||||
ViewType viewType = getCurrentViewType();
|
||||
|
||||
if (viewType == VIEW_TYPE_ICONS)
|
||||
emit gridItemChanged(reply->property("title").toString());
|
||||
|
||||
updateVisibleItems();
|
||||
downloadNextPlaylistThumbnail(nextThumbnail.value("db_name"), nextThumbnail.value("label_noext"), nextThumbnail.value("type"));
|
||||
}
|
||||
else
|
||||
@ -236,7 +236,7 @@ void MainWindow::downloadNextPlaylistThumbnail(QString system, QString title, QS
|
||||
if (!m_playlistThumbnailDownloadFile.open(QIODevice::WriteOnly))
|
||||
{
|
||||
m_failedThumbnails++;
|
||||
|
||||
|
||||
RARCH_ERR("[Qt]: Could not open file for writing: %s\n", fileNameData);
|
||||
|
||||
if (m_pendingPlaylistThumbnails.count() > 0)
|
||||
@ -290,9 +290,9 @@ void MainWindow::downloadPlaylistThumbnails(QString playlistPath)
|
||||
QString system;
|
||||
QString title;
|
||||
QString type;
|
||||
QVector<QHash<QString, QString> > playlistItems = getPlaylistItems(playlistPath);
|
||||
settings_t *settings = config_get_ptr();
|
||||
int i;
|
||||
int count;
|
||||
|
||||
if (!settings || !playlistFile.exists())
|
||||
return;
|
||||
@ -302,12 +302,14 @@ void MainWindow::downloadPlaylistThumbnails(QString playlistPath)
|
||||
m_failedThumbnails = 0;
|
||||
m_playlistThumbnailDownloadWasCanceled = false;
|
||||
|
||||
if (playlistItems.count() == 0)
|
||||
count = m_playlistModel->rowCount();
|
||||
|
||||
if (count == 0)
|
||||
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> hash2;
|
||||
QHash<QString, QString> hash3;
|
||||
|
@ -154,6 +154,8 @@ void MainWindow::onThumbnailDownloadFinished()
|
||||
{
|
||||
RARCH_LOG("[Qt]: Thumbnail download finished successfully.\n");
|
||||
/* reload thumbnail image */
|
||||
m_playlistModel->reloadThumbnailPath(m_thumbnailDownloadFile.fileName());
|
||||
updateVisibleItems();
|
||||
emit itemChanged();
|
||||
}
|
||||
else
|
||||
|
@ -191,7 +191,6 @@ void MainWindow::onThumbnailPackDownloadFinished()
|
||||
|
||||
reply->disconnect();
|
||||
reply->close();
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
QNetworkReply *reply = m_thumbnailPackDownloadReply.data();
|
||||
|
||||
m_playlistModel->reloadSystemThumbnails(reply->property("system").toString());
|
||||
reply->deleteLater();
|
||||
updateVisibleItems();
|
||||
/* reload thumbnail image */
|
||||
emit itemChanged();
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ extern "C" {
|
||||
#include <string/stdstring.h>
|
||||
#include <file/file_path.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
};
|
||||
}
|
||||
|
||||
#define CORE_NAME_COLUMN 0
|
||||
#define CORE_VERSION_COLUMN 1
|
||||
|
@ -313,7 +313,7 @@ static const QString qt_theme_dark_stylesheet = QStringLiteral(R"(
|
||||
padding-left:5px;
|
||||
padding-right:5px;
|
||||
}
|
||||
QTableWidget {
|
||||
QTableView {
|
||||
background-color:rgb(25,25,25);
|
||||
alternate-background-color:rgb(40,40,40);
|
||||
}
|
||||
@ -422,14 +422,18 @@ static const QString qt_theme_dark_stylesheet = QStringLiteral(R"(
|
||||
QSizeGrip {
|
||||
background-color:solid;
|
||||
}
|
||||
ThumbnailWidget#thumbnailWidget, ThumbnailLabel#thumbnailGridLabel, QLabel#thumbnailQLabel {
|
||||
GridView::item {
|
||||
background-color:rgb(40,40,40);
|
||||
}
|
||||
ThumbnailWidget#thumbnailWidgetSelected {
|
||||
background-color:rgb(40,40,40);
|
||||
GridView::item:selected {
|
||||
border:3px solid %1;
|
||||
}
|
||||
QWidget#gridLayoutWidget {
|
||||
GridView {
|
||||
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) :
|
||||
QDialog(parent)
|
||||
QDialog(mainwindow)
|
||||
,m_mainwindow(mainwindow)
|
||||
,m_settings(mainwindow->settings())
|
||||
,m_saveGeometryCheckBox(new QCheckBox(this))
|
||||
@ -27,6 +27,8 @@ ViewOptionsDialog::ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent) :
|
||||
,m_saveLastTabCheckBox(new QCheckBox(this))
|
||||
,m_showHiddenFilesCheckBox(new QCheckBox(this))
|
||||
,m_themeComboBox(new QComboBox(this))
|
||||
,m_thumbnailComboBox(new QComboBox(this))
|
||||
,m_thumbnailCacheSpinBox(new QSpinBox(this))
|
||||
,m_startupPlaylistComboBox(new QComboBox(this))
|
||||
,m_highlightColorPushButton(new QPushButton(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CHOOSE), this))
|
||||
,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_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_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_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_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(m_highlightColorLabel, m_highlightColorPushButton);
|
||||
|
||||
@ -77,9 +88,16 @@ ViewOptionsDialog::ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent) :
|
||||
loadViewOptions();
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
void ViewOptionsDialog::onThumbnailComboBoxIndexChanged(int index)
|
||||
{
|
||||
ThumbnailType type = static_cast<ThumbnailType>(m_thumbnailComboBox->currentData().value<int>());
|
||||
m_mainwindow->setCurrentThumbnailType(type);
|
||||
}
|
||||
|
||||
void ViewOptionsDialog::onThemeComboBoxIndexChanged(int)
|
||||
{
|
||||
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();
|
||||
QString initialPlaylist = m_settings->value("initial_playlist", m_mainwindow->getSpecialPlaylistPath(SPECIAL_PLAYLIST_HISTORY)).toString();
|
||||
int themeIndex = 0;
|
||||
int thumbnailIndex = 0;
|
||||
int playlistIndex = 0;
|
||||
int i;
|
||||
|
||||
@ -148,12 +167,18 @@ void ViewOptionsDialog::loadViewOptions()
|
||||
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_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()));
|
||||
|
||||
if (m_themeComboBox->count() > 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())
|
||||
{
|
||||
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_grid_max_count", m_allPlaylistsGridMaxCountSpinBox->value());
|
||||
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())
|
||||
m_settings->setValue("custom_theme", m_customThemePath);
|
||||
|
||||
m_mainwindow->setAllPlaylistsListMaxCount(m_allPlaylistsListMaxCountSpinBox->value());
|
||||
m_mainwindow->setAllPlaylistsGridMaxCount(m_allPlaylistsGridMaxCountSpinBox->value());
|
||||
m_mainwindow->setThumbnailCacheLimit(m_thumbnailCacheSpinBox->value());
|
||||
}
|
||||
|
||||
void ViewOptionsDialog::onAccepted()
|
||||
@ -229,11 +257,12 @@ void ViewOptionsDialog::onRejected()
|
||||
void ViewOptionsDialog::showDialog()
|
||||
{
|
||||
loadViewOptions();
|
||||
setWindowFlags(windowFlags() | Qt::Tool);
|
||||
show();
|
||||
activateWindow();
|
||||
}
|
||||
|
||||
void ViewOptionsDialog::hideDialog()
|
||||
{
|
||||
reject();
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ public slots:
|
||||
void onRejected();
|
||||
private slots:
|
||||
void onThemeComboBoxIndexChanged(int index);
|
||||
void onThumbnailComboBoxIndexChanged(int index);
|
||||
void onHighlightColorChoose();
|
||||
private:
|
||||
void loadViewOptions();
|
||||
@ -37,6 +38,8 @@ private:
|
||||
QCheckBox *m_saveLastTabCheckBox;
|
||||
QCheckBox *m_showHiddenFilesCheckBox;
|
||||
QComboBox *m_themeComboBox;
|
||||
QComboBox *m_thumbnailComboBox;
|
||||
QSpinBox *m_thumbnailCacheSpinBox;
|
||||
QComboBox *m_startupPlaylistComboBox;
|
||||
QPushButton *m_highlightColorPushButton;
|
||||
QColor m_highlightColor;
|
||||
|
@ -293,11 +293,12 @@ static void* ui_companion_qt_init(void)
|
||||
widget->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
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(customContextMenuRequested(const QPoint&)), mainwindow, SLOT(onFileDropWidgetContextMenuRequested(const QPoint&)));
|
||||
|
||||
layout = new QVBoxLayout();
|
||||
layout->addWidget(mainwindow->contentTableWidget());
|
||||
layout->addWidget(mainwindow->contentTableView());
|
||||
layout->addWidget(mainwindow->contentGridWidget());
|
||||
|
||||
widget->setLayout(layout);
|
||||
@ -513,6 +514,11 @@ static void* ui_companion_qt_init(void)
|
||||
if (qsettings->contains("all_playlists_grid_max_count"))
|
||||
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("save_geometry"))
|
||||
mainwindow->restoreGeometry(qsettings->value("geometry").toByteArray());
|
||||
@ -555,6 +561,25 @@ static void* ui_companion_qt_init(void)
|
||||
else
|
||||
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,
|
||||
* 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 <QTreeView>
|
||||
#include <QListWidget>
|
||||
#include <QTableWidget>
|
||||
#include <QTableView>
|
||||
#include <QFrame>
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
@ -38,6 +38,10 @@
|
||||
#include <QElapsedTimer>
|
||||
#include <QSslError>
|
||||
#include <QNetworkReply>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QCache>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QDir>
|
||||
|
||||
extern "C" {
|
||||
#include <retro_assert.h>
|
||||
@ -84,7 +88,7 @@ class LoadCoreWindow;
|
||||
class MainWindow;
|
||||
class ThumbnailWidget;
|
||||
class ThumbnailLabel;
|
||||
class FlowLayout;
|
||||
class GridView;
|
||||
class ShaderParamsDialog;
|
||||
class CoreOptionsDialog;
|
||||
class CoreInfoDialog;
|
||||
@ -96,19 +100,58 @@ enum SpecialPlaylist
|
||||
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
|
||||
public:
|
||||
GridItem();
|
||||
|
||||
QPointer<ThumbnailWidget> widget;
|
||||
QPointer<ThumbnailLabel> label;
|
||||
QHash<QString, QString> hash;
|
||||
QImage image;
|
||||
QPixmap pixmap;
|
||||
QFutureWatcher<GridItem*> imageWatcher;
|
||||
QString labelText;
|
||||
public:
|
||||
enum Roles
|
||||
{
|
||||
HASH = Qt::UserRole + 1,
|
||||
THUMBNAIL
|
||||
};
|
||||
|
||||
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
|
||||
@ -164,17 +207,12 @@ protected slots:
|
||||
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
||||
};
|
||||
|
||||
class TableWidget : public QTableWidget
|
||||
class TableView : public QTableView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TableWidget(QWidget *parent = 0);
|
||||
TableView(QWidget *parent = 0);
|
||||
bool isEditorOpen();
|
||||
signals:
|
||||
void enterPressed();
|
||||
void deletePressed();
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
};
|
||||
|
||||
class ListWidget : public QListWidget
|
||||
@ -233,6 +271,26 @@ public slots:
|
||||
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
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -263,9 +321,10 @@ public:
|
||||
MainWindow(QWidget *parent = NULL);
|
||||
~MainWindow();
|
||||
TreeView* dirTreeView();
|
||||
PlaylistModel* playlistModel();
|
||||
ListWidget* playlistListWidget();
|
||||
TableWidget* contentTableWidget();
|
||||
FlowLayout* contentGridLayout();
|
||||
TableView* contentTableView();
|
||||
GridView* contentGridView();
|
||||
QWidget* contentGridWidget();
|
||||
QWidget* searchWidget();
|
||||
QLineEdit* searchLineEdit();
|
||||
@ -289,20 +348,26 @@ public:
|
||||
bool setCustomThemeFile(QString filePath);
|
||||
void setCustomThemeString(QString qss);
|
||||
const QString& customThemeString() const;
|
||||
GridItem* doDeferredImageLoad(GridItem *item, QString path);
|
||||
void setCurrentViewType(ViewType viewType);
|
||||
QString getCurrentViewTypeString();
|
||||
ViewType getCurrentViewType();
|
||||
void setCurrentThumbnailType(ThumbnailType thumbnailType);
|
||||
QString getCurrentThumbnailTypeString();
|
||||
ThumbnailType getCurrentThumbnailType();
|
||||
ThumbnailType getThumbnailTypeFromString(QString thumbnailType);
|
||||
void setAllPlaylistsListMaxCount(int count);
|
||||
void setAllPlaylistsGridMaxCount(int count);
|
||||
void setThumbnailCacheLimit(int count);
|
||||
PlaylistEntryDialog* playlistEntryDialog();
|
||||
void addFilesToPlaylist(QStringList files);
|
||||
QString getCurrentPlaylistPath();
|
||||
QModelIndex getCurrentContentIndex();
|
||||
QHash<QString, QString> getCurrentContentHash();
|
||||
static double lerp(double x, double y, double a, double b, double d);
|
||||
QString getSpecialPlaylistPath(SpecialPlaylist playlist);
|
||||
QVector<QPair<QString, QString> > getPlaylists();
|
||||
QString getScrubbedString(QString str);
|
||||
void setDefaultCustomProperties();
|
||||
|
||||
signals:
|
||||
void thumbnailChanged(const QPixmap &pixmap);
|
||||
@ -317,6 +382,7 @@ signals:
|
||||
void showInfoMessageDeferred(QString msg);
|
||||
void extractArchiveDeferred(QString path, QString extractionDir, QString tempExtension, retro_task_callback_t cb);
|
||||
void itemChanged();
|
||||
void updateThumbnails();
|
||||
void gridItemChanged(QString title);
|
||||
void gotThumbnailDownload(QString system, QString title);
|
||||
void scrollToDownloads(QString path);
|
||||
@ -327,15 +393,13 @@ public slots:
|
||||
void onBrowserUpClicked();
|
||||
void onBrowserStartClicked();
|
||||
void initContentTableWidget();
|
||||
void initContentGridLayout();
|
||||
void onViewClosedDocksAboutToShow();
|
||||
void onShowHiddenDockWidgetAction();
|
||||
void setCoreActions();
|
||||
void onRunClicked();
|
||||
void loadContent(const QHash<QString, QString> &contentHash);
|
||||
void onStartCoreClicked();
|
||||
void onTableWidgetEnterPressed();
|
||||
void onTableWidgetDeletePressed();
|
||||
void onDropWidgetEnterPressed();
|
||||
void selectBrowserDir(QString path);
|
||||
void resizeThumbnails(bool one, bool two, bool three);
|
||||
void onResizeThumbnailOne();
|
||||
@ -365,24 +429,20 @@ public slots:
|
||||
void downloadAllThumbnails(QString system, QUrl url = QUrl());
|
||||
void downloadPlaylistThumbnails(QString playlistPath);
|
||||
void downloadNextPlaylistThumbnail(QString system, QString title, QString type, QUrl url = QUrl());
|
||||
void changeThumbnailType(ThumbnailType type);
|
||||
|
||||
private slots:
|
||||
void onLoadCoreClicked(const QStringList &extensionFilters = QStringList());
|
||||
void onUnloadCoreMenuAction();
|
||||
void onTimeout();
|
||||
void onCoreLoaded();
|
||||
void onCurrentTableItemDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
|
||||
void onCurrentListItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
|
||||
void onCurrentTableItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous);
|
||||
void onCurrentTableItemDataChanged(QTableWidgetItem *item);
|
||||
void onCurrentListItemDataChanged(QListWidgetItem *item);
|
||||
void currentItemChanged(const QHash<QString, QString> &hash);
|
||||
void currentItemChanged(const QModelIndex &index);
|
||||
void onSearchEnterPressed();
|
||||
void onSearchLineEditEdited(const QString &text);
|
||||
void addPlaylistItemsToTable(const QStringList &paths, bool all = false);
|
||||
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 onContentItemDoubleClicked(const QModelIndex &index);
|
||||
void onCoreLoadWindowClosed();
|
||||
void onTreeViewItemsSelected(QModelIndexList selectedIndexes);
|
||||
void onSearchResetClicked();
|
||||
@ -390,13 +450,7 @@ private slots:
|
||||
void onFileBrowserTreeContextMenuRequested(const QPoint &pos);
|
||||
void onPlaylistWidgetContextMenuRequested(const QPoint &pos);
|
||||
void onStopClicked();
|
||||
void onDeferredImageLoaded();
|
||||
void onZoomValueChanged(int value);
|
||||
void onContentGridInited();
|
||||
void onUpdateGridItemPixmapFromImage(GridItem *item);
|
||||
void onPendingItemUpdates();
|
||||
void onGridItemDoubleClicked();
|
||||
void onGridItemClicked(ThumbnailWidget *thumbnailWidget = NULL);
|
||||
void onPlaylistFilesDropped(QStringList files);
|
||||
void onShaderParamsClicked();
|
||||
void onCoreOptionsClicked();
|
||||
@ -404,7 +458,6 @@ private slots:
|
||||
void onShowInfoMessage(QString msg);
|
||||
void onContributorsClicked();
|
||||
void onItemChanged();
|
||||
void onGridItemChanged(QString title);
|
||||
void onFileSystemDirLoaded(const QString &path);
|
||||
void onDownloadScroll(QString path);
|
||||
void onDownloadScrollAgain(QString path);
|
||||
@ -439,14 +492,14 @@ private slots:
|
||||
void onPlaylistThumbnailDownloadReadyRead();
|
||||
void onPlaylistThumbnailDownloadCanceled();
|
||||
|
||||
void startTimer();
|
||||
void updateVisibleItems();
|
||||
|
||||
private:
|
||||
void setCurrentCoreLabel();
|
||||
void getPlaylistFiles();
|
||||
bool isCoreLoaded();
|
||||
bool isContentLessCore();
|
||||
void removeGridItems();
|
||||
void loadImageDeferred(GridItem *item, QString path);
|
||||
void calcGridItemSize(GridItem *item, int zoomValue);
|
||||
bool updateCurrentPlaylistEntry(const QHash<QString, QString> &contentHash);
|
||||
int extractArchive(QString path);
|
||||
void removeUpdateTempFiles();
|
||||
@ -454,8 +507,9 @@ private:
|
||||
void renamePlaylistItem(QListWidgetItem *item, QString newName);
|
||||
bool currentPlaylistIsSpecial();
|
||||
bool currentPlaylistIsAll();
|
||||
QVector<QHash<QString, QString> > getPlaylistItems(QString pathString);
|
||||
|
||||
PlaylistModel *m_playlistModel;
|
||||
QSortFilterProxyModel *m_proxyModel;
|
||||
LoadCoreWindow *m_loadCoreWindow;
|
||||
QTimer *m_timer;
|
||||
QString m_currentCore;
|
||||
@ -464,7 +518,7 @@ private:
|
||||
TreeView *m_dirTree;
|
||||
QFileSystemModel *m_dirModel;
|
||||
ListWidget *m_listWidget;
|
||||
TableWidget *m_tableWidget;
|
||||
TableView *m_tableView;
|
||||
QWidget *m_searchWidget;
|
||||
QLineEdit *m_searchLineEdit;
|
||||
QDockWidget *m_searchDock;
|
||||
@ -496,19 +550,19 @@ private:
|
||||
QListWidgetItem *m_historyPlaylistsItem;
|
||||
QIcon m_folderIcon;
|
||||
QString m_customThemeString;
|
||||
FlowLayout *m_gridLayout;
|
||||
GridView *m_gridView;
|
||||
QWidget *m_gridWidget;
|
||||
QScrollArea *m_gridScrollArea;
|
||||
QVector<QPointer<GridItem> > m_gridItems;
|
||||
QWidget *m_gridLayoutWidget;
|
||||
QSlider *m_zoomSlider;
|
||||
int m_lastZoomSliderValue;
|
||||
QList<GridItem*> m_pendingItemUpdates;
|
||||
ViewType m_viewType;
|
||||
ThumbnailType m_thumbnailType;
|
||||
QProgressBar *m_gridProgressBar;
|
||||
QWidget *m_gridProgressWidget;
|
||||
QHash<QString, QString> m_currentGridHash;
|
||||
ViewType m_lastViewType;
|
||||
ThumbnailType m_lastThumbnailType;
|
||||
QPointer<ThumbnailWidget> m_currentGridWidget;
|
||||
int m_allPlaylistsListMaxCount;
|
||||
int m_allPlaylistsGridMaxCount;
|
||||
@ -540,6 +594,9 @@ private:
|
||||
bool m_playlistThumbnailDownloadWasCanceled;
|
||||
QString m_pendingDirScrollPath;
|
||||
|
||||
QTimer *m_thumbnailTimer;
|
||||
GridItem m_gridItem;
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
|
Loading…
x
Reference in New Issue
Block a user