0

I have a QMainWindow which contains, on the left, a QTreeWidget and, on the right, another QMainWindow with windowFlags set to Qt::Widget.

This is because the QMainWindow is the only way to provide docking functionality to a QWidget. (I want the docked components to be popped out of the "real" window entirely if needed.

My problem is that I want users to be able to keep popped out dock widgets even if their item is not selected on the left.

For example, here is the global layout:

Window layout

Let's say I select Item 1. On the right I will have some dockable widgets which I am able to reorder as I wish. If I pop one out to keep an eye on it, I don't want it to disappear if I select Item 2.

To go even further, I could want to show ALL Items' dockable widgets at once if I want.

My original idea to achieve this was to make each Item have its dedicated QMainWindow stored inside its data and I would just switch the right one to reflect the currently active one.

Maybe what I want is a bad idea and maybe it's not even feasible.

Could someone with some Qt knowledge tell me if I'm doing/wanting something wrong please?

Edit:

It would be perfectly fine to me if there were a way to trigger the "inner QMainWindow" pop out manually. Like, for example, a button "pop out" in the top right corner which would completely pop it and make it an entirely new window (still linked to the other one, though)

Edit2:

I's like to point out that I haven't tried anything regarding this question yet. I am essentially wondering if it fits with Qt's way of doing things.

This question made me happy about being able to provide docking capabilities to only a part of the program but I still aren't sure about what I want. Can I really achieve this?

Edit7, MVCE:

Hopefully I didn't forget anything since this is done by modifying my files.

mainwindow2.cpp

#include "mainwindow2.hh"
#include "ui_mainwindow2.h"
#include <QTreeWidgetItem>

MainWindow2::MainWindow2(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow2)
{
    ui->setupUi(this);
    ui->mainPanel->setWindowFlags(Qt::Widget);
    QTreeWidgetItem* item = new QTreeWidgetItem;
    item->setData(0, 0, QVariant::fromValue(QString("Item 1")));
    ui->accountsTreeWidget->addTopLevelItem(item);
    QTreeWidgetItem* item2 = new QTreeWidgetItem;
    item2->setData(0, 0, QVariant::fromValue(QString("Item 2")));
    ui->accountsTreeWidget->addTopLevelItem(item2);
}

MainWindow2::~MainWindow2()
{
    delete ui;
}

mainwindow2.hh

#ifndef MAINWINDOW2_HH
#define MAINWINDOW2_HH

#include <QMainWindow>

namespace Ui {
class MainWindow2;
}

class MainWindow2 : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow2(QWidget *parent = 0);
    ~MainWindow2();

private:
    Ui::MainWindow2 *ui;
};

#endif // MAINWINDOW2_HH

mainwindow2.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow2</class>
 <widget class="QMainWindow" name="MainWindow2">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>1200</width>
    <height>700</height>
   </rect>
  </property>
  <property name="minimumSize">
   <size>
    <width>1200</width>
    <height>700</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>Main Window</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <property name="minimumSize">
    <size>
     <width>1200</width>
     <height>658</height>
    </size>
   </property>
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="1" rowspan="2" colspan="2">
     <widget class="QMainWindow" name="mainPanel"/>
    </item>
    <item row="0" column="0">
     <widget class="QTreeWidget" name="accountsTreeWidget">
      <property name="minimumSize">
       <size>
        <width>200</width>
        <height>0</height>
       </size>
      </property>
      <property name="maximumSize">
       <size>
        <width>300</width>
        <height>16777215</height>
       </size>
      </property>
      <property name="frameShape">
       <enum>QFrame::NoFrame</enum>
      </property>
      <property name="selectionBehavior">
       <enum>QAbstractItemView::SelectItems</enum>
      </property>
      <property name="uniformRowHeights">
       <bool>true</bool>
      </property>
      <attribute name="headerVisible">
       <bool>false</bool>
      </attribute>
      <column>
       <property name="text">
        <string notr="true">1</string>
       </property>
      </column>
     </widget>
    </item>
   </layout>
  </widget>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <connections/>
</ui>

main.cpp

#include "mainwindow2.hh"
#include <QApplication>
#include <QStyleFactory>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    app.setStyle(QStyleFactory::create("Fusion"));

    MainWindow2 w;
    w.show();

    return app.exec();
}

project.pro

#-------------------------------------------------
#
# Project created by QtCreator 2017-11-12T23:07:49
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = project
TEMPLATE = app

DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

INCLUDEPATH += $$PWD

SOURCES += \
        main.cpp \
        mainwindow2.cpp

HEADERS += \
        mainwindow2.hh

FORMS += \
        mainwindow2.ui
Telokis
  • 3,399
  • 14
  • 36
  • 2
    Because of the reputation you have, you must know that you must provide an MVCE. ;P – eyllanesc Nov 15 '17 at 12:59
  • @eyllanesc I do know that it's a nice plus but I'm at work for now and it was more a "Is it possible?" kind of question! :p – Telokis Nov 15 '17 at 13:27
  • 1
    And there is a nice picture baked with my MSPaint skills – Telokis Nov 15 '17 at 13:27
  • My request goes in the sense of being able to have a code to be able to test, I do not want to invest time in creating the widget from scratch, that's why I ask you for an MVCE or that you provide your code through github or similar. I place my order based on your sentence: ***I have** a QMainWindow which contains, on the left, to QTreeWidget and, on the right, another QMainWindow with windowFlags set to Qt :: Widget.* – eyllanesc Nov 15 '17 at 15:17
  • Yes I get it. That's just a .ui file though. I'll update the main post later. – Telokis Nov 15 '17 at 15:19
  • @eyllanesc Did it! – Telokis Nov 15 '17 at 15:43

1 Answers1

1

In the right side, you could add a parent widget, with a QBoxLayout, attach all the items to it, and just hide, show and sort them as you wish.

Make them a custom class, with a public int variable to let you identify them later on. Store their pointers in a QList, and then just loop the list and hide or show items by your criteria ( Using the int variable ).

Example:

Items form category A -> int value 0
Items form category B -> int value 1
etc...

ehopperdietzel
  • 121
  • 1
  • 10
  • How would that handle the situation where I have a popped out window that "should" be hidden? – Telokis Nov 15 '17 at 15:14
  • You can't have a widget docked and showed as an independent window at the same time, you should create a dockable item that represents the independent window, or just duplicate the item and show it twice ( Docked and independent ). – ehopperdietzel Nov 15 '17 at 18:37
  • You should check [this](https://stackoverflow.com/questions/10047321/qt-using-one-widget-in-several-layouts) answer. – ehopperdietzel Nov 15 '17 at 18:44
  • No, I don't want to duplicate things but if I have 3 or 4 dockable tabs in each Item of my list and juste want to pop one out, can I still replace the "view" that is left? Maybe it would be easier to have a way to just pop out the entier "sub-QMainWindow" from my real window? – Telokis Nov 15 '17 at 21:22