Ticket #1201: modelfilter.2.patch
| File modelfilter.2.patch, 41.7 KB (added by asterix, 3 years ago) |
|---|
-
src/roster_window.py
30 30 import sys 31 31 import time 32 32 import urllib 33 import threading 33 34 34 35 import common.sleepy 35 36 import history_window … … 80 81 class RosterWindow: 81 82 '''Class for main window of the GTK+ interface''' 82 83 83 def get_account_iter(self, name ):84 def get_account_iter(self, name, model = None): 84 85 ''' Returns a gtk.TreeIter of accounts in roster data model or None ''' 85 model = self.tree.get_model() 86 if not model: 87 model = self.tree.get_model() 86 88 if model is None: 87 89 return 88 90 account_iter = model.get_iter_root() 89 91 if self.regroup: 90 92 return account_iter 91 93 while account_iter: 92 account_name = model[account_iter][C_ACCOUNT] .decode('utf-8')93 if name == account_name:94 account_name = model[account_iter][C_ACCOUNT] 95 if account_name and name == account_name.decode('utf-8'): 94 96 break 95 97 account_iter = model.iter_next(account_iter) 96 98 return account_iter 97 99 98 def get_group_iter(self, name, account ):100 def get_group_iter(self, name, account, model = None): 99 101 ''' Returns a gtk.TreeIter of groups in roster data model or None ''' 100 model = self.tree.get_model() 101 root = self.get_account_iter(account) 102 if not model: 103 model = self.tree.get_model() 104 root = self.get_account_iter(account, model) 102 105 group_iter = model.iter_children(root) 103 106 # C_NAME column contacts the pango escaped group name 104 107 while group_iter: … … 108 111 group_iter = model.iter_next(group_iter) 109 112 return group_iter 110 113 111 def get_contact_iter(self, jid, account ):114 def get_contact_iter(self, jid, account, model = None): 112 115 if jid == gajim.get_jid_from_account(account): 113 116 iter = self.get_self_contact_iter(account) 114 117 if iter: 115 118 return [iter] 116 119 else: 117 120 return [] 118 model = self.tree.get_model() 119 acct = self.get_account_iter(account) 121 if not model: 122 model = self.tree.get_model() 123 acct = self.get_account_iter(account, model) 120 124 found = [] 121 125 if model is None: # when closing Gajim model can be none (async pbs?) 122 126 return found … … 124 128 while group_iter: 125 129 contact_iter = model.iter_children(group_iter) 126 130 while contact_iter: 127 if jid == model[contact_iter][C_JID].decode('utf-8') and \ 131 iter_jid = model[contact_iter][C_JID] 132 if iter_jid and jid == iter_jid.decode('utf-8') and \ 128 133 account == model[contact_iter][C_ACCOUNT].decode('utf-8'): 129 134 found.append(contact_iter) 130 135 # find next contact iter … … 170 175 # show him 171 176 self.add_contact_to_roster(jid, account) 172 177 iters = self.get_contact_iter(jid, account) 178 #FIXME: adding it doesn't mean it is visible 179 if not iters: 180 return 173 181 path = self.tree.get_model().get_path(iters[0]) 174 182 if self.dragging or not gajim.config.get('scroll_roster_to_last_message'): 175 183 # do not change selection while DND'ing … … 184 192 def add_account_to_roster(self, account): 185 193 ''' Add an account to roster data model. ''' 186 194 model = self.tree.get_model() 195 child_model = model.get_model() 187 196 if self.get_account_iter(account): 188 197 return 189 198 190 199 # if we merge accounts... 191 200 if self.regroup: 192 201 show = helpers.get_global_show() 193 model.append(None, [self.jabber_state_images['16'][show],202 child_model.append(None, [self.jabber_state_images['16'][show], 194 203 _('Merged accounts'), 'account', '', 'all', None]) 195 204 self.draw_account(account) 196 205 return … … 204 213 205 214 our_jid = gajim.get_jid_from_account(account) 206 215 207 model.append(None, [self.jabber_state_images['16'][show],216 child_model.append(None, [self.jabber_state_images['16'][show], 208 217 gobject.markup_escape_text(account), 209 218 'account', our_jid, account, tls_pixbuf]) 210 219 211 220 def draw_account(self, account): 212 model = self.tree.get_model() 213 iter = self.get_account_iter(account) 221 child_iter = self.get_account_iter(account, self.model) 214 222 if self.regroup: 215 223 accounts = gajim.connections.keys() 216 224 else: … … 239 247 new_pixels += chr(128) 240 248 tls_pixbuf = gtk.gdk.pixbuf_new_from_data(new_pixels, colorspace, 241 249 True, bps, width, height, rowstride) 242 model[iter][C_SECPIXBUF] = tls_pixbuf250 self.model[child_iter][C_SECPIXBUF] = tls_pixbuf 243 251 else: 244 model[iter][C_SECPIXBUF] = None245 path = model.get_path(iter)252 self.model[child_iter][C_SECPIXBUF] = None 253 path = self.model.get_path(child_iter) 246 254 account_name = account 247 255 accounts = [account] 248 256 if self.regroup: 249 257 account_name = _('Merged accounts') 250 258 accounts = [] 251 if not self.tree.row_expanded(path) and model.iter_has_child(iter): 259 if not self.tree.row_expanded(path) and self.model.iter_has_child( 260 child_iter): 252 261 # account row not expanded 253 262 account_name = '[%s]' % account_name 254 263 if (gajim.account_is_connected(account) or (self.regroup and \ … … 257 266 nbr_on, nbr_total = gajim.contacts.get_nb_online_total_contacts( 258 267 accounts = accounts) 259 268 account_name += ' (%s/%s)' % (repr(nbr_on),repr(nbr_total)) 260 model[iter][C_NAME] = account_name269 self.model[child_iter][C_NAME] = account_name 261 270 262 271 def remove_newly_added(self, jid, account): 263 272 if jid in gajim.newly_added[account]: … … 270 279 is False, because it has online children, so we need to show it. 271 280 If add_children is True, we also add all children, even if they were not 272 281 already drawn''' 273 showOffline = gajim.config.get('showoffline')274 model = self.tree.get_model()282 model = self.modelfilter 283 child_model = model.get_model() 275 284 contact = gajim.contacts.get_first_contact_from_jid(account, jid) 276 285 nb_events = gajim.events.get_nb_roster_events(account, contact.jid) 277 286 # count events from all resources … … 289 298 self.add_self_contact(account) 290 299 return 291 300 if gajim.jid_is_transport(contact.jid): 292 # if jid is transport, check if we wanna show it in roster293 if not gajim.config.get('show_transports_group') and not nb_events:294 return295 301 contact.groups = [_('Transports')] 296 elif not showOffline and not gajim.account_is_connected(account) and \297 nb_events == 0:298 return299 302 300 # XEP-0162301 hide = contact.is_hidden_from_roster()302 if hide and contact.sub != 'from':303 return304 303 observer = contact.is_observer() 305 304 groupchat = contact.is_groupchat() 306 305 … … 309 308 tag = gajim.contacts.get_metacontacts_tag(account, jid) 310 309 if tag: 311 310 gajim.contacts.remove_metacontact(account, jid) 311 contact.groups = [_('Observers')] 312 312 313 313 # family is [{'account': acct, 'jid': jid, 'priority': prio}, ] 314 314 # 'priority' is optional … … 324 324 continue 325 325 _jid = data['jid'] 326 326 327 if self.get_contact_iter(_jid, _account ):327 if self.get_contact_iter(_jid, _account, self.model): 328 328 shown_family.append(data) 329 329 if _jid == jid and _account == account: 330 330 our_data = data … … 335 335 big_brother_account = big_brother_data['account'] 336 336 if big_brother_jid != jid or big_brother_account != account: 337 337 # We are adding a child contact 338 if contact.show in ('offline', 'error') and \ 339 not showOffline and len(gajim.events.get_events(account, jid)) == 0: 338 parent_iters = self.get_contact_iter(big_brother_jid, 339 big_brother_account, self.model) 340 if parent_iters: 341 name = contact.get_shown_name() 342 added_iters = [] 343 for child_i in parent_iters: 344 # we add some values here. see draw_contact for more 345 i_ = child_model.append(child_i, (None, name, 'contact', jid, 346 account, None)) 347 added_iters.append(i_) 348 self.draw_contact(jid, account) 349 self.draw_avatar(added_iters) 350 self.draw_account(account) 351 # Redraw parent to change icon 352 self.draw_contact(big_brother_jid, big_brother_account) 340 353 return 341 parent_iters = self.get_contact_iter(big_brother_jid,342 big_brother_account)343 name = contact.get_shown_name()344 for i in parent_iters:345 # we add some values here. see draw_contact for more346 model.append(i, (None, name, 'contact', jid, account, None))347 self.draw_contact(jid, account)348 self.draw_avatar(jid, account)349 self.draw_account(account)350 # Redraw parent to change icon351 self.draw_contact(big_brother_jid, big_brother_account)352 return353 354 354 if (contact.show in ('offline', 'error') or hide) and \355 not showOffline and (not _('Transports') in contact.groups or \356 gajim.connections[account].connected < 2) and \357 len(gajim.contacts.get_contacts(account, jid)) == 1 and nb_events == 0 and\358 not _('Not in Roster') in contact.groups:359 return360 361 355 # Remove brother contacts that are already in roster to add them 362 356 # under this iter 363 357 for data in shown_family: … … 370 364 groups = [_('Observers')] 371 365 elif not groups: 372 366 groups = [_('General')] 367 added_iters = [] 373 368 for group in groups: 374 369 self.draw_group(group, account) 375 iterG = self.get_group_iter(group, account)376 if not iterG:377 IterAcct = self.get_account_iter(account)378 iterG = model.append(IterAcct, [370 child_iterG = self.get_group_iter(group, account, self.model) 371 if not child_iterG: 372 child_iterA = self.get_account_iter(account, self.model) 373 child_iterG = self.model.append(child_iterA, [ 379 374 self.jabber_state_images['16']['closed'], 380 375 gobject.markup_escape_text(group), 'group', 381 376 group, account, None]) 382 377 self.draw_group(group, account) 383 if model.iter_n_children(IterAcct) == 1: # We added the first one 384 self.draw_account(account) 385 if group not in gajim.groups[account]: # It can probably never append 378 try: 379 iterG = model.convert_child_iter_to_iter(child_iterG) 380 except RuntimeError: 381 # group is not visible in filtered model 382 iterG = None 383 if group not in gajim.groups[account]: 386 384 if account + group in self.collapsed_rows: 387 385 ishidden = False 388 386 else: 389 387 ishidden = True 390 388 gajim.groups[account][group] = {'expand': ishidden} 391 if not account in self.collapsed_rows:389 if iterG and not account in self.collapsed_rows: 392 390 self.tree.expand_row((model.get_path(iterG)[0]), False) 393 391 394 392 typestr = 'contact' … … 399 397 400 398 name = contact.get_shown_name() 401 399 # we add some values here. see draw_contact for more 402 model.append(iterG, (None, name, typestr, contact.jid, account, None)) 400 i_ = self.model.append(child_iterG, (None, name, typestr, contact.jid, 401 account, None)) 402 added_iters.append(i_) 403 403 404 404 if gajim.groups[account][group]['expand']: 405 self.tree.expand_row(model.get_path(iterG), False) 406 self.draw_contact(jid, account) 407 self.draw_avatar(jid, account) 405 #FIXME: why do we need to recall it? because we added a child? 406 iterG = self.get_group_iter(group, account) 407 if iterG: 408 self.tree.expand_row(model.get_path(iterG), False) 409 if not self.starting: 410 self.draw_contact(jid, account) 411 self.draw_avatar(added_iters) 408 412 self.draw_account(account) 409 413 # put the children under this iter 410 414 for data in shown_family: … … 413 417 self.add_contact_to_roster(data['jid'], data['account']) 414 418 415 419 def draw_group(self, group, account): 416 iter = self.get_group_iter(group, account)417 if not iter:420 child_iter = self.get_group_iter(group, account, self.model) 421 if not child_iter: 418 422 return 419 423 if self.regroup: 420 424 accounts = [] … … 427 431 nbr_on, nbr_total = gajim.contacts.get_nb_online_total_contacts( 428 432 accounts = accounts, groups = [group]) 429 433 text += ' (%s/%s)' % (repr(nbr_on), repr(nbr_total)) 430 model = self.tree.get_model() 431 model.set_value(iter, 1 , text) 434 self.model.set_value(child_iter, 1 , gobject.markup_escape_text(text)) 432 435 433 436 def add_to_not_in_the_roster(self, account, jid, nick = '', resource = ''): 434 437 ''' add jid to group "not in the roster", he MUST not be in roster yet, … … 467 470 return contact 468 471 469 472 def get_self_contact_iter(self, account): 470 model = self.tree.get_model()471 473 iterAcct = self.get_account_iter(account) 472 iter = model.iter_children(iterAcct)474 iter = self.modelfilter.iter_children(iterAcct) 473 475 if not iter: 474 476 return None 475 if model[iter][C_TYPE] == 'self_contact':477 if self.modelfilter[iter][C_TYPE] == 'self_contact': 476 478 return iter 477 479 return None 478 480 479 481 def add_self_contact(self, account): 482 return 480 483 jid = gajim.get_jid_from_account(account) 481 if self.get_self_contact_iter(account): 484 self_contact_iter = self.get_self_contact_iter(account) 485 if self_contact_iter: 482 486 self.draw_contact(jid, account) 483 self.draw_avatar(jid, account) 487 child_iter = self.modelfilter.convert_iter_to_child_iter( 488 self_contact_iter) 489 self.draw_avatar(child_iter) 484 490 return 485 491 486 492 contact = gajim.contacts.get_first_contact_from_jid(account, jid) 487 493 if not contact: 488 494 return 489 showOffline = gajim.config.get('showoffline')490 if (contact.show in ('offline', 'error')) and not showOffline and \491 len(gajim.events.get_events(account, jid)) == 0:492 return493 495 494 496 model = self.tree.get_model() 495 iterAcct = self.get_account_iter(account) 496 model.append(iterAcct, (None, gajim.nicks[account], 'self_contact', jid, 497 account, None)) 497 iterA = self.get_account_iter(account) 498 child_model = model.get_model() 499 child_iterA = model.convert_iter_to_child_iter(iterA) 500 i_ = child_model.append(child_iterA, (None, gajim.nicks[account], 501 'self_contact', jid, account, None)) 498 502 self.draw_contact(jid, account) 499 self.draw_avatar( jid, account)503 self.draw_avatar([i_]) 500 504 501 505 def add_transport_to_roster(self, account, transport): 502 506 c = gajim.contacts.create_contact(jid = transport, name = transport, … … 511 515 return 512 516 if contact.jid in gajim.newly_added[account]: 513 517 return 514 if gajim.jid_is_transport(contact.jid) and gajim.account_is_connected(515 account) and gajim.config.get('show_transports_group'):516 # It's an agent and we show them517 return518 518 if contact.jid in gajim.to_be_removed[account]: 519 519 gajim.to_be_removed[account].remove(contact.jid) 520 # FIXME: refilter only this contact 521 # for iter in self.get_contact_iter(contact.jid, account, self.model): 522 # path = self.model.get_path(iter) 523 # doesn't work 524 # self.model.row_has_child_toggled(path, iter) 525 self.modelfilter.refilter() 520 526 527 # hide = contact.is_hidden_from_roster() 528 # 529 # show_offline = gajim.config.get('showoffline') 530 # show_transports = gajim.config.get('show_transports_group') 531 # 532 # nb_events = 0 533 # jid_list = [contact.jid] 534 # if contact.get_full_jid() != contact.jid: 535 # jid_list.append(contact.get_full_jid()) 536 # for jid in jid_list: 537 # # dont't count printed_chat messages 538 # nb_events += gajim.events.get_nb_roster_events(account, jid, ['chat']) 539 # 540 # if (_('Transports') in contact.groups and not show_transports) or \ 541 # ((contact.show in ('offline', 'error') or hide) and not show_offline and \ 542 # (not _('Transports') in contact.groups or \ 543 # gajim.account_is_disconnected(account))) and nb_events == 0: 544 # else: 545 # self.draw_contact(contact.jid, account) 521 546 522 hide = contact.is_hidden_from_roster()523 524 show_offline = gajim.config.get('showoffline')525 show_transports = gajim.config.get('show_transports_group')526 527 nb_events = 0528 jid_list = [contact.jid]529 if contact.get_full_jid() != contact.jid:530 jid_list.append(contact.get_full_jid())531 for jid in jid_list:532 # dont't count printed_chat messages533 nb_events += gajim.events.get_nb_roster_events(account, jid, ['chat'])534 535 if (_('Transports') in contact.groups and not show_transports) or \536 ((contact.show in ('offline', 'error') or hide) and not show_offline and \537 (not _('Transports') in contact.groups or \538 gajim.account_is_disconnected(account))) and nb_events == 0:539 self.remove_contact(contact, account)540 else:541 self.draw_contact(contact.jid, account)542 543 547 def remove_contact(self, contact, account): 544 548 '''Remove a contact from the roster''' 545 549 if contact.jid in gajim.to_be_removed[account]: 546 550 return 547 model = self.tree.get_model()548 iters = self.get_contact_iter(contact.jid, account )551 # look for iters in all (even not shown) iters 552 iters = self.get_contact_iter(contact.jid, account, self.model) 549 553 if not iters: 550 554 return 551 parent_iter = model.iter_parent(iters[0])552 parent_type = model[parent_iter][C_TYPE]555 parent_iter = self.model.iter_parent(iters[0]) 556 parent_type = self.model[parent_iter][C_TYPE] 553 557 # remember children to re-add them 554 558 children = [] 555 child_iter =model.iter_children(iters[0])556 while child_iter:557 c_jid = model[child_iter][C_JID].decode('utf-8')558 c_account = model[child_iter][C_ACCOUNT].decode('utf-8')559 iterC = self.model.iter_children(iters[0]) 560 while iterC: 561 c_jid = self.model[iterC][C_JID].decode('utf-8') 562 c_account = self.model[iterC][C_ACCOUNT].decode('utf-8') 559 563 children.append((c_jid, c_account)) 560 child_iter = model.iter_next(child_iter)564 iterC = self.model.iter_next(iterC) 561 565 562 566 # Remove iters and group iter if they are empty 563 567 for i in iters: 564 parent_i = model.iter_parent(i)565 model.remove(i)568 parent_i = self.model.iter_parent(i) 569 self.model.remove(i) 566 570 if parent_type == 'group': 567 group = model[parent_i][C_JID].decode('utf-8') 568 if model.iter_n_children(parent_i) == 0: 569 model.remove(parent_i) 570 # We need to check all contacts, even offline contacts 571 for jid in gajim.contacts.get_jid_list(account): 572 if group in gajim.contacts.get_contact_with_highest_priority( 573 account, jid).groups: 574 break 575 else: 576 if gajim.groups[account].has_key(group): 577 del gajim.groups[account][group] 571 group = self.model[parent_i][C_JID].decode('utf-8') 572 if self.model.iter_n_children(parent_i) == 0: 573 self.model.remove(parent_i) 574 if gajim.groups[account].has_key(group): 575 del gajim.groups[account][group] 578 576 else: 579 577 self.draw_group(group, account) 580 578 … … 583 581 self.add_contact_to_roster(child[0], child[1]) 584 582 # redraw parent 585 583 if parent_type == 'contact': 586 parent_jid = model[parent_iter][C_JID].decode('utf-8')587 parent_account = model[parent_iter][C_ACCOUNT].decode('utf-8')584 parent_jid = self.model[parent_iter][C_JID].decode('utf-8') 585 parent_account = self.model[parent_iter][C_ACCOUNT].decode('utf-8') 588 586 self.draw_contact(parent_jid, parent_account) 589 587 590 588 def get_appropriate_state_images(self, jid, size = '16', 591 icon_name = 'online'):589 icon_name = 'online'): 592 590 '''check jid and return the appropriate state images dict for 593 591 the demanded size. icon_name is taken into account when jid is from 594 592 transport: transport iconset doesn't contain all icons, so we fall back … … 603 601 def draw_contact(self, jid, account, selected = False, focus = False): 604 602 '''draw the correct state image, name BUT not avatar''' 605 603 # focus is about if the roster window has toplevel-focus or not 606 model = self.tree.get_model() 607 iters = self.get_contact_iter(jid, account) 608 if len(iters) == 0: 604 child_iters = self.get_contact_iter(jid, account, self.model) 605 if len(child_iters) == 0: 609 606 return 610 607 contact_instances = gajim.contacts.get_contacts(account, jid) 611 608 contact = gajim.contacts.get_highest_prio_contact_from_contacts( … … 653 650 if self.regroup: 654 651 add_acct = False 655 652 # look through all contacts of all accounts 656 for account_ iterin gajim.connections:657 if account_ iter== account: # useless to add accout name653 for account_ in gajim.connections: 654 if account_ == account: # useless to add accout name 658 655 continue 659 for jid_ iter in gajim.contacts.get_jid_list(account_iter):656 for jid_ in gajim.contacts.get_jid_list(account_): 660 657 # [0] cause it'fster than highest_prio 661 contact_iter = gajim.contacts.\ 662 get_first_contact_from_jid(account_iter, jid_iter) 663 if contact_iter.get_shown_name() == \ 664 contact.get_shown_name() and\ 665 (jid_iter, account_iter) != (jid, account): 658 contact_ = gajim.contacts.get_first_contact_from_jid(account_, 659 jid_) 660 if contact_.get_shown_name() == contact.get_shown_name() and \ 661 (jid_, account_) != (jid, account): 666 662 add_acct = True 667 663 break 668 664 if add_acct: … … 683 679 '\n<span size="small" style="italic" foreground="%s">%s</span>' \ 684 680 % (colorstring, gobject.markup_escape_text(status)) 685 681 686 iter = iters[0] # choose the icon with the first iter687 688 682 if gajim.gc_connected[account].has_key(jid): 689 683 contact.show = 'online' 690 model[iter][C_TYPE] = 'groupchat' 684 # There is no reason for it to be in several groups but who knows... 685 for child_iter in child_iters: 686 self.model[child_iter][C_TYPE] = 'groupchat' 691 687 692 688 icon_name = helpers.get_icon_name_to_show(contact, account) 693 689 # look if another resource has awaiting events … … 696 692 if c_icon_name in ('event', 'muc_active', 'muc_inactive'): 697 693 icon_name = c_icon_name 698 694 break 699 path = model.get_path(iter) 700 if model.iter_has_child(iter): 695 child_iters = self.get_contact_iter(jid, account, self.model) 696 child_iter = child_iters[0] # choose the icon with the first iter 697 try: 698 iter = self.modelfilter.convert_child_iter_to_iter(child_iter) 699 except RuntimeError: 700 # iter is not visible in filtered model 701 iter = None 702 if iter and self.modelfilter.iter_has_child(iter): 703 path = self.modelfilter.get_path(iter) 701 704 if not self.tree.row_expanded(path) and \ 702 705 icon_name not in ('event', 'muc_active', 'muc_inactive'): 703 child_iter = model.iter_children(iter)706 iterC = self.modelfilter.iter_children(iter) 704 707 if icon_name in ('error', 'offline'): 705 708 # get the icon from the first child as they are sorted by show 706 child_jid = model[child_iter][C_JID].decode('utf-8')707 child_account = model[child_iter][C_ACCOUNT].decode('utf-8')708 child_contact = gajim.contacts.get_contact_with_highest_priority(709 child_account, child_jid)710 child_icon_name = helpers.get_icon_name_to_show(child_contact,711 child_account)712 if child_icon_namenot in ('error', 'not in roster'):713 icon_name = child_icon_name714 while child_iter:709 jidC = self.modelfilter[iterC][C_JID].decode('utf-8') 710 accountC = self.modelfilter[iterC][C_ACCOUNT].decode( 711 'utf-8') 712 contactC = gajim.contacts.get_contact_with_highest_priority( 713 accountC, jidC) 714 icon_nameC = helpers.get_icon_name_to_show(contactC, accountC) 715 if icon_nameC not in ('error', 'not in roster'): 716 icon_name = icon_nameC 717 while iterC: 715 718 # a child has awaiting messages ? 716 child_jid = model[child_iter][C_JID].decode('utf-8')717 child_account = model[child_iter][C_ACCOUNT].decode('utf-8')718 if len(gajim.events.get_events( child_account, child_jid)):719 jidC = self.modelfilter[iterC][C_JID].decode('utf-8') 720 accountC = self.modelfilter[iterC][C_ACCOUNT].decode('utf-8') 721 if len(gajim.events.get_events(accountC, jidC)): 719 722 icon_name = 'event' 720 723 break 721 child_iter = model.iter_next(child_iter)724 iterC = self.modelfilter.iter_next(iterC) 722 725 if self.tree.row_expanded(path): 723 726 state_images = self.get_appropriate_state_images(jid, 724 727 size = 'opened', icon_name = icon_name) … … 733 736 734 737 img = state_images[icon_name] 735 738 736 for iter in iters: 737 model[iter][C_IMG] = img 738 model[iter][C_NAME] = name 739 for child_iter in child_iters: 740 gtk.gdk.threads_enter() 741 self.model[child_iter][C_IMG] = img 742 self.model[child_iter][C_NAME] = name 743 gtk.gdk.threads_leave() 739 744 740 745 def draw_parent_contact(self, jid, account): 741 model = self.tree.get_model() 742 iters = self.get_contact_iter(jid, account) 743 if not len(iters): 746 child_iters = self.get_contact_iter(jid, account, self.model) 747 if not len(child_iters): 744 748 return 745 parent_iter = model.iter_parent(iters[0])746 if model[parent_iter][C_TYPE] != 'contact':749 parent_iter = self.model.iter_parent(child_iters[0]) 750 if self.model[parent_iter][C_TYPE] != 'contact': 747 751 # parent is not a contact 748 752 return 749 parent_jid = model[parent_iter][C_JID].decode('utf-8')750 parent_account = model[parent_iter][C_ACCOUNT].decode('utf-8')753 parent_jid = self.model[parent_iter][C_JID].decode('utf-8') 754 parent_account = self.model[parent_iter][C_ACCOUNT].decode('utf-8') 751 755 self.draw_contact(parent_jid, parent_account) 752 756 753 def draw_avatar(self, jid, account): 754 '''draw the avatar''' 755 model = self.tree.get_model() 756 iters = self.get_contact_iter(jid, account) 757 def draw_avatar_from_jid(self, jid, account): 758 iters = self.get_contact_iter(jid, account, self.model) 759 self.draw_avatar(iters) 760 761 def draw_avatar(self, iters): 762 '''draw the avatar 763 iters are iters in treemodel, not treemodelfilter''' 764 if not iters: 765 return 766 jid = self.model[iters[0]][C_JID] 767 if not jid: 768 return 769 jid = jid.decode('utf-8') 757 770 if gajim.config.get('show_avatars_in_roster'): 758 771 pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(jid) 759 772 if pixbuf in ('ask', None): … … 762 775 scaled_pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'roster') 763 776 else: 764 777 scaled_pixbuf = None 765 for iter in iters:766 model[iter][C_SECPIXBUF] = scaled_pixbuf778 for child_iter in iters: 779 self.model[child_iter][C_SECPIXBUF] = scaled_pixbuf 767 780 768 781 def join_gc_room(self, account, room_jid, nick, password, minimize=False, 769 782 is_continued=False): … … 1229 1242 1230 1243 def change_roster_style(self, option): 1231 1244 model = self.tree.get_model() 1232 model.foreach(self._change_style, option) 1245 child_model = model.get_model() 1246 child_model.foreach(self._change_style, option) 1233 1247 for win in gajim.interface.msg_win_mgr.windows(): 1234 1248 win.repaint_themed_widgets() 1235 1249 1236 1250 def draw_roster(self): 1237 1251 '''clear and draw roster''' 1238 1252 # clear the model, only if it is not empty 1239 model = self.tree.get_model() 1240 if model: 1241 model.clear() 1253 if self.model: 1254 self.model.clear() 1242 1255 for acct in gajim.connections: 1243 1256 self.add_account_to_roster(acct) 1244 1257 self.add_account_contacts(acct) … … 1247 1260 1248 1261 def add_account_contacts(self, account): 1249 1262 '''adds contacts of group to roster treeview''' 1250 for jid in gajim.contacts.get_jid_list(account): 1263 c1 = time.clock() 1264 self.tree.freeze_child_notify() 1265 jids = gajim.contacts.get_jid_list(account) 1266 self.starting = True 1267 for jid in jids: 1251 1268 self.add_contact_to_roster(jid, account) 1269 self.starting = False 1270 self.tree.thaw_child_notify() 1252 1271 self.draw_account(account) 1272 def draw_contacts(jids, account): 1273 for jid in jids: 1274 self.draw_contact(jid, account) 1275 self.draw_avatar_from_jid(jid, account) 1276 time.sleep(0.01) 1253 1277 1278 t = threading.Thread(target=draw_contacts, args=(jids, account)) 1279 t.start() 1280 c4 = time.clock() 1281 print c4-c1 1282 1254 1283 def fire_up_unread_messages_events(self, account): 1255 1284 '''reads from db the unread messages, and fire them up''' 1256 1285 for jid in gajim.contacts.get_jid_list(account): … … 1275 1304 gajim.contacts.clear_contacts(account) 1276 1305 for jid in array.keys(): 1277 1306 jids = jid.split('/') 1278 # get jid1307 # get jid 1279 1308 ji = jids[0] 1280 # get resource1309 # get resource 1281 1310 resource = '' 1282 1311 if len(jids) > 1: 1283 1312 resource = '/'.join(jids[1:]) 1284 # get name1313 # get name 1285 1314 name = array[jid]['name'] 1286 1315 if not name: 1287 1316 name = '' 1288 1317 show = 'offline' # show is offline by default 1289 status = '' # no status message by default1318 status = '' # no status message by default 1290 1319 1291 1320 keyID = '' 1292 1321 attached_keys = gajim.config.get_per('accounts', account, … … 1356 1385 gajim.contacts.remove_contact(account, contact) 1357 1386 elif len(contact_instances) > 1 and contact.resource != '': 1358 1387 name += '/' + contact.resource 1359 self.remove_contact(contact, account) 1360 self.add_contact_to_roster(contact.jid, account) 1388 if gajim.contacts.has_brother(account, contact.jid): 1389 # Big brother maybe changed 1390 self.remove_contact(contact, account) 1391 self.add_contact_to_roster(contact.jid, account) 1392 else: 1393 self.draw_contact(contact.jid, account) 1361 1394 # print status in chat window and update status/GPG image 1362 1395 if gajim.interface.msg_win_mgr.has_window(contact.jid, account): 1363 1396 win = gajim.interface.msg_win_mgr.get_window(contact.jid, account) … … 1380 1413 contact.jid in gajim.interface.status_sent_to_users[account]: 1381 1414 del gajim.interface.status_sent_to_users[account][contact.jid] 1382 1415 1416 self.modelfilter.refilter() 1383 1417 if not contact.groups: 1384 1418 self.draw_group(_('General'), account) 1385 1419 else: … … 3429 3463 3430 3464 def set_connecting_state(self, account): 3431 3465 model = self.tree.get_model() 3432 accountIter = self.get_account_iter(account) 3433 if accountIter: 3434 model[accountIter][0] = self.jabber_state_images['16']['connecting'] 3466 child_model = model.get_model() 3467 IterA = self.get_account_iter(account) 3468 if IterA: 3469 child_iterA = model.convert_iter_to_child_iter(IterA) 3470 child_model[child_iterA][0] = \ 3471 self.jabber_state_images['16']['connecting'] 3435 3472 if gajim.interface.systray_enabled: 3436 3473 gajim.interface.systray.change_status('connecting') 3437 3474 3438 3475 def send_status(self, account, status, txt, auto = False, to = None): 3439 3476 model = self.tree.get_model() 3440 accountIter = self.get_account_iter(account) 3477 child_model = model.get_model() 3478 iterA = self.get_account_iter(account) 3441 3479 if status != 'offline': 3442 3480 if gajim.connections[account].connected < 2: 3443 3481 self.set_connecting_state(account) … … 3452 3490 _('Save password')) 3453 3491 passphrase, save = w.run() 3454 3492 if passphrase == -1: 3455 if accountIter: 3456 model[accountIter][0] = self.jabber_state_images['16']\ 3457 ['offline'] 3493 if iterA: 3494 child_iterA = model.convert_iter_to_child_iter(iterA) 3495 child_model[child_iterA][0] = self.jabber_state_images[ 3496 '16']['offline'] 3458 3497 if gajim.interface.systray_enabled: 3459 3498 gajim.interface.systray.change_status('offline') 3460 3499 self.update_status_combobox() … … 3775 3814 def set_account_status_icon(self, account): 3776 3815 status = gajim.connections[account].connected 3777 3816 model = self.tree.get_model() 3778 accountIter = self.get_account_iter(account) 3779 if not accountIter: 3817 child_model = model.get_model() 3818 iterA = self.get_account_iter(account) 3819 if not iterA: 3780 3820 return 3821 child_iterA = model.convert_iter_to_child_iter(iterA) 3781 3822 if not self.regroup: 3782 3823 show = gajim.SHOW_LIST[status] 3783 3824 else: # accounts merged 3784 3825 show = helpers.get_global_show() 3785 model[accountIter][C_IMG] = self.jabber_state_images['16'][show]3826 child_model[child_iterA][C_IMG] = self.jabber_state_images['16'][show] 3786 3827 3787 3828 def on_status_changed(self, account, status): 3788 3829 '''the core tells us that our status has changed''' 3789 3830 if account not in gajim.contacts.get_accounts(): 3790 3831 return 3791 3832 model = self.tree.get_model() 3792 accountIter = self.get_account_iter(account) 3833 child_model = model.get_model() 3834 iterA = self.get_account_iter(account) 3835 child_iterA = model.convert_iter_to_child_iter(iterA) 3793 3836 self.set_account_status_icon(account) 3794 3837 if status == 'offline': 3795 3838 if self.quit_on_next_offline > -1: 3796 3839 self.quit_on_next_offline -= 1 3797 3840 if self.quit_on_next_offline < 1: 3798 3841 self.quit_gtkgui_interface() 3799 else: 3800 # No need to redraw contacts if we're quitting 3801 if accountIter: 3802 model[accountIter][C_SECPIXBUF] = None 3803 if gajim.con_types.has_key(account): 3804 gajim.con_types[account] = None 3805 for jid in gajim.contacts.get_jid_list(account): 3806 lcontact = gajim.contacts.get_contacts(account, jid) 3807 lcontact_copy = [] 3808 for contact in lcontact: 3809 lcontact_copy.append(contact) 3810 for contact in lcontact_copy: 3811 self.chg_contact_status(contact, 'offline', '', account) 3842 return # No need to update GUI, we're quitting 3843 if iterA: 3844 child_model[child_iterA][C_SECPIXBUF] = None 3845 if gajim.con_types.has_key(account): 3846 gajim.con_types[account] = None 3847 for jid in gajim.contacts.get_jid_list(account): 3848 lcontact = gajim.contacts.get_contacts(account, jid) 3849 lcontact_copy = [] 3850 for contact in lcontact: 3851 lcontact_copy.append(contact) 3852 for contact in lcontact_copy: 3853 self.chg_contact_status(contact, 'offline', '', account) 3812 3854 self.actions_menu_needs_rebuild = True 3813 3855 self.update_status_combobox() 3814 3856 # Force the rebuild now since the on_activates on the menu itself does … … 3852 3894 3853 3895 def new_chat_from_jid(self, account, fjid): 3854 3896 jid, resource = gajim.get_room_and_nick_from_fjid(fjid) 3855 if resource: 3856 contact = gajim.contacts.get_contact(account, jid, resource) 3857 else: 3858 contact = gajim.contacts.get_contact_with_highest_priority(account, 3859 jid) 3897 contact = gajim.contacts.get_contact(account, jid, resource) 3860 3898 added_to_roster = False 3861 3899 if not contact: 3862 3900 added_to_roster = True … … 4056 4094 4057 4095 def on_show_transports_menuitem_activate(self, widget): 4058 4096 gajim.config.set('show_transports_group', widget.get_active()) 4059 self. draw_roster()4097 self.tree.get_model().refilter() 4060 4098 4061 4099 def on_manage_bookmarks_menuitem_activate(self, widget): 4062 4100 config.ManageBookmarksWindow() … … 4354 4392 def on_roster_treeview_row_expanded(self, widget, iter, path): 4355 4393 '''When a row is expanded change the icon of the arrow''' 4356 4394 model = self.tree.get_model() 4395 child_model = model.get_model() 4396 child_iter = model.convert_iter_to_child_iter(iter) 4357 4397 if self.regroup: # merged accounts 4358 4398 accounts = gajim.connections.keys() 4359 4399 else: 4360 4400 accounts = [model[iter][C_ACCOUNT].decode('utf-8')] 4361 4401 type_ = model[iter][C_TYPE] 4362 4402 if type_ == 'group': 4363 model.set_value(iter, 0, self.jabber_state_images['16']['opened']) 4403 child_model[child_iter][C_IMG] = self.jabber_state_images['16'][ 4404 'opened'] 4364 4405 jid = model[iter][C_JID].decode('utf-8') 4365 4406 for account in accounts: 4366 4407 if gajim.groups[account].has_key(jid): # This account has this group … … 4386 4427 '''When a row is collapsed : 4387 4428 change the icon of the arrow''' 4388 4429 model = self.tree.get_model() 4430 child_model = model.get_model() 4431 child_iter = model.convert_iter_to_child_iter(iter) 4389 4432 if self.regroup: # merged accounts 4390 4433 accounts = gajim.connections.keys() 4391 4434 else: 4392 4435 accounts = [model[iter][C_ACCOUNT].decode('utf-8')] 4393 4436 type_ = model[iter][C_TYPE] 4394 4437 if type_ == 'group': 4395 model.set_value(iter, 0, self.jabber_state_images['16']['closed']) 4438 child_model[child_iter][C_IMG] = self.jabber_state_images['16'][ 4439 'closed'] 4396 4440 jid = model[iter][C_JID].decode('utf-8') 4397 4441 for account in accounts: 4398 4442 if gajim.groups[account].has_key(jid): # This account has this group … … 4409 4453 account = model[iter][C_ACCOUNT].decode('utf-8') 4410 4454 self.draw_contact(jid, account) 4411 4455 4456 def on_model_row_has_child_toggled(self, model, path, iter): 4457 '''When we add child, look if we have to expand parent''' 4458 iter_parent = model.iter_parent(iter) 4459 if not iter_parent: 4460 # it's an account row, nothing to do 4461 return 4462 type_ = model[iter][C_TYPE] 4463 account = model[iter][C_ACCOUNT] 4464 if not account: 4465 return 4466 account = account.decode('utf-8') 4467 if type_ == 'group' and not account in self.collapsed_rows: 4468 # expand account row 4469 self.tree.expand_row(path[:-1], False) 4470 else: 4471 group = model[iter_parent][C_JID].decode('utf-8') 4472 if not account + group in self.collapsed_rows: 4473 self.tree.expand_row(path[:-1], False) 4474 # print ' has_child', model.iter_has_child(iter) 4475 # child_iter = model.convert_iter_to_child_iter(iter) 4476 # print ' expanded', self.model. 4477 4412 4478 def on_service_disco_menuitem_activate(self, widget, account): 4413 4479 server_jid = gajim.config.get_per('accounts', account, 'hostname') 4414 4480 if gajim.interface.instances[account]['disco'].has_key(server_jid): … … 4561 4627 '''when show offline option is changed: 4562 4628 redraw the treeview''' 4563 4629 gajim.config.set('showoffline', not gajim.config.get('showoffline')) 4564 self. draw_roster()4630 self.modelfilter.refilter() 4565 4631 4566 4632 def set_renderer_color(self, renderer, style, set_background = True): 4567 4633 '''set style for treeview cell, using PRELIGHT system color''' … … 4731 4797 show = u.show 4732 4798 return show 4733 4799 4800 def contact_is_visible(self, contact, account): 4801 # show it if pending events 4802 if gajim.events.get_nb_roster_events(account, contact.jid) > 0: 4803 return True 4804 # count events from all resources 4805 for contact_ in gajim.contacts.get_contacts(account, contact.jid): 4806 if contact_.resource and gajim.events.get_nb_roster_events(account, 4807 contact_.get_full_jid()) > 0: 4808 return True 4809 # XEP-0162 4810 hide = contact.is_hidden_from_roster() 4811 if hide and contact.sub != 'from': 4812 return False 4813 4814 showOffline = gajim.config.get('showoffline') 4815 if (contact.show in ('offline', 'error') or hide) and not showOffline: 4816 if contact.jid in gajim.to_be_removed[account]: 4817 return True 4818 return False 4819 return True 4820 4821 def visible_func(self, model, iter): 4822 type_ = model[iter][C_TYPE] 4823 if not type_: 4824 return False 4825 if type_ == 'account': 4826 return True 4827 account = model[iter][C_ACCOUNT] 4828 if not account: 4829 return False 4830 account = account.decode('utf-8') 4831 jid = model[iter][C_JID] 4832 if not jid: 4833 return False 4834 jid = jid.decode('utf-8') 4835 if type_ == 'group': 4836 group = jid 4837 if group == _('Transports'): 4838 return gajim.config.get('show_transports_group') 4839 for contact in gajim.contacts.iter_contacts(account): 4840 # Is this contact in this group ? 4841 if group in contact.groups or (group == _('General') and not \ 4842 contact.groups): 4843 if self.contact_is_visible(contact, account): 4844 return True 4845 return False 4846 if type_ == 'contact': 4847 contact = gajim.contacts.get_first_contact_from_jid(account, jid) 4848 return self.contact_is_visible(contact, account) 4849 if type_ == 'agent': 4850 return gajim.config.get('show_transports_group') 4851 return True 4852 4734 4853 def compareIters(self, model, iter1, iter2, data = None): 4735 4854 '''Compare two iters to sort them''' 4736 4855 name1 = model[iter1][C_NAME] … … 4839 4958 self.dragging = False 4840 4959 4841 4960 def on_drop_in_contact(self, widget, account_source, c_source, account_dest, 4842 c_dest, was_big_brother, context, etime):4961 c_dest, was_big_brother, context, etime): 4843 4962 if not gajim.connections[account_source].private_storage_supported or not\ 4844 4963 gajim.connections[account_dest].private_storage_supported: 4845 4964 dialogs.WarningDialog(_('Metacontacts storage not supported by your ' … … 4921 5040 context.finish(True, True, etime) 4922 5041 4923 5042 def add_contact_to_group(self, account, contact, group): 4924 model = self.tree.get_model()4925 5043 if not group in contact.groups: 4926 5044 contact.groups.append(group) 4927 5045 # Remove all rows because add_contact_to_roster doesn't add it if one 4928 5046 # is already in roster 4929 for i in self.get_contact_iter(contact.jid, account ):4930 model.remove(i)5047 for i in self.get_contact_iter(contact.jid, account, self.model): 5048 self.model.remove(i) 4931 5049 self.add_contact_to_roster(contact.jid, account) 4932 5050 gajim.connections[account].update_contact(contact.jid, contact.name, 4933 5051 contact.groups) … … 4938 5056 contact.groups.remove(group) 4939 5057 self.remove_contact(contact, account) 4940 5058 5059 def drag_drop(self, treeview, context, x, y, timestamp): 5060 target_list = treeview.drag_dest_get_target_list() 5061 target = treeview.drag_dest_find_target(context, target_list) 5062 selection = treeview.drag_get_data(context, target) 5063 context.finish(False, True) 5064 return True 5065 4941 5066 def drag_data_received_data(self, treeview, context, x, y, selection, info, 4942 etime): 5067 etime): 5068 treeview.stop_emission('drag_data_received') 4943 5069 drop_info = treeview.get_dest_row_at_pos(x, y) 4944 5070 if not drop_info: 4945 5071 return … … 5265 5391 self.popup_notification_windows = [] 5266 5392 5267 5393 #(icon, name, type, jid, account, editable, secondary_pixbuf) 5268 model = gtk.TreeStore(gtk.Image, str, str, str, str, gtk.gdk.Pixbuf)5394 self.model = gtk.TreeStore(gtk.Image, str, str, str, str, gtk.gdk.Pixbuf) 5269 5395 5270 model.set_sort_func(1, self.compareIters) 5271 model.set_sort_column_id(1, gtk.SORT_ASCENDING) 5272 self.tree.set_model(model) 5396 self.model.set_sort_func(1, self.compareIters) 5397 self.model.set_sort_column_id(1, gtk.SORT_ASCENDING) 5398 self.modelfilter = self.model.filter_new() 5399 self.modelfilter.set_visible_func(self.visible_func) 5400 self.modelfilter.connect('row_changed', self.on_model_row_has_child_toggled) 5401 self.tree.set_model(self.modelfilter) 5402 5273 5403 # when this value become 0 we quit main application 5274 5404 self.quit_on_next_offline = -1 5275 5405 self.make_jabber_state_images() … … 5400 5530 self.tree.enable_model_drag_dest(TARGETS2, gtk.gdk.ACTION_DEFAULT) 5401 5531 self.tree.connect('drag_begin', self.drag_begin) 5402 5532 self.tree.connect('drag_end', self.drag_end) 5533 self.tree.connect('drag_drop', self.drag_drop) 5403 5534 self.tree.connect('drag_data_get', self.drag_data_get_data) 5404 5535 self.tree.connect('drag_data_received', self.drag_data_received_data) 5405 5536 self.dragging = False -
src/gajim.py
656 656 # It must be an agent 657 657 if ji in jid_list: 658 658 # Update existing iter 659 self.roster.modelfilter.refilter() 659 660 self.roster.draw_contact(ji, account) 660 661 self.roster.draw_group(_('Transports'), account) 661 662 if new_show > 1 and ji in gajim.transport_avatar[account]: … … 1079 1080 if gc_ctrl and gc_ctrl.type_id == message_control.TYPE_GC: 1080 1081 gc_ctrl.draw_avatar(resource) 1081 1082 else: 1082 self.roster.draw_avatar (jid, account)1083 self.roster.draw_avatar_from_jid(jid, account) 1083 1084 if self.remote_ctrl: 1084 1085 self.remote_ctrl.raise_signal('VcardInfo', (account, vcard)) 1085 1086 -
src/common/contacts.py
238 238 return c 239 239 return None 240 240 241 def iter_contacts(self, account): 242 for jid in self._contacts[account]: 243 for contact in self._contacts[account][jid]: 244 yield contact 245 241 246 def get_contact_from_full_jid(self, account, fjid): 242 247 ''' Get Contact object for specific resource of given jid''' 243 248 barejid, resource = common.gajim.get_room_and_nick_from_fjid(fjid) … … 285 290 for account in accounts: 286 291 our_jid = common.gajim.get_jid_from_account(account) 287 292 for jid in self.get_jid_list(account): 288 if self.has_brother(account, jid) and not \289 self.is_big_brother(account, jid):290 # count metacontacts only once291 continue293 # if self.has_brother(account, jid) and not \ 294 # self.is_big_brother(account, jid): 295 # # count metacontacts only once 296 # continue 292 297 if jid == our_jid: 293 298 continue 294 299 if common.gajim.jid_is_transport(jid) and not \
