2021SC@SDUSC
一、materialListWidget类 (一)materialListWidget.hclass MaterialListWidget : public QTreeWidget
{
Q_OBJECT
signals:
void removeMaterial(QUuid materialId);
void modifyMaterial(QUuid materialId);
void cornerButtonClicked(QUuid materialId);
void currentSelectedMaterialChanged(QUuid materialId);
public:
MaterialListWidget(const document *document, QWidget *parent=nullptr);
bool isMaterialSelected(QUuid materialId);
void enableMultipleSelection(bool enabled);
public slots:
void reload();
void removeAllContent();
void materialRemoved(QUuid materialId);
void showContextMenu(const QPoint &pos);
void selectMaterial(QUuid materialId, bool multiple=false);
void copy();
void setCornerButtonVisible(bool visible);
void setHasContextMenu(bool hasContextMenu);
protected:
void resizeEvent(QResizeEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
private:
int calculateColumnCount();
void updateMaterialSelectState(QUuid materialId, bool selected);
const document *m_document = nullptr;
std::map> m_itemMap;
std::set m_selectedMaterialIds;
QUuid m_currentSelectedMaterialId;
QUuid m_shiftStartMaterialId;
bool m_cornerButtonVisible = false;
bool m_hasContextMenu = true;
bool m_multipleSelectionEnabled = true;
};
(二)materialListWidget.cpp
1.构造函数
MaterialListWidget::MaterialListWidget(const document *document, QWidget *parent) :
QTreeWidget(parent),
m_document(document)
{
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
setFocusPolicy(Qt::NoFocus);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setAutoScroll(false);
setHeaderHidden(true);
QPalette palette = this->palette();
palette.setColor(QPalette::Window, Qt::transparent);
palette.setColor(QPalette::base, Qt::transparent);
setPalette(palette);
setStyleSheet("QTreeView {qproperty-indentation: 0;}");
setContentsMargins(0, 0, 0, 0);
connect(document, &document::materialListChanged, this, &MaterialListWidget::reload);
connect(document, &document::cleanup, this, &MaterialListWidget::removeAllContent);
connect(this, &MaterialListWidget::removeMaterial, document, &document::removeMaterial);
setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &QTreeWidget::customContextMenuRequested, this, &MaterialListWidget::showContextMenu);
reload();
}
2.enableMultipleSelection
void MaterialListWidget::enableMultipleSelection(bool enabled)
{
m_multipleSelectionEnabled = enabled;
}
3.materialRemoved
void MaterialListWidget::materialRemoved(QUuid materialId)
{
if (m_currentSelectedMaterialId == materialId)
m_currentSelectedMaterialId = QUuid();
m_selectedMaterialIds.erase(materialId);
m_itemMap.erase(materialId);
}
4.updateMaterialSelectState
void MaterialListWidget::updateMaterialSelectState(QUuid materialId, bool selected)
{
auto findItemResult = m_itemMap.find(materialId);
if (findItemResult == m_itemMap.end()) {
qDebug() << "Find material item failed:" << materialId;
return;
}
MaterialWidget *materialWidget = (MaterialWidget *)itemWidget(findItemResult->second.first, findItemResult->second.second);
materialWidget->updateCheckedState(selected);
if (m_cornerButtonVisible) {
materialWidget->setCornerButtonVisible(selected);
}
}
5.selectMaterial
void MaterialListWidget::selectMaterial(QUuid materialId, bool multiple)
{
if (multiple) {
if (!m_currentSelectedMaterialId.isNull()) {
m_selectedMaterialIds.insert(m_currentSelectedMaterialId);
m_currentSelectedMaterialId = QUuid();
}
if (m_selectedMaterialIds.find(materialId) != m_selectedMaterialIds.end()) {
updateMaterialSelectState(materialId, false);
m_selectedMaterialIds.erase(materialId);
} else {
if (m_multipleSelectionEnabled || m_selectedMaterialIds.empty()) {
updateMaterialSelectState(materialId, true);
m_selectedMaterialIds.insert(materialId);
}
}
if (m_selectedMaterialIds.size() > 1) {
return;
}
if (m_selectedMaterialIds.size() == 1)
materialId = *m_selectedMaterialIds.begin();
else {
materialId = QUuid();
emit currentSelectedMaterialChanged(materialId);
}
}
if (!m_selectedMaterialIds.empty()) {
for (const auto &id: m_selectedMaterialIds) {
updateMaterialSelectState(id, false);
}
m_selectedMaterialIds.clear();
}
if (m_currentSelectedMaterialId != materialId) {
if (!m_currentSelectedMaterialId.isNull()) {
updateMaterialSelectState(m_currentSelectedMaterialId, false);
}
m_currentSelectedMaterialId = materialId;
if (!m_currentSelectedMaterialId.isNull()) {
updateMaterialSelectState(m_currentSelectedMaterialId, true);
}
emit currentSelectedMaterialChanged(m_currentSelectedMaterialId);
}
}
6.mousePressEvent
void MaterialListWidget::mousePressEvent(QMouseEvent *event)
{
QModelIndex itemIndex = indexAt(event->pos());
QTreeView::mousePressEvent(event);
if (event->button() == Qt::LeftButton) {
bool multiple = QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier);
if (itemIndex.isValid()) {
QTreeWidgetItem *item = itemFromIndex(itemIndex);
auto materialId = QUuid(item->data(itemIndex.column(), Qt::UserRole).toString());
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) {
bool startAdd = false;
bool stopAdd = false;
std::vector waitQueue;
for (const auto &childId: m_document->materialIdList) {
if (m_shiftStartMaterialId == childId || materialId == childId) {
if (startAdd) {
stopAdd = true;
} else {
startAdd = true;
}
}
if (startAdd)
waitQueue.push_back(childId);
if (stopAdd)
break;
}
if (stopAdd && !waitQueue.empty()) {
if (!m_selectedMaterialIds.empty()) {
for (const auto &id: m_selectedMaterialIds) {
updateMaterialSelectState(id, false);
}
m_selectedMaterialIds.clear();
}
if (!m_currentSelectedMaterialId.isNull()) {
m_currentSelectedMaterialId = QUuid();
}
for (const auto &waitId: waitQueue) {
selectMaterial(waitId, true);
}
}
return;
} else {
m_shiftStartMaterialId = materialId;
}
selectMaterial(materialId, multiple);
return;
}
if (!multiple)
selectMaterial(QUuid());
}
} 


