Проверьте редактирование для окончательного кода!
Итак... я признаю, что рисую здесь абсолютную пустоту из-за недостатка знаний, и просто представлю свой код и немного помолюсь.
Используя этот фантастический генератор xml в QTreeWidget, который ekhumoro закодировал, я я добавил флажки (tristate для родительских узлов), и теперь я пытаюсь перебрать эти флажки и вернуть словарь или список списков или... что-то с отношением родитель: дети (сервер: службы в этом дереве), поэтому что я могу построить пути к папкам из проверенных результатов дерева. Это произойдет при нажатии кнопки «Пуск» в качестве первой функции в серии.
Конечная цель состоит в том, чтобы иметь инструмент, который извлекает журналы с нескольких серверов и служб для каждого сервера на платформе на основе предоставленного пользователем времени запуска и остановки и доставляет эти журналы в окно администратора с идентичной структурой папок.
Я успешно просмотрел тестовый словарь, нашел и нашел файлы на основе os.path.getctime и getmtime, заархивировал их, а затем скопировал на отдельный диск с идентичной структурой папок, созданной как часть функции...
Однако я практически не нашел документации по TreeWidgetItemIterator (только http://pyqt.sourceforge.net/Docs/PyQt4/qtreewidgetitemiterator.html#details), который мне не очень помог. Итак, я потерял неотъемлемую (и последнюю) часть этой головоломки!
XMLHandler:
from PyQt4 import QtCore, QtGui, QtXml
from PyQt4.QtXml import *
class XmlHandler(QXmlDefaultHandler):
def __init__(self, root):
QtXml.QXmlDefaultHandler.__init__(self)
self._root = root
self._item = None
self._text = ''
self._error = ''
def startElement(self, namespace, name, qname, attributes):
if qname == 'Machine' or qname == 'Feature':
if self._item is not None:
self._item = QtGui.QTreeWidgetItem(self._item)
else:
self._item = QtGui.QTreeWidgetItem(self._root)
self._item.setData(0, QtCore.Qt.UserRole, qname)
self._item.setText(0, 'Unknown Machine')
if qname == 'Machine':
self._item.setExpanded(False)
self._item.setCheckState(0, QtCore.Qt.Unchecked)
self._item.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsDragEnabled|QtCore.Qt.ItemIsUserCheckable|QtCore.Qt.ItemIsEnabled|QtCore.Qt.ItemIsTristate)
elif qname == 'FeatureName':
self._item.setText(1, self._text)
self._text = ''
return True
def endElement(self, namespace, name, qname):
if qname == 'FeatureName' or qname == 'MachineName':
if self._item is not None:
self._item.setText(0, self._text)
self._item.setCheckState(0, QtCore.Qt.Unchecked)
elif qname == 'Feature' or qname == 'Machine':
self._item = self._item.parent()
return True
def characters(self, text):
self._text += text
return True
def fatalError(self, exception):
print('Parse Error: line %d, column %d:\n %s' % (
exception.lineNumber(),
exception.columnNumber(),
exception.message(),
))
return False
Класс, который использует XmlHandler для создания виджета:
class MakeWidget(QtGui.QTreeWidget):
def __init__(self):
QtGui.QTreeWidget.__init__(self)
self.header().setResizeMode(QtGui.QHeaderView.Stretch)
self.setHeaderLabels(['Servers and Services'])
source = QtXml.QXmlInputSource()
source.setData(xml)
handler = XmlHandler(self)
reader = QtXml.QXmlSimpleReader()
reader.setContentHandler(handler)
reader.setErrorHandler(handler)
reader.parse(source)
Создание виджета в моем графическом интерфейсе:
self.treeServiceSelection = MakeWidget(xml, parent=self.ui.groupBoxServiceSelection)
Виджет двухуровневый с родителями и детьми, вот и все:
https://i.imgur.com/npPhG41.jpg
И вот мы подошли к тому, где я застрял. Я могу привязать сигнал к нажатию кнопки, я могу делать все остальное, но получать проверенные элементы из QTreeWidget. Кажется, мне нужно было бы создать итератор и установить флаг Checked в его init, но все, что я пробовал, приводило к bupkiss. Я более чем счастлив работать над решением, а не получать его, но отсутствие отправной точки меня угнетает.
Редактировать: Таким образом, ничто из того, что я на самом деле опубликовал, не было бесполезным, но ekhumoro понял суть моего вопроса и предоставил свое решение (принятый ответ). Я добавил один elif
для обработки всего, где был проверен родитель (поскольку, похоже, не читалось, что дети были проверены в результате этого):
def exportTree(self):
mapping = defaultdict(list)
root = self.tree.invisibleRootItem()
for index in range(root.childCount()):
parent = root.child(index)
if parent.checkState(0) == QtCore.Qt.PartiallyChecked:
features = mapping[parent.text(0)]
for row in range(parent.childCount()):
child = parent.child(row)
if child.checkState(0) == QtCore.Qt.Checked:
features.append(child.text(0))
elif parent.checkState(0) == QtCore.Qt.Checked:
features = mapping[parent.text(0)]
for row in range(parent.childCount()):
features.append((parent.child(row)).text(0))
return mapping
а затем смог использовать этот пример для выбора конкретных дочерних элементов на основе другого поля со списком в другом месте графического интерфейса:
def checkbox2mods(self):
d = {'DMD2K8COR2VM': ['CC2DCP', 'Centercord'],
'DMD2K8COR1VM': ['CC2DCP', 'Centercord']}
root = self.tree.invisibleRootItem()
if self.checkBox2.checkState() == QtCore.Qt.Checked:
for index in range(root.childCount()):
parent = root.child(index)
for row in range(parent.childCount()):
child = parent.child(row)
x = d.values()
y = d.keys()
for _ in x:
if child.text(0) in _:
if parent.text(0) in y:
child.setCheckState(0, QtCore.Qt.Checked)
parent.setExpanded(True)
Я уверен, что код неприятный, но, выбирая только дочерние элементы, он частично проверяет родителей, что позволяет функции экспорта работать правильно.