root/trunk/qt4-gui/src/views/userview.cpp

Revision 6346, 11.2 kB (checked in by eugene, 6 months ago)

Removed PPIDSTRING extern declaration, since it's already declared in licq_user.h

  • Property svn:eol-style set to native
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of Licq, an instant messaging client for UNIX.
4 * Copyright (C) 1999-2006 Licq developers
5 *
6 * Licq is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Licq is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Licq; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 */
20
21#include "userview.h"
22
23#include <QApplication>
24#include <QHeaderView>
25#include <QMouseEvent>
26
27#include "config/contactlist.h"
28#include "config/iconmanager.h"
29#include "config/skin.h"
30
31#include "contactlist/maincontactlistproxy.h"
32
33using namespace LicqQtGui;
34
35UserView::UserView(ContactListModel* contactList, QWidget* parent)
36  : UserViewBase(contactList, parent)
37{
38  // Use a proxy model for sorting and filtering
39  myListProxy = new MainContactListProxy(myContactList, this);
40  setModel(myListProxy);
41
42  // Sorting
43  header()->setClickable(true);
44  header()->setMovable(false);
45  resort();
46  connect(header(), SIGNAL(sectionClicked(int)), SLOT(slotHeaderClicked(int)));
47
48  // Appearance
49  // Base class constructor doesn't know we overridden applySkin() so it we must call it here again
50  applySkin();
51
52  updateRootIndex();
53
54  connect(this, SIGNAL(expanded(const QModelIndex&)), SLOT(slotExpanded(const QModelIndex&)));
55  connect(this, SIGNAL(collapsed(const QModelIndex&)), SLOT(slotCollapsed(const QModelIndex&)));
56  connect(IconManager::instance(), SIGNAL(iconsChanged()), SLOT(configUpdated()));
57  connect(Config::ContactList::instance(), SIGNAL(listLookChanged()), SLOT(configUpdated()));
58  connect(Config::ContactList::instance(), SIGNAL(currentListChanged()), SLOT(updateRootIndex()));
59  connect(Config::ContactList::instance(), SIGNAL(listSortingChanged()), SLOT(resort()));
60  connect(myContactList, SIGNAL(modelReset()), SLOT(updateRootIndex()));
61}
62
63UserView::~UserView()
64{
65  // Empty
66}
67
68bool UserView::MainWindowSelectedItemUser(QString& id, unsigned long& ppid) const
69{
70  if (static_cast<ContactListModel::ItemType>
71      (currentIndex().data(ContactListModel::ItemTypeRole).toInt()) != ContactListModel::UserItem)
72    return false;
73
74  id = currentIndex().data(ContactListModel::UserIdRole).toString();
75  ppid = currentIndex().data(ContactListModel::PpidRole).toUInt();
76  return true;
77}
78
79void UserView::updateRootIndex()
80{
81  bool threadView = Config::ContactList::instance()->threadView();
82  GroupType groupType = Config::ContactList::instance()->groupType();
83  unsigned long groupId = Config::ContactList::instance()->groupId();
84
85  QModelIndex newRoot = QModelIndex();
86
87  if (threadView && groupType == GROUPS_SYSTEM && groupId == GROUP_ALL_USERS)
88  {
89    // Hide the system groups that exist in the model but should not be displayed in threaded view
90    dynamic_cast<MainContactListProxy*>(myListProxy)->setThreadedView(true);
91  }
92  else
93  {
94    newRoot = myContactList->groupIndex(groupType, groupId);
95    if (newRoot.isValid())
96    {
97      // Turn off group filtering first, otherwise we cannot switch from threaded view to a system group
98      dynamic_cast<MainContactListProxy*>(myListProxy)->setThreadedView(false);
99
100      // Hidden groups may not be sorted, force a resort just in case
101      resort();
102    }
103  }
104
105  UserViewBase::setRootIndex(myListProxy->mapFromSource(newRoot));
106  expandGroups();
107  configUpdated();
108}
109
110void UserView::configUpdated()
111{
112  // Set column widths
113  for (unsigned short i = 0; i < Config::ContactList::instance()->columnCount(); i++)
114    setColumnWidth(i, Config::ContactList::instance()->columnWidth(i));
115
116  setVerticalScrollBarPolicy(Config::ContactList::instance()->allowScrollBar() ?
117      Qt::ScrollBarAsNeeded : Qt::ScrollBarAlwaysOff);
118
119  if (Config::ContactList::instance()->showHeader())
120    header()->show();
121  else
122    header()->hide();
123
124  spanRowRange(rootIndex(), 0, model()->rowCount(rootIndex()) - 1);
125}
126
127void UserView::expandGroups()
128{
129  // No point in expanding groups unless we can actually see them
130  if (rootIndex().isValid())
131    return;
132
133  for (int i = 0; i < myListProxy->rowCount(QModelIndex()); ++i)
134  {
135    QModelIndex index = myListProxy->index(i, 0, QModelIndex());
136    unsigned short gid = index.data(ContactListModel::GroupIdRole).toUInt();
137
138    setExpanded(index, Config::ContactList::instance()->groupState(gid));
139  }
140}
141
142void UserView::spanRowRange(const QModelIndex& parent, int start, int end)
143{
144  for (int i = start; i <= end; i++)
145  {
146    // get the real model index
147    QModelIndex index = model()->index(i, 0, parent);
148    unsigned itemType = model()->data(index, ContactListModel::ItemTypeRole).toUInt();
149
150    if (itemType == ContactListModel::GroupItem ||
151        itemType == ContactListModel::BarItem)
152      setFirstColumnSpanned(i, parent, true);
153  }
154}
155
156void UserView::setColors(QColor back)
157{
158  UserViewBase::setColors(back);
159
160  if (!Config::ContactList::instance()->useSystemBackground() &&
161      Config::Skin::active()->frame.transparent)
162  {
163    QPalette pal = palette();
164    pal.setBrush(QPalette::Base, Qt::NoBrush);
165    setPalette(pal);
166  }
167}
168
169void UserView::applySkin()
170{
171  setFrameStyle(Config::Skin::active()->frame.frameStyle);
172  UserViewBase::applySkin();
173}
174
175void UserView::rowsInserted(const QModelIndex& parent, int start, int end)
176{
177  spanRowRange(parent, start, end);
178  UserViewBase::rowsInserted(parent, start, end);
179
180  // If we just got a new group we may want to expand it
181  if (!parent.isValid())
182    expandGroups();
183}
184
185void UserView::mousePressEvent(QMouseEvent* event)
186{
187  UserViewBase::mousePressEvent(event);
188
189  if (event->button() == Qt::LeftButton)
190  {
191    QModelIndex clickedItem = indexAt(event->pos());
192    if (clickedItem.isValid())
193    {
194      ContactListModel::ItemType itemType = static_cast<ContactListModel::ItemType>
195        (currentIndex().data(ContactListModel::ItemTypeRole).toInt());
196      if (itemType == ContactListModel::GroupItem)
197      {
198        if (event->pos().x() <= 18) // we clicked an icon area
199        {
200          bool wasExpanded = isExpanded(clickedItem);
201          setExpanded(clickedItem, !wasExpanded);
202
203          // setExpand may fail, for example after changing sorting an
204          // expanded group can be collapsed but sometimes cannot be expanded
205          // again. This was seen with Qt 4.4.0.
206          if (isExpanded(clickedItem) == wasExpanded)
207          {
208            // Setting expanded state to same state as view currently (falsely)
209            // reports seems to fix it, then set it again to the state we
210            // actually wanted, this times it works.
211            setExpanded(clickedItem, wasExpanded);
212            setExpanded(clickedItem, !wasExpanded);
213          }
214        }
215      }
216    }
217    else
218    {
219      // Clicking outiside list will clear selection
220      selectionModel()->clearSelection();
221      setCurrentIndex(QModelIndex());
222    }
223  }
224}
225
226void UserView::keyPressEvent(QKeyEvent* event)
227{
228  if (event->modifiers() & (Qt::ControlModifier | Qt::AltModifier))
229  {
230    event->ignore();
231    UserViewBase::keyPressEvent(event);
232    return;
233  }
234
235  ContactListModel::ItemType itemType = static_cast<ContactListModel::ItemType>
236    (currentIndex().data(ContactListModel::ItemTypeRole).toInt());
237
238  switch (event->key())
239  {
240    case Qt::Key_Return:
241    case Qt::Key_Enter:
242      if (itemType == ContactListModel::UserItem)
243      {
244        emit doubleClicked(currentIndex());
245        break;
246      }
247      // Fall through so return key expands and collapses groups
248
249    case Qt::Key_Space:
250      if (itemType == ContactListModel::GroupItem)
251      {
252        setExpanded(currentIndex(), !isExpanded(currentIndex()));
253      }
254      else
255      {
256        popupMenu(viewport()->mapToGlobal(QPoint(40, visualRect(currentIndex()).y())), currentIndex());
257      }
258      return;
259
260    default:
261      UserViewBase::keyPressEvent(event);
262  }
263}
264
265void UserView::mouseMoveEvent(QMouseEvent* event)
266{
267  UserViewBase::mouseMoveEvent(event);
268
269  QModelIndex index = currentIndex();
270  if (index.isValid() == false)
271    return;
272
273  if (static_cast<ContactListModel::ItemType>
274      (index.data(ContactListModel::ItemTypeRole).toInt()) != ContactListModel::UserItem)
275    return;
276
277  QString id = index.data(ContactListModel::UserIdRole).toString();
278  unsigned long ppid = index.data(ContactListModel::PpidRole).toUInt();
279
280  if ((event->buttons() & Qt::LeftButton) && !myMousePressPos.isNull() &&
281      (QPoint(event->pos() - myMousePressPos).manhattanLength() >= QApplication::startDragDistance()))
282  {
283    char* p = PPIDSTRING(ppid);
284    QString data(p);
285    data += id;
286    delete [] p;
287
288    QDrag* drag = new QDrag(this);
289    QMimeData* mimeData = new QMimeData;
290    mimeData->setText(data);
291    drag->setMimeData(mimeData);
292    drag->start(Qt::CopyAction);
293  }
294}
295
296void UserView::resort()
297{
298  int column = Config::ContactList::instance()->sortColumn();
299  Qt::SortOrder order = (Config::ContactList::instance()->sortColumnAscending() ? Qt::AscendingOrder : Qt::DescendingOrder);
300
301  // Column 0 means sort on status or unsorted
302  if (column == 0)
303  {
304    dynamic_cast<SortedContactListProxy*>(myListProxy)->sort(0, ContactListModel::SortRole, Qt::AscendingOrder);
305
306    header()->setSortIndicatorShown(false);
307  }
308  else
309  {
310    // Column numbers in configuration is off by one
311    column--;
312
313    dynamic_cast<SortedContactListProxy*>(myListProxy)->sort(column, Qt::DisplayRole, order);
314
315    header()->setSortIndicatorShown(true);
316    header()->setSortIndicator(column, order);
317  }
318
319  // Group expansion gets confused when sorting is changed so refresh it
320  expandGroups();
321}
322
323void UserView::slotExpanded(const QModelIndex& index)
324{
325  unsigned short gid = index.data(ContactListModel::GroupIdRole).toUInt();
326  Config::ContactList::instance()->setGroupState(gid, true);
327}
328
329void UserView::slotCollapsed(const QModelIndex& index)
330{
331  unsigned short gid = index.data(ContactListModel::GroupIdRole).toUInt();
332  Config::ContactList::instance()->setGroupState(gid, false);
333}
334
335void UserView::slotHeaderClicked(int column)
336{
337  // Clicking on a header will switch between three sorting modes
338  //  - Ascending sort on the clicked column
339  //  - Descending sort on the clicked colmun
340  //  - Default sort (unsorted or sort by status)
341
342  // Columns in configuration is off by one as status was previously a separate column
343  column++;
344
345  if (Config::ContactList::instance()->sortColumn() == 0)
346  {
347    // Sort mode was default, change to ascending of this column
348    Config::ContactList::instance()->setSortColumn(column, true);
349  }
350  else if (Config::ContactList::instance()->sortColumn() != column)
351  {
352    // Sorting was of other column, change to ascending of this column
353    Config::ContactList::instance()->setSortColumn(column, true);
354  }
355  else if (Config::ContactList::instance()->sortColumnAscending() == true)
356  {
357    // Sorting was ascending of current column, change to descending
358    Config::ContactList::instance()->setSortColumn(column, false);
359  }
360  else
361  {
362    // Sorting was descending of current column, change to default
363    Config::ContactList::instance()->setSortColumn(0, true);
364  }
365}
Note: See TracBrowser for help on using the browser.