diff options
Diffstat (limited to 'Swift')
-rw-r--r-- | Swift/QtUI/QtChatWindow.cpp | 51 | ||||
-rw-r--r-- | Swift/QtUI/QtChatWindow.h | 19 | ||||
-rw-r--r-- | Swift/QtUI/QtChatWindowFactory.cpp | 10 | ||||
-rw-r--r-- | Swift/QtUI/QtChatWindowFactory.h | 14 | ||||
-rw-r--r-- | Swift/QtUI/QtEmojiCell.cpp | 41 | ||||
-rw-r--r-- | Swift/QtUI/QtEmojiCell.h | 30 | ||||
-rw-r--r-- | Swift/QtUI/QtEmojisGrid.cpp | 72 | ||||
-rw-r--r-- | Swift/QtUI/QtEmojisGrid.h | 31 | ||||
-rw-r--r-- | Swift/QtUI/QtEmojisScroll.cpp | 34 | ||||
-rw-r--r-- | Swift/QtUI/QtEmojisScroll.h | 18 | ||||
-rw-r--r-- | Swift/QtUI/QtEmojisSelector.cpp | 75 | ||||
-rw-r--r-- | Swift/QtUI/QtEmojisSelector.h | 40 | ||||
-rw-r--r-- | Swift/QtUI/QtEmoticonCell.cpp | 36 | ||||
-rw-r--r-- | Swift/QtUI/QtEmoticonCell.h | 40 | ||||
-rw-r--r-- | Swift/QtUI/QtEmoticonsGrid.cpp | 63 | ||||
-rw-r--r-- | Swift/QtUI/QtEmoticonsGrid.h | 46 | ||||
-rw-r--r-- | Swift/QtUI/QtRecentEmojisGrid.cpp | 59 | ||||
-rw-r--r-- | Swift/QtUI/QtRecentEmojisGrid.h | 43 | ||||
-rw-r--r-- | Swift/QtUI/QtSwift.cpp | 7 | ||||
-rw-r--r-- | Swift/QtUI/SConscript | 7 |
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", |