Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlovetox <philipp@hoerist.com>2022-08-18 08:14:41 +0300
committerlovetox <philipp@hoerist.com>2022-08-18 23:13:11 +0300
commit296882410ee8d45e31a4461c99a75c00d509fea9 (patch)
tree2d7f54907e5788df10ad8a6f866a140bf31ede75
parentd93f8645940174764fbffb19b603d82b85e1d7ce (diff)
-rw-r--r--gajim/common/setting_values.py15
-rw-r--r--gajim/common/settings.py31
-rw-r--r--gajim/gtk/chat_list.py94
-rw-r--r--gajim/gtk/chat_list_stack.py22
-rw-r--r--gajim/gtk/chat_page.py13
5 files changed, 141 insertions, 34 deletions
diff --git a/gajim/common/setting_values.py b/gajim/common/setting_values.py
index f18d10f28..d3f71b40b 100644
--- a/gajim/common/setting_values.py
+++ b/gajim/common/setting_values.py
@@ -508,15 +508,24 @@ StringWorkspaceSettings = Literal[
AllWorkspaceSettings = Literal[StringWorkspaceSettings, 'open_chats']
-OpenChatSettingT = list[tuple[str, JID, str, bool]]
-AllWorkspaceSettingsT = Union[str, OpenChatSettingT]
+
+class OpenChatSettingDetails(TypedDict):
+ account: str
+ jid: JID
+ type: str
+ pinned: bool
+ position: int
+
+
+OpenChatsSettingT = list[OpenChatSettingDetails]
+AllWorkspaceSettingsT = Union[str, OpenChatsSettingT]
class WorkspaceSettings(TypedDict):
name: str
color: str
avatar_sha: str
- open_chats: OpenChatSettingT
+ open_chats: OpenChatsSettingT
WORKSPACE_SETTINGS: WorkspaceSettings = {
diff --git a/gajim/common/settings.py b/gajim/common/settings.py
index 43bba70bb..f1a05a390 100644
--- a/gajim/common/settings.py
+++ b/gajim/common/settings.py
@@ -56,7 +56,7 @@ from gajim.common.setting_values import IntGroupChatSettings
from gajim.common.setting_values import StringGroupChatSettings
from gajim.common.setting_values import AllWorkspaceSettings
from gajim.common.setting_values import AllWorkspaceSettingsT
-from gajim.common.setting_values import OpenChatSettingT
+from gajim.common.setting_values import OpenChatsSettingT
from gajim.common.setting_values import StringWorkspaceSettings
from gajim.common.setting_values import ACCOUNT_SETTINGS
from gajim.common.setting_values import PROXY_SETTINGS
@@ -82,6 +82,8 @@ SETTING_TYPE = Union[bool, int, str, object]
log = logging.getLogger('gajim.c.settings')
+CURRENT_USER_VERSION = 2
+
CREATE_SQL = '''
CREATE TABLE settings (
name TEXT UNIQUE,
@@ -100,10 +102,11 @@ CREATE_SQL = '''
INSERT INTO settings(name, settings) VALUES ('plugins', '{}');
INSERT INTO settings(name, settings) VALUES ('workspaces', '%s');
- PRAGMA user_version=1;
+ PRAGMA user_version=%s;
''' % (json.dumps(STATUS_PRESET_EXAMPLES),
json.dumps(PROXY_EXAMPLES),
- json.dumps(INITAL_WORKSPACE))
+ json.dumps(INITAL_WORKSPACE),
+ CURRENT_USER_VERSION)
_SignalCallable = Callable[[Any, str, Optional[str], Optional[JID]], Any]
@@ -217,6 +220,7 @@ class Settings:
self._commit()
self._migrate_database()
self._load_app_overrides()
+ self._commit()
@staticmethod
def _setup_installation_defaults() -> None:
@@ -310,6 +314,8 @@ class Settings:
self._con.close()
log.exception('Error')
sys.exit()
+ else:
+ self._commit_settings('workspaces')
def _migrate(self) -> None:
version = self._get_user_version()
@@ -320,6 +326,21 @@ class Settings:
self._settings['workspaces'] = INITAL_WORKSPACE
self._set_user_version(1)
+ if version < 2:
+ # Migrate open chats tuple to dict
+ for workspace in self._settings['workspaces'].values():
+ open_chats = []
+ for open_chat in workspace.get('open_chats', []):
+ account, jid, type_, pinned = open_chat
+ open_chats.append({'account': account,
+ 'jid': jid,
+ 'type': type_,
+ 'pinned': pinned,
+ 'position': -1})
+
+ workspace['open_chats'] = open_chats
+ self._set_user_version(2)
+
def _migrate_old_config(self) -> None:
config_file = configpaths.get('CONFIG_FILE')
if not config_file.exists():
@@ -1175,7 +1196,7 @@ class Settings:
def set_workspace_setting(self,
workspace_id: str,
setting: Literal['open_chats'],
- value: list[tuple[str, JID, str, bool]]
+ value: OpenChatsSettingT
) -> None:
...
@@ -1202,7 +1223,7 @@ class Settings:
def get_workspace_setting(self,
workspace_id: str,
setting: Literal['open_chats']
- ) -> OpenChatSettingT:
+ ) -> OpenChatsSettingT:
...
@overload
diff --git a/gajim/gtk/chat_list.py b/gajim/gtk/chat_list.py
index 9a0424dfb..e53695a95 100644
--- a/gajim/gtk/chat_list.py
+++ b/gajim/gtk/chat_list.py
@@ -22,6 +22,7 @@ from typing import Union
import logging
import time
import pickle
+import operator
from gi.repository import Gio
from gi.repository import Gdk
@@ -47,6 +48,7 @@ from gajim.common.helpers import message_needs_highlight
from gajim.common.helpers import AdditionalDataDict
from gajim.common.preview_helpers import filename_from_uri
from gajim.common.preview_helpers import guess_simple_file_type
+from gajim.common.setting_values import OpenChatsSettingT
from gajim.common.types import ChatContactT
from gajim.common.types import OneOnOneContactT
from gajim.common.modules.contacts import BareContact
@@ -73,6 +75,7 @@ class ChatList(Gtk.ListBox, EventHelper):
self._chats: dict[tuple[str, JID], Any] = {}
self._current_filter: str = 'all'
self._current_filter_text: str = ''
+ self._chat_order: dict[tuple[str, JID], int] = {}
self.get_style_context().add_class('chatlist')
self.set_filter_func(self._filter_func)
@@ -198,9 +201,11 @@ class ChatList(Gtk.ListBox, EventHelper):
log.debug('Mouseover active, don’t sort rows')
return 0
- # Don’t sort pinned rows themselves
+ # Sort pinned rows according to stored order
if row1.is_pinned and row2.is_pinned:
- return 0
+ if row1.position > row2.position:
+ return 1
+ return -1
# Sort pinned rows to top
if row1.is_pinned > row2.is_pinned:
@@ -250,14 +255,29 @@ class ChatList(Gtk.ListBox, EventHelper):
return row.type
return None
- def add_chat(self, account: str, jid: JID, type_: str,
- pinned: bool = False) -> None:
- if self._chats.get((account, jid)) is not None:
+ def add_chat(self,
+ account: str,
+ jid: JID,
+ type_: str,
+ pinned: bool,
+ position: int
+ ) -> None:
+
+ key = (account, jid)
+ if self._chats.get(key) is not None:
# Chat is already in the List
return
- row = ChatRow(self._workspace_id, account, jid, type_, pinned)
- self._chats[(account, jid)] = row
+ row = ChatRow(self._workspace_id,
+ account,
+ jid,
+ type_,
+ pinned,
+ self._chat_order)
+
+ self._chat_order[key] = position
+ self._chats[key] = row
+
self.add(row)
def select_chat(self, account: str, jid: JID) -> None:
@@ -335,8 +355,12 @@ class ChatList(Gtk.ListBox, EventHelper):
row.toggle_pinned()
self.invalidate_sort()
- def remove_chat(self, account: str, jid: JID,
- emit_unread: bool = True) -> None:
+ def remove_chat(self,
+ account: str,
+ jid: JID,
+ emit_unread: bool = True
+ ) -> None:
+
row = self._chats.pop((account, jid))
self.remove(row)
row.destroy()
@@ -359,10 +383,15 @@ class ChatList(Gtk.ListBox, EventHelper):
def contains_chat(self, account: str, jid: JID) -> bool:
return self._chats.get((account, jid)) is not None
- def get_open_chats(self) -> list[tuple[str, JID, str, bool]]:
- open_chats: list[tuple[str, JID, str, bool]] = []
- for key, value in self._chats.items():
- open_chats.append(key + (value.type, value.is_pinned))
+ def get_open_chats(self) -> OpenChatsSettingT:
+ open_chats: OpenChatsSettingT = []
+ for key, row in self._chats.items():
+ account, jid = key
+ open_chats.append({'account': account,
+ 'jid': jid,
+ 'type': row.type,
+ 'pinned': row.is_pinned,
+ 'position': row.position})
return open_chats
def update_time(self) -> None:
@@ -534,16 +563,47 @@ class ChatList(Gtk.ListBox, EventHelper):
for row in rows:
row.update_name()
+ def _change_pinned_order(self,
+ row: ChatRow,
+ row_after: Optional[ChatRow]) -> None:
+
+ # Make list ordered by position of tuple[account, JID]
+ order = [item[0] for item in sorted(self._chat_order.items(),
+ key=operator.itemgetter(1))]
+
+ key = (row.account, row.jid)
+
+ order.remove(key)
+ if row_after is None or not row_after.is_pinned:
+ order.append(key)
+ else:
+ pos = order.index((row_after.account, row_after.jid))
+ order.insert(pos, key)
+
+ self._chat_order.clear()
+ for pos, value in enumerate(order):
+ self._chat_order[value] = pos
+
+ self.invalidate_sort()
+
class ChatRow(Gtk.ListBoxRow):
- def __init__(self, workspace_id: str, account: str, jid: JID, type_: str,
- pinned: bool) -> None:
+ def __init__(self,
+ workspace_id: str,
+ account: str,
+ jid: JID,
+ type_: str,
+ pinned: bool,
+ position: dict[tuple[str, JID], int]
+ ) -> None:
+
Gtk.ListBoxRow.__init__(self)
self.account = account
self.jid = jid
self.workspace_id = workspace_id
self.type = type_
+ self._position = position
self.active_label = ActiveHeader()
self.conversations_label = ConversationsHeader()
@@ -705,6 +765,10 @@ class ChatRow(Gtk.ListBoxRow):
def is_pinned(self) -> bool:
return self._pinned
+ @property
+ def position(self) -> int:
+ return self._position.get((self.account, self.jid), -1)
+
def _on_button_press(self,
_widget: Gtk.Widget,
event: Gdk.EventButton
diff --git a/gajim/gtk/chat_list_stack.py b/gajim/gtk/chat_list_stack.py
index 117a9f197..9e216349f 100644
--- a/gajim/gtk/chat_list_stack.py
+++ b/gajim/gtk/chat_list_stack.py
@@ -161,8 +161,10 @@ class ChatListStack(Gtk.Stack, EventHelper):
def remove_chat_list(self, workspace_id: str) -> None:
chat_list = self._chat_lists[workspace_id]
self.remove(chat_list)
- for account, jid, _type, _pinned in chat_list.get_open_chats():
- self.remove_chat(workspace_id, account, jid)
+ for open_chat in chat_list.get_open_chats():
+ self.remove_chat(workspace_id,
+ open_chat['account'],
+ open_chat['jid'])
self._chat_lists.pop(workspace_id)
chat_list.destroy()
@@ -187,12 +189,19 @@ class ChatListStack(Gtk.Stack, EventHelper):
self.set_visible_child_name(workspace_id)
- def add_chat(self, workspace_id: str, account: str, jid: JID, type_: str,
- pinned: bool = False) -> None:
+ def add_chat(self,
+ workspace_id: str,
+ account: str,
+ jid: JID,
+ type_: str,
+ pinned: bool,
+ position: int
+ ) -> None:
+
chat_list = self._chat_lists.get(workspace_id)
if chat_list is None:
chat_list = self.add_chat_list(workspace_id)
- chat_list.add_chat(account, jid, type_, pinned)
+ chat_list.add_chat(account, jid, type_, pinned, position)
def select_chat(self, account: str, jid: JID) -> None:
chat_list = self.find_chat(account, jid)
@@ -235,7 +244,8 @@ class ChatListStack(Gtk.Stack, EventHelper):
current_chatlist.remove_chat(params.account, params.jid)
new_chatlist = self.get_chatlist(workspace_id)
- new_chatlist.add_chat(params.account, params.jid, type_)
+ new_chatlist.add_chat(params.account, params.jid, type_, False, -1)
+
self.store_open_chats(current_chatlist.workspace_id)
self.store_open_chats(workspace_id)
diff --git a/gajim/gtk/chat_page.py b/gajim/gtk/chat_page.py
index ec9cdee17..63f99583a 100644
--- a/gajim/gtk/chat_page.py
+++ b/gajim/gtk/chat_page.py
@@ -221,6 +221,7 @@ class ChatPage(Gtk.Box):
jid: JID,
type_: str,
pinned: bool = False,
+ position: int = -1,
select: bool = False) -> None:
client = app.get_client(account)
@@ -240,7 +241,7 @@ class ChatPage(Gtk.Box):
return
self._chat_list_stack.add_chat(workspace_id, account, jid, type_,
- pinned)
+ pinned, position)
if self._startup_finished:
if select:
@@ -252,15 +253,17 @@ class ChatPage(Gtk.Box):
'open_chats')
active_accounts = app.settings.get_active_accounts()
- for account, jid, type_, pinned in open_chats:
+ for open_chat in open_chats:
+ account = open_chat['account']
if account not in active_accounts:
continue
self.add_chat_for_workspace(workspace_id,
account,
- jid,
- type_,
- pinned=pinned)
+ open_chat['jid'],
+ open_chat['type'],
+ pinned=open_chat['pinned'],
+ position=open_chat['position'])
def is_chat_active(self, account: str, jid: JID) -> bool:
return self._chat_list_stack.is_chat_active(account, jid)