1
/***************************************************************************
2
* Copyright (C) 2009-2013 by Savoir-Faire Linux *
3
* Author : Emmanuel Lepage Valle <emmanuel.lepage@savoirfairelinux.com >*
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 3 of the License, or *
8
* (at your option) any later version. *
10
* This program 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 *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17
**************************************************************************/
18
#include "calltreeitemdelegate.h"
21
#include <QtCore/QSize>
22
#include <QtGui/QPainter>
23
#include <QtGui/QPalette>
24
#include <QtGui/QTreeWidget>
25
#include <QtGui/QGraphicsEffect>
26
#include <QtGui/QGraphicsOpacityEffect>
29
#include "../callview.h"
30
#include "calltreeitem.h"
33
CallTreeItemDelegate::CallTreeItemDelegate(CallView* widget,QPalette pal)
34
: QStyledItemDelegate(widget) , m_tree(widget) , m_ConferenceDrawer() , m_Pal(pal),
35
m_LeftMargin(0),m_RightMargin(0)
39
///Guess the size of the item
40
QSize CallTreeItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
42
QSize sh = QStyledItemDelegate::sizeHint(option, index);
43
QTreeWidgetItem* item = (m_tree)->itemFromIndex(index);
45
CallTreeItem* widget = (CallTreeItem*)m_tree->itemWidget(item,0);
47
sh.rheight() = widget->sizeHint().height()+11; //Equal top and bottom padding
49
if (index.parent().isValid() && !index.parent().child(index.row()+1,0).isValid())
56
QRect CallTreeItemDelegate::fullCategoryRect(const QStyleOptionViewItem& option, const QModelIndex& index) const
58
QModelIndex i(index),old(index);
59
//BEGIN real sizeHint()
60
//Otherwise it would be called too often (thanks to valgrind)
61
((CallTreeItemDelegate*)this)->m_SH = QStyledItemDelegate::sizeHint(option, index);
62
((CallTreeItemDelegate*)this)->m_LeftMargin = m_ConferenceDrawer.leftMargin();
63
((CallTreeItemDelegate*)this)->m_RightMargin = m_ConferenceDrawer.rightMargin();
64
if (!index.parent().isValid() && index.child(0,0).isValid()) {
65
((QSize)m_SH).rheight() += 2 * m_ConferenceDrawer.leftMargin();
67
((QSize)m_SH).rheight() += m_ConferenceDrawer.leftMargin();
69
((QSize)m_SH).rwidth() += m_ConferenceDrawer.leftMargin();
72
if (i.parent().isValid()) {
76
//Avoid repainting the category over and over (optimization)
77
//note: 0,0,0,0 is actually wrong, but it wont change anything for this use case
78
if (i != old && old.row()>2)
79
return QRect(0,0,0,0);
81
QTreeWidgetItem* item = m_tree->itemFromIndex(i);
82
QRect r = m_tree->visualItemRect(item);
85
r.setLeft(m_ConferenceDrawer.leftMargin());
86
r.setWidth(m_tree->viewport()->width() - m_ConferenceDrawer.leftMargin() - m_ConferenceDrawer.rightMargin());
89
if (item->isExpanded() && item->childCount() > 0) {
90
const int childCount = item->childCount();
91
//There is a massive implact on CPU usage to have massive rect
92
for (int i =0;i < childCount;i++) {
93
r.setHeight(r.height() + sizeHint(option,index).height());
97
r.setTop(r.top() + m_ConferenceDrawer.leftMargin());
102
///Paint the delegate
103
void CallTreeItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
105
Q_ASSERT(index.isValid());
107
QStyleOptionViewItem opt(option);
108
QTreeWidgetItem* item = m_tree->itemFromIndex(index);
109
CallTreeItem* itemWidget = nullptr;
111
itemWidget = qobject_cast<CallTreeItem*>(m_tree->itemWidget(item,0));
113
//BEGIN: draw toplevel items
114
if (!index.parent().isValid() && index.child(0,0).isValid()) {
115
const QRegion cl = painter->clipRegion();
116
painter->setClipRect(opt.rect);
117
opt.rect = fullCategoryRect(option, index);
118
m_ConferenceDrawer.drawCategory(index, 0, opt, painter,&m_Pal);
121
if (itemWidget->isDragged()) {
122
QSize size = itemWidget->size();
124
while (index.child(i,0).isValid()) i++;
126
// QTreeWidgetItem* firstChild = m_tree->itemFromIndex(index);
127
QWidget* childWidget = qobject_cast<CallTreeItem*>(m_tree->itemWidget(item,0));
129
size.setHeight(itemWidget->height()+(i*childWidget->height())+10);
130
QPixmap pixmap(size);
131
childWidget->render(&pixmap);
132
painter->drawPixmap(10,2,pixmap);
136
painter->setClipRegion(cl);
140
if (!index.parent().parent().isValid()) {
141
opt.rect = fullCategoryRect(option, index);
142
const QRegion cl = painter->clipRegion();
143
QRect cr = option.rect;
144
if (index.column() == 0) {
145
if (m_tree->layoutDirection() == Qt::LeftToRight) {
148
cr.setRight(opt.rect.right());
151
painter->setClipRect(cr);
152
if (index.parent().isValid())
153
m_ConferenceDrawer.drawCategory(index, 0, opt, painter,&m_Pal);
154
painter->setClipRegion(cl);
155
painter->setRenderHint(QPainter::Antialiasing, false);
158
//END: draw background of category for all other items
160
QStyleOptionViewItem opt2(option);
161
if (index.parent().isValid())
162
opt2.rect.setWidth(opt2.rect.width()-15);
163
painter->setClipRect(option.rect);
164
if (option.state & (QStyle::State_Selected | QStyle::State_MouseOver)) {
165
//Draw a copy of the widget when in drag and drop
166
if (itemWidget && itemWidget->isDragged()) {
167
itemWidget->setTextColor(option.state);
169
//Check if it is the last item
170
if (index.parent().isValid() && !index.parent().child(index.row()+1,0).isValid()) {
171
opt2.rect.setHeight(opt2.rect.height()-15);
172
QStyledItemDelegate::paint(painter,opt2,index);
175
//Necessary to render conversation participants
176
if (opt2.rect != option.rect) {
177
QPainter::CompositionMode mode = painter->compositionMode();
178
painter->setCompositionMode(QPainter::CompositionMode_Clear);
179
painter->fillRect(option.rect,Qt::transparent);
180
painter->setCompositionMode(mode);
183
//Remove opacity effect to prevent artefacts when there is no compositor
184
QGraphicsEffect* opacityEffect = itemWidget->graphicsEffect();
186
itemWidget->setGraphicsEffect(nullptr);
187
QStyledItemDelegate::paint(painter,index.parent().isValid()?opt2:option,index);
188
QPixmap pixmap(itemWidget->size());
189
itemWidget->render(&pixmap);
190
painter->drawPixmap(0,0,pixmap);
192
QGraphicsOpacityEffect* opacityEffect2 = new QGraphicsOpacityEffect;
193
itemWidget->setGraphicsEffect(opacityEffect2);
197
//Check if it is not the last item
198
else if (!(index.parent().isValid() && !index.parent().child(index.row()+1,0).isValid())) {
199
QStyledItemDelegate::paint(painter,index.parent().isValid()?opt2:option,index);
203
//Check if it is the last item
204
if (index.parent().isValid() && !index.parent().child(index.row()+1,0).isValid()) {
205
opt2.rect.setHeight(opt2.rect.height()-15);
206
QStyledItemDelegate::paint(painter,opt2,index);
209
if (item && itemWidget) {
210
itemWidget->setTextColor(option.state);
211
itemWidget->setMinimumSize(opt2.rect.width(),10);
212
itemWidget->setMaximumSize(opt2.rect.width(),opt2.rect.height());
213
itemWidget->resize(opt2.rect.width(),option.rect.height());
216
if (index.parent().isValid() && !index.parent().child(index.row()+1,0).isValid()) {
217
m_ConferenceDrawer.drawBoxBottom(index, 0, option, painter);