Skip to content

Commit

Permalink
feature(qchat): send and receive a bbox message
Browse files Browse the repository at this point in the history
  • Loading branch information
gounux committed Nov 17, 2024
1 parent 1876302 commit 5e3dda8
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 5 deletions.
1 change: 1 addition & 0 deletions qtribu/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,4 @@ def local_path(self, base_path: Path = Path().home() / ".geotribu/cdn/") -> Path
QCHAT_MESSAGE_TYPE_LIKE = "like"
QCHAT_MESSAGE_TYPE_GEOJSON = "geojson"
QCHAT_MESSAGE_TYPE_CRS = "crs"
QCHAT_MESSAGE_TYPE_BBOX = "bbox"
39 changes: 35 additions & 4 deletions qtribu/gui/dck_qchat.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
CHEATCODE_IAMAROBOT,
CHEATCODE_QGIS_PRO_LICENSE,
CHEATCODES,
QCHAT_MESSAGE_TYPE_BBOX,
QCHAT_MESSAGE_TYPE_CRS,
QCHAT_MESSAGE_TYPE_GEOJSON,
QCHAT_MESSAGE_TYPE_IMAGE,
Expand All @@ -42,13 +43,15 @@
from qtribu.gui.qchat_tree_widget_items import (
MESSAGE_COLUMN,
QChatAdminTreeWidgetItem,
QChatBboxTreeWidgetItem,
QChatCrsTreeWidgetItem,
QChatGeojsonTreeWidgetItem,
QChatImageTreeWidgetItem,
QChatTextTreeWidgetItem,
)
from qtribu.logic.qchat_api_client import QChatApiClient
from qtribu.logic.qchat_messages import (
QChatBboxMessage,
QChatCrsMessage,
QChatExiterMessage,
QChatGeojsonMessage,
Expand Down Expand Up @@ -169,6 +172,7 @@ def __init__(
self.qchat_ws.like_message_received.connect(self.on_like_message_received)
self.qchat_ws.geojson_message_received.connect(self.on_geojson_message_received)
self.qchat_ws.crs_message_received.connect(self.on_crs_message_received)
self.qchat_ws.bbox_message_received.connect(self.on_bbox_message_received)

# send message signal listener
self.lne_message.returnPressed.connect(self.on_send_button_clicked)
Expand All @@ -190,7 +194,7 @@ def __init__(
)

# send extent message signal listener
self.btn_send_extent.pressed.connect(self.on_send_extent_button_clicked)
self.btn_send_extent.pressed.connect(self.on_send_bbox_button_clicked)
self.btn_send_extent.setIcon(
QIcon(QgsApplication.iconPath("mActionViewExtentInCanvas.svg"))
)
Expand Down Expand Up @@ -576,6 +580,13 @@ def on_crs_message_received(self, message: QChatCrsMessage) -> None:
item = QChatCrsTreeWidgetItem(self.twg_chat, message)
self.add_tree_widget_item(item)

def on_bbox_message_received(self, message: QChatBboxMessage) -> None:
"""
Launched when a BBOX message is received from the websocket
"""
item = QChatBboxTreeWidgetItem(self.twg_chat, message, self.iface.mapCanvas())
self.add_tree_widget_item(item)

# endregion

def on_message_clicked(self, item: QTreeWidgetItem, column: int) -> None:
Expand Down Expand Up @@ -637,6 +648,15 @@ def on_custom_context_menu_requested(self, point: QPoint) -> None:
set_crs_action.triggered.connect(partial(item.on_click, MESSAGE_COLUMN))
menu.addAction(set_crs_action)

# if this is a bbox message
if type(item) is QChatBboxTreeWidgetItem:
set_bbox_action = QAction(
QgsApplication.getThemeIcon("mActionViewExtentInCanvas.svg"),
self.tr("Set current extent"),
)
set_bbox_action.triggered.connect(partial(item.on_click, MESSAGE_COLUMN))
menu.addAction(set_bbox_action)

# like message action if possible
if item.can_be_liked:
like_action = QAction(
Expand Down Expand Up @@ -799,13 +819,24 @@ def on_send_screenshot_button_clicked(self) -> None:
)
self.qchat_ws.send_message(message)

def on_send_extent_button_clicked(self) -> None:
def on_send_bbox_button_clicked(self) -> None:
"""
Action called when the Send extent button is clicked
"""
QMessageBox.critical(
self, self.tr("Send extent"), self.tr("Not implemented yet")
crs = QgsProject.instance().crs()
rect = self.iface.mapCanvas().extent()
message = QChatBboxMessage(
type=QCHAT_MESSAGE_TYPE_BBOX,
author=self.settings.author_nickname,
avatar=self.settings.author_avatar,
crs_wkt=crs.toWkt(),
crs_authid=crs.authid(),
xmin=rect.xMinimum(),
xmax=rect.xMaximum(),
ymin=rect.yMinimum(),
ymax=rect.yMaximum(),
)
self.qchat_ws.send_message(message)

def on_send_crs_button_clicked(self) -> None:
"""
Expand Down
6 changes: 6 additions & 0 deletions qtribu/gui/dck_qchat.ui
Original file line number Diff line number Diff line change
Expand Up @@ -325,13 +325,19 @@
</item>
<item>
<widget class="QPushButton" name="btn_send_extent">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string>Send Extent</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_send_crs">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string>Send CRS</string>
</property>
Expand Down
52 changes: 51 additions & 1 deletion qtribu/gui/qchat_tree_widget_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
from qgis.core import (
QgsApplication,
QgsCoordinateReferenceSystem,
QgsCoordinateTransform,
QgsPointXY,
QgsProject,
QgsRectangle,
QgsVectorLayer,
)
from qgis.gui import QgsMapCanvas
from qgis.PyQt.QtCore import QTime
from qgis.PyQt.QtGui import QBrush, QColor, QIcon, QPixmap
from qgis.PyQt.QtWidgets import (
Expand All @@ -22,6 +26,7 @@

from qtribu.constants import ADMIN_MESSAGES_AVATAR, ADMIN_MESSAGES_NICKNAME
from qtribu.logic.qchat_messages import (
QChatBboxMessage,
QChatCrsMessage,
QChatGeojsonMessage,
QChatImageMessage,
Expand Down Expand Up @@ -268,4 +273,49 @@ def can_be_copied_to_clipboard(self) -> bool:
return True

def copy_to_clipboard(self) -> None:
QgsApplication.instance().clipboard().setText(json.dumps(self.message.crs_wkt))
QgsApplication.instance().clipboard().setText(self.message.crs_wkt)


class QChatBboxTreeWidgetItem(QChatTreeWidgetItem):
def __init__(
self, parent: QTreeWidget, message: QChatBboxMessage, canvas: QgsMapCanvas
):
super().__init__(parent, QTime.currentTime(), message.author, message.avatar)
self.message = message
self.canvas = canvas
self.init_time_and_author()
self.setText(MESSAGE_COLUMN, self.liked_message)
self.setToolTip(MESSAGE_COLUMN, self.liked_message)

# set foreground color if sent by user
if message.author == self.settings.author_nickname:
self.set_foreground_color(self.settings.qchat_color_self)

def on_click(self, column: int) -> None:
if column == MESSAGE_COLUMN:
# set current canvas extent to the received one
project = QgsProject.instance()
tr = QgsCoordinateTransform(
QgsCoordinateReferenceSystem(self.message.crs_wkt),
project.crs(),
project,
)
rect = QgsRectangle(
tr.transform(QgsPointXY(self.message.xmin, self.message.ymin)),
tr.transform(QgsPointXY(self.message.xmax, self.message.ymax)),
)
self.canvas.setExtent(rect)
self.canvas.refresh()

@property
def liked_message(self) -> str:
msg = f"[{self.message.xmin} {self.message.ymin}, {self.message.xmax} {self.message.ymax}]"
return f"<BBOX {self.message.crs_authid}: {msg}>"

@property
def can_be_copied_to_clipboard(self) -> bool:
return True

def copy_to_clipboard(self) -> None:
msg = f"[{self.message.xmin} {self.message.ymin}, {self.message.xmax} {self.message.ymax}]"
QgsApplication.instance().clipboard().setText(msg)
12 changes: 12 additions & 0 deletions qtribu/logic/qchat_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,15 @@ class QChatCrsMessage(QChatMessage):
avatar: Optional[str]
crs_wkt: str
crs_authid: str


@dataclass(init=True, frozen=True)
class QChatBboxMessage(QChatMessage):
author: str
avatar: Optional[str]
crs_wkt: str
crs_authid: str
xmin: float
xmax: float
ymin: float
ymax: float
5 changes: 5 additions & 0 deletions qtribu/logic/qchat_websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from qgis.PyQt.QtCore import QObject, QUrl, pyqtSignal

from qtribu.constants import (
QCHAT_MESSAGE_TYPE_BBOX,
QCHAT_MESSAGE_TYPE_CRS,
QCHAT_MESSAGE_TYPE_EXITER,
QCHAT_MESSAGE_TYPE_GEOJSON,
Expand All @@ -18,6 +19,7 @@
QCHAT_MESSAGE_TYPE_UNCOMPLIANT,
)
from qtribu.logic.qchat_messages import (
QChatBboxMessage,
QChatCrsMessage,
QChatExiterMessage,
QChatGeojsonMessage,
Expand Down Expand Up @@ -72,6 +74,7 @@ def __init__(self):
like_message_received = pyqtSignal(QChatLikeMessage)
geojson_message_received = pyqtSignal(QChatGeojsonMessage)
crs_message_received = pyqtSignal(QChatCrsMessage)
bbox_message_received = pyqtSignal(QChatBboxMessage)

def open(self, qchat_instance_uri: str, room: str) -> None:
"""
Expand Down Expand Up @@ -136,3 +139,5 @@ def on_message_received(self, text: str) -> None:
self.geojson_message_received.emit(QChatGeojsonMessage(**message))
elif msg_type == QCHAT_MESSAGE_TYPE_CRS:
self.crs_message_received.emit(QChatCrsMessage(**message))
elif msg_type == QCHAT_MESSAGE_TYPE_BBOX:
self.bbox_message_received.emit(QChatBboxMessage(**message))

0 comments on commit 5e3dda8

Please sign in to comment.