|
13 | 13 | from qgis.core import Qgis, QgsApplication, QgsJsonExporter, QgsMapLayer, QgsProject |
14 | 14 | from qgis.gui import QgisInterface, QgsDockWidget |
15 | 15 | from qgis.PyQt import uic |
16 | | -from qgis.PyQt.QtCore import QPoint, Qt |
17 | | -from qgis.PyQt.QtGui import QCursor, QIcon |
| 16 | +from qgis.PyQt.QtCore import QPoint, Qt, QUrl |
| 17 | +from qgis.PyQt.QtGui import QCursor, QFont, QFontDatabase, QIcon |
18 | 18 | from qgis.PyQt.QtWidgets import ( |
19 | 19 | QAction, |
20 | 20 | QFileDialog, |
|
43 | 43 | QCHAT_MESSAGE_TYPE_TEXT, |
44 | 44 | QCHAT_NICKNAME_MINLENGTH, |
45 | 45 | ) |
| 46 | +from qchat.gui.emojis.fra_emoji_picker_quick import EmojiButtonHandler |
46 | 47 | from qchat.gui.qchat_tree_widget_items import ( |
47 | 48 | MESSAGE_COLUMN, |
48 | 49 | QChatAdminTreeWidgetItem, |
@@ -104,6 +105,7 @@ def __init__( |
104 | 105 | self.task_manager = QgsApplication.taskManager() |
105 | 106 | self.log = PlgLogger().log |
106 | 107 | self.plg_settings = PlgOptionsManager() |
| 108 | + |
107 | 109 | uic.loadUi(Path(__file__).parent / f"{Path(__file__).stem}.ui", self) |
108 | 110 |
|
109 | 111 | # set channel to autoreconnect to when widget will open |
@@ -190,6 +192,10 @@ def __init__( |
190 | 192 | QIcon(QgsApplication.iconPath("mActionDoubleArrowRight.svg")) |
191 | 193 | ) |
192 | 194 |
|
| 195 | + # emoji picker |
| 196 | + self.emoji_handler = EmojiButtonHandler(parent_button=self.btn_emojis_picker) |
| 197 | + self.emoji_handler.emoji_selected.connect(self.insert_emoji) |
| 198 | + |
193 | 199 | # send image message signal listener |
194 | 200 | self.btn_send_image.pressed.connect(self.on_send_image_button_clicked) |
195 | 201 | self.btn_send_image.setIcon( |
@@ -956,14 +962,26 @@ def on_send_crs_button_clicked(self) -> None: |
956 | 962 | self.qchat_ws.send_message(message) |
957 | 963 |
|
958 | 964 | def add_admin_message(self, text: str, timestamp: Optional[int] = None) -> None: |
| 965 | + """Adds an admin message to QTreeWidget chat. |
| 966 | +
|
| 967 | + :param text: admin message to insert |
| 968 | + :type text: str |
| 969 | + :param timestamp: datetime, defaults to None |
| 970 | + :type timestamp: Optional[int], optional |
959 | 971 | """ |
960 | | - Adds an admin message to QTreeWidget chat |
961 | | - """ |
| 972 | + |
962 | 973 | item = QChatAdminTreeWidgetItem(self.twg_chat, text, timestamp) |
963 | 974 | self.add_tree_widget_item(item) |
964 | 975 |
|
965 | 976 | def add_tree_widget_item(self, item: QTreeWidgetItem) -> None: |
| 977 | + """Adds a QTreeWidgetItem to the chat QTreeWidget. |
| 978 | +
|
| 979 | + :param item: item to insert |
| 980 | + :type item: QTreeWidgetItem |
| 981 | + """ |
966 | 982 | self.twg_chat.addTopLevelItem(item) |
| 983 | + if isinstance(item, QChatTextTreeWidgetItem): |
| 984 | + item.setFont(MESSAGE_COLUMN, QFont("Noto Color Emoji")) |
967 | 985 | if self.ckb_autoscroll.isChecked(): |
968 | 986 | self.twg_chat.scrollToItem(item) |
969 | 987 |
|
@@ -1154,3 +1172,73 @@ def on_send_geojson_layer_to_qchat(self) -> None: |
1154 | 1172 | style=qml_style, |
1155 | 1173 | ) |
1156 | 1174 | self.qchat_ws.send_message(message) |
| 1175 | + |
| 1176 | + # -- FONTS -- |
| 1177 | + def is_font_available(self, font_family: str) -> bool: |
| 1178 | + available_fonts = QFontDatabase().families() |
| 1179 | + return font_family in available_fonts |
| 1180 | + |
| 1181 | + # -- EMOJIS -- |
| 1182 | + |
| 1183 | + def check_emoji_font(self) -> bool: |
| 1184 | + """Check if the font used for displaying emojis is installed. If not, try to |
| 1185 | + download it. |
| 1186 | +
|
| 1187 | + :return: _description_ |
| 1188 | + :rtype: _type_ |
| 1189 | + """ |
| 1190 | + if self.is_font_available(font_family=self.plg_settings.font_emoji_family): |
| 1191 | + self.log( |
| 1192 | + message=self.tr( |
| 1193 | + "Required font to display emojis is already installed: {}".format( |
| 1194 | + self.plg_settings.font_emoji_family |
| 1195 | + ) |
| 1196 | + ), |
| 1197 | + push=False, |
| 1198 | + log_level=Qgis.MessageLevel.NoLevel, |
| 1199 | + ) |
| 1200 | + return True |
| 1201 | + else: |
| 1202 | + self.log( |
| 1203 | + message="Required font for emojis needs to be installed: {}".format( |
| 1204 | + self.plg_settings.font_emoji_family |
| 1205 | + ), |
| 1206 | + push=False, |
| 1207 | + ) |
| 1208 | + font_manager = QgsApplication.fontManager() |
| 1209 | + font_manager.fontDownloadErrorOccurred.connect(self.on_font_download_failed) |
| 1210 | + auto_downloaded = font_manager.tryToDownloadFontFamily( |
| 1211 | + self.plg_settings.font_emoji_family |
| 1212 | + ) |
| 1213 | + if not auto_downloaded: |
| 1214 | + self.log(message="not downloaded", log_level=Qgis.MessageLevel.Warning) |
| 1215 | + |
| 1216 | + font_manager.downloadAndInstallFont( |
| 1217 | + url=QUrl(self.plg_settings.font_emoji_download_url), |
| 1218 | + identifier="qchat-emoji-font", |
| 1219 | + ) |
| 1220 | + |
| 1221 | + def on_font_download_failed(self, error_message: Optional[str] = None): |
| 1222 | + """Handle pyqtsignal emitted by QgsFontManager when font downloading failed. |
| 1223 | +
|
| 1224 | + :param error_message: error message, defaults to None |
| 1225 | + :type error_message: Optional[str], optional |
| 1226 | + """ |
| 1227 | + self.log( |
| 1228 | + message=self.tr( |
| 1229 | + "Downloading the font {} from {} failed. Since it's required to " |
| 1230 | + "correctly display emojis, consider to add it manually to your system. " |
| 1231 | + "Trace: {}".format( |
| 1232 | + self.EMOJI_FONT_FAMILY, self.EMOJI_FONT_DOWNLOAD_URL, error_message |
| 1233 | + ) |
| 1234 | + ) |
| 1235 | + ) |
| 1236 | + |
| 1237 | + def insert_emoji(self, emoji): |
| 1238 | + """Insert selected emoji at cursor position""" |
| 1239 | + cursor_pos = self.lne_message.cursorPosition() |
| 1240 | + current_text = self.lne_message.text() |
| 1241 | + new_text = current_text[:cursor_pos] + emoji + current_text[cursor_pos:] |
| 1242 | + self.lne_message.setText(new_text) |
| 1243 | + self.lne_message.setCursorPosition(cursor_pos + len(emoji)) |
| 1244 | + self.lne_message.setFocus() |
0 commit comments