GH-4164 Assign instances to groups using drag & drop

This commit is contained in:
Petr Mrázek 2021-10-25 23:51:42 +02:00
parent 85ecbad467
commit ae4939e0d2
21 changed files with 345 additions and 334 deletions

View File

@ -573,8 +573,6 @@ SET(LAUNCHER_SOURCES
GuiUtil.cpp
ColumnResizer.h
ColumnResizer.cpp
InstanceProxyModel.h
InstanceProxyModel.cpp
VersionProxyModel.h
VersionProxyModel.cpp
ColorCache.h
@ -802,17 +800,17 @@ SET(LAUNCHER_SOURCES
widgets/WideBar.cpp
# GUI - instance group view
groupview/GroupedProxyModel.cpp
groupview/GroupedProxyModel.h
groupview/AccessibleGroupView.cpp
groupview/AccessibleGroupView.h
groupview/AccessibleGroupView_p.h
groupview/GroupView.cpp
groupview/GroupView.h
groupview/InstanceDelegate.cpp
groupview/InstanceDelegate.h
groupview/VisualGroup.cpp
groupview/VisualGroup.h
instanceview/InstanceProxyModel.cpp
instanceview/InstanceProxyModel.h
instanceview/AccessibleInstanceView.cpp
instanceview/AccessibleInstanceView.h
instanceview/AccessibleInstanceView_p.h
instanceview/InstanceView.cpp
instanceview/InstanceView.h
instanceview/InstanceDelegate.cpp
instanceview/InstanceDelegate.h
instanceview/VisualGroup.cpp
instanceview/VisualGroup.h
)
######## UIs ########

View File

@ -26,6 +26,7 @@
#include <QUuid>
#include <QJsonArray>
#include <QJsonDocument>
#include <QMimeData>
#include "InstanceList.h"
#include "BaseInstance.h"
@ -63,6 +64,50 @@ InstanceList::~InstanceList()
{
}
Qt::DropActions InstanceList::supportedDragActions() const
{
return Qt::MoveAction;
}
Qt::DropActions InstanceList::supportedDropActions() const
{
return Qt::MoveAction;
}
bool InstanceList::canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const
{
if(data && data->hasFormat("application/x-instanceid")) {
return true;
}
return false;
}
bool InstanceList::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
{
if(data && data->hasFormat("application/x-instanceid")) {
return true;
}
return false;
}
QStringList InstanceList::mimeTypes() const
{
auto types = QAbstractListModel::mimeTypes();
types.push_back("application/x-instanceid");
return types;
}
QMimeData * InstanceList::mimeData(const QModelIndexList& indexes) const
{
auto mimeData = QAbstractListModel::mimeData(indexes);
if(indexes.size() == 1) {
auto instanceId = data(indexes[0], InstanceIDRole).toString();
mimeData->setData("application/x-instanceid", instanceId.toUtf8());
}
return mimeData;
}
int InstanceList::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
@ -112,7 +157,7 @@ QVariant InstanceList::data(const QModelIndex &index, int role) const
{
return pdata->iconKey();
}
// HACK: see GroupView.h in gui!
// HACK: see InstanceView.h in gui!
case GroupRole:
{
return getInstanceGroup(pdata->id());

View File

@ -93,7 +93,6 @@ public:
InstListError loadList();
void saveNow();
InstancePtr getInstanceById(QString id) const;
QModelIndex getInstanceIndexById(const QString &id) const;
QStringList getGroups();
@ -128,6 +127,17 @@ public:
int getTotalPlayTime();
Qt::DropActions supportedDragActions() const override;
Qt::DropActions supportedDropActions() const override;
bool canDropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) const override;
bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) override;
QStringList mimeTypes() const override;
QMimeData *mimeData(const QModelIndexList &indexes) const override;
signals:
void dataIsInvalid();
void instancesChanged();

View File

@ -1,38 +0,0 @@
#include "InstanceProxyModel.h"
#include "Launcher.h"
#include <BaseInstance.h>
#include <icons/IconList.h>
InstanceProxyModel::InstanceProxyModel(QObject *parent) : GroupedProxyModel(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 data = QSortFilterProxyModel::data(index, role);
if(role == Qt::DecorationRole)
{
return QVariant(LAUNCHER->icons()->getIcon(data.toString()));
}
return data;
}
bool InstanceProxyModel::subSortLessThan(const QModelIndex &left,
const QModelIndex &right) const
{
BaseInstance *pdataLeft = static_cast<BaseInstance *>(left.internalPointer());
BaseInstance *pdataRight = static_cast<BaseInstance *>(right.internalPointer());
QString sortMode = LAUNCHER->settings()->get("InstSortMode").toString();
if (sortMode == "LastLaunch")
{
return pdataLeft->lastLaunch() > pdataRight->lastLaunch();
}
else
{
return m_naturalSort.compare(pdataLeft->name(), pdataRight->name()) < 0;
}
}

View File

@ -1,19 +0,0 @@
#pragma once
#include "groupview/GroupedProxyModel.h"
#include <QCollator>
/**
* A proxy model that is responsible for sorting instances into groups
*/
class InstanceProxyModel : public GroupedProxyModel
{
public:
explicit InstanceProxyModel(QObject *parent = 0);
QVariant data(const QModelIndex & index, int role) const override;
protected:
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const override;
private:
QCollator m_naturalSort;
};

View File

@ -3,7 +3,7 @@
#include "MainWindow.h"
#include "InstanceWindow.h"
#include "groupview/AccessibleGroupView.h"
#include "instanceview/AccessibleInstanceView.h"
#include <QAccessible>
#include "pages/BasePageProvider.h"

View File

