serverlistview.cpp
1 //------------------------------------------------------------------------------
2 // serverlistview.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301 USA
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2009 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 
24 #include "gui/widgets/serverlistview.h"
25 
26 #include "configuration/doomseekerconfig.h"
27 #include "gui/models/serverlistcolumn.h"
28 #include "refresher/refresher.h"
29 #include <QDebug>
30 #include <QHeaderView>
31 #include <QItemDelegate>
32 #include <QMouseEvent>
33 #include <QPainter>
34 #include <QSortFilterProxyModel>
35 #include <QTextDocument>
36 
41 class CustomItemDelegate : public QItemDelegate
42 {
43  public:
44  void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
45  {
46  // First we're going to check for our new right aligned image
47  // option.
48  bool rightAligned = false;
49  QStyleOptionViewItem opt = option;
50 
51  QVariant userRole = index.data(Qt::UserRole);
52  if(userRole.isValid() && userRole.type() == QVariant::Int && userRole.toInt() == USERROLE_RIGHTALIGNDECORATION)
53  {
54  opt.decorationAlignment = Qt::AlignRight|Qt::AlignVCenter;
55  rightAligned = true;
56  }
57 
58  // Now we draw the table as usual.
59  QItemDelegate::paint(painter, opt, index);
60 
61  // If the row is selected and we are using the right aligned feature
62  // we must now redraw the decoration. The rectangle that was used
63  // in the previous function will cause the image to clip.
64  //
65  // The only other way I can think of for fixing that problem would
66  // be to completely rewrite this class, which I really don't want
67  // to do.
68  if(rightAligned && (opt.state & QStyle::State_Selected))
69  {
70  QVariant decorationRole = index.data(Qt::DecorationRole);
71  if(decorationRole.isValid())
72  {
73  painter->save();
74  painter->setClipRect(opt.rect);
75 
76  QPixmap pixmap = decoration(opt, decorationRole);
77  drawDecoration(painter, opt, opt.rect, pixmap);
78 
79  painter->restore();
80  }
81  }
82  }
83 
84  protected:
85  void drawDecoration(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QPixmap &pixmap) const
86  {
87  if(pixmap.isNull() || !rect.isValid())
88  return;
89 
90  if(option.decorationAlignment == (Qt::AlignRight|Qt::AlignVCenter)) // Special handling.
91  {
92  QPoint p = QStyle::alignedRect(option.direction, option.decorationAlignment, pixmap.size(), option.rect).topLeft();
93  painter->drawPixmap(p, pixmap);
94  }
95  else
96  QItemDelegate::drawDecoration(painter, option, rect, pixmap);
97  }
98 };
99 
101 
102 ServerListView::ServerListView(QWidget* parent) : QTableView(parent)
103 {
104  // Prevent the fat rows problem.
105  verticalHeader()->setDefaultSectionSize(fontMetrics().height() + 6);
106 #if QT_VERSION >= 0x050000
107  verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
108 #else
109  verticalHeader()->setResizeMode(QHeaderView::Fixed);
110 #endif
111  setShowGrid(gConfig.doomseeker.bDrawGridInServerTable);
112 
113  setItemDelegate(new CustomItemDelegate());
114 }
115 
116 void ServerListView::mouseReleaseEvent(QMouseEvent* event)
117 {
118  QModelIndex index = indexAt(event->pos());
119  switch (event->button())
120  {
121  case Qt::MidButton:
122  if (index.isValid())
123  {
124  emit middleMouseClicked(index, event->pos());
125  }
126  break;
127 
128  case Qt::RightButton:
129  if (index.isValid())
130  {
131  emit rightMouseClicked(index, event->pos());
132  }
133  break;
134 
135  default:
136  QTableView::mouseReleaseEvent(event);
137  break;
138  }
139 }
140 
141 void ServerListView::mouseDoubleClickEvent(QMouseEvent* event)
142 {
143  if (event->button() != Qt::LeftButton)
144  {
145  QTableView::mouseDoubleClickEvent(event);
146  }
147  else
148  {
149  QModelIndex index = indexAt(event->pos());
150  if (index.isValid())
151  {
152  emit leftMouseDoubleClicked(index, event->pos());
153  }
154  }
155 }
156 
157 void ServerListView::setupTableProperties()
158 {
159  setIconSize(QSize(26, 15));
160  // Some flags that can't be set from the Designer.
161  horizontalHeader()->setSortIndicatorShown(true);
162  horizontalHeader()->setHighlightSections(false);
163 
164  setMouseTracking(true);
165 
166  setupTableColumnWidths();
167 }
168 
169 void ServerListView::setupTableColumnWidths()
170 {
171  const ServerListColumn* columns = ServerListColumns::columns;
172 
173  // Initialize the defaults.
174  for (int colIdx = 0; colIdx < ServerListColumnId::NUM_SERVERLIST_COLUMNS; ++colIdx)
175  {
176  setColumnWidth(colIdx, columns[colIdx].width);
177  }
178 
179  // Reload state from config, potentially overriding the defaults.
180  QString &headerState = gConfig.doomseeker.serverListColumnState;
181  if (!headerState.isEmpty())
182  {
183  horizontalHeader()->restoreState(QByteArray::fromBase64(headerState.toUtf8()));
184  }
185 
186  // Enforce certain settings on columns, regardless of the state loaded from the config.
187  for (int colIdx = 0; colIdx < ServerListColumnId::NUM_SERVERLIST_COLUMNS; ++colIdx)
188  {
189  setColumnHidden(colIdx, columns[colIdx].bHidden);
190  QHeaderView::ResizeMode resizeMode = columns[colIdx].bResizable ?
191  QHeaderView::Interactive : QHeaderView::Fixed;
192 #if QT_VERSION >= 0x050000
193  horizontalHeader()->setSectionResizeMode(colIdx, resizeMode);
194 #else
195  horizontalHeader()->setResizeMode(colIdx, resizeMode);
196 #endif
197  }
198 
199  // General settings.
200 #if QT_VERSION >= 0x050000
201  horizontalHeader()->setSectionsMovable(true);
202 #else
203  horizontalHeader()->setMovable(true);
204 #endif
205 }