Daniel Brötzmann pushed to branch master at gajim / gajim
Commits:
-
00c68673
by wurstsalat at 2021-12-08T23:27:48+01:00
3 changed files:
Changes:
| ... | ... | @@ -230,12 +230,6 @@ .workspace-sidebar-item image { |
| 230 | 230 |
border-radius: 9px;
|
| 231 | 231 |
margin: 6px;
|
| 232 | 232 |
}
|
| 233 |
-.workspace-sidebar-item.drag-hover-top {
|
|
| 234 |
- border-top: 1px solid #4e9a06;
|
|
| 235 |
-}
|
|
| 236 |
-.workspace-sidebar-item.drag-hover-bottom {
|
|
| 237 |
- border-bottom: 1px solid #4e9a06;
|
|
| 238 |
-}
|
|
| 239 | 233 |
.workspace-add:hover,
|
| 240 | 234 |
.workspace-add:focus {
|
| 241 | 235 |
background: transparent;
|
| ... | ... | @@ -24,6 +24,7 @@ |
| 24 | 24 |
from gi.repository import Gdk
|
| 25 | 25 |
from gi.repository import GLib
|
| 26 | 26 |
from gi.repository import Gtk
|
| 27 |
+import cairo
|
|
| 27 | 28 |
|
| 28 | 29 |
from nbxmpp import JID
|
| 29 | 30 |
|
| ... | ... | @@ -71,6 +72,16 @@ def __init__(self, workspace_id): |
| 71 | 72 |
self.connect('enter-notify-event', self._on_mouse_focus_changed)
|
| 72 | 73 |
self.connect('leave-notify-event', self._on_mouse_focus_changed)
|
| 73 | 74 |
|
| 75 |
+ # Drag and Drop
|
|
| 76 |
+ entries = [Gtk.TargetEntry.new(
|
|
| 77 |
+ 'CHAT_LIST_ITEM',
|
|
| 78 |
+ Gtk.TargetFlags.SAME_APP,
|
|
| 79 |
+ 0)]
|
|
| 80 |
+ self.drag_dest_set(
|
|
| 81 |
+ Gtk.DestDefaults.MOTION | Gtk.DestDefaults.DROP,
|
|
| 82 |
+ entries,
|
|
| 83 |
+ Gdk.DragAction.MOVE)
|
|
| 84 |
+ |
|
| 74 | 85 |
self.register_events([
|
| 75 | 86 |
('account-enabled', ged.GUI2, self._on_account_changed),
|
| 76 | 87 |
('account-disabled', ged.GUI2, self._on_account_changed),
|
| ... | ... | @@ -507,6 +518,18 @@ def __init__(self, workspace_id: str, account: str, jid: JID, type_: str, |
| 507 | 518 |
self._ui.eventbox.connect('button-press-event', self._on_button_press)
|
| 508 | 519 |
self._ui.close_button.connect('clicked', self._on_close_button_clicked)
|
| 509 | 520 |
|
| 521 |
+ # Drag and Drop
|
|
| 522 |
+ entries = [Gtk.TargetEntry.new(
|
|
| 523 |
+ 'CHAT_LIST_ITEM',
|
|
| 524 |
+ Gtk.TargetFlags.SAME_APP,
|
|
| 525 |
+ 0)]
|
|
| 526 |
+ self._ui.eventbox.drag_source_set(
|
|
| 527 |
+ Gdk.ModifierType.BUTTON1_MASK,
|
|
| 528 |
+ entries,
|
|
| 529 |
+ Gdk.DragAction.MOVE)
|
|
| 530 |
+ self._ui.eventbox.connect('drag-begin', self._on_drag_begin)
|
|
| 531 |
+ self._ui.eventbox.connect('drag-data-get', self._on_drag_data_get)
|
|
| 532 |
+ |
|
| 510 | 533 |
if self.type == 'groupchat':
|
| 511 | 534 |
self._ui.group_chat_indicator.show()
|
| 512 | 535 |
|
| ... | ... | @@ -621,6 +644,31 @@ def _popup_menu(self, event): |
| 621 | 644 |
popover.set_pointing_to(rectangle)
|
| 622 | 645 |
popover.popup()
|
| 623 | 646 |
|
| 647 |
+ def _on_drag_begin(self,
|
|
| 648 |
+ widget: Gtk.Widget,
|
|
| 649 |
+ drag_context: Gdk.DragContext
|
|
| 650 |
+ ) -> None:
|
|
| 651 |
+ # Use rendered ChatListRow as drag icon
|
|
| 652 |
+ alloc = self.get_allocation()
|
|
| 653 |
+ surface = cairo.ImageSurface(
|
|
| 654 |
+ cairo.Format.ARGB32, alloc.width, alloc.height)
|
|
| 655 |
+ context = cairo.Context(surface)
|
|
| 656 |
+ self.draw(context)
|
|
| 657 |
+ dest_x, dest_y = widget.translate_coordinates(self, 0, 0)
|
|
| 658 |
+ surface.set_device_offset(-dest_x, -dest_y)
|
|
| 659 |
+ Gtk.drag_set_icon_surface(drag_context, surface)
|
|
| 660 |
+ |
|
| 661 |
+ def _on_drag_data_get(self,
|
|
| 662 |
+ _widget: Gtk.Widget,
|
|
| 663 |
+ _drag_context: Gdk.DragContext,
|
|
| 664 |
+ selection_data: Gtk.SelectionData,
|
|
| 665 |
+ _info: int,
|
|
| 666 |
+ _time: int
|
|
| 667 |
+ ) -> None:
|
|
| 668 |
+ drop_type = Gdk.Atom.intern_static_string('CHAT_LIST_ITEM')
|
|
| 669 |
+ data = f'{self.account} {self.jid}'.encode('utf-8')
|
|
| 670 |
+ selection_data.set(drop_type, 32, data)
|
|
| 671 |
+ |
|
| 624 | 672 |
def toggle_pinned(self) -> None:
|
| 625 | 673 |
self._pinned = not self._pinned
|
| 626 | 674 |
|
| ... | ... | @@ -15,6 +15,8 @@ |
| 15 | 15 |
from typing import Any
|
| 16 | 16 |
from typing import List
|
| 17 | 17 |
|
| 18 |
+import logging
|
|
| 19 |
+ |
|
| 18 | 20 |
from gi.repository import Gdk
|
| 19 | 21 |
from gi.repository import Gio
|
| 20 | 22 |
from gi.repository import GLib
|
| ... | ... | @@ -26,6 +28,8 @@ |
| 26 | 28 |
|
| 27 | 29 |
from .util import open_window
|
| 28 | 30 |
|
| 31 |
+log = logging.getLogger('gajim.gui.workspace_sidebar')
|
|
| 32 |
+ |
|
| 29 | 33 |
|
| 30 | 34 |
class WorkspaceSideBar(Gtk.ListBox):
|
| 31 | 35 |
def __init__(self, chat_page):
|
| ... | ... | @@ -35,10 +39,16 @@ def __init__(self, chat_page): |
| 35 | 39 |
self.get_style_context().add_class('workspace-sidebar')
|
| 36 | 40 |
|
| 37 | 41 |
# Drag and Drop
|
| 38 |
- entries = [Gtk.TargetEntry.new(
|
|
| 39 |
- 'WORKSPACE_SIDEBAR_ITEM',
|
|
| 40 |
- Gtk.TargetFlags.SAME_APP,
|
|
| 41 |
- 0)]
|
|
| 42 |
+ entries = [
|
|
| 43 |
+ Gtk.TargetEntry.new(
|
|
| 44 |
+ 'WORKSPACE_SIDEBAR_ITEM',
|
|
| 45 |
+ Gtk.TargetFlags.SAME_APP,
|
|
| 46 |
+ 0),
|
|
| 47 |
+ Gtk.TargetEntry.new(
|
|
| 48 |
+ 'CHAT_LIST_ITEM',
|
|
| 49 |
+ Gtk.TargetFlags.SAME_APP,
|
|
| 50 |
+ 0)
|
|
| 51 |
+ ]
|
|
| 42 | 52 |
self.drag_dest_set(
|
| 43 | 53 |
Gtk.DestDefaults.MOTION | Gtk.DestDefaults.DROP,
|
| 44 | 54 |
entries,
|
| ... | ... | @@ -50,8 +60,6 @@ def __init__(self, chat_page): |
| 50 | 60 |
|
| 51 | 61 |
self.connect('drag-motion', self._on_drag_motion)
|
| 52 | 62 |
self.connect('drag-data-received', self._on_drag_data_received)
|
| 53 |
- self.connect('drag-leave', self._on_drag_leave)
|
|
| 54 |
- |
|
| 55 | 63 |
self.connect('row-activated', self._on_row_activated)
|
| 56 | 64 |
|
| 57 | 65 |
self.add(AddWorkspace('add'))
|
| ... | ... | @@ -63,17 +71,15 @@ def __init__(self, chat_page): |
| 63 | 71 |
self._on_chat_selected)
|
| 64 | 72 |
self._workspaces = {}
|
| 65 | 73 |
|
| 66 |
- def _on_drag_motion(self, _widget, _drag_context, _x_coord, y_coord,
|
|
| 67 |
- _time):
|
|
| 74 |
+ def _on_drag_motion(self,
|
|
| 75 |
+ _widget: Gtk.Widget,
|
|
| 76 |
+ _drag_context: Gdk.DragContext,
|
|
| 77 |
+ _x_coord: int,
|
|
| 78 |
+ y_coord: int,
|
|
| 79 |
+ _time: int
|
|
| 80 |
+ ) -> None:
|
|
| 68 | 81 |
row = self.get_row_at_y(y_coord)
|
| 69 | 82 |
|
| 70 |
- if self.row_before:
|
|
| 71 |
- self.row_before.get_style_context().remove_class(
|
|
| 72 |
- 'drag-hover-bottom')
|
|
| 73 |
- if self.row_after:
|
|
| 74 |
- self.row_after.get_style_context().remove_class(
|
|
| 75 |
- 'drag-hover-top')
|
|
| 76 |
- |
|
| 77 | 83 |
if row:
|
| 78 | 84 |
alloc = row.get_allocation()
|
| 79 | 85 |
hover_row_y = alloc.y
|
| ... | ... | @@ -91,23 +97,27 @@ def _on_drag_motion(self, _widget, _drag_context, _x_coord, y_coord, |
| 91 | 97 |
if self.drag_row in (self.row_before, self.row_after):
|
| 92 | 98 |
return False
|
| 93 | 99 |
|
| 94 |
- if self.row_before and self.row_before.workspace_id != 'add':
|
|
| 95 |
- self.row_before.get_style_context().add_class('drag-hover-bottom')
|
|
| 96 |
- if self.row_after:
|
|
| 97 |
- self.row_after.get_style_context().add_class('drag-hover-top')
|
|
| 98 | 100 |
return True
|
| 99 | 101 |
|
| 100 |
- def _on_drag_data_received(self, _widget, _drag_context, _x_coord,
|
|
| 101 |
- _y_coord, selection_data, _info, _time):
|
|
| 102 |
- if self.row_before:
|
|
| 103 |
- self.row_before.get_style_context().remove_class(
|
|
| 104 |
- 'drag-hover-bottom')
|
|
| 105 |
- if self.row_after:
|
|
| 106 |
- self.row_after.get_style_context().remove_class(
|
|
| 107 |
- 'drag-hover-top')
|
|
| 102 |
+ def _on_drag_data_received(self,
|
|
| 103 |
+ _widget: Gtk.Widget,
|
|
| 104 |
+ _drag_context: Gdk.DragContext,
|
|
| 105 |
+ _x_coord: int,
|
|
| 106 |
+ y_coord: int,
|
|
| 107 |
+ selection_data: Gtk.SelectionData,
|
|
| 108 |
+ _info: int,
|
|
| 109 |
+ _time: int
|
|
| 110 |
+ ) -> None:
|
|
| 111 |
+ data = selection_data.get_data().decode('utf-8')
|
|
| 112 |
+ item_type = selection_data.get_data_type().name()
|
|
| 113 |
+ if item_type == 'WORKSPACE_SIDEBAR_ITEM':
|
|
| 114 |
+ self._process_workspace_drop(data)
|
|
| 115 |
+ elif item_type == 'CHAT_LIST_ITEM':
|
|
| 116 |
+ self._process_chat_list_drop(data, y_coord)
|
|
| 117 |
+ else:
|
|
| 118 |
+ log.debug('Unknown item type dropped')
|
|
| 108 | 119 |
|
| 109 |
- data = selection_data.get_data()
|
|
| 110 |
- workspace_id = data.decode('utf-8')
|
|
| 120 |
+ def _process_workspace_drop(self, workspace_id: str) -> None:
|
|
| 111 | 121 |
row = self.get_workspace_by_id(workspace_id)
|
| 112 | 122 |
|
| 113 | 123 |
if row in (self.row_after, None):
|
| ... | ... | @@ -126,13 +136,15 @@ def _on_drag_data_received(self, _widget, _drag_context, _x_coord, |
| 126 | 136 |
self.store_workspace_order()
|
| 127 | 137 |
app.window.activate_workspace(workspace_id)
|
| 128 | 138 |
|
| 129 |
- def _on_drag_leave(self, _widget, _drag_context, _time):
|
|
| 130 |
- if self.row_before:
|
|
| 131 |
- self.row_before.get_style_context().remove_class(
|
|
| 132 |
- 'drag-hover-bottom')
|
|
| 133 |
- if self.row_after:
|
|
| 134 |
- self.row_after.get_style_context().remove_class(
|
|
| 135 |
- 'drag-hover-top')
|
|
| 139 |
+ def _process_chat_list_drop(self, identifier: str, y_coord: int) -> None:
|
|
| 140 |
+ account, jid = identifier.split()
|
|
| 141 |
+ workspace_row = self.get_row_at_y(y_coord)
|
|
| 142 |
+ if workspace_row.workspace_id == 'add':
|
|
| 143 |
+ return
|
|
| 144 |
+ |
|
| 145 |
+ app.window.activate_action(
|
|
| 146 |
+ 'move-chat-to-workspace',
|
|
| 147 |
+ GLib.Variant('as', [workspace_row.workspace_id, account, jid]))
|
|
| 136 | 148 |
|
| 137 | 149 |
def _get_row_before(self, row):
|
| 138 | 150 |
return self.get_row_at_index(row.get_index() - 1)
|
| ... | ... | @@ -141,7 +153,7 @@ def _get_row_after(self, row): |
| 141 | 153 |
return self.get_row_at_index(row.get_index() + 1)
|
| 142 | 154 |
|
| 143 | 155 |
def _get_last_workspace_row(self):
|
| 144 |
- # len(children) would include AddWorkspace
|
|
| 156 |
+ # Calling len(children) would include AddWorkspace
|
|
| 145 | 157 |
return self.get_row_at_index(len(self.get_children()) - 1)
|
| 146 | 158 |
|
| 147 | 159 |
def set_drag_row(self, row):
|
| ... | ... | @@ -219,8 +231,6 @@ def __init__(self, workspace_id): |
| 219 | 231 |
CommonWorkspace.__init__(self, workspace_id)
|
| 220 | 232 |
self.get_style_context().add_class('workspace-sidebar-item')
|
| 221 | 233 |
|
| 222 |
- self._workspace_id = workspace_id
|
|
| 223 |
- |
|
| 224 | 234 |
self._unread_label = Gtk.Label()
|
| 225 | 235 |
self._unread_label.get_style_context().add_class(
|
| 226 | 236 |
'unread-counter')
|
| ... | ... | @@ -286,7 +296,7 @@ def _get_workspace_menu(self) -> Gio.Menu: |
| 286 | 296 |
action, label = item
|
| 287 | 297 |
action = f'win.{action}'
|
| 288 | 298 |
menuitem = Gio.MenuItem.new(label, action)
|
| 289 |
- variant = GLib.Variant('s', self._workspace_id)
|
|
| 299 |
+ variant = GLib.Variant('s', self.workspace_id)
|
|
| 290 | 300 |
menuitem.set_action_and_target_value(action, variant)
|
| 291 | 301 |
menu.append_item(menuitem)
|
| 292 | 302 |
return menu
|