Philipp Hörist pushed to branch master at gajim / gajim
Commits:
-
4166e403
by Philipp Hörist at 2022-10-09T20:08:35+02:00
-
48f48849
by Philipp Hörist at 2022-10-09T20:14:00+02:00
-
fdc424f5
by Philipp Hörist at 2022-10-09T21:50:11+02:00
2 changed files:
Changes:
| ... | ... | @@ -44,22 +44,21 @@ |
| 44 | 44 | from gajim.common.helpers import to_user_string
|
| 45 | 45 | from gajim.common.i18n import _
|
| 46 | 46 | from gajim.common.i18n import is_rtl_text
|
| 47 | -from gajim.common.i18n import Q_
|
|
| 48 | 47 | from gajim.common.modules.contacts import GroupchatContact
|
| 49 | 48 | from gajim.common.types import ChatContactT
|
| 50 | 49 | |
| 51 | 50 | from .base import BaseRow
|
| 51 | +from .widgets import AvatarBox
|
|
| 52 | 52 | from .widgets import DateTimeLabel
|
| 53 | 53 | from .widgets import NicknameLabel
|
| 54 | +from .widgets import MessageIcons
|
|
| 54 | 55 | from .widgets import MoreMenuButton
|
| 55 | 56 | from ..message_widget import MessageWidget
|
| 56 | 57 | from ...dialogs import InputDialog
|
| 57 | 58 | from ...dialogs import DialogButton
|
| 58 | -from ...menus import get_groupchat_participant_menu
|
|
| 59 | 59 | from ...preview import PreviewWidget
|
| 60 | -from ...util import GajimPopover
|
|
| 61 | 60 | from ...util import format_fingerprint
|
| 62 | -from ...util import get_cursor
|
|
| 61 | + |
|
| 63 | 62 | |
| 64 | 63 | MERGE_TIMEFRAME = timedelta(seconds=120)
|
| 65 | 64 | |
| ... | ... | @@ -179,19 +178,9 @@ def __init__(self, |
| 179 | 178 | self.set_receipt()
|
| 180 | 179 | |
| 181 | 180 | self._meta_box.pack_start(self._message_icons, False, True, 0)
|
| 182 | - avatar = self._get_avatar(kind, name)
|
|
| 183 | - self._avatar_image = Gtk.Image.new_from_surface(avatar)
|
|
| 184 | 181 | |
| 185 | - if self._is_groupchat:
|
|
| 186 | - avatar_placeholder = Gtk.EventBox()
|
|
| 187 | - avatar_placeholder.connect(
|
|
| 188 | - 'button-press-event', self._on_avatar_clicked, name)
|
|
| 189 | - avatar_placeholder.connect('realize', self._on_realize)
|
|
| 190 | - else:
|
|
| 191 | - avatar_placeholder = Gtk.Box()
|
|
| 192 | - avatar_placeholder.set_size_request(AvatarSize.ROSTER, -1)
|
|
| 193 | - avatar_placeholder.set_valign(Gtk.Align.START)
|
|
| 194 | - avatar_placeholder.add(self._avatar_image)
|
|
| 182 | + avatar = self._get_avatar(kind, name)
|
|
| 183 | + self._avatar_box = AvatarBox(self._contact, name, avatar)
|
|
| 195 | 184 | |
| 196 | 185 | self._bottom_box = Gtk.Box(spacing=6)
|
| 197 | 186 | self._bottom_box.add(self._message_widget)
|
| ... | ... | @@ -201,11 +190,9 @@ def __init__(self, |
| 201 | 190 | self._message_widget.set_direction(Gtk.TextDirection.RTL)
|
| 202 | 191 | |
| 203 | 192 | more_menu_button = MoreMenuButton(self, self._contact, name)
|
| 204 | - more_menu_button.set_hexpand(True)
|
|
| 205 | - more_menu_button.set_halign(Gtk.Align.END)
|
|
| 206 | 193 | self._bottom_box.pack_end(more_menu_button, False, True, 0)
|
| 207 | 194 | |
| 208 | - self.grid.attach(avatar_placeholder, 0, 0, 1, 2)
|
|
| 195 | + self.grid.attach(self._avatar_box, 0, 0, 1, 2)
|
|
| 209 | 196 | self.grid.attach(self._meta_box, 1, 0, 1, 1)
|
| 210 | 197 | self.grid.attach(self._bottom_box, 1, 1, 1, 1)
|
| 211 | 198 | |
| ... | ... | @@ -268,45 +255,6 @@ def _get_avatar(self, kind: str, name: str) -> Optional[cairo.ImageSurface]: |
| 268 | 255 | assert not isinstance(avatar, GdkPixbuf.Pixbuf)
|
| 269 | 256 | return avatar
|
| 270 | 257 | |
| 271 | - def _on_avatar_clicked(self,
|
|
| 272 | - _widget: Gtk.Widget,
|
|
| 273 | - event: Gdk.EventButton,
|
|
| 274 | - name: str
|
|
| 275 | - ) -> int:
|
|
| 276 | - if event.type == Gdk.EventType.BUTTON_PRESS:
|
|
| 277 | - if event.button == 1:
|
|
| 278 | - app.window.activate_action('mention', GLib.Variant('s', name))
|
|
| 279 | - elif event.button == 3:
|
|
| 280 | - self._show_participant_menu(name, event)
|
|
| 281 | - |
|
| 282 | - return Gdk.EVENT_STOP
|
|
| 283 | - |
|
| 284 | - def _show_participant_menu(self, nick: str, event: Gdk.EventButton) -> None:
|
|
| 285 | - assert isinstance(self._contact, GroupchatContact)
|
|
| 286 | - if not self._contact.is_joined:
|
|
| 287 | - return
|
|
| 288 | - |
|
| 289 | - self_contact = self._contact.get_self()
|
|
| 290 | - assert self_contact is not None
|
|
| 291 | - |
|
| 292 | - if nick == self_contact.name:
|
|
| 293 | - # Don’t show menu for us
|
|
| 294 | - return
|
|
| 295 | - |
|
| 296 | - contact = self._contact.get_resource(nick)
|
|
| 297 | - menu = get_groupchat_participant_menu(self._contact.account,
|
|
| 298 | - self_contact,
|
|
| 299 | - contact)
|
|
| 300 | - |
|
| 301 | - popover = GajimPopover(menu, relative_to=self, event=event)
|
|
| 302 | - popover.popup()
|
|
| 303 | - |
|
| 304 | - @staticmethod
|
|
| 305 | - def _on_realize(event_box: Gtk.EventBox) -> None:
|
|
| 306 | - window = event_box.get_window()
|
|
| 307 | - if window is not None:
|
|
| 308 | - window.set_cursor(get_cursor('pointer'))
|
|
| 309 | - |
|
| 310 | 258 | def is_same_sender(self, message: MessageRow) -> bool:
|
| 311 | 259 | return message.name == self.name
|
| 312 | 260 | |
| ... | ... | @@ -487,63 +435,17 @@ def set_error(self, tooltip: str) -> None: |
| 487 | 435 | |
| 488 | 436 | def update_avatar(self) -> None:
|
| 489 | 437 | avatar = self._get_avatar(self.kind, self.name)
|
| 490 | - self._avatar_image.set_from_surface(avatar)
|
|
| 438 | + self._avatar_box.set_from_surface(avatar)
|
|
| 491 | 439 | |
| 492 | 440 | def set_merged(self, merged: bool) -> None:
|
| 493 | 441 | self._merged = merged
|
| 494 | 442 | if merged:
|
| 495 | 443 | self.get_style_context().add_class('merged')
|
| 496 | - self._avatar_image.set_no_show_all(True)
|
|
| 497 | - self._avatar_image.hide()
|
|
| 498 | 444 | self._meta_box.set_no_show_all(True)
|
| 499 | 445 | self._meta_box.hide()
|
| 500 | 446 | else:
|
| 501 | 447 | self.get_style_context().remove_class('merged')
|
| 502 | - self._avatar_image.set_no_show_all(False)
|
|
| 503 | - self._avatar_image.show()
|
|
| 504 | 448 | self._meta_box.set_no_show_all(False)
|
| 505 | 449 | self._meta_box.show()
|
| 506 | 450 | |
| 507 | - |
|
| 508 | -class MessageIcons(Gtk.Box):
|
|
| 509 | - def __init__(self) -> None:
|
|
| 510 | - Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL)
|
|
| 511 | - |
|
| 512 | - self._correction_image = Gtk.Image.new_from_icon_name(
|
|
| 513 | - 'document-edit-symbolic', Gtk.IconSize.MENU)
|
|
| 514 | - self._correction_image.set_no_show_all(True)
|
|
| 515 | - self._correction_image.get_style_context().add_class('dim-label')
|
|
| 516 | - |
|
| 517 | - self._marker_image = Gtk.Image()
|
|
| 518 | - self._marker_image.set_no_show_all(True)
|
|
| 519 | - self._marker_image.get_style_context().add_class('dim-label')
|
|
| 520 | - |
|
| 521 | - self._error_image = Gtk.Image.new_from_icon_name(
|
|
| 522 | - 'dialog-warning-symbolic', Gtk.IconSize.MENU)
|
|
| 523 | - self._error_image.get_style_context().add_class('warning-color')
|
|
| 524 | - self._error_image.set_no_show_all(True)
|
|
| 525 | - |
|
| 526 | - self.add(self._correction_image)
|
|
| 527 | - self.add(self._marker_image)
|
|
| 528 | - self.add(self._error_image)
|
|
| 529 | - self.show_all()
|
|
| 530 | - |
|
| 531 | - def set_receipt_icon_visible(self, visible: bool) -> None:
|
|
| 532 | - if not app.settings.get('positive_184_ack'):
|
|
| 533 | - return
|
|
| 534 | - self._marker_image.set_visible(visible)
|
|
| 535 | - self._marker_image.set_from_icon_name(
|
|
| 536 | - 'feather-check-symbolic', Gtk.IconSize.MENU)
|
|
| 537 | - self._marker_image.set_tooltip_text(Q_('?Message state:Received'))
|
|
| 538 | - |
|
| 539 | - def set_correction_icon_visible(self, visible: bool) -> None:
|
|
| 540 | - self._correction_image.set_visible(visible)
|
|
| 541 | - |
|
| 542 | - def set_correction_tooltip(self, text: str) -> None:
|
|
| 543 | - self._correction_image.set_tooltip_markup(text)
|
|
| 544 | - |
|
| 545 | - def set_error_icon_visible(self, visible: bool) -> None:
|
|
| 546 | - self._error_image.set_visible(visible)
|
|
| 547 | - |
|
| 548 | - def set_error_tooltip(self, text: str) -> None:
|
|
| 549 | - self._error_image.set_tooltip_markup(text) |
|
| 451 | + self._avatar_box.set_merged(merged) |
| ... | ... | @@ -15,14 +15,18 @@ |
| 15 | 15 | from __future__ import annotations
|
| 16 | 16 | |
| 17 | 17 | from typing import TYPE_CHECKING
|
| 18 | +from typing import Optional
|
|
| 18 | 19 | |
| 19 | 20 | from datetime import datetime
|
| 20 | 21 | |
| 21 | 22 | from gi.repository import Gtk
|
| 23 | +from gi.repository import Gdk
|
|
| 22 | 24 | from gi.repository import Pango
|
| 23 | 25 | from gi.repository import GLib
|
| 26 | +import cairo
|
|
| 24 | 27 | |
| 25 | 28 | from gajim.common import app
|
| 29 | +from gajim.common.const import AvatarSize
|
|
| 26 | 30 | from gajim.common.i18n import Q_
|
| 27 | 31 | from gajim.common.helpers import is_retraction_allowed
|
| 28 | 32 | from gajim.common.modules.contacts import GroupchatContact
|
| ... | ... | @@ -31,7 +35,10 @@ |
| 31 | 35 | if TYPE_CHECKING:
|
| 32 | 36 | from .message import MessageRow
|
| 33 | 37 | |
| 38 | +from ...menus import get_groupchat_participant_menu
|
|
| 34 | 39 | from ...util import wrap_with_event_box
|
| 40 | +from ...util import get_cursor
|
|
| 41 | +from ...util import GajimPopover
|
|
| 35 | 42 | |
| 36 | 43 | |
| 37 | 44 | class SimpleLabel(Gtk.Label):
|
| ... | ... | @@ -55,6 +62,7 @@ def __init__(self, |
| 55 | 62 | self.set_valign(Gtk.Align.START)
|
| 56 | 63 | self.set_halign(Gtk.Align.END)
|
| 57 | 64 | self.set_relief(Gtk.ReliefStyle.NONE)
|
| 65 | + self.set_hexpand(True)
|
|
| 58 | 66 | |
| 59 | 67 | self.get_style_context().add_class('conversation-more-button')
|
| 60 | 68 | |
| ... | ... | @@ -196,3 +204,118 @@ def __init__(self, name: str, from_us: bool) -> None: |
| 196 | 204 | css_class = 'gajim-incoming-nickname'
|
| 197 | 205 | |
| 198 | 206 | self.get_style_context().add_class(css_class)
|
| 207 | + |
|
| 208 | + |
|
| 209 | +class MessageIcons(Gtk.Box):
|
|
| 210 | + def __init__(self) -> None:
|
|
| 211 | + Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL)
|
|
| 212 | + |
|
| 213 | + self._correction_image = Gtk.Image.new_from_icon_name(
|
|
| 214 | + 'document-edit-symbolic', Gtk.IconSize.MENU)
|
|
| 215 | + self._correction_image.set_no_show_all(True)
|
|
| 216 | + self._correction_image.get_style_context().add_class('dim-label')
|
|
| 217 | + |
|
| 218 | + self._marker_image = Gtk.Image()
|
|
| 219 | + self._marker_image.set_no_show_all(True)
|
|
| 220 | + self._marker_image.get_style_context().add_class('dim-label')
|
|
| 221 | + |
|
| 222 | + self._error_image = Gtk.Image.new_from_icon_name(
|
|
| 223 | + 'dialog-warning-symbolic', Gtk.IconSize.MENU)
|
|
| 224 | + self._error_image.get_style_context().add_class('warning-color')
|
|
| 225 | + self._error_image.set_no_show_all(True)
|
|
| 226 | + |
|
| 227 | + self.add(self._correction_image)
|
|
| 228 | + self.add(self._marker_image)
|
|
| 229 | + self.add(self._error_image)
|
|
| 230 | + self.show_all()
|
|
| 231 | + |
|
| 232 | + def set_receipt_icon_visible(self, visible: bool) -> None:
|
|
| 233 | + if not app.settings.get('positive_184_ack'):
|
|
| 234 | + return
|
|
| 235 | + self._marker_image.set_visible(visible)
|
|
| 236 | + self._marker_image.set_from_icon_name(
|
|
| 237 | + 'feather-check-symbolic', Gtk.IconSize.MENU)
|
|
| 238 | + self._marker_image.set_tooltip_text(Q_('?Message state:Received'))
|
|
| 239 | + |
|
| 240 | + def set_correction_icon_visible(self, visible: bool) -> None:
|
|
| 241 | + self._correction_image.set_visible(visible)
|
|
| 242 | + |
|
| 243 | + def set_correction_tooltip(self, text: str) -> None:
|
|
| 244 | + self._correction_image.set_tooltip_markup(text)
|
|
| 245 | + |
|
| 246 | + def set_error_icon_visible(self, visible: bool) -> None:
|
|
| 247 | + self._error_image.set_visible(visible)
|
|
| 248 | + |
|
| 249 | + def set_error_tooltip(self, text: str) -> None:
|
|
| 250 | + self._error_image.set_tooltip_markup(text)
|
|
| 251 | + |
|
| 252 | + |
|
| 253 | +class AvatarBox(Gtk.EventBox):
|
|
| 254 | + def __init__(self,
|
|
| 255 | + contact: ChatContactT,
|
|
| 256 | + name: str,
|
|
| 257 | + avatar: Optional[cairo.ImageSurface],
|
|
| 258 | + ) -> None:
|
|
| 259 | + |
|
| 260 | + Gtk.EventBox.__init__(self)
|
|
| 261 | + |
|
| 262 | + self.set_size_request(AvatarSize.ROSTER, -1)
|
|
| 263 | + self.set_valign(Gtk.Align.START)
|
|
| 264 | + |
|
| 265 | + self._contact = contact
|
|
| 266 | + |
|
| 267 | + self._image = Gtk.Image.new_from_surface(avatar)
|
|
| 268 | + self.add(self._image)
|
|
| 269 | + |
|
| 270 | + if self._contact.is_groupchat:
|
|
| 271 | + self.connect('realize', self._on_realize)
|
|
| 272 | + |
|
| 273 | + self.connect('button-press-event',
|
|
| 274 | + self._on_avatar_clicked, name)
|
|
| 275 | + |
|
| 276 | + def set_from_surface(self, surface: Optional[cairo.ImageSurface]) -> None:
|
|
| 277 | + self._image.set_from_surface(surface)
|
|
| 278 | + |
|
| 279 | + def set_merged(self, merged: bool) -> None:
|
|
| 280 | + self._image.set_no_show_all(merged)
|
|
| 281 | + self._image.set_visible(not merged)
|
|
| 282 | + |
|
| 283 | + @staticmethod
|
|
| 284 | + def _on_realize(event_box: Gtk.EventBox) -> None:
|
|
| 285 | + window = event_box.get_window()
|
|
| 286 | + if window is not None:
|
|
| 287 | + window.set_cursor(get_cursor('pointer'))
|
|
| 288 | + |
|
| 289 | + def _on_avatar_clicked(self,
|
|
| 290 | + _widget: Gtk.Widget,
|
|
| 291 | + event: Gdk.EventButton,
|
|
| 292 | + name: str
|
|
| 293 | + ) -> int:
|
|
| 294 | + |
|
| 295 | + if event.type == Gdk.EventType.BUTTON_PRESS:
|
|
| 296 | + if event.button == 1:
|
|
| 297 | + app.window.activate_action('mention', GLib.Variant('s', name))
|
|
| 298 | + elif event.button == 3:
|
|
| 299 | + self._show_participant_menu(name, event)
|
|
| 300 | + |
|
| 301 | + return Gdk.EVENT_STOP
|
|
| 302 | + |
|
| 303 | + def _show_participant_menu(self, nick: str, event: Gdk.EventButton) -> None:
|
|
| 304 | + assert isinstance(self._contact, GroupchatContact)
|
|
| 305 | + if not self._contact.is_joined:
|
|
| 306 | + return
|
|
| 307 | + |
|
| 308 | + self_contact = self._contact.get_self()
|
|
| 309 | + assert self_contact is not None
|
|
| 310 | + |
|
| 311 | + if nick == self_contact.name:
|
|
| 312 | + # Don’t show menu for us
|
|
| 313 | + return
|
|
| 314 | + |
|
| 315 | + contact = self._contact.get_resource(nick)
|
|
| 316 | + menu = get_groupchat_participant_menu(self._contact.account,
|
|
| 317 | + self_contact,
|
|
| 318 | + contact)
|
|
| 319 | + |
|
| 320 | + popover = GajimPopover(menu, relative_to=self, event=event)
|
|
| 321 | + popover.popup() |