Ticket #1201: modelfilter_v2.patch
| File modelfilter_v2.patch, 41.3 kB (added by asterix, 17 months ago) |
|---|
-
src/roster_window.py
23 23 import os 24 24 import time 25 25 import urllib 26 import threading 26 27 27 28 import common.sleepy 28 29 import history_window … … 67 68 class RosterWindow: 68 69 '''Class for main window of the GTK+ interface''' 69 70 70 def get_account_iter(self, name ):71 def get_account_iter(self, name, model = None): 71 72 ''' Returns a gtk.TreeIter of accounts in roster data model or None ''' 72 model = self.tree.get_model() 73 if not model: 74 model = self.tree.get_model() 73 75 if model is None: 74 76 return 75 77 account_iter = model.get_iter_root() 76 78 if self.regroup: 77 79 return account_iter 78 80 while account_iter: 79 account_name = model[account_iter][C_ACCOUNT] .decode('utf-8')80 if name == account_name:81 account_name = model[account_iter][C_ACCOUNT] 82 if account_name and name == account_name.decode('utf-8'): 81 83 break 82 84 account_iter = model.iter_next(account_iter) 83 85 return account_iter 84 86 85 def get_group_iter(self, name, account ):87 def get_group_iter(self, name, account, model = None): 86 88 ''' Returns a gtk.TreeIter of groups in roster data model or None ''' 87 model = self.tree.get_model() 88 root = self.get_account_iter(account) 89 if not model: 90 model = self.tree.get_model() 91 root = self.get_account_iter(account, model) 89 92 group_iter = model.iter_children(root) 90 93 # C_NAME column contacts the pango escaped group name 91 94 while group_iter: … … 95 98 group_iter = model.iter_next(group_iter) 96 99 return group_iter 97 100 98 def get_contact_iter(self, jid, account ):101 def get_contact_iter(self, jid, account, model = None): 99 102 if jid == gajim.get_jid_from_account(account): 100 103 iter = self.get_self_contact_iter(account) 101 104 if iter: 102 105 return [iter] 103 106 else: 104 107 return [] 105 model = self.tree.get_model() 106 acct = self.get_account_iter(account) 108 if not model: 109 model = self.tree.get_model() 110 acct = self.get_account_iter(account, model) 107 111 found = [] 108 112 if model is None: # when closing Gajim model can be none (async pbs?) 109 113 return found … … 111 115 while group_iter: 112 116 contact_iter = model.iter_children(group_iter) 113 117 while contact_iter: 114 if jid == model[contact_iter][C_JID].decode('utf-8') and \ 118 iter_jid = model[contact_iter][C_JID] 119 if iter_jid and jid == iter_jid.decode('utf-8') and \ 115 120 account == model[contact_iter][C_ACCOUNT].decode('utf-8'): 116 121 found.append(contact_iter) 117 122 # find next contact iter … … 157 162 # show him 158 163 self.add_contact_to_roster(jid, account) 159 164 iters = self.get_contact_iter(jid, account) 165 #FIXME: adding it doesn't mean it is visible 166 if not iters: 167 return 160 168 path = self.tree.get_model().get_path(iters[0]) 161 169 if self.dragging or not gajim.config.get('scroll_roster_to_last_message'): 162 170 # do not change selection while DND'ing … … 171 179 def add_account_to_roster(self, account): 172 180 ''' Add an account to roster data model. ''' 173 181 model = self.tree.get_model() 182 child_model = model.get_model() 174 183 if self.get_account_iter(account): 175 184 return 176 185 177 186 # if we merge accounts... 178 187 if self.regroup: 179 188 show = helpers.get_global_show() 180 model.append(None, [self.jabber_state_images['16'][show],189 child_model.append(None, [self.jabber_state_images['16'][show], 181 190 _('Merged accounts'), 'account', '', 'all', None]) 182 191 self.draw_account(account) 183 192 return … … 191 200 192 201 our_jid = gajim.get_jid_from_account(account) 193 202 194 model.append(None, [self.jabber_state_images['16'][show],203 child_model.append(None, [self.jabber_state_images['16'][show], 195 204 gobject.markup_escape_text(account), 196 205 'account', our_jid, account, tls_pixbuf]) 197 206 198 207 def draw_account(self, account): 199 model = self.tree.get_model() 200 iter = self.get_account_iter(account) 208 child_iter = self.get_account_iter(account, self.model) 201 209 if self.regroup: 202 210 accounts = gajim.connections.keys() 203 211 else: … … 226 234 new_pixels += chr(128) 227 235 tls_pixbuf = gtk.gdk.pixbuf_new_from_data(new_pixels, colorspace, 228 236 True, bps, width, height, rowstride) 229 model[iter][C_SECPIXBUF] = tls_pixbuf237 self.model[child_iter][C_SECPIXBUF] = tls_pixbuf 230 238 else: 231 model[iter][C_SECPIXBUF] = None232 path = model.get_path(iter)239 self.model[child_iter][C_SECPIXBUF] = None 240 path = self.model.get_path(child_iter) 233 241 account_name = account 234 242 accounts = [account] 235 243 if self.regroup: 236 244 account_name = _('Merged accounts') 237 245 accounts = [] 238 if not self.tree.row_expanded(path) and model.iter_has_child(iter): 246 if not self.tree.row_expanded(path) and self.model.iter_has_child( 247 child_iter): 239 248 # account row not expanded 240 249 account_name = '[%s]' % account_name 241 250 if (gajim.account_is_connected(account) or (self.regroup and \ … … 244 253 nbr_on, nbr_total = gajim.contacts.get_nb_online_total_contacts( 245 254 accounts = accounts) 246 255 account_name += ' (%s/%s)' % (repr(nbr_on),repr(nbr_total)) 247 model[iter][C_NAME] = account_name256 self.model[child_iter][C_NAME] = account_name 248 257 249 258 def remove_newly_added(self, jid, account): 250 259 if jid in gajim.newly_added[account]: … … 257 266 is False, because it has online children, so we need to show it. 258 267 If add_children is True, we also add all children, even if they were not 259 268 already drawn''' 260 showOffline = gajim.config.get('showoffline')261 model = self.tree.get_model()269 model = self.modelfilter 270 child_model = model.get_model() 262 271 contact = gajim.contacts.get_first_contact_from_jid(account, jid) 263 272 nb_events = gajim.events.get_nb_roster_events(account, contact.jid) 264 273 # count events from all resources … … 275 284 self.add_self_contact(account) 276 285 return 277 286 if gajim.jid_is_transport(contact.jid): 278 # if jid is transport, check if we wanna show it in roster279 if not gajim.config.get('show_transports_group') and not nb_events:280 return281 287 contact.groups = [_('Transports')] 282 elif not showOffline and not gajim.account_is_connected(account) and \283 nb_events == 0:284 return285 288 286 # XEP-0162287 hide = contact.is_hidden_from_roster()288 if hide and contact.sub != 'from':289 return290 289 observer = contact.is_observer() 291 290 groupchat = contact.is_groupchat() 292 291 … … 295 294 tag = gajim.contacts.get_metacontacts_tag(account, jid) 296 295 if tag: 297 296 gajim.contacts.remove_metacontact(account, jid) 297 contact.groups = [_('Observers')] 298 298 299 299 # family is [{'account': acct, 'jid': jid, 'priority': prio}, ] 300 300 # 'priority' is optional … … 310 310 continue 311 311 _jid = data['jid'] 312 312 313 if self.get_contact_iter(_jid, _account ):313 if self.get_contact_iter(_jid, _account, self.model): 314 314 shown_family.append(data) 315 315 316 if _jid == jid and _account == account: 316 317 our_data = data 317 shown_family.append(our_data)318 318 big_brother_data = gajim.contacts.get_metacontacts_big_brother( 319 shown_family )319 shown_family + [our_data]) 320 320 big_brother_jid = big_brother_data['jid'] 321 321 big_brother_account = big_brother_data['account'] 322 322 if big_brother_jid != jid or big_brother_account != account: 323 323 # We are adding a child contact 324 if contact.show in ('offline', 'error') and \ 325 not showOffline and len(gajim.events.get_events(account, jid)) == 0: 324 parent_iters = self.get_contact_iter(big_brother_jid, 325 big_brother_account, self.model) 326 if parent_iters: 327 name = contact.get_shown_name() 328 added_iters = [] 329 for child_i in parent_iters: 330 # we add some values here. see draw_contact for more 331 i_ = child_model.append(child_i, (None, name, 'contact', jid, 332 account, None)) 333 added_iters.append(i_) 334 self.draw_contact(jid, account) 335 self.draw_avatar(added_iters) 336 self.draw_account(account) 337 # Redraw parent to change icon 338 self.draw_contact(big_brother_jid, big_brother_account) 326 339 return 327 parent_iters = self.get_contact_iter(big_brother_jid,328 big_brother_account)329 name = contact.get_shown_name()330 for i in parent_iters:331 # we add some values here. see draw_contact for more332 model.append(i, (None, name, 'contact', jid, account, None))333 self.draw_contact(jid, account)334 self.draw_avatar(jid, account)335 self.draw_account(account)336 # Redraw parent to change icon337 self.draw_contact(big_brother_jid, big_brother_account)338 return339 340 340 if (contact.show in ('offline', 'error') or hide) and \341 not showOffline and (not _('Transports') in contact.groups or \342 gajim.connections[account].connected < 2) and \343 len(gajim.contacts.get_contacts(account, jid)) == 1 and nb_events == 0 and\344 not _('Not in Roster') in contact.groups:345 return346 347 341 # Remove brother contacts that are already in roster to add them 348 342 # under this iter 349 343 for data in shown_family: … … 356 350 groups = [_('Observers')] 357 351 elif not groups: 358 352 groups = [_('General')] 353 added_iters = [] 359 354 for group in groups: 360 355 self.draw_group(group, account) 361 iterG = self.get_group_iter(group, account)362 if not iterG:363 IterAcct = self.get_account_iter(account)364 iterG = model.append(IterAcct, [356 child_iterG = self.get_group_iter(group, account, self.model) 357 if not child_iterG: 358 child_iterA = self.get_account_iter(account, self.model) 359 child_iterG = self.model.append(child_iterA, [ 365 360 self.jabber_state_images['16']['closed'], 366 361 gobject.markup_escape_text(group), 'group', 367 362 group, account, None]) 368 363 self.draw_group(group, account) 369 if model.iter_n_children(IterAcct) == 1: # We added the first one 370 self.draw_account(account) 371 if group not in gajim.groups[account]: # It can probably never append 364 try: 365 iterG = model.convert_child_iter_to_iter(child_iterG) 366 except RuntimeError: 367 # group is not visible in filtered model 368 iterG = None 369 if group not in gajim.groups[account]: 372 370 if account + group in self.collapsed_rows: 373 371 ishidden = False 374 372 else: 375 373 ishidden = True 376 374 gajim.groups[account][group] = {'expand': ishidden} 377 if not account in self.collapsed_rows:375 if iterG and not account in self.collapsed_rows: 378 376 self.tree.expand_row((model.get_path(iterG)[0]), False) 379 377 380 378 typestr = 'contact' … … 385 383 386 384 name = contact.get_shown_name() 387 385 # we add some values here. see draw_contact for more 388 model.append(iterG, (None, name, typestr, contact.jid, account, None)) 386 i_ = self.model.append(child_iterG, (None, name, typestr, contact.jid, 387 account, None)) 388 added_iters.append(i_) 389 389 390 390 if gajim.groups[account][group]['expand']: 391 self.tree.expand_row(model.get_path(iterG), False) 392 self.draw_contact(jid, account) 393 self.draw_avatar(jid, account) 391 #FIXME: why do we need to recall it? because we added a child? 392 iterG = self.get_group_iter(group, account) 393 if iterG: 394 self.tree.expand_row(model.get_path(iterG), False) 395 if not self.starting: 396 self.draw_contact(jid, account) 397 self.draw_avatar(added_iters) 394 398 self.draw_account(account) 395 399 # put the children under this iter 396 400 for data in shown_family: … … 399 403 self.add_contact_to_roster(data['jid'], data['account']) 400 404 401 405 def draw_group(self, group, account): 402 iter = self.get_group_iter(group, account)403 if not iter:406 child_iter = self.get_group_iter(group, account, self.model) 407 if not child_iter: 404 408 return 405 409 if self.regroup: 406 410 accounts = [] … … 413 417 nbr_on, nbr_total = gajim.contacts.get_nb_online_total_contacts( 414 418 accounts = accounts, groups = [group]) 415 419 text += ' (%s/%s)' % (repr(nbr_on), repr(nbr_total)) 416 model = self.tree.get_model() 417 model.set_value(iter, 1 , text) 420 self.model.set_value(child_iter, 1 , gobject.markup_escape_text(text)) 418 421 419 422 def add_to_not_in_the_roster(self, account, jid, nick = '', resource = ''): 420 423 ''' add jid to group "not in the roster", he MUST not be in roster yet, … … 453 456 return contact 454 457 455 458 def get_self_contact_iter(self, account): 456 model = self.tree.get_model()457 459 iterAcct = self.get_account_iter(account) 458 iter = model.iter_children(iterAcct)460 iter = self.modelfilter.iter_children(iterAcct) 459 461 if not iter: 460 462 return None 461 if model[iter][C_TYPE] == 'self_contact':463 if self.modelfilter[iter][C_TYPE] == 'self_contact': 462 464 return iter 463 465 return None 464 466 465 467 def add_self_contact(self, account): 468 return 466 469 jid = gajim.get_jid_from_account(account) 467 if self.get_self_contact_iter(account): 470 self_contact_iter = self.get_self_contact_iter(account) 471 if self_contact_iter: 468 472 self.draw_contact(jid, account) 469 self.draw_avatar(jid, account) 473 child_iter = self.modelfilter.convert_iter_to_child_iter( 474 self_contact_iter) 475 self.draw_avatar(child_iter) 470 476 return 471 477 472 478 contact = gajim.contacts.get_first_contact_from_jid(account, jid) 473 479 if not contact: 474 480 return 475 showOffline = gajim.config.get('showoffline')476 if (contact.show in ('offline', 'error')) and not showOffline and \477 len(gajim.events.get_events(account, jid)) == 0:478 return479 481 480 482 model = self.tree.get_model() 481 iterAcct = self.get_account_iter(account) 482 model.append(iterAcct, (None, gajim.nicks[account], 'self_contact', jid, 483 account, None)) 483 iterA = self.get_account_iter(account) 484 child_model = model.get_model() 485 child_iterA = model.convert_iter_to_child_iter(iterA) 486 i_ = child_model.append(child_iterA, (None, gajim.nicks[account], 487 'self_contact', jid, account, None)) 484 488 self.draw_contact(jid, account) 485 self.draw_avatar( jid, account)489 self.draw_avatar([i_]) 486 490 487 491 def add_transport_to_roster(self, account, transport): 488 492 c = gajim.contacts.create_contact(jid = transport, name = transport, … … 497 501 return 498 502 if contact.jid in gajim.newly_added[account]: 499 503 return 500 if gajim.jid_is_transport(contact.jid) and gajim.account_is_connected(501 account) and gajim.config.get('show_transports_group'):502 # It's an agent and we show them503 return504 504 if contact.jid in gajim.to_be_removed[account]: 505 505 gajim.to_be_removed[account].remove(contact.jid) 506 # FIXME: refilter only this contact 507 # for iter in self.get_contact_iter(contact.jid, account, self.model): 508 # path = self.model.get_path(iter) 509 # doesn't work 510 # self.model.row_has_child_toggled(path, iter) 511 self.modelfilter.refilter() 506 512 513 # hide = contact.is_hidden_from_roster() 514 # 515 # show_offline = gajim.config.get('showoffline') 516 # show_transports = gajim.config.get('show_transports_group') 517 # 518 # nb_events = 0 519 # jid_list = [contact.jid] 520 # if contact.get_full_jid() != contact.jid: 521 # jid_list.append(contact.get_full_jid()) 522 # for jid in jid_list: 523 # # dont't count printed_chat messages 524 # nb_events += gajim.events.get_nb_roster_events(account, jid, ['chat']) 525 # 526 # if (_('Transports') in contact.groups and not show_transports) or \ 527 # ((contact.show in ('offline', 'error') or hide) and not show_offline and \ 528 # (not _('Transports') in contact.groups or \ 529 # gajim.account_is_disconnected(account))) and nb_events == 0: 530 # else: 531 # self.draw_contact(contact.jid, account) 507 532 508 hide = contact.is_hidden_from_roster()509 510 show_offline = gajim.config.get('showoffline')511 show_transports = gajim.config.get('show_transports_group')512 513 nb_events = 0514 jid_list = [contact.jid]515 if contact.get_full_jid() != contact.jid:516 jid_list.append(contact.get_full_jid())517 for jid in jid_list:518 # dont't count printed_chat messages519 nb_events += gajim.events.get_nb_roster_events(account, jid, ['chat'])520 521 if (_('Transports') in contact.groups and not show_transports) or \522 ((contact.show in ('offline', 'error') or hide) and not show_offline and \523 (not _('Transports') in contact.groups or \524 gajim.account_is_disconnected(account))) and nb_events == 0:525 self.remove_contact(contact, account)526 else:527 self.draw_contact(contact.jid, account)528 529 533 def remove_contact(self, contact, account): 530 534 '''Remove a contact from the roster''' 531 535 if contact.jid in gajim.to_be_removed[account]: 532 536 return 533 model = self.tree.get_model()534 iters = self.get_contact_iter(contact.jid, account )537 # look for iters in all (even not shown) iters 538 iters = self.get_contact_iter(contact.jid, account, self.model) 535 539 if not iters: 536 540 return 537 parent_iter = model.iter_parent(iters[0])538 parent_type = model[parent_iter][C_TYPE]541 parent_iter = self.model.iter_parent(iters[0]) 542 parent_type = self.model[parent_iter][C_TYPE] 539 543 # remember children to re-add them 540 544 children = [] 541 child_iter =model.iter_children(iters[0])542 while child_iter:543 c_jid = model[child_iter][C_JID].decode('utf-8')544 c_account = model[child_iter][C_ACCOUNT].decode('utf-8')545 iterC = self.model.iter_children(iters[0]) 546 while iterC: 547 c_jid = self.model[iterC][C_JID].decode('utf-8') 548 c_account = self.model[iterC][C_ACCOUNT].decode('utf-8') 545 549 children.append((c_jid, c_account)) 546 child_iter = model.iter_next(child_iter)550 iterC = self.model.iter_next(iterC) 547 551 548 552 # Remove iters and group iter if they are empty 549 553 for i in iters: 550 parent_i = model.iter_parent(i)551 model.remove(i)554 parent_i = self.model.iter_parent(i) 555 self.model.remove(i) 552 556 if parent_type == 'group': 553 group = model[parent_i][C_JID].decode('utf-8') 554 if model.iter_n_children(parent_i) == 0: 555 model.remove(parent_i) 556 # We need to check all contacts, even offline contacts 557 for jid in gajim.contacts.get_jid_list(account): 558 if group in gajim.contacts.get_contact_with_highest_priority( 559 account, jid).groups: 560 break 561 else: 562 if gajim.groups[account].has_key(group): 563 del gajim.groups[account][group] 557 group = self.model[parent_i][C_JID].decode('utf-8') 558 if self.model.iter_n_children(parent_i) == 0: 559 self.model.remove(parent_i) 560 if gajim.groups[account].has_key(group): 561 del gajim.groups[account][group] 564 562 else: 565 563 self.draw_group(group, account) 566 564 … … 569 567 self.add_contact_to_roster(child[0], child[1]) 570 568 # redraw parent 571 569 if parent_type == 'contact': 572 parent_jid = model[parent_iter][C_JID].decode('utf-8')573 parent_account = model[parent_iter][C_ACCOUNT].decode('utf-8')570 parent_jid = self.model[parent_iter][C_JID].decode('utf-8') 571 parent_account = self.model[parent_iter][C_ACCOUNT].decode('utf-8') 574 572 self.draw_contact(parent_jid, parent_account) 575 573 576 574 def get_appropriate_state_images(self, jid, size = '16', 577 icon_name = 'online'):575 icon_name = 'online'): 578 576 '''check jid and return the appropriate state images dict for 579 577 the demanded size. icon_name is taken into account when jid is from 580 578 transport: transport iconset doesn't contain all icons, so we fall back … … 589 587 def draw_contact(self, jid, account, selected = False, focus = False): 590 588 '''draw the correct state image, name BUT not avatar''' 591 589 # focus is about if the roster window has toplevel-focus or not 592 model = self.tree.get_model() 593 iters = self.get_contact_iter(jid, account) 594 if len(iters) == 0: 590 child_iters = self.get_contact_iter(jid, account, self.model) 591 if len(child_iters) == 0: 595 592 return 596 593 contact_instances = gajim.contacts.get_contacts(account, jid) 597 594 contact = gajim.contacts.get_highest_prio_contact_from_contacts( … … 639 636 if self.regroup: 640 637 add_acct = False 641 638 # look through all contacts of all accounts 642 for account_ iterin gajim.connections:643 if account_ iter== account: # useless to add accout name
