Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
poezio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
204
Issues
204
List
Boards
Labels
Service Desk
Milestones
Merge Requests
9
Merge Requests
9
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
poezio
poezio
Commits
c091e0c1
Commit
c091e0c1
authored
Oct 27, 2010
by
louiz@4325f9fc-e183-4c21-96ce-0ab188b42d13
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Command mode in roster tab, toggle offline contacts with 'o' and sort contacts by show
parent
d6e37883
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
159 additions
and
42 deletions
+159
-42
src/contact.py
src/contact.py
+8
-2
src/gui.py
src/gui.py
+1
-5
src/multiuserchat.py
src/multiuserchat.py
+0
-4
src/roster.py
src/roster.py
+72
-15
src/tab.py
src/tab.py
+56
-10
src/user.py
src/user.py
+0
-1
src/window.py
src/window.py
+22
-5
No files found.
src/contact.py
View file @
c091e0c1
...
...
@@ -14,6 +14,11 @@
# You should have received a copy of the GNU General Public License
# along with Poezio. If not, see <http://www.gnu.org/licenses/>.
"""
Defines the Resource and Contact classes
"""
from
sleekxmpp.xmlstream.stanzabase
import
JID
class
Resource
(
object
):
...
...
@@ -55,7 +60,7 @@ class Resource(object):
class
Contact
(
object
):
"""
This a way to gather multiple resources from the same bare JID.
This class contains zero or more
esource class
and useful methods
This class contains zero or more
Resource object
and useful methods
to get the resource with the highest priority, etc
"""
def
__init__
(
self
,
bare_jid
):
...
...
@@ -116,6 +121,7 @@ class Contact(object):
if
resource
.
get_jid
().
full
==
fulljid
:
return
resource
return
None
def
toggle_folded
(
self
):
"""
Fold if it's unfolded, and vice versa
...
...
@@ -148,7 +154,7 @@ class Contact(object):
def
get_resources
(
self
):
"""
Return all resources
Return all resources
, sorted by priority
"""
compare_resources
=
lambda
x
:
x
.
get_priority
()
return
sorted
(
self
.
_resources
,
key
=
compare_resources
)
...
...
src/gui.py
View file @
c091e0c1
...
...
@@ -171,8 +171,6 @@ class Gui(object):
self
.
refresh_window
()
def
on_got_offline
(
self
,
presence
):
from
common
import
debug
debug
(
'OFFLINE: %s
\n
'
%
presence
)
jid
=
presence
[
'from'
]
contact
=
self
.
roster
.
get_contact_by_jid
(
jid
.
bare
)
if
not
contact
:
...
...
@@ -185,8 +183,6 @@ class Gui(object):
self
.
refresh_window
()
def
on_got_online
(
self
,
presence
):
from
common
import
debug
debug
(
'ONLINE: %s
\n
'
%
presence
)
jid
=
presence
[
'from'
]
contact
=
self
.
roster
.
get_contact_by_jid
(
jid
.
bare
)
if
not
contact
:
...
...
@@ -537,7 +533,7 @@ class Gui(object):
Resize the whole screen
"""
with
resize_lock
:
self
.
resize_timer
=
None
#
self.resize_timer = None
for
tab
in
self
.
tabs
:
tab
.
resize
(
self
.
stdscr
)
self
.
refresh_window
()
...
...
src/multiuserchat.py
View file @
c091e0c1
...
...
@@ -22,9 +22,6 @@ import sleekxmpp
from
xml.etree
import
cElementTree
as
ET
from
common
import
debug
def
send_private_message
(
xmpp
,
jid
,
line
):
"""
Send a private message
...
...
@@ -54,7 +51,6 @@ def change_show(xmpp, jid, own_nick, show, status):
pres
[
'type'
]
=
show
if
status
:
pres
[
'status'
]
=
status
debug
(
'Change presence: %s
\n
'
%
(
pres
))
pres
.
send
()
def
change_subject
(
xmpp
,
jid
,
subject
):
...
...
src/roster.py
View file @
c091e0c1
...
...
@@ -14,6 +14,12 @@
# You should have received a copy of the GNU General Public License
# along with Poezio. If not, see <http://www.gnu.org/licenses/>.
"""
Defines the Roster and RosterGroup classes
"""
from
config
import
config
from
contact
import
Contact
,
Resource
class
Roster
(
object
):
...
...
@@ -29,9 +35,15 @@ class Roster(object):
self
.
_contacts
[
jid
]
=
contact
def
get_contact_len
(
self
):
"""
Return the number of contacts in this group
"""
return
len
(
self
.
_contacts
.
keys
())
def
get_contact_by_jid
(
self
,
jid
):
"""
Returns the contact with the given bare JID
"""
if
jid
in
self
.
_contacts
:
return
self
.
_contacts
[
jid
]
return
None
...
...
@@ -42,15 +54,15 @@ class Roster(object):
Add or remove RosterGroup if needed
"""
# add the contact to each group he is in
if
not
len
(
groups
):
# If the contact hasn't any group, we put her in
# the virtual default 'none' group
if
not
len
(
groups
):
groups
=
[
'none'
]
for
group
in
groups
:
if
group
in
contact
.
_groups
:
continue
else
:
if
group
not
in
contact
.
_groups
:
# create the group if it doesn't exist yet
contact
.
_groups
.
append
(
group
)
self
.
add_contact_to_group
(
group
,
contact
)
self
.
add_contact_to_group
(
group
,
contact
)
# remove the contact from each group he is not in
for
group
in
contact
.
_groups
:
if
group
not
in
groups
:
...
...
@@ -60,7 +72,7 @@ class Roster(object):
def
remove_contact_from_group
(
self
,
group_name
,
contact
):
"""
Remove the contact from the group.
Remove also
the group if this makes it empty
Delete
the group if this makes it empty
"""
for
group
in
self
.
_roster_groups
:
if
group
.
name
==
group_name
:
...
...
@@ -76,28 +88,40 @@ class Roster(object):
"""
for
group
in
self
.
_roster_groups
:
if
group
.
name
==
group_name
:
group
.
add_contact
(
contact
)
if
not
group
.
has_contact
(
contact
):
group
.
add_contact
(
contact
)
return
new_group
=
RosterGroup
(
group_name
)
self
.
_roster_groups
.
append
(
new_group
)
new_group
.
add_contact
(
contact
)
def
get_groups
(
self
):
"""
Returns the list of groups
"""
return
self
.
_roster_groups
def
__len__
(
self
):
"""
Return the number of line that would be printed
for the whole roster
"""
l
=
0
l
ength
=
0
for
group
in
self
.
_roster_groups
:
l
+=
1
if
group
.
get_nb_connected_contacts
()
==
0
:
continue
length
+=
1
# One for the group's line itself
if
not
group
.
folded
:
for
contact
in
group
.
get_contacts
():
l
+=
1
# We do not count the offline contacts (depending on config)
if
config
.
get
(
'roster_show_offline'
,
'false'
)
==
'false'
and
\
contact
.
get_nb_resources
()
==
0
:
continue
length
+=
1
# One for the contact's line
if
not
contact
.
_folded
:
l
+=
contact
.
get_nb_resources
()
return
l
# One for each resource, if the contact is unfolded
length
+=
contact
.
get_nb_resources
()
return
length
def
__repr__
(
self
):
ret
=
'== Roster:
\n
Contacts:
\n
'
...
...
@@ -108,6 +132,13 @@ class Roster(object):
ret
+=
'%s
\n
'
%
(
group
,)
return
ret
+
'
\n
'
PRESENCE_PRIORITY
=
{
'unavailable'
:
0
,
'xa'
:
1
,
'away'
:
2
,
'dnd'
:
3
,
''
:
4
,
'available'
:
4
}
class
RosterGroup
(
object
):
"""
A RosterGroup is a group containing contacts
...
...
@@ -122,6 +153,15 @@ class RosterGroup(object):
def
is_empty
(
self
):
return
len
(
self
.
_contacts
)
==
0
def
has_contact
(
self
,
contact
):
"""
Return a bool, telling if the contact
is already in the group
"""
if
contact
in
self
.
_contacts
:
return
True
return
False
def
remove_contact
(
self
,
contact
):
"""
Remove a Contact object to the list
...
...
@@ -139,10 +179,27 @@ class RosterGroup(object):
self
.
_contacts
.
append
(
contact
)
def
get_contacts
(
self
):
return
self
.
_contacts
def
compare_contact
(
a
):
if
not
a
.
get_highest_priority_resource
():
return
0
show
=
a
.
get_highest_priority_resource
().
get_presence
()
if
show
not
in
PRESENCE_PRIORITY
:
return
5
return
PRESENCE_PRIORITY
[
show
]
return
sorted
(
self
.
_contacts
,
key
=
compare_contact
,
reverse
=
True
)
def
toggle_folded
(
self
):
self
.
folded
=
not
self
.
folded
def
__repr__
(
self
):
return
'<Roster_group: %s; %s>'
%
(
self
.
name
,
self
.
_contacts
)
def
toggle_folded
(
self
):
self
.
folded
=
not
self
.
folded
def
__len__
(
self
):
return
len
(
self
.
_contacts
)
def
get_nb_connected_contacts
(
self
):
l
=
0
for
contact
in
self
.
_contacts
:
if
contact
.
get_highest_priority_resource
():
l
+=
1
return
l
src/tab.py
View file @
c091e0c1
...
...
@@ -28,6 +28,7 @@ MIN_HEIGHT = 16
import
window
import
theme
import
curses
from
config
import
config
from
roster
import
RosterGroup
from
contact
import
Contact
,
Resource
...
...
@@ -357,7 +358,10 @@ class PrivateTab(Tab):
def
on_gain_focus
(
self
):
self
.
_room
.
set_color_state
(
theme
.
COLOR_TAB_CURRENT
)
curses
.
curs_set
(
1
)
if
not
self
.
input
.
input_mode
:
curses
.
curs_set
(
1
)
else
:
curses
.
curs_set
(
0
)
def
on_scroll_up
(
self
):
self
.
_room
.
scroll_up
(
self
.
text_win
.
height
-
1
)
...
...
@@ -382,6 +386,16 @@ class RosterInfoTab(Tab):
A tab, splitted in two, containing the roster and infos
"""
def
__init__
(
self
,
stdscr
):
self
.
single_key_commands
=
{
"^J"
:
self
.
on_enter
,
"^M"
:
self
.
on_enter
,
"
\n
"
:
self
.
on_enter
,
' '
:
self
.
on_space
,
"/"
:
self
.
on_slash
,
"KEY_UP"
:
self
.
move_cursor_up
,
"KEY_DOWN"
:
self
.
move_cursor_down
,
"o"
:
self
.
toggle_offline_show
,
}
Tab
.
__init__
(
self
,
stdscr
)
self
.
name
=
"Roster"
roster_width
=
self
.
width
//
2
...
...
@@ -391,7 +405,7 @@ class RosterInfoTab(Tab):
self
.
info_win
=
window
.
TextWin
(
self
.
height
-
2
,
info_width
,
0
,
roster_width
+
1
,
stdscr
,
self
.
visible
)
self
.
roster_win
=
window
.
RosterWin
(
self
.
height
-
2
-
3
,
roster_width
,
0
,
0
,
stdscr
,
self
.
visible
)
self
.
contact_info_win
=
window
.
ContactInfoWin
(
3
,
roster_width
,
self
.
height
-
2
-
3
,
0
,
stdscr
,
self
.
visible
)
self
.
input
=
window
.
Input
(
1
,
self
.
width
,
self
.
height
-
1
,
0
,
stdscr
,
self
.
visible
)
self
.
input
=
window
.
Input
(
1
,
self
.
width
,
self
.
height
-
1
,
0
,
stdscr
,
self
.
visible
,
False
,
"Enter commands with “/”. “o”: toggle offline show"
)
self
.
set_color_state
(
theme
.
COLOR_TAB_NORMAL
)
def
resize
(
self
,
stdscr
):
...
...
@@ -423,12 +437,34 @@ class RosterInfoTab(Tab):
self
.
_color_state
=
color
def
on_input
(
self
,
key
):
if
key
in
(
'
\n
'
,
'^J'
,
'^M'
)
and
self
.
input
.
is_empty
():
return
self
.
on_enter
()
if
key
==
' '
:
return
self
.
on_space
()
# In writting mode
# return self.input.do_command(key)
if
self
.
input
.
input_mode
:
ret
=
self
.
input
.
do_command
(
key
)
# if the input is empty, go back to command mode
if
self
.
input
.
is_empty
():
self
.
input
.
input_mode
=
False
curses
.
curs_set
(
0
)
self
.
input
.
rewrite_text
()
return
ret
if
key
in
self
.
single_key_commands
:
return
self
.
single_key_commands
[
key
]()
def
toggle_offline_show
(
self
):
"""
Show or hide offline contacts
"""
option
=
'roster_show_offline'
if
config
.
get
(
option
,
'false'
)
==
'false'
:
config
.
set_and_save
(
option
,
'true'
)
else
:
config
.
set_and_save
(
option
,
'false'
)
return
True
def
on_slash
(
self
):
"""
'/' is pressed, we enter "input mode"
"""
self
.
input
.
input_mode
=
True
curses
.
curs_set
(
1
)
self
.
on_input
(
"/"
)
# we add the slash
def
on_lose_focus
(
self
):
self
.
_color_state
=
theme
.
COLOR_TAB_NORMAL
...
...
@@ -440,11 +476,21 @@ class RosterInfoTab(Tab):
def
add_message
(
self
):
return
False
def
on_scroll
_down
(
self
):
def
move_cursor
_down
(
self
):
self
.
roster_win
.
move_cursor_down
()
return
True
def
on_scroll
_up
(
self
):
def
move_cursor
_up
(
self
):
self
.
roster_win
.
move_cursor_up
()
return
True
def
on_scroll_down
(
self
):
# Scroll info win
pass
def
on_scroll_up
(
self
):
# Scroll info down
pass
def
on_info_win_size_changed
(
self
,
_
,
__
):
pass
...
...
src/user.py
View file @
c091e0c1
...
...
@@ -31,7 +31,6 @@ class User(object):
keep trace of an user in a Room
"""
def
__init__
(
self
,
nick
,
affiliation
,
show
,
status
,
role
):
from
common
import
debug
self
.
last_talked
=
datetime
(
1
,
1
,
1
)
# The oldest possible time
self
.
update
(
affiliation
,
show
,
status
,
role
)
self
.
change_nick
(
nick
)
...
...
src/window.py
View file @
c091e0c1
...
...
@@ -518,8 +518,11 @@ class TextWin(Win):
class
Input
(
Win
):
"""
The line where text is entered
It can be in input mode or in commmand mode.
Command mode means that single_key_commands can be entered, handled
by the Tab object, while this input just displays an help text.
"""
def
__init__
(
self
,
height
,
width
,
y
,
x
,
stdscr
,
visible
):
def
__init__
(
self
,
height
,
width
,
y
,
x
,
stdscr
,
visible
,
input_mode
=
True
,
help_text
=
''
):
self
.
key_func
=
{
"KEY_LEFT"
:
self
.
key_left
,
"M-D"
:
self
.
key_left
,
...
...
@@ -548,6 +551,8 @@ class Input(Win):
}
Win
.
__init__
(
self
,
height
,
width
,
y
,
x
,
stdscr
)
self
.
input_mode
=
input_mode
self
.
help_text
=
help_text
# the text displayed in command_mode
self
.
visible
=
visible
self
.
history
=
[]
self
.
text
=
''
...
...
@@ -875,8 +880,12 @@ class Input(Win):
"""
with
g_lock
:
self
.
clear_text
()
self
.
addstr
(
self
.
text
[
self
.
line_pos
:
self
.
line_pos
+
self
.
width
-
1
])
self
.
addstr
(
0
,
self
.
pos
,
''
)
# WTF, this works but .move() doesn't...
if
self
.
input_mode
:
self
.
addstr
(
self
.
text
[
self
.
line_pos
:
self
.
line_pos
+
self
.
width
-
1
])
else
:
self
.
addstr
(
self
.
help_text
,
curses
.
color_pair
(
theme
.
COLOR_INFORMATION_BAR
))
self
.
finish_line
(
theme
.
COLOR_INFORMATION_BAR
)
self
.
addstr
(
0
,
self
.
pos
,
''
)
# WTF, this works but .move() doesn't…
self
.
_refresh
()
def
refresh
(
self
):
...
...
@@ -928,7 +937,7 @@ class RosterWin(Win):
'chat'
:
theme
.
COLOR_STATUS_CHAT
,
'unavailable'
:
theme
.
COLOR_STATUS_UNAVAILABLE
}
# subscription_char = {'both': '
def
__init__
(
self
,
height
,
width
,
y
,
x
,
parent_win
,
visible
):
self
.
visible
=
visible
Win
.
__init__
(
self
,
height
,
width
,
y
,
x
,
parent_win
)
...
...
@@ -967,10 +976,14 @@ class RosterWin(Win):
return
with
g_lock
:
self
.
roster_len
=
len
(
roster
)
while
self
.
roster_len
and
self
.
pos
>=
self
.
roster_len
:
self
.
move_cursor_up
()
self
.
_win
.
erase
()
self
.
draw_roster_information
(
roster
)
y
=
1
for
group
in
roster
.
get_groups
():
if
group
.
get_nb_connected_contacts
()
==
0
:
continue
# Ignore empty groups
# This loop is really REALLY ugly :^)
if
y
-
1
==
self
.
pos
:
self
.
selected_row
=
group
...
...
@@ -980,6 +993,10 @@ class RosterWin(Win):
if
group
.
folded
:
continue
for
contact
in
group
.
get_contacts
():
if
config
.
get
(
'roster_show_offline'
,
'false'
)
==
'false'
and
\
contact
.
get_nb_resources
()
==
0
:
continue
if
y
-
1
==
self
.
pos
:
self
.
selected_row
=
contact
if
y
-
self
.
start_pos
+
1
==
self
.
height
:
...
...
@@ -1007,7 +1024,7 @@ class RosterWin(Win):
def
draw_plus
(
self
,
y
):
"""
Draw the indicator that shows that
the list is longer tha
t
what is displayed
the list is longer tha
n
what is displayed
"""
self
.
addstr
(
y
,
self
.
width
-
5
,
'++++'
,
curses
.
color_pair
(
42
))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment