| |
| |
| #include "toonzqt/treemodel.h" |
| |
| #include <QStringList> |
| #include <QTreeView> |
| #include <QHeaderView> |
| #include <QMouseEvent> |
| #include <qvariant.h> |
| #include <qicon.h> |
| #include <qtextedit.h> |
| |
| #include "tfx.h" |
| #include <assert.h> |
| |
| |
| |
| |
| |
| TreeModel::Item::Item() |
| : m_model(0), m_parent(0), m_depth(0), m_row(0), m_opened(false) |
| { |
| } |
| |
| |
| |
| TreeModel::Item::~Item() |
| { |
| qDeleteAll(m_childItems); |
| m_childItems.clear(); |
| m_model = 0; |
| m_row = 0; |
| m_depth = 0; |
| m_parent = 0; |
| } |
| |
| |
| |
| void TreeModel::Item::updateChild(Item *child, int row) |
| { |
| assert(m_model); |
| child->m_model = m_model; |
| child->m_depth = m_depth + 1; |
| child->m_parent = this; |
| child->m_row = row; |
| } |
| |
| |
| |
| void TreeModel::Item::updateChildren() |
| { |
| int i; |
| for (i = 0; i < m_childItems.size(); i++) |
| updateChild(m_childItems[i], i); |
| } |
| |
| |
| |
| TreeModel::Item *TreeModel::Item::appendChild(TreeModel::Item *child) |
| { |
| assert(child); |
| assert(!m_childItems.contains(child)); |
| updateChild(child, m_childItems.size()); |
| m_childItems.append(child); |
| return child; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| void TreeModel::Item::setChildren(QList<Item *> &newChildren) |
| { |
| assert(m_model); |
| QModelIndex itemIndex = createIndex(); |
| |
| |
| QList<Item *> oldChildren(m_childItems); |
| m_childItems.clear(); |
| int i; |
| |
| |
| for (i = 0; i < newChildren.size(); i++) { |
| Item *newChild = newChildren.at(i); |
| void *newInternalPointer = newChild->getInternalPointer(); |
| if (newInternalPointer != 0) { |
| |
| int j; |
| for (j = 0; j < oldChildren.size(); j++) |
| if (oldChildren.at(j)->getInternalPointer() == newInternalPointer) |
| break; |
| if (j < oldChildren.size()) { |
| Item *oldChild = oldChildren.takeAt(j); |
| if (oldChild != newChild) { |
| |
| |
| delete newChild; |
| newChildren.takeAt(i); |
| i--; |
| |
| newChild = oldChild; |
| oldChild->refresh(); |
| } else { |
| |
| assert(0); |
| } |
| } |
| } |
| |
| m_childItems.push_back(newChild); |
| } |
| |
| updateChildren(); |
| |
| |
| |
| |
| for (i = 0; i < oldChildren.size(); i++) { |
| Item *itemToDelete = oldChildren[i]; |
| if (!m_model->m_itemsToDelete.contains(itemToDelete)) |
| m_model->m_itemsToDelete.push_back(itemToDelete); |
| } |
| } |
| |
| |
| |
| QVariant TreeModel::Item::data(int role) const |
| { |
| if (role == Qt::DecorationRole) |
| return QIcon(isOpen() |
| ? ":Resources/folder_open.png" |
| : ":Resources/folder_close.png"); |
| else |
| return QVariant(); |
| } |
| |
| |
| |
| QModelIndex TreeModel::Item::createIndex() |
| { |
| return m_parent ? m_model->createIndex(m_row, 0, this) : QModelIndex(); |
| } |
| |
| |
| |
| |
| |
| TreeModel::TreeModel(TreeView *parent) |
| : QAbstractItemModel(parent), m_rootItem(0), m_view(parent) |
| { |
| } |
| |
| |
| |
| TreeModel::~TreeModel() |
| { |
| delete m_rootItem; |
| } |
| |
| |
| |
| void TreeModel::setExpandedItem(const QModelIndex &index, bool expanded) |
| { |
| m_view->setExpanded(index, expanded); |
| } |
| |
| |
| |
| void TreeModel::beginRefresh() |
| { |
| emit layoutAboutToBeChanged(); |
| } |
| |
| |
| |
| void TreeModel::endRefresh() |
| { |
| QList<QModelIndex> oldIndices, newIndices; |
| int i; |
| QList<Item *>::iterator it; |
| |
| for (i = m_itemsToDelete.size() - 1; i >= 0; i--) { |
| int row = m_itemsToDelete[i]->getRow(); |
| Item *parentItem = m_itemsToDelete[i]->getParent(); |
| QModelIndex parentIndex = parentItem ? parentItem->createIndex() : QModelIndex(); |
| |
| beginRemoveRows(parentIndex, row, row); |
| removeRow(row, parentIndex); |
| endRemoveRows(); |
| } |
| |
| qDeleteAll(m_itemsToDelete); |
| m_itemsToDelete.clear(); |
| |
| if (!persistentIndexList().empty()) { |
| for (i = 0; i < persistentIndexList().size(); i++) { |
| QModelIndex oldIndex = persistentIndexList()[i]; |
| Item *item = static_cast<Item *>(oldIndex.internalPointer()); |
| if (item) { |
| QModelIndex newIndex = item->createIndex(); |
| if (oldIndex != newIndex) { |
| oldIndices.push_back(oldIndex); |
| newIndices.push_back(newIndex); |
| } |
| } |
| } |
| changePersistentIndexList(oldIndices, newIndices); |
| } |
| |
| emit layoutChanged(); |
| } |
| |
| |
| |
| int TreeModel::columnCount(const QModelIndex &parent) const |
| { |
| return 1; |
| } |
| |
| |
| |
| Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const |
| { |
| if (!index.isValid()) |
| return 0; |
| return Qt::ItemIsEnabled | Qt::ItemIsSelectable; |
| } |
| |
| |
| |
| QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const |
| { |
| |
| if (column != 0) |
| return QModelIndex(); |
| |
| Item *parentItem = parent.isValid() ? (Item *)(parent.internalPointer()) : m_rootItem; |
| |
| if (!parentItem) |
| return QModelIndex(); |
| |
| int childCount = parentItem->getChildCount(); |
| if (row < 0 || row >= childCount) |
| return QModelIndex(); |
| |
| Item *item = parentItem->getChild(row); |
| if (!item) |
| return QModelIndex(); |
| return item->createIndex(); |
| } |
| |
| |
| |
| QModelIndex TreeModel::parent(const QModelIndex &index) const |
| { |
| if (!index.isValid()) |
| return QModelIndex(); |
| |
| Item *item = (Item *)index.internalPointer(); |
| |
| TreeModel::Item *parentItem = item->getParent(); |
| |
| if (!parentItem || parentItem == m_rootItem) |
| return QModelIndex(); |
| |
| return parentItem->createIndex(); |
| } |
| |
| |
| |
| int TreeModel::rowCount(const QModelIndex &parent) const |
| { |
| if (parent.column() > 0) |
| return 0; |
| |
| if (!parent.isValid()) |
| return m_rootItem ? m_rootItem->getChildCount() : 0; |
| else |
| return ((Item *)(parent.internalPointer()))->getChildCount(); |
| } |
| |
| |
| |
| void TreeModel::onExpanded(const QModelIndex &index) |
| { |
| if (!index.isValid()) |
| return; |
| |
| Item *item = (Item *)(index.internalPointer()); |
| item->setIsOpen(true); |
| } |
| |
| |
| |
| void TreeModel::onCollapsed(const QModelIndex &index) |
| { |
| if (!index.isValid()) |
| return; |
| |
| Item *item = (Item *)(index.internalPointer()); |
| item->setIsOpen(false); |
| } |
| |
| |
| |
| QVariant TreeModel::data(const QModelIndex &index, int role) const |
| { |
| if (!index.isValid()) |
| return QVariant(); |
| Item *item = static_cast<Item *>(index.internalPointer()); |
| return item->data(role); |
| } |
| |
| |
| |
| void TreeModel::setRootItem(Item *rootItem) |
| { |
| if (rootItem == m_rootItem) |
| return; |
| delete m_rootItem; |
| m_rootItem = rootItem; |
| if (m_rootItem) |
| m_rootItem->setModel(this); |
| } |
| |
| |
| |
| void TreeModel::setRowHidden(int row, const QModelIndex &parent, bool hide) |
| { |
| m_view->setRowHidden(row, parent, hide); |
| } |
| |
| |
| |
| |
| |
| TreeView::TreeView(QWidget *parent) |
| : QTreeView(parent), m_dragging(false) |
| { |
| header()->hide(); |
| setUniformRowHeights(true); |
| setIconSize(QSize(32, 32)); |
| } |
| |
| |
| |
| |
| void TreeView::resizeToConts(void) |
| { |
| resizeColumnToContents(0); |
| } |
| |
| |
| |
| void TreeView::resizeEvent(QResizeEvent *event) |
| { |
| resizeColumnToContents(0); |
| QTreeView::resizeEvent(event); |
| } |
| |
| |
| |
| void TreeView::setModel(TreeModel *model) |
| { |
| QTreeView::setModel(model); |
| disconnect(); |
| |
| connect(this, SIGNAL(expanded(const QModelIndex &)), model, SLOT(onExpanded(const QModelIndex &))); |
| connect(this, SIGNAL(collapsed(const QModelIndex &)), model, SLOT(onCollapsed(const QModelIndex &))); |
| |
| |
| |
| |
| connect( |
| this, SIGNAL(expanded(const QModelIndex &)), |
| this, SLOT(resizeToConts())); |
| |
| connect( |
| this, SIGNAL(collapsed(const QModelIndex &)), |
| this, SLOT(resizeToConts())); |
| |
| connect( |
| this->model(), SIGNAL(layoutChanged()), |
| this, SLOT(resizeToConts())); |
| } |
| |
| |
| |
| void TreeView::mouseDoubleClickEvent(QMouseEvent *) |
| { |
| |
| } |
| |
| void TreeView::mousePressEvent(QMouseEvent *e) |
| { |
| if (e->button() != Qt::RightButton) |
| QTreeView::mousePressEvent(e); |
| QModelIndex index = indexAt(e->pos()); |
| if (index.isValid()) { |
| TreeModel::Item *item = static_cast<TreeModel::Item *>(index.internalPointer()); |
| QRect itemRect = visualRect(index); |
| QPoint itemPos = e->pos() - itemRect.topLeft(); |
| if (e->button() == Qt::RightButton) { |
| if (selectionMode() != QAbstractItemView::ExtendedSelection) |
| setCurrentIndex(item->createIndex()); |
| onClick(item, itemPos, e); |
| openContextMenu(item, e->globalPos()); |
| } else if (e->button() == Qt::LeftButton) { |
| m_dragging = true; |
| setMouseTracking(true); |
| onClick(item, itemPos, e); |
| } |
| |
| else if (e->button() == Qt::MidButton) { |
| m_dragging = true; |
| setMouseTracking(true); |
| onMidClick(item, itemPos, e); |
| } |
| } |
| } |
| |
| |
| |
| void TreeView::mouseMoveEvent(QMouseEvent *e) |
| { |
| QTreeView::mouseMoveEvent(e); |
| if (m_dragging) { |
| QModelIndex index = indexAt(e->pos()); |
| if (index.isValid()) { |
| TreeModel::Item *item = static_cast<TreeModel::Item *>(index.internalPointer()); |
| QRect itemRect = visualRect(index); |
| QPoint itemPos = e->pos() - itemRect.topLeft(); |
| onDrag(item, itemPos, e); |
| } |
| } |
| } |
| |
| |
| |
| void TreeView::mouseReleaseEvent(QMouseEvent *e) |
| { |
| QTreeView::mouseReleaseEvent(e); |
| if (m_dragging) { |
| m_dragging = false; |
| setMouseTracking(false); |
| onRelease(); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |