primitivus group chat & misc
primitivus: new widget: SurroundedText (text with a character repeated around it) primitivus: new decorator LabelLine (like lineBox, but with a label on the top line) wix & primitivus & quick_app: group chat method move to quick_chat wix: when new message, window is not raised anymore, but RequestUserAttention is called instead
This commit is contained in:
parent
a21a658c33
commit
dbb3520a4f
7 changed files with 113 additions and 31 deletions
|
|
@ -22,7 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
import urwid
|
||||
from quick_frontend.quick_contact_list import QuickContactList
|
||||
from quick_frontend.quick_chat import QuickChat
|
||||
from custom_widgets import Password,List,InputDialog,ConfirmDialog,Alert,SelectableText
|
||||
from custom_widgets import Password,List,InputDialog,ConfirmDialog,Alert,SelectableText,LabelLine,SurroundedText
|
||||
|
||||
|
||||
class Chat(urwid.WidgetWrap, QuickChat):
|
||||
|
|
@ -31,8 +31,8 @@ class Chat(urwid.WidgetWrap, QuickChat):
|
|||
QuickChat.__init__(self, target, host, type)
|
||||
self.content = urwid.SimpleListWalker([])
|
||||
self.text_list = urwid.ListBox(self.content)
|
||||
main_widget = urwid.LineBox(
|
||||
urwid.Frame(self.text_list, urwid.AttrMap(urwid.Text(str(target),'center'),'title'))
|
||||
main_widget = LabelLine(
|
||||
urwid.Frame(self.text_list), SurroundedText(str(target))
|
||||
)
|
||||
urwid.WidgetWrap.__init__(self, main_widget)
|
||||
self.setType(type)
|
||||
|
|
@ -41,6 +41,12 @@ class Chat(urwid.WidgetWrap, QuickChat):
|
|||
QuickChat.setType(self, type)
|
||||
if type == 'one2one':
|
||||
self.historyPrint(profile=self.host.profile)
|
||||
|
||||
def setSubject(self, subject):
|
||||
"""Set title for a group chat"""
|
||||
QuickChat.setSubject(self, subject)
|
||||
self._w.base_widget.header = urwid.AttrMap(urwid.Text(unicode(subject),align='center'),'title')
|
||||
|
||||
|
||||
def printMessage(self, from_jid, msg, profile, timestamp=""):
|
||||
self.content.append(SelectableText("[%s] " % from_jid + msg))
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
import urwid
|
||||
from quick_frontend.quick_contact_list import QuickContactList
|
||||
from custom_widgets import Password,List,InputDialog,ConfirmDialog,Alert
|
||||
from custom_widgets import Password,List,InputDialog,ConfirmDialog,Alert,LabelLine,SurroundedText
|
||||
|
||||
|
||||
class ContactList(urwid.WidgetWrap, QuickContactList):
|
||||
|
|
@ -35,8 +35,8 @@ class ContactList(urwid.WidgetWrap, QuickContactList):
|
|||
#we now build the widget
|
||||
body_content = urwid.SimpleListWalker([self.list_wid])
|
||||
frame_body = urwid.ListBox(body_content)
|
||||
frame = urwid.Frame(frame_body,urwid.AttrMap(urwid.Text(_("Contacts"),align='center'),'title'))
|
||||
self.main_widget = urwid.LineBox(frame)
|
||||
frame = urwid.Frame(frame_body) #,urwid.AttrMap(urwid.Text(_("Contacts"),align='center'),'title'))
|
||||
self.main_widget = LabelLine(frame,SurroundedText(_("Contacts")))
|
||||
urwid.WidgetWrap.__init__(self, self.main_widget)
|
||||
if on_click:
|
||||
urwid.connect_signal(self, 'click', on_click, user_data)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
"""
|
||||
|
||||
import urwid
|
||||
from urwid.escape import utf8decode
|
||||
|
||||
class Password(urwid.Edit):
|
||||
|
||||
|
|
@ -59,7 +60,28 @@ class AdvancedEdit(urwid.Edit):
|
|||
return super(AdvancedEdit, self).keypress(size, key)
|
||||
|
||||
|
||||
class SurroundedText(urwid.FlowWidget):
|
||||
|
||||
def __init__(self,text,car=utf8decode('─')):
|
||||
self.text=text
|
||||
self.car=car
|
||||
|
||||
def rows(self,size,focus=False):
|
||||
return self.display_widget(size, focus).rows(size, focus)
|
||||
|
||||
def render(self, size, focus=False):
|
||||
return self.display_widget(size, focus).render(size, focus)
|
||||
|
||||
def display_widget(self, size, focus):
|
||||
(maxcol,) = size
|
||||
middle = (maxcol-len(self.text))/2
|
||||
render_text = middle * self.car + self.text + (maxcol - len(self.text) - middle) * self.car
|
||||
return urwid.Text(render_text)
|
||||
|
||||
|
||||
|
||||
class SelectableText(urwid.FlowWidget):
|
||||
"""Text which can be selected with space"""
|
||||
signals = ['change']
|
||||
|
||||
def __init__(self, text, align='left'):
|
||||
|
|
@ -255,9 +277,11 @@ class List(urwid.FlowWidget):
|
|||
|
||||
def displayWidget(self, size, focus):
|
||||
list_size = sum([wid.rows(size, focus) for wid in self.genericList.content])
|
||||
height = min(list_size,self.max_height)
|
||||
height = min(list_size,self.max_height) or 1
|
||||
return urwid.BoxAdapter(self.genericList, height)
|
||||
|
||||
## DIALOGS ##
|
||||
|
||||
class GenericDialog(urwid.WidgetWrap):
|
||||
|
||||
def __init__(self, widgets_lst, title, style=[], **kwargs):
|
||||
|
|
@ -286,9 +310,9 @@ class GenericDialog(urwid.WidgetWrap):
|
|||
|
||||
class InputDialog(GenericDialog):
|
||||
|
||||
def __init__(self, title, instrucions, style=['OK/CANCEL'], **kwargs):
|
||||
def __init__(self, title, instrucions, style=['OK/CANCEL'], default_txt = '', **kwargs):
|
||||
instr_wid = urwid.Text(instrucions+':')
|
||||
edit_box = urwid.Edit()
|
||||
edit_box = urwid.Edit(edit_text=default_txt)
|
||||
GenericDialog.__init__(self, [instr_wid,edit_box], title, style, ok_value=edit_box, **kwargs)
|
||||
|
||||
class ConfirmDialog(GenericDialog):
|
||||
|
|
@ -301,6 +325,8 @@ class Alert(GenericDialog):
|
|||
def __init__(self, title, message, style=['OK'], **kwargs):
|
||||
GenericDialog.__init__(self, [urwid.Text(message, 'center')], title, style, ok_value=None, **kwargs)
|
||||
|
||||
## CONTAINERS ##
|
||||
|
||||
class FocusFrame(urwid.Frame):
|
||||
"""Frame which manage "tab" key"""
|
||||
|
||||
|
|
@ -316,3 +342,12 @@ class FocusFrame(urwid.Frame):
|
|||
self.set_focus(focus_name)
|
||||
|
||||
return urwid.Frame.keypress(self, size, key)
|
||||
|
||||
## DECORATORS ##
|
||||
class LabelLine(urwid.LineBox):
|
||||
|
||||
def __init__(self, original_widget, label_widget):
|
||||
urwid.LineBox.__init__(self, original_widget)
|
||||
top_columns = self._w.widget_list[0]
|
||||
top_columns.widget_list[1] = label_widget
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import urwid
|
|||
from profile_manager import ProfileManager
|
||||
from contact_list import ContactList
|
||||
from chat import Chat
|
||||
from custom_widgets import AdvancedEdit,FocusFrame
|
||||
from custom_widgets import AdvancedEdit,FocusFrame,InputDialog,Alert
|
||||
import pdb
|
||||
"""from window import Window
|
||||
from editbox import EditBox
|
||||
|
|
@ -39,6 +39,7 @@ import logging
|
|||
from logging import debug, info, error
|
||||
#import locale
|
||||
import sys, os
|
||||
from tools.jid import JID
|
||||
#from curses import ascii
|
||||
#import locale
|
||||
#from signal import signal, SIGWINCH
|
||||
|
|
@ -104,6 +105,9 @@ class PrimitivusApp(QuickApp):
|
|||
raise urwid.ExitMainLoop()
|
||||
elif input == 'ctrl d' and 'D' in self.bridge.getVersion(): #Debug only for dev versions
|
||||
self.debug()
|
||||
elif input == 'meta j': #user wants to join a room
|
||||
pop_up_widget = InputDialog(_("Entering a MUC room"), _("Please enter MUC's JID"), default_txt = 'test@conference.necton2.int', cancel_cb=self.removePopUp, ok_cb=self.onJoinRoom)
|
||||
self.showPopUp(pop_up_widget)
|
||||
|
||||
def __buildMainWidget(self):
|
||||
self.contactList = ContactList(self, self.CM, on_click = self.contactSelected, on_change=lambda w: self.redraw())
|
||||
|
|
@ -118,7 +122,7 @@ class PrimitivusApp(QuickApp):
|
|||
self.loop.widget = self.__buildMainWidget()
|
||||
QuickApp.plug_profile(self, profile_key)
|
||||
|
||||
def removePopUp(self):
|
||||
def removePopUp(self, widget=None):
|
||||
self.loop.widget = self.main_widget
|
||||
|
||||
def showPopUp(self, pop_up_widget):
|
||||
|
|
@ -134,11 +138,26 @@ class PrimitivusApp(QuickApp):
|
|||
self.center_part.widget_list[1] = self.chat_wins[contact]
|
||||
|
||||
def onTextEntered(self, editBar):
|
||||
contact = self.contactList.get_contact()
|
||||
"""Called when text is entered in the main edit bar"""
|
||||
contact = self.contactList.get_contact() ###Based on the fact that there is currently only one contact selectableat once
|
||||
if contact:
|
||||
self.bridge.sendMessage(contact, editBar.get_edit_text(), profile_key=self.profile)
|
||||
chat = self.chat_wins[contact]
|
||||
self.bridge.sendMessage(contact,
|
||||
editBar.get_edit_text(),
|
||||
type = "groupchat" if chat.type == 'group' else "chat",
|
||||
profile_key=self.profile)
|
||||
editBar.set_edit_text('')
|
||||
|
||||
def onJoinRoom(self, button, edit):
|
||||
self.removePopUp()
|
||||
room_jid = JID(edit.get_edit_text())
|
||||
if room_jid.is_valid():
|
||||
self.bridge.joinMUC(room_jid.domain, room_jid.node, self.profiles[self.profile]['whoami'].node, self.profile)
|
||||
else:
|
||||
message = _("'%s' is an invalid JID !") % room_jid
|
||||
error (message)
|
||||
Alert(_("Error"), message, ok_cb=self.removePopUp)
|
||||
|
||||
sat = PrimitivusApp()
|
||||
sat.start()
|
||||
|
||||
|
|
|
|||
|
|
@ -40,10 +40,40 @@ class QuickChat():
|
|||
"""
|
||||
self.type = type
|
||||
|
||||
def setPresents(self, nicks):
|
||||
"""Set the users presents in the contact list for a group chat
|
||||
@param nicks: list of nicknames
|
||||
"""
|
||||
debug (_("Adding users %s to room") % nicks)
|
||||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to set presents nicks for a non group chat window"))
|
||||
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
|
||||
|
||||
def replaceUser(self, nick):
|
||||
"""Add user if it is not in the group list"""
|
||||
debug (_("Replacing user %s") % nick)
|
||||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to replace user for a non group chat window"))
|
||||
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
|
||||
|
||||
def setUserNick(self, nick):
|
||||
"""Set the nick of the user, usefull for e.g. change the color of the user"""
|
||||
self.nick = nick
|
||||
|
||||
def removeUser(self, nick):
|
||||
"""Remove a user from the group list"""
|
||||
debug(_("Removing user %s") % nick)
|
||||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to remove user for a non group chat window"))
|
||||
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
|
||||
|
||||
def setSubject(self, subject):
|
||||
"""Set title for a group chat"""
|
||||
debug(_("Setting subject to %s") % subject)
|
||||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to set subject for a non group chat window"))
|
||||
raise Exception("INTERNAL ERROR") #TODO: raise proper Exception here
|
||||
|
||||
def historyPrint(self, size=20, keep_last=False, profile='@NONE@'):
|
||||
"""Print the initial history"""
|
||||
debug (_("now we print history"))
|
||||
|
|
|
|||
|
|
@ -128,10 +128,7 @@ class Chat(wx.Frame, QuickChat):
|
|||
"""Set the users presents in the contact list for a group chat
|
||||
@param nicks: list of nicknames
|
||||
"""
|
||||
debug (_("Adding users %s to room") % nicks)
|
||||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to set presents nicks for a non group chat window"))
|
||||
return
|
||||
QuickChat.setPresents(self, nicks)
|
||||
for nick in nicks:
|
||||
self.present_panel.presents.replace(nick)
|
||||
self.occupants.add(nick)
|
||||
|
|
@ -143,27 +140,19 @@ class Chat(wx.Frame, QuickChat):
|
|||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to replace user for a non group chat window"))
|
||||
return
|
||||
self.present_panel.presents.replace(nick)
|
||||
self.occupants.add(nick)
|
||||
|
||||
QuickChat.replaceUser(self, nick)
|
||||
|
||||
def removeUser(self, nick):
|
||||
"""Remove a user from the group list"""
|
||||
debug(_("Removing user %s") % nick)
|
||||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to remove user for a non group chat window"))
|
||||
return
|
||||
QuickChat.removeUser(self, nick)
|
||||
self.present_panel.presents.remove(nick)
|
||||
self.occupants.remove(nick)
|
||||
|
||||
def setSubject(self, subject):
|
||||
"""Set title for a group chat"""
|
||||
debug(_("Setting subject to %s") % subject)
|
||||
if self.type != "group":
|
||||
error (_("[INTERNAL] trying to set subject for a non group chat window"))
|
||||
return
|
||||
QuickChat.setSubject(self, subject)
|
||||
self.subjectBox.SetValue(subject)
|
||||
|
||||
|
||||
def __eraseMenus(self):
|
||||
"""erase all menus"""
|
||||
menuBar = self.GetMenuBar()
|
||||
|
|
@ -228,7 +217,10 @@ class Chat(wx.Frame, QuickChat):
|
|||
self.chatWindow.SetDefaultStyle(wx.TextAttr("BLACK", font=_font))
|
||||
self.chatWindow.AppendText("%s\n" % msg)
|
||||
if not mymess:
|
||||
self.Raise() #FIXME: too intrusive
|
||||
#TODO: use notification system
|
||||
self.RequestUserAttention() #FIXME: do this only if in background.
|
||||
self.Show() #gof: FIXME: to check
|
||||
#self.Raise() #FIXME: too intrusive
|
||||
|
||||
### events ###
|
||||
|
||||
|
|
|
|||
|
|
@ -442,7 +442,7 @@ class MainWindow(wx.Frame, QuickApp):
|
|||
#TODO: a proper MUC room joining dialog with nickname etc
|
||||
dlg = wx.TextEntryDialog(
|
||||
self, _("Please enter MUC's JID"),
|
||||
_('Entering a MUC room'), _('test@conference.necton2.int'))
|
||||
_('Entering a MUC room'), 'test@conference.necton2.int')
|
||||
#_('Entering a MUC room'), _('room@muc_service.server.tld'))
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
room_jid=JID(dlg.GetValue())
|
||||
|
|
|
|||
Loading…
Reference in a new issue