@ -67,11 +67,11 @@
#include <DesktopServices.h>
#include "InstanceWindow.h"
#include "InstancePageProvider.h"
#include "InstanceProxyModel.h"
#include "instanceview/InstanceProxyModel.h"
#include "JavaCommon.h"
#include "LaunchController.h"
#include "groupview/GroupView.h"
#include "groupview/InstanceDelegate.h"
#include "instanceview/InstanceView.h"
#include "instanceview/InstanceDelegate.h"
#include "widgets/LabeledToolButton.h"
#include "dialogs/NewInstanceDialog.h"
#include "dialogs/ProgressDialog.h"
@ -695,7 +695,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
// Create the instance list widget
{
view = new GroupView(ui->centralWidget);
view = new InstanceView(ui->centralWidget);
view->setSelectionMode(QAbstractItemView::SingleSelection);
// FIXME: leaks ListViewDelegate
@ -707,7 +707,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
view->installEventFilter(this);
view->setContextMenuPolicy(Qt::CustomContextMenu);
connect(view, &QWidget::customContextMenuRequested, this, &MainWindow::showInstanceContextMenu);
connect(view, &GroupView::droppedURLs, this, &MainWindow::droppedURLs, Qt::QueuedConnection);
connect(view, &InstanceView::droppedURLs, this, &MainWindow::droppedURLs, Qt::QueuedConnection);
proxymodel = new InstanceProxyModel(this);
proxymodel->setSourceModel(LAUNCHER->instances().get());
@ -718,7 +718,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
view->setSourceOfGroupCollapseStatus([](const QString & groupName)->bool {
return LAUNCHER->instances()->isGroupCollapsed(groupName);
});
connect(view, &GroupView::groupStateChanged, LAUNCHER->instances().get(), &InstanceList::on_GroupStateChanged);
connect(view, &InstanceView::groupStateChanged, LAUNCHER->instances().get(), &InstanceList::on_GroupStateChanged);
ui->horizontalLayout->addWidget(view);
}
// The cat background
@ -730,7 +730,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new MainWindow
setCatBackground(cat_enable);
}
// start instance when double-clicked
connect(view, &GroupView::activated, this, &MainWindow::instanceActivated);
connect(view, &InstanceView::activated, this, &MainWindow::instanceActivated);
// track the selection -- update the instance toolbar
connect(view->selectionModel(), &QItemSelectionModel::currentChanged, this, &MainWindow::instanceChanged);
@ -1313,7 +1313,7 @@ void MainWindow::setCatBackground(bool enabled)
QDateTime xmas(QDate(now.date().year(), 12, 25), QTime(0, 0));
QString cat = (non_stupid_abs(now.daysTo(xmas)) <= 4) ? "catmas" : "kitteh";
view->setStyleSheet(QString(R"(
GroupView
InstanceView
{
background-image: url(:/backgrounds/%1);
background-attachment: fixed;

View File

@ -35,7 +35,7 @@ class LabeledToolButton;
class QLabel;
class MinecraftLauncher;
class BaseProfilerFactory;
class GroupView;
class InstanceView;
class KonamiCode;
class InstanceTask;
@ -201,7 +201,7 @@ private:
std::unique_ptr<Ui> ui;
// these are managed by Qt's memory management model!
GroupView *view = nullptr;
InstanceView *view = nullptr;
InstanceProxyModel *proxymodel = nullptr;
QToolButton *newsLabel = nullptr;
QLabel *m_statusLeft = nullptr;

View File

@ -22,7 +22,7 @@
#include "IconPickerDialog.h"
#include "ui_IconPickerDialog.h"
#include "groupview/InstanceDelegate.h"
#include "instanceview/InstanceDelegate.h"
#include "icons/IconList.h"
#include "icons/IconUtils.h"
@ -126,8 +126,9 @@ void IconPickerDialog::selectionChanged(QItemSelection selected, QItemSelection
return;
QString key = selected.first().indexes().first().data(Qt::UserRole).toString();
if (!key.isEmpty())
if (!key.isEmpty()) {
selectedIconKey = key;
}
}
int IconPickerDialog::execWithSelection(QString selection)
@ -141,8 +142,7 @@ int IconPickerDialog::execWithSelection(QString selection)
contentsWidget->selectionModel()->select(
model_index, QItemSelectionModel::Current | QItemSelectionModel::Select);
QMetaObject::invokeMethod(this, "delayed_scroll", Qt::QueuedConnection,
Q_ARG(QModelIndex, model_index));
QMetaObject::invokeMethod(this, "delayed_scroll", Qt::QueuedConnection, Q_ARG(QModelIndex, model_index));
return QDialog::exec();
}

View File

@ -1,48 +0,0 @@
/* Copyright 2013-2021 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "GroupedProxyModel.h"
#include "GroupView.h"
#include <QDebug>
GroupedProxyModel::GroupedProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
{
}
bool GroupedProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
const QString leftCategory = left.data(GroupViewRoles::GroupRole).toString();
const QString rightCategory = right.data(GroupViewRoles::GroupRole).toString();
if (leftCategory == rightCategory)
{
return subSortLessThan(left, right);
}
else
{
// FIXME: real group sorting happens in GroupView::updateGeometries(), see LocaleString
auto result = leftCategory.localeAwareCompare(rightCategory);
if(result == 0)
{
return subSortLessThan(left, right);
}
return result < 0;
}
}
bool GroupedProxyModel::subSortLessThan(const QModelIndex &left, const QModelIndex &right) const
{
return left.row() < right.row();
}

View File

@ -1,6 +1,6 @@
#include "GroupView.h"
#include "AccessibleGroupView.h"
#include "AccessibleGroupView_p.h"
#include "InstanceView.h"
#include "AccessibleInstanceView.h"
#include "AccessibleInstanceView_p.h"
#include <qvariant.h>
#include <qaccessible.h>
@ -16,44 +16,44 @@ QAccessibleInterface *groupViewAccessibleFactory(const QString &classname, QObje
QWidget *widget = static_cast<QWidget*>(object);
if (classname == QLatin1String("GroupView")) {
iface = new AccessibleGroupView((GroupView *)widget);
if (classname == QLatin1String("InstanceView")) {
iface = new AccessibleInstanceView((InstanceView *)widget);
}
return iface;
}
QAbstractItemView *AccessibleGroupView::view() const
QAbstractItemView *AccessibleInstanceView::view() const
{
return qobject_cast<QAbstractItemView*>(object());
}
int AccessibleGroupView::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();
}
AccessibleGroupView::AccessibleGroupView(QWidget *w)
AccessibleInstanceView::AccessibleInstanceView(QWidget *w)
: QAccessibleObject(w)
{
Q_ASSERT(view());
}
bool AccessibleGroupView::isValid() const
bool AccessibleInstanceView::isValid() const
{
return view();
}
AccessibleGroupView::~AccessibleGroupView()
AccessibleInstanceView::~AccessibleInstanceView()
{
for (QAccessible::Id id : childToId) {
QAccessible::deleteAccessibleInterface(id);
}
}
QAccessibleInterface *AccessibleGroupView::cellAt(int row, int column) const
QAccessibleInterface *AccessibleInstanceView::cellAt(int row, int column) const
{
if (!view()->model()) {
return 0;
@ -61,19 +61,19 @@ QAccessibleInterface *AccessibleGroupView::cellAt(int row, int column) const
QModelIndex index = view()->model()->index(row, column, view()->rootIndex());
if (Q_UNLIKELY(!index.isValid())) {
qWarning() << "AccessibleGroupView::cellAt: invalid index: " << index << " for " << view();
qWarning() << "AccessibleInstanceView::cellAt: invalid index: " << index << " for " << view();
return 0;
}
return child(logicalIndex(index));
}
QAccessibleInterface *AccessibleGroupView::caption() const
QAccessibleInterface *AccessibleInstanceView::caption() const
{
return 0;
}
QString AccessibleGroupView::columnDescription(int column) const
QString AccessibleInstanceView::columnDescription(int column) const
{
if (!view()->model())
return QString();
@ -81,49 +81,49 @@ QString AccessibleGroupView::columnDescription(int column) const
return view()->model()->headerData(column, Qt::Horizontal).toString();
}
int AccessibleGroupView::columnCount() const
int AccessibleInstanceView::columnCount() const
{
if (!view()->model())
return 0;
return 1;
}
int AccessibleGroupView::rowCount() const
int AccessibleInstanceView::rowCount() const
{
if (!view()->model())
return 0;
return view()->model()->rowCount();
}
int AccessibleGroupView::selectedCellCount() const
int AccessibleInstanceView::selectedCellCount() const
{
if (!view()->selectionModel())
return 0;
return view()->selectionModel()->selectedIndexes().count();
}
int AccessibleGroupView::selectedColumnCount() const
int AccessibleInstanceView::selectedColumnCount() const
{
if (!view()->selectionModel())
return 0;
return view()->selectionModel()->selectedColumns().count();
}
int AccessibleGroupView::selectedRowCount() const
int AccessibleInstanceView::selectedRowCount() const
{
if (!view()->selectionModel())
return 0;
return view()->selectionModel()->selectedRows().count();
}
QString AccessibleGroupView::rowDescription(int row) const
QString AccessibleInstanceView::rowDescription(int row) const
{
if (!view()->model())
return QString();
return view()->model()->headerData(row, Qt::Vertical).toString();
}
QList<QAccessibleInterface *> AccessibleGroupView::selectedCells() const
QList<QAccessibleInterface *> AccessibleInstanceView::selectedCells() const
{
QList<QAccessibleInterface*> cells;
if (!view()->selectionModel())
@ -135,7 +135,7 @@ QList<QAccessibleInterface *> AccessibleGroupView::selectedCells() const
return cells;
}
QList<int> AccessibleGroupView::selectedColumns() const
QList<int> AccessibleInstanceView::selectedColumns() const
{
if (!view()->selectionModel()) {
return QList<int>();
@ -152,7 +152,7 @@ QList<int> AccessibleGroupView::selectedColumns() const
return columns;
}
QList<int> AccessibleGroupView::selectedRows() const
QList<int> AccessibleInstanceView::selectedRows() const
{
if (!view()->selectionModel()) {
return QList<int>();
@ -170,12 +170,12 @@ QList<int> AccessibleGroupView::selectedRows() const
return rows;
}
QAccessibleInterface *AccessibleGroupView::summary() const
QAccessibleInterface *AccessibleInstanceView::summary() const
{
return 0;
}
bool AccessibleGroupView::isColumnSelected(int column) const
bool AccessibleInstanceView::isColumnSelected(int column) const
{
if (!view()->selectionModel()) {
return false;
@ -184,7 +184,7 @@ bool AccessibleGroupView::isColumnSelected(int column) const
return view()->selectionModel()->isColumnSelected(column, QModelIndex());
}
bool AccessibleGroupView::isRowSelected(int row) const
bool AccessibleInstanceView::isRowSelected(int row) const
{
if (!view()->selectionModel()) {
return false;
@ -193,7 +193,7 @@ bool AccessibleGroupView::isRowSelected(int row) const
return view()->selectionModel()->isRowSelected(row, QModelIndex());
}
bool AccessibleGroupView::selectRow(int row)
bool AccessibleInstanceView::selectRow(int row)
{
if (!view()->model() || !view()->selectionModel()) {
return false;
@ -229,7 +229,7 @@ bool AccessibleGroupView::selectRow(int row)
return true;
}
bool AccessibleGroupView::selectColumn(int column)
bool AccessibleInstanceView::selectColumn(int column)
{
if (!view()->model() || !view()->selectionModel()) {
return false;
@ -265,7 +265,7 @@ bool AccessibleGroupView::selectColumn(int column)
return true;
}
bool AccessibleGroupView::unselectRow(int row)
bool AccessibleInstanceView::unselectRow(int row)
{
if (!view()->model() || !view()->selectionModel()) {
return false;
@ -308,7 +308,7 @@ bool AccessibleGroupView::unselectRow(int row)
return true;
}
bool AccessibleGroupView::unselectColumn(int column)
bool AccessibleInstanceView::unselectColumn(int column)
{
auto model = view()->model();
if (!model || !view()->selectionModel()) {
@ -350,17 +350,17 @@ bool AccessibleGroupView::unselectColumn(int column)
return true;
}
QAccessible::Role AccessibleGroupView::role() const
QAccessible::Role AccessibleInstanceView::role() const
{
return QAccessible::List;
}
QAccessible::State AccessibleGroupView::state() const
QAccessible::State AccessibleInstanceView::state() const
{
return QAccessible::State();
}
QAccessibleInterface *AccessibleGroupView::childAt(int x, int y) const
QAccessibleInterface *AccessibleInstanceView::childAt(int x, int y) const
{
QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0));
QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset);
@ -373,7 +373,7 @@ QAccessibleInterface *AccessibleGroupView::childAt(int x, int y) const
return 0;
}
int AccessibleGroupView::childCount() const
int AccessibleInstanceView::childCount() const
{
if (!view()->model()) {
return 0;
@ -381,7 +381,7 @@ int AccessibleGroupView::childCount() const
return (view()->model()->rowCount()) * (view()->model()->columnCount());
}
int AccessibleGroupView::indexOfChild(const QAccessibleInterface *iface) const
int AccessibleInstanceView::indexOfChild(const QAccessibleInterface *iface) const
{
if (!view()->model())
return -1;
@ -391,25 +391,25 @@ int AccessibleGroupView::indexOfChild(const QAccessibleInterface *iface) const
Q_ASSERT(iface->role() != QAccessible::TreeItem); // should be handled by tree class
if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
const AccessibleGroupViewItem* cell = static_cast<const AccessibleGroupViewItem*>(iface);
const AccessibleInstanceViewItem* cell = static_cast<const AccessibleInstanceViewItem*>(iface);
return logicalIndex(cell->m_index);
} else if (iface->role() == QAccessible::Pane) {
return 0; // corner button
} else {
qWarning() << "AccessibleGroupView::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;
}
QString AccessibleGroupView::text(QAccessible::Text t) const
QString AccessibleInstanceView::text(QAccessible::Text t) const
{
if (t == QAccessible::Description)
return view()->accessibleDescription();
return view()->accessibleName();
}
QRect AccessibleGroupView::rect() const
QRect AccessibleInstanceView::rect() const
{
if (!view()->isVisible())
return QRect();
@ -417,7 +417,7 @@ QRect AccessibleGroupView::rect() const
return QRect(pos.x(), pos.y(), view()->width(), view()->height());
}
QAccessibleInterface *AccessibleGroupView::parent() const
QAccessibleInterface *AccessibleInstanceView::parent() const
{
if (view() && view()->parent()) {
if (qstrcmp("QComboBoxPrivateContainer", view()->parent()->metaObject()->className()) == 0) {
@ -428,7 +428,7 @@ QAccessibleInterface *AccessibleGroupView::parent() const
return 0;
}
QAccessibleInterface *AccessibleGroupView::child(int logicalIndex) const
QAccessibleInterface *AccessibleInstanceView::child(int logicalIndex) const
{
if (!view()->model())
return 0;
@ -446,24 +446,24 @@ QAccessibleInterface *AccessibleGroupView::child(int logicalIndex) const
QModelIndex index = view()->model()->index(row, column, view()->rootIndex());
if (Q_UNLIKELY(!index.isValid())) {
qWarning("AccessibleGroupView::child: Invalid index at: %d %d", row, column);
qWarning("AccessibleInstanceView::child: Invalid index at: %d %d", row, column);
return 0;
}
iface = new AccessibleGroupViewItem(view(), index);
iface = new AccessibleInstanceViewItem(view(), index);
QAccessible::registerAccessibleInterface(iface);
childToId.insert(logicalIndex, QAccessible::uniqueId(iface));
return iface;
}
void *AccessibleGroupView::interface_cast(QAccessible::InterfaceType t)
void *AccessibleInstanceView::interface_cast(QAccessible::InterfaceType t)
{
if (t == QAccessible::TableInterface)
return static_cast<QAccessibleTableInterface*>(this);
return 0;
}
void AccessibleGroupView::modelChange(QAccessibleTableModelChangeEvent *event)
void AccessibleInstanceView::modelChange(QAccessibleTableModelChangeEvent *event)
{
// if there is no cache yet, we don't update anything
if (childToId.isEmpty())
@ -511,7 +511,7 @@ void AccessibleGroupView::modelChange(QAccessibleTableModelChangeEvent *event)
Q_ASSERT(iface);
if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) {
Q_ASSERT(iface->tableCellInterface());
AccessibleGroupViewItem *cell = static_cast<AccessibleGroupViewItem*>(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,14 @@ void AccessibleGroupView::modelChange(QAccessibleTableModelChangeEvent *event)
// TABLE CELL
AccessibleGroupViewItem::AccessibleGroupViewItem(QAbstractItemView *view_, const QModelIndex &index_)
AccessibleInstanceViewItem::AccessibleInstanceViewItem(QAbstractItemView *view_, const QModelIndex &index_)
: view(view_), m_index(index_)
{
if (Q_UNLIKELY(!index_.isValid()))
qWarning() << "AccessibleGroupViewItem::AccessibleGroupViewItem with invalid index: " << index_;
qWarning() << "AccessibleInstanceViewItem::AccessibleInstanceViewItem with invalid index: " << index_;
}
void *AccessibleGroupViewItem::interface_cast(QAccessible::InterfaceType t)
void *AccessibleInstanceViewItem::interface_cast(QAccessible::InterfaceType t)
{
if (t == QAccessible::TableCellInterface)
return static_cast<QAccessibleTableCellInterface*>(this);
@ -548,20 +548,20 @@ void *AccessibleGroupViewItem::interface_cast(QAccessible::InterfaceType t)
return 0;
}
int AccessibleGroupViewItem::columnExtent() const { return 1; }
int AccessibleGroupViewItem::rowExtent() const { return 1; }
int AccessibleInstanceViewItem::columnExtent() const { return 1; }
int AccessibleInstanceViewItem::rowExtent() const { return 1; }
QList<QAccessibleInterface*> AccessibleGroupViewItem::rowHeaderCells() const
QList<QAccessibleInterface*> AccessibleInstanceViewItem::rowHeaderCells() const
{
return {};
}
QList<QAccessibleInterface*> AccessibleGroupViewItem::columnHeaderCells() const
QList<QAccessibleInterface*> AccessibleInstanceViewItem::columnHeaderCells() const
{
return {};
}
int AccessibleGroupViewItem::columnIndex() const
int AccessibleInstanceViewItem::columnIndex() const
{
if (!isValid()) {
return -1;
@ -570,7 +570,7 @@ int AccessibleGroupViewItem::columnIndex() const
return m_index.column();
}
int AccessibleGroupViewItem::rowIndex() const
int AccessibleInstanceViewItem::rowIndex() const
{
if (!isValid()) {
return -1;
@ -579,7 +579,7 @@ int AccessibleGroupViewItem::rowIndex() const
return m_index.row();
}
bool AccessibleGroupViewItem::isSelected() const
bool AccessibleInstanceViewItem::isSelected() const
{
if (!isValid()) {
return false;
@ -588,14 +588,14 @@ bool AccessibleGroupViewItem::isSelected() const
return view->selectionModel()->isSelected(m_index);
}
QStringList AccessibleGroupViewItem::actionNames() const
QStringList AccessibleInstanceViewItem::actionNames() const
{
QStringList names;
names << toggleAction();
return names;
}
void AccessibleGroupViewItem::doAction(const QString& actionName)
void AccessibleInstanceViewItem::doAction(const QString& actionName)
{
if (actionName == toggleAction()) {
if (isSelected()) {
@ -607,13 +607,13 @@ void AccessibleGroupViewItem::doAction(const QString& actionName)
}
}
QStringList AccessibleGroupViewItem::keyBindingsForAction(const QString &) const
QStringList AccessibleInstanceViewItem::keyBindingsForAction(const QString &) const
{
return QStringList();
}
void AccessibleGroupViewItem::selectCell()
void AccessibleInstanceViewItem::selectCell()
{
if (!isValid()) {
return;
@ -646,7 +646,7 @@ void AccessibleGroupViewItem::selectCell()
view->selectionModel()->select(m_index, QItemSelectionModel::Select);
}
void AccessibleGroupViewItem::unselectCell()
void AccessibleInstanceViewItem::unselectCell()
{
if (!isValid())
return;
@ -677,17 +677,17 @@ void AccessibleGroupViewItem::unselectCell()
view->selectionModel()->select(m_index, QItemSelectionModel::Deselect);
}
QAccessibleInterface *AccessibleGroupViewItem::table() const
QAccessibleInterface *AccessibleInstanceViewItem::table() const
{
return QAccessible::queryAccessibleInterface(view);
}
QAccessible::Role AccessibleGroupViewItem::role() const
QAccessible::Role AccessibleInstanceViewItem::role() const
{
return QAccessible::ListItem;
}
QAccessible::State AccessibleGroupViewItem::state() const
QAccessible::State AccessibleInstanceViewItem::state() const
{
QAccessible::State st;
if (!isValid())
@ -718,7 +718,7 @@ QAccessible::State AccessibleGroupViewItem::state() const
}
QRect AccessibleGroupViewItem::rect() const
QRect AccessibleInstanceViewItem::rect() const
{
QRect r;
if (!isValid())
@ -732,7 +732,7 @@ QRect AccessibleGroupViewItem::rect() const
return r;
}
QString AccessibleGroupViewItem::text(QAccessible::Text t) const
QString AccessibleInstanceViewItem::text(QAccessible::Text t) const
{
QString value;
if (!isValid())
@ -753,24 +753,24 @@ QString AccessibleGroupViewItem::text(QAccessible::Text t) const
return value;
}
void AccessibleGroupViewItem::setText(QAccessible::Text /*t*/, const QString &text)
void AccessibleInstanceViewItem::setText(QAccessible::Text /*t*/, const QString &text)
{
if (!isValid() || !(m_index.flags() & Qt::ItemIsEditable))
return;
view->model()->setData(m_index, text);
}
bool AccessibleGroupViewItem::isValid() const
bool AccessibleInstanceViewItem::isValid() const
{
return view && view->model() && m_index.isValid();
}
QAccessibleInterface *AccessibleGroupViewItem::parent() const
QAccessibleInterface *AccessibleInstanceViewItem::parent() const
{
return QAccessible::queryAccessibleInterface(view);
}
QAccessibleInterface *AccessibleGroupViewItem::child(int) const
QAccessibleInterface *AccessibleInstanceViewItem::child(int) const
{
return 0;
}

View File

@ -5,16 +5,16 @@
#include <QAccessibleWidget>
#include <QAbstractItemView>
#ifndef QT_NO_ACCESSIBILITY
#include "GroupView.h"
#include "InstanceView.h"
// #include <QHeaderView>
class QAccessibleTableCell;
class QAccessibleTableHeaderCell;
class AccessibleGroupView :public QAccessibleTableInterface, public QAccessibleObject
class AccessibleInstanceView :public QAccessibleTableInterface, public QAccessibleObject
{
public:
explicit AccessibleGroupView(QWidget *w);
explicit AccessibleInstanceView(QWidget *w);
bool isValid() const override;
QAccessible::Role role() const override;
@ -63,16 +63,16 @@ protected:
typedef QHash<int, QAccessible::Id> ChildCache;
mutable ChildCache childToId;
virtual ~AccessibleGroupView();
virtual ~AccessibleInstanceView();
private:
inline int logicalIndex(const QModelIndex &index) const;
};
class AccessibleGroupViewItem: public QAccessibleInterface, public QAccessibleTableCellInterface, public QAccessibleActionInterface
class AccessibleInstanceViewItem: public QAccessibleInterface, public QAccessibleTableCellInterface, public QAccessibleActionInterface
{
public:
AccessibleGroupViewItem(QAbstractItemView *view, const QModelIndex &m_index);
AccessibleInstanceViewItem(QAbstractItemView *view, const QModelIndex &m_index);
void *interface_cast(QAccessible::InterfaceType t) override;
QObject *object() const override { return nullptr; }
@ -113,6 +113,6 @@ private:
void selectCell();
void unselectCell();
friend class AccessibleGroupView;
friend class AccessibleInstanceView;
};
#endif /* !QT_NO_ACCESSIBILITY */

View File

@ -21,7 +21,7 @@
#include <QtMath>
#include <QDebug>
#include "GroupView.h"
#include "InstanceView.h"
#include "BaseInstance.h"
#include "InstanceList.h"
#include <xdgicon.h>
@ -321,8 +321,8 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
drawBadges(painter, opt, instance, mode, state);
}
drawProgressOverlay(painter, opt, index.data(GroupViewRoles::ProgressValueRole).toInt(),
index.data(GroupViewRoles::ProgressMaximumRole).toInt());
drawProgressOverlay(painter, opt, index.data(InstanceViewRoles::ProgressValueRole).toInt(),
index.data(InstanceViewRoles::ProgressMaximumRole).toInt());
painter->restore();
}

