PDA

View Full Version : How to remember and reestablish the last currentIndex position of each ListElement?



JaySDC
7th September 2015, 09:36
Hi,

I'm Jay and even though I was always around computers, I am completely new to QT with some knowledge and background in coding but rather small to be honest.

Background stuff:
I have an arcade cab running with a PC backbone.
I have a very specific need for a FrontEnd that will allow me to browse/access easily the different categories and different titles (i.e games) in each category.
I used a QT caroussel to achieve that. A friend is helping me out.



Here is my problem:
I have a ListModel that contains 2 ListElements
Each ListElement is populated with all the "*.png" of a folder (two different folders, one contains 5 png files, the other 42 png files)

Pressing Up or Down switches from one ListElement to the other (they're called TARGET and VERSUS)
Pressing LEFT or RIGHT switches, while positioned on a specific ListElement, from one item to the next (TARGET contains 5 items, VERSUS contains 42)

With the code below, when I press LEFT or RIGHT, it affects the position of BOTH ListElements, regardless of that ListElement being visible or not.
Even though only one ListElement is visible/active, the other IS affected and when I switch back to it, the position/currentIndex (i.e the PNG highlighted) CHANGED compared to the last time we browsed THIS ListElement.

I guess it's the basic behavior of QT.



I want my code to do the following:
For each ListElement (TARGET and VERSUS), always remember the position we're at in order to:
Restore/Refresh that specific position when we cycle BACK to this SPECIFIC ListElement

Demo:
we're at position 3 on TARGET.
we switch to VERSUS.
we go crazy with LEFTs and RIGHTs.
we go back to TARGET
TARGET automatically switches back to last known position : 3




Here is what I tried with global variables initially set at 0 (one for each ListElement):




Item {

// verylow res, using native arcade system capabilities
width: 640
height: 240


//We start at position 0 of each ListElement, i.e Category
property int targetSubTypePosition: 0
property int versusSubTypePosition: 0

property int indexSubTypePath: 0

color: "black"

//Populates the 2 ListElements, each with the content of a folder. We only scan for .png
ListModel {
id: subTypeModel
ListElement { name: "YOKO_TG_"; path: "file:///D:/ArcadeLauncher 25.04.2015/DEV_ARCADE/YOKO_TG_/" ; position: 0}
ListElement { name: "YOKO_VS_"; path: "file:///D:/ArcadeLauncher 25.04.2015/DEV_ARCADE/YOKO_VS_/" ; position: 0}
}

PathView {
id: gameListView
pathItemCount: 14
anchors.fill: parent
focus: true

//Go to next PNG
Keys.onLeftPressed: incrementCurrentIndex()

//Go to previous PNG
Keys.onRightPressed: decrementCurrentIndex()

//Switch to next category. They cycle around. The first "if" makes sure it cycles
Keys.onUpPressed: {
if (indexSubTypePath == subTypeModel.count -1) {
indexSubTypePath = 0;
} else {
indexSubTypePath++;
}

//This is where I "try" to save the last known position of the category that we leave, then I "try" to restore the last known position of the category that we reach
if (indexSubTypePath == 0) {
targetSubTypePosition = currentIndex;
currentIndex = versusSubTypePosition;
} else {
versusSubTypePosition = currentIndex;
currentIndex = targetSubTypePosition;
}

}

//Switch to next category. They cycle around. The first "if" makes sure it cycles
Keys.onDownPressed: {
if (indexSubTypePath == 0) {
indexSubTypePath = subTypeModel.count -1;

} else {
indexSubTypePath--;
}

//This is where I "try" to save the last known position of the category that we leave, then I "try" to restore the last known position of the category that we reach
if (indexSubTypePath == 0) {
targetSubTypePosition = currentIndex;
currentIndex = versusSubTypePosition;
} else {
versusSubTypePosition = currentIndex;
currentIndex = targetSubTypePosition;
}
}

Keys.onSpacePressed: {
positionViewAtIndex(currentIndex, ListView.SnapPosition);
}

model : gameListModel
FolderListModel {
id: gameListModel
nameFilters: ["*.png"]
folder: subTypeModel.get(indexSubTypePath).path//"file:///D:/ArcadeLauncher 25.04.2015/DEV_ARCADE/YOKO_TG_/"
}




This is my full code (the whole project):
https://www.dropbox.com/sh/rv7nz858cfep4wt/AAAdxs4Izp4jVDCb8M8KN8yOa?dl=0

Yours,
--Jay

anda_skoa
7th September 2015, 10:38
Hmm.

As a quick option I would try to have two path views, each one operating on its own data.
The up/down arrows would then simply switch which one of the two is visible.

Cheers,
_

JaySDC
7th September 2015, 11:16
Thanks for the help and good idea.

How do I change this code:



Keys.onUpPressed: {
if (indexSubTypePath == subTypeModel.count -1) {
indexSubTypePath = 0;
} else {
indexSubTypePath++;
}


to switch Path instead?

Yours,
--Jay

Added after 6 minutes:

Wait, that means I also have to duplicate the model, the path, and the delegate?!

Right now I am trying with 2 categories only but in the end I will have about 10 of them, that means almost 10 times the same code...
I am not concerned by having my code all nice and clean but that seems like an extreme quickfix : ).

Any other solution that would involve just one code and a dynamic variable handling?

Yours,
--Jay

anda_skoa
7th September 2015, 12:38
How do I change this code:



Keys.onUpPressed: {
if (indexSubTypePath == subTypeModel.count -1) {
indexSubTypePath = 0;
} else {
indexSubTypePath++;
}


to switch Path instead?

You would switch the current path view's visible property to false and the other path view's visible property to true.

Or you have am "current index" property on the encapsulating item and let the two views bind their visible property to that and compare with their index value.



Wait, that means I also have to duplicate the model, the path, and the delegate?!

No.
Your PathView basically has one input, a directory.
You can easily move the PathView code to a file, e.g. GameListView.qml, add a propery for the directory and use that element twice.



Right now I am trying with 2 categories only but in the end I will have about 10 of them, that means almost 10 times the same code...
I am not concerned by having my code all nice and clean but that seems like an extreme quickfix : ).

Well, it is a quick fix for the situation you had described :)
And it does not require code duplication, just creating a custom component.



Any other solution that would involve just one code and a dynamic variable handling?

Your initial attempt most likely failed because you are "resetting" the current index too soon, i.e. right after the switch but before the model had any chance of loading the new content.
For that you would have to delay resetting the index until the model has completed loading (or at least loaded up to the desired index), or keep the models loaded and switch model as well as current index.

Hence the idea of just keeping the whole view around and see how that goes.

Cheers,
_

JaySDC
7th September 2015, 13:38
Well thank you very much with all that!

I'll see what I can do with my friend.

Even tough I understand what you say and the philosophy behind it, my coding knowledge is too limited to create the code. My skill can only try and customize an existing code based on examples.

: )

--Jay

anda_skoa
7th September 2015, 14:44
Even tough I understand what you say and the philosophy behind it, my coding knowledge is too limited to create the code. My skill can only try and customize an existing code based on examples.


Right, that's one of the reasons I suggested the simpler approach.

Creating a custom component in QML is very easy.
Basically you just copy part of the code you have to a new QML file for which you use a filename that matches the name of how you want to call your component in the QML file using it.

E.g. your code conceptually looks like this



import QtQuick 2.4

Item {
ListModel {
}

PathView {
....
}
}

You then copy all code of that PathView section to a new file along side the original file, e.g. GameListView.qml


import QtQuick 2.4

PathView {
....
}

The original file can then be changed to


import QtQuick 2.4

Item {
ListModel {
}

GameListView {
}
}

That does not work at this point because you have been referencing the list model inside the PathView.
But in fact you only needed the directory. so you add a property for that in GameListView.qml


PathView {
property string directory

....

FolderListModel {
id: gameListModel
nameFilters: ["*.png"]
folder: parent.directory
}
}

You can then use multiple GameListView instances


Item {
property int currentSubType: 0

GameListView {
visible: parent.currentSubType === 0
directory: subTypeModel.get(0).path;
}
GameListView {
visible: parent.currentSubType === 1
directory: subTypeModel.get(1).path;
}
}


Cheers,
_

JaySDC
8th September 2015, 00:34
Thank you very much once again : ) Cheers for the time you spent on helping me out, you earned a lot of Karma points I'm sure ; )

