2
import Ubuntu.Components 0.1
3
import Ubuntu.Components.Popups 0.1
4
import Ubuntu.Components.ListItems 0.1 as ListItem
6
import "dataService.js" as DataService
10
property var defaultDate;
11
property alias errorText: errorPopupDialog.text;
12
property var startDate: new Date()
13
property var endDate: new Date()
23
ListItem.Header { text: i18n.tr("Create event") }
25
highlightWhenPressed: false
27
objectName: "newEventName"
29
placeholderText: i18n.tr("Add event name")
2
* Copyright (C) 2013-2014 Canonical Ltd
4
* This file is part of Ubuntu Calendar App
6
* Ubuntu Calendar App is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 3 as
8
* published by the Free Software Foundation.
10
* Ubuntu Calendar App is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20
import QtOrganizer 5.0
21
import Ubuntu.Components 1.1
22
import Ubuntu.Components.Popups 1.0
23
import Ubuntu.Components.ListItems 1.0 as ListItem
24
import Ubuntu.Components.Themes.Ambiance 1.0
25
import Ubuntu.Components.Pickers 1.0
26
import QtOrganizer 5.0
27
import "Defines.js" as Defines
31
objectName: 'newEventPage'
35
property var event:null;
36
property var rule :null;
39
property var startDate;
42
property alias scrollY: flickable.contentY
43
property bool isEdit: false
45
signal eventAdded(var event);
48
startDateTimeInput.dateTime = startDate;
49
adjustEndDateToStartDate()
53
endDateTimeInput.dateTime = endDate;
56
head.actions: Action {
60
enabled: !!titleEdit.text.trim()
61
onTriggered: saveToQtPim();
64
Component.onCompleted: {
65
//If current date is setted by an argument we don't have to change it.
66
if(typeof(date) === 'undefined'){
70
if( typeof(date) == 'undefined' || (date.getHours() == 0 && date.getMinutes() == 0) ) {
71
var newDate = new Date();
72
date.setHours(newDate.getHours(), newDate.getMinutes());
75
// If startDate is setted by argument we have to not change it
76
//Set the nearest current time.
77
if (typeof(startDate) === 'undefined')
78
startDate = new Date(root.roundDate(date))
80
// If endDate is setted by argument we have to not change it
81
if (typeof(endDate) === 'undefined') {
82
endDate = new Date(root.roundDate(date))
83
endDate.setMinutes(endDate.getMinutes() + 30)
84
endTimeInput.text = Qt.formatDateTime(endDate, Qt.locale().timeFormat(Locale.ShortFormat));
98
function selectCalendar(collectionId) {
100
for(var i=0; i < calendarsOption.model.length; ++i){
101
if(calendarsOption.model[i].collectionId === collectionId){
106
calendarsOption.selectedIndex = index
107
internal.collectionId = collectionId;
110
//Data for Add events
111
function addEvent() {
112
event = Qt.createQmlObject("import QtOrganizer 5.0; Event { }", Qt.application,"NewEvent.qml");
113
//Create fresh Recurrence Object.
114
rule = Qt.createQmlObject("import QtOrganizer 5.0; RecurrenceRule {}", event.recurrence,"EventRepetition.qml");
115
selectCalendar(model.defaultCollection().collectionId);
119
function editEvent(e) {
120
//If there is a ReccruenceRule use that , else create fresh Recurrence Object.
121
if(e.itemType === Type.Event){
122
rule = (e.recurrence.recurrenceRules[0] === undefined || e.recurrence.recurrenceRules[0] === null) ?
123
Qt.createQmlObject("import QtOrganizer 5.0; RecurrenceRule {}", event.recurrence,"EventRepetition.qml")
124
: e.recurrence.recurrenceRules[0];
126
startDate =new Date(e.startDateTime);
127
endDate = new Date(e.endDateTime);
130
titleEdit.text = e.displayLabel;
133
allDayEventCheckbox.checked =true;
137
locationEdit.text = e.location;
140
if( e.description ) {
141
messageEdit.text = e.description;
144
allDayEventCheckbox.checked = e.allDay;
147
if( e.itemType === Type.Event ) {
149
for( var j = 0 ; j < e.attendees.length ; ++j ) {
150
contactList.array.push(e.attendees[j]);
151
contactModel.append(e.attendees[j]);
155
var reminder = e.detail( Detail.VisualReminder);
157
visualReminder.secondsBeforeStart = reminder.secondsBeforeStart;
159
visualReminder.secondsBeforeStart = reminderModel.get(0).value;
162
selectCalendar(e.collectionId);
164
//Save the new or Existing event
165
function saveToQtPim() {
166
internal.clearFocus()
167
if ( startDate >= endDate && !allDayEventCheckbox.checked) {
168
PopupUtils.open(errorDlgComponent,root,{"text":i18n.tr("End time can't be before start time")});
170
var newCollection = calendarsOption.model[calendarsOption.selectedIndex].collectionId;
171
if( internal.collectionId !== newCollection ){
172
//collection change to event is not suported
173
//to change collection we create new event with same data with different collection
174
//and remove old event
175
var eventId = event.itemId;
176
model.removeItem(event.itemId)
177
event = Qt.createQmlObject("import QtOrganizer 5.0; Event {}", Qt.application,"NewEvent.qml");
180
event.startDateTime = startDate;
181
event.endDateTime = endDate;
182
event.displayLabel = titleEdit.text;
183
event.description = messageEdit.text;
184
event.location = locationEdit.text
186
event.allDay = allDayEventCheckbox.checked;
188
if( event.itemType === Type.Event ) {
189
event.attendees = []; // if Edit remove all attendes & add them again if any
191
for(var i=0; i < contactList.array.length ; ++i) {
192
var contact = contactList.array[i]
193
contacts.push(contact);
195
event.attendees = contacts;
198
//Set the Rule object to an event
199
if(rule !== null && rule !== undefined) {
200
event.recurrence.recurrenceRules = [rule]
203
//remove old reminder value
204
var oldVisualReminder = event.detail(Detail.VisualReminder);
205
if(oldVisualReminder) {
206
event.removeDetail(oldVisualReminder);
209
var oldAudibleReminder = event.detail(Detail.AudibleReminder);
210
if(oldAudibleReminder) {
211
event.removeDetail(oldAudibleReminder);
213
if(visualReminder.secondsBeforeStart >= 0) {
214
event.setDetail(visualReminder);
215
event.setDetail(audibleReminder);
217
event.collectionId = calendarsOption.model[calendarsOption.selectedIndex].collectionId;
218
model.saveItem(event);
220
root.eventAdded(event);
231
function getDaysOfWeek(){
233
switch(recurrenceOption.selectedIndex){
235
daysOfWeek = Qt.locale().weekDays;
238
daysOfWeek = [Qt.Monday,Qt.Wednesday,Qt.Friday];
241
daysOfWeek = [Qt.Tuesday,Qt.Thursday];
244
daysOfWeek = internal.weekDays.length === 0 ? [date.getDay()] : internal.weekDays;
250
// Calucate default hour and minute for start and end time on event
251
function roundDate(date) {
252
var tempDate = new Date(date)
253
tempDate.setHours(date.getHours(), date.getMinutes(), 0, 0);
254
if(tempDate.getMinutes() < 30)
255
return tempDate.setMinutes(30)
256
tempDate.setMinutes(0)
257
return tempDate.setHours(tempDate.getHours() + 1)
260
function adjustEndDateToStartDate() {
261
// set time forward to one hour
262
var time_forward = 3600000;
263
endDate = new Date( startDate.getTime() + time_forward );
266
ScrollAnimation{id:scrollAnimation}
268
function scrollOnExpand(Self,Container,Target,Margin,Visible)
270
// Self is needed for "onXxxxxChange" triggers. OnExpansionCompleted however can just write "true".
271
// Container is the item which encapsulates everything, such as a column.
272
// Target is the Flickable id you wish to scroll
273
// Margin is the space between the bottom of the screen and the bottom of the item you are scrolling to.
274
// Visible is needed if there is anything that appears under the item you are scrolling to.
275
if (Self === false){return}
276
var v = units.gu(Margin)
277
for (var i in Visible){if(Visible[i].visible === true){v+=Visible[i].height};}
279
scrollAnimation.target = Target
280
scrollAnimation.to = Container.height-height - v
281
scrollAnimation.start()
285
height: parent.height
287
title: isEdit ? i18n.tr("Edit Event"):i18n.tr("New Event")
289
Keys.onEscapePressed: {
294
id: errorDlgComponent
297
title: i18n.tr("Error")
300
onClicked: PopupUtils.close(dialog)
312
property var activeItem: null
314
function makeMeVisible(item) {
320
var position = flickable.contentItem.mapFromItem(item, 0, 0);
322
// check if the item is already visible
323
var bottomY = flickable.contentY + flickable.height
324
var itemBottom = position.y + item.height
325
if (position.y >= flickable.contentY && itemBottom <= bottomY) {
329
// if it is not, try to scroll and make it visible
330
var targetY = position.y + item.height - flickable.height
331
if (targetY >= 0 && position.y) {
332
flickable.contentY = targetY;
333
} else if (position.y < flickable.contentY) {
334
// if it is hidden at the top, also show it
335
flickable.contentY = position.y;
337
flickable.returnToBounds()
342
contentHeight: column.height + units.gu(10)
41
347
width: parent.width
53
height: dateLabel.height
56
text: Qt.formatDateTime(defaultDate, "ddd, d MMMM yyyy");
74
height: startTimeItem.height
78
anchors.left: timeContainer.left
81
objectName: "startTimeInput"
83
text: Qt.formatDateTime(startDate,"hh:mm")
90
var popupObj = PopupUtils.open(timePicker);
91
popupObj.accepted.connect(function(startHour, startMinute) {
92
var newDate = startDate;
93
newDate.setHours(startHour, startMinute);
104
horizontalCenter: parent.horizontalCenter;
105
verticalCenter: startTimeItem.verticalCenter;
111
highlightWhenPressed: false
112
anchors.right: timeContainer.right
115
objectName: "endTimeInput"
117
text: Qt.formatDateTime(endDate,"hh:mm")
123
internal.clearFocus()
124
var popupObj = PopupUtils.open(timePicker);
125
popupObj.accepted.connect(function(endHour, endMinute) {
126
var newDate = endDate;
127
newDate.setHours(endHour, endMinute);
137
ListItem.Header { text: i18n.tr("Location & People") }
139
highlightWhenPressed: false
141
objectName: "eventLocationInput"
143
placeholderText: i18n.tr("Add Location")
152
highlightWhenPressed: false
154
objectName: "eventPeopleInput"
156
placeholderText: i18n.tr("Invite People")
165
highlightWhenPressed: false
168
title: i18n.tr("Error")
172
onClicked: PopupUtils.close(errorPopupDialog)
176
objectName: "eventSaveButton"
177
text: i18n.tr("Save")
184
internal.clearFocus()
188
if (startDate > endDate)
191
startDate.setDate(defaultDate.getDate());
192
endDate.setDate(defaultDate.getDate());
195
title: titleEdit.text,
197
startTime: startDate.getTime(),
198
endTime: endDate.getTime()
202
DataService.addEvent(event);
203
PopupUtils.close(popover);
350
id: startDateTimeInput
351
header: i18n.tr("From")
352
showTimePicker: !allDayEventCheckbox.checked
358
startDate = dateTime;
364
header: i18n.tr("To")
365
showTimePicker: !allDayEventCheckbox.checked
381
text: i18n.tr("All day event")
384
objectName: "allDayEventCheckbox"
385
id: allDayEventCheckbox
390
ListItem.ThinDivider {}
397
text: i18n.tr("Event Details")
402
objectName: "newEventName"
410
placeholderText: i18n.tr("Event Name")
415
objectName: "eventDescriptionInput"
423
placeholderText: i18n.tr("Description")
428
objectName: "eventLocationInput"
436
placeholderText: i18n.tr("Location")
445
text: i18n.tr("Calendar")
450
objectName: "calendarsOption"
458
containerHeight: itemHeight * 4
459
model: root.model.getCollections();
461
delegate: OptionSelectorDelegate{
467
height: parent.height - units.gu(2)
468
color: modelData.color
469
anchors.right: parent.right
470
anchors.rightMargin: units.gu(2)
471
anchors.verticalCenter: parent.verticalCenter
474
onExpandedChanged: Qt.inputMethod.hide();
483
text: i18n.tr("Guests")
487
text: i18n.tr("Add Guest")
488
objectName: "addGuestButton"
497
var popup = PopupUtils.open(Qt.resolvedUrl("ContactChoicePopup.qml"), contactList);
498
popup.contactSelected.connect( function(contact) {
499
var t = internal.contactToAttendee(contact);
500
if( !internal.isContactAlreadyAdded(contact) ) {
501
contactModel.append(t);
502
contactList.array.push(t);
515
height: contactList.height
519
objectName: "guestList"
525
property var array: []
533
delegate: ListItem.Standard {
534
objectName: "eventGuest%1".arg(index)
539
contactList.array.splice(index, 1)
540
contactModel.remove(index)
547
ListItem.ThinDivider {
548
visible: event.itemType === Type.Event
555
objectName :"thisHappens"
563
visible: event.itemType === Type.Event
564
text: i18n.tr("Repeats")
565
subText: event.itemType === Type.Event ? eventUtils.getRecurrenceString(rule) : ""
566
onClicked: pageStack.push(Qt.resolvedUrl("EventRepetition.qml"),{"rule": rule,"date":date,"isEdit":isEdit});
569
ListItem.ThinDivider {
570
visible: event.itemType === Type.Event
575
objectName : "eventReminder"
582
text: i18n.tr("Reminder")
589
if(visualReminder.secondsBeforeStart !== -1) {
590
for(var i=0; i<reminderModel.count; i++) {
591
if(visualReminder.secondsBeforeStart === reminderModel.get(i).value)
592
return reminderModel.get(i).label
205
errorText = i18n.tr("End time can't be before start time");
206
errorPopupDialog.show();
595
reminderModel.get(0).label
599
onClicked: pageStack.push(Qt.resolvedUrl("EventReminder.qml"),
600
{"visualReminder": visualReminder,
601
"audibleReminder": audibleReminder,
602
"reminderModel": reminderModel,
603
"eventTitle": titleEdit.text})
606
ListItem.ThinDivider {}
609
// used to keep the field visible when the keyboard appear or dismiss
614
if (flickable.activeItem) {
615
flickable.makeMeVisible(flickable.activeItem)
622
property var collectionId;
218
624
function clearFocus() {
219
625
Qt.inputMethod.hide()
220
626
titleEdit.focus = false
221
627
locationEdit.focus = false
222
personEdit.focus = false
628
startDateTimeInput.clearFocus();
629
endDateTimeInput.clearFocus();
630
messageEdit.focus = false
633
function isContactAlreadyAdded(contact) {
634
for(var i=0; i < contactList.array.length ; ++i) {
635
var attendee = contactList.array[i];
636
if( attendee.attendeeId === contact.contactId) {
643
function contactToAttendee(contact) {
644
var attendee = Qt.createQmlObject("import QtOrganizer 5.0; EventAttendee{}", event, "NewEvent.qml");
645
attendee.name = contact.displayLabel.label
646
attendee.emailAddress = contact.email.emailAddress;
647
attendee.attendeeId = contact.contactId;