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. Get QDate from QCalendarWidget custom context menu
Forum Updated to NodeBB v4.3 + New Features

Get QDate from QCalendarWidget custom context menu

Scheduled Pinned Locked Moved Unsolved General and Desktop
7 Posts 3 Posters 488 Views
  • 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.
  • I Offline
    I Offline
    ivanicy
    wrote on 20 Apr 2022, 10:01 last edited by
    #1

    Hello!

    I have a QCalendarWidget in my app. I want to show a context menu when I right click on it. The customContextMenuRequested() function has a QPoint parameter. How can I get the QDate corresponding to that point?

    Thank you very much!

    J 1 Reply Last reply 20 Apr 2022, 10:23
    0
    • I ivanicy
      20 Apr 2022, 10:01

      Hello!

      I have a QCalendarWidget in my app. I want to show a context menu when I right click on it. The customContextMenuRequested() function has a QPoint parameter. How can I get the QDate corresponding to that point?

      Thank you very much!

      J Offline
      J Offline
      JonB
      wrote on 20 Apr 2022, 10:23 last edited by
      #2

      @ivanicy
      Pardon?! The QPoint is where to show a custom menu, it has nothing to do with "the QDate corresponding to that point"?

      I 1 Reply Last reply 20 Apr 2022, 10:33
      0
      • J JonB
        20 Apr 2022, 10:23

        @ivanicy
        Pardon?! The QPoint is where to show a custom menu, it has nothing to do with "the QDate corresponding to that point"?

        I Offline
        I Offline
        ivanicy
        wrote on 20 Apr 2022, 10:33 last edited by ivanicy
        #3

        @JonB For example, when I use the customContextMenuRequested(const QPoint &) signal in a QTreeView, I can retrieve the QModelIndex as follows:

        QModelIndex index = ui->treeView->indexAt(point);
        

        I want to do something like that with the QCalendarWidget, for example to change the color of this cell day.

        J 1 Reply Last reply 20 Apr 2022, 11:04
        0
        • I ivanicy
          20 Apr 2022, 10:33

          @JonB For example, when I use the customContextMenuRequested(const QPoint &) signal in a QTreeView, I can retrieve the QModelIndex as follows:

          QModelIndex index = ui->treeView->indexAt(point);
          

          I want to do something like that with the QCalendarWidget, for example to change the color of this cell day.

          J Offline
          J Offline
          JonB
          wrote on 20 Apr 2022, 11:04 last edited by
          #4

          @ivanicy
          Sorry, I don't understand at all. This is not the same situation as QTreeView::indexAt(point), where you know the point is inside the QtreeView but what to find out which cell/index is at that point. With a QCalendarWidget there are no multiple anythings, the date is stored in the QCalendarWidget....

          Oh... you don't mean the date selected into the widget, you mean "which date on the pop-up of the whole month's dates is at a particular point", right? I had no idea!

          I do not see anything which would map QPoints to the date cell at that point. Though I could be missing something!

          So the only thing I could see is: virtual protectedvoid QCalendarWidget::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const. That is called when a cell with date is painted in rect. Presumably when the widget is first shown every date-cell is painted. So you could override this and save the rectangle position for every date (or be smart and calculate some "formula" from the values you see). Then you could use that to look up your QPoint at a later date. Extremely ugly, but unless someone else tells you how to do it differently....

          1 Reply Last reply
          0
          • V Offline
            V Offline
            VRonin
            wrote on 20 Apr 2022, 11:05 last edited by VRonin
            #5

            How can I get the QDate corresponding to that point?

            A bit clunky but it works:

            #include <QApplication>
            #include <QCalendarWidget>
            #include <QTableView>
            
            int main(int argc, char *argv[])
            {
                QApplication a(argc, argv);
                QCalendarWidget wid;
                wid.setContextMenuPolicy(Qt::CustomContextMenu);
                QObject::connect(&wid,&QWidget::customContextMenuRequested,[&wid](const QPoint &pos){
                    const QTableView* const view = wid.findChild<const QTableView*>();
                    Q_ASSERT(view);
                    const QAbstractItemModel* const model = view->model();
                    const int startCol = wid.verticalHeaderFormat()==QCalendarWidget::NoVerticalHeader ? 0:1;
                    const int startRow = wid.horizontalHeaderFormat()==QCalendarWidget::NoHorizontalHeader ? 0:1;
                    const QModelIndex clickedIndex = view->indexAt(view->viewport()->mapFromGlobal(wid.mapToGlobal(pos)));
                    if(clickedIndex.row() < startRow || clickedIndex.column() < startCol)
                        return;
                    QModelIndex firstIndex;
                    bool firstFound=false;
                    for(int i=startRow, maxI=model->rowCount();!firstFound && i<maxI;++i){
                        for(int j=startCol, maxJ=model->columnCount();!firstFound && j<maxJ;++j){
                            firstIndex = model->index(i,j);
                            if(firstIndex.data().toInt()==1)
                                firstFound =true;
                        }
                    }
                    const int lastDayMonth = QDate(wid.yearShown(),wid.monthShown(),1).addMonths(1).addDays(-1).day();
                    bool lastFound=false;
                    QModelIndex lastIndex;
                    for(int i=model->rowCount()-1, minI=firstIndex.row();!lastFound && i>=minI;--i){
                        for(int j=model->columnCount()-1;!lastFound && j>=startCol;--j){
                            lastIndex= model->index(i,j);
                            if(lastIndex.data().toInt()==lastDayMonth)
                                lastFound=true;
                        }
                    }
                    int monthShift = 0;
                    int yearShift=0;
                    if(clickedIndex.row()<firstIndex.row() || (clickedIndex.row()==firstIndex.row() && clickedIndex.column()<firstIndex.column())){
                            if(wid.monthShown()==1){
                                    yearShift=-1;
                                    monthShift=11;
                            }
                            else
                                monthShift = -1;
                    }
                    else if(clickedIndex.row()>lastIndex.row() || (clickedIndex.row()==lastIndex.row() && clickedIndex.column()>lastIndex.column())){
                            if(wid.monthShown()==12){
                                    yearShift=1;
                                    monthShift=-11;
                            }
                            else
                                monthShift = 1;
                    }
                    qDebug() << QDate(wid.yearShown()+yearShift,wid.monthShown()+monthShift,clickedIndex.data().toInt());
                });
                wid.show();
                return a.exec();
            }
            

            I can retrieve the QModelIndex

            if you just need the QModelIndex and not the actual date it's much easier:

            #include <QApplication>
            #include <QCalendarWidget>
            #include <QTableView>
            
            int main(int argc, char *argv[])
            {
                QApplication a(argc, argv);
                QCalendarWidget wid;
                wid.setContextMenuPolicy(Qt::CustomContextMenu);
                QObject::connect(&wid,&QWidget::customContextMenuRequested,[&wid](const QPoint &pos){
                    const QTableView* const view = wid.findChild<const QTableView*>();
                    Q_ASSERT(view);
                    const int startCol = wid.verticalHeaderFormat()==QCalendarWidget::NoVerticalHeader ? 0:1;
                    const int startRow = wid.horizontalHeaderFormat()==QCalendarWidget::NoHorizontalHeader ? 0:1;
                    const QModelIndex clickedIndex = view->indexAt(view->viewport()->mapFromGlobal(wid.mapToGlobal(pos)));
                    if(clickedIndex.row() < startRow || clickedIndex.column() < startCol)
                        return;
                    qDebug() << clickedIndex;
                });
                wid.show();
                return a.exec();
            }
            

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            J 1 Reply Last reply 20 Apr 2022, 11:07
            2
            • V VRonin
              20 Apr 2022, 11:05

              How can I get the QDate corresponding to that point?

              A bit clunky but it works:

              #include <QApplication>
              #include <QCalendarWidget>
              #include <QTableView>
              
              int main(int argc, char *argv[])
              {
                  QApplication a(argc, argv);
                  QCalendarWidget wid;
                  wid.setContextMenuPolicy(Qt::CustomContextMenu);
                  QObject::connect(&wid,&QWidget::customContextMenuRequested,[&wid](const QPoint &pos){
                      const QTableView* const view = wid.findChild<const QTableView*>();
                      Q_ASSERT(view);
                      const QAbstractItemModel* const model = view->model();
                      const int startCol = wid.verticalHeaderFormat()==QCalendarWidget::NoVerticalHeader ? 0:1;
                      const int startRow = wid.horizontalHeaderFormat()==QCalendarWidget::NoHorizontalHeader ? 0:1;
                      const QModelIndex clickedIndex = view->indexAt(view->viewport()->mapFromGlobal(wid.mapToGlobal(pos)));
                      if(clickedIndex.row() < startRow || clickedIndex.column() < startCol)
                          return;
                      QModelIndex firstIndex;
                      bool firstFound=false;
                      for(int i=startRow, maxI=model->rowCount();!firstFound && i<maxI;++i){
                          for(int j=startCol, maxJ=model->columnCount();!firstFound && j<maxJ;++j){
                              firstIndex = model->index(i,j);
                              if(firstIndex.data().toInt()==1)
                                  firstFound =true;
                          }
                      }
                      const int lastDayMonth = QDate(wid.yearShown(),wid.monthShown(),1).addMonths(1).addDays(-1).day();
                      bool lastFound=false;
                      QModelIndex lastIndex;
                      for(int i=model->rowCount()-1, minI=firstIndex.row();!lastFound && i>=minI;--i){
                          for(int j=model->columnCount()-1;!lastFound && j>=startCol;--j){
                              lastIndex= model->index(i,j);
                              if(lastIndex.data().toInt()==lastDayMonth)
                                  lastFound=true;
                          }
                      }
                      int monthShift = 0;
                      int yearShift=0;
                      if(clickedIndex.row()<firstIndex.row() || (clickedIndex.row()==firstIndex.row() && clickedIndex.column()<firstIndex.column())){
                              if(wid.monthShown()==1){
                                      yearShift=-1;
                                      monthShift=11;
                              }
                              else
                                  monthShift = -1;
                      }
                      else if(clickedIndex.row()>lastIndex.row() || (clickedIndex.row()==lastIndex.row() && clickedIndex.column()>lastIndex.column())){
                              if(wid.monthShown()==12){
                                      yearShift=1;
                                      monthShift=-11;
                              }
                              else
                                  monthShift = 1;
                      }
                      qDebug() << QDate(wid.yearShown()+yearShift,wid.monthShown()+monthShift,clickedIndex.data().toInt());
                  });
                  wid.show();
                  return a.exec();
              }
              

              I can retrieve the QModelIndex

              if you just need the QModelIndex and not the actual date it's much easier:

              #include <QApplication>
              #include <QCalendarWidget>
              #include <QTableView>
              
              int main(int argc, char *argv[])
              {
                  QApplication a(argc, argv);
                  QCalendarWidget wid;
                  wid.setContextMenuPolicy(Qt::CustomContextMenu);
                  QObject::connect(&wid,&QWidget::customContextMenuRequested,[&wid](const QPoint &pos){
                      const QTableView* const view = wid.findChild<const QTableView*>();
                      Q_ASSERT(view);
                      const int startCol = wid.verticalHeaderFormat()==QCalendarWidget::NoVerticalHeader ? 0:1;
                      const int startRow = wid.horizontalHeaderFormat()==QCalendarWidget::NoHorizontalHeader ? 0:1;
                      const QModelIndex clickedIndex = view->indexAt(view->viewport()->mapFromGlobal(wid.mapToGlobal(pos)));
                      if(clickedIndex.row() < startRow || clickedIndex.column() < startCol)
                          return;
                      qDebug() << clickedIndex;
                  });
                  wid.show();
                  return a.exec();
              }
              
              J Offline
              J Offline
              JonB
              wrote on 20 Apr 2022, 11:07 last edited by
              #6

              @VRonin Blimey!!

              V 1 Reply Last reply 20 Apr 2022, 11:08
              0
              • J JonB
                20 Apr 2022, 11:07

                @VRonin Blimey!!

                V Offline
                V Offline
                VRonin
                wrote on 20 Apr 2022, 11:08 last edited by
                #7

                @JonB I agree, it should not be this hard. QCalendarWidget hides way too much in the private API

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                1 Reply Last reply
                0

                1/7

                20 Apr 2022, 10:01

                • Login

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