Merge branch 'develop' into icon-indexing
Signed-off-by: Tayou <31988415+TayouVR@users.noreply.github.com>
This commit is contained in:
@@ -1,42 +1,40 @@
|
||||
#include "InstanceView.h"
|
||||
#include "AccessibleInstanceView.h"
|
||||
#include "AccessibleInstanceView_p.h"
|
||||
#include "InstanceView.h"
|
||||
|
||||
#include <qvariant.h>
|
||||
#include <qaccessible.h>
|
||||
#include <qheaderview.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
|
||||
QAccessibleInterface *groupViewAccessibleFactory(const QString &classname, QObject *object)
|
||||
QAccessibleInterface* groupViewAccessibleFactory(const QString& classname, QObject* object)
|
||||
{
|
||||
QAccessibleInterface *iface = 0;
|
||||
QAccessibleInterface* iface = 0;
|
||||
if (!object || !object->isWidgetType())
|
||||
return iface;
|
||||
|
||||
QWidget *widget = static_cast<QWidget*>(object);
|
||||
QWidget* widget = static_cast<QWidget*>(object);
|
||||
|
||||
if (classname == QLatin1String("InstanceView")) {
|
||||
iface = new AccessibleInstanceView((InstanceView *)widget);
|
||||
iface = new AccessibleInstanceView((InstanceView*)widget);
|
||||
}
|
||||
return iface;
|
||||
}
|
||||
|
||||
|
||||
QAbstractItemView *AccessibleInstanceView::view() const
|
||||
QAbstractItemView* AccessibleInstanceView::view() const
|
||||
{
|
||||
return qobject_cast<QAbstractItemView*>(object());
|
||||
}
|
||||
|
||||
int AccessibleInstanceView::logicalIndex(const QModelIndex &index) const
|
||||
int AccessibleInstanceView::logicalIndex(const QModelIndex& index) const
|
||||
{
|
||||
if (!view()->model() || !index.isValid())
|
||||
return -1;
|
||||
return index.row() * (index.model()->columnCount()) + index.column();
|
||||
}
|
||||
|
||||
AccessibleInstanceView::AccessibleInstanceView(QWidget *w)
|
||||
: QAccessibleObject(w)
|
||||
AccessibleInstanceView::AccessibleInstanceView(QWidget* w) : QAccessibleObject(w)
|
||||
{
|
||||
Q_ASSERT(view());
|
||||
}
|
||||
@@ -53,7 +51,7 @@ AccessibleInstanceView::~AccessibleInstanceView()
|
||||
}
|
||||
}
|
||||
|
||||
QAccessibleInterface *AccessibleInstanceView::cellAt(int row, int column) const
|
||||
QAccessibleInterface* AccessibleInstanceView::cellAt(int row, int column) const
|
||||
{
|
||||
if (!view()->model()) {
|
||||
return 0;
|
||||
@@ -68,7 +66,7 @@ QAccessibleInterface *AccessibleInstanceView::cellAt(int row, int column) const
|
||||
return child(logicalIndex(index));
|
||||
}
|
||||
|
||||
QAccessibleInterface *AccessibleInstanceView::caption() const
|
||||
QAccessibleInterface* AccessibleInstanceView::caption() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -123,14 +121,14 @@ QString AccessibleInstanceView::rowDescription(int row) const
|
||||
return view()->model()->headerData(row, Qt::Vertical).toString();
|
||||
}
|
||||
|
||||
QList<QAccessibleInterface *> AccessibleInstanceView::selectedCells() const
|
||||
QList<QAccessibleInterface*> AccessibleInstanceView::selectedCells() const
|
||||
{
|
||||
QList<QAccessibleInterface*> cells;
|
||||
if (!view()->selectionModel())
|
||||
return cells;
|
||||
const QModelIndexList selectedIndexes = view()->selectionModel()->selectedIndexes();
|
||||
cells.reserve(selectedIndexes.size());
|
||||
for (const QModelIndex &index : selectedIndexes)
|
||||
for (const QModelIndex& index : selectedIndexes)
|
||||
cells.append(child(logicalIndex(index)));
|
||||
return cells;
|
||||
}
|
||||
@@ -145,7 +143,7 @@ QList<int> AccessibleInstanceView::selectedColumns() const
|
||||
|
||||
QList<int> columns;
|
||||
columns.reserve(selectedColumns.size());
|
||||
for (const QModelIndex &index : selectedColumns) {
|
||||
for (const QModelIndex& index : selectedColumns) {
|
||||
columns.append(index.column());
|
||||
}
|
||||
|
||||
@@ -163,14 +161,14 @@ QList<int> AccessibleInstanceView::selectedRows() const
|
||||
const QModelIndexList selectedRows = view()->selectionModel()->selectedRows();
|
||||
|
||||
rows.reserve(selectedRows.size());
|
||||
for (const QModelIndex &index : selectedRows) {
|
||||
for (const QModelIndex& index : selectedRows) {
|
||||
rows.append(index.row());
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
QAccessibleInterface *AccessibleInstanceView::summary() const
|
||||
QAccessibleInterface* AccessibleInstanceView::summary() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -209,16 +207,17 @@ bool AccessibleInstanceView::selectRow(int row)
|
||||
return false;
|
||||
}
|
||||
case QAbstractItemView::SingleSelection: {
|
||||
if (view()->selectionBehavior() != QAbstractItemView::SelectRows && columnCount() > 1 )
|
||||
if (view()->selectionBehavior() != QAbstractItemView::SelectRows && columnCount() > 1)
|
||||
return false;
|
||||
view()->clearSelection();
|
||||
break;
|
||||
}
|
||||
case QAbstractItemView::ContiguousSelection: {
|
||||
if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex())) && !view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex())) {
|
||||
if ((!row || !view()->selectionModel()->isRowSelected(row - 1, view()->rootIndex())) &&
|
||||
!view()->selectionModel()->isRowSelected(row + 1, view()->rootIndex())) {
|
||||
view()->clearSelection();
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
@@ -251,7 +250,8 @@ bool AccessibleInstanceView::selectColumn(int column)
|
||||
}
|
||||
/* fallthrough */
|
||||
case QAbstractItemView::ContiguousSelection: {
|
||||
if ((!column || !view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex())) && !view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) {
|
||||
if ((!column || !view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex())) &&
|
||||
!view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) {
|
||||
view()->clearSelection();
|
||||
}
|
||||
break;
|
||||
@@ -292,10 +292,10 @@ bool AccessibleInstanceView::unselectRow(int row)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if ((!row || selectionModel->isRowSelected(row - 1, view()->rootIndex())) && selectionModel->isRowSelected(row + 1, view()->rootIndex())) {
|
||||
//If there are rows selected both up the current row and down the current rown,
|
||||
//the ones which are down the current row will be deselected
|
||||
if ((!row || selectionModel->isRowSelected(row - 1, view()->rootIndex())) &&
|
||||
selectionModel->isRowSelected(row + 1, view()->rootIndex())) {
|
||||
// If there are rows selected both up the current row and down the current rown,
|
||||
// the ones which are down the current row will be deselected
|
||||
selection = QItemSelection(index, view()->model()->index(rowCount() - 1, 0, view()->rootIndex()));
|
||||
}
|
||||
}
|
||||
@@ -324,8 +324,8 @@ bool AccessibleInstanceView::unselectColumn(int column)
|
||||
|
||||
switch (view()->selectionMode()) {
|
||||
case QAbstractItemView::SingleSelection: {
|
||||
//In SingleSelection and ContiguousSelection once an item
|
||||
//is selected, there's no way for the user to unselect all items
|
||||
// In SingleSelection and ContiguousSelection once an item
|
||||
// is selected, there's no way for the user to unselect all items
|
||||
if (selectedColumnCount() == 1) {
|
||||
return false;
|
||||
}
|
||||
@@ -336,10 +336,10 @@ bool AccessibleInstanceView::unselectColumn(int column)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!column || view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex()))
|
||||
&& view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) {
|
||||
//If there are columns selected both at the left of the current row and at the right
|
||||
//of the current row, the ones which are at the right will be deselected
|
||||
if ((!column || view()->selectionModel()->isColumnSelected(column - 1, view()->rootIndex())) &&
|
||||
view()->selectionModel()->isColumnSelected(column + 1, view()->rootIndex())) {
|
||||
// If there are columns selected both at the left of the current row and at the right
|
||||
// of the current row, the ones which are at the right will be deselected
|
||||
selection = QItemSelection(index, model->index(0, columnCount() - 1, view()->rootIndex()));
|
||||
}
|
||||
default:
|
||||
@@ -360,9 +360,9 @@ QAccessible::State AccessibleInstanceView::state() const
|
||||
return QAccessible::State();
|
||||
}
|
||||
|
||||
QAccessibleInterface *AccessibleInstanceView::childAt(int x, int y) const
|
||||
QAccessibleInterface* AccessibleInstanceView::childAt(int x, int y) const
|
||||
{
|
||||
QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0));
|
||||
QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0, 0));
|
||||
QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset);
|
||||
// FIXME: if indexPosition < 0 in one coordinate, return header
|
||||
|
||||
@@ -381,22 +381,23 @@ int AccessibleInstanceView::childCount() const
|
||||
return (view()->model()->rowCount()) * (view()->model()->columnCount());
|
||||
}
|
||||
|
||||
int AccessibleInstanceView::indexOfChild(const QAccessibleInterface *iface) const
|
||||
int AccessibleInstanceView::indexOfChild(const QAccessibleInterface* iface) const
|
||||
{
|
||||
if (!view()->model())
|
||||
return -1;
|
||||
QAccessibleInterface *parent = iface->parent();
|
||||
QAccessibleInterface* parent = iface->parent();
|
||||
if (parent->object() != view())
|
||||
return -1;
|
||||
|
||||
Q_ASSERT(iface->role() != QAccessible::TreeItem); // should be handled by tree class
|
||||
Q_ASSERT(iface->role() != QAccessible::TreeItem); // should be handled by tree class
|
||||
if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
|
||||
const AccessibleInstanceViewItem* cell = static_cast<const AccessibleInstanceViewItem*>(iface);
|
||||
return logicalIndex(cell->m_index);
|
||||
} else if (iface->role() == QAccessible::Pane) {
|
||||
return 0; // corner button
|
||||
return 0; // corner button
|
||||
} else {
|
||||
qWarning() << "AccessibleInstanceView::indexOfChild has a child with unknown role..." << iface->role() << iface->text(QAccessible::Name);
|
||||
qWarning() << "AccessibleInstanceView::indexOfChild has a child with unknown role..." << iface->role()
|
||||
<< iface->text(QAccessible::Name);
|
||||
}
|
||||
// FIXME: we are in denial of our children. this should stop.
|
||||
return -1;
|
||||
@@ -417,7 +418,7 @@ QRect AccessibleInstanceView::rect() const
|
||||
return QRect(pos.x(), pos.y(), view()->width(), view()->height());
|
||||
}
|
||||
|
||||
QAccessibleInterface *AccessibleInstanceView::parent() const
|
||||
QAccessibleInterface* AccessibleInstanceView::parent() const
|
||||
{
|
||||
if (view() && view()->parent()) {
|
||||
if (qstrcmp("QComboBoxPrivateContainer", view()->parent()->metaObject()->className()) == 0) {
|
||||
@@ -428,7 +429,7 @@ QAccessibleInterface *AccessibleInstanceView::parent() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
QAccessibleInterface *AccessibleInstanceView::child(int logicalIndex) const
|
||||
QAccessibleInterface* AccessibleInstanceView::child(int logicalIndex) const
|
||||
{
|
||||
if (!view()->model())
|
||||
return 0;
|
||||
@@ -442,7 +443,7 @@ QAccessibleInterface *AccessibleInstanceView::child(int logicalIndex) const
|
||||
int row = logicalIndex / columns;
|
||||
int column = logicalIndex % columns;
|
||||
|
||||
QAccessibleInterface *iface = 0;
|
||||
QAccessibleInterface* iface = 0;
|
||||
|
||||
QModelIndex index = view()->model()->index(row, column, view()->rootIndex());
|
||||
if (Q_UNLIKELY(!index.isValid())) {
|
||||
@@ -456,14 +457,14 @@ QAccessibleInterface *AccessibleInstanceView::child(int logicalIndex) const
|
||||
return iface;
|
||||
}
|
||||
|
||||
void *AccessibleInstanceView::interface_cast(QAccessible::InterfaceType t)
|
||||
void* AccessibleInstanceView::interface_cast(QAccessible::InterfaceType t)
|
||||
{
|
||||
if (t == QAccessible::TableInterface)
|
||||
return static_cast<QAccessibleTableInterface*>(this);
|
||||
return 0;
|
||||
return static_cast<QAccessibleTableInterface*>(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AccessibleInstanceView::modelChange(QAccessibleTableModelChangeEvent *event)
|
||||
void AccessibleInstanceView::modelChange(QAccessibleTableModelChangeEvent* event)
|
||||
{
|
||||
// if there is no cache yet, we don't update anything
|
||||
if (childToId.isEmpty())
|
||||
@@ -479,13 +480,12 @@ void AccessibleInstanceView::modelChange(QAccessibleTableModelChangeEvent *event
|
||||
// rows are inserted: move every row after that
|
||||
case QAccessibleTableModelChangeEvent::RowsInserted:
|
||||
case QAccessibleTableModelChangeEvent::ColumnsInserted: {
|
||||
|
||||
ChildCache newCache;
|
||||
ChildCache::ConstIterator iter = childToId.constBegin();
|
||||
|
||||
while (iter != childToId.constEnd()) {
|
||||
QAccessible::Id id = iter.value();
|
||||
QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
|
||||
QAccessibleInterface* iface = QAccessible::accessibleInterface(id);
|
||||
Q_ASSERT(iface);
|
||||
if (indexOfChild(iface) >= 0) {
|
||||
newCache.insert(indexOfChild(iface), id);
|
||||
@@ -507,11 +507,11 @@ void AccessibleInstanceView::modelChange(QAccessibleTableModelChangeEvent *event
|
||||
ChildCache::ConstIterator iter = childToId.constBegin();
|
||||
while (iter != childToId.constEnd()) {
|
||||
QAccessible::Id id = iter.value();
|
||||
QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
|
||||
QAccessibleInterface* iface = QAccessible::accessibleInterface(id);
|
||||
Q_ASSERT(iface);
|
||||
if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
|
||||
Q_ASSERT(iface->tableCellInterface());
|
||||
AccessibleInstanceViewItem *cell = static_cast<AccessibleInstanceViewItem*>(iface->tableCellInterface());
|
||||
AccessibleInstanceViewItem* cell = static_cast<AccessibleInstanceViewItem*>(iface->tableCellInterface());
|
||||
// Since it is a QPersistentModelIndex, we only need to check if it is valid
|
||||
if (cell->m_index.isValid())
|
||||
newCache.insert(indexOfChild(cell), id);
|
||||
@@ -532,14 +532,13 @@ void AccessibleInstanceView::modelChange(QAccessibleTableModelChangeEvent *event
|
||||
|
||||
// TABLE CELL
|
||||
|
||||
AccessibleInstanceViewItem::AccessibleInstanceViewItem(QAbstractItemView *view_, const QModelIndex &index_)
|
||||
: view(view_), m_index(index_)
|
||||
AccessibleInstanceViewItem::AccessibleInstanceViewItem(QAbstractItemView* view_, const QModelIndex& index_) : view(view_), m_index(index_)
|
||||
{
|
||||
if (Q_UNLIKELY(!index_.isValid()))
|
||||
qWarning() << "AccessibleInstanceViewItem::AccessibleInstanceViewItem with invalid index: " << index_;
|
||||
}
|
||||
|
||||
void *AccessibleInstanceViewItem::interface_cast(QAccessible::InterfaceType t)
|
||||
void* AccessibleInstanceViewItem::interface_cast(QAccessible::InterfaceType t)
|
||||
{
|
||||
if (t == QAccessible::TableCellInterface)
|
||||
return static_cast<QAccessibleTableCellInterface*>(this);
|
||||
@@ -548,8 +547,14 @@ void *AccessibleInstanceViewItem::interface_cast(QAccessible::InterfaceType t)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AccessibleInstanceViewItem::columnExtent() const { return 1; }
|
||||
int AccessibleInstanceViewItem::rowExtent() const { return 1; }
|
||||
int AccessibleInstanceViewItem::columnExtent() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int AccessibleInstanceViewItem::rowExtent() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
QList<QAccessibleInterface*> AccessibleInstanceViewItem::rowHeaderCells() const
|
||||
{
|
||||
@@ -600,19 +605,17 @@ void AccessibleInstanceViewItem::doAction(const QString& actionName)
|
||||
if (actionName == toggleAction()) {
|
||||
if (isSelected()) {
|
||||
unselectCell();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
selectCell();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QStringList AccessibleInstanceViewItem::keyBindingsForAction(const QString &) const
|
||||
QStringList AccessibleInstanceViewItem::keyBindingsForAction(const QString&) const
|
||||
{
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
|
||||
void AccessibleInstanceViewItem::selectCell()
|
||||
{
|
||||
if (!isValid()) {
|
||||
@@ -624,7 +627,7 @@ void AccessibleInstanceViewItem::selectCell()
|
||||
}
|
||||
|
||||
Q_ASSERT(table());
|
||||
QAccessibleTableInterface *cellTable = table()->tableInterface();
|
||||
QAccessibleTableInterface* cellTable = table()->tableInterface();
|
||||
|
||||
switch (view->selectionBehavior()) {
|
||||
case QAbstractItemView::SelectItems:
|
||||
@@ -654,7 +657,7 @@ void AccessibleInstanceViewItem::unselectCell()
|
||||
if (selectionMode == QAbstractItemView::NoSelection)
|
||||
return;
|
||||
|
||||
QAccessibleTableInterface *cellTable = table()->tableInterface();
|
||||
QAccessibleTableInterface* cellTable = table()->tableInterface();
|
||||
|
||||
switch (view->selectionBehavior()) {
|
||||
case QAbstractItemView::SelectItems:
|
||||
@@ -669,15 +672,16 @@ void AccessibleInstanceViewItem::unselectCell()
|
||||
return;
|
||||
}
|
||||
|
||||
//If the mode is not MultiSelection or ExtendedSelection and only
|
||||
//one cell is selected it cannot be unselected by the user
|
||||
if ((selectionMode != QAbstractItemView::MultiSelection) && (selectionMode != QAbstractItemView::ExtendedSelection) && (view->selectionModel()->selectedIndexes().count() <= 1))
|
||||
// If the mode is not MultiSelection or ExtendedSelection and only
|
||||
// one cell is selected it cannot be unselected by the user
|
||||
if ((selectionMode != QAbstractItemView::MultiSelection) && (selectionMode != QAbstractItemView::ExtendedSelection) &&
|
||||
(view->selectionModel()->selectedIndexes().count() <= 1))
|
||||
return;
|
||||
|
||||
view->selectionModel()->select(m_index, QItemSelectionModel::Deselect);
|
||||
}
|
||||
|
||||
QAccessibleInterface *AccessibleInstanceViewItem::table() const
|
||||
QAccessibleInterface* AccessibleInstanceViewItem::table() const
|
||||
{
|
||||
return QAccessible::queryAccessibleInterface(view);
|
||||
}
|
||||
@@ -694,7 +698,7 @@ QAccessible::State AccessibleInstanceViewItem::state() const
|
||||
return st;
|
||||
|
||||
QRect globalRect = view->rect();
|
||||
globalRect.translate(view->mapToGlobal(QPoint(0,0)));
|
||||
globalRect.translate(view->mapToGlobal(QPoint(0, 0)));
|
||||
if (!globalRect.intersects(rect()))
|
||||
st.invisible = true;
|
||||
|
||||
@@ -717,7 +721,6 @@ QAccessible::State AccessibleInstanceViewItem::state() const
|
||||
return st;
|
||||
}
|
||||
|
||||
|
||||
QRect AccessibleInstanceViewItem::rect() const
|
||||
{
|
||||
QRect r;
|
||||
@@ -726,7 +729,7 @@ QRect AccessibleInstanceViewItem::rect() const
|
||||
r = view->visualRect(m_index);
|
||||
|
||||
if (!r.isNull()) {
|
||||
r.translate(view->viewport()->mapTo(view, QPoint(0,0)));
|
||||
r.translate(view->viewport()->mapTo(view, QPoint(0, 0)));
|
||||
r.translate(view->mapToGlobal(QPoint(0, 0)));
|
||||
}
|
||||
return r;
|
||||
@@ -737,7 +740,7 @@ QString AccessibleInstanceViewItem::text(QAccessible::Text t) const
|
||||
QString value;
|
||||
if (!isValid())
|
||||
return value;
|
||||
QAbstractItemModel *model = view->model();
|
||||
QAbstractItemModel* model = view->model();
|
||||
switch (t) {
|
||||
case QAccessible::Name:
|
||||
value = model->data(m_index, Qt::AccessibleTextRole).toString();
|
||||
@@ -753,7 +756,7 @@ QString AccessibleInstanceViewItem::text(QAccessible::Text t) const
|
||||
return value;
|
||||
}
|
||||
|
||||
void AccessibleInstanceViewItem::setText(QAccessible::Text /*t*/, const QString &text)
|
||||
void AccessibleInstanceViewItem::setText(QAccessible::Text /*t*/, const QString& text)
|
||||
{
|
||||
if (!isValid() || !(m_index.flags() & Qt::ItemIsEditable))
|
||||
return;
|
||||
@@ -765,12 +768,12 @@ bool AccessibleInstanceViewItem::isValid() const
|
||||
return view && view->model() && m_index.isValid();
|
||||
}
|
||||
|
||||
QAccessibleInterface *AccessibleInstanceViewItem::parent() const
|
||||
QAccessibleInterface* AccessibleInstanceViewItem::parent() const
|
||||
{
|
||||
return QAccessible::queryAccessibleInterface(view);
|
||||
}
|
||||
|
||||
QAccessibleInterface *AccessibleInstanceViewItem::child(int) const
|
||||
QAccessibleInterface* AccessibleInstanceViewItem::child(int) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
class QAccessibleInterface;
|
||||
|
||||
QAccessibleInterface *groupViewAccessibleFactory(const QString &classname, QObject *object);
|
||||
QAccessibleInterface* groupViewAccessibleFactory(const QString& classname, QObject* object);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "QtCore/qpointer.h"
|
||||
#include <QtGui/qaccessible.h>
|
||||
#include <QAccessibleWidget>
|
||||
#include <QAbstractItemView>
|
||||
#include <QAccessibleWidget>
|
||||
#include "QtCore/qpointer.h"
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
#include "InstanceView.h"
|
||||
// #include <QHeaderView>
|
||||
@@ -11,10 +11,9 @@
|
||||
class QAccessibleTableCell;
|
||||
class QAccessibleTableHeaderCell;
|
||||
|
||||
class AccessibleInstanceView :public QAccessibleTableInterface, public QAccessibleObject
|
||||
{
|
||||
public:
|
||||
explicit AccessibleInstanceView(QWidget *w);
|
||||
class AccessibleInstanceView : public QAccessibleTableInterface, public QAccessibleObject {
|
||||
public:
|
||||
explicit AccessibleInstanceView(QWidget* w);
|
||||
bool isValid() const override;
|
||||
|
||||
QAccessible::Role role() const override;
|
||||
@@ -22,19 +21,19 @@ public:
|
||||
QString text(QAccessible::Text t) const override;
|
||||
QRect rect() const override;
|
||||
|
||||
QAccessibleInterface *childAt(int x, int y) const override;
|
||||
QAccessibleInterface* childAt(int x, int y) const override;
|
||||
int childCount() const override;
|
||||
int indexOfChild(const QAccessibleInterface *) const override;
|
||||
int indexOfChild(const QAccessibleInterface*) const override;
|
||||
|
||||
QAccessibleInterface *parent() const override;
|
||||
QAccessibleInterface *child(int index) const override;
|
||||
QAccessibleInterface* parent() const override;
|
||||
QAccessibleInterface* child(int index) const override;
|
||||
|
||||
void *interface_cast(QAccessible::InterfaceType t) override;
|
||||
void* interface_cast(QAccessible::InterfaceType t) override;
|
||||
|
||||
// table interface
|
||||
QAccessibleInterface *cellAt(int row, int column) const override;
|
||||
QAccessibleInterface *caption() const override;
|
||||
QAccessibleInterface *summary() const override;
|
||||
QAccessibleInterface* cellAt(int row, int column) const override;
|
||||
QAccessibleInterface* caption() const override;
|
||||
QAccessibleInterface* summary() const override;
|
||||
QString columnDescription(int column) const override;
|
||||
QString rowDescription(int row) const override;
|
||||
int columnCount() const override;
|
||||
@@ -54,42 +53,41 @@ public:
|
||||
bool unselectRow(int row) override;
|
||||
bool unselectColumn(int column) override;
|
||||
|
||||
QAbstractItemView *view() const;
|
||||
QAbstractItemView* view() const;
|
||||
|
||||
void modelChange(QAccessibleTableModelChangeEvent *event) override;
|
||||
void modelChange(QAccessibleTableModelChangeEvent* event) override;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
// maybe vector
|
||||
typedef QHash<int, QAccessible::Id> ChildCache;
|
||||
mutable ChildCache childToId;
|
||||
|
||||
virtual ~AccessibleInstanceView();
|
||||
|
||||
private:
|
||||
inline int logicalIndex(const QModelIndex &index) const;
|
||||
private:
|
||||
inline int logicalIndex(const QModelIndex& index) const;
|
||||
};
|
||||
|
||||
class AccessibleInstanceViewItem: public QAccessibleInterface, public QAccessibleTableCellInterface, public QAccessibleActionInterface
|
||||
{
|
||||
public:
|
||||
AccessibleInstanceViewItem(QAbstractItemView *view, const QModelIndex &m_index);
|
||||
class AccessibleInstanceViewItem : public QAccessibleInterface, public QAccessibleTableCellInterface, public QAccessibleActionInterface {
|
||||
public:
|
||||
AccessibleInstanceViewItem(QAbstractItemView* view, const QModelIndex& m_index);
|
||||
|
||||
void *interface_cast(QAccessible::InterfaceType t) override;
|
||||
QObject *object() const override { return nullptr; }
|
||||
void* interface_cast(QAccessible::InterfaceType t) override;
|
||||
QObject* object() const override { return nullptr; }
|
||||
QAccessible::Role role() const override;
|
||||
QAccessible::State state() const override;
|
||||
QRect rect() const override;
|
||||
bool isValid() const override;
|
||||
|
||||
QAccessibleInterface *childAt(int, int) const override { return nullptr; }
|
||||
QAccessibleInterface* childAt(int, int) const override { return nullptr; }
|
||||
int childCount() const override { return 0; }
|
||||
int indexOfChild(const QAccessibleInterface *) const override { return -1; }
|
||||
int indexOfChild(const QAccessibleInterface*) const override { return -1; }
|
||||
|
||||
QString text(QAccessible::Text t) const override;
|
||||
void setText(QAccessible::Text t, const QString &text) override;
|
||||
void setText(QAccessible::Text t, const QString& text) override;
|
||||
|
||||
QAccessibleInterface *parent() const override;
|
||||
QAccessibleInterface *child(int) const override;
|
||||
QAccessibleInterface* parent() const override;
|
||||
QAccessibleInterface* child(int) const override;
|
||||
|
||||
// cell interface
|
||||
int columnExtent() const override;
|
||||
@@ -101,13 +99,13 @@ public:
|
||||
bool isSelected() const override;
|
||||
QAccessibleInterface* table() const override;
|
||||
|
||||
//action interface
|
||||
// action interface
|
||||
QStringList actionNames() const override;
|
||||
void doAction(const QString &actionName) override;
|
||||
QStringList keyBindingsForAction(const QString &actionName) const override;
|
||||
void doAction(const QString& actionName) override;
|
||||
QStringList keyBindingsForAction(const QString& actionName) const override;
|
||||
|
||||
private:
|
||||
QPointer<QAbstractItemView > view;
|
||||
private:
|
||||
QPointer<QAbstractItemView> view;
|
||||
QPersistentModelIndex m_index;
|
||||
|
||||
void selectCell();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@@ -34,29 +34,27 @@
|
||||
*/
|
||||
|
||||
#include "InstanceDelegate.h"
|
||||
#include <QPainter>
|
||||
#include <QTextOption>
|
||||
#include <QTextLayout>
|
||||
#include <QApplication>
|
||||
#include <QtMath>
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QTextLayout>
|
||||
#include <QTextOption>
|
||||
#include <QtMath>
|
||||
|
||||
#include "InstanceView.h"
|
||||
#include "BaseInstance.h"
|
||||
#include "InstanceList.h"
|
||||
#include <QIcon>
|
||||
#include <QTextEdit>
|
||||
#include "BaseInstance.h"
|
||||
#include "InstanceList.h"
|
||||
#include "InstanceView.h"
|
||||
|
||||
// Origin: Qt
|
||||
static void viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &height,
|
||||
qreal &widthUsed)
|
||||
static void viewItemTextLayout(QTextLayout& textLayout, int lineWidth, qreal& height, qreal& widthUsed)
|
||||
{
|
||||
height = 0;
|
||||
widthUsed = 0;
|
||||
textLayout.beginLayout();
|
||||
QString str = textLayout.text();
|
||||
while (true)
|
||||
{
|
||||
while (true) {
|
||||
QTextLine line = textLayout.createLine();
|
||||
if (!line.isValid())
|
||||
break;
|
||||
@@ -70,24 +68,20 @@ static void viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &he
|
||||
textLayout.endLayout();
|
||||
}
|
||||
|
||||
ListViewDelegate::ListViewDelegate(QObject *parent) : QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
ListViewDelegate::ListViewDelegate(QObject* parent) : QStyledItemDelegate(parent) {}
|
||||
|
||||
void drawSelectionRect(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QRect &rect)
|
||||
void drawSelectionRect(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect)
|
||||
{
|
||||
if ((option.state & QStyle::State_Selected))
|
||||
painter->fillRect(rect, option.palette.brush(QPalette::Highlight));
|
||||
else
|
||||
{
|
||||
else {
|
||||
QColor backgroundColor = option.palette.color(QPalette::Window);
|
||||
backgroundColor.setAlpha(160);
|
||||
painter->fillRect(rect, QBrush(backgroundColor));
|
||||
}
|
||||
}
|
||||
|
||||
void drawFocusRect(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect)
|
||||
void drawFocusRect(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect)
|
||||
{
|
||||
if (!(option.state & QStyle::State_HasFocus))
|
||||
return;
|
||||
@@ -103,7 +97,7 @@ void drawFocusRect(QPainter *painter, const QStyleOptionViewItem &option, const
|
||||
// Apparently some widget styles expect this hint to not be set
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
QStyle *style = option.widget ? option.widget->style() : QApplication::style();
|
||||
QStyle* style = option.widget ? option.widget->style() : QApplication::style();
|
||||
|
||||
style->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, painter, option.widget);
|
||||
|
||||
@@ -111,11 +105,9 @@ void drawFocusRect(QPainter *painter, const QStyleOptionViewItem &option, const
|
||||
}
|
||||
|
||||
// TODO this can be made a lot prettier
|
||||
void drawProgressOverlay(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const int value, const int maximum)
|
||||
void drawProgressOverlay(QPainter* painter, const QStyleOptionViewItem& option, const int value, const int maximum)
|
||||
{
|
||||
if (maximum == 0 || value == maximum)
|
||||
{
|
||||
if (maximum == 0 || value == maximum) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -131,19 +123,15 @@ void drawProgressOverlay(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void drawBadges(QPainter *painter, const QStyleOptionViewItem &option, BaseInstance *instance, QIcon::Mode mode, QIcon::State state)
|
||||
void drawBadges(QPainter* painter, const QStyleOptionViewItem& option, BaseInstance* instance, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
QList<QString> pixmaps;
|
||||
if (instance->isRunning())
|
||||
{
|
||||
if (instance->isRunning()) {
|
||||
pixmaps.append("status-running");
|
||||
}
|
||||
else if (instance->hasCrashed() || instance->hasVersionBroken())
|
||||
{
|
||||
} else if (instance->hasCrashed() || instance->hasVersionBroken()) {
|
||||
pixmaps.append("status-bad");
|
||||
}
|
||||
if (instance->hasUpdateAvailable())
|
||||
{
|
||||
if (instance->hasUpdateAvailable()) {
|
||||
pixmaps.append("checkupdate");
|
||||
}
|
||||
|
||||
@@ -153,12 +141,9 @@ void drawBadges(QPainter *painter, const QStyleOptionViewItem &option, BaseInsta
|
||||
const int rows = qCeil((double)pixmaps.size() / (double)itemsPerRow);
|
||||
QListIterator<QString> it(pixmaps);
|
||||
painter->translate(option.rect.topLeft());
|
||||
for (int y = 0; y < rows; ++y)
|
||||
{
|
||||
for (int x = 0; x < itemsPerRow; ++x)
|
||||
{
|
||||
if (!it.hasNext())
|
||||
{
|
||||
for (int y = 0; y < rows; ++y) {
|
||||
for (int x = 0; x < itemsPerRow; ++x) {
|
||||
if (!it.hasNext()) {
|
||||
return;
|
||||
}
|
||||
// FIXME: inject this.
|
||||
@@ -166,21 +151,17 @@ void drawBadges(QPainter *painter, const QStyleOptionViewItem &option, BaseInsta
|
||||
// opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state);
|
||||
const QPixmap pixmap;
|
||||
// itemSide
|
||||
QRect badgeRect(
|
||||
option.rect.width() - x * itemSide + qMax(x - 1, 0) * spacing - itemSide,
|
||||
y * itemSide + qMax(y - 1, 0) * spacing,
|
||||
itemSide,
|
||||
itemSide
|
||||
);
|
||||
QRect badgeRect(option.rect.width() - x * itemSide + qMax(x - 1, 0) * spacing - itemSide,
|
||||
y * itemSide + qMax(y - 1, 0) * spacing, itemSide, itemSide);
|
||||
icon.paint(painter, badgeRect, Qt::AlignCenter, mode, state);
|
||||
}
|
||||
}
|
||||
painter->translate(-option.rect.topLeft());
|
||||
}
|
||||
|
||||
static QSize viewItemTextSize(const QStyleOptionViewItem *option)
|
||||
static QSize viewItemTextSize(const QStyleOptionViewItem* option)
|
||||
{
|
||||
QStyle *style = option->widget ? option->widget->style() : QApplication::style();
|
||||
QStyle* style = option->widget ? option->widget->style() : QApplication::style();
|
||||
QTextOption textOption;
|
||||
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
||||
QTextLayout textLayout;
|
||||
@@ -195,8 +176,7 @@ static QSize viewItemTextSize(const QStyleOptionViewItem *option)
|
||||
return QSize(size.width() + 2 * textMargin, size.height());
|
||||
}
|
||||
|
||||
void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
void ListViewDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
@@ -208,7 +188,7 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
|
||||
opt.textElideMode = Qt::ElideRight;
|
||||
opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;
|
||||
|
||||
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
QStyle* style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
|
||||
// const int iconSize = style->pixelMetric(QStyle::PM_IconViewIconSize);
|
||||
const int iconSize = 48;
|
||||
@@ -296,16 +276,12 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
|
||||
opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state);
|
||||
}
|
||||
// set the text colors
|
||||
QPalette::ColorGroup cg =
|
||||
opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
|
||||
QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
|
||||
if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active))
|
||||
cg = QPalette::Inactive;
|
||||
if (opt.state & QStyle::State_Selected)
|
||||
{
|
||||
if (opt.state & QStyle::State_Selected) {
|
||||
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||
}
|
||||
|
||||
@@ -324,20 +300,16 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
|
||||
|
||||
const int lineCount = textLayout.lineCount();
|
||||
|
||||
const QRect layoutRect = QStyle::alignedRect(
|
||||
opt.direction, opt.displayAlignment, QSize(textRect.width(), int(height)), textRect);
|
||||
const QRect layoutRect = QStyle::alignedRect(opt.direction, opt.displayAlignment, QSize(textRect.width(), int(height)), textRect);
|
||||
const QPointF position = layoutRect.topLeft();
|
||||
for (int i = 0; i < lineCount; ++i)
|
||||
{
|
||||
for (int i = 0; i < lineCount; ++i) {
|
||||
const QTextLine line = textLayout.lineAt(i);
|
||||
line.draw(painter, position);
|
||||
}
|
||||
|
||||
// FIXME: this really has no business of being here. Make generic.
|
||||
auto instance = (BaseInstance*)index.data(InstanceList::InstancePointerRole)
|
||||
.value<void *>();
|
||||
if (instance)
|
||||
{
|
||||
auto instance = (BaseInstance*)index.data(InstanceList::InstancePointerRole).value<void*>();
|
||||
if (instance) {
|
||||
drawBadges(painter, opt, instance, mode, state);
|
||||
}
|
||||
|
||||
@@ -347,8 +319,7 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
@@ -357,9 +328,9 @@ QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option,
|
||||
opt.textElideMode = Qt::ElideRight;
|
||||
opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;
|
||||
|
||||
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
QStyle* style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, opt.widget) + 1;
|
||||
int height = 48 + textMargin * 2 + 5; // TODO: turn constants into variables
|
||||
int height = 48 + textMargin * 2 + 5; // TODO: turn constants into variables
|
||||
QSize szz = viewItemTextSize(&opt);
|
||||
height += szz.height();
|
||||
// FIXME: maybe the icon items could scale and keep proportions?
|
||||
@@ -367,36 +338,32 @@ QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option,
|
||||
return sz;
|
||||
}
|
||||
|
||||
class NoReturnTextEdit: public QTextEdit
|
||||
{
|
||||
class NoReturnTextEdit : public QTextEdit {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit NoReturnTextEdit(QWidget *parent) : QTextEdit(parent)
|
||||
public:
|
||||
explicit NoReturnTextEdit(QWidget* parent) : QTextEdit(parent)
|
||||
{
|
||||
setTextInteractionFlags(Qt::TextEditorInteraction);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
|
||||
}
|
||||
bool event(QEvent * event) override
|
||||
bool event(QEvent* event) override
|
||||
{
|
||||
auto eventType = event->type();
|
||||
if(eventType == QEvent::KeyPress || eventType == QEvent::KeyRelease)
|
||||
{
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
if (eventType == QEvent::KeyPress || eventType == QEvent::KeyRelease) {
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
auto key = keyEvent->key();
|
||||
if ((key == Qt::Key_Return || key == Qt::Key_Enter) && eventType == QEvent::KeyPress)
|
||||
{
|
||||
if ((key == Qt::Key_Return || key == Qt::Key_Enter) && eventType == QEvent::KeyPress) {
|
||||
emit editingDone();
|
||||
return true;
|
||||
}
|
||||
if(key == Qt::Key_Tab)
|
||||
{
|
||||
if (key == Qt::Key_Tab) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QTextEdit::event(event);
|
||||
}
|
||||
signals:
|
||||
signals:
|
||||
void editingDone();
|
||||
};
|
||||
|
||||
@@ -412,7 +379,7 @@ void ListViewDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionV
|
||||
void ListViewDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
|
||||
{
|
||||
auto text = index.data(Qt::EditRole).toString();
|
||||
QTextEdit * realeditor = qobject_cast<NoReturnTextEdit *>(editor);
|
||||
QTextEdit* realeditor = qobject_cast<NoReturnTextEdit*>(editor);
|
||||
realeditor->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
|
||||
realeditor->append(text);
|
||||
realeditor->selectAll();
|
||||
@@ -421,19 +388,18 @@ void ListViewDelegate::setEditorData(QWidget* editor, const QModelIndex& index)
|
||||
|
||||
void ListViewDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
|
||||
{
|
||||
QTextEdit * realeditor = qobject_cast<NoReturnTextEdit *>(editor);
|
||||
QTextEdit* realeditor = qobject_cast<NoReturnTextEdit*>(editor);
|
||||
QString text = realeditor->toPlainText();
|
||||
text.replace(QChar('\n'), QChar(' '));
|
||||
text = text.trimmed();
|
||||
// Prevent instance names longer than 128 chars
|
||||
text.truncate(128);
|
||||
if(text.size() != 0)
|
||||
{
|
||||
if (text.size() != 0) {
|
||||
model->setData(index, text);
|
||||
}
|
||||
}
|
||||
|
||||
QWidget * ListViewDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
QWidget* ListViewDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
auto editor = new NoReturnTextEdit(parent);
|
||||
connect(editor, &NoReturnTextEdit::editingDone, this, &ListViewDelegate::editingDone);
|
||||
@@ -442,7 +408,7 @@ QWidget * ListViewDelegate::createEditor(QWidget* parent, const QStyleOptionView
|
||||
|
||||
void ListViewDelegate::editingDone()
|
||||
{
|
||||
NoReturnTextEdit *editor = qobject_cast<NoReturnTextEdit *>(sender());
|
||||
NoReturnTextEdit* editor = qobject_cast<NoReturnTextEdit*>(sender());
|
||||
emit commitData(editor);
|
||||
emit closeEditor(editor);
|
||||
}
|
||||
|
||||
@@ -15,25 +15,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QCache>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class ListViewDelegate : public QStyledItemDelegate
|
||||
{
|
||||
class ListViewDelegate : public QStyledItemDelegate {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ListViewDelegate(QObject *parent = 0);
|
||||
public:
|
||||
explicit ListViewDelegate(QObject* parent = 0);
|
||||
virtual ~ListViewDelegate() {}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
void updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
|
||||
QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
|
||||
void setEditorData(QWidget * editor, const QModelIndex & index) const override;
|
||||
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override;
|
||||
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
|
||||
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
|
||||
|
||||
private slots:
|
||||
private slots:
|
||||
void editingDone();
|
||||
};
|
||||
|
||||
@@ -15,57 +15,54 @@
|
||||
|
||||
#include "InstanceProxyModel.h"
|
||||
|
||||
#include "InstanceView.h"
|
||||
#include "Application.h"
|
||||
#include <BaseInstance.h>
|
||||
#include <icons/IconList.h>
|
||||
#include "Application.h"
|
||||
#include "InstanceView.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
InstanceProxyModel::InstanceProxyModel(QObject *parent) : QSortFilterProxyModel(parent) {
|
||||
InstanceProxyModel::InstanceProxyModel(QObject* parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
m_naturalSort.setNumericMode(true);
|
||||
m_naturalSort.setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
|
||||
// FIXME: use loaded translation as source of locale instead, hook this up to translation changes
|
||||
m_naturalSort.setLocale(QLocale::system());
|
||||
}
|
||||
|
||||
QVariant InstanceProxyModel::data(const QModelIndex & index, int role) const
|
||||
QVariant InstanceProxyModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
QVariant data = QSortFilterProxyModel::data(index, role);
|
||||
if(role == Qt::DecorationRole)
|
||||
{
|
||||
if (role == Qt::DecorationRole) {
|
||||
return QVariant(APPLICATION->icons()->getIcon(data.toString()));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
bool InstanceProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const {
|
||||
bool InstanceProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const
|
||||
{
|
||||
const QString leftCategory = left.data(InstanceViewRoles::GroupRole).toString();
|
||||
const QString rightCategory = right.data(InstanceViewRoles::GroupRole).toString();
|
||||
if (leftCategory == rightCategory) {
|
||||
return subSortLessThan(left, right);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// FIXME: real group sorting happens in InstanceView::updateGeometries(), see LocaleString
|
||||
auto result = leftCategory.localeAwareCompare(rightCategory);
|
||||
if(result == 0) {
|
||||
if (result == 0) {
|
||||
return subSortLessThan(left, right);
|
||||
}
|
||||
return result < 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool InstanceProxyModel::subSortLessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
bool InstanceProxyModel::subSortLessThan(const QModelIndex& left, const QModelIndex& right) const
|
||||
{
|
||||
BaseInstance *pdataLeft = static_cast<BaseInstance *>(left.internalPointer());
|
||||
BaseInstance *pdataRight = static_cast<BaseInstance *>(right.internalPointer());
|
||||
BaseInstance* pdataLeft = static_cast<BaseInstance*>(left.internalPointer());
|
||||
BaseInstance* pdataRight = static_cast<BaseInstance*>(right.internalPointer());
|
||||
QString sortMode = APPLICATION->settings()->get("InstSortMode").toString();
|
||||
if (sortMode == "LastLaunch")
|
||||
{
|
||||
if (sortMode == "LastLaunch") {
|
||||
return pdataLeft->lastLaunch() > pdataRight->lastLaunch();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return m_naturalSort.compare(pdataLeft->name(), pdataRight->name()) < 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,21 +15,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QCollator>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class InstanceProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
class InstanceProxyModel : public QSortFilterProxyModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InstanceProxyModel(QObject *parent = 0);
|
||||
public:
|
||||
InstanceProxyModel(QObject* parent = 0);
|
||||
|
||||
protected:
|
||||
QVariant data(const QModelIndex & index, int role) const override;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
protected:
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
bool lessThan(const QModelIndex& left, const QModelIndex& right) const override;
|
||||
bool subSortLessThan(const QModelIndex& left, const QModelIndex& right) const;
|
||||
|
||||
private:
|
||||
private:
|
||||
QCollator m_naturalSort;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@@ -35,39 +35,36 @@
|
||||
|
||||
#include "InstanceView.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QApplication>
|
||||
#include <QtMath>
|
||||
#include <QMouseEvent>
|
||||
#include <QListView>
|
||||
#include <QPersistentModelIndex>
|
||||
#include <QDrag>
|
||||
#include <QMimeData>
|
||||
#include <QCache>
|
||||
#include <QScrollBar>
|
||||
#include <QAccessible>
|
||||
#include <QApplication>
|
||||
#include <QCache>
|
||||
#include <QDrag>
|
||||
#include <QListView>
|
||||
#include <QMimeData>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPersistentModelIndex>
|
||||
#include <QScrollBar>
|
||||
#include <QtMath>
|
||||
|
||||
#include "VisualGroup.h"
|
||||
#include <QDebug>
|
||||
#include "VisualGroup.h"
|
||||
|
||||
#include <Application.h>
|
||||
#include <InstanceList.h>
|
||||
#include "ui/themes/ThemeManager.h"
|
||||
|
||||
template <typename T> bool listsIntersect(const QList<T> &l1, const QList<T> t2)
|
||||
template <typename T>
|
||||
bool listsIntersect(const QList<T>& l1, const QList<T> t2)
|
||||
{
|
||||
for (auto &item : l1)
|
||||
{
|
||||
if (t2.contains(item))
|
||||
{
|
||||
for (auto& item : l1) {
|
||||
if (t2.contains(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
InstanceView::InstanceView(QWidget *parent)
|
||||
: QAbstractItemView(parent)
|
||||
InstanceView::InstanceView(QWidget* parent) : QAbstractItemView(parent)
|
||||
{
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
@@ -82,23 +79,23 @@ InstanceView::~InstanceView()
|
||||
m_groups.clear();
|
||||
}
|
||||
|
||||
void InstanceView::setModel(QAbstractItemModel *model)
|
||||
void InstanceView::setModel(QAbstractItemModel* model)
|
||||
{
|
||||
QAbstractItemView::setModel(model);
|
||||
connect(model, &QAbstractItemModel::modelReset, this, &InstanceView::modelReset);
|
||||
connect(model, &QAbstractItemModel::rowsRemoved, this, &InstanceView::rowsRemoved);
|
||||
}
|
||||
|
||||
void InstanceView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
|
||||
void InstanceView::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
|
||||
{
|
||||
scheduleDelayedItemsLayout();
|
||||
}
|
||||
void InstanceView::rowsInserted(const QModelIndex &parent, int start, int end)
|
||||
void InstanceView::rowsInserted(const QModelIndex& parent, int start, int end)
|
||||
{
|
||||
scheduleDelayedItemsLayout();
|
||||
}
|
||||
|
||||
void InstanceView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
|
||||
void InstanceView::rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end)
|
||||
{
|
||||
scheduleDelayedItemsLayout();
|
||||
}
|
||||
@@ -116,7 +113,8 @@ void InstanceView::rowsRemoved()
|
||||
void InstanceView::currentChanged(const QModelIndex& current, const QModelIndex& previous)
|
||||
{
|
||||
QAbstractItemView::currentChanged(current, previous);
|
||||
// TODO: for accessibility support, implement+register a factory, steal QAccessibleTable from Qt and return an instance of it for InstanceView.
|
||||
// TODO: for accessibility support, implement+register a factory, steal QAccessibleTable from Qt and return an instance of it for
|
||||
// InstanceView.
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
if (QAccessible::isActive() && current.isValid()) {
|
||||
QAccessibleEvent event(this, QAccessible::Focus);
|
||||
@@ -126,19 +124,13 @@ void InstanceView::currentChanged(const QModelIndex& current, const QModelIndex&
|
||||
#endif /* !QT_NO_ACCESSIBILITY */
|
||||
}
|
||||
|
||||
|
||||
class LocaleString : public QString
|
||||
{
|
||||
public:
|
||||
LocaleString(const char *s) : QString(s)
|
||||
{
|
||||
}
|
||||
LocaleString(const QString &s) : QString(s)
|
||||
{
|
||||
}
|
||||
class LocaleString : public QString {
|
||||
public:
|
||||
LocaleString(const char* s) : QString(s) {}
|
||||
LocaleString(const QString& s) : QString(s) {}
|
||||
};
|
||||
|
||||
inline bool operator<(const LocaleString &lhs, const LocaleString &rhs)
|
||||
inline bool operator<(const LocaleString& lhs, const LocaleString& rhs)
|
||||
{
|
||||
return (QString::localeAwareCompare(lhs, rhs) < 0);
|
||||
}
|
||||
@@ -146,33 +138,28 @@ inline bool operator<(const LocaleString &lhs, const LocaleString &rhs)
|
||||
void InstanceView::updateScrollbar()
|
||||
{
|
||||
int previousScroll = verticalScrollBar()->value();
|
||||
if (m_groups.isEmpty())
|
||||
{
|
||||
if (m_groups.isEmpty()) {
|
||||
verticalScrollBar()->setRange(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
int totalHeight = 0;
|
||||
// top margin
|
||||
totalHeight += m_categoryMargin;
|
||||
int itemScroll = 0;
|
||||
for (auto category : m_groups)
|
||||
{
|
||||
for (auto category : m_groups) {
|
||||
category->m_verticalPosition = totalHeight;
|
||||
totalHeight += category->totalHeight() + m_categoryMargin;
|
||||
if(!itemScroll && category->totalHeight() != 0)
|
||||
{
|
||||
if (!itemScroll && category->totalHeight() != 0) {
|
||||
itemScroll = category->contentHeight() / category->numRows();
|
||||
}
|
||||
}
|
||||
// do not divide by zero
|
||||
if(itemScroll == 0)
|
||||
if (itemScroll == 0)
|
||||
itemScroll = 64;
|
||||
|
||||
totalHeight += m_bottomMargin;
|
||||
verticalScrollBar()->setSingleStep ( itemScroll );
|
||||
const int rowsPerPage = qMax ( viewport()->height() / itemScroll, 1 );
|
||||
verticalScrollBar()->setPageStep ( rowsPerPage * itemScroll );
|
||||
verticalScrollBar()->setSingleStep(itemScroll);
|
||||
const int rowsPerPage = qMax(viewport()->height() / itemScroll, 1);
|
||||
verticalScrollBar()->setPageStep(rowsPerPage * itemScroll);
|
||||
|
||||
verticalScrollBar()->setRange(0, totalHeight - height());
|
||||
}
|
||||
@@ -184,24 +171,19 @@ void InstanceView::updateGeometries()
|
||||
{
|
||||
geometryCache.clear();
|
||||
|
||||
QMap<LocaleString, VisualGroup *> cats;
|
||||
QMap<LocaleString, VisualGroup*> cats;
|
||||
|
||||
for (int i = 0; i < model()->rowCount(); ++i)
|
||||
{
|
||||
for (int i = 0; i < model()->rowCount(); ++i) {
|
||||
const QString groupName = model()->index(i, 0).data(InstanceViewRoles::GroupRole).toString();
|
||||
if (!cats.contains(groupName))
|
||||
{
|
||||
VisualGroup *old = this->category(groupName);
|
||||
if (old)
|
||||
{
|
||||
if (!cats.contains(groupName)) {
|
||||
VisualGroup* old = this->category(groupName);
|
||||
if (old) {
|
||||
auto cat = new VisualGroup(old);
|
||||
cats.insert(groupName, cat);
|
||||
cat->update();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
auto cat = new VisualGroup(groupName, this);
|
||||
if(fVisibility) {
|
||||
if (fVisibility) {
|
||||
cat->collapsed = fVisibility(groupName);
|
||||
}
|
||||
cats.insert(groupName, cat);
|
||||
@@ -216,43 +198,36 @@ void InstanceView::updateGeometries()
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
bool InstanceView::isIndexHidden(const QModelIndex &index) const
|
||||
bool InstanceView::isIndexHidden(const QModelIndex& index) const
|
||||
{
|
||||
VisualGroup *cat = category(index);
|
||||
if (cat)
|
||||
{
|
||||
VisualGroup* cat = category(index);
|
||||
if (cat) {
|
||||
return cat->collapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
VisualGroup *InstanceView::category(const QModelIndex &index) const
|
||||
VisualGroup* InstanceView::category(const QModelIndex& index) const
|
||||
{
|
||||
return category(index.data(InstanceViewRoles::GroupRole).toString());
|
||||
}
|
||||
|
||||
VisualGroup *InstanceView::category(const QString &cat) const
|
||||
VisualGroup* InstanceView::category(const QString& cat) const
|
||||
{
|
||||
for (auto group : m_groups)
|
||||
{
|
||||
if (group->text == cat)
|
||||
{
|
||||
for (auto group : m_groups) {
|
||||
if (group->text == cat) {
|
||||
return group;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VisualGroup *InstanceView::categoryAt(const QPoint &pos, VisualGroup::HitResults & result) const
|
||||
VisualGroup* InstanceView::categoryAt(const QPoint& pos, VisualGroup::HitResults& result) const
|
||||
{
|
||||
for (auto group : m_groups)
|
||||
{
|
||||
for (auto group : m_groups) {
|
||||
result = group->hitScan(pos);
|
||||
if(result != VisualGroup::NoHit)
|
||||
{
|
||||
if (result != VisualGroup::NoHit) {
|
||||
return group;
|
||||
}
|
||||
}
|
||||
@@ -260,14 +235,13 @@ VisualGroup *InstanceView::categoryAt(const QPoint &pos, VisualGroup::HitResults
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString InstanceView::groupNameAt(const QPoint &point)
|
||||
QString InstanceView::groupNameAt(const QPoint& point)
|
||||
{
|
||||
executeDelayedItemsLayout();
|
||||
|
||||
VisualGroup::HitResults hitresult;
|
||||
auto group = categoryAt(point + offset(), hitresult);
|
||||
if(group && (hitresult & (VisualGroup::HeaderHit | VisualGroup::BodyHit)))
|
||||
{
|
||||
if (group && (hitresult & (VisualGroup::HeaderHit | VisualGroup::BodyHit))) {
|
||||
return group->text;
|
||||
}
|
||||
return QString();
|
||||
@@ -288,7 +262,7 @@ int InstanceView::itemWidth() const
|
||||
return m_itemWidth;
|
||||
}
|
||||
|
||||
void InstanceView::mousePressEvent(QMouseEvent *event)
|
||||
void InstanceView::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
executeDelayedItemsLayout();
|
||||
|
||||
@@ -303,17 +277,14 @@ void InstanceView::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
VisualGroup::HitResults hitresult;
|
||||
m_pressedCategory = categoryAt(geometryPos, hitresult);
|
||||
if (m_pressedCategory && hitresult & VisualGroup::CheckboxHit)
|
||||
{
|
||||
if (m_pressedCategory && hitresult & VisualGroup::CheckboxHit) {
|
||||
setState(m_pressedCategory->collapsed ? ExpandingState : CollapsingState);
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
if (index.isValid() && (index.flags() & Qt::ItemIsEnabled))
|
||||
{
|
||||
if(index != currentIndex())
|
||||
{
|
||||
if (index.isValid() && (index.flags() & Qt::ItemIsEnabled)) {
|
||||
if (index != currentIndex()) {
|
||||
// FIXME: better!
|
||||
m_currentCursorColumn = -1;
|
||||
}
|
||||
@@ -329,15 +300,13 @@ void InstanceView::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
// signal handlers may change the model
|
||||
emit pressed(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Forces a finalize() even if mouse is pressed, but not on a item
|
||||
selectionModel()->select(QModelIndex(), QItemSelectionModel::Select);
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceView::mouseMoveEvent(QMouseEvent *event)
|
||||
void InstanceView::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
executeDelayedItemsLayout();
|
||||
|
||||
@@ -345,16 +314,13 @@ void InstanceView::mouseMoveEvent(QMouseEvent *event)
|
||||
QPoint visualPos = event->pos();
|
||||
QPoint geometryPos = event->pos() + offset();
|
||||
|
||||
if (state() == ExpandingState || state() == CollapsingState)
|
||||
{
|
||||
if (state() == ExpandingState || state() == CollapsingState) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state() == DraggingState)
|
||||
{
|
||||
if (state() == DraggingState) {
|
||||
topLeft = m_pressedPosition - offset();
|
||||
if ((topLeft - event->pos()).manhattanLength() > QApplication::startDragDistance())
|
||||
{
|
||||
if ((topLeft - event->pos()).manhattanLength() > QApplication::startDragDistance()) {
|
||||
m_pressedIndex = QModelIndex();
|
||||
startDrag(model()->supportedDragActions());
|
||||
setState(NoState);
|
||||
@@ -363,39 +329,31 @@ void InstanceView::mouseMoveEvent(QMouseEvent *event)
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectionMode() != SingleSelection)
|
||||
{
|
||||
if (selectionMode() != SingleSelection) {
|
||||
topLeft = m_pressedPosition - offset();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
topLeft = geometryPos;
|
||||
}
|
||||
|
||||
if (m_pressedIndex.isValid() && (state() != DragSelectingState) &&
|
||||
(event->buttons() != Qt::NoButton) && !selectedIndexes().isEmpty())
|
||||
{
|
||||
if (m_pressedIndex.isValid() && (state() != DragSelectingState) && (event->buttons() != Qt::NoButton) && !selectedIndexes().isEmpty()) {
|
||||
setState(DraggingState);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((event->buttons() & Qt::LeftButton) && selectionModel())
|
||||
{
|
||||
if ((event->buttons() & Qt::LeftButton) && selectionModel()) {
|
||||
setState(DragSelectingState);
|
||||
|
||||
setSelection(QRect(visualPos, visualPos), QItemSelectionModel::ClearAndSelect);
|
||||
QModelIndex index = indexAt(visualPos);
|
||||
|
||||
// set at the end because it might scroll the view
|
||||
if (index.isValid() && (index != selectionModel()->currentIndex()) &&
|
||||
(index.flags() & Qt::ItemIsEnabled))
|
||||
{
|
||||
if (index.isValid() && (index != selectionModel()->currentIndex()) && (index.flags() & Qt::ItemIsEnabled)) {
|
||||
selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceView::mouseReleaseEvent(QMouseEvent *event)
|
||||
void InstanceView::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
executeDelayedItemsLayout();
|
||||
|
||||
@@ -405,13 +363,11 @@ void InstanceView::mouseReleaseEvent(QMouseEvent *event)
|
||||
|
||||
VisualGroup::HitResults hitresult;
|
||||
|
||||
bool click = (index == m_pressedIndex && index.isValid()) ||
|
||||
(m_pressedCategory && m_pressedCategory == categoryAt(geometryPos, hitresult));
|
||||
bool click =
|
||||
(index == m_pressedIndex && index.isValid()) || (m_pressedCategory && m_pressedCategory == categoryAt(geometryPos, hitresult));
|
||||
|
||||
if (click && m_pressedCategory)
|
||||
{
|
||||
if (state() == ExpandingState)
|
||||
{
|
||||
if (click && m_pressedCategory) {
|
||||
if (state() == ExpandingState) {
|
||||
m_pressedCategory->collapsed = false;
|
||||
emit groupStateChanged(m_pressedCategory->text, false);
|
||||
|
||||
@@ -421,9 +377,7 @@ void InstanceView::mouseReleaseEvent(QMouseEvent *event)
|
||||
m_pressedCategory = nullptr;
|
||||
setState(NoState);
|
||||
return;
|
||||
}
|
||||
else if (state() == CollapsingState)
|
||||
{
|
||||
} else if (state() == CollapsingState) {
|
||||
m_pressedCategory->collapsed = true;
|
||||
emit groupStateChanged(m_pressedCategory->text, true);
|
||||
|
||||
@@ -440,10 +394,8 @@ void InstanceView::mouseReleaseEvent(QMouseEvent *event)
|
||||
|
||||
setState(NoState);
|
||||
|
||||
if (click)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
if (click) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
emit clicked(index);
|
||||
}
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
@@ -452,34 +404,24 @@ void InstanceView::mouseReleaseEvent(QMouseEvent *event)
|
||||
#else
|
||||
QStyleOptionViewItem option = viewOptions();
|
||||
#endif
|
||||
if (m_pressedAlreadySelected)
|
||||
{
|
||||
if (m_pressedAlreadySelected) {
|
||||
option.state |= QStyle::State_Selected;
|
||||
}
|
||||
if ((model()->flags(index) & Qt::ItemIsEnabled) &&
|
||||
style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, &option, this))
|
||||
{
|
||||
style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, &option, this)) {
|
||||
emit activated(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceView::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
void InstanceView::mouseDoubleClickEvent(QMouseEvent* event)
|
||||
{
|
||||
executeDelayedItemsLayout();
|
||||
|
||||
QModelIndex index = indexAt(event->pos());
|
||||
if (!index.isValid() || !(index.flags() & Qt::ItemIsEnabled) || (m_pressedIndex != index))
|
||||
{
|
||||
QMouseEvent me(
|
||||
QEvent::MouseButtonPress,
|
||||
event->localPos(),
|
||||
event->windowPos(),
|
||||
event->screenPos(),
|
||||
event->button(),
|
||||
event->buttons(),
|
||||
event->modifiers()
|
||||
);
|
||||
if (!index.isValid() || !(index.flags() & Qt::ItemIsEnabled) || (m_pressedIndex != index)) {
|
||||
QMouseEvent me(QEvent::MouseButtonPress, event->localPos(), event->windowPos(), event->screenPos(), event->button(),
|
||||
event->buttons(), event->modifiers());
|
||||
mousePressEvent(&me);
|
||||
return;
|
||||
}
|
||||
@@ -493,8 +435,7 @@ void InstanceView::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
#else
|
||||
QStyleOptionViewItem option = viewOptions();
|
||||
#endif
|
||||
if ((model()->flags(index) & Qt::ItemIsEnabled) && !style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, &option, this))
|
||||
{
|
||||
if ((model()->flags(index) & Qt::ItemIsEnabled) && !style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, &option, this)) {
|
||||
emit activated(index);
|
||||
}
|
||||
}
|
||||
@@ -537,9 +478,8 @@ void InstanceView::paintEvent(QPaintEvent* event)
|
||||
|
||||
int wpWidth = viewport()->width();
|
||||
option.rect.setWidth(wpWidth);
|
||||
for (int i = 0; i < m_groups.size(); ++i)
|
||||
{
|
||||
VisualGroup *category = m_groups.at(i);
|
||||
for (int i = 0; i < m_groups.size(); ++i) {
|
||||
VisualGroup* category = m_groups.at(i);
|
||||
int y = category->verticalPosition();
|
||||
y -= verticalOffset();
|
||||
QRect backup = option.rect;
|
||||
@@ -553,28 +493,21 @@ void InstanceView::paintEvent(QPaintEvent* event)
|
||||
option.rect = backup;
|
||||
}
|
||||
|
||||
for (int i = 0; i < model()->rowCount(); ++i)
|
||||
{
|
||||
for (int i = 0; i < model()->rowCount(); ++i) {
|
||||
const QModelIndex index = model()->index(i, 0);
|
||||
if (isIndexHidden(index))
|
||||
{
|
||||
if (isIndexHidden(index)) {
|
||||
continue;
|
||||
}
|
||||
Qt::ItemFlags flags = index.flags();
|
||||
option.rect = visualRect(index);
|
||||
option.features |= QStyleOptionViewItem::WrapText;
|
||||
if (flags & Qt::ItemIsSelectable && selectionModel()->isSelected(index))
|
||||
{
|
||||
option.state |= selectionModel()->isSelected(index) ? QStyle::State_Selected
|
||||
: QStyle::State_None;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & Qt::ItemIsSelectable && selectionModel()->isSelected(index)) {
|
||||
option.state |= selectionModel()->isSelected(index) ? QStyle::State_Selected : QStyle::State_None;
|
||||
} else {
|
||||
option.state &= ~QStyle::State_Selected;
|
||||
}
|
||||
option.state |= (index == currentIndex()) ? QStyle::State_HasFocus : QStyle::State_None;
|
||||
if (!(flags & Qt::ItemIsEnabled))
|
||||
{
|
||||
if (!(flags & Qt::ItemIsEnabled)) {
|
||||
option.state &= ~QStyle::State_Enabled;
|
||||
}
|
||||
itemDelegate()->paint(&painter, option, index);
|
||||
@@ -612,27 +545,23 @@ void InstanceView::paintEvent(QPaintEvent* event)
|
||||
#endif
|
||||
}
|
||||
|
||||
void InstanceView::resizeEvent(QResizeEvent *event)
|
||||
void InstanceView::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
int newItemsPerRow = calculateItemsPerRow();
|
||||
if(newItemsPerRow != m_currentItemsPerRow)
|
||||
{
|
||||
if (newItemsPerRow != m_currentItemsPerRow) {
|
||||
m_currentCursorColumn = -1;
|
||||
m_currentItemsPerRow = newItemsPerRow;
|
||||
updateGeometries();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
updateScrollbar();
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceView::dragEnterEvent(QDragEnterEvent *event)
|
||||
void InstanceView::dragEnterEvent(QDragEnterEvent* event)
|
||||
{
|
||||
executeDelayedItemsLayout();
|
||||
|
||||
if (!isDragEventAccepted(event))
|
||||
{
|
||||
if (!isDragEventAccepted(event)) {
|
||||
return;
|
||||
}
|
||||
m_lastDragPosition = event->pos() + offset();
|
||||
@@ -640,12 +569,11 @@ void InstanceView::dragEnterEvent(QDragEnterEvent *event)
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void InstanceView::dragMoveEvent(QDragMoveEvent *event)
|
||||
void InstanceView::dragMoveEvent(QDragMoveEvent* event)
|
||||
{
|
||||
executeDelayedItemsLayout();
|
||||
|
||||
if (!isDragEventAccepted(event))
|
||||
{
|
||||
if (!isDragEventAccepted(event)) {
|
||||
return;
|
||||
}
|
||||
m_lastDragPosition = event->pos() + offset();
|
||||
@@ -653,7 +581,7 @@ void InstanceView::dragMoveEvent(QDragMoveEvent *event)
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void InstanceView::dragLeaveEvent(QDragLeaveEvent *event)
|
||||
void InstanceView::dragLeaveEvent(QDragLeaveEvent* event)
|
||||
{
|
||||
executeDelayedItemsLayout();
|
||||
|
||||
@@ -661,7 +589,7 @@ void InstanceView::dragLeaveEvent(QDragLeaveEvent *event)
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void InstanceView::dropEvent(QDropEvent *event)
|
||||
void InstanceView::dropEvent(QDropEvent* event)
|
||||
{
|
||||
executeDelayedItemsLayout();
|
||||
|
||||
@@ -672,16 +600,13 @@ void InstanceView::dropEvent(QDropEvent *event)
|
||||
|
||||
auto mimedata = event->mimeData();
|
||||
|
||||
if (event->source() == this)
|
||||
{
|
||||
if(event->possibleActions() & Qt::MoveAction)
|
||||
{
|
||||
std::pair<VisualGroup *, VisualGroup::HitResults> dropPos = rowDropPos(event->pos());
|
||||
const VisualGroup *group = dropPos.first;
|
||||
if (event->source() == this) {
|
||||
if (event->possibleActions() & Qt::MoveAction) {
|
||||
std::pair<VisualGroup*, VisualGroup::HitResults> dropPos = rowDropPos(event->pos());
|
||||
const VisualGroup* group = dropPos.first;
|
||||
auto hitresult = dropPos.second;
|
||||
|
||||
if (hitresult == VisualGroup::HitResult::NoHit)
|
||||
{
|
||||
if (hitresult == VisualGroup::HitResult::NoHit) {
|
||||
viewport()->update();
|
||||
return;
|
||||
}
|
||||
@@ -698,14 +623,12 @@ void InstanceView::dropEvent(QDropEvent *event)
|
||||
}
|
||||
|
||||
// check if the action is supported
|
||||
if (!mimedata)
|
||||
{
|
||||
if (!mimedata) {
|
||||
return;
|
||||
}
|
||||
|
||||
// files dropped from outside?
|
||||
if (mimedata->hasUrls())
|
||||
{
|
||||
if (mimedata->hasUrls()) {
|
||||
auto urls = mimedata->urls();
|
||||
event->accept();
|
||||
emit droppedURLs(urls);
|
||||
@@ -717,57 +640,52 @@ void InstanceView::startDrag(Qt::DropActions supportedActions)
|
||||
executeDelayedItemsLayout();
|
||||
|
||||
QModelIndexList indexes = selectionModel()->selectedIndexes();
|
||||
if(indexes.count() == 0)
|
||||
if (indexes.count() == 0)
|
||||
return;
|
||||
|
||||
QMimeData *data = model()->mimeData(indexes);
|
||||
if (!data)
|
||||
{
|
||||
QMimeData* data = model()->mimeData(indexes);
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
QRect rect;
|
||||
QPixmap pixmap = renderToPixmap(indexes, &rect);
|
||||
QDrag *drag = new QDrag(this);
|
||||
QDrag* drag = new QDrag(this);
|
||||
drag->setPixmap(pixmap);
|
||||
drag->setMimeData(data);
|
||||
drag->setHotSpot(m_pressedPosition - rect.topLeft());
|
||||
Qt::DropAction defaultDropAction = Qt::IgnoreAction;
|
||||
if (this->defaultDropAction() != Qt::IgnoreAction && (supportedActions & this->defaultDropAction()))
|
||||
{
|
||||
if (this->defaultDropAction() != Qt::IgnoreAction && (supportedActions & this->defaultDropAction())) {
|
||||
defaultDropAction = this->defaultDropAction();
|
||||
}
|
||||
/*auto action = */
|
||||
drag->exec(supportedActions, defaultDropAction);
|
||||
}
|
||||
|
||||
QRect InstanceView::visualRect(const QModelIndex &index) const
|
||||
QRect InstanceView::visualRect(const QModelIndex& index) const
|
||||
{
|
||||
const_cast<InstanceView*>(this)->executeDelayedItemsLayout();
|
||||
|
||||
return geometryRect(index).translated(-offset());
|
||||
}
|
||||
|
||||
QRect InstanceView::geometryRect(const QModelIndex &index) const
|
||||
QRect InstanceView::geometryRect(const QModelIndex& index) const
|
||||
{
|
||||
const_cast<InstanceView*>(this)->executeDelayedItemsLayout();
|
||||
|
||||
if (!index.isValid() || isIndexHidden(index) || index.column() > 0)
|
||||
{
|
||||
if (!index.isValid() || isIndexHidden(index) || index.column() > 0) {
|
||||
return QRect();
|
||||
}
|
||||
|
||||
int row = index.row();
|
||||
if(geometryCache.contains(row))
|
||||
{
|
||||
if (geometryCache.contains(row)) {
|
||||
return *geometryCache[row];
|
||||
}
|
||||
|
||||
const VisualGroup *cat = category(index);
|
||||
const VisualGroup* cat = category(index);
|
||||
QPair<int, int> pos = cat->positionOf(index);
|
||||
int x = pos.first;
|
||||
// int y = pos.second;
|
||||
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
QStyleOptionViewItem option;
|
||||
initViewItemOption(&option);
|
||||
@@ -783,43 +701,38 @@ QRect InstanceView::geometryRect(const QModelIndex &index) const
|
||||
return out;
|
||||
}
|
||||
|
||||
QModelIndex InstanceView::indexAt(const QPoint &point) const
|
||||
QModelIndex InstanceView::indexAt(const QPoint& point) const
|
||||
{
|
||||
const_cast<InstanceView*>(this)->executeDelayedItemsLayout();
|
||||
|
||||
for (int i = 0; i < model()->rowCount(); ++i)
|
||||
{
|
||||
for (int i = 0; i < model()->rowCount(); ++i) {
|
||||
QModelIndex index = model()->index(i, 0);
|
||||
if (visualRect(index).contains(point))
|
||||
{
|
||||
if (visualRect(index).contains(point)) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
void InstanceView::setSelection(const QRect &rect, const QItemSelectionModel::SelectionFlags commands)
|
||||
void InstanceView::setSelection(const QRect& rect, const QItemSelectionModel::SelectionFlags commands)
|
||||
{
|
||||
executeDelayedItemsLayout();
|
||||
|
||||
for (int i = 0; i < model()->rowCount(); ++i)
|
||||
{
|
||||
for (int i = 0; i < model()->rowCount(); ++i) {
|
||||
QModelIndex index = model()->index(i, 0);
|
||||
QRect itemRect = visualRect(index);
|
||||
if (itemRect.intersects(rect))
|
||||
{
|
||||
if (itemRect.intersects(rect)) {
|
||||
selectionModel()->select(index, commands);
|
||||
update(itemRect.translated(-offset()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap InstanceView::renderToPixmap(const QModelIndexList &indices, QRect *r) const
|
||||
QPixmap InstanceView::renderToPixmap(const QModelIndexList& indices, QRect* r) const
|
||||
{
|
||||
Q_ASSERT(r);
|
||||
auto paintPairs = draggablePaintPairs(indices, r);
|
||||
if (paintPairs.isEmpty())
|
||||
{
|
||||
if (paintPairs.isEmpty()) {
|
||||
return QPixmap();
|
||||
}
|
||||
QPixmap pixmap(r->size());
|
||||
@@ -832,23 +745,21 @@ QPixmap InstanceView::renderToPixmap(const QModelIndexList &indices, QRect *r) c
|
||||
QStyleOptionViewItem option = viewOptions();
|
||||
#endif
|
||||
option.state |= QStyle::State_Selected;
|
||||
for (int j = 0; j < paintPairs.count(); ++j)
|
||||
{
|
||||
for (int j = 0; j < paintPairs.count(); ++j) {
|
||||
option.rect = paintPairs.at(j).first.translated(-r->topLeft());
|
||||
const QModelIndex ¤t = paintPairs.at(j).second;
|
||||
const QModelIndex& current = paintPairs.at(j).second;
|
||||
itemDelegate()->paint(&painter, option, current);
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
QList<std::pair<QRect, QModelIndex>> InstanceView::draggablePaintPairs(const QModelIndexList &indices, QRect *r) const
|
||||
QList<std::pair<QRect, QModelIndex>> InstanceView::draggablePaintPairs(const QModelIndexList& indices, QRect* r) const
|
||||
{
|
||||
Q_ASSERT(r);
|
||||
QRect &rect = *r;
|
||||
QRect& rect = *r;
|
||||
QList<std::pair<QRect, QModelIndex>> ret;
|
||||
for (int i = 0; i < indices.count(); ++i)
|
||||
{
|
||||
const QModelIndex &index = indices.at(i);
|
||||
for (int i = 0; i < indices.count(); ++i) {
|
||||
const QModelIndex& index = indices.at(i);
|
||||
const QRect current = geometryRect(index);
|
||||
ret += std::make_pair(current, index);
|
||||
rect |= current;
|
||||
@@ -856,12 +767,12 @@ QList<std::pair<QRect, QModelIndex>> InstanceView::draggablePaintPairs(const QMo
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool InstanceView::isDragEventAccepted(QDropEvent *event)
|
||||
bool InstanceView::isDragEventAccepted(QDropEvent* event)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<VisualGroup *, VisualGroup::HitResults> InstanceView::rowDropPos(const QPoint &pos)
|
||||
std::pair<VisualGroup*, VisualGroup::HitResults> InstanceView::rowDropPos(const QPoint& pos)
|
||||
{
|
||||
VisualGroup::HitResults hitresult;
|
||||
auto group = categoryAt(pos + offset(), hitresult);
|
||||
@@ -873,21 +784,18 @@ QPoint InstanceView::offset() const
|
||||
return QPoint(horizontalOffset(), verticalOffset());
|
||||
}
|
||||
|
||||
QRegion InstanceView::visualRegionForSelection(const QItemSelection &selection) const
|
||||
QRegion InstanceView::visualRegionForSelection(const QItemSelection& selection) const
|
||||
{
|
||||
QRegion region;
|
||||
for (auto &range : selection)
|
||||
{
|
||||
for (auto& range : selection) {
|
||||
int start_row = range.top();
|
||||
int end_row = range.bottom();
|
||||
for (int row = start_row; row <= end_row; ++row)
|
||||
{
|
||||
for (int row = start_row; row <= end_row; ++row) {
|
||||
int start_column = range.left();
|
||||
int end_column = range.right();
|
||||
for (int column = start_column; column <= end_column; ++column)
|
||||
{
|
||||
for (int column = start_column; column <= end_column; ++column) {
|
||||
QModelIndex index = model()->index(row, column, rootIndex());
|
||||
region += visualRect(index); // OK
|
||||
region += visualRect(index); // OK
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -897,122 +805,97 @@ QRegion InstanceView::visualRegionForSelection(const QItemSelection &selection)
|
||||
QModelIndex InstanceView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
auto current = currentIndex();
|
||||
if(!current.isValid())
|
||||
{
|
||||
if (!current.isValid()) {
|
||||
return current;
|
||||
}
|
||||
auto cat = category(current);
|
||||
int group_index = m_groups.indexOf(cat);
|
||||
if(group_index < 0)
|
||||
if (group_index < 0)
|
||||
return current;
|
||||
|
||||
QPair<int, int> pos = cat->positionOf(current);
|
||||
int column = pos.first;
|
||||
int row = pos.second;
|
||||
if(m_currentCursorColumn < 0)
|
||||
{
|
||||
if (m_currentCursorColumn < 0) {
|
||||
m_currentCursorColumn = column;
|
||||
}
|
||||
switch(cursorAction)
|
||||
{
|
||||
case MoveUp:
|
||||
{
|
||||
if(row == 0)
|
||||
{
|
||||
int prevgroupindex = group_index-1;
|
||||
while(prevgroupindex >= 0)
|
||||
{
|
||||
switch (cursorAction) {
|
||||
case MoveUp: {
|
||||
if (row == 0) {
|
||||
int prevgroupindex = group_index - 1;
|
||||
while (prevgroupindex >= 0) {
|
||||
auto prevgroup = m_groups[prevgroupindex];
|
||||
if(prevgroup->collapsed)
|
||||
{
|
||||
if (prevgroup->collapsed) {
|
||||
prevgroupindex--;
|
||||
continue;
|
||||
}
|
||||
int newRow = prevgroup->numRows() - 1;
|
||||
int newRowSize = prevgroup->rows[newRow].size();
|
||||
int newColumn = m_currentCursorColumn;
|
||||
if (m_currentCursorColumn >= newRowSize)
|
||||
{
|
||||
if (m_currentCursorColumn >= newRowSize) {
|
||||
newColumn = newRowSize - 1;
|
||||
}
|
||||
return prevgroup->rows[newRow][newColumn];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
int newRow = row - 1;
|
||||
int newRowSize = cat->rows[newRow].size();
|
||||
int newColumn = m_currentCursorColumn;
|
||||
if (m_currentCursorColumn >= newRowSize)
|
||||
{
|
||||
if (m_currentCursorColumn >= newRowSize) {
|
||||
newColumn = newRowSize - 1;
|
||||
}
|
||||
return cat->rows[newRow][newColumn];
|
||||
}
|
||||
return current;
|
||||
}
|
||||
case MoveDown:
|
||||
{
|
||||
if(row == cat->rows.size() - 1)
|
||||
{
|
||||
int nextgroupindex = group_index+1;
|
||||
while (nextgroupindex < m_groups.size())
|
||||
{
|
||||
case MoveDown: {
|
||||
if (row == cat->rows.size() - 1) {
|
||||
int nextgroupindex = group_index + 1;
|
||||
while (nextgroupindex < m_groups.size()) {
|
||||
auto nextgroup = m_groups[nextgroupindex];
|
||||
if(nextgroup->collapsed)
|
||||
{
|
||||
if (nextgroup->collapsed) {
|
||||
nextgroupindex++;
|
||||
continue;
|
||||
}
|
||||
int newRowSize = nextgroup->rows[0].size();
|
||||
int newColumn = m_currentCursorColumn;
|
||||
if (m_currentCursorColumn >= newRowSize)
|
||||
{
|
||||
if (m_currentCursorColumn >= newRowSize) {
|
||||
newColumn = newRowSize - 1;
|
||||
}
|
||||
return nextgroup->rows[0][newColumn];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
int newRow = row + 1;
|
||||
int newRowSize = cat->rows[newRow].size();
|
||||
int newColumn = m_currentCursorColumn;
|
||||
if (m_currentCursorColumn >= newRowSize)
|
||||
{
|
||||
if (m_currentCursorColumn >= newRowSize) {
|
||||
newColumn = newRowSize - 1;
|
||||
}
|
||||
return cat->rows[newRow][newColumn];
|
||||
}
|
||||
return current;
|
||||
}
|
||||
case MoveLeft:
|
||||
{
|
||||
if(column > 0)
|
||||
{
|
||||
case MoveLeft: {
|
||||
if (column > 0) {
|
||||
m_currentCursorColumn = column - 1;
|
||||
return cat->rows[row][column - 1];
|
||||
}
|
||||
// TODO: moving to previous line
|
||||
return current;
|
||||
}
|
||||
case MoveRight:
|
||||
{
|
||||
if(column < cat->rows[row].size() - 1)
|
||||
{
|
||||
case MoveRight: {
|
||||
if (column < cat->rows[row].size() - 1) {
|
||||
m_currentCursorColumn = column + 1;
|
||||
return cat->rows[row][column + 1];
|
||||
}
|
||||
// TODO: moving to next line
|
||||
return current;
|
||||
}
|
||||
case MoveHome:
|
||||
{
|
||||
case MoveHome: {
|
||||
m_currentCursorColumn = 0;
|
||||
return cat->rows[row][0];
|
||||
}
|
||||
case MoveEnd:
|
||||
{
|
||||
case MoveEnd: {
|
||||
auto last = cat->rows[row].size() - 1;
|
||||
m_currentCursorColumn = last;
|
||||
return cat->rows[row][last];
|
||||
@@ -1039,14 +922,13 @@ void InstanceView::scrollContentsBy(int dx, int dy)
|
||||
viewport()->scroll(dx, dy);
|
||||
}
|
||||
|
||||
void InstanceView::scrollTo(const QModelIndex &index, ScrollHint hint)
|
||||
void InstanceView::scrollTo(const QModelIndex& index, ScrollHint hint)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
const QRect rect = visualRect(index);
|
||||
if (hint == EnsureVisible && viewport()->rect().contains(rect))
|
||||
{
|
||||
if (hint == EnsureVisible && viewport()->rect().contains(rect)) {
|
||||
viewport()->update(rect);
|
||||
return;
|
||||
}
|
||||
@@ -1054,7 +936,7 @@ void InstanceView::scrollTo(const QModelIndex &index, ScrollHint hint)
|
||||
verticalScrollBar()->setValue(verticalScrollToValue(index, rect, hint));
|
||||
}
|
||||
|
||||
int InstanceView::verticalScrollToValue(const QModelIndex &index, const QRect &rect, QListView::ScrollHint hint) const
|
||||
int InstanceView::verticalScrollToValue(const QModelIndex& index, const QRect& rect, QListView::ScrollHint hint) const
|
||||
{
|
||||
const QRect area = viewport()->rect();
|
||||
const bool above = (hint == QListView::EnsureVisible && rect.top() < area.top());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@@ -35,95 +35,86 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QListView>
|
||||
#include <QLineEdit>
|
||||
#include <QScrollBar>
|
||||
#include <QCache>
|
||||
#include "VisualGroup.h"
|
||||
#include <QLineEdit>
|
||||
#include <QListView>
|
||||
#include <QScrollBar>
|
||||
#include <functional>
|
||||
#include "VisualGroup.h"
|
||||
|
||||
struct InstanceViewRoles
|
||||
{
|
||||
enum
|
||||
{
|
||||
GroupRole = Qt::UserRole,
|
||||
ProgressValueRole,
|
||||
ProgressMaximumRole
|
||||
};
|
||||
struct InstanceViewRoles {
|
||||
enum { GroupRole = Qt::UserRole, ProgressValueRole, ProgressMaximumRole };
|
||||
};
|
||||
|
||||
class InstanceView : public QAbstractItemView
|
||||
{
|
||||
class InstanceView : public QAbstractItemView {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InstanceView(QWidget *parent = 0);
|
||||
public:
|
||||
InstanceView(QWidget* parent = 0);
|
||||
~InstanceView();
|
||||
|
||||
void setModel(QAbstractItemModel *model) override;
|
||||
void setModel(QAbstractItemModel* model) override;
|
||||
|
||||
using visibilityFunction = std::function<bool(const QString &)>;
|
||||
void setSourceOfGroupCollapseStatus(visibilityFunction f) {
|
||||
fVisibility = f;
|
||||
}
|
||||
using visibilityFunction = std::function<bool(const QString&)>;
|
||||
void setSourceOfGroupCollapseStatus(visibilityFunction f) { fVisibility = f; }
|
||||
|
||||
/// return geometry rectangle occupied by the specified model item
|
||||
QRect geometryRect(const QModelIndex &index) const;
|
||||
QRect geometryRect(const QModelIndex& index) const;
|
||||
/// return visual rectangle occupied by the specified model item
|
||||
virtual QRect visualRect(const QModelIndex &index) const override;
|
||||
virtual QRect visualRect(const QModelIndex& index) const override;
|
||||
/// get the model index at the specified visual point
|
||||
virtual QModelIndex indexAt(const QPoint &point) const override;
|
||||
QString groupNameAt(const QPoint &point);
|
||||
void setSelection(const QRect &rect, const QItemSelectionModel::SelectionFlags commands) override;
|
||||
virtual QModelIndex indexAt(const QPoint& point) const override;
|
||||
QString groupNameAt(const QPoint& point);
|
||||
void setSelection(const QRect& rect, const QItemSelectionModel::SelectionFlags commands) override;
|
||||
|
||||
virtual int horizontalOffset() const override;
|
||||
virtual int verticalOffset() const override;
|
||||
virtual void scrollContentsBy(int dx, int dy) override;
|
||||
virtual void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override;
|
||||
virtual void scrollTo(const QModelIndex& index, ScrollHint hint = EnsureVisible) override;
|
||||
|
||||
virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override;
|
||||
|
||||
virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override;
|
||||
virtual QRegion visualRegionForSelection(const QItemSelection& selection) const override;
|
||||
|
||||
int spacing() const { return m_spacing; };
|
||||
void setPaintCat(bool visible);
|
||||
|
||||
public slots:
|
||||
public slots:
|
||||
virtual void updateGeometries() override;
|
||||
|
||||
protected slots:
|
||||
virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) override;
|
||||
virtual void rowsInserted(const QModelIndex &parent, int start, int end) override;
|
||||
virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override;
|
||||
protected slots:
|
||||
virtual void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles) override;
|
||||
virtual void rowsInserted(const QModelIndex& parent, int start, int end) override;
|
||||
virtual void rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) override;
|
||||
void modelReset();
|
||||
void rowsRemoved();
|
||||
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) override;
|
||||
void currentChanged(const QModelIndex& current, const QModelIndex& previous) override;
|
||||
|
||||
signals:
|
||||
signals:
|
||||
void droppedURLs(QList<QUrl> urls);
|
||||
void groupStateChanged(QString group, bool collapsed);
|
||||
|
||||
protected:
|
||||
bool isIndexHidden(const QModelIndex &index) const override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
protected:
|
||||
bool isIndexHidden(const QModelIndex& index) const override;
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent* event) override;
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||
void dropEvent(QDropEvent *event) override;
|
||||
void dragEnterEvent(QDragEnterEvent* event) override;
|
||||
void dragMoveEvent(QDragMoveEvent* event) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent* event) override;
|
||||
void dropEvent(QDropEvent* event) override;
|
||||
|
||||
void startDrag(Qt::DropActions supportedActions) override;
|
||||
|
||||
void updateScrollbar();
|
||||
|
||||
private:
|
||||
private:
|
||||
friend struct VisualGroup;
|
||||
QList<VisualGroup *> m_groups;
|
||||
QList<VisualGroup*> m_groups;
|
||||
|
||||
visibilityFunction fVisibility;
|
||||
|
||||
@@ -135,7 +126,7 @@ private:
|
||||
int m_spacing = 5;
|
||||
int m_itemWidth = 100;
|
||||
int m_currentItemsPerRow = -1;
|
||||
int m_currentCursorColumn= -1;
|
||||
int m_currentCursorColumn = -1;
|
||||
mutable QCache<int, QRect> geometryCache;
|
||||
bool m_catVisible = false;
|
||||
QPixmap m_catPixmap;
|
||||
@@ -144,30 +135,27 @@ private:
|
||||
QPoint m_pressedPosition;
|
||||
QPersistentModelIndex m_pressedIndex;
|
||||
bool m_pressedAlreadySelected;
|
||||
VisualGroup *m_pressedCategory;
|
||||
VisualGroup* m_pressedCategory;
|
||||
QItemSelectionModel::SelectionFlag m_ctrlDragSelectionFlag;
|
||||
QPoint m_lastDragPosition;
|
||||
|
||||
VisualGroup *category(const QModelIndex &index) const;
|
||||
VisualGroup *category(const QString &cat) const;
|
||||
VisualGroup *categoryAt(const QPoint &pos, VisualGroup::HitResults & result) const;
|
||||
VisualGroup* category(const QModelIndex& index) const;
|
||||
VisualGroup* category(const QString& cat) const;
|
||||
VisualGroup* categoryAt(const QPoint& pos, VisualGroup::HitResults& result) const;
|
||||
|
||||
int itemsPerRow() const
|
||||
{
|
||||
return m_currentItemsPerRow;
|
||||
};
|
||||
int itemsPerRow() const { return m_currentItemsPerRow; };
|
||||
int contentWidth() const;
|
||||
|
||||
private: /* methods */
|
||||
private: /* methods */
|
||||
int itemWidth() const;
|
||||
int calculateItemsPerRow() const;
|
||||
int verticalScrollToValue(const QModelIndex &index, const QRect &rect, QListView::ScrollHint hint) const;
|
||||
QPixmap renderToPixmap(const QModelIndexList &indices, QRect *r) const;
|
||||
QList<std::pair<QRect, QModelIndex>> draggablePaintPairs(const QModelIndexList &indices, QRect *r) const;
|
||||
int verticalScrollToValue(const QModelIndex& index, const QRect& rect, QListView::ScrollHint hint) const;
|
||||
QPixmap renderToPixmap(const QModelIndexList& indices, QRect* r) const;
|
||||
QList<std::pair<QRect, QModelIndex>> draggablePaintPairs(const QModelIndexList& indices, QRect* r) const;
|
||||
|
||||
bool isDragEventAccepted(QDropEvent *event);
|
||||
bool isDragEventAccepted(QDropEvent* event);
|
||||
|
||||
std::pair<VisualGroup *, VisualGroup::HitResults> rowDropPos(const QPoint &pos);
|
||||
std::pair<VisualGroup*, VisualGroup::HitResults> rowDropPos(const QPoint& pos);
|
||||
|
||||
QPoint offset() const;
|
||||
};
|
||||
|
||||
@@ -35,56 +35,48 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QRect>
|
||||
#include <QVector>
|
||||
#include <QString>
|
||||
#include <QStyleOption>
|
||||
#include <QVector>
|
||||
|
||||
class InstanceView;
|
||||
class QPainter;
|
||||
class QModelIndex;
|
||||
|
||||
struct VisualRow
|
||||
{
|
||||
struct VisualRow {
|
||||
QList<QModelIndex> items;
|
||||
int height = 0;
|
||||
int top = 0;
|
||||
inline int size() const
|
||||
{
|
||||
return items.size();
|
||||
}
|
||||
inline QModelIndex &operator[](int i)
|
||||
{
|
||||
return items[i];
|
||||
}
|
||||
inline int size() const { return items.size(); }
|
||||
inline QModelIndex& operator[](int i) { return items[i]; }
|
||||
};
|
||||
|
||||
struct VisualGroup
|
||||
{
|
||||
/* constructors */
|
||||
VisualGroup(QString text, InstanceView *view);
|
||||
explicit VisualGroup(const VisualGroup *other);
|
||||
struct VisualGroup {
|
||||
/* constructors */
|
||||
VisualGroup(QString text, InstanceView* view);
|
||||
explicit VisualGroup(const VisualGroup* other);
|
||||
|
||||
/* data */
|
||||
InstanceView *view = nullptr;
|
||||
/* data */
|
||||
InstanceView* view = nullptr;
|
||||
QString text;
|
||||
bool collapsed = false;
|
||||
QVector<VisualRow> rows;
|
||||
int firstItemIndex = 0;
|
||||
int m_verticalPosition = 0;
|
||||
|
||||
/* logic */
|
||||
/* logic */
|
||||
/// update the internal list of items and flow them into the rows.
|
||||
void update();
|
||||
|
||||
/// draw the header at y-position.
|
||||
void drawHeader(QPainter *painter, const QStyleOptionViewItem &option) const;
|
||||
void drawHeader(QPainter* painter, const QStyleOptionViewItem& option) const;
|
||||
|
||||
/// height of the group, in total. includes a small bit of padding.
|
||||
int totalHeight() const;
|
||||
|
||||
/// height of the group header, in pixels
|
||||
static int headerHeight() ;
|
||||
static int headerHeight();
|
||||
|
||||
/// height of the group content, in pixels
|
||||
int contentHeight() const;
|
||||
@@ -99,26 +91,19 @@ struct VisualGroup
|
||||
int verticalPosition() const;
|
||||
|
||||
/// relative geometry - top of the row of the given item
|
||||
int rowTopOf(const QModelIndex &index) const;
|
||||
int rowTopOf(const QModelIndex& index) const;
|
||||
|
||||
/// height of the row of the given item
|
||||
int rowHeightOf(const QModelIndex &index) const;
|
||||
int rowHeightOf(const QModelIndex& index) const;
|
||||
|
||||
/// x/y position of the given item inside the group (in items!)
|
||||
QPair<int, int> positionOf(const QModelIndex &index) const;
|
||||
QPair<int, int> positionOf(const QModelIndex& index) const;
|
||||
|
||||
enum HitResult
|
||||
{
|
||||
NoHit = 0x0,
|
||||
TextHit = 0x1,
|
||||
CheckboxHit = 0x2,
|
||||
HeaderHit = 0x4,
|
||||
BodyHit = 0x8
|
||||
};
|
||||
enum HitResult { NoHit = 0x0, TextHit = 0x1, CheckboxHit = 0x2, HeaderHit = 0x4, BodyHit = 0x8 };
|
||||
Q_DECLARE_FLAGS(HitResults, HitResult)
|
||||
|
||||
/// shoot! BANG! what did we hit?
|
||||
HitResults hitScan (const QPoint &pos) const;
|
||||
HitResults hitScan(const QPoint& pos) const;
|
||||
|
||||
QList<QModelIndex> items() const;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user