diff options
-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", |