[Development] Qt Quick Controls Calendar
Mark Gaiser
markg85 at gmail.com
Tue Jan 7 15:36:13 UTC 2014
On Tue, Jan 7, 2014 at 2:49 PM, Martin Klapetek
<martin.klapetek at gmail.com> wrote:
> On Fri, Dec 6, 2013 at 3:08 PM, Mark Gaiser <markg85 at gmail.com> wrote:
>>
>>
>> Below is my "feature" list that i'd like to have in that calendar.
>> Since i have some experience in that area i will try to help out as
>> much as i can.
>>
>> -- QML part --
>> * Controls for the calendar grid
>> * Controls for next/forward or just a few functions. This should at
>> least have a nextMonth/previousMonth. Perhaps also nextYear and
>> previousYear for convenience.
>
>
> nextMonth/prevMonth totally agreed. For years, that depends on the UI imho,
> so that the header is not too cluttered with different arrows. I can imagine
> a fading up/down arrows above/below the year, not sure how much would that
> work in practice though...
next/previous year would be just convenience.
Perhaps there should be a more abstract way to do this:
<obj>.setMonth(<obj>.month -12)
which would give you the previous year, same month.
That would be easy for manipulating the calendar view without the need
to reset the full date when you want to change to a different month.
Then nextMonth and previousMonth won't be implemented on the C++ side.
Rather, they would be implemented on the QML side as simple functions:
function nextMonth() {
<obj>.setMonth(<obj>.month + 1)
}
function previousMonth() {
<obj>.setMonth(<obj>.month - 1)
}
function nextYear() {
<obj>.setMonth(<obj>.month + 12)
}
etc..
That allows for far more flexibility and a clean C++ interface without
much convenience functions.
>
>>
>> * Controls for the day names (mon, tue, wed, thu, fri, sat, sun). And
>> the ability to change the name to shorter/longer variants.
>
>
> What would be the usecase for longer variants? Full screen/huuge calendars I
> assume? Here's an important question imho - should the days be capitalized
> or not? Qt's locale follows, well, the locale and for example the Czech
> weekday names are not capitalized because we do not capitalize them, like
> for example Friday in English is. However, when it's put standalone, I think
> it should always be capitalized. It simply looks better.
You're thinking just about the calendar grid now. For that you don't
need more then 3 char day names.
But my intention is more to have a general data model that can be
easily used for more then just a calendar grid though the grid would
be it's primary goal.
So it is tailored towards a grid, but not limited to it.
An example where you might want longer daynames is in a event overview
which just sums up the upcoming events. The current plasma calendar
even has that so i think it should have the ability to set the day
name lengths with the possibilities that you can also find in QDate.
As for capitalize the first char.
I think the model (the C++ side) should just return the string that
the locale gives. Without modification. The QML side - the view - can
then capitalize it. It's kinda pointless to add a model property:
bool capitalizeFirstDayChar..
Possible, but seems a bit odd.
>
>>
>> * Controls for the weeknumbers that are shown in the grid.
>
>
> Optional with default off. But if the visual side is made good enough
> looking, it might work. But in 76% of times you don't need to know the week
> number, then it just clutters the grid.
It's just a model :) on/off is decided by the view i guess.
>
>>
>> As far as i understand the QML code, all but the weeknumbers are in.
>
>
> Yup, but it's made as one single component (for consumers) iirc.
>
>>
>> -- Locale --
>> In KDE there was already an issue with differences between the
>> JavaScript date object and the QDate object. I don't know the fine
>> details here, someone else will probably fill that in i hope. I know
>> there where issues, just not what exactly.
>
>
> I already posted it before, but for the sake of completeness, QDate starts
> weekdays and months with 1 while JS Date object starts both with 0, so eg.
> QDate weekday value 7 is Sunday while JS Date would give you "undefined" for
> 7.
Right, so we either should do no modification in from the C++ model
and let it be done by the view. Or we should do all modifications -
which i can't even think of - and just hope that it won't ever
interfere with the view.
I vote for sending date objects to QML and let the view decide what to
do with it.
>
>>
>> -- C++ part --
>> This is the part where i really would like some feedback. I have a
>> general idea of how it should be done, but i don't know the details or
>> implications it might have.
>> It is my hope that calendar controls like Mitch is proposing now will
>> be extensive enough to simply swap the models to another backend.
>> Akonadi comes to mind. However, there should obviously be a
>> non-akonadi based version for default Qt usage.
>>
>> My idea on that is as follows. Again, i don't know the implications of
>> it or if it's really viable to take this route. Feedback is very much
>> welcome here!
>> The calendar model should be based on a new model that provides some
>> default functionality and properties. I would say:
>> QAbstractCalendarModel : public QAbstractListModel { ... }
>> This model should provide the default - should be implemented -
>> properties:
>> * day -- INT number of the day in a current month
>
>
> You mean like 31, 28 etc? Or what would this property be for? The selected
> day? Then let's name it properly.
Interesting!
I actually thing "day" is named properly :)
The model basically has a list of days (one for each in a month). Each
day had a number which "day" would be.
Perhaps "dayInMonth" would be more clear?
Yes, this is:
1, 2, 3, 4, .... 28, 29, 30...
Note that the abstract model has no knowledge about the selected day.
It just has a list of days represented in a model, another model with
all events for the days in the model and that should be about it.
Besides some convenient models for the week numbers and day names.
However, your reply did make me wonder how i would ever make this work
if the abstract model doesn't know about the currently selected day. I
now think it does need to know abut that, but doesn't need to
implement it. It must know the properties which classes implementing
the abstract model should re-implement to give it meaning.
>
>>
>> * isCurrentMonth -- returns true for the current month (aka, the month
>> you are viewing in the calendar). Returns false for the days before
>> and after the currently viewing month. Based on the position in the
>> grid you can then calculate if the entry where "isCurrentMonth"
>> returns false is before or after the current month.
>
>
> "isCurrentMonth" implicates "is this the month that currently really is",
> eg. QString("January").isCurrentMonth() = true;. If it's supposed to be the
> month currently in the view, let's name it "isCurrentlyDisplayedMonth" or
> something.
+1. isCurrentlyDisplayedMonth makes more sense.
>
>>
>> * containsEvents -- true if the day contains events, false otherwise
>
>
> How would one then retrieve the events for the given day? Also, wouldn't it
> be better to have a model role returning this?
This is something i thought - at the time i wrote the proposal - would
make since since you could use this to check if a day has events. If
it does then you can load the model for that day. However, that
doesn't make any sense anymore. Specially because i forgot to name a
property like:
QAIM events
I think it's better to just return a model for the events in the
current day. That makes more sense anyway.
However, that poses another difficulty. multiday events!
In a grid view you might not want to see multiday events for each day
it occurs. You just want to see it when it starts (like it's now in
plasma calendar). However, in a list view or timeline view you
actually might want to see it for each day.
While writing this mail i'm thinking about leaving out a property for
events altogether and make a function available:
Type would be a flags field with one or more of the following:
- Events
- Todo
- Holiday
- Journal
includeMultiday.
true: for each day the event occurs, you will have an event object
false(default): only the first day of the overlap will have a event object
QAbstractListModel events(QDate, Type, bool includeMultiday)
And a range version of the same function:
QAbstractListModel events(QDate start, QDate end, Type, bool includeMultiday)
I think that would be very flexible and accommodate every need.
>
>>
>>
>> "day" and "isCurrentMonth" should be convenience implemented in the
>> QAbstractCalendarModel.
>>
>> Next there should be a model for core Qt calendar usage. Or in other
>> terms: no akonadi dependency.
>> That would be a class like:
>> QSimpleCalendarModel : public QAbstractCalendarModel { ... }
>>
>> That class should probably have some basic storage in json files
>> somewhere? Or ini or sqlite or..? Just something so that it can be
>> used out of the box without any other requirements beyond Qt.
>> Till this point is what would probably go in Qt. Everything after this
>> line becomes Akonadi specific and should not be in Qt.
>
>
> What would it store? I mean what events would be in the simple calendar? If
> you want that to be a base class for other people implementing calendar
> events backend, I think the Abstract class is enough? Or is that meant just
> as an basic example? Then it can go to qt's examples and use whatever is the
> easiest. Imho.
Well, you can have a calendar without akonadi you know ;) It's more
intended to be a simple calendar storage type for those wanting to
have a calendar but not from anything fancy like akonadi. Just some
local simple storage. How it would store it or where. I don't know.
This is not a class i would implement :)
I would make the abstract version and the akonadi based
implementation. This class would probably be done by Mitch i guess?
>
>>
>> If a structure like the above is approved then Akonadi can be very
>> easily used in KDE with the Qt calendar components.
>> We'd just have to make out own QAbstractCalendarModel implementation
>> that uses akonadi data. That would be a class like:
>> (K)AconadiCalendarModel : public QAbstractCalendarModel { ... }
>>
>> It can still use the base QAbstractCalendarModel implementation for
>> it's grid stuff and re-implement the "containsEvents" property to be
>> filled with data from akonadi.
>
>
> How would that be filled with data if it returns boolean? I mean, what do
> you want to fill where? :)
>
>
> Overall I like the real model backend, however I think your proposal also
> could use definition of roles for the model and what would be returned for
> those roles (what comes to mind is single vs. multiple events in one day,
> would it always return a list or a string in one case and list in other
> case...etc).
The return for those roles is decided in the class re-implementing
QAbstractCalendarModel. In this case the akonadi implementation.
How that would look like is completely unknown right now. You can
however expect it to resemble the stuff i already made for my calendar
components ;)
But i guess there is one class missing here.
The object it returns for events in a day must be known in
QAbstractCalendarModel thus a class has to be defined for that as
well.
Just on the top of my head i'd like to propose (probably very incomplete):
QAbstractCalendarData
{
public:
QVariant data(int col) { return QVariant(); }
}
That class is intended to used per calendar day where the class is the
"wrapper" around an event, journal item, holiday or todo item. So you
will very likely get multiple instances of that class per day. As much
as you have events/jour.... you get the point.
How QAbstractCalendarData is then implemented on the KDE side is of later care.
>
> Cheers
> --
> Martin Klapetek | KDE Developer
>
> _______________________________________________
> Plasma-devel mailing list
> Plasma-devel at kde.org
> https://mail.kde.org/mailman/listinfo/plasma-devel
>
Pfew.. that's it for my very very long mail.
Thank you very much for your feedback. It allowed me to refine my
ideas a bit. Hopefully for the better :)
More information about the Plasma-devel
mailing list