diff --git a/autotests/conflictresolvertest.cpp b/autotests/conflictresolvertest.cpp index 04b6694..6d373c3 100644 --- a/autotests/conflictresolvertest.cpp +++ b/autotests/conflictresolvertest.cpp @@ -1,334 +1,334 @@ /* Copyright (C) 2010 Casey Link Copyright (C) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "conflictresolvertest.h" #include "conflictresolver.h" -#include -#include -#include +#include +#include +#include #include #include using namespace IncidenceEditorNG; void ConflictResolverTest::insertAttendees() { for (const CalendarSupport::FreeBusyItem::Ptr &item : qAsConst(attendees)) { resolver->insertAttendee(item); } } -void ConflictResolverTest::addAttendee(const QString &email, const KCalCore::FreeBusy::Ptr &fb, KCalCore::Attendee::Role role) +void ConflictResolverTest::addAttendee(const QString &email, const KCalendarCore::FreeBusy::Ptr &fb, KCalendarCore::Attendee::Role role) { QString name = QStringLiteral("attendee %1").arg(attendees.count()); - CalendarSupport::FreeBusyItem::Ptr item(new CalendarSupport::FreeBusyItem(KCalCore::Attendee(name, email, false, - KCalCore::Attendee::Accepted, + CalendarSupport::FreeBusyItem::Ptr item(new CalendarSupport::FreeBusyItem(KCalendarCore::Attendee(name, email, false, + KCalendarCore::Attendee::Accepted, role), nullptr)); - item->setFreeBusy(KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(*fb.data()))); + item->setFreeBusy(KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(*fb.data()))); attendees << item; } void ConflictResolverTest::initTestCase() { parent = new QWidget; init(); } void ConflictResolverTest::init() { base = QDateTime::currentDateTime().addDays(1); end = base.addSecs(10 * 60 * 60); resolver = new ConflictResolver(parent, parent); } void ConflictResolverTest::cleanup() { delete resolver; resolver = nullptr; attendees.clear(); } void ConflictResolverTest::simpleTest() { - KCalCore::Period meeting(end.addSecs(-3 * 60 * 60), KCalCore::Duration(2 * 60 * 60)); + KCalendarCore::Period meeting(end.addSecs(-3 * 60 * 60), KCalendarCore::Duration(2 * 60 * 60)); addAttendee(QStringLiteral("albert@einstein.net"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << meeting))); insertAttendees(); static const int resolution = 15 * 60; resolver->setResolution(resolution); resolver->setEarliestDateTime(base); resolver->setLatestDateTime(end); resolver->findAllFreeSlots(); QVERIFY(resolver->availableSlots().size() == 2); - KCalCore::Period first = resolver->availableSlots().at(0); + KCalendarCore::Period first = resolver->availableSlots().at(0); QCOMPARE(first.start(), base); QCOMPARE(first.end(), meeting.start()); - KCalCore::Period second = resolver->availableSlots().at(1); + KCalendarCore::Period second = resolver->availableSlots().at(1); QEXPECT_FAIL("", "Got broken in revision f17b9a8c975588ad7cf4ce8b94ab8e32ac193ed8", Continue); QCOMPARE(second.start(), meeting.end().addSecs(resolution)); //add 15 minutes because the //free block doesn't start until //the next timeslot QCOMPARE(second.end(), end); } void ConflictResolverTest::stillPrettySimpleTest() { - KCalCore::Period meeting1(base, KCalCore::Duration(2 * 60 * 60)); - KCalCore::Period meeting2(base.addSecs(60 * 60), KCalCore::Duration(2 * 60 * 60)); - KCalCore::Period meeting3(end.addSecs(-3 * 60 * 60), KCalCore::Duration(2 * 60 * 60)); + KCalendarCore::Period meeting1(base, KCalendarCore::Duration(2 * 60 * 60)); + KCalendarCore::Period meeting2(base.addSecs(60 * 60), KCalendarCore::Duration(2 * 60 * 60)); + KCalendarCore::Period meeting3(end.addSecs(-3 * 60 * 60), KCalendarCore::Duration(2 * 60 * 60)); addAttendee(QStringLiteral("john.f@kennedy.com"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << meeting1 << meeting3))); addAttendee(QStringLiteral("elvis@rock.com"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << meeting2 << meeting3))); addAttendee(QStringLiteral("albert@einstein.net"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << meeting3))); insertAttendees(); static const int resolution = 15 * 60; resolver->setResolution(resolution); resolver->setEarliestDateTime(base); resolver->setLatestDateTime(end); resolver->findAllFreeSlots(); QVERIFY(resolver->availableSlots().size() == 2); - KCalCore::Period first = resolver->availableSlots().at(0); + KCalendarCore::Period first = resolver->availableSlots().at(0); QEXPECT_FAIL("", "Got broken in revision f17b9a8c975588ad7cf4ce8b94ab8e32ac193ed8", Continue); QCOMPARE(first.start(), meeting2.end().addSecs(resolution)); QCOMPARE(first.end(), meeting3.start()); - KCalCore::Period second = resolver->availableSlots().at(1); + KCalendarCore::Period second = resolver->availableSlots().at(1); QEXPECT_FAIL("", "Got broken in revision f17b9a8c975588ad7cf4ce8b94ab8e32ac193ed8", Continue); QCOMPARE(second.start(), meeting3.end().addSecs(resolution)); //add 15 minutes because the //free block doesn't start until //the next timeslot QCOMPARE(second.end(), end); } #define _time(h, m) QDateTime(base.date(), QTime(h, m)) void ConflictResolverTest::akademy2010() { // based off akademy 2010 schedule // first event was at 9:30, so lets align our start time there base.setTime(QTime(9, 30)); end = base.addSecs(8 * 60 * 60); - KCalCore::Period opening(_time(9, 30), _time(9, 45)); - KCalCore::Period keynote(_time(9, 45), _time(10, 30)); + KCalendarCore::Period opening(_time(9, 30), _time(9, 45)); + KCalendarCore::Period keynote(_time(9, 45), _time(10, 30)); - KCalCore::Period sevenPrinciples(_time(10, 30), _time(11, 15)); - KCalCore::Period commAsService(_time(10, 30), _time(11, 15)); + KCalendarCore::Period sevenPrinciples(_time(10, 30), _time(11, 15)); + KCalendarCore::Period commAsService(_time(10, 30), _time(11, 15)); - KCalCore::Period kdeForums(_time(11, 15), _time(11, 45)); - KCalCore::Period oviStore(_time(11, 15), _time(11, 45)); + KCalendarCore::Period kdeForums(_time(11, 15), _time(11, 45)); + KCalendarCore::Period oviStore(_time(11, 15), _time(11, 45)); // 10 min break - KCalCore::Period highlights(_time(12, 0), _time(12, 45)); - KCalCore::Period styles(_time(12, 0), _time(12, 45)); + KCalendarCore::Period highlights(_time(12, 0), _time(12, 45)); + KCalendarCore::Period styles(_time(12, 0), _time(12, 45)); - KCalCore::Period wikimedia(_time(12, 45), _time(13, 15)); - KCalCore::Period avalanche(_time(12, 45), _time(13, 15)); + KCalendarCore::Period wikimedia(_time(12, 45), _time(13, 15)); + KCalendarCore::Period avalanche(_time(12, 45), _time(13, 15)); - KCalCore::Period pimp(_time(13, 15), _time(13, 45)); - KCalCore::Period direction(_time(13, 15), _time(13, 45)); + KCalendarCore::Period pimp(_time(13, 15), _time(13, 45)); + KCalendarCore::Period direction(_time(13, 15), _time(13, 45)); // lunch 1 hr 25 min lunch - KCalCore::Period blurr(_time(15, 15), _time(16, 00)); - KCalCore::Period plasma(_time(15, 15), _time(16, 00)); + KCalendarCore::Period blurr(_time(15, 15), _time(16, 00)); + KCalendarCore::Period plasma(_time(15, 15), _time(16, 00)); // for ( int i = 1; i < 80; ++i ) { // adds 80 people (adds the same 8 peopl 10 times) addAttendee(QStringLiteral("akademyattendee1@email.com"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << keynote << oviStore << wikimedia << direction))); addAttendee(QStringLiteral("akademyattendee2@email.com"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << keynote << commAsService << highlights << pimp))); addAttendee(QStringLiteral("akademyattendee3@email.com"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << kdeForums << styles << pimp << plasma))); addAttendee(QStringLiteral("akademyattendee4@email.com"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << keynote << oviStore << pimp << blurr))); addAttendee(QStringLiteral("akademyattendee5@email.com"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << keynote << oviStore << highlights << avalanche))); addAttendee(QStringLiteral("akademyattendee6@email.com"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << keynote << commAsService << highlights))); addAttendee(QStringLiteral("akademyattendee7@email.com"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << kdeForums << styles << avalanche << pimp << plasma))); addAttendee(QStringLiteral("akademyattendee8@email.com"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << opening << keynote << oviStore << wikimedia << blurr))); // } insertAttendees(); const int resolution = 5 * 60; resolver->setResolution(resolution); resolver->setEarliestDateTime(base); resolver->setLatestDateTime(end); // QBENCHMARK { resolver->findAllFreeSlots(); // } QVERIFY(resolver->availableSlots().size() == 3); QEXPECT_FAIL("", "Got broken in revision f17b9a8c975588ad7cf4ce8b94ab8e32ac193ed8", Abort); QCOMPARE(resolver->availableSlots().at(0).duration(), - KCalCore::Duration(10 * 60)); + KCalendarCore::Duration(10 * 60)); QCOMPARE(resolver->availableSlots().at(1).duration(), - KCalCore::Duration(1 * 60 * 60 + 25 * 60)); + KCalendarCore::Duration(1 * 60 * 60 + 25 * 60)); QVERIFY(resolver->availableSlots().at(2).start() > plasma.end()); } void ConflictResolverTest::testPeriodIsLargerThenTimeframe() { base.setDate(QDate(2010, 7, 29)); base.setTime(QTime(7, 30)); end.setDate(QDate(2010, 7, 29)); end.setTime(QTime(8, 30)); - KCalCore::Period testEvent(_time(5, 45), _time(8, 45)); + KCalendarCore::Period testEvent(_time(5, 45), _time(8, 45)); addAttendee(QStringLiteral("kdabtest1@demo.kolab.org"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << testEvent))); addAttendee(QStringLiteral("kdabtest2@demo.kolab.org"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List()))); + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List()))); insertAttendees(); resolver->setEarliestDateTime(base); resolver->setLatestDateTime(end); resolver->findAllFreeSlots(); QCOMPARE(resolver->availableSlots().size(), 0); } void ConflictResolverTest::testPeriodBeginsBeforeTimeframeBegins() { base.setDate(QDate(2010, 7, 29)); base.setTime(QTime(7, 30)); end.setDate(QDate(2010, 7, 29)); end.setTime(QTime(9, 30)); - KCalCore::Period testEvent(_time(5, 45), _time(8, 45)); + KCalendarCore::Period testEvent(_time(5, 45), _time(8, 45)); addAttendee(QStringLiteral("kdabtest1@demo.kolab.org"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << testEvent))); addAttendee(QStringLiteral("kdabtest2@demo.kolab.org"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List()))); + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List()))); insertAttendees(); resolver->setEarliestDateTime(base); resolver->setLatestDateTime(end); resolver->findAllFreeSlots(); QCOMPARE(resolver->availableSlots().size(), 1); - KCalCore::Period freeslot = resolver->availableSlots().at(0); + KCalendarCore::Period freeslot = resolver->availableSlots().at(0); QCOMPARE(freeslot.start(), _time(8, 45)); QCOMPARE(freeslot.end(), end); } void ConflictResolverTest::testPeriodEndsAfterTimeframeEnds() { base.setDate(QDate(2010, 7, 29)); base.setTime(QTime(7, 30)); end.setDate(QDate(2010, 7, 29)); end.setTime(QTime(9, 30)); - KCalCore::Period testEvent(_time(8, 00), _time(9, 45)); + KCalendarCore::Period testEvent(_time(8, 00), _time(9, 45)); addAttendee(QStringLiteral("kdabtest1@demo.kolab.org"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << testEvent))); addAttendee(QStringLiteral("kdabtest2@demo.kolab.org"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List()))); + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List()))); insertAttendees(); resolver->setEarliestDateTime(base); resolver->setLatestDateTime(end); resolver->findAllFreeSlots(); QCOMPARE(resolver->availableSlots().size(), 1); - KCalCore::Period freeslot = resolver->availableSlots().at(0); - QCOMPARE(freeslot.duration(), KCalCore::Duration(30 * 60)); + KCalendarCore::Period freeslot = resolver->availableSlots().at(0); + QCOMPARE(freeslot.duration(), KCalendarCore::Duration(30 * 60)); QCOMPARE(freeslot.start(), base); QCOMPARE(freeslot.end(), _time(8, 00)); } void ConflictResolverTest::testPeriodEndsAtSametimeAsTimeframe() { base.setDate(QDate(2010, 7, 29)); base.setTime(QTime(7, 45)); end.setDate(QDate(2010, 7, 29)); end.setTime(QTime(8, 45)); - KCalCore::Period testEvent(_time(5, 45), _time(8, 45)); + KCalendarCore::Period testEvent(_time(5, 45), _time(8, 45)); addAttendee(QStringLiteral("kdabtest1@demo.kolab.org"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List() + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List() << testEvent))); addAttendee(QStringLiteral("kdabtest2@demo.kolab.org"), - KCalCore::FreeBusy::Ptr(new KCalCore::FreeBusy(KCalCore::Period::List()))); + KCalendarCore::FreeBusy::Ptr(new KCalendarCore::FreeBusy(KCalendarCore::Period::List()))); insertAttendees(); resolver->setEarliestDateTime(base); resolver->setLatestDateTime(end); resolver->findAllFreeSlots(); QCOMPARE(resolver->availableSlots().size(), 0); } QTEST_MAIN(ConflictResolverTest) diff --git a/autotests/conflictresolvertest.h b/autotests/conflictresolvertest.h index 2804dcc..2eeea6e 100644 --- a/autotests/conflictresolvertest.h +++ b/autotests/conflictresolvertest.h @@ -1,59 +1,59 @@ /* Copyright (C) 2010 Casey Link Copyright (C) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef CONFLICTRESOLVERTEST_H #define CONFLICTRESOLVERTEST_H #include "CalendarSupport/FreeBusyItem" -#include -#include +#include +#include #include namespace IncidenceEditorNG { class ConflictResolver; } class ConflictResolverTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void init(); void cleanup(); void simpleTest(); void stillPrettySimpleTest(); void akademy2010(); void testPeriodBeginsBeforeTimeframeBegins(); void testPeriodEndsAfterTimeframeEnds(); void testPeriodIsLargerThenTimeframe(); void testPeriodEndsAtSametimeAsTimeframe(); private: void insertAttendees(); - void addAttendee(const QString &email, const KCalCore::FreeBusy::Ptr &fb, KCalCore::Attendee::Role role = KCalCore::Attendee::ReqParticipant); + void addAttendee(const QString &email, const KCalendarCore::FreeBusy::Ptr &fb, KCalendarCore::Attendee::Role role = KCalendarCore::Attendee::ReqParticipant); QList attendees; QWidget *parent; IncidenceEditorNG::ConflictResolver *resolver; QDateTime base, end; }; #endif diff --git a/autotests/testfreebusyganttproxymodel.cpp b/autotests/testfreebusyganttproxymodel.cpp index 9f7e490..8fc25b0 100644 --- a/autotests/testfreebusyganttproxymodel.cpp +++ b/autotests/testfreebusyganttproxymodel.cpp @@ -1,115 +1,115 @@ /* Copyright (C) 2010 Casey Link Copyright (C) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "testfreebusyganttproxymodel.h" #include "freebusyganttproxymodel.h" #include "modeltest.h" #include #include #include -#include +#include #include #include QTEST_MAIN(FreeBusyGanttProxyModelTest) using namespace IncidenceEditorNG; void FreeBusyGanttProxyModelTest::initTestCase() { qputenv("TZ", "UTC"); QStandardPaths::setTestModeEnabled(true); } void FreeBusyGanttProxyModelTest::testModelValidity() { CalendarSupport::FreeBusyItemModel *fbModel = new CalendarSupport::FreeBusyItemModel(); FreeBusyGanttProxyModel *ganttModel = new FreeBusyGanttProxyModel(); ganttModel->setSourceModel(fbModel); ModelTest *modelTest = new ModelTest(ganttModel); Q_UNUSED(modelTest); QVERIFY(ganttModel->rowCount() == 0); const QDateTime dt1(QDate(2010, 8, 24), QTime(7, 0, 0), Qt::UTC); const QDateTime dt2(QDate(2010, 8, 24), QTime(16, 0, 0), Qt::UTC); - KCalCore::Attendee a1(QStringLiteral("fred"), QStringLiteral("fred@example.com")); - KCalCore::FreeBusy::Ptr fb1(new KCalCore::FreeBusy()); + KCalendarCore::Attendee a1(QStringLiteral("fred"), QStringLiteral("fred@example.com")); + KCalendarCore::FreeBusy::Ptr fb1(new KCalendarCore::FreeBusy()); - fb1->addPeriod(dt1, KCalCore::Duration(60 * 60)); - fb1->addPeriod(dt2, KCalCore::Duration(60 * 60)); + fb1->addPeriod(dt1, KCalendarCore::Duration(60 * 60)); + fb1->addPeriod(dt2, KCalendarCore::Duration(60 * 60)); CalendarSupport::FreeBusyItem::Ptr item1(new CalendarSupport::FreeBusyItem(a1, nullptr)); item1->setFreeBusy(fb1); const QDateTime dt3(QDate(2010, 8, 25), QTime(7, 0, 0), Qt::UTC); const QDateTime dt4(QDate(2010, 8, 25), QTime(16, 0, 0), Qt::UTC); - KCalCore::Attendee a2(QStringLiteral("joe"), QStringLiteral("joe@example.com")); - KCalCore::FreeBusy::Ptr fb2(new KCalCore::FreeBusy()); + KCalendarCore::Attendee a2(QStringLiteral("joe"), QStringLiteral("joe@example.com")); + KCalendarCore::FreeBusy::Ptr fb2(new KCalendarCore::FreeBusy()); - fb2->addPeriod(dt3, KCalCore::Duration(60 * 60)); - fb2->addPeriod(dt4, KCalCore::Duration(60 * 60)); + fb2->addPeriod(dt3, KCalendarCore::Duration(60 * 60)); + fb2->addPeriod(dt4, KCalendarCore::Duration(60 * 60)); CalendarSupport::FreeBusyItem::Ptr item2(new CalendarSupport::FreeBusyItem(a2, nullptr)); item2->setFreeBusy(fb2); fbModel->addItem(item1); fbModel->addItem(item2); QCOMPARE(ganttModel->rowCount(), 2); QModelIndex parent0 = ganttModel->index(0, 0); QModelIndex parent1 = ganttModel->index(1, 0); QModelIndex parent2 = ganttModel->index(2, 0); QVERIFY(parent0.isValid()); QVERIFY(parent1.isValid()); QVERIFY(parent2.isValid() == false); QModelIndex source_parent0 = fbModel->index(0, 0); QCOMPARE(parent0.data(), source_parent0.data()); QCOMPARE(parent0.data(KGantt::ItemTypeRole).toInt(), (int)KGantt::TypeMulti); QModelIndex source_parent1 = fbModel->index(1, 0); QCOMPARE(parent1.data(), source_parent1.data()); QCOMPARE(parent1.data(KGantt::ItemTypeRole).toInt(), (int)KGantt::TypeMulti); QModelIndex child0_0 = ganttModel->index(0, 0, parent0); QModelIndex child0_1 = ganttModel->index(1, 0, parent0); QVERIFY(child0_0.isValid()); QVERIFY(child0_1.isValid()); QCOMPARE(child0_0.data(KGantt::ItemTypeRole).toInt(), (int)KGantt::TypeTask); QCOMPARE(child0_0.data(KGantt::StartTimeRole).toDateTime(), dt1); QCOMPARE(child0_1.data(KGantt::ItemTypeRole).toInt(), (int)KGantt::TypeTask); QCOMPARE(child0_1.data(KGantt::StartTimeRole).toDateTime(), dt2); QModelIndex child1_0 = ganttModel->index(0, 0, parent1); QModelIndex child1_1 = ganttModel->index(1, 0, parent1); QVERIFY(child1_0.isValid()); QVERIFY(child1_1.isValid()); QCOMPARE(child1_0.data(KGantt::ItemTypeRole).toInt(), (int)KGantt::TypeTask); QCOMPARE(child1_0.data(KGantt::StartTimeRole).toDateTime(), dt3); QCOMPARE(child1_1.data(KGantt::ItemTypeRole).toInt(), (int)KGantt::TypeTask); QCOMPARE(child1_1.data(KGantt::StartTimeRole).toDateTime(), dt4); } diff --git a/autotests/testindividualmaildialog.cpp b/autotests/testindividualmaildialog.cpp index bd62285..03e3773 100644 --- a/autotests/testindividualmaildialog.cpp +++ b/autotests/testindividualmaildialog.cpp @@ -1,76 +1,76 @@ /* Copyright (c) 2014 Sandro Knauß This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "individualmaildialog.h" #include #include #include using namespace IncidenceEditorNG; class TestIndividualMailDialog : public QObject { Q_OBJECT private Q_SLOTS: void testDialog() { - KCalCore::Attendee::List attendees; + KCalendarCore::Attendee::List attendees; KGuiItem buttonYes = KGuiItem(QStringLiteral("Send Email")); KGuiItem buttonNo = KGuiItem(QStringLiteral("Do not send")); - KCalCore::Attendee attendee1(QStringLiteral("test1"), QStringLiteral("test1@example.com")); - KCalCore::Attendee attendee2(QStringLiteral("test2"), QStringLiteral("test2@example.com")); - KCalCore::Attendee attendee3(QStringLiteral("test3"), QStringLiteral("test3@example.com")); + KCalendarCore::Attendee attendee1(QStringLiteral("test1"), QStringLiteral("test1@example.com")); + KCalendarCore::Attendee attendee2(QStringLiteral("test2"), QStringLiteral("test2@example.com")); + KCalendarCore::Attendee attendee3(QStringLiteral("test3"), QStringLiteral("test3@example.com")); attendees << attendee1 << attendee2 << attendee3; IndividualMailDialog dialog(QStringLiteral("title"), attendees, buttonYes, buttonNo, nullptr); QCOMPARE(dialog.editAttendees().count(), 0); QCOMPARE(dialog.updateAttendees().count(), 3); // Just make sure, that the QCombobox is sorted like we think QComboBox *first = dialog.mAttendeeDecision[0].second; QCOMPARE((IndividualMailDialog::Decisions)first->itemData(0, Qt::UserRole).toInt(), IndividualMailDialog::Update); QCOMPARE((IndividualMailDialog::Decisions)first->itemData(1, Qt::UserRole).toInt(), IndividualMailDialog::NoUpdate); QCOMPARE((IndividualMailDialog::Decisions)first->itemData(2, Qt::UserRole).toInt(), IndividualMailDialog::Edit); // No update for first attendee, other default first->setCurrentIndex(1); QCOMPARE(dialog.editAttendees().count(), 0); QCOMPARE(dialog.updateAttendees().count(), 2); QVERIFY(dialog.updateAttendees().contains(attendee2)); QVERIFY(dialog.updateAttendees().contains(attendee3)); // edit for first attendee, other default first->setCurrentIndex(2); QCOMPARE(dialog.editAttendees().count(), 1); QCOMPARE(dialog.updateAttendees().count(), 2); QCOMPARE(dialog.editAttendees()[0], attendee1); } }; QTEST_MAIN(TestIndividualMailDialog) #include "testindividualmaildialog.moc" diff --git a/src/alarmdialog.cpp b/src/alarmdialog.cpp index 7d90e48..8df9a74 100644 --- a/src/alarmdialog.cpp +++ b/src/alarmdialog.cpp @@ -1,288 +1,288 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "alarmdialog.h" #include "editorconfig.h" #include "ui_alarmdialog.h" #include #include #include #include #include using namespace IncidenceEditorNG; -AlarmDialog::AlarmDialog(KCalCore::Incidence::IncidenceType incidenceType, QWidget *parent) +AlarmDialog::AlarmDialog(KCalendarCore::Incidence::IncidenceType incidenceType, QWidget *parent) : QDialog(parent) , mUi(new Ui::AlarmDialog) , mIncidenceType(incidenceType) , mAllowBeginReminders(true) , mAllowEndReminders(true) { setWindowTitle(i18n("Create a new reminder")); QVBoxLayout *mainLayout = new QVBoxLayout(this); QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, &QDialogButtonBox::accepted, this, &AlarmDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &AlarmDialog::reject); QWidget *mainWidget = new QWidget(this); mUi->setupUi(mainWidget); mainLayout->addWidget(mainWidget); mainLayout->addWidget(buttonBox); const int defaultReminderTime = IncidenceEditorNG::EditorConfig::instance()->reminderTime(); mUi->mAlarmOffset->setValue(defaultReminderTime); int defaultReminderUnits = IncidenceEditorNG::EditorConfig::instance()->reminderTimeUnits(); if (defaultReminderUnits < 0 || defaultReminderUnits > 2) { defaultReminderUnits = 0; // minutes } mUi->mOffsetUnit->setCurrentIndex(defaultReminderUnits); mUi->mSoundFile->setMimeTypeFilters({QStringLiteral("audio/x-wav"), QStringLiteral("audio/x-mp3"), QStringLiteral("application/ogg")}); if (IncidenceEditorNG::EditorConfig::instance()->defaultAudioFileReminders()) { mUi->mSoundFile->setUrl(IncidenceEditorNG::EditorConfig::instance()->audioFilePath()); } fillCombo(); } AlarmDialog::~AlarmDialog() { delete mUi; } -void AlarmDialog::load(const KCalCore::Alarm::Ptr &alarm) +void AlarmDialog::load(const KCalendarCore::Alarm::Ptr &alarm) { if (!alarm) { return; } setWindowTitle(i18n("Edit existing reminder")); // Offsets int offset; int beforeafterpos = 0; if (alarm->hasEndOffset()) { beforeafterpos = 2; offset = alarm->endOffset().asSeconds(); } else { // TODO: Also allow alarms at fixed times, not relative to start/end offset = alarm->startOffset().asSeconds(); } // Negative offset means before the start/end... if (offset < 0) { offset = -offset; } else { ++beforeafterpos; } mUi->mBeforeAfter->setCurrentIndex(beforeafterpos); offset = offset / 60; // make minutes int useoffset = offset; if (offset % (24 * 60) == 0 && offset > 0) { // divides evenly into days? useoffset = offset / (24 * 60); mUi->mOffsetUnit->setCurrentIndex(2); } else if (offset % 60 == 0 && offset > 0) { // divides evenly into hours? useoffset = offset / 60; mUi->mOffsetUnit->setCurrentIndex(1); } else { useoffset = offset; mUi->mOffsetUnit->setCurrentIndex(0); } mUi->mAlarmOffset->setValue(useoffset); // Repeating mUi->mRepeats->setChecked(alarm->repeatCount() > 0); if (alarm->repeatCount() > 0) { mUi->mRepeatCount->setValue(alarm->repeatCount()); mUi->mRepeatInterval->setValue(alarm->snoozeTime().asSeconds() / 60); // show as minutes } int id = 0; switch (alarm->type()) { - case KCalCore::Alarm::Audio: + case KCalendarCore::Alarm::Audio: mUi->mTypeCombo->setCurrentIndex(1); mUi->mSoundFile->setUrl(QUrl::fromLocalFile(alarm->audioFile())); id = 1; break; - case KCalCore::Alarm::Procedure: + case KCalendarCore::Alarm::Procedure: mUi->mTypeCombo->setCurrentIndex(2); mUi->mApplication->setUrl(QUrl::fromLocalFile(alarm->programFile())); mUi->mAppArguments->setText(alarm->programArguments()); id = 2; break; - case KCalCore::Alarm::Email: + case KCalendarCore::Alarm::Email: { mUi->mTypeCombo->setCurrentIndex(3); - KCalCore::Person::List addresses = alarm->mailAddresses(); + KCalendarCore::Person::List addresses = alarm->mailAddresses(); QStringList add; add.reserve(addresses.count()); - const KCalCore::Person::List::ConstIterator end(addresses.constEnd()); - for (KCalCore::Person::List::ConstIterator it = addresses.constBegin(); + const KCalendarCore::Person::List::ConstIterator end(addresses.constEnd()); + for (KCalendarCore::Person::List::ConstIterator it = addresses.constBegin(); it != end; ++it) { add << (*it).fullName(); } mUi->mEmailAddress->setText(add.join(QStringLiteral(", "))); mUi->mEmailText->setPlainText(alarm->mailText()); id = 3; break; } - case KCalCore::Alarm::Display: - case KCalCore::Alarm::Invalid: + case KCalendarCore::Alarm::Display: + case KCalendarCore::Alarm::Invalid: default: mUi->mTypeCombo->setCurrentIndex(0); mUi->mDisplayText->setPlainText(alarm->text()); break; } mUi->mTypeStack->setCurrentIndex(id); if (alarm->audioFile().isEmpty() && IncidenceEditorNG::EditorConfig::instance()->defaultAudioFileReminders()) { mUi->mSoundFile->setUrl(IncidenceEditorNG::EditorConfig::instance()->audioFilePath()); } } -void AlarmDialog::save(const KCalCore::Alarm::Ptr &alarm) const +void AlarmDialog::save(const KCalendarCore::Alarm::Ptr &alarm) const { // Offsets int offset = mUi->mAlarmOffset->value() * 60; // minutes int offsetunit = mUi->mOffsetUnit->currentIndex(); if (offsetunit >= 1) { offset *= 60; // hours } if (offsetunit >= 2) { offset *= 24; // days } if (offsetunit >= 3) { offset *= 7; // weeks } const int beforeafterpos = mUi->mBeforeAfter->currentIndex(); if (beforeafterpos % 2 == 0) { // before -> negative offset = -offset; } // Note: if this triggers, fix the logic at the place causing it. It really makes // no sense to have both disabled. Q_ASSERT(mAllowBeginReminders || mAllowEndReminders); // TODO: Add possibility to specify a given time for the reminder // We assume that if mAllowBeginReminders is not set, that mAllowBeginReminders // is set. if (!mAllowBeginReminders) { // before or after DTDUE - alarm->setEndOffset(KCalCore::Duration(offset)); + alarm->setEndOffset(KCalendarCore::Duration(offset)); } else if (beforeafterpos == 0 || beforeafterpos == 1) { // before or after DTSTART - alarm->setStartOffset(KCalCore::Duration(offset)); + alarm->setStartOffset(KCalendarCore::Duration(offset)); } else if (beforeafterpos == 2 || beforeafterpos == 3) { // before or after DTEND/DTDUE - alarm->setEndOffset(KCalCore::Duration(offset)); + alarm->setEndOffset(KCalendarCore::Duration(offset)); } // Repeating if (mUi->mRepeats->isChecked()) { alarm->setRepeatCount(mUi->mRepeatCount->value()); alarm->setSnoozeTime(mUi->mRepeatInterval->value() * 60); // convert back to seconds } else { alarm->setRepeatCount(0); } if (mUi->mTypeCombo->currentIndex() == 1) { // Audio alarm->setAudioAlarm(mUi->mSoundFile->url().toLocalFile()); } else if (mUi->mTypeCombo->currentIndex() == 2) { // Application / script alarm->setProcedureAlarm(mUi->mApplication->url().toLocalFile(), mUi->mAppArguments->text()); } else if (mUi->mTypeCombo->currentIndex() == 3) { // Email QStringList addresses = KEmailAddress::splitAddressList(mUi->mEmailAddress->text()); - KCalCore::Person::List add; + KCalendarCore::Person::List add; add.reserve(addresses.count()); for (QStringList::Iterator it = addresses.begin(), end = addresses.end(); it != end; ++it) { - add << KCalCore::Person::fromFullName(*it); + add << KCalendarCore::Person::fromFullName(*it); } // TODO: Add a subject line and possibilities for attachments alarm->setEmailAlarm(QString(), mUi->mEmailText->toPlainText(), add); } else { // Display alarm->setDisplayAlarm(mUi->mDisplayText->toPlainText()); } } void AlarmDialog::fillCombo() { QStringList items; - if (mIncidenceType == KCalCore::Incidence::TypeTodo) { + if (mIncidenceType == KCalendarCore::Incidence::TypeTodo) { mUi->mBeforeAfter->clear(); if (mAllowBeginReminders) { items << i18n("Before the to-do starts") << i18n("After the to-do starts"); } if (mAllowEndReminders) { items << i18n("Before the to-do is due") << i18n("After the to-do is due"); } } else { if (mAllowEndReminders) { items << i18n("Before the event starts") << i18n("After the event starts"); } if (mAllowEndReminders) { items << i18n("Before the event ends") << i18n("After the event ends"); } } mUi->mBeforeAfter->clear(); mUi->mBeforeAfter->addItems(items); } void AlarmDialog::setAllowBeginReminders(bool allow) { mAllowBeginReminders = allow; fillCombo(); } void AlarmDialog::setAllowEndReminders(bool allow) { mAllowEndReminders = allow; fillCombo(); } void AlarmDialog::setOffset(int offset) { Q_ASSERT(offset > 0); mUi->mAlarmOffset->setValue(offset); } void AlarmDialog::setUnit(Unit unit) { mUi->mOffsetUnit->setCurrentIndex(unit); } void AlarmDialog::setWhen(When when) { Q_ASSERT(when <= mUi->mBeforeAfter->count()); mUi->mBeforeAfter->setCurrentIndex(when); } diff --git a/src/alarmdialog.h b/src/alarmdialog.h index b0ef63a..e0f44f0 100644 --- a/src/alarmdialog.h +++ b/src/alarmdialog.h @@ -1,76 +1,76 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_ALARMDIALOG_H #define INCIDENCEEDITOR_ALARMDIALOG_H -#include +#include #include namespace Ui { class AlarmDialog; } namespace IncidenceEditorNG { class AlarmDialog : public QDialog { Q_OBJECT public: enum Unit { Minutes, Hours, Days }; enum When { BeforeStart = 0, AfterStart, BeforeEnd, AfterEnd }; public: /** Constructs a new alarm dialog. @p incidenceType will influence i18n strings, that will be different for to-dos. */ - explicit AlarmDialog(KCalCore::Incidence::IncidenceType incidenceType, QWidget *parent = nullptr); + explicit AlarmDialog(KCalendarCore::Incidence::IncidenceType incidenceType, QWidget *parent = nullptr); ~AlarmDialog(); - void load(const KCalCore::Alarm::Ptr &alarm); - void save(const KCalCore::Alarm::Ptr &alarm) const; + void load(const KCalendarCore::Alarm::Ptr &alarm); + void save(const KCalendarCore::Alarm::Ptr &alarm) const; void setAllowBeginReminders(bool allow); void setAllowEndReminders(bool allow); void setOffset(int offset); void setUnit(Unit unit); void setWhen(When when); private: void fillCombo(); private: Ui::AlarmDialog *mUi = nullptr; - KCalCore::Incidence::IncidenceType mIncidenceType; + KCalendarCore::Incidence::IncidenceType mIncidenceType; bool mAllowBeginReminders; bool mAllowEndReminders; }; } #endif // INCIDENCEEDITOR_ALARMDIALOG_H diff --git a/src/alarmpresets.cpp b/src/alarmpresets.cpp index 5b3f218..cdf72e2 100644 --- a/src/alarmpresets.cpp +++ b/src/alarmpresets.cpp @@ -1,251 +1,251 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "alarmpresets.h" #include -#include +#include #include #include "incidenceeditor_debug.h" using namespace CalendarSupport; -using namespace KCalCore; +using namespace KCalendarCore; namespace IncidenceEditorNG { namespace AlarmPresets { // Don't use a map, because order matters Q_GLOBAL_STATIC(QStringList, sBeforeStartPresetNames) Q_GLOBAL_STATIC(QStringList, sBeforeEndPresetNames) -Q_GLOBAL_STATIC(QList, sBeforeStartPresets) -Q_GLOBAL_STATIC(QList, sBeforeEndPresets) +Q_GLOBAL_STATIC(QList, sBeforeStartPresets) +Q_GLOBAL_STATIC(QList, sBeforeEndPresets) static int sDefaultPresetIndex = 0; static int sDefaultAlarmOffset = 0; // We must save it, so we can detect that config changed. int configuredReminderTimeInMinutes() { QList units; units << 1 << 60 << (24 * 60); const int configuredUnits = KCalPrefs::instance()->reminderTimeUnits(); const int unitsToUse = configuredUnits >= 0 && configuredUnits <= 2 ? configuredUnits : 0; const int configuredReminderTime = KCalPrefs::instance()->reminderTime(); const int reminderTimeToUse = configuredReminderTime >= 0 ? configuredReminderTime : DEFAULT_REMINDER_OFFSET; return reminderTimeToUse * units[unitsToUse]; } void initPresets(AlarmPresets::When when) { QList hardcodedPresets; hardcodedPresets << 0 // at start/due << 5 // 5 minutes << 10 << 15 << 30 << 45 << 60 // 1 hour << 2 * 60 // 2 hours << 24 * 60 // 1 day << 2 * 24 * 60 // 2 days << 5 * 24 * 60;// 5 days sDefaultAlarmOffset = configuredReminderTimeInMinutes(); if (!hardcodedPresets.contains(sDefaultAlarmOffset)) { // Lets insert the user's favorite preset (and keep the list sorted): int index; for (index = 0; index < hardcodedPresets.count(); ++index) { if (hardcodedPresets[index] > sDefaultAlarmOffset) { break; } } hardcodedPresets.insert(index, sDefaultAlarmOffset); sDefaultPresetIndex = index; } else { sDefaultPresetIndex = hardcodedPresets.indexOf(sDefaultAlarmOffset); } switch (when) { case AlarmPresets::BeforeStart: for (int i = 0; i < hardcodedPresets.count(); ++i) { - KCalCore::Alarm::Ptr alarm(new KCalCore::Alarm(nullptr)); - alarm->setType(KCalCore::Alarm::Display); + KCalendarCore::Alarm::Ptr alarm(new KCalendarCore::Alarm(nullptr)); + alarm->setType(KCalendarCore::Alarm::Display); const int minutes = hardcodedPresets[i]; alarm->setStartOffset(-minutes * 60); alarm->setEnabled(true); if (minutes == 0) { sBeforeStartPresetNames->append(i18nc("@item:inlistbox", "At start")); } else if (minutes < 60) { sBeforeStartPresetNames->append(i18ncp("@item:inlistbox", "%1 minute before start", "%1 minutes before start", minutes)); } else if (minutes < 24 * 60) { sBeforeStartPresetNames->append(i18ncp("@item:inlistbox", "%1 hour before start", "%1 hours before start", minutes / 60)); } else { sBeforeStartPresetNames->append(i18ncp("@item:inlistbox", "%1 day before start", "%1 days before start", minutes / (24 * 60))); } sBeforeStartPresets->append(alarm); } break; case AlarmPresets::BeforeEnd: for (int i = 0; i < hardcodedPresets.count(); ++i) { - KCalCore::Alarm::Ptr alarm(new KCalCore::Alarm(nullptr)); - alarm->setType(KCalCore::Alarm::Display); + KCalendarCore::Alarm::Ptr alarm(new KCalendarCore::Alarm(nullptr)); + alarm->setType(KCalendarCore::Alarm::Display); const int minutes = hardcodedPresets[i]; alarm->setEndOffset(-minutes * 60); alarm->setEnabled(true); if (minutes == 0) { sBeforeEndPresetNames->append(i18nc("@item:inlistbox", "When due")); } else if (minutes < 60) { sBeforeEndPresetNames->append(i18ncp("@item:inlistbox", "%1 minute before due", "%1 minutes before due", minutes)); } else if (minutes < 24 * 60) { sBeforeEndPresetNames->append(i18ncp("@item:inlistbox", "%1 hour before due", "%1 hours before due", minutes / 60)); } else { sBeforeEndPresetNames->append(i18ncp("@item:inlistbox", "%1 day before due", "%1 days before due", minutes / (24 * 60))); } sBeforeEndPresets->append(alarm); } break; } } void checkInitNeeded(When when) { const int currentAlarmOffset = configuredReminderTimeInMinutes(); const bool configChanged = currentAlarmOffset != sDefaultAlarmOffset; switch (when) { case AlarmPresets::BeforeStart: if (sBeforeStartPresetNames->isEmpty() || configChanged) { sBeforeStartPresetNames->clear(); sBeforeStartPresets->clear(); initPresets(when); } break; case AlarmPresets::BeforeEnd: if (sBeforeEndPresetNames->isEmpty() || configChanged) { sBeforeEndPresetNames->clear(); sBeforeEndPresets->clear(); initPresets(when); } break; default: Q_ASSERT_X(false, "checkInitNeeded", "Unknown preset type"); } } QStringList availablePresets(AlarmPresets::When when) { checkInitNeeded(when); switch (when) { case AlarmPresets::BeforeStart: return *sBeforeStartPresetNames; case AlarmPresets::BeforeEnd: return *sBeforeEndPresetNames; } return QStringList(); } -KCalCore::Alarm::Ptr preset(When when, const QString &name) +KCalendarCore::Alarm::Ptr preset(When when, const QString &name) { checkInitNeeded(when); switch (when) { case AlarmPresets::BeforeStart: // The name should exists and only once if (sBeforeStartPresetNames->count(name) != 1) { // print some debug info before crashing qCDebug(INCIDENCEEDITOR_LOG) << " name = " << name << "; when = " << when << "; count for name = " << sBeforeStartPresetNames->count( name) << "; global count = " << sBeforeStartPresetNames->count(); Q_ASSERT_X(false, "preset", "Number of presets should be one"); } - return KCalCore::Alarm::Ptr( - new KCalCore::Alarm(*sBeforeStartPresets->at(sBeforeStartPresetNames->indexOf(name)))); + return KCalendarCore::Alarm::Ptr( + new KCalendarCore::Alarm(*sBeforeStartPresets->at(sBeforeStartPresetNames->indexOf(name)))); case AlarmPresets::BeforeEnd: Q_ASSERT(sBeforeEndPresetNames->count(name) == 1); // The name should exists and only once - return KCalCore::Alarm::Ptr( - new KCalCore::Alarm(*sBeforeEndPresets->at(sBeforeEndPresetNames->indexOf(name)))); + return KCalendarCore::Alarm::Ptr( + new KCalendarCore::Alarm(*sBeforeEndPresets->at(sBeforeEndPresetNames->indexOf(name)))); } - return KCalCore::Alarm::Ptr(); + return KCalendarCore::Alarm::Ptr(); } -KCalCore::Alarm::Ptr defaultAlarm(When when) +KCalendarCore::Alarm::Ptr defaultAlarm(When when) { checkInitNeeded(when); switch (when) { case AlarmPresets::BeforeStart: return Alarm::Ptr(new Alarm(*sBeforeStartPresets->at(sDefaultPresetIndex))); case AlarmPresets::BeforeEnd: return Alarm::Ptr(new Alarm(*sBeforeEndPresets->at(sDefaultPresetIndex))); } return Alarm::Ptr(); } -int presetIndex(When when, const KCalCore::Alarm::Ptr &alarm) +int presetIndex(When when, const KCalendarCore::Alarm::Ptr &alarm) { checkInitNeeded(when); const QStringList presets = availablePresets(when); for (int i = 0; i < presets.size(); ++i) { - KCalCore::Alarm::Ptr presetAlarm(preset(when, presets.at(i))); + KCalendarCore::Alarm::Ptr presetAlarm(preset(when, presets.at(i))); if (presetAlarm == alarm) { return i; } } return -1; } int defaultPresetIndex() { // BeforeEnd would do too, index is the same. checkInitNeeded(AlarmPresets::BeforeStart); return sDefaultPresetIndex; } } // AlarmPresets } // IncidenceEditorNG diff --git a/src/alarmpresets.h b/src/alarmpresets.h index 4ad9796..8612e21 100644 --- a/src/alarmpresets.h +++ b/src/alarmpresets.h @@ -1,73 +1,73 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_ALARMPRESETS_H #define INCIDENCEEDITOR_ALARMPRESETS_H -#include +#include class QStringList; namespace IncidenceEditorNG { enum { // Fallback in case config is invalid DEFAULT_REMINDER_OFFSET = 15 // minutes }; namespace AlarmPresets { enum When { BeforeStart, BeforeEnd }; /** * Returns the available presets. */ Q_REQUIRED_RESULT QStringList availablePresets(When when = BeforeStart); /** * Returns a recurrence preset for given name. The name must be one * of availablePresets(). * * Note: The caller takes ownership over the pointer. */ -Q_REQUIRED_RESULT KCalCore::Alarm::Ptr preset(When when, const QString &name); +Q_REQUIRED_RESULT KCalendarCore::Alarm::Ptr preset(When when, const QString &name); /** * Returns an Alarm configured accordingly to the default preset. * * Note: The caller takes ownership over the pointer. */ -Q_REQUIRED_RESULT KCalCore::Alarm::Ptr defaultAlarm(When when); +Q_REQUIRED_RESULT KCalendarCore::Alarm::Ptr defaultAlarm(When when); /** * Returns the index of the preset in availablePresets for the given recurrence, * or -1 if no preset is equal to the given recurrence. */ -Q_REQUIRED_RESULT int presetIndex(When when, const KCalCore::Alarm::Ptr &alarm); +Q_REQUIRED_RESULT int presetIndex(When when, const KCalendarCore::Alarm::Ptr &alarm); /** Returns the index of the default preset. ( Comes from KCalPrefs ). */ Q_REQUIRED_RESULT int defaultPresetIndex(); } } #endif // INCIDENCEEDITOR_ALARMPRESETS_H diff --git a/src/attachmenteditdialog.cpp b/src/attachmenteditdialog.cpp index 3a4f149..327672d 100644 --- a/src/attachmenteditdialog.cpp +++ b/src/attachmenteditdialog.cpp @@ -1,189 +1,189 @@ /* Copyright (c) 2003 Cornelius Schumacher Copyright (C) 2005 Reinhold Kainhofer Copyright (c) 2005 Rafal Rzepecki Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company 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. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #include "attachmenteditdialog.h" #include "attachmenticonview.h" #include "ui_attachmenteditdialog.h" #include #include #include #include #include #include #include using namespace IncidenceEditorNG; AttachmentEditDialog::AttachmentEditDialog(AttachmentIconItem *item, QWidget *parent, bool modal) : QDialog(parent) , #ifdef KDEPIM_ENTERPRISE_BUILD - mAttachment(KCalCore::Attachment('\0')) + mAttachment(KCalendarCore::Attachment('\0')) //use the non-uri constructor // as we want inline by default #else - mAttachment(KCalCore::Attachment(QString())) + mAttachment(KCalendarCore::Attachment(QString())) #endif , mItem(item) , mUi(new Ui::AttachmentEditDialog) { setWindowTitle(i18n("Edit Attachment")); QMimeDatabase db; mMimeType = db.mimeTypeForName(item->mimeType()); QWidget *page = new QWidget(this); QVBoxLayout *mainLayout = new QVBoxLayout(this); QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); mOkButton = buttonBox->button(QDialogButtonBox::Ok); mOkButton->setDefault(true); mOkButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, &QDialogButtonBox::accepted, this, &AttachmentEditDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &AttachmentEditDialog::reject); mainLayout->addWidget(page); mainLayout->addWidget(buttonBox); mUi->setupUi(page); mUi->mLabelEdit->setText(item->label().isEmpty() ? item->uri() : item->label()); mUi->mIcon->setPixmap(item->icon()); mUi->mInlineCheck->setChecked(item->isBinary()); const QString typecomment = item->mimeType().isEmpty() ? i18nc("@label unknown mimetype", "Unknown") : mMimeType.comment(); mUi->mTypeLabel->setText(typecomment); setModal(modal); mOkButton->setEnabled(false); mUi->mInlineCheck->setEnabled(false); if (item->attachment().isUri() || item->attachment().data().isEmpty()) { mUi->mStackedWidget->setCurrentIndex(0); mUi->mURLRequester->setUrl(QUrl(item->uri())); urlChanged(item->uri()); } else { mUi->mInlineCheck->setEnabled(true); mUi->mStackedWidget->setCurrentIndex(1); mUi->mSizeLabel->setText(QStringLiteral("%1 (%2)"). arg(KIO::convertSize(item->attachment().size()), QLocale().toString(item->attachment().size()))); } connect(mUi->mInlineCheck, &QCheckBox::stateChanged, this, &AttachmentEditDialog::inlineChanged); connect(mUi->mURLRequester, qOverload(&KUrlRequester::urlSelected), this, static_cast(&AttachmentEditDialog:: urlChanged)); connect(mUi->mURLRequester, &KUrlRequester::textChanged, this, static_cast(&AttachmentEditDialog:: urlChanged)); } AttachmentEditDialog::~AttachmentEditDialog() { delete mUi; } void AttachmentEditDialog::accept() { slotApply(); QDialog::accept(); } void AttachmentEditDialog::slotApply() { QUrl url = mUi->mURLRequester->url(); if (mUi->mLabelEdit->text().isEmpty()) { if (url.isLocalFile()) { mItem->setLabel(url.fileName()); } else { mItem->setLabel(url.url()); } } else { mItem->setLabel(mUi->mLabelEdit->text()); } if (mItem->label().isEmpty()) { mItem->setLabel(i18nc("@label", "New attachment")); } mItem->setMimeType(mMimeType.name()); QString correctedUrl = url.url(); if (!url.isEmpty() && url.isRelative()) { // If the user used KURLRequester's KURLCompletion // (used the line edit instead of the file dialog) // the returned url is not absolute and is always relative // to the home directory (not pwd), so we must prepend home correctedUrl = QDir::home().filePath(url.toLocalFile()); url = QUrl::fromLocalFile(correctedUrl); if (url.isValid()) { urlChanged(url); mItem->setLabel(url.fileName()); mItem->setUri(correctedUrl); mItem->setMimeType(mMimeType.name()); } } if (mUi->mStackedWidget->currentIndex() == 0) { if (mUi->mInlineCheck->isChecked()) { auto job = KIO::storedGet(url); KJobWidgets::setWindow(job, nullptr); if (job->exec()) { QByteArray data = job->data(); mItem->setData(data); } } else { mItem->setUri(correctedUrl); } } } void AttachmentEditDialog::inlineChanged(int state) { mOkButton->setEnabled(!mUi->mURLRequester->url().toDisplayString().trimmed().isEmpty() || mUi->mStackedWidget->currentIndex() == 1); if (state == Qt::Unchecked && mUi->mStackedWidget->currentIndex() == 1) { mUi->mStackedWidget->setCurrentIndex(0); if (!mItem->savedUri().isEmpty()) { mUi->mURLRequester->setUrl(QUrl(mItem->savedUri())); } else { mUi->mURLRequester->setUrl(QUrl(mItem->uri())); } } } void AttachmentEditDialog::urlChanged(const QString &url) { const bool urlIsNotEmpty = !url.trimmed().isEmpty(); mOkButton->setEnabled(urlIsNotEmpty); mUi->mInlineCheck->setEnabled(urlIsNotEmpty || mUi->mStackedWidget->currentIndex() == 1); } void AttachmentEditDialog::urlChanged(const QUrl &url) { QMimeDatabase db; mMimeType = db.mimeTypeForUrl(url); mUi->mTypeLabel->setText(mMimeType.comment()); mUi->mIcon->setPixmap(AttachmentIconItem::icon(mMimeType, url.path())); } diff --git a/src/attachmenteditdialog.h b/src/attachmenteditdialog.h index 9b957dc..ab8758e 100644 --- a/src/attachmenteditdialog.h +++ b/src/attachmenteditdialog.h @@ -1,67 +1,67 @@ /* Copyright (c) 2003 Cornelius Schumacher Copyright (C) 2005 Reinhold Kainhofer Copyright (c) 2005 Rafal Rzepecki Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company 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. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #ifndef INCIDENCEEDITOR_ATTACHMENTEDITDIALOG_H #define INCIDENCEEDITOR_ATTACHMENTEDITDIALOG_H -#include +#include #include #include #include class QPushButton; namespace Ui { class AttachmentEditDialog; } namespace IncidenceEditorNG { class AttachmentIconItem; class AttachmentEditDialog : public QDialog { Q_OBJECT public: AttachmentEditDialog(AttachmentIconItem *item, QWidget *parent, bool modal = true); ~AttachmentEditDialog() override; void accept() override; protected Q_SLOTS: void inlineChanged(int state); void urlChanged(const QUrl &url); void urlChanged(const QString &url); virtual void slotApply(); private: - KCalCore::Attachment mAttachment; + KCalendarCore::Attachment mAttachment; AttachmentIconItem *mItem = nullptr; QMimeType mMimeType; Ui::AttachmentEditDialog *mUi = nullptr; QPushButton *mOkButton = nullptr; }; } #endif // INCIDENCEEDITOR_ATTACHMENTEDITDIALOG_H diff --git a/src/attachmenticonview.cpp b/src/attachmenticonview.cpp index fb3f909..7afab98 100644 --- a/src/attachmenticonview.cpp +++ b/src/attachmenticonview.cpp @@ -1,283 +1,283 @@ /* Copyright (c) 2003 Cornelius Schumacher Copyright (C) 2005 Reinhold Kainhofer Copyright (c) 2005 Rafal Rzepecki Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company 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. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. NOTE: May, 2010. Extracted this code from kdepim/incidenceeditors/editorattachments.{h,cpp} */ #include #include "attachmenticonview.h" #include #include #include #include #include #include #include #include #include #include using namespace IncidenceEditorNG; -AttachmentIconItem::AttachmentIconItem(const KCalCore::Attachment &att, QListWidget *parent) +AttachmentIconItem::AttachmentIconItem(const KCalendarCore::Attachment &att, QListWidget *parent) : QListWidgetItem(parent) { if (!att.isEmpty()) { mAttachment = att; } else { // for the enterprise, inline attachments are the default #ifdef KDEPIM_ENTERPRISE_BUILD - mAttachment = KCalCore::Attachment(QByteArray()); // use the non-uri constructor + mAttachment = KCalendarCore::Attachment(QByteArray()); // use the non-uri constructor // as we want inline by default #else - mAttachment = KCalCore::Attachment(QString()); + mAttachment = KCalendarCore::Attachment(QString()); #endif } readAttachment(); setFlags(flags() | Qt::ItemIsDragEnabled); } AttachmentIconItem::~AttachmentIconItem() { } -KCalCore::Attachment AttachmentIconItem::attachment() const +KCalendarCore::Attachment AttachmentIconItem::attachment() const { return mAttachment; } const QString AttachmentIconItem::uri() const { return mAttachment.uri(); } const QString AttachmentIconItem::savedUri() const { return mSaveUri; } void AttachmentIconItem::setUri(const QString &uri) { mSaveUri = uri; mAttachment.setUri(mSaveUri); readAttachment(); } void AttachmentIconItem::setData(const QByteArray &data) { mAttachment.setDecodedData(data); readAttachment(); } const QString AttachmentIconItem::mimeType() const { return mAttachment.mimeType(); } void AttachmentIconItem::setMimeType(const QString &mime) { mAttachment.setMimeType(mime); readAttachment(); } const QString AttachmentIconItem::label() const { return mAttachment.label(); } void AttachmentIconItem::setLabel(const QString &description) { if (mAttachment.label() == description) { return; } mAttachment.setLabel(description); readAttachment(); } bool AttachmentIconItem::isBinary() const { return mAttachment.isBinary(); } QPixmap AttachmentIconItem::icon() const { QMimeDatabase db; return icon(db.mimeTypeForName(mAttachment.mimeType()), mAttachment.uri(), mAttachment.isBinary()); } QPixmap AttachmentIconItem::icon(const QMimeType &mimeType, const QString &uri, bool binary) { QString iconStr = mimeType.iconName(); QStringList overlays; if (!uri.isEmpty() && !binary) { overlays << QStringLiteral("emblem-link"); } return QIcon(new KIconEngine(iconStr, KIconLoader::global(), overlays)).pixmap( KIconLoader::SizeSmallMedium, KIconLoader::SizeSmallMedium); } void AttachmentIconItem::readAttachment() { setText(mAttachment.label()); setFlags(flags() | Qt::ItemIsEditable); QMimeDatabase db; if (mAttachment.mimeType().isEmpty() || !(db.mimeTypeForName(mAttachment.mimeType()).isDefault())) { QMimeType mimeType; if (mAttachment.isUri()) { mimeType = db.mimeTypeForUrl(QUrl(mAttachment.uri())); } else { mimeType = db.mimeTypeForData(mAttachment.decodedData()); } mAttachment.setMimeType(mimeType.name()); } setIcon(icon()); } AttachmentIconView::AttachmentIconView(QWidget *parent) : QListWidget(parent) { setMovement(Static); setAcceptDrops(true); setSelectionMode(ExtendedSelection); setSelectionRectVisible(false); setIconSize(QSize(KIconLoader::SizeLarge, KIconLoader::SizeLarge)); setFlow(LeftToRight); setWrapping(true); #ifndef QT_NO_DRAGANDDROP setDragDropMode(DragDrop); setDragEnabled(true); #endif setEditTriggers(EditKeyPressed); setContextMenuPolicy(Qt::CustomContextMenu); } QUrl AttachmentIconItem::tempFileForAttachment() { if (mTempFile.isValid()) { return mTempFile; } QTemporaryFile *file = nullptr; QMimeDatabase db; QStringList patterns = db.mimeTypeForName(mAttachment.mimeType()).globPatterns(); if (!patterns.empty()) { file = new QTemporaryFile(QDir::tempPath() + QLatin1String( "/attachementview_XXXXX") + patterns.first().remove(QLatin1Char('*'))); } else { file = new QTemporaryFile(); } file->setParent(listWidget()); file->setAutoRemove(true); file->open(); // read-only not to give the idea that it could be written to file->setPermissions(QFile::ReadUser); file->write(QByteArray::fromBase64(mAttachment.data())); mTempFile = QUrl::fromLocalFile(file->fileName()); file->close(); return mTempFile; } QMimeData *AttachmentIconView::mimeData(const QList< QListWidgetItem *> items) const { // create a list of the URL:s that we want to drag QList urls; QStringList labels; for (QListWidgetItem *it : items) { if (it->isSelected()) { AttachmentIconItem *item = static_cast(it); if (item->isBinary()) { urls.append(item->tempFileForAttachment()); } else { urls.append(QUrl(item->uri())); } labels.append(QString::fromLatin1(QUrl::toPercentEncoding(item->label()))); } } if (selectionMode() == NoSelection) { AttachmentIconItem *item = static_cast(currentItem()); if (item) { urls.append(QUrl(item->uri())); labels.append(QString::fromLatin1(QUrl::toPercentEncoding(item->label()))); } } QMap metadata; metadata[QStringLiteral("labels")] = labels.join(QLatin1Char(':')); QMimeData *mimeData = new QMimeData; mimeData->setUrls(urls); KUrlMimeData::setMetaData(metadata, mimeData); return mimeData; } QMimeData *AttachmentIconView::mimeData() const { return mimeData(selectedItems()); } void AttachmentIconView::startDrag(Qt::DropActions supportedActions) { Q_UNUSED(supportedActions); #ifndef QT_NO_DRAGANDDROP QPixmap pixmap; if (selectedItems().size() > 1) { pixmap = KIconLoader::global()->loadIcon(QStringLiteral( "mail-attachment"), KIconLoader::Desktop); } if (pixmap.isNull()) { pixmap = static_cast(currentItem())->icon(); } const QPoint hotspot(pixmap.width() / 2, pixmap.height() / 2); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData()); drag->setPixmap(pixmap); drag->setHotSpot(hotspot); drag->exec(Qt::CopyAction); #endif } void AttachmentIconView::keyPressEvent(QKeyEvent *event) { if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && currentItem() && state() != EditingState) { Q_EMIT itemDoubleClicked(currentItem()); // ugly, but itemActivated() also includes single click return; } QListWidget::keyPressEvent(event); } diff --git a/src/attachmenticonview.h b/src/attachmenticonview.h index d05f8f0..a82d4ab 100644 --- a/src/attachmenticonview.h +++ b/src/attachmenticonview.h @@ -1,93 +1,93 @@ /* Copyright (c) 2003 Cornelius Schumacher Copyright (C) 2005 Reinhold Kainhofer Copyright (c) 2005 Rafal Rzepecki Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company 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. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. NOTE: May, 2010. Extracted this code from kdepim/incidenceeditors/editorattachments.{h,cpp} */ #ifndef INCIDENCEEDITOR_ATTACHMENTICONVIEW_H #define INCIDENCEEDITOR_ATTACHMENTICONVIEW_H -#include +#include #include #include #include namespace IncidenceEditorNG { class AttachmentIconView : public QListWidget { Q_OBJECT friend class EditorAttachments; public: explicit AttachmentIconView(QWidget *parent = nullptr); Q_REQUIRED_RESULT QMimeData *mimeData() const; protected: QMimeData *mimeData(const QList items) const override; void startDrag(Qt::DropActions supportedActions) override; void keyPressEvent(QKeyEvent *event) override; }; class AttachmentIconItem : public QListWidgetItem { public: - AttachmentIconItem(const KCalCore::Attachment &att, QListWidget *parent); + AttachmentIconItem(const KCalendarCore::Attachment &att, QListWidget *parent); ~AttachmentIconItem(); - KCalCore::Attachment attachment() const; + KCalendarCore::Attachment attachment() const; Q_REQUIRED_RESULT const QString uri() const; Q_REQUIRED_RESULT const QString savedUri() const; void setUri(const QString &uri); using QListWidgetItem::setData; void setData(const QByteArray &data); Q_REQUIRED_RESULT const QString mimeType() const; void setMimeType(const QString &mime); Q_REQUIRED_RESULT const QString label() const; void setLabel(const QString &description); Q_REQUIRED_RESULT bool isBinary() const; static QPixmap icon(const QMimeType &mimeType, const QString &uri, bool binary = false); Q_REQUIRED_RESULT QPixmap icon() const; void readAttachment(); Q_REQUIRED_RESULT QUrl tempFileForAttachment(); private: - KCalCore::Attachment mAttachment; + KCalendarCore::Attachment mAttachment; QString mSaveUri; QUrl mTempFile; }; } #endif // INCIDENCEEDITOR_ATTACHMENTICONVIEW_H diff --git a/src/attendeedata.cpp b/src/attendeedata.cpp index b2cd57d..188be8d 100644 --- a/src/attendeedata.cpp +++ b/src/attendeedata.cpp @@ -1,43 +1,43 @@ /* Copyright (C) 2010 Casey Link Copyright (C) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "attendeedata.h" using namespace IncidenceEditorNG; void AttendeeData::clear() { setName(QString()); setEmail(QString()); setRole(Attendee::ReqParticipant); setStatus(Attendee::None); setRSVP(false); setUid(QString()); } bool AttendeeData::isEmpty() const { return name().isEmpty() && email().isEmpty(); } -KCalCore::Attendee AttendeeData::attendee() const +KCalendarCore::Attendee AttendeeData::attendee() const { - return KCalCore::Attendee(*this); + return KCalendarCore::Attendee(*this); } diff --git a/src/attendeedata.h b/src/attendeedata.h index efd1071..421d9cf 100644 --- a/src/attendeedata.h +++ b/src/attendeedata.h @@ -1,55 +1,55 @@ /* Copyright (C) 2010 Casey Link Copyright (C) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_ATTENDEEDATA_H #define INCIDENCEEDITOR_ATTENDEEDATA_H #include -#include +#include namespace IncidenceEditorNG { -class AttendeeData : public KPIM::MultiplyingLineData, public KCalCore::Attendee +class AttendeeData : public KPIM::MultiplyingLineData, public KCalendarCore::Attendee { public: typedef QSharedPointer Ptr; typedef QList List; AttendeeData(const QString &name, const QString &email, bool rsvp = false, Attendee::PartStat status = Attendee::None, Attendee::Role role = Attendee::ReqParticipant, const QString &uid = QString()) - : KCalCore::Attendee(name, email, rsvp, status, role, uid) + : KCalendarCore::Attendee(name, email, rsvp, status, role, uid) { } - explicit AttendeeData(const KCalCore::Attendee &attendee) : KCalCore::Attendee(attendee) + explicit AttendeeData(const KCalendarCore::Attendee &attendee) : KCalendarCore::Attendee(attendee) { } void clear() override; Q_REQUIRED_RESULT bool isEmpty() const override; /** * Return a copy of the attendee data */ - Q_REQUIRED_RESULT KCalCore::Attendee attendee() const; + Q_REQUIRED_RESULT KCalendarCore::Attendee attendee() const; }; } #endif // INCIDENCEEDITOR_ATTENDEEDATA_H diff --git a/src/attendeeeditor.cpp b/src/attendeeeditor.cpp index e8b0786..3f32f4e 100644 --- a/src/attendeeeditor.cpp +++ b/src/attendeeeditor.cpp @@ -1,102 +1,102 @@ /* Copyright (C) 2010 Casey Link Copyright (C) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "attendeeeditor.h" #include "incidenceeditor_debug.h" using namespace IncidenceEditorNG; AttendeeEditor::AttendeeEditor(QWidget *parent) : MultiplyingLineEditor(new AttendeeLineFactory(parent), parent) { connect(this, &AttendeeEditor::lineAdded, this, &AttendeeEditor::slotLineAdded); addData(); } void AttendeeEditor::slotLineAdded(KPIM::MultiplyingLine *line) { AttendeeLine *att = qobject_cast(line); if (!att) { return; } connect(att, qOverload<>(&AttendeeLine::changed), this, &AttendeeEditor::slotCalculateTotal); - connect(att, qOverload(&AttendeeLine:: changed), this, &AttendeeEditor::changed); + connect(att, qOverload(&AttendeeLine:: changed), this, &AttendeeEditor::changed); connect(att, &AttendeeLine::editingFinished, this, &AttendeeEditor::editingFinished); } void AttendeeEditor::slotCalculateTotal() { int empty = 0; int count = 0; const QList listLines = lines(); for (KPIM::MultiplyingLine *line : listLines) { AttendeeLine *att = qobject_cast(line); if (att) { if (att->isEmpty()) { ++empty; } else { ++count; } } } Q_EMIT countChanged(count); // We always want at least one empty line if (empty == 0) { addData(); } } AttendeeData::List AttendeeEditor::attendees() const { const QList dataList = allData(); AttendeeData::List attList; //qCDebug(INCIDENCEEDITOR_LOG) << "num attendees:" << dataList.size(); for (const KPIM::MultiplyingLineData::Ptr &datum : dataList) { AttendeeData::Ptr att = qSharedPointerDynamicCast(datum); if (!att) { continue; } attList << att; } return attList; } -void AttendeeEditor::addAttendee(const KCalCore::Attendee &attendee) +void AttendeeEditor::addAttendee(const KCalendarCore::Attendee &attendee) { addData(AttendeeData::Ptr(new AttendeeData(attendee))); } void AttendeeEditor::removeAttendee(const AttendeeData::Ptr &attendee) { removeData(attendee); } void AttendeeEditor::setActions(AttendeeLine::AttendeeActions actions) { const QList listLines = lines(); for (KPIM::MultiplyingLine *line : listLines) { AttendeeLine *att = qobject_cast(line); att->setActions(actions); } } diff --git a/src/attendeeeditor.h b/src/attendeeeditor.h index 8fcc0b1..76754a2 100644 --- a/src/attendeeeditor.h +++ b/src/attendeeeditor.h @@ -1,68 +1,68 @@ /* Copyright (C) 2010 Casey Link Copyright (C) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_ATTENDEEEDITOR_H #define INCIDENCEEDITOR_ATTENDEEEDITOR_H #include "attendeeline.h" #include "attendeedata.h" #include namespace IncidenceEditorNG { class AttendeeLineFactory : public KPIM::MultiplyingLineFactory { Q_OBJECT public: explicit AttendeeLineFactory(QObject *parent) : KPIM::MultiplyingLineFactory(parent) { } KPIM::MultiplyingLine *newLine(QWidget *parent) override { return new AttendeeLine(parent); } }; class AttendeeEditor : public KPIM::MultiplyingLineEditor { Q_OBJECT public: explicit AttendeeEditor(QWidget *parent = nullptr); AttendeeData::List attendees() const; - void addAttendee(const KCalCore::Attendee &attendee); + void addAttendee(const KCalendarCore::Attendee &attendee); void removeAttendee(const AttendeeData::Ptr &attendee); void setActions(AttendeeLine::AttendeeActions actions); Q_SIGNALS: void countChanged(int); - void changed(const KCalCore::Attendee &oldAttendee, const KCalCore::Attendee &newAttendee); + void changed(const KCalendarCore::Attendee &oldAttendee, const KCalendarCore::Attendee &newAttendee); void editingFinished(KPIM::MultiplyingLine *); protected Q_SLOTS: void slotLineAdded(KPIM::MultiplyingLine *); void slotCalculateTotal(); }; } #endif diff --git a/src/attendeeline.cpp b/src/attendeeline.cpp index 106be01..30e3bad 100644 --- a/src/attendeeline.cpp +++ b/src/attendeeline.cpp @@ -1,411 +1,411 @@ /* Copyright (C) 2010 Casey Link Copyright (c) 2009-2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "attendeeline.h" #include "attendeedata.h" #include #include #include #include "incidenceeditor_debug.h" #include #include #include #include using namespace IncidenceEditorNG; typedef QPair TextIconPair; AttendeeComboBox::AttendeeComboBox(QWidget *parent) : QToolButton(parent) , mMenu(new QMenu(this)) , mCurrentIndex(-1) { setPopupMode(QToolButton::InstantPopup); setToolButtonStyle(Qt::ToolButtonIconOnly); setMenu(mMenu); } void AttendeeComboBox::addItem(const QIcon &icon, const QString &text) { mList.append(TextIconPair(text, icon)); if (mCurrentIndex == -1) { setCurrentIndex(0); } int index = mList.size() - 1; QAction *act = menu()->addAction(icon, text, this, &AttendeeComboBox::slotActionTriggered); act->setData(index); } void AttendeeComboBox::addItems(const QStringList &texts) { for (const QString &str : texts) { addItem(QIcon(), str); } if (mCurrentIndex == -1) { setCurrentIndex(0); } } int AttendeeComboBox::currentIndex() const { return mCurrentIndex; } void AttendeeComboBox::clear() { mCurrentIndex = -1; mMenu->clear(); mList.clear(); } void AttendeeComboBox::setCurrentIndex(int index) { Q_ASSERT(index < mList.size()); const int old = mCurrentIndex; mCurrentIndex = index; setIcon(mList.at(index).second); setToolTip(mList.at(index).first); if (old != index) { Q_EMIT itemChanged(); } } void AttendeeComboBox::slotActionTriggered() { int index = qobject_cast(sender())->data().toInt(); setCurrentIndex(index); } void AttendeeComboBox::keyPressEvent(QKeyEvent *ev) { if (ev->key() == Qt::Key_Left) { Q_EMIT leftPressed(); } else if (ev->key() == Qt::Key_Right) { Q_EMIT rightPressed(); } else if (!mMenu->isVisible() && ( ev->key() == Qt::Key_Down || ev->key() == Qt::Key_Space)) { showMenu(); } else { QToolButton::keyPressEvent(ev); } } AttendeeLineEdit::AttendeeLineEdit(QWidget *parent) : AddresseeLineEdit(parent, true) { } void AttendeeLineEdit::keyPressEvent(QKeyEvent *ev) { if ((ev->key() == Qt::Key_Enter || ev->key() == Qt::Key_Return) && !completionBox()->isVisible()) { Q_EMIT downPressed(); KPIM::AddresseeLineEdit::keyPressEvent(ev); } else if (ev->key() == Qt::Key_Backspace && text().isEmpty()) { ev->accept(); Q_EMIT deleteMe(); } else if (ev->key() == Qt::Key_Left && cursorPosition() == 0 && !ev->modifiers().testFlag(Qt::ShiftModifier)) { // Shift would be pressed during selection Q_EMIT leftPressed(); } else if (ev->key() == Qt::Key_Right && cursorPosition() == text().length() && !ev->modifiers().testFlag(Qt::ShiftModifier)) { // Shift would be pressed during selection Q_EMIT rightPressed(); } else if (ev->key() == Qt::Key_Down) { Q_EMIT downPressed(); } else if (ev->key() == Qt::Key_Up) { Q_EMIT upPressed(); } else { KPIM::AddresseeLineEdit::keyPressEvent(ev); } } AttendeeLine::AttendeeLine(QWidget *parent) : MultiplyingLine(parent) , mRoleCombo(new AttendeeComboBox(this)) , mStateCombo(new AttendeeComboBox(this)) , mResponseCombo(new AttendeeComboBox(this)) , mEdit(new AttendeeLineEdit(this)) , mData(new AttendeeData(QString(), QString())) , mModified(false) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); QBoxLayout *topLayout = new QHBoxLayout(this); topLayout->setContentsMargins(0, 0, 0, 0); mRoleCombo->addItem(QIcon::fromTheme(QStringLiteral("meeting-participant")), - KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::ReqParticipant)); + KCalUtils::Stringify::attendeeRole(KCalendarCore::Attendee::ReqParticipant)); mRoleCombo->addItem(QIcon::fromTheme(QStringLiteral("meeting-participant-optional")), - KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::OptParticipant)); + KCalUtils::Stringify::attendeeRole(KCalendarCore::Attendee::OptParticipant)); mRoleCombo->addItem(QIcon::fromTheme(QStringLiteral("meeting-observer")), - KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::NonParticipant)); + KCalUtils::Stringify::attendeeRole(KCalendarCore::Attendee::NonParticipant)); mRoleCombo->addItem(QIcon::fromTheme(QStringLiteral("meeting-chair")), - KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::Chair)); + KCalUtils::Stringify::attendeeRole(KCalendarCore::Attendee::Chair)); mResponseCombo->addItem(QIcon::fromTheme(QStringLiteral( "meeting-participant-request-response")), i18nc("@item:inlistbox", "Request Response")); mResponseCombo->addItem(QIcon::fromTheme(QStringLiteral("meeting-participant-no-response")), i18nc("@item:inlistbox", "Request No Response")); mEdit->setToolTip(i18nc("@info:tooltip", "Enter the name or email address of the attendee.")); mEdit->setClearButtonEnabled(true); mStateCombo->setWhatsThis(i18nc("@info:whatsthis", "Edits the current attendance status of the attendee.")); mRoleCombo->setWhatsThis(i18nc("@info:whatsthis", "Edits the role of the attendee.")); mEdit->setWhatsThis(i18nc("@info:whatsthis", "The email address or name of the attendee. An invitation " "can be sent to the user if an email address is provided.")); setActions(EventActions); mResponseCombo->setToolTip(i18nc("@info:tooltip", "Request a response from the attendee")); mResponseCombo->setWhatsThis(i18nc("@info:whatsthis", "Edits whether to send an email to the " "attendee to request a response concerning " "attendance.")); // add them to the layout in the correct order topLayout->addWidget(mRoleCombo); topLayout->addWidget(mEdit); topLayout->addWidget(mStateCombo); topLayout->addWidget(mResponseCombo); connect(mEdit, &AttendeeLineEdit::returnPressed, this, &AttendeeLine::slotReturnPressed); connect(mEdit, &AttendeeLineEdit::deleteMe, this, &AttendeeLine::slotPropagateDeletion, Qt::QueuedConnection); connect(mEdit, &AttendeeLineEdit::textChanged, this, &AttendeeLine::slotTextChanged, Qt::QueuedConnection); connect(mEdit, &AttendeeLineEdit::upPressed, this, &AttendeeLine::slotFocusUp); connect(mEdit, &AttendeeLineEdit::downPressed, this, &AttendeeLine::slotFocusDown); connect(mRoleCombo, &AttendeeComboBox::rightPressed, mEdit, static_cast(&AttendeeLineEdit::setFocus)); connect(mEdit, &AttendeeLineEdit::leftPressed, mRoleCombo, static_cast(&AttendeeComboBox::setFocus)); connect(mEdit, &AttendeeLineEdit::rightPressed, mStateCombo, static_cast(&AttendeeComboBox::setFocus)); connect(mStateCombo, &AttendeeComboBox::leftPressed, mEdit, static_cast(&AttendeeLineEdit::setFocus)); connect(mStateCombo, &AttendeeComboBox::rightPressed, mResponseCombo, static_cast(&AttendeeComboBox::setFocus)); connect(mResponseCombo, &AttendeeComboBox::leftPressed, mStateCombo, static_cast(&AttendeeComboBox::setFocus)); connect(mResponseCombo, &AttendeeComboBox::rightPressed, this, &AttendeeLine::rightPressed); connect(mEdit, &AttendeeLineEdit::editingFinished, this, &AttendeeLine::slotHandleChange, Qt::QueuedConnection); connect(mEdit, &AttendeeLineEdit::textCompleted, this, &AttendeeLine::slotHandleChange, Qt::QueuedConnection); connect(mEdit, &AttendeeLineEdit::clearButtonClicked, this, &AttendeeLine::slotPropagateDeletion, Qt::QueuedConnection); connect(mRoleCombo, &AttendeeComboBox::itemChanged, this, &AttendeeLine::slotComboChanged); connect(mStateCombo, &AttendeeComboBox::itemChanged, this, &AttendeeLine::slotComboChanged); connect(mResponseCombo, &AttendeeComboBox::itemChanged, this, &AttendeeLine::slotComboChanged); } void AttendeeLine::activate() { mEdit->setFocus(); } void AttendeeLine::clear() { mEdit->clear(); mRoleCombo->setCurrentIndex(0); mStateCombo->setCurrentIndex(0); mResponseCombo->setCurrentIndex(0); mUid.clear(); } void AttendeeLine::clearModified() { mModified = false; mEdit->setModified(false); } KPIM::MultiplyingLineData::Ptr AttendeeLine::data() const { if (isModified()) { const_cast(this)->dataFromFields(); } return mData; } void AttendeeLine::dataFromFields() { if (!mData) { return; } - KCalCore::Attendee oldAttendee(mData->attendee()); + KCalendarCore::Attendee oldAttendee(mData->attendee()); QString email, name; KEmailAddress::extractEmailAddressAndName(mEdit->text(), email, name); mData->setName(name); mData->setEmail(email); mData->setRole(AttendeeData::Role(mRoleCombo->currentIndex())); mData->setStatus(AttendeeData::PartStat(mStateCombo->currentIndex())); mData->setRSVP(mResponseCombo->currentIndex() == 0); mData->setUid(mUid); clearModified(); if (!(oldAttendee == mData->attendee()) && !email.isEmpty()) { // if email is empty, we don't want to update anything qCDebug(INCIDENCEEDITOR_LOG) << oldAttendee.email() << mData->email(); Q_EMIT changed(oldAttendee, mData->attendee()); } } void AttendeeLine::fieldsFromData() { if (!mData) { return; } mEdit->setText(mData->fullName()); mRoleCombo->setCurrentIndex(mData->role()); AttendeeData::PartStat partStat = mData->status(); if (partStat != AttendeeData::None) { mStateCombo->setCurrentIndex(partStat); } else { mStateCombo->setCurrentIndex(AttendeeData::NeedsAction); } mResponseCombo->setCurrentIndex(mData->RSVP() ? 0 : 1); mUid = mData->uid(); } void AttendeeLine::fixTabOrder(QWidget *previous) { setTabOrder(previous, mRoleCombo); setTabOrder(mRoleCombo, mEdit); setTabOrder(mEdit, mStateCombo); setTabOrder(mStateCombo, mResponseCombo); } QWidget *AttendeeLine::tabOut() const { return mResponseCombo; } bool AttendeeLine::isActive() const { return mEdit->hasFocus(); } bool AttendeeLine::isEmpty() const { return mEdit->text().isEmpty(); } bool AttendeeLine::isModified() const { return mModified || mEdit->isModified(); } int AttendeeLine::setColumnWidth(int w) { w = qMax(w, mRoleCombo->sizeHint().width()); mRoleCombo->setFixedWidth(w); mRoleCombo->updateGeometry(); parentWidget()->updateGeometry(); return w; } void AttendeeLine::setActions(AttendeeActions actions) { mStateCombo->clear(); } void AttendeeLine::setCompletionMode(KCompletion::CompletionMode mode) { mEdit->setCompletionMode(mode); } void AttendeeLine::setData(const KPIM::MultiplyingLineData::Ptr &data) { AttendeeData::Ptr attendee = qSharedPointerDynamicCast(data); if (!attendee) { return; } mData = attendee; fieldsFromData(); } void AttendeeLine::slotHandleChange() { if (mEdit->text().isEmpty()) { Q_EMIT deleteLine(this); } else { // has bad side-effects, and I have no idea what this was supposed to be doing // mEdit->setCursorPosition( 0 ); Q_EMIT editingFinished(this); dataFromFields(); } } void AttendeeLine::slotTextChanged(const QString &str) { Q_UNUSED(str); mModified = true; Q_EMIT changed(); // TODO: This doesn't seem connected to anywhere in incidenceattendee.cpp. // but the important code is run in slotHandleChange() anyway so we don't see any bug } void AttendeeLine::slotComboChanged() { mModified = true; // If mUid is empty, we're still populating the widget, don't write fields to data yet if (!mUid.isEmpty()) { dataFromFields(); } } void AttendeeLine::aboutToBeDeleted() { if (!mData) { return; } - Q_EMIT changed(mData->attendee(), KCalCore::Attendee(QLatin1String(""), QLatin1String(""))); + Q_EMIT changed(mData->attendee(), KCalendarCore::Attendee(QLatin1String(""), QLatin1String(""))); } bool AttendeeLine::canDeleteLineEdit() const { return mEdit->canDeleteLineEdit(); } diff --git a/src/attendeeline.h b/src/attendeeline.h index 339acde..ec7f972 100644 --- a/src/attendeeline.h +++ b/src/attendeeline.h @@ -1,145 +1,145 @@ /* Copyright (C) 2010 Casey Link Copyright (C) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_ATTENDEELINE_H #define INCIDENCEEDITOR_ATTENDEELINE_H #include #include -#include +#include #include #include class QKeyEvent; namespace IncidenceEditorNG { class AttendeeData; class AttendeeComboBox : public QToolButton { Q_OBJECT public: explicit AttendeeComboBox(QWidget *parent); void addItem(const QIcon &icon, const QString &text); void addItems(const QStringList &texts); Q_REQUIRED_RESULT int currentIndex() const; Q_SIGNALS: void rightPressed(); void leftPressed(); void itemChanged(); public Q_SLOTS: /** Clears the combobox, removing all items. */ void clear(); void setCurrentIndex(int index); protected: void keyPressEvent(QKeyEvent *ev) override; private: void slotActionTriggered(); QMenu *mMenu = nullptr; QVector > mList; int mCurrentIndex; }; class AttendeeLineEdit : public KPIM::AddresseeLineEdit { Q_OBJECT public: explicit AttendeeLineEdit(QWidget *parent); Q_SIGNALS: void deleteMe(); void leftPressed(); void rightPressed(); void upPressed(); void downPressed(); protected: void keyPressEvent(QKeyEvent *ev) override; }; class AttendeeLine : public KPIM::MultiplyingLine { Q_OBJECT public: enum AttendeeActions { EventActions, TodoActions }; explicit AttendeeLine(QWidget *parent); virtual ~AttendeeLine() { } void activate() override; bool isActive() const override; bool isEmpty() const override; void clear() override; bool isModified() const override; void clearModified() override; KPIM::MultiplyingLineData::Ptr data() const override; void setData(const KPIM::MultiplyingLineData::Ptr &data) override; void fixTabOrder(QWidget *previous) override; QWidget *tabOut() const override; void setCompletionMode(KCompletion::CompletionMode) override; int setColumnWidth(int w) override; void aboutToBeDeleted() override; bool canDeleteLineEdit() const override; void setActions(AttendeeActions actions); Q_SIGNALS: void changed(); - void changed(const KCalCore::Attendee &oldAttendee, const KCalCore::Attendee &newAttendee); + void changed(const KCalendarCore::Attendee &oldAttendee, const KCalendarCore::Attendee &newAttendee); void editingFinished(KPIM::MultiplyingLine *); private: void slotTextChanged(const QString &); void slotHandleChange(); void slotComboChanged(); void dataFromFields(); void fieldsFromData(); AttendeeComboBox *mRoleCombo = nullptr; AttendeeComboBox *mStateCombo = nullptr; AttendeeComboBox *mResponseCombo = nullptr; AttendeeLineEdit *mEdit = nullptr; QSharedPointer mData; QString mUid; bool mModified; }; } #endif diff --git a/src/attendeetablemodel.cpp b/src/attendeetablemodel.cpp index 0d82ec9..747e1f2 100644 --- a/src/attendeetablemodel.cpp +++ b/src/attendeetablemodel.cpp @@ -1,314 +1,314 @@ /* * Copyright (C) 2014 Sandro Knauß * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This library 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 Library General Public * License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "attendeetablemodel.h" -#include +#include #include #include using namespace IncidenceEditorNG; AttendeeTableModel::AttendeeTableModel(QObject *parent) : QAbstractTableModel(parent) , mKeepEmpty(false) , mRemoveEmptyLines(false) { } int AttendeeTableModel::rowCount(const QModelIndex & /*parent*/) const { return mAttendeeList.count(); } int AttendeeTableModel::columnCount(const QModelIndex & /*parent*/) const { return 8; } Qt::ItemFlags AttendeeTableModel::flags(const QModelIndex &index) const { if (!index.isValid()) { return Qt::ItemIsEnabled; } if (index.column() == Available || index.column() == Name || index.column() == Email) { //Available is read only return QAbstractTableModel::flags(index); } else { return QAbstractTableModel::flags(index) | Qt::ItemIsEditable; } } QVariant AttendeeTableModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (index.row() >= mAttendeeList.size()) { return QVariant(); } - const KCalCore::Attendee attendee = mAttendeeList[index.row()]; + const KCalendarCore::Attendee attendee = mAttendeeList[index.row()]; if (role == Qt::DisplayRole || role == Qt::EditRole) { switch (index.column()) { case Role: return attendee.role(); case FullName: return attendee.fullName(); case Available: { AvailableStatus available = mAttendeeAvailable[index.row()]; if (role == Qt::DisplayRole) { switch (available) { case Free: return i18n("Free"); case Busy: return i18n("Busy"); case Accepted: return i18n("Accepted"); case Unknown: return i18n("Unknown"); default: return i18n("Unknown"); } } else { return available; } } case Status: return attendee.status(); case CuType: return attendee.cuType(); case Response: return attendee.RSVP(); case Name: return attendee.name(); case Email: return attendee.email(); } } if (role == AttendeeRole) { return QVariant::fromValue(attendee); } return QVariant(); } bool AttendeeTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { QString email, name; if (index.isValid() && role == Qt::EditRole) { - KCalCore::Attendee &attendee = mAttendeeList[index.row()]; + KCalendarCore::Attendee &attendee = mAttendeeList[index.row()]; switch (index.column()) { case Role: - attendee.setRole(static_cast(value.toInt())); + attendee.setRole(static_cast(value.toInt())); break; case FullName: if (mRemoveEmptyLines && value.toString().trimmed().isEmpty()) { // Do not remove last empty line if mKeepEmpty==true // (only works if initially there is only one empty line) if (!mKeepEmpty || !(attendee.name().isEmpty() && attendee.email().isEmpty())) { removeRows(index.row(), 1); return true; } } KEmailAddress::extractEmailAddressAndName(value.toString(), email, name); attendee.setName(name); attendee.setEmail(email); addEmptyAttendee(); break; case Available: mAttendeeAvailable[index.row()] = static_cast(value.toInt()); break; case Status: - attendee.setStatus(static_cast(value.toInt())); + attendee.setStatus(static_cast(value.toInt())); break; case CuType: - attendee.setCuType(static_cast(value.toInt())); + attendee.setCuType(static_cast(value.toInt())); break; case Response: attendee.setRSVP(value.toBool()); break; default: return false; } Q_EMIT dataChanged(index, index); return true; } return false; } QVariant AttendeeTableModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole) { return QVariant(); } if (orientation == Qt::Horizontal) { switch (section) { case Role: return i18nc("vCard attendee role", "Role"); case FullName: return i18nc("Attendees (name+emailaddress)", "Name"); case Available: return i18nc("Is attendee available for incidence", "Available"); case Status: return i18nc("Status of attendee in an incidence (accepted, declined, delegated, ...)", "Status"); case CuType: return i18nc("Type of calendar user (vCard attribute)", "User Type"); case Response: return i18nc("Has attendee to respond to the invitation", "Response"); case Name: return i18nc("Attendee name", "Name"); case Email: return i18nc("Attendee email", "Email"); } } return QVariant(); } bool AttendeeTableModel::insertRows(int position, int rows, const QModelIndex &parent) { beginInsertRows(parent, position, position + rows - 1); for (int row = 0; row < rows; ++row) { - KCalCore::Attendee attendee(QLatin1String(""), QLatin1String("")); + KCalendarCore::Attendee attendee(QLatin1String(""), QLatin1String("")); mAttendeeList.insert(position, attendee); mAttendeeAvailable.insert(mAttendeeAvailable.begin() + position, AvailableStatus{}); } endInsertRows(); return true; } bool AttendeeTableModel::removeRows(int position, int rows, const QModelIndex &parent) { beginRemoveRows(parent, position, position + rows - 1); for (int row = 0; row < rows; ++row) { mAttendeeAvailable.erase(mAttendeeAvailable.begin() + position); mAttendeeList.remove(position); } endRemoveRows(); return true; } -bool AttendeeTableModel::insertAttendee(int position, const KCalCore::Attendee &attendee) +bool AttendeeTableModel::insertAttendee(int position, const KCalendarCore::Attendee &attendee) { beginInsertRows(QModelIndex(), position, position); mAttendeeList.insert(position, attendee); mAttendeeAvailable.insert(mAttendeeAvailable.begin() + position, AvailableStatus{}); endInsertRows(); addEmptyAttendee(); return true; } -void AttendeeTableModel::setAttendees(const KCalCore::Attendee::List &attendees) +void AttendeeTableModel::setAttendees(const KCalendarCore::Attendee::List &attendees) { Q_EMIT layoutAboutToBeChanged(); mAttendeeList = attendees; mAttendeeAvailable.clear(); mAttendeeAvailable.resize(attendees.size()); addEmptyAttendee(); Q_EMIT layoutChanged(); } -KCalCore::Attendee::List AttendeeTableModel::attendees() const +KCalendarCore::Attendee::List AttendeeTableModel::attendees() const { return mAttendeeList; } void AttendeeTableModel::addEmptyAttendee() { if (mKeepEmpty) { bool create = true; - for (const KCalCore::Attendee &attendee : qAsConst(mAttendeeList)) { + for (const KCalendarCore::Attendee &attendee : qAsConst(mAttendeeList)) { if (attendee.fullName().isEmpty()) { create = false; break; } } if (create) { insertRows(rowCount(), 1); } } } bool AttendeeTableModel::keepEmpty() const { return mKeepEmpty; } void AttendeeTableModel::setKeepEmpty(bool keepEmpty) { if (keepEmpty != mKeepEmpty) { mKeepEmpty = keepEmpty; addEmptyAttendee(); } } bool AttendeeTableModel::removeEmptyLines() const { return mRemoveEmptyLines; } void AttendeeTableModel::setRemoveEmptyLines(bool removeEmptyLines) { mRemoveEmptyLines = removeEmptyLines; } ResourceFilterProxyModel::ResourceFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { } bool ResourceFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { QModelIndex cuTypeIndex = sourceModel()->index(sourceRow, AttendeeTableModel::CuType, sourceParent); - KCalCore::Attendee::CuType cuType - = static_cast(sourceModel()->data(cuTypeIndex).toUInt()); + KCalendarCore::Attendee::CuType cuType + = static_cast(sourceModel()->data(cuTypeIndex).toUInt()); - return cuType == KCalCore::Attendee::Resource || cuType == KCalCore::Attendee::Room; + return cuType == KCalendarCore::Attendee::Resource || cuType == KCalendarCore::Attendee::Room; } AttendeeFilterProxyModel::AttendeeFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { } bool AttendeeFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { QModelIndex cuTypeIndex = sourceModel()->index(sourceRow, AttendeeTableModel::CuType, sourceParent); - KCalCore::Attendee::CuType cuType - = static_cast(sourceModel()->data(cuTypeIndex).toUInt()); + KCalendarCore::Attendee::CuType cuType + = static_cast(sourceModel()->data(cuTypeIndex).toUInt()); - return !(cuType == KCalCore::Attendee::Resource || cuType == KCalCore::Attendee::Room); + return !(cuType == KCalendarCore::Attendee::Resource || cuType == KCalendarCore::Attendee::Room); } diff --git a/src/attendeetablemodel.h b/src/attendeetablemodel.h index 365474d..ebe0662 100644 --- a/src/attendeetablemodel.h +++ b/src/attendeetablemodel.h @@ -1,107 +1,107 @@ /* * Copyright (C) 2014 Sandro Knauß * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This library 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 Library General Public * License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_ATTENDEETABLEMODEL_H #define INCIDENCEEDITOR_ATTENDEETABLEMODEL_H -#include +#include #include #include #include namespace IncidenceEditorNG { class AttendeeTableModel : public QAbstractTableModel { Q_OBJECT public: enum Roles { AttendeeRole = Qt::UserRole }; enum Columns { CuType, Role, FullName, Name, Email, Available, Status, Response }; enum AvailableStatus { Unknown, Free, Accepted, Busy, Tentative }; explicit AttendeeTableModel(QObject *parent = nullptr); Q_REQUIRED_RESULT int rowCount(const QModelIndex &parent = QModelIndex()) const override; Q_REQUIRED_RESULT int columnCount(const QModelIndex &parent = QModelIndex()) const override; Q_REQUIRED_RESULT QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; Q_REQUIRED_RESULT QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; Q_REQUIRED_RESULT Qt::ItemFlags flags(const QModelIndex &index) const override; Q_REQUIRED_RESULT bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; Q_REQUIRED_RESULT bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override; Q_REQUIRED_RESULT bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override; - Q_REQUIRED_RESULT bool insertAttendee(int position, const KCalCore::Attendee &attendee); + Q_REQUIRED_RESULT bool insertAttendee(int position, const KCalendarCore::Attendee &attendee); - void setAttendees(const KCalCore::Attendee::List &resources); - Q_REQUIRED_RESULT KCalCore::Attendee::List attendees() const; + void setAttendees(const KCalendarCore::Attendee::List &resources); + Q_REQUIRED_RESULT KCalendarCore::Attendee::List attendees() const; void setKeepEmpty(bool keepEmpty); Q_REQUIRED_RESULT bool keepEmpty() const; void setRemoveEmptyLines(bool removeEmptyLines); Q_REQUIRED_RESULT bool removeEmptyLines() const; private: void addEmptyAttendee(); - KCalCore::Attendee::List mAttendeeList; + KCalendarCore::Attendee::List mAttendeeList; std::vector mAttendeeAvailable; bool mKeepEmpty; bool mRemoveEmptyLines; }; class ResourceFilterProxyModel : public QSortFilterProxyModel { Q_OBJECT public: explicit ResourceFilterProxyModel(QObject *parent = nullptr); bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; }; class AttendeeFilterProxyModel : public QSortFilterProxyModel { Q_OBJECT public: explicit AttendeeFilterProxyModel(QObject *parent = nullptr); bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; }; } #endif diff --git a/src/combinedincidenceeditor.cpp b/src/combinedincidenceeditor.cpp index 173a976..8a2513a 100644 --- a/src/combinedincidenceeditor.cpp +++ b/src/combinedincidenceeditor.cpp @@ -1,155 +1,155 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "combinedincidenceeditor.h" #include "incidenceeditor_debug.h" using namespace IncidenceEditorNG; /// public methods CombinedIncidenceEditor::CombinedIncidenceEditor(QWidget *parent) : IncidenceEditor(parent) , mDirtyEditorCount(0) { } CombinedIncidenceEditor::~CombinedIncidenceEditor() { qDeleteAll(mCombinedEditors); } void CombinedIncidenceEditor::combine(IncidenceEditor *other) { Q_ASSERT(other); mCombinedEditors.append(other); connect(other, &IncidenceEditor::dirtyStatusChanged, this, &CombinedIncidenceEditor::handleDirtyStatusChange); } bool CombinedIncidenceEditor::isDirty() const { return mDirtyEditorCount > 0; } bool CombinedIncidenceEditor::isValid() const { for (IncidenceEditor *editor : qAsConst(mCombinedEditors)) { if (!editor->isValid()) { const QString reason = editor->lastErrorString(); editor->focusInvalidField(); if (!reason.isEmpty()) { Q_EMIT showMessage(reason, KMessageWidget::Warning); } return false; } } return true; } void CombinedIncidenceEditor::handleDirtyStatusChange(bool isDirty) { const int prevDirtyCount = mDirtyEditorCount; Q_ASSERT(mDirtyEditorCount >= 0); if (isDirty) { ++mDirtyEditorCount; } else { --mDirtyEditorCount; } Q_ASSERT(mDirtyEditorCount >= 0); if (prevDirtyCount == 0) { Q_EMIT dirtyStatusChanged(true); } if (mDirtyEditorCount == 0) { Q_EMIT dirtyStatusChanged(false); } } -void CombinedIncidenceEditor::load(const KCalCore::Incidence::Ptr &incidence) +void CombinedIncidenceEditor::load(const KCalendarCore::Incidence::Ptr &incidence) { mLoadedIncidence = incidence; for (IncidenceEditor *editor : qAsConst(mCombinedEditors)) { // load() may fire dirtyStatusChanged(), reset mDirtyEditorCount to make sure // we don't end up with an invalid dirty count. editor->blockSignals(true); editor->load(incidence); editor->blockSignals(false); if (editor->isDirty()) { // We are going to crash due to assert. Print some useful info before crashing. qCWarning(INCIDENCEEDITOR_LOG) << "Faulty editor was " << editor->objectName(); qCWarning(INCIDENCEEDITOR_LOG) << "Incidence " << (incidence ? incidence->uid() : QStringLiteral("null")); editor->printDebugInfo(); Q_ASSERT_X(false, "load", "editor shouldn't be dirty"); } } mWasDirty = false; mDirtyEditorCount = 0; Q_EMIT dirtyStatusChanged(false); } void CombinedIncidenceEditor::load(const Akonadi::Item &item) { for (IncidenceEditor *editor : qAsConst(mCombinedEditors)) { // load() may fire dirtyStatusChanged(), reset mDirtyEditorCount to make sure // we don't end up with an invalid dirty count. editor->blockSignals(true); editor->load(item); editor->blockSignals(false); if (editor->isDirty()) { // We are going to crash due to assert. Print some useful info before crashing. qCWarning(INCIDENCEEDITOR_LOG) << "Faulty editor was " << editor->objectName(); // qCWarning(INCIDENCEEDITOR_LOG) << "Incidence " << ( incidence ? incidence->uid() : "null" ); editor->printDebugInfo(); Q_ASSERT_X(false, "load", "editor shouldn't be dirty"); } } mWasDirty = false; mDirtyEditorCount = 0; Q_EMIT dirtyStatusChanged(false); } -void CombinedIncidenceEditor::save(const KCalCore::Incidence::Ptr &incidence) +void CombinedIncidenceEditor::save(const KCalendarCore::Incidence::Ptr &incidence) { for (IncidenceEditor *editor : qAsConst(mCombinedEditors)) { editor->save(incidence); } } void CombinedIncidenceEditor::save(Akonadi::Item &item) { for (IncidenceEditor *editor : qAsConst(mCombinedEditors)) { editor->save(item); } } diff --git a/src/combinedincidenceeditor.h b/src/combinedincidenceeditor.h index 5fa97ad..46cd2e3 100644 --- a/src/combinedincidenceeditor.h +++ b/src/combinedincidenceeditor.h @@ -1,75 +1,75 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef COMBINEDINCIDENCEEDITOR_H #define COMBINEDINCIDENCEEDITOR_H #include "incidenceeditor-ng.h" #include #include namespace IncidenceEditorNG { /** * The CombinedIncidenceEditor combines optional widgets with zero or more * IncidenceEditors. The CombinedIncidenceEditor keeps track of the dirty state * of the IncidenceEditors that where combined. */ class CombinedIncidenceEditor : public IncidenceEditor { Q_OBJECT public: explicit CombinedIncidenceEditor(QWidget *parent = nullptr); /** * Deletes this editor as well as all editors which are combined into this * one. */ ~CombinedIncidenceEditor() override; void combine(IncidenceEditor *other); /** * Returns whether or not the current values in the editor differ from the * initial values or if one of the combined editors is dirty. */ Q_REQUIRED_RESULT bool isDirty() const override; Q_REQUIRED_RESULT bool isValid() const override; /** * Loads all data from @param incidence into the combined editors. Note, if * you reimplement the load method in a subclass, make sure to call this * implementation too. */ - void load(const KCalCore::Incidence::Ptr &incidence) override; + void load(const KCalendarCore::Incidence::Ptr &incidence) override; void load(const Akonadi::Item &item) override; - void save(const KCalCore::Incidence::Ptr &incidence) override; + void save(const KCalendarCore::Incidence::Ptr &incidence) override; void save(Akonadi::Item &item) override; Q_SIGNALS: void showMessage(const QString &reason, KMessageWidget::MessageType) const; private: void handleDirtyStatusChange(bool isDirty); QVector mCombinedEditors; int mDirtyEditorCount; }; } #endif // COMBINEDINCIDENCEEDITOR_H diff --git a/src/conflictresolver.cpp b/src/conflictresolver.cpp index ced5d29..7d368d5 100644 --- a/src/conflictresolver.cpp +++ b/src/conflictresolver.cpp @@ -1,503 +1,503 @@ /* Copyright (c) 2000,2001,2004 Cornelius Schumacher Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Copyright (c) 2010 Andras Mantia Copyright (C) 2010 Casey Link This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "conflictresolver.h" #include "CalendarSupport/FreeBusyItemModel" #include "incidenceeditor_debug.h" #include static const int DEFAULT_RESOLUTION_SECONDS = 15 * 60; // 15 minutes, 1 slot = 15 minutes using namespace IncidenceEditorNG; ConflictResolver::ConflictResolver(QWidget *parentWidget, QObject *parent) : QObject(parent) , mFBModel(new CalendarSupport::FreeBusyItemModel(this)) , mParentWidget(parentWidget) , mWeekdays(7) , mSlotResolutionSeconds(DEFAULT_RESOLUTION_SECONDS) { const QDateTime currentLocalDateTime = QDateTime::currentDateTime(); - mTimeframeConstraint = KCalCore::Period(currentLocalDateTime, currentLocalDateTime); + mTimeframeConstraint = KCalendarCore::Period(currentLocalDateTime, currentLocalDateTime); // trigger a reload in case any attendees were inserted before // the connection was made // triggerReload(); // set default values, all the days mWeekdays.setBit(0); // Monday mWeekdays.setBit(1); mWeekdays.setBit(2); mWeekdays.setBit(3); mWeekdays.setBit(4); mWeekdays.setBit(5); mWeekdays.setBit(6); // Sunday mMandatoryRoles.reserve(4); - mMandatoryRoles << KCalCore::Attendee::ReqParticipant - << KCalCore::Attendee::OptParticipant - << KCalCore::Attendee::NonParticipant - << KCalCore::Attendee::Chair; + mMandatoryRoles << KCalendarCore::Attendee::ReqParticipant + << KCalendarCore::Attendee::OptParticipant + << KCalendarCore::Attendee::NonParticipant + << KCalendarCore::Attendee::Chair; connect(mFBModel, &CalendarSupport::FreeBusyItemModel::dataChanged, this, &ConflictResolver::freebusyDataChanged); connect(&mCalculateTimer, &QTimer::timeout, this, &ConflictResolver::findAllFreeSlots); mCalculateTimer.setSingleShot(true); } -void ConflictResolver::insertAttendee(const KCalCore::Attendee&attendee) +void ConflictResolver::insertAttendee(const KCalendarCore::Attendee&attendee) { if (!mFBModel->containsAttendee(attendee)) { mFBModel->addItem(CalendarSupport::FreeBusyItem::Ptr(new CalendarSupport::FreeBusyItem( attendee, mParentWidget))); } } void ConflictResolver::insertAttendee(const CalendarSupport::FreeBusyItem::Ptr &freebusy) { if (!mFBModel->containsAttendee(freebusy->attendee())) { mFBModel->addItem(freebusy); } } -void ConflictResolver::removeAttendee(const KCalCore::Attendee &attendee) +void ConflictResolver::removeAttendee(const KCalendarCore::Attendee &attendee) { mFBModel->removeAttendee(attendee); calculateConflicts(); } void ConflictResolver::clearAttendees() { mFBModel->clear(); } -bool ConflictResolver::containsAttendee(const KCalCore::Attendee &attendee) +bool ConflictResolver::containsAttendee(const KCalendarCore::Attendee &attendee) { return mFBModel->containsAttendee(attendee); } void ConflictResolver::setEarliestDate(const QDate &newDate) { QDateTime newStart = mTimeframeConstraint.start(); newStart.setDate(newDate); - mTimeframeConstraint = KCalCore::Period(newStart, mTimeframeConstraint.end()); + mTimeframeConstraint = KCalendarCore::Period(newStart, mTimeframeConstraint.end()); calculateConflicts(); } void ConflictResolver::setEarliestTime(const QTime &newTime) { QDateTime newStart = mTimeframeConstraint.start(); newStart.setTime(newTime); - mTimeframeConstraint = KCalCore::Period(newStart, mTimeframeConstraint.end()); + mTimeframeConstraint = KCalendarCore::Period(newStart, mTimeframeConstraint.end()); calculateConflicts(); } void ConflictResolver::setLatestDate(const QDate &newDate) { QDateTime newEnd = mTimeframeConstraint.end(); newEnd.setDate(newDate); - mTimeframeConstraint = KCalCore::Period(mTimeframeConstraint.start(), newEnd); + mTimeframeConstraint = KCalendarCore::Period(mTimeframeConstraint.start(), newEnd); calculateConflicts(); } void ConflictResolver::setLatestTime(const QTime &newTime) { QDateTime newEnd = mTimeframeConstraint.end(); newEnd.setTime(newTime); - mTimeframeConstraint = KCalCore::Period(mTimeframeConstraint.start(), newEnd); + mTimeframeConstraint = KCalendarCore::Period(mTimeframeConstraint.start(), newEnd); calculateConflicts(); } void ConflictResolver::setEarliestDateTime(const QDateTime &newDateTime) { - mTimeframeConstraint = KCalCore::Period(newDateTime, mTimeframeConstraint.end()); + mTimeframeConstraint = KCalendarCore::Period(newDateTime, mTimeframeConstraint.end()); calculateConflicts(); } void ConflictResolver::setLatestDateTime(const QDateTime &newDateTime) { - mTimeframeConstraint = KCalCore::Period(mTimeframeConstraint.start(), newDateTime); + mTimeframeConstraint = KCalendarCore::Period(mTimeframeConstraint.start(), newDateTime); calculateConflicts(); } void ConflictResolver::freebusyDataChanged() { calculateConflicts(); } int ConflictResolver::tryDate(QDateTime &tryFrom, QDateTime &tryTo) { int conflicts_count = 0; for (int i = 0; i < mFBModel->rowCount(); ++i) { QModelIndex index = mFBModel->index(i); - KCalCore::Attendee attendee + KCalendarCore::Attendee attendee = mFBModel->data(index, - CalendarSupport::FreeBusyItemModel::AttendeeRole).value(); + CalendarSupport::FreeBusyItemModel::AttendeeRole).value(); if (!matchesRoleConstraint(attendee)) { continue; } - KCalCore::FreeBusy::Ptr freebusy + KCalendarCore::FreeBusy::Ptr freebusy = mFBModel->data(index, - CalendarSupport::FreeBusyItemModel::FreeBusyRole).value(); if (!tryDate(freebusy, tryFrom, tryTo)) { ++conflicts_count; } } return conflicts_count; } -bool ConflictResolver::tryDate(const KCalCore::FreeBusy::Ptr &fb, QDateTime &tryFrom, QDateTime &tryTo) +bool ConflictResolver::tryDate(const KCalendarCore::FreeBusy::Ptr &fb, QDateTime &tryFrom, QDateTime &tryTo) { // If we don't have any free/busy information, assume the // participant is free. Otherwise a participant without available // information would block the whole allocation. if (!fb) { return true; } - KCalCore::Period::List busyPeriods = fb->busyPeriods(); + KCalendarCore::Period::List busyPeriods = fb->busyPeriods(); for (auto it = busyPeriods.begin(); it != busyPeriods.end(); ++it) { if ((*it).end() <= tryFrom // busy period ends before try period || (*it).start() >= tryTo) { // busy period starts after try period continue; } else { // the current busy period blocks the try period, try // after the end of the current busy period const qint64 secsDuration = tryFrom.secsTo(tryTo); tryFrom = (*it).end(); tryTo = tryFrom.addSecs(secsDuration); // try again with the new try period tryDate(fb, tryFrom, tryTo); // we had to change the date at least once return false; } } return true; } -bool ConflictResolver::findFreeSlot(const KCalCore::Period &dateTimeRange) +bool ConflictResolver::findFreeSlot(const KCalendarCore::Period &dateTimeRange) { QDateTime dtFrom = dateTimeRange.start(); QDateTime dtTo = dateTimeRange.end(); if (tryDate(dtFrom, dtTo)) { // Current time is acceptable return true; } QDateTime tryFrom = dtFrom; QDateTime tryTo = dtTo; // Make sure that we never suggest a date in the past, even if the // user originally scheduled the meeting to be in the past. QDateTime now = QDateTime::currentDateTimeUtc(); if (tryFrom < now) { // The slot to look for is at least partially in the past. const qint64 secs = tryFrom.secsTo(tryTo); tryFrom = now; tryTo = tryFrom.addSecs(secs); } bool found = false; while (!found) { found = tryDate(tryFrom, tryTo); // PENDING(kalle) Make the interval configurable if (!found && dtFrom.daysTo(tryFrom) > 365) { break; // don't look more than one year in the future } } dtFrom = tryFrom; dtTo = tryTo; return found; } void ConflictResolver::findAllFreeSlots() { // Uses an O(p*n) (n number of attendees, p timeframe range / timeslot resolution ) algorithm to // locate all free blocks in a given timeframe that match the search constraints. // Does so by: // 1. convert each attendees schedule for the timeframe into a bitarray according to // the time resolution, where each time slot has a value of 1 = busy, 0 = free. // 2. align the arrays vertically, and sum the columns // 3. the resulting summation indicates # of conflicts at each timeslot // 4. locate contiguous timeslots with a values of 0. these are the free time blocks. // define these locally for readability const QDateTime begin = mTimeframeConstraint.start(); const QDateTime end = mTimeframeConstraint.end(); // calculate the time resolution // each timeslot in the arrays represents a unit of time // specified here. if (mSlotResolutionSeconds < 1) { // fallback to default, if the user's value is invalid mSlotResolutionSeconds = DEFAULT_RESOLUTION_SECONDS; } // calculate the length of the timeframe in terms of the amount of timeslots. // Example: 1 week timeframe, with resolution of 15 minutes // 1 week = 10080 minutes / 15 = 672 15 min timeslots // So, the array would have a length of 672 const int range = begin.secsTo(end) / mSlotResolutionSeconds; if (range <= 0) { qCWarning(INCIDENCEEDITOR_LOG) << "free slot calculation: invalid range. range( " << begin.secsTo(end) << ") / mSlotResolutionSeconds(" << mSlotResolutionSeconds << ") = " << range; return; } qCDebug(INCIDENCEEDITOR_LOG) << "from " << begin << " to " << end << "; mSlotResolutionSeconds = " << mSlotResolutionSeconds << "; range = " << range; // filter out attendees for which we don't have FB data // and which don't match the mandatory role constraint - QList filteredFBItems; + QList filteredFBItems; for (int i = 0; i < mFBModel->rowCount(); ++i) { QModelIndex index = mFBModel->index(i); - KCalCore::Attendee attendee + KCalendarCore::Attendee attendee = mFBModel->data(index, - CalendarSupport::FreeBusyItemModel::AttendeeRole).value(); + CalendarSupport::FreeBusyItemModel::AttendeeRole).value(); if (!matchesRoleConstraint(attendee)) { continue; } - KCalCore::FreeBusy::Ptr freebusy + KCalendarCore::FreeBusy::Ptr freebusy = mFBModel->data(index, - CalendarSupport::FreeBusyItemModel::FreeBusyRole).value(); if (freebusy) { filteredFBItems << freebusy; } } // now we know the number of attendees we are calculating for const int number_attendees = filteredFBItems.size(); if (number_attendees <= 0) { qCDebug(INCIDENCEEDITOR_LOG) << "no attendees match search criteria"; return; } qCDebug(INCIDENCEEDITOR_LOG) << "num attendees: " << number_attendees; // this is a 2 dimensional array where the rows are attendees // and the columns are 0 or 1 denoting free or busy respectively. QVector< QVector > fbTable; // Explanation of the following loop: // iterate: through each attendee // allocate: an array of length and fill it with 0s // iterate: through each attendee's busy period // if: the period lies inside our timeframe // then: // calculate the array index within the timeframe range of the beginning of the busy period // fill from that index until the period ends with a 1, representing busy // fi // etareti // append the allocated array to // etareti - for (const KCalCore::FreeBusy::Ptr ¤tFB : qAsConst(filteredFBItems)) { + for (const KCalendarCore::FreeBusy::Ptr ¤tFB : qAsConst(filteredFBItems)) { Q_ASSERT(currentFB); // sanity check - const KCalCore::Period::List busyPeriods = currentFB->busyPeriods(); + const KCalendarCore::Period::List busyPeriods = currentFB->busyPeriods(); QVector fbArray(range); fbArray.fill(0); // initialize to zero for (const auto &period : busyPeriods) { if (period.end() >= begin && period.start() <= end) { int start_index = -1; // Initialize it to an invalid value. int duration = -1; // Initialize it to an invalid value. // case1: the period is completely in our timeframe if (period.end() <= end && period.start() >= begin) { start_index = begin.secsTo(period.start()) / mSlotResolutionSeconds; duration = period.start().secsTo(period.end()) / mSlotResolutionSeconds; duration -= 1; // vector starts at 0 // case2: the period begins before our timeframe begins } else if (period.start() <= begin && period.end() <= end) { start_index = 0; duration = (begin.secsTo(period.end()) / mSlotResolutionSeconds) - 1; // case3: the period ends after our timeframe ends } else if (period.end() >= end && period.start() >= begin) { start_index = begin.secsTo(period.start()) / mSlotResolutionSeconds; duration = range - start_index - 1; // case4: case2+case3: our timeframe is inside the period } else if (period.start() <= begin && period.end() >= end) { start_index = 0; duration = range - 1; } else { //QT5 //qCCritical(INCIDENCEEDITOR_LOG) << "impossible condition reached" << period.start() << period.end(); } // qCDebug(INCIDENCEEDITOR_LOG) << start_index << "+" << duration << "=" // << start_index + duration << "<=" << range; Q_ASSERT((start_index + duration) < range); // sanity check for (int i = start_index; i <= start_index + duration; ++i) { fbArray[i] = 1; } } } Q_ASSERT(fbArray.size() == range); // sanity check fbTable.append(fbArray); } Q_ASSERT(fbTable.size() == number_attendees); // Now, create another array to represent the allowed weekdays constraints // All days which are not allowed, will be marked as busy QVector fbArray(range); fbArray.fill(0); // initialize to zero for (int slot = 0; slot < fbArray.size(); ++slot) { const QDateTime dateTime = begin.addSecs(slot * mSlotResolutionSeconds); const int dayOfWeek = dateTime.date().dayOfWeek() - 1; // bitarray is 0 indexed if (!mWeekdays[dayOfWeek]) { fbArray[slot] = 1; } } fbTable.append(fbArray); // Create the composite array that will hold the sums for // each 15 minute timeslot QVector summed(range); summed.fill(0); // initialize to zero // Sum the columns of the table for (int i = 0; i < fbTable.size(); ++i) { for (int j = 0; j < range; ++j) { summed[j] += fbTable[i][j]; } } // Finally, iterate through the composite array locating contiguous free timeslots int free_count = 0; bool free_found = false; mAvailableSlots.clear(); for (int i = 0; i < range; ++i) { // free timeslot encountered, increment counter if (summed[i] == 0) { ++free_count; } if (summed[i] != 0 || (i == (range - 1) && summed[i] == 0)) { // current slot is not free, so push the previous free blocks // OR we are in the last slot and it is free if (free_count > 0) { int free_start_i;// start index of the free block int free_end_i; // end index of the free block if (summed[i] == 0) { // special case: we are on the last slot and it is free // so we want to include this slot in the free block free_start_i = i - free_count + 1; // add one, to set us back inside the array because // free_count was incremented already this iteration free_end_i = i + 1; // add one to compensate for the fact that the array is 0 indexed } else { free_start_i = i - free_count; free_end_i = i - 1 + 1; // add one to compensate for the fact that the array is 0 indexed // compiler will optimize out the -1+1, but I leave it here to make the reasoning apparent. } // convert from our timeslot interval back into to normal seconds // then calculate the date times of the free block based on // our initial timeframe const QDateTime freeBegin = begin.addSecs(free_start_i * mSlotResolutionSeconds); const QDateTime freeEnd = freeBegin.addSecs((free_end_i - free_start_i) * mSlotResolutionSeconds); // push the free block onto the list - mAvailableSlots << KCalCore::Period(freeBegin, freeEnd); + mAvailableSlots << KCalendarCore::Period(freeBegin, freeEnd); free_count = 0; if (!free_found) { free_found = true; } } } } if (free_found) { Q_EMIT freeSlotsAvailable(mAvailableSlots); } #if 0 //DEBUG, dump the arrays. very helpful for debugging QTextStream dump(stdout); dump << " "; dump.setFieldWidth(3); for (int i = 0; i < range; ++i) { // header dump << i; } dump.setFieldWidth(1); dump << "\n\n"; for (int i = 0; i < number_attendees; ++i) { dump.setFieldWidth(1); dump << i << ": "; dump.setFieldWidth(3); for (int j = 0; j < range; ++j) { dump << fbTable[i][j]; } dump << "\n\n"; } dump.setFieldWidth(1); dump << " "; dump.setFieldWidth(3); for (int i = 0; i < range; ++i) { dump << summed[i]; } dump << "\n"; #endif } void ConflictResolver::calculateConflicts() { QDateTime start = mTimeframeConstraint.start(); QDateTime end = mTimeframeConstraint.end(); const int count = tryDate(start, end); Q_EMIT conflictsDetected(count); if (!mCalculateTimer.isActive()) { mCalculateTimer.start(0); } } void ConflictResolver::setAllowedWeekdays(const QBitArray &weekdays) { mWeekdays = weekdays; calculateConflicts(); } -void ConflictResolver::setMandatoryRoles(const QSet< KCalCore::Attendee::Role > &roles) +void ConflictResolver::setMandatoryRoles(const QSet< KCalendarCore::Attendee::Role > &roles) { mMandatoryRoles = roles; calculateConflicts(); } -bool ConflictResolver::matchesRoleConstraint(const KCalCore::Attendee &attendee) +bool ConflictResolver::matchesRoleConstraint(const KCalendarCore::Attendee &attendee) { return mMandatoryRoles.contains(attendee.role()); } -KCalCore::Period::List ConflictResolver::availableSlots() const +KCalendarCore::Period::List ConflictResolver::availableSlots() const { return mAvailableSlots; } void ConflictResolver::setResolution(int seconds) { mSlotResolutionSeconds = seconds; } CalendarSupport::FreeBusyItemModel *ConflictResolver::model() const { return mFBModel; } diff --git a/src/conflictresolver.h b/src/conflictresolver.h index 23b1206..e10c6d4 100644 --- a/src/conflictresolver.h +++ b/src/conflictresolver.h @@ -1,203 +1,203 @@ /* Copyright (c) 2000,2001,2004 Cornelius Schumacher Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Copyright (c) 2010 Andras Mantia Copyright (C) 2010 Casey Link This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_CONFLICTRESOLVER_H #define INCIDENCEEDITOR_CONFLICTRESOLVER_H #include "incidenceeditor_export.h" #include "CalendarSupport/FreeBusyItem" #include #include #include namespace CalendarSupport { class FreeBusyItemModel; } namespace IncidenceEditorNG { /** * Takes a list of attendees and event info (e.g., min time start, max time end) * fetches their freebusy information, then identifies conflicts and periods of non-conflict. * * It exposes these periods so another class can display them to the user and allow * them to choose a correct time. * @author Casey Link */ class INCIDENCEEDITOR_EXPORT ConflictResolver : public QObject { Q_OBJECT public: /** * @param parentWidget is passed to Akonadi when fetching free/busy data. */ explicit ConflictResolver(QWidget *parentWidget, QObject *parent = nullptr); /** * Add an attendee * The attendees free busy info will be fetched * and integrated into the resolver. */ - void insertAttendee(const KCalCore::Attendee &attendee); + void insertAttendee(const KCalendarCore::Attendee &attendee); void insertAttendee(const CalendarSupport::FreeBusyItem::Ptr &freebusy); /** * Removes an attendee * The attendee will no longer be considered when * resolving conflicts */ - void removeAttendee(const KCalCore::Attendee &attendee); + void removeAttendee(const KCalendarCore::Attendee &attendee); /** * Clear all attendees */ void clearAttendees(); /** * Returns whether the resolver contains the attendee */ - Q_REQUIRED_RESULT bool containsAttendee(const KCalCore::Attendee &attendee); + Q_REQUIRED_RESULT bool containsAttendee(const KCalendarCore::Attendee &attendee); /** * Constrain the free time slot search to the weekdays * identified by their KCalendarSystem integer representation * Default is Monday - Friday * @param weekdays a 7 bit array indicating the allowed days (bit 0=Monday, value 1=allowed). * @see KCalendarSystem */ void setAllowedWeekdays(const QBitArray &weekdays); /** * Constrain the free time slot search to the set participant roles. * Mandatory roles are considered the minimum required to attend * the meeting, so only those attendees with the mandatory roles will * be considered in the search. * Default is all roles are mandatory. * @param roles the set of mandatory participant roles */ - void setMandatoryRoles(const QSet &roles); + void setMandatoryRoles(const QSet &roles); /** * Returns a list of date time ranges that conform to the * search constraints. * @see setMandatoryRoles * @see setAllowedWeekdays */ - KCalCore::Period::List availableSlots() const; + KCalendarCore::Period::List availableSlots() const; /** Finds a free slot in the future which has at least the same size as the initial slot. */ - Q_REQUIRED_RESULT bool findFreeSlot(const KCalCore::Period &dateTimeRange); + Q_REQUIRED_RESULT bool findFreeSlot(const KCalendarCore::Period &dateTimeRange); Q_REQUIRED_RESULT QList freeBusyItems() const; CalendarSupport::FreeBusyItemModel *model() const; Q_SIGNALS: /** * Emitted when the user changes the start and end dateTimes * for the incidence. */ void dateTimesChanged(const QDateTime &newStart, const QDateTime &newEnd); /** * Emitted when there are conflicts * @param number the number of conflicts */ void conflictsDetected(int number); /** * Emitted when the resolver locates new free slots. */ - void freeSlotsAvailable(const KCalCore::Period::List &); + void freeSlotsAvailable(const KCalendarCore::Period::List &); public Q_SLOTS: /** * Set the timeframe constraints * * These control the timeframe for which conflicts are to be resolved. */ void setEarliestDate(const QDate &newDate); void setEarliestTime(const QTime &newTime); void setLatestDate(const QDate &newDate); void setLatestTime(const QTime &newTime); void setEarliestDateTime(const QDateTime &newDateTime); void setLatestDateTime(const QDateTime &newDateTime); void freebusyDataChanged(); void findAllFreeSlots(); void setResolution(int seconds); private: /** Checks whether the slot specified by (tryFrom, tryTo) matches the search constraints. If yes, return true. The return value is the number of conflicts that were detected, and (tryFrom, tryTo) contain the next free slot for that participant. In other words, the returned slot does not have to be free for everybody else. */ int tryDate(QDateTime &tryFrom, QDateTime &tryTo); /** Checks whether the slot specified by (tryFrom, tryTo) is available for the participant with specified fb. If yes, return true. If not, return false and change (tryFrom, tryTo) to contain the next possible slot for this participant (not necessarily a slot that is available for all participants). */ - bool tryDate(const KCalCore::FreeBusy::Ptr &fb, QDateTime &tryFrom, QDateTime &tryTo); + bool tryDate(const KCalendarCore::FreeBusy::Ptr &fb, QDateTime &tryFrom, QDateTime &tryTo); /** * Checks whether the supplied attendee passes the * current mandatory role constraint. * @return true if the attendee is of one of the mandatory roles, false if not */ - bool matchesRoleConstraint(const KCalCore::Attendee &attendee); + bool matchesRoleConstraint(const KCalendarCore::Attendee &attendee); void calculateConflicts(); - KCalCore::Period mTimeframeConstraint; //!< the datetime range for outside of which + KCalendarCore::Period mTimeframeConstraint; //!< the datetime range for outside of which //free slots won't be searched. - KCalCore::Period::List mAvailableSlots; + KCalendarCore::Period::List mAvailableSlots; QTimer mCalculateTimer; //!< A timer is used control the calculation of conflicts // to prevent the process from being repeated many times // after a series of quick parameter changes. CalendarSupport::FreeBusyItemModel *mFBModel = nullptr; QWidget *mParentWidget = nullptr; - QSet mMandatoryRoles; + QSet mMandatoryRoles; QBitArray mWeekdays; //!< a 7 bit array indicating the allowed days //(bit 0 = Monday, value 1 = allowed). int mSlotResolutionSeconds; }; } #endif diff --git a/src/editorconfig.cpp b/src/editorconfig.cpp index 95fb4ce..59d5b95 100644 --- a/src/editorconfig.cpp +++ b/src/editorconfig.cpp @@ -1,129 +1,129 @@ /* Copyright (c) 2009 Sebastian Sauer 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. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #include "editorconfig.h" #include "korganizereditorconfig.h" #include using namespace IncidenceEditorNG; class EditorConfig::Private { public: static EditorConfig *config; static void cleanup_config() { delete config; config = nullptr; } - QHash mTemplates; + QHash mTemplates; }; EditorConfig *EditorConfig::Private::config = nullptr; EditorConfig::EditorConfig() : d(new Private) { } EditorConfig::~EditorConfig() { delete d; } EditorConfig *EditorConfig::instance() { if (!Private::config) { // No one called setEditorConfig(), so we default to a KorganizerEditorConfig. EditorConfig::setEditorConfig(new IncidenceEditorNG::KOrganizerEditorConfig); } return Private::config; } void EditorConfig::setEditorConfig(EditorConfig *config) { delete Private::config; Private::config = config; qAddPostRoutine(Private::cleanup_config); } QString EditorConfig::fullName() const { if (Private::config != this) { return Private::config->fullName(); } return QString(); } QString EditorConfig::email() const { if (Private::config != this) { return Private::config->email(); } return QString(); } bool EditorConfig::thatIsMe(const QString &mail) const { if (Private::config != this) { return Private::config->thatIsMe(mail); } return false; } QStringList EditorConfig::allEmails() const { if (Private::config != this) { return Private::config->allEmails(); } QStringList mails; const QString m = email(); if (!m.isEmpty()) { mails << m; } return mails; } QStringList EditorConfig::fullEmails() const { if (Private::config != this) { return Private::config->fullEmails(); } return QStringList(); } bool EditorConfig::showTimeZoneSelectorInIncidenceEditor() const { if (Private::config != this) { return Private::config->showTimeZoneSelectorInIncidenceEditor(); } return true; } -QStringList &EditorConfig::templates(KCalCore::IncidenceBase::IncidenceType type) +QStringList &EditorConfig::templates(KCalendarCore::IncidenceBase::IncidenceType type) { return d->mTemplates[type]; } diff --git a/src/editorconfig.h b/src/editorconfig.h index 17b6a08..e63efe0 100644 --- a/src/editorconfig.h +++ b/src/editorconfig.h @@ -1,125 +1,125 @@ /* Copyright (c) 2009 Sebastian Sauer 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. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #ifndef INCIDENCEEDITOR_EDITORCONFIG_H #define INCIDENCEEDITOR_EDITORCONFIG_H #include "incidenceeditor_export.h" -#include +#include #include #include #include class KConfigSkeleton; namespace IncidenceEditorNG { /** * Configuration details. An application can inherit from this class * to provide application specific configurations to the editor. * */ class INCIDENCEEDITOR_EXPORT EditorConfig { public: EditorConfig(); virtual ~EditorConfig(); static EditorConfig *instance(); static void setEditorConfig(EditorConfig *); virtual KConfigSkeleton *config() const = 0; /// Return the own full name. Q_REQUIRED_RESULT virtual QString fullName() const; /// Return the own mail address. Q_REQUIRED_RESULT virtual QString email() const; /// Return true if the given email belongs to the user. virtual bool thatIsMe(const QString &email) const; /// Returns all email addresses for the user. Q_REQUIRED_RESULT virtual QStringList allEmails() const; /// Returns all email addresses together with the full username for the user. Q_REQUIRED_RESULT virtual QStringList fullEmails() const; /// Show timezone selectors in the event and todo editor dialog. Q_REQUIRED_RESULT virtual bool showTimeZoneSelectorInIncidenceEditor() const; Q_REQUIRED_RESULT virtual QDateTime defaultDuration() const { return QDateTime(QDate(1752, 1, 1), QTime(2, 0)); } Q_REQUIRED_RESULT virtual QDateTime startTime() const { return QDateTime(QDate(1752, 1, 1), QTime(10, 0)); } Q_REQUIRED_RESULT virtual bool defaultAudioFileReminders() const { return false; } Q_REQUIRED_RESULT virtual QUrl audioFilePath() const { return QUrl(); } Q_REQUIRED_RESULT virtual int reminderTime() const { return 15; } Q_REQUIRED_RESULT virtual int reminderTimeUnits() const { return 0; } Q_REQUIRED_RESULT virtual bool defaultTodoReminders() const { return false; } Q_REQUIRED_RESULT virtual bool defaultEventReminders() const { return false; } Q_REQUIRED_RESULT virtual QStringList activeDesignerFields() const { return QStringList(); } - Q_REQUIRED_RESULT virtual QStringList &templates(KCalCore::IncidenceBase::IncidenceType type); + Q_REQUIRED_RESULT virtual QStringList &templates(KCalendarCore::IncidenceBase::IncidenceType type); private: class Private; Private *const d; }; } #endif diff --git a/src/editoritemmanager.cpp b/src/editoritemmanager.cpp index baa1951..b7d8a77 100644 --- a/src/editoritemmanager.cpp +++ b/src/editoritemmanager.cpp @@ -1,395 +1,395 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "editoritemmanager.h" #include "individualmailcomponentfactory.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "incidenceeditor_debug.h" #include #include /// ItemEditorPrivate namespace IncidenceEditorNG { class ItemEditorPrivate { EditorItemManager *q_ptr; Q_DECLARE_PUBLIC(EditorItemManager) public: Akonadi::Item mItem; Akonadi::Item mPrevItem; Akonadi::ItemFetchScope mFetchScope; Akonadi::Monitor *mItemMonitor = nullptr; ItemEditorUi *mItemUi = nullptr; bool mIsCounterProposal = false; EditorItemManager::SaveAction currentAction; Akonadi::IncidenceChanger *mChanger = nullptr; public: ItemEditorPrivate(Akonadi::IncidenceChanger *changer, EditorItemManager *qq); void itemChanged(const Akonadi::Item &, const QSet &); void itemFetchResult(KJob *job); void itemMoveResult(KJob *job); void onModifyFinished(int changeId, const Akonadi::Item &item, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); void onCreateFinished(int changeId, const Akonadi::Item &item, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString); void setupMonitor(); void moveJobFinished(KJob *job); void setItem(const Akonadi::Item &item); }; ItemEditorPrivate::ItemEditorPrivate(Akonadi::IncidenceChanger *changer, EditorItemManager *qq) : q_ptr(qq) , mItemMonitor(nullptr) , mIsCounterProposal(false) , currentAction(EditorItemManager::None) { mFetchScope.fetchFullPayload(); mFetchScope.setAncestorRetrieval(Akonadi::ItemFetchScope::Parent); mFetchScope.setFetchTags(true); mFetchScope.tagFetchScope().setFetchIdOnly(false); mChanger = changer ? changer : new Akonadi::IncidenceChanger(new IndividualMailComponentFactory( qq), qq); qq->connect(mChanger, SIGNAL(modifyFinished(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode, QString)), qq, SLOT(onModifyFinished(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode, QString))); qq->connect(mChanger, SIGNAL(createFinished(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode, QString)), qq, SLOT(onCreateFinished(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode, QString))); } void ItemEditorPrivate::moveJobFinished(KJob *job) { Q_Q(EditorItemManager); if (job->error()) { qCCritical(INCIDENCEEDITOR_LOG) << "Error while moving and modifying " << job->errorString(); mItemUi->reject(ItemEditorUi::ItemMoveFailed, job->errorString()); } else { Akonadi::Item item(mItem.id()); currentAction = EditorItemManager::MoveAndModify; q->load(item); } } void ItemEditorPrivate::itemFetchResult(KJob *job) { Q_ASSERT(job); Q_Q(EditorItemManager); EditorItemManager::SaveAction action = currentAction; currentAction = EditorItemManager::None; if (job->error()) { mItemUi->reject(ItemEditorUi::ItemFetchFailed, job->errorString()); return; } Akonadi::ItemFetchJob *fetchJob = qobject_cast(job); if (fetchJob->items().isEmpty()) { mItemUi->reject(ItemEditorUi::ItemFetchFailed); return; } Akonadi::Item item = fetchJob->items().at(0); if (mItemUi->hasSupportedPayload(item)) { setItem(item); if (action != EditorItemManager::None) { // Finally enable ok/apply buttons, we've finished loading Q_EMIT q->itemSaveFinished(action); } } else { mItemUi->reject(ItemEditorUi::ItemHasInvalidPayload); } } void ItemEditorPrivate::setItem(const Akonadi::Item &item) { Q_ASSERT(item.hasPayload()); mPrevItem = item; mItem = item; mItemUi->load(item); setupMonitor(); } void ItemEditorPrivate::itemMoveResult(KJob *job) { Q_ASSERT(job); Q_Q(EditorItemManager); if (job->error()) { Akonadi::ItemMoveJob *moveJob = qobject_cast(job); Q_ASSERT(moveJob); Q_UNUSED(moveJob); //Q_ASSERT(!moveJob->items().isEmpty()); // TODO: What is reasonable behavior at this point? qCCritical(INCIDENCEEDITOR_LOG) << "Error while moving item ";// << moveJob->items().first().id() << " to collection " //<< moveJob->destinationCollection() << job->errorString(); Q_EMIT q->itemSaveFailed(EditorItemManager::Move, job->errorString()); } else { // Fetch the item again, we want a new mItem, which has an updated parentCollection Akonadi::Item item(mItem.id()); // set currentAction, so the fetchResult slot emits itemSavedFinished(Move); // We could emit it here, but we should only enable ok/apply buttons after the loading // is complete currentAction = EditorItemManager::Move; q->load(item); } } void ItemEditorPrivate::onModifyFinished(int, const Akonadi::Item &item, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString) { Q_Q(EditorItemManager); if (resultCode == Akonadi::IncidenceChanger::ResultCodeSuccess) { if (mItem.parentCollection() == mItemUi->selectedCollection() || mItem.storageCollectionId() == mItemUi->selectedCollection().id()) { mItem = item; Q_EMIT q->itemSaveFinished(EditorItemManager::Modify); setupMonitor(); } else { // There's a collection move too. Akonadi::ItemMoveJob *moveJob = new Akonadi::ItemMoveJob(mItem, mItemUi->selectedCollection()); q->connect(moveJob, SIGNAL(result(KJob*)), SLOT(moveJobFinished(KJob*))); } } else if (resultCode == Akonadi::IncidenceChanger::ResultCodeUserCanceled) { Q_EMIT q->itemSaveFailed(EditorItemManager::Modify, QString()); q->load(Akonadi::Item(mItem.id())); } else { qCCritical(INCIDENCEEDITOR_LOG) << "Modify failed " << errorString; Q_EMIT q->itemSaveFailed(EditorItemManager::Modify, errorString); } } void ItemEditorPrivate::onCreateFinished(int, const Akonadi::Item &item, Akonadi::IncidenceChanger::ResultCode resultCode, const QString &errorString) { Q_Q(EditorItemManager); if (resultCode == Akonadi::IncidenceChanger::ResultCodeSuccess) { currentAction = EditorItemManager::Create; q->load(item); setupMonitor(); } else { qCCritical(INCIDENCEEDITOR_LOG) << "Creation failed " << errorString; Q_EMIT q->itemSaveFailed(EditorItemManager::Create, errorString); } } void ItemEditorPrivate::setupMonitor() { // Q_Q(EditorItemManager); delete mItemMonitor; mItemMonitor = new Akonadi::Monitor; mItemMonitor->setObjectName(QStringLiteral("EditorItemManagerMonitor")); mItemMonitor->ignoreSession(Akonadi::Session::defaultSession()); mItemMonitor->itemFetchScope().fetchFullPayload(); if (mItem.isValid()) { mItemMonitor->setItemMonitored(mItem); } // q->connect(mItemMonitor, SIGNAL(itemChanged(Akonadi::Item,QSet)), // SLOT(itemChanged(Akonadi::Item,QSet))); } void ItemEditorPrivate::itemChanged(const Akonadi::Item &item, const QSet &partIdentifiers) { Q_Q(EditorItemManager); if (mItemUi->containsPayloadIdentifiers(partIdentifiers)) { QPointer dlg = new QMessageBox; //krazy:exclude=qclasses dlg->setIcon(QMessageBox::Question); dlg->setInformativeText(i18n("The item has been changed by another application.\n" "What should be done?")); dlg->addButton(i18n("Take over changes"), QMessageBox::AcceptRole); dlg->addButton(i18n("Ignore and Overwrite changes"), QMessageBox::RejectRole); if (dlg->exec() == QMessageBox::AcceptRole) { Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob(mItem); job->setFetchScope(mFetchScope); mItem = item; q->load(mItem); } else { mItem.setRevision(item.revision()); q->save(); } delete dlg; } // Overwrite or not, we need to update the revision and the remote id to be able // to store item later on. mItem.setRevision(item.revision()); } /// ItemEditor EditorItemManager::EditorItemManager(ItemEditorUi *ui, Akonadi::IncidenceChanger *changer) : d_ptr(new ItemEditorPrivate(changer, this)) { Q_D(ItemEditor); d->mItemUi = ui; } EditorItemManager::~EditorItemManager() { delete d_ptr; } Akonadi::Item EditorItemManager::item(ItemState state) const { Q_D(const ItemEditor); switch (state) { case EditorItemManager::AfterSave: if (d->mItem.hasPayload()) { return d->mItem; } else { qCDebug(INCIDENCEEDITOR_LOG) << "Won't return mItem because isValid = " << d->mItem.isValid() << "; and haPayload is " << d->mItem.hasPayload(); } break; case EditorItemManager::BeforeSave: if (d->mPrevItem.hasPayload()) { return d->mPrevItem; } else { qCDebug(INCIDENCEEDITOR_LOG) << "Won't return mPrevItem because isValid = " << d->mPrevItem.isValid() << "; and haPayload is " << d->mPrevItem.hasPayload(); } break; } qCDebug(INCIDENCEEDITOR_LOG) << "state = " << state; Q_ASSERT_X(false, "EditorItemManager::item", "Unknown enum value"); return Akonadi::Item(); } void EditorItemManager::load(const Akonadi::Item &item) { Q_D(ItemEditor); //We fetch anyways to make sure we have everything required including tags Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob(item, this); job->setFetchScope(d->mFetchScope); connect(job, SIGNAL(result(KJob*)), SLOT(itemFetchResult(KJob*))); } void EditorItemManager::save() { Q_D(ItemEditor); if (!d->mItemUi->isValid()) { Q_EMIT itemSaveFailed(d->mItem.isValid() ? Modify : Create, QString()); return; } if (!d->mItemUi->isDirty() && d->mItemUi->selectedCollection() == d->mItem.parentCollection()) { // Item did not change and was not moved Q_EMIT itemSaveFinished(None); return; } d->mChanger->setGroupwareCommunication( CalendarSupport::KCalPrefs::instance()->useGroupwareCommunication()); Akonadi::Item updateItem = d->mItemUi->save(d->mItem); Q_ASSERT(updateItem.id() == d->mItem.id()); d->mItem = updateItem; if (d->mItem.isValid()) { // A valid item. Means we're modifying. Q_ASSERT(d->mItem.parentCollection().isValid()); - KCalCore::Incidence::Ptr oldPayload = CalendarSupport::incidence(d->mPrevItem); + KCalendarCore::Incidence::Ptr oldPayload = CalendarSupport::incidence(d->mPrevItem); if (d->mItem.parentCollection() == d->mItemUi->selectedCollection() || d->mItem.storageCollectionId() == d->mItemUi->selectedCollection().id()) { d->mChanger->modifyIncidence(d->mItem, oldPayload); } else { Q_ASSERT(d->mItemUi->selectedCollection().isValid()); Q_ASSERT(d->mItem.parentCollection().isValid()); // ETM and the KSelectionProxyModel has a bug wrt collections moves, so this is disabled. // To test this, enable the collection combo-box and remove the following assert. qCDebug(INCIDENCEEDITOR_LOG) << "Moving from" << d->mItem.parentCollection().id() << "to" << d->mItemUi->selectedCollection().id(); if (d->mItemUi->isDirty()) { d->mChanger->modifyIncidence(d->mItem, oldPayload); } else { Akonadi::ItemMoveJob *itemMoveJob = new Akonadi::ItemMoveJob(d->mItem, d->mItemUi->selectedCollection()); connect(itemMoveJob, SIGNAL(result(KJob*)), SLOT(itemMoveResult(KJob*))); } } } else { // An invalid item. Means we're creating. if (d->mIsCounterProposal) { // We don't write back to akonadi, that will be done in ITipHandler. Q_EMIT itemSaveFinished(EditorItemManager::Modify); } else { Q_ASSERT(d->mItemUi->selectedCollection().isValid()); - KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence(d->mItem); + KCalendarCore::Incidence::Ptr incidence = CalendarSupport::incidence(d->mItem); d->mChanger->createIncidence(incidence, d->mItemUi->selectedCollection()); } } } void EditorItemManager::setIsCounterProposal(bool isCounterProposal) { Q_D(ItemEditor); d->mIsCounterProposal = isCounterProposal; } ItemEditorUi::~ItemEditorUi() { } bool ItemEditorUi::isValid() const { return true; } } // namespace #include "moc_editoritemmanager.cpp" diff --git a/src/freebusyganttproxymodel.cpp b/src/freebusyganttproxymodel.cpp index e20a973..1b1a068 100644 --- a/src/freebusyganttproxymodel.cpp +++ b/src/freebusyganttproxymodel.cpp @@ -1,112 +1,112 @@ /* Copyright (C) 2010 Casey Link Copyright (C) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "freebusyganttproxymodel.h" #include "CalendarSupport/FreeBusyItemModel" #include -#include +#include #include #include using namespace IncidenceEditorNG; FreeBusyGanttProxyModel::FreeBusyGanttProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { } QVariant FreeBusyGanttProxyModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } QModelIndex source_index = mapToSource(index); // if the index is not valid, then its a toplevel item, which is an attendee if (!source_index.parent().isValid()) { switch (role) { case KGantt::ItemTypeRole: return KGantt::TypeMulti; case Qt::DisplayRole: return source_index.data(Qt::DisplayRole); default: return QVariant(); } } // if the index is valid, then it corresponds to a free busy period - KCalCore::FreeBusyPeriod period + KCalendarCore::FreeBusyPeriod period = sourceModel()->data(source_index, CalendarSupport::FreeBusyItemModel::FreeBusyPeriodRole). - value(); + value(); switch (role) { case KGantt::ItemTypeRole: return KGantt::TypeTask; case KGantt::StartTimeRole: return period.start().toLocalTime(); case KGantt::EndTimeRole: return period.end().toLocalTime(); case Qt::BackgroundRole: return QColor(Qt::red); case Qt::ToolTipRole: return tooltipify(period); case Qt::DisplayRole: return sourceModel()->data(source_index.parent(), Qt::DisplayRole); default: return QVariant(); } } -QString FreeBusyGanttProxyModel::tooltipify(const KCalCore::FreeBusyPeriod &period) const +QString FreeBusyGanttProxyModel::tooltipify(const KCalendarCore::FreeBusyPeriod &period) const { QString toolTip = QStringLiteral(""); toolTip += QStringLiteral("") + i18nc("@info:tooltip", "Free/Busy Period") + QStringLiteral( ""); toolTip += QStringLiteral("
"); if (!period.summary().isEmpty()) { toolTip += QStringLiteral("") + i18nc("@info:tooltip", "Summary:") + QStringLiteral( "") + QStringLiteral(" "); toolTip += period.summary(); toolTip += QStringLiteral("
"); } if (!period.location().isEmpty()) { toolTip += QStringLiteral("") + i18nc("@info:tooltip", "Location:") + QStringLiteral( "") + QStringLiteral(" "); toolTip += period.location(); toolTip += QStringLiteral("
"); } toolTip += QStringLiteral("") + i18nc("@info:tooltip period start time", "Start:") + QStringLiteral("") + QStringLiteral( " "); toolTip += QLocale().toString(period.start().toLocalTime(), QLocale::ShortFormat); toolTip += QStringLiteral("
"); toolTip += QStringLiteral("") + i18nc("@info:tooltip period end time", "End:") + QStringLiteral("") + QStringLiteral( " "); toolTip += QLocale().toString(period.end().toLocalTime(), QLocale::ShortFormat); toolTip += QStringLiteral("
"); toolTip += QStringLiteral("
"); return toolTip; } diff --git a/src/freebusyganttproxymodel.h b/src/freebusyganttproxymodel.h index e3d56f1..51de7de 100644 --- a/src/freebusyganttproxymodel.h +++ b/src/freebusyganttproxymodel.h @@ -1,53 +1,53 @@ /* Copyright (C) 2010 Casey Link Copyright (C) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_FREEBUSYGANTTPROXYMODEL_H #define INCIDENCEEDITOR_FREEBUSYGANTTPROXYMODEL_H #include "incidenceeditor_export.h" #include -namespace KCalCore { +namespace KCalendarCore { class FreeBusyPeriod; } namespace IncidenceEditorNG { /** * This is a private proxy model, that wraps the free busy data exposed * by the FreeBusyItemModel for use by KDGantt2. * * This model exposes the FreeBusyPeriods, which are the child level nodes * in FreeBusyItemModel, as a list. * * @see FreeBusyItemMode * @see FreeBusyItem */ class INCIDENCEEDITOR_EXPORT FreeBusyGanttProxyModel : public QSortFilterProxyModel { Q_OBJECT public: explicit FreeBusyGanttProxyModel(QObject *parent = nullptr); Q_REQUIRED_RESULT QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - Q_REQUIRED_RESULT QString tooltipify(const KCalCore::FreeBusyPeriod &period) const; + Q_REQUIRED_RESULT QString tooltipify(const KCalendarCore::FreeBusyPeriod &period) const; }; } #endif diff --git a/src/groupwareuidelegate.cpp b/src/groupwareuidelegate.cpp index 7cfd8bd..261e032 100644 --- a/src/groupwareuidelegate.cpp +++ b/src/groupwareuidelegate.cpp @@ -1,65 +1,65 @@ /* Copyright (c) 2010 Kevin Ottens 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 "groupwareuidelegate.h" #include "incidencedialog.h" #include "incidencedialogfactory.h" #include #include #include "incidenceeditor_debug.h" using namespace IncidenceEditorNG; void GroupwareUiDelegate::requestIncidenceEditor(const Akonadi::Item &item) { // TODO_KDE5: // The GroupwareUiDelegate interface should be a QObject. Right now we have no way of emitting a // finished signal, so we have to use dialog->exec(); - const KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence(item); + const KCalendarCore::Incidence::Ptr incidence = CalendarSupport::incidence(item); if (!incidence) { qCWarning(INCIDENCEEDITOR_LOG) << "Incidence is null, won't open the editor"; return; } IncidenceDialog *dialog = IncidenceDialogFactory::create(/*needs initial saving=*/ false, incidence->type(), nullptr); dialog->setAttribute(Qt::WA_DeleteOnClose, false); dialog->setIsCounterProposal(true); dialog->load(item, QDate::currentDate()); dialog->exec(); dialog->deleteLater(); Akonadi::Item newItem = dialog->item(); - if (newItem.hasPayload()) { - KCalCore::IncidenceBase::Ptr newIncidence = newItem.payload(); - *incidence.staticCast() = *newIncidence; + if (newItem.hasPayload()) { + KCalendarCore::IncidenceBase::Ptr newIncidence = newItem.payload(); + *incidence.staticCast() = *newIncidence; } } void GroupwareUiDelegate::setCalendar(const Akonadi::ETMCalendar::Ptr &calendar) { // We don't need a calendar. Q_UNUSED(calendar); } void GroupwareUiDelegate::createCalendar() { // We don't need a calendar } diff --git a/src/incidencealarm.cpp b/src/incidencealarm.cpp index cc2cd7b..5d9bb0a 100644 --- a/src/incidencealarm.cpp +++ b/src/incidencealarm.cpp @@ -1,427 +1,427 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidencealarm.h" #include "alarmdialog.h" #include "alarmpresets.h" #include "incidencedatetime.h" #include "ui_dialogdesktop.h" #include using namespace IncidenceEditorNG; using namespace CalendarSupport; IncidenceAlarm::IncidenceAlarm(IncidenceDateTime *dateTime, Ui::EventOrTodoDesktop *ui) : mUi(ui) , mDateTime(dateTime) , mEnabledAlarmCount(0) , mIsTodo(false) { setObjectName(QStringLiteral("IncidenceAlarm")); mUi->mAlarmPresetCombo->insertItems(0, AlarmPresets::availablePresets()); mUi->mAlarmPresetCombo->setCurrentIndex(AlarmPresets::defaultPresetIndex()); updateButtons(); connect(mDateTime, &IncidenceDateTime::startDateTimeToggled, this, &IncidenceAlarm::handleDateTimeToggle); connect(mDateTime, &IncidenceDateTime::endDateTimeToggled, this, &IncidenceAlarm::handleDateTimeToggle); connect(mUi->mAlarmAddPresetButton, &QPushButton::clicked, this, &IncidenceAlarm::newAlarmFromPreset); connect(mUi->mAlarmList, &QListWidget::itemSelectionChanged, this, &IncidenceAlarm::updateButtons); connect(mUi->mAlarmNewButton, &QPushButton::clicked, this, &IncidenceAlarm::newAlarm); connect(mUi->mAlarmConfigureButton, &QPushButton::clicked, this, &IncidenceAlarm::editCurrentAlarm); connect(mUi->mAlarmToggleButton, &QPushButton::clicked, this, &IncidenceAlarm::toggleCurrentAlarm); connect(mUi->mAlarmRemoveButton, &QPushButton::clicked, this, &IncidenceAlarm::removeCurrentAlarm); } -void IncidenceAlarm::load(const KCalCore::Incidence::Ptr &incidence) +void IncidenceAlarm::load(const KCalendarCore::Incidence::Ptr &incidence) { mLoadedIncidence = incidence; // We must be sure that the date/time in mDateTime is the correct date time. // So don't depend on CombinedIncidenceEditor or whatever external factor to // load the date/time before loading the recurrence mDateTime->load(incidence); mAlarms.clear(); const auto lstAlarms = incidence->alarms(); - for (const KCalCore::Alarm::Ptr &alarm : lstAlarms) { - mAlarms.append(KCalCore::Alarm::Ptr(new KCalCore::Alarm(*alarm.data()))); + for (const KCalendarCore::Alarm::Ptr &alarm : lstAlarms) { + mAlarms.append(KCalendarCore::Alarm::Ptr(new KCalendarCore::Alarm(*alarm.data()))); } - mIsTodo = incidence->type() == KCalCore::Incidence::TypeTodo; + mIsTodo = incidence->type() == KCalendarCore::Incidence::TypeTodo; if (mIsTodo) { mUi->mAlarmPresetCombo->clear(); mUi->mAlarmPresetCombo->addItems(AlarmPresets::availablePresets(AlarmPresets::BeforeEnd)); } else { mUi->mAlarmPresetCombo->clear(); mUi->mAlarmPresetCombo->addItems(AlarmPresets::availablePresets(AlarmPresets::BeforeStart)); } mUi->mAlarmPresetCombo->setCurrentIndex(AlarmPresets::defaultPresetIndex()); handleDateTimeToggle(); mWasDirty = false; updateAlarmList(); } -void IncidenceAlarm::save(const KCalCore::Incidence::Ptr &incidence) +void IncidenceAlarm::save(const KCalendarCore::Incidence::Ptr &incidence) { incidence->clearAlarms(); - const KCalCore::Alarm::List::ConstIterator end(mAlarms.constEnd()); - for (KCalCore::Alarm::List::ConstIterator it = mAlarms.constBegin(); it != end; ++it) { - KCalCore::Alarm::Ptr al(new KCalCore::Alarm(*(*it))); + const KCalendarCore::Alarm::List::ConstIterator end(mAlarms.constEnd()); + for (KCalendarCore::Alarm::List::ConstIterator it = mAlarms.constBegin(); it != end; ++it) { + KCalendarCore::Alarm::Ptr al(new KCalendarCore::Alarm(*(*it))); al->setParent(incidence.data()); // We need to make sure that both lists are the same in the end for isDirty. Q_ASSERT(*al == *(*it)); incidence->addAlarm(al); } } bool IncidenceAlarm::isDirty() const { if (mLoadedIncidence->alarms().count() != mAlarms.count()) { return true; } if (!mLoadedIncidence->alarms().isEmpty()) { - const KCalCore::Alarm::List initialAlarms = mLoadedIncidence->alarms(); + const KCalendarCore::Alarm::List initialAlarms = mLoadedIncidence->alarms(); if (initialAlarms.count() != mAlarms.count()) { return true; // The number of alarms has changed } // Note: Not the most efficient algorithm but I'm assuming that we're only // dealing with a couple, at most tens of alarms. The idea is we check // if all currently enabled alarms are also in the incidence. The // disabled alarms are not changed by our code at all, so we assume that // they're still there. - for (const KCalCore::Alarm::Ptr &alarm : qAsConst(mAlarms)) { + for (const KCalendarCore::Alarm::Ptr &alarm : qAsConst(mAlarms)) { bool found = false; - for (const KCalCore::Alarm::Ptr &initialAlarm : qAsConst(initialAlarms)) { + for (const KCalendarCore::Alarm::Ptr &initialAlarm : qAsConst(initialAlarms)) { if (*alarm == *initialAlarm) { found = true; break; } } if (!found) { // There was an alarm in the mLoadedIncidence->alarms() that wasn't found // in mLastAlarms. This means that one of the alarms was modified. return true; } } } return false; } void IncidenceAlarm::editCurrentAlarm() { - KCalCore::Alarm::Ptr currentAlarm = mAlarms.at(mUi->mAlarmList->currentRow()); + KCalendarCore::Alarm::Ptr currentAlarm = mAlarms.at(mUi->mAlarmList->currentRow()); QPointer dialog(new AlarmDialog(mLoadedIncidence->type(), mUi->mTabWidget)); dialog->load(currentAlarm); dialog->setAllowBeginReminders(mDateTime->startDateTimeEnabled()); dialog->setAllowEndReminders(mDateTime->endDateTimeEnabled()); if (dialog->exec() == QDialog::Accepted) { dialog->save(currentAlarm); updateAlarmList(); checkDirtyStatus(); } delete dialog; } void IncidenceAlarm::handleDateTimeToggle() { QWidget *parent = mUi->mAlarmPresetCombo->parentWidget(); // the parent of a toplevel widget if (parent) { parent->setEnabled(mDateTime->startDateTimeEnabled() || mDateTime->endDateTimeEnabled()); } mUi->mAlarmPresetCombo->setEnabled(mDateTime->endDateTimeEnabled()); mUi->mAlarmAddPresetButton->setEnabled(mDateTime->endDateTimeEnabled()); mUi->mQuickAddReminderLabel->setEnabled(mDateTime->endDateTimeEnabled()); } void IncidenceAlarm::newAlarm() { QPointer dialog(new AlarmDialog(mLoadedIncidence->type(), mUi->mTabWidget)); const int reminderOffset = KCalPrefs::instance()->reminderTime(); if (reminderOffset >= 0) { dialog->setOffset(reminderOffset); } else { dialog->setOffset(DEFAULT_REMINDER_OFFSET); } dialog->setUnit(AlarmDialog::Minutes); if (mIsTodo && mDateTime->endDateTimeEnabled()) { dialog->setWhen(AlarmDialog::BeforeEnd); } else { dialog->setWhen(AlarmDialog::BeforeStart); } dialog->setAllowBeginReminders(mDateTime->startDateTimeEnabled()); dialog->setAllowEndReminders(mDateTime->endDateTimeEnabled()); if (dialog->exec() == QDialog::Accepted) { - KCalCore::Alarm::Ptr newAlarm(new KCalCore::Alarm(nullptr)); + KCalendarCore::Alarm::Ptr newAlarm(new KCalendarCore::Alarm(nullptr)); dialog->save(newAlarm); newAlarm->setEnabled(true); mAlarms.append(newAlarm); updateAlarmList(); checkDirtyStatus(); } delete dialog; } void IncidenceAlarm::newAlarmFromPreset() { if (mIsTodo) { mAlarms.append( AlarmPresets::preset(AlarmPresets::BeforeEnd, mUi->mAlarmPresetCombo->currentText())); } else { mAlarms.append( AlarmPresets::preset(AlarmPresets::BeforeStart, mUi->mAlarmPresetCombo->currentText())); } updateAlarmList(); checkDirtyStatus(); } void IncidenceAlarm::removeCurrentAlarm() { Q_ASSERT(mUi->mAlarmList->selectedItems().size() == 1); const int curAlarmIndex = mUi->mAlarmList->currentRow(); delete mUi->mAlarmList->takeItem(curAlarmIndex); mAlarms.remove(curAlarmIndex); updateAlarmList(); updateButtons(); checkDirtyStatus(); } void IncidenceAlarm::toggleCurrentAlarm() { Q_ASSERT(mUi->mAlarmList->selectedItems().size() == 1); const int curAlarmIndex = mUi->mAlarmList->currentRow(); - KCalCore::Alarm::Ptr alarm = mAlarms.at(curAlarmIndex); + KCalendarCore::Alarm::Ptr alarm = mAlarms.at(curAlarmIndex); alarm->setEnabled(!alarm->enabled()); updateButtons(); updateAlarmList(); checkDirtyStatus(); } void IncidenceAlarm::updateAlarmList() { const int prevEnabledAlarmCount = mEnabledAlarmCount; mEnabledAlarmCount = 0; const QModelIndex currentIndex = mUi->mAlarmList->currentIndex(); mUi->mAlarmList->clear(); - for (const KCalCore::Alarm::Ptr &alarm : qAsConst(mAlarms)) { + for (const KCalendarCore::Alarm::Ptr &alarm : qAsConst(mAlarms)) { mUi->mAlarmList->addItem(stringForAlarm(alarm)); if (alarm->enabled()) { ++mEnabledAlarmCount; } } mUi->mAlarmList->setCurrentIndex(currentIndex); if (prevEnabledAlarmCount != mEnabledAlarmCount) { Q_EMIT alarmCountChanged(mEnabledAlarmCount); } } void IncidenceAlarm::updateButtons() { if (mUi->mAlarmList->count() > 0 && !mUi->mAlarmList->selectedItems().isEmpty()) { mUi->mAlarmConfigureButton->setEnabled(true); mUi->mAlarmRemoveButton->setEnabled(true); mUi->mAlarmToggleButton->setEnabled(true); - KCalCore::Alarm::Ptr selAlarm; + KCalendarCore::Alarm::Ptr selAlarm; if (mUi->mAlarmList->currentIndex().isValid()) { selAlarm = mAlarms.at(mUi->mAlarmList->currentIndex().row()); } if (selAlarm && selAlarm->enabled()) { mUi->mAlarmToggleButton->setText(i18nc("Disable currently selected reminder", "Disable")); } else { mUi->mAlarmToggleButton->setText(i18nc("Enable currently selected reminder", "Enable")); } } else { mUi->mAlarmConfigureButton->setEnabled(false); mUi->mAlarmRemoveButton->setEnabled(false); mUi->mAlarmToggleButton->setEnabled(false); } } -QString IncidenceAlarm::stringForAlarm(const KCalCore::Alarm::Ptr &alarm) +QString IncidenceAlarm::stringForAlarm(const KCalendarCore::Alarm::Ptr &alarm) { Q_ASSERT(alarm); QString action; switch (alarm->type()) { - case KCalCore::Alarm::Display: + case KCalendarCore::Alarm::Display: action = i18nc("Alarm action", "Display a dialog"); break; - case KCalCore::Alarm::Procedure: + case KCalendarCore::Alarm::Procedure: action = i18nc("Alarm action", "Execute a script"); break; - case KCalCore::Alarm::Email: + case KCalendarCore::Alarm::Email: action = i18nc("Alarm action", "Send an email"); break; - case KCalCore::Alarm::Audio: + case KCalendarCore::Alarm::Audio: action = i18nc("Alarm action", "Play an audio file"); break; default: action = i18nc("Alarm action", "Invalid Reminder."); return action; } const int offset = alarm->hasStartOffset() ? alarm->startOffset().asSeconds() / 60 : alarm->endOffset().asSeconds() / 60; // make minutes QString offsetUnitTranslated = i18ncp("The reminder is set to X minutes before/after the event", "1 minute", "%1 minutes", qAbs(offset)); int useoffset = offset; if (offset % (24 * 60) == 0 && offset != 0) { // divides evenly into days? useoffset = offset / 60 / 24; offsetUnitTranslated = i18ncp("The reminder is set to X days before/after the event", "1 day", "%1 days", qAbs(useoffset)); } else if (offset % 60 == 0 && offset != 0) { // divides evenly into hours? useoffset = offset / 60; offsetUnitTranslated = i18ncp("The reminder is set to X hours before/after the event", "1 hour", "%1 hours", qAbs(useoffset)); } QString repeatStr; if (alarm->repeatCount() > 0) { repeatStr = i18nc("The reminder is configured to repeat after snooze", "(Repeats)"); } if (alarm->enabled()) { if (useoffset > 0 && alarm->hasStartOffset()) { if (mIsTodo) { // i18n: These series of strings are used to show the user a description of // the alarm. %1 is replaced by one of the actions above, %2 is replaced by // one of the time units above, %3 is the (Repeats) part that will be used // in case of repetition of the alarm. return i18n("%1 %2 after the to-do started %3", action, offsetUnitTranslated, repeatStr); } else { return i18n("%1 %2 after the event started %3", action, offsetUnitTranslated, repeatStr); } } else if (useoffset < 0 && alarm->hasStartOffset()) { if (mIsTodo) { return i18n("%1 %2 before the to-do starts %3", action, offsetUnitTranslated, repeatStr); } else { return i18n("%1 %2 before the event starts %3", action, offsetUnitTranslated, repeatStr); } } else if (useoffset > 0 && alarm->hasEndOffset()) { if (mIsTodo) { return i18n("%1 %2 after the to-do is due %3", action, offsetUnitTranslated, repeatStr); } else { return i18n("%1 %2 after the event ends %3", action, offsetUnitTranslated, repeatStr); } } else if (useoffset < 0 && alarm->hasEndOffset()) { if (mIsTodo) { return i18n("%1 %2 before the to-do is due %3", action, offsetUnitTranslated, repeatStr); } else { return i18n("%1 %2 before the event ends %3", action, offsetUnitTranslated, repeatStr); } } } else { if (useoffset > 0 && alarm->hasStartOffset()) { if (mIsTodo) { return i18n("%1 %2 after the to-do started %3 (Disabled)", action, offsetUnitTranslated, repeatStr); } else { return i18n("%1 %2 after the event started %3 (Disabled)", action, offsetUnitTranslated, repeatStr); } } else if (useoffset < 0 && alarm->hasStartOffset()) { if (mIsTodo) { return i18n("%1 %2 before the to-do starts %3 (Disabled)", action, offsetUnitTranslated, repeatStr); } else { return i18n("%1 %2 before the event starts %3 (Disabled)", action, offsetUnitTranslated, repeatStr); } } else if (useoffset > 0 && alarm->hasEndOffset()) { if (mIsTodo) { return i18n("%1 %2 after the to-do is due %3 (Disabled)", action, offsetUnitTranslated, repeatStr); } else { return i18n("%1 %2 after the event ends %3 (Disabled)", action, offsetUnitTranslated, repeatStr); } } else if (useoffset < 0 && alarm->hasEndOffset()) { if (mIsTodo) { return i18n("%1 %2 before the to-do is due %3 (Disabled)", action, offsetUnitTranslated, repeatStr); } else { return i18n("%1 %2 before the event ends %3 (Disabled)", action, offsetUnitTranslated, repeatStr); } } } // useoffset == 0 if (alarm->enabled()) { if (mIsTodo && alarm->hasStartOffset()) { return i18n("%1 when the to-do starts", action); } else if (alarm->hasStartOffset()) { return i18n("%1 when the event starts", action); } else if (mIsTodo && alarm->hasEndOffset()) { return i18n("%1 when the to-do is due", action); } else { return i18n("%1 when the event ends", action); } } else { if (mIsTodo && alarm->hasStartOffset()) { return i18n("%1 when the to-do starts (Disabled)", action); } else if (alarm->hasStartOffset()) { return i18n("%1 when the event starts (Disabled)", action); } else if (mIsTodo && alarm->hasEndOffset()) { return i18n("%1 when the to-do is due (Disabled)", action); } else { return i18n("%1 when the event ends (Disabled)", action); } } } diff --git a/src/incidencealarm.h b/src/incidencealarm.h index 0a140f0..5963dd8 100644 --- a/src/incidencealarm.h +++ b/src/incidencealarm.h @@ -1,69 +1,69 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCEALARM_H #define INCIDENCEEDITOR_INCIDENCEALARM_H #include "incidenceeditor-ng.h" namespace Ui { class EventOrTodoDesktop; } namespace IncidenceEditorNG { class IncidenceDateTime; class IncidenceAlarm : public IncidenceEditor { Q_OBJECT public: using IncidenceEditorNG::IncidenceEditor::load; // So we don't trigger -Woverloaded-virtual using IncidenceEditorNG::IncidenceEditor::save; // So we don't trigger -Woverloaded-virtual IncidenceAlarm(IncidenceDateTime *dateTime, Ui::EventOrTodoDesktop *ui); - void load(const KCalCore::Incidence::Ptr &incidence) override; - void save(const KCalCore::Incidence::Ptr &incidence) override; + void load(const KCalendarCore::Incidence::Ptr &incidence) override; + void save(const KCalendarCore::Incidence::Ptr &incidence) override; Q_REQUIRED_RESULT bool isDirty() const override; Q_SIGNALS: void alarmCountChanged(int newCount); private: void editCurrentAlarm(); void handleDateTimeToggle(); void newAlarm(); void newAlarmFromPreset(); void removeCurrentAlarm(); void toggleCurrentAlarm(); void updateAlarmList(); void updateButtons(); - QString stringForAlarm(const KCalCore::Alarm::Ptr &alarm); + QString stringForAlarm(const KCalendarCore::Alarm::Ptr &alarm); private: Ui::EventOrTodoDesktop *mUi = nullptr; - KCalCore::Alarm::List mAlarms; + KCalendarCore::Alarm::List mAlarms; IncidenceDateTime *mDateTime = nullptr; int mEnabledAlarmCount = 0; bool mIsTodo = false; }; } #endif diff --git a/src/incidenceattachment.cpp b/src/incidenceattachment.cpp index f6be4c6..be4c8d8 100644 --- a/src/incidenceattachment.cpp +++ b/src/incidenceattachment.cpp @@ -1,619 +1,619 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidenceattachment.h" #include "attachmenteditdialog.h" #include "attachmenticonview.h" #include "ui_dialogdesktop.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace IncidenceEditorNG; IncidenceAttachment::IncidenceAttachment(Ui::EventOrTodoDesktop *ui) : IncidenceEditor(nullptr) , mUi(ui) , mPopupMenu(new QMenu) { setupActions(); setupAttachmentIconView(); setObjectName(QStringLiteral("IncidenceAttachment")); connect(mUi->mAddButton, &QPushButton::clicked, this, &IncidenceAttachment::addAttachment); connect(mUi->mRemoveButton, &QPushButton::clicked, this, &IncidenceAttachment::removeSelectedAttachments); } IncidenceAttachment::~IncidenceAttachment() { delete mPopupMenu; } -void IncidenceAttachment::load(const KCalCore::Incidence::Ptr &incidence) +void IncidenceAttachment::load(const KCalendarCore::Incidence::Ptr &incidence) { mLoadedIncidence = incidence; mAttachmentView->clear(); - KCalCore::Attachment::List attachments = incidence->attachments(); - for (KCalCore::Attachment::List::ConstIterator it = attachments.constBegin(), + KCalendarCore::Attachment::List attachments = incidence->attachments(); + for (KCalendarCore::Attachment::List::ConstIterator it = attachments.constBegin(), end = attachments.constEnd(); it != end; ++it) { new AttachmentIconItem((*it), mAttachmentView); } mWasDirty = false; } -void IncidenceAttachment::save(const KCalCore::Incidence::Ptr &incidence) +void IncidenceAttachment::save(const KCalendarCore::Incidence::Ptr &incidence) { incidence->clearAttachments(); for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { QListWidgetItem *item = mAttachmentView->item(itemIndex); AttachmentIconItem *attitem = dynamic_cast(item); Q_ASSERT(item); incidence->addAttachment(attitem->attachment()); } } bool IncidenceAttachment::isDirty() const { if (mLoadedIncidence) { if (mAttachmentView->count() != mLoadedIncidence->attachments().count()) { return true; } - KCalCore::Attachment::List origAttachments = mLoadedIncidence->attachments(); + KCalendarCore::Attachment::List origAttachments = mLoadedIncidence->attachments(); for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { QListWidgetItem *item = mAttachmentView->item(itemIndex); Q_ASSERT(dynamic_cast(item)); - const KCalCore::Attachment listAttachment = static_cast(item)->attachment(); + const KCalendarCore::Attachment listAttachment = static_cast(item)->attachment(); for (int i = 0; i < origAttachments.count(); ++i) { - const KCalCore::Attachment attachment = origAttachments.at(i); + const KCalendarCore::Attachment attachment = origAttachments.at(i); if (attachment == listAttachment) { origAttachments.remove(i); break; } } } // All attachments are removed from the list, meaning, the items in mAttachmentView // are equal to the attachments set on mLoadedIncidence. return !origAttachments.isEmpty(); } else { // No incidence loaded, so if the user added attachments we're dirty. return mAttachmentView->count() != 0; } } int IncidenceAttachment::attachmentCount() const { return mAttachmentView->count(); } /// Private slots void IncidenceAttachment::addAttachment() { QPointer that(this); - AttachmentIconItem *item = new AttachmentIconItem(KCalCore::Attachment(), mAttachmentView); + AttachmentIconItem *item = new AttachmentIconItem(KCalendarCore::Attachment(), mAttachmentView); QPointer dialog(new AttachmentEditDialog(item, mAttachmentView)); dialog->setWindowTitle(i18nc("@title", "Add Attachment")); auto dialogResult = dialog->exec(); if (!that) { return; } if (dialogResult == QDialog::Rejected) { delete item; } else { Q_EMIT attachmentCountChanged(mAttachmentView->count()); } delete dialog; checkDirtyStatus(); } void IncidenceAttachment::copyToClipboard() { #ifndef QT_NO_CLIPBOARD QApplication::clipboard()->setMimeData(mAttachmentView->mimeData(), QClipboard::Clipboard); #endif } void IncidenceAttachment::openURL(const QUrl &url) { QString uri = url.url(); UriHandler::process(uri); } void IncidenceAttachment::pasteFromClipboard() { #ifndef QT_NO_CLIPBOARD handlePasteOrDrop(QApplication::clipboard()->mimeData()); #endif } void IncidenceAttachment::removeSelectedAttachments() { QList selected; QStringList labels; for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { QListWidgetItem *it = mAttachmentView->item(itemIndex); if (it->isSelected()) { AttachmentIconItem *attitem = static_cast(it); if (attitem) { - const KCalCore::Attachment att = attitem->attachment(); + const KCalendarCore::Attachment att = attitem->attachment(); labels << att.label(); selected << it; } } } if (selected.isEmpty()) { return; } QString labelsStr = labels.join(QStringLiteral("")); if (KMessageBox::questionYesNo( nullptr, xi18nc("@info", "Do you really want to remove these attachments?%1", labelsStr), i18nc("@title:window", "Remove Attachments?"), KStandardGuiItem::yes(), KStandardGuiItem::no(), QStringLiteral("calendarRemoveAttachments")) != KMessageBox::Yes) { return; } for (QList::iterator it(selected.begin()), end(selected.end()); it != end; ++it) { int row = mAttachmentView->row(*it); QListWidgetItem *next = mAttachmentView->item(++row); QListWidgetItem *prev = mAttachmentView->item(--row); if (next) { next->setSelected(true); } else if (prev) { prev->setSelected(true); } delete *it; } mAttachmentView->update(); Q_EMIT attachmentCountChanged(mAttachmentView->count()); checkDirtyStatus(); } void IncidenceAttachment::saveAttachment(QListWidgetItem *item) { Q_ASSERT(item); Q_ASSERT(dynamic_cast(item)); AttachmentIconItem *attitem = static_cast(item); if (attitem->attachment().isEmpty()) { return; } - KCalCore::Attachment att = attitem->attachment(); + KCalendarCore::Attachment att = attitem->attachment(); // get the saveas file name const QString saveAsFile = QFileDialog::getSaveFileName(nullptr, i18nc("@title", "Save Attachment"), att.label()); if (saveAsFile.isEmpty()) { return; } QUrl sourceUrl; if (att.isUri()) { sourceUrl = QUrl(att.uri()); } else { sourceUrl = attitem->tempFileForAttachment(); } // save the attachment url auto job = KIO::file_copy(sourceUrl, QUrl::fromLocalFile(saveAsFile)); if (!job->exec() && job->error()) { KMessageBox::error(nullptr, job->errorString()); } } void IncidenceAttachment::saveSelectedAttachments() { for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { QListWidgetItem *item = mAttachmentView->item(itemIndex); if (item->isSelected()) { saveAttachment(item); } } } void IncidenceAttachment::showAttachment(QListWidgetItem *item) { Q_ASSERT(item); Q_ASSERT(dynamic_cast(item)); AttachmentIconItem *attitem = static_cast(item); if (attitem->attachment().isEmpty()) { return; } - const KCalCore::Attachment att = attitem->attachment(); + const KCalendarCore::Attachment att = attitem->attachment(); if (att.isUri()) { openURL(QUrl(att.uri())); } else { KRun::RunFlags flags; flags |= KRun::DeleteTemporaryFiles; flags |= KRun::RunExecutables; KRun::runUrl(attitem->tempFileForAttachment(), att.mimeType(), nullptr, flags); } } void IncidenceAttachment::showContextMenu(const QPoint &pos) { QListWidgetItem *item = mAttachmentView->itemAt(pos); const bool enable = item != nullptr; int numSelected = 0; for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { QListWidgetItem *item = mAttachmentView->item(itemIndex); if (item->isSelected()) { numSelected++; } } mOpenAction->setEnabled(enable); //TODO: support saving multiple attachments into a directory mSaveAsAction->setEnabled(enable && numSelected == 1); #ifndef QT_NO_CLIPBOARD mCopyAction->setEnabled(enable && numSelected == 1); mCutAction->setEnabled(enable && numSelected == 1); #endif mDeleteAction->setEnabled(enable); mEditAction->setEnabled(enable); mPopupMenu->exec(mAttachmentView->mapToGlobal(pos)); } void IncidenceAttachment::showSelectedAttachments() { for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { QListWidgetItem *item = mAttachmentView->item(itemIndex); if (item->isSelected()) { showAttachment(item); } } } void IncidenceAttachment::cutToClipboard() { #ifndef QT_NO_CLIPBOARD copyToClipboard(); removeSelectedAttachments(); #endif } void IncidenceAttachment::editSelectedAttachments() { for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { QListWidgetItem *item = mAttachmentView->item(itemIndex); if (item->isSelected()) { Q_ASSERT(dynamic_cast(item)); AttachmentIconItem *attitem = static_cast(item); if (attitem->attachment().isEmpty()) { return; } QPointer dialog( new AttachmentEditDialog(attitem, mAttachmentView, false)); dialog->setModal(false); dialog->setAttribute(Qt::WA_DeleteOnClose, true); dialog->show(); } } } void IncidenceAttachment::slotItemRenamed(QListWidgetItem *item) { Q_ASSERT(item); Q_ASSERT(dynamic_cast(item)); static_cast(item)->setLabel(item->text()); checkDirtyStatus(); } void IncidenceAttachment::slotSelectionChanged() { bool selected = false; for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { QListWidgetItem *item = mAttachmentView->item(itemIndex); if (item->isSelected()) { selected = true; break; } } mUi->mRemoveButton->setEnabled(selected); } /// Private functions void IncidenceAttachment::handlePasteOrDrop(const QMimeData *mimeData) { QList urls; bool probablyWeHaveUris = false; QStringList labels; if (KContacts::VCardDrag::canDecode(mimeData)) { KContacts::Addressee::List addressees; KContacts::VCardDrag::fromMimeData(mimeData, addressees); urls.reserve(addressees.count()); labels.reserve(addressees.count()); const KContacts::Addressee::List::ConstIterator end(addressees.constEnd()); for (KContacts::Addressee::List::ConstIterator it = addressees.constBegin(); it != end; ++it) { urls.append(QUrl(QStringLiteral("uid:") + (*it).uid())); // there is some weirdness about realName(), hence fromUtf8 labels.append(QString::fromUtf8((*it).realName().toLatin1())); } probablyWeHaveUris = true; } else if (mimeData->hasUrls()) { QMap metadata; //QT5 //urls = QList::fromMimeData( mimeData, &metadata ); probablyWeHaveUris = true; labels = metadata[QStringLiteral("labels")].split(QLatin1Char(':'), QString::SkipEmptyParts); const QStringList::Iterator end(labels.end()); for (QStringList::Iterator it = labels.begin(); it != end; ++it) { *it = QUrl::fromPercentEncoding((*it).toLatin1()); } } else if (mimeData->hasText()) { const QString text = mimeData->text(); QStringList lst = text.split(QLatin1Char('\n'), QString::SkipEmptyParts); urls.reserve(lst.count()); QStringList::ConstIterator end(lst.constEnd()); for (QStringList::ConstIterator it = lst.constBegin(); it != end; ++it) { urls.append(QUrl(*it)); } probablyWeHaveUris = true; } QMenu menu; QAction *linkAction = nullptr, *cancelAction = nullptr; if (probablyWeHaveUris) { linkAction = menu.addAction(QIcon::fromTheme(QStringLiteral("insert-link")), i18nc("@action:inmenu", "&Link here")); // we need to check if we can reasonably expect to copy the objects bool weCanCopy = true; QList::ConstIterator end(urls.constEnd()); for (QList::ConstIterator it = urls.constBegin(); it != end; ++it) { if (!(weCanCopy = KProtocolManager::supportsReading(*it))) { break; // either we can copy them all, or no copying at all } } if (weCanCopy) { menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18nc("@action:inmenu", "&Copy here")); } } else { menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18nc("@action:inmenu", "&Copy here")); } menu.addSeparator(); cancelAction = menu.addAction(QIcon::fromTheme(QStringLiteral("process-stop")), i18nc("@action:inmenu", "C&ancel")); QByteArray data; QString mimeType; QString label; if (!mimeData->formats().isEmpty() && !probablyWeHaveUris) { mimeType = mimeData->formats().first(); data = mimeData->data(mimeType); QMimeDatabase db; QMimeType mime = db.mimeTypeForName(mimeType); if (mime.isValid()) { label = mime.comment(); } } QAction *ret = menu.exec(QCursor::pos()); if (linkAction == ret) { QStringList::ConstIterator jt = labels.constBegin(); const QList::ConstIterator jtEnd = urls.constEnd(); for (QList::ConstIterator it = urls.constBegin(); it != jtEnd; ++it) { addUriAttachment((*it).url(), QString(), (jt == labels.constEnd() ? QString() : *(jt++)), true); } } else if (cancelAction != ret) { if (probablyWeHaveUris) { QList::ConstIterator end = urls.constEnd(); for (QList::ConstIterator it = urls.constBegin(); it != end; ++it) { KIO::Job *job = KIO::storedGet(*it); //TODO verify if slot exist ! connect(job, &KIO::Job::result, this, &IncidenceAttachment::downloadComplete); } } else { // we take anything addDataAttachment(data, mimeType, label); } } } void IncidenceAttachment::downloadComplete(KJob *) { //TODO } void IncidenceAttachment::setupActions() { KActionCollection *ac = new KActionCollection(this); // ac->addAssociatedWidget( this ); mOpenAction = new QAction(QIcon::fromTheme(QStringLiteral("document-open")), i18nc("@action:inmenu open the attachment in a viewer", "&Open"), this); connect(mOpenAction, &QAction::triggered, this, &IncidenceAttachment::showSelectedAttachments); ac->addAction(QStringLiteral("view"), mOpenAction); mPopupMenu->addAction(mOpenAction); mSaveAsAction = new QAction(QIcon::fromTheme(QStringLiteral("document-save-as")), i18nc("@action:inmenu save the attachment to a file", "Save As..."), this); connect(mSaveAsAction, &QAction::triggered, this, &IncidenceAttachment::saveSelectedAttachments); mPopupMenu->addAction(mSaveAsAction); mPopupMenu->addSeparator(); #ifndef QT_NO_CLIPBOARD mCopyAction = KStandardAction::copy(this, &IncidenceAttachment::copyToClipboard, ac); mPopupMenu->addAction(mCopyAction); mCutAction = KStandardAction::cut(this, &IncidenceAttachment::cutToClipboard, ac); mPopupMenu->addAction(mCutAction); QAction *action = KStandardAction::paste(this, &IncidenceAttachment::pasteFromClipboard, ac); mPopupMenu->addAction(action); mPopupMenu->addSeparator(); #endif mDeleteAction = new QAction(QIcon::fromTheme(QStringLiteral("list-remove")), i18nc("@action:inmenu remove the attachment", "&Remove"), this); connect(mDeleteAction, &QAction::triggered, this, &IncidenceAttachment::removeSelectedAttachments); ac->addAction(QStringLiteral("remove"), mDeleteAction); mDeleteAction->setShortcut(Qt::Key_Delete); mPopupMenu->addAction(mDeleteAction); mPopupMenu->addSeparator(); mEditAction = new QAction(QIcon::fromTheme(QStringLiteral("document-properties")), i18nc("@action:inmenu show a dialog used to edit the attachment", "&Properties..."), this); connect(mEditAction, &QAction::triggered, this, &IncidenceAttachment::editSelectedAttachments); ac->addAction(QStringLiteral("edit"), mEditAction); mPopupMenu->addAction(mEditAction); } void IncidenceAttachment::setupAttachmentIconView() { mAttachmentView = new AttachmentIconView; mAttachmentView->setWhatsThis(i18nc("@info:whatsthis", "Displays items (files, mail, etc.) that " "have been associated with this event or to-do.")); connect(mAttachmentView, &AttachmentIconView::itemDoubleClicked, this, &IncidenceAttachment::showAttachment); connect(mAttachmentView, &AttachmentIconView::itemChanged, this, &IncidenceAttachment::slotItemRenamed); connect(mAttachmentView, &AttachmentIconView::itemSelectionChanged, this, &IncidenceAttachment::slotSelectionChanged); connect(mAttachmentView, &AttachmentIconView::customContextMenuRequested, this, &IncidenceAttachment::showContextMenu); QGridLayout *layout = new QGridLayout(mUi->mAttachmentViewPlaceHolder); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(mAttachmentView); } -// void IncidenceAttachmentEditor::addAttachment( KCalCore::Attachment *attachment ) +// void IncidenceAttachmentEditor::addAttachment( KCalendarCore::Attachment *attachment ) // { // new AttachmentIconItem( attachment, mAttachmentView ); // } void IncidenceAttachment::addDataAttachment(const QByteArray &data, const QString &mimeType, const QString &label) { - AttachmentIconItem *item = new AttachmentIconItem(KCalCore::Attachment(), mAttachmentView); + AttachmentIconItem *item = new AttachmentIconItem(KCalendarCore::Attachment(), mAttachmentView); QString nlabel = label; if (mimeType == QLatin1String("message/rfc822")) { // mail message. try to set the label from the mail Subject: KMime::Message msg; msg.setContent(data); msg.parse(); nlabel = msg.subject()->asUnicodeString(); } item->setData(data); item->setLabel(nlabel); if (mimeType.isEmpty()) { QMimeDatabase db; item->setMimeType(db.mimeTypeForData(data).name()); } else { item->setMimeType(mimeType); } checkDirtyStatus(); } void IncidenceAttachment::addUriAttachment(const QString &uri, const QString &mimeType, const QString &label, bool inLine) { if (!inLine) { AttachmentIconItem *item - = new AttachmentIconItem(KCalCore::Attachment(), mAttachmentView); + = new AttachmentIconItem(KCalendarCore::Attachment(), mAttachmentView); item->setUri(uri); item->setLabel(label); if (mimeType.isEmpty()) { if (uri.startsWith(QStringLiteral("uid:"))) { item->setMimeType(QStringLiteral("text/directory")); } else if (uri.startsWith(QStringLiteral("kmail:"))) { item->setMimeType(QStringLiteral("message/rfc822")); } else if (uri.startsWith(QStringLiteral("urn:x-ical"))) { item->setMimeType(QStringLiteral("text/calendar")); } else if (uri.startsWith(QStringLiteral("news:"))) { item->setMimeType(QStringLiteral("message/news")); } else { QMimeDatabase db; item->setMimeType(db.mimeTypeForUrl(QUrl(uri)).name()); } } } else { auto job = KIO::storedGet(QUrl(uri)); KJobWidgets::setWindow(job, nullptr); if (job->exec()) { const QByteArray data = job->data(); addDataAttachment(data, mimeType, label); } } } diff --git a/src/incidenceattachment.h b/src/incidenceattachment.h index 73149c7..bd2552a 100644 --- a/src/incidenceattachment.h +++ b/src/incidenceattachment.h @@ -1,100 +1,100 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCEATTACHMENT_H #define INCIDENCEEDITOR_INCIDENCEATTACHMENT_H #include "incidenceeditor-ng.h" class QUrl; class KJob; namespace Ui { class EventOrTodoDesktop; } class QMenu; class QListWidgetItem; class QMimeData; class QAction; namespace IncidenceEditorNG { class AttachmentIconView; class IncidenceAttachment : public IncidenceEditor { Q_OBJECT public: using IncidenceEditorNG::IncidenceEditor::save; // So we don't trigger -Woverloaded-virtual using IncidenceEditorNG::IncidenceEditor::load; // So we don't trigger -Woverloaded-virtual explicit IncidenceAttachment(Ui::EventOrTodoDesktop *ui); ~IncidenceAttachment() override; - void load(const KCalCore::Incidence::Ptr &incidence) override; - void save(const KCalCore::Incidence::Ptr &incidence) override; + void load(const KCalendarCore::Incidence::Ptr &incidence) override; + void save(const KCalendarCore::Incidence::Ptr &incidence) override; Q_REQUIRED_RESULT bool isDirty() const override; Q_REQUIRED_RESULT int attachmentCount() const; Q_SIGNALS: void attachmentCountChanged(int newCount); private: void addAttachment(); void copyToClipboard(); /// Copies selected items to clip board void cutToClipboard(); /// Copies selected items to clipboard and removes them from the list void editSelectedAttachments(); void openURL(const QUrl &url); void pasteFromClipboard(); void removeSelectedAttachments(); void saveAttachment(QListWidgetItem *item); void saveSelectedAttachments(); void showAttachment(QListWidgetItem *item); void showContextMenu(const QPoint &pos); void showSelectedAttachments(); void slotItemRenamed(QListWidgetItem *item); void slotSelectionChanged(); void downloadComplete(KJob *); private: - // void addAttachment( KCalCore::Attachment *attachment ); + // void addAttachment( KCalendarCore::Attachment *attachment ); void addDataAttachment(const QByteArray &data, const QString &mimeType = QString(), const QString &label = QString()); void addUriAttachment(const QString &uri, const QString &mimeType = QString(), const QString &label = QString(), bool inLine = false); void handlePasteOrDrop(const QMimeData *mimeData); void setupActions(); void setupAttachmentIconView(); private: AttachmentIconView *mAttachmentView = nullptr; Ui::EventOrTodoDesktop *mUi = nullptr; QMenu *mPopupMenu = nullptr; QAction *mOpenAction = nullptr; QAction *mSaveAsAction = nullptr; #ifndef QT_NO_CLIPBOARD QAction *mCopyAction = nullptr; QAction *mCutAction = nullptr; #endif QAction *mDeleteAction = nullptr; QAction *mEditAction = nullptr; }; } #endif diff --git a/src/incidenceattendee.cpp b/src/incidenceattendee.cpp index c18bb34..bfaa12f 100644 --- a/src/incidenceattendee.cpp +++ b/src/incidenceattendee.cpp @@ -1,1046 +1,1046 @@ /* Copyright (C) 2010 Casey Link Copyright (c) 2009-2010 Klarälvdalens Datakonsult AB, a KDAB Group company Based on old attendeeeditor.cpp: Copyright (c) 2000,2001 Cornelius Schumacher Copyright (C) 2003-2004 Reinhold Kainhofer Copyright (c) 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidenceattendee.h" #include "attendeetablemodel.h" #include "attendeeeditor.h" #include "attendeecomboboxdelegate.h" #include "attendeelineeditdelegate.h" #include "conflictresolver.h" #include "editorconfig.h" #include "incidencedatetime.h" #include "schedulingdialog.h" #include "CalendarSupport/FreeBusyItemModel" #include "ui_dialogdesktop.h" #include #include #include #include #include #include "incidenceeditor_debug.h" #include #include #include #include using namespace IncidenceEditorNG; IncidenceAttendee::IncidenceAttendee(QWidget *parent, IncidenceDateTime *dateTime, Ui::EventOrTodoDesktop *ui) : mUi(ui) , mParentWidget(parent) , mConflictResolver(nullptr) , mDateTime(dateTime) , mStateDelegate(new AttendeeComboBoxDelegate(this)) , mRoleDelegate(new AttendeeComboBoxDelegate(this)) , mResponseDelegate(new AttendeeComboBoxDelegate(this)) { mDataModel = new AttendeeTableModel(this); mDataModel->setKeepEmpty(true); mDataModel->setRemoveEmptyLines(true); mRoleDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/meeting-participant.png")), - KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::ReqParticipant)); + KCalUtils::Stringify::attendeeRole(KCalendarCore::Attendee::ReqParticipant)); mRoleDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/meeting-participant-optional.png")), - KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::OptParticipant)); + KCalUtils::Stringify::attendeeRole(KCalendarCore::Attendee::OptParticipant)); mRoleDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/meeting-observer.png")), - KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::NonParticipant)); + KCalUtils::Stringify::attendeeRole(KCalendarCore::Attendee::NonParticipant)); mRoleDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/meeting-chair.png")), - KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::Chair)); + KCalUtils::Stringify::attendeeRole(KCalendarCore::Attendee::Chair)); mResponseDelegate->addItem(QIcon::fromTheme(QStringLiteral( "meeting-participant-request-response")), i18nc("@item:inlistbox", "Request Response")); mResponseDelegate->addItem(QIcon::fromTheme(QStringLiteral("meeting-participant-no-response")), i18nc("@item:inlistbox", "Request No Response")); mStateDelegate->setWhatsThis(i18nc("@info:whatsthis", "Edits the current attendance status of the attendee.")); mRoleDelegate->setWhatsThis(i18nc("@info:whatsthis", "Edits the role of the attendee.")); mResponseDelegate->setToolTip(i18nc("@info:tooltip", "Request a response from the attendee")); mResponseDelegate->setWhatsThis(i18nc("@info:whatsthis", "Edits whether to send an email to the " "attendee to request a response concerning " "attendance.")); setObjectName(QStringLiteral("IncidenceAttendee")); AttendeeFilterProxyModel *filterProxyModel = new AttendeeFilterProxyModel(this); filterProxyModel->setDynamicSortFilter(true); filterProxyModel->setSourceModel(mDataModel); connect(mUi->mGroupSubstitution, &QPushButton::clicked, this, &IncidenceAttendee::slotGroupSubstitutionPressed); mUi->mAttendeeTable->setModel(filterProxyModel); mAttendeeDelegate = new AttendeeLineEditDelegate(this); mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Role, roleDelegate()); mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::FullName, attendeeDelegate()); mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Status, stateDelegate()); mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Response, responseDelegate()); mUi->mOrganizerStack->setCurrentIndex(0); fillOrganizerCombo(); mUi->mSolveButton->setEnabled(false); mUi->mOrganizerLabel->setVisible(false); mConflictResolver = new ConflictResolver(parent, parent); mConflictResolver->setEarliestDate(mDateTime->startDate()); mConflictResolver->setEarliestTime(mDateTime->startTime()); mConflictResolver->setLatestDate(mDateTime->endDate()); mConflictResolver->setLatestTime(mDateTime->endTime()); connect(mUi->mSelectButton, &QPushButton::clicked, this, &IncidenceAttendee::slotSelectAddresses); connect(mUi->mSolveButton, &QPushButton::clicked, this, &IncidenceAttendee::slotSolveConflictPressed); /* Added as part of kolab/issue2297, which is currently under review connect(mUi->mOrganizerCombo, qOverload(&QComboBox::activated), this, &IncidenceAttendee::slotOrganizerChanged); */ connect(mUi->mOrganizerCombo, qOverload(&QComboBox::currentIndexChanged), this, &IncidenceAttendee::checkDirtyStatus); connect(mDateTime, &IncidenceDateTime::startDateChanged, this, &IncidenceAttendee::slotEventDurationChanged); connect(mDateTime, &IncidenceDateTime::endDateChanged, this, &IncidenceAttendee::slotEventDurationChanged); connect(mDateTime, &IncidenceDateTime::startTimeChanged, this, &IncidenceAttendee::slotEventDurationChanged); connect(mDateTime, &IncidenceDateTime::endTimeChanged, this, &IncidenceAttendee::slotEventDurationChanged); connect(mConflictResolver, &ConflictResolver::conflictsDetected, this, &IncidenceAttendee::slotUpdateConflictLabel); connect(mConflictResolver->model(), &QAbstractItemModel::rowsInserted, this, &IncidenceAttendee::slotFreeBusyAdded); connect(mConflictResolver->model(), SIGNAL(layoutChanged()), SLOT(updateFBStatus())); connect(mConflictResolver->model(), &QAbstractItemModel::dataChanged, this, &IncidenceAttendee::slotFreeBusyChanged); slotUpdateConflictLabel(0); //initialize label // conflict resolver (should show also resources) connect(mDataModel, &AttendeeTableModel::layoutChanged, this, &IncidenceAttendee::slotConflictResolverLayoutChanged); connect(mDataModel, &AttendeeTableModel::rowsAboutToBeRemoved, this, &IncidenceAttendee::slotConflictResolverAttendeeRemoved); connect(mDataModel, &AttendeeTableModel::rowsInserted, this, &IncidenceAttendee::slotConflictResolverAttendeeAdded); connect(mDataModel, &AttendeeTableModel::dataChanged, this, &IncidenceAttendee::slotConflictResolverAttendeeChanged); //Group substitution connect(filterProxyModel, &AttendeeFilterProxyModel::layoutChanged, this, &IncidenceAttendee::slotGroupSubstitutionLayoutChanged); connect(filterProxyModel, &AttendeeFilterProxyModel::rowsAboutToBeRemoved, this, &IncidenceAttendee::slotGroupSubstitutionAttendeeRemoved); connect(filterProxyModel, &AttendeeFilterProxyModel::rowsInserted, this, &IncidenceAttendee::slotGroupSubstitutionAttendeeAdded); connect(filterProxyModel, &AttendeeFilterProxyModel::dataChanged, this, &IncidenceAttendee::slotGroupSubstitutionAttendeeChanged); connect(filterProxyModel, &AttendeeFilterProxyModel::rowsInserted, this, &IncidenceAttendee::updateCount); connect(filterProxyModel, &AttendeeFilterProxyModel::rowsRemoved, this, &IncidenceAttendee::updateCount); // only update when FullName is changed connect(filterProxyModel, &AttendeeFilterProxyModel::dataChanged, this, &IncidenceAttendee::updateCount); connect(filterProxyModel, &AttendeeFilterProxyModel::layoutChanged, this, &IncidenceAttendee::updateCount); connect(filterProxyModel, &AttendeeFilterProxyModel::layoutChanged, this, &IncidenceAttendee::filterLayoutChanged); } IncidenceAttendee::~IncidenceAttendee() { } -void IncidenceAttendee::load(const KCalCore::Incidence::Ptr &incidence) +void IncidenceAttendee::load(const KCalendarCore::Incidence::Ptr &incidence) { mLoadedIncidence = incidence; if (iAmOrganizer() || incidence->organizer().isEmpty()) { mUi->mOrganizerStack->setCurrentIndex(0); int found = -1; const QString fullOrganizer = incidence->organizer().fullName(); const QString organizerEmail = incidence->organizer().email(); for (int i = 0; i < mUi->mOrganizerCombo->count(); ++i) { - KCalCore::Person organizerCandidate - = KCalCore::Person::fromFullName(mUi->mOrganizerCombo->itemText(i)); + KCalendarCore::Person organizerCandidate + = KCalendarCore::Person::fromFullName(mUi->mOrganizerCombo->itemText(i)); if (organizerCandidate.email() == organizerEmail) { found = i; mUi->mOrganizerCombo->setCurrentIndex(i); break; } } if (found < 0 && !fullOrganizer.isEmpty()) { mUi->mOrganizerCombo->insertItem(0, fullOrganizer); mUi->mOrganizerCombo->setCurrentIndex(0); } mUi->mOrganizerLabel->setVisible(false); } else { // someone else is the organizer mUi->mOrganizerStack->setCurrentIndex(1); mUi->mOrganizerLabel->setText(incidence->organizer().fullName()); mUi->mOrganizerLabel->setVisible(true); } - KCalCore::Attendee::List attendees; - const KCalCore::Attendee::List incidenceAttendees = incidence->attendees(); + KCalendarCore::Attendee::List attendees; + const KCalendarCore::Attendee::List incidenceAttendees = incidence->attendees(); attendees.reserve(incidenceAttendees.count()); - for (const KCalCore::Attendee &a : incidenceAttendees) { - attendees << KCalCore::Attendee(a); + for (const KCalendarCore::Attendee &a : incidenceAttendees) { + attendees << KCalendarCore::Attendee(a); } mDataModel->setAttendees(attendees); slotUpdateConflictLabel(0); setActions(incidence->type()); mWasDirty = false; } -void IncidenceAttendee::save(const KCalCore::Incidence::Ptr &incidence) +void IncidenceAttendee::save(const KCalendarCore::Incidence::Ptr &incidence) { incidence->clearAttendees(); - const KCalCore::Attendee::List attendees = mDataModel->attendees(); + const KCalendarCore::Attendee::List attendees = mDataModel->attendees(); - for (const KCalCore::Attendee &attendee : attendees) { + for (const KCalendarCore::Attendee &attendee : attendees) { bool skip = false; if (attendee.fullName().isEmpty()) { continue; } if (KEmailAddress::isValidAddress(attendee.email())) { if (KMessageBox::warningYesNo( nullptr, i18nc("@info", "%1 does not look like a valid email address. " "Are you sure you want to invite this participant?", attendee.email()), i18nc("@title:window", "Invalid Email Address")) != KMessageBox::Yes) { skip = true; } } if (!skip) { incidence->addAttendee(attendee); } } // Must not have an organizer for items without attendees if (!incidence->attendeeCount()) { return; } if (mUi->mOrganizerStack->currentIndex() == 0) { incidence->setOrganizer(mUi->mOrganizerCombo->currentText()); } else { incidence->setOrganizer(mUi->mOrganizerLabel->text()); } } bool IncidenceAttendee::isDirty() const { if (iAmOrganizer()) { - KCalCore::Event tmp; + KCalendarCore::Event tmp; tmp.setOrganizer(mUi->mOrganizerCombo->currentText()); if (mLoadedIncidence->organizer().email() != tmp.organizer().email()) { qCDebug(INCIDENCEEDITOR_LOG) << "Organizer changed. Old was " << mLoadedIncidence->organizer().name() << mLoadedIncidence->organizer().email() << "; new is " << tmp.organizer().name() << tmp.organizer().email(); return true; } } - const KCalCore::Attendee::List originalList = mLoadedIncidence->attendees(); - KCalCore::Attendee::List newList; + const KCalendarCore::Attendee::List originalList = mLoadedIncidence->attendees(); + KCalendarCore::Attendee::List newList; const auto lstAttendees = mDataModel->attendees(); - for (const KCalCore::Attendee &attendee : lstAttendees) { + for (const KCalendarCore::Attendee &attendee : lstAttendees) { if (!attendee.fullName().isEmpty()) { newList.append(attendee); } } // The lists sizes *must* be the same. When the organizer is attending the // event as well, he should be in the attendees list as well. if (originalList.size() != newList.size()) { return true; } // Okay, again not the most efficient algorithm, but I'm assuming that in the // bulk of the use cases, the number of attendees is not much higher than 10 or so. - for (const KCalCore::Attendee &attendee : originalList) { + for (const KCalendarCore::Attendee &attendee : originalList) { bool found = false; for (int i = 0; i < newList.count(); ++i) { if (newList[i] == attendee) { newList.remove(i); found = true; break; } } if (!found) { // One of the attendees in the original list was not found in the new list. return true; } } return false; } -void IncidenceAttendee::changeStatusForMe(KCalCore::Attendee::PartStat stat) +void IncidenceAttendee::changeStatusForMe(KCalendarCore::Attendee::PartStat stat) { const IncidenceEditorNG::EditorConfig *config = IncidenceEditorNG::EditorConfig::instance(); Q_ASSERT(config); for (int i = 0; i < mDataModel->rowCount(); ++i) { QModelIndex index = mDataModel->index(i, AttendeeTableModel::Email); if (config->thatIsMe(mDataModel->data(index, Qt::DisplayRole).toString())) { index = mDataModel->index(i, AttendeeTableModel::Status); mDataModel->setData(index, stat); break; } } checkDirtyStatus(); } void IncidenceAttendee::acceptForMe() { - changeStatusForMe(KCalCore::Attendee::Accepted); + changeStatusForMe(KCalendarCore::Attendee::Accepted); } void IncidenceAttendee::declineForMe() { - changeStatusForMe(KCalCore::Attendee::Declined); + changeStatusForMe(KCalendarCore::Attendee::Declined); } void IncidenceAttendee::fillOrganizerCombo() { mUi->mOrganizerCombo->clear(); const QStringList lst = IncidenceEditorNG::EditorConfig::instance()->fullEmails(); QStringList uniqueList; for (QStringList::ConstIterator it = lst.begin(), end = lst.end(); it != end; ++it) { if (!uniqueList.contains(*it)) { uniqueList << *it; } } mUi->mOrganizerCombo->addItems(uniqueList); } -void IncidenceAttendee::checkIfExpansionIsNeeded(const KCalCore::Attendee &attendee) +void IncidenceAttendee::checkIfExpansionIsNeeded(const KCalendarCore::Attendee &attendee) { QString fullname = attendee.fullName(); // stop old job KJob *oldJob = mMightBeGroupJobs.key(attendee.uid()); if (oldJob != nullptr) { disconnect(oldJob); oldJob->deleteLater(); mMightBeGroupJobs.remove(oldJob); } mGroupList.remove(attendee.uid()); if (!fullname.isEmpty()) { Akonadi::ContactGroupSearchJob *job = new Akonadi::ContactGroupSearchJob(); job->setQuery(Akonadi::ContactGroupSearchJob::Name, fullname); connect(job, &Akonadi::ContactGroupSearchJob::result, this, &IncidenceAttendee::groupSearchResult); mMightBeGroupJobs.insert(job, attendee.uid()); } } void IncidenceAttendee::groupSearchResult(KJob *job) { Akonadi::ContactGroupSearchJob *searchJob = qobject_cast(job); Q_ASSERT(searchJob); Q_ASSERT(mMightBeGroupJobs.contains(job)); const auto uid = mMightBeGroupJobs.take(job); const KContacts::ContactGroup::List contactGroups = searchJob->contactGroups(); if (contactGroups.isEmpty()) { updateGroupExpand(); return; // Nothing todo, probably a normal email address was entered } // TODO: Give the user the possibility to choose a group when there is more than one?! KContacts::ContactGroup group = contactGroups.first(); const int row = rowOfAttendee(uid); QModelIndex index = dataModel()->index(row, AttendeeTableModel::CuType); - dataModel()->setData(index, KCalCore::Attendee::Group); + dataModel()->setData(index, KCalendarCore::Attendee::Group); mGroupList.insert(uid, group); updateGroupExpand(); } void IncidenceAttendee::updateGroupExpand() { mUi->mGroupSubstitution->setEnabled(!mGroupList.isEmpty()); } void IncidenceAttendee::slotGroupSubstitutionPressed() { for (auto it = mGroupList.cbegin(), end = mGroupList.cend(); it != end; ++it) { Akonadi::ContactGroupExpandJob *expandJob = new Akonadi::ContactGroupExpandJob(it.value(), this); connect(expandJob, &Akonadi::ContactGroupExpandJob::result, this, &IncidenceAttendee::expandResult); mExpandGroupJobs.insert(expandJob, it.key()); expandJob->start(); } } void IncidenceAttendee::expandResult(KJob *job) { Akonadi::ContactGroupExpandJob *expandJob = qobject_cast(job); Q_ASSERT(expandJob); Q_ASSERT(mExpandGroupJobs.contains(job)); const auto uid = mExpandGroupJobs.take(job); const int row = rowOfAttendee(uid); const auto attendee = dataModel()->attendees().at(row); const QString currentEmail = attendee.email(); const KContacts::Addressee::List groupMembers = expandJob->contacts(); bool wasACorrectEmail = false; for (const KContacts::Addressee &member : groupMembers) { if (member.preferredEmail() == currentEmail) { wasACorrectEmail = true; break; } } if (!wasACorrectEmail) { dataModel()->removeRow(row); for (const KContacts::Addressee &member : groupMembers) { - KCalCore::Attendee newAt(member.realName(), member.preferredEmail(), + KCalendarCore::Attendee newAt(member.realName(), member.preferredEmail(), attendee.RSVP(), attendee.status(), attendee.role(), member.uid()); dataModel()->insertAttendee(row, newAt); } } } void IncidenceAttendee::slotSelectAddresses() { QPointer dialog = new Akonadi::EmailAddressSelectionDialog(mParentWidget); dialog->view()->view()->setSelectionMode(QAbstractItemView::ExtendedSelection); dialog->setWindowTitle(i18n("Select Attendees")); if (dialog->exec() == QDialog::Accepted) { const Akonadi::EmailAddressSelection::List list = dialog->selectedAddresses(); for (const Akonadi::EmailAddressSelection &selection : list) { if (selection.item().hasPayload()) { Akonadi::ContactGroupExpandJob *job = new Akonadi::ContactGroupExpandJob( selection.item().payload(), this); connect(job, &Akonadi::ContactGroupExpandJob::result, this, &IncidenceAttendee::expandResult); - KCalCore::Attendee::PartStat partStat = KCalCore::Attendee::NeedsAction; + KCalendarCore::Attendee::PartStat partStat = KCalendarCore::Attendee::NeedsAction; bool rsvp = true; int pos = 0; - KCalCore::Attendee newAt(selection.name(), + KCalendarCore::Attendee newAt(selection.name(), selection.email(), rsvp, partStat, - KCalCore::Attendee::ReqParticipant); + KCalendarCore::Attendee::ReqParticipant); dataModel()->insertAttendee(pos, newAt); mExpandGroupJobs.insert(job, newAt.uid()); job->start(); } else { KContacts::Addressee contact; contact.setName(selection.name()); contact.insertEmail(selection.email()); if (selection.item().hasPayload()) { contact.setUid(selection.item().payload().uid()); } insertAttendeeFromAddressee(contact); } } } delete dialog; } void IncidenceEditorNG::IncidenceAttendee::slotSolveConflictPressed() { const int duration = mDateTime->startTime().secsTo(mDateTime->endTime()); QScopedPointer dialog(new SchedulingDialog(mDateTime->startDate(), mDateTime->startTime(), duration, mConflictResolver, mParentWidget)); dialog->slotUpdateIncidenceStartEnd(mDateTime->currentStartDateTime(), mDateTime->currentEndDateTime()); if (dialog->exec() == QDialog::Accepted) { qCDebug(INCIDENCEEDITOR_LOG) << dialog->selectedStartDate() << dialog->selectedStartTime(); if (dialog->selectedStartDate().isValid() && dialog->selectedStartTime().isValid()) { mDateTime->setStartDate(dialog->selectedStartDate()); mDateTime->setStartTime(dialog->selectedStartTime()); } } } void IncidenceAttendee::slotConflictResolverAttendeeChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { if (AttendeeTableModel::FullName <= bottomRight.column() && AttendeeTableModel::FullName >= topLeft.column()) { for (int i = topLeft.row(); i <= bottomRight.row(); ++i) { QModelIndex email = dataModel()->index(i, AttendeeTableModel::Email); - KCalCore::Attendee attendee = dataModel()->data(email, + KCalendarCore::Attendee attendee = dataModel()->data(email, AttendeeTableModel::AttendeeRole). - value(); + value(); if (mConflictResolver->containsAttendee(attendee)) { mConflictResolver->removeAttendee(attendee); } if (!dataModel()->data(email).toString().isEmpty()) { mConflictResolver->insertAttendee(attendee); } } } checkDirtyStatus(); } void IncidenceAttendee::slotConflictResolverAttendeeAdded(const QModelIndex &index, int first, int last) { for (int i = first; i <= last; ++i) { QModelIndex email = dataModel()->index(i, AttendeeTableModel::Email, index); if (!dataModel()->data(email).toString().isEmpty()) { mConflictResolver->insertAttendee(dataModel()->data(email, AttendeeTableModel::AttendeeRole).value< - KCalCore::Attendee>()); + KCalendarCore::Attendee>()); } } checkDirtyStatus(); } void IncidenceAttendee::slotConflictResolverAttendeeRemoved(const QModelIndex &index, int first, int last) { for (int i = first; i <= last; ++i) { QModelIndex email = dataModel()->index(i, AttendeeTableModel::Email, index); if (!dataModel()->data(email).toString().isEmpty()) { mConflictResolver->removeAttendee(dataModel()->data(email, AttendeeTableModel::AttendeeRole).value< - KCalCore::Attendee>()); + KCalendarCore::Attendee>()); } } checkDirtyStatus(); } void IncidenceAttendee::slotConflictResolverLayoutChanged() { - const KCalCore::Attendee::List attendees = mDataModel->attendees(); + const KCalendarCore::Attendee::List attendees = mDataModel->attendees(); mConflictResolver->clearAttendees(); - for (const KCalCore::Attendee &attendee : attendees) { + for (const KCalendarCore::Attendee &attendee : attendees) { if (!attendee.email().isEmpty()) { mConflictResolver->insertAttendee(attendee); } } checkDirtyStatus(); } void IncidenceAttendee::slotFreeBusyAdded(const QModelIndex &parent, int first, int last) { // We are only interested in toplevel changes if (parent.isValid()) { return; } QAbstractItemModel *model = mConflictResolver->model(); for (int i = first; i <= last; ++i) { QModelIndex index = model->index(i, 0, parent); - const KCalCore::Attendee &attendee - = model->data(index, CalendarSupport::FreeBusyItemModel::AttendeeRole).value(); - const KCalCore::FreeBusy::Ptr &fb - = model->data(index, CalendarSupport::FreeBusyItemModel::FreeBusyRole).value(); + const KCalendarCore::Attendee &attendee + = model->data(index, CalendarSupport::FreeBusyItemModel::AttendeeRole).value(); + const KCalendarCore::FreeBusy::Ptr &fb + = model->data(index, CalendarSupport::FreeBusyItemModel::FreeBusyRole).value(); if (!attendee.isNull()) { updateFBStatus(attendee, fb); } } } void IncidenceAttendee::slotFreeBusyChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { // We are only interested in toplevel changes if (topLeft.parent().isValid()) { return; } QAbstractItemModel *model = mConflictResolver->model(); for (int i = topLeft.row(); i <= bottomRight.row(); ++i) { QModelIndex index = model->index(i, 0); - const KCalCore::Attendee &attendee - = model->data(index, CalendarSupport::FreeBusyItemModel::AttendeeRole).value(); - const KCalCore::FreeBusy::Ptr &fb - = model->data(index, CalendarSupport::FreeBusyItemModel::FreeBusyRole).value(); + const KCalendarCore::Attendee &attendee + = model->data(index, CalendarSupport::FreeBusyItemModel::AttendeeRole).value(); + const KCalendarCore::FreeBusy::Ptr &fb + = model->data(index, CalendarSupport::FreeBusyItemModel::FreeBusyRole).value(); if (!attendee.isNull()) { updateFBStatus(attendee, fb); } } } void IncidenceAttendee::updateFBStatus() { QAbstractItemModel *model = mConflictResolver->model(); for (int i = 0; i < model->rowCount(); ++i) { QModelIndex index = model->index(i, 0); - const KCalCore::Attendee &attendee - = model->data(index, CalendarSupport::FreeBusyItemModel::AttendeeRole).value(); - const KCalCore::FreeBusy::Ptr &fb - = model->data(index, CalendarSupport::FreeBusyItemModel::FreeBusyRole).value(); + const KCalendarCore::Attendee &attendee + = model->data(index, CalendarSupport::FreeBusyItemModel::AttendeeRole).value(); + const KCalendarCore::FreeBusy::Ptr &fb + = model->data(index, CalendarSupport::FreeBusyItemModel::FreeBusyRole).value(); if (!attendee.isNull()) { updateFBStatus(attendee, fb); } } } -void IncidenceAttendee::updateFBStatus(const KCalCore::Attendee &attendee, const KCalCore::FreeBusy::Ptr &fb) +void IncidenceAttendee::updateFBStatus(const KCalendarCore::Attendee &attendee, const KCalendarCore::FreeBusy::Ptr &fb) { - KCalCore::Attendee::List attendees = mDataModel->attendees(); + KCalendarCore::Attendee::List attendees = mDataModel->attendees(); QDateTime startTime = mDateTime->currentStartDateTime(); QDateTime endTime = mDateTime->currentEndDateTime(); if (attendees.contains(attendee)) { int row = dataModel()->attendees().indexOf(attendee); QModelIndex attendeeIndex = dataModel()->index(row, AttendeeTableModel::Available); if (fb) { - KCalCore::Period::List busyPeriods = fb->busyPeriods(); + KCalendarCore::Period::List busyPeriods = fb->busyPeriods(); for (auto it = busyPeriods.begin(); it != busyPeriods.end(); ++it) { // periods started before and lapping into the incidence (s < startTime && e >= startTime) // periods starting in the time of incidence (s >= startTime && s <= endTime) if (((*it).start() < startTime && (*it).end() > startTime) || ((*it).start() >= startTime && (*it).start() <= endTime)) { switch (attendee.status()) { - case KCalCore::Attendee::Accepted: + case KCalendarCore::Attendee::Accepted: dataModel()->setData(attendeeIndex, AttendeeTableModel::Accepted); return; default: dataModel()->setData(attendeeIndex, AttendeeTableModel::Busy); return; } } } dataModel()->setData(attendeeIndex, AttendeeTableModel::Free); } else { dataModel()->setData(attendeeIndex, AttendeeTableModel::Unknown); } } } void IncidenceAttendee::slotUpdateConflictLabel(int count) { if (attendeeCount() > 0) { mUi->mSolveButton->setEnabled(true); if (count > 0) { QString label = i18ncp("@label Shows the number of scheduling conflicts", "%1 conflict", "%1 conflicts", count); mUi->mConflictsLabel->setText(label); mUi->mConflictsLabel->setVisible(true); } else { mUi->mConflictsLabel->setVisible(false); } } else { mUi->mSolveButton->setEnabled(false); mUi->mConflictsLabel->setVisible(false); } } void IncidenceAttendee::slotGroupSubstitutionAttendeeChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { if (AttendeeTableModel::FullName <= bottomRight.column() && AttendeeTableModel::FullName >= topLeft.column()) { for (int i = topLeft.row(); i <= bottomRight.row(); ++i) { QModelIndex email = dataModel()->index(i, AttendeeTableModel::Email); - KCalCore::Attendee attendee = dataModel()->data(email, + KCalendarCore::Attendee attendee = dataModel()->data(email, AttendeeTableModel::AttendeeRole). - value(); + value(); checkIfExpansionIsNeeded(attendee); } } updateGroupExpand(); } void IncidenceAttendee::slotGroupSubstitutionAttendeeAdded(const QModelIndex &index, int first, int last) { Q_UNUSED(index); for (int i = first; i <= last; ++i) { QModelIndex email = dataModel()->index(i, AttendeeTableModel::Email); - KCalCore::Attendee attendee + KCalendarCore::Attendee attendee = dataModel()->data(email, - AttendeeTableModel::AttendeeRole).value(); + AttendeeTableModel::AttendeeRole).value(); checkIfExpansionIsNeeded(attendee); } updateGroupExpand(); } void IncidenceAttendee::slotGroupSubstitutionAttendeeRemoved(const QModelIndex &index, int first, int last) { Q_UNUSED(index); for (int i = first; i <= last; ++i) { QModelIndex email = dataModel()->index(i, AttendeeTableModel::Email); - KCalCore::Attendee attendee + KCalendarCore::Attendee attendee = dataModel()->data(email, - AttendeeTableModel::AttendeeRole).value(); + AttendeeTableModel::AttendeeRole).value(); KJob *job = mMightBeGroupJobs.key(attendee.uid()); if (job) { disconnect(job); job->deleteLater(); mMightBeGroupJobs.remove(job); } job = mExpandGroupJobs.key(attendee.uid()); if (job) { disconnect(job); job->deleteLater(); mExpandGroupJobs.remove(job); } mGroupList.remove(attendee.uid()); } updateGroupExpand(); } void IncidenceAttendee::slotGroupSubstitutionLayoutChanged() { for (auto it = mMightBeGroupJobs.cbegin(), end = mMightBeGroupJobs.cend(); it != end; ++it) { KJob *job = it.key(); disconnect(job); job->deleteLater(); } for (auto it = mExpandGroupJobs.cbegin(), end = mExpandGroupJobs.cend(); it != end; ++it) { KJob *job = it.key(); disconnect(job); job->deleteLater(); } mMightBeGroupJobs.clear(); mExpandGroupJobs.clear(); mGroupList.clear(); QAbstractItemModel *model = mUi->mAttendeeTable->model(); if (!model) { return; } for (int i = 0; i < model->rowCount(QModelIndex()); ++i) { QModelIndex index = model->index(i, AttendeeTableModel::FullName); if (!model->data(index).toString().isEmpty()) { QModelIndex email = dataModel()->index(i, AttendeeTableModel::Email); - KCalCore::Attendee attendee = dataModel()->data(email, + KCalendarCore::Attendee attendee = dataModel()->data(email, AttendeeTableModel::AttendeeRole). - value(); + value(); checkIfExpansionIsNeeded(attendee); } } updateGroupExpand(); } bool IncidenceAttendee::iAmOrganizer() const { if (mLoadedIncidence) { const IncidenceEditorNG::EditorConfig *config = IncidenceEditorNG::EditorConfig::instance(); return config->thatIsMe(mLoadedIncidence->organizer().email()); } return true; } void IncidenceAttendee::insertAttendeeFromAddressee(const KContacts::Addressee &a, int pos /*=-1*/) { const bool sameAsOrganizer = mUi->mOrganizerCombo && KEmailAddress::compareEmail(a.preferredEmail(), mUi->mOrganizerCombo->currentText(), false); - KCalCore::Attendee::PartStat partStat = KCalCore::Attendee::NeedsAction; + KCalendarCore::Attendee::PartStat partStat = KCalendarCore::Attendee::NeedsAction; bool rsvp = true; if (iAmOrganizer() && sameAsOrganizer) { - partStat = KCalCore::Attendee::Accepted; + partStat = KCalendarCore::Attendee::Accepted; rsvp = false; } - KCalCore::Attendee newAt(a.realName(), a.preferredEmail(), + KCalendarCore::Attendee newAt(a.realName(), a.preferredEmail(), rsvp, partStat, - KCalCore::Attendee::ReqParticipant, + KCalendarCore::Attendee::ReqParticipant, a.uid()); if (pos < 0) { pos = dataModel()->rowCount() - 1; } dataModel()->insertAttendee(pos, newAt); } void IncidenceAttendee::slotEventDurationChanged() { const QDateTime start = mDateTime->currentStartDateTime(); const QDateTime end = mDateTime->currentEndDateTime(); if (start >= end) { // This can happen, especially for todos. return; } mConflictResolver->setEarliestDateTime(start); mConflictResolver->setLatestDateTime(end); updateFBStatus(); } void IncidenceAttendee::slotOrganizerChanged(const QString &newOrganizer) { if (KEmailAddress::compareEmail(newOrganizer, mOrganizer, false)) { return; } QString name; QString email; bool success = KEmailAddress::extractEmailAddressAndName(newOrganizer, email, name); if (!success) { qCWarning(INCIDENCEEDITOR_LOG) << "Could not extract email address and name"; return; } int currentOrganizerAttendee = -1; int newOrganizerAttendee = -1; for (int i = 0; i < mDataModel->rowCount(); ++i) { QModelIndex index = mDataModel->index(i, AttendeeTableModel::FullName); QString fullName = mDataModel->data(index, Qt::DisplayRole).toString(); if (fullName == mOrganizer) { currentOrganizerAttendee = i; } if (fullName == newOrganizer) { newOrganizerAttendee = i; } } int answer = KMessageBox::No; if (currentOrganizerAttendee > -1) { answer = KMessageBox::questionYesNo( mParentWidget, i18nc("@option", "You are changing the organizer of this event. " "Since the organizer is also attending this event, would you " "like to change the corresponding attendee as well?")); } else { answer = KMessageBox::Yes; } if (answer == KMessageBox::Yes) { if (currentOrganizerAttendee > -1) { mDataModel->removeRows(currentOrganizerAttendee, 1); } if (newOrganizerAttendee == -1) { bool rsvp = !iAmOrganizer(); // if it is the user, don't make him rsvp. - KCalCore::Attendee::PartStat status = iAmOrganizer() ? KCalCore::Attendee::Accepted - : KCalCore::Attendee::NeedsAction; + KCalendarCore::Attendee::PartStat status = iAmOrganizer() ? KCalendarCore::Attendee::Accepted + : KCalendarCore::Attendee::NeedsAction; - KCalCore::Attendee newAt(name, email, rsvp, status, - KCalCore::Attendee::ReqParticipant); + KCalendarCore::Attendee newAt(name, email, rsvp, status, + KCalendarCore::Attendee::ReqParticipant); mDataModel->insertAttendee(mDataModel->rowCount(), newAt); } } mOrganizer = newOrganizer; } AttendeeTableModel *IncidenceAttendee::dataModel() const { return mDataModel; } AttendeeComboBoxDelegate *IncidenceAttendee::responseDelegate() const { return mResponseDelegate; } AttendeeComboBoxDelegate *IncidenceAttendee::roleDelegate() const { return mRoleDelegate; } AttendeeComboBoxDelegate *IncidenceAttendee::stateDelegate() const { return mStateDelegate; } AttendeeLineEditDelegate *IncidenceAttendee::attendeeDelegate() const { return mAttendeeDelegate; } void IncidenceAttendee::filterLayoutChanged() { QHeaderView *headerView = mUi->mAttendeeTable->horizontalHeader(); headerView->setSectionResizeMode(AttendeeTableModel::Role, QHeaderView::ResizeToContents); headerView->setSectionResizeMode(AttendeeTableModel::FullName, QHeaderView::Stretch); headerView->setSectionResizeMode(AttendeeTableModel::Status, QHeaderView::ResizeToContents); headerView->setSectionResizeMode(AttendeeTableModel::Response, QHeaderView::ResizeToContents); headerView->setSectionHidden(AttendeeTableModel::CuType, true); headerView->setSectionHidden(AttendeeTableModel::Name, true); headerView->setSectionHidden(AttendeeTableModel::Email, true); headerView->setSectionHidden(AttendeeTableModel::Available, true); } void IncidenceAttendee::updateCount() { Q_EMIT attendeeCountChanged(attendeeCount()); checkDirtyStatus(); } int IncidenceAttendee::attendeeCount() const { int c = 0; QModelIndex index; QAbstractItemModel *model = mUi->mAttendeeTable->model(); if (!model) { return 0; } for (int i = 0; i < model->rowCount(QModelIndex()); ++i) { index = model->index(i, AttendeeTableModel::FullName); if (!model->data(index).toString().isEmpty()) { ++c; } } return c; } -void IncidenceAttendee::setActions(KCalCore::Incidence::IncidenceType actions) +void IncidenceAttendee::setActions(KCalendarCore::Incidence::IncidenceType actions) { mStateDelegate->clear(); - if (actions == KCalCore::Incidence::TypeEvent) { + if (actions == KCalendarCore::Incidence::TypeEvent) { mStateDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/task-attention.png")), KCalUtils::Stringify::attendeeStatus(AttendeeData::NeedsAction)); mStateDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/task-accepted.png")), KCalUtils::Stringify::attendeeStatus(AttendeeData::Accepted)); mStateDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/task-reject.png")), KCalUtils::Stringify::attendeeStatus(AttendeeData::Declined)); mStateDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/task-attempt.png")), KCalUtils::Stringify::attendeeStatus(AttendeeData::Tentative)); mStateDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/task-delegate.png")), KCalUtils::Stringify::attendeeStatus(AttendeeData::Delegated)); } else { mStateDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/task-attention.png")), KCalUtils::Stringify::attendeeStatus(AttendeeData::NeedsAction)); mStateDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/task-accepted.png")), KCalUtils::Stringify::attendeeStatus(AttendeeData::Accepted)); mStateDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/task-reject.png")), KCalUtils::Stringify::attendeeStatus(AttendeeData::Declined)); mStateDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/task-attempt.png")), KCalUtils::Stringify::attendeeStatus(AttendeeData::Tentative)); mStateDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/task-delegate.png")), KCalUtils::Stringify::attendeeStatus(AttendeeData::Delegated)); mStateDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/task-complete.png")), KCalUtils::Stringify::attendeeStatus(AttendeeData::Completed)); mStateDelegate->addItem(QIcon::fromTheme(QStringLiteral(":/task-ongoing.png")), KCalUtils::Stringify::attendeeStatus(AttendeeData::InProcess)); } } void IncidenceAttendee::printDebugInfo() const { qCDebug(INCIDENCEEDITOR_LOG) << "I'm organizer : " << iAmOrganizer(); qCDebug(INCIDENCEEDITOR_LOG) << "Loaded organizer: " << mLoadedIncidence->organizer().email(); if (iAmOrganizer()) { - KCalCore::Event tmp; + KCalendarCore::Event tmp; tmp.setOrganizer(mUi->mOrganizerCombo->currentText()); qCDebug(INCIDENCEEDITOR_LOG) << "Organizer combo: " << tmp.organizer().email(); } - const KCalCore::Attendee::List originalList = mLoadedIncidence->attendees(); - KCalCore::Attendee::List newList; + const KCalendarCore::Attendee::List originalList = mLoadedIncidence->attendees(); + KCalendarCore::Attendee::List newList; qCDebug(INCIDENCEEDITOR_LOG) << "List sizes: " << originalList.count() << newList.count(); const auto lstAttendees = mDataModel->attendees(); - for (const KCalCore::Attendee &attendee : lstAttendees) { + for (const KCalendarCore::Attendee &attendee : lstAttendees) { if (!attendee.fullName().isEmpty()) { newList.append(attendee); } } // Okay, again not the most efficient algorithm, but I'm assuming that in the // bulk of the use cases, the number of attendees is not much higher than 10 or so. - for (const KCalCore::Attendee &attendee : originalList) { + for (const KCalendarCore::Attendee &attendee : originalList) { bool found = false; for (int i = 0; i < newList.count(); ++i) { if (newList[i] == attendee) { newList.remove(i); found = true; break; } } if (!found) { qCDebug(INCIDENCEEDITOR_LOG) << "Attendee not found: " << attendee.email() << attendee.name() << attendee.status() << attendee.RSVP() << attendee.role() << attendee.uid() << attendee.cuType() << attendee.delegate() << attendee.delegator() << "; we have:"; for (int i = 0; i < newList.count(); ++i) { - KCalCore::Attendee attendee = newList[i]; + KCalendarCore::Attendee attendee = newList[i]; qCDebug(INCIDENCEEDITOR_LOG) << "Attendee: " << attendee.email() << attendee.name() << attendee.status() << attendee.RSVP() << attendee.role() << attendee.uid() << attendee.cuType() << attendee.delegate() << attendee.delegator(); } return; } } } int IncidenceAttendee::rowOfAttendee(const QString &uid) const { const auto attendees = dataModel()->attendees(); - const auto it = std::find_if(attendees.begin(), attendees.end(), [uid](const KCalCore::Attendee &att) { + const auto it = std::find_if(attendees.begin(), attendees.end(), [uid](const KCalendarCore::Attendee &att) { return att.uid() == uid; }); return std::distance(attendees.begin(), it); } diff --git a/src/incidenceattendee.h b/src/incidenceattendee.h index d208057..bcd241c 100644 --- a/src/incidenceattendee.h +++ b/src/incidenceattendee.h @@ -1,152 +1,152 @@ /* Copyright (C) 2010 Casey Link Copyright (C) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCEATTENDEE_H #define INCIDENCEEDITOR_INCIDENCEATTENDEE_H #include "incidenceeditor-ng.h" -#include +#include namespace Ui { class EventOrTodoDesktop; } namespace KContacts { class Addressee; class ContactGroup; } class KJob; namespace IncidenceEditorNG { class AttendeeComboBoxDelegate; class AttendeeLineEditDelegate; class AttendeeTableModel; class ConflictResolver; class IncidenceDateTime; class IncidenceAttendee : public IncidenceEditor { Q_OBJECT public: using IncidenceEditorNG::IncidenceEditor::save; // So we don't trigger -Woverloaded-virtual using IncidenceEditorNG::IncidenceEditor::load; // So we don't trigger -Woverloaded-virtual IncidenceAttendee(QWidget *parent, IncidenceDateTime *dateTime, Ui::EventOrTodoDesktop *ui); ~IncidenceAttendee() override; - void load(const KCalCore::Incidence::Ptr &incidence) override; - void save(const KCalCore::Incidence::Ptr &incidence) override; + void load(const KCalendarCore::Incidence::Ptr &incidence) override; + void save(const KCalendarCore::Incidence::Ptr &incidence) override; Q_REQUIRED_RESULT bool isDirty() const override; void printDebugInfo() const override; AttendeeTableModel *dataModel() const; AttendeeComboBoxDelegate *stateDelegate() const; AttendeeComboBoxDelegate *roleDelegate() const; AttendeeComboBoxDelegate *responseDelegate() const; AttendeeLineEditDelegate *attendeeDelegate() const; Q_REQUIRED_RESULT int attendeeCount() const; Q_SIGNALS: void attendeeCountChanged(int); public Q_SLOTS: /// If the user is attendee of the loaded event, one of the following slots /// can be used to change the status. void acceptForMe(); void declineForMe(); private Q_SLOTS: // cheks if row is a group, that can/should be expanded - void checkIfExpansionIsNeeded(const KCalCore::Attendee &attendee); + void checkIfExpansionIsNeeded(const KCalendarCore::Attendee &attendee); // results of the group search job void groupSearchResult(KJob *job); void expandResult(KJob *job); void slotSelectAddresses(); void slotSolveConflictPressed(); void slotUpdateConflictLabel(int); void slotOrganizerChanged(const QString &organizer); void slotGroupSubstitutionPressed(); // wrapper for the conflict resolver void slotEventDurationChanged(); void filterLayoutChanged(); void updateCount(); void slotConflictResolverAttendeeAdded(const QModelIndex &index, int first, int last); void slotConflictResolverAttendeeRemoved(const QModelIndex &index, int first, int last); void slotConflictResolverAttendeeChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); void slotConflictResolverLayoutChanged(); void slotFreeBusyAdded(const QModelIndex &index, int first, int last); void slotFreeBusyChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); void updateFBStatus(); - void updateFBStatus(const KCalCore::Attendee &attendee, const KCalCore::FreeBusy::Ptr &fb); + void updateFBStatus(const KCalendarCore::Attendee &attendee, const KCalendarCore::FreeBusy::Ptr &fb); void slotGroupSubstitutionAttendeeAdded(const QModelIndex &index, int first, int last); void slotGroupSubstitutionAttendeeRemoved(const QModelIndex &index, int first, int last); void slotGroupSubstitutionAttendeeChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); void slotGroupSubstitutionLayoutChanged(); private: void updateGroupExpand(); - void changeStatusForMe(KCalCore::Attendee::PartStat); + void changeStatusForMe(KCalendarCore::Attendee::PartStat); /** Returns if I was the organizer of the loaded event */ bool iAmOrganizer() const; /** Reads values from a KContacts::Addressee and inserts a new Attendee * item into the listview with those items. Used when adding attendees * from the addressbook and expanding distribution lists. * The optional Attendee parameter can be used to pass in default values * to be used by the new Attendee. * pos =-1 means insert attendee before empty line */ void insertAttendeeFromAddressee(const KContacts::Addressee &a, int pos = -1); void fillOrganizerCombo(); - void setActions(KCalCore::Incidence::IncidenceType actions); + void setActions(KCalendarCore::Incidence::IncidenceType actions); int rowOfAttendee(const QString &uid) const; Ui::EventOrTodoDesktop *mUi = nullptr; QWidget *mParentWidget = nullptr; ConflictResolver *mConflictResolver = nullptr; IncidenceDateTime *mDateTime = nullptr; QString mOrganizer; /** used dataModel to rely on*/ AttendeeTableModel *mDataModel = nullptr; AttendeeLineEditDelegate *mAttendeeDelegate = nullptr; AttendeeComboBoxDelegate *mStateDelegate = nullptr; AttendeeComboBoxDelegate *mRoleDelegate = nullptr; AttendeeComboBoxDelegate *mResponseDelegate = nullptr; // the QString is Attendee::uid here QMap mGroupList; QMap mMightBeGroupJobs; QMap mExpandGroupJobs; }; } #endif diff --git a/src/incidencecategories.cpp b/src/incidencecategories.cpp index fe3d76a..50cb93c 100644 --- a/src/incidencecategories.cpp +++ b/src/incidencecategories.cpp @@ -1,156 +1,156 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidencecategories.h" #include "editorconfig.h" #include "ui_dialogdesktop.h" #include #include "incidenceeditor_debug.h" #include #include #include #include using namespace IncidenceEditorNG; IncidenceCategories::IncidenceCategories(Ui::EventOrTodoDesktop *ui) : mUi(ui) , mDirty(false) { setObjectName(QStringLiteral("IncidenceCategories")); connect(mUi->mTagWidget, &Akonadi::TagWidget::selectionChanged, this, &IncidenceCategories::onSelectionChanged); } void IncidenceCategories::onSelectionChanged(const Akonadi::Tag::List &list) { Q_UNUSED(list); mDirty = true; checkDirtyStatus(); } -void IncidenceCategories::load(const KCalCore::Incidence::Ptr &incidence) +void IncidenceCategories::load(const KCalendarCore::Incidence::Ptr &incidence) { mLoadedIncidence = incidence; mDirty = false; mWasDirty = false; mMissingCategories.clear(); if (mLoadedIncidence) { Akonadi::TagFetchJob *fetchJob = new Akonadi::TagFetchJob(this); fetchJob->fetchScope().fetchAttribute(); connect(fetchJob, &Akonadi::TagFetchJob::result, this, &IncidenceCategories::onTagsFetched); } } -void IncidenceCategories::save(const KCalCore::Incidence::Ptr &incidence) +void IncidenceCategories::save(const KCalendarCore::Incidence::Ptr &incidence) { Q_ASSERT(incidence); if (mDirty) { incidence->setCategories(categories()); } } void IncidenceCategories::save(Akonadi::Item &item) { const auto &selectedTags = mUi->mTagWidget->selection(); if (mDirty) { item.setTags(selectedTags); } } QStringList IncidenceCategories::categories() const { QStringList list; const auto &selectedTags = mUi->mTagWidget->selection(); list.reserve(selectedTags.count() + mMissingCategories.count()); for (const Akonadi::Tag &tag : selectedTags) { list << tag.name(); } list << mMissingCategories; return list; } void IncidenceCategories::createMissingCategories() { for (const QString &category : qAsConst(mMissingCategories)) { Akonadi::Tag missingTag = Akonadi::Tag::genericTag(category); Akonadi::TagCreateJob *createJob = new Akonadi::TagCreateJob(missingTag, this); connect(createJob, &Akonadi::TagCreateJob::result, this, &IncidenceCategories::onMissingTagCreated); } } bool IncidenceCategories::isDirty() const { return mDirty; } void IncidenceCategories::printDebugInfo() const { qCDebug(INCIDENCEEDITOR_LOG) << "selected categories = " << categories(); qCDebug(INCIDENCEEDITOR_LOG) << "mMissingCategories = " << mMissingCategories; qCDebug(INCIDENCEEDITOR_LOG) << "mLoadedIncidence->categories() = " << mLoadedIncidence->categories(); } void IncidenceCategories::onTagsFetched(KJob *job) { if (job->error()) { qCWarning(INCIDENCEEDITOR_LOG) << "Failed to load tags " << job->errorString(); return; } Akonadi::TagFetchJob *fetchJob = static_cast(job); const Akonadi::Tag::List jobTags = fetchJob->tags(); Q_ASSERT(mLoadedIncidence); mMissingCategories = mLoadedIncidence->categories(); Akonadi::Tag::List selectedTags; selectedTags.reserve(mMissingCategories.count()); for (const auto &tag : jobTags) { if (mMissingCategories.removeAll(tag.name()) > 0) { selectedTags << tag; } } createMissingCategories(); mUi->mTagWidget->setSelection(selectedTags); } void IncidenceCategories::onMissingTagCreated(KJob *job) { if (job->error()) { qCWarning(INCIDENCEEDITOR_LOG) << "Failed to create tag " << job->errorString(); return; } Akonadi::TagCreateJob *createJob = static_cast(job); int count = mMissingCategories.removeAll(createJob->tag().name()); Q_ASSERT(count > 0); QVector selectedTags; selectedTags.reserve(mUi->mTagWidget->selection().count() + 1); selectedTags << mUi->mTagWidget->selection() << createJob->tag(); mUi->mTagWidget->setSelection(selectedTags); } diff --git a/src/incidencecategories.h b/src/incidencecategories.h index 821a79d..b32dd71 100644 --- a/src/incidencecategories.h +++ b/src/incidencecategories.h @@ -1,71 +1,71 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCECATEGORIES_H #define INCIDENCEEDITOR_INCIDENCECATEGORIES_H #include "incidenceeditor-ng.h" namespace Ui { class EventOrTodoDesktop; } namespace IncidenceEditorNG { class IncidenceCategories : public IncidenceEditor { Q_OBJECT public: explicit IncidenceCategories(Ui::EventOrTodoDesktop *ui); - void load(const KCalCore::Incidence::Ptr &incidence) override; - void save(const KCalCore::Incidence::Ptr &incidence) override; + void load(const KCalendarCore::Incidence::Ptr &incidence) override; + void save(const KCalendarCore::Incidence::Ptr &incidence) override; void save(Akonadi::Item &item) override; /** * Returns the list of currently selected categories. */ Q_REQUIRED_RESULT QStringList categories() const; Q_REQUIRED_RESULT bool isDirty() const override; void printDebugInfo() const override; private: void createMissingCategories(); void onSelectionChanged(const Akonadi::Tag::List &); void onTagsFetched(KJob *); void onMissingTagCreated(KJob *); Ui::EventOrTodoDesktop *mUi = nullptr; /** * List of categories for which no tag might exist. * * For each category of the edited incidence, we want to make sure that there exists a * corresponding tag in Akonadi. For missing categories, a \a TagCreateJob is issued. * Eventually, there should be no missing categories left. In case tag creation fails for some * categories, this list still holds these categories so they don't get lost */ QStringList mMissingCategories; bool mDirty = false; }; } #endif diff --git a/src/incidencecompletionpriority.cpp b/src/incidencecompletionpriority.cpp index 95fb326..68f8fc8 100644 --- a/src/incidencecompletionpriority.cpp +++ b/src/incidencecompletionpriority.cpp @@ -1,151 +1,151 @@ /* Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Kevin Krammer This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidencecompletionpriority.h" #include "ui_dialogdesktop.h" -#include +#include using namespace IncidenceEditorNG; class IncidenceCompletionPriority::Private { IncidenceCompletionPriority *const q; public: explicit Private(IncidenceCompletionPriority *parent) : q(parent) , mUi(nullptr) , mOrigPercentCompleted(-1) { } public: Ui::EventOrTodoDesktop *mUi = nullptr; int mOrigPercentCompleted = -1; public: // slots void sliderValueChanged(int); }; void IncidenceCompletionPriority::Private::sliderValueChanged(int value) { if (q->sender() == mUi->mCompletionSlider) { mOrigPercentCompleted = -1; } mUi->mCompletedLabel->setText(QStringLiteral("%1%").arg(value)); q->checkDirtyStatus(); } IncidenceCompletionPriority::IncidenceCompletionPriority(Ui::EventOrTodoDesktop *ui) : IncidenceEditor() , d(new Private(this)) { Q_ASSERT(ui != nullptr); setObjectName(QStringLiteral("IncidenceCompletionPriority")); d->mUi = ui; d->sliderValueChanged(d->mUi->mCompletionSlider->value()); d->mUi->mCompletionPriorityWidget->hide(); d->mUi->mTaskLabel->hide(); const QFontMetrics metrics(d->mUi->mCompletedLabel->font()); d->mUi->mCompletedLabel->setMinimumWidth(metrics.boundingRect(QStringLiteral("100%")).width()); d->mUi->mTaskSeparator->hide(); connect(d->mUi->mCompletionSlider, qOverload(&QSlider::valueChanged), this, [this](int val) { d->sliderValueChanged(val); }); connect(d->mUi->mPriorityCombo, qOverload< int>(&QComboBox::currentIndexChanged), this, &IncidenceCompletionPriority::checkDirtyStatus); } IncidenceCompletionPriority::~IncidenceCompletionPriority() { delete d; } -void IncidenceCompletionPriority::load(const KCalCore::Incidence::Ptr &incidence) +void IncidenceCompletionPriority::load(const KCalendarCore::Incidence::Ptr &incidence) { mLoadedIncidence = incidence; // TODO priority might be valid for other incidence types as well // only for Todos - KCalCore::Todo::Ptr todo = IncidenceCompletionPriority::incidence(); + KCalendarCore::Todo::Ptr todo = IncidenceCompletionPriority::incidence(); if (todo == nullptr) { mWasDirty = false; return; } d->mUi->mCompletionPriorityWidget->show(); d->mUi->mTaskLabel->show(); d->mUi->mTaskSeparator->show(); d->mOrigPercentCompleted = todo->percentComplete(); d->mUi->mCompletionSlider->blockSignals(true); d->mUi->mCompletionSlider->setValue(todo->percentComplete()); d->sliderValueChanged(d->mUi->mCompletionSlider->value()); d->mUi->mCompletionSlider->blockSignals(false); d->mUi->mPriorityCombo->blockSignals(true); d->mUi->mPriorityCombo->setCurrentIndex(todo->priority()); d->mUi->mPriorityCombo->blockSignals(false); mWasDirty = false; } -void IncidenceCompletionPriority::save(const KCalCore::Incidence::Ptr &incidence) +void IncidenceCompletionPriority::save(const KCalendarCore::Incidence::Ptr &incidence) { // TODO priority might be valid for other incidence types as well // only for Todos - KCalCore::Todo::Ptr todo = IncidenceCompletionPriority::incidence(incidence); + KCalendarCore::Todo::Ptr todo = IncidenceCompletionPriority::incidence(incidence); if (todo == nullptr) { return; } // we only have multiples of ten on our combo. If the combo did not change its value, // see if we have an original value to restore if (d->mOrigPercentCompleted != -1) { todo->setPercentComplete(d->mOrigPercentCompleted); } else { todo->setPercentComplete(d->mUi->mCompletionSlider->value()); } todo->setPriority(d->mUi->mPriorityCombo->currentIndex()); } bool IncidenceCompletionPriority::isDirty() const { - KCalCore::Todo::Ptr todo = IncidenceCompletionPriority::incidence(); + KCalendarCore::Todo::Ptr todo = IncidenceCompletionPriority::incidence(); if (!todo) { return false; } if (d->mUi->mCompletionSlider->value() != todo->percentComplete()) { return true; } if (d->mUi->mPriorityCombo->currentIndex() != todo->priority()) { return true; } return false; } #include "moc_incidencecompletionpriority.cpp" diff --git a/src/incidencecompletionpriority.h b/src/incidencecompletionpriority.h index ebd5bf0..2a6e5d3 100644 --- a/src/incidencecompletionpriority.h +++ b/src/incidencecompletionpriority.h @@ -1,51 +1,51 @@ /* Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company Author: Kevin Krammer This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCECOMPLETIONPRIORITY_H #define INCIDENCEEDITOR_INCIDENCECOMPLETIONPRIORITY_H #include "incidenceeditor-ng.h" namespace Ui { class EventOrTodoDesktop; } namespace IncidenceEditorNG { class IncidenceCompletionPriority : public IncidenceEditor { Q_OBJECT public: using IncidenceEditorNG::IncidenceEditor::save; // So we don't trigger -Woverloaded-virtual using IncidenceEditorNG::IncidenceEditor::load; // So we don't trigger -Woverloaded-virtual explicit IncidenceCompletionPriority(Ui::EventOrTodoDesktop *ui); ~IncidenceCompletionPriority() override; - void load(const KCalCore::Incidence::Ptr &incidence) override; - void save(const KCalCore::Incidence::Ptr &incidence) override; + void load(const KCalendarCore::Incidence::Ptr &incidence) override; + void save(const KCalendarCore::Incidence::Ptr &incidence) override; bool isDirty() const override; private: class Private; Private *const d; }; } #endif diff --git a/src/incidencedatetime.cpp b/src/incidencedatetime.cpp index 3ff8d12..406f22a 100644 --- a/src/incidencedatetime.cpp +++ b/src/incidencedatetime.cpp @@ -1,1000 +1,1000 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidencedatetime.h" #include "ui_dialogdesktop.h" #include "incidenceeditor_debug.h" #include #include #include using namespace IncidenceEditorNG; /** * Returns true if the incidence's dates are equal to the default ones specified in config. */ -static bool incidenceHasDefaultTimes(const KCalCore::Incidence::Ptr &incidence) +static bool incidenceHasDefaultTimes(const KCalendarCore::Incidence::Ptr &incidence) { if (!incidence || incidence->allDay()) { return false; } QTime defaultDuration = CalendarSupport::KCalPrefs::instance()->defaultDuration().time(); if (!defaultDuration.isValid()) { return false; } QTime defaultStart = CalendarSupport::KCalPrefs::instance()->mStartTime.time(); if (!defaultStart.isValid()) { return false; } if (incidence->dtStart().time() == defaultStart) { - if (incidence->type() == KCalCore::Incidence::TypeJournal) { + if (incidence->type() == KCalendarCore::Incidence::TypeJournal) { return true; // no duration to compare with } const QDateTime start = incidence->dtStart(); - const QDateTime end = incidence->dateTime(KCalCore::Incidence::RoleEnd); + const QDateTime end = incidence->dateTime(KCalendarCore::Incidence::RoleEnd); if (!end.isValid() || !start.isValid()) { return false; } const int durationInSeconds = defaultDuration.hour() * 3600 + defaultDuration.minute() * 60; return start.secsTo(end) == durationInSeconds; } return false; } IncidenceDateTime::IncidenceDateTime(Ui::EventOrTodoDesktop *ui) : IncidenceEditor(nullptr) , mUi(ui) , mTimezoneCombosWereVisibile(false) { setTimeZonesVisibility(false); setObjectName(QStringLiteral("IncidenceDateTime")); mUi->mTimeZoneLabel->setVisible(!mUi->mWholeDayCheck->isChecked()); connect(mUi->mTimeZoneLabel, &QLabel::linkActivated, this, &IncidenceDateTime::toggleTimeZoneVisibility); mUi->mTimeZoneLabel->setContextMenuPolicy(Qt::NoContextMenu); const QList lineEdits { mUi->mStartDateEdit->lineEdit(), mUi->mEndDateEdit->lineEdit(), mUi->mStartTimeEdit->lineEdit(), mUi->mEndTimeEdit->lineEdit()}; for (QLineEdit *lineEdit : lineEdits) { if (lineEdit) { lineEdit->setClearButtonEnabled(false); } } connect(mUi->mFreeBusyCheck, &QCheckBox::toggled, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mWholeDayCheck, &QCheckBox::toggled, this, &IncidenceDateTime::enableTimeEdits); connect(mUi->mWholeDayCheck, &QCheckBox::toggled, this, &IncidenceDateTime::checkDirtyStatus); connect(this, &IncidenceDateTime::startDateChanged, this, &IncidenceDateTime::updateStartToolTips); connect(this, &IncidenceDateTime::startTimeChanged, this, &IncidenceDateTime::updateStartToolTips); connect(this, &IncidenceDateTime::endDateChanged, this, &IncidenceDateTime::updateEndToolTips); connect(this, &IncidenceDateTime::endTimeChanged, this, &IncidenceDateTime::updateEndToolTips); connect(mUi->mWholeDayCheck, &QCheckBox::toggled, this, &IncidenceDateTime::updateStartToolTips); connect(mUi->mWholeDayCheck, &QCheckBox::toggled, this, &IncidenceDateTime::updateEndToolTips); connect(mUi->mStartCheck, &QCheckBox::toggled, this, &IncidenceDateTime::updateStartToolTips); connect(mUi->mEndCheck, &QCheckBox::toggled, this, &IncidenceDateTime::updateEndToolTips); } IncidenceDateTime::~IncidenceDateTime() { } bool IncidenceDateTime::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::FocusIn) { if (obj == mUi->mStartDateEdit) { qCDebug(INCIDENCEEDITOR_LOG) << "emitting startDateTime: " << mUi->mStartDateEdit; Q_EMIT startDateFocus(obj); } else if (obj == mUi->mEndDateEdit) { qCDebug(INCIDENCEEDITOR_LOG) << "emitting endDateTime: " << mUi->mEndDateEdit; Q_EMIT endDateFocus(obj); } else if (obj == mUi->mStartTimeEdit) { qCDebug(INCIDENCEEDITOR_LOG) << "emitting startTimeTime: " << mUi->mStartTimeEdit; Q_EMIT startTimeFocus(obj); } else if (obj == mUi->mEndTimeEdit) { qCDebug(INCIDENCEEDITOR_LOG) << "emitting endTimeTime: " << mUi->mEndTimeEdit; Q_EMIT endTimeFocus(obj); } return true; } else { // standard event processing return QObject::eventFilter(obj, event); } } -void IncidenceDateTime::load(const KCalCore::Incidence::Ptr &incidence) +void IncidenceDateTime::load(const KCalendarCore::Incidence::Ptr &incidence) { if (mLoadedIncidence && *mLoadedIncidence == *incidence) { return; } const bool isTemplate = incidence->customProperty("kdepim", "isTemplate") == QLatin1String( "true"); const bool templateOverridesTimes = incidenceHasDefaultTimes(mLoadedIncidence); mLoadedIncidence = incidence; mLoadingIncidence = true; // We can only handle events or todos. - if (KCalCore::Todo::Ptr todo = IncidenceDateTime::incidence()) { + if (KCalendarCore::Todo::Ptr todo = IncidenceDateTime::incidence()) { load(todo, isTemplate, templateOverridesTimes); - } else if (KCalCore::Event::Ptr event = IncidenceDateTime::incidence()) { + } else if (KCalendarCore::Event::Ptr event = IncidenceDateTime::incidence()) { load(event, isTemplate, templateOverridesTimes); - } else if (KCalCore::Journal::Ptr journal = IncidenceDateTime::incidence()) { + } else if (KCalendarCore::Journal::Ptr journal = IncidenceDateTime::incidence()) { load(journal, isTemplate, templateOverridesTimes); } else { qCDebug(INCIDENCEEDITOR_LOG) << "Not an Incidence."; } // Set the initial times before calling enableTimeEdits, as enableTimeEdits // assumes that the initial times are initialized. mInitialStartDT = currentStartDateTime(); mInitialEndDT = currentEndDateTime(); enableTimeEdits(); if (mUi->mTimeZoneComboStart->currentIndex() == 0) { // Floating mInitialStartDT.setTimeZone(QTimeZone::systemTimeZone()); } if (mUi->mTimeZoneComboEnd->currentIndex() == 0) { // Floating mInitialEndDT.setTimeZone(QTimeZone::systemTimeZone()); } mWasDirty = false; mLoadingIncidence = false; } -void IncidenceDateTime::save(const KCalCore::Incidence::Ptr &incidence) +void IncidenceDateTime::save(const KCalendarCore::Incidence::Ptr &incidence) { - if (KCalCore::Todo::Ptr todo - = IncidenceDateTime::incidence(incidence)) { + if (KCalendarCore::Todo::Ptr todo + = IncidenceDateTime::incidence(incidence)) { save(todo); - } else if (KCalCore::Event::Ptr event - = IncidenceDateTime::incidence(incidence)) { + } else if (KCalendarCore::Event::Ptr event + = IncidenceDateTime::incidence(incidence)) { save(event); - } else if (KCalCore::Journal::Ptr journal - = IncidenceDateTime::incidence(incidence)) { + } else if (KCalendarCore::Journal::Ptr journal + = IncidenceDateTime::incidence(incidence)) { save(journal); } else { Q_ASSERT_X(false, "IncidenceDateTimeEditor::save", "Only implemented for todos, events and journals"); } } bool IncidenceDateTime::isDirty() const { - if (KCalCore::Todo::Ptr todo = IncidenceDateTime::incidence()) { + if (KCalendarCore::Todo::Ptr todo = IncidenceDateTime::incidence()) { return isDirty(todo); - } else if (KCalCore::Event::Ptr event = IncidenceDateTime::incidence()) { + } else if (KCalendarCore::Event::Ptr event = IncidenceDateTime::incidence()) { return isDirty(event); - } else if (KCalCore::Journal::Ptr journal = IncidenceDateTime::incidence()) { + } else if (KCalendarCore::Journal::Ptr journal = IncidenceDateTime::incidence()) { return isDirty(journal); } else { Q_ASSERT_X(false, "IncidenceDateTimeEditor::isDirty", "Only implemented for todos and events"); return false; } } void IncidenceDateTime::setActiveDate(const QDate &activeDate) { mActiveDate = activeDate; } QDate IncidenceDateTime::startDate() const { return currentStartDateTime().date(); } QDate IncidenceDateTime::endDate() const { return currentEndDateTime().date(); } QTime IncidenceDateTime::startTime() const { return currentStartDateTime().time(); } QTime IncidenceDateTime::endTime() const { return currentEndDateTime().time(); } /// private slots for General void IncidenceDateTime::setTimeZonesVisibility(bool visible) { static const QString tz(i18nc("@action show or hide the time zone widgets", "Time zones")); QString placeholder(QStringLiteral("<< %1")); if (visible) { placeholder = placeholder.arg(tz); } else { placeholder = QStringLiteral("%1 >>"); placeholder = placeholder.arg(tz); } mUi->mTimeZoneLabel->setText(placeholder); mUi->mTimeZoneComboStart->setVisible(visible); - mUi->mTimeZoneComboEnd->setVisible(visible && type() != KCalCore::Incidence::TypeJournal); + mUi->mTimeZoneComboEnd->setVisible(visible && type() != KCalendarCore::Incidence::TypeJournal); } void IncidenceDateTime::toggleTimeZoneVisibility() { setTimeZonesVisibility(!mUi->mTimeZoneComboStart->isVisible()); } void IncidenceDateTime::updateStartTime(const QTime &newTime) { if (!newTime.isValid()) { return; } QDateTime endDateTime = currentEndDateTime(); const int secsep = mCurrentStartDateTime.secsTo(endDateTime); mCurrentStartDateTime.setTime(newTime); if (mUi->mEndCheck->isChecked()) { // Only update the end time when it is actually enabled, adjust end time so // that the event/todo has the same duration as before. endDateTime = mCurrentStartDateTime.addSecs(secsep); mUi->mEndTimeEdit->setTime(endDateTime.time()); mUi->mEndDateEdit->setDate(endDateTime.date()); } Q_EMIT startTimeChanged(mCurrentStartDateTime.time()); checkDirtyStatus(); } void IncidenceDateTime::updateStartDate(const QDate &newDate) { if (!newDate.isValid()) { return; } const bool dateChanged = mCurrentStartDateTime.date().day() != newDate.day() || mCurrentStartDateTime.date().month() != newDate.month(); QDateTime endDateTime = currentEndDateTime(); int daysep = mCurrentStartDateTime.daysTo(endDateTime); mCurrentStartDateTime.setDate(newDate); if (mUi->mEndCheck->isChecked()) { // Only update the end time when it is actually enabled, adjust end time so // that the event/todo has the same duration as before. endDateTime.setDate(mCurrentStartDateTime.date().addDays(daysep)); mUi->mEndDateEdit->setDate(endDateTime.date()); } checkDirtyStatus(); if (dateChanged) { Q_EMIT startDateChanged(mCurrentStartDateTime.date()); } } void IncidenceDateTime::updateStartSpec() { const QDate prevDate = mCurrentStartDateTime.date(); if (mUi->mEndCheck->isChecked() && currentEndDateTime().timeZone() == mCurrentStartDateTime.timeZone()) { mUi->mTimeZoneComboEnd->selectTimeZone(mUi->mTimeZoneComboStart->selectedTimeZone()); } mCurrentStartDateTime.setTimeZone(mUi->mTimeZoneComboStart->selectedTimeZone()); const bool dateChanged = mCurrentStartDateTime.date().day() != prevDate.day() || mCurrentStartDateTime.date().month() != prevDate.month(); if (dateChanged) { Q_EMIT startDateChanged(mCurrentStartDateTime.date()); } - if (type() == KCalCore::Incidence::TypeJournal) { + if (type() == KCalendarCore::Incidence::TypeJournal) { checkDirtyStatus(); } } /// private slots for Todo void IncidenceDateTime::enableStartEdit(bool enable) { mUi->mStartDateEdit->setEnabled(enable); if (mUi->mEndCheck->isChecked() || mUi->mStartCheck->isChecked()) { mUi->mWholeDayCheck->setEnabled(true); setTimeZoneLabelEnabled(!mUi->mWholeDayCheck->isChecked()); } else { mUi->mWholeDayCheck->setEnabled(false); mUi->mWholeDayCheck->setChecked(false); setTimeZoneLabelEnabled(false); } if (enable) { mUi->mStartTimeEdit->setEnabled(!mUi->mWholeDayCheck->isChecked()); mUi->mTimeZoneComboStart->setEnabled(!mUi->mWholeDayCheck->isChecked()); } else { mUi->mStartTimeEdit->setEnabled(false); mUi->mTimeZoneComboStart->setEnabled(false); } mUi->mTimeZoneComboStart->setFloating(!mUi->mTimeZoneComboStart->isEnabled()); checkDirtyStatus(); } void IncidenceDateTime::enableEndEdit(bool enable) { mUi->mEndDateEdit->setEnabled(enable); if (mUi->mEndCheck->isChecked() || mUi->mStartCheck->isChecked()) { mUi->mWholeDayCheck->setEnabled(true); setTimeZoneLabelEnabled(!mUi->mWholeDayCheck->isChecked()); } else { mUi->mWholeDayCheck->setEnabled(false); mUi->mWholeDayCheck->setChecked(false); setTimeZoneLabelEnabled(false); } if (enable) { mUi->mEndTimeEdit->setEnabled(!mUi->mWholeDayCheck->isChecked()); mUi->mTimeZoneComboEnd->setEnabled(!mUi->mWholeDayCheck->isChecked()); } else { mUi->mEndTimeEdit->setEnabled(false); mUi->mTimeZoneComboEnd->setEnabled(false); } mUi->mTimeZoneComboEnd->setFloating(!mUi->mTimeZoneComboEnd->isEnabled()); checkDirtyStatus(); } bool IncidenceDateTime::timeZonesAreLocal(const QDateTime &start, const QDateTime &end) { // Returns false if the incidence start or end timezone is not the local zone. if ((start.isValid() && start.timeZone() != QTimeZone::systemTimeZone()) || (end.isValid() && end.timeZone() != QTimeZone::systemTimeZone())) { return false; } else { return true; } } void IncidenceDateTime::enableTimeEdits() { // NOTE: assumes that the initial times are initialized. const bool wholeDayChecked = mUi->mWholeDayCheck->isChecked(); setTimeZoneLabelEnabled(!wholeDayChecked); if (mUi->mStartCheck->isChecked()) { mUi->mStartTimeEdit->setEnabled(!wholeDayChecked); mUi->mTimeZoneComboStart->setEnabled(!wholeDayChecked); mUi->mTimeZoneComboStart->setFloating(wholeDayChecked, mInitialStartDT.timeZone()); } if (mUi->mEndCheck->isChecked()) { mUi->mEndTimeEdit->setEnabled(!wholeDayChecked); mUi->mTimeZoneComboEnd->setEnabled(!wholeDayChecked); mUi->mTimeZoneComboEnd->setFloating(wholeDayChecked, mInitialEndDT.timeZone()); } /** When editing a whole-day event, unchecking mWholeDayCheck shouldn't set both times to 00:00. DTSTART must always be smaller than DTEND */ if (sender() == mUi->mWholeDayCheck && !wholeDayChecked // Somebody unchecked it, the incidence will now have time. && mUi->mStartCheck->isChecked() && mUi->mEndCheck->isChecked() // The incidence has both start and end/due dates && currentStartDateTime() == currentEndDateTime()) { // DTSTART == DTEND. This is illegal, lets correct it. // Not sure about the best time here... doesn't really matter, when someone unchecks mWholeDayCheck, she will // always want to set a time. mUi->mStartTimeEdit->setTime(QTime(0, 0)); mUi->mEndTimeEdit->setTime(QTime(1, 0)); } const bool currentlyVisible = mUi->mTimeZoneLabel->text().contains(QStringLiteral("<<")); setTimeZonesVisibility(!wholeDayChecked && mTimezoneCombosWereVisibile); mTimezoneCombosWereVisibile = currentlyVisible; if (!wholeDayChecked && !timeZonesAreLocal(currentStartDateTime(), currentEndDateTime())) { setTimeZonesVisibility(true); mTimezoneCombosWereVisibile = true; } } -bool IncidenceDateTime::isDirty(const KCalCore::Todo::Ptr &todo) const +bool IncidenceDateTime::isDirty(const KCalendarCore::Todo::Ptr &todo) const { Q_ASSERT(todo); const bool hasDateTimes = mUi->mStartCheck->isChecked() || mUi->mEndCheck->isChecked(); // First check the start time/date of the todo if (todo->hasStartDate() != mUi->mStartCheck->isChecked()) { return true; } if ((hasDateTimes && todo->allDay()) != mUi->mWholeDayCheck->isChecked()) { return true; } if (todo->hasDueDate() != mUi->mEndCheck->isChecked()) { return true; } if (mUi->mStartCheck->isChecked()) { // Use mActiveStartTime. This is the QTimeZone selected on load coming from // the combobox. We use this one as it can slightly differ (e.g. missing // country code in the incidence time spec) from the incidence. if (currentStartDateTime() != mInitialStartDT) { return true; } } if (mUi->mEndCheck->isChecked() && currentEndDateTime() != mInitialEndDT) { return true; } return false; } /// Event specific methods -bool IncidenceDateTime::isDirty(const KCalCore::Event::Ptr &event) const +bool IncidenceDateTime::isDirty(const KCalendarCore::Event::Ptr &event) const { if (event->allDay() != mUi->mWholeDayCheck->isChecked()) { return true; } if (mUi->mFreeBusyCheck->isChecked() - && event->transparency() != KCalCore::Event::Opaque) { + && event->transparency() != KCalendarCore::Event::Opaque) { return true; } if (!mUi->mFreeBusyCheck->isChecked() - && event->transparency() != KCalCore::Event::Transparent) { + && event->transparency() != KCalendarCore::Event::Transparent) { return true; } if (event->allDay()) { if (mUi->mStartDateEdit->date() != mInitialStartDT.date() || mUi->mEndDateEdit->date() != mInitialEndDT.date()) { return true; } } else { if (currentStartDateTime() != mInitialStartDT || currentEndDateTime() != mInitialEndDT || currentStartDateTime().timeZone() != mInitialStartDT.timeZone() || currentEndDateTime().timeZone() != mInitialEndDT.timeZone()) { return true; } } return false; } -bool IncidenceDateTime::isDirty(const KCalCore::Journal::Ptr &journal) const +bool IncidenceDateTime::isDirty(const KCalendarCore::Journal::Ptr &journal) const { if (journal->allDay() != mUi->mWholeDayCheck->isChecked()) { return true; } if (journal->allDay()) { if (mUi->mStartDateEdit->date() != mInitialStartDT.date()) { return true; } } else { if (currentStartDateTime() != mInitialStartDT) { return true; } } return false; } /// Private methods QDateTime IncidenceDateTime::currentStartDateTime() const { return QDateTime( mUi->mStartDateEdit->date(), mUi->mStartTimeEdit->time(), mUi->mTimeZoneComboStart->selectedTimeZone()); } QDateTime IncidenceDateTime::currentEndDateTime() const { return QDateTime( mUi->mEndDateEdit->date(), mUi->mEndTimeEdit->time(), mUi->mTimeZoneComboEnd->selectedTimeZone()); } -void IncidenceDateTime::load(const KCalCore::Event::Ptr &event, bool isTemplate, bool templateOverridesTimes) +void IncidenceDateTime::load(const KCalendarCore::Event::Ptr &event, bool isTemplate, bool templateOverridesTimes) { // First en/disable the necessary ui bits and pieces mUi->mStartCheck->setVisible(false); mUi->mStartCheck->setChecked(true); // Set to checked so we can reuse enableTimeEdits. mUi->mEndCheck->setVisible(false); mUi->mEndCheck->setChecked(true); // Set to checked so we can reuse enableTimeEdits. // Start time connect(mUi->mStartTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::updateStartTime); // when editing with mouse, or up/down arrows connect(mUi->mStartTimeEdit, &KTimeComboBox::timeEdited, this, &IncidenceDateTime::updateStartTime); // When editing with any key except up/down connect(mUi->mStartDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::updateStartDate); connect(mUi->mTimeZoneComboStart, static_cast(&IncidenceEditorNG:: KTimeZoneComboBox:: currentIndexChanged), this, &IncidenceDateTime::updateStartSpec); // End time connect(mUi->mEndTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndTimeEdit, &KTimeComboBox::timeEdited, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::endTimeChanged); connect(mUi->mEndTimeEdit, &KTimeComboBox::timeEdited, this, &IncidenceDateTime::endTimeChanged); connect(mUi->mEndDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::endDateChanged); connect(mUi->mTimeZoneComboEnd, static_cast(&IncidenceEditorNG:: KTimeZoneComboBox:: currentIndexChanged), this, &IncidenceDateTime::checkDirtyStatus); mUi->mWholeDayCheck->setChecked(event->allDay()); enableTimeEdits(); if (isTemplate) { if (templateOverridesTimes) { // We only use the template times if the user didn't override them. setTimes(event->dtStart(), event->dtEnd()); } } else { QDateTime startDT = event->dtStart(); QDateTime endDT = event->dtEnd(); setDateTimes(startDT, endDT); } switch (event->transparency()) { - case KCalCore::Event::Transparent: + case KCalendarCore::Event::Transparent: mUi->mFreeBusyCheck->setChecked(false); break; - case KCalCore::Event::Opaque: + case KCalendarCore::Event::Opaque: mUi->mFreeBusyCheck->setChecked(true); break; } } -void IncidenceDateTime::load(const KCalCore::Journal::Ptr &journal, bool isTemplate, bool templateOverridesTimes) +void IncidenceDateTime::load(const KCalendarCore::Journal::Ptr &journal, bool isTemplate, bool templateOverridesTimes) { // First en/disable the necessary ui bits and pieces mUi->mStartCheck->setVisible(false); mUi->mStartCheck->setChecked(true); // Set to checked so we can reuse enableTimeEdits. mUi->mEndCheck->setVisible(false); mUi->mEndCheck->setChecked(true); // Set to checked so we can reuse enableTimeEdits. mUi->mEndDateEdit->setVisible(false); mUi->mEndTimeEdit->setVisible(false); mUi->mTimeZoneComboEnd->setVisible(false); mUi->mEndLabel->setVisible(false); mUi->mFreeBusyCheck->setVisible(false); // Start time connect(mUi->mStartTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::updateStartTime); connect(mUi->mStartDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::updateStartDate); connect(mUi->mTimeZoneComboStart, static_cast(&IncidenceEditorNG:: KTimeZoneComboBox:: currentIndexChanged), this, &IncidenceDateTime::updateStartSpec); mUi->mWholeDayCheck->setChecked(journal->allDay()); enableTimeEdits(); if (isTemplate) { if (templateOverridesTimes) { // We only use the template times if the user didn't override them. setTimes(journal->dtStart(), QDateTime()); } } else { QDateTime startDT = journal->dtStart(); // Convert UTC to local timezone, if needed (i.e. for kolab #204059) if (startDT.timeZone() == QTimeZone::utc()) { startDT = startDT.toLocalTime(); } setDateTimes(startDT, QDateTime()); } } -void IncidenceDateTime::load(const KCalCore::Todo::Ptr &todo, bool isTemplate, bool templateOverridesTimes) +void IncidenceDateTime::load(const KCalendarCore::Todo::Ptr &todo, bool isTemplate, bool templateOverridesTimes) { // First en/disable the necessary ui bits and pieces mUi->mStartCheck->setVisible(true); mUi->mStartCheck->setChecked(todo->hasStartDate()); mUi->mStartDateEdit->setEnabled(todo->hasStartDate()); mUi->mStartTimeEdit->setEnabled(todo->hasStartDate()); mUi->mTimeZoneComboStart->setEnabled(todo->hasStartDate()); mUi->mEndLabel->setText(i18nc("@label The due date/time of a to-do", "Due:")); mUi->mEndCheck->setVisible(true); mUi->mEndCheck->setChecked(todo->hasDueDate()); mUi->mEndDateEdit->setEnabled(todo->hasDueDate()); mUi->mEndTimeEdit->setEnabled(todo->hasDueDate()); mUi->mTimeZoneComboEnd->setEnabled(todo->hasDueDate()); // These fields where not enabled in the old code either: mUi->mFreeBusyCheck->setVisible(false); const bool hasDateTimes = mUi->mEndCheck->isChecked() || mUi->mStartCheck->isChecked(); mUi->mWholeDayCheck->setChecked(hasDateTimes && todo->allDay()); mUi->mWholeDayCheck->setEnabled(hasDateTimes); // Connect to the right logic connect(mUi->mStartCheck, &QCheckBox::toggled, this, &IncidenceDateTime::enableStartEdit); connect(mUi->mStartCheck, &QCheckBox::toggled, this, &IncidenceDateTime::startDateTimeToggled); connect(mUi->mStartDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mStartTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::updateStartTime); connect(mUi->mStartTimeEdit, &KTimeComboBox::timeEdited, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mTimeZoneComboStart, static_cast(&IncidenceEditorNG:: KTimeZoneComboBox:: currentIndexChanged), this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndCheck, &QCheckBox::toggled, this, &IncidenceDateTime::enableEndEdit); connect(mUi->mEndCheck, &QCheckBox::toggled, this, &IncidenceDateTime::endDateTimeToggled); connect(mUi->mEndDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndTimeEdit, &KTimeComboBox::timeEdited, this, &IncidenceDateTime::checkDirtyStatus); connect(mUi->mEndDateEdit, &KDateComboBox::dateChanged, this, &IncidenceDateTime::endDateChanged); connect(mUi->mEndTimeEdit, &KTimeComboBox::timeChanged, this, &IncidenceDateTime::endTimeChanged); connect(mUi->mTimeZoneComboEnd, static_cast(&IncidenceEditorNG:: KTimeZoneComboBox:: currentIndexChanged), this, &IncidenceDateTime::checkDirtyStatus); const QDateTime rightNow = QDateTime::currentDateTime(); if (isTemplate) { if (templateOverridesTimes) { // We only use the template times if the user didn't override them. - setTimes(todo->dtStart(), todo->dateTime(KCalCore::Incidence::RoleEnd)); + setTimes(todo->dtStart(), todo->dateTime(KCalendarCore::Incidence::RoleEnd)); } } else { const QDateTime endDT = todo->hasDueDate() ? todo->dtDue(true /** first */) : rightNow; const QDateTime startDT = todo->hasStartDate() ? todo->dtStart(true /** first */) : rightNow; setDateTimes(startDT, endDT); } } -void IncidenceDateTime::save(const KCalCore::Event::Ptr &event) +void IncidenceDateTime::save(const KCalendarCore::Event::Ptr &event) { if (mUi->mWholeDayCheck->isChecked()) { // All day event event->setAllDay(true); // TODO: need to change this. QDateTime eventDTStart = currentStartDateTime(); event->setAllDay(true); event->setDtStart(eventDTStart); QDateTime eventDTEnd = currentEndDateTime(); event->setDtEnd(eventDTEnd); } else { // Timed Event event->setAllDay(false); // set date/time end event->setDtStart(currentStartDateTime()); event->setDtEnd(currentEndDateTime()); } // Free == Event::Transparent // Busy == Event::Opaque event->setTransparency(mUi->mFreeBusyCheck->isChecked() - ? KCalCore::Event::Opaque - : KCalCore::Event::Transparent); + ? KCalendarCore::Event::Opaque + : KCalendarCore::Event::Transparent); } -void IncidenceDateTime::save(const KCalCore::Todo::Ptr &todo) +void IncidenceDateTime::save(const KCalendarCore::Todo::Ptr &todo) { if (mUi->mStartCheck->isChecked()) { todo->setDtStart(currentStartDateTime()); // Set allday must be executed after setDtStart todo->setAllDay(mUi->mWholeDayCheck->isChecked()); if (currentStartDateTime() != mInitialStartDT) { // We don't offer any way to edit the current completed occurrence. // So, if the start date changes, reset the dtRecurrence todo->setDtRecurrence(currentStartDateTime()); } } else { todo->setDtStart(QDateTime()); } if (mUi->mEndCheck->isChecked()) { todo->setDtDue(currentEndDateTime(), true /** first */); // Set allday must be executed after setDtDue todo->setAllDay(mUi->mWholeDayCheck->isChecked()); } else { todo->setDtDue(QDateTime()); } } -void IncidenceDateTime::save(const KCalCore::Journal::Ptr &journal) +void IncidenceDateTime::save(const KCalendarCore::Journal::Ptr &journal) { journal->setAllDay(mUi->mWholeDayCheck->isChecked()); if (mUi->mWholeDayCheck->isChecked()) { // All day journal QDateTime journalDTStart = currentStartDateTime(); journal->setAllDay(true); journal->setDtStart(journalDTStart); } else { // Timed Journal // set date/time end journal->setDtStart(currentStartDateTime()); } } void IncidenceDateTime::setDateTimes(const QDateTime &start, const QDateTime &end) { if (start.isValid()) { mUi->mStartDateEdit->setDate(start.date()); mUi->mStartTimeEdit->setTime(start.time()); mUi->mTimeZoneComboStart->selectTimeZone(start.timeZone()); } else { QDateTime dt = QDateTime::currentDateTime(); mUi->mStartDateEdit->setDate(dt.date()); mUi->mStartTimeEdit->setTime(dt.time()); mUi->mTimeZoneComboStart->selectTimeZone(dt.timeZone()); } if (end.isValid()) { mUi->mEndDateEdit->setDate(end.date()); mUi->mEndTimeEdit->setTime(end.time()); mUi->mTimeZoneComboEnd->selectTimeZone(end.timeZone()); } else { QDateTime dt(QDate::currentDate(), QTime::currentTime().addSecs(60 * 60)); mUi->mEndDateEdit->setDate(dt.date()); mUi->mEndTimeEdit->setTime(dt.time()); mUi->mTimeZoneComboEnd->selectTimeZone(dt.timeZone()); } mCurrentStartDateTime = currentStartDateTime(); Q_EMIT startDateChanged(start.date()); Q_EMIT startTimeChanged(start.time()); Q_EMIT endDateChanged(end.date()); Q_EMIT endTimeChanged(end.time()); updateStartToolTips(); updateEndToolTips(); } void IncidenceDateTime::updateStartToolTips() { if (mUi->mStartCheck->isChecked()) { QString datetimeStr = KCalUtils::IncidenceFormatter::dateTimeToString( currentStartDateTime(), mUi->mWholeDayCheck->isChecked(), false); mUi->mStartDateEdit->setToolTip(i18n("Starts: %1", datetimeStr)); mUi->mStartTimeEdit->setToolTip(i18n("Starts: %1", datetimeStr)); } else { mUi->mStartDateEdit->setToolTip(i18n("Starting Date")); mUi->mStartTimeEdit->setToolTip(i18n("Starting Time")); } } void IncidenceDateTime::updateEndToolTips() { if (mUi->mStartCheck->isChecked()) { QString datetimeStr = KCalUtils::IncidenceFormatter::dateTimeToString( currentEndDateTime(), mUi->mWholeDayCheck->isChecked(), false); - if (mLoadedIncidence->type() == KCalCore::Incidence::TypeTodo) { + if (mLoadedIncidence->type() == KCalendarCore::Incidence::TypeTodo) { mUi->mEndDateEdit->setToolTip(i18n("Due on: %1", datetimeStr)); mUi->mEndTimeEdit->setToolTip(i18n("Due on: %1", datetimeStr)); } else { mUi->mEndDateEdit->setToolTip(i18n("Ends: %1", datetimeStr)); mUi->mEndTimeEdit->setToolTip(i18n("Ends: %1", datetimeStr)); } } else { - if (mLoadedIncidence->type() == KCalCore::Incidence::TypeTodo) { + if (mLoadedIncidence->type() == KCalendarCore::Incidence::TypeTodo) { mUi->mEndDateEdit->setToolTip(i18n("Due Date")); mUi->mEndTimeEdit->setToolTip(i18n("Due Time")); } else { mUi->mEndDateEdit->setToolTip(i18n("Ending Date")); mUi->mEndTimeEdit->setToolTip(i18n("Ending Time")); } } } void IncidenceDateTime::setTimes(const QDateTime &start, const QDateTime &end) { // like setDateTimes(), but it set only the start/end time, not the date // it is used while applying a template to an event. mUi->mStartTimeEdit->blockSignals(true); mUi->mStartTimeEdit->setTime(start.time()); mUi->mStartTimeEdit->blockSignals(false); mUi->mEndTimeEdit->setTime(end.time()); mUi->mTimeZoneComboStart->selectTimeZone(start.timeZone()); mUi->mTimeZoneComboEnd->selectTimeZone(end.timeZone()); // emitDateTimeStr(); } void IncidenceDateTime::setStartDate(const QDate &newDate) { mUi->mStartDateEdit->setDate(newDate); updateStartDate(newDate); } void IncidenceDateTime::setStartTime(const QTime &newTime) { mUi->mStartTimeEdit->setTime(newTime); updateStartTime(newTime); } bool IncidenceDateTime::startDateTimeEnabled() const { return mUi->mStartCheck->isChecked(); } bool IncidenceDateTime::endDateTimeEnabled() const { return mUi->mEndCheck->isChecked(); } bool IncidenceDateTime::isValid() const { if (startDateTimeEnabled() && !currentStartDateTime().isValid()) { mLastErrorString = i18nc("@info", "Invalid start date and time."); qCWarning(INCIDENCEEDITOR_LOG) << "Start date is invalid"; return false; } if (endDateTimeEnabled() && !currentEndDateTime().isValid()) { mLastErrorString = i18nc("@info", "Invalid end date and time."); qCWarning(INCIDENCEEDITOR_LOG) << "End date is invalid"; return false; } if (startDateTimeEnabled() && endDateTimeEnabled() && currentStartDateTime() > currentEndDateTime()) { - if (mLoadedIncidence->type() == KCalCore::Incidence::TypeEvent) { + if (mLoadedIncidence->type() == KCalendarCore::Incidence::TypeEvent) { mLastErrorString = i18nc("@info", "The event ends before it starts.\n" "Please correct dates and times."); - } else if (mLoadedIncidence->type() == KCalCore::Incidence::TypeTodo) { + } else if (mLoadedIncidence->type() == KCalendarCore::Incidence::TypeTodo) { mLastErrorString = i18nc("@info", "The to-do is due before it starts.\n" "Please correct dates and times."); - } else if (mLoadedIncidence->type() == KCalCore::Incidence::TypeJournal) { + } else if (mLoadedIncidence->type() == KCalendarCore::Incidence::TypeJournal) { return true; } qCDebug(INCIDENCEEDITOR_LOG) << mLastErrorString; return false; } else { mLastErrorString.clear(); return true; } } void IncidenceDateTime::printDebugInfo() const { qCDebug(INCIDENCEEDITOR_LOG) << "startDateTimeEnabled() : " << startDateTimeEnabled(); qCDebug(INCIDENCEEDITOR_LOG) << "endDateTimeEnabled() : " << endDateTimeEnabled(); qCDebug(INCIDENCEEDITOR_LOG) << "currentStartDateTime().isValid(): " << currentStartDateTime().isValid(); qCDebug(INCIDENCEEDITOR_LOG) << "currentEndDateTime().isValid() : " << currentEndDateTime().isValid(); qCDebug(INCIDENCEEDITOR_LOG) << "currentStartDateTime() : " << currentStartDateTime().toString(); qCDebug(INCIDENCEEDITOR_LOG) << "currentEndDateTime() : " << currentEndDateTime().toString(); qCDebug(INCIDENCEEDITOR_LOG) << "Incidence type : " << mLoadedIncidence->type(); qCDebug(INCIDENCEEDITOR_LOG) << "allday : " << mLoadedIncidence->allDay(); qCDebug(INCIDENCEEDITOR_LOG) << "mInitialStartDT : " << mInitialStartDT.toString(); qCDebug(INCIDENCEEDITOR_LOG) << "mInitialEndDT : " << mInitialEndDT.toString(); qCDebug(INCIDENCEEDITOR_LOG) << "currentStartDateTime().timeZone(): " << currentStartDateTime().timeZone().id(); qCDebug(INCIDENCEEDITOR_LOG) << "currentEndDateTime().timeZone() : " << currentEndDateTime().timeZone().id(); qCDebug(INCIDENCEEDITOR_LOG) << "mInitialStartDT.timeZone() : " << mInitialStartDT.timeZone().id(); qCDebug(INCIDENCEEDITOR_LOG) << "mInitialEndDT.timeZone() : " << mInitialEndDT.timeZone().id(); qCDebug(INCIDENCEEDITOR_LOG) << "dirty test1: " << (mLoadedIncidence->allDay() != mUi->mWholeDayCheck->isChecked()); - if (mLoadedIncidence->type() == KCalCore::Incidence::TypeEvent) { - KCalCore::Event::Ptr event = mLoadedIncidence.staticCast(); + if (mLoadedIncidence->type() == KCalendarCore::Incidence::TypeEvent) { + KCalendarCore::Event::Ptr event = mLoadedIncidence.staticCast(); qCDebug(INCIDENCEEDITOR_LOG) << "dirty test2: " << (mUi->mFreeBusyCheck->isChecked() - && event->transparency() != KCalCore::Event::Opaque); + && event->transparency() != KCalendarCore::Event::Opaque); qCDebug(INCIDENCEEDITOR_LOG) << "dirty test3: " << (!mUi->mFreeBusyCheck->isChecked() - && event->transparency() != KCalCore::Event::Transparent); + && event->transparency() != KCalendarCore::Event::Transparent); } if (mLoadedIncidence->allDay()) { qCDebug(INCIDENCEEDITOR_LOG) << "dirty test4: " << (mUi->mStartDateEdit->date() != mInitialStartDT.date() || mUi->mEndDateEdit->date() != mInitialEndDT.date()); } else { qCDebug(INCIDENCEEDITOR_LOG) << "dirty test4.1: " << (currentStartDateTime() != mInitialStartDT); qCDebug(INCIDENCEEDITOR_LOG) << "dirty test4.2: " << (currentEndDateTime() != mInitialEndDT); qCDebug(INCIDENCEEDITOR_LOG) << "dirty test4.3: " << (currentStartDateTime().timeZone() != mInitialStartDT.timeZone()); qCDebug(INCIDENCEEDITOR_LOG) << "dirty test4.4: " << (currentEndDateTime().timeZone() != mInitialEndDT.timeZone()); } } void IncidenceDateTime::setTimeZoneLabelEnabled(bool enable) { mUi->mTimeZoneLabel->setVisible(enable); } diff --git a/src/incidencedatetime.h b/src/incidencedatetime.h index c644289..f9a6e22 100644 --- a/src/incidencedatetime.h +++ b/src/incidencedatetime.h @@ -1,147 +1,147 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCEDATETIME_H #define INCIDENCEEDITOR_INCIDENCEDATETIME_H #include "incidenceeditor-ng.h" -#include -#include -#include +#include +#include +#include #include namespace Ui { class EventOrTodoDesktop; } namespace IncidenceEditorNG { class IncidenceDateTime : public IncidenceEditor { Q_OBJECT public: using IncidenceEditorNG::IncidenceEditor::save; // So we don't trigger -Woverloaded-virtual using IncidenceEditorNG::IncidenceEditor::load; // So we don't trigger -Woverloaded-virtual explicit IncidenceDateTime(Ui::EventOrTodoDesktop *ui); ~IncidenceDateTime() override; - void load(const KCalCore::Incidence::Ptr &incidence) override; - void save(const KCalCore::Incidence::Ptr &incidence) override; + void load(const KCalendarCore::Incidence::Ptr &incidence) override; + void save(const KCalendarCore::Incidence::Ptr &incidence) override; Q_REQUIRED_RESULT bool isDirty() const override; /** * Sets the active date for the editing session. This defaults to the current * date. It should be set before loading a non-empty (i.e. existing * incidence). */ void setActiveDate(const QDate &activeDate); Q_REQUIRED_RESULT QDate startDate() const; /// Returns the current start date. Q_REQUIRED_RESULT QTime startTime() const; /// Returns the current start time. Q_REQUIRED_RESULT QDate endDate() const; /// Returns the current end date. Q_REQUIRED_RESULT QTime endTime() const; /// Returns the current endtime. /// Created from the values in the widgets Q_REQUIRED_RESULT QDateTime currentStartDateTime() const; Q_REQUIRED_RESULT QDateTime currentEndDateTime() const; void setStartTime(const QTime &newTime); void setStartDate(const QDate &newDate); Q_REQUIRED_RESULT bool startDateTimeEnabled() const; Q_REQUIRED_RESULT bool endDateTimeEnabled() const; Q_REQUIRED_RESULT bool isValid() const override; void printDebugInfo() const override; Q_SIGNALS: // used to indicate that the widgets were activated void startDateFocus(QObject *obj); void endDateFocus(QObject *obj); void startTimeFocus(QObject *obj); void endTimeFocus(QObject *obj); // general void startDateTimeToggled(bool enabled); void startDateChanged(const QDate &newDate); void startTimeChanged(const QTime &newTime); void endDateTimeToggled(bool enabled); void endDateChanged(const QDate &newDate); void endTimeChanged(const QTime &newTime); private Q_SLOTS: /// General void setTimeZonesVisibility(bool visible); void toggleTimeZoneVisibility(); void updateStartTime(const QTime &newTime); void updateStartDate(const QDate &newDate); void updateStartSpec(); void updateStartToolTips(); void updateEndToolTips(); private Q_SLOTS: /// Todo specific void enableStartEdit(bool enable); void enableEndEdit(bool enable); void enableTimeEdits(); private: - bool isDirty(const KCalCore::Todo::Ptr &todo) const; - bool isDirty(const KCalCore::Event::Ptr &event) const; - bool isDirty(const KCalCore::Journal::Ptr &journal) const; + bool isDirty(const KCalendarCore::Todo::Ptr &todo) const; + bool isDirty(const KCalendarCore::Event::Ptr &event) const; + bool isDirty(const KCalendarCore::Journal::Ptr &journal) const; protected: bool eventFilter(QObject *obj, QEvent *event) override; private: - void load(const KCalCore::Event::Ptr &event, bool isTemplate = false, bool templateOverridesTimes = false); - void load(const KCalCore::Todo::Ptr &todo, bool isTemplate = false, bool templateOverridesTimes = false); - void load(const KCalCore::Journal::Ptr &journal, bool isTemplate = false, bool templateOverridesTimes = false); - void save(const KCalCore::Event::Ptr &event); - void save(const KCalCore::Todo::Ptr &todo); - void save(const KCalCore::Journal::Ptr &journal); + void load(const KCalendarCore::Event::Ptr &event, bool isTemplate = false, bool templateOverridesTimes = false); + void load(const KCalendarCore::Todo::Ptr &todo, bool isTemplate = false, bool templateOverridesTimes = false); + void load(const KCalendarCore::Journal::Ptr &journal, bool isTemplate = false, bool templateOverridesTimes = false); + void save(const KCalendarCore::Event::Ptr &event); + void save(const KCalendarCore::Todo::Ptr &todo); + void save(const KCalendarCore::Journal::Ptr &journal); void setDateTimes(const QDateTime &start, const QDateTime &end); void setTimes(const QDateTime &start, const QDateTime &end); void setTimeZoneLabelEnabled(bool enable); bool timeZonesAreLocal(const QDateTime &start, const QDateTime &end); private: Ui::EventOrTodoDesktop *mUi = nullptr; QDate mActiveDate; /** * These might differ from mLoadedIncidence->(dtStart|dtDue) as these take * in account recurrence if needed. The values are calculated once on load(). * and don't change afterwards. */ QDateTime mInitialStartDT; QDateTime mInitialEndDT; /** * We need to store the current start date/time to be able to update the end * time appropriate when the start time changes. */ QDateTime mCurrentStartDateTime; /// Remembers state when switching between takes whole day and timed event/to-do. bool mTimezoneCombosWereVisibile; }; } #endif diff --git a/src/incidencedefaults.cpp b/src/incidencedefaults.cpp index 887cab3..e9b9569 100644 --- a/src/incidencedefaults.cpp +++ b/src/incidencedefaults.cpp @@ -1,433 +1,433 @@ /* Copyright (C) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "incidencedefaults.h" #include "alarmpresets.h" #include "incidenceeditor_debug.h" #include #include //krazy:exclude=camelcase this is a generated file #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include #include #include #include using namespace CalendarSupport; using namespace IncidenceEditorNG; -using namespace KCalCore; +using namespace KCalendarCore; namespace IncidenceEditorNG { enum { UNSPECIFED_PRIORITY = 0 }; class IncidenceDefaultsPrivate { public: /// Members - KCalCore::Attachment::List mAttachments; - QVector mAttendees; + KCalendarCore::Attachment::List mAttachments; + QVector mAttendees; QStringList mEmails; QString mGroupWareDomain; - KCalCore::Incidence::Ptr mRelatedIncidence; + KCalendarCore::Incidence::Ptr mRelatedIncidence; QDateTime mStartDt; QDateTime mEndDt; bool mCleanupTemporaryFiles; /// Methods - KCalCore::Person organizerAsPerson() const; - KCalCore::Attendee organizerAsAttendee(const KCalCore::Person &organizer) const; + KCalendarCore::Person organizerAsPerson() const; + KCalendarCore::Attendee organizerAsAttendee(const KCalendarCore::Person &organizer) const; - void todoDefaults(const KCalCore::Todo::Ptr &todo) const; - void eventDefaults(const KCalCore::Event::Ptr &event) const; - void journalDefaults(const KCalCore::Journal::Ptr &journal) const; + void todoDefaults(const KCalendarCore::Todo::Ptr &todo) const; + void eventDefaults(const KCalendarCore::Event::Ptr &event) const; + void journalDefaults(const KCalendarCore::Journal::Ptr &journal) const; }; } -KCalCore::Person IncidenceDefaultsPrivate::organizerAsPerson() const +KCalendarCore::Person IncidenceDefaultsPrivate::organizerAsPerson() const { const QString invalidEmail = IncidenceDefaults::invalidEmailAddress(); - KCalCore::Person organizer; + KCalendarCore::Person organizer; organizer.setName(i18nc("@label", "no (valid) identities found")); organizer.setEmail(invalidEmail); if (mEmails.isEmpty()) { // Don't bother any longer, either someone forget to call setFullEmails, or // the user has no identities configured. return organizer; } if (!mGroupWareDomain.isEmpty()) { // Check if we have an identity with an email that ends with the groupware // domain. for (const QString &fullEmail : qAsConst(mEmails)) { QString name; QString email; const bool success = KEmailAddress::extractEmailAddressAndName(fullEmail, email, name); if (success && email.endsWith(mGroupWareDomain)) { organizer.setName(name); organizer.setEmail(email); break; } } } if (organizer.email() == invalidEmail) { // Either, no groupware was used, or we didn't find a groupware email address. // Now try to for (const QString &fullEmail : qAsConst(mEmails)) { QString name; QString email; const bool success = KEmailAddress::extractEmailAddressAndName(fullEmail, email, name); if (success) { organizer.setName(name); organizer.setEmail(email); break; } } } return organizer; } -KCalCore::Attendee IncidenceDefaultsPrivate::organizerAsAttendee( - const KCalCore::Person &organizer) const +KCalendarCore::Attendee IncidenceDefaultsPrivate::organizerAsAttendee( + const KCalendarCore::Person &organizer) const { - KCalCore::Attendee organizerAsAttendee; + KCalendarCore::Attendee organizerAsAttendee; // Really, the appropriate values (even the fall back values) should come from // organizer. (See organizerAsPerson for more details). organizerAsAttendee.setName(organizer.name()); organizerAsAttendee.setEmail(organizer.email()); // NOTE: Don't set the status to None, this value is not supported by the attendee // editor atm. - organizerAsAttendee.setStatus(KCalCore::Attendee::Accepted); - organizerAsAttendee.setRole(KCalCore::Attendee::ReqParticipant); + organizerAsAttendee.setStatus(KCalendarCore::Attendee::Accepted); + organizerAsAttendee.setRole(KCalendarCore::Attendee::ReqParticipant); return organizerAsAttendee; } -void IncidenceDefaultsPrivate::eventDefaults(const KCalCore::Event::Ptr &event) const +void IncidenceDefaultsPrivate::eventDefaults(const KCalendarCore::Event::Ptr &event) const { QDateTime startDT; if (mStartDt.isValid()) { startDT = mStartDt; } else { startDT = QDateTime::currentDateTime(); if (KCalPrefs::instance()->startTime().isValid()) { startDT.setTime(KCalPrefs::instance()->startTime().time()); } } const QTime defaultDurationTime = KCalPrefs::instance()->defaultDuration().time(); const int defaultDuration = (defaultDurationTime.hour() * 3600) +(defaultDurationTime.minute() * 60); const QDateTime endDT = mEndDt.isValid() ? mEndDt : startDT.addSecs(defaultDuration); event->setDtStart(startDT); event->setDtEnd(endDT); - event->setTransparency(KCalCore::Event::Opaque); + event->setTransparency(KCalendarCore::Event::Opaque); if (KCalPrefs::instance()->defaultEventReminders()) { event->addAlarm(AlarmPresets::defaultAlarm(AlarmPresets::BeforeStart)); } } -void IncidenceDefaultsPrivate::journalDefaults(const KCalCore::Journal::Ptr &journal) const +void IncidenceDefaultsPrivate::journalDefaults(const KCalendarCore::Journal::Ptr &journal) const { const QDateTime startDT = mStartDt.isValid() ? mStartDt : QDateTime::currentDateTime(); journal->setDtStart(startDT); journal->setAllDay(true); } -void IncidenceDefaultsPrivate::todoDefaults(const KCalCore::Todo::Ptr &todo) const +void IncidenceDefaultsPrivate::todoDefaults(const KCalendarCore::Todo::Ptr &todo) const { - KCalCore::Todo::Ptr relatedTodo = mRelatedIncidence.dynamicCast(); + KCalendarCore::Todo::Ptr relatedTodo = mRelatedIncidence.dynamicCast(); if (relatedTodo) { todo->setCategories(relatedTodo->categories()); } if (mEndDt.isValid()) { todo->setDtDue(mEndDt, true /** first */); } else if (relatedTodo && relatedTodo->hasDueDate()) { todo->setDtDue(relatedTodo->dtDue(true), true /** first */); todo->setAllDay(relatedTodo->allDay()); } else if (relatedTodo) { todo->setDtDue(QDateTime()); } else { todo->setDtDue(QDateTime::currentDateTime().addDays(1), true /** first */); } if (mStartDt.isValid()) { todo->setDtStart(mStartDt); } else if (relatedTodo && !relatedTodo->hasStartDate()) { todo->setDtStart(QDateTime()); } else if (relatedTodo && relatedTodo->hasStartDate() && relatedTodo->dtStart() <= todo->dtDue()) { todo->setDtStart(relatedTodo->dtStart()); todo->setAllDay(relatedTodo->allDay()); } else if (!mEndDt.isValid() || (QDateTime::currentDateTime() < mEndDt)) { todo->setDtStart(QDateTime::currentDateTime()); } else { todo->setDtStart(mEndDt.addDays(-1)); } todo->setCompleted(false); todo->setPercentComplete(0); // I had a bunch of to-dos and couldn't distinguish between those that had priority '5' // because I wanted, and those that had priority '5' because it was set by default // and I forgot to unset it. // So don't be smart and try to guess a good default priority for the user, just use unspecified. todo->setPriority(UNSPECIFED_PRIORITY); if (KCalPrefs::instance()->defaultTodoReminders()) { todo->addAlarm(AlarmPresets::defaultAlarm(AlarmPresets::BeforeEnd)); } } /// IncidenceDefaults IncidenceDefaults::IncidenceDefaults(bool cleanupAttachmentTemporaryFiles) : d_ptr(new IncidenceDefaultsPrivate) { d_ptr->mCleanupTemporaryFiles = cleanupAttachmentTemporaryFiles; } IncidenceDefaults::IncidenceDefaults(const IncidenceDefaults &other) : d_ptr(new IncidenceDefaultsPrivate) { *d_ptr = *other.d_ptr; } IncidenceDefaults::~IncidenceDefaults() { delete d_ptr; } IncidenceDefaults &IncidenceDefaults::operator=(const IncidenceDefaults &other) { if (&other != this) { *d_ptr = *other.d_ptr; } return *this; } void IncidenceDefaults::setAttachments(const QStringList &attachments, const QStringList &attachmentMimetypes, const QStringList &attachmentLabels, bool inlineAttachment) { Q_D(IncidenceDefaults); d->mAttachments.clear(); QStringList::ConstIterator it; int i = 0; for (it = attachments.constBegin(); it != attachments.constEnd(); ++it, ++i) { if (!(*it).isEmpty()) { QString mimeType; if (attachmentMimetypes.count() > i) { mimeType = attachmentMimetypes[ i ]; } - KCalCore::Attachment attachment; + KCalendarCore::Attachment attachment; if (inlineAttachment) { auto job = KIO::storedGet(QUrl::fromUserInput(*it)); if (job->exec()) { const QByteArray data = job->data(); - attachment = KCalCore::Attachment(data.toBase64(), mimeType); + attachment = KCalendarCore::Attachment(data.toBase64(), mimeType); if (i < attachmentLabels.count()) { attachment.setLabel(attachmentLabels[ i ]); } } else { qCCritical(INCIDENCEEDITOR_LOG) << "Error downloading uri " << *it << job->errorString(); } if (d_ptr->mCleanupTemporaryFiles) { QFile file(*it); if (!file.remove()) { qCCritical(INCIDENCEEDITOR_LOG) << "Uname to remove file " << *it; } } } else { - attachment = KCalCore::Attachment(*it, mimeType); + attachment = KCalendarCore::Attachment(*it, mimeType); if (i < attachmentLabels.count()) { attachment.setLabel(attachmentLabels[ i ]); } } if (!attachment.isEmpty()) { if (attachment.label().isEmpty()) { if (attachment.isUri()) { attachment.setLabel(attachment.uri()); } else { attachment.setLabel( i18nc("@label attachment contains binary data", "[Binary data]")); } } d->mAttachments << attachment; attachment.setShowInline(inlineAttachment); } } } } void IncidenceDefaults::setAttendees(const QStringList &attendees) { Q_D(IncidenceDefaults); d->mAttendees.clear(); QStringList::ConstIterator it; for (it = attendees.begin(); it != attendees.end(); ++it) { QString name, email; KContacts::Addressee::parseEmailAddress(*it, name, email); - d->mAttendees << KCalCore::Attendee(name, email, true, KCalCore::Attendee::NeedsAction); + d->mAttendees << KCalendarCore::Attendee(name, email, true, KCalendarCore::Attendee::NeedsAction); } } void IncidenceDefaults::setFullEmails(const QStringList &fullEmails) { Q_D(IncidenceDefaults); d->mEmails = fullEmails; } void IncidenceDefaults::setGroupWareDomain(const QString &domain) { Q_D(IncidenceDefaults); d->mGroupWareDomain = domain; } -void IncidenceDefaults::setRelatedIncidence(const KCalCore::Incidence::Ptr &incidence) +void IncidenceDefaults::setRelatedIncidence(const KCalendarCore::Incidence::Ptr &incidence) { Q_D(IncidenceDefaults); d->mRelatedIncidence = incidence; } void IncidenceDefaults::setStartDateTime(const QDateTime &startDT) { Q_D(IncidenceDefaults); d->mStartDt = startDT; } void IncidenceDefaults::setEndDateTime(const QDateTime &endDT) { Q_D(IncidenceDefaults); d->mEndDt = endDT; } -void IncidenceDefaults::setDefaults(const KCalCore::Incidence::Ptr &incidence) const +void IncidenceDefaults::setDefaults(const KCalendarCore::Incidence::Ptr &incidence) const { Q_D(const IncidenceDefaults); // First some general defaults incidence->setSummary(QString(), false); incidence->setLocation(QString(), false); incidence->setCategories(QStringList()); - incidence->setSecrecy(KCalCore::Incidence::SecrecyPublic); - incidence->setStatus(KCalCore::Incidence::StatusNone); + incidence->setSecrecy(KCalendarCore::Incidence::SecrecyPublic); + incidence->setStatus(KCalendarCore::Incidence::StatusNone); incidence->setAllDay(false); incidence->setCustomStatus(QString()); incidence->setResources(QStringList()); incidence->setPriority(0); if (d->mRelatedIncidence) { incidence->setRelatedTo(d->mRelatedIncidence->uid()); } incidence->clearAlarms(); incidence->clearAttachments(); incidence->clearAttendees(); incidence->clearComments(); incidence->clearContacts(); incidence->clearRecurrence(); - const KCalCore::Person organizerAsPerson = d->organizerAsPerson(); + const KCalendarCore::Person organizerAsPerson = d->organizerAsPerson(); #ifdef KDEPIM_ENTERPRISE_BUILD incidence->addAttendee(d->organizerAsAttendee(organizerAsPerson)); #endif - for (const KCalCore::Attendee &attendee : qAsConst(d->mAttendees)) { + for (const KCalendarCore::Attendee &attendee : qAsConst(d->mAttendees)) { incidence->addAttendee(attendee); } // Ical standard: No attendees -> must not have an organizer! if (incidence->attendeeCount()) { incidence->setOrganizer(organizerAsPerson); } - for (const KCalCore::Attachment &attachment : qAsConst(d->mAttachments)) { + for (const KCalendarCore::Attachment &attachment : qAsConst(d->mAttachments)) { incidence->addAttachment(attachment); } switch (incidence->type()) { - case KCalCore::Incidence::TypeEvent: - d->eventDefaults(incidence.dynamicCast()); + case KCalendarCore::Incidence::TypeEvent: + d->eventDefaults(incidence.dynamicCast()); break; - case KCalCore::Incidence::TypeTodo: - d->todoDefaults(incidence.dynamicCast()); + case KCalendarCore::Incidence::TypeTodo: + d->todoDefaults(incidence.dynamicCast()); break; - case KCalCore::Incidence::TypeJournal: - d->journalDefaults(incidence.dynamicCast()); + case KCalendarCore::Incidence::TypeJournal: + d->journalDefaults(incidence.dynamicCast()); break; default: qCDebug(INCIDENCEEDITOR_LOG) << "Unsupported incidence type, keeping current values. Type: " << static_cast(incidence->type()); } } /** static */ IncidenceDefaults IncidenceDefaults::minimalIncidenceDefaults(bool cleanupAttachmentTempFiles) { IncidenceDefaults defaults(cleanupAttachmentTempFiles); // Set the full emails manually here, to avoid that we get dependencies on // KCalPrefs all over the place. defaults.setFullEmails(CalendarSupport::KCalPrefs::instance()->fullEmails()); // NOTE: At some point this should be generalized. That is, we now use the // freebusy url as a hack, but this assumes that the user has only one // groupware account. Which doesn't have to be the case necessarily. // This method should somehow depend on the calendar selected to which // the incidence is added. if (CalendarSupport::KCalPrefs::instance()->useGroupwareCommunication()) { defaults.setGroupWareDomain( QUrl(Akonadi::CalendarSettings::self()->freeBusyRetrieveUrl()).host()); } return defaults; } /** static */ QString IncidenceDefaults::invalidEmailAddress() { static const QString invalidEmail(i18nc("@label invalid email address marker", "invalid@email.address")); return invalidEmail; } diff --git a/src/incidencedefaults.h b/src/incidencedefaults.h index f9c4481..f2e72d7 100644 --- a/src/incidencedefaults.h +++ b/src/incidencedefaults.h @@ -1,117 +1,117 @@ /* Copyright (C) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCEDEFAULTS_H #define INCIDENCEEDITOR_INCIDENCEDEFAULTS_H #include "incidenceeditor_export.h" -#include +#include namespace IncidenceEditorNG { class IncidenceDefaultsPrivate; class INCIDENCEEDITOR_EXPORT IncidenceDefaults { public: explicit IncidenceDefaults(bool cleanupAttachmentTEmporaryFiles = false); IncidenceDefaults(const IncidenceDefaults &other); ~IncidenceDefaults(); IncidenceDefaults &operator=(const IncidenceDefaults &other); /** Sets the attachments that are added by default to incidences. */ void setAttachments(const QStringList &attachments, const QStringList &attachmentMimetypes = QStringList(), const QStringList &attachmentLabels = QStringList(), bool inlineAttachment = false); /** Sets the attendees that are added by default to incidences. @param attendees Expected to be of the form "name name " */ void setAttendees(const QStringList &attendees); /** Sets the list of identities to be used for the user. The items in the list are expected to be of the form: "name [name] ". If the list is empty, it is assumed that no valid identities are configured. @param fullEmails The list of name email pairs that the user has configured as identities. */ void setFullEmails(const QStringList &fullEmails); /** This is used to do a smarter guess about which identity to use for the organizer. If the groupware server is not set, the first avaialble identity will be used. @param domain The gropuware server domain name without any protocol prefixes (e.g. demo.kolab.org). */ void setGroupWareDomain(const QString &domain); /** Sets the incidence related to the incidence for which to set the defaults. For example the parent todo of a new sub todo. */ - void setRelatedIncidence(const KCalCore::Incidence::Ptr &incidence); + void setRelatedIncidence(const KCalendarCore::Incidence::Ptr &incidence); /** Set the start date/time to use for passed incidences. This defaults to the current start date/time. The main purpose of this method is supporting defaults for new incidences that where created with a given time slot. @param startDT The start date time to set on the incidence. */ void setStartDateTime(const QDateTime &startDT); /** Set the end date/time to use for passed incidences. This defaults to the current start date/time. The main purpose of this method is supporting defaults for new incidences that where created with a given time slot. @param endDT The start date time to set on the incidence. */ void setEndDateTime(const QDateTime &endDT); /** Sets the default values for @param incidence. This method is merely meant for new incidences. However, it will clear out all fields and set them to default values. @param incidence The incidence that will get default values for all of its field. */ - void setDefaults(const KCalCore::Incidence::Ptr &incidence) const; + void setDefaults(const KCalendarCore::Incidence::Ptr &incidence) const; /** * Returns minimal incidence defaults: e-mails and groupware domain. * * TODO: See if this is always called when using IncidenceDefaults. * If yes, this should be done inside ctor. */ Q_REQUIRED_RESULT static IncidenceDefaults minimalIncidenceDefaults(bool cleanupAttachmentTempFiles = false); // Returns the e-mail address used for the organizer when we can't find anything useful // This is something like "invalid@invalid" Q_REQUIRED_RESULT static QString invalidEmailAddress(); private: IncidenceDefaultsPrivate *const d_ptr; Q_DECLARE_PRIVATE(IncidenceDefaults) }; } #endif diff --git a/src/incidencedescription.cpp b/src/incidencedescription.cpp index 90cd195..b21257b 100644 --- a/src/incidencedescription.cpp +++ b/src/incidencedescription.cpp @@ -1,230 +1,230 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidencedescription.h" #include "ui_dialogdesktop.h" #include #include "incidenceeditor_debug.h" #include #include #include using namespace IncidenceEditorNG; namespace IncidenceEditorNG { class IncidenceDescriptionPrivate { public: IncidenceDescriptionPrivate() : mRichTextEnabled(false) { } QString mRealOriginalDescriptionEditContents; bool mRichTextEnabled; }; } IncidenceDescription::IncidenceDescription(Ui::EventOrTodoDesktop *ui) : IncidenceEditor(nullptr) , mUi(ui) , d(new IncidenceDescriptionPrivate()) { setObjectName(QStringLiteral("IncidenceDescription")); mUi->mRichTextLabel->setContextMenuPolicy(Qt::NoContextMenu); setupToolBar(); connect(mUi->mRichTextLabel, &QLabel::linkActivated, this, &IncidenceDescription::toggleRichTextDescription); connect( mUi->mDescriptionEdit->richTextComposer(), &KPIMTextEdit::RichTextComposer::textChanged, this, &IncidenceDescription::checkDirtyStatus); } IncidenceDescription::~IncidenceDescription() { delete d; } -void IncidenceDescription::load(const KCalCore::Incidence::Ptr &incidence) +void IncidenceDescription::load(const KCalendarCore::Incidence::Ptr &incidence) { mLoadedIncidence = incidence; d->mRealOriginalDescriptionEditContents.clear(); if (incidence) { enableRichTextDescription(incidence->descriptionIsRich()); if (incidence->descriptionIsRich()) { mUi->mDescriptionEdit->richTextComposer()->setHtml(incidence->richDescription()); d->mRealOriginalDescriptionEditContents = mUi->mDescriptionEdit->richTextComposer()->toHtml(); } else { mUi->mDescriptionEdit->richTextComposer()->setPlainText(incidence->description()); d->mRealOriginalDescriptionEditContents = mUi->mDescriptionEdit->richTextComposer()->toPlainText(); } } else { enableRichTextDescription(false); mUi->mDescriptionEdit->richTextComposer()->clear(); } mWasDirty = false; } -void IncidenceDescription::save(const KCalCore::Incidence::Ptr &incidence) +void IncidenceDescription::save(const KCalendarCore::Incidence::Ptr &incidence) { if (d->mRichTextEnabled) { incidence->setDescription(mUi->mDescriptionEdit->richTextComposer()->toHtml(), true); } else { incidence->setDescription(mUi->mDescriptionEdit->richTextComposer()->toPlainText(), false); } } bool IncidenceDescription::isDirty() const { /* Sometimes, what you put in a KRichTextWidget isn't the same as what you get out. Line terminators (cr,lf) for example can be converted. So, to see if the user changed something, we can't compare the original incidence with the new editor content. Instead we compare the new editor content, with the original editor content, this way any transformation regarding non-printable chars will be irrelevant. */ if (d->mRichTextEnabled) { return !mLoadedIncidence->descriptionIsRich() || d->mRealOriginalDescriptionEditContents != mUi->mDescriptionEdit->richTextComposer()->toHtml(); } else { return mLoadedIncidence->descriptionIsRich() || d->mRealOriginalDescriptionEditContents != mUi->mDescriptionEdit->richTextComposer()->toPlainText(); } } void IncidenceDescription::enableRichTextDescription(bool enable) { d->mRichTextEnabled = enable; QString rt(i18nc("@action Enable or disable rich text editing", "Enable rich text")); QString placeholder(QStringLiteral("%1 >>")); if (enable) { rt = i18nc("@action Enable or disable rich text editing", "Disable rich text"); placeholder = QStringLiteral("<< %1"); mUi->mDescriptionEdit->richTextComposer()->activateRichText(); d->mRealOriginalDescriptionEditContents = mUi->mDescriptionEdit->richTextComposer()->toHtml(); } else { mUi->mDescriptionEdit->richTextComposer()->switchToPlainText(); d->mRealOriginalDescriptionEditContents = mUi->mDescriptionEdit->richTextComposer()->toPlainText(); } placeholder = placeholder.arg(rt); mUi->mRichTextLabel->setText(placeholder); mUi->mDescriptionEdit->richTextComposer()->setEnableActions(enable); mUi->mEditToolBarPlaceHolder->setVisible(enable); checkDirtyStatus(); } void IncidenceDescription::toggleRichTextDescription() { enableRichTextDescription(!d->mRichTextEnabled); } void IncidenceDescription::setupToolBar() { #ifndef QT_NO_TOOLBAR KActionCollection *collection = new KActionCollection(this); mUi->mDescriptionEdit->richTextComposer()->createActions(collection); KToolBar *mEditToolBar = new KToolBar(mUi->mEditToolBarPlaceHolder); mEditToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); mEditToolBar->addAction(collection->action(QStringLiteral("format_text_bold"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_text_italic"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_text_underline"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_text_strikeout"))); mEditToolBar->addSeparator(); mEditToolBar->addAction(collection->action(QStringLiteral("format_font_family"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_font_size"))); mEditToolBar->addSeparator(); mEditToolBar->addAction(collection->action(QStringLiteral("format_text_foreground_color"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_text_background_color"))); mEditToolBar->addSeparator(); mEditToolBar->addAction(collection->action(QStringLiteral("format_list_style"))); mEditToolBar->addSeparator(); mEditToolBar->addAction(collection->action(QStringLiteral("format_align_left"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_align_center"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_align_right"))); mEditToolBar->addAction(collection->action(QStringLiteral("format_align_justify"))); mEditToolBar->addSeparator(); mEditToolBar->addAction(collection->action(QStringLiteral("format_painter"))); mUi->mDescriptionEdit->richTextComposer()->setEnableActions(false); QGridLayout *layout = new QGridLayout(mUi->mEditToolBarPlaceHolder); layout->addWidget(mEditToolBar); #endif // By default we don't show the rich text toolbar. mUi->mEditToolBarPlaceHolder->setVisible(false); d->mRichTextEnabled = false; } void IncidenceDescription::printDebugInfo() const { // We're going to crash qCDebug(INCIDENCEEDITOR_LOG) << "RichText enabled " << d->mRichTextEnabled; if (mLoadedIncidence) { qCDebug(INCIDENCEEDITOR_LOG) << "Incidence description is rich " << mLoadedIncidence->descriptionIsRich(); if (mLoadedIncidence->descriptionIsRich()) { qCDebug(INCIDENCEEDITOR_LOG) << "desc is rich, and it is " << mLoadedIncidence->richDescription() << "; " << "widget has " << mUi->mDescriptionEdit->richTextComposer()->toHtml() << "; " << "expr mLoadedIncidence->richDescription() != mUi->mDescriptionEdit->toHtml() is " << (mLoadedIncidence->richDescription() != mUi->mDescriptionEdit->richTextComposer()->toHtml()); } else { qCDebug(INCIDENCEEDITOR_LOG) << "desc is not rich, and it is " << mLoadedIncidence->description() << "; " << "widget has " << mUi->mDescriptionEdit->richTextComposer()->toPlainText() << "; " << "expr mLoadedIncidence->description() != mUi->mDescriptionEdit->toPlainText() is " << (mLoadedIncidence->description() != mUi->mDescriptionEdit->richTextComposer()->toPlainText()); } } else { qCDebug(INCIDENCEEDITOR_LOG) << "Incidence is invalid"; } } diff --git a/src/incidencedescription.h b/src/incidencedescription.h index 7a698a3..53c8525 100644 --- a/src/incidencedescription.h +++ b/src/incidencedescription.h @@ -1,71 +1,71 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCEDESCRIPTION_H #define INCIDENCEEDITOR_INCIDENCEDESCRIPTION_H #include "incidenceeditor-ng.h" namespace Ui { class EventOrTodoDesktop; } namespace IncidenceEditorNG { class IncidenceDescriptionPrivate; /** * The IncidenceDescriptionEditor keeps track of the following Incidence parts: * - description */ class IncidenceDescription : public IncidenceEditor { Q_OBJECT public: using IncidenceEditorNG::IncidenceEditor::save; // So we don't trigger -Woverloaded-virtual using IncidenceEditorNG::IncidenceEditor::load; // So we don't trigger -Woverloaded-virtual explicit IncidenceDescription(Ui::EventOrTodoDesktop *ui); ~IncidenceDescription() override; - void load(const KCalCore::Incidence::Ptr &incidence) override; - void save(const KCalCore::Incidence::Ptr &incidence) override; + void load(const KCalendarCore::Incidence::Ptr &incidence) override; + void save(const KCalendarCore::Incidence::Ptr &incidence) override; Q_REQUIRED_RESULT bool isDirty() const override; // For debugging purposes Q_REQUIRED_RESULT bool richTextEnabled() const; void printDebugInfo() const override; private: void toggleRichTextDescription(); void enableRichTextDescription(bool enable); void setupToolBar(); private: Ui::EventOrTodoDesktop *mUi = nullptr; //@cond PRIVATE Q_DECLARE_PRIVATE(IncidenceDescription) IncidenceDescriptionPrivate *const d; //@endcond }; } #endif diff --git a/src/incidencedialog.cpp b/src/incidencedialog.cpp index 78ff520..347ec64 100644 --- a/src/incidencedialog.cpp +++ b/src/incidencedialog.cpp @@ -1,869 +1,869 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Copyright (C) 2012 Allen Winter This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidencedialog.h" #include "incidenceeditor_debug.h" #include "combinedincidenceeditor.h" #include "editorconfig.h" #include "incidencealarm.h" #include "incidenceattachment.h" #include "incidenceattendee.h" #include "incidencecategories.h" #include "incidencecompletionpriority.h" #include "incidencedatetime.h" #include "incidencedescription.h" #include "incidencerecurrence.h" #include "incidenceresource.h" #include "incidencesecrecy.h" #include "incidencewhatwhere.h" #include "templatemanagementdialog.h" #include "ui_dialogdesktop.h" #include #include #include #include #include #include -#include -#include +#include +#include #include #include #include #include #include #include #include #include using namespace IncidenceEditorNG; namespace IncidenceEditorNG { enum Tabs { GeneralTab = 0, AttendeesTab, ResourcesTab, AlarmsTab, RecurrenceTab, AttachmentsTab }; class IncidenceDialogPrivate : public ItemEditorUi { IncidenceDialog *q_ptr; Q_DECLARE_PUBLIC(IncidenceDialog) public: Ui::EventOrTodoDesktop *mUi = nullptr; Akonadi::CollectionComboBox *mCalSelector = nullptr; bool mCloseOnSave = false; EditorItemManager *mItemManager = nullptr; CombinedIncidenceEditor *mEditor = nullptr; IncidenceDateTime *mIeDateTime = nullptr; IncidenceAttendee *mIeAttendee = nullptr; IncidenceRecurrence *mIeRecurrence = nullptr; IncidenceResource *mIeResource = nullptr; bool mInitiallyDirty = false; Akonadi::Item mItem; QString typeToString(const int type) const; public: IncidenceDialogPrivate(Akonadi::IncidenceChanger *changer, IncidenceDialog *qq); ~IncidenceDialogPrivate(); /// General methods void handleAlarmCountChange(int newCount); void handleRecurrenceChange(IncidenceEditorNG::RecurrenceType type); void loadTemplate(const QString &templateName); void manageTemplates(); void saveTemplate(const QString &templateName); void storeTemplatesInConfig(const QStringList &newTemplates); void updateAttachmentCount(int newCount); void updateAttendeeCount(int newCount); void updateResourceCount(int newCount); void updateButtonStatus(bool isDirty); void showMessage(const QString &text, KMessageWidget::MessageType type); void slotInvalidCollection(); /// ItemEditorUi methods bool containsPayloadIdentifiers(const QSet &partIdentifiers) const override; void handleItemSaveFinish(EditorItemManager::SaveAction); void handleItemSaveFail(EditorItemManager::SaveAction, const QString &errorMessage); bool hasSupportedPayload(const Akonadi::Item &item) const override; bool isDirty() const override; bool isValid() const override; void load(const Akonadi::Item &item) override; Akonadi::Item save(const Akonadi::Item &item) override; Akonadi::Collection selectedCollection() const override; void reject(RejectReason reason, const QString &errorMessage = QString()) override; }; } IncidenceDialogPrivate::IncidenceDialogPrivate(Akonadi::IncidenceChanger *changer, IncidenceDialog *qq) : q_ptr(qq) , mUi(new Ui::EventOrTodoDesktop) , mCalSelector(new Akonadi::CollectionComboBox) , mCloseOnSave(false) , mItemManager(new EditorItemManager(this, changer)) , mEditor(new CombinedIncidenceEditor(qq)) , mInitiallyDirty(false) { Q_Q(IncidenceDialog); mUi->setupUi(q); mUi->mMessageWidget->hide(); QGridLayout *layout = new QGridLayout(mUi->mCalSelectorPlaceHolder); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(mCalSelector); mCalSelector->setAccessRightsFilter(Akonadi::Collection::CanCreateItem); mUi->label->setBuddy(mCalSelector); q->connect(mCalSelector, &Akonadi::CollectionComboBox::currentChanged, q, &IncidenceDialog::handleSelectedCollectionChange); // Now instantiate the logic of the dialog. These editors update the ui, validate // fields and load/store incidences in the ui. IncidenceWhatWhere *ieGeneral = new IncidenceWhatWhere(mUi); mEditor->combine(ieGeneral); IncidenceCategories *ieCategories = new IncidenceCategories(mUi); mEditor->combine(ieCategories); mIeDateTime = new IncidenceDateTime(mUi); mEditor->combine(mIeDateTime); IncidenceCompletionPriority *ieCompletionPriority = new IncidenceCompletionPriority(mUi); mEditor->combine(ieCompletionPriority); IncidenceDescription *ieDescription = new IncidenceDescription(mUi); mEditor->combine(ieDescription); IncidenceAlarm *ieAlarm = new IncidenceAlarm(mIeDateTime, mUi); mEditor->combine(ieAlarm); IncidenceAttachment *ieAttachments = new IncidenceAttachment(mUi); mEditor->combine(ieAttachments); mIeRecurrence = new IncidenceRecurrence(mIeDateTime, mUi); mEditor->combine(mIeRecurrence); IncidenceSecrecy *ieSecrecy = new IncidenceSecrecy(mUi); mEditor->combine(ieSecrecy); mIeAttendee = new IncidenceAttendee(qq, mIeDateTime, mUi); mIeAttendee->setParent(qq); mEditor->combine(mIeAttendee); mIeResource = new IncidenceResource(mIeAttendee, mIeDateTime, mUi); mEditor->combine(mIeResource); q->connect(mEditor, SIGNAL(showMessage(QString,KMessageWidget::MessageType)), SLOT(showMessage(QString,KMessageWidget::MessageType))); q->connect(mEditor, SIGNAL(dirtyStatusChanged(bool)), SLOT(updateButtonStatus(bool))); q->connect(mItemManager, SIGNAL(itemSaveFinished(IncidenceEditorNG::EditorItemManager::SaveAction)), SLOT(handleItemSaveFinish(IncidenceEditorNG::EditorItemManager::SaveAction))); q->connect(mItemManager, SIGNAL(itemSaveFailed(IncidenceEditorNG::EditorItemManager::SaveAction,QString)), SLOT(handleItemSaveFail(IncidenceEditorNG::EditorItemManager::SaveAction,QString))); q->connect(ieAlarm, SIGNAL(alarmCountChanged(int)), SLOT(handleAlarmCountChange(int))); q->connect(mIeRecurrence, SIGNAL(recurrenceChanged(IncidenceEditorNG::RecurrenceType)), SLOT(handleRecurrenceChange(IncidenceEditorNG::RecurrenceType))); q->connect(ieAttachments, SIGNAL(attachmentCountChanged(int)), SLOT(updateAttachmentCount(int))); q->connect(mIeAttendee, SIGNAL(attendeeCountChanged(int)), SLOT(updateAttendeeCount(int))); q->connect(mIeResource, SIGNAL(resourceCountChanged(int)), SLOT(updateResourceCount(int))); } IncidenceDialogPrivate::~IncidenceDialogPrivate() { delete mItemManager; delete mEditor; delete mUi; } void IncidenceDialogPrivate::slotInvalidCollection() { showMessage(i18n("Select a valid collection first."), KMessageWidget::Warning); } void IncidenceDialogPrivate::showMessage(const QString &text, KMessageWidget::MessageType type) { mUi->mMessageWidget->setText(text); mUi->mMessageWidget->setMessageType(type); mUi->mMessageWidget->show(); } void IncidenceDialogPrivate::handleAlarmCountChange(int newCount) { QString tabText; if (newCount > 0) { tabText = i18nc("@title:tab Tab to configure the reminders of an event or todo", "Reminder (%1)", newCount); } else { tabText = i18nc("@title:tab Tab to configure the reminders of an event or todo", "Reminder"); } mUi->mTabWidget->setTabText(AlarmsTab, tabText); } void IncidenceDialogPrivate::handleRecurrenceChange(IncidenceEditorNG::RecurrenceType type) { QString tabText = i18nc("@title:tab Tab to configure the recurrence of an event or todo", "Rec&urrence"); // Keep this numbers in sync with the items in mUi->mRecurrenceTypeCombo. I // tried adding an enum to IncidenceRecurrence but for whatever reason I could // Qt not play nice with namespaced enums in signal/slot connections. // Anyways, I don't expect these values to change. switch (type) { case RecurrenceTypeNone: break; case RecurrenceTypeDaily: tabText += i18nc("@title:tab Daily recurring event, capital first letter only", " (D)"); break; case RecurrenceTypeWeekly: tabText += i18nc("@title:tab Weekly recurring event, capital first letter only", " (W)"); break; case RecurrenceTypeMonthly: tabText += i18nc("@title:tab Monthly recurring event, capital first letter only", " (M)"); break; case RecurrenceTypeYearly: tabText += i18nc("@title:tab Yearly recurring event, capital first letter only", " (Y)"); break; case RecurrenceTypeException: tabText += i18nc("@title:tab Exception to a recurring event, capital first letter only", " (E)"); break; default: Q_ASSERT_X(false, "handleRecurrenceChange", "Fix your program"); } mUi->mTabWidget->setTabText(RecurrenceTab, tabText); } QString IncidenceDialogPrivate::typeToString(const int type) const { // Do not translate. switch (type) { - case KCalCore::Incidence::TypeEvent: + case KCalendarCore::Incidence::TypeEvent: return QStringLiteral("Event"); - case KCalCore::Incidence::TypeTodo: + case KCalendarCore::Incidence::TypeTodo: return QStringLiteral("Todo"); - case KCalCore::Incidence::TypeJournal: + case KCalendarCore::Incidence::TypeJournal: return QStringLiteral("Journal"); default: return QStringLiteral("Unknown"); } } void IncidenceDialogPrivate::loadTemplate(const QString &templateName) { Q_Q(IncidenceDialog); - KCalCore::MemoryCalendar::Ptr cal(new KCalCore::MemoryCalendar(QTimeZone::systemTimeZone())); + KCalendarCore::MemoryCalendar::Ptr cal(new KCalendarCore::MemoryCalendar(QTimeZone::systemTimeZone())); const QString fileName = QStandardPaths::locate( QStandardPaths::GenericDataLocation, QStringLiteral("/korganizer/templates/") +typeToString(mEditor->type()) + QLatin1Char('/') +templateName); if (fileName.isEmpty()) { KMessageBox::error( q, i18nc("@info", "Unable to find template '%1'.", templateName)); return; } - KCalCore::ICalFormat format; + KCalendarCore::ICalFormat format; if (!format.load(cal, fileName)) { KMessageBox::error( q, i18nc("@info", "Error loading template file '%1'.", fileName)); return; } - KCalCore::Incidence::List incidences = cal->incidences(); + KCalendarCore::Incidence::List incidences = cal->incidences(); if (incidences.isEmpty()) { KMessageBox::error( q, i18nc("@info", "Template does not contain a valid incidence.")); return; } mIeDateTime->setActiveDate(QDate()); - KCalCore::Incidence::Ptr newInc = KCalCore::Incidence::Ptr(incidences.first()->clone()); - newInc->setUid(KCalCore::CalFormat::createUniqueId()); + KCalendarCore::Incidence::Ptr newInc = KCalendarCore::Incidence::Ptr(incidences.first()->clone()); + newInc->setUid(KCalendarCore::CalFormat::createUniqueId()); // We add a custom property so that some fields aren't loaded, dates for example newInc->setCustomProperty(QByteArray("kdepim"), "isTemplate", QStringLiteral("true")); mEditor->load(newInc); newInc->removeCustomProperty(QByteArray(), "isTemplate"); } void IncidenceDialogPrivate::manageTemplates() { Q_Q(IncidenceDialog); QStringList &templates = IncidenceEditorNG::EditorConfig::instance()->templates(mEditor->type()); QPointer dialog( new IncidenceEditorNG::TemplateManagementDialog( q, templates, KCalUtils::Stringify::incidenceType(mEditor->type()))); q->connect(dialog, SIGNAL(loadTemplate(QString)), SLOT(loadTemplate(QString))); q->connect(dialog, SIGNAL(templatesChanged(QStringList)), SLOT(storeTemplatesInConfig(QStringList))); q->connect(dialog, SIGNAL(saveTemplate(QString)), SLOT(saveTemplate(QString))); dialog->exec(); delete dialog; } void IncidenceDialogPrivate::saveTemplate(const QString &templateName) { Q_ASSERT(!templateName.isEmpty()); - KCalCore::MemoryCalendar::Ptr cal(new KCalCore::MemoryCalendar(QTimeZone::systemTimeZone())); + KCalendarCore::MemoryCalendar::Ptr cal(new KCalendarCore::MemoryCalendar(QTimeZone::systemTimeZone())); switch (mEditor->type()) { - case KCalCore::Incidence::TypeEvent: + case KCalendarCore::Incidence::TypeEvent: { - KCalCore::Event::Ptr event(new KCalCore::Event()); + KCalendarCore::Event::Ptr event(new KCalendarCore::Event()); mEditor->save(event); - cal->addEvent(KCalCore::Event::Ptr(event->clone())); + cal->addEvent(KCalendarCore::Event::Ptr(event->clone())); break; } - case KCalCore::Incidence::TypeTodo: + case KCalendarCore::Incidence::TypeTodo: { - KCalCore::Todo::Ptr todo(new KCalCore::Todo); + KCalendarCore::Todo::Ptr todo(new KCalendarCore::Todo); mEditor->save(todo); - cal->addTodo(KCalCore::Todo::Ptr(todo->clone())); + cal->addTodo(KCalendarCore::Todo::Ptr(todo->clone())); break; } - case KCalCore::Incidence::TypeJournal: + case KCalendarCore::Incidence::TypeJournal: { - KCalCore::Journal::Ptr journal(new KCalCore::Journal); + KCalendarCore::Journal::Ptr journal(new KCalendarCore::Journal); mEditor->save(journal); - cal->addJournal(KCalCore::Journal::Ptr(journal->clone())); + cal->addJournal(KCalendarCore::Journal::Ptr(journal->clone())); break; } default: Q_ASSERT_X(false, "saveTemplate", "Fix your program"); } QString fileName = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +QStringLiteral("/korganizer/templates/") + typeToString(mEditor->type()) + QLatin1Char('/'); QDir().mkpath(fileName); fileName += templateName; - KCalCore::ICalFormat format; + KCalendarCore::ICalFormat format; format.save(cal, fileName); } void IncidenceDialogPrivate::storeTemplatesInConfig(const QStringList &templateNames) { // I find this somewhat broken. templates() returns a reference, maybe it should // be changed by adding a setTemplates method. const QStringList origTemplates = IncidenceEditorNG::EditorConfig::instance()->templates(mEditor->type()); const QString defaultPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +QStringLiteral("korganizer/templates/") +typeToString(mEditor->type()) + QLatin1Char('/'); QDir().mkpath(defaultPath); for (const QString &tmpl : origTemplates) { if (!templateNames.contains(tmpl)) { const QString fileName = defaultPath + tmpl; QFile file(fileName); if (file.exists()) { file.remove(); } } } IncidenceEditorNG::EditorConfig::instance()->templates(mEditor->type()) = templateNames; IncidenceEditorNG::EditorConfig::instance()->config()->save(); } void IncidenceDialogPrivate::updateAttachmentCount(int newCount) { if (newCount > 0) { mUi->mTabWidget->setTabText( AttachmentsTab, i18nc("@title:tab Tab to modify attachments of an event or todo", "Attac&hments (%1)", newCount)); } else { mUi->mTabWidget->setTabText( AttachmentsTab, i18nc("@title:tab Tab to modify attachments of an event or todo", "Attac&hments")); } } void IncidenceDialogPrivate::updateAttendeeCount(int newCount) { if (newCount > 0) { mUi->mTabWidget->setTabText( AttendeesTab, i18nc("@title:tab Tab to modify attendees of an event or todo", "&Attendees (%1)", newCount)); } else { mUi->mTabWidget->setTabText( AttendeesTab, i18nc("@title:tab Tab to modify attendees of an event or todo", "&Attendees")); } } void IncidenceDialogPrivate::updateResourceCount(int newCount) { if (newCount > 0) { mUi->mTabWidget->setTabText( ResourcesTab, i18nc("@title:tab Tab to modify attendees of an event or todo", "&Resources (%1)", newCount)); } else { mUi->mTabWidget->setTabText( ResourcesTab, i18nc("@title:tab Tab to modify attendees of an event or todo", "&Resources")); } } void IncidenceDialogPrivate::updateButtonStatus(bool isDirty) { mUi->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(isDirty || mInitiallyDirty); } bool IncidenceDialogPrivate::containsPayloadIdentifiers( const QSet &partIdentifiers) const { return partIdentifiers.contains(QByteArray("PLD:RFC822")); } void IncidenceDialogPrivate::handleItemSaveFail(EditorItemManager::SaveAction, const QString &errorMessage) { Q_Q(IncidenceDialog); bool retry = false; if (!errorMessage.isEmpty()) { const QString message = i18nc("@info", "Unable to store the incidence in the calendar. Try again?\n\n " "Reason: %1", errorMessage); retry = (KMessageBox::warningYesNo(q, message) == KMessageBox::Yes); } if (retry) { mItemManager->save(); } else { updateButtonStatus(isDirty()); mUi->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); mUi->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(true); } } void IncidenceDialogPrivate::handleItemSaveFinish(EditorItemManager::SaveAction saveAction) { Q_Q(IncidenceDialog); if (mCloseOnSave) { q->accept(); } else { const Akonadi::Item item = mItemManager->item(); Q_ASSERT(item.isValid()); Q_ASSERT(item.hasPayload()); - Q_ASSERT(item.hasPayload()); + Q_ASSERT(item.hasPayload()); // Now the item is successfully saved, reload it in the editor in order to // reset the dirty status of the editor. - mEditor->load(item.payload()); + mEditor->load(item.payload()); mEditor->load(item); // Set the buttons to a reasonable state as well (ok and apply should be // disabled at this point). mUi->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); mUi->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(true); mUi->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(isDirty()); } if (saveAction == EditorItemManager::Create) { Q_EMIT q->incidenceCreated(mItemManager->item()); } } bool IncidenceDialogPrivate::hasSupportedPayload(const Akonadi::Item &item) const { return CalendarSupport::incidence(item); } bool IncidenceDialogPrivate::isDirty() const { if (mItem.isValid()) { return mEditor->isDirty() || mCalSelector->currentCollection().id() != mItem.storageCollectionId(); } else { return mEditor->isDirty(); } } bool IncidenceDialogPrivate::isValid() const { Q_Q(const IncidenceDialog); if (mEditor->isValid()) { // Check if there's a selected collection. if (mCalSelector->currentCollection().isValid()) { return true; } else { qCWarning(INCIDENCEEDITOR_LOG) << "Select a collection first"; Q_EMIT q->invalidCollection(); } } return false; } void IncidenceDialogPrivate::load(const Akonadi::Item &item) { Q_Q(IncidenceDialog); Q_ASSERT(hasSupportedPayload(item)); if (CalendarSupport::hasJournal(item)) { //mUi->mTabWidget->removeTab(5); mUi->mTabWidget->removeTab(AttachmentsTab); mUi->mTabWidget->removeTab(RecurrenceTab); mUi->mTabWidget->removeTab(AlarmsTab); mUi->mTabWidget->removeTab(AttendeesTab); mUi->mTabWidget->removeTab(ResourcesTab); } mEditor->load(CalendarSupport::incidence(item)); mEditor->load(item); - const KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence(item); + const KCalendarCore::Incidence::Ptr incidence = CalendarSupport::incidence(item); const QStringList allEmails = IncidenceEditorNG::EditorConfig::instance()->allEmails(); - const KCalCore::Attendee me = incidence->attendeeByMails(allEmails); + const KCalendarCore::Attendee me = incidence->attendeeByMails(allEmails); if (incidence->attendeeCount() > 1 // >1 because you won't drink alone - && !me.isNull() && (me.status() == KCalCore::Attendee::NeedsAction - || me.status() == KCalCore::Attendee::Tentative - || me.status() == KCalCore::Attendee::InProcess)) { + && !me.isNull() && (me.status() == KCalendarCore::Attendee::NeedsAction + || me.status() == KCalendarCore::Attendee::Tentative + || me.status() == KCalendarCore::Attendee::InProcess)) { // Show the invitation bar: "You are invited [accept] [decline]" mUi->mInvitationBar->show(); } else { mUi->mInvitationBar->hide(); } qCDebug(INCIDENCEEDITOR_LOG) << "Loading item " << item.id() << "; parent " << item.parentCollection().id() << "; storage " << item.storageCollectionId(); if (item.storageCollectionId() > -1) { mCalSelector->setDefaultCollection(Akonadi::Collection(item.storageCollectionId())); } if (!mCalSelector->mimeTypeFilter().contains(QStringLiteral("text/calendar")) || !mCalSelector->mimeTypeFilter().contains(incidence->mimeType())) { mCalSelector->setMimeTypeFilter(QStringList() << incidence->mimeType() << QStringLiteral("text/calendar")); } - if (mEditor->type() == KCalCore::Incidence::TypeTodo) { + if (mEditor->type() == KCalendarCore::Incidence::TypeTodo) { q->setWindowIcon(QIcon::fromTheme(QStringLiteral("view-calendar-tasks"))); - } else if (mEditor->type() == KCalCore::Incidence::TypeEvent) { + } else if (mEditor->type() == KCalendarCore::Incidence::TypeEvent) { q->setWindowIcon(QIcon::fromTheme(QStringLiteral("view-calendar-day"))); - } else if (mEditor->type() == KCalCore::Incidence::TypeJournal) { + } else if (mEditor->type() == KCalendarCore::Incidence::TypeJournal) { q->setWindowIcon(QIcon::fromTheme(QStringLiteral("view-pim-journal"))); } // Initialize tab's titles updateAttachmentCount(incidence->attachments().size()); updateResourceCount(mIeResource->resourceCount()); updateAttendeeCount(mIeAttendee->attendeeCount()); handleRecurrenceChange(mIeRecurrence->currentRecurrenceType()); handleAlarmCountChange(incidence->alarms().count()); mItem = item; q->show(); } Akonadi::Item IncidenceDialogPrivate::save(const Akonadi::Item &item) { - Q_ASSERT(mEditor->incidence()); + Q_ASSERT(mEditor->incidence()); - KCalCore::Incidence::Ptr incidenceInEditor = mEditor->incidence(); - KCalCore::Incidence::Ptr newIncidence(incidenceInEditor->clone()); + KCalendarCore::Incidence::Ptr incidenceInEditor = mEditor->incidence(); + KCalendarCore::Incidence::Ptr newIncidence(incidenceInEditor->clone()); Akonadi::Item result = item; result.setMimeType(newIncidence->mimeType()); // There's no editor that has the relatedTo property. We must set it here, by hand. // Otherwise it gets lost. // FIXME: Why don't we clone() incidenceInEditor then pass the clone to save(), // I wonder if we're not leaking other properties. newIncidence->setRelatedTo(incidenceInEditor->relatedTo()); mEditor->save(newIncidence); mEditor->save(result); // Make sure that we don't loose uid for existing incidence - newIncidence->setUid(mEditor->incidence()->uid()); + newIncidence->setUid(mEditor->incidence()->uid()); // Mark the incidence as changed if (mItem.isValid()) { newIncidence->setRevision(newIncidence->revision() + 1); } - result.setPayload(newIncidence); + result.setPayload(newIncidence); return result; } Akonadi::Collection IncidenceDialogPrivate::selectedCollection() const { return mCalSelector->currentCollection(); } void IncidenceDialogPrivate::reject(RejectReason reason, const QString &errorMessage) { Q_UNUSED(reason); Q_Q(IncidenceDialog); qCCritical(INCIDENCEEDITOR_LOG) << "Rejecting:" << errorMessage; q->deleteLater(); } /// IncidenceDialog IncidenceDialog::IncidenceDialog(Akonadi::IncidenceChanger *changer, QWidget *parent, Qt::WindowFlags flags) : QDialog(parent, flags) , d_ptr(new IncidenceDialogPrivate(changer, this)) { Q_D(IncidenceDialog); setAttribute(Qt::WA_DeleteOnClose); d->mUi->mTabWidget->setCurrentIndex(0); d->mUi->mSummaryEdit->setFocus(); d->mUi->buttonBox->button(QDialogButtonBox::Apply)->setToolTip(i18nc("@info:tooltip", "Save current changes")); d->mUi->buttonBox->button(QDialogButtonBox::Ok)->setToolTip(i18nc("@action:button", "Save changes and close dialog")); d->mUi->buttonBox->button(QDialogButtonBox::Cancel)->setToolTip(i18nc("@action:button", "Discard changes and close dialog")); d->mUi->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); auto defaultButton = d->mUi->buttonBox->button(QDialogButtonBox::RestoreDefaults); defaultButton->setText(i18nc("@action:button", "&Templates...")); defaultButton->setIcon(QIcon::fromTheme(QStringLiteral("project-development-new-template"))); defaultButton->setToolTip(i18nc("@info:tooltip", "Manage templates for this item")); defaultButton->setWhatsThis( i18nc("@info:whatsthis", "Push this button to show a dialog that helps " "you manage a set of templates. Templates " "can make creating new items easier and faster " "by putting your favorite default values into " "the editor automatically.")); connect(d->mUi->buttonBox, &QDialogButtonBox::clicked, this, &IncidenceDialog::slotButtonClicked); setModal(false); connect(d->mUi->mAcceptInvitationButton, &QAbstractButton::clicked, d->mIeAttendee, &IncidenceAttendee::acceptForMe); connect(d->mUi->mAcceptInvitationButton, &QAbstractButton::clicked, d->mUi->mInvitationBar, &QWidget::hide); connect(d->mUi->mDeclineInvitationButton, &QAbstractButton::clicked, d->mIeAttendee, &IncidenceAttendee::declineForMe); connect(d->mUi->mDeclineInvitationButton, &QAbstractButton::clicked, d->mUi->mInvitationBar, &QWidget::hide); connect(this, SIGNAL(invalidCollection()), this, SLOT(slotInvalidCollection())); readConfig(); } IncidenceDialog::~IncidenceDialog() { writeConfig(); delete d_ptr; } void IncidenceDialog::writeConfig() { KConfigGroup group(KSharedConfig::openConfig(), "IncidenceDialog"); group.writeEntry("Size", size()); const Akonadi::Collection col = d_ptr->mCalSelector->currentCollection(); // col might not be valid if the collection wasn't found yet (the combo is async), skip saving in that case if (col.isValid() && col.id() != IncidenceEditorNG::IncidenceEditorSettings::self()->lastSelectedFolder()) { IncidenceEditorNG::IncidenceEditorSettings::self()->setLastSelectedFolder(col.id()); IncidenceEditorNG::IncidenceEditorSettings::self()->save(); } } void IncidenceDialog::readConfig() { KConfigGroup group(KSharedConfig::openConfig(), "IncidenceDialog"); const QSize size = group.readEntry("Size", QSize()); if (size.isValid()) { resize(size); } else { resize(QSize(500, 500).expandedTo(minimumSizeHint())); } } void IncidenceDialog::load(const Akonadi::Item &item, const QDate &activeDate) { Q_D(IncidenceDialog); d->mIeDateTime->setActiveDate(activeDate); if (item.isValid()) { // We're editing d->mItemManager->load(item); } else { // We're creating Q_ASSERT(d->hasSupportedPayload(item)); d->load(item); show(); } } void IncidenceDialog::selectCollection(const Akonadi::Collection &collection) { Q_D(IncidenceDialog); if (collection.isValid()) { d->mCalSelector->setDefaultCollection(collection); } else { d->mCalSelector->setCurrentIndex(0); } } void IncidenceDialog::setIsCounterProposal(bool isCounterProposal) { Q_D(IncidenceDialog); d->mItemManager->setIsCounterProposal(isCounterProposal); } QObject *IncidenceDialog::typeAheadReceiver() const { Q_D(const IncidenceDialog); return d->mUi->mSummaryEdit; } void IncidenceDialog::slotButtonClicked(QAbstractButton *button) { Q_D(IncidenceDialog); if (d->mUi->buttonBox->button(QDialogButtonBox::Ok) == button) { if (d->isDirty() || d->mInitiallyDirty) { d->mUi->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); d->mUi->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); d->mUi->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); d->mCloseOnSave = true; d->mInitiallyDirty = false; d->mItemManager->save(); } else { close(); } } else if (d->mUi->buttonBox->button(QDialogButtonBox::Apply) == button) { d->mUi->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); d->mUi->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); d->mUi->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); d->mCloseOnSave = false; d->mInitiallyDirty = false; d->mItemManager->save(); } else if (d->mUi->buttonBox->button(QDialogButtonBox::Cancel) == button) { if (d->isDirty() && KMessageBox::questionYesNo( this, i18nc("@info", "Do you really want to cancel?"), i18nc("@title:window", "KOrganizer Confirmation")) == KMessageBox::Yes) { QDialog::reject(); // Discard current changes } else if (!d->isDirty()) { QDialog::reject(); // No pending changes, just close the dialog. } // else { // the user wasn't finished editing after all } } else if (d->mUi->buttonBox->button(QDialogButtonBox::RestoreDefaults)) { d->manageTemplates(); } else { Q_ASSERT(false); // Shouldn't happen } } void IncidenceDialog::closeEvent(QCloseEvent *event) { Q_D(IncidenceDialog); if (d->isDirty() && KMessageBox::questionYesNo( this, i18nc("@info", "Do you really want to cancel?"), i18nc("@title:window", "KOrganizer Confirmation")) == KMessageBox::Yes) { QDialog::reject(); // Discard current changes QDialog::closeEvent(event); } else if (!d->isDirty()) { QDialog::reject(); // No pending changes, just close the dialog. QDialog::closeEvent(event); } else { event->ignore(); } } void IncidenceDialog::setInitiallyDirty(bool initiallyDirty) { Q_D(IncidenceDialog); d->mInitiallyDirty = initiallyDirty; } Akonadi::Item IncidenceDialog::item() const { Q_D(const IncidenceDialog); return d->mItemManager->item(); } void IncidenceDialog::handleSelectedCollectionChange(const Akonadi::Collection &collection) { Q_D(IncidenceDialog); if (d->mItem.parentCollection().isValid()) { d->mUi->buttonBox->button(QDialogButtonBox::Apply)->setEnabled( collection.id() != d->mItem.parentCollection().id()); } } #include "moc_incidencedialog.cpp" diff --git a/src/incidencedialog.h b/src/incidencedialog.h index a7d8e8e..02cdebb 100644 --- a/src/incidencedialog.h +++ b/src/incidencedialog.h @@ -1,125 +1,125 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCEDIALOG_H #define INCIDENCEEDITOR_INCIDENCEDIALOG_H #include "incidenceeditor_export.h" #include "editoritemmanager.h" #include #include class QAbstractButton; namespace Akonadi { class IncidenceChanger; } namespace IncidenceEditorNG { class IncidenceDialogPrivate; class INCIDENCEEDITOR_EXPORT IncidenceDialog : public QDialog { Q_OBJECT public: explicit IncidenceDialog(Akonadi::IncidenceChanger *changer = nullptr, QWidget *parent = nullptr, Qt::WindowFlags flags = {}); ~IncidenceDialog() override; /** * Loads the @param item into the dialog. * * To create a new Incidence pass an invalid item with either an - * KCalCore::Event:Ptr or a KCalCore::Todo:Ptr set as payload. Note: When the + * KCalendarCore::Event:Ptr or a KCalendarCore::Todo:Ptr set as payload. Note: When the * item is invalid, i.e. it has an invalid id, a valid payload must * be set. * * When the item has is valid this method will fetch the payload when this is * not already set. */ virtual void load(const Akonadi::Item &item, const QDate &activeDate = QDate()); /** * Sets the Collection combobox to @param collection. */ virtual void selectCollection(const Akonadi::Collection &collection); virtual void setIsCounterProposal(bool isCounterProposal); /** Returns the object that will receive all key events. */ QObject *typeAheadReceiver() const; /** By default, if you load an incidence into the editor ( load(item) ), then press [OK] without changing anything, the dialog is dismissed, and the incidence isn't saved to akonadi. Call this method with @p initiallyDirty = true if you want the incidence to be saved, It's useful if you're creating a dialog with an already crafted content, like in kmail's "Create Todo/Reminder Feature". */ void setInitiallyDirty(bool initiallyDirty); Q_REQUIRED_RESULT Akonadi::Item item() const; Q_SIGNALS: /** * This signal is emitted when an incidence is created. * @param collection The collection where it was created. */ void incidenceCreated(const Akonadi::Item &); void invalidCollection() const; protected: void closeEvent(QCloseEvent *event) override; protected Q_SLOTS: void slotButtonClicked(QAbstractButton *button); void handleSelectedCollectionChange(const Akonadi::Collection &collection); private: IncidenceDialogPrivate *const d_ptr; Q_DECLARE_PRIVATE(IncidenceDialog) Q_DISABLE_COPY(IncidenceDialog) void writeConfig(); void readConfig(); Q_PRIVATE_SLOT(d_ptr, void handleAlarmCountChange(int)) Q_PRIVATE_SLOT(d_ptr, void handleItemSaveFinish( IncidenceEditorNG::EditorItemManager::SaveAction)) Q_PRIVATE_SLOT(d_ptr, void handleItemSaveFail(IncidenceEditorNG::EditorItemManager::SaveAction, QString)) Q_PRIVATE_SLOT(d_ptr, void handleRecurrenceChange(IncidenceEditorNG::RecurrenceType)) Q_PRIVATE_SLOT(d_ptr, void loadTemplate(QString)) Q_PRIVATE_SLOT(d_ptr, void saveTemplate(QString)) Q_PRIVATE_SLOT(d_ptr, void storeTemplatesInConfig(QStringList)) Q_PRIVATE_SLOT(d_ptr, void updateAttachmentCount(int)) Q_PRIVATE_SLOT(d_ptr, void updateAttendeeCount(int)) Q_PRIVATE_SLOT(d_ptr, void updateResourceCount(int)) Q_PRIVATE_SLOT(d_ptr, void updateButtonStatus(bool)) Q_PRIVATE_SLOT(d_ptr, void showMessage(QString, KMessageWidget::MessageType)) Q_PRIVATE_SLOT(d_ptr, void slotInvalidCollection()) }; } #endif diff --git a/src/incidencedialogfactory.cpp b/src/incidencedialogfactory.cpp index 5a67b90..854ab95 100644 --- a/src/incidencedialogfactory.cpp +++ b/src/incidencedialogfactory.cpp @@ -1,113 +1,113 @@ /* Copyright (C) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidencedialogfactory.h" #include "incidencedialog.h" #include "incidencedefaults.h" -#include -#include +#include +#include #include #include using namespace IncidenceEditorNG; -using namespace KCalCore; +using namespace KCalendarCore; -IncidenceDialog *IncidenceDialogFactory::create(bool needsSaving, KCalCore::IncidenceBase::IncidenceType type, Akonadi::IncidenceChanger *changer, QWidget *parent, Qt::WindowFlags flags) +IncidenceDialog *IncidenceDialogFactory::create(bool needsSaving, KCalendarCore::IncidenceBase::IncidenceType type, Akonadi::IncidenceChanger *changer, QWidget *parent, Qt::WindowFlags flags) { switch (type) { - case KCalCore::IncidenceBase::TypeEvent: // Fall through - case KCalCore::IncidenceBase::TypeTodo: - case KCalCore::IncidenceBase::TypeJournal: + case KCalendarCore::IncidenceBase::TypeEvent: // Fall through + case KCalendarCore::IncidenceBase::TypeTodo: + case KCalendarCore::IncidenceBase::TypeJournal: { IncidenceDialog *dialog = new IncidenceDialog(changer, parent, flags); // needs to be save to akonadi?, apply button should be turned on if so. dialog->setInitiallyDirty(needsSaving /* mInitiallyDirty */); return dialog; } default: return nullptr; } } IncidenceDialog *IncidenceDialogFactory::createTodoEditor(const QString &summary, const QString &description, const QStringList &attachments, const QStringList &attendees, const QStringList &attachmentMimetypes, const QStringList &attachmentLabels, bool inlineAttachment, const Akonadi::Collection &defaultCollection, bool cleanupAttachmentTempFiles, QWidget *parent, Qt::WindowFlags flags) { IncidenceDefaults defaults = IncidenceDefaults::minimalIncidenceDefaults(cleanupAttachmentTempFiles); // if attach or attendee list is empty, these methods don't do anything, so // it's safe to call them in every case defaults.setAttachments(attachments, attachmentMimetypes, attachmentLabels, inlineAttachment); defaults.setAttendees(attendees); Todo::Ptr todo(new Todo); defaults.setDefaults(todo); todo->setSummary(summary); todo->setDescription(description); Akonadi::Item item; item.setPayload(todo); IncidenceDialog *dialog = create(true, /* no need for, we're not editing an existing to-do */ - KCalCore::Incidence::TypeTodo, + KCalendarCore::Incidence::TypeTodo, nullptr, parent, flags); dialog->selectCollection(defaultCollection); dialog->load(item); return dialog; } IncidenceDialog *IncidenceDialogFactory::createEventEditor(const QString &summary, const QString &description, const QStringList &attachments, const QStringList &attendees, const QStringList &attachmentMimetypes, const QStringList &attachmentLabels, bool inlineAttachment, const Akonadi::Collection &defaultCollection, bool cleanupAttachmentTempFiles, QWidget *parent, Qt::WindowFlags flags) { IncidenceDefaults defaults = IncidenceDefaults::minimalIncidenceDefaults(cleanupAttachmentTempFiles); // if attach or attendee list is empty, these methods don't do anything, so // it's safe to call them in every case defaults.setAttachments(attachments, attachmentMimetypes, attachmentLabels, inlineAttachment); defaults.setAttendees(attendees); Event::Ptr event(new Event); defaults.setDefaults(event); event->setSummary(summary); event->setDescription(description); Akonadi::Item item; item.setPayload(event); IncidenceDialog *dialog = create(false, // not needed for saving, as we're not editing an existing incidence - KCalCore::Incidence::TypeEvent, + KCalendarCore::Incidence::TypeEvent, nullptr, parent, flags); dialog->selectCollection(defaultCollection); dialog->load(item); return dialog; } diff --git a/src/incidencedialogfactory.h b/src/incidencedialogfactory.h index 4756a8d..ab510d0 100644 --- a/src/incidencedialogfactory.h +++ b/src/incidencedialogfactory.h @@ -1,64 +1,64 @@ /* Copyright (C) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCEDIALOGFACTORY_H #define INCIDENCEEDITOR_INCIDENCEDIALOGFACTORY_H #include "incidenceeditor_export.h" -#include +#include #include namespace Akonadi { class IncidenceChanger; } namespace IncidenceEditorNG { class IncidenceDialog; namespace IncidenceDialogFactory { /** * Creates a new IncidenceDialog for given type. Returns 0 for unsupported types. * * @param needsSaving If true, the editor will be initially dirty, and needs saving. * Apply button will be turned on. This is used for example when * we fill the editor with data that's not yet in akonadi, like * the "Create To-do/Reminder" in KMail. * @param type The Incidence type for which to create a dialog. * @param parent The parent widget of the dialog * @param flags The window flags for the dialog. * * TODO: Implement support for Journals. * NOTE: There is no editor for Incidence::TypeFreeBusy */ INCIDENCEEDITOR_EXPORT IncidenceDialog *create( - bool needsSaving, KCalCore::IncidenceBase::IncidenceType type, Akonadi::IncidenceChanger *changer, QWidget *parent = nullptr, Qt::WindowFlags flags = {}); + bool needsSaving, KCalendarCore::IncidenceBase::IncidenceType type, Akonadi::IncidenceChanger *changer, QWidget *parent = nullptr, Qt::WindowFlags flags = {}); INCIDENCEEDITOR_EXPORT IncidenceDialog *createTodoEditor( const QString &summary, const QString &description, const QStringList &attachments, const QStringList &attendees, const QStringList &attachmentMimetypes, const QStringList &attachmentLabels, bool inlineAttachment, const Akonadi::Collection &defaultCollection, bool cleanupAttachmentTemp, QWidget *parent = nullptr, Qt::WindowFlags flags = {}); INCIDENCEEDITOR_EXPORT IncidenceDialog *createEventEditor( const QString &summary, const QString &description, const QStringList &attachments, const QStringList &attendees, const QStringList &attachmentMimetypes, const QStringList &attachmentLabels, bool inlineAttachment, const Akonadi::Collection &defaultCollection, bool cleanupAttachmentTempFiles, QWidget *parent = nullptr, Qt::WindowFlags flags = {}); } // namespace IncidenceDialogFactory } // namespace IncidenceEditorNG #endif diff --git a/src/incidenceeditor-ng.h b/src/incidenceeditor-ng.h index 6cc760b..6e8485e 100644 --- a/src/incidenceeditor-ng.h +++ b/src/incidenceeditor-ng.h @@ -1,133 +1,133 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_NG_H #define INCIDENCEEDITOR_NG_H #include "incidenceeditor_export.h" -#include +#include #include namespace IncidenceEditorNG { /** * KCal Incidences are complicated objects. The user interfaces to create/modify * are therefore complex too. The IncedenceEditor class is a divide and conquer * approach to this complexity. An IncidenceEditor is an editor for a specific * part(s) of an Incidence. */ class INCIDENCEEDITOR_EXPORT IncidenceEditor : public QObject { Q_OBJECT public: ~IncidenceEditor() override; /** * Load the values of @param incidence into the editor widgets. The passed * incidence is kept for comparing with the current values of the editor. */ - virtual void load(const KCalCore::Incidence::Ptr &incidence) = 0; + virtual void load(const KCalendarCore::Incidence::Ptr &incidence) = 0; /// This was introduced to replace categories with Akonadi::Tags virtual void load(const Akonadi::Item &item); /** * Store the current values of the editor into @param incidence . */ - virtual void save(const KCalCore::Incidence::Ptr &incidence) = 0; + virtual void save(const KCalendarCore::Incidence::Ptr &incidence) = 0; /// This was introduced to replace categories with Akonadi::Tags virtual void save(Akonadi::Item &item); /** * Returns whether or not the current values in the editor differ from the * initial values. */ virtual bool isDirty() const = 0; /** * Returns whether or not the content of this editor is valid. The default * implementation returns always true. */ virtual bool isValid() const; /** Returns the last error, which is set in isValid() on error, and cleared on success. */ Q_REQUIRED_RESULT QString lastErrorString() const; /** * Sets focus on the invalid field. */ virtual void focusInvalidField(); /** * Returns the type of the Incidence that is currently loaded. */ - Q_REQUIRED_RESULT KCalCore::IncidenceBase::IncidenceType type() const; + Q_REQUIRED_RESULT KCalendarCore::IncidenceBase::IncidenceType type() const; /** Convenience method to get a pointer for a specific const Incidence Type. */ template QSharedPointer incidence() const { return mLoadedIncidence.dynamicCast(); } /** Re-implement this and print important member values and widget enabled/disabled states that could have lead to isDirty() returning true when the user didn't do any interaction with the editor. This method is called in CombinedIncidenceEditor before crashing due to assert( !editor->isDirty() ) */ virtual void printDebugInfo() const; Q_SIGNALS: /** * Signals whether the dirty status of this editor has changed. The new dirty * status is passed as argument. */ void dirtyStatusChanged(bool isDirty); public Q_SLOTS: /** * Checks if the dirty status has changed until last check and emits the * dirtyStatusChanged signal if needed. */ void checkDirtyStatus(); protected: /** Only subclasses can instantiate IncidenceEditors */ IncidenceEditor(QObject *parent = nullptr); template - QSharedPointer incidence(const KCalCore::Incidence::Ptr &inc) + QSharedPointer incidence(const KCalendarCore::Incidence::Ptr &inc) { return inc.dynamicCast(); } protected: - KCalCore::Incidence::Ptr mLoadedIncidence; + KCalendarCore::Incidence::Ptr mLoadedIncidence; mutable QString mLastErrorString; bool mWasDirty; bool mLoadingIncidence; }; } // IncidenceEditorNG #endif // INCIDENCEEDITOR_H diff --git a/src/incidenceeditor.cpp b/src/incidenceeditor.cpp index 33546c4..9051441 100644 --- a/src/incidenceeditor.cpp +++ b/src/incidenceeditor.cpp @@ -1,95 +1,95 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidenceeditor-ng.h" #include "incidenceeditor_debug.h" using namespace IncidenceEditorNG; IncidenceEditor::IncidenceEditor(QObject *parent) : QObject(parent) , mWasDirty(false) , mLoadingIncidence(false) { } IncidenceEditor::~IncidenceEditor() { } void IncidenceEditor::checkDirtyStatus() { if (!mLoadedIncidence) { qCDebug(INCIDENCEEDITOR_LOG) << "checkDirtyStatus called on an invalid incidence"; return; } if (mLoadingIncidence) { // Still loading the incidence, ignore changes to widgets. return; } const bool dirty = isDirty(); if (mWasDirty != dirty) { mWasDirty = dirty; Q_EMIT dirtyStatusChanged(dirty); } } bool IncidenceEditor::isValid() const { mLastErrorString.clear(); return true; } QString IncidenceEditor::lastErrorString() const { return mLastErrorString; } void IncidenceEditor::focusInvalidField() { } -KCalCore::IncidenceBase::IncidenceType IncidenceEditor::type() const +KCalendarCore::IncidenceBase::IncidenceType IncidenceEditor::type() const { if (mLoadedIncidence) { return mLoadedIncidence->type(); } else { - return KCalCore::IncidenceBase::TypeUnknown; + return KCalendarCore::IncidenceBase::TypeUnknown; } } void IncidenceEditor::printDebugInfo() const { // implement this in derived classes. } void IncidenceEditor::load(const Akonadi::Item &item) { Q_UNUSED(item); } void IncidenceEditor::save(Akonadi::Item &item) { Q_UNUSED(item); } #include "moc_incidenceeditor-ng.cpp" diff --git a/src/incidencerecurrence.cpp b/src/incidencerecurrence.cpp index 0e2e99f..079fdb2 100644 --- a/src/incidencerecurrence.cpp +++ b/src/incidencerecurrence.cpp @@ -1,996 +1,996 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidencerecurrence.h" #include "incidencedatetime.h" #include "ui_dialogdesktop.h" #include "incidenceeditor_debug.h" #include #include using namespace IncidenceEditorNG; enum { // Keep in sync with mRecurrenceEndCombo RecurrenceEndNever = 0, RecurrenceEndOn, RecurrenceEndAfter }; /** Description of available recurrence types: 0 - None 1 - 2 - 3 - rDaily 4 - rWeekly 5 - rMonthlyPos - 3rd Saturday of month, last Wednesday of month... 6 - rMonthlyDay - 17th day of month 7 - rYearlyMonth - 10th of July 8 - rYearlyDay - on the 117th day of the year 9 - rYearlyPos - 1st Wednesday of July */ enum { // Indexes of the month combo, keep in sync with descriptions. ComboIndexMonthlyDay = 0, // 11th of June ComboIndexMonthlyDayInverted, // 20th of June ( 11 to end ) ComboIndexMonthlyPos, // 1st Monday of the Month ComboIndexMonthlyPosInverted // Last Monday of the Month }; enum { // Indexes of the year combo, keep in sync with descriptions. ComboIndexYearlyMonth = 0, ComboIndexYearlyMonthInverted, ComboIndexYearlyPos, ComboIndexYearlyPosInverted, ComboIndexYearlyDay }; IncidenceRecurrence::IncidenceRecurrence(IncidenceDateTime *dateTime, Ui::EventOrTodoDesktop *ui) : mUi(ui) , mDateTime(dateTime) , mMonthlyInitialType(0) , mYearlyInitialType(0) { setObjectName(QStringLiteral("IncidenceRecurrence")); // Set some sane defaults mUi->mRecurrenceTypeCombo->setCurrentIndex(RecurrenceTypeNone); mUi->mRecurrenceEndCombo->setCurrentIndex(RecurrenceEndNever); mUi->mRecurrenceEndStack->setCurrentIndex(0); mUi->mRepeatStack->setCurrentIndex(0); mUi->mEndDurationEdit->setValue(1); handleEndAfterOccurrencesChange(1); toggleRecurrenceWidgets(RecurrenceTypeNone); fillCombos(); const QList lineEdits { mUi->mExceptionDateEdit->lineEdit(), mUi->mRecurrenceEndDate->lineEdit()}; for (QLineEdit *lineEdit : lineEdits) { if (lineEdit) { lineEdit->setClearButtonEnabled(false); } } connect(mDateTime, &IncidenceDateTime::startDateTimeToggled, this, &IncidenceRecurrence::handleDateTimeToggle); connect(mDateTime, &IncidenceDateTime::startDateChanged, this, &IncidenceRecurrence::handleStartDateChange); connect(mUi->mExceptionAddButton, &QPushButton::clicked, this, &IncidenceRecurrence::addException); connect(mUi->mExceptionRemoveButton, &QPushButton::clicked, this, &IncidenceRecurrence::removeExceptions); connect(mUi->mExceptionDateEdit, &KDateComboBox::dateChanged, this, &IncidenceRecurrence::handleExceptionDateChange); connect(mUi->mExceptionList, &QListWidget::itemSelectionChanged, this, &IncidenceRecurrence::updateRemoveExceptionButton); connect(mUi->mRecurrenceTypeCombo, qOverload(&QComboBox::currentIndexChanged), this, &IncidenceRecurrence::handleRecurrenceTypeChange); connect(mUi->mEndDurationEdit, qOverload(&QSpinBox::valueChanged), this, &IncidenceRecurrence::handleEndAfterOccurrencesChange); connect(mUi->mFrequencyEdit, qOverload(&QSpinBox::valueChanged), this, &IncidenceRecurrence::handleFrequencyChange); // Check the dirty status when the user changes values. connect(mUi->mRecurrenceTypeCombo, qOverload(&QComboBox::currentIndexChanged), this, &IncidenceRecurrence::checkDirtyStatus); connect(mUi->mFrequencyEdit, qOverload(&QSpinBox::valueChanged), this, &IncidenceRecurrence::checkDirtyStatus); connect(mUi->mFrequencyEdit, qOverload(&QSpinBox::valueChanged), this, &IncidenceRecurrence::checkDirtyStatus); connect(mUi->mWeekDayCombo, &KPIM::KWeekdayCheckCombo::checkedItemsChanged, this, &IncidenceRecurrence::checkDirtyStatus); connect(mUi->mMonthlyCombo, qOverload(&QComboBox::currentIndexChanged), this, &IncidenceRecurrence::checkDirtyStatus); connect(mUi->mYearlyCombo, qOverload(&QComboBox::currentIndexChanged), this, &IncidenceRecurrence::checkDirtyStatus); connect(mUi->mRecurrenceEndCombo, qOverload(&QComboBox::currentIndexChanged), this, &IncidenceRecurrence::checkDirtyStatus); connect(mUi->mEndDurationEdit, qOverload(&QSpinBox::valueChanged), this, &IncidenceRecurrence::checkDirtyStatus); connect(mUi->mRecurrenceEndDate, &KDateComboBox::dateChanged, this, &IncidenceRecurrence::checkDirtyStatus); connect(mUi->mThisAndFutureCheck, &QCheckBox::stateChanged, this, &IncidenceRecurrence::checkDirtyStatus); } // this method must be at the top of this file in order to ensure // that its message to translators appears before any usages of this method. KLocalizedString IncidenceRecurrence::subsOrdinal(const KLocalizedString &text, int number) const { QString q = i18nc("In several of the messages below, " "an ordinal number is substituted into the message. " "Translate this as \"0\" if English ordinal suffixes " "should be added (1st, 22nd, 123rd); " "translate this as \"1\" if just the number itself " "should be substituted (1, 22, 123).", "0"); if (q == QLatin1String("0")) { const QString ordinal = numberToString(number); return text.subs(ordinal); } else { return text.subs(number); } } -void IncidenceRecurrence::load(const KCalCore::Incidence::Ptr &incidence) +void IncidenceRecurrence::load(const KCalendarCore::Incidence::Ptr &incidence) { Q_ASSERT(incidence); mLoadedIncidence = incidence; // We must be sure that the date/time in mDateTime is the correct date time. // So don't depend on CombinedIncidenceEditor or whatever external factor to // load the date/time before loading the recurrence - mCurrentDate = mLoadedIncidence->dateTime(KCalCore::IncidenceBase::RoleRecurrenceStart).date(); + mCurrentDate = mLoadedIncidence->dateTime(KCalendarCore::IncidenceBase::RoleRecurrenceStart).date(); mDateTime->load(incidence); mDateTime->endDate(); fillCombos(); setDefaults(); //This is an exception if (mLoadedIncidence->hasRecurrenceId()) { handleRecurrenceTypeChange(RecurrenceTypeException); mUi->mThisAndFutureCheck->setChecked(mLoadedIncidence->thisAndFuture()); mWasDirty = false; return; } int f = 0; - KCalCore::Recurrence *r = nullptr; - if (mLoadedIncidence->recurrenceType() != KCalCore::Recurrence::rNone) { + KCalendarCore::Recurrence *r = nullptr; + if (mLoadedIncidence->recurrenceType() != KCalendarCore::Recurrence::rNone) { r = mLoadedIncidence->recurrence(); f = r->frequency(); } switch (mLoadedIncidence->recurrenceType()) { - case KCalCore::Recurrence::rNone: + case KCalendarCore::Recurrence::rNone: mUi->mRecurrenceTypeCombo->setCurrentIndex(RecurrenceTypeNone); handleRecurrenceTypeChange(RecurrenceTypeNone); break; - case KCalCore::Recurrence::rDaily: + case KCalendarCore::Recurrence::rDaily: mUi->mRecurrenceTypeCombo->setCurrentIndex(RecurrenceTypeDaily); handleRecurrenceTypeChange(RecurrenceTypeDaily); setFrequency(f); break; - case KCalCore::Recurrence::rWeekly: + case KCalendarCore::Recurrence::rWeekly: { mUi->mRecurrenceTypeCombo->setCurrentIndex(RecurrenceTypeWeekly); handleRecurrenceTypeChange(RecurrenceTypeWeekly); QBitArray disableDays(7 /*size*/, 0 /*default value*/); // dayOfWeek returns between 1 and 7 disableDays.setBit(currentDate().dayOfWeek() - 1, 1); mUi->mWeekDayCombo->setDays(r->days(), disableDays); setFrequency(f); break; } - case KCalCore::Recurrence::rMonthlyPos: // Fall through - case KCalCore::Recurrence::rMonthlyDay: + case KCalendarCore::Recurrence::rMonthlyPos: // Fall through + case KCalendarCore::Recurrence::rMonthlyDay: mUi->mRecurrenceTypeCombo->setCurrentIndex(RecurrenceTypeMonthly); handleRecurrenceTypeChange(RecurrenceTypeMonthly); selectMonthlyItem(r, mLoadedIncidence->recurrenceType()); setFrequency(f); break; - case KCalCore::Recurrence::rYearlyMonth: // Fall through - case KCalCore::Recurrence::rYearlyPos: // Fall through - case KCalCore::Recurrence::rYearlyDay: + case KCalendarCore::Recurrence::rYearlyMonth: // Fall through + case KCalendarCore::Recurrence::rYearlyPos: // Fall through + case KCalendarCore::Recurrence::rYearlyDay: mUi->mRecurrenceTypeCombo->setCurrentIndex(RecurrenceTypeYearly); handleRecurrenceTypeChange(RecurrenceTypeYearly); selectYearlyItem(r, mLoadedIncidence->recurrenceType()); setFrequency(f); break; default: break; } if (mLoadedIncidence->recurs() && r) { setDuration(r->duration()); if (r->duration() == 0) { mUi->mRecurrenceEndDate->setDate(r->endDate()); } } setExceptionDates(mLoadedIncidence->recurrence()->exDates()); handleDateTimeToggle(); mWasDirty = false; } -void IncidenceRecurrence::writeToIncidence(const KCalCore::Incidence::Ptr &incidence) const +void IncidenceRecurrence::writeToIncidence(const KCalendarCore::Incidence::Ptr &incidence) const { // clear out any old settings; - KCalCore::Recurrence *r = incidence->recurrence(); + KCalendarCore::Recurrence *r = incidence->recurrence(); r->unsetRecurs(); // Why not clear() ? const RecurrenceType recurrenceType = currentRecurrenceType(); if (recurrenceType == RecurrenceTypeException) { incidence->setThisAndFuture(mUi->mThisAndFutureCheck->isChecked()); return; } if (recurrenceType == RecurrenceTypeNone || !mUi->mRecurrenceTypeCombo->isEnabled()) { return; } const int lDuration = duration(); QDate endDate; if (lDuration == 0) { endDate = mUi->mRecurrenceEndDate->date(); } if (recurrenceType == RecurrenceTypeDaily) { r->setDaily(mUi->mFrequencyEdit->value()); } else if (recurrenceType == RecurrenceTypeWeekly) { r->setWeekly(mUi->mFrequencyEdit->value(), mUi->mWeekDayCombo->days()); } else if (recurrenceType == RecurrenceTypeMonthly) { r->setMonthly(mUi->mFrequencyEdit->value()); if (mUi->mMonthlyCombo->currentIndex() == ComboIndexMonthlyDay) { // Every nth r->addMonthlyDate(dayOfMonthFromStart()); } else if (mUi->mMonthlyCombo->currentIndex() == ComboIndexMonthlyDayInverted) { // Every (last - n)th last day r->addMonthlyDate(-dayOfMonthFromEnd()); } else if (mUi->mMonthlyCombo->currentIndex() == ComboIndexMonthlyPos) { // Every ith weekday r->addMonthlyPos(monthWeekFromStart(), weekday()); } else { // Every (last - i)th last weekday r->addMonthlyPos(-monthWeekFromEnd(), weekday()); } } else if (recurrenceType == RecurrenceTypeYearly) { r->setYearly(mUi->mFrequencyEdit->value()); if (mUi->mYearlyCombo->currentIndex() == ComboIndexYearlyMonth) { //Every nth of month r->addYearlyDate(dayOfMonthFromStart()); r->addYearlyMonth(currentDate().month()); } else if (mUi->mYearlyCombo->currentIndex() == ComboIndexYearlyMonthInverted) { //Every (last - n)th last day of month r->addYearlyDate(-dayOfMonthFromEnd()); r->addYearlyMonth(currentDate().month()); } else if (mUi->mYearlyCombo->currentIndex() == ComboIndexYearlyPos) { //Every ith weekday of month r->addYearlyMonth(currentDate().month()); r->addYearlyPos(monthWeekFromStart(), weekday()); } else if (mUi->mYearlyCombo->currentIndex() == ComboIndexYearlyPosInverted) { //Every (last - i)th last weekday of month r->addYearlyMonth(currentDate().month()); r->addYearlyPos(-monthWeekFromEnd(), weekday()); } else { // The lth day of the year (l : 1 - 356) r->addYearlyDay(dayOfYearFromStart()); } } r->setDuration(lDuration); if (lDuration == 0) { r->setEndDate(endDate); } r->setExDates(mExceptionDates); } -void IncidenceRecurrence::save(const KCalCore::Incidence::Ptr &incidence) +void IncidenceRecurrence::save(const KCalendarCore::Incidence::Ptr &incidence) { writeToIncidence(incidence); mMonthlyInitialType = mUi->mMonthlyCombo->currentIndex(); mYearlyInitialType = mUi->mYearlyCombo->currentIndex(); } bool IncidenceRecurrence::isDirty() const { const RecurrenceType recurrenceType = currentRecurrenceType(); if (mLoadedIncidence->recurs() && recurrenceType == RecurrenceTypeNone) { return true; } if (recurrenceType == RecurrenceTypeException) { return mLoadedIncidence->thisAndFuture() != mUi->mThisAndFutureCheck->isChecked(); } if (!mLoadedIncidence->recurs() && recurrenceType != IncidenceEditorNG::RecurrenceTypeNone) { return true; } // The incidence is not recurring and that hasn't changed, so don't check the // other values. if (recurrenceType == RecurrenceTypeNone) { return false; } - const KCalCore::Recurrence *recurrence = mLoadedIncidence->recurrence(); + const KCalendarCore::Recurrence *recurrence = mLoadedIncidence->recurrence(); switch (recurrence->recurrenceType()) { - case KCalCore::Recurrence::rDaily: + case KCalendarCore::Recurrence::rDaily: if (recurrenceType != RecurrenceTypeDaily || mUi->mFrequencyEdit->value() != recurrence->frequency()) { return true; } break; - case KCalCore::Recurrence::rWeekly: + case KCalendarCore::Recurrence::rWeekly: if (recurrenceType != RecurrenceTypeWeekly || mUi->mFrequencyEdit->value() != recurrence->frequency() || mUi->mWeekDayCombo->days() != recurrence->days()) { return true; } break; - case KCalCore::Recurrence::rMonthlyDay: + case KCalendarCore::Recurrence::rMonthlyDay: if (recurrenceType != RecurrenceTypeMonthly || mUi->mFrequencyEdit->value() != recurrence->frequency() || mUi->mMonthlyCombo->currentIndex() != mMonthlyInitialType) { return true; } break; - case KCalCore::Recurrence::rMonthlyPos: + case KCalendarCore::Recurrence::rMonthlyPos: if (recurrenceType != RecurrenceTypeMonthly || mUi->mFrequencyEdit->value() != recurrence->frequency() || mUi->mMonthlyCombo->currentIndex() != mMonthlyInitialType) { return true; } break; - case KCalCore::Recurrence::rYearlyDay: + case KCalendarCore::Recurrence::rYearlyDay: if (recurrenceType != RecurrenceTypeYearly || mUi->mFrequencyEdit->value() != recurrence->frequency() || mUi->mYearlyCombo->currentIndex() != mYearlyInitialType) { return true; } break; - case KCalCore::Recurrence::rYearlyMonth: + case KCalendarCore::Recurrence::rYearlyMonth: if (recurrenceType != RecurrenceTypeYearly || mUi->mFrequencyEdit->value() != recurrence->frequency() || mUi->mYearlyCombo->currentIndex() != mYearlyInitialType) { return true; } break; - case KCalCore::Recurrence::rYearlyPos: + case KCalendarCore::Recurrence::rYearlyPos: if (recurrenceType != RecurrenceTypeYearly || mUi->mFrequencyEdit->value() != recurrence->frequency() || mUi->mYearlyCombo->currentIndex() != mYearlyInitialType) { return true; } break; } // Recurrence end // -1 means "recurs forever" if (recurrence->duration() == -1 && mUi->mRecurrenceEndCombo->currentIndex() != RecurrenceEndNever) { return true; } else if (recurrence->duration() == 0) { // 0 means "end date is set" if (mUi->mRecurrenceEndCombo->currentIndex() != RecurrenceEndOn || recurrence->endDate() != mUi->mRecurrenceEndDate->date()) { return true; } } else if (recurrence->duration() > 0) { if (mUi->mEndDurationEdit->value() != recurrence->duration() || mUi->mRecurrenceEndCombo->currentIndex() != RecurrenceEndAfter) { return true; } } // Exceptions if (mExceptionDates != recurrence->exDates()) { return true; } return false; } bool IncidenceRecurrence::isValid() const { mLastErrorString.clear(); if (currentRecurrenceType() == IncidenceEditorNG::RecurrenceTypeException) { //Nothing you can do wrong here return true; } - KCalCore::Incidence::Ptr incidence(mLoadedIncidence->clone()); + KCalendarCore::Incidence::Ptr incidence(mLoadedIncidence->clone()); // Write start and end dates to the incidence mDateTime->save(incidence); // Write new recurring parameters to incidence writeToIncidence(incidence); // Check if the incidence will occur at least once if (incidence->recurs()) { // dtStart for events, dtDue for to-dos const QDateTime referenceDate - = incidence->dateTime(KCalCore::Incidence::RoleRecurrenceStart); + = incidence->dateTime(KCalendarCore::Incidence::RoleRecurrenceStart); if (referenceDate.isValid()) { if (!(incidence->recurrence()->recursOn(referenceDate.date(), referenceDate.timeZone()) || incidence->recurrence()->getNextDateTime(referenceDate).isValid())) { mLastErrorString = i18n("A recurring event or to-do must occur at least once. " "Adjust the recurring parameters."); qCDebug(INCIDENCEEDITOR_LOG) << mLastErrorString; return false; } } else { mLastErrorString = i18n("The incidence's start date is invalid."); qCDebug(INCIDENCEEDITOR_LOG) << mLastErrorString; return false; } if (mUi->mRecurrenceEndCombo->currentIndex() == RecurrenceEndOn && !mUi->mRecurrenceEndDate->date().isValid()) { qCWarning(INCIDENCEEDITOR_LOG) << "Recurrence end date is invalid."; // TODO: strings after freeze return false; } } return true; } void IncidenceRecurrence::addException() { const QDate date = mUi->mExceptionDateEdit->date(); if (!date.isValid()) { qCWarning(INCIDENCEEDITOR_LOG) << "Refusing to add invalid date"; return; } const QString dateStr = QLocale().toString(date); if (mUi->mExceptionList->findItems(dateStr, Qt::MatchExactly).isEmpty()) { mExceptionDates.append(date); mUi->mExceptionList->addItem(dateStr); } mUi->mExceptionAddButton->setEnabled(false); checkDirtyStatus(); } void IncidenceRecurrence::fillCombos() { if (!currentDate().isValid()) { // Can happen if you're editing with keyboard return; } // Next the monthly combo. This contains the following elements: // - nth day of the month // - (month.lastDay() - n)th day of the month // - the ith ${weekday} of the month // - the (month.weekCount() - i)th day of the month const int currentMonthlyIndex = mUi->mMonthlyCombo->currentIndex(); mUi->mMonthlyCombo->clear(); const QDate date = mDateTime->startDate(); QString item = subsOrdinal( ki18nc("example: the 30th", "the %1"), dayOfMonthFromStart()).toString(); mUi->mMonthlyCombo->addItem(item); item = subsOrdinal(ki18nc("example: the 4th to last day", "the %1 to last day"), dayOfMonthFromEnd()).toString(); mUi->mMonthlyCombo->addItem(item); item = subsOrdinal( ki18nc("example: the 5th Wednesday", "the %1 %2"), monthWeekFromStart()). subs(QLocale::system().dayName(date.dayOfWeek(), QLocale::QLocale::LongFormat)).toString(); mUi->mMonthlyCombo->addItem(item); if (monthWeekFromEnd() == 1) { item = ki18nc("example: the last Wednesday", "the last %1"). subs(QLocale::system().dayName(date.dayOfWeek(), QLocale::LongFormat)).toString(); } else { item = subsOrdinal( ki18nc("example: the 5th to last Wednesday", "the %1 to last %2"), monthWeekFromEnd()). subs(QLocale::system().dayName(date.dayOfWeek(), QLocale::LongFormat)).toString(); } mUi->mMonthlyCombo->addItem(item); mUi->mMonthlyCombo->setCurrentIndex(currentMonthlyIndex == -1 ? 0 : currentMonthlyIndex); // Finally the yearly combo. This contains the following options: // - ${n}th of ${long-month-name} // - ${month.lastDay() - n}th last day of ${long-month-name} // - the ${i}th ${weekday} of ${long-month-name} // - the ${month.weekCount() - i}th day of ${long-month-name} // - the ${m}th day of the year const int currentYearlyIndex = mUi->mYearlyCombo->currentIndex(); mUi->mYearlyCombo->clear(); const QString longMonthName = QLocale::system().monthName(date.month(), QLocale::LongFormat); item = subsOrdinal(ki18nc("example: the 5th of June", "the %1 of %2"), date.day()). subs(longMonthName).toString(); mUi->mYearlyCombo->addItem(item); item = subsOrdinal( ki18nc("example: the 3rd to last day of June", "the %1 to last day of %2"), date.daysInMonth() - date.day()).subs(longMonthName).toString(); mUi->mYearlyCombo->addItem(item); item = subsOrdinal( ki18nc("example: the 4th Wednesday of June", "the %1 %2 of %3"), monthWeekFromStart()). subs(QLocale::system().dayName(date.dayOfWeek(), QLocale::LongFormat)). subs(longMonthName).toString(); mUi->mYearlyCombo->addItem(item); if (monthWeekFromEnd() == 1) { item = ki18nc("example: the last Wednesday of June", "the last %1 of %2"). subs(QLocale::system().dayName(date.dayOfWeek(), QLocale::LongFormat)). subs(longMonthName).toString(); } else { item = subsOrdinal( ki18nc("example: the 4th to last Wednesday of June", "the %1 to last %2 of %3 "), monthWeekFromEnd()). subs(QLocale::system().dayName(date.dayOfWeek(), QLocale::LongFormat)). subs(longMonthName).toString(); } mUi->mYearlyCombo->addItem(item); item = subsOrdinal( ki18nc("example: the 15th day of the year", "the %1 day of the year"), date.dayOfYear()).toString(); mUi->mYearlyCombo->addItem(item); mUi->mYearlyCombo->setCurrentIndex(currentYearlyIndex == -1 ? 0 : currentYearlyIndex); } void IncidenceRecurrence::handleDateTimeToggle() { QWidget *parent = mUi->mRepeatStack->parentWidget(); // Take the parent of a toplevel widget; if (parent) { parent->setEnabled(mDateTime->startDateTimeEnabled()); } } void IncidenceRecurrence::handleEndAfterOccurrencesChange(int currentValue) { mUi->mRecurrenceOccurrencesLabel->setText( i18ncp("Recurrence ends after n occurrences", "occurrence", "occurrences", currentValue)); } void IncidenceRecurrence::handleExceptionDateChange(const QDate ¤tDate) { const QDate date = mUi->mExceptionDateEdit->date(); const QString dateStr = QLocale().toString(date); mUi->mExceptionAddButton->setEnabled( currentDate >= mDateTime->startDate() && mUi->mExceptionList->findItems(dateStr, Qt::MatchExactly).isEmpty()); } void IncidenceRecurrence::handleFrequencyChange() { handleRecurrenceTypeChange(currentRecurrenceType()); } void IncidenceRecurrence::handleRecurrenceTypeChange(int currentIndex) { toggleRecurrenceWidgets(currentIndex); QString labelFreq; QString freqKey; int frequency = mUi->mFrequencyEdit->value(); switch (currentIndex) { case 2: labelFreq = i18ncp("repeat every N >weeks<", "week", "weeks", frequency); freqKey = QLatin1Char('w'); break; case 3: labelFreq = i18ncp("repeat every N >months<", "month", "months", frequency); freqKey = QLatin1Char('m'); break; case 4: labelFreq = i18ncp("repeat every N >years<", "year", "years", frequency); freqKey = QLatin1Char('y'); break; default: labelFreq = i18ncp("repeat every N >days<", "day", "days", frequency); freqKey = QLatin1Char('d'); } const QString labelEvery = ki18ncp("repeat >every< N years/months/...; " "dynamic context 'type': 'd' days, 'w' weeks, " "'m' months, 'y' years", "every", "every"). subs(frequency).inContext(QStringLiteral("type"), freqKey).toString(); mUi->mFrequencyLabel->setText(labelEvery); mUi->mRecurrenceRuleLabel->setText(labelFreq); Q_EMIT recurrenceChanged(static_cast(currentIndex)); } void IncidenceRecurrence::removeExceptions() { const QList selectedExceptions = mUi->mExceptionList->selectedItems(); for (QListWidgetItem *selectedException : selectedExceptions) { const int row = mUi->mExceptionList->row(selectedException); mExceptionDates.removeAt(row); delete mUi->mExceptionList->takeItem(row); } handleExceptionDateChange(mUi->mExceptionDateEdit->date()); checkDirtyStatus(); } void IncidenceRecurrence::updateRemoveExceptionButton() { mUi->mExceptionRemoveButton->setEnabled(!mUi->mExceptionList->selectedItems().isEmpty()); } void IncidenceRecurrence::updateWeekDays(const QDate &newStartDate) { const int oldStartDayIndex = mUi->mWeekDayCombo->weekdayIndex(mCurrentDate); const int newStartDayIndex = mUi->mWeekDayCombo->weekdayIndex(newStartDate); if (oldStartDayIndex >= 0) { mUi->mWeekDayCombo->setItemCheckState(oldStartDayIndex, Qt::Unchecked); mUi->mWeekDayCombo->setItemEnabled(oldStartDayIndex, true); } if (newStartDayIndex >= 0) { mUi->mWeekDayCombo->setItemCheckState(newStartDayIndex, Qt::Checked); mUi->mWeekDayCombo->setItemEnabled(newStartDayIndex, false); } if (newStartDate.isValid()) { mCurrentDate = newStartDate; } } short IncidenceRecurrence::dayOfMonthFromStart() const { return currentDate().day(); } short IncidenceRecurrence::dayOfMonthFromEnd() const { const QDate start = currentDate(); return start.daysInMonth() - start.day() + 1; } short IncidenceRecurrence::dayOfYearFromStart() const { return currentDate().dayOfYear(); } int IncidenceRecurrence::duration() const { if (mUi->mRecurrenceEndCombo->currentIndex() == RecurrenceEndNever) { return -1; } else if (mUi->mRecurrenceEndCombo->currentIndex() == RecurrenceEndAfter) { return mUi->mEndDurationEdit->value(); } else { // 0 means "end date set" return 0; } } short IncidenceRecurrence::monthWeekFromStart() const { const QDate date = currentDate(); int count; if (date.isValid()) { count = 1; QDate tmp = date.addDays(-7); while (tmp.month() == date.month()) { tmp = tmp.addDays(-7); // Count backward ++count; } } else { // date can be invalid if you're editing the date with your keyboard count = -1; } // 1 is the first week, 4/5 is the last week of the month return count; } short IncidenceRecurrence::monthWeekFromEnd() const { const QDate date = currentDate(); int count; if (date.isValid()) { count = 1; QDate tmp = date.addDays(7); while (tmp.month() == date.month()) { tmp = tmp.addDays(7); // Count forward ++count; } } else { // date can be invalid if you're editing the date with your keyboard count = -1; } // 1 is the last week, 4/5 is the first week of the month return count; } QString IncidenceRecurrence::numberToString(int number) const { // The code in here was adapted from an article by Johnathan Wood, see: // http://www.blackbeltcoder.com/Articles/strings/converting-numbers-to-ordinal-strings static QString _numSuffixes[] = { QStringLiteral("th"), QStringLiteral("st"), QStringLiteral("nd"), QStringLiteral("rd"), QStringLiteral("th"), QStringLiteral("th"), QStringLiteral("th"), QStringLiteral("th"), QStringLiteral( "th"), QStringLiteral("th") }; int i = (number % 100); int j = (i > 10 && i < 20) ? 0 : (number % 10); return QString::number(number) + _numSuffixes[j]; } -void IncidenceRecurrence::selectMonthlyItem(KCalCore::Recurrence *recurrence, ushort recurenceType) +void IncidenceRecurrence::selectMonthlyItem(KCalendarCore::Recurrence *recurrence, ushort recurenceType) { - Q_ASSERT(recurenceType == KCalCore::Recurrence::rMonthlyPos - || recurenceType == KCalCore::Recurrence::rMonthlyDay); + Q_ASSERT(recurenceType == KCalendarCore::Recurrence::rMonthlyPos + || recurenceType == KCalendarCore::Recurrence::rMonthlyDay); - if (recurenceType == KCalCore::Recurrence::rMonthlyPos) { - QList rmp = recurrence->monthPositions(); + if (recurenceType == KCalendarCore::Recurrence::rMonthlyPos) { + QList rmp = recurrence->monthPositions(); if (rmp.isEmpty()) { return; // Use the default values. Probably marks the editor as dirty } if (rmp.first().pos() > 0) { // nth day // TODO if ( rmp.first().pos() != mDateTime->startDate().day() ) { warn user } // NOTE: This silently changes the recurrence when: // rmp.first().pos() != mDateTime->startDate().day() mUi->mMonthlyCombo->setCurrentIndex(ComboIndexMonthlyPos); } else { // (month.last() - n)th day // TODO: Handle recurrences we cannot represent // QDate startDate = mDateTime->startDate(); // const int dayFromEnd = startDate.daysInMonth() - startDate.day(); // if ( qAbs( rmp.first().pos() ) != dayFromEnd ) { /* warn user */ } mUi->mMonthlyCombo->setCurrentIndex(ComboIndexMonthlyPosInverted); } } else { // Monthly by day // check if we have any setting for which day (vcs import is broken and // does not set any day, thus we need to check) const int day = recurrence->monthDays().isEmpty() ? currentDate().day() : recurrence->monthDays().at(0); // Days from the end are after the ones from the begin, so correct for the // negative sign and add 30 (index starting at 0) // TODO: Do similar checks as in the monthlyPos case if (day > 0 && day <= 31) { mUi->mMonthlyCombo->setCurrentIndex(ComboIndexMonthlyDay); } else if (day < 0) { mUi->mMonthlyCombo->setCurrentIndex(ComboIndexMonthlyDayInverted); } } // So we can easily detect if the user changed the type, without going through this logic ^ mMonthlyInitialType = mUi->mMonthlyCombo->currentIndex(); } -void IncidenceRecurrence::selectYearlyItem(KCalCore::Recurrence *recurrence, ushort recurenceType) +void IncidenceRecurrence::selectYearlyItem(KCalendarCore::Recurrence *recurrence, ushort recurenceType) { - Q_ASSERT(recurenceType == KCalCore::Recurrence::rYearlyDay - || recurenceType == KCalCore::Recurrence::rYearlyMonth - || recurenceType == KCalCore::Recurrence::rYearlyPos); + Q_ASSERT(recurenceType == KCalendarCore::Recurrence::rYearlyDay + || recurenceType == KCalendarCore::Recurrence::rYearlyMonth + || recurenceType == KCalendarCore::Recurrence::rYearlyPos); - if (recurenceType == KCalCore::Recurrence::rYearlyDay) { + if (recurenceType == KCalendarCore::Recurrence::rYearlyDay) { /* const int day = recurrence->yearDays().isEmpty() ? currentDate().dayOfYear() : recurrence->yearDays().first(); */ // TODO Check if day has actually the same value as in the combo. mUi->mYearlyCombo->setCurrentIndex(ComboIndexYearlyDay); - } else if (recurenceType == KCalCore::Recurrence::rYearlyMonth) { + } else if (recurenceType == KCalendarCore::Recurrence::rYearlyMonth) { const int day = recurrence->yearDates().isEmpty() ? currentDate().day() : recurrence->yearDates().at(0); /* int month = currentDate().month(); if ( !recurrence->yearMonths().isEmpty() ) { month = recurrence->yearMonths().first(); } */ // TODO check month and day to be correct values with respect to what is // presented in the combo box. if (day > 0) { mUi->mYearlyCombo->setCurrentIndex(ComboIndexYearlyMonth); } else { mUi->mYearlyCombo->setCurrentIndex(ComboIndexYearlyMonthInverted); } - } else { //KCalCore::Recurrence::rYearlyPos + } else { //KCalendarCore::Recurrence::rYearlyPos /* int month = currentDate().month(); if ( !recurrence->yearMonths().isEmpty() ) { month = recurrence->yearMonths().first(); } */ // count is the nth weekday of the month or the ith last weekday of the month. int count = (currentDate().day() - 1) / 7; if (!recurrence->yearPositions().isEmpty()) { count = recurrence->yearPositions().at(0).pos(); } // TODO check month,count and day to be correct values with respect to what is // presented in the combo box. if (count > 0) { mUi->mYearlyCombo->setCurrentIndex(ComboIndexYearlyPos); } else { mUi->mYearlyCombo->setCurrentIndex(ComboIndexYearlyPosInverted); } } // So we can easily detect if the user changed the type, without going through this logic ^ mYearlyInitialType = mUi->mYearlyCombo->currentIndex(); } void IncidenceRecurrence::setDefaults() { mUi->mRecurrenceEndCombo->setCurrentIndex(RecurrenceEndNever); mUi->mRecurrenceEndDate->setDate(currentDate()); mUi->mRecurrenceTypeCombo->setCurrentIndex(RecurrenceTypeNone); setFrequency(1); // -1 because we want between 0 and 6 const int day = currentDate().dayOfWeek() - 1; QBitArray checkDays(7, 0); checkDays.setBit(day); QBitArray disableDays(7, 0); disableDays.setBit(day); mUi->mWeekDayCombo->setDays(checkDays, disableDays); mUi->mMonthlyCombo->setCurrentIndex(0); // Recur on the nth of the month mUi->mYearlyCombo->setCurrentIndex(0); // Recur on the nth of the month } void IncidenceRecurrence::setDuration(int duration) { if (duration == -1) { // No end date mUi->mRecurrenceEndCombo->setCurrentIndex(RecurrenceEndNever); mUi->mRecurrenceEndStack->setCurrentIndex(0); } else if (duration == 0) { mUi->mRecurrenceEndCombo->setCurrentIndex(RecurrenceEndOn); mUi->mRecurrenceEndStack->setCurrentIndex(1); } else { mUi->mRecurrenceEndCombo->setCurrentIndex(RecurrenceEndAfter); mUi->mRecurrenceEndStack->setCurrentIndex(2); mUi->mEndDurationEdit->setValue(duration); } } -void IncidenceRecurrence::setExceptionDates(const KCalCore::DateList &dates) +void IncidenceRecurrence::setExceptionDates(const KCalendarCore::DateList &dates) { mUi->mExceptionList->clear(); mExceptionDates.clear(); - KCalCore::DateList::ConstIterator dit; + KCalendarCore::DateList::ConstIterator dit; for (dit = dates.begin(); dit != dates.end(); ++dit) { mUi->mExceptionList->addItem(QLocale().toString(*dit)); mExceptionDates.append(*dit); } } void IncidenceRecurrence::setFrequency(int frequency) { if (frequency < 1) { frequency = 1; } mUi->mFrequencyEdit->setValue(frequency); } void IncidenceRecurrence::toggleRecurrenceWidgets(int recurrenceType) { bool enable = (recurrenceType != RecurrenceTypeNone) && (recurrenceType != RecurrenceTypeException); mUi->mRecurrenceTypeCombo->setVisible(recurrenceType != RecurrenceTypeException); mUi->mRepeatLabel->setVisible(recurrenceType != RecurrenceTypeException); mUi->mRecurrenceEndLabel->setVisible(enable); mUi->mOnLabel->setVisible(enable && recurrenceType != RecurrenceTypeDaily); if (!enable) { // So we can hide the exceptions labels and not trigger column resizing. mUi->mRepeatLabel->setMinimumSize(mUi->mExceptionsLabel->sizeHint()); } mUi->mFrequencyLabel->setVisible(enable); mUi->mFrequencyEdit->setVisible(enable); mUi->mRecurrenceRuleLabel->setVisible(enable); mUi->mRepeatStack->setVisible(enable && recurrenceType != RecurrenceTypeDaily); mUi->mRepeatStack->setCurrentIndex(recurrenceType); mUi->mRecurrenceEndCombo->setVisible(enable); mUi->mEndDurationEdit->setVisible(enable); mUi->mRecurrenceEndStack->setVisible(enable); // Exceptions widgets mUi->mExceptionsLabel->setVisible(enable); mUi->mExceptionDateEdit->setVisible(enable); mUi->mExceptionAddButton->setVisible(enable); mUi->mExceptionAddButton->setEnabled(mUi->mExceptionDateEdit->date() >= currentDate()); mUi->mExceptionRemoveButton->setVisible(enable); mUi->mExceptionRemoveButton->setEnabled(!mUi->mExceptionList->selectedItems().isEmpty()); mUi->mExceptionList->setVisible(enable); mUi->mThisAndFutureCheck->setVisible(recurrenceType == RecurrenceTypeException); } QBitArray IncidenceRecurrence::weekday() const { QBitArray days(7); // QDate::dayOfWeek() -> returns [1 - 7], 1 == monday days.setBit(currentDate().dayOfWeek() - 1, true); return days; } int IncidenceRecurrence::weekdayCountForMonth(const QDate &date) const { Q_ASSERT(date.isValid()); // This methods returns how often the weekday specified by @param date occurs // in the month represented by @param date. int count = 1; QDate tmp = date.addDays(-7); while (tmp.month() == date.month()) { tmp = tmp.addDays(-7); ++count; } tmp = date.addDays(7); while (tmp.month() == date.month()) { tmp = tmp.addDays(7); ++count; } return count; } RecurrenceType IncidenceRecurrence::currentRecurrenceType() const { if (mLoadedIncidence && mLoadedIncidence->hasRecurrenceId()) { return RecurrenceTypeException; } const int currentIndex = mUi->mRecurrenceTypeCombo->currentIndex(); Q_ASSERT_X(currentIndex >= 0 && currentIndex < RecurrenceTypeUnknown, "currentRecurrenceType", "Keep the combo-box values in sync with the enum"); return static_cast(currentIndex); } void IncidenceRecurrence::handleStartDateChange(const QDate &date) { if (currentDate().isValid()) { fillCombos(); updateWeekDays(date); mUi->mExceptionDateEdit->setDate(date); } } QDate IncidenceRecurrence::currentDate() const { return mDateTime->startDate(); } diff --git a/src/incidencerecurrence.h b/src/incidencerecurrence.h index f1839b2..7173bf2 100644 --- a/src/incidencerecurrence.h +++ b/src/incidencerecurrence.h @@ -1,132 +1,132 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCERECURRENCE_H #define INCIDENCEEDITOR_INCIDENCERECURRENCE_H #include "incidenceeditor-ng.h" #include #include namespace Ui { class EventOrTodoDesktop; } namespace IncidenceEditorNG { class IncidenceDateTime; /// Keep this in sync with the values in mUi->mRecurrenceTypeCombo enum RecurrenceType { RecurrenceTypeNone = 0, RecurrenceTypeDaily, RecurrenceTypeWeekly, RecurrenceTypeMonthly, RecurrenceTypeYearly, RecurrenceTypeUnknown, // keep this one at the end of the ones which are also in the combobox RecurrenceTypeException }; class IncidenceRecurrence : public IncidenceEditor { Q_OBJECT public: using IncidenceEditorNG::IncidenceEditor::save; // So we don't trigger -Woverloaded-virtual using IncidenceEditorNG::IncidenceEditor::load; // So we don't trigger -Woverloaded-virtual IncidenceRecurrence(IncidenceDateTime *dateTime, Ui::EventOrTodoDesktop *ui); - void load(const KCalCore::Incidence::Ptr &incidence) override; - void save(const KCalCore::Incidence::Ptr &incidence) override; + void load(const KCalendarCore::Incidence::Ptr &incidence) override; + void save(const KCalendarCore::Incidence::Ptr &incidence) override; Q_REQUIRED_RESULT bool isDirty() const override; Q_REQUIRED_RESULT bool isValid() const override; Q_REQUIRED_RESULT RecurrenceType currentRecurrenceType() const; Q_SIGNALS: void recurrenceChanged(IncidenceEditorNG::RecurrenceType type); private: void addException(); void fillCombos(); void handleDateTimeToggle(); void handleEndAfterOccurrencesChange(int currentValue); void handleExceptionDateChange(const QDate ¤tDate); void handleFrequencyChange(); void handleRecurrenceTypeChange(int currentIndex); void removeExceptions(); void updateRemoveExceptionButton(); void updateWeekDays(const QDate &newStartDate); void handleStartDateChange(const QDate &); /** I needed save() to be const, so created this func. save() calls this now, and changes members outside. */ - void writeToIncidence(const KCalCore::Incidence::Ptr &incidence) const; + void writeToIncidence(const KCalendarCore::Incidence::Ptr &incidence) const; KLocalizedString subsOrdinal(const KLocalizedString &text, int number) const; /** * Return the day in the month/year on which the event recurs, starting at the * beginning/end. Both return a positive number. */ short dayOfMonthFromStart() const; short dayOfMonthFromEnd() const; short dayOfYearFromStart() const; // We don't need from end for year int duration() const; /** Returns the week number (1-5) of the month in which the start date occurs. */ short monthWeekFromStart() const; short monthWeekFromEnd() const; /** DO NOT USE THIS METHOD DIRECTLY use subsOrdinal() instead for i18n * */ QString numberToString(int number) const; - void selectMonthlyItem(KCalCore::Recurrence *recurrence, ushort recurenceType); - void selectYearlyItem(KCalCore::Recurrence *recurrence, ushort recurenceType); + void selectMonthlyItem(KCalendarCore::Recurrence *recurrence, ushort recurenceType); + void selectYearlyItem(KCalendarCore::Recurrence *recurrence, ushort recurenceType); void setDefaults(); void setDuration(int duration); - void setExceptionDates(const KCalCore::DateList &dates); + void setExceptionDates(const KCalendarCore::DateList &dates); void setFrequency(int freq); void toggleRecurrenceWidgets(int enable); /** Returns an array with the weekday on which the event occurs set to 1 */ QBitArray weekday() const; /** * Return how many times the weekday represented by @param date occurs in * the month of @param date. */ int weekdayCountForMonth(const QDate &date) const; QDate currentDate() const; private: Ui::EventOrTodoDesktop *mUi = nullptr; QDate mCurrentDate; IncidenceDateTime *mDateTime = nullptr; - KCalCore::DateList mExceptionDates; + KCalendarCore::DateList mExceptionDates; // So we can easily detect if the user changed the type, // without going through complicated recurrence logic: int mMonthlyInitialType = -1; int mYearlyInitialType = -1; }; } #endif diff --git a/src/incidenceresource.cpp b/src/incidenceresource.cpp index 115197c..2bfb86c 100644 --- a/src/incidenceresource.cpp +++ b/src/incidenceresource.cpp @@ -1,209 +1,209 @@ /* * Copyright (c) 2014 Sandro Knauß * * 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. * * As a special exception, permission is given to link this program * with any edition of Qt, and distribute the resulting executable, * without including the source code for Qt in the source distribution. */ #include "incidenceresource.h" #include "resourcemanagement.h" #include "resourcemodel.h" #include "attendeecomboboxdelegate.h" #include "attendeelineeditdelegate.h" #include "incidencedatetime.h" #include "ui_dialogdesktop.h" #include #include #include using namespace IncidenceEditorNG; class SwitchRoleProxy : public QSortFilterProxyModel { public: explicit SwitchRoleProxy(QObject *parent = nullptr) : QSortFilterProxyModel(parent) { } QVariant data(const QModelIndex &index, int role) const override { QVariant d; if (role == Qt::DisplayRole || role == Qt::EditRole) { d = QSortFilterProxyModel::data(index, ResourceModel::FullName); return d; } d = QSortFilterProxyModel::data(index, role); return d; } }; IncidenceResource::IncidenceResource(IncidenceAttendee *ieAttendee, IncidenceDateTime *dateTime, Ui::EventOrTodoDesktop *ui) : IncidenceEditor(nullptr) , mUi(ui) , dataModel(ieAttendee->dataModel()) , mDateTime(dateTime) , resourceDialog(new ResourceManagement()) { setObjectName(QStringLiteral("IncidenceResource")); connect(resourceDialog, &ResourceManagement::accepted, this, &IncidenceResource::dialogOkPressed); connect(mDateTime, &IncidenceDateTime::startDateChanged, this, &IncidenceResource::slotDateChanged); connect(mDateTime, &IncidenceDateTime::endDateChanged, this, &IncidenceResource::slotDateChanged); QStringList attrs; attrs << QStringLiteral("cn") << QStringLiteral("mail"); completer = new QCompleter(this); ResourceModel *model = new ResourceModel(attrs, this); KDescendantsProxyModel *proxyModel = new KDescendantsProxyModel(this); proxyModel->setSourceModel(model); SwitchRoleProxy *proxyModel2 = new SwitchRoleProxy(this); proxyModel2->setSourceModel(proxyModel); completer->setModel(proxyModel2); completer->setCompletionRole(ResourceModel::FullName); completer->setWrapAround(false); mUi->mNewResource->setCompleter(completer); AttendeeLineEditDelegate *attendeeDelegate = new AttendeeLineEditDelegate(this); ResourceFilterProxyModel *filterProxyModel = new ResourceFilterProxyModel(this); filterProxyModel->setDynamicSortFilter(true); filterProxyModel->setSourceModel(dataModel); mUi->mResourcesTable->setModel(filterProxyModel); mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Role, ieAttendee->roleDelegate()); mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::FullName, attendeeDelegate); mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Status, ieAttendee->stateDelegate()); mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Response, ieAttendee->responseDelegate()); connect(mUi->mFindResourcesButton, &QPushButton::clicked, this, &IncidenceResource::findResources); connect(mUi->mBookResourceButton, &QPushButton::clicked, this, &IncidenceResource::bookResource); connect(filterProxyModel, &ResourceFilterProxyModel::layoutChanged, this, &IncidenceResource::layoutChanged); connect(filterProxyModel, &ResourceFilterProxyModel::layoutChanged, this, &IncidenceResource::updateCount); connect(filterProxyModel, &ResourceFilterProxyModel::rowsInserted, this, &IncidenceResource::updateCount); connect(filterProxyModel, &ResourceFilterProxyModel::rowsRemoved, this, &IncidenceResource::updateCount); // only update when FullName is changed connect(filterProxyModel, &ResourceFilterProxyModel::dataChanged, this, &IncidenceResource::updateCount); } -void IncidenceResource::load(const KCalCore::Incidence::Ptr &incidence) +void IncidenceResource::load(const KCalendarCore::Incidence::Ptr &incidence) { Q_UNUSED(incidence); slotDateChanged(); } void IncidenceResource::slotDateChanged() { resourceDialog->slotDateChanged(mDateTime->startDate(), mDateTime->endDate()); } -void IncidenceResource::save(const KCalCore::Incidence::Ptr &incidence) +void IncidenceResource::save(const KCalendarCore::Incidence::Ptr &incidence) { Q_UNUSED(incidence); //all logic inside IncidenceAtendee (using same model) } bool IncidenceResource::isDirty() const { //all logic inside IncidenceAtendee (using same model) return false; } void IncidenceResource::bookResource() { if (mUi->mNewResource->text().trimmed().isEmpty()) { return; } QString name, email; KEmailAddress::extractEmailAddressAndName(mUi->mNewResource->text(), email, name); - KCalCore::Attendee attendee(name, email); - attendee.setCuType(KCalCore::Attendee::Resource); + KCalendarCore::Attendee attendee(name, email); + attendee.setCuType(KCalendarCore::Attendee::Resource); dataModel->insertAttendee(dataModel->rowCount(), attendee); } void IncidenceResource::findResources() { resourceDialog->show(); } void IncidenceResource::dialogOkPressed() { ResourceItem::Ptr item = resourceDialog->selectedItem(); if (item) { const QString name = QString::fromLatin1(item->ldapObject().value(QStringLiteral("cn"))); const QString email = QString::fromLatin1(item->ldapObject().value(QStringLiteral("mail"))); - KCalCore::Attendee attendee(name, email); - attendee.setCuType(KCalCore::Attendee::Resource); + KCalendarCore::Attendee attendee(name, email); + attendee.setCuType(KCalendarCore::Attendee::Resource); dataModel->insertAttendee(dataModel->rowCount(), attendee); } } void IncidenceResource::layoutChanged() { QHeaderView *headerView = mUi->mResourcesTable->horizontalHeader(); headerView->setSectionHidden(AttendeeTableModel::CuType, true); headerView->setSectionHidden(AttendeeTableModel::Name, true); headerView->setSectionHidden(AttendeeTableModel::Email, true); headerView->setSectionResizeMode(AttendeeTableModel::Role, QHeaderView::ResizeToContents); headerView->setSectionResizeMode(AttendeeTableModel::FullName, QHeaderView::Stretch); headerView->setSectionResizeMode(AttendeeTableModel::Available, QHeaderView::ResizeToContents); headerView->setSectionResizeMode(AttendeeTableModel::Status, QHeaderView::ResizeToContents); headerView->setSectionResizeMode(AttendeeTableModel::Response, QHeaderView::ResizeToContents); } void IncidenceResource::updateCount() { Q_EMIT resourceCountChanged(resourceCount()); } int IncidenceResource::resourceCount() const { int c = 0; QModelIndex index; QAbstractItemModel *model = mUi->mResourcesTable->model(); if (!model) { return 0; } const int nbRow = model->rowCount(QModelIndex()); for (int i = 0; i < nbRow; ++i) { index = model->index(i, AttendeeTableModel::FullName); if (!model->data(index).toString().isEmpty()) { ++c; } } return c; } diff --git a/src/incidenceresource.h b/src/incidenceresource.h index 04f856a..52c0dc9 100644 --- a/src/incidenceresource.h +++ b/src/incidenceresource.h @@ -1,82 +1,82 @@ /* * Copyright (c) 2014 Sandro Knauß * * 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. * * As a special exception, permission is given to link this program * with any edition of Qt, and distribute the resulting executable, * without including the source code for Qt in the source distribution. */ #ifndef INCIDENCEEDITOR_INCIDENCERESOURCE_H #define INCIDENCEEDITOR_INCIDENCERESOURCE_H #include "incidenceeditor-ng.h" #include "incidenceattendee.h" #include "attendeetablemodel.h" #include namespace Ui { class EventOrTodoDesktop; } namespace IncidenceEditorNG { class ResourceManagement; class IncidenceResource : public IncidenceEditor { Q_OBJECT public: using IncidenceEditorNG::IncidenceEditor::save; // So we don't trigger -Woverloaded-virtual using IncidenceEditorNG::IncidenceEditor::load; // So we don't trigger -Woverloaded-virtual explicit IncidenceResource(IncidenceAttendee *mIeAttendee, IncidenceDateTime *dateTime, Ui::EventOrTodoDesktop *ui); - void load(const KCalCore::Incidence::Ptr &incidence) override; - void save(const KCalCore::Incidence::Ptr &incidence) override; + void load(const KCalendarCore::Incidence::Ptr &incidence) override; + void save(const KCalendarCore::Incidence::Ptr &incidence) override; bool isDirty() const override; /** return the count of resources */ Q_REQUIRED_RESULT int resourceCount() const; Q_SIGNALS: /** is emitted it the count of the resources is changed. * @arg: new count of resources. */ void resourceCountChanged(int); private: void findResources(); void bookResource(); void layoutChanged(); void updateCount(); void slotDateChanged(); void dialogOkPressed(); Ui::EventOrTodoDesktop *mUi = nullptr; /** completer for findResources */ QCompleter *completer = nullptr; /** used dataModel to rely on*/ AttendeeTableModel *dataModel = nullptr; IncidenceDateTime *mDateTime = nullptr; ResourceManagement *resourceDialog = nullptr; }; } #endif diff --git a/src/incidencesecrecy.cpp b/src/incidencesecrecy.cpp index 9187885..cac30b4 100644 --- a/src/incidencesecrecy.cpp +++ b/src/incidencesecrecy.cpp @@ -1,83 +1,83 @@ /* Copyright (C) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidencesecrecy.h" #include "ui_dialogdesktop.h" #include using namespace IncidenceEditorNG; IncidenceSecrecy::IncidenceSecrecy(Ui::EventOrTodoDesktop *ui) : mUi(ui) { setObjectName(QStringLiteral("IncidenceSecrecy")); mUi->mSecrecyCombo->addItems(KCalUtils::Stringify::incidenceSecrecyList()); connect(mUi->mSecrecyCombo, qOverload< int>(&QComboBox::currentIndexChanged), this, &IncidenceSecrecy::checkDirtyStatus); } -void IncidenceSecrecy::load(const KCalCore::Incidence::Ptr &incidence) +void IncidenceSecrecy::load(const KCalendarCore::Incidence::Ptr &incidence) { mLoadedIncidence = incidence; if (mLoadedIncidence) { Q_ASSERT(mUi->mSecrecyCombo->count() == KCalUtils::Stringify::incidenceSecrecyList().count()); mUi->mSecrecyCombo->setCurrentIndex(mLoadedIncidence->secrecy()); - if (incidence->type() == KCalCore::Incidence::TypeJournal) { + if (incidence->type() == KCalendarCore::Incidence::TypeJournal) { mUi->mSecrecyCombo->setVisible(false); mUi->mSecrecyLabel->setVisible(false); } } else { mUi->mSecrecyCombo->setCurrentIndex(0); } mWasDirty = false; } -void IncidenceSecrecy::save(const KCalCore::Incidence::Ptr &incidence) +void IncidenceSecrecy::save(const KCalendarCore::Incidence::Ptr &incidence) { Q_ASSERT(incidence); switch (mUi->mSecrecyCombo->currentIndex()) { case 1: - incidence->setSecrecy(KCalCore::Incidence::SecrecyPrivate); + incidence->setSecrecy(KCalendarCore::Incidence::SecrecyPrivate); break; case 2: - incidence->setSecrecy(KCalCore::Incidence::SecrecyConfidential); + incidence->setSecrecy(KCalendarCore::Incidence::SecrecyConfidential); break; default: - incidence->setSecrecy(KCalCore::Incidence::SecrecyPublic); + incidence->setSecrecy(KCalendarCore::Incidence::SecrecyPublic); } } bool IncidenceSecrecy::isDirty() const { if (mLoadedIncidence) { if (mLoadedIncidence->secrecy() != mUi->mSecrecyCombo->currentIndex()) { return true; } } else { if (mUi->mSecrecyCombo->currentIndex() != 0) { return true; } } return false; } diff --git a/src/incidencesecrecy.h b/src/incidencesecrecy.h index d5a1b00..bd0ebef 100644 --- a/src/incidencesecrecy.h +++ b/src/incidencesecrecy.h @@ -1,49 +1,49 @@ /* Copyright (C) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCESECRECY_H #define INCIDENCEEDITOR_INCIDENCESECRECY_H #include "incidenceeditor-ng.h" namespace Ui { class EventOrTodoDesktop; } namespace IncidenceEditorNG { class IncidenceSecrecy : public IncidenceEditor { Q_OBJECT public: using IncidenceEditorNG::IncidenceEditor::save; // So we don't trigger -Woverloaded-virtual using IncidenceEditorNG::IncidenceEditor::load; // So we don't trigger -Woverloaded-virtual explicit IncidenceSecrecy(Ui::EventOrTodoDesktop *ui); - void load(const KCalCore::Incidence::Ptr &incidence) override; - void save(const KCalCore::Incidence::Ptr &incidence) override; + void load(const KCalendarCore::Incidence::Ptr &incidence) override; + void save(const KCalendarCore::Incidence::Ptr &incidence) override; Q_REQUIRED_RESULT bool isDirty() const override; private: Ui::EventOrTodoDesktop *mUi = nullptr; }; } #endif diff --git a/src/incidencewhatwhere.cpp b/src/incidencewhatwhere.cpp index d00c221..2e3567f 100644 --- a/src/incidencewhatwhere.cpp +++ b/src/incidencewhatwhere.cpp @@ -1,95 +1,95 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "incidencewhatwhere.h" #include "ui_dialogdesktop.h" #include "incidenceeditor_debug.h" #include using namespace IncidenceEditorNG; IncidenceWhatWhere::IncidenceWhatWhere(Ui::EventOrTodoDesktop *ui) : IncidenceEditor(nullptr) , mUi(ui) { setObjectName(QStringLiteral("IncidenceWhatWhere")); connect(mUi->mSummaryEdit, &QLineEdit::textChanged, this, &IncidenceWhatWhere::checkDirtyStatus); connect(mUi->mLocationEdit, &QLineEdit::textChanged, this, &IncidenceWhatWhere::checkDirtyStatus); } -void IncidenceWhatWhere::load(const KCalCore::Incidence::Ptr &incidence) +void IncidenceWhatWhere::load(const KCalendarCore::Incidence::Ptr &incidence) { qCDebug(INCIDENCEEDITOR_LOG); mLoadedIncidence = incidence; if (mLoadedIncidence) { mUi->mSummaryEdit->setText(mLoadedIncidence->summary()); mUi->mLocationEdit->setText(mLoadedIncidence->location()); } else { mUi->mSummaryEdit->clear(); mUi->mLocationEdit->clear(); } - mUi->mLocationEdit->setVisible(type() != KCalCore::Incidence::TypeJournal); - mUi->mLocationLabel->setVisible(type() != KCalCore::Incidence::TypeJournal); + mUi->mLocationEdit->setVisible(type() != KCalendarCore::Incidence::TypeJournal); + mUi->mLocationLabel->setVisible(type() != KCalendarCore::Incidence::TypeJournal); mWasDirty = false; } -void IncidenceWhatWhere::save(const KCalCore::Incidence::Ptr &incidence) +void IncidenceWhatWhere::save(const KCalendarCore::Incidence::Ptr &incidence) { Q_ASSERT(incidence); incidence->setSummary(mUi->mSummaryEdit->text()); incidence->setLocation(mUi->mLocationEdit->text()); } bool IncidenceWhatWhere::isDirty() const { if (mLoadedIncidence) { return (mUi->mSummaryEdit->text() != mLoadedIncidence->summary()) || (mUi->mLocationEdit->text() != mLoadedIncidence->location()); } else { return mUi->mSummaryEdit->text().isEmpty() && mUi->mLocationEdit->text().isEmpty(); } } bool IncidenceWhatWhere::isValid() const { if (mUi->mSummaryEdit->text().isEmpty()) { qCDebug(INCIDENCEEDITOR_LOG) << "Specify a title"; mLastErrorString = i18nc("@info", "Please specify a title."); return false; } else { mLastErrorString.clear(); return true; } } void IncidenceWhatWhere::validate() { if (mUi->mSummaryEdit->text().isEmpty()) { mUi->mSummaryEdit->setFocus(); } } diff --git a/src/incidencewhatwhere.h b/src/incidencewhatwhere.h index 2930075..06310b6 100644 --- a/src/incidencewhatwhere.h +++ b/src/incidencewhatwhere.h @@ -1,57 +1,57 @@ /* Copyright (c) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef INCIDENCEEDITOR_INCIDENCEWHATWHERE_H #define INCIDENCEEDITOR_INCIDENCEWHATWHERE_H #include "incidenceeditor-ng.h" namespace Ui { class EventOrTodoDesktop; } namespace IncidenceEditorNG { /** * The IncidenceGeneralEditor keeps track of the following Incidence parts: * - Summary * - Location * - Categories */ class IncidenceWhatWhere : public IncidenceEditor { Q_OBJECT public: using IncidenceEditorNG::IncidenceEditor::save; // So we don't trigger -Woverloaded-virtual using IncidenceEditorNG::IncidenceEditor::load; // So we don't trigger -Woverloaded-virtual explicit IncidenceWhatWhere(Ui::EventOrTodoDesktop *ui); - void load(const KCalCore::Incidence::Ptr &incidence) override; - void save(const KCalCore::Incidence::Ptr &incidence) override; + void load(const KCalendarCore::Incidence::Ptr &incidence) override; + void save(const KCalendarCore::Incidence::Ptr &incidence) override; Q_REQUIRED_RESULT bool isDirty() const override; Q_REQUIRED_RESULT bool isValid() const override; virtual void validate(); private: Ui::EventOrTodoDesktop *mUi = nullptr; }; } // IncidenceEditorNG #endif diff --git a/src/individualmailcomponentfactory.cpp b/src/individualmailcomponentfactory.cpp index dde0f5b..2932bb5 100644 --- a/src/individualmailcomponentfactory.cpp +++ b/src/individualmailcomponentfactory.cpp @@ -1,275 +1,275 @@ /* * Copyright (c) 2014 Sandro Knauß * * 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. * * As a special exception, permission is given to link this program * with any edition of Qt, and distribute the resulting executable, * without including the source code for Qt in the source distribution. */ #include "individualmailcomponentfactory.h" #include "individualmaildialog.h" #include "opencomposerjob.h" #include #include #include #include using namespace IncidenceEditorNG; // IndividualMessageQueueJob -IndividualMessageQueueJob::IndividualMessageQueueJob(const KIdentityManagement::Identity &identity, const KCalCore::Attendee::List &update, const KCalCore::Attendee::List &edit, QObject *parent) +IndividualMessageQueueJob::IndividualMessageQueueJob(const KIdentityManagement::Identity &identity, const KCalendarCore::Attendee::List &update, const KCalendarCore::Attendee::List &edit, QObject *parent) : MailTransport::MessageQueueJob(parent) , mUpdate(update) , mEdit(edit) , mIdentity(identity) , mQueueJob(nullptr) , mComposerJob(nullptr) { } void IndividualMessageQueueJob::start() { QSet attendeesTo(QSet::fromList(addressAttribute().to())); QSet attendeesCc(QSet::fromList(addressAttribute().cc())); QStringList attendeesAutoTo, attendeesAutoCc; - for (const KCalCore::Attendee &attendee : qAsConst(mUpdate)) { + for (const KCalendarCore::Attendee &attendee : qAsConst(mUpdate)) { if (attendeesTo.contains(attendee.email())) { attendeesAutoTo.append(attendee.fullName()); } if (attendeesCc.contains(attendee.email())) { attendeesAutoCc.append(attendee.fullName()); } } if (!attendeesAutoTo.isEmpty() || !attendeesAutoCc.isEmpty() || !addressAttribute().bcc().isEmpty()) { startQueueJob(attendeesAutoTo, addressAttribute().to(), attendeesAutoCc, addressAttribute().cc()); } QStringList attendeesComposerTo, attendeesComposerCc; - for (const KCalCore::Attendee &attendee : qAsConst(mEdit)) { + for (const KCalendarCore::Attendee &attendee : qAsConst(mEdit)) { if (attendeesTo.contains(attendee.email())) { attendeesComposerTo.append(attendee.fullName()); } if (attendeesCc.contains(attendee.email())) { attendeesComposerCc.append(attendee.fullName()); } } if (!attendeesComposerTo.isEmpty() || !attendeesComposerCc.isEmpty()) { startComposerJob(attendeesComposerTo, attendeesComposerCc); } // No subjob has been started if (!mQueueJob && !mComposerJob) { emitResult(); } } void IndividualMessageQueueJob::startQueueJob(const QStringList &messageTo, const QStringList &to, const QStringList &messageCc, const QStringList &cc) { KMime::Message::Ptr msg(message()); msg->to()->fromUnicodeString(messageTo.join(QStringLiteral(", ")), "utf-8"); msg->cc()->fromUnicodeString(messageCc.join(QStringLiteral(", ")), "utf-8"); msg->assemble(); mQueueJob = new MailTransport::MessageQueueJob(this); mQueueJob->setMessage(msg); mQueueJob->transportAttribute().setTransportId(mIdentity.isNull() ? transportAttribute().transportId() : mIdentity.transport().toInt()); mQueueJob->addressAttribute().setFrom(addressAttribute().from()); mQueueJob->addressAttribute().setTo(to); mQueueJob->addressAttribute().setCc(cc); mQueueJob->addressAttribute().setBcc(addressAttribute().bcc()); if (mIdentity.disabledFcc()) { mQueueJob->sentBehaviourAttribute().setSentBehaviour(MailTransport::SentBehaviourAttribute::Delete); } else { const Akonadi::Collection sentCollection(mIdentity.fcc().toLongLong()); if (sentCollection.isValid()) { mQueueJob->sentBehaviourAttribute().setSentBehaviour(MailTransport::SentBehaviourAttribute::MoveToCollection); mQueueJob->sentBehaviourAttribute().setMoveToCollection(sentCollection); } else { mQueueJob->sentBehaviourAttribute().setSentBehaviour( MailTransport::SentBehaviourAttribute::MoveToDefaultSentCollection); } } connect(mQueueJob, &MailTransport::MessageQueueJob::finished, this, &IndividualMessageQueueJob::handleJobFinished); mQueueJob->start(); } void IndividualMessageQueueJob::startComposerJob(const QStringList &to, const QStringList &cc) { mComposerJob = new OpenComposerJob(this, to.join(QStringLiteral(", ")), cc.join(QStringLiteral( ", ")), QString(), message(), mIdentity); connect(mComposerJob, &OpenComposerJob::finished, this, &IndividualMessageQueueJob::handleJobFinished); mComposerJob->start(); } void IndividualMessageQueueJob::handleJobFinished(KJob *job) { if (job->error()) { if (job == mQueueJob && mComposerJob) { mComposerJob->kill(); mComposerJob = nullptr; } else if (job == mComposerJob && mQueueJob) { mQueueJob->kill(); mQueueJob = nullptr; } setError(job->error()); setErrorText(job->errorString()); emitResult(); return; } if (job == mQueueJob) { if (!mComposerJob) { emitResult(); } mQueueJob = nullptr; } else { if (!mQueueJob) { emitResult(); } mComposerJob = nullptr; } } // IndividualMailAskDelegator IndividualMailITIPHandlerDialogDelegate::IndividualMailITIPHandlerDialogDelegate( - const KCalCore::Incidence::Ptr &incidence, KCalCore::iTIPMethod method, QWidget *parent) + const KCalendarCore::Incidence::Ptr &incidence, KCalendarCore::iTIPMethod method, QWidget *parent) : Akonadi::ITIPHandlerDialogDelegate(incidence, method, parent) , mDialog(nullptr) { } -void IndividualMailITIPHandlerDialogDelegate::openDialog(const QString &question, const KCalCore::Attendee::List &attendees, Action action, const KGuiItem &buttonYes, const KGuiItem &buttonNo) +void IndividualMailITIPHandlerDialogDelegate::openDialog(const QString &question, const KCalendarCore::Attendee::List &attendees, Action action, const KGuiItem &buttonYes, const KGuiItem &buttonNo) { switch (action) { case ActionSendMessage: Q_EMIT setUpdate(mIncidence, attendees); Q_EMIT dialogClosed(KMessageBox::Yes, mMethod, mIncidence); break; case ActionDontSendMessage: Q_EMIT dialogClosed(KMessageBox::No, mMethod, mIncidence); break; default: switch (CalendarSupport::KCalPrefs::instance()->sendPolicy()) { case (CalendarSupport::KCalPrefs::InvitationPolicySend): Q_EMIT setUpdate(mIncidence, attendees); Q_EMIT dialogClosed(KMessageBox::Yes, mMethod, mIncidence); break; case (CalendarSupport::KCalPrefs::InvitationPolicyDontSend): Q_EMIT dialogClosed(KMessageBox::No, mMethod, mIncidence); break; case (CalendarSupport::KCalPrefs::InvitationPolicyAsk): default: mDialog = new IndividualMailDialog(question, attendees, buttonYes, buttonNo, mParent); connect(mDialog, &QDialog::finished, this, &IndividualMailITIPHandlerDialogDelegate::onDialogClosed); mDialog->show(); break; } break; } } void IndividualMailITIPHandlerDialogDelegate::openDialogIncidenceCreated(Recipient recipient, const QString &question, Action action, const KGuiItem &buttonYes, const KGuiItem &buttonNo) { if (recipient == Attendees) { openDialog(question, mIncidence->attendees(), action, buttonYes, buttonNo); } else { - KCalCore::Attendee organizer(mIncidence->organizer().name(), mIncidence->organizer().email()); - openDialog(question, KCalCore::Attendee::List() << organizer, action, buttonYes, buttonNo); + KCalendarCore::Attendee organizer(mIncidence->organizer().name(), mIncidence->organizer().email()); + openDialog(question, KCalendarCore::Attendee::List() << organizer, action, buttonYes, buttonNo); } } void IndividualMailITIPHandlerDialogDelegate::openDialogIncidenceModified( bool attendeeStatusChanged, Recipient recipient, const QString &question, Action action, const KGuiItem &buttonYes, const KGuiItem &buttonNo) { Q_UNUSED(attendeeStatusChanged); if (recipient == Attendees) { openDialog(question, mIncidence->attendees(), action, buttonYes, buttonNo); } else { - KCalCore::Attendee organizer(mIncidence->organizer().name(), mIncidence->organizer().email()); - openDialog(question, KCalCore::Attendee::List() << organizer, action, buttonYes, buttonNo); + KCalendarCore::Attendee organizer(mIncidence->organizer().name(), mIncidence->organizer().email()); + openDialog(question, KCalendarCore::Attendee::List() << organizer, action, buttonYes, buttonNo); } } void IndividualMailITIPHandlerDialogDelegate::openDialogIncidenceDeleted(Recipient recipient, const QString &question, Action action, const KGuiItem &buttonYes, const KGuiItem &buttonNo) { if (recipient == Attendees) { openDialog(question, mIncidence->attendees(), action, buttonYes, buttonNo); } else { - KCalCore::Attendee organizer(mIncidence->organizer().name(), mIncidence->organizer().email()); - openDialog(question, KCalCore::Attendee::List() << organizer, action, buttonYes, buttonNo); + KCalendarCore::Attendee organizer(mIncidence->organizer().name(), mIncidence->organizer().email()); + openDialog(question, KCalendarCore::Attendee::List() << organizer, action, buttonYes, buttonNo); } } void IndividualMailITIPHandlerDialogDelegate::onDialogClosed(int result) { if (result == QDialogButtonBox::Yes) { Q_EMIT setEdit(mIncidence, mDialog->editAttendees()); Q_EMIT setUpdate(mIncidence, mDialog->updateAttendees()); Q_EMIT dialogClosed(KMessageBox::Yes, mMethod, mIncidence); } else { Q_EMIT dialogClosed(KMessageBox::No, mMethod, mIncidence); } } // IndividualMailJobFactory IndividualMailComponentFactory::IndividualMailComponentFactory(QObject *parent) : Akonadi::ITIPHandlerComponentFactory(parent) { } MailTransport::MessageQueueJob *IndividualMailComponentFactory::createMessageQueueJob( - const KCalCore::IncidenceBase::Ptr &incidence, const KIdentityManagement::Identity &identity, QObject *parent) + const KCalendarCore::IncidenceBase::Ptr &incidence, const KIdentityManagement::Identity &identity, QObject *parent) { return new IndividualMessageQueueJob(identity, mUpdate.take(incidence->uid()), mEdit.take(incidence->uid()), parent); } Akonadi::ITIPHandlerDialogDelegate *IndividualMailComponentFactory::createITIPHanderDialogDelegate( - const KCalCore::Incidence::Ptr &incidence, KCalCore::iTIPMethod method, QWidget *parent) + const KCalendarCore::Incidence::Ptr &incidence, KCalendarCore::iTIPMethod method, QWidget *parent) { IndividualMailITIPHandlerDialogDelegate *askDelegator = new IndividualMailITIPHandlerDialogDelegate(incidence, method, parent); connect(askDelegator, &IndividualMailITIPHandlerDialogDelegate::setEdit, this, &IndividualMailComponentFactory::onSetEdit); connect(askDelegator, &IndividualMailITIPHandlerDialogDelegate::setUpdate, this, &IndividualMailComponentFactory::onSetUpdate); return askDelegator; } -void IndividualMailComponentFactory::onSetEdit(const KCalCore::Incidence::Ptr &incidence, const KCalCore::Attendee::List &edit) +void IndividualMailComponentFactory::onSetEdit(const KCalendarCore::Incidence::Ptr &incidence, const KCalendarCore::Attendee::List &edit) { mEdit[incidence->uid()] = edit; } -void IndividualMailComponentFactory::onSetUpdate(const KCalCore::Incidence::Ptr &incidence, const KCalCore::Attendee::List &update) +void IndividualMailComponentFactory::onSetUpdate(const KCalendarCore::Incidence::Ptr &incidence, const KCalendarCore::Attendee::List &update) { mUpdate[incidence->uid()] = update; } diff --git a/src/individualmailcomponentfactory.h b/src/individualmailcomponentfactory.h index 30d55e5..5480878 100644 --- a/src/individualmailcomponentfactory.h +++ b/src/individualmailcomponentfactory.h @@ -1,115 +1,115 @@ /* * Copyright (c) 2014 Sandro Knauß * * 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. * * As a special exception, permission is given to link this program * with any edition of Qt, and distribute the resulting executable, * without including the source code for Qt in the source distribution. */ #ifndef INCIDENCEEDITOR_INDIVIDUALMAILCOMPONENTFACTORY_H #define INCIDENCEEDITOR_INDIVIDUALMAILCOMPONENTFACTORY_H #include "incidenceeditor_export.h" #include #include #include namespace IncidenceEditorNG { class OpenComposerJob; class IndividualMailDialog; class IndividualMessageQueueJob : public MailTransport::MessageQueueJob { Q_OBJECT public: - explicit IndividualMessageQueueJob(const KIdentityManagement::Identity &identity, const KCalCore::Attendee::List &update, const KCalCore::Attendee::List &edit, QObject *parent); + explicit IndividualMessageQueueJob(const KIdentityManagement::Identity &identity, const KCalendarCore::Attendee::List &update, const KCalendarCore::Attendee::List &edit, QObject *parent); void start() override; private: void startQueueJob(const QStringList &messageTo, const QStringList &to, const QStringList &messageCc, const QStringList &cc); void startComposerJob(const QStringList &to, const QStringList &cc); void handleJobFinished(KJob *job); - KCalCore::Attendee::List mUpdate; - KCalCore::Attendee::List mEdit; + KCalendarCore::Attendee::List mUpdate; + KCalendarCore::Attendee::List mEdit; KIdentityManagement::Identity mIdentity; MailTransport::MessageQueueJob *mQueueJob = nullptr; OpenComposerJob *mComposerJob = nullptr; }; class IndividualMailITIPHandlerDialogDelegate : public Akonadi::ITIPHandlerDialogDelegate { Q_OBJECT public: - explicit IndividualMailITIPHandlerDialogDelegate(const KCalCore::Incidence::Ptr &incidence, KCalCore::iTIPMethod method, QWidget *parent); + explicit IndividualMailITIPHandlerDialogDelegate(const KCalendarCore::Incidence::Ptr &incidence, KCalendarCore::iTIPMethod method, QWidget *parent); void openDialogIncidenceCreated( Recipient recipient, const QString &question, Action action = ActionAsk, const KGuiItem &buttonYes = KGuiItem(i18nc("@action:button dialog positive answer", "Send Email")), const KGuiItem &buttonNo = KGuiItem(i18nc( "@action:button dialog negative answer", "Do Not Send"))) override; void openDialogIncidenceModified( bool attendeeStatusChanged, Recipient recipient, const QString &question, Action action = ActionAsk, const KGuiItem &buttonYes = KGuiItem(i18nc("@action:button dialog positive answer", "Send Email")), const KGuiItem &buttonNo = KGuiItem(i18nc( "@action:button dialog negative answer", "Do Not Send"))) override; void openDialogIncidenceDeleted( Recipient recipient, const QString &question, Action action = ActionAsk, const KGuiItem &buttonYes = KGuiItem(i18nc("@action:button dialog positive answer", "Send Email")), const KGuiItem &buttonNo = KGuiItem(i18nc( "@action:button dialog negative answer", "Do Not Send"))) override; Q_SIGNALS: - void setEdit(const KCalCore::Incidence::Ptr &incidence, const KCalCore::Attendee::List &edit); - void setUpdate(const KCalCore::Incidence::Ptr &incidence, const KCalCore::Attendee::List &update); + void setEdit(const KCalendarCore::Incidence::Ptr &incidence, const KCalendarCore::Attendee::List &edit); + void setUpdate(const KCalendarCore::Incidence::Ptr &incidence, const KCalendarCore::Attendee::List &update); protected: - void openDialog(const QString &question, const KCalCore::Attendee::List &attendees, Action action, const KGuiItem &buttonYes, const KGuiItem &buttonNo); + void openDialog(const QString &question, const KCalendarCore::Attendee::List &attendees, Action action, const KGuiItem &buttonYes, const KGuiItem &buttonNo); private: void onDialogClosed(int result); IndividualMailDialog *mDialog = nullptr; }; class INCIDENCEEDITOR_EXPORT IndividualMailComponentFactory : public Akonadi:: ITIPHandlerComponentFactory { Q_OBJECT public: explicit IndividualMailComponentFactory(QObject *parent = nullptr); MailTransport::MessageQueueJob *createMessageQueueJob( - const KCalCore::IncidenceBase::Ptr &incidence, const KIdentityManagement::Identity &identity, QObject *parent) override; + const KCalendarCore::IncidenceBase::Ptr &incidence, const KIdentityManagement::Identity &identity, QObject *parent) override; Akonadi::ITIPHandlerDialogDelegate *createITIPHanderDialogDelegate( - const KCalCore::Incidence::Ptr &incidence, KCalCore::iTIPMethod method, QWidget *parent) override; + const KCalendarCore::Incidence::Ptr &incidence, KCalendarCore::iTIPMethod method, QWidget *parent) override; public Q_SLOTS: - void onSetEdit(const KCalCore::Incidence::Ptr &incidence, const KCalCore::Attendee::List &edit); - void onSetUpdate(const KCalCore::Incidence::Ptr &incidence, const KCalCore::Attendee::List &update); + void onSetEdit(const KCalendarCore::Incidence::Ptr &incidence, const KCalendarCore::Attendee::List &edit); + void onSetUpdate(const KCalendarCore::Incidence::Ptr &incidence, const KCalendarCore::Attendee::List &update); private: - QHash mEdit; - QHash mUpdate; + QHash mEdit; + QHash mUpdate; }; } #endif diff --git a/src/individualmaildialog.cpp b/src/individualmaildialog.cpp index a49f4f3..c9e3a91 100644 --- a/src/individualmaildialog.cpp +++ b/src/individualmaildialog.cpp @@ -1,137 +1,137 @@ /* * Copyright (c) 2014 Sandro Knauß * * 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. * * As a special exception, permission is given to link this program * with any edition of Qt, and distribute the resulting executable, * without including the source code for Qt in the source distribution. */ #include "individualmaildialog.h" #include #include #include #include #include #include #include using namespace IncidenceEditorNG; -IndividualMailDialog::IndividualMailDialog(const QString &question, const KCalCore::Attendee::List &attendees, const KGuiItem &buttonYes, const KGuiItem &buttonNo, QWidget *parent) +IndividualMailDialog::IndividualMailDialog(const QString &question, const KCalendarCore::Attendee::List &attendees, const KGuiItem &buttonYes, const KGuiItem &buttonNo, QWidget *parent) : QDialog(parent) { setWindowTitle(i18nc("@title:window", "Group Scheduling Email")); m_detailsWidget = new QWidget(); QGridLayout *layout = new QGridLayout(m_detailsWidget); mAttendeeDecision.reserve(attendees.size()); int row = 0; - for (const KCalCore::Attendee &attendee : attendees) { + for (const KCalendarCore::Attendee &attendee : attendees) { QComboBox *options = new QComboBox(); options->addItem(i18nc("@item:inlistbox ITIP Messages for one attendee", "Send update"), QVariant(Update)); options->addItem(i18nc("@item:inlistbox ITIP Messages for one attendee", "Send no update"), QVariant(NoUpdate)); options->addItem(i18nc("@item:inlistbox ITIP Messages for one attendee", "Edit mail"), QVariant(Edit)); options->setWhatsThis(i18nc("@info:whatsthis", "Options for this particular attendee.")); options->setToolTip(i18nc("@info:tooltip", "Choose an option for this attendee.")); mAttendeeDecision.push_back(std::make_pair(attendee, options)); layout->addWidget(new QLabel(attendee.fullName()), row, 0); layout->addWidget(options, row, 1); ++row; } QSizePolicy sizePolicy = m_detailsWidget->sizePolicy(); sizePolicy.setHorizontalStretch(1); sizePolicy.setVerticalStretch(1); m_detailsWidget->setSizePolicy(sizePolicy); QWidget *mW = new QLabel(question); auto topLayout = new QVBoxLayout(this); topLayout->addWidget(mW); topLayout->addWidget(m_detailsWidget); m_buttons = new QDialogButtonBox(this); m_buttons->setStandardButtons( QDialogButtonBox::Yes | QDialogButtonBox::No | QDialogButtonBox::Help); auto yesButton = m_buttons->button(QDialogButtonBox::Yes); yesButton->setText(buttonYes.text()); connect(yesButton, &QPushButton::clicked, this, [this]() { done(QDialogButtonBox::Yes); }); auto noButton = m_buttons->button(QDialogButtonBox::No); noButton->setText(buttonNo.text()); connect(noButton, &QPushButton::clicked, this, [this]() { done(QDialogButtonBox::No); }); auto detailsButton = m_buttons->button(QDialogButtonBox::Help); detailsButton->setIcon(QIcon::fromTheme(QStringLiteral("help-about"))); connect(detailsButton, &QPushButton::clicked, this, [this]() { m_detailsWidget->setVisible(!m_detailsWidget->isVisible()); updateButtonState(); adjustSize(); }); m_detailsWidget->setVisible(false); updateButtonState(); topLayout->addWidget(m_buttons); } IndividualMailDialog::~IndividualMailDialog() { } -KCalCore::Attendee::List IndividualMailDialog::editAttendees() const +KCalendarCore::Attendee::List IndividualMailDialog::editAttendees() const { - KCalCore::Attendee::List edit; + KCalendarCore::Attendee::List edit; for (auto it = mAttendeeDecision.cbegin(), end = mAttendeeDecision.cend(); it != end; ++it) { const int index = (*it).second->currentIndex(); if ((*it).second->itemData(index, Qt::UserRole) == Edit) { edit.append((*it).first); } } return edit; } -KCalCore::Attendee::List IndividualMailDialog::updateAttendees() const +KCalendarCore::Attendee::List IndividualMailDialog::updateAttendees() const { - KCalCore::Attendee::List update; + KCalendarCore::Attendee::List update; for (auto it = mAttendeeDecision.cbegin(), end = mAttendeeDecision.cend(); it != end; ++it) { const int index = (*it).second->currentIndex(); if ((*it).second->itemData(index, Qt::UserRole) == Update) { update.append((*it).first); } } return update; } void IndividualMailDialog::updateButtonState() { auto detailsButton = m_buttons->button(QDialogButtonBox::Help); if (m_detailsWidget->isVisible()) { detailsButton->setText(i18nc("@action:button show list of attendees", "Individual mailsettings <<")); } else { detailsButton->setText(i18nc("@action:button show list of attendees", "Individual mailsettings >>")); } } diff --git a/src/individualmaildialog.h b/src/individualmaildialog.h index da2e6d5..c5b4c63 100644 --- a/src/individualmaildialog.h +++ b/src/individualmaildialog.h @@ -1,64 +1,64 @@ /* * Copyright (c) 2014 Sandro Knauß * * 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. * * As a special exception, permission is given to link this program * with any edition of Qt, and distribute the resulting executable, * without including the source code for Qt in the source distribution. */ #ifndef INCIDENCEEDITOR_INDIVIDUALMAILDIALOG_H #define INCIDENCEEDITOR_INDIVIDUALMAILDIALOG_H -#include +#include #include #include #include class KGuiItem; class TestIndividualMailDialog; namespace IncidenceEditorNG { // Shows a dialog with a question and the option to select which attendee should get the mail or to open a composer for him. // Used to get individual mails for attendees of an event. class IndividualMailDialog : public QDialog { Q_OBJECT friend class ::TestIndividualMailDialog; public: enum Decisions { Update, /**< send automatic mail to attendee */ NoUpdate, /**< do not send mail to attendee */ Edit /**< open composer for attendee */ }; - explicit IndividualMailDialog(const QString &question, const KCalCore::Attendee::List &attendees, const KGuiItem &buttonYes, const KGuiItem &buttonNo, QWidget *parent = nullptr); + explicit IndividualMailDialog(const QString &question, const KCalendarCore::Attendee::List &attendees, const KGuiItem &buttonYes, const KGuiItem &buttonNo, QWidget *parent = nullptr); ~IndividualMailDialog() override; - Q_REQUIRED_RESULT KCalCore::Attendee::List editAttendees() const; - Q_REQUIRED_RESULT KCalCore::Attendee::List updateAttendees() const; + Q_REQUIRED_RESULT KCalendarCore::Attendee::List editAttendees() const; + Q_REQUIRED_RESULT KCalendarCore::Attendee::List updateAttendees() const; private: void updateButtonState(); - std::vector> mAttendeeDecision; + std::vector> mAttendeeDecision; QDialogButtonBox *m_buttons = nullptr; QWidget *m_detailsWidget = nullptr; }; } #endif diff --git a/src/korganizereditorconfig.cpp b/src/korganizereditorconfig.cpp index d95f241..9e4c241 100644 --- a/src/korganizereditorconfig.cpp +++ b/src/korganizereditorconfig.cpp @@ -1,127 +1,127 @@ /* Copyright (c) 2010 Kevin Ottens 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 "korganizereditorconfig.h" #include using namespace IncidenceEditorNG; KOrganizerEditorConfig::KOrganizerEditorConfig() : EditorConfig() { } KOrganizerEditorConfig::~KOrganizerEditorConfig() { } KConfigSkeleton *KOrganizerEditorConfig::config() const { return CalendarSupport::KCalPrefs::instance(); } QString KOrganizerEditorConfig::fullName() const { return CalendarSupport::KCalPrefs::instance()->fullName(); } QString KOrganizerEditorConfig::email() const { return CalendarSupport::KCalPrefs::instance()->email(); } bool KOrganizerEditorConfig::thatIsMe(const QString &email) const { return CalendarSupport::KCalPrefs::instance()->thatIsMe(email); } QStringList KOrganizerEditorConfig::allEmails() const { return CalendarSupport::KCalPrefs::instance()->allEmails(); } QStringList KOrganizerEditorConfig::fullEmails() const { return CalendarSupport::KCalPrefs::instance()->fullEmails(); } bool KOrganizerEditorConfig::showTimeZoneSelectorInIncidenceEditor() const { return CalendarSupport::KCalPrefs::instance()->showTimeZoneSelectorInIncidenceEditor(); } QDateTime KOrganizerEditorConfig::defaultDuration() const { return CalendarSupport::KCalPrefs::instance()->defaultDuration(); } QDateTime KOrganizerEditorConfig::startTime() const { return CalendarSupport::KCalPrefs::instance()->startTime(); } bool KOrganizerEditorConfig::defaultAudioFileReminders() const { return CalendarSupport::KCalPrefs::instance()->defaultAudioFileReminders(); } QUrl KOrganizerEditorConfig::audioFilePath() const { return QUrl::fromLocalFile(CalendarSupport::KCalPrefs::instance()->audioFilePath()); } int KOrganizerEditorConfig::reminderTime() const { return CalendarSupport::KCalPrefs::instance()->reminderTime(); } int KOrganizerEditorConfig::reminderTimeUnits() const { return CalendarSupport::KCalPrefs::instance()->reminderTimeUnits(); } bool KOrganizerEditorConfig::defaultTodoReminders() const { return CalendarSupport::KCalPrefs::instance()->defaultTodoReminders(); } bool KOrganizerEditorConfig::defaultEventReminders() const { return CalendarSupport::KCalPrefs::instance()->defaultEventReminders(); } QStringList KOrganizerEditorConfig::activeDesignerFields() const { return CalendarSupport::KCalPrefs::instance()->activeDesignerFields(); } -QStringList &KOrganizerEditorConfig::templates(KCalCore::IncidenceBase::IncidenceType type) +QStringList &KOrganizerEditorConfig::templates(KCalendarCore::IncidenceBase::IncidenceType type) { - if (type == KCalCore::IncidenceBase::TypeEvent) { + if (type == KCalendarCore::IncidenceBase::TypeEvent) { //TODO remove mEventTemplates+etc from Prefs::instance() return CalendarSupport::KCalPrefs::instance()->mEventTemplates; } - if (type == KCalCore::IncidenceBase::TypeTodo) { + if (type == KCalendarCore::IncidenceBase::TypeTodo) { return CalendarSupport::KCalPrefs::instance()->mTodoTemplates; } - if (type == KCalCore::IncidenceBase::TypeJournal) { + if (type == KCalendarCore::IncidenceBase::TypeJournal) { return CalendarSupport::KCalPrefs::instance()->mJournalTemplates; } return EditorConfig::templates(type); } diff --git a/src/korganizereditorconfig.h b/src/korganizereditorconfig.h index 09a62f7..00b02bf 100644 --- a/src/korganizereditorconfig.h +++ b/src/korganizereditorconfig.h @@ -1,53 +1,53 @@ /* Copyright (c) 2010 Kevin Ottens 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. */ #ifndef INCIDENCEEDITOR_KORGANIZEREDITORCONFIG_H #define INCIDENCEEDITOR_KORGANIZEREDITORCONFIG_H #include "editorconfig.h" -#include +#include namespace IncidenceEditorNG { class INCIDENCEEDITOR_EXPORT KOrganizerEditorConfig : public IncidenceEditorNG::EditorConfig { public: KOrganizerEditorConfig(); ~KOrganizerEditorConfig() override; KConfigSkeleton *config() const override; Q_REQUIRED_RESULT QString fullName() const override; Q_REQUIRED_RESULT QString email() const override; Q_REQUIRED_RESULT bool thatIsMe(const QString &email) const override; Q_REQUIRED_RESULT QStringList allEmails() const override; Q_REQUIRED_RESULT QStringList fullEmails() const override; Q_REQUIRED_RESULT bool showTimeZoneSelectorInIncidenceEditor() const override; Q_REQUIRED_RESULT QDateTime defaultDuration() const override; Q_REQUIRED_RESULT QDateTime startTime() const override; Q_REQUIRED_RESULT bool defaultAudioFileReminders() const override; Q_REQUIRED_RESULT QUrl audioFilePath() const override; Q_REQUIRED_RESULT int reminderTime() const override; Q_REQUIRED_RESULT int reminderTimeUnits() const override; Q_REQUIRED_RESULT bool defaultTodoReminders() const override; Q_REQUIRED_RESULT bool defaultEventReminders() const override; Q_REQUIRED_RESULT QStringList activeDesignerFields() const override; - Q_REQUIRED_RESULT QStringList &templates(KCalCore::IncidenceBase::IncidenceType type) override; + Q_REQUIRED_RESULT QStringList &templates(KCalendarCore::IncidenceBase::IncidenceType type) override; }; } // IncidenceEditors #endif diff --git a/src/resourcemanagement.cpp b/src/resourcemanagement.cpp index 0dda0a0..8a5c535 100644 --- a/src/resourcemanagement.cpp +++ b/src/resourcemanagement.cpp @@ -1,304 +1,304 @@ /* * Copyright (c) 2014 Sandro Knauß * * 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. * * As a special exception, permission is given to link this program * with any edition of Qt, and distribute the resulting executable, * without including the source code for Qt in the source distribution. */ #include "resourcemanagement.h" #include "ui_resourcemanagement.h" #include "resourcemodel.h" #include "CalendarSupport/FreeBusyItem" #include "CalendarSupport/FreeBusyCalendar" #include "ldaputils.h" #include "freebusyganttproxymodel.h" #include #include #include -#include -#include +#include +#include #include #include #include #include #include #include #include #include #include using namespace IncidenceEditorNG; class FreebusyViewCalendar : public EventViews::ViewCalendar { public: virtual ~FreebusyViewCalendar() { } - bool isValid(const KCalCore::Incidence::Ptr &incidence) const override + bool isValid(const KCalendarCore::Incidence::Ptr &incidence) const override { return isValid(incidence->uid()); } bool isValid(const QString &incidenceIdentifier) const override { return incidenceIdentifier.startsWith(QStringLiteral("fb-")); } - QString displayName(const KCalCore::Incidence::Ptr &incidence) const override + QString displayName(const KCalendarCore::Incidence::Ptr &incidence) const override { Q_UNUSED(incidence); return QStringLiteral("Freebusy"); } - QColor resourceColor(const KCalCore::Incidence::Ptr &incidence) const override + QColor resourceColor(const KCalendarCore::Incidence::Ptr &incidence) const override { bool ok = false; int status = incidence->customProperty(QStringLiteral( "FREEBUSY").toLatin1(), QStringLiteral( "STATUS").toLatin1()).toInt(&ok); if (!ok) { return QColor(85, 85, 85); } switch (status) { - case KCalCore::FreeBusyPeriod::Busy: + case KCalendarCore::FreeBusyPeriod::Busy: return QColor(255, 0, 0); - case KCalCore::FreeBusyPeriod::BusyTentative: - case KCalCore::FreeBusyPeriod::BusyUnavailable: + case KCalendarCore::FreeBusyPeriod::BusyTentative: + case KCalendarCore::FreeBusyPeriod::BusyUnavailable: return QColor(255, 119, 0); - case KCalCore::FreeBusyPeriod::Free: + case KCalendarCore::FreeBusyPeriod::Free: return QColor(0, 255, 0); default: return QColor(85, 85, 85); } } - QString iconForIncidence(const KCalCore::Incidence::Ptr &incidence) const override + QString iconForIncidence(const KCalendarCore::Incidence::Ptr &incidence) const override { Q_UNUSED(incidence); return QString(); } - KCalCore::Calendar::Ptr getCalendar() const override + KCalendarCore::Calendar::Ptr getCalendar() const override { return mCalendar; } - KCalCore::Calendar::Ptr mCalendar; + KCalendarCore::Calendar::Ptr mCalendar; }; ResourceManagement::ResourceManagement(QWidget *parent) : QDialog(parent) { setWindowTitle(i18n("Resource Management")); QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Close, this); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); okButton->setText(i18nc("@action:button add resource to attendeelist", "Book resource")); connect(buttonBox, &QDialogButtonBox::accepted, this, &ResourceManagement::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &ResourceManagement::reject); mUi = new Ui_resourceManagement; QWidget *w = new QWidget(this); mUi->setupUi(w); QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->addWidget(w); mainLayout->addWidget(buttonBox); mModel = new CalendarSupport::FreeBusyItemModel(this); mFreebusyCalendar.setModel(mModel); mAgendaView = new EventViews::AgendaView(QDate(), QDate(), false, false); FreebusyViewCalendar *fbCalendar = new FreebusyViewCalendar(); fbCalendar->mCalendar = mFreebusyCalendar.calendar(); mFbCalendar = EventViews::ViewCalendar::Ptr(fbCalendar); mAgendaView->addCalendar(mFbCalendar); mUi->resourceCalender->addWidget(mAgendaView); QStringList attrs; attrs << QStringLiteral("cn") << QStringLiteral("mail") << QStringLiteral("owner") << QStringLiteral("givenname") << QStringLiteral("sn") << QStringLiteral("kolabDescAttribute") << QStringLiteral("description"); ResourceModel *resourcemodel = new ResourceModel(attrs); mUi->treeResults->setModel(resourcemodel); // This doesn't work till now :(-> that's why i use the click signal mUi->treeResults->setSelectionMode(QAbstractItemView::SingleSelection); selectionModel = mUi->treeResults->selectionModel(); connect(mUi->resourceSearch, &KLineEdit::textChanged, this, &ResourceManagement::slotStartSearch); connect(mUi->treeResults, &QTreeView::clicked, this, &ResourceManagement::slotShowDetails); connect(resourcemodel, &ResourceModel::layoutChanged, this, &ResourceManagement::slotLayoutChanged); readConfig(); } ResourceManagement::~ResourceManagement() { writeConfig(); delete mModel; delete mUi; } void ResourceManagement::readConfig() { KConfigGroup group(KSharedConfig::openConfig(), "ResourceManagement"); const QSize size = group.readEntry("Size", QSize(600, 400)); if (size.isValid()) { resize(size); } } void ResourceManagement::writeConfig() { KConfigGroup group(KSharedConfig::openConfig(), "ResourceManagement"); group.writeEntry("Size", size()); group.sync(); } ResourceItem::Ptr ResourceManagement::selectedItem() const { return mSelectedItem; } void ResourceManagement::slotStartSearch(const QString &text) { (static_cast(mUi->treeResults->model()))->startSearch(text); } void ResourceManagement::slotShowDetails(const QModelIndex ¤t) { ResourceItem::Ptr item = current.model()->data(current, ResourceModel::Resource).value(); mSelectedItem = item; showDetails(item->ldapObject(), item->ldapClient()); } void ResourceManagement::showDetails(const KLDAP::LdapObject &obj, const KLDAP::LdapClient &client) { // Clean up formDetails QLayoutItem *child = nullptr; while ((child = mUi->formDetails->takeAt(0)) != nullptr) { delete child->widget(); delete child; } mUi->groupOwner->setHidden(true); // Fill formDetails with data for (auto it = obj.attributes().cbegin(), end = obj.attributes().cbegin(); it != end; ++it) { const QString &key = it.key(); if (key == QStringLiteral("objectClass") || key == QLatin1String("email")) { continue; } else if (key == QStringLiteral("owner")) { QStringList attrs; attrs << QStringLiteral("cn") << QStringLiteral("mail") << QStringLiteral("mobile") << QStringLiteral("telephoneNumber") << QStringLiteral("kolabDescAttribute") << QStringLiteral("description"); mOwnerItem = ResourceItem::Ptr(new ResourceItem(KLDAP::LdapDN(QString::fromUtf8(it.value().at(0))), attrs, client)); connect( mOwnerItem.data(), &ResourceItem::searchFinished, this, &ResourceManagement::slotOwnerSearchFinished); mOwnerItem->startSearch(); continue; } QStringList list; const QList values = it.value(); list.reserve(values.count()); for (const QByteArray &value: values) { list << QString::fromUtf8(value); } mUi->formDetails->addRow(translateLDAPAttributeForDisplay(key), new QLabel(list.join(QLatin1Char('\n')))); } QString name = QString::fromUtf8(obj.attributes().value(QStringLiteral("cn"))[0]); QString email = QString::fromUtf8(obj.attributes().value(QStringLiteral("mail"))[0]); - KCalCore::Attendee attendee(name, email); + KCalendarCore::Attendee attendee(name, email); CalendarSupport::FreeBusyItem::Ptr freebusy(new CalendarSupport::FreeBusyItem(attendee, this)); mModel->clear(); mModel->addItem(freebusy); } void ResourceManagement::slotLayoutChanged() { const int columnCount = mUi->treeResults->model()->columnCount(QModelIndex()); for (int i = 1; i < columnCount; ++i) { mUi->treeResults->setColumnHidden(i, true); } } void ResourceManagement::slotOwnerSearchFinished() { // Clean up formDetails QLayoutItem *child = nullptr; while ((child = mUi->formOwner->takeAt(0)) != nullptr) { delete child->widget(); delete child; } mUi->groupOwner->setHidden(false); const KLDAP::LdapObject &obj = mOwnerItem->ldapObject(); const KLDAP::LdapAttrMap &ldapAttrMap = obj.attributes(); for (auto it = ldapAttrMap.cbegin(), end = ldapAttrMap.cend(); it != end; ++it) { const QString &key = it.key(); if (key == QStringLiteral("objectClass") || key == QStringLiteral("owner") || key == QStringLiteral("givenname") || key == QStringLiteral("sn")) { continue; } QStringList list; const QList values = it.value(); list.reserve(values.count()); for (const QByteArray &value : values) { list << QString::fromUtf8(value); } mUi->formOwner->addRow(translateLDAPAttributeForDisplay(key), new QLabel(list.join(QLatin1Char('\n')))); } } void ResourceManagement::slotDateChanged(const QDate &start, const QDate &end) { if (start.daysTo(end) < 7) { mAgendaView->showDates(start, start.addDays(7)); } mAgendaView->showDates(start, end); } diff --git a/src/resourcemanagement.h b/src/resourcemanagement.h index c5646d3..8dfcc31 100644 --- a/src/resourcemanagement.h +++ b/src/resourcemanagement.h @@ -1,98 +1,98 @@ /* * Copyright (c) 2014 Sandro Knauß * * 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. * * As a special exception, permission is given to link this program * with any edition of Qt, and distribute the resulting executable, * without including the source code for Qt in the source distribution. */ #ifndef RESOURCEMANAGEMENT_H #define RESOURCEMANAGEMENT_H #include "incidenceeditor_export.h" #include #include #include "CalendarSupport/FreeBusyCalendar" #include "resourceitem.h" #include #include class Ui_resourceManagement; class QItemSelectionModel; namespace EventViews { class AgendaView; } namespace IncidenceEditorNG { class INCIDENCEEDITOR_EXPORT ResourceManagement : public QDialog { Q_OBJECT public: explicit ResourceManagement(QWidget *parent = nullptr); ~ResourceManagement(); Q_REQUIRED_RESULT ResourceItem::Ptr selectedItem() const; public Q_SLOTS: void slotDateChanged(const QDate &start, const QDate &end); private: /* Shows the details of a resource * */ void showDetails(const KLDAP::LdapObject &, const KLDAP::LdapClient &client); QItemSelectionModel *selectionModel = nullptr; private: /* A new searchString is entered * */ void slotStartSearch(const QString &); /* A detail view is requested * */ void slotShowDetails(const QModelIndex ¤t); /** * The Owner search is done */ void slotOwnerSearchFinished(); void slotLayoutChanged(); private: void readConfig(); void writeConfig(); CalendarSupport::FreeBusyItemModel *mModel = nullptr; CalendarSupport::FreeBusyCalendar mFreebusyCalendar; ResourceItem::Ptr mOwnerItem; ResourceItem::Ptr mSelectedItem; EventViews::ViewCalendar::Ptr mFbCalendar; Ui_resourceManagement *mUi = nullptr; - QMap mFbEvent; + QMap mFbEvent; EventViews::AgendaView *mAgendaView = nullptr; }; } #endif // RESOURCEMANAGEMENT_H diff --git a/src/schedulingdialog.cpp b/src/schedulingdialog.cpp index d6a8635..185d38a 100644 --- a/src/schedulingdialog.cpp +++ b/src/schedulingdialog.cpp @@ -1,228 +1,228 @@ /* Copyright (C) 2010 Casey Link Copyright (C) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "schedulingdialog.h" #include "conflictresolver.h" #include "CalendarSupport/FreePeriodModel" #include "visualfreebusywidget.h" #include #include #include #include #include #include using namespace IncidenceEditorNG; SchedulingDialog::SchedulingDialog(const QDate &startDate, const QTime &startTime, int duration, ConflictResolver *resolver, QWidget *parent) : QDialog(parent) , mResolver(resolver) , mPeriodModel(new CalendarSupport::FreePeriodModel(this)) { setWindowTitle(i18n("Scheduling")); QVBoxLayout *mainLayout = new QVBoxLayout(this); QWidget *w = new QWidget(this); setupUi(w); QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, &QDialogButtonBox::accepted, this, &SchedulingDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &SchedulingDialog::reject); mainLayout->addWidget(w); mainLayout->addWidget(buttonBox); fillCombos(); Q_ASSERT(duration > 0); mDuration = duration; mVisualWidget = new VisualFreeBusyWidget(resolver->model(), 8); QVBoxLayout *ganttlayout = new QVBoxLayout(mGanttTab); mGanttTab->setLayout(ganttlayout); ganttlayout->addWidget(mVisualWidget); connect(mStartDate, &KDateComboBox::dateEdited, mResolver, &ConflictResolver::setEarliestDate); connect(mStartTime, &KTimeComboBox::timeEdited, mResolver, &ConflictResolver::setEarliestTime); connect(mEndDate, &KDateComboBox::dateEdited, mResolver, &ConflictResolver::setLatestDate); connect(mEndTime, &KTimeComboBox::timeEdited, mResolver, &ConflictResolver::setLatestTime); connect(mStartDate, &KDateComboBox::dateEdited, this, &SchedulingDialog::slotStartDateChanged); connect(mWeekdayCombo, &KPIM::KWeekdayCheckCombo::checkedItemsChanged, this, &SchedulingDialog::slotWeekdaysChanged); connect(mWeekdayCombo, &KPIM::KWeekdayCheckCombo::checkedItemsChanged, this, &SchedulingDialog::slotMandatoryRolesChanged); connect(mResolver, &ConflictResolver::freeSlotsAvailable, mPeriodModel, &CalendarSupport::FreePeriodModel::slotNewFreePeriods); connect(mMoveBeginTimeEdit, &KTimeComboBox::timeEdited, this, &SchedulingDialog::slotSetEndTimeLabel); mTableView->setModel(mPeriodModel); connect( mTableView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &SchedulingDialog::slotRowSelectionChanged); mStartDate->setDate(startDate); mEndDate->setDate(mStartDate->date().addDays(7)); mStartTime->setTime(startTime); mEndTime->setTime(startTime); mResolver->setEarliestDate(mStartDate->date()); mResolver->setEarliestTime(mStartTime->time()); mResolver->setLatestDate(mEndDate->date()); mResolver->setLatestTime(mEndTime->time()); mMoveApptGroupBox->hide(); } SchedulingDialog::~SchedulingDialog() { } void SchedulingDialog::slotUpdateIncidenceStartEnd(const QDateTime &startDateTime, const QDateTime &endDateTime) { mVisualWidget->slotUpdateIncidenceStartEnd(startDateTime, endDateTime); } void SchedulingDialog::fillCombos() { // Note: we depend on the following order mRolesCombo->addItem(QIcon::fromTheme(QStringLiteral("meeting-participant")), - KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::ReqParticipant)); + KCalUtils::Stringify::attendeeRole(KCalendarCore::Attendee::ReqParticipant)); mRolesCombo->addItem(QIcon::fromTheme(QStringLiteral("meeting-participant-optional")), - KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::OptParticipant)); + KCalUtils::Stringify::attendeeRole(KCalendarCore::Attendee::OptParticipant)); mRolesCombo->addItem(QIcon::fromTheme(QStringLiteral("meeting-observer")), - KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::NonParticipant)); + KCalUtils::Stringify::attendeeRole(KCalendarCore::Attendee::NonParticipant)); mRolesCombo->addItem(QIcon::fromTheme(QStringLiteral("meeting-chair")), - KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::Chair)); + KCalUtils::Stringify::attendeeRole(KCalendarCore::Attendee::Chair)); mRolesCombo->setWhatsThis(i18nc("@info:whatsthis", "Edits the role of the attendee.")); mRolesCombo->setItemCheckState(0, Qt::Checked); mRolesCombo->setItemCheckState(1, Qt::Checked); mRolesCombo->setItemCheckState(2, Qt::Checked); mRolesCombo->setItemCheckState(3, Qt::Checked); QBitArray days(7); days.setBit(0); //Monday days.setBit(1); //Tuesday days.setBit(2); //Wednesday days.setBit(3); //Thursday days.setBit(4); //Friday.. surprise! mWeekdayCombo->setDays(days); mResolver->setAllowedWeekdays(days); } void SchedulingDialog::slotStartDateChanged(const QDate &newDate) { QDate oldDate = mStDate; mStDate = newDate; if (newDate.isValid() && oldDate.isValid()) { updateWeekDays(oldDate); } } void SchedulingDialog::updateWeekDays(const QDate &oldDate) { const int oldStartDayIndex = mWeekdayCombo->weekdayIndex(oldDate); const int newStartDayIndex = mWeekdayCombo->weekdayIndex(mStDate); mWeekdayCombo->setItemCheckState(oldStartDayIndex, Qt::Unchecked); mWeekdayCombo->setItemEnabled(oldStartDayIndex, true); mWeekdayCombo->setItemCheckState(newStartDayIndex, Qt::Checked); mWeekdayCombo->setItemEnabled(newStartDayIndex, false); } void SchedulingDialog::slotWeekdaysChanged() { // notify the resolver mResolver->setAllowedWeekdays(mWeekdayCombo->days()); } void SchedulingDialog::slotMandatoryRolesChanged() { - QSet roles; + QSet roles; for (int i = 0; i < mRolesCombo->count(); ++i) { if (mRolesCombo->itemCheckState(i) == Qt::Checked) { - roles << KCalCore::Attendee::Role(i); + roles << KCalendarCore::Attendee::Role(i); } } mResolver->setMandatoryRoles(roles); } void SchedulingDialog::slotRowSelectionChanged(const QModelIndex ¤t, const QModelIndex &previous) { Q_UNUSED(previous); if (!current.isValid()) { mMoveApptGroupBox->hide(); return; } - KCalCore::Period period - = current.data(CalendarSupport::FreePeriodModel::PeriodRole).value(); + KCalendarCore::Period period + = current.data(CalendarSupport::FreePeriodModel::PeriodRole).value(); const QDate startDate = period.start().date(); const int dayOfWeek = startDate.dayOfWeek(); const QString dayLabel = ki18nc("@label Day of week followed by day of the month, then the month. " "Example: Monday, 12 June", "%1, %2 %3"). subs(QLocale::system().dayName(dayOfWeek, QLocale::LongFormat)). subs(startDate.day()). subs(QLocale::system().monthName(startDate.month(), QLocale::LongFormat)).toString(); mMoveDayLabel->setText(dayLabel); mMoveBeginTimeEdit->setTimeRange(period.start().time(), period.end().addSecs(-mDuration).time()); mMoveBeginTimeEdit->setTime(period.start().time()); slotSetEndTimeLabel(period.start().time()); mMoveApptGroupBox->show(); mSelectedDate = startDate; } void SchedulingDialog::slotSetEndTimeLabel(const QTime &startTime) { const QTime endTime = startTime.addSecs(mDuration); const QString endTimeLabel = ki18nc("@label This is a suffix following a time selecting widget. " "Example: [timeedit] to 10:00am", "to %1").subs(QLocale::system().toString(endTime)).toString(); mMoveEndTimeLabel->setText(endTimeLabel); mSelectedTime = startTime; } QDate SchedulingDialog::selectedStartDate() const { return mSelectedDate; } QTime SchedulingDialog::selectedStartTime() const { return mSelectedTime; } diff --git a/src/templatemanagementdialog.h b/src/templatemanagementdialog.h index 31d4dfc..309b42b 100644 --- a/src/templatemanagementdialog.h +++ b/src/templatemanagementdialog.h @@ -1,89 +1,89 @@ /****************************************************************************** ** ** Filename : templatemanagerdialog.h ** Created on : 05 June, 2005 ** Copyright : (c) 2005 Till Adam ** Copyright (C) 2009 Allen Winter ** ******************************************************************************/ /****************************************************************************** ** ** 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. ** ** It 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 ** ** In addition, as a special exception, the copyright holders give ** permission to link the code of this program with any edition of ** the Qt library by Trolltech AS, Norway (or with modified versions ** of Qt that use the same license as Qt), and distribute linked ** combinations including the two. You must obey the GNU General ** Public License in all respects for all of the code used other than ** Qt. If you modify this file, you may extend this exception to ** your version of the file, but you are not obligated to do so. If ** you do not wish to do so, delete this exception statement from ** your version. ** ******************************************************************************/ #ifndef INCIDENCEEDITOR_TEMPLATEMANAGEMENTDIALOG_H #define INCIDENCEEDITOR_TEMPLATEMANAGEMENTDIALOG_H #include "ui_template_management_dialog_base.h" -#include +#include #include namespace IncidenceEditorNG { class TemplateManagementDialog : public QDialog { Q_OBJECT public: TemplateManagementDialog(QWidget *parent, const QStringList &templates, const QString &incidenceType); Q_SIGNALS: /* Emitted whenever the user hits apply, indicating that the currently selected template should be loaded into to the incidence editor which triggered this. */ void loadTemplate(const QString &templateName); /* Emitted whenever the user wants to add the current incidence as a template with the given name. */ void saveTemplate(const QString &templateName); /* Emitted when the dialog changed the list of templates. Calling code can the replace the list that was handed in with the one this signal transports. */ void templatesChanged(const QStringList &templates); protected Q_SLOTS: void slotItemSelected(); void slotAddTemplate(); void slotRemoveTemplate(); void slotApplyTemplate(); void slotOk(); private: void slotHelp(); void updateButtons(); Ui::TemplateManagementDialog_base m_base; QStringList m_templates; QString m_type; QString m_newTemplate; bool m_changed; }; } #endif diff --git a/src/tests/main.cpp b/src/tests/main.cpp index 0a1236c..03bdc4c 100644 --- a/src/tests/main.cpp +++ b/src/tests/main.cpp @@ -1,120 +1,120 @@ /* Copyright (C) 2010 Bertjan Broeksema Copyright (C) 2010 Klaralvdalens Datakonsult AB, a KDAB Group company 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 "korganizereditorconfig.h" #include "incidencedialog.h" #include "incidencedefaults.h" #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include #include using namespace IncidenceEditorNG; int main(int argc, char **argv) { QApplication app(argc, argv); QCoreApplication::setApplicationName(QStringLiteral("IncidenceEditorNGApp")); QCoreApplication::setApplicationVersion(QStringLiteral("0.1")); QCommandLineParser parser; parser.addHelpOption(); parser.addVersionOption(); parser.addOption(QCommandLineOption(QStringLiteral("new-event"), QStringLiteral("Creates a new event"))); parser.addOption(QCommandLineOption(QStringLiteral("new-todo"), QStringLiteral("Creates a new todo"))); parser.addOption(QCommandLineOption(QStringLiteral("new-journal"), QStringLiteral( "Creates a new journal"))); parser.addOption(QCommandLineOption(QStringLiteral("item"), QStringLiteral( "Loads an existing item, or returns without doing anything " "when the item is not an event or todo."), QStringLiteral("id"))); parser.process(app); Akonadi::Item item(-1); IncidenceDefaults defaults; // Set the full emails manually here, to avoid that we get dependencies on // KCalPrefs all over the place. defaults.setFullEmails(CalendarSupport::KCalPrefs::instance()->fullEmails()); // NOTE: At some point this should be generalized. That is, we now use the // freebusy url as a hack, but this assumes that the user has only one // groupware account. Which doesn't have to be the case necessarily. // This method should somehow depend on the calendar selected to which // the incidence is added. if (CalendarSupport::KCalPrefs::instance()->useGroupwareCommunication()) { defaults.setGroupWareDomain( QUrl(Akonadi::CalendarSettings::self()->freeBusyRetrieveUrl()).host()); } if (parser.isSet(QStringLiteral("new-event"))) { std::cout << "Creating new event..." << std::endl; - KCalCore::Event::Ptr event(new KCalCore::Event); + KCalendarCore::Event::Ptr event(new KCalendarCore::Event); defaults.setDefaults(event); - item.setPayload(event); + item.setPayload(event); } else if (parser.isSet(QStringLiteral("new-todo"))) { std::cout << "Creating new todo..." << std::endl; - KCalCore::Todo::Ptr todo(new KCalCore::Todo); + KCalendarCore::Todo::Ptr todo(new KCalendarCore::Todo); defaults.setDefaults(todo); - item.setPayload(todo); + item.setPayload(todo); } else if (parser.isSet(QStringLiteral("new-journal"))) { std::cout << "Creating new journal..." << std::endl; - KCalCore::Journal::Ptr journal(new KCalCore::Journal); + KCalendarCore::Journal::Ptr journal(new KCalendarCore::Journal); defaults.setDefaults(journal); - item.setPayload(journal); + item.setPayload(journal); } else if (parser.isSet(QStringLiteral("item"))) { bool ok = false; qint64 id = parser.value(QStringLiteral("item")).toLongLong(&ok); if (!ok) { std::cerr << "Invalid akonadi item id given." << std::endl; return 1; } item.setId(id); std::cout << "Trying to load Akonadi Item " << QString::number(id).toLatin1().data(); std::cout << "..." << std::endl; } else { std::cerr << "Invalid usage." << std::endl << std::endl; return 1; } EditorConfig::setEditorConfig(new KOrganizerEditorConfig); IncidenceDialog *dialog = new IncidenceDialog(); Akonadi::Collection collection(CalendarSupport::KCalPrefs::instance()->defaultCalendarId()); if (collection.isValid()) { dialog->selectCollection(collection); } dialog->load(item); // The dialog will show up once the item is loaded. return app.exec(); } diff --git a/tests/individualmaildialog_test.cpp b/tests/individualmaildialog_test.cpp index 3effc6c..f9dc115 100644 --- a/tests/individualmaildialog_test.cpp +++ b/tests/individualmaildialog_test.cpp @@ -1,42 +1,42 @@ /* Copyright (C) 2017 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library 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 Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "../src/individualmaildialog.h" #include #include using namespace IncidenceEditorNG; int main(int argc, char **argv) { QApplication app(argc, argv); - KCalCore::Attendee::List attendees; + KCalendarCore::Attendee::List attendees; KGuiItem buttonYes = KGuiItem(QStringLiteral("Send Email")); KGuiItem buttonNo = KGuiItem(QStringLiteral("Do not send")); - KCalCore::Attendee attendee1(QStringLiteral("test1"), QStringLiteral("test1@example.com")); - KCalCore::Attendee attendee2(QStringLiteral("test2"), QStringLiteral("test2@example.com")); - KCalCore::Attendee attendee3(QStringLiteral("test3"), QStringLiteral("test3@example.com")); + KCalendarCore::Attendee attendee1(QStringLiteral("test1"), QStringLiteral("test1@example.com")); + KCalendarCore::Attendee attendee2(QStringLiteral("test2"), QStringLiteral("test2@example.com")); + KCalendarCore::Attendee attendee3(QStringLiteral("test3"), QStringLiteral("test3@example.com")); attendees << attendee1 << attendee2 << attendee3; IndividualMailDialog dialog(QStringLiteral("title"), attendees, buttonYes, buttonNo, nullptr); dialog.show(); return app.exec(); }