I'll give all this a go tomorrow morning with fresh eyes!!

JaySDC
8th September 2015, 08:45
Hmm it is not working yet.

Where shall I put all the code concerning the actual Path ?



path: Path {
id:myPath

// CURRENT WORKING
// Path

// Premiere position (LENTILLE)
startX: 95; startY: 160

// Differents points de passage QUAD
PathQuad { x: 43; y: 53 ; controlX: 18; controlY: 78}
PathAttribute { name: "angle"; value: itemAngle }

PathQuad { x: 180; y: 22 ; controlX: 108; controlY: 26}
PathAttribute { name: "angle"; value: itemAngle*2 }

PathQuad { x: 320; y: 19 ; controlX: 250; controlY: 21}
PathAttribute { name: "angle"; value: itemAngle*3 }

PathQuad { x: 460; y: 22 ; controlX: 390; controlY: 21}
PathAttribute { name: "angle"; value: itemAngle*4 }

PathQuad { x: 597; y: 53 ; controlX: 528; controlY: 37}
PathAttribute { name: "angle"; value: itemAngle*5 }

PathQuad { x: 545; y: 159 ; controlX: 571; controlY: 106}
PathAttribute { name: "angle"; value: itemAngle*6 }


}


Added after 16 minutes:

Haha nevermind I'm lost.

I'll have my friend have a look to help me out.

Cheers though,
--Jay

anda_skoa
8th September 2015, 09:11
I am not sure I understand the question.
"path" is a propery of the PathView, so that code needs to be inside the Path element unless you want each instance to use a different path.

Cheers,
_

JaySDC
8th September 2015, 09:34
Yes nevermind that last one, my understanding is too limited for me to ask pertinent questions : P.

I'll check with my friend about the whole thing you proposed and then I might come and ask more precisions.

Thanks,
--Jay