diff options
author | Daniel Baczynski <danielbaczynski8@gmail.com> | 2015-03-25 00:16:20 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2015-03-26 07:39:31 (GMT) |
commit | 85e53159321ab3e013dd2fc0a16748ed6755b119 (patch) | |
tree | 6ed333198bb756c8e1946505663ae0c95e72223b | |
parent | b23f4fb9bee49f93bbba6a9039f0f764664125cd (diff) | |
download | swift-85e53159321ab3e013dd2fc0a16748ed6755b119.zip swift-85e53159321ab3e013dd2fc0a16748ed6755b119.tar.bz2 |
Add emoticons input popup
This is simple popup menu added to chat window where it is possible to choose an emoticon. To activate click on the smiling face next to input field.
When emoticon is selected its text equivalent is appended to input.
License:
This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details.
Test-Information:
Tested on Ubuntu 14.10 with KDE and Qt 4.8.6
Change-Id: I6c5907959970398c9c38591f64ceec20efcbf409
-rw-r--r-- | Swift/QtUI/QtChatWindow.cpp | 25 | ||||
-rw-r--r-- | Swift/QtUI/QtChatWindow.h | 11 | ||||
-rw-r--r-- | Swift/QtUI/QtChatWindowFactory.cpp | 4 | ||||
-rw-r--r-- | Swift/QtUI/QtChatWindowFactory.h | 9 | ||||
-rw-r--r-- | Swift/QtUI/QtEmoticonCell.cpp | 30 | ||||
-rw-r--r-- | Swift/QtUI/QtEmoticonCell.h | 34 | ||||
-rw-r--r-- | Swift/QtUI/QtEmoticonsGrid.cpp | 59 | ||||
-rw-r--r-- | Swift/QtUI/QtEmoticonsGrid.h | 40 | ||||
-rw-r--r-- | Swift/QtUI/QtSwift.cpp | 2 | ||||
-rw-r--r-- | Swift/QtUI/SConscript | 2 |
10 files changed, 207 insertions, 9 deletions
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 33bec75..f25c033 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -15,6 +15,7 @@ #include <QBoxLayout> #include <QCloseEvent> #include <QComboBox> +#include <QCursor> #include <QFileDialog> #include <QFileInfo> #include <QInputDialog> @@ -23,7 +24,9 @@ #include <QMenu> #include <QMessageBox> #include <QMimeData> +#include <QPoint> #include <QPushButton> +#include <QSize> #include <QSplitter> #include <QString> #include <QTextDocument> @@ -57,7 +60,7 @@ namespace Swift { -QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings) : QtTabbable(), id_(Q2PSTRING(contact)), contact_(contact), nextAlertId_(0), eventStream_(eventStream), blockingState_(BlockingUnsupported), isMUC_(false), supportsImpromptuChat_(false) { +QtChatWindow::QtChatWindow(const QString& contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings, const std::map<std::string, std::string>& emoticons) : QtTabbable(), id_(Q2PSTRING(contact)), contact_(contact), nextAlertId_(0), eventStream_(eventStream), blockingState_(BlockingUnsupported), isMUC_(false), supportsImpromptuChat_(false) { settings_ = settings; unreadCount_ = 0; isOnline_ = true; @@ -140,8 +143,17 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt inputBarLayout->addWidget(correctingLabel_); correctingLabel_->hide(); + QPushButton* emoticonsButton_ = new QPushButton(this); + emoticonsButton_->setIcon(QIcon(":/emoticons/smile.png")); + connect(emoticonsButton_, SIGNAL(clicked()), this, SLOT(handleEmoticonsButtonClicked())); + + emoticonsMenu_ = new QMenu(this); + QtEmoticonsGrid* emoticonsGrid = new QtEmoticonsGrid(emoticons, emoticonsMenu_); + connect(emoticonsGrid, SIGNAL(emoticonClicked(QString)), this, SLOT(handleEmoticonClicked(QString))); + // using an extra layout to work around Qt margin glitches on OS X QHBoxLayout* actionLayout = new QHBoxLayout(); + actionLayout->addWidget(emoticonsButton_); actionLayout->addWidget(actionButton_); inputBarLayout->addLayout(actionLayout); @@ -514,6 +526,7 @@ void QtChatWindow::updateTitleWithUnreadCount() { + void QtChatWindow::flash() { emit requestFlash(); } @@ -637,6 +650,16 @@ void QtChatWindow::setSubject(const std::string& subject) { subject_->setCursorPosition(0); } +void QtChatWindow::handleEmoticonsButtonClicked() { + emoticonsMenu_->adjustSize(); + QSize menuSize = emoticonsMenu_->size(); + emoticonsMenu_->exec(QPoint(QCursor::pos().x() - menuSize.width(), QCursor::pos().y() - menuSize.height())); +} + +void QtChatWindow::handleEmoticonClicked(QString emoticonAsText) { + input_->textCursor().insertText(emoticonAsText); +} + void QtChatWindow::handleActionButtonClicked() { QMenu contextMenu; QAction* changeSubject = NULL; diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index da3a3b9..5c6fa2a 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.h @@ -8,9 +8,11 @@ #include <map> +#include <QMap> +#include <QMenu> #include <QPointer> +#include <QString> #include <QTextCursor> -#include <QMap> #include <SwifTools/LastLineTracker.h> @@ -18,12 +20,12 @@ #include <Swift/QtUI/ChatSnippet.h> #include <Swift/QtUI/QtAffiliationEditor.h> +#include <Swift/QtUI/QtEmoticonsGrid.h> #include <Swift/QtUI/QtMUCConfigurationWindow.h> #include <Swift/QtUI/QtSwiftUtil.h> #include <Swift/QtUI/QtTabbable.h> - class QTextEdit; class QLineEdit; class QComboBox; @@ -77,7 +79,7 @@ namespace Swift { Q_OBJECT public: - QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings); + QtChatWindow(const QString& contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings, const std::map<std::string, std::string>& emoticons); virtual ~QtChatWindow(); std::string addMessage(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight); std::string addAction(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight); @@ -169,6 +171,8 @@ namespace Swift { void handleActionButtonClicked(); void handleAffiliationEditorAccepted(); void handleCurrentLabelChanged(int); + void handleEmoticonsButtonClicked(); + void handleEmoticonClicked(QString emoticonAsText); private: void updateTitleWithUnreadCount(); @@ -221,5 +225,6 @@ namespace Swift { bool impromptu_; bool isMUC_; bool supportsImpromptuChat_; + QMenu* emoticonsMenu_; }; } diff --git a/Swift/QtUI/QtChatWindowFactory.cpp b/Swift/QtUI/QtChatWindowFactory.cpp index 3793392..1774653 100644 --- a/Swift/QtUI/QtChatWindowFactory.cpp +++ b/Swift/QtUI/QtChatWindowFactory.cpp @@ -21,7 +21,7 @@ namespace Swift { static const QString SPLITTER_STATE = "mucSplitterState"; static const QString CHAT_TABS_GEOMETRY = "chatTabsGeometry"; -QtChatWindowFactory::QtChatWindowFactory(QtSingleWindow* splitter, SettingsProvider* settings, QtSettingsProvider* qtSettings, QtChatTabs* tabs, const QString& themePath) : themePath_(themePath) { +QtChatWindowFactory::QtChatWindowFactory(QtSingleWindow* splitter, SettingsProvider* settings, QtSettingsProvider* qtSettings, QtChatTabs* tabs, const QString& themePath, const std::map<std::string, std::string>& emoticons) : themePath_(themePath), emoticons_(emoticons) { qtOnlySettings_ = qtSettings; settings_ = settings; tabs_ = tabs; @@ -50,7 +50,7 @@ ChatWindow* QtChatWindowFactory::createChatWindow(const JID &contact,UIEventStre } } - QtChatWindow *chatWindow = new QtChatWindow(P2QSTRING(contact.toString()), theme_, eventStream, settings_); + QtChatWindow* chatWindow = new QtChatWindow(P2QSTRING(contact.toString()), theme_, eventStream, settings_, emoticons_); connect(chatWindow, SIGNAL(splitterMoved()), this, SLOT(handleSplitterMoved())); connect(this, SIGNAL(changeSplitterState(QByteArray)), chatWindow, SLOT(handleChangeSplitterState(QByteArray))); diff --git a/Swift/QtUI/QtChatWindowFactory.h b/Swift/QtUI/QtChatWindowFactory.h index aa91d0b..c38202f 100644 --- a/Swift/QtUI/QtChatWindowFactory.h +++ b/Swift/QtUI/QtChatWindowFactory.h @@ -6,12 +6,16 @@ #pragma once -#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h> +#include <map> +#include <string> #include <QObject> #include <QSplitter> #include <Swiften/JID/JID.h> + +#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h> + #include <Swift/QtUI/QtSettingsProvider.h> namespace Swift { @@ -23,7 +27,7 @@ namespace Swift { class QtChatWindowFactory : public QObject, public ChatWindowFactory { Q_OBJECT public: - QtChatWindowFactory(QtSingleWindow* splitter, SettingsProvider* settings, QtSettingsProvider* qtSettings, QtChatTabs* tabs, const QString& themePath); + QtChatWindowFactory(QtSingleWindow* splitter, SettingsProvider* settings, QtSettingsProvider* qtSettings, QtChatTabs* tabs, const QString& themePath, const std::map<std::string, std::string>& emoticons); ~QtChatWindowFactory(); ChatWindow* createChatWindow(const JID &contact, UIEventStream* eventStream); signals: @@ -37,6 +41,7 @@ namespace Swift { QtSettingsProvider* qtOnlySettings_; QtChatTabs* tabs_; QtChatTheme* theme_; + std::map<std::string, std::string> emoticons_; }; } diff --git a/Swift/QtUI/QtEmoticonCell.cpp b/Swift/QtUI/QtEmoticonCell.cpp new file mode 100644 index 0000000..1c1f6ed --- /dev/null +++ b/Swift/QtUI/QtEmoticonCell.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 Daniel Baczynski + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtEmoticonCell.h" + +namespace Swift { + +QtEmoticonCell::QtEmoticonCell(const QString emoticonAsText, QString filePath, QWidget* parent) : QLabel(parent), emoticonAsText_(emoticonAsText) { + if (filePath.startsWith("qrc:/")) { + filePath.remove(0, 3); + } + setPixmap(QPixmap(filePath)); + setToolTip(emoticonAsText_); +} + +QtEmoticonCell::~QtEmoticonCell() { + +} + +void QtEmoticonCell::mousePressEvent (QMouseEvent* event) { + emit emoticonClicked(emoticonAsText_); + QLabel::mousePressEvent(event); +} + +} + + diff --git a/Swift/QtUI/QtEmoticonCell.h b/Swift/QtUI/QtEmoticonCell.h new file mode 100644 index 0000000..379f5d6 --- /dev/null +++ b/Swift/QtUI/QtEmoticonCell.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 Daniel Baczynski + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <map> +#include <string> + +#include <QLabel> +#include <QPixmap> +#include <QString> + +class QWidget; +class QMouseEvent; + +namespace Swift { + + class QtEmoticonCell : public QLabel { + Q_OBJECT + public: + QtEmoticonCell(const QString emoticonAsText, QString filePath, QWidget* parent = 0); + ~QtEmoticonCell(); + virtual void mousePressEvent(QMouseEvent* event); + + signals: + void emoticonClicked(QString emoticonAsText); + + private: + QString emoticonAsText_; + }; +} diff --git a/Swift/QtUI/QtEmoticonsGrid.cpp b/Swift/QtUI/QtEmoticonsGrid.cpp new file mode 100644 index 0000000..4a599ea --- /dev/null +++ b/Swift/QtUI/QtEmoticonsGrid.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 Daniel Baczynski + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtEmoticonsGrid.h" + +#include <set> + +#include <QPushButton> + +#include <Swiften/Base/foreach.h> + +#include <Swift/QtUI/QtSwiftUtil.h> + +namespace Swift { + +typedef std::map<std::string, std::string> EmoticonsMap; // Without this typedef compiler complains when using foreach + +QtEmoticonsGrid::QtEmoticonsGrid(const std::map<std::string, std::string>& emoticons, QWidget* parent) : QGridLayout(parent) { + makeUniqueEmoticonsMap(emoticons); + + // Create grid: 3 columns, [uniqueEmoticons_.size()/3] rows + int row = 0; + int column = 0; + + foreach(EmoticonsMap::value_type emoticon, uniqueEmoticons_) { + QtEmoticonCell* newCell = new QtEmoticonCell(P2QSTRING(emoticon.first), P2QSTRING(emoticon.second)); + addWidget(newCell, row, column); + connect(newCell, SIGNAL(emoticonClicked(QString)), this, SLOT(emoticonClickedSlot(QString))); + + column++; + if (column >= 3) { + column = 0; + row++; + } + } +} + +QtEmoticonsGrid::~QtEmoticonsGrid() { + +} + +void QtEmoticonsGrid::makeUniqueEmoticonsMap(const std::map<std::string, std::string>& emoticons) { + std::set<std::string> paths; + reverse_foreach(EmoticonsMap::value_type emoticon, emoticons) { + if (paths.find(emoticon.second) == paths.end()) { + uniqueEmoticons_.insert(emoticon); + paths.insert(emoticon.second); + } + } +} + +void QtEmoticonsGrid::emoticonClickedSlot(QString emoticonAsText) { + emit emoticonClicked(emoticonAsText); +} + +} diff --git a/Swift/QtUI/QtEmoticonsGrid.h b/Swift/QtUI/QtEmoticonsGrid.h new file mode 100644 index 0000000..b045b26 --- /dev/null +++ b/Swift/QtUI/QtEmoticonsGrid.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 Daniel Baczynski + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <map> +#include <string> + +#include <QGridLayout> +#include <QLabel> +#include <QSize> +#include <QString> + +#include <Swift/QtUI/QtEmoticonCell.h> + +class QWidget; + +namespace Swift { + + class QtEmoticonsGrid : public QGridLayout { + Q_OBJECT + public: + explicit QtEmoticonsGrid(const std::map<std::string, std::string>& emoticons, QWidget* parent = 0); + virtual ~QtEmoticonsGrid(); + + signals: + void emoticonClicked(QString emoticonAsText); + + public slots: + void emoticonClickedSlot(QString emoticonAsText); + + private: + void makeUniqueEmoticonsMap(const std::map<std::string, std::string>& emoticons); + + std::map<std::string, std::string> uniqueEmoticons_; + }; +} diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp index 1d945da..bce3ca4 100644 --- a/Swift/QtUI/QtSwift.cpp +++ b/Swift/QtUI/QtSwift.cpp @@ -170,7 +170,7 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa applicationPathProvider_ = new PlatformApplicationPathProvider(SWIFT_APPLICATION_NAME); storagesFactory_ = new FileStoragesFactory(applicationPathProvider_->getDataDir(), networkFactories_.getCryptoProvider()); certificateStorageFactory_ = new CertificateFileStorageFactory(applicationPathProvider_->getDataDir(), tlsFactories_.getCertificateFactory(), networkFactories_.getCryptoProvider()); - chatWindowFactory_ = new QtChatWindowFactory(splitter_, settingsHierachy_, qtSettings_, tabs_, ""); + chatWindowFactory_ = new QtChatWindowFactory(splitter_, settingsHierachy_, qtSettings_, tabs_, "", emoticons); soundPlayer_ = new QtSoundPlayer(applicationPathProvider_); // Ugly, because the dock depends on the tray, but the temporary diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 858df19..36f7cc9 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -124,6 +124,8 @@ sources = [ "QtBookmarkDetailWindow.cpp", "QtAddBookmarkWindow.cpp", "QtEditBookmarkWindow.cpp", + "QtEmoticonsGrid.cpp", + "QtEmoticonCell.cpp", "QtContactEditWindow.cpp", "QtContactEditWidget.cpp", "QtSingleWindow.cpp", |