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