Add multiple select on parts tree
parent
0bf64eeb2d
commit
94d63237e7
|
@ -1489,6 +1489,27 @@ void SkeletonDocument::createNewComponentAndMoveThisIn(QUuid componentId)
|
||||||
emit optionsChanged();
|
emit optionsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkeletonDocument::createNewChildComponent(QUuid parentComponentId)
|
||||||
|
{
|
||||||
|
SkeletonComponent *parentComponent = (SkeletonComponent *)findComponent(parentComponentId);
|
||||||
|
if (!parentComponent->linkToPartId.isNull()) {
|
||||||
|
parentComponentId = parentComponent->parentId;
|
||||||
|
parentComponent = (SkeletonComponent *)findComponent(parentComponentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
SkeletonComponent newComponent(QUuid::createUuid());
|
||||||
|
newComponent.name = tr("Group") + " " + QString::number(componentMap.size() - partMap.size() + 1);
|
||||||
|
|
||||||
|
parentComponent->addChild(newComponent.id);
|
||||||
|
newComponent.parentId = parentComponentId;
|
||||||
|
|
||||||
|
componentMap[newComponent.id] = newComponent;
|
||||||
|
|
||||||
|
emit componentChildrenChanged(parentComponentId);
|
||||||
|
emit componentAdded(newComponent.id);
|
||||||
|
emit optionsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void SkeletonDocument::removePart(QUuid partId)
|
void SkeletonDocument::removePart(QUuid partId)
|
||||||
{
|
{
|
||||||
auto part = partMap.find(partId);
|
auto part = partMap.find(partId);
|
||||||
|
@ -1613,6 +1634,20 @@ void SkeletonDocument::removeComponentRecursively(QUuid componentId)
|
||||||
void SkeletonDocument::setCurrentCanvasComponentId(QUuid componentId)
|
void SkeletonDocument::setCurrentCanvasComponentId(QUuid componentId)
|
||||||
{
|
{
|
||||||
m_currentCanvasComponentId = componentId;
|
m_currentCanvasComponentId = componentId;
|
||||||
|
const SkeletonComponent *component = findComponent(m_currentCanvasComponentId);
|
||||||
|
if (nullptr == component) {
|
||||||
|
//qDebug() << "Current component switch to nullptr componentId:" << componentId;
|
||||||
|
m_currentCanvasComponentId = QUuid();
|
||||||
|
} else {
|
||||||
|
//qDebug() << "Current component switch to " << component->name << "componentId:" << componentId;
|
||||||
|
if (!component->linkToPartId.isNull()) {
|
||||||
|
m_currentCanvasComponentId = component->parentId;
|
||||||
|
component = findComponent(m_currentCanvasComponentId);
|
||||||
|
//if (nullptr != component) {
|
||||||
|
// qDebug() << "Then switch to " << component->name << "componentId:" << m_currentCanvasComponentId;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonDocument::addComponent(QUuid parentId)
|
void SkeletonDocument::addComponent(QUuid parentId)
|
||||||
|
@ -1986,7 +2021,7 @@ void SkeletonDocument::collectComponentDescendantParts(QUuid componentId, std::v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonDocument::collectComponentDescendantComponents(QUuid componentId, std::vector<QUuid> &componentIds)
|
void SkeletonDocument::collectComponentDescendantComponents(QUuid componentId, std::vector<QUuid> &componentIds) const
|
||||||
{
|
{
|
||||||
const SkeletonComponent *component = findComponent(componentId);
|
const SkeletonComponent *component = findComponent(componentId);
|
||||||
if (nullptr == component)
|
if (nullptr == component)
|
||||||
|
@ -1996,9 +2031,8 @@ void SkeletonDocument::collectComponentDescendantComponents(QUuid componentId, s
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentIds.push_back(component->id);
|
|
||||||
|
|
||||||
for (const auto &childId: component->childrenIds) {
|
for (const auto &childId: component->childrenIds) {
|
||||||
|
componentIds.push_back(childId);
|
||||||
collectComponentDescendantComponents(childId, componentIds);
|
collectComponentDescendantComponents(childId, componentIds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -428,6 +428,7 @@ public:
|
||||||
bool isPostProcessResultObsolete() const;
|
bool isPostProcessResultObsolete() const;
|
||||||
void findAllNeighbors(QUuid nodeId, std::set<QUuid> &neighbors) const;
|
void findAllNeighbors(QUuid nodeId, std::set<QUuid> &neighbors) const;
|
||||||
void collectComponentDescendantParts(QUuid componentId, std::vector<QUuid> &partIds) const;
|
void collectComponentDescendantParts(QUuid componentId, std::vector<QUuid> &partIds) const;
|
||||||
|
void collectComponentDescendantComponents(QUuid componentId, std::vector<QUuid> &componentIds) const;
|
||||||
public slots:
|
public slots:
|
||||||
void removeNode(QUuid nodeId);
|
void removeNode(QUuid nodeId);
|
||||||
void removeEdge(QUuid edgeId);
|
void removeEdge(QUuid edgeId);
|
||||||
|
@ -473,6 +474,7 @@ public slots:
|
||||||
void moveComponent(QUuid componentId, QUuid toParentId);
|
void moveComponent(QUuid componentId, QUuid toParentId);
|
||||||
void setCurrentCanvasComponentId(QUuid componentId);
|
void setCurrentCanvasComponentId(QUuid componentId);
|
||||||
void createNewComponentAndMoveThisIn(QUuid componentId);
|
void createNewComponentAndMoveThisIn(QUuid componentId);
|
||||||
|
void createNewChildComponent(QUuid parentComponentId);
|
||||||
void setComponentExpandState(QUuid componentId, bool expanded);
|
void setComponentExpandState(QUuid componentId, bool expanded);
|
||||||
void setComponentSmoothAll(QUuid componentId, float toSmoothAll);
|
void setComponentSmoothAll(QUuid componentId, float toSmoothAll);
|
||||||
void setComponentSmoothSeam(QUuid componentId, float toSmoothSeam);
|
void setComponentSmoothSeam(QUuid componentId, float toSmoothSeam);
|
||||||
|
@ -513,7 +515,6 @@ private:
|
||||||
void addPartToComponent(QUuid partId, QUuid componentId);
|
void addPartToComponent(QUuid partId, QUuid componentId);
|
||||||
bool isDescendantComponent(QUuid componentId, QUuid suspiciousId);
|
bool isDescendantComponent(QUuid componentId, QUuid suspiciousId);
|
||||||
void removeComponentRecursively(QUuid componentId);
|
void removeComponentRecursively(QUuid componentId);
|
||||||
void collectComponentDescendantComponents(QUuid componentId, std::vector<QUuid> &componentIds);
|
|
||||||
void resetDirtyFlags();
|
void resetDirtyFlags();
|
||||||
void markAllDirty();
|
void markAllDirty();
|
||||||
private: // need initialize
|
private: // need initialize
|
||||||
|
|
|
@ -594,6 +594,7 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
|
||||||
connect(partTreeWidget, &SkeletonPartTreeWidget::moveComponentToBottom, m_document, &SkeletonDocument::moveComponentToBottom);
|
connect(partTreeWidget, &SkeletonPartTreeWidget::moveComponentToBottom, m_document, &SkeletonDocument::moveComponentToBottom);
|
||||||
connect(partTreeWidget, &SkeletonPartTreeWidget::checkPart, m_document, &SkeletonDocument::checkPart);
|
connect(partTreeWidget, &SkeletonPartTreeWidget::checkPart, m_document, &SkeletonDocument::checkPart);
|
||||||
connect(partTreeWidget, &SkeletonPartTreeWidget::createNewComponentAndMoveThisIn, m_document, &SkeletonDocument::createNewComponentAndMoveThisIn);
|
connect(partTreeWidget, &SkeletonPartTreeWidget::createNewComponentAndMoveThisIn, m_document, &SkeletonDocument::createNewComponentAndMoveThisIn);
|
||||||
|
connect(partTreeWidget, &SkeletonPartTreeWidget::createNewChildComponent, m_document, &SkeletonDocument::createNewChildComponent);
|
||||||
connect(partTreeWidget, &SkeletonPartTreeWidget::renameComponent, m_document, &SkeletonDocument::renameComponent);
|
connect(partTreeWidget, &SkeletonPartTreeWidget::renameComponent, m_document, &SkeletonDocument::renameComponent);
|
||||||
connect(partTreeWidget, &SkeletonPartTreeWidget::setComponentExpandState, m_document, &SkeletonDocument::setComponentExpandState);
|
connect(partTreeWidget, &SkeletonPartTreeWidget::setComponentExpandState, m_document, &SkeletonDocument::setComponentExpandState);
|
||||||
connect(partTreeWidget, &SkeletonPartTreeWidget::setComponentSmoothAll, m_document, &SkeletonDocument::setComponentSmoothAll);
|
connect(partTreeWidget, &SkeletonPartTreeWidget::setComponentSmoothAll, m_document, &SkeletonDocument::setComponentSmoothAll);
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QWidgetAction>
|
#include <QWidgetAction>
|
||||||
|
#include <QRadialGradient>
|
||||||
|
#include <QBrush>
|
||||||
|
#include <QGuiApplication>
|
||||||
#include "skeletonparttreewidget.h"
|
#include "skeletonparttreewidget.h"
|
||||||
#include "skeletonpartwidget.h"
|
#include "skeletonpartwidget.h"
|
||||||
#include "skeletongraphicswidget.h"
|
#include "skeletongraphicswidget.h"
|
||||||
|
@ -45,77 +48,210 @@ SkeletonPartTreeWidget::SkeletonPartTreeWidget(const SkeletonDocument *document,
|
||||||
|
|
||||||
setFont(m_normalFont);
|
setFont(m_normalFont);
|
||||||
|
|
||||||
|
QRadialGradient gradient(QPointF(0.25, 0.3), 0.3);
|
||||||
|
QColor fillColor = QColor(0xfb, 0xf9, 0x87);
|
||||||
|
fillColor.setAlphaF(0.85);
|
||||||
|
gradient.setCoordinateMode(QGradient::StretchToDeviceMode);
|
||||||
|
gradient.setColorAt(0, fillColor);
|
||||||
|
gradient.setColorAt(1, Qt::transparent);
|
||||||
|
m_hightlightedPartBackground = QBrush(gradient);
|
||||||
|
|
||||||
connect(this, &QTreeWidget::customContextMenuRequested, this, &SkeletonPartTreeWidget::showContextMenu);
|
connect(this, &QTreeWidget::customContextMenuRequested, this, &SkeletonPartTreeWidget::showContextMenu);
|
||||||
connect(this, &QTreeWidget::itemChanged, this, &SkeletonPartTreeWidget::groupChanged);
|
connect(this, &QTreeWidget::itemChanged, this, &SkeletonPartTreeWidget::groupChanged);
|
||||||
connect(this, &QTreeWidget::itemExpanded, this, &SkeletonPartTreeWidget::groupExpanded);
|
connect(this, &QTreeWidget::itemExpanded, this, &SkeletonPartTreeWidget::groupExpanded);
|
||||||
connect(this, &QTreeWidget::itemCollapsed, this, &SkeletonPartTreeWidget::groupCollapsed);
|
connect(this, &QTreeWidget::itemCollapsed, this, &SkeletonPartTreeWidget::groupCollapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonPartTreeWidget::selectComponent(QUuid componentId)
|
void SkeletonPartTreeWidget::selectComponent(QUuid componentId, bool multiple)
|
||||||
{
|
{
|
||||||
if (m_currentSelectedComponent != componentId) {
|
if (multiple) {
|
||||||
if (!m_currentSelectedComponent.isNull()) {
|
if (!m_currentSelectedComponentId.isNull()) {
|
||||||
auto item = m_componentItemMap.find(m_currentSelectedComponent);
|
m_selectedComponentIds.insert(m_currentSelectedComponentId);
|
||||||
if (item != m_componentItemMap.end()) {
|
m_currentSelectedComponentId = QUuid();
|
||||||
item->second->setFont(0, m_normalFont);
|
emit currentComponentChanged(m_currentSelectedComponentId);
|
||||||
|
}
|
||||||
|
if (m_selectedComponentIds.find(componentId) != m_selectedComponentIds.end()) {
|
||||||
|
updateComponentSelectState(componentId, false);
|
||||||
|
m_selectedComponentIds.erase(componentId);
|
||||||
|
} else {
|
||||||
|
updateComponentSelectState(componentId, true);
|
||||||
|
m_selectedComponentIds.insert(componentId);
|
||||||
|
}
|
||||||
|
if (m_selectedComponentIds.size() > 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_selectedComponentIds.size() == 1)
|
||||||
|
componentId = *m_selectedComponentIds.begin();
|
||||||
|
else
|
||||||
|
componentId = QUuid();
|
||||||
|
}
|
||||||
|
if (!m_selectedComponentIds.empty()) {
|
||||||
|
for (const auto &id: m_selectedComponentIds) {
|
||||||
|
updateComponentSelectState(id, false);
|
||||||
|
}
|
||||||
|
m_selectedComponentIds.clear();
|
||||||
|
}
|
||||||
|
if (m_currentSelectedComponentId != componentId) {
|
||||||
|
if (!m_currentSelectedComponentId.isNull()) {
|
||||||
|
updateComponentSelectState(m_currentSelectedComponentId, false);
|
||||||
|
}
|
||||||
|
m_currentSelectedComponentId = componentId;
|
||||||
|
if (!m_currentSelectedComponentId.isNull()) {
|
||||||
|
updateComponentSelectState(m_currentSelectedComponentId, true);
|
||||||
|
}
|
||||||
|
emit currentComponentChanged(m_currentSelectedComponentId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_currentSelectedComponent = componentId;
|
|
||||||
if (!m_currentSelectedComponent.isNull()) {
|
void SkeletonPartTreeWidget::updateComponentSelectState(QUuid componentId, bool selected)
|
||||||
auto item = m_componentItemMap.find(m_currentSelectedComponent);
|
{
|
||||||
|
const SkeletonComponent *component = m_document->findComponent(componentId);
|
||||||
|
if (nullptr == component) {
|
||||||
|
qDebug() << "Component not found:" << componentId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!component->linkToPartId.isNull()) {
|
||||||
|
auto item = m_partItemMap.find(component->linkToPartId);
|
||||||
if (item != m_componentItemMap.end()) {
|
if (item != m_componentItemMap.end()) {
|
||||||
|
SkeletonPartWidget *widget = (SkeletonPartWidget *)itemWidget(item->second, 0);
|
||||||
|
widget->updateCheckedState(selected);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto item = m_componentItemMap.find(componentId);
|
||||||
|
if (item != m_componentItemMap.end()) {
|
||||||
|
if (selected) {
|
||||||
item->second->setFont(0, m_selectedFont);
|
item->second->setFont(0, m_selectedFont);
|
||||||
|
item->second->setForeground(0, QBrush(Theme::red));
|
||||||
|
} else {
|
||||||
|
item->second->setFont(0, m_normalFont);
|
||||||
|
item->second->setForeground(0, QBrush(Theme::white));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit currentComponentChanged(m_currentSelectedComponent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonPartTreeWidget::mousePressEvent(QMouseEvent *event)
|
void SkeletonPartTreeWidget::mousePressEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
QModelIndex itemIndex = indexAt(event->pos());
|
QModelIndex itemIndex = indexAt(event->pos());
|
||||||
QTreeView::mousePressEvent(event);
|
QTreeView::mousePressEvent(event);
|
||||||
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
bool multiple = QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier);
|
||||||
if (itemIndex.isValid()) {
|
if (itemIndex.isValid()) {
|
||||||
QTreeWidgetItem *item = itemFromIndex(itemIndex);
|
QTreeWidgetItem *item = itemFromIndex(itemIndex);
|
||||||
auto componentId = QUuid(item->data(0, Qt::UserRole).toString());
|
auto componentId = QUuid(item->data(0, Qt::UserRole).toString());
|
||||||
if (m_componentItemMap.find(componentId) != m_componentItemMap.end()) {
|
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) {
|
||||||
selectComponent(componentId);
|
if (!m_shiftStartComponentId.isNull()) {
|
||||||
|
const SkeletonComponent *parent = m_document->findComponentParent(m_shiftStartComponentId);
|
||||||
|
if (parent) {
|
||||||
|
if (!parent->childrenIds.empty()) {
|
||||||
|
bool startAdd = false;
|
||||||
|
bool stopAdd = false;
|
||||||
|
std::vector<QUuid> waitQueue;
|
||||||
|
for (const auto &childId: parent->childrenIds) {
|
||||||
|
if (m_shiftStartComponentId == childId || componentId == childId) {
|
||||||
|
if (startAdd) {
|
||||||
|
stopAdd = true;
|
||||||
|
} else {
|
||||||
|
startAdd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (startAdd)
|
||||||
|
waitQueue.push_back(childId);
|
||||||
|
if (stopAdd)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (stopAdd && !waitQueue.empty()) {
|
||||||
|
if (!m_selectedComponentIds.empty()) {
|
||||||
|
for (const auto &id: m_selectedComponentIds) {
|
||||||
|
updateComponentSelectState(id, false);
|
||||||
|
}
|
||||||
|
m_selectedComponentIds.clear();
|
||||||
|
}
|
||||||
|
if (!m_currentSelectedComponentId.isNull()) {
|
||||||
|
m_currentSelectedComponentId = QUuid();
|
||||||
|
emit currentComponentChanged(m_currentSelectedComponentId);
|
||||||
|
}
|
||||||
|
for (const auto &waitId: waitQueue) {
|
||||||
|
selectComponent(waitId, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
m_shiftStartComponentId = componentId;
|
||||||
|
}
|
||||||
|
selectComponent(componentId, multiple);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
item = item->parent();
|
if (!multiple)
|
||||||
if (nullptr != item) {
|
|
||||||
componentId = QUuid(item->data(0, Qt::UserRole).toString());
|
|
||||||
if (m_componentItemMap.find(componentId) != m_componentItemMap.end()) {
|
|
||||||
selectComponent(componentId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selectComponent(QUuid());
|
selectComponent(QUuid());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SkeletonPartTreeWidget::showContextMenu(const QPoint &pos)
|
void SkeletonPartTreeWidget::showContextMenu(const QPoint &pos)
|
||||||
{
|
{
|
||||||
QTreeWidgetItem *item = itemAt(pos);
|
const SkeletonComponent *component = nullptr;
|
||||||
if (nullptr == item)
|
const SkeletonPart *part = nullptr;
|
||||||
return;
|
|
||||||
|
|
||||||
auto componentId = QUuid(item->data(0, Qt::UserRole).toString());
|
std::set<QUuid> unorderedComponentIds = m_selectedComponentIds;
|
||||||
const SkeletonComponent *component = m_document->findComponent(componentId);
|
if (!m_currentSelectedComponentId.isNull())
|
||||||
if (nullptr == component) {
|
unorderedComponentIds.insert(m_currentSelectedComponentId);
|
||||||
qDebug() << "Find component failed:" << componentId;
|
|
||||||
return;
|
if (unorderedComponentIds.empty()) {
|
||||||
|
QTreeWidgetItem *item = itemAt(pos);
|
||||||
|
if (nullptr != item) {
|
||||||
|
QUuid componentId = QUuid(item->data(0, Qt::UserRole).toString());
|
||||||
|
unorderedComponentIds.insert(componentId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkeletonPart *part = nullptr;
|
std::vector<QUuid> componentIds;
|
||||||
if (!component->linkToPartId.isNull()) {
|
std::vector<QUuid> candidates;
|
||||||
part = m_document->findPart(component->linkToPartId);
|
m_document->collectComponentDescendantComponents(QUuid(), candidates);
|
||||||
|
for (const auto &cand: candidates) {
|
||||||
|
if (unorderedComponentIds.find(cand) != unorderedComponentIds.end())
|
||||||
|
componentIds.push_back(cand);
|
||||||
}
|
}
|
||||||
|
|
||||||
QMenu contextMenu(this);
|
QMenu contextMenu(this);
|
||||||
|
|
||||||
if (!component->name.isEmpty())
|
if (componentIds.size() == 1) {
|
||||||
contextMenu.addSection(component->name);
|
QUuid componentId = *componentIds.begin();
|
||||||
|
component = m_document->findComponent(componentId);
|
||||||
|
if (nullptr == component) {
|
||||||
|
qDebug() << "Component not found:" << componentId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (component && !component->linkToPartId.isNull()) {
|
||||||
|
part = m_document->findPart(component->linkToPartId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidgetAction forDisplayPartImage(this);
|
||||||
|
QLabel *previewLabel = new QLabel;
|
||||||
|
previewLabel->setFixedHeight(Theme::previewImageSize);
|
||||||
|
previewLabel->setStyleSheet("QLabel {color: " + Theme::red.name() + "}");
|
||||||
|
if (nullptr != part) {
|
||||||
|
previewLabel->setPixmap(QPixmap::fromImage(part->preview));
|
||||||
|
} else if (nullptr != component) {
|
||||||
|
previewLabel->setText(component->name);
|
||||||
|
} else if (!componentIds.empty()) {
|
||||||
|
previewLabel->setText(tr("(%1 items)").arg(QString::number(componentIds.size())));
|
||||||
|
}
|
||||||
|
QHBoxLayout *layout = new QHBoxLayout;
|
||||||
|
layout->setAlignment(Qt::AlignCenter);
|
||||||
|
layout->addWidget(previewLabel);
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
layout->setSpacing(0);
|
||||||
|
QWidget *widget = new QWidget;
|
||||||
|
widget->setLayout(layout);
|
||||||
|
forDisplayPartImage.setDefaultWidget(widget);
|
||||||
|
if (!componentIds.empty()) {
|
||||||
|
contextMenu.addAction(&forDisplayPartImage);
|
||||||
|
contextMenu.addSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
QAction showAction(tr("Show"), this);
|
QAction showAction(tr("Show"), this);
|
||||||
showAction.setIcon(Theme::awesome()->icon(fa::eye));
|
showAction.setIcon(Theme::awesome()->icon(fa::eye));
|
||||||
|
@ -129,10 +265,12 @@ void SkeletonPartTreeWidget::showContextMenu(const QPoint &pos)
|
||||||
QAction cancelInverseAction(tr("Cancel Inverse"), this);
|
QAction cancelInverseAction(tr("Cancel Inverse"), this);
|
||||||
QAction selectAction(tr("Select"), this);
|
QAction selectAction(tr("Select"), this);
|
||||||
|
|
||||||
if (!component->linkToPartId.isNull()) {
|
if (nullptr != component && nullptr != part) {
|
||||||
emit checkPart(component->linkToPartId);
|
connect(&selectAction, &QAction::triggered, [=]() {
|
||||||
|
emit addPartToSelection(component->linkToPartId);
|
||||||
|
});
|
||||||
|
contextMenu.addAction(&selectAction);
|
||||||
|
|
||||||
if (nullptr != part) {
|
|
||||||
if (part->visible) {
|
if (part->visible) {
|
||||||
connect(&hideAction, &QAction::triggered, [=]() {
|
connect(&hideAction, &QAction::triggered, [=]() {
|
||||||
emit setPartVisibleState(component->linkToPartId, false);
|
emit setPartVisibleState(component->linkToPartId, false);
|
||||||
|
@ -156,78 +294,84 @@ void SkeletonPartTreeWidget::showContextMenu(const QPoint &pos)
|
||||||
});
|
});
|
||||||
contextMenu.addAction(&lockAction);
|
contextMenu.addAction(&lockAction);
|
||||||
}
|
}
|
||||||
}
|
} else if (!componentIds.empty()) {
|
||||||
} else {
|
|
||||||
if (!component->childrenIds.empty()) {
|
|
||||||
connect(&selectAction, &QAction::triggered, [=]() {
|
connect(&selectAction, &QAction::triggered, [=]() {
|
||||||
|
for (const auto &componentId: componentIds) {
|
||||||
std::vector<QUuid> partIds;
|
std::vector<QUuid> partIds;
|
||||||
m_document->collectComponentDescendantParts(componentId, partIds);
|
m_document->collectComponentDescendantParts(componentId, partIds);
|
||||||
for (const auto &partId: partIds) {
|
for (const auto &partId: partIds) {
|
||||||
emit addPartToSelection(partId);
|
emit addPartToSelection(partId);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
contextMenu.addAction(&selectAction);
|
contextMenu.addAction(&selectAction);
|
||||||
|
|
||||||
connect(&showAction, &QAction::triggered, [=]() {
|
connect(&showAction, &QAction::triggered, [=]() {
|
||||||
|
for (const auto &componentId: componentIds)
|
||||||
emit showDescendantComponents(componentId);
|
emit showDescendantComponents(componentId);
|
||||||
});
|
});
|
||||||
contextMenu.addAction(&showAction);
|
contextMenu.addAction(&showAction);
|
||||||
|
|
||||||
connect(&hideAction, &QAction::triggered, [=]() {
|
connect(&hideAction, &QAction::triggered, [=]() {
|
||||||
|
for (const auto &componentId: componentIds)
|
||||||
emit hideDescendantComponents(componentId);
|
emit hideDescendantComponents(componentId);
|
||||||
});
|
});
|
||||||
contextMenu.addAction(&hideAction);
|
contextMenu.addAction(&hideAction);
|
||||||
|
|
||||||
connect(&lockAction, &QAction::triggered, [=]() {
|
connect(&lockAction, &QAction::triggered, [=]() {
|
||||||
|
for (const auto &componentId: componentIds)
|
||||||
emit lockDescendantComponents(componentId);
|
emit lockDescendantComponents(componentId);
|
||||||
});
|
});
|
||||||
contextMenu.addAction(&lockAction);
|
contextMenu.addAction(&lockAction);
|
||||||
|
|
||||||
connect(&unlockAction, &QAction::triggered, [=]() {
|
connect(&unlockAction, &QAction::triggered, [=]() {
|
||||||
|
for (const auto &componentId: componentIds)
|
||||||
emit unlockDescendantComponents(componentId);
|
emit unlockDescendantComponents(componentId);
|
||||||
});
|
});
|
||||||
contextMenu.addAction(&unlockAction);
|
contextMenu.addAction(&unlockAction);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!component->inverse) {
|
if (component && !component->inverse) {
|
||||||
connect(&invertAction, &QAction::triggered, [=]() {
|
connect(&invertAction, &QAction::triggered, [=]() {
|
||||||
emit setComponentInverseState(componentId, true);
|
emit setComponentInverseState(component->id, true);
|
||||||
});
|
});
|
||||||
contextMenu.addAction(&invertAction);
|
contextMenu.addAction(&invertAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component->inverse) {
|
if (component && component->inverse) {
|
||||||
connect(&cancelInverseAction, &QAction::triggered, [=]() {
|
connect(&cancelInverseAction, &QAction::triggered, [=]() {
|
||||||
emit setComponentInverseState(componentId, false);
|
emit setComponentInverseState(component->id, false);
|
||||||
});
|
});
|
||||||
contextMenu.addAction(&cancelInverseAction);
|
contextMenu.addAction(&cancelInverseAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
contextMenu.addSeparator();
|
contextMenu.addSeparator();
|
||||||
|
|
||||||
QMenu *smoothMenu = contextMenu.addMenu(tr("Smooth"));
|
|
||||||
QWidgetAction smoothAction(this);
|
QWidgetAction smoothAction(this);
|
||||||
smoothAction.setDefaultWidget(createSmoothMenuWidget(componentId));
|
QAction hideOthersAction(tr("Hide Others"), this);
|
||||||
|
QAction lockOthersAction(tr("Lock Others"), this);
|
||||||
|
if (nullptr != component) {
|
||||||
|
QMenu *smoothMenu = contextMenu.addMenu(tr("Smooth"));
|
||||||
|
|
||||||
|
smoothAction.setDefaultWidget(createSmoothMenuWidget(component->id));
|
||||||
smoothMenu->addAction(&smoothAction);
|
smoothMenu->addAction(&smoothAction);
|
||||||
|
|
||||||
contextMenu.addSeparator();
|
contextMenu.addSeparator();
|
||||||
|
|
||||||
QAction hideOthersAction(tr("Hide Others"), this);
|
|
||||||
hideOthersAction.setIcon(Theme::awesome()->icon(fa::eyeslash));
|
hideOthersAction.setIcon(Theme::awesome()->icon(fa::eyeslash));
|
||||||
connect(&hideOthersAction, &QAction::triggered, [=]() {
|
connect(&hideOthersAction, &QAction::triggered, [=]() {
|
||||||
emit hideOtherComponents(componentId);
|
emit hideOtherComponents(component->id);
|
||||||
});
|
});
|
||||||
contextMenu.addAction(&hideOthersAction);
|
contextMenu.addAction(&hideOthersAction);
|
||||||
|
|
||||||
QAction lockOthersAction(tr("Lock Others"), this);
|
|
||||||
lockOthersAction.setIcon(Theme::awesome()->icon(fa::lock));
|
lockOthersAction.setIcon(Theme::awesome()->icon(fa::lock));
|
||||||
connect(&lockOthersAction, &QAction::triggered, [=]() {
|
connect(&lockOthersAction, &QAction::triggered, [=]() {
|
||||||
emit lockOtherComponents(componentId);
|
emit lockOtherComponents(component->id);
|
||||||
});
|
});
|
||||||
contextMenu.addAction(&lockOthersAction);
|
contextMenu.addAction(&lockOthersAction);
|
||||||
|
|
||||||
contextMenu.addSeparator();
|
contextMenu.addSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
QAction collapseAllAction(tr("Collapse All"), this);
|
QAction collapseAllAction(tr("Collapse All"), this);
|
||||||
connect(&collapseAllAction, &QAction::triggered, [=]() {
|
connect(&collapseAllAction, &QAction::triggered, [=]() {
|
||||||
|
@ -275,62 +419,77 @@ void SkeletonPartTreeWidget::showContextMenu(const QPoint &pos)
|
||||||
|
|
||||||
contextMenu.addSeparator();
|
contextMenu.addSeparator();
|
||||||
|
|
||||||
|
QAction newGroupAction(tr("New Group"), this);
|
||||||
|
newGroupAction.setIcon(Theme::awesome()->icon(fa::file));
|
||||||
|
connect(&newGroupAction, &QAction::triggered, [=]() {
|
||||||
|
emit createNewChildComponent(nullptr == component ? QUuid() : component->id);
|
||||||
|
});
|
||||||
|
contextMenu.addAction(&newGroupAction);
|
||||||
|
|
||||||
|
contextMenu.addSeparator();
|
||||||
|
|
||||||
|
std::vector<QAction *> groupsActions;
|
||||||
|
QAction deleteAction(tr("Delete"), this);
|
||||||
|
QAction moveToTopAction(tr("Top"), this);
|
||||||
|
QAction moveUpAction(tr("Up"), this);
|
||||||
|
QAction moveDownAction(tr("Down"), this);
|
||||||
|
QAction moveToBottomAction(tr("Bottom"), this);
|
||||||
|
QAction moveToNewGroupAction(tr("New Group"), this);
|
||||||
|
QAction moveToRootGroupAction(tr("Root"), this);
|
||||||
|
std::function<void(QUuid, int)> addChildGroupsFunc;
|
||||||
|
if (!componentIds.empty()) {
|
||||||
QMenu *moveToMenu = contextMenu.addMenu(tr("Move To"));
|
QMenu *moveToMenu = contextMenu.addMenu(tr("Move To"));
|
||||||
|
|
||||||
QAction moveToTopAction(tr("Top"), this);
|
if (nullptr != component) {
|
||||||
moveToTopAction.setIcon(Theme::awesome()->icon(fa::angledoubleup));
|
moveToTopAction.setIcon(Theme::awesome()->icon(fa::angledoubleup));
|
||||||
connect(&moveToTopAction, &QAction::triggered, [=]() {
|
connect(&moveToTopAction, &QAction::triggered, [=]() {
|
||||||
emit moveComponentToTop(componentId);
|
emit moveComponentToTop(component->id);
|
||||||
});
|
});
|
||||||
moveToMenu->addAction(&moveToTopAction);
|
moveToMenu->addAction(&moveToTopAction);
|
||||||
|
|
||||||
QAction moveUpAction(tr("Up"), this);
|
|
||||||
moveUpAction.setIcon(Theme::awesome()->icon(fa::angleup));
|
moveUpAction.setIcon(Theme::awesome()->icon(fa::angleup));
|
||||||
connect(&moveUpAction, &QAction::triggered, [=]() {
|
connect(&moveUpAction, &QAction::triggered, [=]() {
|
||||||
emit moveComponentUp(componentId);
|
emit moveComponentUp(component->id);
|
||||||
});
|
});
|
||||||
moveToMenu->addAction(&moveUpAction);
|
moveToMenu->addAction(&moveUpAction);
|
||||||
|
|
||||||
QAction moveDownAction(tr("Down"), this);
|
|
||||||
moveDownAction.setIcon(Theme::awesome()->icon(fa::angledown));
|
moveDownAction.setIcon(Theme::awesome()->icon(fa::angledown));
|
||||||
connect(&moveDownAction, &QAction::triggered, [=]() {
|
connect(&moveDownAction, &QAction::triggered, [=]() {
|
||||||
emit moveComponentDown(componentId);
|
emit moveComponentDown(component->id);
|
||||||
});
|
});
|
||||||
moveToMenu->addAction(&moveDownAction);
|
moveToMenu->addAction(&moveDownAction);
|
||||||
|
|
||||||
QAction moveToBottomAction(tr("Bottom"), this);
|
|
||||||
moveToBottomAction.setIcon(Theme::awesome()->icon(fa::angledoubledown));
|
moveToBottomAction.setIcon(Theme::awesome()->icon(fa::angledoubledown));
|
||||||
connect(&moveToBottomAction, &QAction::triggered, [=]() {
|
connect(&moveToBottomAction, &QAction::triggered, [=]() {
|
||||||
emit moveComponentToBottom(componentId);
|
emit moveComponentToBottom(component->id);
|
||||||
});
|
});
|
||||||
moveToMenu->addAction(&moveToBottomAction);
|
moveToMenu->addAction(&moveToBottomAction);
|
||||||
|
|
||||||
moveToMenu->addSeparator();
|
moveToMenu->addSeparator();
|
||||||
|
|
||||||
QAction moveToNewGroupAction(tr("New Group"), this);
|
|
||||||
moveToNewGroupAction.setIcon(Theme::awesome()->icon(fa::file));
|
moveToNewGroupAction.setIcon(Theme::awesome()->icon(fa::file));
|
||||||
moveToMenu->addAction(&moveToNewGroupAction);
|
moveToMenu->addAction(&moveToNewGroupAction);
|
||||||
connect(&moveToNewGroupAction, &QAction::triggered, [=]() {
|
connect(&moveToNewGroupAction, &QAction::triggered, [=]() {
|
||||||
emit createNewComponentAndMoveThisIn(componentId);
|
emit createNewComponentAndMoveThisIn(component->id);
|
||||||
});
|
});
|
||||||
|
|
||||||
moveToMenu->addSeparator();
|
moveToMenu->addSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
QAction moveToRootGroupAction(tr("Root"), this);
|
|
||||||
moveToMenu->addAction(&moveToRootGroupAction);
|
moveToMenu->addAction(&moveToRootGroupAction);
|
||||||
connect(&moveToRootGroupAction, &QAction::triggered, [=]() {
|
connect(&moveToRootGroupAction, &QAction::triggered, [=]() {
|
||||||
|
for (const auto &componentId: componentIds)
|
||||||
emit moveComponent(componentId, QUuid());
|
emit moveComponent(componentId, QUuid());
|
||||||
});
|
});
|
||||||
|
|
||||||
std::vector<QAction *> groupsActions;
|
addChildGroupsFunc = [this, &groupsActions, &addChildGroupsFunc, &moveToMenu, &componentIds](QUuid currentId, int tabs) -> void {
|
||||||
std::function<void(QUuid, int)> addChildGroupsFunc;
|
|
||||||
addChildGroupsFunc = [this, &groupsActions, &addChildGroupsFunc, &moveToMenu, &componentId](QUuid currentId, int tabs) -> void {
|
|
||||||
const SkeletonComponent *current = m_document->findComponent(currentId);
|
const SkeletonComponent *current = m_document->findComponent(currentId);
|
||||||
if (nullptr == current)
|
if (nullptr == current)
|
||||||
return;
|
return;
|
||||||
if (!current->id.isNull() && current->linkDataType().isEmpty()) {
|
if (!current->id.isNull() && current->linkDataType().isEmpty()) {
|
||||||
QAction *action = new QAction(QString(" ").repeated(tabs * 4) + current->name, this);
|
QAction *action = new QAction(QString(" ").repeated(tabs * 4) + current->name, this);
|
||||||
connect(action, &QAction::triggered, [=]() {
|
connect(action, &QAction::triggered, [=]() {
|
||||||
|
for (const auto &componentId: componentIds)
|
||||||
emit moveComponent(componentId, current->id);
|
emit moveComponent(componentId, current->id);
|
||||||
});
|
});
|
||||||
groupsActions.push_back(action);
|
groupsActions.push_back(action);
|
||||||
|
@ -344,12 +503,13 @@ void SkeletonPartTreeWidget::showContextMenu(const QPoint &pos)
|
||||||
|
|
||||||
contextMenu.addSeparator();
|
contextMenu.addSeparator();
|
||||||
|
|
||||||
QAction deleteAction(tr("Delete"), this);
|
|
||||||
deleteAction.setIcon(Theme::awesome()->icon(fa::trash));
|
deleteAction.setIcon(Theme::awesome()->icon(fa::trash));
|
||||||
connect(&deleteAction, &QAction::triggered, [=]() {
|
connect(&deleteAction, &QAction::triggered, [=]() {
|
||||||
|
for (const auto &componentId: componentIds)
|
||||||
emit removeComponent(componentId);
|
emit removeComponent(componentId);
|
||||||
});
|
});
|
||||||
contextMenu.addAction(&deleteAction);
|
contextMenu.addAction(&deleteAction);
|
||||||
|
}
|
||||||
|
|
||||||
contextMenu.exec(mapToGlobal(pos));
|
contextMenu.exec(mapToGlobal(pos));
|
||||||
|
|
||||||
|
@ -504,6 +664,7 @@ void SkeletonPartTreeWidget::addComponentChildrenToItem(QUuid componentId, QTree
|
||||||
m_componentItemMap[childId] = item;
|
m_componentItemMap[childId] = item;
|
||||||
addComponentChildrenToItem(childId, item);
|
addComponentChildrenToItem(childId, item);
|
||||||
}
|
}
|
||||||
|
updateComponentSelectState(childId, isComponentSelected(childId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,7 +719,9 @@ void SkeletonPartTreeWidget::componentRemoved(QUuid componentId)
|
||||||
auto componentItem = m_componentItemMap.find(componentId);
|
auto componentItem = m_componentItemMap.find(componentId);
|
||||||
if (componentItem == m_componentItemMap.end())
|
if (componentItem == m_componentItemMap.end())
|
||||||
return;
|
return;
|
||||||
|
m_selectedComponentIds.erase(componentId);
|
||||||
|
if (m_currentSelectedComponentId == componentId)
|
||||||
|
m_currentSelectedComponentId = QUuid();
|
||||||
m_componentItemMap.erase(componentId);
|
m_componentItemMap.erase(componentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,8 +885,7 @@ void SkeletonPartTreeWidget::partChecked(QUuid partId)
|
||||||
qDebug() << "Part item not found:" << partId;
|
qDebug() << "Part item not found:" << partId;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SkeletonPartWidget *widget = (SkeletonPartWidget *)itemWidget(item->second, 0);
|
item->second->setBackground(0, m_hightlightedPartBackground);
|
||||||
widget->updateCheckedState(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonPartTreeWidget::partUnchecked(QUuid partId)
|
void SkeletonPartTreeWidget::partUnchecked(QUuid partId)
|
||||||
|
@ -733,8 +895,7 @@ void SkeletonPartTreeWidget::partUnchecked(QUuid partId)
|
||||||
//qDebug() << "Part item not found:" << partId;
|
//qDebug() << "Part item not found:" << partId;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SkeletonPartWidget *widget = (SkeletonPartWidget *)itemWidget(item->second, 0);
|
item->second->setBackground(0, QBrush(Qt::transparent));
|
||||||
widget->updateCheckedState(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize SkeletonPartTreeWidget::sizeHint() const
|
QSize SkeletonPartTreeWidget::sizeHint() const
|
||||||
|
@ -754,3 +915,9 @@ void SkeletonPartTreeWidget::keyPressEvent(QKeyEvent *event)
|
||||||
if (m_graphicsFunctions)
|
if (m_graphicsFunctions)
|
||||||
m_graphicsFunctions->keyPress(event);
|
m_graphicsFunctions->keyPress(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkeletonPartTreeWidget::isComponentSelected(QUuid componentId)
|
||||||
|
{
|
||||||
|
return (m_currentSelectedComponentId == componentId ||
|
||||||
|
m_selectedComponentIds.find(componentId) != m_selectedComponentIds.end());
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ signals:
|
||||||
void moveComponentToBottom(QUuid componentId);
|
void moveComponentToBottom(QUuid componentId);
|
||||||
void checkPart(QUuid partId);
|
void checkPart(QUuid partId);
|
||||||
void createNewComponentAndMoveThisIn(QUuid componentId);
|
void createNewComponentAndMoveThisIn(QUuid componentId);
|
||||||
|
void createNewChildComponent(QUuid parentComponentId);
|
||||||
void renameComponent(QUuid componentId, QString name);
|
void renameComponent(QUuid componentId, QString name);
|
||||||
void setComponentExpandState(QUuid componentId, bool expanded);
|
void setComponentExpandState(QUuid componentId, bool expanded);
|
||||||
void setComponentSmoothAll(QUuid componentId, float toSmoothAll);
|
void setComponentSmoothAll(QUuid componentId, float toSmoothAll);
|
||||||
|
@ -76,8 +77,10 @@ protected:
|
||||||
private:
|
private:
|
||||||
void addComponentChildrenToItem(QUuid componentId, QTreeWidgetItem *parentItem);
|
void addComponentChildrenToItem(QUuid componentId, QTreeWidgetItem *parentItem);
|
||||||
void deleteItemChildren(QTreeWidgetItem *item);
|
void deleteItemChildren(QTreeWidgetItem *item);
|
||||||
void selectComponent(QUuid componentId);
|
void selectComponent(QUuid componentId, bool multiple=false);
|
||||||
QWidget *createSmoothMenuWidget(QUuid componentId);
|
QWidget *createSmoothMenuWidget(QUuid componentId);
|
||||||
|
void updateComponentSelectState(QUuid componentId, bool selected);
|
||||||
|
bool isComponentSelected(QUuid componentId);
|
||||||
private:
|
private:
|
||||||
const SkeletonDocument *m_document = nullptr;
|
const SkeletonDocument *m_document = nullptr;
|
||||||
std::map<QUuid, QTreeWidgetItem *> m_partItemMap;
|
std::map<QUuid, QTreeWidgetItem *> m_partItemMap;
|
||||||
|
@ -85,7 +88,10 @@ private:
|
||||||
SkeletonGraphicsFunctions *m_graphicsFunctions = nullptr;
|
SkeletonGraphicsFunctions *m_graphicsFunctions = nullptr;
|
||||||
QFont m_normalFont;
|
QFont m_normalFont;
|
||||||
QFont m_selectedFont;
|
QFont m_selectedFont;
|
||||||
QUuid m_currentSelectedComponent;
|
QUuid m_currentSelectedComponentId;
|
||||||
|
QBrush m_hightlightedPartBackground;
|
||||||
|
QUuid m_shiftStartComponentId;
|
||||||
|
std::set<QUuid> m_selectedComponentIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -250,7 +250,7 @@ void SkeletonPartWidget::updateAllButtons()
|
||||||
void SkeletonPartWidget::updateCheckedState(bool checked)
|
void SkeletonPartWidget::updateCheckedState(bool checked)
|
||||||
{
|
{
|
||||||
if (checked)
|
if (checked)
|
||||||
m_backgroundWidget->setStyleSheet("QWidget#background {border: 1px solid #f7d9c8;}");
|
m_backgroundWidget->setStyleSheet("QWidget#background {border: 1px solid " + Theme::red.name() + ";}");
|
||||||
else
|
else
|
||||||
m_backgroundWidget->setStyleSheet("QWidget#background {border: 1px solid transparent;}");
|
m_backgroundWidget->setStyleSheet("QWidget#background {border: 1px solid transparent;}");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue