PDA

View Full Version : Custom ListView. Using the model / view framework.



plopes21
27th April 2012, 12:08
Good morning people,

I have to do a custom listview. But I do not understand how to make the view / model of the QT framework.
I want to do something like this:
http://qt-apps.org/content/show.php/qTwitter?content=99087
The application has a custom listview. Have I downloaded the source code, but can not understand how he does. He liked to do as he did, a "item.ui" where he designed to put your item in the listview.

Regards, Pedro Lopes

folibis
27th April 2012, 13:37
You have to implement QAbstractListModel to provide data for your list and also inplement from QAbstractItemDelegate to provide custom view of items.
You can find lot of examples in Qt Assistant

plopes21
27th April 2012, 15:59
Thank you for your response, I will do something and if not put to understand something here.

thank folibis

plopes21
27th April 2012, 21:21
Good evening,
So far did this:
Files .h
mainwindow.h
tarefaDelegate.h
tarefa.h
tarefaModel.h
tarefaWidget.h

Files .cpp
main.cpp
mainwindow.cpp
tarefaDelegate.cpp
tarefaModel.cpp
tarefaWidget.cpp
tarefa.cpp

Forms
mainwindow.ui
tarefaWidget.ui (picture below)

7638

First want to make the Model. For now I have this


#ifndef TAREFAMODEL_H
#define TAREFAMODEL_H
#include <QAbstractListModel>
#include <tarefa.h>
#include <QList>
#include <QListView>

class TarefaModel : public QAbstractListModel
{
Q_OBJECT
public:
TarefaModel(QList<Tarefa> &tarefas, QObject *parent = 0)
: QAbstractListModel(parent), listatarefas(tarefas) {}


int rowCount(const QModelIndex &parent=QModelIndex() ) const;
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;

bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex());
bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex());

private:
QList<Tarefa> listatarefas;
};



#endif // TAREFAMODEL_H





#include "tarefamodel.h"
#include <QTime>
#include <tarefa.h>
#include <QList>



int TarefaModel::rowCount(const QModelIndex& parent) const
{
return this->listatarefas.count();
}


QVariant TarefaModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();

if (index.row() >= listatarefas.size())
return QVariant();

if (role == Qt::DisplayRole)
return listatarefas.at(index.row());
else
return QVariant();
}

bool TarefaModel::insertRows(int position, int rows, const QModelIndex &parent)
{
beginInsertRows(QModelIndex(), position, position+rows-1);

for (int row = 0; row < rows; ++row) {
Tarefa *tarefa1 = new Tarefa("primeira tarefa");
listatarefas.insert(position, *tarefa1);
}

endInsertRows();
return true;
}

bool TarefaModel::removeRows(int position, int rows, const QModelIndex &parent)
{
beginRemoveRows(QModelIndex(), position, position+rows-1);

for (int row = 0; row < rows; ++row) {
listatarefas.removeAt(position);
}

endRemoveRows();
return true;
}


Tarefa.h


#ifndef TAREFA_H
#define TAREFA_H

#include <QString>
using namespace std;

class Tarefa{
private:
QString name;
QString context;
QString project;

public:
//construtor
Tarefa(QString name);

void setName(QString name);
void setContext(QString context);
void setProject(QString project);


QString getName();
QString getContext();
QString getProjec();
};

#endif // TAREFA_H


Is anything wrong?

thanks for all!

folibis
27th April 2012, 23:31
if your list is read only so rowCount() and data() will be enough.

plopes21
28th April 2012, 14:10
I have the following ui's:

listview
7643

items
7644

I have to use the class QAbstractItemDelegate like you said. But I do not know how to use. This class does what?

I do not understand very well. Thanks

plopes21
30th April 2012, 05:44
Help me please...

plopes21
1st May 2012, 11:29
I really need this, please help me.

plopes21
1st May 2012, 17:27
Atão pah!!! Respondei-me a essa cena majé!! =)

folibis
2nd May 2012, 01:19
Ok, you had implemented QAbstractListModel so now you have common list which can display rows of text.
But you need different view of your items.
For than reason you need to inplement QAbstractItemDelegate and set it to your model.
You new class have to implement 2 methods:
- void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
- QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;
sizeHint returns bounds of item, specified by index and inside paint() you just paint your item as you want with painter.

very simple.
You can find an example in Qt help, Pixelator or something like that

P.S. I see now than you item have controls. but you cannot insert control directly in the list.
Anyway you can draw it with
void QStyle::drawControl ( ControlElement element, const QStyleOption * option, QPainter * painter, const QWidget * widget = 0 ) const

plopes21
2nd May 2012, 13:28
Hello my friend,

I now have this:
7665

and if you do this code mainwindow.cpp



TaskModel model(5);
QListView list;
list.setModel( &model );
list.show();


a list appears with the correct values​​.

but if you do this


TarefaModel model(5);
ui->listView->setModel(&model);


the program unexpectedly quits, why?

Le_B
2nd May 2012, 14:54
because your model is destroyed at the end of the function.
if you put ui->listView->setModel(new TarefaModel(5, this));
does it work ?

plopes21
2nd May 2012, 15:14
Your code worked.

I have another problem. When I click on the pushbutton 'Add Task' will want to add a task list that is declared in taskModel.
I have this code but does not work ...






void MainWindow::on_addTarefa_clicked()
{
Task t1(ui->lineNameTask->text());
// t1.setContext(ui->LineContext->text());
// t1.setProject(ui->lineProject->text());
TaskModel model(5);
model.addTask(t1);

// TaskModel::taskList.push_back(t1);
}




void TaskModel::addTask(const Task &task){
beginInsertRows(QModelIndex(), rowCount(),rowCount());
qDebug("hello");
// taskList<< task;
taskList.push_back(task);
endInsertRows();
}

Le_B
2nd May 2012, 15:22
same thing here.
you need to control the life of your objects:

if you write:
{
TarefaModel model(5);
//it lives
}
//it s dead

so in your exemple you create a whole new model add an item to it and the it is destroyed at the end of your function
1) why do you recreate a new model every time : create one model and control the content is way better.
2) if you need to create your models use new and pass this as the parent so it will be destroyed by the parent

plopes21
2nd May 2012, 17:02
I managed to add.
Now I am working with QAbstractItemDelegate.

I want to use this item that I did:
7667

I really have to use QAbstractItemDelegate?

How do I set up my item with QAbstractItemDelegate?

Thanks

Le_B
2nd May 2012, 17:13
i think it s the way but i don't know much about delegates (i switched to QML it is way easier for that)
but this exemple sould help you:
http://qt-project.org/doc/qt-4.8/itemviews-stardelegate.html

plopes21
2nd May 2012, 17:20
I'll try to solve this problem and will post here some questions that will arise.

Thanks Le_B

plopes21
4th May 2012, 17:28
How can I put a distance between the margin items?

I like this:

7685

plopes21
7th May 2012, 12:12
answer me please.

zhiyongwoo
8th May 2012, 09:43
Hi plopes21,

I think you need to add Vertical Layout to all those labels in tarefaWidget.ui.

I am working something quite close to what you are doing and would you mind to upload your project files to have a look on how you put everything into one piece?
Thanks