Change parts tree menu trigger method

Left mouse single press will popup short version of context menu
master
Jeremy Hu 2020-01-13 20:50:37 +09:30
parent 89d49d488d
commit cff5cff6bc
4 changed files with 131 additions and 60 deletions

View File

@ -70,7 +70,9 @@ PartTreeWidget::PartTreeWidget(const Document *document, QWidget *parent) :
m_firstSelect = true; m_firstSelect = true;
selectComponent(QUuid()); selectComponent(QUuid());
connect(this, &QTreeWidget::customContextMenuRequested, this, &PartTreeWidget::showContextMenu); connect(this, &QTreeWidget::customContextMenuRequested, this, [&](const QPoint &pos) {
showContextMenu(pos);
});
connect(this, &QTreeWidget::itemChanged, this, &PartTreeWidget::groupChanged); connect(this, &QTreeWidget::itemChanged, this, &PartTreeWidget::groupChanged);
connect(this, &QTreeWidget::itemExpanded, this, &PartTreeWidget::groupExpanded); connect(this, &QTreeWidget::itemExpanded, this, &PartTreeWidget::groupExpanded);
connect(this, &QTreeWidget::itemCollapsed, this, &PartTreeWidget::groupCollapsed); connect(this, &QTreeWidget::itemCollapsed, this, &PartTreeWidget::groupCollapsed);
@ -154,64 +156,104 @@ void PartTreeWidget::updateComponentSelectState(QUuid componentId, bool selected
} }
} }
void PartTreeWidget::mousePressEvent(QMouseEvent *event) void PartTreeWidget::mouseDoubleClickEvent(QMouseEvent *event)
{ {
QModelIndex itemIndex = indexAt(event->pos()); delete m_delayedMousePressTimer;
QTreeView::mousePressEvent(event); m_delayedMousePressTimer = nullptr;
if (event->button() == Qt::LeftButton) {
bool multiple = QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier); QWidget::mouseDoubleClickEvent(event);
if (itemIndex.isValid()) { auto componentIds = collectSelectedComponentIds(event->pos());
QTreeWidgetItem *item = itemFromIndex(itemIndex); for (const auto &componentId: componentIds) {
auto componentId = QUuid(item->data(0, Qt::UserRole).toString()); std::vector<QUuid> partIds;
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) { m_document->collectComponentDescendantParts(componentId, partIds);
if (!m_shiftStartComponentId.isNull()) { for (const auto &partId: partIds) {
const Component *parent = m_document->findComponentParent(m_shiftStartComponentId); emit addPartToSelection(partId);
if (parent) { }
if (!parent->childrenIds.empty()) { }
bool startAdd = false; event->accept();
bool stopAdd = false; }
std::vector<QUuid> waitQueue;
for (const auto &childId: parent->childrenIds) { void PartTreeWidget::handleSingleClick(const QPoint &pos)
if (m_shiftStartComponentId == childId || componentId == childId) { {
if (startAdd) { QModelIndex itemIndex = indexAt(pos);
stopAdd = true;
} else { auto showMenu = [=]() {
startAdd = true; delete m_delayedMousePressTimer;
} m_delayedMousePressTimer = new QTimer(this);
m_delayedMousePressTimer->setSingleShot(true);
m_delayedMousePressTimer->setInterval(200);
connect(m_delayedMousePressTimer, &QTimer::timeout, this, [=]() {
showContextMenu(pos, true);
});
m_delayedMousePressTimer->start();
};
bool multiple = QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier);
if (itemIndex.isValid()) {
QTreeWidgetItem *item = itemFromIndex(itemIndex);
auto componentId = QUuid(item->data(0, Qt::UserRole).toString());
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) {
if (!m_shiftStartComponentId.isNull()) {
const Component *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 (startAdd)
if (!m_selectedComponentIds.empty()) { waitQueue.push_back(childId);
for (const auto &id: m_selectedComponentIds) { if (stopAdd)
updateComponentSelectState(id, false); break;
} }
m_selectedComponentIds.clear(); if (stopAdd && !waitQueue.empty()) {
} if (!m_selectedComponentIds.empty()) {
if (!m_currentSelectedComponentId.isNull()) { for (const auto &id: m_selectedComponentIds) {
m_currentSelectedComponentId = QUuid(); updateComponentSelectState(id, false);
emit currentComponentChanged(m_currentSelectedComponentId);
}
for (const auto &waitId: waitQueue) {
selectComponent(waitId, true);
} }
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); showMenu();
return; return;
} else {
m_shiftStartComponentId = componentId;
} }
if (!multiple) selectComponent(componentId, multiple);
selectComponent(QUuid()); showMenu();
return;
} }
if (!multiple)
selectComponent(QUuid());
showMenu();
}
void PartTreeWidget::mousePressEvent(QMouseEvent *event)
{
QTreeView::mousePressEvent(event);
if (event->button() != Qt::LeftButton)
return;
handleSingleClick(event->pos());
} }
void PartTreeWidget::showClothSettingMenu(const QPoint &pos, const QUuid &componentId) void PartTreeWidget::showClothSettingMenu(const QPoint &pos, const QUuid &componentId)
@ -294,12 +336,8 @@ void PartTreeWidget::showClothSettingMenu(const QPoint &pos, const QUuid &compon
popupMenu.exec(mapToGlobal(pos)); popupMenu.exec(mapToGlobal(pos));
} }
void PartTreeWidget::showContextMenu(const QPoint &pos) std::vector<QUuid> PartTreeWidget::collectSelectedComponentIds(const QPoint &pos)
{ {
const Component *component = nullptr;
const SkeletonPart *part = nullptr;
PartWidget *partWidget = nullptr;
std::set<QUuid> unorderedComponentIds = m_selectedComponentIds; std::set<QUuid> unorderedComponentIds = m_selectedComponentIds;
if (!m_currentSelectedComponentId.isNull()) if (!m_currentSelectedComponentId.isNull())
unorderedComponentIds.insert(m_currentSelectedComponentId); unorderedComponentIds.insert(m_currentSelectedComponentId);
@ -320,6 +358,25 @@ void PartTreeWidget::showContextMenu(const QPoint &pos)
componentIds.push_back(cand); componentIds.push_back(cand);
} }
return componentIds;
}
void PartTreeWidget::showContextMenu(const QPoint &pos, bool shorted)
{
delete m_delayedMousePressTimer;
m_delayedMousePressTimer = nullptr;
const Component *component = nullptr;
const SkeletonPart *part = nullptr;
PartWidget *partWidget = nullptr;
std::vector<QUuid> componentIds = collectSelectedComponentIds(pos);
if (shorted) {
if (componentIds.size() != 1)
return;
}
QMenu contextMenu(this); QMenu contextMenu(this);
if (componentIds.size() == 1) { if (componentIds.size() == 1) {
@ -493,6 +550,13 @@ void PartTreeWidget::showContextMenu(const QPoint &pos)
contextMenu.addSeparator(); contextMenu.addSeparator();
//} //}
if (shorted) {
auto globalPos = mapToGlobal(pos);
globalPos.setX(globalPos.x() - contextMenu.sizeHint().width() - pos.x());
contextMenu.exec(globalPos);
return;
}
QAction showAction(tr("Show"), this); QAction showAction(tr("Show"), this);
showAction.setIcon(Theme::awesome()->icon(fa::eye)); showAction.setIcon(Theme::awesome()->icon(fa::eye));
QAction hideAction(tr("Hide"), this); QAction hideAction(tr("Hide"), this);
@ -758,7 +822,9 @@ void PartTreeWidget::showContextMenu(const QPoint &pos)
contextMenu.addAction(&deleteAction); contextMenu.addAction(&deleteAction);
} }
contextMenu.exec(mapToGlobal(pos)); auto globalPos = mapToGlobal(pos);
globalPos.setX(globalPos.x() - contextMenu.sizeHint().width() - pos.x());
contextMenu.exec(globalPos);
for (const auto &action: groupsActions) { for (const auto &action: groupsActions) {
delete action; delete action;

View File

@ -4,6 +4,7 @@
#include <QUuid> #include <QUuid>
#include <QMouseEvent> #include <QMouseEvent>
#include <QTreeWidgetItem> #include <QTreeWidgetItem>
#include <QTimer>
#include "document.h" #include "document.h"
class PartTreeWidget : public QTreeWidget class PartTreeWidget : public QTreeWidget
@ -85,11 +86,12 @@ public slots:
void groupExpanded(QTreeWidgetItem *item); void groupExpanded(QTreeWidgetItem *item);
void groupCollapsed(QTreeWidgetItem *item); void groupCollapsed(QTreeWidgetItem *item);
void removeAllContent(); void removeAllContent();
void showContextMenu(const QPoint &pos); void showContextMenu(const QPoint &pos, bool shorted=false);
void showClothSettingMenu(const QPoint &pos, const QUuid &componentId); void showClothSettingMenu(const QPoint &pos, const QUuid &componentId);
protected: protected:
QSize sizeHint() const override; QSize sizeHint() const override;
void mousePressEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
private: private:
void addComponentChildrenToItem(QUuid componentId, QTreeWidgetItem *parentItem); void addComponentChildrenToItem(QUuid componentId, QTreeWidgetItem *parentItem);
void deleteItemChildren(QTreeWidgetItem *item); void deleteItemChildren(QTreeWidgetItem *item);
@ -98,9 +100,12 @@ private:
void updateComponentSelectState(QUuid componentId, bool selected); void updateComponentSelectState(QUuid componentId, bool selected);
void updateComponentAppearance(QUuid componentId); void updateComponentAppearance(QUuid componentId);
bool isComponentSelected(QUuid componentId); bool isComponentSelected(QUuid componentId);
std::vector<QUuid> collectSelectedComponentIds(const QPoint &pos);
void handleSingleClick(const QPoint &pos);
private: private:
const Document *m_document = nullptr; const Document *m_document = nullptr;
QTreeWidgetItem *m_rootItem = nullptr; QTreeWidgetItem *m_rootItem = nullptr;
QTimer *m_delayedMousePressTimer = nullptr;
bool m_firstSelect = true; bool m_firstSelect = true;
std::map<QUuid, QTreeWidgetItem *> m_partItemMap; std::map<QUuid, QTreeWidgetItem *> m_partItemMap;
std::map<QUuid, QTreeWidgetItem *> m_componentItemMap; std::map<QUuid, QTreeWidgetItem *> m_componentItemMap;

View File

@ -323,11 +323,11 @@ void PartWidget::updateUnnormalState(bool unnormal)
updateAllButtons(); updateAllButtons();
} }
void PartWidget::mouseDoubleClickEvent(QMouseEvent *event) //void PartWidget::mouseDoubleClickEvent(QMouseEvent *event)
{ //{
QWidget::mouseDoubleClickEvent(event); // QWidget::mouseDoubleClickEvent(event);
emit checkPart(m_partId); // emit checkPart(m_partId);
} //}
void PartWidget::initToolButtonWithoutFont(QPushButton *button) void PartWidget::initToolButtonWithoutFont(QPushButton *button)
{ {

View File

@ -58,7 +58,7 @@ public:
static QSize preferredSize(); static QSize preferredSize();
ModelWidget *previewWidget(); ModelWidget *previewWidget();
protected: protected:
void mouseDoubleClickEvent(QMouseEvent *event) override; //void mouseDoubleClickEvent(QMouseEvent *event) override;
public slots: public slots:
void showDeformSettingPopup(const QPoint &pos); void showDeformSettingPopup(const QPoint &pos);
void showCutRotationSettingPopup(const QPoint &pos); void showCutRotationSettingPopup(const QPoint &pos);