~0x44/nova/extdoc

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/twisted/words/im/basechat.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
 
2
# See LICENSE for details.
 
3
 
 
4
#
 
5
 
 
6
"""Base classes for Instance Messenger clients."""
 
7
 
 
8
from twisted.words.im.locals import OFFLINE, ONLINE, AWAY
 
9
 
 
10
class ContactsList:
 
11
    """A GUI object that displays a contacts list"""
 
12
    def __init__(self, chatui):
 
13
        """
 
14
        @param chatui: ???
 
15
        @type chatui: L{ChatUI}
 
16
        """
 
17
        self.chatui = chatui
 
18
        self.contacts = {}
 
19
        self.onlineContacts = {}
 
20
        self.clients = []
 
21
 
 
22
    def setContactStatus(self, person):
 
23
        """Inform the user that a person's status has changed.
 
24
 
 
25
        @type person: L{Person<interfaces.IPerson>}
 
26
        """
 
27
        if not self.contacts.has_key(person.name):
 
28
            self.contacts[person.name] = person
 
29
        if not self.onlineContacts.has_key(person.name) and \
 
30
            (person.status == ONLINE or person.status == AWAY):
 
31
            self.onlineContacts[person.name] = person
 
32
        if self.onlineContacts.has_key(person.name) and \
 
33
           person.status == OFFLINE:
 
34
            del self.onlineContacts[person.name]
 
35
 
 
36
    def registerAccountClient(self, client):
 
37
        """Notify the user that an account client has been signed on to.
 
38
 
 
39
        @type client: L{Client<interfaces.IClient>}
 
40
        """
 
41
        if not client in self.clients:
 
42
            self.clients.append(client)
 
43
 
 
44
    def unregisterAccountClient(self, client):
 
45
        """Notify the user that an account client has been signed off
 
46
        or disconnected from.
 
47
 
 
48
        @type client: L{Client<interfaces.IClient>}
 
49
        """
 
50
        if client in self.clients:
 
51
            self.clients.remove(client)
 
52
 
 
53
    def contactChangedNick(self, person, newnick):
 
54
        oldname = person.name
 
55
        if self.contacts.has_key(oldname):
 
56
            del self.contacts[oldname]
 
57
            person.name = newnick
 
58
            self.contacts[newnick] = person
 
59
            if self.onlineContacts.has_key(oldname):
 
60
                del self.onlineContacts[oldname]
 
61
                self.onlineContacts[newnick] = person
 
62
 
 
63
 
 
64
class Conversation:
 
65
    """A GUI window of a conversation with a specific person"""
 
66
    def __init__(self, person, chatui):
 
67
        """
 
68
        @type person: L{Person<interfaces.IPerson>}
 
69
        @type chatui: L{ChatUI}
 
70
        """
 
71
        self.chatui = chatui
 
72
        self.person = person
 
73
 
 
74
    def show(self):
 
75
        """Displays the ConversationWindow"""
 
76
        raise NotImplementedError("Subclasses must implement this method")
 
77
 
 
78
    def hide(self):
 
79
        """Hides the ConversationWindow"""
 
80
        raise NotImplementedError("Subclasses must implement this method")
 
81
 
 
82
    def sendText(self, text):
 
83
        """Sends text to the person with whom the user is conversing.
 
84
 
 
85
        @returntype: L{Deferred<twisted.internet.defer.Deferred>}
 
86
        """
 
87
        self.person.sendMessage(text, None)
 
88
 
 
89
    def showMessage(self, text, metadata=None):
 
90
        """Display a message sent from the person with whom she is conversing
 
91
 
 
92
        @type text: string
 
93
        @type metadata: dict
 
94
        """
 
95
        raise NotImplementedError("Subclasses must implement this method")
 
96
 
 
97
    def contactChangedNick(self, person, newnick):
 
98
        """Change a person's name.
 
99
 
 
100
        @type person: L{Person<interfaces.IPerson>}
 
101
        @type newnick: string
 
102
        """
 
103
        self.person.name = newnick
 
104
 
 
105
 
 
106
class GroupConversation:
 
107
    """A conversation with a group of people."""
 
