Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F16569978
kacalendar.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
kacalendar.cpp
View Options
/*
* kacalendar.cpp - KAlarm kcal library calendar and event functions
* Program: kalarm
* Copyright © 2001-2010 by David Jarvie <djarvie@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include
"kacalendar.h"
#include
"kaevent.h"
#include
"version.h"
#include
<kglobal.h>
#include
<klocale.h>
#include
<kdebug.h>
#ifdef USE_AKONADI
#include
<kcalcore/event.h>
#include
<kcalcore/alarm.h>
#include
<kcalcore/memorycalendar.h>
#else
#include
<kcal/event.h>
#include
<kcal/alarm.h>
#include
<kcal/calendarlocal.h>
#endif
#include
<QMap>
#include
<QFile>
#include
<QFileInfo>
#include
<QTextStream>
#ifdef USE_AKONADI
using
namespace
KCalCore
;
#else
using
namespace
KCal
;
#endif
namespace
KAlarm
{
#ifdef USE_AKONADI
const
QLatin1String
MIME_BASE
(
"application/x-vnd.kde.alarm"
);
const
QLatin1String
MIME_ACTIVE
(
"application/x-vnd.kde.alarm.active"
);
const
QLatin1String
MIME_ARCHIVED
(
"application/x-vnd.kde.alarm.archived"
);
const
QLatin1String
MIME_TEMPLATE
(
"application/x-vnd.kde.alarm.template"
);
#endif
static
const
QByteArray
VERSION_PROPERTY
(
"VERSION"
);
// X-KDE-KALARM-VERSION VCALENDAR property
static
bool
isUTC
(
const
QString
&
localFile
);
/*=============================================================================
* Class: Calendar
*============================================================================*/
const
QByteArray
Calendar
::
APPNAME
(
"KALARM"
);
QByteArray
Calendar
::
mIcalProductId
;
bool
Calendar
::
mHaveKAlarmCatalog
=
false
;
void
Calendar
::
setProductId
(
const
QByteArray
&
progName
,
const
QByteArray
&
progVersion
)
{
mIcalProductId
=
QByteArray
(
"-//K Desktop Environment//NONSGML "
+
progName
+
" "
+
progVersion
+
"//EN"
);
}
QByteArray
Calendar
::
icalProductId
()
{
return
mIcalProductId
.
isEmpty
()
?
QByteArray
(
"-//K Desktop Environment//NONSGML //EN"
)
:
mIcalProductId
;
}
/******************************************************************************
* Check the version of KAlarm which wrote a calendar file, and convert it in
* memory to the current KAlarm format if possible. The storage file is not
* updated. The compatibility of the calendar format is indicated by the return
* value.
*/
#ifdef USE_AKONADI
int
Calendar
::
checkCompatibility
(
const
FileStorage
::
Ptr
&
fileStorage
,
QString
&
versionString
)
#else
int
Calendar
::
checkCompatibility
(
CalendarLocal
&
calendar
,
const
QString
&
localFile
,
QString
&
versionString
)
#endif
{
bool
version057_UTC
=
false
;
QString
subVersion
;
#ifdef USE_AKONADI
int
version
=
readKAlarmVersion
(
fileStorage
,
subVersion
,
versionString
);
#else
int
version
=
readKAlarmVersion
(
calendar
,
localFile
,
subVersion
,
versionString
);
#endif
if
(
!
version
)
return
0
;
// calendar is in the current KAlarm format
if
(
version
<
0
||
version
>
KAEvent
::
currentCalendarVersion
())
return
-1
;
// calendar was created by another program, or an unknown version of KAlarm
// Calendar was created by an earlier version of KAlarm.
// Convert it to the current format.
#ifdef USE_AKONADI
const
QString
localFile
=
fileStorage
->
fileName
();
#endif
if
(
version
==
KAlarm
::
Version
(
0
,
5
,
7
)
&&
!
localFile
.
isEmpty
())
{
// KAlarm version 0.5.7 - check whether times are stored in UTC, in which
// case it is the KDE 3.0.0 version, which needs adjustment of summer times.
version057_UTC
=
isUTC
(
localFile
);
kDebug
()
<<
"KAlarm version 0.5.7 ("
<<
(
version057_UTC
?
""
:
"non-"
)
<<
"UTC)"
;
}
else
kDebug
()
<<
"KAlarm version"
<<
version
;
// Convert events to current KAlarm format for when/if the calendar is saved
#ifdef USE_AKONADI
KAEvent
::
convertKCalEvents
(
fileStorage
->
calendar
(),
version
,
version057_UTC
);
#else
KAEvent
::
convertKCalEvents
(
calendar
,
version
,
version057_UTC
);
#endif
return
version
;
}
/******************************************************************************
* Return the KAlarm version which wrote the calendar which has been loaded.
* The format is, for example, 000507 for 0.5.7.
* Reply = 0 if the calendar was created by the current version of KAlarm
* = -1 if it was created by KAlarm pre-0.3.5, or another program
* = version number if created by another KAlarm version.
*/
#ifdef USE_AKONADI
int
Calendar
::
readKAlarmVersion
(
const
FileStorage
::
Ptr
&
fileStorage
,
QString
&
subVersion
,
QString
&
versionString
)
#else
int
Calendar
::
readKAlarmVersion
(
CalendarLocal
&
calendar
,
const
QString
&
localFile
,
QString
&
subVersion
,
QString
&
versionString
)
#endif
{
subVersion
.
clear
();
#ifdef USE_AKONADI
KCalCore
::
Calendar
::
Ptr
calendar
=
fileStorage
->
calendar
();
versionString
=
calendar
->
customProperty
(
APPNAME
,
VERSION_PROPERTY
);
#else
versionString
=
calendar
.
customProperty
(
APPNAME
,
VERSION_PROPERTY
);
#endif
if
(
versionString
.
isEmpty
())
{
// Pre-KAlarm 1.4 defined the KAlarm version number in the PRODID field.
// If another application has written to the file, this may not be present.
#ifdef USE_AKONADI
const
QString
prodid
=
calendar
->
productId
();
#else
const
QString
prodid
=
calendar
.
productId
();
#endif
if
(
prodid
.
isEmpty
())
{
// Check whether the calendar file is empty, in which case
// it can be written to freely.
#ifdef USE_AKONADI
QFileInfo
fi
(
fileStorage
->
fileName
());
#else
QFileInfo
fi
(
localFile
);
#endif
if
(
!
fi
.
size
())
return
0
;
}
// Find the KAlarm identifier
QString
progname
=
QLatin1String
(
" KAlarm "
);
int
i
=
prodid
.
indexOf
(
progname
,
0
,
Qt
::
CaseInsensitive
);
if
(
i
<
0
)
{
// Older versions used KAlarm's translated name in the product ID, which
// could have created problems using a calendar in different locales.
insertKAlarmCatalog
();
progname
=
QString
(
" "
)
+
i18n
(
"KAlarm"
)
+
' '
;
i
=
prodid
.
indexOf
(
progname
,
0
,
Qt
::
CaseInsensitive
);
if
(
i
<
0
)
return
-1
;
// calendar wasn't created by KAlarm
}
// Extract the KAlarm version string
versionString
=
prodid
.
mid
(
i
+
progname
.
length
()).
trimmed
();
i
=
versionString
.
indexOf
(
'/'
);
int
j
=
versionString
.
indexOf
(
' '
);
if
(
j
>=
0
&&
j
<
i
)
i
=
j
;
if
(
i
<=
0
)
return
-1
;
// missing version string
versionString
=
versionString
.
left
(
i
);
// 'versionString' now contains the KAlarm version string
}
if
(
versionString
==
KAEvent
::
currentCalendarVersionString
())
return
0
;
// the calendar is in the current KAlarm format
int
ver
=
KAlarm
::
getVersionNumber
(
versionString
,
&
subVersion
);
if
(
ver
==
KAEvent
::
currentCalendarVersion
())
return
0
;
// the calendar is in the current KAlarm format
return
KAlarm
::
getVersionNumber
(
versionString
,
&
subVersion
);
}
/******************************************************************************
* Access the KAlarm message translation catalog.
*/
void
Calendar
::
insertKAlarmCatalog
()
{
if
(
!
mHaveKAlarmCatalog
)
{
KGlobal
::
locale
()
->
insertCatalog
(
"kalarm"
);
mHaveKAlarmCatalog
=
true
;
}
}
/******************************************************************************
* Check whether the calendar file has its times stored as UTC times,
* indicating that it was written by the KDE 3.0.0 version of KAlarm 0.5.7.
* Reply = true if times are stored in UTC
* = false if the calendar is a vCalendar, times are not UTC, or any error occurred.
*/
bool
isUTC
(
const
QString
&
localFile
)
{
// Read the calendar file into a string
QFile
file
(
localFile
);
if
(
!
file
.
open
(
QIODevice
::
ReadOnly
))
return
false
;
QTextStream
ts
(
&
file
);
ts
.
setCodec
(
"ISO 8859-1"
);
QByteArray
text
=
ts
.
readAll
().
toLocal8Bit
();
file
.
close
();
// Extract the CREATED property for the first VEVENT from the calendar
const
QByteArray
BEGIN_VCALENDAR
(
"BEGIN:VCALENDAR"
);
const
QByteArray
BEGIN_VEVENT
(
"BEGIN:VEVENT"
);
const
QByteArray
CREATED
(
"CREATED:"
);
QList
<
QByteArray
>
lines
=
text
.
split
(
'\n'
);
for
(
int
i
=
0
,
end
=
lines
.
count
();
i
<
end
;
++
i
)
{
if
(
lines
[
i
].
startsWith
(
BEGIN_VCALENDAR
))
{
while
(
++
i
<
end
)
{
if
(
lines
[
i
].
startsWith
(
BEGIN_VEVENT
))
{
while
(
++
i
<
end
)
{
if
(
lines
[
i
].
startsWith
(
CREATED
))
return
lines
[
i
].
endsWith
(
'Z'
);
}
}
}
break
;
}
}
return
false
;
}
/*=============================================================================
* Class: KCalEvent
*============================================================================*/
// Struct to contain static strings, to allow use of K_GLOBAL_STATIC
// to delete them on program termination.
struct
StaticStrings
{
StaticStrings
()
:
STATUS_PROPERTY
(
"TYPE"
),
ACTIVE_STATUS
(
QLatin1String
(
"ACTIVE"
)),
TEMPLATE_STATUS
(
QLatin1String
(
"TEMPLATE"
)),
ARCHIVED_STATUS
(
QLatin1String
(
"ARCHIVED"
)),
DISPLAYING_STATUS
(
QLatin1String
(
"DISPLAYING"
)),
ARCHIVED_UID
(
QLatin1String
(
"-exp-"
)),
DISPLAYING_UID
(
QLatin1String
(
"-disp-"
)),
TEMPLATE_UID
(
QLatin1String
(
"-tmpl-"
))
{}
// Event custom properties.
// Note that all custom property names are prefixed with X-KDE-KALARM- in the calendar file.
const
QByteArray
STATUS_PROPERTY
;
// X-KDE-KALARM-TYPE property
const
QString
ACTIVE_STATUS
;
const
QString
TEMPLATE_STATUS
;
const
QString
ARCHIVED_STATUS
;
const
QString
DISPLAYING_STATUS
;
// Event ID identifiers
const
QString
ARCHIVED_UID
;
const
QString
DISPLAYING_UID
;
// Old KAlarm format identifiers
const
QString
TEMPLATE_UID
;
};
K_GLOBAL_STATIC
(
StaticStrings
,
staticStrings
)
typedef
QMap
<
QString
,
CalEvent
::
Type
>
PropertyMap
;
static
PropertyMap
properties
;
/******************************************************************************
* Convert a unique ID to indicate that the event is in a specified calendar file.
*/
QString
CalEvent
::
uid
(
const
QString
&
id
,
Type
status
)
{
QString
result
=
id
;
Type
oldType
;
int
i
,
len
;
if
((
i
=
result
.
indexOf
(
staticStrings
->
ARCHIVED_UID
))
>
0
)
{
oldType
=
ARCHIVED
;
len
=
staticStrings
->
ARCHIVED_UID
.
length
();
}
else
if
((
i
=
result
.
indexOf
(
staticStrings
->
DISPLAYING_UID
))
>
0
)
{
oldType
=
DISPLAYING
;
len
=
staticStrings
->
DISPLAYING_UID
.
length
();
}
else
{
oldType
=
ACTIVE
;
i
=
result
.
lastIndexOf
(
'-'
);
len
=
1
;
if
(
i
<
0
)
{
i
=
result
.
length
();
len
=
0
;
}
else
len
=
1
;
}
if
(
status
!=
oldType
&&
i
>
0
)
{
QString
part
;
switch
(
status
)
{
case
ARCHIVED
:
part
=
staticStrings
->
ARCHIVED_UID
;
break
;
case
DISPLAYING
:
part
=
staticStrings
->
DISPLAYING_UID
;
break
;
case
ACTIVE
:
case
TEMPLATE
:
case
EMPTY
:
default
:
part
=
QLatin1String
(
"-"
);
break
;
}
result
.
replace
(
i
,
len
,
part
);
}
return
result
;
}
/******************************************************************************
* Check an event to determine its type - active, archived, template or empty.
* The default type is active if it contains alarms and there is nothing to
* indicate otherwise.
* Note that the mere fact that all an event's alarms have passed does not make
* an event archived, since it may be that they have not yet been able to be
* triggered. They will be archived once KAlarm tries to handle them.
* Do not call this function for the displaying alarm calendar.
*/
#ifdef USE_AKONADI
CalEvent
::
Type
CalEvent
::
status
(
const
ConstEventPtr
&
event
,
QString
*
param
)
#else
CalEvent
::
Type
CalEvent
::
status
(
const
Event
*
event
,
QString
*
param
)
#endif
{
// Set up a static quick lookup for type strings
if
(
properties
.
isEmpty
())
{
properties
[
staticStrings
->
ACTIVE_STATUS
]
=
ACTIVE
;
properties
[
staticStrings
->
TEMPLATE_STATUS
]
=
TEMPLATE
;
properties
[
staticStrings
->
ARCHIVED_STATUS
]
=
ARCHIVED
;
properties
[
staticStrings
->
DISPLAYING_STATUS
]
=
DISPLAYING
;
}
if
(
param
)
param
->
clear
();
if
(
!
event
)
return
EMPTY
;
Alarm
::
List
alarms
=
event
->
alarms
();
if
(
alarms
.
isEmpty
())
return
EMPTY
;
const
QString
property
=
event
->
customProperty
(
Calendar
::
APPNAME
,
staticStrings
->
STATUS_PROPERTY
);
if
(
!
property
.
isEmpty
())
{
// There's a X-KDE-KALARM-TYPE property.
// It consists of the event type, plus an optional parameter.
PropertyMap
::
ConstIterator
it
=
properties
.
constFind
(
property
);
if
(
it
!=
properties
.
constEnd
())
return
it
.
value
();
int
i
=
property
.
indexOf
(
';'
);
if
(
i
<
0
)
return
EMPTY
;
it
=
properties
.
constFind
(
property
.
left
(
i
));
if
(
it
==
properties
.
constEnd
())
return
EMPTY
;
if
(
param
)
*
param
=
property
.
mid
(
i
+
1
);
return
it
.
value
();
}
// The event either wasn't written by KAlarm, or was written by a pre-2.0 version.
// Check first for an old KAlarm format, which indicated the event type in its UID.
QString
uid
=
event
->
uid
();
if
(
uid
.
indexOf
(
staticStrings
->
ARCHIVED_UID
)
>
0
)
return
ARCHIVED
;
if
(
uid
.
indexOf
(
staticStrings
->
TEMPLATE_UID
)
>
0
)
return
TEMPLATE
;
// Otherwise, assume it's an active alarm
return
ACTIVE
;
}
/******************************************************************************
* Set the event's type - active, archived, template, etc.
* If a parameter is supplied, it will be appended as a second parameter to the
* custom property.
*/
#ifdef USE_AKONADI
void
CalEvent
::
setStatus
(
const
Event
::
Ptr
&
event
,
CalEvent
::
Type
status
,
const
QString
&
param
)
#else
void
CalEvent
::
setStatus
(
Event
*
event
,
CalEvent
::
Type
status
,
const
QString
&
param
)
#endif
{
if
(
!
event
)
return
;
QString
text
;
switch
(
status
)
{
case
ACTIVE
:
text
=
staticStrings
->
ACTIVE_STATUS
;
break
;
case
TEMPLATE
:
text
=
staticStrings
->
TEMPLATE_STATUS
;
break
;
case
ARCHIVED
:
text
=
staticStrings
->
ARCHIVED_STATUS
;
break
;
case
DISPLAYING
:
text
=
staticStrings
->
DISPLAYING_STATUS
;
break
;
default
:
event
->
removeCustomProperty
(
Calendar
::
APPNAME
,
staticStrings
->
STATUS_PROPERTY
);
return
;
}
if
(
!
param
.
isEmpty
())
text
+=
';'
+
param
;
event
->
setCustomProperty
(
Calendar
::
APPNAME
,
staticStrings
->
STATUS_PROPERTY
,
text
);
}
#ifdef USE_AKONADI
CalEvent
::
Type
CalEvent
::
type
(
const
QString
&
mimeType
)
{
if
(
mimeType
==
KAlarm
::
MIME_ACTIVE
)
return
ACTIVE
;
if
(
mimeType
==
KAlarm
::
MIME_ARCHIVED
)
return
ARCHIVED
;
if
(
mimeType
==
KAlarm
::
MIME_TEMPLATE
)
return
TEMPLATE
;
return
EMPTY
;
}
CalEvent
::
Types
CalEvent
::
types
(
const
QStringList
&
mimeTypes
)
{
Types
types
=
0
;
foreach
(
const
QString
&
type
,
mimeTypes
)
{
if
(
type
==
KAlarm
::
MIME_ACTIVE
)
types
|=
ACTIVE
;
if
(
type
==
KAlarm
::
MIME_ARCHIVED
)
types
|=
ARCHIVED
;
if
(
type
==
KAlarm
::
MIME_TEMPLATE
)
types
|=
TEMPLATE
;
}
return
types
;
}
QString
CalEvent
::
mimeType
(
CalEvent
::
Type
type
)
{
switch
(
type
)
{
case
ACTIVE
:
return
KAlarm
::
MIME_ACTIVE
;
case
ARCHIVED
:
return
KAlarm
::
MIME_ARCHIVED
;
case
TEMPLATE
:
return
KAlarm
::
MIME_TEMPLATE
;
default
:
return
QString
();
}
}
QStringList
CalEvent
::
mimeTypes
(
CalEvent
::
Types
types
)
{
QStringList
mimes
;
for
(
int
i
=
1
;
types
;
i
<<=
1
)
{
if
(
types
&
i
)
{
mimes
+=
mimeType
(
CalEvent
::
Type
(
i
));
types
&=
~
i
;
}
}
return
mimes
;
}
#endif
}
// namespace KAlarm
// vim: et sw=4:
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Fri, Nov 1, 8:58 AM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
10075392
Default Alt Text
kacalendar.cpp (15 KB)
Attached To
Mode
rKP kdepim
Attached
Detach File
Event Timeline
Log In to Comment