diff options
author | Mateusz Piekos <mateuszpiekos@gmail.com> | 2012-05-30 12:40:27 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2012-09-08 16:14:27 (GMT) |
commit | fe8a8aa031da734f3112184420b372021d9e10c7 (patch) | |
tree | 9f8e0b7d11d7612eb25a8682cf940fa647ca67f2 /Swift/QtUI | |
parent | 0174723efbc1f612433d45c6916a2ad4596b96ba (diff) | |
download | swift-contrib-fe8a8aa031da734f3112184420b372021d9e10c7.zip swift-contrib-fe8a8aa031da734f3112184420b372021d9e10c7.tar.bz2 |
Support whiteboarding.
License: This patch is BSD-licensed, see http://www.opensource.org/licenses/bsd-license.php
Diffstat (limited to 'Swift/QtUI')
28 files changed, 1790 insertions, 0 deletions
diff --git a/Swift/QtUI/ChatList/ChatListDelegate.cpp b/Swift/QtUI/ChatList/ChatListDelegate.cpp index bcd1585..5b879df 100644 --- a/Swift/QtUI/ChatList/ChatListDelegate.cpp +++ b/Swift/QtUI/ChatList/ChatListDelegate.cpp @@ -12,6 +12,7 @@ #include "Swift/QtUI/ChatList/ChatListItem.h" #include "Swift/QtUI/ChatList/ChatListMUCItem.h" #include "Swift/QtUI/ChatList/ChatListRecentItem.h" +#include "Swift/QtUI/ChatList/ChatListWhiteboardItem.h" #include "Swift/QtUI/ChatList/ChatListGroupItem.h" namespace Swift { @@ -38,6 +39,9 @@ QSize ChatListDelegate::sizeHint(const QStyleOptionViewItem& option, const QMode } else if (item && dynamic_cast<ChatListGroupItem*>(item)) { return groupDelegate_->sizeHint(option, index); + } + else if (item && dynamic_cast<ChatListWhiteboardItem*>(item)) { + return common_.contactSizeHint(option, index, compact_); } return QStyledItemDelegate::sizeHint(option, index); } @@ -65,6 +69,9 @@ void ChatListDelegate::paint(QPainter* painter, const QStyleOptionViewItem& opti ChatListGroupItem* group = dynamic_cast<ChatListGroupItem*>(item); groupDelegate_->paint(painter, option, group->data(Qt::DisplayRole).toString(), group->rowCount(), option.state & QStyle::State_Open); } + else if (item && dynamic_cast<ChatListWhiteboardItem*>(item)) { + paintWhiteboard(painter, option, dynamic_cast<ChatListWhiteboardItem*>(item)); + } else { QStyledItemDelegate::paint(painter, option, index); } @@ -116,4 +123,19 @@ void ChatListDelegate::paintRecent(QPainter* painter, const QStyleOptionViewItem common_.paintContact(painter, option, nameColor, avatarPath, presenceIcon, name, statusText, item->getChat().unreadCount, compact_); } +void ChatListDelegate::paintWhiteboard(QPainter* painter, const QStyleOptionViewItem& option, ChatListWhiteboardItem* item) const { + QColor nameColor = item->data(Qt::TextColorRole).value<QColor>(); + QString avatarPath; + if (item->data(ChatListWhiteboardItem::AvatarRole).isValid() && !item->data(ChatListWhiteboardItem::AvatarRole).value<QString>().isNull()) { + avatarPath = item->data(ChatListWhiteboardItem::AvatarRole).value<QString>(); + } + QIcon presenceIcon;/* = item->data(ChatListWhiteboardItem::PresenceIconRole).isValid() && !item->data(ChatListWhiteboardItem::PresenceIconRole).value<QIcon>().isNull() + ? item->data(ChatListWhiteboardItem::PresenceIconRole).value<QIcon>() + : QIcon(":/icons/offline.png");*/ + QString name = item->data(Qt::DisplayRole).toString(); + //qDebug() << "Avatar for " << name << " = " << avatarPath; + QString statusText = item->data(ChatListWhiteboardItem::DetailTextRole).toString(); + common_.paintContact(painter, option, nameColor, avatarPath, presenceIcon, name, statusText, item->getChat().unreadCount, compact_); +} + } diff --git a/Swift/QtUI/ChatList/ChatListDelegate.h b/Swift/QtUI/ChatList/ChatListDelegate.h index 5ac45ce..9460c28 100644 --- a/Swift/QtUI/ChatList/ChatListDelegate.h +++ b/Swift/QtUI/ChatList/ChatListDelegate.h @@ -13,6 +13,7 @@ namespace Swift { class ChatListMUCItem; class ChatListRecentItem; + class ChatListWhiteboardItem; class ChatListDelegate : public QStyledItemDelegate { public: ChatListDelegate(bool compact); @@ -24,6 +25,7 @@ namespace Swift { private: void paintMUC(QPainter* painter, const QStyleOptionViewItem& option, ChatListMUCItem* item) const; void paintRecent(QPainter* painter, const QStyleOptionViewItem& option, ChatListRecentItem* item) const; + void paintWhiteboard(QPainter* painter, const QStyleOptionViewItem& option, ChatListWhiteboardItem* item) const; QSize mucSizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const; QSize recentSizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const; diff --git a/Swift/QtUI/ChatList/ChatListModel.cpp b/Swift/QtUI/ChatList/ChatListModel.cpp index 681c1c2..15f4dfe 100644 --- a/Swift/QtUI/ChatList/ChatListModel.cpp +++ b/Swift/QtUI/ChatList/ChatListModel.cpp @@ -8,6 +8,7 @@ #include <Swift/QtUI/ChatList/ChatListMUCItem.h> #include <Swift/QtUI/ChatList/ChatListRecentItem.h> +#include <Swift/QtUI/ChatList/ChatListWhiteboardItem.h> namespace Swift { @@ -15,8 +16,10 @@ ChatListModel::ChatListModel() { root_ = new ChatListGroupItem("", NULL, false); mucBookmarks_ = new ChatListGroupItem(tr("Bookmarked Rooms"), root_); recents_ = new ChatListGroupItem(tr("Recent Chats"), root_, false); + whiteboards_ = new ChatListGroupItem(tr("Opened Whiteboards"), root_, false); root_->addItem(recents_); root_->addItem(mucBookmarks_); + root_->addItem(whiteboards_); } void ChatListModel::clearBookmarks() { @@ -46,11 +49,30 @@ void ChatListModel::removeMUCBookmark(const Swift::MUCBookmark& bookmark) { } } +void ChatListModel::addWhiteboardSession(const ChatListWindow::Chat& chat) { + emit layoutAboutToBeChanged(); + whiteboards_->addItem(new ChatListWhiteboardItem(chat, whiteboards_)); + emit layoutChanged(); +} + +void ChatListModel::removeWhiteboardSession(const JID& jid) { + for (int i = 0; i < whiteboards_->rowCount(); i++) { + ChatListWhiteboardItem* item = dynamic_cast<ChatListWhiteboardItem*>(whiteboards_->item(i)); + if (item->getChat().jid == jid) { + emit layoutAboutToBeChanged(); + whiteboards_->remove(i); + emit layoutChanged(); + break; + } + } +} + void ChatListModel::setRecents(const std::list<ChatListWindow::Chat>& recents) { emit layoutAboutToBeChanged(); recents_->clear(); foreach (const ChatListWindow::Chat chat, recents) { recents_->addItem(new ChatListRecentItem(chat, recents_)); +//whiteboards_->addItem(new ChatListRecentItem(chat, whiteboards_)); } emit layoutChanged(); } diff --git a/Swift/QtUI/ChatList/ChatListModel.h b/Swift/QtUI/ChatList/ChatListModel.h index 8e7828c..e384a04 100644 --- a/Swift/QtUI/ChatList/ChatListModel.h +++ b/Swift/QtUI/ChatList/ChatListModel.h @@ -23,6 +23,8 @@ namespace Swift { ChatListModel(); void addMUCBookmark(const MUCBookmark& bookmark); void removeMUCBookmark(const MUCBookmark& bookmark); + void addWhiteboardSession(const ChatListWindow::Chat& chat); + void removeWhiteboardSession(const JID& jid); int columnCount(const QModelIndex& parent = QModelIndex()) const; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const; @@ -34,6 +36,7 @@ namespace Swift { private: ChatListGroupItem* mucBookmarks_; ChatListGroupItem* recents_; + ChatListGroupItem* whiteboards_; ChatListGroupItem* root_; }; diff --git a/Swift/QtUI/ChatList/ChatListWhiteboardItem.cpp b/Swift/QtUI/ChatList/ChatListWhiteboardItem.cpp new file mode 100644 index 0000000..41648b6 --- /dev/null +++ b/Swift/QtUI/ChatList/ChatListWhiteboardItem.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swift/QtUI/ChatList/ChatListWhiteboardItem.h> + +#include <Swift/QtUI/QtSwiftUtil.h> + +namespace Swift { + ChatListWhiteboardItem::ChatListWhiteboardItem(const ChatListWindow::Chat& chat, ChatListGroupItem* parent) : ChatListItem(parent), chat_(chat) { + + } + + const ChatListWindow::Chat& ChatListWhiteboardItem::getChat() const { + return chat_; + } + + QVariant ChatListWhiteboardItem::data(int role) const { + switch (role) { + case Qt::DisplayRole: return P2QSTRING(chat_.chatName); + case DetailTextRole: return P2QSTRING(chat_.activity); + /*case Qt::TextColorRole: return textColor_; + case Qt::BackgroundColorRole: return backgroundColor_; + case Qt::ToolTipRole: return isContact() ? toolTipString() : QVariant(); + case StatusTextRole: return statusText_;*/ + case AvatarRole: return QVariant(QString(chat_.avatarPath.string().c_str())); + case PresenceIconRole: return getPresenceIcon(); + default: return QVariant(); + } + } + + QIcon ChatListWhiteboardItem::getPresenceIcon() const { + QString iconString; + switch (chat_.statusType) { + case StatusShow::Online: iconString = "online";break; + case StatusShow::Away: iconString = "away";break; + case StatusShow::XA: iconString = "away";break; + case StatusShow::FFC: iconString = "online";break; + case StatusShow::DND: iconString = "dnd";break; + case StatusShow::None: iconString = "offline";break; + } + return QIcon(":/icons/" + iconString + ".png"); + } +} + diff --git a/Swift/QtUI/ChatList/ChatListWhiteboardItem.h b/Swift/QtUI/ChatList/ChatListWhiteboardItem.h new file mode 100644 index 0000000..2dc6255 --- /dev/null +++ b/Swift/QtUI/ChatList/ChatListWhiteboardItem.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <QList> +#include <QIcon> + +#include <boost/shared_ptr.hpp> + +#include <Swiften/MUC/MUCBookmark.h> +#include <Swift/Controllers/UIInterfaces/ChatListWindow.h> + +#include <Swift/QtUI/ChatList/ChatListItem.h> + +namespace Swift { + class ChatListWhiteboardItem : public ChatListItem { + public: + enum RecentItemRoles { + DetailTextRole = Qt::UserRole, + AvatarRole = Qt::UserRole + 1, + PresenceIconRole = Qt::UserRole + 2/*, + StatusShowTypeRole = Qt::UserRole + 3*/ + }; + ChatListWhiteboardItem(const ChatListWindow::Chat& chat, ChatListGroupItem* parent); + const ChatListWindow::Chat& getChat() const; + QVariant data(int role) const; + private: + QIcon getPresenceIcon() const; + ChatListWindow::Chat chat_; + }; +} diff --git a/Swift/QtUI/ChatList/QtChatListWindow.cpp b/Swift/QtUI/ChatList/QtChatListWindow.cpp index 42eb43b..9692c9c 100644 --- a/Swift/QtUI/ChatList/QtChatListWindow.cpp +++ b/Swift/QtUI/ChatList/QtChatListWindow.cpp @@ -13,6 +13,7 @@ #include <Swift/QtUI/ChatList/ChatListMUCItem.h> #include <Swift/QtUI/ChatList/ChatListRecentItem.h> +#include <Swift/QtUI/ChatList/ChatListWhiteboardItem.h> #include <Swift/QtUI/QtAddBookmarkWindow.h> #include <Swift/QtUI/QtEditBookmarkWindow.h> #include <Swift/QtUI/QtUISettingConstants.h> @@ -21,6 +22,7 @@ #include <Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h> #include <Swift/Controllers/UIEvents/RemoveMUCBookmarkUIEvent.h> #include <Swift/Controllers/UIEvents/EditMUCBookmarkUIEvent.h> +#include <Swift/Controllers/UIEvents/ShowWhiteboardUIEvent.h> #include <Swift/Controllers/Settings/SettingsProvider.h> @@ -97,6 +99,11 @@ void QtChatListWindow::handleItemActivated(const QModelIndex& index) { onRecentActivated(recentItem->getChat()); } } + else if (ChatListWhiteboardItem* whiteboardItem = dynamic_cast<ChatListWhiteboardItem*>(item)) { + if (!whiteboardItem->getChat().isMUC || bookmarksEnabled_) { + eventStream_->send(boost::make_shared<ShowWhiteboardUIEvent>(whiteboardItem->getChat().jid)); + } + } } void QtChatListWindow::clearBookmarks() { @@ -111,6 +118,14 @@ void QtChatListWindow::removeMUCBookmark(const MUCBookmark& bookmark) { model_->removeMUCBookmark(bookmark); } +void QtChatListWindow::addWhiteboardSession(const ChatListWindow::Chat& chat) { + model_->addWhiteboardSession(chat); +} + +void QtChatListWindow::removeWhiteboardSession(const JID& jid) { + model_->removeWhiteboardSession(jid); +} + void QtChatListWindow::setRecents(const std::list<ChatListWindow::Chat>& recents) { model_->setRecents(recents); } diff --git a/Swift/QtUI/ChatList/QtChatListWindow.h b/Swift/QtUI/ChatList/QtChatListWindow.h index 33131ce..ef4ce0f 100644 --- a/Swift/QtUI/ChatList/QtChatListWindow.h +++ b/Swift/QtUI/ChatList/QtChatListWindow.h @@ -22,6 +22,8 @@ namespace Swift { virtual ~QtChatListWindow(); void addMUCBookmark(const MUCBookmark& bookmark); void removeMUCBookmark(const MUCBookmark& bookmark); + void addWhiteboardSession(const ChatListWindow::Chat& chat); + void removeWhiteboardSession(const JID& jid); void setBookmarksEnabled(bool enabled); void setRecents(const std::list<ChatListWindow::Chat>& recents); void setUnreadCount(int unread); diff --git a/Swift/QtUI/QtChatView.cpp b/Swift/QtUI/QtChatView.cpp index eaec3b6..433ade4 100644 --- a/Swift/QtUI/QtChatView.cpp +++ b/Swift/QtUI/QtChatView.cpp @@ -430,6 +430,20 @@ void QtChatView::setFileTransferStatus(QString id, const ChatWindow::FileTransfe ftElement.setInnerXml(newInnerHTML); } +void QtChatView::setWhiteboardSessionStatus(QString id, const ChatWindow::WhiteboardSessionState state) { + QWebElement divElement = findDivElementWithID(document_, id); + QString newInnerHTML; + if (state == ChatWindow::WhiteboardAccepted) { + newInnerHTML = tr("Started whiteboard chat") + "<br/>" + + QtChatWindow::buildChatWindowButton(tr("Show whiteboard"), QtChatWindow::ButtonWhiteboardShowWindow, id); + } else if (state == ChatWindow::WhiteboardTerminated) { + newInnerHTML = tr("Whiteboard chat has been canceled"); + } else if (state == ChatWindow::WhiteboardRejected) { + newInnerHTML = tr("Whiteboard chat request has been rejected"); + } + divElement.setInnerXml(newInnerHTML); +} + void QtChatView::setMUCInvitationJoined(QString id) { QWebElement divElement = findDivElementWithID(document_, id); QWebElement buttonElement = divElement.findFirst("input#mucinvite"); diff --git a/Swift/QtUI/QtChatView.h b/Swift/QtUI/QtChatView.h index 118f14b..9080808 100644 --- a/Swift/QtUI/QtChatView.h +++ b/Swift/QtUI/QtChatView.h @@ -44,6 +44,7 @@ namespace Swift { void addToJSEnvironment(const QString&, QObject*); void setFileTransferProgress(QString id, const int percentageDone); void setFileTransferStatus(QString id, const ChatWindow::FileTransferState state, const QString& msg); + void setWhiteboardSessionStatus(QString id, const ChatWindow::WhiteboardSessionState state); void setMUCInvitationJoined(QString id); void showEmoticons(bool show); int getSnippetPositionByDate(const QDate& date); diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 2bb9ae0..6c96b34 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -54,6 +54,9 @@ namespace Swift { +const QString QtChatWindow::ButtonWhiteboardSessionCancel = QString("whiteboard-cancel"); +const QString QtChatWindow::ButtonWhiteboardSessionAcceptRequest = QString("whiteboard-acceptrequest"); +const QString QtChatWindow::ButtonWhiteboardShowWindow = QString("whiteboard-showwindow"); const QString QtChatWindow::ButtonFileTransferCancel = QString("filetransfer-cancel"); const QString QtChatWindow::ButtonFileTransferSetDescription = QString("filetransfer-setdescription"); const QString QtChatWindow::ButtonFileTransferSendRequest = QString("filetransfer-sendrequest"); @@ -649,6 +652,39 @@ void QtChatWindow::setFileTransferStatus(std::string id, const FileTransferState messageLog_->setFileTransferStatus(QString::fromStdString(id), state, QString::fromStdString(msg)); } +std::string QtChatWindow::addWhiteboardRequest(bool senderIsSelf) { + QString wb_id = QString("wb%1").arg(P2QSTRING(boost::lexical_cast<std::string>(idCounter_++))); + QString htmlString; + if (senderIsSelf) { + htmlString = "<div id='" + wb_id + "'>" + tr("Starting whiteboard chat") + "<br />"+ + buildChatWindowButton(tr("Cancel"), ButtonWhiteboardSessionCancel, wb_id) + + "</div>"; + } else { + htmlString = "<div id='" + wb_id + "'>" + Qt::escape(contact_) + tr(" would like to start whiteboard chat") + ": <br/>" + + buildChatWindowButton(tr("Cancel"), ButtonWhiteboardSessionCancel, wb_id) + + buildChatWindowButton(tr("Accept"), ButtonWhiteboardSessionAcceptRequest, wb_id) + + "</div>"; + } + + if (lastLineTracker_.getShouldMoveLastLine()) { + /* should this be queued? */ + messageLog_->addLastSeenLine(); + /* if the line is added we should break the snippet */ +// appendToPrevious = false; + } + QString qAvatarPath = "qrc:/icons/avatar.png"; + std::string id = "wbmessage" + boost::lexical_cast<std::string>(idCounter_++); + messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new MessageSnippet(htmlString, Qt::escape(contact_), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, false, false, theme_, P2QSTRING(id)))); + + previousMessageWasSelf_ = false; + previousSenderName_ = contact_; + return Q2PSTRING(wb_id); +} + +void QtChatWindow::setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state) { + messageLog_->setWhiteboardSessionStatus(QString::fromStdString(id), state); +} + void QtChatWindow::handleHTMLButtonClicked(QString id, QString encodedArgument1, QString encodedArgument2, QString encodedArgument3) { QString arg1 = decodeButtonArgument(encodedArgument1); QString arg2 = decodeButtonArgument(encodedArgument2); @@ -681,6 +717,20 @@ void QtChatWindow::handleHTMLButtonClicked(QString id, QString encodedArgument1, onFileTransferAccept(Q2PSTRING(ft_id), Q2PSTRING(path)); } } + else if (id.startsWith(ButtonWhiteboardSessionAcceptRequest)) { + QString id = arg1; + messageLog_->setWhiteboardSessionStatus(QString::fromStdString(Q2PSTRING(id)), ChatWindow::WhiteboardAccepted); + onWhiteboardSessionAccept(); + } + else if (id.startsWith(ButtonWhiteboardSessionCancel)) { + QString id = arg1; + messageLog_->setWhiteboardSessionStatus(QString::fromStdString(Q2PSTRING(id)), ChatWindow::WhiteboardTerminated); + onWhiteboardSessionCancel(); + } + else if (id.startsWith(ButtonWhiteboardShowWindow)) { + QString id = arg1; + onWhiteboardWindowShow(); + } else if (id.startsWith(ButtonMUCInvite)) { QString roomJID = arg1; QString password = arg2; diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index a703818..3416b42 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.h @@ -73,6 +73,9 @@ namespace Swift { Q_OBJECT public: + static const QString ButtonWhiteboardSessionCancel; + static const QString ButtonWhiteboardSessionAcceptRequest; + static const QString ButtonWhiteboardShowWindow; static const QString ButtonFileTransferCancel; static const QString ButtonFileTransferSetDescription; static const QString ButtonFileTransferSendRequest; @@ -94,6 +97,9 @@ namespace Swift { void setFileTransferProgress(std::string id, const int percentageDone); void setFileTransferStatus(std::string id, const FileTransferState state, const std::string& msg); + std::string addWhiteboardRequest(bool senderIsSelf); + void setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state); + void show(); void activate(); void setUnreadMessageCount(int count); diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp index 2197ec6..a154fb0 100644 --- a/Swift/QtUI/QtUIFactory.cpp +++ b/Swift/QtUI/QtUIFactory.cpp @@ -25,9 +25,11 @@ #include "QtContactEditWindow.h" #include "QtAdHocCommandWindow.h" #include "QtFileTransferListWidget.h" +#include "Whiteboard/QtWhiteboardWindow.h" #include <Swift/Controllers/Settings/SettingsProviderHierachy.h> #include <Swift/QtUI/QtUISettingConstants.h> #include <QtHistoryWindow.h> +#include <Swiften/Whiteboard/WhiteboardSession.h> namespace Swift { @@ -155,6 +157,10 @@ ContactEditWindow* QtUIFactory::createContactEditWindow() { return new QtContactEditWindow(); } +WhiteboardWindow* QtUIFactory::createWhiteboardWindow(boost::shared_ptr<WhiteboardSession> whiteboardSession) { + return new QtWhiteboardWindow(whiteboardSession); +} + void QtUIFactory::createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command) { new QtAdHocCommandWindow(command); } diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h index 1b2431f..30f0101 100644 --- a/Swift/QtUI/QtUIFactory.h +++ b/Swift/QtUI/QtUIFactory.h @@ -25,6 +25,7 @@ namespace Swift { class QtChatWindow; class TimerFactory; class historyWindow_; + class WhiteboardSession; class QtUIFactory : public QObject, public UIFactory { Q_OBJECT @@ -44,6 +45,7 @@ namespace Swift { virtual ProfileWindow* createProfileWindow(); virtual ContactEditWindow* createContactEditWindow(); virtual FileTransferListWidget* createFileTransferListWidget(); + virtual WhiteboardWindow* createWhiteboardWindow(boost::shared_ptr<WhiteboardSession> whiteboardSession); virtual void createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command); private slots: diff --git a/Swift/QtUI/Roster/QtRosterWidget.cpp b/Swift/QtUI/Roster/QtRosterWidget.cpp index 2fe7f33..1cf073b 100644 --- a/Swift/QtUI/Roster/QtRosterWidget.cpp +++ b/Swift/QtUI/Roster/QtRosterWidget.cpp @@ -15,6 +15,7 @@ #include "Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h" #include "Swift/Controllers/UIEvents/RenameGroupUIEvent.h" #include "Swift/Controllers/UIEvents/SendFileUIEvent.h" +#include "Swift/Controllers/UIEvents/RequestWhiteboardUIEvent.h" #include "QtContactEditWindow.h" #include "Swift/Controllers/Roster/ContactRosterItem.h" #include "Swift/Controllers/Roster/GroupRosterItem.h" @@ -62,6 +63,12 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) { sendFile = contextMenu.addAction(tr("Send File")); } #endif +#ifdef SWIFT_EXPERIMENTAL_WB + QAction* startWhiteboardChat = NULL; + if (contact->supportsFeature(ContactRosterItem::WhiteboardFeature)) { + startWhiteboardChat = contextMenu.addAction(tr("Start Whiteboard Chat")); + } +#endif QAction* result = contextMenu.exec(event->globalPos()); if (result == editContact) { eventStream_->send(boost::make_shared<RequestContactEditorUIEvent>(contact->getJID())); @@ -79,6 +86,11 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) { } } #endif +#ifdef SWIFT_EXPERIMENTAL_WB + else if (startWhiteboardChat && result == startWhiteboardChat) { + eventStream_->send(boost::make_shared<RequestWhiteboardUIEvent>(contact->getJID())); + } +#endif } else if (GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item)) { QAction* renameGroupAction = contextMenu.addAction(tr("Rename")); diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index fe186e5..5ab9c9e 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -135,6 +135,7 @@ sources = [ "ChatList/ChatListDelegate.cpp", "ChatList/ChatListMUCItem.cpp", "ChatList/ChatListRecentItem.cpp", + "ChatList/ChatListWhiteboardItem.cpp", "MUCSearch/QtMUCSearchWindow.cpp", "MUCSearch/MUCSearchModel.cpp", "MUCSearch/MUCSearchRoomItem.cpp", @@ -147,6 +148,11 @@ sources = [ "UserSearch/QtUserSearchWindow.cpp", "UserSearch/UserSearchModel.cpp", "UserSearch/UserSearchDelegate.cpp", + "Whiteboard/FreehandLineItem.cpp", + "Whiteboard/GView.cpp", + "Whiteboard/TextDialog.cpp", + "Whiteboard/QtWhiteboardWindow.cpp", + "Whiteboard/ColorWidget.cpp", "QtSubscriptionRequestWindow.cpp", "QtRosterHeader.cpp", "QtWebView.cpp", diff --git a/Swift/QtUI/Swift.qrc b/Swift/QtUI/Swift.qrc index cf1ee05..eb4f7ee 100644 --- a/Swift/QtUI/Swift.qrc +++ b/Swift/QtUI/Swift.qrc @@ -21,5 +21,13 @@ <file alias="icons/new-chat.png">../resources/icons/new-chat.png</file> <file alias="icons/actions.png">../resources/icons/actions.png</file> <file alias="COPYING">COPYING</file> + <file alias="icons/line.png">../resources/icons/line.png</file> + <file alias="icons/rect.png">../resources/icons/rect.png</file> + <file alias="icons/circle.png">../resources/icons/circle.png</file> + <file alias="icons/handline.png">../resources/icons/handline.png</file> + <file alias="icons/text.png">../resources/icons/text.png</file> + <file alias="icons/polygon.png">../resources/icons/polygon.png</file> + <file alias="icons/cursor.png">../resources/icons/cursor.png</file> + <file alias="icons/eraser.png">../resources/icons/eraser.png</file> </qresource> </RCC> diff --git a/Swift/QtUI/Whiteboard/ColorWidget.cpp b/Swift/QtUI/Whiteboard/ColorWidget.cpp new file mode 100644 index 0000000..e96b760 --- /dev/null +++ b/Swift/QtUI/Whiteboard/ColorWidget.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + + +#include "ColorWidget.h" +#include <QPainter> +#include <QMouseEvent> + +namespace Swift { + ColorWidget::ColorWidget(QWidget* parent) : QWidget(parent) { + setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + } + + QSize ColorWidget::sizeHint() const { + return QSize(20, 20); + } + + void ColorWidget::setColor(QColor color) { + this->color = color; + update(); + } + + void ColorWidget::paintEvent(QPaintEvent* /*event*/) { + QPainter painter(this); + painter.fillRect(0, 0, 20, 20, color); + } + + void ColorWidget::mouseReleaseEvent(QMouseEvent* event) { + if (event->button() == Qt::LeftButton) { + emit clicked(); + } + } +} + diff --git a/Swift/QtUI/Whiteboard/ColorWidget.h b/Swift/QtUI/Whiteboard/ColorWidget.h new file mode 100644 index 0000000..6abdf00 --- /dev/null +++ b/Swift/QtUI/Whiteboard/ColorWidget.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +namespace Swift { + class ColorWidget : public QWidget { + Q_OBJECT; + public: + ColorWidget(QWidget* parent = 0); + QSize sizeHint() const; + + public slots: + void setColor(QColor color); + + private: + QColor color; + + protected: + void paintEvent(QPaintEvent* /*event*/); + void mouseReleaseEvent(QMouseEvent* event); + + signals: + void clicked(); + + }; +} + diff --git a/Swift/QtUI/Whiteboard/FreehandLineItem.cpp b/Swift/QtUI/Whiteboard/FreehandLineItem.cpp new file mode 100644 index 0000000..8821062 --- /dev/null +++ b/Swift/QtUI/Whiteboard/FreehandLineItem.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "FreehandLineItem.h" + + +namespace Swift { + FreehandLineItem::FreehandLineItem(QGraphicsItem* parent) : QGraphicsItem(parent) { + } + + QRectF FreehandLineItem::boundingRect() const + { + return boundRect; + } + + void FreehandLineItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) + { + painter->setPen(pen_); + if (points_.size() > 0) { + QVector<QPointF>::const_iterator it = points_.begin(); + QPointF previous = *it; + ++it; + for (; it != points_.end(); ++it) { + painter->drawLine(previous, *it); + previous = *it; + } + } + } + + void FreehandLineItem::setStartPoint(QPointF point) + { + points_.clear(); + points_.append(point); + QRectF rect(point, point); + prepareGeometryChange(); + boundRect = rect; + } + + void FreehandLineItem::lineTo(QPointF point) + { + qreal x1, x2, y1, y2; + x1 = points_.last().x(); + x2 = point.x(); + y1 = points_.last().y(); + y2 = point.y(); + if (x1 > x2) { + qreal temp = x1; + x1 = x2; + x2 = temp; + } + if (y1 > y2) { + qreal temp = y1; + y1 = y2; + y2 = temp; + } + QRectF rect(x1-1, y1-1, x2+1-x1, y2+1-y1); + + points_.append(point); + + prepareGeometryChange(); + boundRect |= rect; + } + + bool FreehandLineItem::collidesWithPath(const QPainterPath& path, Qt::ItemSelectionMode /*mode*/) const + { + QVector<QPointF>::const_iterator it; + QSizeF size(1,1); + for (it = points_.begin(); it != points_.end(); ++it) { + if (path.intersects(QRectF(*it, size))) { + return true; + } + } + return false; + } + + void FreehandLineItem::setPen(const QPen& pen) + { + pen_ = pen; + update(boundRect); + } + + QPen FreehandLineItem::pen() const + { + return pen_; + } + + const QVector<QPointF>& FreehandLineItem::points() const { + return points_; + } + + int FreehandLineItem::type() const { + return Type; + } +} diff --git a/Swift/QtUI/Whiteboard/FreehandLineItem.h b/Swift/QtUI/Whiteboard/FreehandLineItem.h new file mode 100644 index 0000000..f3c6607 --- /dev/null +++ b/Swift/QtUI/Whiteboard/FreehandLineItem.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QGraphicsItem> +#include <QPainter> +#include <iostream> + +using namespace std; + +namespace Swift { + class FreehandLineItem : public QGraphicsItem { + public: + enum {Type = UserType + 1}; + FreehandLineItem(QGraphicsItem* parent = 0); + QRectF boundingRect() const; + void paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/ = 0); + void setStartPoint(QPointF point); + void lineTo(QPointF point); + bool collidesWithPath(const QPainterPath& path, Qt::ItemSelectionMode /*mode*/ = Qt::IntersectsItemShape) const; + void setPen(const QPen& pen); + QPen pen() const; + const QVector<QPointF>& points() const; + int type() const; + + private: + QPen pen_; + QVector<QPointF> points_; + QRectF boundRect; + }; +} diff --git a/Swift/QtUI/Whiteboard/GView.cpp b/Swift/QtUI/Whiteboard/GView.cpp new file mode 100644 index 0000000..d725cbb --- /dev/null +++ b/Swift/QtUI/Whiteboard/GView.cpp @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "GView.h" +#include <QtSwiftUtil.h> + +namespace Swift { + GView::GView(QGraphicsScene* scene, QWidget* parent) : QGraphicsView(scene, parent), brush(QColor(Qt::white)), defaultBrush(QColor(Qt::white)) { + selectionRect = 0; + lastItem = 0; + zValue = 0; + } + + void GView::setLineWidth(int i) { + pen.setWidth(i); + if (selectionRect) { + QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); + changePenAndBrush(selectionRect->data(1).value<QGraphicsItem*>(), pen, brush); + lastItemChanged(item, items_.indexOf(item)+1, Update); + } else { + defaultPen.setWidth(i); + } + } + + void GView::setLineColor(QColor color) { + pen.setColor(color); + if (selectionRect) { + QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); + changePenAndBrush(selectionRect->data(1).value<QGraphicsItem*>(), pen, brush); + lastItemChanged(item, items_.indexOf(item)+1, Update); + } else { + defaultPen.setColor(color); + } + lineColorChanged(color); + } + + QColor GView::getLineColor() { + return pen.color(); + } + + void GView::setBrushColor(QColor color) { + brush.setColor(color); + if (selectionRect) { + QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); + changePenAndBrush(selectionRect->data(1).value<QGraphicsItem*>(), pen, brush); + lastItemChanged(item, items_.indexOf(item)+1, Update); + } else { + defaultBrush.setColor(color); + } + brushColorChanged(color); + } + + QColor GView::getBrushColor() { + return brush.color(); + } + + void GView::setMode(Mode mode) { + this->mode = mode; + lastItem = 0; + deselect(); + } + + void GView::addItem(QGraphicsItem* item, QString id, int pos) { + itemsMap_.insert(id, item); + if (pos > items_.size()) { + item->setZValue(zValue++); + scene()->addItem(item); + items_.append(item); + } else { + QGraphicsItem* temp = items_.at(pos-1); + item->setZValue(temp->zValue()); + scene()->addItem(item); + item->stackBefore(temp); + items_.insert(pos-1, item); + } + } + + void GView::clear() { + scene()->clear(); + items_.clear(); + itemsMap_.clear(); + lastItem = 0; + selectionRect = 0; + brush = QBrush(QColor(Qt::white)); + defaultBrush = QBrush(QColor(Qt::white)); + pen = QPen(); + pen.setWidth(1); + defaultPen = pen; + lineWidthChanged(1); + lineColorChanged(pen.color()); + brushColorChanged(brush.color()); + } + + QGraphicsItem* GView::getItem(QString id) { + return itemsMap_.value(id); + } + + void GView::deleteItem(QString id) { + deselect(id); + QGraphicsItem* item = itemsMap_.value(id); + items_.removeOne(item); + itemsMap_.remove(id); + scene()->removeItem(item); + delete item; + } + + QString GView::getNewID() { + return P2QSTRING(idGenerator.generateID()); + } + + void GView::mouseMoveEvent(QMouseEvent* event) + { + if (!mousePressed) { + return; + } + + if (mode == Line) { + QGraphicsLineItem* item = qgraphicsitem_cast<QGraphicsLineItem*>(lastItem); + if(item != 0) { + QLineF line = item->line(); + line.setP1(this->mapToScene(event->pos())); + item->setLine(line); + + } + } + else if (mode == Rect) { + QGraphicsRectItem* item = qgraphicsitem_cast<QGraphicsRectItem*>(lastItem); + if (item != 0) { + QPointF beginPoint = item->data(0).toPointF(); + QPointF newPoint = this->mapToScene(event->pos()); + QRectF rect = item->rect(); + if (beginPoint.x() <= newPoint.x() && beginPoint.y() <= newPoint.y()) { + rect.setTopLeft(beginPoint); + rect.setBottomRight(newPoint); + } + else if (beginPoint.x() > newPoint.x() && beginPoint.y() <= newPoint.y()) { + rect.setTopRight(beginPoint); + rect.setBottomLeft(newPoint); + } + else if (beginPoint.x() <= newPoint.x() && beginPoint.y() > newPoint.y()) { + rect.setBottomLeft(beginPoint); + rect.setTopRight(newPoint); + } + else if (beginPoint.x() > newPoint.x() && beginPoint.y() > newPoint.y()) { + rect.setBottomRight(beginPoint); + rect.setTopLeft(newPoint); + } + item->setRect(rect); + } + } + else if (mode == Circle) { + QGraphicsEllipseItem* item = qgraphicsitem_cast<QGraphicsEllipseItem*>(lastItem); + QPainterPath path; + QPointF beginPoint = item->data(0).toPointF(); + QPointF newPoint = this->mapToScene(event->pos()); + QRectF rect = item->rect(); + if (beginPoint.x() <= newPoint.x() && beginPoint.y() <= newPoint.y()) { + rect.setTopLeft(beginPoint); + rect.setBottomRight(newPoint); + } + else if (beginPoint.x() > newPoint.x() && beginPoint.y() <= newPoint.y()) { + rect.setTopRight(beginPoint); + rect.setBottomLeft(newPoint); + } + else if (beginPoint.x() <= newPoint.x() && beginPoint.y() > newPoint.y()) { + rect.setBottomLeft(beginPoint); + rect.setTopRight(newPoint); + } + else if (beginPoint.x() > newPoint.x() && beginPoint.y() > newPoint.y()) { + rect.setBottomRight(beginPoint); + rect.setTopLeft(newPoint); + } + + item->setRect(rect); + } + else if (mode == HandLine) { + FreehandLineItem* item = qgraphicsitem_cast<FreehandLineItem*>(lastItem); + if (item != 0) { + QPointF newPoint = this->mapToScene(event->pos()); + item->lineTo(newPoint); + } + } + else if (mode == Polygon) { + QGraphicsPolygonItem* item = qgraphicsitem_cast<QGraphicsPolygonItem*>(lastItem); + QPointF newPoint = this->mapToScene(event->pos()); + QPolygonF polygon = item->polygon(); + polygon.erase(polygon.end()-1); + polygon.append(newPoint); + item->setPolygon(polygon); + } + else if (mode == Select) { + QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); + if (item != 0) { + QPainterPath path; + QPointF beginPoint = selectionRect->data(0).toPointF(); + QPointF newPoint = this->mapToScene(event->pos()); + item->setPos(beginPoint + newPoint); + selectionRect->setPos(beginPoint + newPoint); + } + } + } + + void GView::mousePressEvent(QMouseEvent *event) + { + mousePressed = true; + deselect(); + if (mode == Line) { + QPointF point = this->mapToScene(event->pos()); + QGraphicsItem* item = scene()->addLine(point.x(), point.y(), point.x(), point.y(), pen); + QString id = getNewID(); + item->setZValue(10000000); + item->setData(100, id); + item->setData(101, items_.size()); + lastItem = item; + } + else if (mode == Rect) { + QPointF point = this->mapToScene(event->pos()); + QGraphicsRectItem* item = scene()->addRect(point.x(), point.y(), 0, 0, pen, brush); + QString id = getNewID(); + item->setZValue(10000000); + item->setData(0, point); + item->setData(100, id); + item->setData(101, items_.size()); + lastItem = item; + } + else if (mode == Rubber) { + QPointF point = this->mapToScene(event->pos()); + int w = pen.width(); + QRectF rect(point.x()-w, point.y()-w, w*2, w*2); + QList<QGraphicsItem*> list = scene()->items(rect); + if (!list.isEmpty()) + { + QGraphicsItem* item = scene()->items(rect).first(); + QString id = item->data(100).toString(); + int pos = items_.indexOf(item)+1; + itemDeleted(id, pos); + deleteItem(id); + } + } + else if (mode == Circle) { + QPointF point = this->mapToScene(event->pos()); + QGraphicsEllipseItem* item = scene()->addEllipse(point.x(), point.y(), 0, 0, pen, brush); + QString id = getNewID(); + item->setZValue(10000000); + item->setData(0, point); + item->setData(100, id); + item->setData(101, items_.size()); + lastItem = item; + } + else if (mode == HandLine) { + QPointF point = this->mapToScene(event->pos()); + FreehandLineItem* item = new FreehandLineItem; + QString id = getNewID(); + item->setPen(pen); + item->setStartPoint(point); + item->setZValue(10000000); + item->setData(100, id); + item->setData(101, items_.size()); + scene()->addItem(item); + lastItem = item; + } + else if (mode == Text) { + QPointF point = this->mapToScene(event->pos()); + QGraphicsTextItem* item = scene()->addText(""); + QString id = getNewID(); + item->setData(100, id); + item->setData(101, items_.size()); + item->setDefaultTextColor(pen.color()); + textDialog = new TextDialog(item, this); + connect(textDialog, SIGNAL(accepted(QGraphicsTextItem*)), this, SLOT(handleTextItemModified(QGraphicsTextItem*))); + textDialog->setAttribute(Qt::WA_DeleteOnClose); + textDialog->show(); + item->setPos(point); + lastItem = item; + } + else if (mode == Polygon) { + QPointF point = this->mapToScene(event->pos()); + QGraphicsPolygonItem* item = dynamic_cast<QGraphicsPolygonItem*>(lastItem); + if (item == 0) { + QPolygonF polygon; + polygon.append(point); + polygon.append(point); + item = scene()->addPolygon(polygon, pen, brush); + QString id = getNewID(); + item->setZValue(10000000); + item->setData(100, id); + item->setData(101, items_.size()); + lastItem = item; + } + else { + QPolygonF polygon; + polygon = item->polygon(); + polygon.append(point); + item->setPolygon(polygon); + } + } + else if (mode == Select) { + QPointF point = this->mapToScene(event->pos()); + int w = pen.width(); + if (w == 0) { + w = 1; + } + QRectF rect(point.x()-w, point.y()-w, w*2, w*2); + QList<QGraphicsItem*> list = scene()->items(rect); + if (!list.isEmpty()) { + QPen pen; + pen.setColor(QColor(Qt::gray)); + pen.setStyle(Qt::DashLine); + QGraphicsItem *item = scene()->items(rect).first(); + selectionRect = scene()->addRect(item->boundingRect(), pen); + selectionRect->setZValue(1000000); + selectionRect->setData(0, item->pos()-point); + selectionRect->setPos(item->pos()); + QVariant var(QVariant::UserType); + var.setValue(item); + selectionRect->setData(1, var); + setActualPenAndBrushFromItem(item); + } + } + } + + void GView::mouseReleaseEvent(QMouseEvent* /*event*/) + { + mousePressed = false; + QGraphicsPolygonItem* polygon = dynamic_cast<QGraphicsPolygonItem*>(lastItem); + if (polygon && polygon->polygon().size() >= 3) { + lastItemChanged(polygon, items_.indexOf(polygon)+1, Update); + } else if (lastItem) { + zValue++; + lastItem->setZValue(zValue++); + items_.append(lastItem); + itemsMap_.insert(lastItem->data(100).toString(), lastItem); + + lastItemChanged(lastItem, items_.size(), New); + } else if (selectionRect){ + QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); + lastItemChanged(item, items_.indexOf(item)+1, Update); + } + } + + + void GView::handleTextItemModified(QGraphicsTextItem* item) { + lastItemChanged(item, item->data(101).toInt(), Update); + } + + void GView::moveUpSelectedItem() + { + if (selectionRect) { + QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); + int pos = items_.indexOf(item); + if (pos < items_.size()-1) { + lastItemChanged(item, pos+1, MoveUp); + move(item, pos+2); + } + } + } + + void GView::moveDownSelectedItem() + { + if (selectionRect) { + QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); + int pos = items_.indexOf(item); + if (pos > 0) { + lastItemChanged(item, pos+1, MoveDown); + move(item, pos); + } + } + } + + void GView::move(QGraphicsItem* item, int npos) { + int pos = items_.indexOf(item); + QGraphicsItem* itemAfter = NULL; + if (npos-1 > pos) { + if (npos == items_.size()) { + item->setZValue(zValue++); + } else { + itemAfter = items_.at(npos); + } + + items_.insert(npos, item); + items_.removeAt(pos); + } else if (npos-1 < pos) { + itemAfter = items_.at(npos-1); + items_.insert(npos-1, item); + items_.removeAt(pos+1); + } + if (itemAfter) { + item->setZValue(itemAfter->zValue()); + item->stackBefore(itemAfter); + } + } + + void GView::changePenAndBrush(QGraphicsItem* item, QPen pen, QBrush brush) { + QGraphicsLineItem* lineItem = qgraphicsitem_cast<QGraphicsLineItem*>(item); + if (lineItem) { + lineItem->setPen(pen); + } + + FreehandLineItem* handLineItem = qgraphicsitem_cast<FreehandLineItem*>(item); + if (handLineItem) { + handLineItem->setPen(pen); + } + + QGraphicsRectItem* rectItem = qgraphicsitem_cast<QGraphicsRectItem*>(item); + if (rectItem) { + rectItem->setPen(pen); + rectItem->setBrush(brush); + } + + QGraphicsTextItem* textItem = qgraphicsitem_cast<QGraphicsTextItem*>(item); + if (textItem) { + textItem->setDefaultTextColor(pen.color()); + } + + QGraphicsPolygonItem* polygonItem = qgraphicsitem_cast<QGraphicsPolygonItem*>(item); + if (polygonItem) { + polygonItem->setPen(pen); + polygonItem->setBrush(brush); + } + + QGraphicsEllipseItem* ellipseItem = qgraphicsitem_cast<QGraphicsEllipseItem*>(item); + if (ellipseItem) { + ellipseItem->setPen(pen); + ellipseItem->setBrush(brush); + } + lineColorChanged(pen.color()); + brushColorChanged(brush.color()); + } + + void GView::setActualPenAndBrushFromItem(QGraphicsItem* item) { + QGraphicsLineItem* lineItem = qgraphicsitem_cast<QGraphicsLineItem*>(item); + if (lineItem) { + pen = lineItem->pen(); + } + + FreehandLineItem* handLineItem = qgraphicsitem_cast<FreehandLineItem*>(item); + if (handLineItem) { + pen = handLineItem->pen(); + } + + QGraphicsRectItem* rectItem = qgraphicsitem_cast<QGraphicsRectItem*>(item); + if (rectItem) { + pen = rectItem->pen(); + brush = rectItem->brush(); + } + + QGraphicsTextItem* textItem = qgraphicsitem_cast<QGraphicsTextItem*>(item); + if (textItem) { + pen.setColor(textItem->defaultTextColor()); + } + + QGraphicsPolygonItem* polygonItem = qgraphicsitem_cast<QGraphicsPolygonItem*>(item); + if (polygonItem) { + pen = polygonItem->pen(); + brush = polygonItem->brush(); + } + + QGraphicsEllipseItem* ellipseItem = qgraphicsitem_cast<QGraphicsEllipseItem*>(item); + if (ellipseItem) { + pen = ellipseItem->pen(); + brush = ellipseItem->brush(); + } + lineWidthChanged(pen.width()); + lineColorChanged(pen.color()); + brushColorChanged(brush.color()); + } + + void GView::deselect() { + if (selectionRect != 0) { + pen = defaultPen; + brush = defaultBrush; + scene()->removeItem(selectionRect); + delete selectionRect; + selectionRect = 0; + lineWidthChanged(pen.width()); + lineColorChanged(pen.color()); + brushColorChanged(brush.color()); + } + } + + void GView::deselect(QString id) { + if (selectionRect != 0) { + QGraphicsItem* item = getItem(id); + if (item && selectionRect->data(1).value<QGraphicsItem*>() == item) { + pen = defaultPen; + brush = defaultBrush; + scene()->removeItem(selectionRect); + delete selectionRect; + selectionRect = 0; + lineWidthChanged(pen.width()); + lineColorChanged(pen.color()); + brushColorChanged(brush.color()); + } + } + } +} diff --git a/Swift/QtUI/Whiteboard/GView.h b/Swift/QtUI/Whiteboard/GView.h new file mode 100644 index 0000000..88ea326 --- /dev/null +++ b/Swift/QtUI/Whiteboard/GView.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QGraphicsView> +#include <QGraphicsLineItem> +#include <QMouseEvent> +#include <QPen> +#include <iostream> +#include <Swiften/Base/IDGenerator.h> + +#include "TextDialog.h" +#include "FreehandLineItem.h" + +namespace Swift { + class GView : public QGraphicsView { + Q_OBJECT; + public: + enum Mode { Rubber, Line, Rect, Circle, HandLine, Text, Polygon, Select }; + enum Type { New, Update, MoveUp, MoveDown }; + GView(QGraphicsScene* scene, QWidget* parent = 0); + void setLineWidth(int i); + void setLineColor(QColor color); + QColor getLineColor(); + void setBrushColor(QColor color); + QColor getBrushColor(); + void setMode(Mode mode); + void mouseMoveEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* /*event*/); + void addItem(QGraphicsItem* item, QString id, int pos); + void clear(); + QGraphicsItem* getItem(QString id); + void deleteItem(QString id); + QString getNewID(); + void move(QGraphicsItem* item, int npos); + void deselect(QString id); + + public slots: + void moveUpSelectedItem(); + void moveDownSelectedItem(); + + private slots: + void handleTextItemModified(QGraphicsTextItem*); + private: + void changePenAndBrush(QGraphicsItem* item, QPen pen, QBrush brush); + void setActualPenAndBrushFromItem(QGraphicsItem* item); + void deselect(); + + int zValue; + bool mousePressed; + QPen pen; + QBrush brush; + QPen defaultPen; + QBrush defaultBrush; + Mode mode; + QGraphicsItem* lastItem; + QGraphicsRectItem* selectionRect; + TextDialog* textDialog; + QMap<QString, QGraphicsItem*> itemsMap_; + QList<QGraphicsItem*> items_; + IDGenerator idGenerator; + + signals: + void lastItemChanged(QGraphicsItem* item, int pos, GView::Type type); + void itemDeleted(QString id, int pos); + void lineWidthChanged(int i); + void lineColorChanged(QColor color); + void brushColorChanged(QColor color); + }; +} diff --git a/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp new file mode 100644 index 0000000..50d7f54 --- /dev/null +++ b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtWhiteboardWindow.h" + +#include <iostream> + +#include <boost/bind.hpp> +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Whiteboard/WhiteboardSession.h> +#include <Swiften/Elements/WhiteboardPayload.h> +#include <Swiften/Elements/Whiteboard/WhiteboardLineElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardRectElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h> +#include <Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h> +#include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h> +#include <Swift/QtUI/Whiteboard/WhiteboardElementDrawingVisitor.h> + +#include <QMessageBox> +#include <QLabel> + +namespace Swift { + QtWhiteboardWindow::QtWhiteboardWindow(WhiteboardSession::ref whiteboardSession) : QWidget() { +#ifndef Q_WS_MAC + setWindowIcon(QIcon(":/logo-icon-16.png")); +#endif + layout = new QVBoxLayout(this); + hLayout = new QHBoxLayout; + sidebarLayout = new QVBoxLayout; + toolboxLayout = new QGridLayout; + + scene = new QGraphicsScene(this); + scene->setSceneRect(0, 0, 400, 400); + + graphicsView = new GView(scene, this); + graphicsView->setMode(GView::Line); + connect(graphicsView, SIGNAL(lastItemChanged(QGraphicsItem*, int, GView::Type)), this, SLOT(handleLastItemChanged(QGraphicsItem*, int, GView::Type))); + connect(graphicsView, SIGNAL(itemDeleted(QString, int)), this, SLOT(handleItemDeleted(QString, int))); + + widthBox = new QSpinBox(this); + connect(widthBox, SIGNAL(valueChanged(int)), this, SLOT(changeLineWidth(int))); + connect(graphicsView, SIGNAL(lineWidthChanged(int)), widthBox, SLOT(setValue(int))); + widthBox->setValue(1); + + moveUpButton = new QPushButton("Move Up", this); + connect(moveUpButton, SIGNAL(clicked()), graphicsView, SLOT(moveUpSelectedItem())); + + moveDownButton = new QPushButton("Move Down", this); + connect(moveDownButton, SIGNAL(clicked()), graphicsView, SLOT(moveDownSelectedItem())); + + strokeLayout = new QHBoxLayout; + strokeColor = new ColorWidget; + strokeLayout->addWidget(new QLabel("Stroke:")); + strokeLayout->addWidget(strokeColor); + connect(strokeColor, SIGNAL(clicked()), this, SLOT(showColorDialog())); + connect(graphicsView, SIGNAL(lineColorChanged(QColor)), strokeColor, SLOT(setColor(QColor))); + + fillLayout = new QHBoxLayout; + fillColor = new ColorWidget; + fillLayout->addWidget(new QLabel("Fill:")); + fillLayout->addWidget(fillColor); + connect(fillColor, SIGNAL(clicked()), this, SLOT(showBrushColorDialog())); + connect(graphicsView, SIGNAL(brushColorChanged(QColor)), fillColor, SLOT(setColor(QColor))); + + rubberButton = new QToolButton(this); + rubberButton->setIcon(QIcon(":/icons/eraser.png")); + rubberButton->setCheckable(true); + rubberButton->setAutoExclusive(true); + connect(rubberButton, SIGNAL(clicked()), this, SLOT(setRubberMode())); + + lineButton = new QToolButton(this); + lineButton->setIcon(QIcon(":/icons/line.png")); + lineButton->setCheckable(true); + lineButton->setAutoExclusive(true); + lineButton->setChecked(true); + connect(lineButton, SIGNAL(clicked()), this, SLOT(setLineMode())); + + rectButton = new QToolButton(this); + rectButton->setIcon(QIcon(":/icons/rect.png")); + rectButton->setCheckable(true); + rectButton->setAutoExclusive(true); + connect(rectButton, SIGNAL(clicked()), this, SLOT(setRectMode())); + + circleButton = new QToolButton(this); + circleButton->setIcon(QIcon(":/icons/circle.png")); + circleButton->setCheckable(true); + circleButton->setAutoExclusive(true); + connect(circleButton, SIGNAL(clicked()), this, SLOT(setCircleMode())); + + handLineButton = new QToolButton(this); + handLineButton->setIcon(QIcon(":/icons/handline.png")); + handLineButton->setCheckable(true); + handLineButton->setAutoExclusive(true); + connect(handLineButton, SIGNAL(clicked()), this, SLOT(setHandLineMode())); + + textButton = new QToolButton(this); + textButton->setIcon(QIcon(":/icons/text.png")); + textButton->setCheckable(true); + textButton->setAutoExclusive(true); + connect(textButton, SIGNAL(clicked()), this, SLOT(setTextMode())); + + polygonButton = new QToolButton(this); + polygonButton->setIcon(QIcon(":/icons/polygon.png")); + polygonButton->setCheckable(true); + polygonButton->setAutoExclusive(true); + connect(polygonButton, SIGNAL(clicked()), this, SLOT(setPolygonMode())); + + selectButton = new QToolButton(this); + selectButton->setIcon(QIcon(":/icons/cursor.png")); + selectButton->setCheckable(true); + selectButton->setAutoExclusive(true); + connect(selectButton, SIGNAL(clicked()), this, SLOT(setSelectMode())); + + toolboxLayout->addWidget(rubberButton, 0, 0); + toolboxLayout->addWidget(selectButton, 0, 1); + toolboxLayout->addWidget(lineButton, 0, 2); + toolboxLayout->addWidget(circleButton, 1, 0); + toolboxLayout->addWidget(handLineButton, 1, 1); + toolboxLayout->addWidget(rectButton, 1, 2); + toolboxLayout->addWidget(textButton, 2, 0); + toolboxLayout->addWidget(polygonButton, 2, 1); + + sidebarLayout->addLayout(toolboxLayout); + sidebarLayout->addSpacing(30); + sidebarLayout->addWidget(moveUpButton); + sidebarLayout->addWidget(moveDownButton); + sidebarLayout->addSpacing(40); + sidebarLayout->addWidget(widthBox); + sidebarLayout->addLayout(strokeLayout); + sidebarLayout->addLayout(fillLayout); + sidebarLayout->addStretch(); + hLayout->addWidget(graphicsView); + hLayout->addLayout(sidebarLayout); + layout->addLayout(hLayout); + this->setLayout(layout); + + setSession(whiteboardSession); + } + + void QtWhiteboardWindow::handleWhiteboardOperationReceive(const WhiteboardOperation::ref operation) { + WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast<WhiteboardInsertOperation>(operation); + if (insertOp) { + WhiteboardElementDrawingVisitor visitor(graphicsView, operation->getPos(), GView::New); + insertOp->getElement()->accept(visitor); + } + + WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast<WhiteboardUpdateOperation>(operation); + if (updateOp) { + WhiteboardElementDrawingVisitor visitor(graphicsView, operation->getPos(), GView::Update); + updateOp->getElement()->accept(visitor); + if (updateOp->getPos() != updateOp->getNewPos()) { + graphicsView->move(graphicsView->getItem(P2QSTRING(updateOp->getElement()->getID())), updateOp->getNewPos()); + } + } + + WhiteboardDeleteOperation::ref deleteOp = boost::dynamic_pointer_cast<WhiteboardDeleteOperation>(operation); + if (deleteOp) { + graphicsView->deleteItem(P2QSTRING(deleteOp->getElementID())); + } + } + + void QtWhiteboardWindow::changeLineWidth(int i) + { + graphicsView->setLineWidth(i); + } + + void QtWhiteboardWindow::showColorDialog() + { + QColor color = QColorDialog::getColor(graphicsView->getLineColor(), 0, "Select pen color", QColorDialog::ShowAlphaChannel); + if(color.isValid()) + graphicsView->setLineColor(color); + } + + void QtWhiteboardWindow::showBrushColorDialog() + { + QColor color = QColorDialog::getColor(graphicsView->getBrushColor(), 0, "Select brush color", QColorDialog::ShowAlphaChannel); + if(color.isValid()) + graphicsView->setBrushColor(color); + } + + void QtWhiteboardWindow::setRubberMode() + { + graphicsView->setMode(GView::Rubber); + } + + void QtWhiteboardWindow::setLineMode() + { + graphicsView->setMode(GView::Line); + } + + void QtWhiteboardWindow::setRectMode() + { + graphicsView->setMode(GView::Rect); + } + + void QtWhiteboardWindow::setCircleMode() + { + graphicsView->setMode(GView::Circle); + } + + void QtWhiteboardWindow::setHandLineMode() + { + graphicsView->setMode(GView::HandLine); + } + + void QtWhiteboardWindow::setTextMode() + { + graphicsView->setMode(GView::Text); + } + + void QtWhiteboardWindow::setPolygonMode() + { + graphicsView->setMode(GView::Polygon); + } + + void QtWhiteboardWindow::setSelectMode() + { + graphicsView->setMode(GView::Select); + } + + void QtWhiteboardWindow::show() + { + QWidget::show(); + } + + void QtWhiteboardWindow::setSession(WhiteboardSession::ref session) { + graphicsView->clear(); + whiteboardSession_ = session; + whiteboardSession_->onOperationReceived.connect(boost::bind(&QtWhiteboardWindow::handleWhiteboardOperationReceive, this, _1)); + whiteboardSession_->onRequestAccepted.connect(boost::bind(&QWidget::show, this)); + whiteboardSession_->onSessionTerminated.connect(boost::bind(&QtWhiteboardWindow::handleSessionTerminate, this)); + } + + void QtWhiteboardWindow::activateWindow() { + QWidget::activateWindow(); + } + + void QtWhiteboardWindow::setName(const std::string& name) { + setWindowTitle(P2QSTRING(name)); + } + + void QtWhiteboardWindow::handleLastItemChanged(QGraphicsItem* item, int pos, GView::Type type) { + WhiteboardElement::ref el; + QGraphicsLineItem* lineItem = qgraphicsitem_cast<QGraphicsLineItem*>(item); + if (lineItem != 0) { + QLine line = lineItem->line().toLine(); + QColor color = lineItem->pen().color(); + WhiteboardLineElement::ref element = boost::make_shared<WhiteboardLineElement>(line.x1()+lineItem->pos().x(), line.y1()+lineItem->pos().y(), line.x2()+lineItem->pos().x(), line.y2()+lineItem->pos().y()); + element->setColor(WhiteboardColor(color.red(), color.green(), color.blue(), color.alpha())); + element->setPenWidth(lineItem->pen().width()); + + element->setID(lineItem->data(100).toString().toStdString()); + el = element; + } + + FreehandLineItem* freehandLineItem = qgraphicsitem_cast<FreehandLineItem*>(item); + if (freehandLineItem != 0) { + WhiteboardFreehandPathElement::ref element = boost::make_shared<WhiteboardFreehandPathElement>(); + QColor color = freehandLineItem->pen().color(); + std::vector<std::pair<int, int> > points; + QVector<QPointF>::const_iterator it = freehandLineItem->points().constBegin(); + for ( ; it != freehandLineItem->points().constEnd(); ++it) { + points.push_back(std::pair<int, int>(it->x()+item->pos().x(), it->y()+item->pos().y())); + } + + element->setColor(WhiteboardColor(color.red(), color.green(), color.blue(), color.alpha())); + element->setPenWidth(freehandLineItem->pen().width()); + element->setPoints(points); + + element->setID(freehandLineItem->data(100).toString().toStdString()); + el = element; + } + + QGraphicsRectItem* rectItem = qgraphicsitem_cast<QGraphicsRectItem*>(item); + if (rectItem != 0) { + QRectF rect = rectItem->rect(); + WhiteboardRectElement::ref element = boost::make_shared<WhiteboardRectElement>(rect.x()+item->pos().x(), rect.y()+item->pos().y(), rect.width(), rect.height()); + QColor penColor = rectItem->pen().color(); + QColor brushColor = rectItem->brush().color(); + + element->setBrushColor(WhiteboardColor(brushColor.red(), brushColor.green(), brushColor.blue(), brushColor.alpha())); + element->setPenColor(WhiteboardColor(penColor.red(), penColor.green(), penColor.blue(), penColor.alpha())); + element->setPenWidth(rectItem->pen().width()); + + element->setID(rectItem->data(100).toString().toStdString()); + el = element; + } + + QGraphicsTextItem* textItem = qgraphicsitem_cast<QGraphicsTextItem*>(item); + if (textItem != 0) { + QPointF point = textItem->pos(); + WhiteboardTextElement::ref element = boost::make_shared<WhiteboardTextElement>(point.x(), point.y()); + element->setText(textItem->toPlainText().toStdString()); + element->setSize(textItem->font().pointSize()); + QColor color = textItem->defaultTextColor(); + element->setColor(WhiteboardColor(color.red(), color.green(), color.blue(), color.alpha())); + + element->setID(textItem->data(100).toString().toStdString()); + el = element; + } + + QGraphicsPolygonItem* polygonItem = qgraphicsitem_cast<QGraphicsPolygonItem*>(item); + if (polygonItem) { + WhiteboardPolygonElement::ref element = boost::make_shared<WhiteboardPolygonElement>(); + QPolygonF polygon = polygonItem->polygon(); + std::vector<std::pair<int, int> > points; + QVector<QPointF>::const_iterator it = polygon.begin(); + for (; it != polygon.end(); ++it) { + points.push_back(std::pair<int, int>(it->x()+item->pos().x(), it->y()+item->pos().y())); + } + + element->setPoints(points); + + QColor penColor = polygonItem->pen().color(); + QColor brushColor = polygonItem->brush().color(); + element->setPenColor(WhiteboardColor(penColor.red(), penColor.green(), penColor.blue(), penColor.alpha())); + element->setBrushColor(WhiteboardColor(brushColor.red(), brushColor.green(), brushColor.blue(), brushColor.alpha())); + element->setPenWidth(polygonItem->pen().width()); + + element->setID(polygonItem->data(100).toString().toStdString()); + el = element; + } + + QGraphicsEllipseItem* ellipseItem = qgraphicsitem_cast<QGraphicsEllipseItem*>(item); + if (ellipseItem) { + QRectF rect = ellipseItem->rect(); + int cx = rect.x()+rect.width()/2 + item->pos().x(); + int cy = rect.y()+rect.height()/2 + item->pos().y(); + int rx = rect.width()/2; + int ry = rect.height()/2; + WhiteboardEllipseElement::ref element = boost::make_shared<WhiteboardEllipseElement>(cx, cy, rx, ry); + + QColor penColor = ellipseItem->pen().color(); + QColor brushColor = ellipseItem->brush().color(); + element->setPenColor(WhiteboardColor(penColor.red(), penColor.green(), penColor.blue(), penColor.alpha())); + element->setBrushColor(WhiteboardColor(brushColor.red(), brushColor.green(), brushColor.blue(), brushColor.alpha())); + element->setPenWidth(ellipseItem->pen().width()); + + element->setID(ellipseItem->data(100).toString().toStdString()); + el = element; + } + + if (type == GView::New) { + WhiteboardInsertOperation::ref insertOp = boost::make_shared<WhiteboardInsertOperation>(); + insertOp->setPos(pos); + insertOp->setElement(el); + whiteboardSession_->sendOperation(insertOp); + } else { + WhiteboardUpdateOperation::ref updateOp = boost::make_shared<WhiteboardUpdateOperation>(); + updateOp->setPos(pos); + if (type == GView::Update) { + updateOp->setNewPos(pos); + } else if (type == GView::MoveUp) { + updateOp->setNewPos(pos+1); + } else if (type == GView::MoveDown) { + updateOp->setNewPos(pos-1); + } + updateOp->setElement(el); + whiteboardSession_->sendOperation(updateOp); + } + } + + void QtWhiteboardWindow::handleItemDeleted(QString id, int pos) { + WhiteboardDeleteOperation::ref deleteOp = boost::make_shared<WhiteboardDeleteOperation>(); + deleteOp->setElementID(Q2PSTRING(id)); + deleteOp->setPos(pos); + whiteboardSession_->sendOperation(deleteOp); + } + + void QtWhiteboardWindow::handleSessionTerminate() { + hide(); + } + + void QtWhiteboardWindow::closeEvent(QCloseEvent* event) { + QMessageBox box(this); + box.setText(tr("Closing window is equivalent closing the session. Are you sure you want to do this?")); + box.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + box.setIcon(QMessageBox::Question); + if (box.exec() == QMessageBox::Yes) { + whiteboardSession_->cancel(); + } else { + event->ignore(); + } + } +} diff --git a/Swift/QtUI/Whiteboard/QtWhiteboardWindow.h b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.h new file mode 100644 index 0000000..4665ef0 --- /dev/null +++ b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swift/Controllers/UIInterfaces/WhiteboardWindow.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Whiteboard/WhiteboardSession.h> +#include <Swiften/Elements/Whiteboard/WhiteboardElement.h> + +#include <QWidget> +#include <QGraphicsView> +#include <QGraphicsScene> +#include <QVBoxLayout> +#include <QHBoxLayout> +#include <QGridLayout> +#include <QPainter> +#include <QPushButton> +#include <QSpinBox> +#include <QColorDialog> +#include <QToolButton> +#include <QCloseEvent> + +#include "GView.h" +#include "ColorWidget.h" + +namespace Swift { + class QtWhiteboardWindow : public QWidget, public WhiteboardWindow + { + Q_OBJECT; + public: + QtWhiteboardWindow(WhiteboardSession::ref whiteboardSession); + void show(); + void setSession(WhiteboardSession::ref session); + void activateWindow(); + void setName(const std::string& name); + + private slots: + void changeLineWidth(int i); + void showColorDialog(); + void showBrushColorDialog(); + void setRubberMode(); + void setLineMode(); + void setRectMode(); + void setCircleMode(); + void setHandLineMode(); + void setTextMode(); + void setPolygonMode(); + void setSelectMode(); + void handleLastItemChanged(QGraphicsItem* item, int pos, GView::Type type); + void handleItemDeleted(QString id, int pos); + + private: + void handleSessionTerminate(); + void handleWhiteboardOperationReceive(const WhiteboardOperation::ref operation); + void closeEvent(QCloseEvent* event); + + private: + QGraphicsScene* scene; + GView* graphicsView; + QVBoxLayout* layout; + QVBoxLayout* sidebarLayout; + QHBoxLayout* hLayout; + QGridLayout* toolboxLayout; + QHBoxLayout* strokeLayout; + QHBoxLayout* fillLayout; + ColorWidget* strokeColor; + ColorWidget* fillColor; + QWidget* widget; + QPushButton* moveUpButton; + QPushButton* moveDownButton; + QSpinBox* widthBox; + QToolButton* rubberButton; + QToolButton* lineButton; + QToolButton* rectButton; + QToolButton* circleButton; + QToolButton* handLineButton; + QToolButton* textButton; + QToolButton* polygonButton; + QToolButton* selectButton; + + std::string lastOpID; + WhiteboardSession::ref whiteboardSession_; + }; +} diff --git a/Swift/QtUI/Whiteboard/TextDialog.cpp b/Swift/QtUI/Whiteboard/TextDialog.cpp new file mode 100644 index 0000000..021895a --- /dev/null +++ b/Swift/QtUI/Whiteboard/TextDialog.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "TextDialog.h" + +namespace Swift { + TextDialog::TextDialog(QGraphicsTextItem* item, QWidget* parent) : QDialog(parent) + { + this->item = item; + + layout = new QVBoxLayout(this); + hLayout = new QHBoxLayout; + + editor = new QLineEdit(this); + connect(editor, SIGNAL(textChanged(const QString&)), this, SLOT(changeItemText(const QString&))); + + fontSizeBox = new QSpinBox(this); + fontSizeBox->setMinimum(1); + connect(fontSizeBox, SIGNAL(valueChanged(int)), this, SLOT(changeItemFontSize(int))); + fontSizeBox->setValue(13); + + + buttonBox = new QDialogButtonBox(this); + buttonBox->setStandardButtons(QDialogButtonBox::Ok); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + + hLayout->addWidget(editor); + hLayout->addWidget(fontSizeBox); + layout->addLayout(hLayout); + layout->addWidget(buttonBox); + } + + void TextDialog::changeItemText(const QString &text) + { + item->setPlainText(text); + } + + void TextDialog::changeItemFontSize(int i) + { + QFont font = item->font(); + font.setPointSize(i); + item->setFont(font); + } + + void TextDialog::accept() { + emit accepted(item); + done(QDialog::Accepted); + } +} diff --git a/Swift/QtUI/Whiteboard/TextDialog.h b/Swift/QtUI/Whiteboard/TextDialog.h new file mode 100644 index 0000000..f4d9a13 --- /dev/null +++ b/Swift/QtUI/Whiteboard/TextDialog.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QDialog> +#include <QVBoxLayout> +#include <QHBoxLayout> +#include <QDialogButtonBox> +#include <QLineEdit> +#include <QGraphicsTextItem> +#include <QSpinBox> + +#include <iostream> + +using namespace std; + +namespace Swift { + class TextDialog : public QDialog + { + Q_OBJECT; + public: + TextDialog(QGraphicsTextItem* item, QWidget* parent = 0); + + private: + QGraphicsTextItem* item; + QLineEdit* editor; + QDialogButtonBox* buttonBox; + QVBoxLayout* layout; + QHBoxLayout* hLayout; + QSpinBox* fontSizeBox; + + signals: + void accepted(QGraphicsTextItem* item); + + private slots: + void accept(); + void changeItemText(const QString &text); + void changeItemFontSize(int i); + }; +} + diff --git a/Swift/QtUI/Whiteboard/WhiteboardElementDrawingVisitor.h b/Swift/QtUI/Whiteboard/WhiteboardElementDrawingVisitor.h new file mode 100644 index 0000000..74c6c1d --- /dev/null +++ b/Swift/QtUI/Whiteboard/WhiteboardElementDrawingVisitor.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Elements/Whiteboard/WhiteboardElementVisitor.h> +#include <Swiften/Elements/Whiteboard/WhiteboardLineElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardPolygonElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardTextElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardEllipseElement.h> +#include <Swiften/Elements/Whiteboard/WhiteboardFreehandPathElement.h> +#include <Swift/QtUI/Whiteboard/GView.h> +#include <QtSwiftUtil.h> + +namespace Swift { + class WhiteboardElementDrawingVisitor : public WhiteboardElementVisitor { + public: + WhiteboardElementDrawingVisitor(GView* graphicsView, int pos, GView::Type type) : graphicsView_(graphicsView), pos_(pos), type_(type) {} + + void visit(WhiteboardLineElement& element) { + QGraphicsLineItem *item; + if (type_ == GView::New) { + item = new QGraphicsLineItem(element.x1(), element.y1(), element.x2(), element.y2()); + graphicsView_->addItem(item, P2QSTRING(element.getID()), pos_); + } else { + item = qgraphicsitem_cast<QGraphicsLineItem*>(graphicsView_->getItem(P2QSTRING(element.getID()))); + QLineF line(element.x1(), element.y1(), element.x2(), element.y2()); + item->setLine(line); + item->setPos(0,0); + graphicsView_->deselect(P2QSTRING(element.getID())); + } + if (item) { + QPen pen; + WhiteboardColor color = element.getColor(); + pen.setColor(QColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha())); + pen.setWidth(element.getPenWidth()); + item->setPen(pen); + QString id = P2QSTRING(element.getID()); + item->setData(100, id); + } + } + + void visit(WhiteboardFreehandPathElement& element) { + FreehandLineItem *item; + if (type_ == GView::New) { + item = new FreehandLineItem; + } else { + item = qgraphicsitem_cast<FreehandLineItem*>(graphicsView_->getItem(P2QSTRING(element.getID()))); + item->setPos(0,0); + graphicsView_->deselect(P2QSTRING(element.getID())); + } + + if (item) { + QPen pen; + WhiteboardColor color = element.getColor(); + pen.setColor(QColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha())); + pen.setWidth(element.getPenWidth()); + item->setPen(pen); + + std::vector<std::pair<int, int> >::const_iterator it = element.getPoints().begin(); + item->setStartPoint(QPointF(it->first, it->second)); + for (++it; it != element.getPoints().end(); ++it) { + item->lineTo(QPointF(it->first, it->second)); + } + + QString id = P2QSTRING(element.getID()); + item->setData(100, id); + } + if (type_ == GView::New) { + graphicsView_->addItem(item, P2QSTRING(element.getID()), pos_); + } + } + + void visit(WhiteboardRectElement& element) { + QGraphicsRectItem* item; + if (type_ == GView::New) { + item = new QGraphicsRectItem(element.getX(), element.getY(), element.getWidth(), element.getHeight()); + graphicsView_->addItem(item, P2QSTRING(element.getID()), pos_); + } else { + item = qgraphicsitem_cast<QGraphicsRectItem*>(graphicsView_->getItem(P2QSTRING(element.getID()))); + QRectF rect(element.getX(), element.getY(), element.getWidth(), element.getHeight()); + item->setRect(rect); + item->setPos(0,0); + graphicsView_->deselect(P2QSTRING(element.getID())); + } + + if (item) { + QPen pen; + QBrush brush(Qt::SolidPattern); + WhiteboardColor penColor = element.getPenColor(); + WhiteboardColor brushColor = element.getBrushColor(); + pen.setColor(QColor(penColor.getRed(), penColor.getGreen(), penColor.getBlue(), penColor.getAlpha())); + pen.setWidth(element.getPenWidth()); + brush.setColor(QColor(brushColor.getRed(), brushColor.getGreen(), brushColor.getBlue(), brushColor.getAlpha())); + item->setPen(pen); + item->setBrush(brush); + QString id = P2QSTRING(element.getID()); + item->setData(100, id); + } + } + + void visit(WhiteboardPolygonElement& element) { + QGraphicsPolygonItem* item = qgraphicsitem_cast<QGraphicsPolygonItem*>(graphicsView_->getItem(P2QSTRING(element.getID()))); + if (item == 0 && type_ == GView::New) { + item = new QGraphicsPolygonItem(); + QString id = P2QSTRING(element.getID()); + item->setData(100, id); + graphicsView_->addItem(item, id, pos_); + } + graphicsView_->deselect(P2QSTRING(element.getID())); + QPen pen; + QBrush brush(Qt::SolidPattern); + WhiteboardColor penColor = element.getPenColor(); + WhiteboardColor brushColor = element.getBrushColor(); + pen.setColor(QColor(penColor.getRed(), penColor.getGreen(), penColor.getBlue(), penColor.getAlpha())); + pen.setWidth(element.getPenWidth()); + brush.setColor(QColor(brushColor.getRed(), brushColor.getGreen(), brushColor.getBlue(), brushColor.getAlpha())); + item->setPen(pen); + item->setBrush(brush); + + item->setPos(0,0); + QPolygonF polygon; + std::vector<std::pair<int, int> >::const_iterator it = element.getPoints().begin(); + for (; it != element.getPoints().end(); ++it) { + polygon.append(QPointF(it->first, it->second)); + } + item->setPolygon(polygon); + } + + void visit(WhiteboardTextElement& element) { + QGraphicsTextItem* item; + QString id = P2QSTRING(element.getID()); + if (type_ == GView::New) { + item = new QGraphicsTextItem; + graphicsView_->addItem(item, id, pos_); + } else { + item = qgraphicsitem_cast<QGraphicsTextItem*>(graphicsView_->getItem(id)); + graphicsView_->deselect(P2QSTRING(element.getID())); + } + if (item) { + item->setPlainText(P2QSTRING(element.getText())); + item->setPos(QPointF(element.getX(), element.getY())); + QFont font = item->font(); + font.setPointSize(element.getSize()); + item->setFont(font); + WhiteboardColor color = element.getColor(); + item->setDefaultTextColor(QColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha())); + item->setData(100, id); + } + } + + void visit(WhiteboardEllipseElement& element) { + QRectF rect; + QGraphicsEllipseItem* item; + QString id = P2QSTRING(element.getID()); + rect.setTopLeft(QPointF(element.getCX()-element.getRX(), element.getCY()-element.getRY())); + rect.setBottomRight(QPointF(element.getCX()+element.getRX(), element.getCY()+element.getRY())); + if (type_ == GView::New) { + item = new QGraphicsEllipseItem(rect); + graphicsView_->addItem(item, id, pos_); + } else { + item = qgraphicsitem_cast<QGraphicsEllipseItem*>(graphicsView_->getItem(id)); + item->setRect(rect); + item->setPos(0,0); + graphicsView_->deselect(P2QSTRING(element.getID())); + } + QPen pen; + QBrush brush(Qt::SolidPattern); + WhiteboardColor penColor = element.getPenColor(); + WhiteboardColor brushColor = element.getBrushColor(); + pen.setColor(QColor(penColor.getRed(), penColor.getGreen(), penColor.getBlue(), penColor.getAlpha())); + pen.setWidth(element.getPenWidth()); + brush.setColor(QColor(brushColor.getRed(), brushColor.getGreen(), brushColor.getBlue(), brushColor.getAlpha())); + item->setPen(pen); + item->setBrush(brush); + item->setData(100, id); + } + + private: + GView* graphicsView_; + int pos_; + GView::Type type_; + }; +} |