PDA

View Full Version : Link two models in PyQt



kiran_g4e
25th February 2015, 06:24
I'm new to python programming.Learning on own, with google and you guys help.

Now working on a API project.need to query a list of tasks on UI and on selection of item It should query details of that task.

Its working that way.But I want to keep this task execution in background and show other naming on UI.

Here is detailed picture
10963


Screen shot of my UI



http://i.stack.imgur.com/t9o48.jpg

Thanks to Yasin for Dark Orange theme.

My idea is,
we query tasks,shots seperately and feed them in seperate models.
will show display_list.
If I click on Proj_Shot_Dept_002,its index value is 1.. so I want to send tasklist(index of 1) as signal parameter.
I'm googling got some possible ways like "widget dta mapper" or a delegate method..
But Im very new to Python n PyQt..so still couldn't get way to solve it.


In simple words, I want to show Display list model on UI but when User click,that signal should send tasklist item to execute next query. How can I access it?
or is there any other way to do it?

StrikeByte
25th February 2015, 09:54
What kind of model are you using, qstandarditemmodel or a custom made model?
If you are using a standarditem model you can use setData ( const QModelIndex & index, pointer to you're detail data class, Qt::UserRole )
when you click a item you can query data ( the index of the selected item, Qt::UserRole) this will return a QVariant with the pointer to the detail data class, then you can forward this pointer to the detail view.

to get the clicked item you can connect to the clicked ( const QModelIndex & index ) sinal of the listview

kiran_g4e
25th February 2015, 13:26
@StrikeByte,
Thankyou for reply :)

It's not qstandarditemmodel.
I'm verymuch new to programming,I could not understand userRole :(
can you explain me a bit?

I'm posting my code for better view.



base, form = uic.loadUiType("uiMainWindow.ui")
class ArtistUi(base, form):
def __init__(self, parent=None):
super(base, self).__init__(parent)
self.setupUi(self)

Task = MyTasks()
Task_num = Task.getTask() # List of tasks
Shot_num2 = Task.getShot() # list of shots


taskModel = QtGui.QStringListModel(Task_num)
shotModel = QtGui.QStringListModel(Shot_num2)

self.mytasks.setModel(taskModel)

self.show()

self.connect(self.mytasks, QtCore.SIGNAL("clicked(QModelIndex)"), self.Task_Detail)
# Task_Detail function will query using Task_num and displays in details listview

StrikeByte
26th February 2015, 07:58
For each data point in a model there are different roles, each role can contain data
Some of the roles are predefined like Qt:: DecorationRole, you can use it for decoration puposes, the Qt::UserRole is predefined for the users own data (like a pointer to the detail info)
So one item in the model can have Qt::EditRole, Qt:: DisplayRole and Qt::UserRole data.

I don't know if the code below is the way it should be used in python, I'm a c++ programmer and have little experience with python

In your case
setting data:
taskModel.setData(QModelIndex of the selected item or newly created item,QVariant.fromValue(TaskDetailData),Qt::UserRo le);

getting data:
taskModel.data(QModelIndex of the selected item),Qt::UserRole); //this returns a QVariant with a pointer to the data. Please check if it is a valid one!!!!

kiran_g4e
26th February 2015, 08:31
Thank you.I know that DisplayRole.
Now I got little clarity about userRoles.
Thanks for your time,but implementation doesn't work this way.
I need to figureout for pythonic way or I should change my model type.
I will update once I get i done :D

Santosh Reddy
3rd March 2015, 06:12
Try this way

1. The slot (or function) Task_Detail should take a parameter of type QModelIndex
2. Using this QModelIndex you can get the index of the shot that was clicked, first get the shot name using modelIndex.data().toString(), and the find the index of this string in the Shot_num2.

That should solve your problem. If it still does not help sit back run and understand the code below.

It is in C++, it should be trivial to port it to Py



#include <QtWidgets>

class ArtistUi : public QWidget
{
Q_OBJECT

public:
ArtistUi(QWidget * parent = 0)
: QWidget(parent)
{
taskList = QStringList() << "task001" << "task002" << "task007" << "task134" << "task591";
shotList = QStringList() << "Proj_Shot_dept_002" << "Proj_Shot_dept_004" << "Proj_Shot_dept_005";

taskModel = new QStringListModel(taskList);
shotModel = new QStringListModel(shotList);

mytasks = new QListView();
myshots = new QListView();

mytasks->setModel(taskModel);
myshots->setModel(shotModel);

mytasks->show();
myshots->show();

mytasks->setEditTriggers(QListView::NoEditTriggers);
myshots->setEditTriggers(QListView::NoEditTriggers);

output = new QLabel();

QGridLayout * layout = new QGridLayout(this);
layout->addWidget(mytasks, 0, 0, 1, 1);
layout->addWidget(myshots, 0, 1, 1, 1);
layout->addWidget(output, 1, 0, 1, 2, Qt::AlignHCenter);

currentTaskIndex = -1;

connect(mytasks, SIGNAL(clicked(QModelIndex)), this, SLOT(on_mytasks_clicked(QModelIndex)));
connect(myshots, SIGNAL(clicked(QModelIndex)), this, SLOT(on_myshots_clicked(QModelIndex)));
}

private slots:
void on_mytasks_clicked(const QModelIndex & index)
{
int i = taskList.indexOf(index.data().toString());

if(i != -1)
{
currentTaskIndex = i;
}
}

void on_myshots_clicked(const QModelIndex & index)
{
if(currentTaskIndex == -1)
{
output->setText("No Task Selected");
}
else
{
output->setText(index.data().toString() + " and " + taskList.at(currentTaskIndex));
}
}

private:
QStringList taskList;
QStringList shotList;

QStringListModel * taskModel;
QStringListModel * shotModel;

QListView * mytasks;
QListView * myshots;

QLabel * output;

int currentTaskIndex;
};

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

ArtistUi w;
w.show();

return app.exec();
}

#include "main.moc"

kiran_g4e
3rd March 2015, 06:34
Thankyou Verymuch .
I will work on this