Get QDate from QCalendarWidget custom context menu
-
@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.
-
@ivanicy
Sorry, I don't understand at all. This is not the same situation asQTreeView::indexAt(point)
, where you know the point is inside theQtreeView
but what to find out which cell/index is at that point. With aQCalendarWidget
there are no multiple anythings, the date is stored in theQCalendarWidget
....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
QPoint
s 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 inrect
. 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 yourQPoint
at a later date. Extremely ugly, but unless someone else tells you how to do it differently.... -
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(); }