summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Dalheimer <jan@dalheimer.de>2013-12-24 11:47:30 +0100
committerJan Dalheimer <jan@dalheimer.de>2013-12-24 11:47:30 +0100
commitccbf341dc8d8e515d9cf918bff7ff9435c477847 (patch)
tree7ca5071ba6dcc52dd6e77e265ece4afafcac58f7
downloadMultiMC-ccbf341dc8d8e515d9cf918bff7ff9435c477847.tar
MultiMC-ccbf341dc8d8e515d9cf918bff7ff9435c477847.tar.gz
MultiMC-ccbf341dc8d8e515d9cf918bff7ff9435c477847.tar.lz
MultiMC-ccbf341dc8d8e515d9cf918bff7ff9435c477847.tar.xz
MultiMC-ccbf341dc8d8e515d9cf918bff7ff9435c477847.zip
Initial commit. Basics work. Next: Drag and Drop
-rw-r--r--.gitignore2
-rw-r--r--CMakeLists.txt35
-rw-r--r--CategorizedProxyModel.cpp12
-rw-r--r--CategorizedProxyModel.h18
-rw-r--r--CategorizedView.cpp587
-rw-r--r--CategorizedView.h96
-rw-r--r--main.cpp53
7 files changed, 803 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..a5d18fa3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+build/
+*.user*
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 00000000..8a246bcf
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 2.8.9)
+
+project(GroupView)
+
+set(CMAKE_AUTOMOC ON)
+
+IF(APPLE)
+ message(STATUS "Using APPLE CMAKE_CXX_FLAGS")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
+ELSEIF(UNIX)
+ # assume GCC, add C++0x/C++11 stuff
+ MESSAGE(STATUS "Using UNIX CMAKE_CXX_FLAGS")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
+ELSEIF(MINGW)
+ MESSAGE(STATUS "Using MINGW CMAKE_CXX_FLAGS")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall")
+ENDIF()
+
+find_package(Qt5Core REQUIRED)
+find_package(Qt5Gui REQUIRED)
+find_package(Qt5Widgets REQUIRED)
+
+include_directories(${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS})
+
+set(SOURCES
+ main.cpp
+
+ CategorizedView.h
+ CategorizedView.cpp
+ CategorizedProxyModel.h
+ CategorizedProxyModel.cpp
+)
+
+add_executable(GroupView ${SOURCES})
+qt5_use_modules(GroupView Core Gui Widgets)
diff --git a/CategorizedProxyModel.cpp b/CategorizedProxyModel.cpp
new file mode 100644
index 00000000..2b54ce1b
--- /dev/null
+++ b/CategorizedProxyModel.cpp
@@ -0,0 +1,12 @@
+#include "CategorizedProxyModel.h"
+
+#include "CategorizedView.h"
+
+CategorizedProxyModel::CategorizedProxyModel(QObject *parent)
+ : QSortFilterProxyModel(parent)
+{
+}
+bool CategorizedProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
+{
+ return left.data(CategorizedView::CategoryRole).toString() < right.data(CategorizedView::CategoryRole).toString();
+}
diff --git a/CategorizedProxyModel.h b/CategorizedProxyModel.h
new file mode 100644
index 00000000..6e4f3fdc
--- /dev/null
+++ b/CategorizedProxyModel.h
@@ -0,0 +1,18 @@
+#ifndef CATEGORIZEDPROXYMODEL_H
+#define CATEGORIZEDPROXYMODEL_H
+
+#include <QSortFilterProxyModel>
+
+class CategorizedProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ CategorizedProxyModel(QObject *parent = 0);
+
+protected:
+ bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
+};
+
+
+#endif // CATEGORIZEDPROXYMODEL_H
diff --git a/CategorizedView.cpp b/CategorizedView.cpp
new file mode 100644
index 00000000..46b1e072
--- /dev/null
+++ b/CategorizedView.cpp
@@ -0,0 +1,587 @@
+#include "CategorizedView.h"
+
+#include <QPainter>
+#include <QApplication>
+#include <QtMath>
+#include <QDebug>
+#include <QMouseEvent>
+
+CategorizedView::Category::Category(const QString &text, CategorizedView *view)
+ : view(view), text(text), collapsed(false)
+{
+}
+CategorizedView::Category::Category(const CategorizedView::Category *other) :
+ view(other->view), text(other->text), collapsed(other->collapsed), iconRect(other->iconRect), textRect(other->textRect)
+{
+}
+
+void CategorizedView::Category::drawHeader(QPainter *painter, const int y)
+{
+ painter->save();
+
+ int height = headerHeight() - 4;
+ int collapseSize = height;
+
+ // the icon
+ iconRect = QRect(view->m_rightMargin + 2, 2 + y, collapseSize, collapseSize);
+ painter->setPen(QPen(Qt::black, 1));
+ painter->drawRect(iconRect);
+ static const int margin = 2;
+ QRect iconSubrect = iconRect.adjusted(margin, margin, -margin, -margin);
+ int midX = iconSubrect.center().x();
+ int midY = iconSubrect.center().y();
+ if (collapsed)
+ {
+ painter->drawLine(midX, iconSubrect.top(), midX, iconSubrect.bottom());
+ }
+ painter->drawLine(iconSubrect.left(), midY, iconSubrect.right(), midY);
+
+ // the text
+ int textWidth = painter->fontMetrics().width(text);
+ textRect = QRect(iconRect.right() + 4, y, textWidth, headerHeight());
+ painter->drawText(textRect, text, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter));
+
+ // the line
+ painter->drawLine(textRect.right() + 4, y + headerHeight() / 2, view->contentWidth() - view->m_rightMargin, y + headerHeight() / 2);
+
+ painter->restore();
+}
+
+int CategorizedView::Category::totalHeight() const
+{
+ return headerHeight() + 5 + contentHeight();
+}
+int CategorizedView::Category::headerHeight() const
+{
+ return qApp->fontMetrics().height() + 4;
+}
+int CategorizedView::Category::contentHeight() const
+{
+ if (collapsed)
+ {
+ return 0;
+ }
+ const int rows = qMax(1, qCeil((qreal)view->numItemsForCategory(this) / (qreal)view->itemsPerRow()));
+ return view->itemSize().height() * rows;
+}
+QSize CategorizedView::Category::categoryTotalSize() const
+{
+ return QSize(view->contentWidth(), contentHeight());
+}
+
+CategorizedView::CategorizedView(QWidget *parent)
+ : QListView(parent), m_leftMargin(5), m_rightMargin(5), m_categoryMargin(5)//, m_updatesDisabled(false), m_categoryEditor(0), m_editedCategory(0)
+{
+ setViewMode(IconMode);
+ setMovement(Snap);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ setWordWrap(true);
+}
+
+CategorizedView::~CategorizedView()
+{
+ qDeleteAll(m_categories);
+ m_categories.clear();
+}
+
+void CategorizedView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
+{
+// if (m_updatesDisabled)
+// {
+// return;
+// }
+
+ QListView::dataChanged(topLeft, bottomRight, roles);
+
+ if (roles.contains(CategoryRole))
+ {
+ updateGeometries();
+ update();
+ }
+}
+void CategorizedView::rowsInserted(const QModelIndex &parent, int start, int end)
+{
+// if (m_updatesDisabled)
+// {
+// return;
+// }
+
+ QListView::rowsInserted(parent, start, end);
+
+ updateGeometries();
+ update();
+}
+void CategorizedView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+{
+// if (m_updatesDisabled)
+// {
+// return;
+// }
+
+ QListView::rowsAboutToBeRemoved(parent, start, end);
+
+ updateGeometries();
+ update();
+}
+
+void CategorizedView::updateGeometries()
+{
+ QListView::updateGeometries();
+
+ m_cachedItemSize = QSize();
+
+ QMap<QString, Category *> cats;
+
+ for (int i = 0; i < model()->rowCount(); ++i)
+ {
+ const QString category = model()->index(i, 0).data(CategoryRole).toString();
+ if (!cats.contains(category))
+ {
+ Category *old = this->category(category);
+ if (old)
+ {
+ cats.insert(category, new Category(old));
+ }
+ else
+ {
+ cats.insert(category, new Category(category, this));
+ }
+ }
+ }
+
+ /*if (m_editedCategory)
+ {
+ m_editedCategory = cats[m_editedCategory->text];
+ }*/
+
+ qDeleteAll(m_categories);
+ m_categories = cats.values();
+
+ update();
+}
+
+bool CategorizedView::isIndexHidden(const QModelIndex &index) const
+{
+ Category *cat = category(index);
+ if (cat)
+ {
+ return cat->collapsed;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+CategorizedView::Category *CategorizedView::category(const QModelIndex &index) const
+{
+ return category(index.data(CategoryRole).toString());
+}
+CategorizedView::Category *CategorizedView::category(const QString &cat) const
+{
+ for (int i = 0; i < m_categories.size(); ++i)
+ {
+ if (m_categories.at(i)->text == cat)
+ {
+ return m_categories.at(i);
+ }
+ }
+ return 0;
+}
+
+int CategorizedView::numItemsForCategory(const CategorizedView::Category *category) const
+{
+ return itemsForCategory(category).size();
+}
+QList<QModelIndex> CategorizedView::itemsForCategory(const CategorizedView::Category *category) const
+{
+ QList<QModelIndex> indices;
+ for (int i = 0; i < model()->rowCount(); ++i)
+ {
+ if (model()->index(i, 0).data(CategoryRole).toString() == category->text)
+ {
+ indices += model()->index(i, 0);
+ }
+ }
+ return indices;
+}
+
+int CategorizedView::categoryTop(const CategorizedView::Category *category) const
+{
+ int res = 0;
+ const QList<Category *> cats = sortedCategories();
+ for (int i = 0; i < cats.size(); ++i)
+ {
+ if (cats.at(i) == category)
+ {
+ break;
+ }
+ res += cats.at(i)->totalHeight() + m_categoryMargin;
+ }
+ return res;
+}
+
+int CategorizedView::itemsPerRow() const
+{
+ return qFloor((qreal)contentWidth() / (qreal)itemSize().width());
+}
+int CategorizedView::contentWidth() const
+{
+ return width() - m_leftMargin - m_rightMargin;
+}
+
+bool CategorizedView::lessThanCategoryPointer(const CategorizedView::Category *c1, const CategorizedView::Category *c2)
+{
+ return c1->text < c2->text;
+}
+QList<CategorizedView::Category *> CategorizedView::sortedCategories() const
+{
+ QList<Category *> out = m_categories;
+ qSort(out.begin(), out.end(), &CategorizedView::lessThanCategoryPointer);
+ return out;
+}
+
+QSize CategorizedView::itemSize(const QStyleOptionViewItem &option) const
+{
+ if (!m_cachedItemSize.isValid())
+ {
+ QModelIndex sample = model()->index(model()->rowCount() -1, 0);
+ const QAbstractItemDelegate *delegate = itemDelegate();
+ if (delegate)
+ {
+ m_cachedItemSize = delegate->sizeHint(option, sample);
+ m_cachedItemSize.setWidth(m_cachedItemSize.width() + 20);
+ m_cachedItemSize.setHeight(m_cachedItemSize.height() + 20);
+ }
+ else
+ {
+ m_cachedItemSize = QSize();
+ }
+ }
+ return m_cachedItemSize;
+}
+
+void CategorizedView::mousePressEvent(QMouseEvent *event)
+{
+ //endCategoryEditor();
+
+ if (event->buttons() & Qt::LeftButton)
+ {
+ foreach (Category *category, m_categories)
+ {
+ if (category->iconRect.contains(event->pos()))
+ {
+ category->collapsed = !category->collapsed;
+ updateGeometries();
+ viewport()->update();
+ event->accept();
+ return;
+ }
+ }
+
+ for (int i = 0; i < model()->rowCount(); ++i)
+ {
+ QModelIndex index = model()->index(i, 0);
+ if (visualRect(index).contains(event->pos()))
+ {
+ selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
+ event->accept();
+ return;
+ }
+ }
+ }
+
+ QListView::mousePressEvent(event);
+}
+void CategorizedView::mouseMoveEvent(QMouseEvent *event)
+{
+ if (event->buttons() & Qt::LeftButton)
+ {
+ for (int i = 0; i < model()->rowCount(); ++i)
+ {
+ QModelIndex index = model()->index(i, 0);
+ if (visualRect(index).contains(event->pos()))
+ {
+ selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
+ event->accept();
+ return;
+ }
+ }
+ }
+
+ QListView::mouseMoveEvent(event);
+}
+void CategorizedView::mouseReleaseEvent(QMouseEvent *event)
+{
+ if (event->buttons() & Qt::LeftButton)
+ {
+ for (int i = 0; i < model()->rowCount(); ++i)
+ {
+ QModelIndex index = model()->index(i, 0);
+ if (visualRect(index).contains(event->pos()))
+ {
+ selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
+ event->accept();
+ return;
+ }
+ }
+ }
+
+ QListView::mouseReleaseEvent(event);
+}
+void CategorizedView::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ /*endCategoryEditor();
+
+ foreach (Category *category, m_categories)
+ {
+ if (category->textRect.contains(event->pos()) && m_categoryEditor == 0)
+ {
+ startCategoryEditor(category);
+ event->accept();
+ return;
+ }
+ }*/
+
+ QListView::mouseDoubleClickEvent(event);
+}
+void CategorizedView::paintEvent(QPaintEvent *event)
+{
+ QPainter painter(this->viewport());
+
+ int y = 0;
+ for (int i = 0; i < m_categories.size(); ++i)
+ {
+ Category *category = m_categories.at(i);
+ category->drawHeader(&painter, y);
+ y += category->totalHeight() + m_categoryMargin;
+ }
+
+ for (int i = 0; i < model()->rowCount(); ++i)
+ {
+ const QModelIndex index = model()->index(i, 0);
+ if (isIndexHidden(index))
+ {
+ continue;
+ }
+ Qt::ItemFlags flags = index.flags();
+ QStyleOptionViewItemV4 option(viewOptions());
+ option.rect = visualRect(index);
+ option.widget = this;
+ option.features |= wordWrap() ? QStyleOptionViewItemV2::WrapText : QStyleOptionViewItemV2::None;
+ if (flags & Qt::ItemIsSelectable)
+ {
+ 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))
+ {
+ option.state &= ~QStyle::State_Enabled;
+ }
+ itemDelegate()->paint(&painter, option, index);
+ }
+}
+void CategorizedView::resizeEvent(QResizeEvent *event)
+{
+ QListView::resizeEvent(event);
+
+// if (m_categoryEditor)
+// {
+// m_categoryEditor->resize(qMax(contentWidth() / 2, m_editedCategory->textRect.width()), m_categoryEditor->height());
+// }
+
+ updateGeometries();
+}
+
+void CategorizedView::dragEnterEvent(QDragEnterEvent *event)
+{
+ // TODO
+}
+void CategorizedView::dragMoveEvent(QDragMoveEvent *event)
+{
+ // TODO
+}
+void CategorizedView::dragLeaveEvent(QDragLeaveEvent *event)
+{
+ // TODO
+}
+void CategorizedView::dropEvent(QDropEvent *event)
+{
+ stopAutoScroll();
+ setState(NoState);
+
+ if (event->source() != this || !(event->possibleActions() & Qt::MoveAction))
+ {
+ return;
+ }
+
+ // check that we aren't on a category header and calculate which category we're in
+ Category *category = 0;
+ {
+ int y = 0;
+ foreach (Category *cat, m_categories)
+ {
+ if (event->pos().y() > y && event->pos().y() < (y + cat->headerHeight()))
+ {
+ viewport()->update();
+ return;
+ }
+ y += cat->totalHeight() + m_categoryMargin;
+ if (event->pos().y() < y)
+ {
+ category = cat;
+ break;
+ }
+ }
+ }
+
+ // calculate the internal column
+ int internalColumn = -1;
+ {
+ const int itemWidth = itemSize().width();
+ for (int i = 0, c = 0;
+ i < contentWidth();
+ i += itemWidth, ++c)
+ {
+ if (event->pos().x() > (i - itemWidth / 2) &&
+ event->pos().x() < (i + itemWidth / 2))
+ {
+ internalColumn = c;
+ break;
+ }
+ }
+ if (internalColumn == -1)
+ {
+ viewport()->update();
+ return;
+ }
+ }
+
+ // calculate the internal row
+ int internalRow = -1;
+ {
+ const int itemHeight = itemSize().height();
+ const int top = categoryTop(category);
+ for (int i = top + category->headerHeight(), r = 0;
+ i < top + category->totalHeight();
+ i += itemHeight, ++r)
+ {
+ if (event->pos().y() > i && event->pos().y() < (i + itemHeight))
+ {
+ internalRow = r;
+ break;
+ }
+ }
+ if (internalRow == -1)
+ {
+ viewport()->update();
+ return;
+ }
+ }
+
+ QList<QModelIndex> indices = itemsForCategory(category);
+
+ // flaten the internalColumn/internalRow to one row
+ int categoryRow;
+ {
+ for (int i = 0; i < internalRow; ++i)
+ {
+ if (i == internalRow)
+ {
+ break;
+ }
+ categoryRow += itemsPerRow();
+ }
+ categoryRow += internalColumn;
+ }
+
+ int row = indices.at(categoryRow).row();
+ if (model()->dropMimeData(event->mimeData(), Qt::MoveAction, row, 0, QModelIndex()))
+ {
+ event->setDropAction(Qt::MoveAction);
+ event->accept();
+ }
+ updateGeometries();
+}
+
+bool lessThanQModelIndex(const QModelIndex &i1, const QModelIndex &i2)
+{
+ return i1.data() < i2.data();
+}
+QRect CategorizedView::visualRect(const QModelIndex &index) const
+{
+ if (!index.isValid() || isIndexHidden(index) || index.column() > 0)
+ {
+ return QRect();
+ }
+
+ const Category *cat = category(index);
+ QList<QModelIndex> indices = itemsForCategory(cat);
+ qSort(indices.begin(), indices.end(), &lessThanQModelIndex);
+ 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;
+ }
+ }
+
+ QSize size = itemSize();
+
+ QRect out;
+ out.setTop(categoryTop(cat) + cat->headerHeight() + 5 + y * size.height());
+ out.setLeft(x * size.width());
+ out.setSize(size);
+
+ 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);
+}
+
+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();
+}
+*/
diff --git a/CategorizedView.h b/CategorizedView.h
new file mode 100644
index 00000000..1e918496
--- /dev/null
+++ b/CategorizedView.h
@@ -0,0 +1,96 @@
+#ifndef WIDGET_H
+#define WIDGET_H
+
+#include <QListView>
+#include <QLineEdit>
+
+class CategorizedView : public QListView
+{
+ Q_OBJECT
+
+public:
+ CategorizedView(QWidget *parent = 0);
+ ~CategorizedView();
+
+ enum
+ {
+ CategoryRole = Qt::UserRole
+ };
+
+ virtual QRect visualRect(const QModelIndex &index) const;
+
+protected slots:
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
+ virtual void rowsInserted(const QModelIndex &parent, int start, int end);
+ virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ virtual void updateGeometries();
+
+protected:
+ virtual bool isIndexHidden(const QModelIndex &index) const;
+ 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;
+
+private:
+ struct Category
+ {
+ Category(const QString &text, CategorizedView *view);
+ Category(const Category *other);
+ CategorizedView *view;
+ QString text;
+ bool collapsed;
+ QRect iconRect;
+ QRect textRect;
+
+ void drawHeader(QPainter *painter, const int y);
+ int totalHeight() const;
+ int headerHeight() const;
+ int contentHeight() const;
+ QSize categoryTotalSize() const;
+ };
+ friend struct Category;
+
+ QList<Category *> m_categories;
+
+ int m_leftMargin;
+ int m_rightMargin;
+ int m_categoryMargin;
+ int m_itemSpacing;
+
+ //bool m_updatesDisabled;
+
+ Category *category(const QModelIndex &index) const;
+ Category *category(const QString &cat) const;
+ int numItemsForCategory(const Category *category) const;
+ QList<QModelIndex> itemsForCategory(const Category *category) const;
+
+ int categoryTop(const Category *category) const;
+
+ int itemsPerRow() const;
+ int contentWidth() const;
+
+ static bool lessThanCategoryPointer(const Category *c1, const Category *c2);
+ QList<Category *> sortedCategories() const;
+
+private:
+ mutable QSize m_cachedItemSize;
+ QSize itemSize(const QStyleOptionViewItem &option) const;
+ QSize itemSize() const { return itemSize(viewOptions()); }
+
+ /*QLineEdit *m_categoryEditor;
+ Category *m_editedCategory;
+ void startCategoryEditor(Category *category);
+
+private slots:
+ void endCategoryEditor();*/
+};
+
+#endif // WIDGET_H
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 00000000..24d7075e
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,53 @@
+#include "CategorizedView.h"
+#include <QApplication>
+#include <QStandardItemModel>
+
+#include "CategorizedProxyModel.h"
+
+QPixmap icon(const Qt::GlobalColor color)
+{
+ QPixmap p = QPixmap(32, 32);
+ p.fill(QColor(color));
+ return p;
+}
+QStandardItem *createItem(const Qt::GlobalColor color, const QString &text, const QString &category)
+{
+ QStandardItem *item = new QStandardItem;
+ item->setText(text);
+ item->setData(icon(color), Qt::DecorationRole);
+ item->setData(category, CategorizedView::CategoryRole);
+ item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+ return item;
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+
+ QStandardItemModel model;
+ model.setRowCount(10);
+ model.setColumnCount(1);
+
+ model.setItem(0, createItem(Qt::red, "Red", "Colorful"));
+ model.setItem(1, createItem(Qt::blue, "Blue", "Colorful"));
+ model.setItem(2, createItem(Qt::yellow, "Yellow", "Colorful"));
+
+ model.setItem(3, createItem(Qt::black, "Black", "Not Colorful"));
+ model.setItem(4, createItem(Qt::darkGray, "Dark Gray", "Not Colorful"));
+ model.setItem(5, createItem(Qt::gray, "Gray", "Not Colorful"));
+ model.setItem(6, createItem(Qt::lightGray, "Light Gray", "Not Colorful"));
+ model.setItem(7, createItem(Qt::white, "White", "Not Colorful"));
+
+ model.setItem(8, createItem(Qt::darkGreen, "Dark Green", ""));
+ model.setItem(9, createItem(Qt::green, "Green", ""));
+
+ CategorizedProxyModel pModel;
+ pModel.setSourceModel(&model);
+
+ CategorizedView w;
+ w.setModel(&pModel);
+ w.resize(640, 480);
+ w.show();
+
+ return a.exec();
+}