Getting access to filepath with QFileSystemModel - c++

I have a QFileSystemModel within a QListView that allows me to select items within the file system.
When I select an item, I want to return the filepath in a QMessageBox.
So far I have the following code:
filemodel = new QFileSystemModel(this);
filemodel->setFilter(QDir::NoDotAndDotDot | QDir::Files);
filemodel->setNameFilters(filters);
filemodel->setNameFilterDisables(false);
filemodel->setRootPath(sPath);
//get file path
QString filepath = filemodel->fileName(index);
QMessageBox::information(this, "title", filepath);
ui->listView->setModel(filemodel);
This creates the filemodel.
I'm getting this error:
mainwindow.cpp:46: error: no matching function for call to 'QFileSystemModel::fileName(char* (&)(const char*, int))'
Is this the correct way to go about this? Returning the filepath when an item is selected?
EDIT #dunc123
In constructor:
connect(ui->listView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(selectedFile(QItemSelection one, QItemSelection two)));
selectedFile:
void MainWindow::selectedFile(QItemSelection one, QItemSelection two){
QString file_name = filemodel->fileName(ui->listView->selectionModel()->currentIndex());
QMessageBox::information(this, "title", file_name);
}
It builds and runs but when I click on a file, I get the following error:
Object::connect: No such slot MainWindow::selectedFile(QItemSelection one, QItemSelection two) in ../Images/mainwindow.cpp:26
Object::connect: (receiver name: 'MainWindow')
I'm assuming the way I pass the variables is wrong?
Could you help me out?

You need to pass a QModelIndex object to the fileName method of QFileSystemModel. It appears the symbol "index" is being resolved as a function. At a guess you have a member function named index in your class.
Edit:
The larger issue here is that you want something to happen when you select an item in your QListView, but you are putting the code to handle this in the constructor. You need to create a slot in your class and connect this to the signal emitted when an item is selected.
connect(ui->listView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &), this, SLOT(...));
In this slot you should call the fileName method and display that information. You'll need to make filemodel a member variable of your class as well so that you can access it from the slot.
Edit 2:
The way you are specifying your slot when calling connect is incorrect, it should be:
connect(ui->listView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(selectedFile(QItemSelection , QItemSelection)));
However, since you aren't using either of those parameters in your slot, you can infact remove them all together from your slot, e.g. define it in your header as:
void selectedFile();
And connect it using:
connect(ui->listView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(selectedFile()));
QT will work out that you don't want either of the parameters from the signal.

You can get a list of selected indexes with QItemSelectionModel::selectedIndexes() function.
Heres an example of how you can use it:
QModelIndexList list = ui->listView->selectionModel()->selectedIndexes();
foreach (QModelIndex index, list)
{
QString file_name = fileModel->fileName(index);
}
Or if you can only select a single item, you can use the QItemSelectionModel::currentIndex function like this:
QString file_name = fileMode->fileName(ui->listView->selectionModel()->currentIndex());
You can also connect the QItemSelectionModel::selectionChanged signal to a slot and use that in similar fashion. QListView has a selectionModel() function that you can use to retrieve a QItemSelectionModel object. QItemSelection has a indexes() function that returns a QModelIndexList.

QString filepath = filemodel->fileName(index);
mainwindow.cpp:46: error: no matching function for call to 'QFileSystemModel::fileName(char* (&)(const char*, int))'
Looks like "index" is a function, not a QModelIndex...
You can use a slot that is connected to the model's signal "currentChanged(QModelIndex,QModelIndex)" to get the new selected index.

Related

passing the QAction's QString text as an argument

I have a QAction which when clicked emits a triggered signal which calls the slot method RegroupEtudes::OnNouvelleEtude
connect(ui.actionNouvelle_tude, &QAction::triggered, this, &RegroupEtudes::OnNouvelleEtude);
It is possible for void RegroupEtudes::OnNouvelleEtude() to take a QString parameter if I change its definition. But how can i have QAction::triggered give its text QString parameter to void RegroupEtudes::OnNouvelleEtude() ?
That is, if my QAction is named "etude 1", is there anyway that RegroupEtudes::OnNouvelleEtude(QString) gets called as RegroupEtudes::OnNouvelleEtude("etude 1") ?
Since Qt5, you can use a lambda expression and the new connect synthax to pass an extra parameter to your slot:
QAction *actionNouvelle_tude = new QAction(tr("Nouvelle étude..."), this);
connect(actionNouvelle_tude, &QAction::triggered, this, [openAct, this]() {
this->OnNouvelleEtude(openAct->text());
});
It will call OnNouvelleEtude with the text of your action as parameter

How to programmatically change the Index of QComboBox using QStandardItemModel?

