Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QWidget::windowRole() use as storage for small textual data



  • Hi,

    In my application I need to distinguish two types of windows:
    a) those who displays some data (graphs)
    b) other windows
    To do this I thinking about to set QWidget::setWindowRole() like:

    window1->setWindowRole("display data");
    window2->setWindowRole("not display data"):
    

    In documentation it is said that it only makes sense with X11 window system (I haven't ever used it). Is it because this windowRole() text appears somewhere on the window so the user can see this textual data?
    Is there a nicer way to distinguish these two types of windows in my case?


  • Lifetime Qt Champion

    Hi,

    You can use a dynamic property.


  • Lifetime Qt Champion

    Hi,

    You can use a dynamic property.



  • @SGaist thank you! I think this is what I was looking for :)



  • @SGaist I'm trying to use bool QObject::setProperty(const char *name, const QVariant &value)
    In my MainWindow I call MyClass where I create some objects and set for each of them property:

    MyClass::BlaBla(){
        ads::CDockWidget* dockWidget = new ads::CDockWidget("2D Window");
        dockWidget->setWidget(qvtkOpenGLStereoWidget);
        dockWidget->setProperty("IsVisualization", true);
        dockManager->addDockWidget(ads::RightDockWidgetArea, dockWidget);
    }
    

    If I write QVariant variant = dockWidget->property("IsVisualization"); then the variant contains correct data everything if ok at this step.
    But if I do the same in the MainWindow inside onFocusChanged method I get invalid QVariant:

    void MainWindow::onFocusChanged(QWidget* old, QWidget* now){
        if (old != nullptr){
            QVariant variantOLD = old->property("IsVisualization");
        }
        if (now != nullptr){
            QVariant variantNOW = now->property("IsVisualization");
        }
    }
    

    What is wrong?

    P.S. dockManager and dockWidget are from advanced_docking_system library



  • @Please_Help_me_D
    Since being inside onFocusChanged() makes no difference to whether you can read a property or not, I can only conclude that neither old nor now are the dockWidget on which you previously set the property, or you have reset it since then.

    Did you even try object_cast<>ing old/now to verify they are ads::CDockWidget*?



  • @JonB after you wrote I tried it... Yes you are right, they are not a ads::CDockWidget*
    I guess I should be able to get ads::CDockWidget* from old/now via old->children?



  • @Please_Help_me_D
    I was doing this just today. The focus can be hitting some sub widget on a container. In my case widgets on a QMdiSubWindow. To find that I go up via parentWidget() till I find one or hit the topmost. If you are same thing you will want to go up parents from old/now, not chidren?



  • @JonB nice to hear that
    As I understood I should go up from old/now until I meet ads::CDockWidget* dockWidget != nullptr condition, correct? Like:

    {
    ads::CDockWidget* dockWidget = qobject_cast<ads::CDockWidget*>(old->parent());
    if (CDockWidget != nullptr){}
    }
    

    but in some while or for loop...



  • @Please_Help_me_D

    ads::CDockWidget* dockWidget = nullptr;
    while (old != nullptr && (dockWidget = qobject_cast<ads::CDockWidget*>(old)) == nullptr)
        old = old->parentWidget();
    qDebug() << dockWidget;
    


  • @JonB thank you
    But the loop ended and dockWidget is always nullptr. It takes about 7 cycles and there is no ads::CDockWidget*



  • @Please_Help_me_D
    So in that case the old or now (you have written this loop on both, haven't you?!) in the focus change is not a descendent of your ads::CDockWidget* dockWidget. I never said it was, you did! Or you check children if whatever it is works that way.



  • @JonB yes I have written both old and now
    Yes I'm trying to find this widget via old->children();. I need few minuts



  • @JonB this code can't find ads::CDockWidget* neither:

    void MainWindow::onFocusChanged(QWidget* old, QWidget* now){
        if (old != nullptr){
            ads::CDockWidget* dockWidget = nullptr;
            QObjectList objList = old->children();
            int i = 0;
            while (i < objList.count() && dockWidget == nullptr){
                dockWidget = qobject_cast<ads::CDockWidget*>(objList.at(i));
                i++;
            }
        }
    
        if (now != nullptr){
            ads::CDockWidget* dockWidget = nullptr;
            QObjectList objList = now->children();
            int i = 0;
            while (i < objList.count() && dockWidget == nullptr){
                dockWidget = qobject_cast<ads::CDockWidget*>(objList.at(i));
                i++;
            }
        }
    }
    


  • @Please_Help_me_D
    So read up on what a ads::CDockWidget is/how it works. Your assumption in that QWidget::focusChanged(old, now) must lead to widgets either ancestors or descendants of this dock widget. I have no idea whether that is the case. Also your code may need to recurse down through children, no? At least start by finding out what old & now actually are in your focus change.



  • @JonB yes possibly I should have done the recursion down to the other children but it alredy becomes too complicated solution for such kind of a task.
    Now I'm trying to set property not on CDockWidget but to some parent. I'm trying...


  • Lifetime Qt Champion

    Hi
    It wont be the DockWidget that has the focus. it will be its widget/children.

    I would call dumpObjectTree()
    on old and now to see how they are made up.



  • @mrjj thank you for advice. Here is the output:

    setFocus(Qt::OtherFocusReason);
    setFocus(Qt::OtherFocusReason);
    ads::CDockWidget::2D Window 
        QBoxLayout:: 
        QAction:: 
        QScrollArea::dockWidgetScrollArea 
            QWidget::qt_scrollarea_viewport 
                QVTKOpenGLStereoWidget:: 
                    QVBoxLayout:: 
                    QWindowContainer:: 
            QWidget::qt_scrollarea_hcontainer 
                QScrollBar:: 
                QBoxLayout:: 
            QWidget::qt_scrollarea_vcontainer 
                QScrollBar:: 
                QBoxLayout:: 
    setFocus(Qt::OtherFocusReason);
    setFocus(Qt::OtherFocusReason);
    setFocus(Qt::OtherFocusReason);
    

    So the focus should be on one of those?
    By the way this tree is from ads::CDockWidget
    Just a moment and I find tree for old
    /
    and here is tree for now object:

    ads::CDockWidgetTab:: 
        QBoxLayout:: 
        ads::CElidingLabel::dockWidgetTabLabel 
        QPushButton::tabCloseButton 
    

  • Lifetime Qt Champion

    hi
    yes it should but we don't have to guess.
    you can do
    QWidget * fw = qApp->focusWidget();
    and check out in the debugger (or qDebug its object name) to see what it is.

    It should be possible to get hold of the Dock again to get your data back.



  • @mrjj QWidget * fw and now widget is the same. See the picture please
    1.png



  • @mrjj now I'm trying to set property to the tabWidgets to wich CDockWidget belongs to:

    QVTKOpenGLStereoWidget* MainWindowObjectCreator::createVTK2DWindow(){
        QVTKOpenGLStereoWidget* qvtkOpenGLStereoWidget = new QVTKOpenGLStereoWidget;
        ads::CDockWidget* dockWidget = new ads::CDockWidget("2D Window");
        dockWidget->setWidget(qvtkOpenGLStereoWidget);
        dockManager->addDockWidget(ads::RightDockWidgetArea, dockWidget);
        dockWidget->tabWidget()->setProperty("IsVisualization", 4443);
        //dockWidget->dumpObjectTree();
        return qvtkOpenGLStereoWidget;
    }
    

    but each time I manually change the focus the MainWindow::onFocusChanged(QWidget* old, QWidget* now) works twice:
    first time now is the old window
    second time is the new window
    and when the second time this method works then I get the correct value of property:

    void MainWindow::onFocusChanged(QWidget* old, QWidget* now){
        QWidget * fw = qApp->focusWidget();
        fw->dumpObjectTree();
        if (now != nullptr){
            now->dumpObjectTree();
            QVariant varia = now->property("IsVisualization"); 
        }
    }
    

    By the way this works only if the focused window is tabbed. Otherwise the focused widget is not a tabWidget(). So idea to set property to the tabWidget() doesn't seem to work


  • Lifetime Qt Champion

    @Please_Help_me_D

    Ah silly me. of cause now will be the same as qApp->focusWidget(); :)
    and it does seem to be the actual DockWidget ! which i didn't expect.

    Is it possible you have 2 connects to the onFocusChanged signal ?
    Not really sure why it should run twice. I don't recall it normally does that.

    Its normally not an issue to loop up the chain to find the top parent.
    So not sure why it dont seem to work for you here.



  • @mrjj yes, now I also find this looking for parent not working for me strange :)
    Just a moment I guess that I'm missing something important...


  • Lifetime Qt Champion

    @Please_Help_me_D
    Yeah as the dumptree clearly shows its the top as we expect
    ads::CDockWidget::2D Window
    QBoxLayout::
    QAction::
    QScrollArea::dockWidgetScrollArea
    QWidget::qt_scrollarea_viewport
    QVTKOpenGLStereoWidget::
    QVBoxLayout::
    ....

    But the test with qApp->focusWidget(); showd now is the Dock so
    looking at this code.

    f (now != nullptr){
    ads::CDockWidget* dockWidget = nullptr;
    QObjectList objList = now->children();

    Do you only check its children ?
    and in that case, the line
    dockWidget = qobject_castads::CDockWidget*(objList.at(i));

    will always return null as you skip the now ? and only cast children ?



  • @mrjj let me clarify one moment.
    Earlier wrote an unclear post about what widget which dumptree has.
    Also there are two possible ways how ads::CDockWidget is attached to the application:

    1. CDockWidget is tabbed
    2. CDockWidget is float (we can pick and drag it as it is like a new window)

    So we have different dumptrees for QWidget* now object on onFocusChanged(QWidget* old, QWidget* now)

    Here is dumptree for tabbed CDOckWidget:

    ads::CDockWidgetTab:: 
        QBoxLayout:: 
        ads::CElidingLabel::dockWidgetTabLabel 
        QPushButton::tabCloseButton 
    

    And here is for float CDockWidget:

    QScrollArea::dockWidgetScrollArea 
        QWidget::qt_scrollarea_viewport 
            QVTKOpenGLStereoWidget:: 
                QVBoxLayout:: 
                QWindowContainer:: 
        QWidget::qt_scrollarea_hcontainer 
            QScrollBar:: 
            QBoxLayout:: 
        QWidget::qt_scrollarea_vcontainer 
            QScrollBar:: 
            QBoxLayout:: 
    

    So we have a deal with two types of top level widgets :)
    But I would like to set the property only to a single type widget and if onFocusChanged() look for that object in now widget


  • Lifetime Qt Champion

    @Please_Help_me_D
    aha. I missed the being tabbed part.
    So when tabbed, the Dock becomes a CDockWidgetTab and the Dock is not around any more?



  • @mrjj when tabbed the focused widget is CDockWidgetTab (because I do this dumptree on the now widget when certain widget is focused). And I don't know exactly where CDockWidget disappears :)


  • Lifetime Qt Champion

    @Please_Help_me_D
    Is CDockWidget just a normal QDockWidget ?

    alt text



  • @mrjj here it is
    60fdf08f-d549-41cb-9f34-b63f0c12d046-image.png

    with the code:

    void MainWindow::onFocusChanged(QWidget* old, QWidget* now){
        if (now != nullptr){
            now->dumpObjectTree();
        }
    }
    

    I started interactively change focused window and the qDebug output shows me that the toplevel widget of dumpObjectTree depends upon where I click: if I click on the QTreeWidget the this widget is on the rop, if on the label then CDockWidgetTab is on the top...


  • Lifetime Qt Champion

    @Please_Help_me_D
    Hi
    I think its a custom setup as it dont look the same for Qt exmaples
    alt text

    Is CDockWidget your own class ?



  • @mrjj it is a standalone library link text


  • Lifetime Qt Champion

    @Please_Help_me_D
    ah. its looks awesome.
    Ok so that makes sense. So it will actually hide the dock and the tab
    is the parent.
    That means setting your value on teh Dock will not work as it not there when tabbed.

    You could instead add a plain QWidget + layout + qvtkOpenGLStereoWidget/ what you normal put in the dock
    so that we always have this QWidget as top and you can add the dynamic property there.
    This ofcause adds extra widget to all docks so if you have huge tons of them, it might be wasteful.



  • @mrjj said in QWidget::windowRole() use as storage for small textual data:

    You could instead add a plain QWidget + layout + qvtkOpenGLStereoWidget/ what you normal put in the dock
    so that we always have this QWidget as top and you can add the dynamic property there.
    This ofcause adds extra widget to all docks so if you have huge tons of them, it might be wasteful.

    Could you please explain this a little bit more? Can't understand the idea.
    Or we could postpone it till tomorrow it is late night :)


  • Lifetime Qt Champion

    @Please_Help_me_D
    Yes let do it tomorrow as im also tired :)
    Its nothing complicated just extra widget with a layout that holds your normal content.
    Im assuminng that even CDock will go away, your actual content still exists so if we add a new QWidget that
    is always included we could add the property there.


Log in to reply