1
/***************************************************************************
2
* Copyright (C) 2008 by Christian Mollekopf chrigi_1@fastmail.fm *
4
* This program is free software; you can redistribute it and/or modify *
5
* it under the terms of the GNU General Public License as published by *
6
* the Free Software Foundation; either version 2 of the License, or *
7
* (at your option) any later version. *
9
* This program is distributed in the hope that it will be useful, *
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12
* GNU General Public License for more details. *
14
* You should have received a copy of the GNU General Public License *
15
* along with this program; if not, write to the *
16
* Free Software Foundation, Inc., *
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
18
***************************************************************************/
20
#include "taskitemlayout.h"
23
#include <taskmanager/taskmanager.h>
24
#include <taskmanager/abstractgroupableitem.h>
25
#include <taskmanager/groupmanager.h>
28
#include <QGraphicsScene>
29
#include <QGraphicsGridLayout>
36
#include "windowtaskitem.h"
37
#include "taskgroupitem.h"
40
//GroupItem Constructor
41
TaskItemLayout::TaskItemLayout(TaskGroupItem *parent, Tasks *applet)
42
: QGraphicsGridLayout(0),
50
m_layoutOrientation(Qt::Horizontal)
52
setContentsMargins(0,0,0,0);
53
setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));
54
setMaximumSize(INT_MAX,INT_MAX);
56
foreach (AbstractTaskItem *item, m_groupItem->members()) {
61
TaskItemLayout::~TaskItemLayout()
66
void TaskItemLayout::setOrientation(Plasma::FormFactor orientation)
68
Qt::Orientation oldOrientation = m_layoutOrientation;
70
if (orientation == Plasma::Vertical) {
71
m_layoutOrientation = Qt::Vertical;
73
m_layoutOrientation = Qt::Horizontal;
76
if (m_layoutOrientation != oldOrientation) {
83
void TaskItemLayout::addTaskItem(AbstractTaskItem * item)
87
kDebug() << "invalid item";
91
if (m_itemPositions.contains(item)) {
92
//kDebug() << "already in this layout";
96
if (m_groupItem->scene() && !item->scene()) {
97
//kDebug() << "layout widget got scene"<<m_groupItem->scene()<< "add item to scene" <<item->scene();
98
m_groupItem->scene()->addItem(item);
99
//kDebug() << "itemScene" << item->scene();
102
if (!insert(m_groupItem->indexOf(item, false), item)) {
103
kDebug() << "error on insert";
111
void TaskItemLayout::removeTaskItem(AbstractTaskItem *item)
119
if (m_groupItem->scene()) {
120
//kDebug() << "got scene";
121
m_groupItem->scene()->removeItem(item);
123
kDebug() << "No Scene available";
125
//kDebug() << "done";
128
bool TaskItemLayout::insert(int index, AbstractTaskItem *item)
130
//kDebug() << item->text() << index;
137
for (listIndex = 0; listIndex < m_itemPositions.size(); listIndex++) {
138
if (index <= m_groupItem->indexOf(m_itemPositions.at(listIndex), false)) {
143
if (m_itemPositions.removeAll(item) == 0) {
144
connect(item, SIGNAL(destroyed(AbstractTaskItem*)), this, SLOT(remove(AbstractTaskItem*)));
147
m_itemPositions.insert(listIndex, item);
153
bool TaskItemLayout::remove(AbstractTaskItem* item)
156
kDebug() << "null Item";
161
disconnect(item, 0, this, 0);
162
m_itemPositions.removeAll(item);
168
/** size including expanded groups*/
169
int TaskItemLayout::size()
173
foreach (AbstractTaskItem *item, m_groupItem->members()) {
174
if (!item->abstractItem()) {
175
// this item is a startup task or the task no longer exists
176
kDebug() << "Error, invalid item in groupMembers";
180
if (item->abstractItem()->itemType() == TaskManager::GroupItemType) {
181
TaskGroupItem *group = static_cast<TaskGroupItem*>(item);
182
if (!group->collapsed()) {
183
TaskItemLayout *layout = dynamic_cast<TaskItemLayout*>(group->tasksLayout());
185
kDebug() << "Error group has no layout";
189
// increase number of items since expanded groups occupy several spaces
190
groupSize += layout->size();
198
//kDebug() << "group size" << groupSize;
202
//return maximum colums set by the user unless the setting is to high and the items would get unusable
203
int TaskItemLayout::maximumRows()
206
if (m_itemPositions.isEmpty()) {
214
// in this case rows are columns, columns are rows...
215
//TODO basicPreferredSize isn't the optimal source here because it changes because of margins probably
216
QSizeF itemSize = m_itemPositions.first()->basicPreferredSize();
217
if (m_layoutOrientation == Qt::Vertical) {
218
maxRows = qMin(qMax(1, int(m_groupItem->geometry().width() / itemSize.width())), m_maxRows);
220
maxRows = qMin(qMax(1, int(m_groupItem->geometry().height() / itemSize.height())), m_maxRows);
223
//kDebug() << "maximum rows: " << maxRows << m_maxRows << m_groupItem->geometry().height() << itemSize.height();
227
//returns a reasonable amount of columns
228
int TaskItemLayout::preferredColumns()
233
if (m_itemPositions.isEmpty()) {
237
//TODO basicPreferredSize isn't the optimal source here because it changes because of margins probably
238
QSizeF itemSize = m_itemPositions.first()->basicPreferredSize();
239
//kDebug() << itemSize.width() << m_groupItem->geometry().width();
240
if (m_layoutOrientation == Qt::Vertical) {
241
m_rowSize = qMax(1, int(m_groupItem->geometry().height() / itemSize.height()));
243
//Launchers doesn't need the same space as task- and groupitems on horizontal Layouts so the size needs to be adjusted
244
qreal horizontalSpace = m_groupItem->geometry().width();
245
int numberOflaunchers = 0;
246
foreach (AbstractTaskItem *item, m_itemPositions) {
247
if (item->abstractItem() && item->abstractItem()->itemType() == TaskManager::LauncherItemType) {
248
horizontalSpace -= item->preferredHeight(); //The icon is a square so we can use the height as width
252
m_rowSize = qMax(1, int(horizontalSpace / itemSize.width()));
253
m_rowSize += numberOflaunchers;
256
//kDebug() << "preferred columns: " << qMax(1, m_rowSize);
257
return qMax(1, m_rowSize);
261
QPair<int, int> TaskItemLayout::gridLayoutSize()
263
int groupSize = size();
265
int columns = preferredColumns();
266
int maxRows = maximumRows();
268
//check for adjustments on columns because there isnt room enough yet for all of the items
269
while (ceil(static_cast<float>(groupSize)/static_cast<float>(columns)) > maxRows) {
270
columns++; // more rows needed than allowed so we add some columns instead
272
//kDebug() << "groupWidth" << columns << maxRows << m_maxRows;
277
rows = ceil(static_cast<float>(groupSize) / static_cast<float>(columns)); //actually needed rows
280
return QPair<int,int>(columns, rows);
284
void TaskItemLayout::layoutItems()
288
QPair<int,int> grid = gridLayoutSize();
289
int columns = qMax(grid.first, 1);
290
//int rows = qMax(grid.second, 1);
292
//kDebug() << "Laying out with" << columns << rows;
293
//kDebug() << "geometry" << m_groupItem->geometry();
294
//int rowHeight = qMax(1, int(m_groupItem->geometry().height() / rows));
295
//kDebug() << "rowHeight" << rowHeight;
296
//int columnWidth = qMax(1, int(m_groupItem->geometry().size().width() / columns));
297
//kDebug() << "column width set to " << columnWidth;
299
//FIXME: resetting column preferred sizesthey shouldn't be taken into account for inexistent ones but they are, probably upstream issue
300
for (int i = 0; i < columnCount(); ++i) {
301
setColumnMaximumWidth(i, 0);
302
setColumnPreferredWidth(i, 0);
305
for (int i = 0; i < rowCount(); ++i) {
306
setRowMaximumHeight(i, 0);
307
setRowPreferredHeight(i, 0);
315
QSizeF maximumCellSize;
316
if (!m_itemPositions.isEmpty()) {
317
maximumCellSize = m_itemPositions.first()->basicPreferredSize() * 1.8;
320
setHorizontalSpacing(0);
321
setVerticalSpacing(0);
323
//go through all items of this layoutwidget and populate the layout with items
324
int numberOfItems = 0;
325
foreach (AbstractTaskItem *item, m_itemPositions) {
328
if (m_layoutOrientation == Qt::Vertical) {
329
row = numberOfItems % columns;
330
col = numberOfItems / columns;
332
row = numberOfItems / columns;
333
col = numberOfItems % columns;
336
//not good if we don't recreate the layout every time
337
//m_layout->setColumnPreferredWidth(col, columnWidth);//Somehow this line is absolutely crucial
338
//m_layout->setRowPreferredHeight(row, rowHeight);//Somehow this line is absolutely crucial
341
//FIXME: this is a glorious hack
342
if (maximumCellSize.isValid()) {
343
if (m_layoutOrientation == Qt::Vertical) {
344
setRowMaximumHeight(row, maximumCellSize.height());
345
setColumnMaximumWidth(col, QWIDGETSIZE_MAX);
347
if (item->abstractItem() && item->abstractItem()->itemType() == TaskManager::LauncherItemType) {
348
setColumnFixedWidth(col, maximumCellSize.height()); //The Icon size is a sqare, so it needs the same width as height
350
setColumnMaximumWidth(col, maximumCellSize.width());
352
setRowMaximumHeight(row, QWIDGETSIZE_MAX);
354
setRowPreferredHeight(row, maximumCellSize.height());
355
setColumnPreferredWidth(col, maximumCellSize.width());
358
if (item->abstractItem() &&
359
item->abstractItem()->itemType() == TaskManager::GroupItemType) {
361
TaskGroupItem *group = static_cast<TaskGroupItem*>(item);
362
if (group->collapsed()) {
363
group->unsplitGroup();
364
addItem(item, row, col, 1, 1);
367
TaskItemLayout *layout = group->tasksLayout();
369
kDebug() << "group has no valid layout";
373
int groupRowWidth = m_layoutOrientation == Qt::Vertical ? layout->numberOfRows() : layout->numberOfColumns();
375
if ((columns - col) < groupRowWidth) {
376
//we need to split the group
377
int splitIndex = columns - col;//number of items in group that are on this row
378
if (m_layoutOrientation == Qt::Vertical) {
379
addItem(item, row, col, splitIndex, 1);
381
addItem(item, row, col, 1, splitIndex);
384
//kDebug() << "add normal item: split index = column span " << splitIndex;
385
TaskGroupItem *splitChild = group->splitGroup(splitIndex);
387
//also add the second part of the group if there is one
388
if (m_layoutOrientation == Qt::Vertical) {
389
addItem(splitChild, 0, col + 1, groupRowWidth - splitIndex, 1);
391
addItem(splitChild, row + 1, 0, 1, groupRowWidth - splitIndex);
394
//kDebug() << "add split item: column span " << groupRowWidth - splitIndex;
396
//Add the normal item
397
group->unsplitGroup();
399
if (m_layoutOrientation == Qt::Vertical) {
400
addItem(item, row, col, groupRowWidth, 1);
402
addItem(item, row, col, 1, groupRowWidth);
404
//kDebug() << "add unsplit expanded item over columns " << groupRowWidth;
407
numberOfItems += groupRowWidth;
410
addItem(item, row, col, 1, 1);
414
//kDebug() << "addItem at: " << row << col;
417
updatePreferredSize();
418
//m_groupItem->setLayout(m_layout);
422
void TaskItemLayout::updatePreferredSize()
424
//kDebug() << "column count: " << m_layout->columnCount();
427
QSizeF s = itemAt(0)->preferredSize();
428
//kDebug() << s << columnCount();
429
setPreferredSize(s.width() * columnCount(), s.height() * rowCount());
431
//Empty taskbar, arbitrary small value
432
kDebug() << "Empty layout!!!!!!!!!!!!!!!!!!";
433
if (m_layoutOrientation == Qt::Vertical) {
434
setPreferredSize(/*m_layout->preferredSize().width()*/10, 10); //since we recreate the layout we don't have the previous values
436
setPreferredSize(10, /*m_layout->preferredSize().height()*/10);
439
//kDebug() << "preferred size: " << m_layout->preferredSize();
440
m_groupItem->updatePreferredSize();
443
void TaskItemLayout::setMaximumRows(int rows)
445
if (rows != m_maxRows) {
451
void TaskItemLayout::setForceRows(bool forceRows)
453
m_forceRows = forceRows;
456
int TaskItemLayout::insertionIndexAt(const QPointF &pos)
458
int insertIndex = -1;
459
int row = numberOfRows();
460
int col = numberOfColumns();
462
//if pos is (-1,-1) insert at the end of the panel
463
if (pos.toPoint() == QPoint(-1, -1)) {
467
QRectF siblingGeometry;
470
for (int i = 0; i < numberOfRows(); i++) {
471
if (m_layoutOrientation == Qt::Vertical) {
472
siblingGeometry = itemAt(0, i)->geometry();//set geometry of single item
473
if (pos.x() <= siblingGeometry.right()) {
478
siblingGeometry = itemAt(i, 0)->geometry();//set geometry of single item
479
if (pos.y() <= siblingGeometry.bottom()) {
486
for (int i = 0; i < numberOfColumns(); i++) {
487
if (m_layoutOrientation == Qt::Vertical) {
488
siblingGeometry = itemAt(i, 0)->geometry();//set geometry of single item
489
qreal vertMiddle = (siblingGeometry.top() + siblingGeometry.bottom()) / 2.0;
490
if (pos.y() < vertMiddle) {
495
} else if (itemAt(0, i)) {
496
siblingGeometry = itemAt(0, i)->geometry();//set geometry of single item
497
qreal horizMiddle = (siblingGeometry.left() + siblingGeometry.right()) / 2.0;
498
//kDebug() << "pos middle " << pos.x() << horizMiddle;
499
if (pos.x() < horizMiddle) {
507
//kDebug() << row << col;
509
insertIndex = row * numberOfColumns() + col;
511
if (insertIndex > count()) {
513
//kDebug() << "correction";
516
//kDebug() << "insert Index" << insertIndex;
520
int TaskItemLayout::numberOfRows()
522
if (m_layoutOrientation == Qt::Vertical) {
523
return columnCount();
529
int TaskItemLayout::numberOfColumns()
531
if (m_layoutOrientation == Qt::Vertical) {
534
return columnCount();
538
#include "taskitemlayout.moc"