diff options
| -rw-r--r-- | Swift/Controllers/Chat/MUCController.cpp | 22 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/MUCController.h | 6 | ||||
| -rw-r--r-- | Swift/Controllers/UIInterfaces/ChatWindow.h | 7 | ||||
| -rw-r--r-- | Swift/Controllers/UIInterfaces/InviteToChatWindow.h | 28 | ||||
| -rw-r--r-- | Swift/Controllers/UnitTest/MockChatWindow.h | 1 | ||||
| -rw-r--r-- | Swift/QtUI/QtChatWindow.cpp | 13 | ||||
| -rw-r--r-- | Swift/QtUI/QtChatWindow.h | 2 | ||||
| -rw-r--r-- | Swift/QtUI/QtInviteToChatWindow.cpp | 107 | ||||
| -rw-r--r-- | Swift/QtUI/QtInviteToChatWindow.h | 41 | ||||
| -rw-r--r-- | Swift/QtUI/SConscript | 1 |
10 files changed, 217 insertions, 11 deletions
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index e4209f4..3d04b34 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -13,18 +13,19 @@ #include <Swift/Controllers/Intl.h> #include <Swiften/Base/format.h> #include <Swiften/Network/Timer.h> #include <Swiften/Network/TimerFactory.h> #include <Swiften/Base/foreach.h> #include <SwifTools/TabComplete.h> #include <Swiften/Base/foreach.h> #include <Swift/Controllers/XMPPEvents/EventController.h> #include <Swift/Controllers/UIInterfaces/ChatWindow.h> +#include <Swift/Controllers/UIInterfaces/InviteToChatWindow.h> #include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h> #include <Swift/Controllers/UIEvents/UIEventStream.h> #include <Swift/Controllers/UIEvents/RequestChatUIEvent.h> #include <Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> #include <Swiften/Avatars/AvatarManager.h> #include <Swiften/Elements/Delay.h> #include <Swiften/MUC/MUC.h> @@ -58,32 +59,33 @@ MUCController::MUCController ( EventController* eventController, EntityCapsProvider* entityCapsProvider) : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider), muc_(muc), nick_(nick), desiredNick_(nick), password_(password) { parting_ = true; joined_ = false; lastWasPresence_ = false; shouldJoinOnReconnect_ = true; doneGettingHistory_ = false; events_ = uiEventStream; + inviteWindow_ = NULL; roster_ = new Roster(false, true); completer_ = new TabComplete(); chatWindow_->setRosterModel(roster_); chatWindow_->setTabComplete(completer_); chatWindow_->setName(muc->getJID().getNode()); chatWindow_->onClosed.connect(boost::bind(&MUCController::handleWindowClosed, this)); chatWindow_->onOccupantSelectionChanged.connect(boost::bind(&MUCController::handleWindowOccupantSelectionChanged, this, _1)); chatWindow_->onOccupantActionSelected.connect(boost::bind(&MUCController::handleActionRequestedOnOccupant, this, _1, _2)); chatWindow_->onChangeSubjectRequest.connect(boost::bind(&MUCController::handleChangeSubjectRequest, this, _1)); chatWindow_->onConfigureRequest.connect(boost::bind(&MUCController::handleConfigureRequest, this, _1)); chatWindow_->onConfigurationFormCancelled.connect(boost::bind(&MUCController::handleConfigurationCancelled, this)); chatWindow_->onDestroyRequest.connect(boost::bind(&MUCController::handleDestroyRoomRequest, this)); - chatWindow_->onInvitePersonToThisMUCRequest.connect(boost::bind(&MUCController::handleInvitePersonToThisMUCRequest, this, _1, _2)); + chatWindow_->onInvitePersonToThisMUCRequest.connect(boost::bind(&MUCController::handleInvitePersonToThisMUCRequest, this)); chatWindow_->onGetAffiliationsRequest.connect(boost::bind(&MUCController::handleGetAffiliationsRequest, this)); chatWindow_->onChangeAffiliationsRequest.connect(boost::bind(&MUCController::handleChangeAffiliationsRequest, this, _1)); muc_->onJoinComplete.connect(boost::bind(&MUCController::handleJoinComplete, this, _1)); muc_->onJoinFailed.connect(boost::bind(&MUCController::handleJoinFailed, this, _1)); muc_->onOccupantJoined.connect(boost::bind(&MUCController::handleOccupantJoined, this, _1)); muc_->onOccupantPresenceChange.connect(boost::bind(&MUCController::handleOccupantPresenceChange, this, _1)); muc_->onOccupantLeft.connect(boost::bind(&MUCController::handleOccupantLeft, this, _1, _2, _3)); muc_->onOccupantRoleChanged.connect(boost::bind(&MUCController::handleOccupantRoleChanged, this, _1, _2, _3)); muc_->onOccupantAffiliationChanged.connect(boost::bind(&MUCController::handleOccupantAffiliationChanged, this, _1, _2, _3)); @@ -713,20 +715,34 @@ void MUCController::handleConfigurationFormReceived(Form::ref form) { void MUCController::handleConfigurationCancelled() { muc_->cancelConfigureRoom(); } void MUCController::handleDestroyRoomRequest() { muc_->destroyRoom(); } -void MUCController::handleInvitePersonToThisMUCRequest(const JID& jid, const std::string& reason) { - muc_->invitePerson(jid, reason); +void MUCController::handleInvitePersonToThisMUCRequest() { + if (!inviteWindow_) { + inviteWindow_ = chatWindow_->createInviteToChatWindow(); + inviteWindow_->onCompleted.connect(boost::bind(&MUCController::handleInviteToMUCWindowCompleted, this)); + inviteWindow_->onDismissed.connect(boost::bind(&MUCController::handleInviteToMUCWindowDismissed, this)); + } +} + +void MUCController::handleInviteToMUCWindowDismissed() { + inviteWindow_= NULL; +} + +void MUCController::handleInviteToMUCWindowCompleted() { + foreach (const JID& jid, inviteWindow_->getJIDs()) { + muc_->invitePerson(jid, inviteWindow_->getReason()); + } } void MUCController::handleGetAffiliationsRequest() { muc_->requestAffiliationList(MUCOccupant::Owner); muc_->requestAffiliationList(MUCOccupant::Admin); muc_->requestAffiliationList(MUCOccupant::Member); muc_->requestAffiliationList(MUCOccupant::Outcast); } diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h index 9550ca9..8b43dcf 100644 --- a/Swift/Controllers/Chat/MUCController.h +++ b/Swift/Controllers/Chat/MUCController.h @@ -25,18 +25,19 @@ namespace Swift { class StanzaChannel; class IQRouter; class ChatWindowFactory; class Roster; class AvatarManager; class UIEventStream; class TimerFactory; class TabComplete; + class InviteToChatWindow; enum JoinPart {Join, Part, JoinThenPart, PartThenJoin}; struct NickJoinPart { NickJoinPart(const std::string& nick, JoinPart type) : nick(nick), type(type) {}; std::string nick; JoinPart type; }; @@ -89,24 +90,26 @@ namespace Swift { void updateJoinParts(); bool shouldUpdateJoinParts(); void dayTicked() {clearPresenceQueue();} void processUserPart(); void handleBareJIDCapsChanged(const JID& jid); void handleConfigureRequest(Form::ref); void handleConfigurationFailed(ErrorPayload::ref); void handleConfigurationFormReceived(Form::ref); void handleDestroyRoomRequest(); - void handleInvitePersonToThisMUCRequest(const JID& jid, const std::string& reason); + void handleInvitePersonToThisMUCRequest(); void handleConfigurationCancelled(); void handleOccupantRoleChangeFailed(ErrorPayload::ref, const JID&, MUCOccupant::Role); void handleGetAffiliationsRequest(); void handleAffiliationListReceived(MUCOccupant::Affiliation affiliation, const std::vector<JID>& jids); void handleChangeAffiliationsRequest(const std::vector<std::pair<MUCOccupant::Affiliation, JID> >& changes); + void handleInviteToMUCWindowDismissed(); + void handleInviteToMUCWindowCompleted(); private: MUC::ref muc_; UIEventStream* events_; std::string nick_; std::string desiredNick_; Roster* roster_; TabComplete* completer_; bool parting_; @@ -114,12 +117,13 @@ namespace Swift { bool lastWasPresence_; bool shouldJoinOnReconnect_; bool doneGettingHistory_; boost::bsignals::scoped_connection avatarChangedConnection_; boost::shared_ptr<Timer> loginCheckTimer_; std::set<std::string> currentOccupants_; std::vector<NickJoinPart> joinParts_; boost::posix_time::ptime lastActivity_; boost::optional<std::string> password_; + InviteToChatWindow* inviteWindow_; }; } diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index b5b1604..9188c7f 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -1,19 +1,19 @@ /* * Copyright (c) 2010-2012 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <boost/optional.hpp> -#include "Swiften/Base/boost_bsignals.h" +#include <Swiften/Base/boost_bsignals.h> #include <boost/shared_ptr.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <vector> #include <string> #include <Swiften/Elements/SecurityLabelsCatalog.h> #include <Swiften/Elements/ChatState.h> #include <Swiften/Elements/Form.h> #include <Swiften/Elements/MUCOccupant.h> @@ -21,18 +21,19 @@ namespace Swift { class AvatarManager; class TreeWidget; class Roster; class TabComplete; class RosterItem; class ContactRosterItem; class FileTransferController; + class InviteToChatWindow; class ChatWindow { public: enum AckState {Pending, Received, Failed}; enum ReceiptState {ReceiptRequested, ReceiptReceived}; enum Tristate {Yes, No, Maybe}; enum OccupantAction {Kick, Ban, MakeModerator, MakeParticipant, MakeVisitor, AddContact}; enum RoomAction {ChangeSubject, Configure, Affiliations, Destroy, Invite}; enum FileTransferState {WaitingForAccept, Negotiating, Transferring, Canceled, Finished, FTFailed}; @@ -99,31 +100,33 @@ namespace Swift { */ virtual void setAvailableOccupantActions(const std::vector<OccupantAction>& actions) = 0; /** * A room configuration has been requested, show the form. * If the form is cancelled, must emit onConfigurationFormCancelled(). */ virtual void showRoomConfigurationForm(Form::ref) = 0; + virtual InviteToChatWindow* createInviteToChatWindow() = 0; + boost::signal<void ()> onClosed; boost::signal<void ()> onAllMessagesRead; boost::signal<void (const std::string&, bool isCorrection)> onSendMessageRequest; boost::signal<void ()> onSendCorrectionMessageRequest; boost::signal<void ()> onUserTyping; boost::signal<void ()> onUserCancelsTyping; boost::signal<void ()> onAlertButtonClicked; boost::signal<void (ContactRosterItem*)> onOccupantSelectionChanged; boost::signal<void (ChatWindow::OccupantAction, ContactRosterItem*)> onOccupantActionSelected; boost::signal<void (const std::string&)> onChangeSubjectRequest; boost::signal<void (Form::ref)> onConfigureRequest; boost::signal<void ()> onDestroyRequest; - boost::signal<void (const JID&, const std::string& /*reason*/)> onInvitePersonToThisMUCRequest; + boost::signal<void ()> onInvitePersonToThisMUCRequest; boost::signal<void ()> onConfigurationFormCancelled; boost::signal<void ()> onGetAffiliationsRequest; boost::signal<void (MUCOccupant::Affiliation, const JID&)> onSetAffiliationRequest; boost::signal<void (const std::vector<std::pair<MUCOccupant::Affiliation, JID> >& changes)> onChangeAffiliationsRequest; boost::signal<void ()> onLogCleared; // File transfer related boost::signal<void (std::string /* id */)> onFileTransferCancel; boost::signal<void (std::string /* id */, std::string /* description */)> onFileTransferStart; diff --git a/Swift/Controllers/UIInterfaces/InviteToChatWindow.h b/Swift/Controllers/UIInterfaces/InviteToChatWindow.h new file mode 100644 index 0000000..f34a485 --- /dev/null +++ b/Swift/Controllers/UIInterfaces/InviteToChatWindow.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <vector> + +#include <string> +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/JID/JID.h> + +namespace Swift { + class InviteToChatWindow { + public: + virtual ~InviteToChatWindow() {}; + + virtual std::string getReason() const = 0; + + virtual std::vector<JID> getJIDs() const = 0; + + boost::signal<void ()> onCompleted; + boost::signal<void ()> onDismissed; + }; +} + diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h index e0e18a0..dbfef3e 100644 --- a/Swift/Controllers/UnitTest/MockChatWindow.h +++ b/Swift/Controllers/UnitTest/MockChatWindow.h @@ -48,18 +48,19 @@ namespace Swift { virtual void setAlert(const std::string& /*alertText*/, const std::string& /*buttonText*/) {}; virtual void cancelAlert() {}; virtual void setCorrectionEnabled(Tristate /*enabled*/) {} void setAvailableOccupantActions(const std::vector<OccupantAction>&/* actions*/) {} void setSubject(const std::string& /*subject*/) {} virtual void showRoomConfigurationForm(Form::ref) {} virtual void addMUCInvitation(const std::string& /*senderName*/, const JID& /*jid*/, const std::string& /*reason*/, const std::string& /*password*/, bool = true) {}; virtual void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&) {} virtual void setAvailableRoomActions(const std::vector<RoomAction> &) {}; + virtual InviteToChatWindow* createInviteToChatWindow() {return NULL;} std::string name_; std::string lastMessageBody_; std::vector<SecurityLabelsCatalog::Item> labels_; bool labelsEnabled_; SecurityLabelsCatalog::Item label_; }; } diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 52ce701..137c044 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -11,18 +11,19 @@ #include "Swift/Controllers/Roster/ContactRosterItem.h" #include "Roster/QtOccupantListWidget.h" #include "SwifTools/Linkify.h" #include "QtChatView.h" #include "MessageSnippet.h" #include "SystemMessageSnippet.h" #include "QtTextEdit.h" #include "QtSettingsProvider.h" #include "QtScaledAvatarCache.h" +#include "QtInviteToChatWindow.h" #include <Swiften/StringCodecs/Base64.h> #include "SwifTools/TabComplete.h" #include <Swift/Controllers/UIEvents/UIEventStream.h> #include <Swift/Controllers/UIEvents/SendFileUIEvent.h> #include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h> #include "QtChatWindowJSBridge.h" #include <boost/cstdint.hpp> @@ -837,23 +838,19 @@ void QtChatWindow::handleActionButtonClicked() { msgBox.setText(tr("Are you sure you want to destroy the room?")); msgBox.setInformativeText(tr("This will destroy the room.")); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); if (msgBox.exec() == QMessageBox::Yes) { onDestroyRequest(); } } else if (result == invite) { - bool ok; - QString jid = QInputDialog::getText(this, tr("Enter person's address"), tr("Address:"), QLineEdit::Normal, "", &ok); - if (ok) { - onInvitePersonToThisMUCRequest(JID(Q2PSTRING(jid)), ""); - } + onInvitePersonToThisMUCRequest(); } } void QtChatWindow::handleAffiliationEditorAccepted() { onChangeAffiliationsRequest(affiliationEditor_->getChanges()); } void QtChatWindow::setAffiliations(MUCOccupant::Affiliation affiliation, const std::vector<JID>& jids) { if (!affiliationEditor_) return; @@ -902,10 +899,16 @@ void QtChatWindow::addMUCInvitation(const std::string& senderName, const JID& ji } QString qAvatarPath = "qrc:/icons/avatar.png"; messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new MessageSnippet(htmlString, Qt::escape(P2QSTRING(senderName)), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, false, appendToPrevious, theme_, id))); previousMessageWasSelf_ = false; previousSenderName_ = P2QSTRING(senderName); previousMessageKind_ = PreviousMessageWasMUCInvite; } + +InviteToChatWindow* QtChatWindow::createInviteToChatWindow() { + return new QtInviteToChatWindow(this); +} + + } diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index 4b888eb..ff26c9c 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.h @@ -85,18 +85,20 @@ namespace Swift { void flash(); QByteArray getSplitterState(); virtual void setAvailableOccupantActions(const std::vector<OccupantAction>& actions); void setSubject(const std::string& subject); void showRoomConfigurationForm(Form::ref); void addMUCInvitation(const std::string& senderName, const JID& jid, const std::string& reason, const std::string& password, bool direct = true); void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&); void setAvailableRoomActions(const std::vector<RoomAction> &actions); + InviteToChatWindow* createInviteToChatWindow(); + static QString buildChatWindowButton(const QString& name, const QString& id, const QString& arg1 = QString(), const QString& arg2 = QString(), const QString& arg3 = QString()); public slots: void handleChangeSplitterState(QByteArray state); void handleFontResized(int fontSizeSteps); void setAlert(const std::string& alertText, const std::string& buttonText = ""); void cancelAlert(); void setCorrectionEnabled(Tristate enabled); diff --git a/Swift/QtUI/QtInviteToChatWindow.cpp b/Swift/QtUI/QtInviteToChatWindow.cpp new file mode 100644 index 0000000..d53c493 --- /dev/null +++ b/Swift/QtUI/QtInviteToChatWindow.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2012 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swift/QtUI/QtInviteToChatWindow.h> + +#include <QHBoxLayout> +#include <QCompleter> +#include <QLabel> +#include <QLineEdit> +#include <QPushButton> +#include <QDialogButtonBox> + +#include <Swift/QtUI/QtSwiftUtil.h> + +namespace Swift { + +QtInviteToChatWindow::QtInviteToChatWindow(QWidget* parent) : QDialog(parent) { + QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom, this); + layout->setContentsMargins(0,0,0,0); + layout->setSpacing(2); + + QLabel* description = new QLabel(tr("Users to invite to this chat (one per line):")); + layout->addWidget(description); + + jidsLayout_ = new QBoxLayout(QBoxLayout::TopToBottom); + layout->addLayout(jidsLayout_); + + QLabel* reasonLabel = new QLabel(tr("If you want to provide a reason for the invitation, enter it here")); + layout->addWidget(reasonLabel); + reason_ = new QLineEdit(this); + layout->addWidget(reason_); + addJIDLine(); + + connect(this, SIGNAL(accepted()), this, SLOT(handleAccepting())); + connect(this, SIGNAL(rejected()), this, SLOT(handleRejecting())); + + + QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + + connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + layout->addWidget(buttonBox); + + setModal(false); + show(); +} + +QtInviteToChatWindow::~QtInviteToChatWindow() { + +} + +void QtInviteToChatWindow::handleAccepting() { + onCompleted(); +} + +void QtInviteToChatWindow::handleRejecting() { + onDismissed(); +} + +std::string QtInviteToChatWindow::getReason() const { + return Q2PSTRING(reason_->text()); +} + +std::vector<JID> QtInviteToChatWindow::getJIDs() const { + std::vector<JID> results; + foreach (QLineEdit* jidEdit, jids_) { + QStringList parts = jidEdit->text().split(" "); + if (parts.size() > 0) { + JID jid(Q2PSTRING(parts.last())); + if (jid.isValid() && !jid.getNode().empty()) { + results.push_back(jid); + } + } + } + return results; +} + +void QtInviteToChatWindow::addJIDLine() { + QLineEdit* jid = new QLineEdit(this); + QCompleter* completer = new QCompleter(completions_, this); + completer->setCaseSensitivity(Qt::CaseInsensitive); + jid->setCompleter(completer); + jids_.push_back(jid); + jidsLayout_->addWidget(jid); + connect(jid, SIGNAL(textChanged(const QString&)), this, SLOT(handleJIDTextChanged())); +} + +void QtInviteToChatWindow::handleJIDTextChanged() { + bool gotEmpty = false; + foreach(QLineEdit* edit, jids_) { + if (edit->text().isEmpty()) { + gotEmpty = true; + } + } + if (!gotEmpty) { + addJIDLine(); + } +} + +} + + + diff --git a/Swift/QtUI/QtInviteToChatWindow.h b/Swift/QtUI/QtInviteToChatWindow.h new file mode 100644 index 0000000..c009861 --- /dev/null +++ b/Swift/QtUI/QtInviteToChatWindow.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swift/Controllers/UIInterfaces/InviteToChatWindow.h> + +#include <QDialog> +#include <QStringList> + +class QLineEdit; +class QBoxLayout; + +namespace Swift { + class QtInviteToChatWindow : public QDialog, public InviteToChatWindow { + Q_OBJECT + public: + QtInviteToChatWindow(QWidget* parent = NULL); + virtual ~QtInviteToChatWindow(); + + virtual std::string getReason() const; + + virtual std::vector<JID> getJIDs() const; + private: + void addJIDLine(); + private slots: + void handleJIDTextChanged(); + void handleAccepting(); + void handleRejecting(); + private: + QStringList completions_; + QLineEdit* reason_; + QBoxLayout* jidsLayout_; + std::vector<QLineEdit*> jids_; + }; +} + + diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 4c53313..042e2a0 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -103,18 +103,19 @@ sources = [ "QtContactEditWidget.cpp", "ChatSnippet.cpp", "MessageSnippet.cpp", "SystemMessageSnippet.cpp", "QtElidingLabel.cpp", "QtFormWidget.cpp", "QtFormResultItemModel.cpp", "QtLineEdit.cpp", "QtJoinMUCWindow.cpp", + "QtInviteToChatWindow.cpp", "Roster/RosterModel.cpp", "Roster/QtTreeWidget.cpp", # "Roster/QtTreeWidgetItem.cpp", "Roster/RosterDelegate.cpp", "Roster/GroupItemDelegate.cpp", "Roster/DelegateCommons.cpp", "Roster/QtRosterWidget.cpp", "Roster/QtOccupantListWidget.cpp", "EventViewer/EventModel.cpp", |
Swift