tags:

views:

66

answers:

1

At present the QCalendarWidget only supports SingleSelection or NoSelection. I'd like to be able to write a widget that inherits from QCalendarWidget in Qt 4.6.2 and adds the ability for the user to select any day in a week and have that custom week selected.

e.g. Click on Thu 5 August 2010 and all days from Saturday 31 July to Friday 6 August inclusive get selected.

My experience with Qt is limited and it's been a while since I've done some C++ so do I need to worry about implementing a copy constructor or virtual destructors when inheriting in Qt, or any other pitfalls to be aware of? What would the header and cpp files look like for such a custom widget and where is the best place to add my custom paint logic and SelectionMode?

I'm using gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) and Qt 4.6.2

+1  A: 

After reading the QCalendarWidget source code, it seems to me this might be the case for inheritance, but there will be issues.

First, classes that derive from QObject, widgets included, shouldn’t have copy constructors. The explanation for this is here. The QObject destructor is virtual, so no matter how you declare yours, it will be virtual too.

When extending a class to change its behavior, look for virtual functions. If there aren’t any, it’s a good indication that inheritance might not be the best approach. In this case, we have three virtual methods:

virtual QSize sizeHint() const;
virtual QSize minimumSizeHint() const;
virtual void paintCell(QPainter *painter, const QRect &rect, const QDate &date) const;

The first two are virtuals from QWidget and deal with sizing the widget. They are probably not important. The last one might do part of what you want: making the whole week appear selected when a day of that week is picked by the user.

Now, for the possible issues:

The selection mode property is non-virtual and, moreover, is enum-valued. One cannot extend the enumerated type to include the new proposed WeekSelection value. If you don’t have to change selection modes on runtime, you can safely ignore this property and work only with week selections. (Ignoring a property is a good indication that your widget should probably have a QCalendarView and not be a QCalendarView.)

QCalendarView is also a composite widget (unlike a label or push button). Internally, it is made of a QTableView, many QToolButtons, a QSpinBox and so on. This kind of widget is harder to extend by inheritance, because you don’t have access to its internals and most of the behavior (such as painting and handling input events) is done by the internal widgets, not by QCalendarView itself.

In some situations, you can hunt for the children widgets using findChildren() and modify their behavior by changing properties and installing event filters. This is prone to break, however, because Nokia can change the internals from 4.6.2 to 4.6.3 as long as the public binary interface of the class is preserved.

Ask yourself if the new widget must inherit from QCalendarWidget. If not and inheriting leads you to a dead end, consider copying the source code of QCalendarWidget and adapting it to your needs. You can go even further and clone the Qt source code, change the original widget itself to include your behavior and propose a merge request back to Nokia.

andref