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;
32namespace
33{
34static const char myResourceManagementConfigGroupName[] = "ResourceManagement";
35}
36class FreebusyViewCalendar : public EventViews::ViewCalendar
37{
38public:
39 ~FreebusyViewCalendar() override = default;
40
41 [[nodiscard]] bool isValid(const KCalendarCore::Incidence::Ptr &incidence) const override
42 {
43 return isValid(incidence->uid());
44 }
45
46 [[nodiscard]] bool isValid(const QString &incidenceIdentifier) const override
47 {
48 return incidenceIdentifier.startsWith(QLatin1StringView("fb-"));
49 }
50
51 [[nodiscard]] QString displayName(const KCalendarCore::Incidence::Ptr &incidence) const override
52 {
53 Q_UNUSED(incidence)
54 return QStringLiteral("Freebusy");
55 }
56
57 [[nodiscard]] QColor resourceColor(const KCalendarCore::Incidence::Ptr &incidence) const override
58 {
59 bool ok = false;
60 int status = incidence->customProperty(QStringLiteral("FREEBUSY").toLatin1(), QStringLiteral("STATUS").toLatin1()).toInt(&ok);
61
62 if (!ok) {
63 return {85, 85, 85};
64 }
65
66 switch (status) {
67 case KCalendarCore::FreeBusyPeriod::Busy:
68 return {255, 0, 0};
69 case KCalendarCore::FreeBusyPeriod::BusyTentative:
70 case KCalendarCore::FreeBusyPeriod::BusyUnavailable:
71 return {255, 119, 0};
72 case KCalendarCore::FreeBusyPeriod::Free:
73 return {0, 255, 0};
74 default:
75 return {85, 85, 85};
76 }
77 }
78
79 [[nodiscard]] QString iconForIncidence(const KCalendarCore::Incidence::Ptr &incidence) const override
80 {
81 Q_UNUSED(incidence)
82 return {};
83 }
84
85 [[nodiscard]] KCalendarCore::Calendar::Ptr getCalendar() const override
86 {
87 return mCalendar;
88 }
89
91};
92
93ResourceManagement::ResourceManagement(QWidget *parent)
94 : QDialog(parent)
95{
96 setWindowTitle(i18nc("@title:window", "Resource Management"));
98 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
99 okButton->setDefault(true);
101 okButton->setText(i18nc("@action:button add resource to attendeelist", "Book resource"));
102
103 connect(buttonBox, &QDialogButtonBox::accepted, this, &ResourceManagement::accept);
104 connect(buttonBox, &QDialogButtonBox::rejected, this, &ResourceManagement::reject);
105
106 mUi = new Ui_resourceManagement;
107
108 auto w = new QWidget(this);
109 mUi->setupUi(w);
110 auto mainLayout = new QVBoxLayout(this);
111 mainLayout->addWidget(w);
112
113 mainLayout->addWidget(buttonBox);
114
115 mModel = new CalendarSupport::FreeBusyItemModel(this);
116 mFreebusyCalendar.setModel(mModel);
117
118 mAgendaView = new EventViews::AgendaView(QDate(), QDate(), false, false);
119
120 auto fbCalendar = new FreebusyViewCalendar();
121 fbCalendar->mCalendar = mFreebusyCalendar.calendar();
122 mFbCalendar = EventViews::ViewCalendar::Ptr(fbCalendar);
123 mAgendaView->addCalendar(mFbCalendar);
124
125 mUi->resourceCalender->addWidget(mAgendaView);
126
127 QStringList attrs;
128 attrs << QStringLiteral("cn") << QStringLiteral("mail") << QStringLiteral("owner") << QStringLiteral("givenname") << QStringLiteral("sn")
129 << QStringLiteral("kolabDescAttribute") << QStringLiteral("description");
130 auto resourcemodel = new ResourceModel(attrs, this);
131 mUi->treeResults->setModel(resourcemodel);
132
133 // This doesn't work till now :(-> that's why i use the click signal
134 mUi->treeResults->setSelectionMode(QAbstractItemView::SingleSelection);
135 selectionModel = mUi->treeResults->selectionModel();
136
137 connect(mUi->resourceSearch, &QLineEdit::textChanged, this, &ResourceManagement::slotStartSearch);
138
139 connect(mUi->treeResults, &QTreeView::clicked, this, &ResourceManagement::slotShowDetails);
140
141 connect(resourcemodel, &ResourceModel::layoutChanged, this, &ResourceManagement::slotLayoutChanged);
142 readConfig();
143}
144
145ResourceManagement::~ResourceManagement()
146{
147 writeConfig();
148 delete mModel;
149 delete mUi;
150}
151
152void ResourceManagement::readConfig()
153{
154 create(); // ensure a window is created
155 windowHandle()->resize(QSize(600, 400));
158 resize(windowHandle()->size()); // workaround for QTBUG-40584
159}
160
161void ResourceManagement::writeConfig()
162{
165 group.sync();
166}
167
168ResourceItem::Ptr ResourceManagement::selectedItem() const
169{
170 return mSelectedItem;
171}
172
173void ResourceManagement::slotStartSearch(const QString &text)
174{
175 (static_cast<ResourceModel *>(mUi->treeResults->model()))->startSearch(text);
176}
177
178void ResourceManagement::slotShowDetails(const QModelIndex &current)
179{
180 auto item = current.model()->data(current, ResourceModel::Resource).value<ResourceItem::Ptr>();
181 mSelectedItem = item;
182 showDetails(item->ldapObject(), item->ldapClient());
183}
184
185void ResourceManagement::showDetails(const KLDAPCore::LdapObject &obj, const KLDAPWidgets::LdapClient &client)
186{
187 // Clean up formDetails
188 QLayoutItem *child = nullptr;
189 while ((child = mUi->formDetails->takeAt(0)) != nullptr) {
190 delete child->widget();
191 delete child;
192 }
193 mUi->groupOwner->setHidden(true);
194
195 // Fill formDetails with data
196 for (auto it = obj.attributes().cbegin(), end = obj.attributes().cbegin(); it != end; ++it) {
197 const QString &key = it.key();
198 if (key == QLatin1StringView("objectClass") || key == QLatin1StringView("email")) {
199 continue;
200 } else if (key == QLatin1StringView("owner")) {
202 attrs << QStringLiteral("cn") << QStringLiteral("mail") << QStringLiteral("mobile") << QStringLiteral("telephoneNumber")
203 << QStringLiteral("kolabDescAttribute") << QStringLiteral("description");
204 mOwnerItem = ResourceItem::Ptr(new ResourceItem(KLDAPCore::LdapDN(QString::fromUtf8(it.value().at(0))), attrs, client));
205 connect(mOwnerItem.data(), &ResourceItem::searchFinished, this, &ResourceManagement::slotOwnerSearchFinished);
206 mOwnerItem->startSearch();
207 continue;
208 }
210 const QList<QByteArray> values = it.value();
211 list.reserve(values.count());
212 for (const QByteArray &value : values) {
213 list << QString::fromUtf8(value);
214 }
215 mUi->formDetails->addRow(translateLDAPAttributeForDisplay(key), new QLabel(list.join(QLatin1Char('\n'))));
216 }
217
218 QString name = QString::fromUtf8(obj.attributes().value(QStringLiteral("cn"))[0]);
219 QString email = QString::fromUtf8(obj.attributes().value(QStringLiteral("mail"))[0]);
220 KCalendarCore::Attendee attendee(name, email);
221 CalendarSupport::FreeBusyItem::Ptr freebusy(new CalendarSupport::FreeBusyItem(attendee, this));
222 mModel->clear();
223 mModel->addItem(freebusy);
224}
225
226void ResourceManagement::slotLayoutChanged()
227{
228 const int columnCount = mUi->treeResults->model()->columnCount(QModelIndex());
229 for (int i = 1; i < columnCount; ++i) {
230 mUi->treeResults->setColumnHidden(i, true);
231 }
232}
233
234void ResourceManagement::slotOwnerSearchFinished()
235{
236 // Clean up formDetails
237 QLayoutItem *child = nullptr;
238 while ((child = mUi->formOwner->takeAt(0)) != nullptr) {
239 delete child->widget();
240 delete child;
241 }
242 mUi->groupOwner->setHidden(false);
243
244 const KLDAPCore::LdapObject &obj = mOwnerItem->ldapObject();
245 const KLDAPCore::LdapAttrMap &ldapAttrMap = obj.attributes();
246 for (auto it = ldapAttrMap.cbegin(), end = ldapAttrMap.cend(); it != end; ++it) {
247 const QString &key = it.key();
248 if (key == QLatin1StringView("objectClass") || key == QLatin1StringView("owner") || key == QLatin1StringView("givenname")
249 || key == QLatin1StringView("sn")) {
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
static KSharedConfig::Ptr openStateConfig(const QString &fileName=QString())
Q_SCRIPTABLE Q_NOREPLY void start()
Q_SCRIPTABLE CaptureState status()
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)
const QList< QKeySequence > & end()
QString name(StandardShortcut 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)
const QAbstractItemModel * model() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T qobject_cast(QObject *object)
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 Tue Mar 26 2024 11:19:37 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.