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

How to initialize and configure QMenu in separate class?



  • So I have a custom QGraphicsScene, which has A LOT of stuff to handle, and each of the selectable elements calls a QMenu, which is also very complicated. So far I've kept the initialization of all the QActions, their signals and slots connections and their logic for setting checked/unchecked status concerning multiple selection of qgraphicsitems in the scene cpp file in different methods, but the cpp becomes too large and I want to refactor a bit. I want to create QMenu in different class. Should I inherit from QGraphicsScene in the new class, or QMenu, or else?

    Edit: I will have a pointer to my custom scene in the new class, which will be set in it's constructor, so when I create the menu class in the scene, I will write something like CustomMenu menu = CustomMenu(this);
    ...I am also a beginner, so yeah :D


  • Lifetime Qt Champion

    Hi
    Do you also want this new Helper class to handle the signals from the scene ?



  • @Hristo-Konstantinov said in How to initialize and configure QMenu in separate class?:

    I want to create QMenu in different class. Should I inherit from QGraphicsScene in the new class, or QMenu, or else?

    If you want to create a QMenu, you should inherit from QMenu, and not (also) from QGraphicsScene! :)

    If you need to access the scene from the menu, then yes access that via a member variable, or parent or something. Whether your menu will really need access to the scene (as opposed to the other direction) is another matter. Within reason, the more you keep your classes distinct from each other, the better. In Qt, signals & slots can help keep classes separate.



  • I tried subclassing from QMenu and QGraphicsScene but it didn't work, that's why I'm posting here. Got lot of errors. But if the problem is with me, I'll try again :)


  • Lifetime Qt Champion

    Hi
    Its a bit hard to give advice when we dont know the code you have / want to move.
    And how you want the new object and the existing ones to talk to each other.
    Subclassing QMenu would most of the time be used to make a special menu and
    you already have a subclassed scene, right ?

    Could you show some of the code you want to move away ?



  • void Scene::checkboxSet()
    {
        Tooth *tooth;
    
    
        for(int i = 0; i < 6; i++)
        {
            bool uncheckedFound = 0;
            int allunchecked = 0;
            for(QGraphicsItem* item : selectedItems())
            {
                tooth = (Tooth*)item;
    
                if(!tooth->status->obturation ||
                  (tooth->status->obturation && !tooth->status->surfO[i]))
                    {
                        uncheckedFound = 1; allunchecked++;
                    }
            }
    
            if(allunchecked == selectedItems().size()) surfObt[i]->setChecked(0);
            else if(uncheckedFound)surfObt[i]->setChecked(0); //the special exception
            else surfObt[i]->setChecked(1);
    
        }
    
        for(int i = 0; i < 6; i++)
        {
            bool uncheckedFound = 0;
            int allunchecked = 0;
            for(QGraphicsItem* item : selectedItems())
            {
                tooth = (Tooth*)item;
    
                if(!tooth->status->caries ||
                  (tooth->status->caries && !tooth->status->surfC[i]))
                    {
                        uncheckedFound = 1; allunchecked++;
                    }
            }
    
            if(allunchecked == selectedItems().size()) surfCar[i]->setChecked(0);
            else if(uncheckedFound)surfCar[i]->setChecked(0); //the special exception
            else surfCar[i]->setChecked(1);
        }
    
        int molarsSelected = 0;
    
        for(int i = 0; i<19; i++)
        {
              bool uncheckedFound = 0;
              int allunchecked = 0;
    
              for(QGraphicsItem* item : selectedItems())
              {
                 tooth = (Tooth*)item;
    
                      if(!tooth->status->checkMarks[i])
                          {uncheckedFound = 1; allunchecked++;}
                      if(tooth->status->toothType == ToothType::molar) molarsSelected++;
              }
              if(allunchecked == selectedItems().size()) menuAction[i]->setChecked(0);
              else if(uncheckedFound)menuAction[i]->setChecked(0); //partially checked
              else menuAction[i]->setChecked(1);
        }
    
        if(molarsSelected/19 == selectedItems().size())
            menuAction[0]->setDisabled(1);
        else
            menuAction[0]->setDisabled(0);
    }
    
    void Scene::contextMenuInitializer()
    {
        menu = new QMenu;
    
        QMenu *ObturMenu = menu->addMenu("&Обтурация");
        QMenu *CariesMenu = menu->addMenu("&Кариес");
        QMenu *EndoMenu = menu->addMenu("&Ендодонтия");
    {
        QString surfName[6] = {"&Оклузално", "&Медиално", "&Дистално", "&Букално", "&Лингвално", "&Цервикално"};
    
    
    
        for(int i = 0; i < 6; i++)
        {
            surfObt[i] = ObturMenu->addAction(surfName[i]);
            surfCar[i] = CariesMenu->addAction(surfName[i]);
            connect(surfObt[i], &QAction::triggered, [this, i](){changeSurfaceObt(i);});
            connect(surfCar[i], &QAction::triggered, [this, i](){changeSurfaceCar(i);});
            surfObt[i]->setCheckable(1);
            surfCar[i]->setCheckable(1);
        }
    
    }
        QString actionNames[19] = {"&Временен зъб", "&Обтурация", "&Кариес",
                                   "&Пулпит", "&Пулпна некроза", "&Ендодонтско лечение","&Инфектиран пълнеж",
                                   "&Екстракция", "&Корен", "Имплант", "&Периодонтит",
                                   "&Фрактура", "&Пародонтит", "&Първа степен", "&Втора степен", "&Трета степен",
                                   "&Корона", "&Мост", };
    
    
    
        for(int i = 0; i<19; i++) //too lazy to initialize all the actions;
        {
            menuAction[i] = new QAction(actionNames[i]);
            menuAction[i] ->setCheckable(1);
            //if(i != o || i != c || i !=d1 || i != d2 || i !=d3) //those have their own logic :)
            connect(menuAction[i], &QAction::triggered, [this, i](){inputDiagnosis(i);});
        }
    
        ObturMenu->addSeparator();
        QAction *obturMO = ObturMenu->addAction("Обтурация МО");
        connect(obturMO, &QAction::triggered, [this](){removeObturation();changeSurfaceObt(medial); changeSurfaceObt(occlusal);});
        QAction *obturDO = ObturMenu->addAction("Обтурация ДО");
        connect(obturDO, &QAction::triggered, [this](){removeObturation();changeSurfaceObt(distal); changeSurfaceObt(occlusal);});
        QAction *obturMOD = ObturMenu->addAction("Обтурация МОД");
        connect(obturMOD, &QAction::triggered, [this](){removeObturation();changeSurfaceObt(medial); changeSurfaceObt(occlusal); changeSurfaceObt(distal);});
        ObturMenu->addSeparator();
        QAction *obturRemove = ObturMenu->addAction("&Премахни");
        connect(obturRemove, &QAction::triggered, [this](){removeObturation();});
    
        CariesMenu->addSeparator();
        QAction *cariesRemove = CariesMenu->addAction("&Премахни");
        connect(cariesRemove, &QAction::triggered, [this](){removeCaries();});
    
        menu->addSeparator();
    
        EndoMenu->addAction(menuAction[pulpitis]);
        EndoMenu->addAction(menuAction[necrosis]);
        EndoMenu->addAction(menuAction[endo]);
        EndoMenu->addAction(menuAction[endofail]);
    
        menu->addSeparator();
    
        menu->addAction(menuAction[root]);
        menu->addAction(menuAction[extraction]);
        menu->addAction(menuAction[implant]);
    
        menu->addSeparator();
    
        menu->addAction(menuAction[16]);
    
        menu->addSeparator();
    
        menu->addAction(menuAction[deciduous]);
    
        menu->addSeparator();
    
        QAction *statusRemove = menu->addAction("&Премахни статус");
        connect(statusRemove, &QAction::triggered, [this](){reinitializeStatus();});
    
    
    }
    
    

    the first function sets the checkbox of the QActions depending on the items selected and their status, and the second one just initializes the menu. I have all QActions as member variables in my subclassed scene.


Log in to reply