Where does QModelIndex() come from in seekRoot.parent() != QModelIndex(); - c++

In Qt help, there is an example in Model/View Tutorial - 3.2 Working with Selections. The resource codes are in Qt\Qt5.9.1\Examples\Qt-5.9.1\widgets\tutorials\modelview\7_selections.
I cannot understand what is QModelIndex() in while(seekRoot.parent() != QModelIndex()).
It looks like a constructor of QModelIndex, but what's the usage here? It returns a new empty model index? Or it is a function of MainWindow? It seems impossible.
Where does it come from? And what is the return value?
void MainWindow::selectionChangedSlot(const QItemSelection & /*newSelection*/, const QItemSelection & /*oldSelection*/)
{
//get the text of the selected item
const QModelIndex index = treeView->selectionModel()->currentIndex();
QString selectedText = index.data(Qt::DisplayRole).toString();
//find out the hierarchy level of the selected item
int hierarchyLevel=1;
QModelIndex seekRoot = index;
while(seekRoot.parent() != QModelIndex())
{
seekRoot = seekRoot.parent();
hierarchyLevel++;
}
QString showString = QString("%1, Level %2").arg(selectedText)
.arg(hierarchyLevel);
setWindowTitle(showString);
}

The empty QModelIndex() constructor indicates an invalid (i.e. non existing) QModelIndex:
Creates a new empty model index. This type of model index is used to
indicate that the position in the model is invalid.
So seekRoot.parent() != QModelIndex() checks if seekRoot has a parent (i.e. its parent is not invalid).
It could also be written (more clearly) as seekRoot.parent().isValid() (see QModelIndex::isValid).

The default constructor QModelIndex() creates a temporary invalid index the output of seekRoot.parent() call compared with. In other words, this expression checks whether the parent index is valid or not.

Related

How can I reference the value of a QVariant without making a copy?

As part of parsing a JSON response, we are traversing a tree of QVariantMaps. To my understanding, we are creating a copy at each level by calling QVariant::toMap() or qvariant_cast<QVariantMap>(). I would like to optimize this process however I can.
QString parse (QVariant input) {
QVariantMap map = input.toMap();
QVariant innerValue = map.value("key");
QVariantMap subMap = innerValue.toMap();
QVariant desiredValue = subMap.value("key2");
return desiredValue.toString();
}
Can we avoid copying each map by directly referencing the underlying value inside the QVariant? I assume that we would need a pointer, something like the following:
QString parse (QVariant input) {
// Assuming we know that input is a map
QVariantMap* map = getVariantPointer<QVariantMap*>(input);
QVariantMap* subMap = getVariantPointer<QVariantMap*>(map->value("key"));
return getVariantPointer<QString*>(subMap->value("key2"));

What should overloaded QAbstractItemModel::flags return for non valid QModelIndex?

I'm reading a QT documentation for a model/view architecture https://doc.qt.io/qt-5/model-view-programming.html#making-the-model-editable and see an example of overloading QAbstractItemModel::flags method that returns Qt::ItemIsEnabled for invalid index:
Qt::ItemFlags StringListModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::ItemIsEnabled;
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}
So, if index is not valid, i.e. can have negative row, we still consider that user can interact with it. Is there any sence for that logic? For me, returning Qt::NoItemFlags in that case could be more logical
What you need is Qt::NoItemFlags: https://doc.qt.io/Qt-5/qt.html#ItemFlag-enum.
It's the default value of the flags enum (since it's the first item in the enum). You could also write it as return {};, and it will give you the same Qt::NoItemFlags.

How to get data back from QVariant for a usertype?

I'm using a QVariant to store a pointer to my object in a QComboBox
void MainFrame::initContainerBox(QComboBox *oBox)
{
IDataContainer *idc = new CSVContainer();
QVariant v(QVariant::UserType, idc);
oBox->addItem(idc->getContainername(), v);
void *idc1 = v.data();
if(idc1 == idc)
printf("Test\n");
}
But how do I get the data back? When I use data() the pointer is different, so this doesn't seem to be correct. From gooogling I had the impression that I have to register a type for each class I want to use in a QVariant is that correct or can I retrieve the value without that?
After two days of googling and trying all kind of combinations I finally found out how to do this. Here is an example using a QComboBox putting an item and getting it back. IDataContainer * is an arbitrary class which is not related to Qt.
Q_DECLARE_METATYPE(IDataContainer *)
void MainFrame::initContainerBox(QComboBox *oBox)
{
IDataContainer *idc = new CSVContainer();
QVariant v;
v.setValue(idc);
oBox->addItem(idc->getContainername(), v);
QVariant v2 = oBox->itemData(oBox->currentIndex());
IDataContainer *idc1 = v2.value<IDataContainer *>();
if(idc1 == idc)
printf("Test\n");
}
So with my first approach of using value() I was on the right track, the only missing bits were how to set the value and using the macro Q_DECLARE_METATYPE(IDataContainer *).
Apparently using the constructor doesn't work, so one has to call setValue() instead. If somebody knows how to use the constructor it would be nice to show it.

