4

I have a simple QTreeWidget pointing to the root directory:

#include <QTreeWidget>
#include <QStringList>
#include <QApplication>

int main(int argc, char **argv)
{
QApplication application(argc, argv);
QStringList fileNames{"TEST/branch", "trunk"};
QTreeWidget treeWidget;
treeWidget.setColumnCount(1);

for (const auto& filename : fileNames) 
{
    QTreeWidgetItem *parentTreeItem = new QTreeWidgetItem(&treeWidget);
    parentTreeItem->setText(0, filename.split('/').first());
    QStringList filenameParts = filename.split('/').mid(1);

    for(const auto& filenamePart : filenameParts) 
    {
         QTreeWidgetItem *treeItem = new QTreeWidgetItem();
         treeItem->setText(0, filenamePart);
         parentTreeItem->addChild(treeItem);
         parentTreeItem = treeItem;
    }
}

treeWidget.show();
return application.exec();
}

Output:

enter image description here

The item I have selected above is /TEST/branches. How can I get the absolute path of the currently selected item?

oğuzhan kaynar
  • 77
  • 1
  • 10
  • Shouldn't *the absolute path of the currently selected item* in the screenshot be `/TEST`? How exactly is it `/TEST/branches`? – Mike Dec 08 '16 at 12:44
  • When I click on the branches directory, I want view "branches" file path. So, branches file path= TEST/branches. @Mike – oğuzhan kaynar Dec 08 '16 at 13:00

2 Answers2

3

Well, I don't think there is a built in function does that but you can write a function yourself like

QString treeItemToFullPath(QTreeWidgetItem* treeItem)
{
    QString fullPath= treeItem->text(0);

    while (treeItem->parent() != NULL)
    {
        fullPath= treeItem->parent()->text(0) + "/" + fullPath;
        treeItem = treeItem->parent();
    }
    return fullPath;
}

edit: Input treeItem is the selected tree item that you want to show its path. if you are sure at least one item is selected, you can get it by

treeWidget.selectedItems().first();

Another mehtod is using tooltips. You can add tip for each item, while you are adding them to tree, but you can do this after you add them in their final place.

change this

for(const auto& filenamePart : filenameParts) 
{
     QTreeWidgetItem *treeItem = new QTreeWidgetItem();
     treeItem->setText(0, filenamePart);
     parentTreeItem->addChild(treeItem);
     parentTreeItem = treeItem;
}

as this

for(const auto& filenamePart : filenameParts) 
{
     QTreeWidgetItem *treeItem = new QTreeWidgetItem();
     treeItem->setText(0, filenamePart);
     parentTreeItem->addChild(treeItem);
     parentTreeItem = treeItem;
     treeItem->setToolTip(0, treeItemToFullPath(treeItem));
}

this way you will see the full path whenever you hover the mouse on the item.

t.m.
  • 1,430
  • 16
  • 29
  • What to send as a parameter when calling a function @tm – oğuzhan kaynar Dec 09 '16 at 06:22
  • The selected treewidget item that you want to get its path. You can reach all selected items at a certain time by treeWidget.selectedItems(); – t.m. Dec 09 '16 at 06:26
  • Do you know how to connect clicked item to a function? – t.m. Dec 09 '16 at 06:30
  • I edited the answer and added an alternative method. – t.m. Dec 09 '16 at 06:52
  • Well, if you want to use second option I explained, you don't need to connect click event to a function. If you insist this should be a click event, you should connect void QTreeWidget::itemClicked(QTreeWidgetItem *item, int column) event to a function first, or make connection as in Kube Ober's answer. – t.m. Dec 09 '16 at 08:01
  • I wanted it to be. Thank you :). @t.m. – oğuzhan kaynar Dec 09 '16 at 08:45
2

To get notified of the current item change, one can use QTreeWidget::currentItemChanged or QItemSelectionModel::currentChanged.

There are two main approaches to obtaining the full path:

  1. Iterate up the tree from the selected item and reconstruct the path. This keeps the data model normalized - without redundant information.

  2. Store full path to each item.

If the tree is large, storing the model normalized will use less memory. Given that selection of the items is presumably rare because it's done on explicit user input, the cost of iterating the tree to extract the full path is minuscule. Humans aren't all that fast when it comes to mashing the keys or the mouse button.

The example demonstrates both approaches:

// https://github.com/KubaO/stackoverflown/tree/master/questions/tree-path-41037995
#include <QtWidgets>

QTreeWidgetItem *get(QTreeWidgetItem *parent, const QString &text) {
   for (int i = 0; i < parent->childCount(); ++i) {
      auto child = parent->child(i);
      if (child->text(0) == text)
         return child;
   }
   return new QTreeWidgetItem(parent, {text});
}

int main(int argc, char **argv)
{
   QApplication app(argc, argv);
   QStringList filenames{"TEST/branch", "TEST/foo", "trunk"};
   QWidget window;
   QVBoxLayout layout(&window);
   QTreeWidget treeWidget;
   QLabel label1, label2;

   for (const auto &filename : filenames) {
      QString path;
      auto item = treeWidget.invisibleRootItem();
      for (auto const &chunk : filename.split('/')) {
         item = get(item, chunk);
         path.append(QStringLiteral("/%1").arg(chunk));
         item->setData(0, Qt::UserRole, path);
      }
   }

   QObject::connect(&treeWidget, &QTreeWidget::currentItemChanged, [&](const QTreeWidgetItem *item){
      QString path;
      for (; item; item = item->parent())
         path.prepend(QStringLiteral("/%1").arg(item->text(0)));
      label1.setText(path);
   });

   QObject::connect(&treeWidget, &QTreeWidget::currentItemChanged, [&](const QTreeWidgetItem *item){
      label2.setText(item->data(0, Qt::UserRole).toString());
   });

   layout.addWidget(&treeWidget);
   layout.addWidget(&label1);
   layout.addWidget(&label2);
   window.show();
   return app.exec();
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313