matrixion/resources/qml/emoji/EmojiPicker.qml

337 lines
11 KiB
QML
Raw Normal View History

2021-03-05 02:35:15 +03:00
// SPDX-FileCopyrightText: 2021 Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later
2020-10-08 22:11:21 +03:00
import "../"
import QtGraphicalEffects 1.0
import QtQuick 2.9
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import im.nheko 1.0
import im.nheko.EmojiModel 1.0
Popup {
2020-10-08 22:11:21 +03:00
id: emojiPopup
2020-07-20 01:42:48 +03:00
2020-11-16 20:41:29 +03:00
property var callback
property var colors
property alias model: gridView.model
property var textArea
property string emojiCategory: "people"
property real highlightHue: colors.highlight.hslHue
property real highlightSat: colors.highlight.hslSaturation
property real highlightLight: colors.highlight.hslLightness
2020-11-16 20:41:29 +03:00
function show(showAt, callback) {
console.debug("Showing emojiPicker");
2020-10-08 22:11:21 +03:00
if (showAt) {
parent = showAt;
x = Math.round((showAt.width - width) / 2);
y = showAt.height;
}
2020-11-16 20:41:29 +03:00
emojiPopup.callback = callback;
2020-10-08 22:11:21 +03:00
open();
}
margins: 0
2020-05-14 03:19:15 +03:00
bottomPadding: 1
leftPadding: 1
rightPadding: 1
modal: true
focus: true
2020-05-14 03:19:15 +03:00
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
ColumnLayout {
2020-05-14 03:19:15 +03:00
id: columnView
2020-10-08 22:11:21 +03:00
anchors.fill: parent
2020-05-14 03:19:15 +03:00
spacing: 0
Layout.bottomMargin: 0
Layout.leftMargin: 3
Layout.rightMargin: 3
Layout.topMargin: 2
// emoji grid
GridView {
id: gridView
2020-05-14 03:19:15 +03:00
Layout.preferredHeight: emojiPopup.height
Layout.fillWidth: true
Layout.fillHeight: true
2020-05-14 03:19:15 +03:00
Layout.leftMargin: 4
cellWidth: 52
cellHeight: 52
2020-06-10 03:47:21 +03:00
boundsBehavior: Flickable.StopAtBounds
clip: true
2020-10-12 23:05:55 +03:00
currentIndex: -1 // prevent sorting from stealing focus
// Individual emoji
delegate: AbstractButton {
width: 48
height: 48
2020-10-08 22:11:21 +03:00
hoverEnabled: true
ToolTip.text: model.shortName
ToolTip.visible: hovered
// TODO: maybe add favorites at some point?
onClicked: {
2020-11-16 20:41:29 +03:00
console.debug("Picked " + model.unicode);
2020-10-08 22:11:21 +03:00
emojiPopup.close();
2020-11-16 20:41:29 +03:00
callback(model.unicode);
2020-10-08 22:11:21 +03:00
}
// give the emoji a little oomf
DropShadow {
width: parent.width
height: parent.height
horizontalOffset: 3
verticalOffset: 3
radius: 8
samples: 17
color: "#80000000"
source: parent.contentItem
}
contentItem: Text {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
2020-06-24 17:24:22 +03:00
font.family: Settings.emojiFont
2020-05-14 03:19:15 +03:00
font.pixelSize: 36
text: model.unicode
}
background: Rectangle {
anchors.fill: parent
color: hovered ? colors.highlight : 'transparent'
radius: 5
}
}
2020-05-14 03:19:15 +03:00
// Search field
header: TextField {
id: emojiSearch
2020-10-08 22:11:21 +03:00
2020-05-14 03:19:15 +03:00
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: emojiScroll.width + 4
placeholderText: qsTr("Search")
selectByMouse: true
rightPadding: clearSearch.width
2020-10-08 22:11:21 +03:00
onTextChanged: searchTimer.restart()
onVisibleChanged: {
if (visible)
forceActiveFocus();
}
2020-05-14 03:19:15 +03:00
Timer {
id: searchTimer
2020-10-08 22:11:21 +03:00
2020-05-14 03:19:15 +03:00
interval: 350 // tweak as needed?
onTriggered: {
2020-10-08 22:11:21 +03:00
emojiPopup.model.filter = emojiSearch.text;
2021-01-23 04:07:23 +03:00
emojiPopup.model.category = Emoji.Category.Search;
2020-05-14 03:19:15 +03:00
}
}
ToolButton {
id: clearSearch
2020-10-08 22:11:21 +03:00
visible: emojiSearch.text !== ''
icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.png?" + (clearSearch.hovered ? colors.highlight : colors.buttonText)
focusPolicy: Qt.NoFocus
onClicked: emojiSearch.clear()
2020-05-14 03:19:15 +03:00
anchors {
verticalCenter: parent.verticalCenter
right: parent.right
}
// clear the default hover effects.
2020-10-08 22:11:21 +03:00
background: Item {
}
2020-05-14 03:19:15 +03:00
}
}
2020-10-08 22:11:21 +03:00
ScrollBar.vertical: ScrollBar {
id: emojiScroll
}
}
// Separator
Rectangle {
Layout.fillWidth: true
2020-05-14 03:19:15 +03:00
Layout.preferredHeight: 1
2020-10-26 15:50:44 +03:00
color: emojiPopup.colors.alternateBase
}
// Category picker row
2020-05-14 03:19:15 +03:00
RowLayout {
Layout.bottomMargin: 0
Layout.preferredHeight: 42
implicitHeight: 42
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
2020-10-08 22:11:21 +03:00
2020-05-14 03:19:15 +03:00
// Display the normal categories
Repeater {
2020-10-08 22:11:21 +03:00
model: ListModel {
// TODO: Would like to get 'simple' icons for the categories
2020-10-08 22:11:21 +03:00
ListElement {
image: ":/icons/icons/emoji-categories/people.png"
2021-01-23 04:07:23 +03:00
category: Emoji.Category.People
2020-10-08 22:11:21 +03:00
}
ListElement {
image: ":/icons/icons/emoji-categories/nature.png"
2021-01-23 04:07:23 +03:00
category: Emoji.Category.Nature
2020-10-08 22:11:21 +03:00
}
ListElement {
image: ":/icons/icons/emoji-categories/foods.png"
2021-01-23 04:07:23 +03:00
category: Emoji.Category.Food
2020-10-08 22:11:21 +03:00
}
ListElement {
image: ":/icons/icons/emoji-categories/activity.png"
2021-01-23 04:07:23 +03:00
category: Emoji.Category.Activity
2020-10-08 22:11:21 +03:00
}
ListElement {
image: ":/icons/icons/emoji-categories/travel.png"
2021-01-23 04:07:23 +03:00
category: Emoji.Category.Travel
2020-10-08 22:11:21 +03:00
}
ListElement {
image: ":/icons/icons/emoji-categories/objects.png"
2021-01-23 04:07:23 +03:00
category: Emoji.Category.Objects
2020-10-08 22:11:21 +03:00
}
ListElement {
image: ":/icons/icons/emoji-categories/symbols.png"
2021-01-23 04:07:23 +03:00
category: Emoji.Category.Symbols
2020-10-08 22:11:21 +03:00
}
ListElement {
image: ":/icons/icons/emoji-categories/flags.png"
2021-01-23 04:07:23 +03:00
category: Emoji.Category.Flags
2020-10-08 22:11:21 +03:00
}
}
delegate: AbstractButton {
2020-05-14 03:19:15 +03:00
Layout.preferredWidth: 36
Layout.preferredHeight: 36
2020-10-08 22:11:21 +03:00
hoverEnabled: true
ToolTip.text: {
switch (model.category) {
2021-01-23 04:07:23 +03:00
case Emoji.Category.People:
2020-10-08 22:11:21 +03:00
return qsTr('People');
2021-01-23 04:07:23 +03:00
case Emoji.Category.Nature:
2020-10-08 22:11:21 +03:00
return qsTr('Nature');
2021-01-23 04:07:23 +03:00
case Emoji.Category.Food:
2020-10-08 22:11:21 +03:00
return qsTr('Food');
2021-01-23 04:07:23 +03:00
case Emoji.Category.Activity:
2020-10-08 22:11:21 +03:00
return qsTr('Activity');
2021-01-23 04:07:23 +03:00
case Emoji.Category.Travel:
2020-10-08 22:11:21 +03:00
return qsTr('Travel');
2021-01-23 04:07:23 +03:00
case Emoji.Category.Objects:
2020-10-08 22:11:21 +03:00
return qsTr('Objects');
2021-01-23 04:07:23 +03:00
case Emoji.Category.Symbols:
2020-10-08 22:11:21 +03:00
return qsTr('Symbols');
2021-01-23 04:07:23 +03:00
case Emoji.Category.Flags:
2020-10-08 22:11:21 +03:00
return qsTr('Flags');
}
}
ToolTip.visible: hovered
onClicked: {
emojiPopup.model.category = model.category;
}
MouseArea {
id: mouseArea
anchors.fill: parent
onPressed: mouse.accepted = false
cursorShape: Qt.PointingHandCursor
}
2020-05-14 03:19:15 +03:00
contentItem: Image {
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
fillMode: Image.Pad
sourceSize.width: 32
sourceSize.height: 32
source: "image://colorimage/" + model.image + "?" + (hovered ? colors.highlight : colors.buttonText)
}
background: Rectangle {
anchors.fill: parent
2020-10-08 22:11:21 +03:00
color: emojiPopup.model.category === model.category ? Qt.hsla(highlightHue, highlightSat, highlightLight, 0.2) : 'transparent'
radius: 5
2020-05-14 03:19:15 +03:00
border.color: emojiPopup.model.category === model.category ? colors.highlight : 'transparent'
}
2020-05-14 03:19:15 +03:00
}
2020-10-08 22:11:21 +03:00
2020-05-14 03:19:15 +03:00
}
// Separator
Rectangle {
Layout.fillHeight: true
Layout.preferredWidth: 1
implicitWidth: 1
height: parent.height
2020-10-26 15:50:44 +03:00
color: emojiPopup.colors.alternateBase
2020-05-14 03:19:15 +03:00
}
// Search Button is special
AbstractButton {
id: searchBtn
2020-10-08 22:11:21 +03:00
2020-05-14 03:19:15 +03:00
hoverEnabled: true
Layout.alignment: Qt.AlignRight
Layout.bottomMargin: 0
ToolTip.text: qsTr("Search")
ToolTip.visible: hovered
onClicked: {
// clear any filters
2021-01-23 04:07:23 +03:00
emojiPopup.model.category = Emoji.Category.Search;
2020-10-08 22:11:21 +03:00
gridView.positionViewAtBeginning();
emojiSearch.forceActiveFocus();
2020-05-14 03:19:15 +03:00
}
Layout.preferredWidth: 36
Layout.preferredHeight: 36
implicitWidth: 36
implicitHeight: 36
2020-10-08 22:11:21 +03:00
MouseArea {
id: mouseArea
anchors.fill: parent
onPressed: mouse.accepted = false
cursorShape: Qt.PointingHandCursor
}
2020-05-14 03:19:15 +03:00
contentItem: Image {
anchors.right: parent.right
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
sourceSize.width: 32
sourceSize.height: 32
2020-06-10 03:47:21 +03:00
fillMode: Image.Pad
smooth: true
2020-06-10 04:21:30 +03:00
source: "image://colorimage/:/icons/icons/ui/search.png?" + (parent.hovered ? colors.highlight : colors.buttonText)
}
2020-06-10 03:47:21 +03:00
}
2020-10-08 22:11:21 +03:00
}
2020-10-08 22:11:21 +03:00
}
2020-10-08 22:11:21 +03:00
}