Branch 'dev/resourcemanagement' - incidenceeditor-ng/attendeecomboboxdelegate.cpp incidenceeditor-ng/attendeecomboboxdelegate.h incidenceeditor-ng/CMakeLists.txt incidenceeditor-ng/incidenceattendee.cpp incidenceeditor-ng/incidencedialog.cpp incidenceeditor-ng/incidencedialog.h incidenceeditor-ng/incidenceresource.cpp incidenceeditor-ng/incidenceresource.h incidenceeditor-ng/resourcetablemodel.cpp incidenceeditor-ng/resourcetablemodel.h
Sandro Knauß
knauss at kolabsys.com
Fri May 2 01:20:06 CEST 2014
incidenceeditor-ng/CMakeLists.txt | 2
incidenceeditor-ng/attendeecomboboxdelegate.cpp | 73 +++++
incidenceeditor-ng/attendeecomboboxdelegate.h | 59 ++++
incidenceeditor-ng/incidenceattendee.cpp | 18 -
incidenceeditor-ng/incidencedialog.cpp | 19 +
incidenceeditor-ng/incidencedialog.h | 1
incidenceeditor-ng/incidenceresource.cpp | 338 ++++++++++--------------
incidenceeditor-ng/incidenceresource.h | 7
incidenceeditor-ng/resourcetablemodel.cpp | 191 +++++++++++++
incidenceeditor-ng/resourcetablemodel.h | 92 ++++++
10 files changed, 601 insertions(+), 199 deletions(-)
New commits:
commit 427de16b1f7e4d4304f05813b7332199819a5cc9
Author: Sandro Knauà <knauss at kolabsys.com>
Date: Fri May 2 00:51:49 2014 +0200
Model für Attendees auslagern
diff --git a/incidenceeditor-ng/CMakeLists.txt b/incidenceeditor-ng/CMakeLists.txt
index 1d56da2..551ea12 100644
--- a/incidenceeditor-ng/CMakeLists.txt
+++ b/incidenceeditor-ng/CMakeLists.txt
@@ -65,6 +65,8 @@ set(incidenceeditors_ng_shared_LIB_SRCS
resourcemanagement.cpp
resourceitem.cpp
resourcemodel.cpp
+ resourcetablemodel.cpp
+ attendeecomboboxdelegate.cpp
)
kde4_add_kcfg_files(incidenceeditors_ng_shared_LIB_SRCS globalsettings_base.kcfgc)
diff --git a/incidenceeditor-ng/attendeecomboboxdelegate.cpp b/incidenceeditor-ng/attendeecomboboxdelegate.cpp
new file mode 100644
index 0000000..fda6a7e
--- /dev/null
+++ b/incidenceeditor-ng/attendeecomboboxdelegate.cpp
@@ -0,0 +1,73 @@
+#include "attendeecomboboxdelegate.h"
+
+#include "attendeeline.h"
+
+#include <QApplication>
+
+using namespace IncidenceEditorNG;
+
+AttendeeComboBoxDelegate::AttendeeComboBoxDelegate(QObject *parent)
+:QStyledItemDelegate(parent)
+,standardIndex(0)
+{
+
+}
+
+void AttendeeComboBoxDelegate::addItem(const QIcon &icon, const QString &text)
+{
+ QPair<QIcon,QString> pair;
+ pair.first = icon;
+ pair.second = text;
+ entries << pair;
+}
+
+void AttendeeComboBoxDelegate::setStandardIndex(int index)
+{
+ standardIndex = index;
+}
+
+
+QWidget *AttendeeComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex &/* index */) const
+{
+ AttendeeComboBox* editor = new AttendeeComboBox(parent);
+ QPair<QIcon,QString> pair;
+
+ foreach(pair, entries) {
+ editor->addItem(pair.first, pair.second);
+ }
+
+ return editor;
+}
+
+void AttendeeComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+{
+ AttendeeComboBox *comboBox = static_cast<AttendeeComboBox*>(editor);
+ int value = index.model()->data(index, Qt::EditRole).toUInt();
+ if (value >= entries.count())
+ value = standardIndex;
+ comboBox->setCurrentIndex(value);
+}
+
+void AttendeeComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
+{
+ AttendeeComboBox *comboBox = static_cast<AttendeeComboBox*>(editor);
+ model->setData(index, comboBox->currentIndex(), Qt::EditRole);
+}
+
+void AttendeeComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
+{
+ editor->setGeometry(option.rect);
+}
+
+void AttendeeComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ QStyleOptionButton pushButton;
+ int value = index.model()->data(index).toUInt();
+ pushButton.rect = option.rect;
+ pushButton.features |= QStyleOptionButton::HasMenu;
+ if (value >= entries.count())
+ value = standardIndex;
+ pushButton.icon = entries[value].first;
+
+ QApplication::style()->drawControl(QStyle::CE_PushButton, &pushButton, painter);
+}
diff --git a/incidenceeditor-ng/attendeecomboboxdelegate.h b/incidenceeditor-ng/attendeecomboboxdelegate.h
new file mode 100644
index 0000000..7d5f455
--- /dev/null
+++ b/incidenceeditor-ng/attendeecomboboxdelegate.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014 Sandro Knauà <knauss at kolabsys.com>
+ *
+ * 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) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef INCIDENCEEDITOR_ATTENDEECOMBOBOXDELEGATE_H
+#define INCIDENCEEDITOR_ATTENDEECOMBOBOXDELEGATE_H
+
+#include <QStyledItemDelegate>
+#include <QModelIndex>
+#include <QIcon>
+#include <QString>
+
+
+namespace IncidenceEditorNG
+{
+
+class AttendeeComboBoxDelegate : public QStyledItemDelegate
+{
+Q_OBJECT
+public:
+ AttendeeComboBoxDelegate(QObject *parent = 0);
+
+ QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+ void setEditorData(QWidget *editor, const QModelIndex &index) const;
+ void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
+ void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+ void addItem(const QIcon&, const QString&);
+ void setStandardIndex(int);
+
+private:
+ QList<QPair<QIcon,QString> > entries;
+ int standardIndex;
+
+};
+
+
+
+}
+
+#endif
\ No newline at end of file
diff --git a/incidenceeditor-ng/incidenceattendee.cpp b/incidenceeditor-ng/incidenceattendee.cpp
index fa1811f..32d7f04 100644
--- a/incidenceeditor-ng/incidenceattendee.cpp
+++ b/incidenceeditor-ng/incidenceattendee.cpp
@@ -185,7 +185,9 @@ void IncidenceAttendee::load( const KCalCore::Incidence::Ptr &incidence )
const KCalCore::Attendee::List attendees = incidence->attendees();
foreach ( const KCalCore::Attendee::Ptr &a, attendees ) {
- mAttendeeEditor->addAttendee( a );
+ if (!(a->cuType() == KCalCore::Attendee::Resource || a->cuType() == KCalCore::Attendee::Room)) {
+ mAttendeeEditor->addAttendee( a );
+ }
}
mWasDirty = false;
@@ -193,7 +195,7 @@ void IncidenceAttendee::load( const KCalCore::Incidence::Ptr &incidence )
void IncidenceAttendee::save( const KCalCore::Incidence::Ptr &incidence )
{
- incidence->clearAttendees();
+ /*incidence->clearAttendees();
AttendeeData::List attendees = mAttendeeEditor->attendees();
foreach ( AttendeeData::Ptr attendee, attendees ) {
@@ -219,7 +221,7 @@ void IncidenceAttendee::save( const KCalCore::Incidence::Ptr &incidence )
// Must not have an organizer for items without attendees
if ( !incidence->attendeeCount() ) {
return;
- }
+ }*/
if ( mUi->mOrganizerStack->currentIndex() == 0 ) {
incidence->setOrganizer( mUi->mOrganizerCombo->currentText() );
@@ -247,13 +249,16 @@ bool IncidenceAttendee::isDirty() const
// 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() ) {
+ /*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.
foreach ( const KCalCore::Attendee::Ptr &attendee, originalList ) {
+ if (attendee->cuType() == KCalCore::Attendee::Resource || attendee->cuType() == KCalCore::Attendee::Room) {
+ continue;
+ }
bool found = false;
for ( int i = 0; i < newList.size(); ++i ) {
if ( compareAttendees( newList.at( i )->attendee(), attendee) ) {
@@ -265,6 +270,7 @@ bool IncidenceAttendee::isDirty() const
if ( !found ) {
// One of the attendees in the original list was not found in the new list.
+ kDebug() << "One of the attendees in the original list was not found in the new list";
return true;
}
}
@@ -605,6 +611,7 @@ void IncidenceAttendee::printDebugInfo() const
<< attendee->RSVP()
<< attendee->role()
<< attendee->uid()
+ << attendee->cuType()
<< attendee->delegate()
<< attendee->delegator()
<< "; we have:";
@@ -616,6 +623,7 @@ void IncidenceAttendee::printDebugInfo() const
<< attendee->RSVP()
<< attendee->role()
<< attendee->uid()
+ << attendee->cuType()
<< attendee->delegate()
<< attendee->delegator();
}
diff --git a/incidenceeditor-ng/incidencedialog.cpp b/incidenceeditor-ng/incidencedialog.cpp
index bcc1923..11a0e88 100644
--- a/incidenceeditor-ng/incidencedialog.cpp
+++ b/incidenceeditor-ng/incidencedialog.cpp
@@ -99,6 +99,7 @@ class IncidenceDialogPrivate : public ItemEditorUi
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 );
@@ -192,6 +193,8 @@ IncidenceDialogPrivate::IncidenceDialogPrivate( Akonadi::IncidenceChanger *chang
SLOT(updateAttachmentCount(int)) );
q->connect( mIeAttendee, SIGNAL(attendeeCountChanged(int)),
SLOT(updateAttendeeCount(int)) );
+ q->connect( mIeResource, SIGNAL(resourceCountChanged(int)),
+ SLOT(updateResourceCount(int)) );
}
IncidenceDialogPrivate::~IncidenceDialogPrivate()
@@ -420,6 +423,21 @@ void IncidenceDialogPrivate::updateAttendeeCount( int newCount )
}
}
+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 )
{
Q_Q( IncidenceDialog );
@@ -565,6 +583,7 @@ void IncidenceDialogPrivate::load( const Akonadi::Item &item )
// Initialize tab's titles
updateAttachmentCount( incidence->attachments().size() );
+ updateResourceCount( mIeResource->resourcesCount() );
handleRecurrenceChange( mIeRecurrence->currentRecurrenceType() );
handleAlarmCountChange( incidence->alarms().count() );
diff --git a/incidenceeditor-ng/incidencedialog.h b/incidenceeditor-ng/incidencedialog.h
index 7d7c36c..4d22699 100644
--- a/incidenceeditor-ng/incidencedialog.h
+++ b/incidenceeditor-ng/incidencedialog.h
@@ -108,6 +108,7 @@ class INCIDENCEEDITORS_NG_EXPORT IncidenceDialog : public KDialog
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) )
};
diff --git a/incidenceeditor-ng/incidenceresource.cpp b/incidenceeditor-ng/incidenceresource.cpp
index c40bfcc..9086104 100644
--- a/incidenceeditor-ng/incidenceresource.cpp
+++ b/incidenceeditor-ng/incidenceresource.cpp
@@ -20,6 +20,7 @@
#include "incidenceresource.h"
#include "resourcemanagement.h"
#include "resourcemodel.h"
+#include "attendeecomboboxdelegate.h"
#ifdef KDEPIM_MOBILE_UI
#include "ui_dialogmoremobile.h"
@@ -27,14 +28,19 @@
#include "ui_dialogdesktop.h"
#endif
-#include <kdebug.h>
+#include <KDebug>
+#include <KMessageBox>
+
+#include <KCalUtils/Stringify>
+#include <KPIMUtils/Email>
+
#include <QCompleter>
using namespace IncidenceEditorNG;
#include <QStandardItem>
#include <QAbstractProxyModel>
-
+#include <QSortFilterProxyModel>
/* Flatten the TreeModel of Resources */
class SortProxy : public QAbstractProxyModel
{
@@ -110,183 +116,9 @@ private:
QMap<QPersistentModelIndex, QPersistentModelIndex> mapping;
};
-//Own line of resource in the resource editor table
-class Resource
-{
-public:
- Resource() {
- name = QString("");
- role = 0;
- available = false;
- status = 0;
- }
- void setName(const QString &name) {
- this->name = name;
- }
- void setRole(int role) {
- this->role = role;
- }
- void setAvailable(bool available) {
- this->available = available;
- }
- void setStatus(int status) {
- this->status = status;
- }
-public:
- QString name;
- int role;
- bool available;
- int status;
-};
-
-#include <QAbstractTableModel>
-
-/* TableView for the Resource Tab
- * 0 = role
- * 1 = name
- * 2 = available
- * 3 = status
- */
-
-class ResourceTableModel : public QAbstractTableModel
-{
- Q_OBJECT
-
-public:
- ResourceTableModel(const QList <Resource> &resources, QObject *parent = 0)
- : QAbstractTableModel(parent), resourceList(resources) {}
-
- int rowCount(const QModelIndex &parent = QModelIndex()) const;
- int columnCount(const QModelIndex &parent = QModelIndex()) const;
- QVariant data(const QModelIndex &index, int role) const;
- QVariant headerData(int section, Qt::Orientation orientation,
- int role = Qt::DisplayRole) const;
-
- Qt::ItemFlags flags(const QModelIndex &index) const;
- bool setData(const QModelIndex &index, const QVariant &value,
- int role = Qt::EditRole);
- bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex());
- bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex());
-
-private:
- QList<Resource> resourceList;
-};
-int ResourceTableModel::rowCount(const QModelIndex &/*parent*/) const
-{
- return resourceList.count();
-}
-
-int ResourceTableModel::columnCount(const QModelIndex &/*parent*/) const
-{
- return 4;
-}
-
-Qt::ItemFlags ResourceTableModel::flags(const QModelIndex &index) const
-{
- if (!index.isValid())
- return Qt::ItemIsEnabled;
-
- return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
-}
-
-QVariant ResourceTableModel::data(const QModelIndex &index, int role) const
-{
- if (!index.isValid())
- return QVariant();
-
- if (index.row() >= resourceList.size())
- return QVariant();
-
- if (role == Qt::DisplayRole || role == Qt::EditRole) {
- switch (index.column()) {
- case 0:
- return resourceList.at(index.row()).role;
- case 1:
- return resourceList.at(index.row()).name;
- case 2:
- return resourceList.at(index.row()).available;
- case 3:
- return resourceList.at(index.row()).status;
- }
-
- }
- return QVariant();
-}
-
-bool ResourceTableModel::setData(const QModelIndex& index, const QVariant& value, int role)
-{
- if (index.isValid() && role == Qt::EditRole) {
- switch (index.column()) {
- case 0:
- resourceList[index.row()].role = value.toInt();
- break;
- case 1:
- resourceList[index.row()].name = value.toString() ;
- break;
- case 2:
- resourceList[index.row()].available = value.toBool();
- break;
- case 3:
- resourceList[index.row()].status = value.toInt();
- break;
- default:
- return false;
- }
- emit dataChanged(index, index);
- return true;
- }
- return false;
-}
-
-QVariant ResourceTableModel::headerData(int section, Qt::Orientation orientation,
- int role) const
-{
- if (role != Qt::DisplayRole)
- return QVariant();
-
- if (orientation == Qt::Horizontal) {
- switch (section) {
- case 0:
- return QString("role");
- case 1:
- return QString("name");
- case 2:
- return QString("available");
- case 3:
- return QString("status");
- }
- }
-
- return QVariant();
-}
-
-bool ResourceTableModel::insertRows(int position, int rows, const QModelIndex &parent)
-{
- beginInsertRows(QModelIndex(), position, position + rows - 1);
-
- for (int row = 0; row < rows; ++row) {
- resourceList.insert(position, Resource());
- }
-
- endInsertRows();
- return true;
-}
-
-bool ResourceTableModel::removeRows(int position, int rows, const QModelIndex &parent)
-{
- beginRemoveRows(QModelIndex(), position, position + rows - 1);
-
- for (int row = 0; row < rows; ++row) {
- resourceList.removeAt(position);
- }
-
- endRemoveRows();
- return true;
-}
-
#ifdef KDEPIM_MOBILE_UI
IncidenceResource::IncidenceResource(Ui::EventOrTodoMore *ui)
#else
@@ -297,6 +129,54 @@ IncidenceResource::IncidenceResource(Ui::EventOrTodoDesktop *ui)
{
setObjectName("IncidenceResource");
+ AttendeeComboBoxDelegate* roleDelegate(new AttendeeComboBoxDelegate(this));
+#ifdef KDEPIM_MOBILE_UI
+ roleDelegate->addItem( DesktopIcon( "meeting-participant", 48 ),
+ KCalUtils::Stringify::attendeeRole( KCalCore::Attendee::ReqParticipant ) );
+ roleDelegate->addItem( DesktopIcon( "meeting-participant-optional", 48 ),
+ KCalUtils::Stringify::attendeeRole( KCalCore::Attendee::OptParticipant ) );
+ roleDelegate->addItem( DesktopIcon( "meeting-observer", 48 ),
+ KCalUtils::Stringify::attendeeRole( KCalCore::Attendee::NonParticipant ) );
+ roleDelegate->addItem( DesktopIcon( "meeting-chair", 48 ),
+ KCalUtils::Stringify::attendeeRole( KCalCore::Attendee::Chair ) );
+
+#else
+ roleDelegate->addItem( SmallIcon( "meeting-participant" ),
+ KCalUtils::Stringify::attendeeRole( KCalCore::Attendee::ReqParticipant ) );
+ roleDelegate->addItem( SmallIcon( "meeting-participant-optional" ),
+ KCalUtils::Stringify::attendeeRole( KCalCore::Attendee::OptParticipant ) );
+ roleDelegate->addItem( SmallIcon( "meeting-observer" ),
+ KCalUtils::Stringify::attendeeRole( KCalCore::Attendee::NonParticipant ) );
+ roleDelegate->addItem( SmallIcon( "meeting-chair" ),
+ KCalUtils::Stringify::attendeeRole( KCalCore::Attendee::Chair ) );
+#endif
+
+ AttendeeComboBoxDelegate *stateDelegate(new AttendeeComboBoxDelegate(this));
+
+ #ifdef KDEPIM_MOBILE_UI
+ stateDelegate->addItem( DesktopIcon( "task-attention", 48 ),
+ KCalUtils::Stringify::attendeeStatus( KCalCore::Attendee::NeedsAction ) );
+ stateDelegate->addItem( DesktopIcon( "task-accepted", 48 ),
+ KCalUtils::Stringify::attendeeStatus( KCalCore::Attendee::Accepted ) );
+ stateDelegate->addItem( DesktopIcon( "task-reject", 48 ),
+ KCalUtils::Stringify::attendeeStatus( KCalCore::Attendee::Declined ) );
+ stateDelegate->addItem( DesktopIcon( "task-attempt", 48 ),
+ KCalUtils::Stringify::attendeeStatus( KCalCore::Attendee::Tentative ) );
+ stateDelegate->addItem( DesktopIcon( "task-delegate", 48 ),
+ KCalUtils::Stringify::attendeeStatus( KCalCore::Attendee::Delegated ) );
+#else
+ stateDelegate->addItem( SmallIcon( "task-attention" ),
+ KCalUtils::Stringify::attendeeStatus( KCalCore::Attendee::NeedsAction ) );
+ stateDelegate->addItem( SmallIcon( "task-accepted" ),
+ KCalUtils::Stringify::attendeeStatus( KCalCore::Attendee::Accepted ) );
+ stateDelegate->addItem( SmallIcon( "task-reject" ),
+ KCalUtils::Stringify::attendeeStatus( KCalCore::Attendee::Declined ) );
+ stateDelegate->addItem( SmallIcon( "task-attempt" ),
+ KCalUtils::Stringify::attendeeStatus( KCalCore::Attendee::Tentative ) );
+ stateDelegate->addItem( SmallIcon( "task-delegate" ),
+ KCalUtils::Stringify::attendeeStatus( KCalCore::Attendee::Delegated ) );
+#endif
+
#ifndef KDEPIM_MOBILE_UI
QStringList attrs;
attrs << QLatin1String("cn");
@@ -309,47 +189,104 @@ IncidenceResource::IncidenceResource(Ui::EventOrTodoDesktop *ui)
completer->setWrapAround(false);
mUi->mNewResource->setCompleter(completer);
- Resource resource;
- resource.name = QString("test");
- resource.role = 1;
- resource.available = false;
- resource.status = 0;
+ KCalCore::Attendee::List resources;
- QList<Resource> resources;
- resources << resource;
-
- ResourceTableModel *resourceModel = new ResourceTableModel(resources, this);
- mUi->mResourcesTable->setModel(resourceModel);
+ dataModel = new ResourceTableModel(resources, this);
+ ResourceFilterProxyModel *filterProxyModel = new ResourceFilterProxyModel(this);
+ filterProxyModel->setDynamicSortFilter(true);
+ filterProxyModel->setSourceModel(dataModel);
+ mUi->mResourcesTable->setModel(filterProxyModel);
+ mUi->mResourcesTable->setColumnHidden(4, true);
+ mUi->mResourcesTable->setItemDelegateForColumn(0, roleDelegate);
+ mUi->mResourcesTable->setItemDelegateForColumn(3, stateDelegate);
connect(mUi->mFindResourcesButton, SIGNAL(clicked()), SLOT(findResources()));
connect(mUi->mBookResourceButton, SIGNAL(clicked()), SLOT(bookResource()));
+ connect(dataModel, SIGNAL(layoutChanged()), SLOT(layoutChanged()));
+ connect(dataModel, SIGNAL(rowsInserted(const QModelIndex&, int , int)), SLOT(layoutChanged()));
+ connect(dataModel, SIGNAL(rowsRemoved(const QModelIndex&, int , int)), SLOT(layoutChanged()));
#endif
}
void IncidenceResource::load(const KCalCore::Incidence::Ptr &incidence)
{
-
+ mLoadedIncidence = incidence;
+ dataModel->setAttendees(incidence->attendees());
}
void IncidenceResource::save(const KCalCore::Incidence::Ptr &incidence)
{
+ incidence->clearAttendees();
+ KCalCore::Attendee::List attendees = dataModel->attendees();
+
+ foreach ( KCalCore::Attendee::Ptr attendee, attendees ) {
+ Q_ASSERT( attendee );
+
+ bool skip = false;
+ if ( KPIMUtils::isValidAddress( attendee->email() ) ) {
+ if ( KMessageBox::warningYesNo(
+ 0,
+ 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;
+ }
}
bool IncidenceResource::isDirty() const
{
- return false;
+ const KCalCore::Attendee::List originalList = mLoadedIncidence->attendees();
+ KCalCore::Attendee::List newList = dataModel->attendees();
+
+ // 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.
+ foreach ( const KCalCore::Attendee::Ptr &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 IncidenceResource::bookResource()
{
#ifndef KDEPIM_MOBILE_UI
- kDebug() << "bookResource: " << mUi->mNewResource->text();
-
- // create new line and set name to mUi->mNewResource->text()
- mUi->mResourcesTable->model()->insertRows(mUi->mResourcesTable->model()->rowCount(), 1, QModelIndex());
- QModelIndex index = mUi->mResourcesTable->model()->index(mUi->mResourcesTable->model()->rowCount() - 1, 1, QModelIndex());
- mUi->mResourcesTable->model()->setData(index, mUi->mNewResource->text(), Qt::EditRole);
+ QString name, email;
+
+ KPIMUtils::extractEmailAddressAndName( mUi->mNewResource->text(), email, name );
+ KCalCore::Attendee::Ptr attendee(new KCalCore::Attendee(name,email));
+ attendee->setCuType(KCalCore::Attendee::Resource);
+ dataModel->insertAttendee(dataModel->rowCount(), attendee);
#endif
}
@@ -359,4 +296,17 @@ void IncidenceResource::findResources()
dialog->show();
}
+void IncidenceResource::layoutChanged()
+{
+ emit resourceCountChanged(resourcesCount());
+}
+
+int IncidenceResource::resourcesCount() const
+{
+#ifndef KDEPIM_MOBILE_UI
+ return mUi->mResourcesTable->model()->rowCount(QModelIndex());
+#endif
+ return 0;
+}
+
#include "incidenceresource.moc"
\ No newline at end of file
diff --git a/incidenceeditor-ng/incidenceresource.h b/incidenceeditor-ng/incidenceresource.h
index 6d283fa..42a49b9 100644
--- a/incidenceeditor-ng/incidenceresource.h
+++ b/incidenceeditor-ng/incidenceresource.h
@@ -21,6 +21,7 @@
#define INCIDENCEEDITOR_INCIDENCERESOURCE_H
#include "incidenceeditor-ng.h"
+#include "resourcetablemodel.h"
#include <QModelIndex>
#include <QCompleter>
@@ -47,10 +48,15 @@ public:
void load(const KCalCore::Incidence::Ptr &incidence);
void save(const KCalCore::Incidence::Ptr &incidence);
bool isDirty() const;
+ int resourcesCount() const;
+
+signals:
+ void resourceCountChanged( int );
private slots:
void findResources();
void bookResource();
+ void layoutChanged();
private:
#ifdef KDEPIM_MOBILE_UI
@@ -59,6 +65,7 @@ private:
Ui::EventOrTodoDesktop *mUi;
#endif
QCompleter *completer;
+ ResourceTableModel *dataModel;
};
}
diff --git a/incidenceeditor-ng/resourcetablemodel.cpp b/incidenceeditor-ng/resourcetablemodel.cpp
new file mode 100644
index 0000000..2678283
--- /dev/null
+++ b/incidenceeditor-ng/resourcetablemodel.cpp
@@ -0,0 +1,191 @@
+#include "resourcetablemodel.h"
+
+#include <KCalCore/Attendee>
+#include <KPIMUtils/Email>
+
+#include <KDebug>
+
+using namespace IncidenceEditorNG;
+
+ResourceTableModel::ResourceTableModel(const KCalCore::Attendee::List &resources, QObject *parent )
+: QAbstractTableModel(parent)
+, resourceList(resources)
+{
+
+}
+
+int ResourceTableModel::rowCount(const QModelIndex &/*parent*/) const
+{
+ return resourceList.count();
+}
+
+int ResourceTableModel::columnCount(const QModelIndex &/*parent*/) const
+{
+ return 5;
+}
+
+Qt::ItemFlags ResourceTableModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return Qt::ItemIsEnabled;
+
+ return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
+}
+
+QVariant ResourceTableModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (index.row() >= resourceList.size())
+ return QVariant();
+
+ if (role == Qt::DisplayRole || role == Qt::EditRole) {
+ switch (index.column()) {
+ case 0:
+ return resourceList[index.row()]->role();
+ case 1:
+ return resourceList[index.row()]->fullName();
+ case 2:
+ return 0;//resourceList.at(index.row()).available;
+ case 3:
+ return resourceList[index.row()]->status();
+ case 4:
+ return resourceList[index.row()]->cuType();
+ }
+
+ }
+ return QVariant();
+}
+
+bool ResourceTableModel::setData(const QModelIndex& index, const QVariant& value, int role)
+{
+ QString email, name;
+ if (index.isValid() && role == Qt::EditRole) {
+ switch (index.column()) {
+ case 0:
+ resourceList[index.row()]->setRole(static_cast<KCalCore::Attendee::Role>(value.toInt()));
+ break;
+ case 1:
+ KPIMUtils::extractEmailAddressAndName( value.toString(), email, name );
+ resourceList[index.row()]->setName(name);
+ resourceList[index.row()]->setEmail(email);
+ break;
+ case 2:
+ //resourceList[index.row()].available = value.toBool();
+ break;
+ case 3:
+ resourceList[index.row()]->setStatus(static_cast<KCalCore::Attendee::PartStat>(value.toInt()));
+ break;
+ case 4:
+ resourceList[index.row()]->setCuType(static_cast<KCalCore::Attendee::CuType>(value.toInt()));
+ break;
+ default:
+ return false;
+ }
+ emit dataChanged(index, index);
+ return true;
+ }
+ return false;
+}
+
+QVariant ResourceTableModel::headerData(int section, Qt::Orientation orientation,
+ int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (orientation == Qt::Horizontal) {
+ switch (section) {
+ case 0:
+ return QString("role");
+ case 1:
+ return QString("name");
+ case 2:
+ return QString("available");
+ case 3:
+ return QString("status");
+ case 4:
+ return QString("cuType");
+ }
+ }
+
+ return QVariant();
+}
+
+bool ResourceTableModel::insertRows(int position, int rows, const QModelIndex &parent)
+{
+ beginInsertRows(QModelIndex(), position, position + rows);
+
+ for (int row = 0; row < rows; ++row) {
+ KCalCore::Attendee::Ptr attendee(new KCalCore::Attendee("",""));
+ resourceList.insert(position, attendee);
+ }
+
+ endInsertRows();
+ return true;
+}
+
+bool ResourceTableModel::removeRows(int position, int rows, const QModelIndex &parent)
+{
+ beginRemoveRows(QModelIndex(), position, position + rows);
+
+ for (int row = 0; row < rows; ++row) {
+ resourceList.remove(position);
+ }
+
+ endRemoveRows();
+ return true;
+}
+
+bool ResourceTableModel::insertAttendee(int position, const KCalCore::Attendee::Ptr& attendee)
+{
+ beginInsertRows(QModelIndex(), position, position + 1);
+
+ resourceList.insert(position, attendee);
+
+ endInsertRows();
+
+ return true;
+}
+
+void ResourceTableModel::setAttendees(const KCalCore::Attendee::List resources)
+{
+ emit layoutAboutToBeChanged();
+
+ resourceList = resources;
+
+ emit layoutChanged();
+}
+
+
+KCalCore::Attendee::List ResourceTableModel::attendees() const
+{
+ return resourceList;
+}
+
+ResourceFilterProxyModel::ResourceFilterProxyModel(QObject *parent)
+: QSortFilterProxyModel(parent)
+{
+}
+
+bool ResourceFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+{
+ QModelIndex cuTypeIndex = sourceModel()->index(sourceRow, 4, sourceParent);
+ KCalCore::Attendee::CuType cuType = static_cast<KCalCore::Attendee::CuType>(sourceModel()->data(cuTypeIndex).toUInt());
+
+ return (cuType == KCalCore::Attendee::Resource || cuType == KCalCore::Attendee::Room);
+}
+
+AttendeeFilterProxyModel::AttendeeFilterProxyModel(QObject *parent)
+: QSortFilterProxyModel(parent)
+{
+}
+
+bool AttendeeFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+{
+ QModelIndex cuTypeIndex = sourceModel()->index(sourceRow, 4, sourceParent);
+ KCalCore::Attendee::CuType cuType = static_cast<KCalCore::Attendee::CuType>(sourceModel()->data(cuTypeIndex).toUInt());
+
+ return !(cuType == KCalCore::Attendee::Resource || cuType == KCalCore::Attendee::Room);
+}
diff --git a/incidenceeditor-ng/resourcetablemodel.h b/incidenceeditor-ng/resourcetablemodel.h
new file mode 100644
index 0000000..6925c1e
--- /dev/null
+++ b/incidenceeditor-ng/resourcetablemodel.h
@@ -0,0 +1,92 @@
+
+/*
+ Copyright (C) 2014 Sandro Knauà <knauss at kolabsys.com>
+
+ 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_INCIDENCERESOURCETABLEMODEL_H
+#define INCIDENCEEDITOR_INCIDENCERESOURCETABLEMODEL_H
+
+#include <KCalCore/Attendee>
+
+#include <QAbstractTableModel>
+#include <QSortFilterProxyModel>
+#include <QModelIndex>
+#include <QVector>
+
+namespace IncidenceEditorNG
+{
+
+/* TableView for the Resource Tab
+ * 0 = role
+ * 1 = name
+ * 2 = available
+ * 3 = status
+ * 4 = cutype
+ */
+
+class ResourceTableModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ ResourceTableModel(const KCalCore::Attendee::List &resources, QObject *parent = 0);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role) const;
+ QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const;
+
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ bool setData(const QModelIndex &index, const QVariant &value,
+ int role = Qt::EditRole);
+
+ bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex());
+ bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex());
+
+ bool insertAttendee(int position, const KCalCore::Attendee::Ptr &attendee);
+ void setAttendees(const KCalCore::Attendee::List resources);
+
+ KCalCore::Attendee::List attendees() const;
+
+private:
+ KCalCore::Attendee::List resourceList;
+};
+
+class ResourceFilterProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ ResourceFilterProxyModel(QObject *parent = 0);
+ bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
+};
+
+class AttendeeFilterProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ AttendeeFilterProxyModel(QObject *parent = 0);
+ bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
+};
+
+
+}
+
+#endif
+
+
More information about the commits
mailing list