Index: kopete/kopete/contactlist/contactlistproxymodel.cpp =================================================================== --- kopete/kopete/contactlist/contactlistproxymodel.cpp (revision 1046954) +++ kopete/kopete/contactlist/contactlistproxymodel.cpp (working copy) @@ -22,9 +22,11 @@ #include "kopetegroup.h" #include "kopetemetacontact.h" +#include "kopetecontact.h" #include "kopetecontactlist.h" #include "kopeteappearancesettings.h" #include "kopeteitembase.h" +#include namespace Kopete { @@ -65,6 +67,11 @@ default: QString leftName = left.data( Qt::DisplayRole ).toString(); QString rightName = right.data( Qt::DisplayRole ).toString(); + + // Trying to force offline to the bottom. Seems to glitch up + //if ( QString::localeAwareCompare( leftName.left(7), "Offline" ) == 0 ) + // return true; + return QString::localeAwareCompare( leftName, rightName ) < 0; } } @@ -113,17 +120,53 @@ if ( qobject_cast(groupObject) == Kopete::Group::topLevel() ) return true; + QString displayName = qobject_cast(groupObject)->displayName(); + int connectedContactsCount = model->data( current, Kopete::Items::ConnectedCountRole ).toInt(); int totalContactsCount = model->data( current, Kopete::Items::TotalCountRole ).toInt(); - // TODO: Find out how to check if we should hide the group if no metaContact was found. + // Count the number of sub contacts that are sticky in this group. If sticky > 0 then display the container + int stickyContactsCount = 0; + + // Go through each groups contacts and see if they are either sticky or part of a search param + // so we can show the folder + for ( int i = 0; i < model->rowCount( current ); i++ ) + { + QModelIndex qmi = model->index( i, 0, current ); + QObject* mcObject = qVariantValue( model->data( qmi, Kopete::Items::ObjectRole ) ); + Kopete::MetaContact *mc = qobject_cast(mcObject); + + if ( model->data( qmi, Kopete::Items::TypeRole ) != Kopete::Items::MetaContact ) + continue; + + if ( mc->isSticky() ) + stickyContactsCount++; + + // Don't search the offline group + if ( !filterRegExp().isEmpty() && QString::localeAwareCompare( displayName, "Offline" ) != 0 ) + { + // Do a better search. + if ( searchContactInfo( mc, filterRegExp() ) ) + return true; + } + } + if ( !filterRegExp().isEmpty() ) - return true; - - if ( !showEmpty && totalContactsCount == 0 ) + { + // Expand the folder for the found contacts + qobject_cast(groupObject)->setExpanded(true); return false; + } + + if ( !showEmpty && stickyContactsCount == 0 && totalContactsCount == 0 && QString::localeAwareCompare( displayName, "Offline" ) != 0 ) + return false; - if ( !showEmpty && !showOffline && connectedContactsCount == 0 ) + // dont display offline when viewing in grouped offline mode + if ( showOffline && QString::localeAwareCompare( displayName, "Offline" ) == 0 ) + return false; + + + if ( !showEmpty && !showOffline && stickyContactsCount == 0 && connectedContactsCount == 0 && QString::localeAwareCompare( displayName, "Offline" ) != 0) return false; return true; @@ -131,11 +174,34 @@ if ( model->data( current, Kopete::Items::TypeRole ) == Kopete::Items::MetaContact ) { + QObject* groupObject = qVariantValue( model->data( sourceParent, Kopete::Items::ObjectRole ) ); + QString displayName = qobject_cast(groupObject)->displayName(); + QObject* contactObject = qVariantValue( model->data( current, Kopete::Items::ObjectRole ) ); + Kopete::MetaContact *mc = qobject_cast(contactObject); + if ( !filterRegExp().isEmpty() ) { - QString mcName = model->data( current, Qt::DisplayRole ).toString(); - return mcName.contains( filterRegExp() ); + // Do a better search + if ( searchContactInfo( mc, filterRegExp() ) ) + return true; + else + return false; } + + if ( mc && mc->isSticky() ) + { + return true; + } + + // If this contact's group is called Offline, and we are not globally + // showing offline all users show the offline folder + if ( QString::localeAwareCompare( displayName, "Offline" ) == 0) + { + if ( showOffline ) + return false; + else + return true; + } int mcStatus = model->data( current, Kopete::Items::OnlineStatusRole ).toInt(); if ( mcStatus <= OnlineStatus::Offline && !showOffline ) @@ -143,7 +209,35 @@ else return true; } + + return false; +} +// Better search. Now a search will look in the metacontact display name, the invidual account contact names and any email addresses. +bool ContactListProxyModel::searchContactInfo(Kopete::MetaContact *mc, QRegExp searchPattern) const +{ + // Check the display name + if ( mc->displayName().contains( searchPattern ) ) + return true; + + // Check the address book + KABC::Addressee addressee = KABC::StdAddressBook::self()->findByUid( mc->kabcId() ); + if ( !addressee.isEmpty() ) + { + QString emailAddr = addressee.fullEmail(); + + if ( emailAddr.contains( searchPattern ) ) + return true; + } + + // Check alternative names + foreach( Kopete::Contact* c , mc->contacts() ) + { + // Search each metacontacts' contacts + if ( c->contactId().contains( searchPattern ) ) + return true; + } + return false; } Index: kopete/kopete/contactlist/contactlisttreemodel.cpp =================================================================== --- kopete/kopete/contactlist/contactlisttreemodel.cpp (revision 1046954) +++ kopete/kopete/contactlist/contactlisttreemodel.cpp (working copy) @@ -57,6 +57,18 @@ foreach( Kopete::Group* g, contact->groups() ) addMetaContactToGroup( contact, g ); + + if ( !contact->isOnline() ) + { + //BAZ create the group "offline" + Kopete::Group *offline = Kopete::ContactList::self()->findGroup( "Offline" ); + addMetaContactToGroup( contact, offline ); + } + else + { + Kopete::Group *offline = Kopete::ContactList::self()->findGroup( "Offline" ); + removeMetaContactFromGroup( contact, offline ); + } } void ContactListTreeModel::removeMetaContact( Kopete::MetaContact* contact ) @@ -579,6 +591,17 @@ // and now notify all the changes foreach(QModelIndex index, indexList) { + if ( !mc->isOnline() ) + { + //BAZ create the group "offline" + Kopete::Group *offline = Kopete::ContactList::self()->findGroup( "Offline" ); + addMetaContactToGroup( mc, offline ); + } + else + { + Kopete::Group *offline = Kopete::ContactList::self()->findGroup( "Offline" ); + removeMetaContactFromGroup( mc, offline ); + } // we need to emit the dataChanged signal to the groups this metacontact belongs to // so that proxy filtering is aware of the changes, first we have to update the parent // otherwise the group won't be expandable. Index: kopete/kopete/contactlist/kopetecontactlistview.h =================================================================== --- kopete/kopete/contactlist/kopetecontactlistview.h (revision 1046954) +++ kopete/kopete/contactlist/kopetecontactlistview.h (working copy) @@ -80,6 +80,7 @@ void addGroup(); void startChat(); void sendFile(); + void makeSticky(); //Baz void sendMessage(); void sendEmail(); void addTemporaryContact(); Index: kopete/kopete/contactlist/kopeteitemdelegate.cpp =================================================================== --- kopete/kopete/contactlist/kopeteitemdelegate.cpp (revision 1046954) +++ kopete/kopete/contactlist/kopeteitemdelegate.cpp (working copy) @@ -182,6 +182,7 @@ QList KopeteItemDelegate::filterContacts( const QList contacts ) const { + return contacts; if ( Kopete::AppearanceSettings::self()->showOfflineUsers() ) return contacts; Index: kopete/kopete/contactlist/contactlistproxymodel.h =================================================================== --- kopete/kopete/contactlist/contactlistproxymodel.h (revision 1046954) +++ kopete/kopete/contactlist/contactlistproxymodel.h (working copy) @@ -47,6 +47,9 @@ bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const; bool showOffline; bool showEmptyFolders; + + private: + bool searchContactInfo( Kopete::MetaContact *mc, QRegExp searchPattern ) const; }; } Index: kopete/kopete/contactlist/kopetecontactlistview.cpp =================================================================== --- kopete/kopete/contactlist/kopetecontactlistview.cpp (revision 1046954) +++ kopete/kopete/contactlist/kopetecontactlistview.cpp (working copy) @@ -83,6 +83,8 @@ KAction *actionSendFile; KActionMenu *actionAddContact; KAction *actionSendEmail; + // Baz + KAction *actionMakeSticky; KSelectAction *actionMove; KSelectAction *actionCopy; KAction *actionRename; @@ -182,7 +184,13 @@ d->actionSendEmail = new KAction( KIcon("mail-send"), i18n( "Send Email..." ), ac ); ac->addAction( "contactSendEmail", d->actionSendEmail ); connect( d->actionSendEmail, SIGNAL(triggered(bool)), this, SLOT(sendEmail()) ); + + // Baz Make the contact sticky in the list, (i.e still show if offline) + d->actionMakeSticky = new KAction( KIcon("list-add-user"), i18n( "Make Sticky..." ), ac ); + ac->addAction( "contactSticky", d->actionMakeSticky ); + connect( d->actionMakeSticky, SIGNAL(triggered(bool)), this, SLOT(makeSticky()) ); + // FIXME: Do we need this, it's in properties // -* this actionRename is buggy, and useless with properties, removed in kopeteui.rc*- // d->actionRename = new KAction( KIcon("edit-rename"), i18n( "Rename" ), ac ); @@ -532,6 +540,18 @@ } } +// Baz Make the contact sticky. +void KopeteContactListView::makeSticky() +{ + Kopete::MetaContact* metaContact = metaContactFromIndex( currentIndex() ); + if ( metaContact ) + { + metaContact->setSticky( !metaContact->isSticky() ); + updateActions(); + Kopete::AppearanceSettings::self()->writeConfig(); + } +} + void KopeteContactListView::addTemporaryContact() { Kopete::MetaContact* metaContact = metaContactFromIndex( currentIndex() ); @@ -819,6 +839,11 @@ d->actionRemove->setEnabled( true ); d->actionAddContact->setText( i18n("&Add Subcontact") ); d->actionAddContact->setEnabled( !metaContact->isTemporary() ); + // Baz + if ( metaContact->isSticky() ) + d->actionMakeSticky->setText("Un-Sticky"); + else + d->actionMakeSticky->setText("Make Sticky"); } else if ( singleGroupSelected ) { Index: kopete/kopete/kopeteui.rc =================================================================== --- kopete/kopete/kopeteui.rc (revision 1046954) +++ kopete/kopete/kopeteui.rc (working copy) @@ -57,7 +57,7 @@ - + @@ -66,6 +66,7 @@ + @@ -76,6 +77,7 @@ + Index: kopete/libkopete/kopetemetacontact_p.h =================================================================== --- kopete/libkopete/kopetemetacontact_p.h (revision 1046954) +++ kopete/libkopete/kopetemetacontact_p.h (working copy) @@ -70,6 +70,9 @@ // The photo cache. Reduce disk access and CPU usage. Picture customPicture, contactPicture, kabcPicture; + //Baz show the contact evev if offline + bool contactSticky; + Kopete::StatusMessage statusMessage; }; Index: kopete/libkopete/contactlist/xmlcontactstorage.cpp =================================================================== --- kopete/libkopete/contactlist/xmlcontactstorage.cpp (revision 1046954) +++ kopete/libkopete/contactlist/xmlcontactstorage.cpp (working copy) @@ -426,6 +426,10 @@ QString val = contactElement.text(); metaContact->setAddressBookField( 0, app, key , val ); } + else if ( contactElement.tagName() == QString::fromUtf8( "is-sticky" ) ) + { + metaContact->setSticky(contactElement.text() == QString::fromUtf8( "true" ) ? 1 : 0 ); + } else //if( groupElement.tagName() == QString::fromUtf8( "plugin-data" ) || groupElement.tagName() == QString::fromUtf8("custom-icons" )) { parseContactListElement( metaContact, contactElement ); @@ -665,6 +669,12 @@ displayName.appendChild( metaContactDoc.createTextNode( metaContact->customDisplayName() ) ); metaContactDoc.documentElement().appendChild( displayName ); + + // Baz the custom display name, used for the custom name source + QDomElement sticky = metaContactDoc.createElement( QString::fromUtf8("is-sticky" ) ); + sticky.appendChild( metaContactDoc.createTextNode( metaContact->isSticky() ? "true" : "false" ) ); + metaContactDoc.documentElement().appendChild( sticky ); + QDomElement photo = metaContactDoc.createElement( QString::fromUtf8("photo" ) ); photo.appendChild( metaContactDoc.createTextNode( metaContact->customPhoto().url() ) ); metaContactDoc.documentElement().appendChild( photo ); Index: kopete/libkopete/kopetemetacontact.cpp =================================================================== --- kopete/libkopete/kopetemetacontact.cpp (revision 1046954) +++ kopete/libkopete/kopetemetacontact.cpp (working copy) @@ -69,7 +69,7 @@ addToGroup( Group::topLevel() ); // I'm not sure this is correct -Olivier // we probably should do the check in groups() instead - + d->contactSticky = false; } MetaContact::~MetaContact() @@ -1332,7 +1332,17 @@ d->notifyOnlineStatus = newNotifyOnlineStatus; } +bool MetaContact::isSticky() const +{ + return d->contactSticky; +} +void MetaContact::setSticky( bool sticky ) +{ + d->contactSticky = sticky; + emit persistentDataChanged(); +} + } //END namespace Kopete #include "kopetemetacontact.moc" Index: kopete/libkopete/kopetemetacontact.h =================================================================== --- kopete/libkopete/kopetemetacontact.h (revision 1046954) +++ kopete/libkopete/kopetemetacontact.h (working copy) @@ -65,6 +65,7 @@ //Q_PROPERTY( ulong idleTime READ idleTime ) Q_PROPERTY( QUuid metaContactId READ metaContactId WRITE setMetaContactId ) Q_PROPERTY( bool photoSyncedWithKABC READ isPhotoSyncedWithKABC WRITE setPhotoSyncedWithKABC ) + Q_PROPERTY( bool isSticky READ isSticky WRITE setSticky) //Baz public: typedef QList List; @@ -401,6 +402,18 @@ */ StatusMessage statusMessage() const; + /** + * @Brief Set If the contact is sticky (shown offline) or not + * @param sticky The flag if sticky or not + */ + void setSticky( bool sticky ); + + /** + * @Brief If the contact is sticky (shown offline) or not + * @return bool value of stickyness + */ + bool isSticky() const; + public slots: /**