108
    def __init__(self, group, chatui):
 
109
        """
 
110
        @type group: L{Group<interfaces.IGroup>}
 
111
        @param chatui: ???
 
112
        @type chatui: L{ChatUI}
 
113
        """
 
114
        self.chatui = chatui
 
115
        self.group = group
 
116
        self.members = []
 
117
 
 
118
    def show(self):
 
119
        """Displays the GroupConversationWindow."""
 
120
        raise NotImplementedError("Subclasses must implement this method")
 
121
 
 
122
    def hide(self):
 
123
        """Hides the GroupConversationWindow."""
 
124
        raise NotImplementedError("Subclasses must implement this method")
 
125
 
 
126
    def sendText(self, text):
 
127
        """Sends text to the group.
 
128
 
 
129
        @type text: string
 
130
        @returntype: L{Deferred<twisted.internet.defer.Deferred>}
 
131
        """
 
132
        self.group.sendGroupMessage(text, None)
 
133
 
 
134
    def showGroupMessage(self, sender, text, metadata=None):
 
135
        """Displays to the user a message sent to this group from the given sender
 
136
        @type sender: string (XXX: Not Person?)
 
137
        @type text: string
 
138
        @type metadata: dict
 
139
        """
 
140
        raise NotImplementedError("Subclasses must implement this method")
 
141
 
 
142
    def setGroupMembers(self, members):
 
143
        """Sets the list of members in the group and displays it to the user
 
144
        """
 
145
        self.members = members
 
146
 
 
147
    def setTopic(self, topic, author):
 
148
        """Displays the topic (from the server) for the group conversation window
 
149
 
 
150
        @type topic: string
 
151
        @type author: string (XXX: Not Person?)
 
152
        """
 
153
        raise NotImplementedError("Subclasses must implement this method")
 
154
 
 
155
    def memberJoined(self, member):
 
156
        """Adds the given member to the list of members in the group conversation
 
157
        and displays this to the user
 
158
 
 
159
        @type member: string (XXX: Not Person?)
 
160
        """
 
161
        if not member in self.members:
 
162
            self.members.append(member)
 
163
 
 
164
    def memberChangedNick(self, oldnick, newnick):
 
165
        """Changes the oldnick in the list of members to newnick and displays this
 
166
        change to the user
 
167
 
 
168
        @type oldnick: string
 
169
        @type newnick: string
 
170
        """
 
171
        if oldnick in self.members:
 
172
            self.members.remove(oldnick)
 
173
            self.members.append(newnick)
 
174
            #self.chatui.contactChangedNick(oldnick, newnick)
 
175
 
 
176
    def memberLeft(self, member):
 
177
        """Deletes the given member from the list of members in the group
 
178
        conversation and displays the change to the user
 
179
 
 
180
        @type member: string
 
181
        """
 
182
        if member in self.members:
 
183
            self.members.remove(member)
 
184
 
 
185
 
 
186
class ChatUI:
 
187
    """A GUI chat client"""
 
188
    def __init__(self):
 
189
        self.conversations = {}      # cache of all direct windows
 
190
        self.groupConversations = {} # cache of all group windows
 
191
        self.persons = {}            # keys are (name, client)
 
192
        self.groups = {}             # cache of all groups
 
193
        self.onlineClients = []      # list of message sources currently online
 
194
        self.contactsList = ContactsList(self)
 
195
 
 
196
    def registerAccountClient(self, client):
 
197
        """Notifies user that an account has been signed on to.
 
198
 
 
199
        @type client: L{Client<interfaces.IClient>}
 
200
        @returns: client, so that I may be used in a callback chain
 
201
        """
 
202
        print "signing onto", client.accountName
 
203
        self.onlineClients.append(client)
 
204
        self.contactsList.registerAccountClient(client)
 
205
        return client
 
206
 
 
207
    def unregisterAccountClient(self, client):
 
208
        """Notifies user that an account has been signed off or disconnected
 
209
 
 
210
        @type client: L{Client<interfaces.IClient>}
 
211
        """
 
212
        print "signing off from", client.accountName
 
213
        self.onlineClients.remove(client)
 
