diff --git a/CMakeLists.txt b/CMakeLists.txt index e57d389..e0b5bf9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,87 +1,88 @@ project (ktp-contactlist) set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" ${CMAKE_MODULE_PATH} ) set(IS_KTP_INTERNAL_MODULE TRUE) set(KDE_MIN_VERSION "4.4.75") find_package (KDE4 4.4.75 REQUIRED) find_package (TelepathyQt4 0.8.90 REQUIRED) find_package (KTp REQUIRED) include (KDE4Defaults) include (MacroLibrary) add_definitions (${KDE4_DEFINITIONS} ) include_directories (${KDE4_INCLUDES} ${TELEPATHY_QT4_INCLUDE_DIR} ${KTP_INCLUDE_DIR} ) set (ktp_contactlist_SRCS + rooms-model.cpp contact-list-widget.cpp context-menu.cpp abstract-contact-delegate.cpp contact-list-application.cpp contact-view-hover-button.cpp contact-overlays.cpp contact-delegate-overlay.cpp contact-delegate.cpp contact-delegate-compact.cpp account-button.cpp account-buttons-panel.cpp filter-bar.cpp main.cpp main-widget.cpp global-presence-chooser.cpp dialogs/add-contact-dialog.cpp dialogs/join-chat-room-dialog.cpp dialogs/remove-contact-dialog.cpp dialogs/contact-info.cpp dialogs/custom-presence-dialog.cpp presence-model.cpp tooltips/ktooltip.cpp tooltips/tooltipmanager.cpp tooltips/ktooltipwindow.cpp tooltips/contacttooltip.cpp ) kde4_add_ui_files (ktp_contactlist_SRCS main-widget.ui dialogs/add-contact-dialog.ui dialogs/join-chat-room-dialog.ui dialogs/remove-contact-dialog.ui dialogs/contact-info.ui tooltips/contacttooltip.ui ) add_subdirectory (icons) kde4_add_executable (ktp-contactlist ${ktp_contactlist_SRCS} ) target_link_libraries (ktp-contactlist ${TELEPATHY_QT4_LIBRARIES} ${KTP_LIBRARIES} ${KTP_MODELS_LIBRARIES} ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} ${KDE4_KCMUTILS_LIBS} ) # Install: install (TARGETS ktp-contactlist DESTINATION ${BIN_INSTALL_DIR} ) install(FILES ktelepathy.notifyrc DESTINATION ${DATA_INSTALL_DIR}/ktelepathy) install (PROGRAMS ktp-contactlist.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} ) diff --git a/dialogs/join-chat-room-dialog.cpp b/dialogs/join-chat-room-dialog.cpp index 164f910..06d0a3a 100644 --- a/dialogs/join-chat-room-dialog.cpp +++ b/dialogs/join-chat-room-dialog.cpp @@ -1,89 +1,233 @@ /* * This file is part of telepathy-contactslist-prototype * * Copyright (C) 2011 Francesco Nwokeka + * Copyright (C) 2012 Dominik Cermak * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "join-chat-room-dialog.h" #include "ui_join-chat-room-dialog.h" #include #include +#include #include +#include +#include +#include +#include + +#include + +#include + +#include JoinChatRoomDialog::JoinChatRoomDialog(Tp::AccountManagerPtr accountManager, QWidget* parent) : KDialog(parent, Qt::Dialog) , ui(new Ui::JoinChatRoomDialog) + , m_model(new RoomsModel(this) + ) { QWidget *joinChatRoomDialog = new QWidget(this); m_accounts = accountManager->allAccounts(); ui->setupUi(joinChatRoomDialog); setMainWidget(joinChatRoomDialog); + setWindowIcon(KIcon("telepathy-kde")); // disable OK button on start button(Ok)->setEnabled(false); - // populate combobox with accounts that support chat rooms for (int i = 0; i < m_accounts.count(); ++i) { Tp::AccountPtr acc = m_accounts.at(i); if (acc->capabilities().textChatrooms() && acc->isOnline()) { // add unique data to identify the correct account later on ui->comboBox->addItem(KIcon(acc->iconName()), acc->displayName(), acc->uniqueIdentifier()); } } + if (ui->comboBox->count() > 0) { + ui->queryPushButton->setEnabled(true); + } + + QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this); + proxyModel->setSourceModel(m_model); + proxyModel->setSortLocaleAware(true); + proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + proxyModel->setFilterKeyColumn(RoomsModel::NameColumn); + proxyModel->setDynamicSortFilter(true); + + ui->treeView->setModel(proxyModel); + ui->treeView->header()->setResizeMode(QHeaderView::ResizeToContents); + ui->treeView->sortByColumn(RoomsModel::NameColumn, Qt::AscendingOrder); + // connects connect(ui->lineEdit, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString))); + connect(ui->queryPushButton, SIGNAL(clicked(bool)), this, SLOT(getRoomList())); + connect(ui->stopPushButton, SIGNAL(clicked(bool)), this, SLOT(stopListing())); + connect(ui->treeView, SIGNAL(clicked(QModelIndex)), this, SLOT(onRoomClicked(QModelIndex))); + connect(ui->filterBar, SIGNAL(textChanged(QString)), proxyModel, SLOT(setFilterFixedString(QString))); } JoinChatRoomDialog::~JoinChatRoomDialog() { delete ui; } Tp::AccountPtr JoinChatRoomDialog::selectedAccount() const { Tp::AccountPtr account; bool found = false; for (int i = 0; i < m_accounts.count() && !found; ++i) { if (m_accounts.at(i)->uniqueIdentifier() == ui->comboBox->itemData(ui->comboBox->currentIndex()).toString()) { account = m_accounts.at(i); found = true; } } // account should never be empty return account; } +void JoinChatRoomDialog::getRoomList() +{ + Tp::AccountPtr account = selectedAccount(); + + // Clear the list from previous items + m_model->clearRoomInfoList(); + + // Build the channelrequest + QVariantMap request; + request.insert(TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType"), + TP_QT_IFACE_CHANNEL_TYPE_ROOM_LIST); + request.insert(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType"), + Tp::HandleTypeNone); + + // If the user provided a server use it, else use the standard server for the selected account + if (!ui->serverLineEdit->text().isEmpty()) { + request.insert(TP_QT_IFACE_CHANNEL + QLatin1String(".Type.RoomList.Server"), + ui->serverLineEdit->text()); + } + + m_pendingRoomListChannel = account->createAndHandleChannel(request, QDateTime::currentDateTime()); + connect(m_pendingRoomListChannel, SIGNAL(finished(Tp::PendingOperation*)), + this, SLOT(onRoomListChannelReadyForHandling(Tp::PendingOperation*))); + +} + +void JoinChatRoomDialog::stopListing() +{ + m_iface->StopListing(); +} + +void JoinChatRoomDialog::onRoomListChannelReadyForHandling(Tp::PendingOperation *operation) +{ + if (operation->isError()) { + kDebug() << operation->errorName(); + kDebug() << operation->errorMessage(); + QString errorMsg(operation->errorName() + QLatin1String(": ") + operation->errorMessage()); + sendNotificationToUser(errorMsg); + } else { + m_roomListChannel = m_pendingRoomListChannel->channel(); + + connect(m_roomListChannel->becomeReady(), + SIGNAL(finished(Tp::PendingOperation*)), + SLOT(onRoomListChannelReady(Tp::PendingOperation*))); + } +} + +void JoinChatRoomDialog::onRoomListChannelReady(Tp::PendingOperation *operation) +{ + if (operation->isError()) { + kDebug() << operation->errorName(); + kDebug() << operation->errorMessage(); + QString errorMsg(operation->errorName() + QLatin1String(": ") + operation->errorMessage()); + sendNotificationToUser(errorMsg); + } else { + m_iface = m_roomListChannel->interface(); + + m_iface->ListRooms(); + + connect(m_iface, SIGNAL(ListingRooms(bool)), SLOT(onListing(bool))); + connect(m_iface, SIGNAL(GotRooms(Tp::RoomInfoList)), SLOT(onGotRooms(Tp::RoomInfoList))); + } +} + +void JoinChatRoomDialog::onRoomListChannelClosed(Tp::PendingOperation *operation) +{ + if (operation->isError()) { + kDebug() << operation->errorName(); + kDebug() << operation->errorMessage(); + QString errorMsg(operation->errorName() + QLatin1String(": ") + operation->errorMessage()); + sendNotificationToUser(errorMsg); + } else { + ui->queryPushButton->setEnabled(true); + ui->stopPushButton->setEnabled(false); + } +} + +void JoinChatRoomDialog::onListing(bool isListing) +{ + if (isListing) { + kDebug() << "listing"; + ui->queryPushButton->setEnabled(false); + ui->stopPushButton->setEnabled(true); + } else { + kDebug() << "finished listing"; + Tp::PendingOperation *op = m_roomListChannel->requestClose(); + connect(op, + SIGNAL(finished(Tp::PendingOperation*)), + SLOT(onRoomListChannelClosed(Tp::PendingOperation*))); + } +} + +void JoinChatRoomDialog::onGotRooms(Tp::RoomInfoList roomInfoList) +{ + m_model->addRooms(roomInfoList); +} + +void JoinChatRoomDialog::onRoomClicked(const QModelIndex& index) +{ + ui->lineEdit->setText(index.data(RoomsModel::HandleNameRole).toString()); +} + QString JoinChatRoomDialog::selectedChatRoom() const { return ui->lineEdit->text(); } void JoinChatRoomDialog::onTextChanged(QString newText) { if (button(Ok)->isEnabled() == newText.isEmpty()) { button(Ok)->setEnabled(!newText.isEmpty()); } } +void JoinChatRoomDialog::sendNotificationToUser(const QString& errorMsg) +{ + //The pointer is automatically deleted when the event is closed + KNotification *notification; + notification = new KNotification(QLatin1String("telepathyError"), this); + + notification->setText(errorMsg); + notification->sendEvent(); +} diff --git a/dialogs/join-chat-room-dialog.h b/dialogs/join-chat-room-dialog.h index d0aba22..b5f7c67 100644 --- a/dialogs/join-chat-room-dialog.h +++ b/dialogs/join-chat-room-dialog.h @@ -1,51 +1,67 @@ /* * This file is part of telepathy-contactslist-prototype * * Copyright (C) 2011 Francesco Nwokeka * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef JOINCHATROOMDIALOG_H #define JOINCHATROOMDIALOG_H #include #include namespace Ui { class JoinChatRoomDialog; } +class RoomsModel; + class JoinChatRoomDialog : public KDialog { Q_OBJECT public: explicit JoinChatRoomDialog(Tp::AccountManagerPtr accountManager, QWidget *parent = 0); ~JoinChatRoomDialog(); Tp::AccountPtr selectedAccount() const; /** returns selected account */ QString selectedChatRoom() const; /** returns selected chat room */ private slots: void onTextChanged(QString newText); + void getRoomList(); + void stopListing(); + void onRoomListChannelReadyForHandling(Tp::PendingOperation *operation); + void onRoomListChannelReady(Tp::PendingOperation *operation); + void onRoomListChannelClosed(Tp::PendingOperation *operation); + void onListing(bool isListing); + void onGotRooms(Tp::RoomInfoList roomInfoList); + void onRoomClicked(const QModelIndex &index); private: + void sendNotificationToUser(const QString& errorMsg); + QList m_accounts; Ui::JoinChatRoomDialog *ui; + Tp::PendingChannel *m_pendingRoomListChannel; + Tp::ChannelPtr m_roomListChannel; + Tp::Client::ChannelTypeRoomListInterface *m_iface; + RoomsModel *m_model; }; #endif // JOINCHATROOMDIALOG_H diff --git a/dialogs/join-chat-room-dialog.ui b/dialogs/join-chat-room-dialog.ui index 6c64151..bec0805 100644 --- a/dialogs/join-chat-room-dialog.ui +++ b/dialogs/join-chat-room-dialog.ui @@ -1,43 +1,128 @@ JoinChatRoomDialog 0 0 - 400 - 134 + 525 + 325 + + + 525 + 0 + + + + Join Chatroom + Enter chat room: + + + + Server to be queried: + + + + + + + + + + + + Leave blank for the selected account's default server + + + true + + + + + + + false + + + Query + + + + + + + false + + + Stop + + + + + + + + + true + + + QAbstractItemView::ExtendedSelection + + + false + + + true + + + true + + + + + + + + + + Search rooms + + + true + + + KComboBox QComboBox
kcombobox.h
KLineEdit QLineEdit
klineedit.h
diff --git a/rooms-model.cpp b/rooms-model.cpp new file mode 100644 index 0000000..8a5cbb0 --- /dev/null +++ b/rooms-model.cpp @@ -0,0 +1,146 @@ +/* + * Rooms Model - A model of chatrooms. + * Copyright (C) 2012 Dominik Cermak + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "rooms-model.h" +#include +#include + +RoomsModel::RoomsModel(QObject *parent): QAbstractListModel(parent) +{ +} + +int RoomsModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } else { + return m_roomInfoList.size(); + } +} + +int RoomsModel::columnCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } else { + return 4; + } +} + +QVariant RoomsModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + if (index.row() >= m_roomInfoList.count()) { + return QVariant(); + } + + const int row = index.row(); + const Tp::RoomInfo &roomInfo = m_roomInfoList.at(row); + + // this is handled here because when putting it in the switch below + // all columns get an empty space for the decoration + if (index.column() == PasswordColumn) { + switch (role) { + case Qt::DecorationRole: + if (roomInfo.info.value("password").toBool()) { + return KIcon("object-locked"); + } else { + return QVariant(); + } + case Qt::ToolTipRole: + if (roomInfo.info.value("password").toBool()) { + return i18n("Password required"); + } else { + return i18n("No password required"); + } + } + } + + switch(role) { + case Qt::DisplayRole: + switch (index.column()) { + case PasswordColumn: + return QVariant(); + case NameColumn: + return roomInfo.info.value(QString("name")); + case DescriptionColumn: + return roomInfo.info.value(QString("description")); + case MembersColumn: + return roomInfo.info.value(QString("members")); + } + case Qt::ToolTipRole: + switch (index.column()) { + case MembersColumn: + return i18n("Member count"); + } + case RoomsModel::HandleNameRole: + return roomInfo.info.value(QString("handle-name")); + } + + return QVariant(); +} + +QVariant RoomsModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole && role != Qt::DecorationRole) { + return QVariant(); + } + + if (orientation == Qt::Horizontal) { + switch (role) { + case Qt::DisplayRole: + switch (section) { + case NameColumn: + return i18nc("Chatrooms name", "Name"); + case DescriptionColumn: + return i18nc("Chatrooms description", "Description"); + } + case Qt::DecorationRole: + switch (section) { + case PasswordColumn: + return KIcon("object-locked"); + case MembersColumn: + return KIcon("meeting-participant"); + } + } + } + + return QVariant(); +} + +void RoomsModel::addRooms(const Tp::RoomInfoList newRoomList) +{ + if (newRoomList.size() > 0) { + beginInsertRows(QModelIndex(), m_roomInfoList.size(), m_roomInfoList.size() + newRoomList.size() - 1); + m_roomInfoList.append(newRoomList); + endInsertRows(); + } +} + +void RoomsModel::clearRoomInfoList() +{ + if (m_roomInfoList.size() > 0) { + beginRemoveRows(QModelIndex(), 0, m_roomInfoList.size() - 1); + m_roomInfoList.clear(); + endRemoveRows(); + } +} diff --git a/rooms-model.h b/rooms-model.h new file mode 100644 index 0000000..675ea4c --- /dev/null +++ b/rooms-model.h @@ -0,0 +1,65 @@ +/* + * Rooms Model - A model of chatrooms. + * Copyright (C) 2012 Dominik Cermak + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ROOMSMODEL_H +#define ROOMSMODEL_H + +#include +#include + +class RoomsModel : public QAbstractListModel +{ + Q_OBJECT + +public: + // TODO: find a suitable icon and add an invitation column + enum Column { + PasswordColumn=0, + MembersColumn, + NameColumn, + DescriptionColumn + }; + + enum Roles { + HandleNameRole = Qt::UserRole + }; + + explicit RoomsModel(QObject *parent = 0); + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; + + /** + * \brief Add new rooms to the list. + * + * \param newRoomList The list with the new rooms to add. + */ + void addRooms(const Tp::RoomInfoList newRoomList); + + /** + * \brief Clear the room list. + */ + void clearRoomInfoList(); + +private: + Tp::RoomInfoList m_roomInfoList; +}; + +#endif // ROOMSMODEL_H