#include "treeviewmanager.h" #include "OriginalWnd.h" // ���캯�� TreeViewManager::TreeViewManager(OriginalWnd* originalWnd, QWidget *widget2, QWidget *parent) : QWidget(parent), widget2(widget2), treeViewDown(new QTreeView(widget2)), m_originalWnd(originalWnd), navigationWidget(nullptr), buttonOpenFile(nullptr), buttonUp(nullptr), buttonDown(nullptr), buttonLeft(nullptr), buttonRight(nullptr), restoring(false) { if (!widget2) { qWarning() << "TreeViewManager: widget2 δ��ʼ��"; return; } downModel = new QStandardItemModel(this); // ��ʼ��Ŀ¼��ģ�� treeViewDown->setModel(downModel); applyCustomStyles(); // Ŀ¼����ʽ�� treeViewDown->setHeaderHidden(true); // ������ʾͷ�� treeViewDown->setGeometry(16, 106, widget2->width()-16, widget2->height() - 106); //Ŀ¼����С��λ�� treeViewDown->setEditTriggers(QAbstractItemView::NoEditTriggers); //��ֹĿ¼���� treeViewDown->viewport()->installEventFilter(this); // �� viewport() ��װ�¼����������Ա������� Paint �¼� QFrame *lineFrame1 = createUnifiedSeparator(widget2, 2); // ʹ��ͳһ�ķָ��ߴ������� lineFrame1->setGeometry(16, 89, 428, 2); lineFrame1->show(); setupButton(); // �������Ͻǰ�ť�����ò��� navigationWidget = new QWidget(widget2); // ���������� navigationWidget->setGeometry(15, 15, 300, 74); loadVisitedPaths(); // ���ز�չ���ϴη��ʹ���·�� // ����Ŀ¼ǰ�ĸ�ѡ���ź���� connect(downModel, &QStandardItemModel::itemChanged, this, &TreeViewManager::onItemChanged); // Ŀ¼�����ӵ���ź� connect(treeViewDown, &QTreeView::clicked, this, [=](const QModelIndex &index) { QStandardItem *item = downModel->itemFromIndex(index); if (!item) return; if (!restoring) { // ���ڷǻָ�״̬�¼�¼ѡ��·�� QStringList path = buildItemPath(item); addVisitedPath(path); } QVariant data = item->data(Qt::UserRole); if (data.canConvert<QJsonObject>()) { QJsonObject fields = data.toJsonObject(); if (fields.contains("isThirdLevel") && fields["isThirdLevel"].toBool()) { updateNavigationBar(index); // ���µ����� displayThirdLevelFields(fields); // ��ʾ����Ŀ¼�ֶ����� treeViewDown->hide(); // ����Ŀ¼ updateSeparatorLine(); // ����Ŀ¼�ָ��� return; } } updateNavigationBar(index); // ��ʹ�Ƿ�����Ŀ¼��Ҳ���µ����� // qDebug() << "���µ�������Ŀ¼�" << item->text(); }); // ����Ŀ¼ expanded �� collapsed �ź� connect(treeViewDown, &QTreeView::expanded, this, [=](const QModelIndex &index) { QStandardItem *item = downModel->itemFromIndex(index); if (!item) return; QStringList path = buildItemPath(item); addExpandedPath(path); updateSeparatorLine(); }); connect(treeViewDown, &QTreeView::collapsed, this, [=](const QModelIndex &index) { QStandardItem *item = downModel->itemFromIndex(index); if (!item) return; QStringList path = buildItemPath(item); removeExpandedPath(path); updateSeparatorLine(); }); // ����չ��������ɺ���·ָ��� QTimer::singleShot(0, this, [=]() { QStandardItem *rootItem = downModel->invisibleRootItem(); QStandardItem *thirdItem = findFirstThirdLevelItemDFS(rootItem); if (thirdItem) { QJsonObject thirdLevelObj = thirdItem->data(Qt::UserRole).toJsonObject(); if (thirdLevelObj.contains("isThirdLevel") && thirdLevelObj["isThirdLevel"].toBool()) { loadButtonConfigForThirdLevel(thirdLevelObj); } } }); connect(buttonOpenFile, &QPushButton::clicked, this, &TreeViewManager::onButtonOpenFileClicked); connect(buttonUp, &QPushButton::clicked, this, &TreeViewManager::onButtonUpClicked); connect(buttonDown, &QPushButton::clicked, this, &TreeViewManager::onButtonDownClicked); connect(buttonLeft, &QPushButton::clicked, this, &TreeViewManager::onButtonLeftClicked); connect(buttonRight, &QPushButton::clicked, this, &TreeViewManager::onButtonRightClicked); } TreeViewManager::~TreeViewManager() { } // ���ز�ɾ�����зָ��� void TreeViewManager::clearAllSeparators() { for (auto separator : firstLevelSeparators.values()) { if (separator) { separator->hide(); separator->deleteLater(); } } firstLevelSeparators.clear(); // ���map } // ���ҷ�����Ŀ¼���������ӷָ��� QStandardItem* TreeViewManager::findFirstThirdLevelItemDFS(QStandardItem *parentItem) { if (!parentItem) { return nullptr; } // ������ǰ parentItem �������� for (int i = 0; i < parentItem->rowCount(); ++i) { QStandardItem *child = parentItem->child(i); if (!child) continue; // �������ӽڵ��Ƿ�������Ŀ¼ QVariant data = child->data(Qt::UserRole); if (data.canConvert<QJsonObject>()) { QJsonObject obj = data.toJsonObject(); if (obj.contains("isThirdLevel") && obj["isThirdLevel"].toBool()) { // �ҵ���һ�� isThirdLevel = true �Ľڵ�ͷ��� return child; } } // ������� isThirdLevel���������ӽڵ����� QStandardItem* deeperFound = findFirstThirdLevelItemDFS(child); if (deeperFound) { return deeperFound; } } return nullptr; } // �ݹ���¸�ѡ������״̬ void TreeViewManager::updateChildItems(QStandardItem *parentItem, Qt::CheckState state) { if (!parentItem) return; // qDebug() << "Updating child items of:" << parentItem->text() << "to state:" << state; for (int i = 0; i < parentItem->rowCount(); ++i) { QStandardItem *child = parentItem->child(i); if (child) { child->setCheckState(state); updateChildItems(child, state); // �ݹ�������� //qDebug() << "updateChildItems:" << parentItem->text() << "to state:" << state; } } } // �ռ����б�ѡ�еĸ�ѡ��·�� QStringList TreeViewManager::collectCheckedPathsRecursive(QStandardItem *item, QStringList path) { QStringList checkedList; if (!item) { item = downModel->invisibleRootItem(); } for (int i = 0; i < item->rowCount(); ++i) { QStandardItem *child = item->child(i); if (child) { QStringList currentPath = path; currentPath << child->text(); if (child->checkState() == Qt::Checked) { checkedList << currentPath.join("/"); } // �ݹ��ռ����� checkedList << collectCheckedPathsRecursive(child, currentPath); } } return checkedList; } // �����汾�� collectCheckedPaths �������� QStringList TreeViewManager::collectCheckedPaths() { return collectCheckedPathsRecursive(downModel->invisibleRootItem(), QStringList()); } void TreeViewManager::setCheckedPaths(const QStringList &checkedPathsList) { //qDebug() << "Setting checked paths:" << checkedPathsList; m_blockItemChanged = true; // qDebug() << "setCheckedPaths: m_blockItemChanged set to true"; for (const QString &pathStr : checkedPathsList) { QStringList path = pathStr.split("/"); QModelIndex idx = findItemByPath(path); if (idx.isValid()) { QStandardItem *item = downModel->itemFromIndex(idx); if (item) { qDebug() << " - Setting item:" << item->text() << "to Checked"; item->setCheckState(Qt::Checked); visitedPaths.insert(pathStr); qDebug() << "Added visited path:" << pathStr; } } else { qDebug() << "Path not found:" << pathStr; } } m_blockItemChanged = false; //qDebug() << "setCheckedPaths: m_blockItemChanged set to false"; } // ���渴ѡ��״̬ void TreeViewManager::saveCheckedPaths() { if (currentConfigFilePath.isEmpty()) { qWarning() << "��ǰ�����ļ�·��Ϊ�գ������渴ѡ��״̬��"; return; } QSettings settings("RunCloudTech", "David"); QString configKey = currentConfigKey(currentConfigFilePath); settings.beginGroup("TreeViewCheckedState"); // ����ѡ��·�� QString keyChecked = QString("checkedPaths/%1").arg(configKey); QStringList checkedList = collectCheckedPaths(); settings.setValue(keyChecked, checkedList); settings.endGroup(); qDebug() << "���渴ѡ��״̬·����" << checkedList; } // ���ظ�ѡ��״̬ void TreeViewManager::loadCheckedPaths() { if (currentConfigFilePath.isEmpty()) { qWarning() << "��ǰ�����ļ�·��Ϊ�գ������ظ�ѡ��״̬��"; return; } QSettings settings("RunCloudTech", "David"); QString configKey = currentConfigKey(currentConfigFilePath); settings.beginGroup("TreeViewCheckedState"); // Read checked paths QString keyChecked = QString("checkedPaths/%1").arg(configKey); QStringList loadedChecked = settings.value(keyChecked).toStringList(); settings.endGroup(); qDebug() << "���ظ�ѡ��״̬·����" << loadedChecked; m_blockItemChanged = true; //qDebug() << "loadCheckedPaths: m_blockItemChanged set to true"; setCheckedPaths(loadedChecked); m_blockItemChanged = false; //qDebug() << "loadCheckedPaths: m_blockItemChanged set to false"; } void TreeViewManager::onItemChanged(QStandardItem *item) { //qDebug() << "onItemChanged called for item:" << item->text(); //qDebug() << "Flags - m_blockItemChanged:" << m_blockItemChanged << ", restoring:" << restoring; if (m_blockItemChanged || restoring) { qDebug() << "Exiting onItemChanged due to flags."; return; // ��ֹ�ݹ�ͻָ��ڼ䴥�� } m_blockItemChanged = true; qDebug() << "Processing item:" << item->text(); Qt::CheckState state = item->checkState(); updateChildItems(item, state); // ������������ĸ�ѡ��״̬ updateParentItems(item->parent()); // �������и���ĸ�ѡ��״̬ m_blockItemChanged = false; // ������ڻָ�ģʽ�£���¼��ѡ�е�·�� if (!restoring) { QStringList path = buildItemPath(item); if (state == Qt::Checked) { addVisitedPath(path); } else { // �����Ҫ��ȡ��ѡ��ʱִ��ijЩ����������� visitedPaths ���Ƴ� QString joinedPath = path.join("/"); if (visitedPaths.contains(joinedPath)) { visitedPaths.remove(joinedPath); qDebug() << "�Ƴ�ѡ��·����" << joinedPath; } } // ��¼��ѡ��״̬ saveCheckedPaths(); } } //�������и���ĸ�ѡ��״̬ void TreeViewManager::updateParentItems(QStandardItem *parentItem) { if (!parentItem) return; int checkedCount = 0; int totalCount = parentItem->rowCount(); qDebug() << "Updating child items of:" ; for (int i = 0; i < totalCount; ++i) { QStandardItem *child = parentItem->child(i); if (child && child->checkState() == Qt::Checked) { checkedCount++; } } if (checkedCount == totalCount) { parentItem->setCheckState(Qt::Checked); } else { parentItem->setCheckState(Qt::Unchecked); } // �ݹ�����ϲ㸸�� updateParentItems(parentItem->parent()); } //����������ʽ QFrame* TreeViewManager::createUnifiedSeparator(QWidget *parent, int height) { QFrame *separator = new QFrame(parent); separator->setFrameShape(QFrame::NoFrame); // �Ƴ�Ĭ�Ͽ�� separator->setFixedHeight(height); // ���ù̶��߶� separator->setStyleSheet("background-color: #C7CAEB;"); // ���ñ�����ɫ separator->hide(); // ������Ҫ��ʼ��Ϊ���� //qDebug() << "����ͳһ�ָ��� QFrame��������" << parent; return separator; } // Ŀ¼���ĺ��� void TreeViewManager::updateSeparatorLine() { // ��� treeViewDown �Ƿ�ɼ� if (!treeViewDown->isVisible()) { // �������к��� for (auto separator : firstLevelSeparators) { if (separator) separator->hide(); } return; } // ������¼��һ��Ŀ¼ for (auto it = firstLevelSeparators.begin(); it != firstLevelSeparators.end(); ++it) { QStandardItem *firstLevelItem = it.key(); QFrame *separator = it.value(); if (!firstLevelItem || !separator) continue; QModelIndex firstLevelIndex = downModel->indexFromItem(firstLevelItem); QRect firstLevelRect = treeViewDown->visualRect(firstLevelIndex); if (!firstLevelRect.isValid()) { separator->hide(); continue; } if (treeViewDown->isExpanded(firstLevelIndex) && firstLevelItem->hasChildren()) { // �ҵ����һ���ɼ���Ŀ¼ QModelIndex lastVisibleChild = findLastVisibleChild(firstLevelIndex); if (lastVisibleChild.isValid()) { QRect lastChildRect = treeViewDown->visualRect(lastVisibleChild); if (lastChildRect.isValid()) { // �����߷��������һ����Ŀ¼�·� separator->setGeometry(16, lastChildRect.bottom() + 105, widget2->width() - 32, 2); separator->show(); } else { // �����Ŀ¼���ɼ������߷���һ��Ŀ¼�·� separator->setGeometry(16, firstLevelRect.bottom() + 105, widget2->width() - 32, 2); separator->show(); } } else { // û�пɼ���Ŀ¼�������һ��Ŀ¼�·� separator->setGeometry(16, firstLevelRect.bottom() + 105, widget2->width() - 32, 2); separator->show(); } } else { // һ��Ŀ¼���𣬺���ֱ�����·� separator->setGeometry(16, firstLevelRect.bottom() + 105, widget2->width() - 32, 2); separator->show(); } } } // �ָ��� �ҵ����һ���ɼ����� QModelIndex TreeViewManager::findLastVisibleChild(const QModelIndex &parentIndex) { if (!parentIndex.isValid()) return QModelIndex(); int childCount = downModel->rowCount(parentIndex); QModelIndex lastVisibleChild; for (int i = childCount - 1; i >= 0; --i) { QModelIndex childIndex = downModel->index(i, 0, parentIndex); if (!treeViewDown->isRowHidden(i, parentIndex)) { // ȷ������δ������ if (treeViewDown->isExpanded(childIndex) && downModel->rowCount(childIndex) > 0) { QModelIndex deeperChild = findLastVisibleChild(childIndex); if (deeperChild.isValid()) { return deeperChild; } } lastVisibleChild = childIndex; break; // �ҵ����һ���ɼ�������˳�ѭ�� } } return lastVisibleChild; } // ʹ���ļ�����ΪΨһ��ʶ�� QString TreeViewManager::currentConfigKey(const QString &configFilePath) { QFileInfo fileInfo(configFilePath); QString key = fileInfo.fileName(); qDebug() << "Generated config key:" << key; return key; } void TreeViewManager::saveVisitedPaths() { if (currentConfigFilePath.isEmpty()) { qWarning() << "��ǰ�����ļ�·��Ϊ�գ������渴ѡ��״̬��"; return; } QSettings settings("RunCloudTech", "David"); QString configKey = currentConfigKey(currentConfigFilePath); settings.beginGroup("TreeViewState"); // ����ѡ��·�� QString keyVisited = QString("visitedPaths/%1").arg(configKey); QStringList visitedList(visitedPaths.begin(), visitedPaths.end()); settings.setValue(keyVisited, visitedList); // ����չ��·�� QString keyExpanded = QString("expandedPaths/%1").arg(configKey); QStringList expandedList(expandedPaths.begin(), expandedPaths.end()); settings.setValue(keyExpanded, expandedList); settings.endGroup(); qDebug() << "����ѡ��·����" << visitedList; qDebug() << "����չ��·����" << expandedList; // ���ñ��渴ѡ��״̬ saveCheckedPaths(); } void TreeViewManager::loadVisitedPaths() { if (currentConfigFilePath.isEmpty()) { qWarning() << "��ǰ�����ļ�·��Ϊ�գ������ط���·����"; return; } QSettings settings("RunCloudTech", "David"); QString configKey = currentConfigKey(currentConfigFilePath); settings.beginGroup("TreeViewState"); // ��ȡѡ��·�� QString keyVisited = QString("visitedPaths/%1").arg(configKey); QStringList loadedVisited = settings.value(keyVisited).toStringList(); // ��ȡչ��·�� QString keyExpanded = QString("expandedPaths/%1").arg(configKey); QStringList loadedExpanded = settings.value(keyExpanded).toStringList(); settings.endGroup(); qDebug() << "����ѡ��·����" << loadedVisited; qDebug() << "����չ��·����" << loadedExpanded; restoring = true; // ����ָ�ģʽ // �ָ�չ��·�� for (const QString &p : loadedExpanded) { QStringList path = p.split("/"); QModelIndex idx = findItemByPath(path); if (idx.isValid()) { treeViewDown->expand(idx); expandedPaths.insert(p); // ���²��� qDebug() << "�ɹ��ָ�չ��·����" << p; } else { qDebug() << "δ�ҵ�չ��·�����֣� " << p; } } // �ָ�ѡ��·�� for (const QString &p : loadedVisited) { QStringList path = p.split("/"); QModelIndex idx = findItemByPath(path); if (idx.isValid()) { QStandardItem *item = downModel->itemFromIndex(idx); if (item) { item->setCheckState(Qt::Checked); visitedPaths.insert(p); qDebug() << "�ɹ��ָ�ѡ��·����" << p; } } else { qDebug() << "δ�ҵ�ѡ��·�����֣� " << p; } } // �ָ���ѡ��״̬ loadCheckedPaths(); restoring = false; // �˳��ָ�ģʽ // ���µ����� if (!loadedVisited.isEmpty()) { QString lastPathStr = loadedVisited.last(); QStringList lastPath = lastPathStr.split("/"); QModelIndex lastIdx = findItemByPath(lastPath); if (lastIdx.isValid()) { treeViewDown->setCurrentIndex(lastIdx); updateNavigationBar(lastIdx); } } else { // ���û�м��ص��κ�·�����Զ�ѡ���һ��Ŀ¼ QStandardItem *rootItem = downModel->invisibleRootItem(); if (rootItem->rowCount() > 0) { QModelIndex firstIndex = downModel->index(0, 0, QModelIndex()); if (firstIndex.isValid()) { treeViewDown->setCurrentIndex(firstIndex); updateNavigationBar(firstIndex); treeViewDown->expand(firstIndex); // չ����һ��Ŀ¼ QStandardItem *firstItem = downModel->itemFromIndex(firstIndex); QVariant data = firstItem->data(Qt::UserRole); if (data.canConvert<QJsonObject>()) { QJsonObject thirdLevelObj = data.toJsonObject(); if (thirdLevelObj.contains("isThirdLevel") && thirdLevelObj["isThirdLevel"].toBool()) { loadButtonConfigForThirdLevel(thirdLevelObj); } } } } } // ʹ�� singleShot ȷ��������չ��������ɺ���·ָ��� QTimer::singleShot(0, this, &TreeViewManager::updateSeparatorLine); } //��¼ѡ�е�·�� void TreeViewManager::addVisitedPath(const QStringList &path) { QString joined = path.join("/"); if (!visitedPaths.contains(joined)) { visitedPaths.insert(joined); qDebug() << "��¼[ѡ��]·����" << joined; } } //��¼չ����·�� void TreeViewManager::addExpandedPath(const QStringList &path) { QString joined = path.join("/"); if (!expandedPaths.contains(joined)) { expandedPaths.insert(joined); qDebug() << "��¼[չ��]·����" << joined; } } //�Ƴ�չ����·�� void TreeViewManager::removeExpandedPath(const QStringList &path) { QString joinedPath = path.join("/"); if (expandedPaths.contains(joinedPath)) { expandedPaths.remove(joinedPath); qDebug() << "�Ƴ�չ��·����" << joinedPath; } } // �����ڵ������·�� QStringList TreeViewManager::buildItemPath(QStandardItem *item) { QStringList path; QStandardItem *currentItem = item; while (currentItem) { path.prepend(currentItem->text()); currentItem = currentItem->parent(); } return path; } // ����·�����Ҷ�Ӧ�Ľڵ� QModelIndex TreeViewManager::findItemByPath(const QStringList &path) { if (path.isEmpty()) return QModelIndex(); QStandardItem *currentItem = downModel->invisibleRootItem(); QModelIndex currentIndex; for (const QString &part : path) { bool found = false; for (int i = 0; i < currentItem->rowCount(); ++i) { QStandardItem *child = currentItem->child(i); if (child->text() == part) { currentIndex = downModel->indexFromItem(child); currentItem = child; found = true; break; } } if (!found) { qWarning() << "δ�ҵ�·�����֣�" << part; return QModelIndex(); } } return currentIndex; } bool TreeViewManager::eventFilter(QObject *watched, QEvent *event) { // ���� Paint �¼� if (watched == treeViewDown->viewport() && event->type() == QEvent::Paint) { // ����Ĭ�ϻ��ơ����ڵ㡱�������� bool handled = QWidget::eventFilter(watched, event); //ʹ�� QPainter ���ӻ����ս��ߡ� QPainter painter(treeViewDown->viewport()); if (!painter.isActive()) { qWarning() << "Painter not active"; return handled; } painter.save(); painter.setPen(QPen(Qt::gray, 1, Qt::DashLine)); // ��ɫ��1px �������� // ����һ���ݹ����������������нڵ�ĸ�->���ߡ��ֵ��������߶����� paintAllBranches(QModelIndex(), painter); painter.restore(); return handled; } // �����¼���������Ĭ�ϴ��� return QWidget::eventFilter(watched, event); } void TreeViewManager::paintAllBranches(const QModelIndex &parentIndex, QPainter &painter) { int rowCount = downModel->rowCount(parentIndex); for(int i = 0; i < rowCount; ++i) { // ��ǰ�ӽڵ� QModelIndex childIndex = downModel->index(i, 0, parentIndex); if (!childIndex.isValid()) continue; // 1) ��->�ӹս��� drawParentChildLine(childIndex, painter); // 2) �ֵ���������(������ڵ㲻�����һ���ֵܣ����ڹյ��л������µ���) if (i < rowCount - 1) { drawSiblingLine(childIndex, painter); } // 3) �ݹ鴦���ӽڵ� paintAllBranches(childIndex, painter); } } //�ڡ����ڵ� -> �ӽڵ㡱�仭һ����L���ս��ߣ����������߶εij��� void TreeViewManager::drawParentChildLine(const QModelIndex &childIndex, QPainter &painter) { QModelIndex parentIndex = childIndex.parent(); if (!parentIndex.isValid()) { // ������ڵ㡱����һ���̶������ (rootX, rootY) int indent = treeViewDown->indentation(); int depth = 0; // ����ڵ����Ϊ0 int branchX = (depth + 1) * indent - indent / 2; // ���� branchX ������������� // ���� rootY Ϊ�ڵ����� Y QRect childRect = treeViewDown->visualRect(childIndex); if (!childRect.isValid()) return; int rootY = childRect.center().y(); // �������ƫ���� const int hOffset = -20; // �������� painter.drawLine(QPoint(branchX, rootY), QPoint(branchX, childRect.center().y())); // �����µĺ����յ� int newX = childRect.left() + hOffset; // ���ƺ��� painter.drawLine(QPoint(branchX, childRect.center().y()), QPoint(newX, childRect.center().y())); return; } QRect parentRect = treeViewDown->visualRect(parentIndex); QRect childRect = treeViewDown->visualRect(childIndex); if (!parentRect.isValid() || !childRect.isValid()) { // �����ӳ����������� return; } int pMidY = parentRect.center().y(); int cMidY = childRect.center().y(); // ����ڵ���� int depth = 0; QModelIndex p = parentIndex; while (p.isValid()) { depth++; p = p.parent(); } int indent = treeViewDown->indentation(); int branchX = depth * indent - indent / 2; // branchX ��������ͼ��Χ branchX = std::max(branchX, 0); // �������ƫ���� const int hOffset = -15; // �������� painter.drawLine(QPoint(branchX, pMidY), QPoint(branchX, cMidY)); // �����µĺ����յ� int newX = childRect.left() + hOffset; // ���ƺ��� painter.drawLine(QPoint(branchX, cMidY), QPoint(newX, cMidY)); } // �ڵ����滹���ֵܣ����ڹյ�������������»����� void TreeViewManager::drawSiblingLine(const QModelIndex &childIndex, QPainter &painter) { QModelIndex parentIndex = childIndex.parent(); if (!parentIndex.isValid()) { return; // û�и��ڵ� } // ��һ���ֵ� int row = childIndex.row(); int lastRow = downModel->rowCount(parentIndex) - 1; if (row >= lastRow) { return; // ˵�������һ���ֵܣ����û������� } QModelIndex nextSibling = downModel->index(row + 1, 0, parentIndex); QRect currRect = treeViewDown->visualRect(childIndex); QRect nextRect = treeViewDown->visualRect(nextSibling); if (!currRect.isValid() || !nextRect.isValid()) { return; } // ����ڵ���� int depth = 0; QModelIndex p = parentIndex; while (p.isValid()) { depth++; p = p.parent(); } int indent = treeViewDown->indentation(); int branchX = depth * indent - indent / 2; // ȷ�� branchX ��������ͼ��Χ branchX = std::max(branchX, 0); // �ӵ�ǰ�ڵ�ײ��������쵽��һ���ֵܽڵ㶥�� int startY = currRect.bottom(); int endY = nextRect.top(); painter.drawLine(QPoint(branchX, startY), QPoint(branchX, endY)); } // һ���Զ�ȡ configPaths ������� JSON �ļ��������浽 m_configCache void TreeViewManager::preloadAllConfigs(const QStringList &configPaths) { m_configCache.clear(); // ����� for (const QString &path : configPaths) { QFile file(path); if (!file.exists()) { qWarning() << "preloadAllConfigs: JSON �ļ������ڣ�" << path; continue; } if (!file.open(QIODevice::ReadOnly)) { qWarning() << "preloadAllConfigs: ���� JSON �ļ���" << path; continue; } QByteArray data = file.readAll(); file.close(); QJsonDocument doc = QJsonDocument::fromJson(data); if (doc.isNull() || !doc.isObject()) { qWarning() << "preloadAllConfigs: JSON �ļ���ʽ����" << path; continue; } // �� fileName ��Ϊ key������ "home_config.json" QString key = QFileInfo(path).fileName(); m_configCache.insert(key, doc); qDebug() << "preloadAllConfigs: �ѻ��������ļ�" << key; } } //�л������ļ� void TreeViewManager::switchConfig(const QString &configKey) { qDebug() << "�л������ļ�����" << configKey; // �ȱ��浱ǰ���õ�״̬ saveVisitedPaths(); // �����ؼ��б��ͽ������� m_fieldWidgets.clear(); m_currentFieldIndex = -1; // ��� configKey �Ƿ�����ڻ����� if (!m_configCache.contains(configKey)) { qWarning() << "switchConfig: δ�ҵ� configKey =" << configKey << "�����л�"; return; } // ��ȡ��Ӧ�� QJsonDocument QJsonDocument doc = m_configCache.value(configKey); // ������һ�����ò����ĺ��� clearAllSeparators(); // ��������Ŀ¼�˵����� clearThirdLevelMenu(); //�����µ� JSON ���� loadJsonDoc(doc, configKey); } //��������������Ŀ¼�˵����� void TreeViewManager::clearThirdLevelMenu() { // ���������ӿؼ����ҵ�����Ϊ "�ֶ�չʾ" �Ĵ��ڲ��ر� foreach (QObject *child, widget2->children()) { QWidget *childWidget = qobject_cast<QWidget*>(child); if (childWidget && childWidget->windowTitle() == "�ֶ�չʾ") { qDebug() << "�ر����е��ֶ�չʾ����"; childWidget->close(); } } // ��ʾ��Ŀ¼���ͷָ��� treeViewDown->show(); for (auto separator : firstLevelSeparators) { separator->show(); } } void TreeViewManager::loadJsonDoc(const QJsonDocument &doc, const QString &configFilePath) { currentConfigFilePath = configFilePath; //qDebug() << "[DEBUG] loadJsonDoc ��ɣ���Ӧ configKey =" << configFilePath; m_blockItemChanged = true; //qDebug() << "Loading JSON config, m_blockItemChanged set to true"; // ��� downModel->clear(); firstLevelSeparators.clear(); visitedPaths.clear(); expandedPaths.clear(); // ������ if (!doc.isObject()) { qWarning() << "loadJsonDoc: doc ���Ƕ���ṹ"; return; } QJsonObject rootObj = doc.object(); buildTree(rootObj, downModel->invisibleRootItem()); loadVisitedPaths();// �ָ� ����·�� + ��ѡ��״̬ m_blockItemChanged = false; // qDebug() << "Finished loading JSON config, m_blockItemChanged set to false"; } //Ŀ¼����ʽ void TreeViewManager::applyCustomStyles() { treeViewDown->setStyleSheet(R"( /* ���÷�֧ͼ�� */ QTreeView::branch:closed:has-children { border-image: none; image: url(:/images/home_add.png); } QTreeView::branch:open:has-children { border-image: none; image: url(:/images/home_minus.png); } /* ���ö�ѡ�� */ QTreeView::indicator:unchecked { image: url(:/images/home_NotSelecte.png); } QTreeView::indicator:checked { image: url(:/images/home_selected.png); } /* ���������м�� */ QTreeView { background: transparent; border: none; } /* ������Ŀѡ�еı���ɫ */ QTreeView::item:selected { background-color: #A9B4FF; } /* ������Ŀ���м�� */ QTreeView::item { padding-top: 5px; /* �ϱ߾� */ padding-bottom: 5px; /* �±߾� */ } )"); } //����Ŀ¼�� void TreeViewManager::buildTree(const QJsonObject &jsonObj, QStandardItem *parent) { for (auto it = jsonObj.begin(); it != jsonObj.end(); ++it) { // ��������Ҫ���ֶ� if (it.key() == "isThirdLevel" || it.key() == "separator" || it.key() == "buttons") { continue; } QStandardItem *item = new QStandardItem(it.key()); item->setCheckable(true); // ���Ӷ�ѡ�� item->setCheckState(Qt::Unchecked); // Ĭ��״̬Ϊδѡ�� parent->appendRow(item); //qDebug() << "����Ŀ¼�" << it.key(); if (it.value().isObject()) { QJsonObject childObj = it.value().toObject(); if (childObj.contains("isThirdLevel") && childObj["isThirdLevel"].toBool()) { // ������Ŀ¼���洢�������� UserRole item->setData(childObj, Qt::UserRole); //qDebug() << "Ŀ¼��Ϊ����Ŀ¼��" << it.key(); } else { // �ݹ鴦������Ŀ¼ buildTree(childObj, item); } } // �����һ��Ŀ¼������Ƿ���Ҫ�����ָ��� if (parent == downModel->invisibleRootItem()) { QJsonObject currentObj = it.value().toObject(); bool hasSeparator = currentObj.contains("separator") && currentObj["separator"].toBool(); if (hasSeparator) { QFrame *separator = createUnifiedSeparator(widget2, 2); separator->hide(); // ��ʼ���� firstLevelSeparators.insert(item, separator); //qDebug() << "Ϊһ��Ŀ¼����ͳһ�ָ��ߣ�" << it.key(); } } } // ����������������ɺ��¸���ĸ�ѡ��״̬ if (parent != downModel->invisibleRootItem()) { updateParentItems(parent); } } //��������̬���� void TreeViewManager::updateNavigationBar(const QModelIndex &index) { //�����ǰ index ��Ч�����Դ� QSettings ��ȡ���ϴε���·�������ָ� if (!index.isValid()) { //qWarning() << "updateNavigationBar(): ��ǰ index ��Ч�����Դ� QSettings �ָ��ϴε���"; QSettings settings("RunCloudTech", "David"); settings.beginGroup("TreeViewNav"); QStringList lastNavPath = settings.value("lastNavPath").toStringList(); settings.endGroup(); if (!lastNavPath.isEmpty()) { // �ҵ���Ӧ�Ľڵ����� QModelIndex savedIndex = findItemByPath(lastNavPath); if (savedIndex.isValid()) { qDebug() << "�ɹ��� QSettings �ָ�����·����" << lastNavPath << "����Ӧ�" << downModel->itemFromIndex(savedIndex)->text(); updateNavigationBar(savedIndex); // �ٴε��ñ����������µ����� } else { qWarning() << "QSettings ����·�����ҵ���Ӧ�ڵ㣬���ָ���"; } } else { qWarning() << "QSettings ��û�д��κε���·������Ϊ�ա�"; } return; } QStandardItem *item = downModel->itemFromIndex(index); if (!item) { qWarning() << "����������ʧ�ܣ�δ�ҵ���Ӧ��"; return; } //qDebug() << "���������£�Ŀ¼�" << item->text(); // ������������в��֣������� if (navigationWidget->layout()) { QLayoutItem *child; while ((child = navigationWidget->layout()->takeAt(0)) != nullptr) { if (child->widget()) { child->widget()->deleteLater(); } delete child; } delete navigationWidget->layout(); } // ����·���б����ӵ�ǰ����ݵ����ڵ� QList<QStandardItem *> path; QStandardItem *temp = item; while (temp) { if (temp->text() != "isThirdLevel") { // �ų� "isThirdLevel" ��ʶ path.prepend(temp); // �Ӹ��ڵ㿪ʼ } temp = temp->parent(); } qDebug() << "����·����" << [path]() { QStringList pathNames; for (QStandardItem *p : path) { pathNames.append(p->text()); } return pathNames.join(" -> "); }(); QVBoxLayout *newLayout = new QVBoxLayout; // �����µĵ��������� newLayout->setContentsMargins(0, 0, 3, 3); newLayout->setSpacing(0); // ȷ����ʾ���� for (int i = 0; i < 3; ++i) { QLabel *label = new QLabel; if (i < path.size()) { QString text = path[i]->text(); if (i == 1) text = " " + text; // ����Ŀ¼���� if (i == 2) text = " " + text; // ����Ŀ¼���� label->setText(text); } else { label->setText(""); // ���հ��� } QFont font = label->font(); // �����������ʽ font.setPointSize(14); font.setFamily("˼Դ����"); font.setBold(true); //��������Ϊ���� font.setLetterSpacing(QFont::PercentageSpacing,105); //�����ּ��100%ΪĬ�� label->setFont(font); label->setFixedHeight(navigationWidget->height() / 3); newLayout->addWidget(label); } // ���ò��ֲ����µ����� navigationWidget->setLayout(newLayout); navigationWidget->update(); //qDebug() << "������������ɣ�" << path.size() << "��"; //��ǰ·���浽 QSettings�����´������ָ� QStringList pathStrings; for (QStandardItem *p : path) { pathStrings << p->text(); } QSettings settings("RunCloudTech", "David"); settings.beginGroup("TreeViewNav"); settings.setValue("lastNavPath", pathStrings); settings.endGroup(); //qDebug() << "�ѽ���ǰ����·��д�� QSettings��" << pathStrings; } //���ز���ʾ����Ŀ¼��Ӧ��ť������Ϣ void TreeViewManager::loadButtonConfigForThirdLevel(const QJsonObject &thirdLevelObj) { if (!m_originalWnd) { qWarning() << "OriginalWnd ָ��Ϊ�գ������ذ�ť����"; return; } if (!thirdLevelObj.contains("buttons")) { qWarning() << "����Ŀ¼�����в����� 'buttons' �ֶ�"; return; } QJsonArray buttonsArray = thirdLevelObj.value("buttons").toArray(); // ��ȡ widget_left QWidget* widgetLeft = m_originalWnd->getWidgetLeft(); if (!widgetLeft) { qWarning() << "������ widget_left"; return; } // ��� widget_left ���� loadButtonConfigForThirdLevel �����İ�ť QList<QPushButton*> existingButtons = widgetLeft->findChildren<QPushButton*>(); for (QPushButton* button : existingButtons) { if (button->objectName().startsWith("thirdLevelBtn_")) { // ��ɾ���ض���ť button->deleteLater(); } } // ʹ�þ��Զ�λ������ť for (int i = 0; i < buttonsArray.size() && i < 12; ++i) { QJsonObject buttonObj = buttonsArray[i].toObject(); QString buttonId = buttonObj.value("id").toString(); QString buttonIcon = buttonObj.value("icon").toString(); QString buttonText = buttonObj.value("text").toString(); bool isEnabled = buttonObj.value("enabled").toBool(); // ������ť QPushButton *button = new QPushButton(widgetLeft); button->setObjectName("thirdLevelBtn_" + buttonId); // ���ô�ǰ�Ķ������� //���ð�ť����ʽ������ͼ����ı���λ�� button->setStyleSheet(R"( QPushButton { position: absolute; border-radius: 6px; opacity: 1; background: #CBD0FF; border: none; } QPushButton:hover { background-color: #A9B4FF; /* �����ͣЧ�� */ } )"); // ���ð�ť��λ�úʹ�С int x = 16; int y = 245 + i * (48 + 13); // ��һ����ť y=245������ÿ����ť���13px button->setGeometry(x, y, 158, 48); // ���ð�ť�Ŀɼ��ԣ����� "enabled" �ֶ���ʾ�����ذ�ť button->setVisible(isEnabled); // ����ͼ���ǩ QLabel *iconLabel = new QLabel(button); iconLabel->setPixmap(QIcon(buttonIcon).pixmap(16, 16)); iconLabel->setGeometry(10, 16, 16, 16); // ͼ��������10px������16px iconLabel->setFixedSize(16, 16); iconLabel->setStyleSheet("background-color: transparent;"); iconLabel->setVisible(isEnabled); // ���ݰ�ť�Ŀɼ�������ͼ��Ŀɼ��� // �����ı���ǩ QLabel *textLabel = new QLabel(buttonText, button); textLabel->setGeometry(34, 0, 90, 48); // �ı��������34px��ռ��ʣ��ռ� textLabel->setWordWrap(true); // �������� textLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); //textLabel->setStyleSheet("background-color: transparent;"); textLabel->setStyleSheet(R"( QLabel { background: transparent; font-family: "˼Դ����"; font-size: 14px; font-weight: 500; color: #4E51CE; } )"); textLabel->setVisible(isEnabled); // ���ݰ�ť�Ŀɼ��������ı��Ŀɼ��� // ���� F1-F12 ��ǩ QString fLabelText = QString("F%1").arg(i + 1); // F1, F2, ..., F12 QLabel *fLabel = new QLabel(fLabelText, button); fLabel->setFixedSize(21, 16); // ���ô�СΪ21x16 fLabel->setAlignment(Qt::AlignCenter); fLabel->setStyleSheet(R"( QLabel { background-color: transparent; color: #2A7ED8; font-size: 12px; font-weight: bold; } )"); // ���ñ�ǩ��λ�� int fX = 134; int fY = 2; fLabel->setGeometry(fX, fY, 14, 16); fLabel->setVisible(isEnabled); // ���ݰ�ť�Ŀɼ������ñ�ǩ�Ŀɼ��� //qDebug() << "������ť��" << buttonId << ", �ı���" << buttonText << ", ͼ�꣺" << buttonIcon << ", ���ã�" << isEnabled; } } //����Ŀ¼�ֶδ��� void TreeViewManager::displayThirdLevelFields(const QJsonObject &fields) { if (fields.isEmpty()) { qWarning() << "�ֶ�����Ϊ�գ�����ʾ"; return; } // qDebug() << "��ʾ���ֶ����ݣ�" << fields; // ����Ƿ�Ϊ����Ŀ¼ if (!fields.contains("isThirdLevel") || !fields["isThirdLevel"].toBool()) { qWarning() << "��������Ŀ¼��������ť����"; return; } // ����Ŀ¼�� treeViewDown->hide(); // �������к��� for (auto separator : firstLevelSeparators) { separator->hide(); } // ���ذ�ť���� loadButtonConfigForThirdLevel(fields); // ����֮ǰ�Ŀؼ��б� m_fieldWidgets.clear(); m_currentFieldIndex = -1; // ����Ƿ��Ѵ����ֶδ��ڣ���ֹ�ظ����� foreach (QObject *child, widget2->children()) { QWidget *childWidget = qobject_cast<QWidget*>(child); if (childWidget && childWidget->windowTitle() == "�ֶ�չʾ") { // qDebug() << "�ֶδ����Ѵ��ڣ��رվɴ���"; childWidget->close(); } } // ����һ���µ� ���ֶ�չʾ�� ���� QWidget *fieldWindow = new QWidget(widget2); fieldWindow->setWindowTitle("�ֶ�չʾ"); fieldWindow->setGeometry(treeViewDown->geometry()); //����һ���������� QScrollArea QScrollArea *scrollArea = new QScrollArea(fieldWindow); scrollArea->setWidgetResizable(true); // ��������Ӧ��С scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); // ����ˮƽ������ //qDebug() << "QScrollArea �Ѵ�����ˮƽ��������������Ϊ ScrollBarAsNeeded"; //������������ scrollWidget�������ô�ֱ���� QWidget *scrollWidget = new QWidget; scrollWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); // ���ȸ��游���� QVBoxLayout *scrollLayout = new QVBoxLayout(scrollWidget); scrollLayout->setSpacing(10); // �ֶεĴ�ֱ��� scrollLayout->setContentsMargins(10, 10, 10, 10); // ���ٱ߾� // ���� JSON �е��ֶΣ����ɿؼ� for (auto it = fields.begin(); it != fields.end(); ++it) { QString fieldName = it.key(); if (fieldName == "isThirdLevel") { continue; // ���� isThirdLevel �ֶ� } if (fieldName == "buttons") { continue; // ���� buttons �ֶ� } QJsonObject fieldConfig = it.value().toObject(); QString fieldType = fieldConfig["type"].toString(); // qDebug() << "�����ֶΣ�" << fieldName << "���ͣ�" << fieldType; // ÿ���ֶ�һ�У�Label���ؼ����� QHBoxLayout *fieldLayout = new QHBoxLayout; fieldLayout->setSpacing(5); // ����ÿ�е�ˮƽ��� // ��ࣺ�ֶ��� QLabel *label = new QLabel(fieldName); label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); label->setFixedHeight(24); label->setMinimumWidth(120); fieldLayout->addWidget(label); // ���м���뵯��������ʹ����Ŀؼ����� fieldLayout->addStretch(1); // ���� fieldType ������Ӧ�ؼ� QWidget *rightWidget = new QWidget; QHBoxLayout *rightLayout = new QHBoxLayout(rightWidget); rightLayout->setContentsMargins(0, 0, 20, 0); // �ؼ��Ҳ�߾�20 rightLayout->setSpacing(5); // ���ٿؼ�֮��ļ�� QWidget *createdWidget = nullptr; // ���ڴ洢�����Ŀؼ� if (fieldType == "input") { // ���� QLineEdit ����� QLineEdit *lineEdit = new QLineEdit(fieldConfig["value"].toString()); lineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); // ˮƽ������չ lineEdit->setFixedSize(120, 28); // ���ٿ��Ⱥ߶� lineEdit->setAlignment(Qt::AlignLeft); // ���������� lineEdit->setStyleSheet(R"( QLineEdit { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 6px; padding: 2px 5px; } )"); rightLayout->addWidget(lineEdit); createdWidget = lineEdit; // ��¼�����Ŀؼ� //qDebug() << "���������" << fieldName; } else if (fieldType == "radio") { // ����һ�� QRadioButton ��ѡ�� QHBoxLayout *radioLayout = new QHBoxLayout; radioLayout->setSpacing(5); // ���ٵ�ѡ��ť֮��ļ�� QButtonGroup *radioGroup = new QButtonGroup(rightWidget); QString currentValue = fieldConfig["value"].toString(); QJsonArray options = fieldConfig["options"].toArray(); for (const QJsonValue &option : options) { QRadioButton *radioButton = new QRadioButton(option.toString()); if (option.toString() == currentValue) { radioButton->setChecked(true); } radioGroup->addButton(radioButton); radioLayout->addWidget(radioButton); m_fieldWidgets.append(radioButton); // ���ӵ��ؼ��б� //qDebug() << "���ӵ�ѡ��ť��" << option.toString(); } rightLayout->addLayout(radioLayout); } else if (fieldType == "checkbox") { // ���� QCheckBox ��ѡ����ʾ���� QCheckBox *checkBox = new QCheckBox; checkBox->setChecked(fieldConfig["value"].toBool()); // Ӧ��ָ������ʽ checkBox->setStyleSheet(R"( QCheckBox::indicator { width: 20px; height: 20px; } QCheckBox::indicator:unchecked { background-color: #FFFFFF; border: 1px solid #BABBDC; border-radius: 2px; } QCheckBox::indicator:checked { image: url(:/images/three_Selecte.png); } QCheckBox { /* ȡ����ʾ�ı� */ spacing: 0px; } )"); rightLayout->addWidget(checkBox); createdWidget = checkBox; // ��¼�����Ŀؼ� //qDebug() << "���Ӹ�ѡ��" << fieldName; } else if (fieldType == "dropdown") { // ���� QComboBox ������ QComboBox *comboBox = new QComboBox; comboBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); // �̶����� comboBox->setFixedSize(120, 28); comboBox->setStyleSheet(R"( QComboBox { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 6px; padding: 2px 5px; } QComboBox::drop-down { width: 20px; } )"); QJsonArray options = fieldConfig["options"].toArray(); for (const QJsonValue &option : options) { comboBox->addItem(option.toString()); } comboBox->setCurrentText(fieldConfig["value"].toString()); rightLayout->addWidget(comboBox); createdWidget = comboBox; // ��¼�����Ŀؼ� //qDebug() << "����������" << fieldName; } else if (fieldType == "time") { // ���� QTimeEdit ʱ��ѡ��� QTimeEdit *timeEdit = new QTimeEdit; timeEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); // �̶����� timeEdit->setFixedSize(120, 28); // ���ٿ��Ⱥ߶� timeEdit->setStyleSheet(R"( QTimeEdit { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 6px; padding: 2px 5px; } )"); timeEdit->setDisplayFormat("HH:mm:ss"); timeEdit->setTime(QTime::fromString(fieldConfig["value"].toString(), "HH:mm:ss")); rightLayout->addWidget(timeEdit); createdWidget = timeEdit; // ��¼�����Ŀؼ� //qDebug() << "����ʱ��ѡ���" << fieldName; } else if (fieldType == "switch") { // ���� QCheckBox ���ؿؼ������������ֱ�ǩ�������͡��ء� QWidget *switchContainer = new QWidget; QHBoxLayout *switchLayout = new QHBoxLayout(switchContainer); switchLayout->setSpacing(5); // ���ٿ��غͱ�ǩ֮��ļ�� switchLayout->setContentsMargins(0, 0, 0, 0); QCheckBox *switchBox = new QCheckBox; switchBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); switchBox->setFixedSize(30, 30); // �������ش�С switchBox->setStyleSheet(R"( QCheckBox::indicator { width: 30px; height: 30px; } QCheckBox::indicator:unchecked { background-color: #BABBDC; border-radius: 6px; } QCheckBox::indicator:checked { background-color: #4CAF50; border-radius: 6px; } )"); // ���ó�ʼ״̬ QString switchValue = fieldConfig["value"].toString(); if (switchValue == "on") { switchBox->setChecked(true); } else { switchBox->setChecked(false); } // �������ֱ�ǩ QLabel *switchLabel = new QLabel(switchBox->isChecked() ? "��" : "��"); switchLabel->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); switchLabel->setStyleSheet("font-size: 14px;"); //���������С // ���ӿ���״̬�ı��ź��Ը��±�ǩ���� connect(switchBox, &QCheckBox::stateChanged, [switchLabel](int state){ if (state == Qt::Checked) { switchLabel->setText("��"); } else { switchLabel->setText("��"); } }); switchLayout->addWidget(switchBox); switchLayout->addWidget(switchLabel); rightLayout->addWidget(switchContainer); createdWidget = switchBox; // �����ؿؼ����ӵ��ؼ��б� //qDebug() << "���ӿ��ؿؼ��ͱ�ǩ��" << fieldName; } else if (fieldType == "combined") { // ��Ͽؼ������� QLineEdit ������ QToolButton�� QJsonObject combinedValue = fieldConfig["value"].toObject(); // ȷ����Ҫ���ֶδ��� if (!combinedValue.contains("inputValue") || !combinedValue.contains("moduleButton") || !combinedValue.contains("axisButton")) { //qWarning() << "��Ͽؼ��� value �ֶβ�������" << fieldName; continue; } QLineEdit *comboInput = new QLineEdit(combinedValue["inputValue"].toString()); comboInput->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); // ˮƽ������չ comboInput->setFixedHeight(28); // ���ٸ߶� comboInput->setStyleSheet(R"( QLineEdit { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 5px; padding: 2px 5px; } )"); m_fieldWidgets.append(comboInput); //qDebug() << "������Ͽؼ��������" << fieldName; // ����һ������ widget ��������Ͽؼ� QWidget *combinedWidget = new QWidget; QHBoxLayout *combinedLayout = new QHBoxLayout(combinedWidget); combinedLayout->setSpacing(5); // ���ٿؼ�֮��ļ�� combinedLayout->setContentsMargins(0, 0, 0, 0); // ��ģ�顱 QToolButton QToolButton *moduleButton = new QToolButton(combinedWidget); // ���ø��� moduleButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); moduleButton->setFixedSize(80, 28); // ������ť��С moduleButton->setStyleSheet(R"( QToolButton { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 5px; padding: 0px; /* �Ƴ�Ĭ���ڱ߾� */ text-align: center; /* ʹ�ı����� */ } QToolButton::menu-indicator { image: none; } QToolButton::checked { background: #4CAF50; /* ������ɫ */ } /* ǿ���ı����� */ QToolButton::hover { qproperty-textAlignment: 'AlignCenter'; } )"); moduleButton->setText("ģ��"); moduleButton->setCheckable(true); moduleButton->setPopupMode(QToolButton::InstantPopup); m_fieldWidgets.append(moduleButton); // ������ QToolButton QToolButton *axisButton = new QToolButton(combinedWidget); // ���ø��� axisButton->setObjectName("axisButton"); // Ϊ����ť���ö������Ա���� axisButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); axisButton->setFixedSize(80, 28); // ������ť��С axisButton->setStyleSheet(R"( QToolButton { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 5px; padding: 0px; /* �Ƴ�Ĭ���ڱ߾� */ text-align: center; /* ʹ�ı����� */ } QToolButton::menu-indicator { image: none; } QToolButton::checked { background: #4CAF50; /* ������ɫ */ } /* ǿ���ı����� */ QToolButton::hover { qproperty-textAlignment: 'AlignCenter'; } )"); axisButton->setText("����"); axisButton->setCheckable(true); axisButton->setPopupMode(QToolButton::InstantPopup); axisButton->setEnabled(false); // ��ʼʱ��������ť m_fieldWidgets.append(axisButton); // ���� QMenu ���ڡ�����ť����������ʽ�� QMenu *axisMenu = new QMenu(axisButton); axisMenu->setStyleSheet(R"( QMenu { background-color: white; color: black; border: 1px solid #BABBDC; } QMenu::item:selected { background-color: #4CAF50; /* ѡ��ʱ������ɫ */ color: white; /* ѡ��ʱ������ɫ */ } )"); QJsonObject axisMap = fieldConfig["axisMap"].toObject(); // ��ʼ������˵�����Ϊ�գ��ȴ�ѡ��ģ������ axisButton->setMenu(axisMenu); //qDebug() << "��ʼ������˵�Ϊ�գ�" << fieldName; // ���ӡ�����ť�IJ˵������¼������¡����˵� connect(axisMenu, &QMenu::triggered, this, [axisButton](QAction *action){ axisButton->setText(action->text()); axisButton->setChecked(true); //qDebug() << "����ѡ��" << action->text(); }); // ��ģ�顱 QMenu QMenu *moduleMenu = new QMenu(moduleButton); moduleMenu->setStyleSheet(R"( QMenu { background-color: white; color: black; border: 1px solid #BABBDC; } QMenu::item:selected { background-color: #4CAF50; /* ѡ��ʱ������ɫ */ color: white; /* ѡ��ʱ������ɫ */ } )"); QJsonArray moduleOptions = fieldConfig["moduleOptions"].toArray(); for (const QJsonValue &mod : moduleOptions) { QAction *action = moduleMenu->addAction(mod.toString()); // ʹ�ð�ֵ����������ָ�� connect(action, &QAction::triggered, this, [moduleButton, action, fieldConfig, combinedWidget, fieldName, axisButton, axisMenu, axisMap]() { moduleButton->setText(action->text()); moduleButton->setChecked(true); //qDebug() << "ģ��ѡ��" << action->text(); // ���ı�����ɫΪ����ɫ moduleButton->setStyleSheet("background: #4CAF50;"); axisButton->setStyleSheet("background: #4CAF50;"); //qDebug() << "��Ͽؼ���ɫ���л�Ϊ������ɫ"; // ��������ť axisButton->setEnabled(true); // ��̬�������˵� axisMenu->clear(); // ������в˵��� if (axisMap.contains(action->text())) { QJsonArray axes = axisMap[action->text()].toArray(); for (const QJsonValue &axis : axes) { axisMenu->addAction(axis.toString()); } //qDebug() << "����˵��Ѹ���ģ��ѡ��̬���"; } else { //qDebug() << "û���ҵ���Ӧģ�������ѡ��"; } // ������ʱ�� int timeoutSec = fieldConfig["timeout"].toInt(180); // Ĭ��180�루3���ӣ� QTimer *timer = new QTimer(combinedWidget); timer->setSingleShot(true); connect(timer, &QTimer::timeout, combinedWidget, [moduleButton, axisButton]() { // �ָ�������ɫΪĬ�� moduleButton->setStyleSheet("background: #FFFFFF;"); axisButton->setStyleSheet("background: #FFFFFF;"); //qDebug() << "��Ͽؼ���ɫ���л�ΪĬ�ϣ���ʱ��"; }); timer->start(timeoutSec * 1000); // ����Ϊ timeoutSec * 1000 ���� (3����) //qDebug() << "������ʱ����" << timeoutSec << "��������Ͽؼ���ɫ"; }); } moduleButton->setMenu(moduleMenu); //qDebug() << "������Ͽؼ���ģ�鰴ť��" << fieldName; // ����һ������ widget ��������Ͽؼ� combinedLayout->addWidget(comboInput); combinedLayout->addWidget(moduleButton); combinedLayout->addWidget(axisButton); combinedLayout->addStretch(); // ��֤��Ͽؼ��������� rightLayout->addWidget(combinedWidget); //qDebug() << "��Ͽؼ������ӵ����֣�" << fieldName; } else { qWarning() << "δ֪�ֶ����ͣ�" << fieldType; } // �������Ŀؼ����ӵ��ؼ��б� if (createdWidget) { m_fieldWidgets.append(createdWidget); } // �� rightWidget �ӵ� fieldLayout ���Ҳ� fieldLayout->addWidget(rightWidget); // qDebug() << "�� rightWidget ���ӵ� fieldLayout"; // �� fieldLayout ���ӵ� scrollLayout scrollLayout->addLayout(fieldLayout); //qDebug() << "�����ֶβ��֣�" << fieldName; if (fieldConfig.contains("separator") && fieldConfig["separator"].toBool()) { QFrame *separator = createUnifiedSeparator(scrollWidget, 2); QHBoxLayout *separatorLayout = new QHBoxLayout; separatorLayout->setContentsMargins(0, 5, 0, 5); // 5px ���±߾� separatorLayout->addWidget(separator); scrollLayout->addLayout(separatorLayout); separator->show(); // ��ʾ�ָ��� //qDebug() << "����ͳһ�Ķ�̬�ָ��ߣ�������ʾ"; } } // �����������õײ�Ҳ��һ����϶ scrollLayout->addStretch(); // �� scrollWidget ���ø� scrollArea scrollArea->setWidget(scrollWidget); // scrollArea �ŵ� fieldWindow ���������� QVBoxLayout *mainLayout = new QVBoxLayout(fieldWindow); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->addWidget(scrollArea); // ��ʾ���� fieldWindow->show(); //qDebug() << "����Ŀ¼�ֶδ����Ѵ�"; } void TreeViewManager::onButtonUpClicked() { if (m_fieldWidgets.isEmpty()) { // �����ǰû�������˵���û�пɵ����Ŀؼ���ִ��ԭ�е�Ŀ¼������ // ������ѡ�����ť�����ָ�ԭ�е�Ŀ¼���������絼������һ��Ŀ¼� return; } if (m_currentFieldIndex <= 0) { // �Ѿ��ڵ�һ���ؼ����������ƶ� return; } // �ƶ�����һ���ؼ� m_currentFieldIndex--; QWidget *widgetToFocus = m_fieldWidgets[m_currentFieldIndex]; if (widgetToFocus) { widgetToFocus->setFocus(); } } // �� onButtonDownClicked ���� void TreeViewManager::onButtonDownClicked() { if (m_fieldWidgets.isEmpty()) { // �����ǰû�������˵���û�пɵ����Ŀؼ���ִ��ԭ�е�Ŀ¼������ // ������ѡ�����ť�����ָ�ԭ�е�Ŀ¼���������絼������һ��Ŀ¼� return; } if (m_currentFieldIndex < 0) { // �����ǰû���κοؼ����۽���Ĭ�Ͼ۽���һ���ؼ� m_currentFieldIndex = 0; } else if (m_currentFieldIndex >= m_fieldWidgets.size() - 1) { // �Ѿ������һ���ؼ����������ƶ� return; } else { // �ƶ�����һ���ؼ� m_currentFieldIndex++; } QWidget *widgetToFocus = m_fieldWidgets[m_currentFieldIndex]; if (widgetToFocus) { widgetToFocus->setFocus(); } } //�������а�ť void TreeViewManager::setupButton() { // ������ť���������� auto createButton = [&](QPushButton*& button, QWidget* parent, const QString& iconPath, const QRect& geometry) { button = new QPushButton(parent); button->setIcon(QIcon(iconPath)); button->setGeometry(geometry); button->setStyleSheet(R"( QPushButton { position: absolute; border-radius: 6px; opacity: 1; background: #FFFFFF; border: 1px solid #BABBDC; } QPushButton:hover { background-color: #A9B4FF; /* �����ͣЧ�� */ } )"); button->show(); }; createButton(buttonOpenFile, widget2, ":/images/home_openFile.png", QRect(328, 16, 76, 30)); createButton(buttonUp, widget2, ":/images/home_up.png", QRect(408, 16, 36, 30)); createButton(buttonDown, widget2, ":/images/home_down.png", QRect(408, 50, 36, 30)); createButton(buttonLeft, widget2, ":/images/home_left.png", QRect(328, 50, 36, 30)); createButton(buttonRight, widget2, ":/images/home_right.png", QRect(368, 50, 36, 30)); } void TreeViewManager::onButtonOpenFileClicked() { foreach (QObject *child, widget2->children()) { QWidget *childWidget = qobject_cast<QWidget *>(child); if (childWidget && childWidget->windowTitle() == "�ֶ�չʾ") { //qDebug() << "�ر��ֶδ��ڣ�" << childWidget; childWidget->close(); } } treeViewDown->show(); // ��ʾ treeViewDown treeViewDown->collapseAll(); // �������нڵ� treeViewDown->clearSelection(); // �����ؼ��б��ͽ������� m_fieldWidgets.clear(); m_currentFieldIndex = -1; // չ��һ��Ŀ¼ QStandardItem *rootItem = downModel->invisibleRootItem(); if (rootItem) { for (int i = 0; i < rootItem->rowCount(); ++i) { QStandardItem *childItem = rootItem->child(i); if (childItem) { treeViewDown->expand(downModel->indexFromItem(childItem)); // qDebug() << "չ��һ��Ŀ¼��" << childItem->text(); } } } // ���õ����� updateNavigationBar(QModelIndex()); // ���º��ߵ�λ�úͿɼ��� QTimer::singleShot(0, this, &TreeViewManager::updateSeparatorLine); //qDebug() << "�ɹ����ص�һ���˵�"; } void TreeViewManager::onButtonLeftClicked() { //qDebug() << "TreeViewManager: ������һ��Ŀ¼"; // ����Ƿ�������Ŀ¼�ֶ�չʾ���� bool isFieldWindowClosed = false; // ���º��ߵ�λ�úͿɼ��� QTimer::singleShot(0, this, &TreeViewManager::updateSeparatorLine); foreach (QObject *child, widget2->children()) { QWidget *childWidget = qobject_cast<QWidget *>(child); if (childWidget && childWidget->windowTitle() == "�ֶ�չʾ") { //qDebug() << "�ر�����Ŀ¼���ڲ����ص�����Ŀ¼"; childWidget->close(); // �ر��ֶ�չʾ���� isFieldWindowClosed = true; } } if (isFieldWindowClosed) { // ������ʾ treeViewDown ���ָ�����Ӧ������Ŀ¼���� treeViewDown->show(); QModelIndex currentIndex = treeViewDown->currentIndex(); if (currentIndex.isValid()) { updateNavigationBar(currentIndex); // ���µ����� //qDebug() << "���ص�����Ŀ¼������" << downModel->itemFromIndex(currentIndex)->text(); } else { qWarning() << "��ǰ������Ч�������µ�����"; } // �����ؼ��б��ͽ������� m_fieldWidgets.clear(); m_currentFieldIndex = -1; // ����ִ�����ϱ������� QModelIndex parentIndex = currentIndex.parent(); if (parentIndex.isValid()) { treeViewDown->setCurrentIndex(parentIndex); treeViewDown->expand(parentIndex); // ȷ�����ڵ�չ�� updateNavigationBar(parentIndex); // ���µ����� QStandardItem *parentItem = downModel->itemFromIndex(parentIndex); if (parentItem) { qDebug() << "������һ��Ŀ¼��" << parentItem->text(); } else { qWarning() << "δ�ҵ���Ŀ¼��"; } } else { qWarning() << "��ǰ�ڵ�û�и��ڵ�"; } return; } // ��ȡ��ǰѡ��������� QModelIndex currentIndex = treeViewDown->currentIndex(); if (!currentIndex.isValid()) { qDebug() << "��ǰ����Ч������������"; return; } // ��ȡ���ڵ����� QModelIndex parentIndex = currentIndex.parent(); if (parentIndex.isValid()) { // ����и��ڵ㣬���ص����ڵ� treeViewDown->setCurrentIndex(parentIndex); treeViewDown->expand(parentIndex); // չ�����ڵ� updateNavigationBar(parentIndex); // ���µ����� QStandardItem *parentItem = downModel->itemFromIndex(parentIndex); if (parentItem) { //qDebug() << "������һ��Ŀ¼��" << parentItem->text(); } else { qWarning() << "δ�ҵ���Ŀ¼��"; } } else { // ���û�и��ڵ㣬���ص�һ��Ŀ¼�ĵ�һ�� QModelIndex firstIndex = downModel->index(0, 0); if (firstIndex.isValid()) { treeViewDown->setCurrentIndex(firstIndex); treeViewDown->expand(firstIndex); // չ��һ��Ŀ¼ updateNavigationBar(firstIndex); // ���µ����� QStandardItem *firstItem = downModel->itemFromIndex(firstIndex); if (firstItem) { qDebug() << "���ص�һ��Ŀ¼�ĵ�һ�У�" << firstItem->text(); } else { qWarning() << "δ�ҵ�һ��Ŀ¼�ĵ�һ��"; } } else { qWarning() << "���ҵ��κ�һ��Ŀ¼"; } } } void TreeViewManager::onButtonRightClicked() { //qDebug() << "TreeViewManager: ������һ��Ŀ¼"; // ��ȡ��ǰѡ�������� QModelIndex currentIndex = treeViewDown->currentIndex(); if (!currentIndex.isValid()) { //qDebug() << "��ǰ����Ч�������Զ��ӵ�һ�����ڵ㿪ʼ"; currentIndex = downModel->index(0, 0); // �Ӹ��ڵ��һ����ʼ } QStandardItem *currentItem = downModel->itemFromIndex(currentIndex); if (!currentItem) { qWarning() << "����ȡ��ǰĿ¼��"; return; } // ��鵱ǰ���Ƿ����ӽڵ� if (currentItem->hasChildren()) { //qDebug() << "��ǰĿ¼����Ŀ¼��չ���������һ����Ŀ¼��" << currentItem->text(); // չ����ǰ������һ������ treeViewDown->expand(currentIndex); QModelIndex childIndex = downModel->index(0, 0, currentIndex); // ʹ�� QAbstractItemModel::index() if (childIndex.isValid()) { treeViewDown->setCurrentIndex(childIndex); updateNavigationBar(childIndex); // ���µ����� // qDebug() << "������Ŀ¼��" << downModel->itemFromIndex(childIndex)->text(); return; } else { qWarning() << "չ��ʧ�ܣ�δ�ҵ��ӽڵ�"; return; } } // ��ǰĿ¼û���ӽڵ㣬Ѱ��ͬ������һ���ڵ� QModelIndex nextSiblingIndex = currentIndex.siblingAtRow(currentIndex.row() + 1); while (!nextSiblingIndex.isValid()) { // ���û����һ��ͬ���ڵ㣬���ϲ��Ҹ��ڵ����һ��ͬ���ڵ� QModelIndex parentIndex = currentIndex.parent(); if (!parentIndex.isValid()) { // qDebug() << "�ѵ�����ײ�Ŀ¼��û�и������һ���ڵ�"; return; // �Ѿ����������нڵ� } nextSiblingIndex = parentIndex.siblingAtRow(parentIndex.row() + 1); currentIndex = parentIndex; } // ������һ��ͬ���ڵ� treeViewDown->setCurrentIndex(nextSiblingIndex); updateNavigationBar(nextSiblingIndex); // ���µ����� //qDebug() << "����ͬ��Ŀ¼��" << downModel->itemFromIndex(nextSiblingIndex)->text(); }