Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. create ms word-like context menu
Forum Updated to NodeBB v4.3 + New Features

create ms word-like context menu

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 3 Posters 2.5k Views 3 Watching
  • 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.
  • U Offline
    U Offline
    user4592357
    wrote on last edited by user4592357
    #1

    i want to create a custom context menu where i'll have something like this (the "paste options" and the icon below).
    alt text

    i tried using QWidgetAction:

    QMenu *contextMenu = new QMenu(this);
    
    QWidgetAction *widget = new QWidgetAction(contextMenu);
    widget->setIcon(QIcon(":/icon_path"));
    widget->setText(QString("Paste Options:"));
    
    contextMenu->insertAction(beforeActionPtr, widget);
    

    but it doesn't actually do what i want.

    i thought i could make a QActionGroup and add the action to the group, and then set the action group as widget's default widget via:

    widget->setDefaultWidget(actionGroup);
    

    but QActionGroup is derived from QObject so it wasn't a good idea.

    how can i do this?

    raven-worxR 1 Reply Last reply
    0
    • U user4592357

      i want to create a custom context menu where i'll have something like this (the "paste options" and the icon below).
      alt text

      i tried using QWidgetAction:

      QMenu *contextMenu = new QMenu(this);
      
      QWidgetAction *widget = new QWidgetAction(contextMenu);
      widget->setIcon(QIcon(":/icon_path"));
      widget->setText(QString("Paste Options:"));
      
      contextMenu->insertAction(beforeActionPtr, widget);
      

      but it doesn't actually do what i want.

      i thought i could make a QActionGroup and add the action to the group, and then set the action group as widget's default widget via:

      widget->setDefaultWidget(actionGroup);
      

      but QActionGroup is derived from QObject so it wasn't a good idea.

      how can i do this?

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

      @user4592357
      Almost right way. You are just using it wrong.

      QVBoxLayout* layout = new QVBoxLayout;
           layout->setContentMargins( 20, 2, 2, 2 );
           layout->addWidget( ... );  // add your (sub-)options there
      
      QWidget* w = new QWidget( contextMenu );
      w->setLayout( layout );
      
      QWidgetAction* wa = new QWIdgetAction( contextMenu );
          wa->setDefaultWidget( w );
      contextMenu->addAction( wa );
      

      Also you need to make sure once a sub-action (widget) is triggered the menu is closed. Either by calling contextMenu->close() or by calling wa->trigger()

      What exactly triggers your sub-action depends on the type you insert.

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      3
      • U Offline
        U Offline
        user4592357
        wrote on last edited by
        #3

        i have another question. how can i add an icon to the left of the menu. in qt docs, it says:
        This property holds the action's icon.
        In toolbars, the icon is used as the tool button icon; in menus, it is displayed to the left of the menu text. There is no default icon.

        so here's my code:

        auto button1 = new QToolButton;
        button1 ->setIcon(QIcon(":/icon1"))
        
        auto button1 = new QToolButton;
        button1 ->setIcon(QIcon(":/icon2"))
        
        // add a Paste Options label and the tool buttons to a grid layout
        auto widget = new QWidget;
        auto layout = new QGridLayout(widget);
        layout->setContentsMargins(0, 0, 0, 3);
        layout->setColumnMinimumWidth(0, 37);
        
        auto pasteOptionslabel = new QLabel(QObject::tr("Paste Options:"), contextMenu);
        pasteOptionslabel->setStyleSheet("background-color: #D5D5D5;");
        
        layout->addWidget(pasteOptionslabel, 0, 1, 1, 3);
        layout->addWidget(button1, 1, 1);
        layout->addWidget(button2, 1, 2);
        layout->setColumnStretch(5, 255);
        
        // add a widget action to the context menu
        auto pasteOptionsWidget = new QWidgetAction(contextMenu);
        pasteOptionsWidget->setIcon(QIcon(":/icon1"));
        pasteOptionsWidget->setDefaultWidget(widget);
        

        it doesn't add an icon (i suppose it's because i already have a widget added?). so how can i add an icon?

        and another question is, i wanna add a background to label, but the background shows only behind text. how can i do that?

        thanks

        raven-worxR 1 Reply Last reply
        0
        • U user4592357

          i have another question. how can i add an icon to the left of the menu. in qt docs, it says:
          This property holds the action's icon.
          In toolbars, the icon is used as the tool button icon; in menus, it is displayed to the left of the menu text. There is no default icon.

          so here's my code:

          auto button1 = new QToolButton;
          button1 ->setIcon(QIcon(":/icon1"))
          
          auto button1 = new QToolButton;
          button1 ->setIcon(QIcon(":/icon2"))
          
          // add a Paste Options label and the tool buttons to a grid layout
          auto widget = new QWidget;
          auto layout = new QGridLayout(widget);
          layout->setContentsMargins(0, 0, 0, 3);
          layout->setColumnMinimumWidth(0, 37);
          
          auto pasteOptionslabel = new QLabel(QObject::tr("Paste Options:"), contextMenu);
          pasteOptionslabel->setStyleSheet("background-color: #D5D5D5;");
          
          layout->addWidget(pasteOptionslabel, 0, 1, 1, 3);
          layout->addWidget(button1, 1, 1);
          layout->addWidget(button2, 1, 2);
          layout->setColumnStretch(5, 255);
          
          // add a widget action to the context menu
          auto pasteOptionsWidget = new QWidgetAction(contextMenu);
          pasteOptionsWidget->setIcon(QIcon(":/icon1"));
          pasteOptionsWidget->setDefaultWidget(widget);
          

          it doesn't add an icon (i suppose it's because i already have a widget added?). so how can i add an icon?

          and another question is, i wanna add a background to label, but the background shows only behind text. how can i do that?

          thanks

          raven-worxR Offline
          raven-worxR Offline
          raven-worx
          Moderators
          wrote on last edited by raven-worx
          #4

          @user4592357 said in create ms word-like context menu:

          it doesn't add an icon (i suppose it's because i already have a widget added?). so how can i add an icon?

          the widget action stretches over the full menu width. So there is no icon shown. You can place the icon inside your widget though.

          and another question is, i wanna add a background to label, but the background shows only behind text. how can i do that?

          i don't quite understand this? Isn't a background not supposed to show behind the content?? o.O

          --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
          If you have a question please use the forum so others can benefit from the solution in the future

          1 Reply Last reply
          1
          • U Offline
            U Offline
            user4592357
            wrote on last edited by user4592357
            #5

            i've figured out the part to add bg to the label, the problem is that in context menu, the items are a little bit indented and i need the background include that indent space too, as in the picture in first post.

            and i've tried to pasteOptionsWidget->setIconVisibleInMenu(true); but still no luck. so how can i add icon inside widget?

            1 Reply Last reply
            0
            • Chris KawaC Online
              Chris KawaC Online
              Chris Kawa
              Lifetime Qt Champion
              wrote on last edited by
              #6

              To simplify the submenu you can use a toolbar. As for the label item, if you're gonna use this pattern often you might invest in a custom widget that paints it.

              Here's the code for such menu:

                  QMenu menu(this);
                  menu.addAction(QIcon(":/cut.png"), tr("Cut"));
                  menu.addAction(QIcon(":/copy.png"), tr("Copy"));
              
                  auto paste_section_act = new QWidgetAction(&menu);
                  paste_section_act->setDefaultWidget(new SectionWidget(QIcon(":/paste.png"), tr("Paste Options:"), &menu));
              
                  auto paste_toolbar = new QToolBar();
                  paste_toolbar->setIconSize(QSize(26,26));
                  auto paste_toolbar_act = new QWidgetAction(&menu);
                  paste_toolbar_act->setDefaultWidget(paste_toolbar);
              
                  auto spacer = new QWidget();
                  spacer->setMinimumWidth(20);
                  paste_toolbar->addWidget(spacer);
                  paste_toolbar->addAction(QIcon(":/paste.png"), QString());
                  paste_toolbar->addAction(QIcon(":/paste.png"), QString());
                  paste_toolbar->addAction(QIcon(":/paste.png"), QString());
              
                  menu.addAction(paste_section_act);
                  menu.addAction(paste_toolbar_act);
              
                  connect(paste_toolbar, &QToolBar::actionTriggered, &menu, &QMenu::close);
              
                  menu.exec();
              

              And here's a code for a custom section item:

              class SectionWidget : public QWidget
              {
              public:
                  SectionWidget(const QIcon& icon, const QString& text, QWidget* parent = nullptr)
                      : QWidget(parent), icon(icon), text(text) {}
              protected:
                  void paintEvent(QPaintEvent* event) override
                  {
                      QPainter p(this);
              
                      QStyleOptionMenuItem opt;
                      opt.initFrom(this);
                      opt.rect = rect();
                      opt.icon = icon;
                      opt.text = text;
                      opt.font.setBold(true);
              
                      const int icon_size = style()->pixelMetric(QStyle::PM_SmallIconSize, &opt, this);
              
                      p.fillRect(rect().adjusted(icon_size + 8, 0, -1, 0), palette().color(QPalette::Base).darker(110));
                      style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this);
                  }
                  QSize minimumSizeHint() const override
                  {
                      QRect text_rect = fontMetrics().boundingRect(QRect(), Qt::TextSingleLine | Qt::TextShowMnemonic, text);
                      QStyleOptionMenuItem opt;
                      opt.initFrom(this);
                      const int icon_size = style()->pixelMetric(QStyle::PM_SmallIconSize, &opt, this);
                      const int some_margin = 6;
                      QSize cs;
                      cs.setWidth(some_margin + icon_size + text_rect.width());
                      cs.setHeight(some_margin + qMax(icon_size, text_rect.height()));
                      return style()->sizeFromContents(QStyle::CT_MenuItem, &opt, cs, this);
                  }
              private:
                  QIcon icon;
                  QString text;
              };
              

              This is the result I got:
              office_menu

              1 Reply Last reply
              4
              • U Offline
                U Offline
                user4592357
                wrote on last edited by user4592357
                #7

                thanks a lot! for some reason it works a little differently for me so i'm trying to correct some things. for me, the toolbar actually shows the outline (that button effect). how can i get rid of that?

                and for the text inside widget isn't aligned in center (vertically). i've tried setting flags (Qt::AlignCenter, Qt::AlignJustify) for textRect but that didn't work

                1 Reply Last reply
                0
                • Chris KawaC Online
                  Chris KawaC Online
                  Chris Kawa
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  for me the bottom padding a larger than top padding

                  That could be due to the icon size you used i.e. if it's larger than the calculated text height (notice I'm using max of these two values).

                  U 1 Reply Last reply
                  0
                  • U Offline
                    U Offline
                    user4592357
                    wrote on last edited by
                    #9

                    okay got it. and the toolbar i added has some weird outline (border?) around it and it gives button effect to the toolbar. how can i remove it?

                    1 Reply Last reply
                    0
                    • Chris KawaC Chris Kawa

                      for me the bottom padding a larger than top padding

                      That could be due to the icon size you used i.e. if it's larger than the calculated text height (notice I'm using max of these two values).

                      U Offline
                      U Offline
                      user4592357
                      wrote on last edited by
                      #10

                      @Chris-Kawa

                      there's another thing. when the context menu is shown and when i mouse over the items from top to bottom, when i get to the this custom section, the item above it (i.e. copy) has the focus. how do i change this?

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved