#include #include #include #include #include #include namespace { /// Number of columns displayed in the tree const auto TREE_NB_COLUMNS = 1; /// Header labels for the tree const auto TREE_HEADER_LABELS = QStringList { QObject::tr("Name") }; /** * Creates the item associated to a data source * @param dataSource the data source for which to create the item * @return the new item */ DataSourceTreeWidgetItem* createTreeWidgetItem(DataSourceItem* dataSource) { // Creates item for the data source auto item = new DataSourceTreeWidgetItem { dataSource }; // Generates items for the children of the data source std::for_each(dataSource->cbegin(), dataSource->cend(), [&item](const std::unique_ptr& child) { item->addChild(createTreeWidgetItem(child.get())); }); return item; } } // namespace DataSourceWidget::DataSourceWidget(QWidget* parent) : QWidget { parent } , ui { new Ui::DataSourceWidget } , m_Root { std::make_unique( DataSourceItemType::NODE, QStringLiteral("Sources")) } { ui->setupUi(this); // Set tree properties ui->treeWidget->setColumnCount(TREE_NB_COLUMNS); ui->treeWidget->setHeaderLabels(TREE_HEADER_LABELS); ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); // Connection to show a menu when right clicking on the tree connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this, &DataSourceWidget::onTreeMenuRequested); // Connection to filter tree connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &DataSourceWidget::filterChanged); // First init updateTreeWidget(); } DataSourceWidget::~DataSourceWidget() noexcept { delete ui; } void DataSourceWidget::addDataSource(DataSourceItem* dataSource) noexcept { // Merges the data source (without taking its root) if (dataSource) { std::for_each(std::cbegin(*dataSource), std::cend(*dataSource), [this](const auto& child) { this->m_Root->merge(*child.get()); }); updateTreeWidget(); } } void DataSourceWidget::updateTreeWidget() noexcept { ui->treeWidget->clear(); auto rootItem = createTreeWidgetItem(m_Root.get()); ui->treeWidget->addTopLevelItem(rootItem); rootItem->setExpanded(true); // Sorts tree ui->treeWidget->setSortingEnabled(true); ui->treeWidget->sortByColumn(0, Qt::AscendingOrder); } void DataSourceWidget::filterChanged(const QString& text) noexcept { auto validateItem = [&text](const DataSourceTreeWidgetItem& item) { auto regExp = QRegExp { text, Qt::CaseInsensitive, QRegExp::Wildcard }; // An item is valid if any of its metadata validates the text filter auto itemMetadata = item.data()->data(); auto itemMetadataEnd = itemMetadata.cend(); auto acceptFilter = [®Exp](const auto& variant) { return variant.toString().contains(regExp); }; return std::find_if(itemMetadata.cbegin(), itemMetadataEnd, acceptFilter) != itemMetadataEnd; }; // Applies filter on tree widget DataSourceTreeWidgetHelper::filter(*ui->treeWidget, validateItem); } void DataSourceWidget::onTreeMenuRequested(const QPoint& pos) noexcept { // Retrieves the selected item in the tree, and build the menu from its actions if (auto selectedItem = dynamic_cast(ui->treeWidget->itemAt(pos))) { QMenu treeMenu {}; treeMenu.addActions(selectedItem->actions()); if (!treeMenu.isEmpty()) { treeMenu.exec(QCursor::pos()); } } }