214
        self.contactsList.unregisterAccountClient(client)
 
215
 
 
216
    def getContactsList(self):
 
217
        """
 
218
        @returntype: L{ContactsList}
 
219
        """
 
220
        return self.contactsList
 
221
 
 
222
    def getConversation(self, person, Class=Conversation, stayHidden=0):
 
223
        """For the given person object, returns the conversation window
 
224
        or creates and returns a new conversation window if one does not exist.
 
225
 
 
226
        @type person: L{Person<interfaces.IPerson>}
 
227
        @type Class: L{Conversation<interfaces.IConversation>} class
 
228
        @type stayHidden: boolean
 
229
 
 
230
        @returntype: L{Conversation<interfaces.IConversation>}
 
231
        """
 
232
        conv = self.conversations.get(person)
 
233
        if not conv:
 
234
            conv = Class(person, self)
 
235
            self.conversations[person] = conv
 
236
        if stayHidden:
 
237
            conv.hide()
 
238
        else:
 
239
            conv.show()
 
240
        return conv
 
241
 
 
242
    def getGroupConversation(self,group,Class=GroupConversation,stayHidden=0):
 
243
        """For the given group object, returns the group conversation window or
 
244
        creates and returns a new group conversation window if it doesn't exist
 
245
 
 
246
        @type group: L{Group<interfaces.IGroup>}
 
247
        @type Class: L{Conversation<interfaces.IConversation>} class
 
248
        @type stayHidden: boolean
 
249
 
 
250
        @returntype: L{GroupConversation<interfaces.IGroupConversation>}
 
251
        """
 
252
        conv = self.groupConversations.get(group)
 
253
        if not conv:
 
254
            conv = Class(group, self)
 
255
            self.groupConversations[group] = conv
 
256
        if stayHidden:
 
257
            conv.hide()
 
258
        else:
 
259
            conv.show()
 
260
        return conv
 
261
 
 
262
    def getPerson(self, name, client):
 
263
        """For the given name and account client, returns the instance of the
 
264
        AbstractPerson subclass, or creates and returns a new AbstractPerson
 
265
        subclass of the type Class
 
266
 
 
267
        @type name: string
 
268
        @type client: L{Client<interfaces.IClient>}
 
269
 
 
270
        @returntype: L{Person<interfaces.IPerson>}
 
271
        """
 
272
        account = client.account
 
273
        p = self.persons.get((name, account))
 
274
        if not p:
 
275
            p = account.getPerson(name)
 
276
            self.persons[name, account] = p
 
277
        return p
 
278
 
 
279
    def getGroup(self, name, client):
 
280
        """For the given name and account client, returns the instance of the
 
281
        AbstractGroup subclass, or creates and returns a new AbstractGroup
 
282
        subclass of the type Class
 
283
 
 
284
        @type name: string
 
285
        @type client: L{Client<interfaces.IClient>}
 
286
 
 
287
        @returntype: L{Group<interfaces.IGroup>}
 
288
        """
 
289
        # I accept 'client' instead of 'account' in my signature for
 
290
        # backwards compatibility.  (Groups changed to be Account-oriented
 
291
        # in CVS revision 1.8.)
 
292
        account = client.account
 
293
        g = self.groups.get((name, account))
 
294
        if not g:
 
295
            g = account.getGroup(name)
 
296
            self.groups[name, account] = g
 
297
        return g
 
298
 
 
299
    def contactChangedNick(self, oldnick, newnick):
 
300
        """For the given person, changes the person's name to newnick, and
 
301
        tells the contact list and any conversation windows with that person
 
302
        to change as well.
 
303
 
 
304
        @type oldnick: string
 
305
        @type newnick: string
 
306
        """
 
307
        if self.persons.has_key((person.name, person.account)):
 
308
            conv = self.conversations.get(person)
 
309
            if conv:
 
310
                conv.contactChangedNick(person, newnick)
 
311
 
 
312
            self.contactsList.contactChangedNick(person, newnick)
 
313
 
 
314
            del self.persons[person.name, person.account]
 
315
            person.name = newnick
 
316
            self.persons[person.name, person.account] = person