diff options
author | Tobias Markmann <tm@ayena.de> | 2016-04-15 17:03:02 (GMT) |
---|---|---|
committer | Kevin Smith <kevin.smith@isode.com> | 2016-04-25 08:38:46 (GMT) |
commit | ef341e4762b1017047555c37dac1dfdc6ba2489d (patch) | |
tree | e4b3454c3f7b0fd3523269f193c8402c0bf30c4c | |
parent | 511c43aec78279ecaa6008bd7f4f08159d3a5c00 (diff) | |
download | swift-ef341e4762b1017047555c37dac1dfdc6ba2489d.zip swift-ef341e4762b1017047555c37dac1dfdc6ba2489d.tar.bz2 |
Fix detection of vertical scroll bar position in chat views
Chat views are expected to remember the scroll position.
If the user scrolled all the way down, the view should keep
scrolled all the way down, even if the windows is resized,
new messages are added or the user enters a multi line message
in the message input box.
Qt WebKit only provides reliable scroll position updates in
their web environment. This requires to have scroll changes
call a JS hook that calls our C++ signal.
Test-Information:
Tested and verified the following cases for correct behavior:
* entering a multi line message keeping the view scrolled down
* resizing the window and keeping it scrolled down
* receiving messages and the view keeps being scrolled down
* verified that view does not scroll down if it is not yet on
resize of the window, entering multi line messages, and
receiving new messages
Change-Id: I579a07d0b073c34e7a46b0fde1bc09f3da08d5da
-rw-r--r-- | Swift/QtUI/QtChatWindowJSBridge.h | 1 | ||||
-rw-r--r-- | Swift/QtUI/QtWebKitChatView.cpp | 51 | ||||
-rw-r--r-- | Swift/QtUI/QtWebKitChatView.h | 5 |
3 files changed, 34 insertions, 23 deletions
diff --git a/Swift/QtUI/QtChatWindowJSBridge.h b/Swift/QtUI/QtChatWindowJSBridge.h index bedf6a4..553e929 100644 --- a/Swift/QtUI/QtChatWindowJSBridge.h +++ b/Swift/QtUI/QtChatWindowJSBridge.h @@ -27,6 +27,7 @@ public: virtual ~QtChatWindowJSBridge(); signals: void buttonClicked(QString id, QString arg1, QString arg2, QString arg3, QString arg4, QString arg5); + void verticalScrollBarPositionChanged(double scrollbarPosition); }; } diff --git a/Swift/QtUI/QtWebKitChatView.cpp b/Swift/QtUI/QtWebKitChatView.cpp index 46e8763..aec8589 100644 --- a/Swift/QtUI/QtWebKitChatView.cpp +++ b/Swift/QtUI/QtWebKitChatView.cpp @@ -84,7 +84,6 @@ QtWebKitChatView::QtWebKitChatView(QtChatWindow* window, UIEventStream* eventStr } webView_->setPage(webPage_); connect(webPage_, SIGNAL(selectionChanged()), SLOT(copySelectionToClipboard())); - connect(webPage_, SIGNAL(scrollRequested(int, int, const QRect&)), SLOT(handleScrollRequested(int, int, const QRect&))); viewReady_ = false; isAtBottom_ = true; @@ -93,7 +92,7 @@ QtWebKitChatView::QtWebKitChatView(QtChatWindow* window, UIEventStream* eventStr jsBridge = new QtChatWindowJSBridge(); addToJSEnvironment("chatwindow", jsBridge); connect(jsBridge, SIGNAL(buttonClicked(QString,QString,QString,QString,QString,QString)), this, SLOT(handleHTMLButtonClicked(QString,QString,QString,QString,QString,QString))); - + connect(jsBridge, SIGNAL(verticalScrollBarPositionChanged(double)), this, SLOT(handleVerticalScrollBarPositionChanged(double))); } QtWebKitChatView::~QtWebKitChatView() { @@ -253,7 +252,9 @@ void QtWebKitChatView::displayReceiptInfo(const QString& id, bool showIt) { } void QtWebKitChatView::rememberScrolledToBottom() { - isAtBottom_ = webPage_->mainFrame()->scrollBarValue(Qt::Vertical) >= (webPage_->mainFrame()->scrollBarMaximum(Qt::Vertical) - 1); + if (webPage_) { + isAtBottom_ = webPage_->mainFrame()->scrollBarValue(Qt::Vertical) >= (webPage_->mainFrame()->scrollBarMaximum(Qt::Vertical) - 1); + } } void QtWebKitChatView::scrollToBottom() { @@ -339,6 +340,11 @@ void QtWebKitChatView::resetView() { scrollToBottom(); connect(webPage_->mainFrame(), SIGNAL(contentsSizeChanged(const QSize&)), this, SLOT(handleFrameSizeChanged()), Qt::UniqueConnection); + + // Hooking up to scroll bar update, because Qt does not provide a way to retrieve accurate scroll bar updates from C++ directly. + QWebElement body = document_.findFirst("body"); + assert(!body.isNull()); + body.setAttribute("onscroll", "chatwindow.verticalScrollBarPositionChanged(document.body.scrollTop / (document.body.scrollHeight - window.innerHeight))"); } static QWebElement findElementWithID(QWebElement document, QString elementName, QString id) { @@ -446,20 +452,6 @@ void QtWebKitChatView::askDesktopToOpenFile(const QString& filename) { } } -void QtWebKitChatView::handleScrollRequested(int, int dy, const QRect&) { - rememberScrolledToBottom(); - - int pos = webPage_->mainFrame()->scrollBarValue(Qt::Vertical) - dy; - emit scrollRequested(pos); - - if (pos == 0) { - emit scrollReachedTop(); - } - else if (pos == webPage_->mainFrame()->scrollBarMaximum(Qt::Vertical)) { - emit scrollReachedBottom(); - } -} - int QtWebKitChatView::getSnippetPositionByDate(const QDate& date) { QWebElement message = webPage_->mainFrame()->documentElement().findFirst(".date" + date.toString(Qt::ISODate)); @@ -590,6 +582,16 @@ QString QtWebKitChatView::buildChatWindowButton(const QString& name, const QStri return html; } +void QtWebKitChatView::resizeEvent(QResizeEvent* event) { + // This code ensures that if the user is scrolled all to the bottom of a chat view, + // the view stays scrolled to the bottom if the view is resized or if the message + // input widget becomes multi line. + if (isAtBottom_) { + scrollToBottom(); + } + QWidget::resizeEvent(event); +} + std::string QtWebKitChatView::addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes, const std::string& description) { SWIFT_LOG(debug) << "addFileTransfer" << std::endl; QString ft_id = QString("ft%1").arg(P2QSTRING(boost::lexical_cast<std::string>(idCounter_++))); @@ -788,6 +790,16 @@ void QtWebKitChatView::handleHTMLButtonClicked(QString id, QString encodedArgume } } +void QtWebKitChatView::handleVerticalScrollBarPositionChanged(double position) { + rememberScrolledToBottom(); + if (position == 0) { + emit scrollReachedTop(); + } + else if (position == 1) { + emit scrollReachedBottom(); + } +} + void QtWebKitChatView::addErrorMessage(const ChatWindow::ChatMessage& errorMessage) { if (window_->isWidgetSelected()) { window_->onAllMessagesRead(); @@ -968,9 +980,4 @@ ChatSnippet::Direction QtWebKitChatView::getActualDirection(const ChatWindow::Ch } } -// void QtWebKitChatView::setShowEmoticons(bool value) { -// showEmoticons_ = value; -// } - - } diff --git a/Swift/QtUI/QtWebKitChatView.h b/Swift/QtUI/QtWebKitChatView.h index 31bf8a5..098c1ac 100644 --- a/Swift/QtUI/QtWebKitChatView.h +++ b/Swift/QtUI/QtWebKitChatView.h @@ -124,8 +124,8 @@ namespace Swift { void handleViewLoadFinished(bool); void handleFrameSizeChanged(); void handleClearRequested(); - void handleScrollRequested(int dx, int dy, const QRect& rectToScroll); void handleHTMLButtonClicked(QString id, QString arg1, QString arg2, QString arg3, QString arg4, QString arg5); + void handleVerticalScrollBarPositionChanged(double position); private: enum PreviousMessageKind { @@ -159,6 +159,9 @@ namespace Swift { QString chatMessageToHTML(const ChatWindow::ChatMessage& message); static QString buildChatWindowButton(const QString& name, const QString& id, const QString& arg1 = QString(), const QString& arg2 = QString(), const QString& arg3 = QString(), const QString& arg4 = QString(), const QString& arg5 = QString()); + protected: + void resizeEvent(QResizeEvent* event) SWIFTEN_OVERRIDE; + private: void headerEncode(); void messageEncode(); |