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. Calendar Week and Day views, need advises
Qt 6.11 is out! See what's new in the release blog

Calendar Week and Day views, need advises

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 5 Posters 4.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.
  • G Offline
    G Offline
    Gulivert
    wrote on last edited by
    #1

    Hi,

    I'm new in QT dev and start to develop an application where I need to manage events and display them to Week and Day calendar view.
    As calendar widget support only month view I want to develop custom widget for each view.

    My problem is I do not know what is the best solution or even a working solution to create for instance a view for a day, where I can add, remove, drag and drop .... events.

    I was thinking that maybe that a list view to manage the day view and table view to manage week view could do the job.

    I will really appreciate any hints from you if you have good enough (and surely better than me) in QT dev to have a better overview of a good solution.

    Just for information, the events are coming from an API REST and events created and modified will be save to this API, I think it will not do any difference but I prefere mention it.

    Thank's a lot for any advise.

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #2

      While QCalendarWidget uses the model/view concept and you could use the same using a tree model, a custom view and a custom delegate, I think the easiest way to implement something similar to Google Calendar is using the QGraphicsScene framework instead

      "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
      2
      • G Offline
        G Offline
        Gulivert
        wrote on last edited by Gulivert
        #3

        Thank you for your reply. I come back a long time after your response but I needed to learn more Qt to go further with my application.

        So now my App has growing up with a lot a functionality but I'm still stuck with my Calendar views.

        I finally managed the Day and Week view by using QTableView with a custom model from QAbstractTableModel. This model manage the layout of the QTableView with the needed rows and column, and also manage the headers and background color for working hours.
        Next to I created a a delegate from QItemDelegate where I'm able to manage the split cell lines. It looks nice and exactly with what I want

        So here is the result for week:
        week view
        for day:
        day view

        Now I need to add Events on this view and it where I'm stuck. I tried to add a simple QWidget with a label and set a background color, then finally add them to the table (and not the model...) like this.

                 QWidget *eventWidget = new QWidget(ui->dayTable);
                 eventWidget->setStyleSheet("background-color:rgb(145, 37, 5);"); 
        
                QLabel *label = new QLabel(eventWidget);
                label->setStyleSheet("QLabel { font-size : 11px; }");
                label->setText("John Doe");
        
                QVBoxLayout *eventLayout = new QVBoxLayout(eventWidget);
                eventLayout->addWidget(label);
                eventLayout->setMargin(2);
                eventWidget->setLayout(eventLayout);
        
                ui->dayTable->setIndexWidget(ui->dayTable->model()->index(hours * 3 + minutes / 20, 0), eventWidget);
        

        Then I get my Widgets render inside the table. Great! But I need for instance to change the size of some of event according to start and end date (maybe an event must cover 3 cells and not only one), so how I should manage the events inside the table ?
        I also want to have actions from right click on events and show a popup menu, and also want to be able to drag and drop the event.
        I'm also not able to delete the widgets on the table. Finally I also need to manage placement with more than one event in the same place. A lot of questions :'(

        Any idea from your side ?

        Here is a final result:
        day view events

        In the example we see that the Event call Vasseur Astrid should start at 10:00 and finish at 11:00 (take 3 cells) but I do not know how to manage that.

        Thank you in advance to taking time for an answer which would be really helpful.

        JonBJ 1 Reply Last reply
        0
        • G Gulivert

          Thank you for your reply. I come back a long time after your response but I needed to learn more Qt to go further with my application.

          So now my App has growing up with a lot a functionality but I'm still stuck with my Calendar views.

          I finally managed the Day and Week view by using QTableView with a custom model from QAbstractTableModel. This model manage the layout of the QTableView with the needed rows and column, and also manage the headers and background color for working hours.
          Next to I created a a delegate from QItemDelegate where I'm able to manage the split cell lines. It looks nice and exactly with what I want

          So here is the result for week:
          week view
          for day:
          day view

          Now I need to add Events on this view and it where I'm stuck. I tried to add a simple QWidget with a label and set a background color, then finally add them to the table (and not the model...) like this.

                   QWidget *eventWidget = new QWidget(ui->dayTable);
                   eventWidget->setStyleSheet("background-color:rgb(145, 37, 5);"); 
          
                  QLabel *label = new QLabel(eventWidget);
                  label->setStyleSheet("QLabel { font-size : 11px; }");
                  label->setText("John Doe");
          
                  QVBoxLayout *eventLayout = new QVBoxLayout(eventWidget);
                  eventLayout->addWidget(label);
                  eventLayout->setMargin(2);
                  eventWidget->setLayout(eventLayout);
          
                  ui->dayTable->setIndexWidget(ui->dayTable->model()->index(hours * 3 + minutes / 20, 0), eventWidget);
          

          Then I get my Widgets render inside the table. Great! But I need for instance to change the size of some of event according to start and end date (maybe an event must cover 3 cells and not only one), so how I should manage the events inside the table ?
          I also want to have actions from right click on events and show a popup menu, and also want to be able to drag and drop the event.
          I'm also not able to delete the widgets on the table. Finally I also need to manage placement with more than one event in the same place. A lot of questions :'(

          Any idea from your side ?

          Here is a final result:
          day view events

          In the example we see that the Event call Vasseur Astrid should start at 10:00 and finish at 11:00 (take 3 cells) but I do not know how to manage that.

          Thank you in advance to taking time for an answer which would be really helpful.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #4

          @Gulivert

          Vasseur Astrid should start at 10:00 and finish at 11:00 (take 3 cells) but I do not know how to manage that

          It looks like you want that item to span more than 1 row downward. Just as you can make item span multiple columns you can do that for rows too. See https://doc.qt.io/qt-5/qtableview.html#setSpan

          If that does not work well for what you want (and it may not), you may have to look into creating multiple elements for one event at different times. There are pros & cons to doing it each way, design what you will need first.

          G 1 Reply Last reply
          0
          • JonBJ JonB

            @Gulivert

            Vasseur Astrid should start at 10:00 and finish at 11:00 (take 3 cells) but I do not know how to manage that

            It looks like you want that item to span more than 1 row downward. Just as you can make item span multiple columns you can do that for rows too. See https://doc.qt.io/qt-5/qtableview.html#setSpan

            If that does not work well for what you want (and it may not), you may have to look into creating multiple elements for one event at different times. There are pros & cons to doing it each way, design what you will need first.

            G Offline
            G Offline
            Gulivert
            wrote on last edited by
            #5

            @JonB
            Thank you for your quick answer.

            setSpan is to merge cells together, am I right ?
            If I have correctly understand this will not help me in case I have to show two events in same cell. Or did I miss something?

            JonBJ 1 Reply Last reply
            0
            • G Gulivert

              @JonB
              Thank you for your quick answer.

              setSpan is to merge cells together, am I right ?
              If I have correctly understand this will not help me in case I have to show two events in same cell. Or did I miss something?

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #6

              @Gulivert
              I think of setSpan() as allowing a single cell to span multiple columns, or in this case multiple rows. The idea being to get a single cell to occupy the 10:00, 10:20 & 10:40 cell rows (or something like that), which I believe is what you were asking for? I don't think it matters whether you think of it as "spanning" or "merging" cells.

              in case I have to show two events in same cell

              Well, you're going to have problems with your simple representation if you need that, depending on exactly what you want. Since it allows you to span your rows by column, if you do have multiple events you could place them in separate columns, one with multi-row span and the other with single row, and that should still work for what you have in mind?

              1 Reply Last reply
              0
              • G Offline
                G Offline
                Gulivert
                wrote on last edited by
                #7

                OK I finally managed my view to be ok. I finally will never have any double events for the same hours then it is now a bit more easy to manage events placement and span the cells correctly by event.

                But I still have one last problem. When I delete an event on the table the application crash if my Calendar view is updated (Like changing the current date, then the table is updated to show the new date).

                Here is what I do to create the event and to delete it :

                foreach (const QJsonValue &value, appointmentsArr) {
                        QJsonObject appointmentObj = value.toObject();
                
                        // Create event model
                        Event *event = new Event(appointmentObj); // create a new event from model
                        event->setPosCol(QDate::fromString(appointmentObj["start_date"].toString(), Qt::ISODate).dayOfWeek() - 1);
                
                        // Create event EventLabels for calendar table views
                        EventLabel *eventLabel = new EventLabel();
                        eventLabel->setEvent(event);
                
                        // Add event labels to eventLabels list
                        this->eventLabels.append(eventLabel);
                
                        // Connect labels for mouse events
                        connect(eventLabel, &EventLabel::doubleClicked, this, &CalendarView::onEventDoubleClicked);
                        connect(eventLabel, &EventLabel::modifyActionClicked, this, &CalendarView::onModifyActionClicked);
                        connect(eventLabel, &EventLabel::deleteActionClicked, this, &CalendarView::onDeleteActionClicked);
                
                        // Span table cells for event label if needed
                        if (eventLabel->getEvent()->getSpanRow() != 1) {
                            ui->calendarWeekTable->setSpan(eventLabel->getEvent()->getPosRow(), eventLabel->getEvent()->getPosCol(), eventLabel->getEvent()->getSpanRow(), 1);
                        }
                
                        // Add event label to the table view
                        ui->calendarWeekTable->setIndexWidget(ui->calendarWeekTable->model()->index(eventLabel->getEvent()->getPosRow(), eventLabel->getEvent()->getPosCol()), eventLabel);
                    }
                

                Then later to delete an event :

                void CalendarView::onDeleteActionClicked(EventLabel *eventLabel)
                {
                    this->apiClient->deleteAppointment(eventLabel->getEvent()->getId());
                
                    // Hide the label
                    eventLabel->setHidden(true);
                    eventLabel->setParent(NULL); // Detach eventLabel to table
                    // Remove label to the list
                    eventLabels.removeOne(eventLabel);
                
                    // Remove span cell to table if needed
                    if (eventLabel->getEvent()->getSpanRow() != 1) {
                        ui->calendarWeekTable->setSpan(eventLabel->getEvent()->getPosRow(), eventLabel->getEvent()->getPosCol(), 1, 1);
                    }
                
                    // Delete event widget
                    eventLabel->deleteLater();
                }
                

                It is like the eventLabel object is still inside the table. Should I do something special to remove a widget from a QTableView ?

                mrjjM 1 Reply Last reply
                0
                • G Gulivert

                  OK I finally managed my view to be ok. I finally will never have any double events for the same hours then it is now a bit more easy to manage events placement and span the cells correctly by event.

                  But I still have one last problem. When I delete an event on the table the application crash if my Calendar view is updated (Like changing the current date, then the table is updated to show the new date).

                  Here is what I do to create the event and to delete it :

                  foreach (const QJsonValue &value, appointmentsArr) {
                          QJsonObject appointmentObj = value.toObject();
                  
                          // Create event model
                          Event *event = new Event(appointmentObj); // create a new event from model
                          event->setPosCol(QDate::fromString(appointmentObj["start_date"].toString(), Qt::ISODate).dayOfWeek() - 1);
                  
                          // Create event EventLabels for calendar table views
                          EventLabel *eventLabel = new EventLabel();
                          eventLabel->setEvent(event);
                  
                          // Add event labels to eventLabels list
                          this->eventLabels.append(eventLabel);
                  
                          // Connect labels for mouse events
                          connect(eventLabel, &EventLabel::doubleClicked, this, &CalendarView::onEventDoubleClicked);
                          connect(eventLabel, &EventLabel::modifyActionClicked, this, &CalendarView::onModifyActionClicked);
                          connect(eventLabel, &EventLabel::deleteActionClicked, this, &CalendarView::onDeleteActionClicked);
                  
                          // Span table cells for event label if needed
                          if (eventLabel->getEvent()->getSpanRow() != 1) {
                              ui->calendarWeekTable->setSpan(eventLabel->getEvent()->getPosRow(), eventLabel->getEvent()->getPosCol(), eventLabel->getEvent()->getSpanRow(), 1);
                          }
                  
                          // Add event label to the table view
                          ui->calendarWeekTable->setIndexWidget(ui->calendarWeekTable->model()->index(eventLabel->getEvent()->getPosRow(), eventLabel->getEvent()->getPosCol()), eventLabel);
                      }
                  

                  Then later to delete an event :

                  void CalendarView::onDeleteActionClicked(EventLabel *eventLabel)
                  {
                      this->apiClient->deleteAppointment(eventLabel->getEvent()->getId());
                  
                      // Hide the label
                      eventLabel->setHidden(true);
                      eventLabel->setParent(NULL); // Detach eventLabel to table
                      // Remove label to the list
                      eventLabels.removeOne(eventLabel);
                  
                      // Remove span cell to table if needed
                      if (eventLabel->getEvent()->getSpanRow() != 1) {
                          ui->calendarWeekTable->setSpan(eventLabel->getEvent()->getPosRow(), eventLabel->getEvent()->getPosCol(), 1, 1);
                      }
                  
                      // Delete event widget
                      eventLabel->deleteLater();
                  }
                  

                  It is like the eventLabel object is still inside the table. Should I do something special to remove a widget from a QTableView ?

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

                  @Gulivert said in Calendar Week and Day views, need advises:

                  eventLabel

                  Hi
                  you used
                  https://doc.qt.io/qt-5/qabstractitemview.html#setIndexWidget
                  which states the viewport takes ownership.

                  You can try setting a nullptr to same index instead of
                  eventLabel->deleteLater();
                  setIndexWidget is not really meant for dynamic content so
                  there seems to be no API for removing it again, howver doc
                  says calling setIndexWidget will delete any existing.
                  So try give it a nullptr and see.

                  G 1 Reply Last reply
                  3
                  • mrjjM mrjj

                    @Gulivert said in Calendar Week and Day views, need advises:

                    eventLabel

                    Hi
                    you used
                    https://doc.qt.io/qt-5/qabstractitemview.html#setIndexWidget
                    which states the viewport takes ownership.

                    You can try setting a nullptr to same index instead of
                    eventLabel->deleteLater();
                    setIndexWidget is not really meant for dynamic content so
                    there seems to be no API for removing it again, howver doc
                    says calling setIndexWidget will delete any existing.
                    So try give it a nullptr and see.

                    G Offline
                    G Offline
                    Gulivert
                    wrote on last edited by
                    #9

                    @mrjj
                    Haaaa thank you soooo muchhhhh :) It works !

                    1 Reply Last reply
                    1
                    • J Offline
                      J Offline
                      JerS
                      wrote on last edited by JerS
                      #10

                      Hi,
                      I'm trying to do something similar: a month/week/day view widget to use instead of the calendar.
                      If you had any wish to share your code it would be greatly appreciated :)
                      Thanks,
                      Jerome

                      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