Incidenceeditor

resourcemanagement.cpp
1/*
2 * SPDX-FileCopyrightText: 2014 Sandro Knauß <knauss@kolabsys.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
5 */
6
7#include "resourcemanagement.h"
8#include "ldaputils.h"
9#include "resourcemodel.h"
10#include "ui_resourcemanagement.h"
11#include <CalendarSupport/FreeBusyItem>
12
13#include <Akonadi/FreeBusyManager>
14
15#include <EventViews/AgendaView>
16
17#include <KCalendarCore/Event>
18
19#include <KConfigGroup>
20#include <KLocalizedString>
21#include <KSharedConfig>
22
23#include <KWindowConfig>
24#include <QColor>
25#include <QDialogButtonBox>
26#include <QLabel>
27#include <QPushButton>
28#include <QStringList>
29#include <QWindow>
30
31using namespace IncidenceEditorNG;
32using namespace Qt::Literals::StringLiterals;
33namespace
34{
35static const char myResourceManagementConfigGroupName[] = "ResourceManagement";
36}
37class FreebusyViewCalendar : public EventViews::ViewCalendar
38{
39public:
40 ~FreebusyViewCalendar() override = default;
41
42 [[nodiscard]] bool isValid(const KCalendarCore::Incidence::Ptr &incidence) const override
43 {
44 return isValid(incidence->uid());
45 }
46
47 [[nodiscard]] bool isValid(const QString &incidenceIdentifier) const override
48 {
49 return incidenceIdentifier.startsWith("fb-"_L1);
50 }
51
52 [[nodiscard]] QString displayName(const KCalendarCore::Incidence::Ptr &incidence) const override
53 {
54 Q_UNUSED(incidence)
55 return QStringLiteral("Freebusy");
56 }
57
58 [[nodiscard]] QColor resourceColor(const KCalendarCore::Incidence::Ptr &incidence) const override
59 {
60 bool ok = false;
61 int status = incidence->customProperty(QStringLiteral("FREEBUSY").toLatin1(), QStringLiteral("STATUS").toLatin1()).toInt(&ok);
62
63 if (!ok) {
64 return {85, 85, 85};
65 }
66
67 switch (status) {
68 case KCalendarCore::FreeBusyPeriod::Busy:
69 return {255, 0, 0};
70 case KCalendarCore::FreeBusyPeriod::BusyTentative:
71 case KCalendarCore::FreeBusyPeriod::BusyUnavailable:
72 return {255, 119, 0};
73 case KCalendarCore::FreeBusyPeriod::Free:
74 return {0, 255, 0};
75 default:
76 return {85, 85, 85};
77 }
78 }
79
80 [[nodiscard]] QString iconForIncidence(const KCalendarCore::Incidence::Ptr &incidence) const override
81 {
82 Q_UNUSED(incidence)
83 return {};
84 }
85
86 [[nodiscard]] KCalendarCore::Calendar::Ptr getCalendar() const override
87 {
88 return mCalendar;
89 }
90
92};
93
94ResourceManagement::ResourceManagement(QWidget *parent)
95 : QDialog(parent)
96{
97 setWindowTitle(i18nc("@title:window", "Resource Management"));
99 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
100 okButton->setDefault(true);
102 okButton->setText(i18nc("@action:button add resource to attendeelist", "Book resource"));
103
104 connect(buttonBox, &QDialogButtonBox::accepted, this, &ResourceManagement::accept);
105 connect(buttonBox, &QDialogButtonBox::rejected, this, &ResourceManagement::reject);
106
107 mUi = new Ui_resourceManagement;
108
109 auto w = new QWidget(this);
110 mUi->setupUi(w);
111 auto mainLayout = new QVBoxLayout(this);
112 mainLayout->addWidget(w);
113
114 mainLayout->addWidget(buttonBox);
115
116 mModel = new CalendarSupport::FreeBusyItemModel(this);
117 mFreebusyCalendar.setModel(mModel);
118
119 mAgendaView = new EventViews::AgendaView(QDate(), QDate(), false, false);
120
121 auto fbCalendar = new FreebusyViewCalendar();
122 fbCalendar->mCalendar = mFreebusyCalendar.calendar();
123 mFbCalendar = EventViews::ViewCalendar::Ptr(fbCalendar);
124 mAgendaView->addCalendar(mFbCalendar);
125
126 mUi->resourceCalender->addWidget(mAgendaView);
127
128 QStringList attrs;
129 attrs << QStringLiteral("cn") << QStringLiteral("mail") << QStringLiteral("owner") << QStringLiteral("givenname") << QStringLiteral("sn")
130 << QStringLiteral("kolabDescAttribute") << QStringLiteral("description");
131 auto resourcemodel = new ResourceModel(attrs, this);
132 mUi->treeResults->setModel(resourcemodel);
133
134 // This doesn't work till now :(-> that's why i use the click signal
135 mUi->treeResults->setSelectionMode(QAbstractItemView::SingleSelection);
136 selectionModel = mUi->treeResults->selectionModel();
137
138 connect(mUi->resourceSearch, &QLineEdit::textChanged, this, &ResourceManagement::slotStartSearch);
139
140 connect(mUi->treeResults, &QTreeView::clicked, this, &ResourceManagement::slotShowDetails);
141
142 connect(resourcemodel, &ResourceModel::layoutChanged, this, &ResourceManagement::slotLayoutChanged);
143 readConfig();
144}
145
146ResourceManagement::~ResourceManagement()
147{
148 writeConfig();
149 delete mModel;
150 delete mUi;
151}
152
153void ResourceManagement::readConfig()
154{
155 create(); // ensure a window is created
156 windowHandle()->resize(QSize(600, 400));
157 KConfigGroup group(KSharedConfig::openStateConfig(), QLatin1StringView(myResourceManagementConfigGroupName));
159 resize(windowHandle()->size()); // workaround for QTBUG-40584
160}
161
162void ResourceManagement::writeConfig()
163{
164 KConfigGroup group(KSharedConfig::openStateConfig(), QLatin1StringView(myResourceManagementConfigGroupName));
166 group.sync();
167}
168
169ResourceItem::Ptr ResourceManagement::selectedItem() const
170{
171 return mSelectedItem;
172}
173
174void ResourceManagement::slotStartSearch(const QString &text)
175{
176 (static_cast<ResourceModel *>(mUi->treeResults->model()))->startSearch(text);
177}
178
179void ResourceManagement::slotShowDetails(const QModelIndex &current)
180{
181 auto item = current.model()->data(current, ResourceModel::Resource).value<ResourceItem::Ptr>();
182 mSelectedItem = item;
183 showDetails(item->ldapObject(), item->ldapClient());
184}
185
186void ResourceManagement::showDetails(const KLDAPCore::LdapObject &obj, const KLDAPCore::LdapClient &client)
187{
188 // Clean up formDetails
189 QLayoutItem *child = nullptr;
190 while ((child = mUi->formDetails->takeAt(0)) != nullptr) {
191 delete child->widget();
192 delete child;
193 }
194 mUi->groupOwner->setHidden(true);
195
196 // Fill formDetails with data
197 for (auto it = obj.attributes().cbegin(), end = obj.attributes().cbegin(); it != end; ++it) {
198 const QString &key = it.key();
199 if (key == "objectClass"_L1 || key == "email"_L1) {
200 continue;
201 } else if (key == "owner"_L1) {
202 QStringList attrs;
203 attrs << QStringLiteral("cn") << QStringLiteral("mail") << QStringLiteral("mobile") << QStringLiteral("telephoneNumber")
204 << QStringLiteral("kolabDescAttribute") << QStringLiteral("description");
205 mOwnerItem = ResourceItem::Ptr(new ResourceItem(KLDAPCore::LdapDN(QString::fromUtf8(it.value().at(0))), attrs, client));
206 connect(mOwnerItem.data(), &ResourceItem::searchFinished, this, &ResourceManagement::slotOwnerSearchFinished);
207 mOwnerItem->startSearch();
208 continue;
209 }
211 const QList<QByteArray> values = it.value();
212 list.reserve(values.count());
213 for (const QByteArray &value : values) {
214 list << QString::fromUtf8(value);
215 }
216 mUi->formDetails->addRow(translateLDAPAttributeForDisplay(key), new QLabel(list.join(QLatin1Char('\n'))));
217 }
218
219 QString name = QString::fromUtf8(obj.attributes().value(QStringLiteral("cn"))[0]);
220 QString email = QString::fromUtf8(obj.attributes().value(QStringLiteral("mail"))[0]);
221 KCalendarCore::Attendee attendee(name, email);
222 CalendarSupport::FreeBusyItem::Ptr freebusy(new CalendarSupport::FreeBusyItem(attendee, this));
223 mModel->clear();
224 mModel->addItem(freebusy);
225}
226
227void ResourceManagement::slotLayoutChanged()
228{
229 const int columnCount = mUi->treeResults->model()->columnCount(QModelIndex());
230 for (int i = 1; i < columnCount; ++i) {
231 mUi->treeResults->setColumnHidden(i, true);
232 }
233}
234
235void ResourceManagement::slotOwnerSearchFinished()
236{
237 // Clean up formDetails
238 QLayoutItem *child = nullptr;
239 while ((child = mUi->formOwner->takeAt(0)) != nullptr) {
240 delete child->widget();
241 delete child;
242 }
243 mUi->groupOwner->setHidden(false);
244
245 const KLDAPCore::LdapObject &obj = mOwnerItem->ldapObject();
246 const KLDAPCore::LdapAttrMap &ldapAttrMap = obj.attributes();
247 for (auto it = ldapAttrMap.cbegin(), end = ldapAttrMap.cend(); it != end; ++it) {
248 const QString &key = it.key();
249 if (key == QLatin1StringView("objectClass") || key == "owner"_L1 || key == "givenname"_L1 || key == "sn"_L1) {
250 continue;
251 }
253 const QList<QByteArray> values = it.value();
254 list.reserve(values.count());
255 for (const QByteArray &value : values) {
256 list << QString::fromUtf8(value);
257 }
258 mUi->formOwner->addRow(translateLDAPAttributeForDisplay(key), new QLabel(list.join(QLatin1Char('\n'))));
259 }
260}
261
262void ResourceManagement::slotDateChanged(const QDate &start, const QDate &end)
263{
264 if (start.daysTo(end) < 7) {
265 mAgendaView->showDates(start, start.addDays(7));
266 }
267 mAgendaView->showDates(start, end);
268}
269
270#include "moc_resourcemanagement.cpp"
void showDates(const QDate &start, const QDate &end, const QDate &preferredMonth=QDate()) override
const LdapAttrMap & attributes() const
static KSharedConfig::Ptr openStateConfig(const QString &fileName=QString())
Q_SCRIPTABLE CaptureState status()
Q_SCRIPTABLE Q_NOREPLY void start()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Incidence::Ptr incidence(const Akonadi::Item &item)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
QString name(StandardAction id)
KCONFIGGUI_EXPORT void saveWindowSize(const QWindow *window, KConfigGroup &config, KConfigGroup::WriteConfigFlags options=KConfigGroup::Normal)
KCONFIGGUI_EXPORT void restoreWindowSize(QWindow *window, const KConfigGroup &config)
void setShortcut(const QKeySequence &key)
void setText(const QString &text)
virtual QVariant data(const QModelIndex &index, int role) const const=0
void clicked(const QModelIndex &index)
virtual QWidget * widget() const const
void textChanged(const QString &text)
qsizetype count() const const
void reserve(qsizetype size)
T value(qsizetype i) const const
const QAbstractItemModel * model() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void setDefault(bool)
T * data() const const
QString fromUtf8(QByteArrayView str)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString join(QChar separator) const const
Key_Return
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
T value() const const
void create(WId window, bool initializeWindow, bool destroyOldWindow)
void resize(const QSize &)
QWindow * windowHandle() const const
void resize(const QSize &newSize)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:16:44 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.