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