41 #include <kcmdlineargs.h>
42 #include <kaboutdata.h>
46 #include <kstandarddirs.h>
49 #include <KApplication>
51 #include <KCalCore/CalFormat>
53 #include <QtCore/QDateTime>
54 #include <QtCore/QFile>
55 #include <QtCore/QFileInfo>
56 #include <QtCore/QEventLoop>
62 using namespace KCalCore;
66 static const char progName[] =
"konsolekalendar";
67 static const char progDisplay[] =
"KonsoleKalendar";
68 #include "kdepim-version.h"
69 static const char progVersion[] = KDEPIM_VERSION;
70 static const char progDesc[] =
"A command line interface to KDE calendars";
71 static const char progURL[] =
"pim.kde.org/components/konsolekalendar.php";
73 int main(
int argc,
char *argv[] )
80 KAboutData::License_GPL,
81 ki18n(
"(c) 2002-2009, Tuukka Pasanen and Allen Winter" ),
88 ki18n(
"Allen Winter" ),
89 ki18n(
"Maintainer" ),
94 ki18n(
"Tuukka Pasanen" ),
96 "illuusio@mailcity.com",
100 KCmdLineArgs::init( argc, argv, &aboutData, KCmdLineArgs::CmdLineArgNone );
102 KCmdLineOptions options;
103 options.add(
"verbose",
104 ki18n(
"Print helpful runtime messages" ) );
105 options.add(
"dry-run",
106 ki18n(
"Print what would have been done, but do not execute" ) );
107 options.add(
"allow-gui",
108 ki18n(
"Allow calendars which might need an interactive user interface" ) );
110 ki18n(
"Incidence types (these options can be combined):" ) );
111 options.add(
"event",
112 ki18n(
" Operate for Events only (Default)" ) );
114 ki18n(
" Operate for To-dos only [NOT WORKING YET]" ) );
115 options.add(
"journal",
116 ki18n(
" Operate for Journals only [NOT WORKING YET]" ) );
118 ki18n(
"Major operation modes:" ) );
120 ki18n(
" Print incidences in specified export format" ) );
122 ki18n(
" Insert an incidence into the calendar" ) );
123 options.add(
"change",
124 ki18n(
" Modify an existing incidence" ) );
125 options.add(
"delete",
126 ki18n(
" Remove an existing incidence" ) );
127 options.add(
"create",
128 ki18n(
" Create new calendar file if one does not exist" ) );
129 options.add(
"import <import-file>",
130 ki18n(
" Import this calendar to main calendar" ) );
131 options.add(
"list-calendars",
132 ki18n(
" List available calendars" ) );
134 ki18n(
"Operation modifiers:" ) );
136 ki18n(
" View all calendar entries, ignoring date/time options" ) );
138 ki18n(
" View next activity in calendar" ) );
139 options.add(
"show-next <days>",
140 ki18n(
" From start date show next # days' activities" ) );
141 options.add(
"uid <uid>",
142 ki18n(
" Incidence Unique-string identifier" ) );
143 options.add(
"date <start-date>",
144 ki18n(
" Start from this day [YYYY-MM-DD]" ) );
145 options.add(
"time <start-time>",
146 ki18n(
" Start from this time [HH:MM:SS]" ) );
147 options.add(
"end-date <end-date>",
148 ki18n(
" End at this day [YYYY-MM-DD]" ) );
149 options.add(
"end-time <end-time>",
150 ki18n(
" End at this time [HH:MM:SS]" ) );
151 options.add(
"epoch-start <epoch-time>",
152 ki18n(
" Start from this time [secs since epoch]" ) );
153 options.add(
"epoch-end <epoch-time>",
154 ki18n(
" End at this time [secs since epoch]" ) );
155 options.add(
"summary <summary>",
156 ki18n(
" Add summary to incidence (for add/change modes)" ) );
157 options.add(
"description <description>",
158 ki18n(
"Add description to incidence (for add/change modes)" ) );
159 options.add(
"location <location>",
160 ki18n(
" Add location to incidence (for add/change modes)" ) );
161 options.add(
"calendar <calendar id>",
162 ki18n(
" Calendar to use when creating a new incidence" ) );
164 ki18n(
"Export options:" ) );
165 options.add(
"export-type <export-type>",
166 ki18n(
"Export file type (Default: text)" ) );
167 options.add(
"export-file <export-file>",
168 ki18n(
"Export to file (Default: stdout)" ) );
169 options.add(
"export-list",
170 ki18n(
" Print list of export types supported and exit" ) );
173 " konsolekalendar --view\n"
174 " konsolekalendar --list-calendars\n"
175 " konsolekalendar --add --collection 42 --date 2003-06-04 "
176 "--time 10:00 --end-time 12:00 \\\n"
177 " --summary \"Doctor Visit\" "
178 "--description \"Get My Head Examined\"\n"
179 " konsolekalendar --delete --uid KOrganizer-1740326.803" ) );
181 ki18n(
"For more information visit the program home page at:\n"
182 " http://pim.kde.org/components/konsolekalendar.php" ) );
183 KCmdLineArgs::addCmdLineOptions( options );
185 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
189 args->isSet(
"allow-gui" )
194 QTime starttime( 7, 0 );
198 QTime endtime( 17, 0 );
207 bool importFile =
false;
216 if ( args->isSet(
"verbose" ) ) {
220 if ( args->isSet(
"dry-run" ) ) {
224 if ( args->isSet(
"allow-gui" ) ) {
231 if ( args->isSet(
"export-list" ) ) {
233 cout << i18n(
"%1 supports these export formats:",
236 cout << i18nc(
"the default export format",
" %1 [Default]",
239 cout << i18nc(
"short text export",
" %1 (like %2, but more compact)",
242 cout << i18nc(
"HTML export",
" %1",
245 cout << i18nc(
"HTMLmonth export",
" %1 (like %2, but in a month view)",
248 cout << i18nc(
"comma-separated values export",
" %1 (Comma-Separated Values)",
258 if ( args->isSet(
"event" ) ) {
260 kDebug() <<
"main | parse options | use Events";
262 if ( args->isSet(
"todo" ) ) {
264 kDebug() <<
"main | parse options | use To-dos";
265 cout << i18n(
"Sorry, To-dos are not working yet." ).toLocal8Bit().data()
269 if ( args->isSet(
"journal" ) ) {
271 kDebug() <<
"main | parse options | use Journals";
272 cout << i18n(
"Sorry, Journals are not working yet." ).toLocal8Bit().data()
277 if ( !args->isSet(
"event" ) &&
278 !args->isSet(
"todo" ) &&
279 !args->isSet(
"journal" ) ) {
281 kDebug() <<
"main | parse options | use Events (Default)";
288 if ( args->isSet(
"export-type" ) ) {
289 option = args->getOption(
"export-type" );
292 kDebug() <<
"main | export-type | Export to HTML";
295 kDebug() <<
"main | export-type | Export to HTML by Month";
298 kDebug() <<
"main | export-type | Export to CSV";
301 kDebug() <<
"main | export-type | Export to TEXT (default)";
304 kDebug() <<
"main | export-type | Export to TEXT-SHORT";
307 cout << i18n(
"Invalid Export Type Specified: %1", option ).toLocal8Bit().data()
316 if ( args->isSet(
"export-file" ) ) {
317 option = args->getOption(
"export-file" );
319 kDebug() <<
"main | parse options |"
321 <<
"(" << option <<
")";
329 if ( args->isSet(
"view" ) ) {
332 kDebug() <<
"main | parse options |"
333 <<
"Mode: (Print incidences)";
339 if ( args->isSet(
"add" ) ) {
343 kDebug() <<
"main | parse options |"
344 <<
"Mode: (Add incidence)";
350 if ( args->isSet(
"change" ) ) {
354 kDebug() <<
"main | parse options |"
355 <<
"Mode: (Change incidence)";
361 if ( args->isSet(
"delete" ) ) {
365 kDebug() <<
"main | parse options |"
366 <<
"Mode: (Delete incidence)";
372 if ( args->isSet(
"create" ) ) {
376 kDebug() <<
"main | parse options |"
377 <<
"Calendar File: (Create)";
383 if ( args->isSet(
"summary" ) ) {
384 option = args->getOption(
"summary" );
386 kDebug() <<
"main | parse options |"
388 <<
"(" << option <<
")";
396 if ( args->isSet(
"description" ) ) {
397 option = args->getOption(
"description" );
399 kDebug() <<
"main | parse options |"
401 <<
"(" << option <<
")";
406 if ( args->isSet(
"calendar" ) ) {
407 option = args->getOption(
"calendar" );
409 int colId = option.
toInt(&ok);
417 if ( args->isSet(
"location" ) ) {
418 option = args->getOption(
"location" );
420 kDebug() <<
"main | parse options |"
422 <<
"(" << option <<
")";
430 if ( args->isSet(
"next" ) ) {
431 kDebug() <<
"main | parse options |"
432 <<
"Show next incidence only";
440 if ( args->isSet(
"uid" ) ) {
441 option = args->getOption(
"uid" );
443 kDebug() <<
"main | parse options |"
445 <<
"(" << option <<
")";
447 variables.
setUID( option );
453 if ( args->isSet(
"date" ) ) {
454 option = args->getOption(
"date" );
456 kDebug() <<
"main | parse options |"
457 <<
"Start date before conversion:"
458 <<
"(" << option <<
")";
461 if ( !startdate.isValid() ) {
462 cout << i18n(
"Invalid Start Date Specified: %1",
463 option ).toLocal8Bit().data()
467 kDebug() <<
"main | parse options |"
468 <<
"Start date after conversion:"
469 <<
"(" << startdate.toString() <<
")";
475 if ( args->isSet(
"time" ) ) {
476 option = args->getOption(
"time" );
478 kDebug() <<
"main | parse options |"
479 <<
"Start time before conversion :"
480 <<
"(" << option <<
")";
488 if ( !starttime.isValid() ) {
489 cout << i18n(
"Invalid Start Time Specified: %1", option ).toLocal8Bit().data()
493 kDebug() <<
"main | parse options |"
494 <<
"Start time after conversion:"
495 <<
"(" << starttime.toString() <<
")";
498 kDebug() <<
"main | parse options |"
499 <<
"Floating event time specified";
506 if ( args->isSet(
"end-date" ) ) {
507 option = args->getOption(
"end-date" );
509 kDebug() <<
"main | parse options |"
510 <<
"End date before conversion:"
511 <<
"(" << option <<
")";
515 cout << i18n(
"Invalid End Date Specified: %1",
516 option ).toLocal8Bit().data()
520 kDebug() <<
"main | parse options |"
521 <<
"End date after conversion:"
522 <<
"(" << enddate.
toString() <<
")";
528 if ( args->isSet(
"show-next" ) ) {
531 option = args->getOption(
"show-next" );
532 kDebug() <<
"main | parse options |"
533 <<
"Show" << option <<
"days ahead";
537 cout << i18n(
"Invalid Date Count Specified: %1", option ).toLocal8Bit().data()
544 kDebug() <<
"main | parse options |"
545 <<
"End date after conversion:"
546 <<
"(" << enddate.
toString() <<
")";
552 if ( args->isSet(
"end-time" ) ) {
553 option = args->getOption(
"end-time" );
555 kDebug() <<
"main | parse options |"
556 <<
"End time before conversion:"
557 <<
"(" << option <<
")";
565 if ( !endtime.isValid() ) {
566 cout << i18n(
"Invalid End Time Specified: %1", option ).toLocal8Bit().data()
571 kDebug() <<
"main | parse options |"
572 <<
"End time after conversion:"
573 <<
"(" << endtime.toString() <<
")";
576 kDebug() <<
"main | parse options |"
577 <<
"Floating event time specified";
584 time_t epochstart = 0;
585 if ( args->isSet(
"epoch-start" ) ) {
586 option = args->getOption(
"epoch-start" );
588 kDebug() <<
"main | parse options |"
590 <<
"(" << option <<
")";
592 epochstart = ( time_t ) option.
toULong( 0, 10 );
599 if ( args->isSet(
"epoch-end" ) ) {
600 option = args->getOption(
"epoch-end" );
602 kDebug() <<
"main | parse options |"
604 <<
"(" << option <<
")";
606 epochend = ( time_t ) option.
toULong( 0, 10 );
609 if ( args->isSet(
"all" ) ) {
612 variables.
setAll(
false );
615 if ( args->isSet(
"import" ) ) {
618 option = args->getOption(
"import" );
621 kDebug() <<
"main | parse options |"
622 <<
"importing file from:"
623 <<
"(" << option <<
")";
628 if (args->isSet(
"list-calendars")) {
634 Akonadi::FetchJobCalendar::Ptr calendar = Akonadi::FetchJobCalendar::Ptr(
new Akonadi::FetchJobCalendar() );
636 kDebug() <<
"Starting to load calendar";
640 kDebug() <<
"Calendar loaded in" << t.
elapsed() <<
"ms; success=" << calendar->isLoaded() <<
"; num incidences=" << calendar->incidences().count();
642 if ( !args->isSet(
"import" ) ) {
652 if ( !args->isSet(
"end-date" ) && !args->isSet(
"show-next" ) &&
653 args->isSet(
"date" ) ) {
655 kDebug() <<
"main | datetimestamp |"
656 <<
"setting enddate to startdate";
657 }
else if ( args->isSet(
"end-date" ) && !args->isSet(
"date" ) ) {
659 kDebug() <<
"main | datetimestamp |"
660 <<
"setting startdate to enddate";
668 if ( !args->isSet(
"end-time" ) && !args->isSet(
"epoch-end" ) ) {
669 if ( args->isSet(
"time" ) ) {
670 endtime = starttime.addSecs( 60 * 60 );
671 kDebug() <<
"main | datetimestamp |"
672 <<
"setting endtime 1 hour after starttime";
673 }
else if ( args->isSet(
"epoch-start" ) ) {
675 enddatetime = startdatetime.
addSecs( 60 * 60 );
676 kDebug() <<
"main | datetimestamp |"
677 <<
"setting endtime 1 hour after epochstart";
684 if ( !args->isSet(
"time" ) && !args->isSet(
"epoch-start" ) ) {
685 if ( args->isSet(
"end-time" ) ) {
686 starttime = endtime.
addSecs( -60 * 60 );
687 kDebug() <<
"main | datetimestamp |"
688 <<
"setting starttime 1 hour before endtime";
689 }
else if ( args->isSet(
"epoch-end" ) ) {
691 startdatetime = enddatetime.
addSecs( -60 * 60 );
692 kDebug() <<
"main | datetimestamp |"
693 <<
"setting starttime 1 before after epochend";
699 if ( !args->isSet(
"time" ) && !args->isSet(
"epoch-start" ) &&
700 !args->isSet(
"end-time" ) && !args->isSet(
"epoch-end" ) ) {
702 startdatetime =
QDateTime( startdate, starttime );
703 kDebug() <<
"main | datetimestamp |"
704 <<
"setting startdatetime from"
705 <<
"default startdate (today) and starttime";
707 enddatetime =
QDateTime( enddate, endtime );
708 kDebug() <<
"main | datetimestamp |"
709 <<
"setting enddatetime from"
710 <<
"default enddate (today) and endtime";
714 if ( startdatetime.
isNull() ) {
715 startdatetime =
QDateTime( startdate, starttime );
716 kDebug() <<
"main | datetimestamp |"
717 <<
"setting startdatetime from startdate and starttime";
719 if ( enddatetime.
isNull() ) {
720 enddatetime =
QDateTime( enddate, endtime );
721 kDebug() <<
"main | datetimestamp |"
722 <<
"setting enddatetime from enddate and endtime";
728 if ( !args->isSet(
"time" ) && !args->isSet(
"end-time" ) &&
729 !args->isSet(
"epoch-start" ) && !args->isSet(
"epoch-end" ) ) {
731 kDebug() <<
"main | floatingcheck |"
732 <<
"turn-on floating event";
743 if ( args->isSet(
"time" ) || args->isSet(
"epoch-start" ) ||
744 args->isSet(
"end-time" ) || args->isSet(
"epoch-end" ) ) {
751 kDebug() <<
"main | datetimestamp | StartDate="
752 << startdatetime.
toString( Qt::TextDate );
753 kDebug() <<
"main | datetimestamp | EndDate="
754 << enddatetime.
toString( Qt::TextDate );
761 if ( create + view + add + change + del > 1 ) {
762 cout << i18n(
"Only 1 operation mode "
763 "(view, add, change, delete, create) "
769 if ( startdatetime > enddatetime ) {
770 cout << i18n(
"Ending Date/Time occurs before the Starting Date/Time" ).toLocal8Bit().data()
791 cout << i18n(
"Calendar %1 successfully imported",
796 cout << i18n(
"Unable to import calendar: %1",
804 if ( !konsolekalendar->
isEvent( startdatetime, enddatetime,
806 kDebug() <<
"main | modework |"
807 <<
"calling addEvent()";
810 cout << i18n(
"Attempting to insert an event that already exists" ).toLocal8Bit().data()
817 kDebug() <<
"main | modework |"
818 <<
"calling changeEvent()";
819 if ( !variables.
isUID() ) {
820 cout << i18n(
"Missing event UID: "
821 "use --uid command line option" ).toLocal8Bit().data()
826 cout << i18n(
"No such event UID: change event failed" ).toLocal8Bit().data()
830 kDebug() <<
"main | modework |"
831 <<
"successful changeEvent()";
835 kDebug() <<
"main | modework |"
836 <<
"calling deleteEvent()";
837 if ( !variables.
isUID() ) {
838 cout << i18n(
"Missing event UID: "
839 "use --uid command line option" ).toLocal8Bit().data()
844 cout << i18n(
"No such event UID: delete event failed" ).toLocal8Bit().data()
848 kDebug() <<
"main | modework |"
849 <<
"successful deleteEvent()";
853 kDebug() <<
"main | modework |"
854 <<
"calling showInstance() to view events";
856 cout << i18n(
"Cannot open specified export file: %1",
863 delete konsolekalendar;
866 kDebug() <<
"main | exiting";
Export HTML for the time span on month boundaries.
QString toString(Qt::DateFormat format) const
ulong toULong(bool *ok, int base) const
QString & append(QChar ch)
void setAll(bool all)
View all option.
bool changeEvent()
Change event.
bool printCalendarList()
Prints the available calendars.
QString toString(Qt::DateFormat format) const
void setDescription(const QString &description)
Add description.
void setUseJournals(bool useJournals)
Set switch to use Journals.
void setDaysCount(int count)
Sets how many day should be seen.
void setAllowGui(bool allow)
Sets whether to allow using resources with potential GUI dependencies.
void setStartDateTime(const QDateTime &start)
Sets start date.
QString getExportFile() const
To what file we'll output.
QString getSummary() const
Get summary.
QTime fromString(const QString &string, Qt::DateFormat format)
void setVerbose(bool verbose)
Should program be more verbose?
This class provides all the variables for the program.
bool isUID() const
Is there UID set?
void setLocation(const QString &location)
Add location information.
Provides the KonsoleKalendar class definition.
QDate fromString(const QString &string, Qt::DateFormat format)
void setNext(bool next)
Show only next activity and exit.
void setCollectionId(Akonadi::Collection::Id)
int exec(QFlags< QEventLoop::ProcessEventsFlag > flags)
int toInt(bool *ok, int base) const
void setExportFile(const QString &export_file)
Sets the output file name to export_file.
void setSummary(const QString &summary)
Add summary.
bool addEvent()
Add event to calendar.
QString getImportFile() const
Return import filename.
void setUID(const QString &uid)
Sets the UID, the unique tag for VCard entry.
QByteArray toLocal8Bit() const
void setUseEvents(bool useEvents)
Set switch to use Events.
Provides the KonsoleKalendarEpoch class definition.
void setDryRun(bool dryrun)
Should we only try to run it and do nothing?
bool showInstance()
Visualize what we need.
Export HTML for the specified time span.
void setImportFile(const QString &calendar)
Set file to import active calendar.
bool importCalendar()
Imports calendar file.
void setFloating(bool floating)
Set if Event is floating.
void setEndDateTime(const QDateTime &end)
Sets end date.
int getDaysCount() const
Get how many day should be seen.
void setExportType(ExportType exportType)
Sets the ExportType to use.
bool isEvent(const QDateTime &startdate, const QDateTime &enddate, const QString &summary)
Detect if event already exists.
QString fromLatin1(const char *str, int size)
void setCalendar(const Akonadi::FetchJobCalendar::Ptr &)
Sets the calendar resources for global use.
QDate addDays(int ndays) const
QDateTime addSecs(int s) const
bool deleteEvent()
Delete event.
static QDateTime epoch2QDateTime(uint epoch)
Converts epoch time to QDateTime format.
Export Comma-Separated Values.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
void setUseTodos(bool useTodos)
Set switch to use Todos.
The base class of the project.
Class for timestamps expressed as epochs.
Provides the KonsoleKalendarVariables class definition.