PDA

View Full Version : 3 Questions on QListView



jiveaxe
1st August 2007, 09:55
Hi everybody,
i was learning qlistview and writing simple application for testing. First of all the sample code:


#include <QApplication>
#include <QVBoxLayout>
#include <QListView>
#include <QLabel>
#include <QStringListModel>
#include <QStringList>

class MyWidget: public QWidget
{
Q_OBJECT

public:
MyWidget(QWidget *parent=0);

private slots:
void currentSelected(const QModelIndex &);

private:
QListView *listView;
QLabel *selectedItemText;
QStringListModel *model;
};

MyWidget::MyWidget(QWidget *parent)
:QWidget(parent)
{
listView = new QListView;
selectedItemText = new QLabel;

model = new QStringListModel();
QStringList list;
list << "lemons" << "melons" << "oranges" << "pears"
<< "grapes" << "apples" << "potatoes";
model->setStringList(list);

listView->setModel(model);

QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(listView);
layout->addWidget(selectedItemText);
setLayout(layout);

connect(listView, SIGNAL(clicked(const QModelIndex&)),
this, SLOT(currentSelected(const QModelIndex &)));
}

void MyWidget::currentSelected(const QModelIndex &current)
{
selectedItemText->setText(current.data().toString());
}

int main(int argc, char *argv[])
{
QApplication app( argc, argv );

QWidget *window = new QWidget;
window->setWindowTitle("Sample ListView");

MyWidget *myWidget = new MyWidget;

QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(myWidget);
window->setLayout(mainLayout);
window->show();

return app.exec();
}

#include "main.moc"

My questions are:

1) How start the application with some item already selected?
With the code above when an item is selected the QLabel is filled with the item data; but when the application starts no item is selected and the label is empty.

2) How bind the function currentSelected(const QModelIndex &) with up/down arrows keys?
In the application if I move the selection with the up/arrow keys the highlighted item changes but the label is not updated with the text of the highlighted item. I want the behavior of mouse single click with up/arrow keys.

3) How change the double-click event?
Now when an item is double-clicked the item goes in edit mode; i don't want this. Double-click like single-click is sufficient for me.

Hoping i was clear, thanks in advance for helping me.
Giuseppe

marcel
1st August 2007, 10:06
1. Use setCurrentIndex(model()->index(0));

2.

connect(listView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(currentSelected(const QModelIndex &)));
}

The last parameter in the signal will be ignored by the slot.

3. listView->setEditTriggers(QAbstractItemView::NoEditTriggers) ;

Regards

jiveaxe
1st August 2007, 12:00
Thanks marcel for your help; I noticed that code 2) solves question 1) too.

Can I post you a new Question? How word wrap text in a listview? I have used


listView->setWordWrap(true);

but nothing happens; what's wrong? missing something else? :confused:

Thanks a lot,
Giuseppe

marcel
1st August 2007, 12:11
What do you expect it to do?


wordWrap : bool This property holds the item text word-wrapping policy.
If this property is true then item text text is wrapped where necessary at word-breaks; otherwise it is not wrapped at all. This property is false by default.



So, if you have a really long word, then it won't be wrapped. If you have multiple words, then they will be wrapped as necessary.

A possible solution is( that is guaranteed to work), is to create your own item delegate ( a delegate dictates the look and feel of an item ).

When you paint the delegate, then you can take care of the wrapping too.

Regards

jiveaxe
1st August 2007, 12:22
Ok, marcel; now open the manual and search for delegate to learn using it.

Again thanks

marcel
1st August 2007, 12:25
:) OK.
A hint: I think you can use QStyleOptionViewItem::rect. This is the dimension of the item. You can do the wrapping relative to its size. A QStyleOptionViewItem object is passed to the delegate's paint method.

Regards

jiveaxe
1st August 2007, 14:01
I have to return on marcel' replay to my first post; i have noticed that using, as in answer to question 1, this code:


currentSelected(model->index(2));

(with 2 instead of 0 (zero)) the item selected is the first (with index = 0). If, instead, putting a comment in front of the marcel's code in answer 2 the correct item is displayed in the label.

Where is the problem?

Bye

marcel
1st August 2007, 14:05
Could you post your code?
Only the relevant sections.

Regards

jiveaxe
1st August 2007, 14:09
Take as sample the code in my first post; i have inserted after the connect statement in constructor


connect(listView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(currentSelected(const QModelIndex &)));

currentSelected(model->index(2));

marcel
1st August 2007, 14:17
Do you change the selection programatically after this code?

Regards

jiveaxe
1st August 2007, 14:20
No, i hope.
Here the complete code:


#include <QApplication>
#include <QVBoxLayout>
#include <QListView>
#include <QLabel>
#include <QStringListModel>
#include <QStringList>

class MyWidget: public QWidget
{
Q_OBJECT

public:
MyWidget(QWidget *parent=0);

private slots:
void currentSelected(const QModelIndex &);

private:
QListView *listView;
QLabel *selectedItemText;
QStringListModel *model;
};

MyWidget::MyWidget(QWidget *parent)
:QWidget(parent)
{
listView = new QListView;
listView->setWordWrap(true);
listView->setEditTriggers(QAbstractItemView::NoEditTriggers );
selectedItemText = new QLabel;

model = new QStringListModel();
QStringList list;
list << "lemons" << "melons" << "oranges" << "pears"
<< "grapes" << "apples" << "potatoes";
model->setStringList(list);

listView->setModel(model);

QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(listView);
layout->addWidget(selectedItemText);
setLayout(layout);

connect(listView, SIGNAL(clicked(const QModelIndex&)),
this, SLOT(currentSelected(const QModelIndex &)));
connect(listView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(currentSelected(const QModelIndex &)));

currentSelected(model->index(2));
}

void MyWidget::currentSelected(const QModelIndex &current)
{
selectedItemText->setText(current.data().toString());
}

int main(int argc, char *argv[])
{
QApplication app( argc, argv );

QWidget *window = new QWidget;
window->setWindowTitle("Sample ListView");

MyWidget *myWidget = new MyWidget;

QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(myWidget);
window->setLayout(mainLayout);
window->show();

return app.exec();
}

#include "main.moc"



Regards,
Giuseppe

marcel
1st August 2007, 14:34
The code looks OK.
I don't think there is any need to connect the clicked signal anymore. The selection model should take care of selection changes.

Also, try to interrogate directly the model for the data, not the model index.


void MyWidget::currentSelected(const QModelIndex &current)
{
selectedItemText->setText( listView->model()->data(current, Qt::DisplayRole ) );
}


Regards

jiveaxe
1st August 2007, 14:42
Unfortunately the code doesn't work; the item shown is always the first.

Thanks for your time

marcel
1st August 2007, 14:51
Disregards my last post.
I debugged your example a bit, and the solution is:


currentSelected(model->index(2));
listView->selectionModel()->setCurrentIndex(model->index(2), QItemSelectionModel::SelectCurrent);


So you also have to let the selection model what you want to do.

Regards

jiveaxe
1st August 2007, 15:03
Magic Marcel, you're right; the application works great now.

Thanks a lot