View File

@ -0,0 +1,71 @@
/* Copyright 2013-2021 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "InstanceProxyModel.h"
#include "InstanceView.h"
#include "Launcher.h"
#include <BaseInstance.h>
#include <icons/IconList.h>
#include <QDebug>
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 data = QSortFilterProxyModel::data(index, role);
if(role == Qt::DecorationRole)
{
return QVariant(LAUNCHER->icons()->getIcon(data.toString()));
}
return data;
}
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 {
// FIXME: real group sorting happens in InstanceView::updateGeometries(), see LocaleString
auto result = leftCategory.localeAwareCompare(rightCategory);
if(result == 0) {
return subSortLessThan(left, right);
}
return result < 0;
}
}
bool InstanceProxyModel::subSortLessThan(const QModelIndex &left, const QModelIndex &right) const
{
BaseInstance *pdataLeft = static_cast<BaseInstance *>(left.internalPointer());
BaseInstance *pdataRight = static_cast<BaseInstance *>(right.internalPointer());
QString sortMode = LAUNCHER->settings()->get("InstSortMode").toString();
if (sortMode == "LastLaunch")
{
return pdataLeft->lastLaunch() > pdataRight->lastLaunch();
}
else
{
return m_naturalSort.compare(pdataLeft->name(), pdataRight->name()) < 0;
}
}

View File

@ -16,15 +16,20 @@
#pragma once
#include <QSortFilterProxyModel>
#include <QCollator>
class GroupedProxyModel : public QSortFilterProxyModel
class InstanceProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
GroupedProxyModel(QObject *parent = 0);
InstanceProxyModel(QObject *parent = 0);
protected:
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const;
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:
QCollator m_naturalSort;
};

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
#include "GroupView.h"
#include "InstanceView.h"
#include <QPainter>
#include <QApplication>
@ -30,6 +30,10 @@
#include "VisualGroup.h"
#include <QDebug>
#include <Launcher.h>
#include <InstanceList.h>
template <typename T> bool listsIntersect(const QList<T> &l1, const QList<T> t2)
{
for (auto &item : l1)
@ -42,7 +46,7 @@ template <typename T> bool listsIntersect(const QList<T> &l1, const QList<T> t2)
return false;
}
GroupView::GroupView(QWidget *parent)
InstanceView::InstanceView(QWidget *parent)
: QAbstractItemView(parent)
{
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
@ -51,48 +55,47 @@ GroupView::GroupView(QWidget *parent)
setAutoScroll(true);
}
GroupView::~GroupView()
InstanceView::~InstanceView()
{
qDeleteAll(m_groups);
m_groups.clear();
}
void GroupView::setModel(QAbstractItemModel *model)
void InstanceView::setModel(QAbstractItemModel *model)
{
QAbstractItemView::setModel(model);
connect(model, &QAbstractItemModel::modelReset, this, &GroupView::modelReset);
connect(model, &QAbstractItemModel::rowsRemoved, this, &GroupView::rowsRemoved);
connect(model, &QAbstractItemModel::modelReset, this, &InstanceView::modelReset);
connect(model, &QAbstractItemModel::rowsRemoved, this, &InstanceView::rowsRemoved);
}
void GroupView::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 GroupView::rowsInserted(const QModelIndex &parent, int start, int end)
void InstanceView::rowsInserted(const QModelIndex &parent, int start, int end)
{
scheduleDelayedItemsLayout();
}
void GroupView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
void InstanceView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
scheduleDelayedItemsLayout();
}
void GroupView::modelReset()
void InstanceView::modelReset()
{
scheduleDelayedItemsLayout();
}
void GroupView::rowsRemoved()
void InstanceView::rowsRemoved()
{
scheduleDelayedItemsLayout();
}
void GroupView::currentChanged(const QModelIndex& current, const QModelIndex& previous)
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 GroupView.
// 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);
@ -119,7 +122,7 @@ inline bool operator<(const LocaleString &lhs, const LocaleString &rhs)
return (QString::localeAwareCompare(lhs, rhs) < 0);
}
void GroupView::updateScrollbar()
void InstanceView::updateScrollbar()
{
int previousScroll = verticalScrollBar()->value();
if (m_groups.isEmpty())
@ -156,7 +159,7 @@ void GroupView::updateScrollbar()
verticalScrollBar()->setValue(qMin(previousScroll, verticalScrollBar()->maximum()));
}
void GroupView::updateGeometries()
void InstanceView::updateGeometries()
{
geometryCache.clear();
@ -164,7 +167,7 @@ void GroupView::updateGeometries()
for (int i = 0; i < model()->rowCount(); ++i)
{
const QString groupName = model()->index(i, 0).data(GroupViewRoles::GroupRole).toString();
const QString groupName = model()->index(i, 0).data(InstanceViewRoles::GroupRole).toString();
if (!cats.contains(groupName))
{
VisualGroup *old = this->category(groupName);
@ -192,7 +195,7 @@ void GroupView::updateGeometries()
viewport()->update();
}
bool GroupView::isIndexHidden(const QModelIndex &index) const
bool InstanceView::isIndexHidden(const QModelIndex &index) const
{
VisualGroup *cat = category(index);
if (cat)
@ -205,12 +208,12 @@ bool GroupView::isIndexHidden(const QModelIndex &index) const
}
}
VisualGroup *GroupView::category(const QModelIndex &index) const
VisualGroup *InstanceView::category(const QModelIndex &index) const
{
return category(index.data(GroupViewRoles::GroupRole).toString());
return category(index.data(InstanceViewRoles::GroupRole).toString());
}
VisualGroup *GroupView::category(const QString &cat) const
VisualGroup *InstanceView::category(const QString &cat) const
{
for (auto group : m_groups)
{
@ -222,7 +225,7 @@ VisualGroup *GroupView::category(const QString &cat) const
return nullptr;
}
VisualGroup *GroupView::categoryAt(const QPoint &pos, VisualGroup::HitResults & result) const
VisualGroup *InstanceView::categoryAt(const QPoint &pos, VisualGroup::HitResults & result) const
{
for (auto group : m_groups)
{
@ -236,7 +239,7 @@ VisualGroup *GroupView::categoryAt(const QPoint &pos, VisualGroup::HitResults &
return nullptr;
}
QString GroupView::groupNameAt(const QPoint &point)
QString InstanceView::groupNameAt(const QPoint &point)
{
executeDelayedItemsLayout();
@ -249,22 +252,22 @@ QString GroupView::groupNameAt(const QPoint &point)
return QString();
}
int GroupView::calculateItemsPerRow() const
int InstanceView::calculateItemsPerRow() const
{
return qFloor((qreal)(contentWidth()) / (qreal)(itemWidth() + m_spacing));
}
int GroupView::contentWidth() const
int InstanceView::contentWidth() const
{
return width() - m_leftMargin - m_rightMargin;
}
int GroupView::itemWidth() const
int InstanceView::itemWidth() const
{
return m_itemWidth;
}
void GroupView::mousePressEvent(QMouseEvent *event)
void InstanceView::mousePressEvent(QMouseEvent *event)
{
executeDelayedItemsLayout();
@ -313,7 +316,7 @@ void GroupView::mousePressEvent(QMouseEvent *event)
}
}
void GroupView::mouseMoveEvent(QMouseEvent *event)
void InstanceView::mouseMoveEvent(QMouseEvent *event)
{
executeDelayedItemsLayout();
@ -371,7 +374,7 @@ void GroupView::mouseMoveEvent(QMouseEvent *event)
}
}
void GroupView::mouseReleaseEvent(QMouseEvent *event)
void InstanceView::mouseReleaseEvent(QMouseEvent *event)
{
executeDelayedItemsLayout();
@ -435,16 +438,22 @@ void GroupView::mouseReleaseEvent(QMouseEvent *event)
}
}
void GroupView::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());
QMouseEvent me(
QEvent::MouseButtonPress,
event->localPos(),
event->windowPos(),
event->screenPos(),
event->button(),
event->buttons(),
event->modifiers()
);
mousePressEvent(&me);
return;
}
@ -459,7 +468,7 @@ void GroupView::mouseDoubleClickEvent(QMouseEvent *event)
}
}
void GroupView::paintEvent(QPaintEvent *event)
void InstanceView::paintEvent(QPaintEvent *event)
{
executeDelayedItemsLayout();
@ -545,7 +554,7 @@ void GroupView::paintEvent(QPaintEvent *event)
#endif
}
void GroupView::resizeEvent(QResizeEvent *event)
void InstanceView::resizeEvent(QResizeEvent *event)
{
int newItemsPerRow = calculateItemsPerRow();
if(newItemsPerRow != m_currentItemsPerRow)
@ -560,7 +569,7 @@ void GroupView::resizeEvent(QResizeEvent *event)
}
}
void GroupView::dragEnterEvent(QDragEnterEvent *event)
void InstanceView::dragEnterEvent(QDragEnterEvent *event)
{
executeDelayedItemsLayout();
@ -573,7 +582,7 @@ void GroupView::dragEnterEvent(QDragEnterEvent *event)
event->accept();
}
void GroupView::dragMoveEvent(QDragMoveEvent *event)
void InstanceView::dragMoveEvent(QDragMoveEvent *event)
{
executeDelayedItemsLayout();
@ -586,7 +595,7 @@ void GroupView::dragMoveEvent(QDragMoveEvent *event)
event->accept();
}
void GroupView::dragLeaveEvent(QDragLeaveEvent *event)
void InstanceView::dragLeaveEvent(QDragLeaveEvent *event)
{
executeDelayedItemsLayout();
@ -594,7 +603,7 @@ void GroupView::dragLeaveEvent(QDragLeaveEvent *event)
viewport()->update();
}
void GroupView::dropEvent(QDropEvent *event)
void InstanceView::dropEvent(QDropEvent *event)
{
executeDelayedItemsLayout();
@ -603,32 +612,32 @@ void GroupView::dropEvent(QDropEvent *event)
stopAutoScroll();
setState(NoState);
auto mimedata = event->mimeData();
if (event->source() == this)
{
if(event->possibleActions() & Qt::MoveAction)
{
QPair<VisualGroup *, int> dropPos = rowDropPos(event->pos() + offset());
const VisualGroup *category = dropPos.first;
const int row = dropPos.second;
QPair<VisualGroup *, VisualGroup::HitResults> dropPos = rowDropPos(event->pos());
const VisualGroup *group = dropPos.first;
auto hitresult = dropPos.second;
if (row == -1)
if (hitresult == VisualGroup::HitResult::NoHit)
{
viewport()->update();
return;
}
auto instanceId = QString::fromUtf8(mimedata->data("application/x-instanceid"));
auto instanceList = LAUNCHER->instances().get();
instanceList->setInstanceGroup(instanceId, group->text);
event->setDropAction(Qt::MoveAction);
event->accept();
const QString categoryText = category->text;
if (model()->dropMimeData(event->mimeData(), Qt::MoveAction, row, 0, QModelIndex()))
{
model()->setData(model()->index(row, 0), categoryText, GroupViewRoles::GroupRole);
event->setDropAction(Qt::MoveAction);
event->accept();
}
updateGeometries();
viewport()->update();
}
return;
}
auto mimedata = event->mimeData();
// check if the action is supported
if (!mimedata)
@ -645,7 +654,7 @@ void GroupView::dropEvent(QDropEvent *event)
}
}
void GroupView::startDrag(Qt::DropActions supportedActions)
void InstanceView::startDrag(Qt::DropActions supportedActions)
{
executeDelayedItemsLayout();
@ -666,42 +675,24 @@ void GroupView::startDrag(Qt::DropActions supportedActions)
drag->setPixmap(pixmap);
drag->setMimeData(data);
Qt::DropAction defaultDropAction = Qt::IgnoreAction;
if (this->defaultDropAction() != Qt::IgnoreAction &&
(supportedActions & this->defaultDropAction()))
if (this->defaultDropAction() != Qt::IgnoreAction && (supportedActions & this->defaultDropAction()))
{
defaultDropAction = this->defaultDropAction();
}
if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction)
{
const QItemSelection selection = selectionModel()->selection();
for (auto it = selection.constBegin(); it != selection.constEnd(); ++it)
{
QModelIndex parent = (*it).parent();
if ((*it).left() != 0)
{
continue;
}
if ((*it).right() != (model()->columnCount(parent) - 1))
{
continue;
}
int count = (*it).bottom() - (*it).top() + 1;
model()->removeRows((*it).top(), count, parent);
}
}
/*auto action = */
drag->exec(supportedActions, defaultDropAction);
}
QRect GroupView::visualRect(const QModelIndex &index) const
QRect InstanceView::visualRect(const QModelIndex &index) const
{
const_cast<GroupView*>(this)->executeDelayedItemsLayout();
const_cast<InstanceView*>(this)->executeDelayedItemsLayout();
return geometryRect(index).translated(-offset());
}
QRect GroupView::geometryRect(const QModelIndex &index) const
QRect InstanceView::geometryRect(const QModelIndex &index) const
{
const_cast<GroupView*>(this)->executeDelayedItemsLayout();
const_cast<InstanceView*>(this)->executeDelayedItemsLayout();
if (!index.isValid() || isIndexHidden(index) || index.column() > 0)
{
@ -727,9 +718,9 @@ QRect GroupView::geometryRect(const QModelIndex &index) const
return out;
}
QModelIndex GroupView::indexAt(const QPoint &point) const
QModelIndex InstanceView::indexAt(const QPoint &point) const
{
const_cast<GroupView*>(this)->executeDelayedItemsLayout();
const_cast<InstanceView*>(this)->executeDelayedItemsLayout();
for (int i = 0; i < model()->rowCount(); ++i)
{
@ -742,7 +733,7 @@ QModelIndex GroupView::indexAt(const QPoint &point) const
return QModelIndex();
}
void GroupView::setSelection(const QRect &rect, const QItemSelectionModel::SelectionFlags commands)
void InstanceView::setSelection(const QRect &rect, const QItemSelectionModel::SelectionFlags commands)
{
executeDelayedItemsLayout();
@ -758,7 +749,7 @@ void GroupView::setSelection(const QRect &rect, const QItemSelectionModel::Selec
}
}
QPixmap GroupView::renderToPixmap(const QModelIndexList &indices, QRect *r) const
QPixmap InstanceView::renderToPixmap(const QModelIndexList &indices, QRect *r) const
{
Q_ASSERT(r);
auto paintPairs = draggablePaintPairs(indices, r);
@ -780,7 +771,7 @@ QPixmap GroupView::renderToPixmap(const QModelIndexList &indices, QRect *r) cons
return pixmap;
}
QList<QPair<QRect, QModelIndex>> GroupView::draggablePaintPairs(const QModelIndexList &indices, QRect *r) const
QList<QPair<QRect, QModelIndex>> InstanceView::draggablePaintPairs(const QModelIndexList &indices, QRect *r) const
{
Q_ASSERT(r);
QRect &rect = *r;
@ -795,22 +786,24 @@ QList<QPair<QRect, QModelIndex>> GroupView::draggablePaintPairs(const QModelInde
return ret;
}
bool GroupView::isDragEventAccepted(QDropEvent *event)
bool InstanceView::isDragEventAccepted(QDropEvent *event)
{
return true;
}
QPair<VisualGroup *, int> GroupView::rowDropPos(const QPoint &pos)
QPair<VisualGroup *, VisualGroup::HitResults> InstanceView::rowDropPos(const QPoint &pos)
{
return qMakePair<VisualGroup*, int>(nullptr, -1);
VisualGroup::HitResults hitresult;
auto group = categoryAt(pos + offset(), hitresult);
return qMakePair<VisualGroup*, int>(group, hitresult);
}
QPoint GroupView::offset() const
QPoint InstanceView::offset() const
{
return QPoint(horizontalOffset(), verticalOffset());
}
QRegion GroupView::visualRegionForSelection(const QItemSelection &selection) const
QRegion InstanceView::visualRegionForSelection(const QItemSelection &selection) const
{
QRegion region;
for (auto &range : selection)
@ -831,8 +824,7 @@ QRegion GroupView::visualRegionForSelection(const QItemSelection &selection) con
return region;
}
QModelIndex GroupView::moveCursor(QAbstractItemView::CursorAction cursorAction,
Qt::KeyboardModifiers modifiers)
QModelIndex InstanceView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
{
auto current = currentIndex();
if(!current.isValid())
@ -970,23 +962,23 @@ QModelIndex GroupView::moveCursor(QAbstractItemView::CursorAction cursorAction,
return current;
}
int GroupView::horizontalOffset() const
int InstanceView::horizontalOffset() const
{
return horizontalScrollBar()->value();
}
int GroupView::verticalOffset() const
int InstanceView::verticalOffset() const
{
return verticalScrollBar()->value();
}
void GroupView::scrollContentsBy(int dx, int dy)
void InstanceView::scrollContentsBy(int dx, int dy)
{
scrollDirtyRegion(dx, dy);
viewport()->scroll(dx, dy);
}
void GroupView::scrollTo(const QModelIndex &index, ScrollHint hint)
void InstanceView::scrollTo(const QModelIndex &index, ScrollHint hint)
{
if (!index.isValid())
return;
@ -1001,8 +993,7 @@ void GroupView::scrollTo(const QModelIndex &index, ScrollHint hint)
verticalScrollBar()->setValue(verticalScrollToValue(index, rect, hint));
}
int GroupView::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());

View File

@ -22,7 +22,7 @@
#include "VisualGroup.h"
#include <functional>
struct GroupViewRoles
struct InstanceViewRoles
{
enum
{
@ -32,13 +32,13 @@ struct GroupViewRoles
};
};
class GroupView : public QAbstractItemView
class InstanceView : public QAbstractItemView
{
Q_OBJECT
public:
GroupView(QWidget *parent = 0);
~GroupView();
InstanceView(QWidget *parent = 0);
~InstanceView();
void setModel(QAbstractItemModel *model) override;
@ -61,8 +61,7 @@ public:
virtual void scrollContentsBy(int dx, int dy) override;
virtual void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override;
virtual QModelIndex moveCursor(CursorAction cursorAction,
Qt::KeyboardModifiers modifiers) override;
virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override;
virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override;
@ -75,8 +74,7 @@ public slots:
virtual void updateGeometries() override;
protected slots:
virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
const QVector<int> &roles) override;
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();
@ -88,7 +86,7 @@ signals:
void groupStateChanged(QString group, bool collapsed);
protected:
virtual bool isIndexHidden(const QModelIndex &index) const override;
bool isIndexHidden(const QModelIndex &index) const override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
@ -143,15 +141,13 @@ private:
private: /* methods */
int itemWidth() const;
int calculateItemsPerRow() const;
int verticalScrollToValue(const QModelIndex &index, const QRect &rect,
QListView::ScrollHint hint) const;
int verticalScrollToValue(const QModelIndex &index, const QRect &rect, QListView::ScrollHint hint) const;
QPixmap renderToPixmap(const QModelIndexList &indices, QRect *r) const;
QList<QPair<QRect, QModelIndex>> draggablePaintPairs(const QModelIndexList &indices,
QRect *r) const;
QList<QPair<QRect, QModelIndex>> draggablePaintPairs(const QModelIndexList &indices, QRect *r) const;
bool isDragEventAccepted(QDropEvent *event);
QPair<VisualGroup *, int> rowDropPos(const QPoint &pos);
QPair<VisualGroup *, VisualGroup::HitResults> rowDropPos(const QPoint &pos);
QPoint offset() const;
};

View File

@ -21,9 +21,9 @@
#include <QApplication>
#include <QDebug>
#include "GroupView.h"
#include "InstanceView.h"
VisualGroup::VisualGroup(const QString &text, GroupView *view) : view(view), text(text), collapsed(false)
VisualGroup::VisualGroup(const QString &text, InstanceView *view) : view(view), text(text), collapsed(false)
{
}
@ -308,7 +308,7 @@ QList<QModelIndex> VisualGroup::items() const
for (int i = 0; i < view->model()->rowCount(); ++i)
{
const QModelIndex index = view->model()->index(i, 0);
if (index.data(GroupViewRoles::GroupRole).toString() == text)
if (index.data(InstanceViewRoles::GroupRole).toString() == text)
{
indices.append(index);
}

View File

@ -20,7 +20,7 @@
#include <QVector>
#include <QStyleOption>
class GroupView;
class InstanceView;
class QPainter;
class QModelIndex;
@ -42,11 +42,11 @@ struct VisualRow
struct VisualGroup
{
/* constructors */
VisualGroup(const QString &text, GroupView *view);
VisualGroup(const QString &text, InstanceView *view);
VisualGroup(const VisualGroup *other);
/* data */
GroupView *view = nullptr;
InstanceView *view = nullptr;
QString text;
bool collapsed = false;
QVector<VisualRow> rows;