Fix hover handling in the timeline

pull/476/head
Nicolas Werner 4 years ago
parent 0d61f4bff1
commit d43607d01c
  1. 2
      CMakeLists.txt
  2. 4
      README.md
  3. 5
      resources/qml/Avatar.qml
  4. 9
      resources/qml/EncryptionIndicator.qml
  5. 4
      resources/qml/ImageButton.qml
  6. 8
      resources/qml/MatrixText.qml
  7. 13
      resources/qml/MessageView.qml
  8. 38
      resources/qml/TimelineRow.qml
  9. 12
      resources/qml/delegates/FileMessage.qml
  10. 16
      resources/qml/delegates/ImageMessage.qml
  11. 11
      resources/qml/delegates/PlayableMediaMessage.qml
  12. 16
      resources/qml/delegates/Reply.qml
  13. 1
      resources/qml/delegates/TextMessage.qml
  14. 4
      src/timeline/TimelineViewManager.cpp
  15. 25
      src/ui/NhekoCursorShape.cpp
  16. 26
      src/ui/NhekoCursorShape.h

@ -281,6 +281,7 @@ set(SRC_FILES
src/ui/InfoMessage.cpp
src/ui/Label.cpp
src/ui/LoadingIndicator.cpp
src/ui/NhekoCursorShape.cpp
src/ui/NhekoDropArea.cpp
src/ui/OverlayModal.cpp
src/ui/OverlayWidget.cpp
@ -495,6 +496,7 @@ qt5_wrap_cpp(MOC_HEADERS
src/ui/Label.h
src/ui/FloatingButton.h
src/ui/Menu.h
src/ui/NhekoCursorShape.h
src/ui/NhekoDropArea.h
src/ui/OverlayWidget.h
src/ui/SnackBar.h

@ -116,9 +116,7 @@ brew install --cask nheko
### Build Requirements
- Qt5 (5.10 or greater). Qt 5.7 adds support for color font rendering with
Freetype, which is essential to properly support emoji, 5.8 adds some features
to make interopability with Qml easier, 5.10 makes sliders actually visible with different palettes.
- Qt5 (5.12 or greater). Required for overlapping hover handlers in Qml.
- CMake 3.15 or greater. (Lower version may work, but may break boost linking)
- [mtxclient](https://github.com/Nheko-Reborn/mtxclient)
- [LMDB](https://symas.com/lightning-memory-mapped-database/)

@ -90,4 +90,9 @@ Rectangle {
}
}
CursorShape {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
}
}

@ -1,4 +1,4 @@
import QtQuick 2.5
import QtQuick 2.12
import QtQuick.Controls 2.1
import im.nheko 1.0
@ -24,14 +24,11 @@ Rectangle {
color: "transparent"
width: 16
height: 16
ToolTip.visible: ma.containsMouse && indicator.visible
ToolTip.visible: ma.hovered && indicator.visible
ToolTip.text: getEncryptionTooltip()
MouseArea {
HoverHandler {
id: ma
anchors.fill: parent
hoverEnabled: true
}
Image {

@ -1,6 +1,7 @@
import "./ui"
import QtQuick 2.3
import QtQuick.Controls 2.3
import im.nheko 1.0 // for cursor shape
AbstractButton {
id: button
@ -23,11 +24,10 @@ AbstractButton {
source: image != "" ? ("image://colorimage/" + image + "?" + ((button.hovered && changeColorOnHover) ? highlightColor : buttonTextColor)) : ""
}
MouseArea {
CursorShape {
id: mouseArea
anchors.fill: parent
onPressed: mouse.accepted = false
cursorShape: Qt.PointingHandCursor
}

@ -8,6 +8,7 @@ TextEdit {
focus: false
wrapMode: Text.Wrap
selectByMouse: !Settings.mobileMode
enabled: selectByMouse
color: colors.text
onLinkActivated: {
if (/^https:\/\/matrix.to\/#\/(@.*)$/.test(link)) {
@ -25,12 +26,9 @@ TextEdit {
ToolTip.visible: hoveredLink
ToolTip.text: hoveredLink
MouseArea {
id: ma
CursorShape {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
cursorShape: hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}

@ -1,6 +1,6 @@
import "./delegates"
import QtGraphicalEffects 1.0
import QtQuick 2.9
import QtQuick 2.12
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
@ -153,12 +153,15 @@ ScrollView {
color: TimelineManager.userColor(modelData ? modelData.userId : "", colors.window)
textFormat: Text.RichText
MouseArea {
TapHandler {
//cursorShape: Qt.PointingHandCursor
onSingleTapped: chat.model.openUserProfile(modelData.userId)
}
CursorShape {
anchors.fill: parent
Layout.alignment: Qt.AlignHCenter
onClicked: chat.model.openUserProfile(modelData.userId)
cursorShape: Qt.PointingHandCursor
propagateComposedEvents: true
}
}

@ -1,6 +1,6 @@
import "./delegates"
import "./emoji"
import QtQuick 2.6
import QtQuick 2.12
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
@ -12,27 +12,23 @@ Item {
height: row.height
Rectangle {
color: (Settings.messageHoverHighlight && hoverHandler.containsMouse) ? colors.alternateBase : "transparent"
color: (Settings.messageHoverHighlight && hoverHandler.hovered) ? colors.alternateBase : "transparent"
anchors.fill: row
}
MouseArea {
HoverHandler {
id: hoverHandler
anchors.fill: parent
propagateComposedEvents: true
preventStealing: false
hoverEnabled: true
acceptedButtons: Qt.AllButtons
onClicked: {
if (mouse.button === Qt.RightButton)
messageContextMenu.show(model.id, model.type, model.isEncrypted, model.isEditable, row);
else
mouse.accepted = false;
}
onPressAndHold: {
messageContextMenu.show(model.id, model.type, model.isEncrypted, model.isEditable, row, mapToItem(timelineRoot, mouse.x, mouse.y));
}
acceptedDevices: PointerDevice.GenericPointer
}
TapHandler {
acceptedButtons: Qt.RightButton
onSingleTapped: messageContextMenu.show(model.id, model.type, model.isEncrypted, model.isEditable, row, mapToItem(timelineRoot, eventPoint.position.x, eventPoint.position.y))
}
TapHandler {
onLongPressed: messageContextMenu.show(model.id, model.type, model.isEncrypted, model.isEditable, row, mapToItem(timelineRoot, point.position.x, point.position.y))
}
RowLayout {
@ -151,15 +147,11 @@ Item {
text: model.timestamp.toLocaleTimeString("HH:mm")
width: Math.max(implicitWidth, text.length * fontMetrics.maximumCharacterWidth)
color: inactiveColors.text
ToolTip.visible: ma.containsMouse
ToolTip.visible: ma.hovered
ToolTip.text: Qt.formatDateTime(model.timestamp, Qt.DefaultLocaleLongDate)
MouseArea {
HoverHandler {
id: ma
anchors.fill: parent
hoverEnabled: true
propagateComposedEvents: true
}
}

@ -1,4 +1,4 @@
import QtQuick 2.6
import QtQuick 2.12
import QtQuick.Layouts 1.2
import im.nheko 1.0
@ -31,7 +31,15 @@ Item {
MouseArea {
anchors.fill: parent
onClicked: TimelineManager.timeline.saveMedia(model.data.id)
cursorShape: Qt.PointingHandCursor
}
TapHandler {
onSingleTapped: TimelineManager.timeline.saveMedia(model.data.id)
}
CursorShape {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
}

@ -1,4 +1,4 @@
import QtQuick 2.6
import QtQuick 2.12
import im.nheko 1.0
Item {
@ -32,20 +32,20 @@ Item {
smooth: true
mipmap: true
MouseArea {
id: mouseArea
TapHandler {
enabled: model.data.type == MtxEvent.ImageMessage && img.status == Image.Ready
hoverEnabled: true
anchors.fill: parent
onClicked: TimelineManager.openImageOverlay(model.data.url, model.data.id)
onSingleTapped: TimelineManager.openImageOverlay(model.data.url, model.data.id)
}
HoverHandler {
id: mouseArea
}
Item {
id: overlay
anchors.fill: parent
visible: mouseArea.containsMouse
visible: mouseArea.hovered
Rectangle {
id: container

@ -1,5 +1,5 @@
import QtMultimedia 5.6
import QtQuick 2.6
import QtQuick 2.12
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.2
import im.nheko 1.0
@ -140,9 +140,8 @@ Rectangle {
fillMode: Image.Pad
}
MouseArea {
anchors.fill: parent
onClicked: {
TapHandler {
onSingleTapped: {
switch (button.state) {
case "":
TimelineManager.timeline.cacheMedia(model.data.id);
@ -159,6 +158,10 @@ Rectangle {
break;
}
}
}
CursorShape {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
}

@ -1,4 +1,4 @@
import QtQuick 2.6
import QtQuick 2.12
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
@ -13,10 +13,12 @@ Item {
width: parent.width
height: replyContainer.height
MouseArea {
TapHandler {
onSingleTapped: chat.positionViewAtIndex(chat.model.idToIndex(modelData.id), ListView.Contain)
}
CursorShape {
anchors.fill: parent
preventStealing: false
onClicked: chat.positionViewAtIndex(chat.model.idToIndex(modelData.id), ListView.Contain)
cursorShape: Qt.PointingHandCursor
}
@ -43,10 +45,8 @@ Item {
color: replyComponent.userColor
textFormat: Text.RichText
MouseArea {
anchors.fill: parent
onClicked: chat.model.openUserProfile(reply.modelData.userId)
cursorShape: Qt.PointingHandCursor
TapHandler {
onSingleTapped: chat.model.openUserProfile(reply.modelData.userId)
}
}

@ -8,5 +8,6 @@ MatrixText {
width: parent ? parent.width : undefined
height: isReply ? Math.round(Math.min(timelineRoot.height / 8, implicitHeight)) : undefined
clip: isReply
selectByMouse: !Settings.mobileMode && !isReply
font.pointSize: (Settings.enlargeEmojiOnlyMessages && model.data.isOnlyEmoji > 0 && model.data.isOnlyEmoji < 4) ? Settings.fontSize * 3 : Settings.fontSize
}

@ -21,6 +21,7 @@
#include "dialogs/ImageOverlay.h"
#include "emoji/EmojiModel.h"
#include "emoji/Provider.h"
#include "ui/NhekoCursorShape.h"
#include "ui/NhekoDropArea.h"
#include <iostream> //only for debugging
@ -118,6 +119,7 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par
qmlRegisterType<DelegateChoice>("im.nheko", 1, 0, "DelegateChoice");
qmlRegisterType<DelegateChooser>("im.nheko", 1, 0, "DelegateChooser");
qmlRegisterType<NhekoDropArea>("im.nheko", 1, 0, "NhekoDropArea");
qmlRegisterType<NhekoCursorShape>("im.nheko", 1, 0, "CursorShape");
qmlRegisterUncreatableType<DeviceVerificationFlow>(
"im.nheko", 1, 0, "DeviceVerificationFlow", "Can't create verification flow from QML!");
qmlRegisterUncreatableType<UserProfile>(
@ -548,4 +550,4 @@ void
TimelineViewManager::focusMessageInput()
{
emit focusInput();
}
}

@ -0,0 +1,25 @@
#include "NhekoCursorShape.h"
#include <QCursor>
NhekoCursorShape::NhekoCursorShape(QQuickItem *parent)
: QQuickItem(parent)
, currentShape_(Qt::CursorShape::ArrowCursor)
{}
Qt::CursorShape
NhekoCursorShape::cursorShape() const
{
return cursor().shape();
}
void
NhekoCursorShape::setCursorShape(Qt::CursorShape cursorShape)
{
if (currentShape_ == cursorShape)
return;
currentShape_ = cursorShape;
setCursor(cursorShape);
emit cursorShapeChanged();
}

@ -0,0 +1,26 @@
#pragma once
// see
// https://stackoverflow.com/questions/27821054/how-to-change-cursor-shape-in-qml-when-mousearea-is-covered-with-another-mousear/29382092#29382092
#include <QQuickItem>
class NhekoCursorShape : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape NOTIFY
cursorShapeChanged)
public:
explicit NhekoCursorShape(QQuickItem *parent = 0);
private:
Qt::CursorShape cursorShape() const;
void setCursorShape(Qt::CursorShape cursorShape);
Qt::CursorShape currentShape_;
signals:
void cursorShapeChanged();
};
Loading…
Cancel
Save