Qt ActiveX dynamicCall return value always empty

This is a follow up to a previous question: Qt ActiveX
I am trying to use an ActiveX control in my program.
QAxWidget* mAX = new QAxWidget();
mAX->setControl("{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}");
I know that there is a function like the one below (used getDocumentation()):
SendCommand(QString input, QString& output)
But when I try to execute it:
QString returString;
mAX->dynamicCall("SendCommand(QString,QString&)","something",returnString);
I always get:
returString = "";
I searched the web and saw a similar bug which was reported on their bug tracker. It does not seem fixed yet:
Calling functions through dynamicCall() don't return values by QVariant
Also a post where someone seems to have the same problem:
QAxObject and dynamicCall
Anybody know of a solution/work around ?
EDIT:
The original function is SendCommand(LPCTSTR command,BSTR* ret).
Maybe an issue with the way the BSTR* is handled as a &QString ?
you can use this solution
QString strRetVal;
QVariant returnValue("");
QVariant param1("something");
QList<QVariant> inplist;
inplist<<param1;
inplist<<returnValue;
mAX->dynamicCall("SendCommand(QString,QString&)",inplist );
strRetVal=inplist.at(1).toString();
From looking at the documentation, you are not calling the function correctly. You are passing in a QString, yet the function takes a QVariant. Since QVariant doesn't have explicit constructors (by design), a temporary QVariant is created and passed to dynamicCall. As a consequence your returnValue doesn't get updated.
QVariant dynamicCall( const char * function, const QVariant & var1 = QVariant(), ...
, const QVariant & var8 = QVariant() )
I think that everything will work when you use a QVariant instead.
QVariant returnValue;
mAX->dynamicCall("SendCommand(QString,QString&)", "something", returnValue );

Converting QModelIndex to QString

Is there a way to convert QModelIndex to QString? The main goal behind this is that I want to work with the contents of dynamically generated QListView-Items.
QFileSystemModel *foolist = new QFileSystemModel;
foolist->setRootPath(QDir::rootPath());
foolistView->setModel(foolist);
[...]
QMessageBox bar;
QString foolist_selectedtext = foolistView->selectionModel()->selectedIndexes();
bar.setText(foolist_selectedtext);
bar.exec;
Is this even the correct way to get the currently selected Item?
Thanks in advance!
foolistView->selectionModel()->selectedIndexes();
Send you back a QList of QModelIndex (only one if you view is in QAbstractItemView::SingleSelection)
The data method of QModelIndex return a QVariant corresponding to the value of this index.
You can get the string value of this QVariant by calling toString on it.
No, is the short answer. A QModelIndex is an index into a model - not the data held in the model at that index. You need to call data( const QModelIndex& index, int role = Qt::DisplayRole) const on your model with index being your QModelIndex. If you're just dealing with text the DislayRole should sufficient.
Yes the way you are getting the selected item is correct, but depending your selection mode, it may return more than one QModelIndex (in a QModelIndexList).
QModelIndex is identifier of some data structure. You should read QModelIndex documentation. There is a QVariant data(int role) method. In most cases you will need Qt::DisplayRole to get selected item text. Note that also selectIndexes() returns a list of QModelIndex. It may be empty or contain more then one item. If you want to get (i.e. comma separated) texts of all selected indexes you should do something like this:
QModelIndexList selectedIndexes = foolistView->selectionModel()->selectedIndexes();
QStringList selectedTexts;
foreach(const QModelIndex &idx, selectedIndexes)
{
selectedTexts << idx.data(Qt::DisplayRole).toString();
}
bar.setText(selectedTexts.join(", "));