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. How to get proper position for createStandardContextMenu for actions that are sensitive to the position where the user clicked inside customContextMenuRequested handler?

How to get proper position for createStandardContextMenu for actions that are sensitive to the position where the user clicked inside customContextMenuRequested handler?

Scheduled Pinned Locked Moved Unsolved General and Desktop
19 Posts 3 Posters 2.0k Views 1 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.
  • Christian EhrlicherC Offline
    Christian EhrlicherC Offline
    Christian Ehrlicher
    Lifetime Qt Champion
    wrote on last edited by
    #2

    viewport() also has mapToGlobal() since it's a widget too.

    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
    Visit the Qt Academy at https://academy.qt.io/catalog

    R 1 Reply Last reply
    0
    • Christian EhrlicherC Christian Ehrlicher

      viewport() also has mapToGlobal() since it's a widget too.

      R Offline
      R Offline
      Rian Firth
      wrote on last edited by
      #3

      @Christian-Ehrlicher non of them works for me:

      auto viewport = ui->textBrowser->viewport();
      qDebug() << viewport->mapToGlobal(pos);
      qDebug() << viewport->mapFromGlobal(pos);
      qDebug() << viewport->mapToParent(pos);
      qDebug() << viewport->mapFromParent(pos);
      qDebug() << viewport->mapTo(ui->textBrowser, pos);
      qDebug() << viewport->mapFrom(ui->textBrowser, pos);
      

      Clicking in the beginning in approximately top left corner:

      QPoint(296,216)
      QPoint(-290,-212)
      QPoint(4,3)
      QPoint(2,1)
      QPoint(4,3)
      QPoint(2,1)
      

      The same but after scrolling to the bottom:

      QPoint(295,217)
      QPoint(-291,-211)
      QPoint(3,4)
      QPoint(1,2)
      QPoint(3,4)
      QPoint(1,2)
      

      Maybe I'm doing something wrong?

      1 Reply Last reply
      0
      • Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #4

        @Rian-Firth said in How to get proper position for createStandardContextMenu for actions that are sensitive to the position where the user clicked inside customContextMenuRequested handler?:

        qDebug() << viewport->mapToGlobal(pos);

        That's the correct one.

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        R 1 Reply Last reply
        0
        • Christian EhrlicherC Christian Ehrlicher

          @Rian-Firth said in How to get proper position for createStandardContextMenu for actions that are sensitive to the position where the user clicked inside customContextMenuRequested handler?:

          qDebug() << viewport->mapToGlobal(pos);

          That's the correct one.

          R Offline
          R Offline
          Rian Firth
          wrote on last edited by Rian Firth
          #5

          @Christian-Ehrlicher viewport->mapToGlobal(pos) returns screen position [0-1366; 0-768] but createStandardContextMenu(const QPoint &pos) takes local position of scrollarea [0-areaWidth; 0-areaHeight].

          As I already said, for example, if viewport has [500; 200] size but the whole document in QTextBrowser (scrollarea itself) is way more in size [500; 2000], vertical scrollbar will be created and createStandardContextMenu(const QPoint &pos) have to take coordinates [500; 2000] but not [500; 200] or [1366; 768].

          1 Reply Last reply
          0
          • Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #6

            Please post some code where we can see what you're really doing. From your post above you see that viewport->mapToGlobal(pos); returns the same screen coordinates no matter if you scroll or not. Now you're telling me it does not work - this does not match.

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            R 2 Replies Last reply
            0
            • Christian EhrlicherC Christian Ehrlicher

              Please post some code where we can see what you're really doing. From your post above you see that viewport->mapToGlobal(pos); returns the same screen coordinates no matter if you scroll or not. Now you're telling me it does not work - this does not match.

              R Offline
              R Offline
              Rian Firth
              wrote on last edited by
              #7

              @Christian-Ehrlicher I don't understand. I've already posted the code.
              That's how literally it is now:

              MainWindow::MainWindow(QWidget *parent)
                  : QMainWindow(parent)
                  , ui(new Ui::MainWindow)
              {
                  ui->setupUi(this);
                  ui->textBrowser->setContextMenuPolicy(Qt::CustomContextMenu);
              
                  connect(ui->textBrowser, &QTextBrowser::customContextMenuRequested, this, &MainWindow::OnShowContextMenu);
              }
              
              MainWindow::~MainWindow()
              {
                  delete ui;
              }
              
              void MainWindow::OnShowContextMenu(const QPoint& pos)
              {
                  QMenu* menu = ui->textBrowser->createStandardContextMenu(pos);
                  QAction* defaultCopyLink = menu->actions()[1];
              
                  auto viewport = ui->textBrowser->viewport();
                  qDebug() << viewport->mapToGlobal(pos);
                  qDebug() << viewport->mapFromGlobal(pos);
                  qDebug() << viewport->mapToParent(pos);
                  qDebug() << viewport->mapFromParent(pos);
                  qDebug() << viewport->mapTo(ui->textBrowser, pos);
                  qDebug() << viewport->mapFrom(ui->textBrowser, pos);
              
                  connect(defaultCopyLink, &QAction::triggered, [](){
                      auto clipboard = QApplication::clipboard();
                      clipboard->setText("prefix." + clipboard->text());
                  });
              
                  menu->exec(ui->textBrowser->mapToGlobal(pos));
                  delete menu;
              }
              

              Yes, I see that viewport->mapToGlobal(pos); returns the same screen coordinates no matter if I scroll or not. And it makes sense because it's screen coordinates, it's not related to scroll area anyhow. But I don't need screen coordinates. createStandardContextMenu doesn't take screen position.
              Passing screen position from viewport->mapToGlobal(pos); to createStandardContextMenu doesn't work. Actions that are sensitive to the position where the user clicked ("Copy Link Location") won't work like that.

              Sorry if I'm confusing you.
              Please, tell me if you need anything else, I'll try my best.

              1 Reply Last reply
              0
              • Christian EhrlicherC Christian Ehrlicher

                Please post some code where we can see what you're really doing. From your post above you see that viewport->mapToGlobal(pos); returns the same screen coordinates no matter if you scroll or not. Now you're telling me it does not work - this does not match.

                R Offline
                R Offline
                Rian Firth
                wrote on last edited by Rian Firth
                #8

                @Christian-Ehrlicher I created handler for customContextMenuRequested signal so I could create my own QMenu for QTextBrowser:

                MainWindow::MainWindow(QWidget *parent)
                    : QMainWindow(parent)
                    , ui(new Ui::MainWindow)
                {
                    ui->setupUi(this);
                
                    ui->textBrowser->setContextMenuPolicy(Qt::CustomContextMenu);
                    connect(ui->textBrowser, &QTextBrowser::customContextMenuRequested, this, &MainWindow::OnShowContextMenu);
                }
                
                void MainWindow::OnShowContextMenu(const QPoint& pos)
                {
                    QMenu* menu = ui->textBrowser->createStandardContextMenu(pos);
                    menu->exec(ui->textBrowser->mapToGlobal(pos));
                    delete menu;
                }
                

                createStandardContextMenu just creates standard menu for QTextBrowser:

                Copy
                Copy Link Location
                ------------------
                Select All
                

                But this code doesn't work properly because I'm passing pos from OnShowContextMenu(const QPoint& pos) function like this createStandardContextMenu(pos). So "Copy Link Location" action from menu doesn't work when I'm trying to right click on any link in QTextBrowser when I scrolled down.
                a98da421-a787-44d9-a720-9fbb552dfd53-image.png

                The problem is that:

                The position pos is the position of the context menu event that the widget receives. Normally this is in widget coordinates. The exception to this rule is QAbstractScrollArea and its subclasses that map the context menu event to coordinates of the viewport().
                

                QTextBrowser is a subclass of QAbstractScrollArea so pos is just in viewport() coordinates which is [0-vpWidth;0-vpHeight].
                But createStandardContextMenu needs coordinates [0-scrollAreaWidth;0-scrollAreaHeight]. I might be calling it wrong but by scrollArea I mean the whole document that is in QTextBrowser.

                1 Reply Last reply
                0
                • mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on last edited by mrjj
                  #9

                  Hi
                  just call createStandardContextMenu with the translated pos :)

                  void MainWindow::OnShowContextMenu(const QPoint& pos)
                  {
                      QPoint globalPos = ui->textBrowser->mapToGlobal(pos);
                      QMenu* menu = ui->textBrowser->createStandardContextMenu(globalPos); <<<<
                      QAction* defaultCopyLink = menu->actions()[1];
                  
                      auto viewport = ui->textBrowser->viewport();
                      qDebug() << viewport->mapToGlobal(pos);
                      qDebug() << viewport->mapFromGlobal(pos);
                      qDebug() << viewport->mapToParent(pos);
                      qDebug() << viewport->mapFromParent(pos);
                      qDebug() << viewport->mapTo(ui->textBrowser, pos);
                      qDebug() << viewport->mapFrom(ui->textBrowser, pos);
                  
                      connect(defaultCopyLink, &QAction::triggered, [](){
                          auto clipboard = QApplication::clipboard();
                          clipboard->setText("prefix." + clipboard->text());
                      });
                  
                      menu->exec(globalPos);
                      delete menu;
                  
                  

                  alt text

                  R 1 Reply Last reply
                  2
                  • mrjjM mrjj

                    Hi
                    just call createStandardContextMenu with the translated pos :)

                    void MainWindow::OnShowContextMenu(const QPoint& pos)
                    {
                        QPoint globalPos = ui->textBrowser->mapToGlobal(pos);
                        QMenu* menu = ui->textBrowser->createStandardContextMenu(globalPos); <<<<
                        QAction* defaultCopyLink = menu->actions()[1];
                    
                        auto viewport = ui->textBrowser->viewport();
                        qDebug() << viewport->mapToGlobal(pos);
                        qDebug() << viewport->mapFromGlobal(pos);
                        qDebug() << viewport->mapToParent(pos);
                        qDebug() << viewport->mapFromParent(pos);
                        qDebug() << viewport->mapTo(ui->textBrowser, pos);
                        qDebug() << viewport->mapFrom(ui->textBrowser, pos);
                    
                        connect(defaultCopyLink, &QAction::triggered, [](){
                            auto clipboard = QApplication::clipboard();
                            clipboard->setText("prefix." + clipboard->text());
                        });
                    
                        menu->exec(globalPos);
                        delete menu;
                    
                    

                    alt text

                    R Offline
                    R Offline
                    Rian Firth
                    wrote on last edited by Rian Firth
                    #10

                    @mrjj I just literally copied your example but it doesn't work for me even when I don't scroll down. :c

                    746ec745-382b-44c8-be73-8b7e27189023-image.png

                    mrjjM 1 Reply Last reply
                    0
                    • R Rian Firth

                      @mrjj I just literally copied your example but it doesn't work for me even when I don't scroll down. :c

                      746ec745-382b-44c8-be73-8b7e27189023-image.png

                      mrjjM Offline
                      mrjjM Offline
                      mrjj
                      Lifetime Qt Champion
                      wrote on last edited by
                      #11

                      @Rian-Firth
                      Hi
                      I just used your code.
                      I did check it calls your QAction::triggered lambda and all seems ok.

                      This is Qt 5.15.1 on windows.

                      And we are 100% sure those are actual links ?
                      If you click them page is changed ?

                      R 1 Reply Last reply
                      0
                      • mrjjM mrjj

                        @Rian-Firth
                        Hi
                        I just used your code.
                        I did check it calls your QAction::triggered lambda and all seems ok.

                        This is Qt 5.15.1 on windows.

                        And we are 100% sure those are actual links ?
                        If you click them page is changed ?

                        R Offline
                        R Offline
                        Rian Firth
                        wrote on last edited by Rian Firth
                        #12

                        @mrjj it's not about QAction::triggered lambda. It's about that my "Copy Link Location" is not even highlighted when I right click on any link. So I can't even press "Copy Link Location". Basically it has the same behavior when you press in any empty space: you can't press it and it's gray (not highlighted) as if it's disabled. And it's like this even if you click on links.

                        They're 100% actual links and if I click on them page is changed (becomes empty).

                        mrjjM 1 Reply Last reply
                        0
                        • R Rian Firth

                          @mrjj it's not about QAction::triggered lambda. It's about that my "Copy Link Location" is not even highlighted when I right click on any link. So I can't even press "Copy Link Location". Basically it has the same behavior when you press in any empty space: you can't press it and it's gray (not highlighted) as if it's disabled. And it's like this even if you click on links.

                          They're 100% actual links and if I click on them page is changed (becomes empty).

                          mrjjM Offline
                          mrjjM Offline
                          mrjj
                          Lifetime Qt Champion
                          wrote on last edited by
                          #13

                          @Rian-Firth
                          Hi
                          I understand the issue that Copy Link is not enabled. ( so it can't be clicked)

                          Ok so could be a platform thing as it clearly works here.

                          What Qt version and platform are you on?

                          Would it be possible to zip your project and paste link here ?
                          I could then run it and if that still dont work its something else that Qt version/ platform.

                          R 1 Reply Last reply
                          0
                          • Christian EhrlicherC Offline
                            Christian EhrlicherC Offline
                            Christian Ehrlicher
                            Lifetime Qt Champion
                            wrote on last edited by
                            #14

                            @mrjj said in How to get proper position for createStandardContextMenu for actions that are sensitive to the position where the user clicked inside customContextMenuRequested handler?:

                            createStandardContextMenu

                            this function needs local coordinates: "This function creates the standard context menu which is shown when the user clicks on the text edit with the right mouse button. It is called from the default contextMenuEvent() handler and it takes the position in document coordinates where the mouse click was. This can enable actions that are sensitive to the position where the user clicked. The popup menu's ownership is transferred to the caller."

                            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                            Visit the Qt Academy at https://academy.qt.io/catalog

                            1 Reply Last reply
                            2
                            • mrjjM mrjj

                              @Rian-Firth
                              Hi
                              I understand the issue that Copy Link is not enabled. ( so it can't be clicked)

                              Ok so could be a platform thing as it clearly works here.

                              What Qt version and platform are you on?

                              Would it be possible to zip your project and paste link here ?
                              I could then run it and if that still dont work its something else that Qt version/ platform.

                              R Offline
                              R Offline
                              Rian Firth
                              wrote on last edited by
                              #15

                              @mrjj I've tried it on 5.12.9 and 5.15.1, Windows 10.
                              Here you are: https://mega.nz/file/Ik8x1SZS#I6UpE-M-1nWurI1KgUN6esbgcYdpfxh88rPTkLVbUZM

                              1 Reply Last reply
                              0
                              • Christian EhrlicherC Offline
                                Christian EhrlicherC Offline
                                Christian Ehrlicher
                                Lifetime Qt Champion
                                wrote on last edited by Christian Ehrlicher
                                #16
                                
                                void MainWindow::OnShowContextMenu(const QPoint& pos)
                                {
                                    QMenu* menu = ui->textBrowser->createStandardContextMenu(pos);
                                

                                'Normally this is in widget coordinates'
                                ...
                                'and it takes the position in document coordinates where the mouse click was'

                                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                Visit the Qt Academy at https://academy.qt.io/catalog

                                R 1 Reply Last reply
                                0
                                • Christian EhrlicherC Christian Ehrlicher
                                  
                                  void MainWindow::OnShowContextMenu(const QPoint& pos)
                                  {
                                      QMenu* menu = ui->textBrowser->createStandardContextMenu(pos);
                                  

                                  'Normally this is in widget coordinates'
                                  ...
                                  'and it takes the position in document coordinates where the mouse click was'

                                  R Offline
                                  R Offline
                                  Rian Firth
                                  wrote on last edited by
                                  #17

                                  @Christian-Ehrlicher true. How to get that position in document coordinates considering scrolling tho.

                                  1 Reply Last reply
                                  0
                                  • Christian EhrlicherC Offline
                                    Christian EhrlicherC Offline
                                    Christian Ehrlicher
                                    Lifetime Qt Champion
                                    wrote on last edited by Christian Ehrlicher
                                    #18

                                    Ok, now I've a problem or we found a bug. Looks like createStandardContextMenu(QPoint) is not adding the viewport offset. anchorAt() and cursorForPosition() are doing right.
                                    Here the working code (only adjusted y, x must be done the same)

                                    void MainWindow::OnShowContextMenu(const QPoint& pos)
                                    {
                                        QPoint p = pos;
                                        p.ry() += ui->textBrowser->verticalScrollBar()->value();
                                        qDebug() << p;
                                        QMenu* menu = ui->textBrowser->createStandardContextMenu(p);
                                    

                                    /edit: and no bug report for this... strange
                                    /edit2: Using actions()[1] is not good - better search the object with menu->qFindChild<QAction*>("link-copy")
                                    /edit3: at least it was known (also not fixed/explained how to fix it by yourself): https://codereview.qt-project.org/c/qt/qtbase/+/105486
                                    /edit4: https://bugreports.qt.io/browse/QTBUG-89439

                                    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                    Visit the Qt Academy at https://academy.qt.io/catalog

                                    R 1 Reply Last reply
                                    3
                                    • Christian EhrlicherC Christian Ehrlicher

                                      Ok, now I've a problem or we found a bug. Looks like createStandardContextMenu(QPoint) is not adding the viewport offset. anchorAt() and cursorForPosition() are doing right.
                                      Here the working code (only adjusted y, x must be done the same)

                                      void MainWindow::OnShowContextMenu(const QPoint& pos)
                                      {
                                          QPoint p = pos;
                                          p.ry() += ui->textBrowser->verticalScrollBar()->value();
                                          qDebug() << p;
                                          QMenu* menu = ui->textBrowser->createStandardContextMenu(p);
                                      

                                      /edit: and no bug report for this... strange
                                      /edit2: Using actions()[1] is not good - better search the object with menu->qFindChild<QAction*>("link-copy")
                                      /edit3: at least it was known (also not fixed/explained how to fix it by yourself): https://codereview.qt-project.org/c/qt/qtbase/+/105486
                                      /edit4: https://bugreports.qt.io/browse/QTBUG-89439

                                      R Offline
                                      R Offline
                                      Rian Firth
                                      wrote on last edited by
                                      #19

                                      @Christian-Ehrlicher thank you so much for workaround, menu->qFindChild<QAction*>("link-copy") advise and bug report!

                                      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