1 /*
2     iconcells.cpp  -  Icon Cells
3 
4     Copyright (c) 2007 by Roman Jarosz <kedgedev@centrum.cz>
5     Kopete    (c) 2007 by the Kopete developers  <kopete-devel@kde.org>
6 
7     *************************************************************************
8     *                                                                       *
9     * This program is free software; you can redistribute it and/or modify  *
10     * it under the terms of the GNU General Public License as published by  *
11     * the Free Software Foundation; either version 2 of the License, or     *
12     * (at your option) any later version.                                   *
13     *                                                                       *
14     *************************************************************************
15 */
16 
17 #include "iconcells.h"
18 
19 #include <math.h>
20 
21 #include <QList>
22 #include <QHeaderView>
23 
24 class IconCells::IconCellsPrivate
25 {
26 public:
IconCellsPrivate()27 	IconCellsPrivate()
28 	{
29 		selected = -1;
30 	}
31 
32 	QList<QIcon> icons;
33 	int selected;
34 };
35 
IconCells(QWidget * parent)36 IconCells::IconCells( QWidget *parent )
37 : QTableWidget( parent ), d(new IconCellsPrivate())
38 {
39 	setColumnCount( 0 );
40 	setRowCount( 0 );
41 
42 	verticalHeader()->hide();
43 	horizontalHeader()->hide();
44 
45 	d->selected = 0;
46 	int pm = style()->pixelMetric( QStyle::PM_SmallIconSize, 0, this );
47 	setIconSize( QSize( pm, pm ) );
48 
49 	setSelectionMode( QAbstractItemView::SingleSelection );
50 	setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
51 	setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
52 	viewport()->setBackgroundRole( QPalette::Background );
53 	setBackgroundRole( QPalette::Background );
54 
55 	// HACK: Looks like any antialiased font brakes grid and icon painting.
56 	// We only have icons so we can set the font to one which isn't antialiased.
57 	QFont timesFont( QStringLiteral("Times"), 10, QFont::Normal );
58 	setFont( timesFont );
59 
60 	connect(this, &IconCells::cellActivated, this, &IconCells::slotSelected);
61 	connect(this, &IconCells::cellPressed, this, &IconCells::slotSelected);
62 }
63 
~IconCells()64 IconCells::~IconCells()
65 {
66 	delete d;
67 }
68 
icon(int index) const69 QIcon IconCells::icon( int index ) const
70 {
71 	return d->icons.at( index );
72 }
73 
count() const74 int IconCells::count() const
75 {
76 	return d->icons.count();
77 }
78 
setSelectedIndex(int index)79 void IconCells::setSelectedIndex( int index )
80 {
81 	Q_ASSERT( index >= 0 && index < d->icons.count() );
82 
83 	d->selected = index;
84 
85 	const int column = columnFromIndex( index );
86 	const int row = rowFromIndex( index );
87 	setCurrentCell( row, column );
88 }
89 
selectedIndex() const90 int IconCells::selectedIndex() const
91 {
92 	return d->selected;
93 }
94 
sizeHint() const95 QSize IconCells::sizeHint () const
96 {
97 	int width = columnCount() * (iconSize().width() + 8) + 2 * frameWidth();
98 	int height = rowCount() * (iconSize().height() + 8) + 2 * frameWidth();
99 	return QSize( width, height );
100 }
101 
setIcons(const QList<QIcon> & icons)102 void IconCells::setIcons( const QList<QIcon> &icons )
103 {
104 	d->icons = icons;
105 	setRowCount( (int)ceil( (double)d->icons.size() / columnCount() ) );
106 
107 	for ( int row = 0; row < rowCount(); ++row )
108 	{
109 		for ( int column = 0; column < columnCount(); ++column )
110 		{
111 			int index = row * columnCount() + column;
112 			QTableWidgetItem* tableItem = item( row, column );
113 
114 			if ( tableItem == 0 )
115 			{
116 				tableItem = new QTableWidgetItem();
117 				tableItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
118 				setItem( row, column, tableItem );
119 			}
120 
121 			if ( index < d->icons.count() )
122 			{
123 				QIcon icon = d->icons.at(index);
124 				tableItem->setData( Qt::DecorationRole, icon );
125 			}
126 		}
127 	}
128 	setMinimumSize( sizeHint() );
129 }
130 
slotSelected(int row,int column)131 void IconCells::slotSelected( int row, int column )
132 {
133 	int index = row * columnCount() + column;
134 
135 	if ( index < d->icons.count() )
136 	{
137 		d->selected = index;
138 		emit selected( index );
139 	}
140 }
141 
resizeEvent(QResizeEvent *)142 void IconCells::resizeEvent( QResizeEvent* )
143 {
144 	// iterate over each column and each row and resize them to fit their contents.
145 	// resizeColumnsToContents() and resizeRowsToContents() are not used because
146 	// of 150382 bug in Qt 4.2 where the aforementioned methods do not ignore the height/width
147 	// of hidden headers as they should do.
148 
149 	for ( int index = 0 ; index < columnCount() ; index++ )
150 		resizeColumnToContents(index);
151 	for ( int index = 0 ; index < rowCount() ; index++ )
152 		resizeRowToContents(index);
153 
154 	// use the method below when the bug is fixed:
155 	//resizeColumnsToContents();
156 	//resizeRowsToContents();
157 }
158 
sizeHintForColumn(int) const159 int IconCells::sizeHintForColumn(int /*column*/) const
160 {
161 	return (int)floor((double)(width() - 2 * frameWidth()) / columnCount());
162 }
163 
sizeHintForRow(int) const164 int IconCells::sizeHintForRow(int /*row*/) const
165 {
166 	return (int)floor((double)(height() - 2 * frameWidth()) / rowCount());
167 }
168 
rowFromIndex(int index) const169 int IconCells::rowFromIndex( int index ) const
170 {
171 	return (int)floor( (double)index / columnCount() );
172 }
173 
columnFromIndex(int index) const174 int IconCells::columnFromIndex( int index ) const
175 {
176 	return index % columnCount();
177 }
178 
179