Daniel Brötzmann pushed to branch master at gajim / gajim
Commits: 2dd4d29c by wurstsalat at 2021-12-12T18:44:28+01:00 ChatFilter: Typing
- - - - - 21c104d9 by wurstsalat at 2021-12-12T18:45:07+01:00 Features: Typing, simplify code
- - - - - ee952abe by wurstsalat at 2021-12-12T18:45:35+01:00 GroupchatInfo: Typing
- - - - - 83eb5f6c by wurstsalat at 2021-12-12T18:45:48+01:00 GroupchatNick: Typing
- - - - - 13d23b16 by wurstsalat at 2021-12-12T18:46:00+01:00 SearchView: Typing
- - - - - 1dabf2e9 by wurstsalat at 2021-12-12T18:46:17+01:00 Dialogs: Typing
- - - - - b2db91ee by wurstsalat at 2021-12-12T18:46:43+01:00 Notification: Typing
- - - - - 3cf9543c by wurstsalat at 2021-12-12T19:27:54+01:00 Archive: Typing
- - - - -
8 changed files:
- gajim/common/storage/archive.py - gajim/gtk/chat_filter.py - gajim/gtk/dialogs.py - gajim/gtk/features.py - gajim/gtk/groupchat_info.py - gajim/gtk/groupchat_nick.py - gajim/gtk/notification.py - gajim/gtk/search_view.py
Changes:
===================================== gajim/common/storage/archive.py ===================================== @@ -21,6 +21,10 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see http://www.gnu.org/licenses/.
+from typing import Any +from typing import List +from typing import Optional + import time import datetime import calendar @@ -125,7 +129,7 @@ def _namedtuple_factory(self, cursor, row): named_row = named_row._replace(account=jid) return named_row
- def _migrate(self): + def _migrate(self) -> None: user_version = self.user_version if user_version == 0: # All migrations from 0.16.9 until 1.0.0 @@ -183,7 +187,7 @@ def dispatch(event, error): app.ged.raise_event(event, None, str(error))
@staticmethod - def _get_timeout(): + def _get_timeout() -> int: """ returns the timeout in epoch """ @@ -195,11 +199,11 @@ def _get_timeout(): return timeout
@staticmethod - def _like(search_str): - return '%{}%'.format(search_str) + def _like(search_str: str) -> str: + return f'%{search_str}%'
@timeit - def _get_jid_ids_from_db(self): + def _get_jid_ids_from_db(self) -> None: """ Load all jid/jid_id tuples into a dict for faster access """ @@ -215,7 +219,7 @@ def get_jid_from_id(self, jid_id): def get_jids_in_db(self): return self._jid_ids.keys()
- def jid_is_from_pm(self, jid): + def jid_is_from_pm(self, jid: str) -> bool: """ If jid is gajim@conf/nkour it's likely a pm one, how we know gajim@conf is not a normal guy and nkour is not his resource? we ask if gajim@conf @@ -230,7 +234,7 @@ def jid_is_from_pm(self, jid): # it's not a full jid, so it's not a pm one return False
- def jid_is_room_jid(self, jid): + def jid_is_room_jid(self, jid: str) -> bool: """ Return True if it's a room jid, False if it's not, None if we don't know """ @@ -239,18 +243,25 @@ def jid_is_room_jid(self, jid): return None return jid_.type == JIDConstant.ROOM_TYPE
- def get_account_id(self, account, type_=JIDConstant.NORMAL_TYPE): + def get_account_id(self, + account: str, + type_: JIDConstant = JIDConstant.NORMAL_TYPE + ) -> int: jid = app.get_jid_from_account(account) return self.get_jid_id(jid, type_=type_)
- def get_active_account_ids(self): + def get_active_account_ids(self) -> List[int]: account_ids = [] for account in app.settings.get_active_accounts(): account_ids.append(self.get_account_id(account)) return account_ids
@timeit - def get_jid_id(self, jid, kind=None, type_=None): + def get_jid_id(self, + jid: JID, + kind: Optional[KindConstant] = None, + type_: Optional[JIDConstant] = None + ) -> int: """ Get the jid id from a jid. In case the jid id is not found create a new one. @@ -291,7 +302,8 @@ def get_jid_id(self, jid, kind=None, type_=None): return lastrowid
@staticmethod - def convert_show_values_to_db_api_values(show): + def convert_show_values_to_db_api_values(show: Optional[str] + ) -> Optional[ShowConstant]: """ Convert from string style to constant ints for db """ @@ -315,8 +327,13 @@ def convert_show_values_to_db_api_values(show): return None
@timeit - def get_conversation_before_after(self, account, jid, before, timestamp, - n_lines): + def get_conversation_before_after(self, + account: str, + jid: JID, + before: bool, + timestamp: float, + n_lines: int + ) -> List[namedtuple]: """ Load n_lines lines of conversation with jid before or after timestamp
@@ -359,8 +376,13 @@ def get_conversation_before_after(self, account, jid, before, timestamp, tuple(jids) + (timestamp, n_lines)).fetchall()
@timeit - def get_conversation_muc_before_after(self, account, jid, before, - timestamp, n_lines): + def get_conversation_muc_before_after(self, + _account: str, + jid: JID, + before: bool, + timestamp: float, + n_lines: int + ) -> List[namedtuple]: """ Load n_lines lines of conversation with jid before or after timestamp
@@ -401,7 +423,10 @@ def get_conversation_muc_before_after(self, account, jid, before, tuple(jids) + (timestamp, n_lines)).fetchall()
@timeit - def get_last_conversation_line(self, account, jid): + def get_last_conversation_line(self, + account: str, + jid: JID + ) -> List[namedtuple]: """ Load the last line of a conversation with jid for account. Loads messages, but no status messages or error messages. @@ -433,7 +458,11 @@ def get_last_conversation_line(self, account, jid): return self._con.execute(sql, tuple(jids)).fetchone()
@timeit - def get_conversation_around(self, account, jid, timestamp): + def get_conversation_around(self, + account: str, + jid: JID, + timestamp: float + ) -> List[namedtuple]: """ Load all lines of conversation with jid around a specific timestamp
@@ -561,8 +590,14 @@ def get_messages_for_date(self, account, jid, date): tuple(jids) + (date_ts, delta_ts)).fetchall()
@timeit - def search_log(self, account, jid, query, from_users=None, before=None, - after=None): + def search_log(self, + _account: str, + jid: JID, + query: str, + from_users: Optional[List[str]] = None, + before: Optional[datetime.datetime] = None, + after: Optional[datetime.datetime] = None + ) -> List[namedtuple]: """ Search the conversation log for messages containing the `query` string.
@@ -626,7 +661,12 @@ def search_log(self, account, jid, query, from_users=None, before=None, query, users, after_ts, before_ts)).fetchall()
@timeit - def search_all_logs(self, query, from_users=None, before=None, after=None): + def search_all_logs(self, + query: str, + from_users: Optional[List[str]] = None, + before: Optional[datetime.datetime] = None, + after: Optional[datetime.datetime] = None + ) -> List[namedtuple]: """ Search all conversation logs for messages containing the `query` string. @@ -682,7 +722,7 @@ def search_all_logs(self, query, from_users=None, before=None, after=None): sql, (query, users, after_ts, before_ts)).fetchall()
@timeit - def get_days_with_logs(self, account, jid, year, month): + def get_days_with_logs(self, _account, jid, year, month): """ Request the days in a month where we received messages for a given `jid`. @@ -723,7 +763,7 @@ def get_days_with_logs(self, account, jid, year, month): (date + delta).timestamp())).fetchall()
@timeit - def get_last_date_that_has_logs(self, account, jid): + def get_last_date_that_has_logs(self, _account, jid): """ Get the timestamp of the last message we received for the jid.
@@ -750,7 +790,7 @@ def get_last_date_that_has_logs(self, account, jid): return self._con.execute(sql, tuple(jids)).fetchone().time
@timeit - def get_first_date_that_has_logs(self, account, jid): + def get_first_date_that_has_logs(self, _account, jid): """ Get the timestamp of the first message we received for the jid.
@@ -777,7 +817,7 @@ def get_first_date_that_has_logs(self, account, jid): return self._con.execute(sql, tuple(jids)).fetchone().time
@timeit - def get_date_has_logs(self, account, jid, date): + def get_date_has_logs(self, _account, jid, date): """ Get single timestamp of a message we received for the jid in the time range of one day. @@ -809,8 +849,13 @@ def get_date_has_logs(self, account, jid, date): sql, tuple(jids) + (start, end)).fetchone()
@timeit - def deduplicate_muc_message(self, account, jid, resource, - timestamp, message_id): + def deduplicate_muc_message(self, + account: str, + jid: str, + resource: str, + timestamp: float, + message_id: str + ) -> bool: """ Check if a message is already in the `logs` table
@@ -857,8 +902,13 @@ def deduplicate_muc_message(self, account, jid, resource, return False
@timeit - def find_stanza_id(self, account, archive_jid, stanza_id, origin_id=None, - groupchat=False): + def find_stanza_id(self, + account: str, + archive_jid: str, + stanza_id: str, + origin_id: Optional[str] = None, + groupchat: bool = False + ) -> bool: """ Checks if a stanza-id is already in the `logs` table
@@ -916,7 +966,8 @@ def find_stanza_id(self, account, archive_jid, stanza_id, origin_id=None,
if result is not None: log.info('Found duplicated message, stanza-id: %s, origin-id: %s, ' - 'archive-jid: %s, account: %s', stanza_id, origin_id, archive_jid, account_id) + 'archive-jid: %s, account: %s', stanza_id, origin_id, + archive_jid, account_id) return True return False
@@ -1043,7 +1094,11 @@ def update_additional_data(self, sql, (serialized_dict, stanza_id, account_id, KindConstant.GC_MSG))
- def insert_jid(self, jid, kind=None, type_=JIDConstant.NORMAL_TYPE): + def insert_jid(self, + jid: str, + kind: Optional[KindConstant] = None, + type_: JIDConstant = JIDConstant.NORMAL_TYPE + ) -> int: """ Insert a new jid into the `jids` table. This is an alias of get_jid_id() for better readablility. @@ -1057,7 +1112,13 @@ def insert_jid(self, jid, kind=None, type_=JIDConstant.NORMAL_TYPE): return self.get_jid_id(jid, kind, type_)
@timeit - def insert_into_logs(self, account, jid, time_, kind, **kwargs): + def insert_into_logs(self, + account: str, + jid: str, + time_: float, + kind: KindConstant, + **kwargs: Any + ) -> int: """ Insert a new message into the `logs` table
@@ -1100,7 +1161,12 @@ def insert_into_logs(self, account, jid, time_, kind, **kwargs): return lastrowid
@timeit - def set_message_error(self, account_jid, jid, message_id, error): + def set_message_error(self, + account_jid: str, + jid: JID, + message_id: str, + error: str + ) -> None: """ Update the corresponding message with the error
@@ -1129,7 +1195,12 @@ def set_message_error(self, account_jid, jid, message_id, error): self._delayed_commit()
@timeit - def set_marker(self, account_jid, jid, message_id, state): + def set_marker(self, + account_jid: str, + jid: str, + message_id: str, + state: str + ) -> None: """ Update the marker state of the corresponding message
@@ -1234,8 +1305,11 @@ def reset_archive_infos(self, jid): log.info('Reset message archive info: %s', jid) self._delayed_commit()
- def remove_chat_history(self, account: str, jid: str, - groupchat: bool = False) -> None: + def remove_chat_history(self, + account: str, + jid: str, + groupchat: bool = False + ) -> None: """ Remove chat history for a specific chat. If it's a group chat, remove last MAM ID as well. @@ -1255,7 +1329,7 @@ def remove_chat_history(self, account: str, jid: str, self._delayed_commit() log.info('Removed chat history for: %s', jid)
- def _cleanup_chat_history(self): + def _cleanup_chat_history(self) -> None: """ Remove messages from account where messages are older than max_age """
===================================== gajim/gtk/chat_filter.py ===================================== @@ -26,7 +26,7 @@ class ChatFilter(Gtk.Box): (str, )), }
- def __init__(self, icons=False): + def __init__(self, icons: bool = False) -> None: Gtk.Box.__init__(self) self.set_halign(Gtk.Align.CENTER)
@@ -69,10 +69,10 @@ def __init__(self, icons=False): self.add(toolbar) self.show_all()
- def _on_button_clicked(self, button): + def _on_button_clicked(self, button: Gtk.Button) -> None: if button.get_active(): self.emit('filter-changed', button.get_name())
- def reset(self): + def reset(self) -> None: self._all_button.set_active(True) self.emit('filter-changed', 'all')
===================================== gajim/gtk/dialogs.py ===================================== @@ -149,7 +149,11 @@ class WarningDialog(HigDialog): HIG compliant warning dialog """
- def __init__(self, pritext, sectext='', transient_for=None): + def __init__(self, + pritext: str, + sectext: str = '', + transient_for: Optional[Gtk.Window] = None + ) -> None: if transient_for is None: transient_for = app.app.get_active_window() HigDialog.__init__(self, @@ -167,7 +171,11 @@ class InformationDialog(HigDialog): HIG compliant info dialog """
- def __init__(self, pritext, sectext='', transient_for=None): + def __init__(self, + pritext: str, + sectext: str = '', + transient_for: Optional[Gtk.Window] = None + ) -> None: if transient_for is None: transient_for = app.app.get_active_window() HigDialog.__init__(self,
===================================== gajim/gtk/features.py ===================================== @@ -19,9 +19,11 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see http://www.gnu.org/licenses/.
+from typing import NamedTuple +from typing import List + import os import sys -from collections import namedtuple
from gi.repository import Gtk from gi.repository import Gdk @@ -30,8 +32,17 @@ from gajim.common.i18n import _
+class Feature(NamedTuple): + name: str + available: bool + tooltip: str + dependency_u: str + dependency_w: str + enabled: bool + + class Features(Gtk.ApplicationWindow): - def __init__(self): + def __init__(self) -> None: Gtk.ApplicationWindow.__init__(self) self.set_application(app.app) self.set_position(Gtk.WindowPosition.CENTER) @@ -64,24 +75,21 @@ def __init__(self):
self.show_all()
- def _on_key_press(self, _widget, event): + def _on_key_press(self, + _widget: Gtk.Widget, + event: Gdk.EventButton) -> None: if event.keyval == Gdk.KEY_Escape: self.destroy()
- def _add_feature(self, feature): + def _add_feature(self, feature: Feature) -> None: item = FeatureItem(feature) self.feature_listbox.add(item) - item.get_parent().set_tooltip_text(item.tooltip)
- def _get_features(self): - Feature = namedtuple('Feature', - ['name', 'available', 'tooltip', - 'dependency_u', 'dependency_w', 'enabled']) - - notification_sounds_available = ( + def _get_features(self) -> List[Feature]: + notification_sounds_available: bool = ( app.is_installed('GSOUND') or sys.platform in ('win32', 'darwin')) - notification_sounds_enabled = app.settings.get('sounds_on') - spell_check_enabled = app.settings.get('use_speller') + notification_sounds_enabled: bool = app.settings.get('sounds_on') + spell_check_enabled: bool = app.settings.get('use_speller')
auto_status = [app.settings.get('autoaway'), app.settings.get('autoxa')] auto_status_enabled = bool(any(auto_status)) @@ -156,77 +164,67 @@ def _get_features(self): ]
@staticmethod - def _some_keyring_available(): + def _some_keyring_available() -> bool: from gajim.common import passwords return passwords.KEYRING_AVAILABLE
@staticmethod - def _idle_available(): + def _idle_available() -> bool: from gajim.common import idle return idle.Monitor.is_available()
class FeatureItem(Gtk.Grid): - def __init__(self, feature): - super().__init__() + def __init__(self, feature: Feature) -> None: + Gtk.Grid.__init__(self) self.set_column_spacing(12)
- self.tooltip = feature.tooltip - self.feature_dependency_u_text = feature.dependency_u - self.feature_dependency_w_text = feature.dependency_w + feature_label = Gtk.Label(label=feature.name) + feature_label.set_halign(Gtk.Align.START) + self._box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) + self._box.pack_start(feature_label, True, True, 0) + self._box.set_tooltip_text(feature.tooltip)
- self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) - self.feature_label = Gtk.Label(label=feature.name) - self.feature_label.set_halign(Gtk.Align.START) - self.box.pack_start(self.feature_label, True, True, 0) + feature_dependency = Gtk.Label(label=feature.dependency_u) + feature_dependency.get_style_context().add_class('dim-label')
- self.feature_dependency_u = Gtk.Label(label=feature.dependency_u) - self.feature_dependency_u.get_style_context().add_class('dim-label') - self.feature_dependency_w = Gtk.Label(label=feature.dependency_w) - self.feature_dependency_w.get_style_context().add_class('dim-label') + if os.name == 'nt': + feature_dependency.set_label(feature.dependency_w) + else: + feature_dependency.set_label(feature.dependency_u)
if not feature.available: - self.feature_dependency_u.set_halign(Gtk.Align.START) - self.feature_dependency_u.set_xalign(0.0) - self.feature_dependency_u.set_yalign(0.0) - self.feature_dependency_u.set_line_wrap(True) - self.feature_dependency_u.set_max_width_chars(50) - self.feature_dependency_u.set_selectable(True) - self.feature_dependency_w.set_halign(Gtk.Align.START) - self.feature_dependency_w.set_xalign(0.0) - self.feature_dependency_w.set_yalign(0.0) - self.feature_dependency_w.set_line_wrap(True) - self.feature_dependency_w.set_max_width_chars(50) - self.feature_dependency_w.set_selectable(True) - - if os.name == 'nt': - self.box.pack_start(self.feature_dependency_w, True, True, 0) - else: - self.box.pack_start(self.feature_dependency_u, True, True, 0) - - self.icon = Gtk.Image() - self.label_disabled = Gtk.Label(label=_('Disabled in Preferences')) - self.label_disabled.get_style_context().add_class('dim-label') - self.set_feature(feature.available, feature.enabled) - - self.add(self.icon) - self.add(self.box) - - def set_feature(self, available, enabled): - self.icon.get_style_context().remove_class('error-color') - self.icon.get_style_context().remove_class('warning-color') - self.icon.get_style_context().remove_class('success-color') + feature_dependency.set_halign(Gtk.Align.START) + feature_dependency.set_xalign(0.0) + feature_dependency.set_yalign(0.0) + feature_dependency.set_line_wrap(True) + feature_dependency.set_max_width_chars(50) + feature_dependency.set_selectable(True) + self._box.pack_start(feature_dependency, True, True, 0) + + self._icon = Gtk.Image() + self._label_disabled = Gtk.Label(label=_('Disabled in Preferences')) + self._label_disabled.get_style_context().add_class('dim-label') + self._set_feature(feature.available, feature.enabled) + + self.add(self._icon) + self.add(self._box) + + def _set_feature(self, available: bool, enabled: bool) -> None: + self._icon.get_style_context().remove_class('error-color') + self._icon.get_style_context().remove_class('warning-color') + self._icon.get_style_context().remove_class('success-color')
if not available: - self.icon.set_from_icon_name('window-close-symbolic', - Gtk.IconSize.MENU) - self.icon.get_style_context().add_class('error-color') + self._icon.set_from_icon_name( + 'window-close-symbolic', Gtk.IconSize.MENU) + self._icon.get_style_context().add_class('error-color') elif enabled is False: - self.icon.set_from_icon_name('dialog-warning-symbolic', - Gtk.IconSize.MENU) - self.box.pack_start(self.label_disabled, True, True, 0) - self.icon.get_style_context().add_class('warning-color') + self._icon.set_from_icon_name( + 'dialog-warning-symbolic', Gtk.IconSize.MENU) + self._box.pack_start(self._label_disabled, True, True, 0) + self._icon.get_style_context().add_class('warning-color') else: - self.icon.set_from_icon_name('emblem-ok-symbolic', - Gtk.IconSize.MENU) - self.icon.get_style_context().add_class('success-color') + self._icon.set_from_icon_name( + 'emblem-ok-symbolic', Gtk.IconSize.MENU) + self._icon.get_style_context().add_class('success-color')
===================================== gajim/gtk/groupchat_info.py ===================================== @@ -12,13 +12,20 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see http://www.gnu.org/licenses/.
+from typing import Any +from typing import Dict +from typing import List +from typing import Optional + import time
from gi.repository import Gdk from gi.repository import GLib from gi.repository import Gtk
+from nbxmpp import JID from nbxmpp.namespaces import Namespace +from nbxmpp.structs import DiscoInfo
from gajim.common import app from gajim.common.i18n import _ @@ -97,7 +104,10 @@
class GroupChatInfoScrolled(Gtk.ScrolledWindow): - def __init__(self, account=None, options=None): + def __init__(self, + account: Optional[str] = None, + options: Optional[Dict[str, Any]] = None + ) -> None: Gtk.ScrolledWindow.__init__(self) if options is None: options = {} @@ -116,23 +126,26 @@ def __init__(self, account=None, options=None): Gtk.PolicyType.AUTOMATIC)
self._account = account - self._info = None + self._info: Optional[DiscoInfo] = None
self._ui = get_builder('groupchat_info_scrolled.ui') self.add(self._ui.info_grid) self._ui.connect_signals(self) self.show_all()
- def get_account(self): + def get_account(self) -> str: return self._account
- def set_account(self, account): + def set_account(self, account: str) -> None: self._account = account
- def get_jid(self): + def get_jid(self) -> Optional[JID]: return self._info.jid
- def set_author(self, author, epoch_timestamp=None): + def set_author(self, + author: Optional[str], + epoch_timestamp: Optional[float] = None + ) -> None: has_author = bool(author) if has_author and epoch_timestamp is not None: time_ = time.strftime('%c', time.localtime(epoch_timestamp)) @@ -142,14 +155,14 @@ def set_author(self, author, epoch_timestamp=None): self._ui.author.set_visible(has_author) self._ui.author_label.set_visible(has_author)
- def set_subject(self, subject): + def set_subject(self, subject: str) -> None: has_subject = bool(subject) subject = GLib.markup_escape_text(subject or '') self._ui.subject.set_markup(make_href_markup(subject)) self._ui.subject.set_visible(has_subject) self._ui.subject_label.set_visible(has_subject)
- def set_from_disco_info(self, info): + def set_from_disco_info(self, info: DiscoInfo) -> None: self._info = info # Set name if self._account is None: @@ -219,7 +232,7 @@ def set_from_disco_info(self, info):
self._add_features(info.features)
- def _add_features(self, features): + def _add_features(self, features: List[str]) -> None: grid = self._ui.info_grid for row in range(30, 9, -1): # Remove everything from row 30 to 10 @@ -244,7 +257,7 @@ def _add_features(self, features): row += 1 grid.show_all()
- def _on_copy_address(self, _button): + def _on_copy_address(self, _button: Gtk.Button) -> None: clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) clipboard.set_text(f'xmpp:{self._info.jid}?join', -1)
@@ -265,7 +278,7 @@ def _on_activate_subject_link(_label, uri): return Gdk.EVENT_STOP
@staticmethod - def _get_feature_icon(icon, tooltip): + def _get_feature_icon(icon, tooltip: str) -> Gtk.Image: image = Gtk.Image.new_from_icon_name(icon, Gtk.IconSize.MENU) image.set_valign(Gtk.Align.CENTER) image.set_halign(Gtk.Align.END) @@ -273,13 +286,13 @@ def _get_feature_icon(icon, tooltip): return image
@staticmethod - def _get_feature_label(text): + def _get_feature_label(text: str) -> Gtk.Label: label = Gtk.Label(label=text, use_markup=True) label.set_halign(Gtk.Align.START) label.set_valign(Gtk.Align.START) return label
- def _get_contact_button(self, contact): + def _get_contact_button(self, contact: str) -> Gtk.Button: button = Gtk.LinkButton.new(contact) button.set_halign(Gtk.Align.START) button.get_style_context().add_class('link-button')
===================================== gajim/gtk/groupchat_nick.py ===================================== @@ -21,7 +21,7 @@
class NickChooser(Gtk.MenuButton): - def __init__(self): + def __init__(self) -> None: Gtk.MenuButton.__init__(self) self._ui = get_builder('groupchat_nick_chooser.ui') self.add(self._ui.button_content) @@ -34,24 +34,24 @@ def __init__(self): self._ui.entry.connect('changed', self._on_nickname_changed) self._ui.apply_button.connect('clicked', self._on_apply_nickname)
- def get_text(self): + def get_text(self) -> str: return self._ui.entry.get_text()
- def set_text(self, text): + def set_text(self, text: str) -> None: self._ui.entry.set_text(text) self._ui.label.set_text(text)
- def _on_nickname_button_toggled(self, _widget): + def _on_nickname_button_toggled(self, _widget: Gtk.MenuButton) -> None: self._ui.entry.grab_focus()
- def _on_nickname_changed(self, entry): + def _on_nickname_changed(self, entry: Gtk.Entry) -> None: try: validate_resourcepart(entry.get_text()) self._ui.apply_button.set_sensitive(True) except InvalidJid: self._ui.apply_button.set_sensitive(False)
- def _on_apply_nickname(self, _button): + def _on_apply_nickname(self, _button: Gtk.Button) -> None: nickname = self._ui.entry.get_text() self._ui.popover.popdown() self._ui.label.set_text(nickname)
===================================== gajim/gtk/notification.py ===================================== @@ -24,13 +24,19 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see http://www.gnu.org/licenses/.
+from typing import Dict +from typing import Optional +from typing import Tuple + import sys import logging
from gi.repository import GLib from gi.repository import Gio from gi.repository import Gdk +from gi.repository import GdkPixbuf from gi.repository import Gtk +from gi.repository import GObject
from gajim.common import app from gajim.common import ged @@ -49,7 +55,7 @@
log = logging.getLogger('gajim.gui.notification')
-NOTIFICATION_ICONS = { +NOTIFICATION_ICONS: Dict[str, str] = { 'incoming-message': 'gajim-chat_msg_recv', 'group-chat-invitation': 'gajim-gc_invitation', 'incoming-call': 'call-start-symbolic', @@ -64,9 +70,9 @@ class Notification(EventHelper): """ Handle notifications """ - def __init__(self): + def __init__(self) -> None: EventHelper.__init__(self) - self._dbus_available = False + self._dbus_available: bool = False self._daemon_capabilities = ['actions'] self._win32_active_popup = None
@@ -79,7 +85,7 @@ def __init__(self): ('connection-lost', ged.GUI2, self._on_connection_lost) ])
- def _detect_dbus_caps(self): + def _detect_dbus_caps(self) -> None: if sys.platform in ('win32', 'darwin'): return
@@ -87,7 +93,10 @@ def _detect_dbus_caps(self): self._dbus_available = True return
- def on_proxy_ready(_source, res, _data=None): + def on_proxy_ready(_source: GObject.Object, + res: Gio.AsyncResult, + _data: Optional[object] = None + ) -> None: try: proxy = Gio.DBusProxy.new_finish(res) self._daemon_capabilities = proxy.GetCapabilities() @@ -177,14 +186,15 @@ def _on_connection_lost(self, event): icon_name='gajim-connection_lost')
def _issue_notification(self, - notif_type, - account, - jid, - notif_detail='', - title='', - text='', - icon_name=None, - timeout=-1): + notif_type: str, + account: str, + jid: Optional[str], + notif_detail: str = '', + title: str = '', + text: str = '', + icon_name: Optional[str] = None, + timeout: int = -1 + ) -> None: """ Notify a user of an event using GNotification and GApplication under Linux, Use PopupNotificationWindow under Windows @@ -263,7 +273,9 @@ def _issue_notification(self, app.app.send_notification(notif_id, notification)
@staticmethod - def _get_avatar_for_notification(account, jid): + def _get_avatar_for_notification(account: str, + jid: str + ) -> GdkPixbuf.Pixbuf: scale = get_monitor_scale_factor() client = app.get_client(account) contact = client.get_module('Contacts').get_contact(jid) @@ -286,14 +298,15 @@ def _make_id(*args):
class PopupNotification(Gtk.Window): def __init__(self, - notif_type, - account, - jid, - notif_detail, - title, - text, - icon_name, - timeout): + notif_type: str, + account: str, + jid: Optional[str], + notif_detail: str, + title: str, + text: str, + icon_name: str, + timeout: int + ) -> None: Gtk.Window.__init__(self) self.set_type_hint(Gdk.WindowTypeHint.NOTIFICATION) self.set_focus_on_map(False) @@ -301,7 +314,7 @@ def __init__(self, self.set_skip_taskbar_hint(True) self.set_decorated(False)
- self._timeout_id = None + self._timeout_id: Optional[int] = None self._account = account self._jid = jid self._notif_type = notif_type @@ -334,11 +347,9 @@ def __init__(self, add_css_to_widget(self._ui.color_bar, bar_class) self._ui.color_bar.get_style_context().add_class('popup-bar')
- if title is None: - title = '' self._ui.event_type_label.set_markup(title)
- if text is None: + if not text: client = app.get_client(account) contact = client.get_module('Contacts').get_contact(jid) text = contact.name @@ -357,7 +368,7 @@ def __init__(self, self._timeout_id = GLib.timeout_add_seconds(timeout, self.destroy)
@staticmethod - def _get_window_pos(): + def _get_window_pos() -> Tuple[int, int]: pos_x = app.settings.get('notification_position_x') screen_w, screen_h = get_total_screen_geometry() if pos_x < 0: @@ -367,10 +378,13 @@ def _get_window_pos(): pos_y = screen_h - 95 - 80 + pos_y + 1 return pos_x, pos_y
- def _on_close_button_clicked(self, _widget): + def _on_close_button_clicked(self, _button: Gtk.Button) -> None: self.destroy()
- def _on_button_press(self, _widget, event): + def _on_button_press(self, + _widget: Gtk.Widget, + event: Gdk.EventButton + ) -> None: if event.button == 1: app.interface.handle_event( self._account, self._jid, self._notif_type)
===================================== gajim/gtk/search_view.py ===================================== @@ -11,13 +11,21 @@ # # You should have received a copy of the GNU General Public License # along with Gajim. If not, see http://www.gnu.org/licenses/. + +from typing import Dict +from typing import List +from typing import Optional +from typing import Tuple + import datetime import logging import time import re +from collections import namedtuple
from gi.repository import GObject from gi.repository import Gtk +import cairo
from nbxmpp import JID
@@ -43,14 +51,14 @@ class SearchView(Gtk.Box): ()), }
- def __init__(self): + def __init__(self) -> None: Gtk.Box.__init__(self) self.set_size_request(300, -1)
- self._account = None - self._jid = None - self._results = [] - self._scope = None + self._account: Optional[str] = None + self._jid: Optional[JID] = None + self._results: List[str] = [] + self._scope: Optional[str] = None
self._ui = get_builder('search_view.ui') self._ui.results_listbox.set_header_func(self._header_func) @@ -86,19 +94,19 @@ def _header_func(row, before): else: row.set_header(None)
- def _on_hide_clicked(self, _button): + def _on_hide_clicked(self, _button: Gtk.Button) -> None: self.emit('hide-search')
- def clear(self): + def clear(self) -> None: self._ui.search_entry.set_text('') self._clear_results()
- def _clear_results(self): + def _clear_results(self) -> None: for row in self._ui.results_listbox.get_children(): self._ui.results_listbox.remove(row) row.destroy()
- def _on_search(self, entry): + def _on_search(self, entry: Gtk.Entry) -> None: self._clear_results() self._ui.date_hint.hide() text = entry.get_text() @@ -162,15 +170,20 @@ def _on_search(self, entry): if has_filters is not None: filetypes = [] for filetype in has_filters: - filetypes.append(FILE_CATEGORIES.get(filetype, filetype)) - - filetypes = self._flatten(filetypes) + types = FILE_CATEGORIES.get(filetype) + if types is None: + filetypes.append(filetype) + else: + for type_ in types: + filetypes.append(type_) self._filter_results_for_files(filetypes)
self._add_counter() self._add_results()
- def _filter_results_for_files(self, filetypes): + def _filter_results_for_files(self, + filetypes: List[str] + ) -> None: if 'file' in filetypes: results = [] for result in self._results: @@ -189,7 +202,9 @@ def _filter_results_for_files(self, filetypes): self._results = results
@staticmethod - def _strip_filters(text, filter_name): + def _strip_filters(text: str, + filter_name: str + ) -> Tuple[str, Optional[List[str]]]: filters = [] start = 0 new_text = '' @@ -201,23 +216,12 @@ def _strip_filters(text, filter_name): new_text += text[start:] return new_text, filters or None
- @staticmethod - def _flatten(to_flatten): - nlist = [] - for element in to_flatten: - if isinstance(element, list): - for sub_element in element: - nlist.append(sub_element) - else: - nlist.append(element) - return nlist - - def _add_counter(self): + def _add_counter(self) -> None: results_count = len(self._results) if results_count: self._ui.results_listbox.add(CounterRow(results_count))
- def _add_results(self): + def _add_results(self) -> None: accounts = self._get_accounts() for msg in self._results[:25]: if self._scope == 'everywhere': @@ -231,14 +235,17 @@ def _add_results(self): self._ui.results_listbox.add(result_row) self._results = self._results[25:]
- def _on_edge_reached(self, _scrolledwin, pos): + def _on_edge_reached(self, + _scrolledwin: Gtk.ScrolledWindow, + pos: Gtk.PositionType + ) -> None: if pos != Gtk.PositionType.BOTTOM: return
self._add_results()
@staticmethod - def _get_accounts(): + def _get_accounts() -> Dict[str, str]: accounts = {} for account in app.settings.get_accounts(): account_id = app.storage.archive.get_account_id(account) @@ -246,7 +253,7 @@ def _get_accounts(): return accounts
@staticmethod - def _on_row_activated(_listbox, row): + def _on_row_activated(_listbox: Gtk.ListBox, row: Gtk.ListBoxRow) -> None: if row.type == 'counter': return
@@ -264,17 +271,17 @@ def _on_row_activated(_listbox, row): if control is not None: control.scroll_to_message(row.log_line_id, row.timestamp)
- def set_focus(self): + def set_focus(self) -> None: self._ui.search_entry.grab_focus()
- def set_context(self, account, jid): + def set_context(self, account: str, jid: JID) -> None: self._account = account self._jid = jid self._ui.search_checkbutton.set_active(jid is None)
class RowHeader(Gtk.Box): - def __init__(self, account, jid, timestamp): + def __init__(self, account: str, jid: JID, timestamp: float) -> None: Gtk.Box.__init__(self) self.set_hexpand(True)
@@ -293,11 +300,11 @@ def __init__(self, account, jid, timestamp):
class CounterRow(Gtk.ListBoxRow): - def __init__(self, count): + def __init__(self, count: int) -> None: Gtk.ListBoxRow.__init__(self) - self.type = 'counter' - self.jid = '' - self.time = 0 + self.type: str = 'counter' + self.jid = None + self.time: float = 0.0 self.get_style_context().add_class('search-view-counter')
if count == 1: @@ -310,7 +317,7 @@ def __init__(self, count):
class ResultRow(Gtk.ListBoxRow): - def __init__(self, msg, account, jid): + def __init__(self, msg: namedtuple, account: str, jid: JID) -> None: Gtk.ListBoxRow.__init__(self) self.account = account self.jid = jid @@ -359,7 +366,10 @@ def __init__(self, msg, account, jid):
self.show_all()
- def _get_avatar(self, kind, name): + def _get_avatar(self, + kind: str, + name: str + ) -> Optional[cairo.ImageSurface]: scale = self.get_scale_factor() if self.contact.is_groupchat: contact = self.contact.get_resource(name)
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/b12b9b5f7e809cd1fede087593257336...