File indexing completed on 2024-05-12 15:27:53
0001 /*************************************************************************** 0002 File : ROOTOptionsWidget.cpp 0003 Project : LabPlot 0004 Description : widget providing options for the import of ROOT data 0005 -------------------------------------------------------------------- 0006 Copyright : (C) 2018 Christoph Roick (chrisito@gmx.de) 0007 ***************************************************************************/ 0008 0009 /*************************************************************************** 0010 * * 0011 * This program is free software; you can redistribute it and/or modify * 0012 * it under the terms of the GNU General Public License as published by * 0013 * the Free Software Foundation; either version 2 of the License, or * 0014 * (at your option) any later version. * 0015 * * 0016 * This program is distributed in the hope that it will be useful, * 0017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0019 * GNU General Public License for more details. * 0020 * * 0021 * You should have received a copy of the GNU General Public License * 0022 * along with this program; if not, write to the Free Software * 0023 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0024 * Boston, MA 02110-1301 USA * 0025 * * 0026 ***************************************************************************/ 0027 0028 #include "ROOTOptionsWidget.h" 0029 #include "ImportFileWidget.h" 0030 0031 #include "backend/datasources/filters/ROOTFilter.h" 0032 #include "backend/lib/macros.h" 0033 0034 ROOTOptionsWidget::ROOTOptionsWidget(QWidget* parent, ImportFileWidget* fileWidget) : QWidget(parent), m_fileWidget(fileWidget) { 0035 ui.setupUi(parent); 0036 histItem = new QTreeWidgetItem(ui.twContent, QStringList(i18n("Histograms"))); 0037 histItem->setFlags(Qt::ItemIsEnabled); 0038 treeItem = new QTreeWidgetItem(ui.twContent, QStringList(i18n("Trees and Tuples"))); 0039 treeItem->setFlags(Qt::ItemIsEnabled); 0040 0041 connect(ui.twContent, &QTreeWidget::itemSelectionChanged, this, &ROOTOptionsWidget::rootObjectSelectionChanged); 0042 connect(ui.bRefreshPreview, &QPushButton::clicked, fileWidget, &ImportFileWidget::refreshPreview); 0043 } 0044 0045 void ROOTOptionsWidget::clear() { 0046 qDeleteAll(histItem->takeChildren()); 0047 qDeleteAll(treeItem->takeChildren()); 0048 ui.twPreview->clearContents(); 0049 } 0050 0051 void fillTree(QTreeWidgetItem* node, const ROOTFilter::Directory& dir) 0052 { 0053 node->setFlags(Qt::ItemIsEnabled); 0054 for (const ROOTFilter::Directory& child : dir.children) 0055 fillTree(new QTreeWidgetItem(node, QStringList(child.name)), child); 0056 for (const auto& content : dir.content) 0057 (new QTreeWidgetItem(node, QStringList(content.first)))->setData(0, Qt::UserRole, content.second); 0058 } 0059 0060 QHash<QStringList, QVector<QStringList> > findLeaves( 0061 QTreeWidgetItem* node, 0062 ROOTFilter* filter, 0063 const QString& fileName, const QStringList& path = QStringList{} 0064 ) { 0065 QHash<QStringList, QVector<QStringList> > leaves; 0066 if (node->childCount() > 0) { 0067 for (int i = 0; i < node->childCount(); ++i) 0068 leaves.unite(findLeaves(node->child(i), filter, fileName, path + QStringList(node->child(i)->text(0)))); 0069 } else { 0070 leaves[path] = filter->listLeaves(fileName, node->data(0, Qt::UserRole).toLongLong()); 0071 } 0072 return leaves; 0073 } 0074 0075 void ROOTOptionsWidget::updateContent(ROOTFilter* filter, const QString& fileName) { 0076 DEBUG("updateContent()"); 0077 0078 qDeleteAll(histItem->takeChildren()); 0079 qDeleteAll(treeItem->takeChildren()); 0080 fillTree(histItem, filter->listHistograms(fileName)); 0081 fillTree(treeItem, filter->listTrees(fileName)); 0082 leaves = findLeaves(treeItem, filter, fileName); 0083 } 0084 0085 void ROOTOptionsWidget::rootObjectSelectionChanged() { 0086 DEBUG("rootObjectSelectionChanged()"); 0087 auto items = ui.twContent->selectedItems(); 0088 QDEBUG("SELECTED ITEMS =" << items); 0089 0090 ui.twColumns->clear(); 0091 0092 if (items.isEmpty()) { 0093 ui.twColumns->setHeaderHidden(true); 0094 return; 0095 } 0096 0097 QTreeWidgetItem* p = items.first(); 0098 QStringList path; 0099 while (p && p != histItem && p != treeItem) { 0100 path.prepend(p->text(0)); 0101 p = p->parent(); 0102 } 0103 0104 if (p == histItem) { 0105 ui.twColumns->setColumnCount(1); 0106 ui.twColumns->setHeaderHidden(false); 0107 ui.twColumns->setHeaderLabels(QStringList(i18n("Histogram Data"))); 0108 0109 auto center = new QTreeWidgetItem(ui.twColumns, QStringList(i18n("Bin Center"))); 0110 center->setData(0, Qt::UserRole, QStringList(QStringLiteral("center"))); 0111 center->setSelected(true); 0112 center->setFirstColumnSpanned(true); 0113 auto low = new QTreeWidgetItem(ui.twColumns, QStringList(i18n("Low Edge"))); 0114 low->setData(0, Qt::UserRole, QStringList(QStringLiteral("low"))); 0115 low->setFirstColumnSpanned(true); 0116 auto content = new QTreeWidgetItem(ui.twColumns, QStringList(i18n("Content"))); 0117 content->setData(0, Qt::UserRole, QStringList(QStringLiteral("content"))); 0118 content->setSelected(true); 0119 content->setFirstColumnSpanned(true); 0120 auto error = new QTreeWidgetItem(ui.twColumns, QStringList(i18n("Error"))); 0121 error->setData(0, Qt::UserRole, QStringList(QStringLiteral("error"))); 0122 error->setSelected(true); 0123 error->setFirstColumnSpanned(true); 0124 0125 if (!histselected) { 0126 histselected = true; 0127 ui.sbFirst->setMaximum(0); 0128 ui.sbLast->setMaximum(0); 0129 } 0130 } else if (p == treeItem) { 0131 ui.twColumns->setColumnCount(2); 0132 ui.twColumns->setHeaderHidden(false); 0133 ui.twColumns->setHeaderLabels(QStringList({i18n("Branch/Leaf"), i18n("Array Size")})); 0134 0135 auto it = leaves.find(path); 0136 if (it != leaves.end()) { 0137 for (const auto& l : it.value()) { 0138 auto leaf = new QTreeWidgetItem(ui.twColumns, l); 0139 bool ok = false; 0140 if (l.count() > 1) { 0141 QString index(l.back()); 0142 if (index.at(0) == '[' && index.at(index.size() - 1) == ']') { 0143 size_t elements = index.midRef(1, index.length() - 2).toUInt(&ok); 0144 if (ok) { 0145 leaf->setFlags(Qt::ItemIsEnabled); 0146 QStringList elname({l.at(l.count() - 2), QString()}); 0147 QStringList eldata(elname); 0148 if (l.count() > 2) 0149 eldata.prepend(l.front()); 0150 for (size_t i = 0; i < elements; ++i) { 0151 eldata.last() = elname.last() = QString("[%1]").arg(i); 0152 auto el = new QTreeWidgetItem(leaf, elname); 0153 el->setData(0, Qt::UserRole, eldata); 0154 } 0155 } 0156 } 0157 } else 0158 leaf->setFirstColumnSpanned(true); 0159 0160 if (!ok) 0161 leaf->setData(0, Qt::UserRole, l); 0162 } 0163 0164 ui.twColumns->header()->setSectionResizeMode(QHeaderView::ResizeToContents); 0165 } 0166 0167 if (histselected) { 0168 histselected = false; 0169 ui.sbFirst->setMaximum(0); 0170 ui.sbLast->setMaximum(0); 0171 } 0172 } 0173 0174 m_fileWidget->refreshPreview(); 0175 } 0176 0177 const QStringList ROOTOptionsWidget::selectedNames() const { 0178 QStringList names; 0179 0180 for (QTreeWidgetItem* item : ui.twContent->selectedItems()) { 0181 QString path; 0182 while (item && item != histItem && item != treeItem) { 0183 path.prepend('/' + item->text(0)); 0184 item = item->parent(); 0185 } 0186 path[0] = ':'; 0187 if (item == histItem) 0188 names << QStringLiteral("Hist") + path; 0189 else if (item == treeItem) 0190 names << QStringLiteral("Tree") + path; 0191 } 0192 0193 return names; 0194 } 0195 0196 QVector<QStringList> ROOTOptionsWidget::columns() const { 0197 QVector<QStringList> cols; 0198 0199 // ui.twColumns->selectedItems() returns the items in the order of selection. 0200 // Iterate through the tree to retain the displayed order. 0201 for (int t = 0; t < ui.twColumns->topLevelItemCount(); ++t) { 0202 auto titem = ui.twColumns->topLevelItem(t); 0203 if (titem->isSelected()) 0204 cols << titem->data(0, Qt::UserRole).toStringList(); 0205 for (int c = 0; c < titem->childCount(); ++c) { 0206 auto citem = titem->child(c); 0207 if (citem->isSelected()) 0208 cols << citem->data(0, Qt::UserRole).toStringList(); 0209 } 0210 } 0211 0212 return cols; 0213 } 0214 0215 void ROOTOptionsWidget::setNRows(int nrows) { 0216 // try to retain the range settings: 0217 // - if nrows was not 0, keep start row, 0218 // else set it to one after underflow 0219 // - if nrows didn't change, keep end row, 0220 // else set it to one before overflow 0221 const int max = qMax(nrows - 1, 0); 0222 int firstval = ui.sbFirst->value(); 0223 if (ui.sbFirst->maximum() == 0) 0224 firstval = qMin(nrows - 1, histselected ? 1 : 0); 0225 ui.sbFirst->setMaximum(max); 0226 ui.sbFirst->setValue(firstval); 0227 0228 int lastval = max == ui.sbLast->maximum() ? ui.sbLast->value() 0229 : qMax(max - (histselected ? 1 : 0), 0); 0230 ui.sbLast->setMaximum(max); 0231 ui.sbLast->setValue(lastval); 0232 }