summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2014-07-12 21:13:23 +0200
committerPetr Mrázek <peterix@gmail.com>2014-07-12 21:13:23 +0200
commitcc6968e9a3059451c4c1a5296ea5da7457ca831f (patch)
tree59ee62072326ab2573f1c5e0af9e79845e585f5e
parentd570037331f68f77eb010e65fa41129074123318 (diff)
downloadMultiMC-cc6968e9a3059451c4c1a5296ea5da7457ca831f.tar
MultiMC-cc6968e9a3059451c4c1a5296ea5da7457ca831f.tar.gz
MultiMC-cc6968e9a3059451c4c1a5296ea5da7457ca831f.tar.lz
MultiMC-cc6968e9a3059451c4c1a5296ea5da7457ca831f.tar.xz
MultiMC-cc6968e9a3059451c4c1a5296ea5da7457ca831f.zip
Group view gets keyboard navigation back.
And a bunch of fixes.
-rw-r--r--CMakeLists.txt4
-rw-r--r--gui/groupview/GroupView.cpp463
-rw-r--r--gui/groupview/GroupView.h101
-rw-r--r--gui/groupview/VisualGroup.cpp (renamed from gui/groupview/Group.cpp)124
-rw-r--r--gui/groupview/VisualGroup.h (renamed from gui/groupview/Group.h)44
5 files changed, 385 insertions, 351 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 83057b3c..077c2650 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -366,14 +366,14 @@ SET(MULTIMC_SOURCES
# GUI - instance group view
- gui/groupview/Group.cpp
- gui/groupview/Group.h
gui/groupview/GroupedProxyModel.cpp
gui/groupview/GroupedProxyModel.h
gui/groupview/GroupView.cpp
gui/groupview/GroupView.h
gui/groupview/InstanceDelegate.cpp
gui/groupview/InstanceDelegate.h
+ gui/groupview/VisualGroup.cpp
+ gui/groupview/VisualGroup.h
# LOGIC - Base classes and infrastructure
logic/BaseVersion.h
diff --git a/gui/groupview/GroupView.cpp b/gui/groupview/GroupView.cpp
index 6f6f0f8e..3f85c6e9 100644
--- a/gui/groupview/GroupView.cpp
+++ b/gui/groupview/GroupView.cpp
@@ -11,7 +11,7 @@
#include <QCache>
#include <QScrollBar>
-#include "Group.h"
+#include "VisualGroup.h"
#include "logger/QsLog.h"
template <typename T> bool listsIntersect(const QList<T> &l1, const QList<T> t2)
@@ -27,17 +27,12 @@ template <typename T> bool listsIntersect(const QList<T> &l1, const QList<T> t2)
}
GroupView::GroupView(QWidget *parent)
- : QAbstractItemView(parent), m_leftMargin(5), m_rightMargin(5), m_bottomMargin(5),
- m_categoryMargin(5) //, m_updatesDisabled(false), m_categoryEditor(0), m_editedCategory(0)
+ : QAbstractItemView(parent)
{
- // setViewMode(IconMode);
- // setMovement(Snap);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- // setWordWrap(true);
- // setDragDropMode(QListView::InternalMove);
setAcceptDrops(true);
- m_spacing = 5;
+ setAutoScroll(true);
}
GroupView::~GroupView()
@@ -72,7 +67,7 @@ void GroupView::updateGeometries()
geometryCache.clear();
int previousScroll = verticalScrollBar()->value();
- QMap<QString, Group *> cats;
+ QMap<QString, VisualGroup *> cats;
for (int i = 0; i < model()->rowCount(); ++i)
{
@@ -80,14 +75,14 @@ void GroupView::updateGeometries()
model()->index(i, 0).data(GroupViewRoles::GroupRole).toString();
if (!cats.contains(groupName))
{
- Group *old = this->category(groupName);
+ VisualGroup *old = this->category(groupName);
if (old)
{
- cats.insert(groupName, new Group(old));
+ cats.insert(groupName, new VisualGroup(old));
}
else
{
- cats.insert(groupName, new Group(groupName, this));
+ cats.insert(groupName, new VisualGroup(groupName, this));
}
}
}
@@ -149,7 +144,7 @@ void GroupView::modelReset()
bool GroupView::isIndexHidden(const QModelIndex &index) const
{
- Group *cat = category(index);
+ VisualGroup *cat = category(index);
if (cat)
{
return cat->collapsed;
@@ -160,12 +155,12 @@ bool GroupView::isIndexHidden(const QModelIndex &index) const
}
}
-Group *GroupView::category(const QModelIndex &index) const
+VisualGroup *GroupView::category(const QModelIndex &index) const
{
return category(index.data(GroupViewRoles::GroupRole).toString());
}
-Group *GroupView::category(const QString &cat) const
+VisualGroup *GroupView::category(const QString &cat) const
{
for (auto group : m_groups)
{
@@ -177,11 +172,11 @@ Group *GroupView::category(const QString &cat) const
return nullptr;
}
-Group *GroupView::categoryAt(const QPoint &pos) const
+VisualGroup *GroupView::categoryAt(const QPoint &pos) const
{
for (auto group : m_groups)
{
- if(group->hitScan(pos) & Group::CheckboxHit)
+ if(group->hitScan(pos) & VisualGroup::CheckboxHit)
{
return group;
}
@@ -189,7 +184,7 @@ Group *GroupView::categoryAt(const QPoint &pos) const
return nullptr;
}
-int GroupView::itemsPerRow() const
+int GroupView::calculateItemsPerRow() const
{
return qFloor((qreal)(contentWidth()) / (qreal)(itemWidth() + m_spacing));
}
@@ -201,77 +196,7 @@ int GroupView::contentWidth() const
int GroupView::itemWidth() const
{
- return itemDelegate()
- ->sizeHint(viewOptions(), model()->index(model()->rowCount() - 1, 0))
- .width();
-}
-
-int GroupView::categoryRowHeight(const QModelIndex &index) const
-{
- QModelIndexList indices;
- int internalRow = categoryInternalPosition(index).second;
- for (auto &i : category(index)->items())
- {
- if (categoryInternalPosition(i).second == internalRow)
- {
- indices.append(i);
- }
- }
-
- int largestHeight = 0;
- for (auto &i : indices)
- {
- largestHeight =
- qMax(largestHeight, itemDelegate()->sizeHint(viewOptions(), i).height());
- }
- return largestHeight + m_spacing;
-}
-
-QPair<int, int> GroupView::categoryInternalPosition(const QModelIndex &index) const
-{
- QList<QModelIndex> indices = category(index)->items();
- int x = 0;
- int y = 0;
- const int perRow = itemsPerRow();
- for (int i = 0; i < indices.size(); ++i)
- {
- if (indices.at(i) == index)
- {
- break;
- }
- ++x;
- if (x == perRow)
- {
- x = 0;
- ++y;
- }
- }
- return qMakePair(x, y);
-}
-
-int GroupView::categoryInternalRowTop(const QModelIndex &index) const
-{
- Group *cat = category(index);
- int categoryInternalRow = categoryInternalPosition(index).second;
- int result = 0;
- for (int i = 0; i < categoryInternalRow; ++i)
- {
- result += cat->rowHeights.at(i);
- }
- return result;
-}
-
-int GroupView::itemHeightForCategoryRow(const Group *category, const int internalRow) const
-{
- for (auto &i : category->items())
- {
- QPair<int, int> pos = categoryInternalPosition(i);
- if (pos.second == internalRow)
- {
- return categoryRowHeight(i);
- }
- }
- return -1;
+ return m_itemWidth;
}
void GroupView::mousePressEvent(QMouseEvent *event)
@@ -297,13 +222,19 @@ void GroupView::mousePressEvent(QMouseEvent *event)
if (index.isValid() && (index.flags() & Qt::ItemIsEnabled))
{
+ if(index != currentIndex())
+ {
+ // FIXME: better!
+ m_currentCursorColumn = -1;
+ }
// we disable scrollTo for mouse press so the item doesn't change position
// when the user is interacting with it (ie. clicking on it)
bool autoScroll = hasAutoScroll();
setAutoScroll(false);
selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
+
setAutoScroll(autoScroll);
- QRect rect(geometryPos, geometryPos);
+ QRect rect(visualPos, visualPos);
setSelection(rect, QItemSelectionModel::ClearAndSelect);
// signal handlers may change the model
@@ -360,7 +291,7 @@ void GroupView::mouseMoveEvent(QMouseEvent *event)
{
setState(DragSelectingState);
- setSelection(QRect(geometryPos, geometryPos), QItemSelectionModel::ClearAndSelect);
+ setSelection(QRect(visualPos, visualPos), QItemSelectionModel::ClearAndSelect);
QModelIndex index = indexAt(visualPos);
// set at the end because it might scroll the view
@@ -453,7 +384,7 @@ void GroupView::paintEvent(QPaintEvent *event)
option.rect.setWidth(wpWidth);
for (int i = 0; i < m_groups.size(); ++i)
{
- Group *category = m_groups.at(i);
+ VisualGroup *category = m_groups.at(i);
int y = category->verticalPosition();
y -= verticalOffset();
QRect backup = option.rect;
@@ -529,16 +460,12 @@ void GroupView::paintEvent(QPaintEvent *event)
void GroupView::resizeEvent(QResizeEvent *event)
{
- // QListView::resizeEvent(event);
-
- // if (m_categoryEditor)
- // {
- // m_categoryEditor->resize(qMax(contentWidth() / 2,
- // m_editedCategory->textRect.width()),
- // m_categoryEditor->height());
- // }
-
- updateGeometries();
+ int newItemsPerRow = calculateItemsPerRow();
+ if(newItemsPerRow != m_currentItemsPerRow)
+ {
+ m_currentItemsPerRow = newItemsPerRow;
+ updateGeometries();
+ }
}
void GroupView::dragEnterEvent(QDragEnterEvent *event)
@@ -581,8 +508,8 @@ void GroupView::dropEvent(QDropEvent *event)
return;
}
- QPair<Group *, int> dropPos = rowDropPos(event->pos() + offset());
- const Group *category = dropPos.first;
+ QPair<VisualGroup *, int> dropPos = rowDropPos(event->pos() + offset());
+ const VisualGroup *category = dropPos.first;
const int row = dropPos.second;
if (row == -1)
@@ -606,44 +533,44 @@ void GroupView::dropEvent(QDropEvent *event)
void GroupView::startDrag(Qt::DropActions supportedActions)
{
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);
- //rect.translate(offset());
- // rect.adjust(horizontalOffset(), verticalOffset(), 0, 0);
- QDrag *drag = new QDrag(this);
- drag->setPixmap(pixmap);
- drag->setMimeData(data);
- Qt::DropAction defaultDropAction = Qt::IgnoreAction;
- if (this->defaultDropAction() != Qt::IgnoreAction &&
- (supportedActions & this->defaultDropAction()))
- {
- defaultDropAction = this->defaultDropAction();
- }
- if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction)
- {
- const QItemSelection selection = selectionModel()->selection();
+ return;
+ }
+ QRect rect;
+ QPixmap pixmap = renderToPixmap(indexes, &rect);
+ //rect.translate(offset());
+ // rect.adjust(horizontalOffset(), verticalOffset(), 0, 0);
+ QDrag *drag = new QDrag(this);
+ drag->setPixmap(pixmap);
+ drag->setMimeData(data);
+ Qt::DropAction defaultDropAction = Qt::IgnoreAction;
+ 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)
+ for (auto it = selection.constBegin(); it != selection.constEnd(); ++it)
+ {
+ QModelIndex parent = (*it).parent();
+ if ((*it).left() != 0)
{
- 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);
+ continue;
+ }
+ if ((*it).right() != (model()->columnCount(parent) - 1))
+ {
+ continue;
}
+ int count = (*it).bottom() - (*it).top() + 1;
+ model()->removeRows((*it).top(), count, parent);
}
}
}
@@ -665,60 +592,19 @@ QRect GroupView::geometryRect(const QModelIndex &index) const
{
return *geometryCache[row];
}
- else
- {
- const Group *cat = category(index);
- QPair<int, int> pos = categoryInternalPosition(index);
- int x = pos.first;
- // int y = pos.second;
- QRect out;
- out.setTop(cat->verticalPosition() + cat->headerHeight() + 5 + categoryInternalRowTop(index));
- out.setLeft(m_spacing + x * (itemWidth() + m_spacing));
- out.setSize(itemDelegate()->sizeHint(viewOptions(), index));
- const_cast<QCache<int, QRect>&>(geometryCache).insert(row, new QRect(out));
- return out;
- }
-}
-
-/*
-void CategorizedView::startCategoryEditor(Category *category)
-{
- if (m_categoryEditor != 0)
- {
- return;
- }
- m_editedCategory = category;
- m_categoryEditor = new QLineEdit(m_editedCategory->text, this);
- QRect rect = m_editedCategory->textRect;
- rect.setWidth(qMax(contentWidth() / 2, rect.width()));
- m_categoryEditor->setGeometry(rect);
- m_categoryEditor->show();
- m_categoryEditor->setFocus();
- connect(m_categoryEditor, &QLineEdit::returnPressed, this,
-&CategorizedView::endCategoryEditor);
-}
+ const VisualGroup *cat = category(index);
+ QPair<int, int> pos = cat->positionOf(index);
+ int x = pos.first;
+ // int y = pos.second;
-void CategorizedView::endCategoryEditor()
-{
- if (m_categoryEditor == 0)
- {
- return;
- }
- m_editedCategory->text = m_categoryEditor->text();
- m_updatesDisabled = true;
- foreach (const QModelIndex &index, itemsForCategory(m_editedCategory))
- {
- const_cast<QAbstractItemModel *>(index.model())->setData(index,
-m_categoryEditor->text(), CategoryRole);
- }
- m_updatesDisabled = false;
- delete m_categoryEditor;
- m_categoryEditor = 0;
- m_editedCategory = 0;
- updateGeometries();
+ QRect out;
+ out.setTop(cat->verticalPosition() + cat->headerHeight() + 5 + cat->rowTopOf(index));
+ out.setLeft(m_spacing + x * (itemWidth() + m_spacing));
+ out.setSize(itemDelegate()->sizeHint(viewOptions(), index));
+ geometryCache.insert(row, new QRect(out));
+ return out;
}
-*/
QModelIndex GroupView::indexAt(const QPoint &point) const
{
@@ -733,21 +619,19 @@ QModelIndex GroupView::indexAt(const QPoint &point) const
return QModelIndex();
}
-// FIXME: is rect supposed to be geometry or visual coords?
void GroupView::setSelection(const QRect &rect,
const QItemSelectionModel::SelectionFlags commands)
{
for (int i = 0; i < model()->rowCount(); ++i)
{
QModelIndex index = model()->index(i, 0);
- QRect itemRect = geometryRect(index);
+ QRect itemRect = visualRect(index);
if (itemRect.intersects(rect))
{
selectionModel()->select(index, commands);
update(itemRect.translated(-offset()));
}
}
-
}
QPixmap GroupView::renderToPixmap(const QModelIndexList &indices, QRect *r) const
@@ -790,33 +674,23 @@ QList<QPair<QRect, QModelIndex>> GroupView::draggablePaintPairs(const QModelInde
bool GroupView::isDragEventAccepted(QDropEvent *event)
{
- if (event->source() != this)
- {
- return false;
- }
- if (!listsIntersect(event->mimeData()->formats(), model()->mimeTypes()))
- {
- return false;
- }
- if (!model()->canDropMimeData(event->mimeData(), event->dropAction(),
- rowDropPos(event->pos()).second, 0, QModelIndex()))
- {
- return false;
- }
- return true;
+ return false;
}
-QPair<Group *, int> GroupView::rowDropPos(const QPoint &pos)
+QPair<VisualGroup *, int> GroupView::rowDropPos(const QPoint &pos)
{
+ return qMakePair<VisualGroup*, int>(nullptr, -1);
+ // FIXME: PIXIE DUST.
+ /*
// check that we aren't on a category header and calculate which category we're in
- Group *category = 0;
+ VisualGroup *category = 0;
{
int y = 0;
for (auto cat : m_groups)
{
if (pos.y() > y && pos.y() < (y + cat->headerHeight()))
{
- return qMakePair<Group*, int>(nullptr, -1);
+ return qMakePair<VisualGroup*, int>(nullptr, -1);
}
y += cat->totalHeight() + m_categoryMargin;
if (pos.y() < y)
@@ -827,7 +701,7 @@ QPair<Group *, int> GroupView::rowDropPos(const QPoint &pos)
}
if (category == 0)
{
- return qMakePair<Group*, int>(nullptr, -1);
+ return qMakePair<VisualGroup*, int>(nullptr, -1);
}
}
@@ -843,7 +717,7 @@ QPair<Group *, int> GroupView::rowDropPos(const QPoint &pos)
}
else
{
- for (int i = 0, c = 0; i < contentWidth(); i += itemWidth + 10 /*spacing()*/, ++c)
+ for (int i = 0, c = 0; i < contentWidth(); i += itemWidth + 10 , ++c)
{
if (pos.x() > (i - itemWidth / 2) && pos.x() <= (i + itemWidth / 2))
{
@@ -854,7 +728,7 @@ QPair<Group *, int> GroupView::rowDropPos(const QPoint &pos)
}
if (internalColumn == -1)
{
- return qMakePair<Group*, int>(nullptr, -1);
+ return qMakePair<VisualGroup*, int>(nullptr, -1);
}
}
@@ -874,13 +748,13 @@ QPair<Group *, int> GroupView::rowDropPos(const QPoint &pos)
}
if (internalRow == -1)
{
- return qMakePair<Group*, int>(nullptr, -1);
+ return qMakePair<VisualGroup*, int>(nullptr, -1);
}
// this happens if we're in the margin between a one category and another
// categories header
if (internalRow > (indices.size() / itemsPerRow()))
{
- return qMakePair<Group*, int>(nullptr, -1);
+ return qMakePair<VisualGroup*, int>(nullptr, -1);
}
}
@@ -894,6 +768,7 @@ QPair<Group *, int> GroupView::rowDropPos(const QPoint &pos)
}
return qMakePair(category, indices.at(categoryRow).row());
+ */
}
QPoint GroupView::offset() const
@@ -921,34 +796,162 @@ QRegion GroupView::visualRegionForSelection(const QItemSelection &selection) con
}
return region;
}
+
QModelIndex GroupView::moveCursor(QAbstractItemView::CursorAction cursorAction,
Qt::KeyboardModifiers modifiers)
{
auto current = currentIndex();
if(!current.isValid())
{
- QLOG_DEBUG() << "model row: invalid";
return current;
}
- QLOG_DEBUG() << "model row: " << current.row();
auto cat = category(current);
- int i = m_groups.indexOf(cat);
- if(i >= 0)
+ int group_index = m_groups.indexOf(cat);
+ if(group_index < 0)
+ return current;
+
+ auto real_group = m_groups[group_index];
+ int beginning_row = 0;
+ for(auto group: m_groups)
+ {
+ if(group == real_group)
+ break;
+ beginning_row += group->numRows();
+ }
+
+ QPair<int, int> pos = cat->positionOf(current);
+ int column = pos.first;
+ int row = pos.second;
+ if(m_currentCursorColumn < 0)
{
- // this is a pile of something foul
- auto real_group = m_groups[i];
- int beginning_row = 0;
- for(auto group: m_groups)
+ m_currentCursorColumn = column;
+ }
+ switch(cursorAction)
+ {
+ case MoveUp:
{
- if(group == real_group)
- break;
- beginning_row += group->numRows();
+ if(row == 0)
+ {
+ if(group_index == 0)
+ return current;
+ auto prevgroup = m_groups[group_index-1];
+ int newRow = prevgroup->numRows() - 1;
+ int newRowSize = prevgroup->rows[newRow].size();
+ int newColumn = m_currentCursorColumn;
+ if (m_currentCursorColumn >= newRowSize)
+ {
+ newColumn = newRowSize - 1;
+ }
+ return prevgroup->rows[newRow][newColumn];
+ }
+ else
+ {
+ int newRow = row - 1;
+ int newRowSize = cat->rows[newRow].size();
+ int newColumn = m_currentCursorColumn;
+ if (m_currentCursorColumn >= newRowSize)
+ {
+ newColumn = newRowSize - 1;
+ }
+ return cat->rows[newRow][newColumn];
+ }
}
- QLOG_DEBUG() << "category: " << real_group->text;
- QPair<int, int> pos = categoryInternalPosition(current);
- int row = beginning_row + pos.second;
- QLOG_DEBUG() << "row: " << row;
- QLOG_DEBUG() << "column: " << pos.first;
+ case MoveDown:
+ {
+ if(row == cat->rows.size() - 1)
+ {
+ if(group_index == m_groups.size() - 1)
+ return current;
+ auto nextgroup = m_groups[group_index+1];
+ int newRowSize = nextgroup->rows[0].size();
+ int newColumn = m_currentCursorColumn;
+ if (m_currentCursorColumn >= newRowSize)
+ {
+ newColumn = newRowSize - 1;
+ }
+ return nextgroup->rows[0][newColumn];
+ }
+ else
+ {
+ int newRow = row + 1;
+ int newRowSize = cat->rows[newRow].size();
+ int newColumn = m_currentCursorColumn;
+ if (m_currentCursorColumn >= newRowSize)
+ {
+ newColumn = newRowSize - 1;
+ }
+ return cat->rows[newRow][newColumn];
+ }
+ }
+ case MoveLeft:
+ {
+ if(column > 0)
+ {
+ m_currentCursorColumn = column - 1;
+ return cat->rows[row][column - 1];
+ }
+ return current;
+ }
+ case MoveRight:
+ {
+ if(column < cat->rows[row].size() - 1)
+ {
+ m_currentCursorColumn = column + 1;
+ return cat->rows[row][column + 1];
+ }
+ return current;
+ }
+ default:
+ break;
}
return current;
}
+
+int GroupView::horizontalOffset() const
+{
+ return horizontalScrollBar()->value();
+}
+
+int GroupView::verticalOffset() const
+{
+ return verticalScrollBar()->value();
+}
+
+void GroupView::scrollContentsBy(int dx, int dy)
+{
+ scrollDirtyRegion(dx, dy);
+ viewport()->scroll(dx, dy);
+}
+
+void GroupView::scrollTo(const QModelIndex &index, ScrollHint hint)
+{
+ if (!index.isValid())
+ return;
+
+ const QRect rect = visualRect(index);
+ if (hint == EnsureVisible && viewport()->rect().contains(rect))
+ {
+ viewport()->update(rect);
+ return;
+ }
+
+ verticalScrollBar()->setValue(verticalScrollToValue(index, rect, hint));
+}
+
+int GroupView::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());
+ const bool below = (hint == QListView::EnsureVisible && rect.bottom() > area.bottom());
+
+ int verticalValue = verticalScrollBar()->value();
+ QRect adjusted = rect.adjusted(-spacing(), -spacing(), spacing(), spacing());
+ if (hint == QListView::PositionAtTop || above)
+ verticalValue += adjusted.top();
+ else if (hint == QListView::PositionAtBottom || below)
+ verticalValue += qMin(adjusted.top(), adjusted.bottom() - area.height() + 1);
+ else if (hint == QListView::PositionAtCenter)
+ verticalValue += adjusted.top() - ((area.height() - adjusted.height()) / 2);
+ return verticalValue;
+}
diff --git a/gui/groupview/GroupView.h b/gui/groupview/GroupView.h
index 736bfbeb..93e45ed7 100644
--- a/gui/groupview/GroupView.h
+++ b/gui/groupview/GroupView.h
@@ -15,7 +15,7 @@ struct GroupViewRoles
};
};
-struct Group;
+struct VisualGroup;
class GroupView : public QAbstractItemView
{
@@ -36,35 +36,20 @@ public:
void setSelection(const QRect &rect,
const QItemSelectionModel::SelectionFlags commands) override;
- virtual int horizontalOffset() const override
- {
- return horizontalScrollBar()->value();
- }
-
- virtual int verticalOffset() const override
- {
- return verticalScrollBar()->value();
- }
-
- virtual void scrollContentsBy(int dx, int dy) override
- {
- scrollDirtyRegion(dx, dy);
- viewport()->scroll(dx, dy);
- }
-
- /*
- * TODO!
- */
- virtual void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override
- {
- return;
- }
+ 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 QModelIndex moveCursor(CursorAction cursorAction,
Qt::KeyboardModifiers modifiers) override;
virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override;
+ int spacing() const
+ {
+ return m_spacing;
+ };
protected
slots:
virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
@@ -91,58 +76,50 @@ protected:
void startDrag(Qt::DropActions supportedActions) override;
private:
- friend struct Group;
-
- QList<Group *> m_groups;
-
- int m_leftMargin;
- int m_rightMargin;
- int m_bottomMargin;
- int m_categoryMargin;
-
- // bool m_updatesDisabled;
-
- Group *category(const QModelIndex &index) const;
- Group *category(const QString &cat) const;
- Group *categoryAt(const QPoint &pos) const;
-
- int itemsPerRow() const;
- int contentWidth() const;
-
-private:
- int itemWidth() const;
- int categoryRowHeight(const QModelIndex &index) const;
-
- /*QLineEdit *m_categoryEditor;
- Category *m_editedCategory;
- void startCategoryEditor(Category *category);
-
-private slots:
- void endCategoryEditor();*/
+ friend struct VisualGroup;
+ QList<VisualGroup *> m_groups;
+
+ // geometry
+ int m_leftMargin = 5;
+ int m_rightMargin = 5;
+ int m_bottomMargin = 5;
+ int m_categoryMargin = 5;
+ int m_spacing = 5;
+ int m_itemWidth = 100;
+ int m_currentItemsPerRow = -1;
+ int m_currentCursorColumn= -1;
+ mutable QCache<int, QRect> geometryCache;
-private: /* variables */
- /// point where the currently active mouse action started in geometry coordinates
+ // point where the currently active mouse action started in geometry coordinates
QPoint m_pressedPosition;
QPersistentModelIndex m_pressedIndex;
bool m_pressedAlreadySelected;
- Group *m_pressedCategory;
+ VisualGroup *m_pressedCategory;
QItemSelectionModel::SelectionFlag m_ctrlDragSelectionFlag;
QPoint m_lastDragPosition;
- int m_spacing = 5;
- QCache<int, QRect> geometryCache;
-private: /* methods */
- QPair<int, int> categoryInternalPosition(const QModelIndex &index) const;
- int categoryInternalRowTop(const QModelIndex &index) const;
- int itemHeightForCategoryRow(const Group *category, const int internalRow) const;
+ VisualGroup *category(const QModelIndex &index) const;
+ VisualGroup *category(const QString &cat) const;
+ VisualGroup *categoryAt(const QPoint &pos) const;
+ int itemsPerRow() const
+ {
+ return m_currentItemsPerRow;
+ };
+ int contentWidth() const;
+
+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<QPair<QRect, QModelIndex>> draggablePaintPairs(const QModelIndexList &indices,
QRect *r) const;
bool isDragEventAccepted(QDropEvent *event);
- QPair<Group *, int> rowDropPos(const QPoint &pos);
+ QPair<VisualGroup *, int> rowDropPos(const QPoint &pos);
QPoint offset() const;
};
diff --git a/gui/groupview/Group.cpp b/gui/groupview/VisualGroup.cpp
index 51aa6658..560fc9ca 100644
--- a/gui/groupview/Group.cpp
+++ b/gui/groupview/VisualGroup.cpp
@@ -1,4 +1,4 @@
-#include "Group.h"
+#include "VisualGroup.h"
#include <QModelIndex>
#include <QPainter>
@@ -7,30 +7,83 @@
#include "GroupView.h"
-Group::Group(const QString &text, GroupView *view) : view(view), text(text), collapsed(false)
+VisualGroup::VisualGroup(const QString &text, GroupView *view) : view(view), text(text), collapsed(false)
{
}
-Group::Group(const Group *other)
+VisualGroup::VisualGroup(const VisualGroup *other)
: view(other->view), text(other->text), collapsed(other->collapsed)
{
}
-void Group::update()
+void VisualGroup::update()
{
- firstItemIndex = firstItem().row();
+ auto temp_items = items();
+ auto itemsPerRow = view->itemsPerRow();
- rowHeights = QVector<int>(numRows());
- for (int i = 0; i < numRows(); ++i)
+ int numRows = qMax(1, qCeil((qreal)temp_items.size() / (qreal)itemsPerRow));
+ rows = QVector<VisualRow>(numRows);
+
+ int maxRowHeight = 0;
+ int positionInRow = 0;
+ int currentRow = 0;
+ int offsetFromTop = 0;
+ for (auto item: temp_items)
{
- rowHeights[i] = view->categoryRowHeight(
- view->model()->index(i * view->itemsPerRow() + firstItemIndex, 0));
+ if(positionInRow == itemsPerRow)
+ {
+ rows[currentRow].height = maxRowHeight;
+ rows[currentRow].top = offsetFromTop;
+ currentRow ++;
+ offsetFromTop += maxRowHeight + 5;
+ positionInRow = 0;
+ maxRowHeight = 0;
+ }
+ auto itemHeight = view->itemDelegate()->sizeHint(view->viewOptions(), item).height();
+ if(itemHeight > maxRowHeight)
+ {
+ maxRowHeight = itemHeight;
+ }
+ rows[currentRow].items.append(item);
+ positionInRow++;
}
+ rows[currentRow].height = maxRowHeight;
+ rows[currentRow].top = offsetFromTop;
+}
+
+QPair<int, int> VisualGroup::positionOf(const QModelIndex &index) const
+{
+ int x = 0;
+ int y = 0;
+ for (auto & row: rows)
+ {
+ for(auto x = 0; x < row.items.size(); x++)
+ {
+ if(row.items[x] == index)
+ {
+ return qMakePair(x,y);
+ }
+ }
+ y++;
+ }
+ return qMakePair(x, y);
+}
+
+int VisualGroup::rowTopOf(const QModelIndex &index) const
+{
+ auto position = positionOf(index);
+ return rows[position.second].top;
}
-Group::HitResults Group::hitScan(const QPoint &pos) const
+int VisualGroup::rowHeightOf(const QModelIndex &index) const
{
- Group::HitResults results = Group::NoHit;
+ auto position = positionOf(index);
+ return rows[position.second].height;
+}
+
+VisualGroup::HitResults VisualGroup::hitScan(const QPoint &pos) const
+{
+ VisualGroup::HitResults results = VisualGroup::NoHit;
int y_start = verticalPosition();
int body_start = y_start + headerHeight();
int body_end = body_start + contentHeight() + 5; // FIXME: wtf is this 5?
@@ -38,28 +91,28 @@ Group::HitResults Group::hitScan(const QPoint &pos) const
// int x = pos.x();
if (y < y_start)
{
- results = Group::NoHit;
+ results = VisualGroup::NoHit;
}
else if (y < body_start)
{
- results = Group::HeaderHit;
+ results = VisualGroup::HeaderHit;
int collapseSize = headerHeight() - 4;
// the icon
QRect iconRect = QRect(view->m_leftMargin + 2, 2 + y_start, collapseSize, collapseSize);
if (iconRect.contains(pos))
{
- results |= Group::CheckboxHit;
+ results |= VisualGroup::CheckboxHit;
}
}
else if (y < body_end)
{
- results |= Group::BodyHit;
+ results |= VisualGroup::BodyHit;
}
return results;
}
-void Group::drawHeader(QPainter *painter, const QStyleOptionViewItem &option)
+void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &option)
{
painter->setRenderHint(QPainter::Antialiasing);
@@ -190,12 +243,12 @@ void Group::drawHeader(QPainter *painter, const QStyleOptionViewItem &option)
//END: text
}
-int Group::totalHeight() const
+int VisualGroup::totalHeight() const
{
return headerHeight() + 5 + contentHeight(); // FIXME: wtf is that '5'?
}
-int Group::headerHeight() const
+int VisualGroup::headerHeight() const
{
QFont font(QApplication::font());
font.setBold(true);
@@ -213,31 +266,27 @@ int Group::headerHeight() const
*/
}
-int Group::contentHeight() const
+int VisualGroup::contentHeight() const
{
if (collapsed)
{
return 0;
}
- int result = 0;
- for (int i = 0; i < rowHeights.size(); ++i)
- {
- result += rowHeights[i];
- }
- return result;
+ auto last = rows[numRows() - 1];
+ return last.top + last.height;
}
-int Group::numRows() const
+int VisualGroup::numRows() const
{
- return qMax(1, qCeil((qreal)numItems() / (qreal)view->itemsPerRow()));
+ return rows.size();
}
-int Group::verticalPosition() const
+int VisualGroup::verticalPosition() const
{
return m_verticalPosition;
}
-QList<QModelIndex> Group::items() const
+QList<QModelIndex> VisualGroup::items() const
{
QList<QModelIndex> indices;
for (int i = 0; i < view->model()->rowCount(); ++i)
@@ -250,20 +299,3 @@ QList<QModelIndex> Group::items() const
}
return indices;
}
-
-int Group::numItems() const
-{
- return items().size();
-}
-
-QModelIndex Group::firstItem() const
-{
- QList<QModelIndex> indices = items();
- return indices.isEmpty() ? QModelIndex() : indices.first();
-}
-
-QModelIndex Group::lastItem() const
-{
- QList<QModelIndex> indices = items();
- return indices.isEmpty() ? QModelIndex() : indices.last();
-}
diff --git a/gui/groupview/Group.h b/gui/groupview/VisualGroup.h
index 3b797f4c..d8d1f145 100644
--- a/gui/groupview/Group.h
+++ b/gui/groupview/VisualGroup.h
@@ -9,22 +9,37 @@ class GroupView;
class QPainter;
class QModelIndex;
-struct Group
+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];
+ }
+};
+
+struct VisualGroup
{
/* constructors */
- Group(const QString &text, GroupView *view);
- Group(const Group *other);
+ VisualGroup(const QString &text, GroupView *view);
+ VisualGroup(const VisualGroup *other);
/* data */
GroupView *view = nullptr;
QString text;
bool collapsed = false;
- QVector<int> rowHeights;
+ QVector<VisualRow> rows;
int firstItemIndex = 0;
int m_verticalPosition = 0;
/* logic */
- /// do stuff. and things. TODO: redo.
+ /// update the internal list of items and flow them into the rows.
void update();
/// draw the header at y-position.
@@ -42,9 +57,21 @@ struct Group
/// the number of visual rows this group has
int numRows() const;
+ /// actually calculate the above value
+ int calculateNumRows() const;
+
/// the height at which this group starts, in pixels
int verticalPosition() const;
+ /// relative geometry - top of the row of the given item
+ int rowTopOf(const QModelIndex &index) const;
+
+ /// height of the row of the given item
+ 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;
+
enum HitResult
{
NoHit = 0x0,
@@ -58,12 +85,7 @@ struct Group
/// shoot! BANG! what did we hit?
HitResults hitScan (const QPoint &pos) const;
- /// super derpy thing.
QList<QModelIndex> items() const;
- /// I don't even
- int numItems() const;
- QModelIndex firstItem() const;
- QModelIndex lastItem() const;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(Group::HitResults)
+Q_DECLARE_OPERATORS_FOR_FLAGS(VisualGroup::HitResults)