Index: ../kopete/kopete/contactlist/contactlistproxymodel.cpp =================================================================== --- ../kopete/kopete/contactlist/contactlistproxymodel.cpp (revision 1046954) +++ ../kopete/kopete/contactlist/contactlistproxymodel.cpp (working copy) @@ -65,6 +65,15 @@ default: QString leftName = left.data( Qt::DisplayRole ).toString(); QString rightName = right.data( Qt::DisplayRole ).toString(); + + // Force the offline group to the bottom + QObject* groupObjectLeft = qVariantValue( sourceModel()->data( left, Kopete::Items::ObjectRole ) ); + QObject* groupObjectRight = qVariantValue( sourceModel()->data( right, Kopete::Items::ObjectRole ) ); + + if ( groupObjectLeft == Kopete::Group::offline() ) + return false; + else if ( groupObjectRight == Kopete::Group::offline() ) + return true; return QString::localeAwareCompare( leftName, rightName ) < 0; } } @@ -116,16 +125,28 @@ int connectedContactsCount = model->data( current, Kopete::Items::ConnectedCountRole ).toInt(); int totalContactsCount = model->data( current, Kopete::Items::TotalCountRole ).toInt(); + bool isOfflineGroup = groupObject == Kopete::Group::offline(); + if ( !filterRegExp().isEmpty() && isOfflineGroup ) + return false; + + // TODO: Find out how to check if we should hide the group if no metaContact was found. if ( !filterRegExp().isEmpty() ) return true; - if ( !showEmpty && totalContactsCount == 0 ) + if ( !Kopete::AppearanceSettings::self()->showOfflineGrouped() && isOfflineGroup ) return false; - if ( !showEmpty && !showOffline && connectedContactsCount == 0 ) + if ( !showEmpty && totalContactsCount == 0 && !isOfflineGroup) return false; + // dont display offline when viewing in grouped offline mode + if ( showOffline && isOfflineGroup ) + return false; + + if ( !showEmpty && !showOffline && connectedContactsCount == 0 && !isOfflineGroup ) + return false; + return true; } @@ -137,6 +158,17 @@ return mcName.contains( filterRegExp() ); } + // Get the MetaContacts parent group name + QObject* groupObject = qVariantValue( model->data( sourceParent, Kopete::Items::ObjectRole ) ); + + if ( Kopete::AppearanceSettings::self()->groupContactByGroup() && qobject_cast(groupObject) != 0 ) + { + // If this contact's group is called Offline, and we are not globally + // showing offline all users show the offline folder + if ( groupObject == Kopete::Group::offline() ) + return !showOffline; + } + int mcStatus = model->data( current, Kopete::Items::OnlineStatusRole ).toInt(); if ( mcStatus <= OnlineStatus::Offline && !showOffline ) 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,14 @@ foreach( Kopete::Group* g, contact->groups() ) addMetaContactToGroup( contact, g ); + + if ( Kopete::AppearanceSettings::self()->showOfflineGrouped() ) + { + if ( !contact->isOnline() ) + addMetaContactToGroup( contact, Kopete::Group::offline() ); + else + removeMetaContactFromGroup( contact, Kopete::Group::offline() ); + } } void ContactListTreeModel::removeMetaContact( Kopete::MetaContact* contact ) @@ -579,6 +587,11 @@ // and now notify all the changes foreach(QModelIndex index, indexList) { + if ( !mc->isOnline() ) + addMetaContactToGroup( mc, Kopete::Group::offline() ); + else + removeMetaContactFromGroup( mc, Kopete::Group::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/kopeteitemdelegate.cpp =================================================================== --- ../kopete/kopete/contactlist/kopeteitemdelegate.cpp (revision 1046954) +++ ../kopete/kopete/contactlist/kopeteitemdelegate.cpp (working copy) @@ -182,7 +182,8 @@ QList KopeteItemDelegate::filterContacts( const QList contacts ) const { - if ( Kopete::AppearanceSettings::self()->showOfflineUsers() ) + if ( Kopete::AppearanceSettings::self()->showOfflineUsers() || + Kopete::AppearanceSettings::self()->showOfflineGrouped() ) return contacts; QList filtered; Index: ../kopete/kopete/contactlist/kopetecontactlistview.cpp =================================================================== --- ../kopete/kopete/contactlist/kopetecontactlistview.cpp (revision 1046954) +++ ../kopete/kopete/contactlist/kopetecontactlistview.cpp (working copy) @@ -368,6 +368,10 @@ if ( group == Kopete::Group::topLevel() ) continue; + // Can't remove the offline group + if ( group == Kopete::Group::offline() ) + continue; + groupList.append( group ); if( !group->displayName().isEmpty() ) @@ -453,6 +457,10 @@ QObject* groupObject = qVariantValue( index.data( Kopete::Items::MetaContactGroupRole ) ); Kopete::Group* fromGroup = qobject_cast(groupObject); + // Can't move to the offline group manually + if ( toGroup == Kopete::Group::offline() ) + return; + metaContact->moveToGroup( fromGroup, toGroup ); } } @@ -483,6 +491,10 @@ if ( !toGroup ) return; + // Can't copy to the offline group manually + if ( toGroup == Kopete::Group::offline() ) + return; + metaContact->addToGroup( toGroup ); } } @@ -996,6 +1008,9 @@ return; } + if ( group == Kopete::Group::offline() ) + return; + KMenu *popup = dynamic_cast( window->factory()->container( "group_popup", window ) ); if ( popup ) { Index: ../kopete/kopete/config/appearance/appearanceconfig_contactlist.ui =================================================================== --- ../kopete/kopete/config/appearance/appearanceconfig_contactlist.ui (revision 1046954) +++ ../kopete/kopete/config/appearance/appearanceconfig_contactlist.ui (working copy) @@ -189,6 +189,19 @@ + + + + 0 + 0 + + + + Show offline contacts in a &separate folder + + + + Index: ../kopete/libkopete/kopetegroup.h =================================================================== --- ../kopete/libkopete/kopetegroup.h (revision 1046954) +++ ../kopete/libkopete/kopetegroup.h (working copy) @@ -53,7 +53,7 @@ typedef QList List; /** Kinds of groups. */ - enum GroupType { Normal=0, Temporary, TopLevel }; + enum GroupType { Normal=0, Temporary, TopLevel, Offline }; /** * \brief Create an empty group @@ -122,8 +122,13 @@ * \return a Group pointer to the temporary group */ static Group *temporary(); - + /** + * \return a Group pointer to the offline group + */ + static Group *offline(); + + /** * @internal */ void setGroupId( uint groupId ); @@ -162,10 +167,11 @@ static Group *s_topLevel; static Group *s_temporary; + static Group *s_offline; class Private; Private * const d; - + /** * @internal used to get reachabe contact to send message to thom. */ Index: ../kopete/libkopete/kopetegroup.cpp =================================================================== --- ../kopete/libkopete/kopetegroup.cpp (revision 1046954) +++ ../kopete/libkopete/kopetegroup.cpp (working copy) @@ -31,6 +31,7 @@ Group *Group::s_topLevel = 0L; Group *Group::s_temporary = 0L; +Group *Group::s_offline = 0L; Group * Group::topLevel() { if ( !s_topLevel ) @@ -47,6 +48,14 @@ return s_temporary; } +Group * Group::offline() +{ + if ( !s_offline ) + s_offline = new Group( i18n( "Offline Users" ), Group::Offline ); + + return s_offline; +} + uint Group::Private::uniqueGroupId = 0; Group::Group( const QString &_name ) @@ -81,6 +90,8 @@ s_topLevel=0L; if(d->type == Temporary) s_temporary=0L; + if(d->type == Offline) + s_offline=0L; delete d; } Index: ../kopete/libkopete/contactlist/xmlcontactstorage.cpp =================================================================== --- ../kopete/libkopete/contactlist/xmlcontactstorage.cpp (revision 1046954) +++ ../kopete/libkopete/contactlist/xmlcontactstorage.cpp (working copy) @@ -506,7 +506,7 @@ } // Don't overwrite type for Temporary and TopLevel groups - if ( group->type() != Kopete::Group::Temporary && group->type() != Kopete::Group::TopLevel ) + if ( group->type() != Kopete::Group::Temporary && group->type() != Kopete::Group::TopLevel && group->type() != Kopete::Group::Offline ) { QString type = element.attribute( QLatin1String( "type" ), QLatin1String( "standard" ) ); if ( type == QLatin1String( "temporary" ) ) @@ -525,6 +525,14 @@ return false; } } + else if ( type == QLatin1String( "offline" ) ) + { + if ( group->type() != Kopete::Group::Offline ) + { + parseGroup( Kopete::Group::offline(), element ); + return false; + } + } } QString view = element.attribute( QLatin1String( "view" ), QLatin1String( "expanded" ) ); @@ -561,6 +569,9 @@ case Kopete::Group::TopLevel: group->setDisplayName( QLatin1String( "Top-Level" ) ); break; + case Kopete::Group::Offline: + group->setDisplayName( QLatin1String( "Offline" ) ); + break; default: group->setDisplayName( i18n( "(Unnamed Group)" ) ); break; @@ -748,6 +759,10 @@ case Kopete::Group::TopLevel: type = QLatin1String( "top-level" ); break; + case Kopete::Group::Offline: + type = QLatin1String( "offline" ); + break; + default: type = QLatin1String( "standard" ); // == Normal break; Index: ../kopete/libkopete/contactlist/kopetecontactliststorage.cpp =================================================================== --- ../kopete/libkopete/contactlist/kopetecontactliststorage.cpp (revision 1046954) +++ ../kopete/libkopete/contactlist/kopetecontactliststorage.cpp (working copy) @@ -80,6 +80,8 @@ return Kopete::Group::temporary(); if( type == Kopete::Group::TopLevel ) return Kopete::Group::topLevel(); + if( type == Kopete::Group::Offline ) + return Kopete::Group::offline(); foreach( Kopete::Group * group, d->groupList ) { Index: ../kopete/libkopete/kopeteappearancesettings.kcfg =================================================================== --- ../kopete/libkopete/kopeteappearancesettings.kcfg (revision 1046954) +++ ../kopete/libkopete/kopeteappearancesettings.kcfg (working copy) @@ -250,10 +250,14 @@ false - true + + + false + + Index: ../kopete/libkopete/kopetecontactlist.cpp =================================================================== --- ../kopete/libkopete/kopetecontactlist.cpp (revision 1046954) +++ ../kopete/libkopete/kopetecontactlist.cpp (working copy) @@ -198,7 +198,9 @@ return Group::temporary(); if( type == Group::TopLevel ) return Group::topLevel(); - + if( type == Group::Offline ) + return Group::offline(); + if ( displayName == i18n ("Top Level") ) return Group::topLevel(); Index: ../kopete/libkopete/kopetemetacontact.cpp =================================================================== --- ../kopete/libkopete/kopetemetacontact.cpp (revision 1046954) +++ ../kopete/libkopete/kopetemetacontact.cpp (working copy) @@ -957,6 +957,9 @@ return; } + if ( to->type() == Group::Offline ) + return; + if ( isTemporary() && to->type() != Group::Temporary ) return;