2021-03-05 02:35:15 +03:00
|
|
|
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
2021-03-07 07:57:56 +03:00
|
|
|
//
|
2021-03-05 02:35:15 +03:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
2020-10-08 22:11:21 +03:00
|
|
|
import "../"
|
|
|
|
import QtGraphicalEffects 1.0
|
2021-01-12 17:03:39 +03:00
|
|
|
import QtQuick 2.9
|
2020-06-17 22:34:02 +03:00
|
|
|
import QtQuick.Controls 2.3
|
2021-01-12 17:03:39 +03:00
|
|
|
import QtQuick.Layouts 1.3
|
2020-05-13 07:35:26 +03:00
|
|
|
import im.nheko 1.0
|
|
|
|
import im.nheko.EmojiModel 1.0
|
|
|
|
|
2021-03-23 20:05:43 +03:00
|
|
|
Menu {
|
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
|
2020-05-13 07:35:26 +03:00
|
|
|
property var colors
|
|
|
|
property alias model: gridView.model
|
|
|
|
property var textArea
|
|
|
|
property string emojiCategory: "people"
|
2020-05-22 04:21:35 +03:00
|
|
|
property real highlightHue: colors.highlight.hslHue
|
|
|
|
property real highlightSat: colors.highlight.hslSaturation
|
|
|
|
property real highlightLight: colors.highlight.hslLightness
|
2020-05-13 07:35:26 +03:00
|
|
|
|
2020-11-16 20:41:29 +03:00
|
|
|
function show(showAt, callback) {
|
|
|
|
console.debug("Showing emojiPicker");
|
|
|
|
emojiPopup.callback = callback;
|
2021-03-23 20:05:43 +03:00
|
|
|
popup(showAt ? showAt : null);
|
2020-10-08 22:11:21 +03:00
|
|
|
}
|
2020-05-13 07:35:26 +03:00
|
|
|
|
|
|
|
margins: 0
|
2020-05-14 03:19:15 +03:00
|
|
|
bottomPadding: 1
|
|
|
|
leftPadding: 1
|
|
|
|
rightPadding: 1
|
2020-05-13 07:35:26 +03:00
|
|
|
modal: true
|
|
|
|
focus: true
|
2020-05-14 03:19:15 +03:00
|
|
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
2021-03-23 20:05:43 +03:00
|
|
|
height: columnView.implicitHeight + 4
|
2021-04-14 00:47:08 +03:00
|
|
|
width: columnView.implicitWidth
|
2021-03-23 20:05:43 +03:00
|
|
|
|
2020-05-13 07:35:26 +03:00
|
|
|
ColumnLayout {
|
2020-05-14 03:19:15 +03:00
|
|
|
id: columnView
|
2020-10-08 22:11:21 +03:00
|
|
|
|
2020-05-14 03:19:15 +03:00
|
|
|
spacing: 0
|
2021-03-23 20:05:43 +03:00
|
|
|
anchors.leftMargin: 3
|
|
|
|
anchors.rightMargin: 3
|
2021-04-11 23:24:39 +03:00
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
anchors.left: parent.left
|
|
|
|
anchors.right: parent.right
|
|
|
|
anchors.topMargin: 2
|
2020-05-13 07:35:26 +03:00
|
|
|
|
|
|
|
// emoji grid
|
|
|
|
GridView {
|
|
|
|
id: gridView
|
|
|
|
|
2021-04-11 23:24:39 +03:00
|
|
|
Layout.preferredHeight: cellHeight * 5
|
|
|
|
Layout.preferredWidth: 7 * 52 + 20
|
2020-05-14 03:19:15 +03:00
|
|
|
Layout.leftMargin: 4
|
2020-05-13 07:35:26 +03:00
|
|
|
cellWidth: 52
|
|
|
|
cellHeight: 52
|
2020-06-10 03:47:21 +03:00
|
|
|
boundsBehavior: Flickable.StopAtBounds
|
2020-05-13 07:35:26 +03:00
|
|
|
clip: true
|
2020-10-12 23:05:55 +03:00
|
|
|
currentIndex: -1 // prevent sorting from stealing focus
|
2020-05-13 07:35:26 +03:00
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2020-05-13 07:35:26 +03:00
|
|
|
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
|
2020-05-13 07:35:26 +03:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2020-05-13 07:35:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
2020-05-13 07:35:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
2020-05-13 07:35:26 +03:00
|
|
|
Repeater {
|
2020-10-08 22:11:21 +03:00
|
|
|
|
2020-05-13 07:35:26 +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
|
|
|
}
|
|
|
|
|
2020-05-13 07:35:26 +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-13 07:35:26 +03:00
|
|
|
|
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)
|
2020-05-13 07:35:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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'
|
2020-05-13 07:35:26 +03:00
|
|
|
radius: 5
|
2020-05-14 03:19:15 +03:00
|
|
|
border.color: emojiPopup.model.category === model.category ? colors.highlight : 'transparent'
|
2020-05-13 07:35:26 +03:00
|
|
|
}
|
|
|
|
|
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-05-13 07:35:26 +03:00
|
|
|
}
|
2020-06-10 03:47:21 +03:00
|
|
|
|
2020-05-13 07:35:26 +03:00
|
|
|
}
|
2020-10-08 22:11:21 +03:00
|
|
|
|
2020-05-13 07:35:26 +03:00
|
|
|
}
|
2020-10-08 22:11:21 +03:00
|
|
|
|
2020-05-13 07:35:26 +03:00
|
|
|
}
|
2020-10-08 22:11:21 +03:00
|
|
|
|
2020-05-13 07:35:26 +03:00
|
|
|
}
|