1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the examples of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QDebug>
43 #include <QTime>
44
45 #include "itemrecyclinglist.h"
46 #include "listitemcontainer.h"
47 #include "abstractviewitem.h"
48 #include "recycledlistitem.h"
49 #include "theme.h"
50 #include "scrollbar.h"
51
ItemRecyclingList(const int itemBuffer,QGraphicsWidget * parent)52 ItemRecyclingList::ItemRecyclingList(const int itemBuffer, QGraphicsWidget * parent)
53 : ItemRecyclingListView(parent),
54 m_listModel(new ListModel(this))
55 {
56 ListItemContainer *container = new ListItemContainer(itemBuffer, this, this);
57 container->setParentItem(this);
58 ItemRecyclingListView::setContainer(container);
59 ItemRecyclingListView::setModel(m_listModel, new RecycledListItem(this));
60 setObjectName("ItemRecyclingList");
61 connect(Theme::p(), SIGNAL(themeChanged()), this, SLOT(themeChange()));
62
63 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
64 }
65
66 /* virtual */
~ItemRecyclingList()67 ItemRecyclingList::~ItemRecyclingList()
68 {
69 }
70
71 /* virtual */
insertItem(int index,RecycledListItem * item)72 void ItemRecyclingList::insertItem(int index, RecycledListItem *item)
73 {
74 if (index<0)
75 index = 0;
76 if (index > m_listModel->rowCount())
77 index = m_listModel->rowCount();
78 if (m_listModel && item)
79 m_listModel->insert(index,item);
80
81 updateListItemBackgrounds(index);
82 }
83
84 /* virtual */
addItem(RecycledListItem * item)85 void ItemRecyclingList::addItem(RecycledListItem *item)
86 {
87 if (item)
88 m_listModel->appendRow(item);
89
90 const int index = m_listModel->rowCount()-1;
91 updateListItemBackgrounds(index);
92 }
93
94 /* virtual */
clear()95 void ItemRecyclingList::clear()
96 {
97 m_listModel->clear();
98 }
99
100 /* virtual */
takeItem(const int row)101 AbstractViewItem *ItemRecyclingList::takeItem(const int row)
102 {
103 if (row < 0 || row >= m_listModel->rowCount() || !m_listModel)
104 return 0;
105 return m_listModel->takeItem(row);
106 }
107
108 /*virtual*/
setItemPrototype(AbstractViewItem * prototype)109 void ItemRecyclingList::setItemPrototype(AbstractViewItem* prototype)
110 {
111 ItemRecyclingListView::setItemPrototype(prototype);
112 }
113
themeChange()114 void ItemRecyclingList::themeChange()
115 {
116 const bool caching = listItemCaching();
117 setListItemCaching(false);
118
119 const QString iconName = Theme::p()->pixmapPath()+"contact_default_icon.svg";
120 const int count = m_listModel->rowCount();
121
122 for (int i=0; i<count; ++i)
123 {
124 RecycledListItem *ritem = m_listModel->item(i);
125 if (ritem) {
126 ListItem *item = ritem->item();
127
128 // Update default icons
129 const QString filename = item->icon(ListItem::LeftIcon)->fileName();
130 if (filename.contains("contact_default_icon")) {
131 item->icon(ListItem::LeftIcon)->setFileName(iconName);
132 }
133
134 // Update status icons
135 QString statusIcon = item->icon(ListItem::RightIcon)->fileName();
136 const int index = statusIcon.indexOf("contact_status");
137 if (index != -1) {
138 statusIcon.remove(0, index);
139 item->icon(ListItem::RightIcon)->setFileName(Theme::p()->pixmapPath()+statusIcon);
140 }
141
142 // Update fonts
143 item->setFont(Theme::p()->font(Theme::ContactName), ListItem::FirstPos);
144 item->setFont(Theme::p()->font(Theme::ContactNumber), ListItem::SecondPos);
145 item->setFont(Theme::p()->font(Theme::ContactEmail), ListItem::ThirdPos);
146
147 // Update list dividers
148 if (i%2) {
149 item->setBackgroundBrush(Theme::p()->listItemBackgroundBrushOdd());
150 item->setBackgroundOpacity(Theme::p()->listItemBackgroundOpacityOdd());
151 }
152 else {
153 item->setBackgroundBrush(Theme::p()->listItemBackgroundBrushEven());
154 item->setBackgroundOpacity(Theme::p()->listItemBackgroundOpacityEven());
155 }
156
157 // Update borders
158 item->setBorderPen(Theme::p()->listItemBorderPen());
159 item->setRounding(Theme::p()->listItemRounding());
160
161 // Update icons
162 item->icon(ListItem::LeftIcon)->setRotation(Theme::p()->iconRotation(ListItem::LeftIcon));
163 item->icon(ListItem::RightIcon)->setRotation(Theme::p()->iconRotation(ListItem::RightIcon));
164 #if (QT_VERSION >= 0x040600)
165 item->icon(ListItem::LeftIcon)->setOpacityEffectEnabled(Theme::p()->isIconOpacityEffectEnabled(ListItem::LeftIcon));
166 item->icon(ListItem::RightIcon)->setOpacityEffectEnabled(Theme::p()->isIconOpacityEffectEnabled(ListItem::RightIcon));
167 #endif
168 item->icon(ListItem::LeftIcon)->setSmoothTransformationEnabled(Theme::p()->isIconSmoothTransformationEnabled(ListItem::LeftIcon));
169 item->icon(ListItem::RightIcon)->setSmoothTransformationEnabled(Theme::p()->isIconSmoothTransformationEnabled(ListItem::RightIcon));
170 }
171 }
172 updateViewContent();
173 setListItemCaching(caching);
174 }
175
keyPressEvent(QKeyEvent * event)176 void ItemRecyclingList::keyPressEvent(QKeyEvent *event)
177 {
178 static QTime keyPressInterval = QTime::currentTime();
179 static qreal step = 0.0;
180 static bool repeat = false;
181 int interval = keyPressInterval.elapsed();
182
183 ScrollBar* sb = verticalScrollBar();
184 qreal currentValue = sb->sliderPosition();
185
186 if(interval < 250 ) {
187 if(!repeat) step = 0.0;
188 step = step + 2.0;
189 if(step > 100) step = 100;
190 repeat = true;
191 }
192 else {
193 step = 1.0;
194 if(m_listModel->item(0)) m_listModel->item(0)->size().height();
195 step = m_listModel->item(0)->size().height();
196 repeat = false;
197 }
198
199 if(event->key() == Qt::Key_Up ) { //Up Arrow
200 sb->setSliderPosition(currentValue - step);
201 }
202
203 if(event->key() == Qt::Key_Down ) { //Down Arrow
204 sb->setSliderPosition(currentValue + step);
205 }
206 keyPressInterval.start();
207 }
208
listItemCaching() const209 bool ItemRecyclingList::listItemCaching() const
210 {
211 #if (QT_VERSION >= 0x040600)
212 ListItemContainer *container =
213 static_cast<ListItemContainer *>(m_container);
214
215 return container->listItemCaching();
216 #else
217 return false;
218 #endif
219 }
220
setListItemCaching(bool enabled)221 void ItemRecyclingList::setListItemCaching(bool enabled)
222 {
223 #if (QT_VERSION >= 0x040600)
224 ListItemContainer *container =
225 static_cast<ListItemContainer *>(m_container);
226 container->setListItemCaching(enabled);
227 #else
228 Q_UNUSED(enabled)
229 #endif
230 }
231
updateListItemBackgrounds(int index)232 void ItemRecyclingList::updateListItemBackgrounds(int index)
233 {
234 const int itemCount = m_listModel->rowCount();
235
236 for (int i=index; i<itemCount; ++i)
237 {
238 RecycledListItem *ritem = m_listModel->item(i);
239 if (ritem) {
240 ListItem *item = ritem->item();
241 if (i%2) {
242 item->setBackgroundBrush(Theme::p()->listItemBackgroundBrushOdd());
243 item->setBackgroundOpacity(Theme::p()->listItemBackgroundOpacityOdd());
244 }
245 else {
246 item->setBackgroundBrush(Theme::p()->listItemBackgroundBrushEven());
247 item->setBackgroundOpacity(Theme::p()->listItemBackgroundOpacityEven());
248 }
249 }
250 }
251 }
252
setTwoColumns(const bool enabled)253 void ItemRecyclingList::setTwoColumns(const bool enabled)
254 {
255 if (twoColumns() == enabled)
256 return;
257
258 #if (QT_VERSION >= 0x040600)
259 const bool caching = listItemCaching();
260 setListItemCaching(false);
261 #endif
262
263 m_container->setTwoColumns(enabled);
264 refreshContainerGeometry();
265
266 #if (QT_VERSION >= 0x040600)
267 setListItemCaching(caching);
268 #endif
269 }
270
twoColumns()271 bool ItemRecyclingList::twoColumns()
272 {
273 return m_container->twoColumns();
274 }
275
276