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

How to rewrite MDI example structure C++ code



  • I am still not sure how to modify my Qt MDI example.
    I am using it because it does what I am after utilizing QMainWindow..

    I am not interested in changing the horse in middle of the race.

    Here is rough description of the process / structure , somewhat in "top to bottom way".

    create central MDI widget - mdiArea
    create sub windows list QMdiSubWindow
    create sun window contents - MDIChild derived from test editor
    insert MDIChild to sub window list

    Now the MDI example works fine as is - happily processing
    mdiArea -> subwindow -> child's file

    The "problem" is I do not need to manipulate "file".
    Unfortunately "file" (text name ) is used to do neat stuff likes tiling multiple subwindows in areaMDI.

    So I have MDIChild QTextEdit derived class and I am stuck on HOW to
    add my C++ code creating form / widget.

    QTextEdit base class is QWidget - how do I physically "append" my
    C++ code creating the form ?

    I was thinking of multiple inheritance , but why when QTextEdit is already derived from QWidget?
    here is stripped down , minimal comments , of createMDIChild

    MdiChild *MainWindow::createMdiChild()
    {
    // change MdiChild from text edit to widget ??
    // MDIChild is derived from QTextEdit and QWidget
    MdiChild *child = new MdiChild;
    QMdiSubWindow *currentSubWindow = mdiArea->addSubWindow(child);
    #ifndef QT_NO_CLIPBOARD
    connect(child, &QTextEdit::copyAvailable, cutAct, &QAction::setEnabled);
    connect(child, &QTextEdit::copyAvailable, copyAct, &QAction::setEnabled);
    #endif
    return child;
    }

    In  other words - how do I "add ' my C++  form creation  code to "MDIChild" 
    and keep original QTextEdit  variables - such as "file name"  for "tile" processing ?  Another "subclass" just for widget creation?


  • @AnneRanch
    I'm sorry I don't understand much of the question. But there should be no need for multiple inheritance, or indeed inheritance anything. I don't know why you have any special class MdiChild.

    Normally I would just do all MDI children as

    QTextEdit *textEdit = new QTextEdit;
    QWidget *mdiChild = new QWidget;
    mdiChild->setLayout(new QVBoxLayout);
    mdiChild->layout()->addWidget(textEdit);
    // mdiChild->layout()->addWidget(new QLabel("Type into the TextArea above"));
    // mdiChild->layout()->addWidget(new QPushButton("Click this"));
    QMdiSubWindow *currentSubWindow = mdiArea->addSubWindow(mdiChild);
    

    That creates a QWidget, which is what I add as an MDI subwindow. On that I have put layout and then you can add whatever of your widgets.

    If you want to skip the QWidget layer, you could just go:

    QTextEdit *textEdit = new QTextEdit;
    QMdiSubWindow *currentSubWindow = mdiArea->addSubWindow(textEdit);
    

    That's probably fine with a QTextEdit, which can grow to be big & multiline and fill the window, but would look a little odd if the widget is just some tiny QPushButton or similar. And without a containing widget as per the first example you won't be able to add anything but a single widget to the subwindow, which is why the first example is probably the way to go.

    If you have designed your own Form, perhaps in Qt Designer, with its own layout and sub-widgets on it, you can use that as the widget for the MDI child window:

    Form *myForm = new Form;
    QMdiSubWindow *currentSubWindow = mdiArea->addSubWindow(myForm);
    

  • Moderators

    @JonB said in How to rewrite MDI example structure C++ code:

    there should be no need for multiple inheritance, or indeed inheritance anything. I don't know why you have any special class MdiChild.

    I agree that multiple inheritance is not the way.

    Regarding MdiChild, it's just how one of the old examples did it: https://code.qt.io/cgit/qt/qtbase.git/tree/examples/widgets/mainwindows/mdi/mdichild.h While I wouldn't inherit QTextEdit personally, this example's MdiChild has the same role as the Form at the end of your post.



  • Thanks for replies.
    You are correct the MDIChild just complicates things - but when one starts by hacking / using Qt examples there is not much choice while using it as a base. Wright or (old) wrong.

    I have made some progress since I started , most parts work.

    I am pretty much stuck on implementing Window "Tile" - it requires "file name" as subwindow title etc...
    In my view I am hacking the MDI example going "backward" since my widget is not a file with a name .
    But I can obviously add fake file name to make MDIChild happy.

    However ,for now et me work on elimination the MDIChild from the MDI example.



  • I am posting my current under construction code to illustrate "the problem".

    The example MDIChild uses real file - with name.
    This part of the code adds such files to MDI example "Window" menu.
    Works fine.

    Now when I build my widget it is NOT a file - hence no name.

    Missing name breaks this "Window" menu code big time - obviously.

    I was thinking to add "fake file" to my widget so I can reuse this part of "Window" menu code.

    Not the best , but does that approach makes some sense?
    I am still trying to reuse as much of the original MDI example code.

    Again to clarify - I do not have much issues changing the "QTextEdit" to QWidget - the "file name " is the issue as far as I can tell.

    // initially create empty QList<QMdiSubWindow *> windows
        void MainWindow::updateWindowMenu()
        {
            qDebug() << "START void MainWindow::updateWindowMenu()" <<__FUNCTION__<<
                        " @line " <<__LINE__;
            //  windowMenu initilized (?)
            qDebug() << "TRACE access pn initialization " <<__FUNCTION__<<
                        " @line " <<__LINE__;
            windowMenu->clear();
            windowMenu->addAction(closeAct);
            windowMenu->addAction(closeAllAct);
            windowMenu->addSeparator();
            windowMenu->addSeparator();
            windowMenu->addSeparator();
            windowMenu->addAction(tileAct);
            windowMenu->addAction(cascadeAct);
            windowMenu->addSeparator();
            windowMenu->addAction(nextAct);
            windowMenu->addAction(previousAct);
            windowMenu->addAction(windowMenuSeparatorAct);
    
            qDebug() << "TRACE get list of subwindows in mdiArea" <<__FUNCTION__<<
                        " @line " <<__LINE__;
            qDebug() << "TRACE breakpoint " <<__FUNCTION__<<
                        " @line " <<__LINE__;
            QList<QMdiSubWindow *> windows = mdiArea->subWindowList();
            qDebug() << "TRACE breakpoint " <<__FUNCTION__<<
                        " @line " <<__LINE__;
    
            windowMenuSeparatorAct->setVisible(!windows.isEmpty());
            qDebug() << "TRACE breakpoint " <<__FUNCTION__<<
                        " @line " <<__LINE__;
            // check initilal windows size
            qDebug() << "TRACE check subwindows size / count  " <<windows.size(); // __FUNCTION__<<
            //               " @line " <<__LINE__;
            for (int i = 0; i < windows.size(); ++i) {
                // mdi area subwindow  from list
                QMdiSubWindow *mdiSubWindow = windows.at(i);
                //   mdiSubWindow
                //  retive contents of subwindow as child
                MdiChild *child = qobject_cast<MdiChild *>(mdiSubWindow->widget());
    
                //  scan for widget type so far only a label
                // child->MDIChildType
                //HERE
    
    
                // temporary bypass  no file
                if(  child->MDIChildType == 0)
                    //if(!child->userFriendlyCurrentFile().isEmpty())
                { // add file info to menu
                    // check initilal windows size
                    qDebug() << "TRACE *****************  process CTextEdit child "<< __FUNCTION__<<__LINE__;
    
                    QString text;
                    if (i < 9) {
                        text = tr("&%1 %2").arg(i + 1)
                                .arg(child->userFriendlyCurrentFile());
                    } else {
                        text = tr("%1 %2").arg(i + 1)
                                .arg(child->userFriendlyCurrentFile());
                    }
                    // show files in "windows" menu (?)
                    // create "window" menu action / items
                    QAction *action = windowMenu->addAction(text,
                                                            mdiSubWindow, [this, mdiSubWindow]()
                    {
                        // why block (?)
                        mdiArea->setActiveSubWindow(mdiSubWindow);
                    }
                    );
                    action->setCheckable(true);
                    action->setChecked(child == activeMdiChild());
                }
                else
                {
                    qDebug() << "TRACE %%%%%%%%%%%%%%%%%%%%%%%%%%*****************  process CTextEdit child "<< __FUNCTION__<<__LINE__;
    
                    // try setting FDB to stop[ here on warning
                    mdiSubWindow->widget()->show();
                }
            }
            qDebug() << "TRACE breakpoint " <<__FUNCTION__<<
                        " @line " <<__LINE__;
        }
    


  • SOLVED with the help of this forum.
    It was just a matter of putting the code in relevant places.

    Adding widgets to MdiChild
    PARTIALLY SOLVED


  • Lifetime Qt Champion

    Good, then please mark the thread as solved using the "Topic Tools" button or the three doted menu beside the answer you deem correct so that other forum users may know a solution has been found :-)



  • This post is deleted!


  • @AnneRanch said in How to rewrite MDI example structure C++ code:

    I now have two processes running and the "myProcess" dialog works fine - what I wnat is to insert the dialog from one process to another .

    You have asked this previously, and the answer remains the same. So long as you have "separate processes" --- something run via QProcess --- you cannot "insert the dialog from one process to another ." MDI or not makes no difference. If you wish to have a dialog from one set of code appear in another set of code, they must both be in the same application, no independent processes.

    On a separate matter, if you do wish to use QProcess you still presently have:

    myProcess->start();
    int result_execute  = myProcess->execute(program); //, arguments);
    

    We have said before that this will run two instances of the btscanner program, and so you should find there are two btscanner windows opened, which is not right.


Log in to reply