Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Unsolved Grid layout reordering after modifications

    General and Desktop
    gridlayout widgets
    2
    15
    4557
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • kshegunov
      kshegunov Moderators last edited by kshegunov

      Hello,
      For my button dial widget I have put a grid layout to hold my buttons. Since they are created based on the actions attached to the widget I've also intercepted the ChildAdded/ChildRemoved events of the action objects and I'm creating/destroying buttons based on that. For more information on what exactly I'm doing you could look here.

      Currently, when a child is removed I destroy the corresponding button, but that button might be laid out in a place that's nether the beginning nor the ending of the grid. To have consistency (no holes in my layout) I'm removing all the buttons following the one I'm deleting and then reinserting them at their new positions, like this:

      
      void AgDialPrivate::destroyButton(QObject * action)
      {
      	ButtonHash::Iterator i = buttons.find(action);
      	if (i == buttons.end())
      		return;
      
      	// Remove the button
      	QAction * parentAction = qobject_cast<QAction *>(action->parent());
      	if (parentAction && parentAction->findChildren<QAction *>(QString(), Qt::FindDirectChildrenOnly).count() <= 1)  {
      		destroyPage(parentAction);	// If there's a parent page and there's no more children, remove it!
      		return;
      	}
      
      	QToolButton * button = qobject_cast<QToolButton *>(i.value());
      	QGridLayout * layout = qobject_cast<QGridLayout *>(button->parentWidget()->layout());
      
      	qint32 index = layout->indexOf(button);
      	if (index < 0)
      		return;
      
      	// Take out the remaining items from the layout
      	QVector<QLayoutItem *> items;
      	for (qint32 count = layout->count() - 1; count > index; count--)
      		items.append(layout->takeAt(count));
      
      	// Remove the current button
      	delete button;
      	buttons.erase(i);
      
      	// Reinsert the items in the layout
      	for (qint32 i = items.size() - 1; i >= 0; i--)  {
      		QPoint position = newItemLayoutPosition(layout);
      		layout->addItem(items[i], position.y(), position.x());
      	}
      }
      

      Is there a smarter way to do this? Can I somehow instruct the layout to reorder the items without doing that manually?
      As a side question, can I pre-determine the number of rows and columns for a QGridLayout, I was not able to see anything like this in the documentation, but I might have missed something?

      Kind regards.

      Read and abide by the Qt Code of Conduct

      1 Reply Last reply Reply Quote 0
      • mrjj
        mrjj Lifetime Qt Champion last edited by

        Hi
        I was wondering.
        If I make a layout in designer, say a grid layout and put buttons 1,2,3,4,5 in it,
        then I delete 3. the others are rearranged so no holes.

        So I wonder what will happen if you call activate() on layout after u removed the
        button(s).

        kshegunov 1 Reply Last reply Reply Quote 0
        • kshegunov
          kshegunov Moderators @mrjj last edited by kshegunov

          @mrjj
          Hm, indeed, no need to call activate even. If I comment out the taking-out-and-reinserting code the layout is rearranged automatically after the delete button. This is however a bit strange for me, because how is the layout supposed to know the number of columns/rows I'm expecting?

          Nope, this seems to "work" only if I have a single row in the layout, otherwise I get a hole at the place the button was supposed to be.

          Read and abide by the Qt Code of Conduct

          1 Reply Last reply Reply Quote 0
          • mrjj
            mrjj Lifetime Qt Champion last edited by mrjj

            Im not sure its expecting anything. just seems to start with
            first Layoutitem and then then just position one by one.

            The number of rows seems to the height / items.
            if I set minimum height to such degree they can not longer fit with
            in layout_height, they start to overlap.

            Ahh. the hole is a "column"

            kshegunov 1 Reply Last reply Reply Quote 0
            • kshegunov
              kshegunov Moderators @mrjj last edited by

              @mrjj
              Well not a whole column, but a single item in the grid. I could add more buttons to the layout for testing purposes, but since a picture is worth a thousand words, I think the link explains what's my issue quite well.

              Read and abide by the Qt Code of Conduct

              mrjj 1 Reply Last reply Reply Quote 0
              • mrjj
                mrjj Lifetime Qt Champion @kshegunov last edited by

                @kshegunov
                Yes pictures made it very clear.
                Try to reproduce it in Creator. Its seems to
                rearrange.

                kshegunov 1 Reply Last reply Reply Quote 0
                • kshegunov
                  kshegunov Moderators @mrjj last edited by

                  @mrjj
                  Do you mean to make the form in the designer? Unfortunately, in this case this is not an option, see the linked thread for details as to why.

                  Read and abide by the Qt Code of Conduct

                  mrjj 1 Reply Last reply Reply Quote 0
                  • mrjj
                    mrjj Lifetime Qt Champion @kshegunov last edited by

                    @kshegunov
                    I know u cant use UI file.
                    Im just wondering why in creator,
                    if I create a grid 3x2 with buttons.
                    Then from code, i take() and delete say button 3, i
                    get no holes. But in AgDial there is.
                    I should get the same, shouldn't I?

                    kshegunov 1 Reply Last reply Reply Quote 0
                    • kshegunov
                      kshegunov Moderators @mrjj last edited by kshegunov

                      @mrjj
                      I suppose so. But I'm not takeing the item itself, maybe this is why the behavior differs. I'll try it out.
                      Nope, substituting the relevant reinsertion code with:

                      	delete layout->takeAt(index);
                      	delete button;
                      	buttons.erase(i);
                      

                      Produces the same hole. I have no idea why this works in your case ...

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply Reply Quote 0
                      • mrjj
                        mrjj Lifetime Qt Champion last edited by

                        Just to be sure, we are talking
                        about a normal gridlayout in a widget?
                        At runtime, there should be no difference between one from
                        UI files and one from code.
                        So your case must be different or mine too simple.

                        kshegunov 1 Reply Last reply Reply Quote 0
                        • kshegunov
                          kshegunov Moderators @mrjj last edited by

                          @mrjj

                          Just to be sure, we are talking
                          about a normal gridlayout in a widget?

                          Absolutely! Here's how a create a page:

                          bool AgDialPrivate::createPage(QAction * action)
                          {
                          	Q_ASSERT(action);
                          	QList<QAction *> children = action->findChildren<QAction *>(QString(), Qt::FindDirectChildrenOnly);
                          	if (children.count() <= 0 || pages.value(action, NULL))
                          		return false;
                          
                          	// Create a page for this action
                          	AGUI_Q(AgDial);
                          
                          	QWidget * page = new QWidget(q);
                          	new QGridLayout(page);
                          
                          	pages.insert(action, page);
                          	q->addWidget(page);
                          
                          	// Create a return button
                          	QAction * parent = qobject_cast<QAction *>(action->parent());
                          	createReturnButton(page, parent);
                          
                          	// If the action has any children, create their buttons and/or pages
                          	foreach (QAction * child, children)  {
                          		createButton(child);
                          		if (child->children().count() > 0)
                          			createPage(child);
                          	}
                          
                          	// Map the triggered signal of the child action
                          	QSignalMapper * mapper = new QSignalMapper(page);
                          	mapper->setMapping(action, page);
                          	QObject::connect(action, SIGNAL(triggered()), mapper, SLOT(map()));
                          	QObject::connect(mapper, SIGNAL(mapped(QWidget *)), q, SLOT(setCurrentWidget(QWidget *)));
                          
                          	return true;
                          }
                          

                          Read and abide by the Qt Code of Conduct

                          1 Reply Last reply Reply Quote 0
                          • mrjj
                            mrjj Lifetime Qt Champion last edited by

                            Ok, i delete sample and tried again.
                            Now I get hole too! ?
                            only difference is that I had min/max heights in other test.

                            kshegunov 1 Reply Last reply Reply Quote 0
                            • mrjj
                              mrjj Lifetime Qt Champion last edited by

                              Ok. now even in Creator it leaves holes.
                              my first sample must not been proper.

                              1 Reply Last reply Reply Quote 0
                              • kshegunov
                                kshegunov Moderators @mrjj last edited by

                                @mrjj said:

                                only difference is that I had min/max heights in other test.

                                Maybe the layout's redistribution of item space had hidden the effect in the previous test? I couldn't think of another reason.

                                Read and abide by the Qt Code of Conduct

                                mrjj 1 Reply Last reply Reply Quote 0
                                • mrjj
                                  mrjj Lifetime Qt Champion @kshegunov last edited by mrjj

                                  @kshegunov
                                  I agree . must been something like that as now the effect
                                  is 100% as your experience. Even in designer.
                                  Sorry for the confusion.

                                  1 Reply Last reply Reply Quote 1
                                  • First post
                                    Last post