File indexing completed on 2024-11-24 04:48:29

0001 /*
0002   This file is part of KOrganizer.
0003 
0004   SPDX-FileCopyrightText: 2000, 2001 Cornelius Schumacher <schumacher@kde.org>
0005   SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
0006 
0007   SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0008 */
0009 
0010 #include "koeventview.h"
0011 #include "kocore.h"
0012 #include "koeventpopupmenu.h"
0013 
0014 #include <Akonadi/CalendarUtils>
0015 #include <Akonadi/EntityTreeModel>
0016 #include <CalendarSupport/KCalPrefs>
0017 
0018 #include "korganizer_debug.h"
0019 #include <KXMLGUIFactory>
0020 
0021 #include <QApplication>
0022 #include <QMenu>
0023 
0024 //---------------------------------------------------------------------------
0025 
0026 KOEventView::KOEventView(QWidget *parent)
0027     : KOrg::BaseView(parent)
0028 {
0029     // AKONADI_PORT review: the FocusLineEdit in the editor emits focusReceivedSignal(),
0030     // which triggered finishTypeAhead. But the global focus widget in QApplication is
0031     // changed later, thus subsequent keyevents still went to this view, triggering
0032     // another editor, for each keypress
0033     // Thus listen to the global focusChanged() signal (seen with Qt 4.6-stable-patched 20091112)
0034     //  -Frank
0035     connect(qobject_cast<QApplication *>(QApplication::instance()), &QApplication::focusChanged, this, &KOEventView::focusChanged);
0036 }
0037 
0038 //---------------------------------------------------------------------------
0039 
0040 KOEventView::~KOEventView() = default;
0041 
0042 //---------------------------------------------------------------------------
0043 
0044 KOEventPopupMenu *KOEventView::eventPopup()
0045 {
0046     auto eventPopup = new KOEventPopupMenu(this);
0047 
0048     connect(eventPopup, &KOEventPopupMenu::editIncidenceSignal, this, &KOEventView::editIncidenceSignal);
0049     connect(eventPopup, &KOEventPopupMenu::showIncidenceSignal, this, &KOEventView::showIncidenceSignal);
0050     connect(eventPopup, &KOEventPopupMenu::deleteIncidenceSignal, this, &KOEventView::deleteIncidenceSignal);
0051     connect(eventPopup, &KOEventPopupMenu::cutIncidenceSignal, this, &KOEventView::cutIncidenceSignal);
0052     connect(eventPopup, &KOEventPopupMenu::copyIncidenceSignal, this, &KOEventView::copyIncidenceSignal);
0053     connect(eventPopup, &KOEventPopupMenu::pasteIncidenceSignal, this, &KOEventView::pasteIncidenceSignal);
0054     connect(eventPopup, &KOEventPopupMenu::toggleAlarmSignal, this, &KOEventView::toggleAlarmSignal);
0055     connect(eventPopup, &KOEventPopupMenu::toggleOccurrenceCompletedSignal, this, &KOEventView::toggleOccurrenceCompletedSignal);
0056     connect(eventPopup, &KOEventPopupMenu::copyIncidenceToResourceSignal, this, &KOEventView::copyIncidenceToResourceSignal);
0057     connect(eventPopup, &KOEventPopupMenu::moveIncidenceToResourceSignal, this, &KOEventView::moveIncidenceToResourceSignal);
0058     connect(eventPopup, &KOEventPopupMenu::dissociateOccurrencesSignal, this, &KOEventView::dissociateOccurrencesSignal);
0059 
0060     return eventPopup;
0061 }
0062 
0063 QMenu *KOEventView::newEventPopup()
0064 {
0065     KXMLGUIClient *client = KOCore::self()->xmlguiClient(this);
0066     if (!client) {
0067         qCCritical(KORGANIZER_LOG) << "no xmlGuiClient.";
0068         return nullptr;
0069     }
0070     if (!client->factory()) {
0071         qCCritical(KORGANIZER_LOG) << "no factory";
0072         return nullptr; // can happen if called too early
0073     }
0074 
0075     return static_cast<QMenu *>(client->factory()->container(QStringLiteral("rmb_selection_popup"), client));
0076 }
0077 
0078 //---------------------------------------------------------------------------
0079 
0080 void KOEventView::popupShow()
0081 {
0082     Q_EMIT showIncidenceSignal(mCurrentIncidence);
0083 }
0084 
0085 //---------------------------------------------------------------------------
0086 
0087 void KOEventView::popupEdit()
0088 {
0089     Q_EMIT editIncidenceSignal(mCurrentIncidence);
0090 }
0091 
0092 //---------------------------------------------------------------------------
0093 
0094 void KOEventView::popupDelete()
0095 {
0096     Q_EMIT deleteIncidenceSignal(mCurrentIncidence);
0097 }
0098 
0099 //---------------------------------------------------------------------------
0100 
0101 void KOEventView::popupCut()
0102 {
0103     Q_EMIT cutIncidenceSignal(mCurrentIncidence);
0104 }
0105 
0106 //---------------------------------------------------------------------------
0107 
0108 void KOEventView::popupCopy()
0109 {
0110     Q_EMIT copyIncidenceSignal(mCurrentIncidence);
0111 }
0112 
0113 //---------------------------------------------------------------------------
0114 
0115 void KOEventView::showNewEventPopup()
0116 {
0117     QMenu *popup = newEventPopup();
0118     if (!popup) {
0119         qCCritical(KORGANIZER_LOG) << "popup creation failed";
0120         return;
0121     }
0122 
0123     popup->popup(QCursor::pos());
0124 }
0125 
0126 //---------------------------------------------------------------------------
0127 
0128 void KOEventView::defaultAction(const Akonadi::Item &aitem)
0129 {
0130     const KCalendarCore::Incidence::Ptr incidence = Akonadi::CalendarUtils::incidence(aitem);
0131     if (!incidence) {
0132         qCDebug(KORGANIZER_LOG) << "Ouch, null incidence";
0133         return;
0134     }
0135 
0136     const auto collection = Akonadi::EntityTreeModel::updatedCollection(model(), aitem.storageCollectionId());
0137     if (collection.rights() & Akonadi::Collection::CanChangeItem) {
0138         Q_EMIT editIncidenceSignal(aitem);
0139     } else {
0140         Q_EMIT showIncidenceSignal(aitem);
0141     }
0142 }
0143 
0144 void KOEventView::setTypeAheadReceiver(QObject *o)
0145 {
0146     mTypeAheadReceiver = o;
0147 }
0148 
0149 void KOEventView::focusChanged(QWidget *, QWidget *now)
0150 {
0151     if (mTypeAhead && now && now == mTypeAheadReceiver) {
0152         finishTypeAhead();
0153     }
0154 }
0155 
0156 void KOEventView::finishTypeAhead()
0157 {
0158     if (mTypeAheadReceiver) {
0159         for (QEvent *e : std::as_const(mTypeAheadEvents)) {
0160             QApplication::sendEvent(mTypeAheadReceiver, e);
0161         }
0162     }
0163     qDeleteAll(mTypeAheadEvents);
0164     mTypeAheadEvents.clear();
0165     mTypeAhead = false;
0166 }
0167 
0168 bool KOEventView::usesCompletedTodoPixmap(const Akonadi::Item &aitem, const QDate &date)
0169 {
0170     const KCalendarCore::Todo::Ptr todo = Akonadi::CalendarUtils::todo(aitem);
0171     if (!todo) {
0172         return false;
0173     }
0174 
0175     if (todo->isCompleted()) {
0176         return true;
0177     } else if (todo->recurs()) {
0178         QTime time;
0179         if (todo->allDay()) {
0180             time = QTime(0, 0);
0181         } else {
0182             time = todo->dtDue().toLocalTime().time();
0183         }
0184 
0185         QDateTime itemDateTime(date, time, Qt::LocalTime);
0186 
0187         return itemDateTime < todo->dtDue(false).toLocalTime();
0188     } else {
0189         return false;
0190     }
0191 }
0192 
0193 #include "moc_koeventview.cpp"