Ticket #1201: modelfilter.2.patch
| File modelfilter.2.patch, 41.7 kB (added by asterix, 14 months 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_&nbs
