PDA

View Full Version : Displaying large amount of widgets in different styles



themagician
2nd January 2012, 03:04
I'm working on "yet another" media manager for movies. So I have a list of movie data in some data structure, including cover images. The user has the option to display these movie items (widgets) in different modes, e.g. "cover only", "cover + title" or "cover + title + year" and so forth. So the first problem is what kind of pattern would I use for easily adding new display modes? Would it be something like this (not tested or anything, just to give an idea of what I've thought):


typedef QMap<QString, QString> MovieData;

QWidget *coverAndTitle(const MovieData &data)
{
QWidget *w = new QWidget;
// Build the widget out of data so that it contains title and cover image
return w;
}

QWidget *coverOnly(const MovieData &data)
{
QWidget *w = new QWidget;
// Build the widget out of data so that it contains only cover
return w;
}

QList<MovieData> movieDataList;
enum { DisplayMode_Cover, DisplayMode_CoverAndTitle };

// ...

for(int i = 0; i < movieDataList.size(); ++i)
{
MovieData md = movieDataList.at(i);

QWidget *w = nullptr;
if(displayMode == DisplayMode_CoverAndTitle)
{
w = coverAndTitle(md);
}
else if(displayMode == DisplayMode_Cover)
{
w = coverOnly(md);
}

// proceed to add this widget to some container where it's displayed
}
}


So that's a pretty simplistic solution (if it even works). Would appreciate some feedback on this solution and on better solutions.

Then another problem is if my widgets e.g. take 100x150 pixels of space + 15px margin. So that would probably only display cover image for every movie. I'd want them to behave like this (http://jsfiddle.net/K8TeG/1/) in the container. Drag the vertical bar sideways and you'll see how the yellow boxes behave as the space changes. How would I go about implementing it this way when the user resizes the window the widgets would behave similarly?

Thanks!

themagician
3rd January 2012, 02:21
I solved the second problem with FlowLayout from Qt site: http://developer.qt.nokia.com/doc/qt-4.8/layouts-flowlayout.html

But how can I get the widget called root to expand in this code below?


QScrollArea *content = new QScrollArea(this);

FlowLayout *flowLayout = new FlowLayout;

for(int i = 0; i < 20; ++i)
{
QWidget *w = new QWidget;
w->setFixedSize(100, 150);
w->setStyleSheet("margin: 15px; background-color: #000000");

flowLayout->addWidget(w);
}

QWidget *root = new QWidget;
root->setStyleSheet("background-color: #ffff66");
root->setLayout(flowLayout);

content->setStyleSheet("background-color: #ff6600");
content->setWidget(root);

setCentralWidget(content);

QScrollArea *content is orange
QWidget *root is yellow

http://i.imgur.com/uUEbu.png

If I remove the root QWidget and set flowLayout as a direct child of the content QScrollArea, then it works fine, but there's no scrollbar even if I force it.

EDIT: I re-implemented QMainWindow's resizeEvent() and the QWidget *root is resized every time that event takes place. Not sure if that's a good solution?

EDIT2: Well that didn't work too well. I should somehow connect the widget's size to the flowLayout probably.

EDIT3: This solution works:


void MainWindow::resizeEvent(QResizeEvent *ev)
{
int cWidth = content->viewport()->width();
int lNeededHeight = flowLayout->minimumHeightForWidth(cWidth);

root->setFixedWidth(cWidth);
root->setFixedHeight(lNeededHeight);
}

Any feedback on this approach? Now at leas thet root QWidget resizes itself properly:

http://i.imgur.com/LhvQ5.png

themagician
3rd January 2012, 15:00
That was not a good solution! All I had to do was call QScrollArea::setWidgetResizeable(true); to make the root QWidget fill the QScrollArea.

Still have to tackle with the first problem: How to make, e.g. in the above screenshots, the black boxes change their appearance when the user e.g. selects from the menu View -> Blue Boxes, Double-size and it would change the appearance of the black boxes to "blue and double the size".

Should I:

1) Keep the movie data (see OP) in a simple data structure and construct new QWidgets every time the user requests their appearance to change via some factory pattern that returns whatever template (as in layout) generator function/object that takes the movie data as an argument and spits the desired QWidgets.
or 2) Sub-class QWidgets that have methods for changing their own appearance, perhaps combined with the above pattern suggestion, that are called when the user wants to use another layout for the movie items
or 3) Something else?

Thanks again.