The contact list now remembers and restores contact group items expanded/collapsed state.

git-svn-id: http://voip.null.ro/svn/yate@4572 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2011-08-26 15:07:23 +00:00
parent 65bea65ac0
commit 76a1c40a0d
3 changed files with 126 additions and 15 deletions

View File

@ -291,7 +291,7 @@ void QtHtmlItemDelegate::drawDisplay(QPainter* painter, const QStyleOptionViewIt
static CustomTreeFactory s_factory;
static const String s_noGroupId(String(Time::secNow()) + "_" + MD5("Yate").hexDigest());
static const String s_noGroupId(MD5("Yate").hexDigest() + "_NOGROUP");
static const String s_offline("offline");
@ -393,9 +393,10 @@ int replaceHtmlParams(String& str, const NamedList& list, bool spaceEol = false)
/*
* QtTreeItem
*/
QtTreeItem::QtTreeItem(const char* id, int type, const char* text)
QtTreeItem::QtTreeItem(const char* id, int type, const char* text, bool storeExp)
: QTreeWidgetItem(type),
NamedList(id)
NamedList(id),
m_storeExp(storeExp)
{
if (!TelEngine::null(text))
QTreeWidgetItem::setText(0,QtClient::setUtf8(text));
@ -1220,6 +1221,43 @@ void QtCustomTree::setSorting(QString s)
updateSorting(key,order.toBoolean(true) ? Qt::AscendingOrder : Qt::DescendingOrder);
}
// Retrieve items expanded status value
QString QtCustomTree::itemsExpStatus()
{
String tmp;
for (int i = 0; i < m_expStatus.size(); i++) {
String val;
val << m_expStatus[i].first.uriEscape(',') << "=" <<
String::boolText(m_expStatus[i].second > 0);
tmp.append(val,",");
}
return QtClient::setUtf8(tmp);
}
// Set items expanded status value
void QtCustomTree::setItemsExpStatus(QString s)
{
m_expStatus.clear();
QStringList list = s.split(",",QString::SkipEmptyParts);
for (int i = 0; i < list.size(); i++) {
String id;
String value;
int pos = list[i].lastIndexOf('=');
if (pos > 0) {
QtClient::getUtf8(id,list[i].left(pos));
int n = list[i].size() - pos - 1;
if (n)
QtClient::getUtf8(value,list[i].right(n));
}
else
QtClient::getUtf8(id,list[i]);
if (id) {
id = id.uriUnescape();
m_expStatus.append(QtTokenDict(id,value.toBoolean(m_autoExpand) ? 1 : 0));
}
}
}
// Apply item widget style sheet
void QtCustomTree::applyStyleSheet(QtTreeItem* item, bool selected)
{
@ -1262,6 +1300,8 @@ void QtCustomTree::onItemExpandedChanged(QtTreeItem* item)
{
if (!item)
return;
if (item->m_storeExp)
setStoreExpStatus(item->id(),item->isExpanded());
setStateImage(*item);
applyItemStatistics(*item);
}
@ -1338,8 +1378,15 @@ QMenu* QtCustomTree::contextMenu(QtTreeItem* item)
// Item added notification
void QtCustomTree::itemAdded(QtTreeItem& item, QtTreeItem* parent)
{
if (m_autoExpand)
item.setExpanded(true);
bool on = m_autoExpand;
if (item.m_storeExp) {
int n = getStoreExpStatus(item.id());
if (n >= 0)
on = (n > 0);
else
setStoreExpStatus(item.id(),on);
}
item.setExpanded(on);
setStateImage(item);
applyItemTooltip(item);
applyItemStatistics(item);
@ -1417,6 +1464,30 @@ void QtCustomTree::applyItemStatistics(QtTreeItem& item)
updateItem(item,params);
}
// Store (update) to or remove from item expanded status storage an item
void QtCustomTree::setStoreExpStatus(const String& id, bool on, bool store)
{
if (!id)
return;
for (int i = 0; i < m_expStatus.size(); i++)
if (m_expStatus[i].first == id) {
m_expStatus[i].second = on ? 1 : 0;
return;
}
m_expStatus.append(QtTokenDict(id,on ? 1 : 0));
}
// Retrieve the expanded status of an item from storage
int QtCustomTree::getStoreExpStatus(const String& id)
{
if (!id)
return -1;
for (int i = 0; i < m_expStatus.size(); i++)
if (m_expStatus[i].first == id)
return m_expStatus[i].second;
return -1;
}
/*
* ContactList
@ -1426,6 +1497,7 @@ ContactList::ContactList(const char* name, const NamedList& params, QWidget* par
m_flatList(true),
m_showOffline(true),
m_hideEmptyGroups(true),
m_expStatusGrp(true),
m_menuContact(0),
m_menuChatRoom(0),
m_sortOrder(Qt::AscendingOrder),
@ -1909,7 +1981,7 @@ QtTreeItem* ContactList::getGroup(const String& name, bool create)
if (noGrp)
pos = root->indexOfChild(noGrp);
}
QtTreeItem* g = createGroup(grp,gText);
QtTreeItem* g = createGroup(grp,gText,m_expStatusGrp);
if (!addChild(g,pos))
TelEngine::destruct(g);
return g;
@ -1986,7 +2058,7 @@ void ContactList::createContactTree(ContactItem* c, ContactItemList& cil)
if (grp->null())
continue;
noGrp = false;
int index = cil.getGroupIndex(*grp,*grp);
int index = cil.getGroupIndex(*grp,*grp,m_expStatusGrp);
if (o->skipNext())
cil.m_contacts[index].append(createContact(c->id(),*c));
else
@ -1994,7 +2066,7 @@ void ContactList::createContactTree(ContactItem* c, ContactItemList& cil)
}
TelEngine::destruct(grps);
if (noGrp) {
int index = cil.getGroupIndex(s_noGroupId,m_noGroupText);
int index = cil.getGroupIndex(s_noGroupId,m_noGroupText,m_expStatusGrp);
cil.m_contacts[index].append(c);
}
}
@ -2063,7 +2135,7 @@ bool ContactItem::offline()
/*
* ContactItemList
*/
int ContactItemList::getGroupIndex(const String& id, const String& text)
int ContactItemList::getGroupIndex(const String& id, const String& text, bool expStat)
{
for (int i = 0; i < m_groups.size(); i++) {
QtTreeItem* item = static_cast<QtTreeItem*>(m_groups[i]);
@ -2074,7 +2146,7 @@ int ContactItemList::getGroupIndex(const String& id, const String& text)
if (pos && id != s_noGroupId &&
(static_cast<QtTreeItem*>(m_groups[pos - 1]))->id() == s_noGroupId)
pos--;
m_groups.insert(pos,ContactList::createGroup(id,text));
m_groups.insert(pos,ContactList::createGroup(id,text,expStat));
m_contacts.insert(pos,QtTreeItemList());
return pos;
}

View File

@ -38,6 +38,7 @@ class ContactItemList; // Groups and contact items belonging t
typedef QList<QTreeWidgetItem*> QtTreeItemList;
typedef QPair<QTreeWidgetItem*,QString> QtTreeItemKey;
typedef QPair<String,int> QtTokenDict;
/**
* This class holds data about a tree widget container item
@ -80,8 +81,9 @@ public:
* @param id Item id
* @param type Item type
* @param text Optional text for item column 0
* @param storeExp Set it to true to (re)store item expanded state
*/
QtTreeItem(const char* id, int type = Type, const char* text = 0);
QtTreeItem(const char* id, int type = Type, const char* text = 0, bool storeExp = false);
/**
* Destructor
@ -136,6 +138,11 @@ public:
*/
inline const String& id() const
{ return toString(); }
/**
* Save/restore item expanded status
*/
bool m_storeExp;
};
/**
@ -164,6 +171,7 @@ class QtCustomTree : public QtTree
Q_PROPERTY(QString _yate_itembackground READ itemBg WRITE setItemBg(QString))
Q_PROPERTY(QString _yate_col_widths READ colWidths WRITE setColWidths(QString))
Q_PROPERTY(QString _yate_sorting READ sorting WRITE setSorting(QString))
Q_PROPERTY(QString _yate_itemsexpstatus READ itemsExpStatus WRITE setItemsExpStatus(QString))
public:
/**
* List item type enumeration
@ -685,6 +693,18 @@ public:
*/
void setSorting(QString s);
/**
* Retrieve items expanded status value
* @return Items expanded status value
*/
QString itemsExpStatus();
/**
* Set items expanded status value
* param s Items expanded status value
*/
void setItemsExpStatus(QString s);
protected slots:
/**
* Handle item children actions
@ -866,11 +886,27 @@ protected:
*/
void applyItemStatistics(QtTreeItem& item);
/**
* Store (update) to or remove from item expanded status storage an item
* @param id Item id
* @param on Expanded status
* @param store True to store, false to remove
*/
void setStoreExpStatus(const String& id, bool on, bool store = true);
/**
* Retrieve the expanded status of an item from storage
* @param id Item id
* @return 1 if expanded, 0 if collapsed, -1 if not found
*/
int getStoreExpStatus(const String& id);
bool m_hasCheckableCols; // True if we have checkable columns
QMenu* m_menu; // Tree context menu
bool m_autoExpand; // Items are expanded when added
int m_rowHeight; // Tree row height
NamedList m_itemPropsType; // Tree item type to item props translation
QList<QtTokenDict> m_expStatus; // List of stored item IDs and expanded status
};
/**
@ -1069,10 +1105,11 @@ public:
* Create a group item
* @param id Group id
* @param name Group name
* @param expStat Expanded state (re)store indicator
* @return Valid QtTreeItem pointer
*/
static QtTreeItem* createGroup(const String& id, const String& name) {
QtTreeItem* g = new QtTreeItem(id,TypeGroup,name);
static inline QtTreeItem* createGroup(const String& id, const String& name, bool expStat) {
QtTreeItem* g = new QtTreeItem(id,TypeGroup,name,expStat);
g->addParam("name",name);
return g;
}
@ -1202,6 +1239,7 @@ private:
bool m_flatList; // Flat list
bool m_showOffline; // Show or hide offline contacts
bool m_hideEmptyGroups; // Show or hide empty groups
bool m_expStatusGrp; // Save/restore groups expanded status
String m_noGroupText; // Group text to show for contacts not belonging to any group
QMap<QString,QString> m_statusOrder; // Status order (names are mapped to status icons)
QMenu* m_menuContact;
@ -1248,9 +1286,10 @@ public:
* Retrieve a group. Create it if not found. Create contact list entry when a group is created
* @param id Group id
* @param text Group text
* @param expStat Expanded state (re)store indicator for created item
* @return Valid groups index
*/
int getGroupIndex(const String& id, const String& text);
int getGroupIndex(const String& id, const String& text, bool expStat);
QList<QTreeWidgetItem*> m_groups;
QList<QtTreeItemList> m_contacts;

View File

@ -197,7 +197,7 @@
<string>columns=name</string>
<string>htmldelegate=name</string>
<string>delegateparam.name.drawfocus=false</string>
<string>property:_yate_save_props=_yate_flatlist,_yate_showofflinecontacts,_yate_hideemptygroups</string>
<string>property:_yate_save_props=_yate_flatlist,_yate_showofflinecontacts,_yate_hideemptygroups,_yate_itemsexpstatus</string>
<string>property:_yate_flatlist=false</string>
<string>property:_yate_showofflinecontacts=true</string>
<string>property:_yate_hideemptygroups=true</string>