Eventviews

journalframe.cpp
1/*
2 This file is part of KOrganizer.
3
4 SPDX-FileCopyrightText: 2001 Cornelius Schumacher <schumacher@kde.org>
5 SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
6 SPDX-FileCopyrightText: 2007 Mike McQuaid <mike@mikemcquaid.com>
7
8 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
9*/
10
11// Journal Entry
12
13#include "journalframe.h"
14using namespace Qt::Literals::StringLiterals;
15
16#include <Akonadi/CalendarUtils>
17#include <CalendarSupport/Utils>
18
19#include <KCalendarCore/Journal>
20
21#include <KCalUtils/IncidenceFormatter>
22
23#include "calendarview_debug.h"
24#include <KLocalizedString>
25#include <QTextBrowser>
26
27#include <QEvent>
28#include <QFontDatabase>
29#include <QHBoxLayout>
30#include <QPushButton>
31
32using namespace EventViews;
33
34JournalDateView::JournalDateView(const Akonadi::CollectionCalendar::Ptr &calendar, QWidget *parent)
35 : QWidget(parent)
36 , mCalendar(calendar)
37{
38 auto layout = new QVBoxLayout(this);
39 layout->setContentsMargins({});
40 layout->setSpacing(0);
41}
42
43JournalDateView::~JournalDateView() = default;
44
45void JournalDateView::setDate(QDate date)
46{
47 mDate = date;
48 Q_EMIT setDateSignal(date);
49}
50
51void JournalDateView::clear()
52{
53 qDeleteAll(mEntries);
54 mEntries.clear();
55}
56
57// should only be called by the JournalView now.
58void JournalDateView::addJournal(const Akonadi::Item &j)
59{
61 if (pos != mEntries.end()) {
62 return;
63 }
64
65 auto container = new QWidget(this);
66 layout()->addWidget(container);
67 auto layout = new QHBoxLayout(container);
68 layout->addStretch(1);
69 auto entry = new JournalFrame(j, mCalendar, this);
70 layout->addWidget(entry, 3 /*stretch*/);
71 layout->addStretch(1);
72
73 entry->show();
74 entry->setDate(mDate);
75 entry->setIncidenceChanger(mChanger);
76
77 mEntries.insert(j.id(), entry);
78 connect(this, &JournalDateView::setIncidenceChangerSignal, entry, &JournalFrame::setIncidenceChanger);
79 connect(this, &JournalDateView::setDateSignal, entry, &JournalFrame::setDate);
80 connect(entry, &JournalFrame::deleteIncidence, this, &JournalDateView::deleteIncidence);
81 connect(entry, &JournalFrame::editIncidence, this, &JournalDateView::editIncidence);
82 connect(entry, &JournalFrame::incidenceSelected, this, &JournalDateView::incidenceSelected);
83 connect(entry,
84 qOverload<const KCalendarCore::Journal::Ptr &, bool>(&JournalFrame::printJournal),
85 this,
86 qOverload<const KCalendarCore::Journal::Ptr &, bool>(&JournalDateView::printJournal));
87}
88
89Akonadi::Item::List JournalDateView::journals() const
90{
92 l.reserve(mEntries.count());
93 for (const JournalFrame *const i : std::as_const(mEntries)) {
94 l.push_back(i->journal());
95 }
96 return l;
97}
98
99void JournalDateView::setIncidenceChanger(Akonadi::IncidenceChanger *changer)
100{
101 mChanger = changer;
102 Q_EMIT setIncidenceChangerSignal(changer);
103}
104
105void JournalDateView::emitNewJournal()
106{
107 Q_EMIT newJournal(mDate);
108}
109
110void JournalDateView::journalEdited(const Akonadi::Item &journal)
111{
113 if (pos == mEntries.end()) {
114 return;
115 }
116
117 pos.value()->setJournal(journal);
118}
119
120void JournalDateView::journalDeleted(const Akonadi::Item &journal)
121{
123 if (pos == mEntries.end()) {
124 return;
125 }
126
127 delete pos.value();
128 mEntries.remove(journal.id());
129}
130
131JournalFrame::JournalFrame(const Akonadi::Item &j, const Akonadi::CollectionCalendar::Ptr &calendar, QWidget *parent)
132 : QFrame(parent)
133 , mJournal(j)
134 , mCalendar(calendar)
135{
136 mDirty = false;
137 mWriteInProgress = false;
138 mChanger = nullptr;
139
140 auto verticalLayout = new QVBoxLayout(this);
141
142 mBrowser = new QTextBrowser(this);
143 mBrowser->viewport()->installEventFilter(this);
144 mBrowser->setFrameStyle(QFrame::NoFrame);
145 verticalLayout->addWidget(mBrowser);
146
147 auto buttonsLayout = new QHBoxLayout();
148 verticalLayout->addLayout(buttonsLayout);
149 buttonsLayout->addStretch();
150
151 mEditButton = new QPushButton(this);
152 mEditButton->setObjectName("editButton"_L1);
153 mEditButton->setText(i18nc("@action: button", "&Edit"));
154 mEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")));
155 mEditButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
156 mEditButton->setToolTip(i18nc("@info:tooltip", "Edit this journal entry"));
157 mEditButton->setWhatsThis(i18nc("@info:whatsthis", "Opens an editor dialog for this journal entry"));
158 buttonsLayout->addWidget(mEditButton);
159 connect(mEditButton, &QPushButton::clicked, this, &JournalFrame::editItem);
160
161 mDeleteButton = new QPushButton(this);
162 mDeleteButton->setObjectName("deleteButton"_L1);
163 mDeleteButton->setText(i18nc("@action: button", "&Delete"));
164 mDeleteButton->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete")));
165 mDeleteButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
166 mDeleteButton->setToolTip(i18nc("@info:tooltip", "Delete this journal entry"));
167 mDeleteButton->setWhatsThis(i18nc("@info:whatsthis", "Delete this journal entry"));
168 buttonsLayout->addWidget(mDeleteButton);
169 connect(mDeleteButton, &QPushButton::pressed, this, &JournalFrame::deleteItem);
170
171 mPrintButton = new QPushButton(this);
172 mPrintButton->setText(i18nc("@action: button", "&Print"));
173 mPrintButton->setObjectName("printButton"_L1);
174 mPrintButton->setIcon(QIcon::fromTheme(QStringLiteral("document-print")));
175 mPrintButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
176 mPrintButton->setToolTip(i18nc("@info:tooltip", "Print this journal entry"));
177 mPrintButton->setWhatsThis(i18nc("@info:whatsthis", "Opens a print dialog for this journal entry"));
178 buttonsLayout->addWidget(mPrintButton);
179 connect(mPrintButton, &QPushButton::clicked, this, qOverload<>(&JournalFrame::printJournal));
180
181 mPrintPreviewButton = new QPushButton(this);
182 mPrintPreviewButton->setText(i18nc("@action: button", "Print preview"));
183 mPrintPreviewButton->setObjectName("printButton"_L1);
184 mPrintPreviewButton->setIcon(QIcon::fromTheme(QStringLiteral("document-print-preview")));
185 mPrintPreviewButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
186 mPrintPreviewButton->setToolTip(i18nc("@info:tooltip", "Print preview this journal entry"));
187 mPrintPreviewButton->setWhatsThis(i18nc("@info:whatsthis", "Opens a print preview of this journal entry"));
188 buttonsLayout->addWidget(mPrintPreviewButton);
189 connect(mPrintPreviewButton, &QAbstractButton::clicked, this, &JournalFrame::printPreviewJournal);
190
191 readJournal(mJournal);
192 mDirty = false;
193 setFrameStyle(QFrame::Box);
194 // These probably shouldn't be hardcoded
195 setStyleSheet(QStringLiteral("QFrame { border: 1px solid; border-radius: 7px; } "));
196 mBrowser->setStyleSheet(QStringLiteral("QFrame { border: 0px solid white } "));
197}
198
199JournalFrame::~JournalFrame() = default;
200
201bool JournalFrame::eventFilter(QObject *object, QEvent *event)
202{
203 Q_UNUSED(object)
204
205 // object is our QTextBrowser
206 if (!mJournal.isValid()) {
207 return false;
208 }
209
210 switch (event->type()) {
212 Q_EMIT incidenceSelected(mJournal, mDate);
213 break;
215 Q_EMIT editIncidence(mJournal);
216 break;
217 default:
218 break;
219 }
220
221 return false;
222}
223
224void JournalFrame::deleteItem()
225{
226 if (CalendarSupport::hasJournal(mJournal)) {
227 Q_EMIT deleteIncidence(mJournal);
228 }
229}
230
231void JournalFrame::editItem()
232{
233 if (CalendarSupport::hasJournal(mJournal)) {
234 Q_EMIT editIncidence(mJournal);
235 }
236}
237
238void JournalFrame::setCalendar(const Akonadi::CollectionCalendar::Ptr &calendar)
239{
240 mCalendar = calendar;
241}
242
243void JournalFrame::setDate(QDate date)
244{
245 mDate = date;
246}
247
248void JournalFrame::setJournal(const Akonadi::Item &journal)
249{
250 if (!CalendarSupport::hasJournal(journal)) {
251 return;
252 }
253
254 mJournal = journal;
255 readJournal(journal);
256
257 mDirty = false;
258}
259
260void JournalFrame::setDirty()
261{
262 mDirty = true;
263 qCDebug(CALENDARVIEW_LOG);
264}
265
266void JournalFrame::printJournal()
267{
268 Q_EMIT printJournal(Akonadi::CalendarUtils::journal(mJournal), false);
269}
270
271void JournalFrame::printPreviewJournal()
272{
273 Q_EMIT printJournal(Akonadi::CalendarUtils::journal(mJournal), true);
274}
275
276void JournalFrame::readJournal(const Akonadi::Item &j)
277{
279 mJournal = j;
281 mBrowser->clear();
282 QTextCursor cursor = QTextCursor(mBrowser->textCursor());
283 cursor.movePosition(QTextCursor::Start);
284
285 QTextBlockFormat bodyBlock = QTextBlockFormat(cursor.blockFormat());
286 // FIXME: Do padding
287 bodyBlock.setTextIndent(2);
288 QTextCharFormat bodyFormat = QTextCharFormat(cursor.charFormat());
289 if (!journal->summary().isEmpty()) {
290 QTextCharFormat titleFormat = bodyFormat;
291 titleFormat.setFontWeight(QFont::Bold);
292 titleFormat.setFontPointSize(baseFontSize + 4);
293 cursor.insertText(journal->summary(), titleFormat);
294 cursor.insertBlock();
295 }
296 QTextCharFormat dateFormat = bodyFormat;
297 dateFormat.setFontWeight(QFont::Bold);
298 dateFormat.setFontPointSize(baseFontSize + 1);
299 cursor.insertText(KCalUtils::IncidenceFormatter::dateTimeToString(journal->dtStart(), journal->allDay()), dateFormat);
300 cursor.insertBlock();
301 cursor.insertBlock();
302 cursor.setBlockCharFormat(bodyFormat);
303 const QString description = journal->description();
304 if (journal->descriptionIsRich()) {
305 mBrowser->insertHtml(description);
306 } else {
307 mBrowser->insertPlainText(description);
308 }
309 cursor.movePosition(QTextCursor::Start);
310 mBrowser->setTextCursor(cursor);
311 mBrowser->ensureCursorVisible();
312
313 if (mCalendar) {
314 mEditButton->setEnabled(mCalendar->hasRight(Akonadi::Collection::CanChangeItem));
315 mDeleteButton->setEnabled(mCalendar->hasRight(Akonadi::Collection::CanDeleteItem));
316 }
317}
318
319#include "moc_journalframe.cpp"
Id id() const
QList< Item > List
QSharedPointer< Calendar > Ptr
QSharedPointer< Journal > Ptr
QString i18nc(const char *context, const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Journal::Ptr journal(const Akonadi::Item &item)
Namespace EventViews provides facilities for displaying incidences, including events,...
Definition agenda.h:33
KCALUTILS_EXPORT QString dateTimeToString(const QDateTime &date, bool dateOnly=false, bool shortfmt=true)
void clicked(bool checked)
MouseButtonPress
int pointSize() const const
QFont systemFont(SystemFont type)
virtual bool event(QEvent *e) override
QIcon fromTheme(const QString &name)
void addWidget(QWidget *w)
void push_back(parameter_type value)
void reserve(qsizetype size)
typedef Iterator
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void setTextIndent(qreal indent)
void setFontPointSize(qreal size)
void setFontWeight(int weight)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QWidget(QWidget *parent, Qt::WindowFlags f)
QLayout * layout() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 25 2025 11:46:21 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.