summaryrefslogtreecommitdiffstats
path: root/Swift
diff options
context:
space:
mode:
Diffstat (limited to 'Swift')
-rw-r--r--Swift/QtUI/QtChatWindow.cpp51
-rw-r--r--Swift/QtUI/QtChatWindow.h19
-rw-r--r--Swift/QtUI/QtChatWindowFactory.cpp10
-rw-r--r--Swift/QtUI/QtChatWindowFactory.h14
-rw-r--r--Swift/QtUI/QtEmojiCell.cpp41
-rw-r--r--Swift/QtUI/QtEmojiCell.h30
-rw-r--r--Swift/QtUI/QtEmojisGrid.cpp72
-rw-r--r--Swift/QtUI/QtEmojisGrid.h31
-rw-r--r--Swift/QtUI/QtEmojisScroll.cpp34
-rw-r--r--Swift/QtUI/QtEmojisScroll.h18
-rw-r--r--Swift/QtUI/QtEmojisSelector.cpp75
-rw-r--r--Swift/QtUI/QtEmojisSelector.h40
-rw-r--r--Swift/QtUI/QtEmoticonCell.cpp36
-rw-r--r--Swift/QtUI/QtEmoticonCell.h40
-rw-r--r--Swift/QtUI/QtEmoticonsGrid.cpp63
-rw-r--r--Swift/QtUI/QtEmoticonsGrid.h46
-rw-r--r--Swift/QtUI/QtRecentEmojisGrid.cpp59
-rw-r--r--Swift/QtUI/QtRecentEmojisGrid.h43
-rw-r--r--Swift/QtUI/QtSwift.cpp7
-rw-r--r--Swift/QtUI/SConscript7
20 files changed, 509 insertions, 227 deletions
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index d799e19..345139c 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2017 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -19,6 +19,7 @@
#include <QDebug>
#include <QFileDialog>
#include <QFileInfo>
+#include <QFontMetrics>
#include <QInputDialog>
#include <QLabel>
#include <QLineEdit>
@@ -46,11 +47,12 @@
#include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
#include <Swift/Controllers/UIEvents/UIEventStream.h>
+#include <SwifTools/EmojiMapper.h>
#include <SwifTools/TabComplete.h>
#include <Swift/QtUI/QtAddBookmarkWindow.h>
#include <Swift/QtUI/QtEditBookmarkWindow.h>
-#include <Swift/QtUI/QtEmoticonsGrid.h>
+#include <Swift/QtUI/QtEmojisSelector.h>
#include <Swift/QtUI/QtPlainChatView.h>
#include <Swift/QtUI/QtScaledAvatarCache.h>
#include <Swift/QtUI/QtSettingsProvider.h>
@@ -62,8 +64,7 @@
namespace Swift {
-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), roomBookmarkState_(RoomNotBookmarked) {
- settings_ = settings;
+QtChatWindow::QtChatWindow(const QString& contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings, QtSettingsProvider* qtOnlySettings) : QtTabbable(), id_(Q2PSTRING(contact)), contact_(contact), nextAlertId_(0), eventStream_(eventStream), settings_(settings), qtOnlySettings_(qtOnlySettings), blockingState_(BlockingUnsupported), isMUC_(false), supportsImpromptuChat_(false), roomBookmarkState_(RoomNotBookmarked) {
unreadCount_ = 0;
isOnline_ = true;
completer_ = nullptr;
@@ -145,17 +146,13 @@ QtChatWindow::QtChatWindow(const QString& contact, QtChatTheme* theme, UIEventSt
connect(input_, SIGNAL(receivedFocus()), this, SLOT(handleTextInputReceivedFocus()));
connect(input_, SIGNAL(lostFocus()), this, SLOT(handleTextInputLostFocus()));
- 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)));
+ QPushButton* emojisButton_ = new QPushButton(this);
+ emojisButton_->setText("\xF0\x9F\x98\x83");
+ connect(emojisButton_, SIGNAL(clicked()), this, SLOT(handleEmojisButtonClicked()));
// using an extra layout to work around Qt margin glitches on OS X
QHBoxLayout* actionLayout = new QHBoxLayout();
- actionLayout->addWidget(emoticonsButton_);
+ actionLayout->addWidget(emojisButton_);
actionLayout->addWidget(actionButton_);
inputBarLayout->addLayout(actionLayout);
@@ -663,15 +660,31 @@ 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::handleEmojisButtonClicked() {
+ // Create QtEmojisSelector and QMenu
+ emojisGrid_ = new QtEmojisSelector(qtOnlySettings_->getQSettings());
+ auto emojisLayout = new QVBoxLayout();
+ emojisLayout->setContentsMargins(style()->pixelMetric(QStyle::PM_MenuHMargin),style()->pixelMetric(QStyle::PM_MenuVMargin),
+ style()->pixelMetric(QStyle::PM_MenuHMargin),style()->pixelMetric(QStyle::PM_MenuVMargin));
+ emojisLayout->addWidget(emojisGrid_);
+ emojisMenu_ = std::unique_ptr<QMenu>(new QMenu());
+ emojisMenu_->setLayout(emojisLayout);
+ emojisMenu_->adjustSize();
+
+ connect(emojisGrid_, SIGNAL(emojiClicked(QString)), this, SLOT(handleEmojiClicked(QString)));
+
+ QSize menuSize = emojisMenu_->size();
+ emojisMenu_->exec(QPoint(QCursor::pos().x() - menuSize.width(), QCursor::pos().y() - menuSize.height()));
}
-void QtChatWindow::handleEmoticonClicked(QString emoticonAsText) {
- input_->textCursor().insertText(emoticonAsText);
- input_->setFocus();
+void QtChatWindow::handleEmojiClicked(QString emoji) {
+ if (isVisible()) {
+ input_->textCursor().insertText(emoji);
+ input_->setFocus();
+ // The next line also deletes the emojisGrid_, as it was added to the
+ // layout of the emojisMenu_.
+ emojisMenu_.reset();
+ }
}
void QtChatWindow::handleTextInputReceivedFocus() {
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index 08ad7ad..4c64c84 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2017 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -13,13 +13,16 @@
#include <QPointer>
#include <QString>
#include <QTextCursor>
+#include <QVBoxLayout>
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
+#include <SwifTools/EmojiMapper.h>
#include <SwifTools/LastLineTracker.h>
#include <Swift/QtUI/ChatSnippet.h>
#include <Swift/QtUI/QtAffiliationEditor.h>
+#include <Swift/QtUI/QtEmojisSelector.h>
#include <Swift/QtUI/QtMUCConfigurationWindow.h>
#include <Swift/QtUI/QtSwiftUtil.h>
#include <Swift/QtUI/QtTabbable.h>
@@ -40,7 +43,7 @@ namespace Swift {
class UIEventStream;
class QtChatWindowJSBridge;
class SettingsProvider;
- class QtEmoticonsGrid;
+ class QtSettingsProvider;
class LabelModel : public QAbstractListModel {
Q_OBJECT
@@ -78,7 +81,7 @@ namespace Swift {
Q_OBJECT
public:
- QtChatWindow(const QString& contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings, const std::map<std::string, std::string>& emoticons);
+ QtChatWindow(const QString& contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings, QtSettingsProvider* qtOnlySettings);
virtual ~QtChatWindow();
std::string addMessage(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, std::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time);
std::string addAction(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, std::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time);
@@ -138,6 +141,7 @@ namespace Swift {
public slots:
void handleChangeSplitterState(QByteArray state);
+ void handleEmojiClicked(QString emoji);
void handleFontResized(int fontSizeSteps);
AlertID addAlert(const std::string& alertText);
void removeAlert(const AlertID id);
@@ -171,8 +175,7 @@ namespace Swift {
void handleActionButtonClicked();
void handleAffiliationEditorAccepted();
void handleCurrentLabelChanged(int);
- void handleEmoticonsButtonClicked();
- void handleEmoticonClicked(QString emoticonAsText);
+ void handleEmojisButtonClicked();
void handleTextInputReceivedFocus();
void handleTextInputLostFocus();
@@ -221,7 +224,8 @@ namespace Swift {
QString alertStyleSheet_;
QPointer<QtMUCConfigurationWindow> mucConfigurationWindow_;
QPointer<QtAffiliationEditor> affiliationEditor_;
- SettingsProvider* settings_;
+ SettingsProvider* settings_ = nullptr;
+ QtSettingsProvider* qtOnlySettings_ = nullptr;
std::vector<ChatWindow::RoomAction> availableRoomActions_;
QPalette defaultLabelsPalette_;
LabelModel* labelModel_;
@@ -230,6 +234,7 @@ namespace Swift {
bool isMUC_;
bool supportsImpromptuChat_;
RoomBookmarkState roomBookmarkState_;
- QMenu* emoticonsMenu_;
+ std::unique_ptr<QMenu> emojisMenu_;
+ QPointer<QtEmojisSelector> emojisGrid_;
};
}
diff --git a/Swift/QtUI/QtChatWindowFactory.cpp b/Swift/QtUI/QtChatWindowFactory.cpp
index 9c59e9a..5a4a501 100644
--- a/Swift/QtUI/QtChatWindowFactory.cpp
+++ b/Swift/QtUI/QtChatWindowFactory.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2017 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -8,12 +8,13 @@
#include <QDesktopWidget>
-#include <qdebug.h>
+#include <SwifTools/EmojiMapper.h>
#include <Swift/QtUI/QtChatTabs.h>
#include <Swift/QtUI/QtChatTabsBase.h>
#include <Swift/QtUI/QtChatTheme.h>
#include <Swift/QtUI/QtChatWindow.h>
+#include <Swift/QtUI/QtEmojisSelector.h>
#include <Swift/QtUI/QtSingleWindow.h>
#include <Swift/QtUI/QtSwiftUtil.h>
@@ -22,7 +23,7 @@ namespace Swift {
static const QString SPLITTER_STATE = "mucSplitterState";
static const QString CHAT_TABS_GEOMETRY = "chatTabsGeometry";
-QtChatWindowFactory::QtChatWindowFactory(QtSingleWindow* splitter, SettingsProvider* settings, QtSettingsProvider* qtSettings, QtChatTabsBase* tabs, const QString& themePath, const std::map<std::string, std::string>& emoticons) : themePath_(themePath), emoticons_(emoticons) {
+QtChatWindowFactory::QtChatWindowFactory(QtSingleWindow* splitter, SettingsProvider* settings, QtSettingsProvider* qtSettings, QtChatTabsBase* tabs, const QString& themePath) : themePath_(themePath) {
qtOnlySettings_ = qtSettings;
settings_ = settings;
tabs_ = tabs;
@@ -53,7 +54,8 @@ ChatWindow* QtChatWindowFactory::createChatWindow(const JID &contact,UIEventStre
}
}
- QtChatWindow* chatWindow = new QtChatWindow(P2QSTRING(contact.toString()), theme_, eventStream, settings_, emoticons_);
+ QtChatWindow* chatWindow = new QtChatWindow(P2QSTRING(contact.toString()), theme_, eventStream, settings_, qtOnlySettings_);
+
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 29bc5bc..a217215 100644
--- a/Swift/QtUI/QtChatWindowFactory.h
+++ b/Swift/QtUI/QtChatWindowFactory.h
@@ -1,21 +1,23 @@
/*
- * Copyright (c) 2010-2015 Isode Limited.
+ * Copyright (c) 2010-2017 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#pragma once
-#include <map>
-#include <string>
-
+#include <QMenu>
#include <QObject>
#include <QSplitter>
+#include <QVBoxLayout>
#include <Swiften/JID/JID.h>
#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
+#include <SwifTools/EmojiMapper.h>
+
+#include <Swift/QtUI/QtEmojisSelector.h>
#include <Swift/QtUI/QtSettingsProvider.h>
namespace Swift {
@@ -27,7 +29,7 @@ namespace Swift {
class QtChatWindowFactory : public QObject, public ChatWindowFactory {
Q_OBJECT
public:
- QtChatWindowFactory(QtSingleWindow* splitter, SettingsProvider* settings, QtSettingsProvider* qtSettings, QtChatTabsBase* tabs, const QString& themePath, const std::map<std::string, std::string>& emoticons);
+ QtChatWindowFactory(QtSingleWindow* splitter, SettingsProvider* settings, QtSettingsProvider* qtSettings, QtChatTabsBase* tabs, const QString& themePath);
~QtChatWindowFactory();
ChatWindow* createChatWindow(const JID &contact, UIEventStream* eventStream);
signals:
@@ -41,7 +43,5 @@ namespace Swift {
QtSettingsProvider* qtOnlySettings_;
QtChatTabsBase* tabs_;
QtChatTheme* theme_;
- std::map<std::string, std::string> emoticons_;
};
}
-
diff --git a/Swift/QtUI/QtEmojiCell.cpp b/Swift/QtUI/QtEmojiCell.cpp
new file mode 100644
index 0000000..4932ece
--- /dev/null
+++ b/Swift/QtUI/QtEmojiCell.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016-2017 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/QtEmojiCell.h>
+
+#include <QFont>
+#include <QFontMetrics>
+#include <QPushButton>
+#include <QString>
+
+#include <SwifTools/EmojiMapper.h>
+
+namespace Swift {
+ QtEmojiCell::QtEmojiCell(QString shortname, QString text, QWidget* parent) : QPushButton(parent) {
+ setText(text);
+ QFont font = this->font();
+ font.setPointSize(22);
+ font.setBold(true);
+ setFont(font);
+
+ setFixedWidth(fontMetrics().width("\xF0\x9F\x98\x83")+5);
+
+ setFlat(true);
+ setToolTip(shortname);
+ connect(this, SIGNAL(clicked()), this, SLOT(handleEmojiClicked()));
+ }
+
+ QtEmojiCell::QtEmojiCell(const QtEmojiCell& b) : QtEmojiCell(b.toolTip(), b.text()) {
+ }
+
+ QtEmojiCell::~QtEmojiCell() {
+ }
+
+ void QtEmojiCell::handleEmojiClicked () {
+ emit emojiClicked(text());
+ }
+
+}
diff --git a/Swift/QtUI/QtEmojiCell.h b/Swift/QtUI/QtEmojiCell.h
new file mode 100644
index 0000000..62f989b
--- /dev/null
+++ b/Swift/QtUI/QtEmojiCell.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <QPushButton>
+#include <QString>
+
+#include <SwifTools/EmojiMapper.h>
+
+class QWidget;
+class QMouseEvent;
+
+namespace Swift {
+ class QtEmojiCell : public QPushButton {
+ Q_OBJECT
+ public:
+ QtEmojiCell(const QtEmojiCell& b);
+ QtEmojiCell(QString shortname, QString text, QWidget* parent = nullptr);
+ ~QtEmojiCell();
+ signals:
+ void emojiClicked(QString emojiAsText);
+
+ private slots:
+ void handleEmojiClicked();
+ };
+}
diff --git a/Swift/QtUI/QtEmojisGrid.cpp b/Swift/QtUI/QtEmojisGrid.cpp
new file mode 100644
index 0000000..eadc64f
--- /dev/null
+++ b/Swift/QtUI/QtEmojisGrid.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016-2017 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/QtEmojisGrid.h>
+
+#include <string>
+
+#include <QString>
+#include <QVector>
+
+#include <SwifTools/EmojiMapper.h>
+
+#include <Swift/QtUI/QtEmojiCell.h>
+#include <Swift/QtUI/QtRecentEmojisGrid.h>
+#include <Swift/QtUI/QtSwiftUtil.h>
+
+namespace Swift {
+QtEmojisGrid::QtEmojisGrid() {
+
+}
+
+QtEmojisGrid::QtEmojisGrid(QString categoryName) {
+ auto category = EmojiMapper::categoryNameToEmojis(Q2PSTRING(categoryName));
+
+ QVector<QString> categoryEmojis;
+
+ for (const auto& emoji : category) {
+ categoryEmojis.push_back(P2QSTRING(emoji));
+ }
+
+ setEmojis(categoryEmojis);
+ }
+
+ void QtEmojisGrid::setEmojis(const QVector<QString>& emojis) {
+ clearEmojis();
+
+ int iEmoji = 0;
+ for (const auto& unicodeEmoji : emojis) {
+ QString shortname = QString::fromStdString(EmojiMapper::unicodeToShortname(Q2PSTRING(unicodeEmoji)));
+ QtEmojiCell* emoji = new QtEmojiCell(shortname, unicodeEmoji);
+ this->addWidget(emoji, iEmoji/6, iEmoji%6);
+ connect(emoji, SIGNAL(emojiClicked(QString)), this, SIGNAL(onEmojiSelected(QString)));
+ iEmoji++;
+ }
+ for (int index = 0; index < columnCount(); index++) {
+ auto layoutItem = itemAtPosition(0, index);
+ if (layoutItem) {
+ auto cellWidget = layoutItem->widget();
+ if (cellWidget) {
+ setColumnMinimumWidth(index, cellWidget->width());
+ }
+ }
+ }
+ setSpacing(5);
+ }
+
+ void QtEmojisGrid::clearEmojis() {
+ QLayoutItem* child = nullptr;
+ while ((child = this->takeAt(0)) != 0) {
+ if (child->widget()) {
+ child->widget()->hide();
+ removeWidget(child->widget());
+ }
+ else {
+ removeItem(child);
+ }
+ }
+ }
+}
diff --git a/Swift/QtUI/QtEmojisGrid.h b/Swift/QtUI/QtEmojisGrid.h
new file mode 100644
index 0000000..e4bc664
--- /dev/null
+++ b/Swift/QtUI/QtEmojisGrid.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016-2017 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <QGridLayout>
+#include <QString>
+#include <QVector>
+
+#include <SwifTools/EmojiMapper.h>
+
+namespace Swift {
+ class QtEmojisGrid : public QGridLayout {
+ Q_OBJECT
+ public:
+ explicit QtEmojisGrid();
+ explicit QtEmojisGrid(QString categoryName);
+
+ protected:
+ void setEmojis(const QVector<QString>& emojis);
+
+ private:
+ void clearEmojis();
+
+ signals:
+ void onEmojiSelected(QString emoji);
+ };
+}
diff --git a/Swift/QtUI/QtEmojisScroll.cpp b/Swift/QtUI/QtEmojisScroll.cpp
new file mode 100644
index 0000000..3e9969b
--- /dev/null
+++ b/Swift/QtUI/QtEmojisScroll.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016-2017 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/QtEmojisScroll.h>
+
+#include <QLayout>
+#include <QScrollArea>
+#include <QStyle>
+
+#include <Swift/QtUI/QtEmojisGrid.h>
+#include <Swift/QtUI/QtRecentEmojisGrid.h>
+
+namespace Swift {
+ QtEmojisScroll::QtEmojisScroll(QGridLayout* emojiLayout, QWidget *parent) : QWidget(parent) {
+ auto selector = new QWidget();
+ auto scrollArea = new QScrollArea();
+ scrollArea->setWidgetResizable(true);
+ scrollArea->setWidget(selector);
+ // Set minimum width to fit GridLayout (no horizontal ScrollBar)
+ const int margin = style()->pixelMetric(QStyle::PM_MenuHMargin) * 2;
+ scrollArea->setMinimumWidth((emojiLayout->columnCount()+1)*(emojiLayout->columnMinimumWidth(0)+emojiLayout->spacing())+margin);
+ // Set height according to width (better ratio)
+ const double ratio = 16.0/9.0; //ratio width/height
+ scrollArea->setMinimumHeight(scrollArea->minimumWidth()/ratio);
+ selector->setLayout(emojiLayout);
+
+ this->setLayout(new QVBoxLayout);
+ this->layout()->addWidget(scrollArea);
+ this->layout()->setContentsMargins(0,0,0,0);
+ }
+}
diff --git a/Swift/QtUI/QtEmojisScroll.h b/Swift/QtUI/QtEmojisScroll.h
new file mode 100644
index 0000000..8ee9257
--- /dev/null
+++ b/Swift/QtUI/QtEmojisScroll.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2016-2017 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <QGridLayout>
+#include <QWidget>
+
+namespace Swift {
+ class QtEmojisScroll : public QWidget {
+ Q_OBJECT
+ public:
+ QtEmojisScroll(QGridLayout* emojiLayout, QWidget *parent = 0);
+ };
+}
diff --git a/Swift/QtUI/QtEmojisSelector.cpp b/Swift/QtUI/QtEmojisSelector.cpp
new file mode 100644
index 0000000..8b21380
--- /dev/null
+++ b/Swift/QtUI/QtEmojisSelector.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016-2017 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/QtEmojisSelector.h>
+
+#include <QScrollArea>
+#include <QSettings>
+#include <QString>
+#include <QWidget>
+
+#include <SwifTools/EmojiMapper.h>
+
+#include <Swift/QtUI/QtEmojisGrid.h>
+#include <Swift/QtUI/QtEmojisScroll.h>
+#include <Swift/QtUI/QtRecentEmojisGrid.h>
+#include <Swift/QtUI/QtSwiftUtil.h>
+
+namespace Swift {
+ QtEmojisSelector::QtEmojisSelector(QSettings* settings, QWidget* parent) : QTabWidget(parent), settings_(settings) {
+ recentEmojisGrid_ = addRecentTab();
+ connect(recentEmojisGrid_, SIGNAL(onEmojiSelected(QString)), this, SLOT(emojiClickedSlot(QString)));
+
+ for (const auto& category : EmojiMapper::getCategories()) {
+ if (category != "modifier") {
+ QtEmojisGrid* grid = addTab(P2QSTRING(category));
+ connect(grid, SIGNAL(onEmojiSelected(QString)), this, SLOT(emojiClickedSlot(QString)));
+ }
+ }
+
+ loadSettings();
+ }
+
+ QtEmojisSelector::~QtEmojisSelector() {
+ writeSettings();
+ }
+
+ QtRecentEmojisGrid* QtEmojisSelector::addRecentTab() {
+ QtRecentEmojisGrid* recent = new QtRecentEmojisGrid(settings_);
+ QtEmojisScroll* scroll = new QtEmojisScroll(recent);
+ QTabWidget::addTab(scroll, QString::fromStdString(EmojiMapper::categoryToFlagshipUnicodeEmoji("recent")));
+
+ setTabToolTip(count()-1, tr("Recent"));
+
+ return recent;
+ }
+
+ QtEmojisGrid* QtEmojisSelector::addTab(QString categoryName) {
+ QtEmojisGrid* grid = new QtEmojisGrid(categoryName);
+ QtEmojisScroll* scroll = new QtEmojisScroll(grid);
+ QTabWidget::addTab(scroll, QString::fromStdString(EmojiMapper::categoryToFlagshipUnicodeEmoji(Q2PSTRING(categoryName))));
+ setTabToolTip(count()-1, categoryName.replace(0, 1, categoryName[0].toUpper()));
+
+ return grid;
+ }
+
+ void QtEmojisSelector::loadSettings() {
+ if (settings_->contains("currentEmojiTab")) {
+ setCurrentIndex(settings_->value("currentEmojiTab").toInt());
+ } else {
+ setCurrentIndex(1); //index of people category
+ }
+ }
+
+ void QtEmojisSelector::writeSettings() {
+ settings_->setValue("currentEmojiTab", currentIndex());
+ }
+
+ void QtEmojisSelector::emojiClickedSlot(QString emoji) {
+ recentEmojisGrid_->handleEmojiClicked(emoji);
+ emit emojiClicked(emoji);
+ }
+}
diff --git a/Swift/QtUI/QtEmojisSelector.h b/Swift/QtUI/QtEmojisSelector.h
new file mode 100644
index 0000000..1065aa0
--- /dev/null
+++ b/Swift/QtUI/QtEmojisSelector.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016-2017 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <QSettings>
+#include <QTabWidget>
+
+#include <Swift/QtUI/QtEmojisGrid.h>
+#include <Swift/QtUI/QtRecentEmojisGrid.h>
+
+namespace Swift {
+
+class QtEmojisSelector : public QTabWidget {
+ Q_OBJECT
+ public:
+ QtEmojisSelector(QSettings* settings, QWidget * parent = 0);
+ ~QtEmojisSelector();
+
+ public slots:
+ void emojiClickedSlot(QString emoji);
+
+ signals:
+ void emojiClicked(QString emoji);
+
+ private:
+ QtRecentEmojisGrid* addRecentTab();
+ QtEmojisGrid* addTab(QString categoryName);
+ void loadSettings();
+ void writeSettings();
+
+ private:
+ QSettings* settings_ = nullptr;
+ QtRecentEmojisGrid* recentEmojisGrid_ = nullptr;
+};
+
+}
diff --git a/Swift/QtUI/QtEmoticonCell.cpp b/Swift/QtUI/QtEmoticonCell.cpp
deleted file mode 100644
index fe580aa..0000000
--- a/Swift/QtUI/QtEmoticonCell.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2015 Daniel Baczynski
- * Licensed under the Simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-/*
- * Copyright (c) 2016 Isode Limited.
- * All rights reserved.
- * See the COPYING file for more information.
- */
-
-#include <Swift/QtUI/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
deleted file mode 100644
index 669d1ed..0000000
--- a/Swift/QtUI/QtEmoticonCell.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2015 Daniel Baczynski
- * Licensed under the Simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-/*
- * Copyright (c) 2016 Isode Limited.
- * All rights reserved.
- * See the COPYING file 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 = nullptr);
- ~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
deleted file mode 100644
index 4c8c024..0000000
--- a/Swift/QtUI/QtEmoticonsGrid.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2015 Daniel Baczynski
- * Licensed under the Simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-/*
- * Copyright (c) 2016 Isode Limited.
- * All rights reserved.
- * See the COPYING file for more information.
- */
-
-#include <Swift/QtUI/QtEmoticonsGrid.h>
-
-#include <set>
-
-#include <boost/range/adaptor/reversed.hpp>
-
-#include <QPushButton>
-
-#include <Swift/QtUI/QtSwiftUtil.h>
-
-namespace Swift {
-
-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;
-
- for (auto&& 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;
- for (auto&& emoticon : boost::adaptors::reverse(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
deleted file mode 100644
index b3b8ac3..0000000
--- a/Swift/QtUI/QtEmoticonsGrid.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2015 Daniel Baczynski
- * Licensed under the Simplified BSD license.
- * See Documentation/Licenses/BSD-simplified.txt for more information.
- */
-
-/*
- * Copyright (c) 2016 Isode Limited.
- * All rights reserved.
- * See the COPYING file 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 = nullptr);
- 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/QtRecentEmojisGrid.cpp b/Swift/QtUI/QtRecentEmojisGrid.cpp
new file mode 100644
index 0000000..54cca76
--- /dev/null
+++ b/Swift/QtUI/QtRecentEmojisGrid.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016-2017 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/QtRecentEmojisGrid.h>
+
+#include <algorithm>
+
+#include <QSettings>
+#include <QVector>
+
+#include <SwifTools/EmojiMapper.h>
+
+#include <Swift/QtUI/QtEmojiCell.h>
+#include <Swift/QtUI/QtSwiftUtil.h>
+
+namespace Swift {
+ const int QtRecentEmojisGrid::MAX_RECENTS = 50;
+
+ QtRecentEmojisGrid::QtRecentEmojisGrid(QSettings* settings) : QtEmojisGrid(), settings_(settings) {
+ loadSettings();
+ connect(this, SIGNAL(onEmojiSelected(QString)), this, SLOT(handleEmojiClicked(QString)));
+ refresh();
+ }
+
+ QtRecentEmojisGrid::~QtRecentEmojisGrid() {
+ writeSettings();
+ }
+
+ void QtRecentEmojisGrid::handleEmojiClicked(QString emoji) {
+ recents_.erase(std::remove(recents_.begin(), recents_.end(), emoji), recents_.end());
+
+ if (recents_.size() > MAX_RECENTS) {
+ recents_.resize(MAX_RECENTS - 1);
+ }
+
+ recents_.push_front(emoji);
+ refresh();
+ }
+
+ void QtRecentEmojisGrid::refresh() {
+ QtEmojisGrid::setEmojis(recents_);
+ }
+
+ void QtRecentEmojisGrid::loadSettings() {
+ QByteArray readData = settings_->value("recentEmojis").toByteArray();
+ QDataStream readStream(&readData, QIODevice::ReadOnly);
+ readStream >> recents_;
+ }
+
+ void QtRecentEmojisGrid::writeSettings() {
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly);
+ stream << recents_;
+ settings_->setValue("recentEmojis", data);
+ }
+}
diff --git a/Swift/QtUI/QtRecentEmojisGrid.h b/Swift/QtUI/QtRecentEmojisGrid.h
new file mode 100644
index 0000000..6201b26
--- /dev/null
+++ b/Swift/QtUI/QtRecentEmojisGrid.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016-2017 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <QGridLayout>
+#include <QSettings>
+#include <QSize>
+#include <QString>
+#include <QVector>
+
+#include <SwifTools/EmojiMapper.h>
+
+#include <Swift/QtUI/QtEmojisGrid.h>
+
+namespace Swift {
+ class QtRecentEmojisGrid : public QtEmojisGrid {
+ Q_OBJECT
+ public:
+ explicit QtRecentEmojisGrid(QSettings* settings);
+ ~QtRecentEmojisGrid();
+
+ public slots:
+ void handleEmojiClicked(QString emoji);
+
+ private:
+ void refresh();
+ void loadSettings();
+ void writeSettings();
+
+ private:
+ static const int MAX_RECENTS;
+
+ private:
+ QVector<QString> recents_;
+ QSettings* settings_;
+ };
+}
diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp
index 3f6ce8e..ee21c4f 100644
--- a/Swift/QtUI/QtSwift.cpp
+++ b/Swift/QtUI/QtSwift.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2017 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -29,6 +29,7 @@
#include <SwifTools/Application/PlatformApplicationPathProvider.h>
#include <SwifTools/AutoUpdater/AutoUpdater.h>
#include <SwifTools/AutoUpdater/PlatformAutoUpdaterFactory.h>
+#include <SwifTools/EmojiMapper.h>
#include <Swift/Controllers/ApplicationInfo.h>
#include <Swift/Controllers/BuildVersion.h>
@@ -228,7 +229,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_, ":/themes/Default/", emoticons);
+ chatWindowFactory_ = new QtChatWindowFactory(splitter_, settingsHierachy_, qtSettings_, tabs_, ":/themes/Default/");
soundPlayer_ = new QtSoundPlayer(applicationPathProvider_);
// Ugly, because the dock depends on the tray, but the temporary
@@ -324,6 +325,7 @@ QtSwift::~QtSwift() {
delete tray;
}
delete tabs_;
+ delete chatWindowFactory_;
delete splitter_;
delete settingsHierachy_;
delete qtSettings_;
@@ -332,7 +334,6 @@ QtSwift::~QtSwift() {
delete uriHandler_;
delete dock_;
delete soundPlayer_;
- delete chatWindowFactory_;
delete certificateStorageFactory_;
delete storagesFactory_;
delete applicationPathProvider_;
diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript
index 88cb1ac..99759f4 100644
--- a/Swift/QtUI/SConscript
+++ b/Swift/QtUI/SConscript
@@ -136,8 +136,11 @@ sources = [
"QtBookmarkDetailWindow.cpp",
"QtAddBookmarkWindow.cpp",
"QtEditBookmarkWindow.cpp",
- "QtEmoticonsGrid.cpp",
- "QtEmoticonCell.cpp",
+ "QtEmojisGrid.cpp",
+ "QtEmojiCell.cpp",
+ "QtEmojisScroll.cpp",
+ "QtEmojisSelector.cpp",
+ "QtRecentEmojisGrid.cpp",
"QtContactEditWindow.cpp",
"QtContactEditWidget.cpp",
"QtSingleWindow.cpp",