File indexing completed on 2024-05-12 05:10:37

0001 /******************************************************************************
0002  * main.cpp                                                                   *
0003  *                                                                            *
0004  * KonsoleKalendar is a command line interface to KDE calendars               *
0005  * SPDX-FileCopyrightText: 2002-2004 Tuukka Pasanen <illuusio@mailcity.com>   *
0006  * SPDX-FileCopyrightText: 2003-2009 Allen Winter <winter@kde.org>            *
0007  * SPDX-FileCopyrightText: 2013 Sérgio Martins <iamsergio@gmail.com>          *
0008  *                                                                            *
0009  * SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 *
0010  *                                                                            *
0011  *****************************************************************************/
0012 /**
0013  * @file main.cpp
0014  * KonsoleKalendar main program.
0015  * @author Tuukka Pasanen
0016  * @author Allen Winter
0017  * @author Sérgio Martins
0018  */
0019 
0020 #include "konsolekalendar.h"
0021 #include "konsolekalendarepoch.h"
0022 
0023 #include "konsolekalendarvariables.h"
0024 
0025 #include <KLocalizedString>
0026 #include <kconfig.h>
0027 
0028 #include "konsolekalendar_debug.h"
0029 
0030 #include <KCalendarCore/CalFormat>
0031 
0032 #include <QDateTime>
0033 #include <QElapsedTimer>
0034 #include <QEventLoop>
0035 #include <QFile>
0036 
0037 #include <KAboutData>
0038 #include <QApplication>
0039 #include <QCommandLineParser>
0040 #include <cstdlib>
0041 #include <ctime>
0042 #include <iostream>
0043 
0044 using namespace KCalendarCore;
0045 using namespace std;
0046 
0047 //@cond IGNORE
0048 static const char progName[] = "konsolekalendar";
0049 static const char progDisplay[] = "KonsoleKalendar";
0050 #include "console-version.h"
0051 static const char progVersion[] = KDEPIM_VERSION;
0052 
0053 int main(int argc, char *argv[])
0054 {
0055     KLocalizedString::setApplicationDomain(QByteArrayLiteral("konsolekalendar"));
0056     QApplication app(argc, argv);
0057 
0058     KAboutData aboutData(QLatin1StringView(progName),
0059                          i18n("KonsoleKalendar"),
0060                          QStringLiteral(KDEPIM_VERSION),
0061                          i18n("A command line interface to KDE calendars"),
0062                          KAboutLicense::GPL,
0063                          i18n("(c) 2002-2009, Tuukka Pasanen and Allen Winter"));
0064 
0065     aboutData.addAuthor(i18n("Laurent Montel"), i18n("Bug fixing"), QStringLiteral("montel@kde.org"));
0066     aboutData.addAuthor(i18n("Allen Winter"), i18n("Maintainer"), QStringLiteral("winter@kde.org"));
0067     aboutData.addAuthor(i18n("Tuukka Pasanen"), i18n("Author"), QStringLiteral("illuusio@mailcity.com"));
0068 
0069     QCommandLineParser parser;
0070     KAboutData::setApplicationData(aboutData);
0071     aboutData.setupCommandLine(&parser);
0072 
0073     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("verbose"), i18n("Print helpful runtime messages")));
0074     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("dry-run"), i18n("Print what would have been done, but do not execute")));
0075     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("allow-gui"), i18n("Allow calendars which might need an interactive user interface")));
0076     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("event"), i18n("Operate for Events only (Default)")));
0077     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("todo"), i18n("Operate for To-dos only [NOT WORKING YET]")));
0078     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("journal"), i18n("Operate for Journals only [NOT WORKING YET]")));
0079     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("view"), i18n("Print incidences in specified export format")));
0080     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("add"), i18n("Insert an incidence into the calendar")));
0081     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("change"), i18n("Modify an existing incidence")));
0082     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("delete"), i18n("Remove an existing incidence")));
0083     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("create <filename>"), i18n("Create new Akonadi Resource for file")));
0084     parser.addOption(
0085         QCommandLineOption(QStringList() << QStringLiteral("import"), i18n("Import this calendar to main calendar"), QStringLiteral("[import-file]")));
0086     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("list-calendars"), i18n("List available calendars")));
0087     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("all"), i18n("View all calendar entries, ignoring date/time options")));
0088     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("next"), i18n("View next activity in calendar")));
0089     parser.addOption(
0090         QCommandLineOption(QStringList() << QStringLiteral("show-next"), i18n("From start date show next # days' activities"), QStringLiteral("[days]")));
0091     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("uid"), i18n("Incidence Unique-string identifier"), QStringLiteral("[uid]")));
0092     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("date"), i18n("Start from this day [YYYY-MM-DD]"), QStringLiteral("[start-date]")));
0093     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("time"), i18n("Start from this time [HH:MM:SS]"), QStringLiteral("[start-time]")));
0094     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("end-date"), i18n("End at this day [YYYY-MM-DD]"), QStringLiteral("[end-date]")));
0095     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("end-time"), i18n("End at this time [HH:MM:SS]"), QStringLiteral("[end-time]")));
0096     parser.addOption(
0097         QCommandLineOption(QStringList() << QStringLiteral("epoch-start"), i18n("Start from this time [secs since epoch]"), QStringLiteral("[epoch-time]")));
0098     parser.addOption(
0099         QCommandLineOption(QStringList() << QStringLiteral("epoch-end"), i18n("End at this time [secs since epoch]"), QStringLiteral("[epoch-time]")));
0100     parser.addOption(
0101         QCommandLineOption(QStringList() << QStringLiteral("summary"), i18n("Add summary to incidence (for add/change modes)"), QStringLiteral("[summary]")));
0102     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("description"),
0103                                         i18n("Add description to incidence (for add/change modes)"),
0104                                         QStringLiteral("[description]")));
0105     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("location"),
0106                                         i18n("Add location to incidence (for add/change modes)"),
0107                                         QStringLiteral("[location]")));
0108     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("calendar"),
0109                                         i18n("Calendar to use when creating a new incidence"),
0110                                         QStringLiteral("[calendar id]")));
0111     parser.addOption(
0112         QCommandLineOption(QStringList() << QStringLiteral("export-type"), i18n("Export file type (Default: text)"), QStringLiteral("[export-type]")));
0113     parser.addOption(
0114         QCommandLineOption(QStringList() << QStringLiteral("export-file"), i18n("Export to file (Default: stdout)"), QStringLiteral("[export-type]")));
0115     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("export-list"), i18n("Print list of export types supported and exit")));
0116     parser.process(app);
0117     aboutData.processCommandLine(&parser);
0118 
0119     // Laurent: allow or not gui FIXME
0120     //        // when not set (default) GUI is not enabled - disable all GUI stuff
0121     //        parser.isSet(QStringLiteral("allow-gui"));
0122 
0123     // Default values for start date/time (today at 07:00)
0124     QDate startdate = QDate::currentDate();
0125     QTime starttime(7, 0);
0126 
0127     // Default values for end date/time (today at 17:00)
0128     QDate enddate = QDate::currentDate();
0129     QTime endtime(17, 0);
0130 
0131     // Default values for switches
0132     bool view = true;
0133     bool add = false;
0134     bool change = false;
0135     bool del = false;
0136     bool create = false;
0137     // bool calendarFile = false;
0138     bool importFile = false;
0139 
0140     QString option;
0141 
0142     KonsoleKalendarVariables variables;
0143     KonsoleKalendarEpoch epochs;
0144 
0145     variables.setFloating(false); // by default, new events do NOT float
0146 
0147     if (parser.isSet(QStringLiteral("verbose"))) {
0148         variables.setVerbose(true);
0149     }
0150 
0151     if (parser.isSet(QStringLiteral("dry-run"))) {
0152         variables.setDryRun(true);
0153     }
0154 
0155     if (parser.isSet(QStringLiteral("allow-gui"))) {
0156         variables.setAllowGui(true);
0157     }
0158 
0159     /*
0160      * Switch on export list
0161      */
0162     if (parser.isSet(QStringLiteral("export-list"))) {
0163         cout << endl;
0164         cout << i18n("%1 supports these export formats:", QString::fromLatin1(progDisplay)).toLocal8Bit().data() << endl;
0165         cout << i18nc("the default export format", "  %1 [Default]", QStringLiteral("Text")).toLocal8Bit().data() << endl;
0166         cout << i18nc("short text export", "  %1 (like %2, but more compact)", QStringLiteral("Short"), QStringLiteral("Text")).toLocal8Bit().data() << endl;
0167         cout << i18nc("comma-separated values export", "  %1 (Comma-Separated Values)", QStringLiteral("CSV")).toLocal8Bit().data() << endl;
0168         cout << endl;
0169         return 0;
0170     }
0171 
0172     /*
0173      * Set incidence type(s)
0174      */
0175     if (parser.isSet(QStringLiteral("event"))) {
0176         variables.setUseEvents(true);
0177         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options | use Events";
0178     }
0179     if (parser.isSet(QStringLiteral("todo"))) {
0180         variables.setUseTodos(true);
0181         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options | use To-dos";
0182         cout << i18n("Sorry, To-dos are not working yet.").toLocal8Bit().data() << endl;
0183         return 1;
0184     }
0185     if (parser.isSet(QStringLiteral("journal"))) {
0186         variables.setUseJournals(true);
0187         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options | use Journals";
0188         cout << i18n("Sorry, Journals are not working yet.").toLocal8Bit().data() << endl;
0189         return 1;
0190     }
0191     // Use Events if no incidence type is specified on the command line
0192     if (!parser.isSet(QStringLiteral("event")) && !parser.isSet(QStringLiteral("todo")) && !parser.isSet(QStringLiteral("journal"))) {
0193         variables.setUseEvents(true);
0194         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options | use Events (Default)";
0195     }
0196 
0197     /*
0198      * Switch on exporting
0199      */
0200     variables.setExportType(ExportTypeText);
0201     if (parser.isSet(QStringLiteral("export-type"))) {
0202         option = parser.value(QStringLiteral("export-type"));
0203 
0204         if (option.toUpper() == QLatin1StringView("CSV")) {
0205             qCDebug(KONSOLEKALENDAR_LOG) << "main | export-type | Export to CSV";
0206             variables.setExportType(ExportTypeCSV);
0207         } else if (option.toUpper() == QLatin1StringView("TEXT")) {
0208             qCDebug(KONSOLEKALENDAR_LOG) << "main | export-type | Export to TEXT (default)";
0209             variables.setExportType(ExportTypeText);
0210         } else if (option.toUpper() == QLatin1StringView("SHORT")) {
0211             qCDebug(KONSOLEKALENDAR_LOG) << "main | export-type | Export to TEXT-SHORT";
0212             variables.setExportType(ExportTypeTextShort);
0213         } else {
0214             cout << i18n("Invalid Export Type Specified: %1", option).toLocal8Bit().data() << endl;
0215             return 1;
0216         }
0217     }
0218 
0219     /*
0220      * Switch on export file name
0221      */
0222     if (parser.isSet(QStringLiteral("export-file"))) {
0223         option = parser.value(QStringLiteral("export-file"));
0224 
0225         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0226                                      << "Export File:"
0227                                      << "(" << option << ")";
0228 
0229         variables.setExportFile(option);
0230     }
0231 
0232     /*
0233      * Switch on View (Print Entries).  This is the default mode of operation.
0234      */
0235     if (parser.isSet(QStringLiteral("view"))) {
0236         view = true;
0237 
0238         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0239                                      << "Mode: (Print incidences)";
0240     }
0241 
0242     /*
0243      * Switch on Add (Insert Entry)
0244      */
0245     if (parser.isSet(QStringLiteral("add"))) {
0246         view = false;
0247         add = true;
0248 
0249         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0250                                      << "Mode: (Add incidence)";
0251     }
0252 
0253     /*
0254      * Switch on Change (Modify Entry)
0255      */
0256     if (parser.isSet(QStringLiteral("change"))) {
0257         view = false;
0258         change = true;
0259 
0260         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0261                                      << "Mode: (Change incidence)";
0262     }
0263 
0264     /*
0265      * Switch on Delete (Remove Entry)
0266      */
0267     if (parser.isSet(QStringLiteral("delete"))) {
0268         view = false;
0269         del = true;
0270 
0271         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0272                                      << "Mode: (Delete incidence)";
0273     }
0274 
0275     /*
0276      * Switch on Create
0277      */
0278     if (parser.isSet(QStringLiteral("create"))) {
0279         view = false;
0280         create = true;
0281 
0282         option = parser.value(QStringLiteral("create"));
0283         variables.setCalendarFile(option);
0284 
0285         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0286                                      << "Create Akonadi Resource for"
0287                                      << "(" << option << ")";
0288     }
0289 
0290     /*
0291      * If there is summary attached.
0292      */
0293     if (parser.isSet(QStringLiteral("summary"))) {
0294         option = parser.value(QStringLiteral("summary"));
0295 
0296         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0297                                      << "Summary:"
0298                                      << "(" << option << ")";
0299 
0300         variables.setSummary(option);
0301     }
0302 
0303     /*
0304      * If there is description attached.
0305      */
0306     if (parser.isSet(QStringLiteral("description"))) {
0307         option = parser.value(QStringLiteral("description"));
0308 
0309         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0310                                      << "Description:"
0311                                      << "(" << option << ")";
0312 
0313         variables.setDescription(option);
0314     }
0315 
0316     if (parser.isSet(QStringLiteral("calendar"))) {
0317         option = parser.value(QStringLiteral("calendar"));
0318         bool ok = false;
0319         int colId = option.toInt(&ok);
0320         if (ok) {
0321             variables.setCollectionId(colId);
0322         }
0323     }
0324 
0325     /*
0326      * If there is location information
0327      */
0328     if (parser.isSet(QStringLiteral("location"))) {
0329         option = parser.value(QStringLiteral("location"));
0330 
0331         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0332                                      << "Location:"
0333                                      << "(" << option << ")";
0334 
0335         variables.setLocation(option);
0336     }
0337 
0338     /*
0339      * Show next happening and exit
0340      */
0341     if (parser.isSet(QStringLiteral("next"))) {
0342         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0343                                      << "Show next incidence only";
0344 
0345         variables.setNext(true);
0346     }
0347 
0348     /*
0349      * Set incidence unique string identifier
0350      */
0351     if (parser.isSet(QStringLiteral("uid"))) {
0352         option = parser.value(QStringLiteral("uid"));
0353 
0354         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0355                                      << "incidence UID:"
0356                                      << "(" << option << ")";
0357 
0358         variables.setUID(option);
0359     }
0360 
0361     /*
0362      * Set starting date for calendar
0363      */
0364     if (parser.isSet(QStringLiteral("date"))) {
0365         option = parser.value(QStringLiteral("date"));
0366 
0367         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0368                                      << "Start date before conversion:"
0369                                      << "(" << option << ")";
0370 
0371         startdate = QDate::fromString(option, Qt::ISODate);
0372         if (!startdate.isValid()) {
0373             cout << i18n("Invalid Start Date Specified: %1", option).toLocal8Bit().data() << endl;
0374             return 1;
0375         }
0376         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0377                                      << "Start date after conversion:"
0378                                      << "(" << startdate.toString() << ")";
0379     }
0380 
0381     /*
0382      * Set starting time
0383      */
0384     if (parser.isSet(QStringLiteral("time"))) {
0385         option = parser.value(QStringLiteral("time"));
0386 
0387         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0388                                      << "Start time before conversion :"
0389                                      << "(" << option << ")";
0390 
0391         if (option.toUpper() != QLatin1StringView("FLOAT")) {
0392             if (option.count(QLatin1Char(':')) < 2) {
0393                 // need to append seconds
0394                 option.append(QLatin1StringView(":00"));
0395             }
0396             starttime = QTime::fromString(option, Qt::ISODate);
0397             if (!starttime.isValid()) {
0398                 cout << i18n("Invalid Start Time Specified: %1", option).toLocal8Bit().data() << endl;
0399                 return 1;
0400             }
0401             qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0402                                          << "Start time after conversion:"
0403                                          << "(" << starttime.toString() << ")";
0404         } else {
0405             variables.setFloating(true);
0406             qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0407                                          << "Floating event time specified";
0408         }
0409     }
0410 
0411     /*
0412      * Set end date for calendar
0413      */
0414     if (parser.isSet(QStringLiteral("end-date"))) {
0415         option = parser.value(QStringLiteral("end-date"));
0416 
0417         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0418                                      << "End date before conversion:"
0419                                      << "(" << option << ")";
0420 
0421         enddate = QDate::fromString(option, Qt::ISODate);
0422         if (!enddate.isValid()) {
0423             cout << i18n("Invalid End Date Specified: %1", option).toLocal8Bit().data() << endl;
0424             return 1;
0425         }
0426         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0427                                      << "End date after conversion:"
0428                                      << "(" << enddate.toString() << ")";
0429     }
0430 
0431     /*
0432      * Show next # days and exit
0433      */
0434     if (parser.isSet(QStringLiteral("show-next"))) {
0435         bool ok;
0436 
0437         option = parser.value(QStringLiteral("show-next"));
0438         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0439                                      << "Show" << option << "days ahead";
0440         variables.setDaysCount(option.toInt(&ok, 10));
0441 
0442         if (!ok) {
0443             cout << i18n("Invalid Date Count Specified: %1", option).toLocal8Bit().data() << endl;
0444             return 1;
0445         }
0446 
0447         enddate = startdate;
0448         enddate = enddate.addDays(variables.getDaysCount());
0449         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0450                                      << "End date after conversion:"
0451                                      << "(" << enddate.toString() << ")";
0452     }
0453 
0454     /*
0455      * Set ending time
0456      */
0457     if (parser.isSet(QStringLiteral("end-time"))) {
0458         option = parser.value(QStringLiteral("end-time"));
0459 
0460         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0461                                      << "End time before conversion:"
0462                                      << "(" << option << ")";
0463 
0464         if (option.toUpper() != QLatin1StringView("FLOAT")) {
0465             if (option.count(QLatin1Char(':')) < 2) {
0466                 // need to append seconds
0467                 option.append(QLatin1StringView(":00"));
0468             }
0469             endtime = QTime::fromString(option, Qt::ISODate);
0470             if (!endtime.isValid()) {
0471                 cout << i18n("Invalid End Time Specified: %1", option).toLocal8Bit().data() << endl;
0472                 return 1;
0473             }
0474 
0475             qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0476                                          << "End time after conversion:"
0477                                          << "(" << endtime.toString() << ")";
0478         } else {
0479             variables.setFloating(true);
0480             qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0481                                          << "Floating event time specified";
0482         }
0483     }
0484 
0485     /*
0486      * Set start date/time from epoch
0487      */
0488     time_t epochstart = 0;
0489     if (parser.isSet(QStringLiteral("epoch-start"))) {
0490         option = parser.value(QStringLiteral("epoch-start"));
0491 
0492         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0493                                      << "Epoch start:"
0494                                      << "(" << option << ")";
0495 
0496         epochstart = (time_t)option.toULong(nullptr, 10);
0497     }
0498 
0499     /*
0500      * Set end date/time from epoch
0501      */
0502     time_t epochend = 0;
0503     if (parser.isSet(QStringLiteral("epoch-end"))) {
0504         option = parser.value(QStringLiteral("epoch-end"));
0505 
0506         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0507                                      << "Epoch end:"
0508                                      << "(" << option << ")";
0509 
0510         epochend = (time_t)option.toULong(nullptr, 10);
0511     }
0512 
0513     if (parser.isSet(QStringLiteral("all"))) {
0514         variables.setAll(true);
0515     } else {
0516         variables.setAll(false);
0517     }
0518 
0519     if (parser.isSet(QStringLiteral("import"))) {
0520         view = false;
0521         importFile = true;
0522         option = parser.value(QStringLiteral("import"));
0523         variables.setImportFile(option);
0524 
0525         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0526                                      << "importing file from:"
0527                                      << "(" << option << ")";
0528     }
0529 
0530     auto konsolekalendar = new KonsoleKalendar(&variables);
0531 
0532     if (parser.isSet(QStringLiteral("list-calendars"))) {
0533         konsolekalendar->printCalendarList();
0534         return 0;
0535     }
0536 
0537     QEventLoop loop;
0538     Akonadi::FetchJobCalendar::Ptr calendar = Akonadi::FetchJobCalendar::Ptr(new Akonadi::FetchJobCalendar());
0539     QObject::connect(calendar.data(), &Akonadi::FetchJobCalendar::loadFinished, &loop, &QEventLoop::quit);
0540     qCDebug(KONSOLEKALENDAR_LOG) << "Starting to load calendar";
0541     QElapsedTimer t;
0542     t.start();
0543     loop.exec();
0544     qCDebug(KONSOLEKALENDAR_LOG) << "Calendar loaded in" << t.elapsed() << "ms; success=" << !calendar->isLoading()
0545                                  << "; num incidences=" << calendar->incidences().count();
0546 
0547     variables.setCalendar(calendar);
0548 
0549     /***************************************************************************
0550      * Glorious date/time checking and setting code                            *
0551      ***************************************************************************/
0552     QDateTime startdatetime;
0553     QDateTime enddatetime;
0554 
0555     // Handle case with either date or end-date unspecified
0556     if (!parser.isSet(QStringLiteral("end-date")) && !parser.isSet(QStringLiteral("show-next")) && parser.isSet(QStringLiteral("date"))) {
0557         enddate = startdate;
0558         qCDebug(KONSOLEKALENDAR_LOG) << "main | datetimestamp |"
0559                                      << "setting enddate to startdate";
0560     } else if (parser.isSet(QStringLiteral("end-date")) && !parser.isSet(QStringLiteral("date"))) {
0561         startdate = enddate;
0562         qCDebug(KONSOLEKALENDAR_LOG) << "main | datetimestamp |"
0563                                      << "setting startdate to enddate";
0564     }
0565 
0566     // NOTE: If neither date nor end-date specified, then event will be today.
0567 
0568     // Case:
0569     //   End time (or epoch) unspecified, and start time (or epoch) IS specified.
0570     //   In this case, set the ending to 1 hour after starting.
0571     if (!parser.isSet(QStringLiteral("end-time")) && !parser.isSet(QStringLiteral("epoch-end"))) {
0572         if (parser.isSet(QStringLiteral("time"))) {
0573             endtime = starttime.addSecs(60 * 60); // end is 1 hour after start
0574             qCDebug(KONSOLEKALENDAR_LOG) << "main | datetimestamp |"
0575                                          << "setting endtime 1 hour after starttime";
0576         } else if (parser.isSet(QStringLiteral("epoch-start"))) {
0577             startdatetime = epochs.epoch2QDateTime(epochstart);
0578             enddatetime = startdatetime.addSecs(60 * 60);
0579             qCDebug(KONSOLEKALENDAR_LOG) << "main | datetimestamp |"
0580                                          << "setting endtime 1 hour after epochstart";
0581         }
0582     }
0583 
0584     // Case:
0585     //   Time (or epoch) unspecified, and end-time (or epoch) IS specified.
0586     //   In this case, set the starting to 1 hour before ending.
0587     if (!parser.isSet(QStringLiteral("time")) && !parser.isSet(QStringLiteral("epoch-start"))) {
0588         if (parser.isSet(QStringLiteral("end-time"))) {
0589             starttime = endtime.addSecs(-60 * 60); // start is 1 hour before end
0590             qCDebug(KONSOLEKALENDAR_LOG) << "main | datetimestamp |"
0591                                          << "setting starttime 1 hour before endtime";
0592         } else if (parser.isSet(QStringLiteral("epoch-end"))) {
0593             enddatetime = epochs.epoch2QDateTime(epochend);
0594             startdatetime = enddatetime.addSecs(-60 * 60);
0595             qCDebug(KONSOLEKALENDAR_LOG) << "main | datetimestamp |"
0596                                          << "setting starttime 1 before after epochend";
0597         }
0598     }
0599 
0600     // Case:
0601     //   Time (or epoch) unspecified, and end-time (or epoch) unspecified.
0602     if (!parser.isSet(QStringLiteral("time")) && !parser.isSet(QStringLiteral("epoch-start")) && !parser.isSet(QStringLiteral("end-time"))
0603         && !parser.isSet(QStringLiteral("epoch-end"))) {
0604         // set default start date/time
0605         startdatetime = QDateTime(startdate, starttime);
0606         qCDebug(KONSOLEKALENDAR_LOG) << "main | datetimestamp |"
0607                                      << "setting startdatetime from"
0608                                      << "default startdate (today) and starttime";
0609         // set default end date/time
0610         enddatetime = QDateTime(enddate, endtime);
0611         qCDebug(KONSOLEKALENDAR_LOG) << "main | datetimestamp |"
0612                                      << "setting enddatetime from"
0613                                      << "default enddate (today) and endtime";
0614     }
0615 
0616     // Set startdatetime, enddatetime if still necessary
0617     if (startdatetime.isNull()) {
0618         startdatetime = QDateTime(startdate, starttime);
0619         qCDebug(KONSOLEKALENDAR_LOG) << "main | datetimestamp |"
0620                                      << "setting startdatetime from startdate and starttime";
0621     }
0622     if (enddatetime.isNull()) {
0623         enddatetime = QDateTime(enddate, endtime);
0624         qCDebug(KONSOLEKALENDAR_LOG) << "main | datetimestamp |"
0625                                      << "setting enddatetime from enddate and endtime";
0626     }
0627 
0628     // Float check for add mode:
0629     //   Events float if time AND end-time AND epoch times are UNspecified
0630     if (add) {
0631         if (!parser.isSet(QStringLiteral("time")) && !parser.isSet(QStringLiteral("end-time")) && !parser.isSet(QStringLiteral("epoch-start"))
0632             && !parser.isSet(QStringLiteral("epoch-end"))) {
0633             variables.setFloating(true);
0634             qCDebug(KONSOLEKALENDAR_LOG) << "main | floatingcheck |"
0635                                          << "turn-on floating event";
0636         }
0637     }
0638 
0639     // Finally! Set the start/end date times
0640     if (!change) {
0641         variables.setStartDateTime(startdatetime);
0642         variables.setEndDateTime(enddatetime);
0643     } else {
0644         // Do NOT set start/end datetimes in change mode,
0645         //   unless they were specified on commandline
0646         if (parser.isSet(QStringLiteral("time")) || parser.isSet(QStringLiteral("epoch-start")) || parser.isSet(QStringLiteral("end-time"))
0647             || parser.isSet(QStringLiteral("epoch-end"))) {
0648             variables.setStartDateTime(startdatetime);
0649             variables.setEndDateTime(enddatetime);
0650         }
0651     }
0652 
0653     // Some more debug prints
0654     qCDebug(KONSOLEKALENDAR_LOG) << "main | datetimestamp | StartDate=" << startdatetime.toString(Qt::TextDate);
0655     qCDebug(KONSOLEKALENDAR_LOG) << "main | datetimestamp | EndDate=" << enddatetime.toString(Qt::TextDate);
0656 
0657     /***************************************************************************
0658      * Sanity checks                                                           *
0659      ***************************************************************************/
0660 
0661     // Cannot combine modes
0662     if (create + view + add + change + del > 1) {
0663         cout << i18n(
0664                     "Only 1 operation mode "
0665                     "(view, add, change, delete, create) "
0666                     "permitted at any one time")
0667                     .toLocal8Bit()
0668                     .data()
0669              << endl;
0670         return 1;
0671     }
0672 
0673     // Cannot have a ending before starting
0674     if (startdatetime > enddatetime) {
0675         cout << i18n("Ending Date/Time occurs before the Starting Date/Time").toLocal8Bit().data() << endl;
0676         return 1;
0677     }
0678 
0679     /***************************************************************************
0680      * And away we go with the real work...                                    *
0681      ***************************************************************************/
0682 
0683     // Free up some memory.
0684 
0685     /*
0686      * Set our application name for use in unique IDs and error messages,
0687      * and product ID for incidence PRODID property
0688      */
0689     QString prodId = QStringLiteral("-//K Desktop Environment//NONSGML %1 %2//EN");
0690     CalFormat::setApplication(QLatin1StringView(progDisplay), prodId.arg(QLatin1StringView(progDisplay)).arg(QLatin1StringView(progVersion)));
0691 
0692     if (importFile) {
0693         if (konsolekalendar->importCalendar()) {
0694             cout << i18n("Calendar %1 successfully imported", variables.getImportFile()).toLocal8Bit().data() << endl;
0695             return 0;
0696         } else {
0697             cout << i18n("Unable to import calendar: %1", variables.getImportFile()).toLocal8Bit().data() << endl;
0698             return 1;
0699         }
0700     }
0701 
0702     if (add) {
0703         if (!konsolekalendar->isEvent(startdatetime, enddatetime, variables.getSummary())) {
0704             qCDebug(KONSOLEKALENDAR_LOG) << "main | modework |"
0705                                          << "calling addEvent()";
0706             konsolekalendar->addEvent();
0707         } else {
0708             cout << i18n("Attempting to insert an event that already exists").toLocal8Bit().data() << endl;
0709             return 1;
0710         }
0711     }
0712 
0713     if (change) {
0714         qCDebug(KONSOLEKALENDAR_LOG) << "main | modework |"
0715                                      << "calling changeEvent()";
0716         if (!variables.isUID()) {
0717             cout << i18n(
0718                         "Missing event UID: "
0719                         "use --uid command line option")
0720                         .toLocal8Bit()
0721                         .data()
0722                  << endl;
0723             return 1;
0724         }
0725         if (!konsolekalendar->changeEvent()) {
0726             cout << i18n("No such event UID: change event failed").toLocal8Bit().data() << endl;
0727             return 1;
0728         }
0729         qCDebug(KONSOLEKALENDAR_LOG) << "main | modework |"
0730                                      << "successful changeEvent()";
0731     }
0732 
0733     if (del) {
0734         qCDebug(KONSOLEKALENDAR_LOG) << "main | modework |"
0735                                      << "calling deleteEvent()";
0736         if (!variables.isUID()) {
0737             cout << i18n(
0738                         "Missing event UID: "
0739                         "use --uid command line option")
0740                         .toLocal8Bit()
0741                         .data()
0742                  << endl;
0743             return 1;
0744         }
0745         if (!konsolekalendar->deleteEvent()) {
0746             cout << i18n("No such event UID: delete event failed").toLocal8Bit().data() << endl;
0747             return 1;
0748         }
0749         qCDebug(KONSOLEKALENDAR_LOG) << "main | modework |"
0750                                      << "successful deleteEvent()";
0751     }
0752 
0753     if (view) {
0754         qCDebug(KONSOLEKALENDAR_LOG) << "main | modework |"
0755                                      << "calling showInstance() to view events";
0756         if (!konsolekalendar->showInstance()) {
0757             cout << i18n("Cannot open specified export file: %1", variables.getExportFile()).toLocal8Bit().data() << endl;
0758             return 1;
0759         }
0760     }
0761 
0762     if (create) {
0763         qCDebug(KONSOLEKALENDAR_LOG) << "main | parse options |"
0764                                      << "creating Akonadi resource from file:"
0765                                      << "(" << variables.getCalendarFile() << ")";
0766         if (!konsolekalendar->createCalendar()) {
0767             cout << i18n("Cannot create Akonadi resource from file: %1", variables.getCalendarFile()).toLocal8Bit().data() << endl;
0768             return 1;
0769         }
0770     }
0771 
0772     delete konsolekalendar;
0773 
0774     qCDebug(KONSOLEKALENDAR_LOG) << "main | exiting";
0775 
0776     return 0;
0777 }
0778 
0779 //@endcond