How to use the QStandardItemModel::setData function to set the current value for a QComboBox that is found in a certain cell for example at index (0,0) that works as a delegate such that the QStandardItemModel::setData function calls the ComboBoxItemDelegate::setModelData function.
I know that ComboBoxItemDelegate::setModelData function is called when an item is selected from the comboBox but my problem is that ComboBoxItemDelegate::setModelData function is not called by calling the comboBox::setData.
So I want to call comboBox::setData or (any other function that) programatically that will call ComboBoxItemDelegate::setModelData
What I have tried:
Here is the setModelData function that is called when an item from the comboBox is selected from the UI:
void ComboBoxItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
if (QComboBox* cb = qobject_cast<QComboBox*>(editor)){
qDebug()<<"hello, i have been called from the setModelData";
}
else
QStyledItemDelegate::setModelData(editor, model, index);
}
But when I tried to set the data of the comboBox (that is found in index (0,0)) to "Item A" by the following:
ui->tableView->model()->setData ( ui->tableView->model()->index(0,0), "Item A, Qt::EditRole);
the comboBox's value was set successfully, but the ComboBoxItemDelegate::setModelData function was not called, and this is my problem

QT connect a SIGNAL with fewer arguments than SLOT

I have this code:
QObject::connect(lineEdit_1, SIGNAL(textChanged(const QString &)), MainWindow, SLOT(myMethod(const QString &, QLineEdit* )) );
This code works correctly when myMethod has only the first argument (equal to the SIGNAL) but I need to pass a pointer lo lineEdit_1 in order to allow myMethod to know on which LineEdit it has to operate.
What I should to do?
Thanks a lot.
It is not necessary that you send as an additional argument the object that emits the signal for it, the QObjects have the sender() method that allows us to obtain that object:
QObject::connect(lineEdit_1, &QLineEdit::textChanged, MainWindow, &Your_Class::myMethod);
void Your_Class::MyMethod(const QString & text){
if(QLineEdit *le = qobject_cast<QLineEdit *>(sender())){
qDebug() << le;
}
}
If you need to pass other arguments you can use the lambda functions but always take the time to see the limitations (how to use it depends on the context):
QObject::connect(lineEdit_1, &QLineEdit::textChanged, [ /* & or = */](const QString & text){
MainWindow->MyMethod(text, another_arguments);
});

C++ Qt: Connect a TextEdit with a Label

In a Qt GUI I'm trying to connect a TextEdit with a label so that when the user types something, the label updates it's text. Here is what I've tried:
void MainWindow ::updatelabel()
{
ui->label->setText("Hello");
}
void MainWindow::changeTextColor()
{
QString textEdit = ui->textEdit->toPlainText();
QString label = ui->label->text();
connect(textEdit, SIGNAL(textChanged()), label, SLOT(updateLabel()));
}
This gives me an error though:
error: no matching function for call to 'MainWindow::connect(QString&, const char*, QString&, const char*)'
connect(textEdit, SIGNAL(textChanged()), label, SLOT(updateLabel()));
^
What am I doing wrong and how can I fix it? Thanks!
You have a few problems in your code. Here's changed code with comments explaining it:
// make sure updateLabel is declared under slots: tag in .h file
void MainWindow ::updatelabel()
{
// set label text to be the text in the text edit when this slot is called
ui->label->setText(ui->textEdit->toPlainText());
}
// this is a very suspicious method. Where do you call it from?
// I changed its name to better indicate what it does.
void MainWindow::initializeUpdatingLabel()
{
//QString textEdit = ui->textEdit->toPlainText(); // not used
//QString label = ui->label->text(); // not used
// when ever textChanged is emitted, call our updatelabel slot
connect(ui->textEdit, SIGNAL(textChanged()),
this, SLOT(updatelabel())); // updateLabel or updatelabel??!
}
A practical hint: when ever you use SIGNAL and SLOT macros, let Qt Creator to autocomplete them. If you type them by hand, and make a typo, you don't get a compile time error, instead there will be a runtime warning print about having no a matching signal/slot.
Or, assuming you are using Qt5 and C++11 capable compiler, you can use the new connect syntax, which will give you compiler error if you get it wrong. First add line CONFIG += C++11 to the .pro file, and then do the connect like this:
void MainWindow::initializeUpdatingLabel()
{
connect(ui->textEdit, &QTextEdit::textChanged,
this, &MainWindow::updatelabel);
}
Now if you for example actually have no updateLabel method, you get compile time error, which is much nicer than runtime message which you might not even notice. You could also replace the whole updatelabel method with a lambda, but that goes out of the scope of this question/answer.
You're connecting to the wrong textEdit and label variables in that method:
- connect(textEdit, SIGNAL(textChanged()), label, SLOT(updateLabel()));
+ connect(ui->textEdit, SIGNAL(textChanged()), this, SLOT(updateLabel()));
A QString is not a widget with signals and slots. You want the actual widget from ui, ui->textEdit, and this for the current class which contains updateLabel().
Edits: fix mistakes I made because I answered while tired.

How to get selection changed notification in QTreeView

I am trying to figure this out and it seems like I have to use QItemSelectionModel but I can't find an example how to wire things up.
I have defined in .h file.
QItemSelectionModel* selectionModel;
Now in constructor of the view, I set:
selectionModel = ui->treeView->selectionModel();
// the following line is not compiling!
connect(ui->treeView->selectionModel(), SIGNAL( ui->treeView->selectionModel(const QModelIndex&, const QModelIndex &) ),
this, this->selectionChanged ( QItemSelection & sel, QItemSelection & desel) );
I thought there would be predefined slot but I can't find one so I added this one (the syntax of which I found here)
void MyDialog::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
qDebug() << "Item selection changed";
}
I also tried replacing QItemSelection with QModelIndex but still doesn't work.
What do I need to do in order to simply get notified when selection has changed and than obviously grab the newly selected item?
the QObject::connect method should be used as follow :
QObject::connect(sender, SIGNAL(signal_method), receiver, SLOT(slot_method));
so in your case it should be something like
connect(selectionModel, SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)), this, SLOT(mySelectionChanged(const QItemSelection&,const QItemSelection&)));