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 /Swift/QtUI | |
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
Diffstat (limited to 'Swift/QtUI')
-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 @@ -12,21 +12,24 @@ #include <qdebug.h> #include <QApplication> #include <QBoxLayout> #include <QCloseEvent> #include <QComboBox> +#include <QCursor> #include <QFileDialog> #include <QFileInfo> #include <QInputDialog> #include <QLabel> #include <QLineEdit> #include <QMenu> #include <QMessageBox> #include <QMimeData> +#include <QPoint> #include <QPushButton> +#include <QSize> #include <QSplitter> #include <QString> #include <QTextDocument> #include <QTextEdit> #include <QTime> #include <QToolButton> @@ -54,13 +57,13 @@ #include <Swift/QtUI/QtUISettingConstants.h> #include <Swift/QtUI/QtUtilities.h> #include <Swift/QtUI/QtWebKitChatView.h> 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; completer_ = NULL; affiliationEditor_ = NULL; theme_ = theme; @@ -137,14 +140,23 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt inputBarLayout->addWidget(midBar_); inputBarLayout->addWidget(input_); correctingLabel_ = new QLabel(tr("Correcting"), this); 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); layout->addLayout(inputBarLayout); inputClearing_ = false; @@ -511,12 +523,13 @@ void QtChatWindow::updateTitleWithUnreadCount() { } emit titleUpdated(); } + void QtChatWindow::flash() { emit requestFlash(); } int QtChatWindow::getCount() { return unreadCount_; @@ -634,12 +647,22 @@ void QtChatWindow::setSubject(const std::string& subject) { //subject_->setVisible(!subject.empty()); subject_->setText(P2QSTRING(subject)); subject_->setToolTip(P2QSTRING(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; QAction* configure = NULL; QAction* affiliations = NULL; QAction* destroy = 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 @@ -5,28 +5,30 @@ */ #pragma once #include <map> +#include <QMap> +#include <QMenu> #include <QPointer> +#include <QString> #include <QTextCursor> -#include <QMap> #include <SwifTools/LastLineTracker.h> #include <Swift/Controllers/UIInterfaces/ChatWindow.h> #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; class QLabel; class QSplitter; class QPushButton; @@ -74,13 +76,13 @@ namespace Swift { }; class QtChatWindow : public QtTabbable, public ChatWindow { 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); std::string addSystemMessage(const ChatMessage& message, Direction direction); void addPresenceMessage(const ChatMessage& message, Direction direction); @@ -166,12 +168,14 @@ namespace Swift { void handleKeyPressEvent(QKeyEvent* event); void handleSplitterMoved(int pos, int index); void handleAlertButtonClicked(); void handleActionButtonClicked(); void handleAffiliationEditorAccepted(); void handleCurrentLabelChanged(int); + void handleEmoticonsButtonClicked(); + void handleEmoticonClicked(QString emoticonAsText); private: void updateTitleWithUnreadCount(); void tabComplete(); void beginCorrection(); void cancelCorrection(); @@ -218,8 +222,9 @@ namespace Swift { QPalette defaultLabelsPalette_; LabelModel* labelModel_; BlockingState blockingState_; 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 @@ -18,13 +18,13 @@ 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; theme_ = NULL; if (splitter) { splitter->addWidget(tabs_); @@ -47,13 +47,13 @@ ChatWindow* QtChatWindowFactory::createChatWindow(const JID &contact,UIEventStre if (theme_->getIncomingContent().isEmpty()) { delete theme_; theme_ = new QtChatTheme(""); /* Use the inbuilt theme */ } } - 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))); QVariant splitterState = qtOnlySettings_->getQSettings()->value(SPLITTER_STATE); if(splitterState.isValid()) { chatWindow->handleChangeSplitterState(splitterState.toByteArray()); 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 @@ -3,30 +3,34 @@ * All rights reserved. * See the COPYING file for more information. */ #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 { class QtChatTabs; class QtChatTheme; class UIEventStream; class QtUIPreferences; class QtSingleWindow; 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: void changeSplitterState(QByteArray); private slots: void handleWindowGeometryChanged(); @@ -34,9 +38,10 @@ namespace Swift { private: QString themePath_; SettingsProvider* settings_; 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 @@ -167,13 +167,13 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa bool enableAdHocCommandOnJID = options.count("enable-jid-adhocs") > 0; tabs_ = options.count("no-tabs") && !splitter_ ? NULL : new QtChatTabs(splitter_ != NULL, settingsHierachy_, options.count("trellis")); bool startMinimized = options.count("start-minimized") > 0; 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 // multi-account hack creates one tray per account. QtSystemTray* systemTray = new QtSystemTray(); systemTrays_.push_back(systemTray); diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 858df19..36f7cc9 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -121,12 +121,14 @@ sources = [ "QtAdHocCommandWindow.cpp", "QtAdHocCommandWithJIDWindow.cpp", "QtUtilities.cpp", "QtBookmarkDetailWindow.cpp", "QtAddBookmarkWindow.cpp", "QtEditBookmarkWindow.cpp", + "QtEmoticonsGrid.cpp", + "QtEmoticonCell.cpp", "QtContactEditWindow.cpp", "QtContactEditWidget.cpp", "QtSingleWindow.cpp", "QtHighlightEditor.cpp", "QtColorToolButton.cpp", "QtClosableLineEdit.cpp", |