00001 #include "layoutwidget.h"
00002
00003
00004 #include <taskmanager/taskmanager.h>
00005 #include <taskmanager/abstractgroupableitem.h>
00006 #include <taskmanager/groupmanager.h>
00007
00008
00009 #include <QList>
00010 #include <QGraphicsScene>
00011 #include <QGraphicsGridLayout>
00012 #include <QPainter>
00013
00014 #include <math.h>
00015
00016 #include "windowtaskitem.h"
00017 #include "taskgroupitem.h"
00018
00019
00020
00021 LayoutWidget::LayoutWidget(TaskGroupItem *parent, Tasks *applet)
00022 : QObject(parent),
00023 m_hasSpacer(false),
00024 m_spacer(0),
00025 m_groupItem(parent),
00026 m_rowSize(1),
00027 m_maxRows(1),
00028 m_forceRows(false),
00029 m_applet(applet),
00030 m_layout(0)
00031 {
00032 init();
00033
00034 foreach(AbstractTaskItem *item, m_groupItem->memberList()) {
00035 addTaskItem(item);
00036 }
00037 }
00038
00039 LayoutWidget::~LayoutWidget()
00040 {
00041
00042 }
00043
00044
00045 void LayoutWidget::init()
00046 {
00047 createLayout();
00048
00049 }
00050
00051
00052 void LayoutWidget::constraintsChanged(Plasma::Constraints constraints)
00053 {
00054 Q_ASSERT(m_applet);
00055
00056
00057 if (constraints & Plasma::SizeConstraint) {
00058 layoutItems();
00059 }
00060 }
00061
00062 void LayoutWidget::addTaskItem(AbstractTaskItem * item)
00063 {
00064
00065 if (!item) {
00066 kDebug() << "invalid item";
00067 return;
00068 }
00069 if (m_itemPositions.contains(item)) {
00070 kDebug() << "already in this layout";
00071 return;
00072 }
00073 if (item->abstractItem()) {
00074 if (item->abstractItem()->isGroupItem()) {
00075 connect(static_cast<TaskGroupItem*>(item), SIGNAL(changed()), this, SLOT(update()));
00076 }
00077 }
00078 if (m_groupItem->scene() && !item->scene()) {
00079
00080 m_groupItem->scene()->addItem(item);
00081
00082 }
00083
00084 if (!insert(m_groupItem->indexOf(item), item)) {
00085 kDebug() << "error on insert";
00086 return;
00087 }
00088 item->show();
00089
00090 }
00091
00092 void LayoutWidget::removeTaskItem(AbstractTaskItem * item)
00093 {
00094 if (!remove(item)) {
00095 return;
00096 }
00097
00098
00099
00100 if (m_groupItem->scene()) {
00101
00102 m_groupItem->scene()->removeItem(item);
00103 } else {
00104 kDebug() << "No Scene available";
00105 }
00106
00107 }
00108
00109 bool LayoutWidget::insert(int index, AbstractTaskItem* item)
00110 {
00111
00112 if (!item ) {
00113 kDebug() << "error";
00114 return false;
00115 }
00116 int listIndex;
00117 for (listIndex = 0; listIndex < m_itemPositions.size(); listIndex++) {
00118 if (index <= m_groupItem->indexOf(m_itemPositions.at(listIndex))) {
00119 break;
00120 }
00121 }
00122
00123 m_itemPositions.insert(listIndex, item);
00124
00125 layoutItems();
00126 return true;
00127 }
00128
00129 bool LayoutWidget::remove(AbstractTaskItem* item)
00130 {
00131 if (!item) {
00132 kDebug() << "null Item";
00133 }
00134
00135 m_itemPositions.removeAll(item);
00136 layoutItems();
00137 return true;
00138 }
00139
00140 void LayoutWidget::update()
00141 {
00142
00143 layoutItems();
00144 }
00145
00146
00148 int LayoutWidget::size()
00149 {
00150 int groupSize = 0;
00151
00152 foreach (AbstractTaskItem *item, m_groupItem->memberList()) {
00153 if (!item->abstractItem()) {
00154 kDebug() << "Error, invalid item in groupMembers";
00155 continue;
00156 }
00157
00158 if (item->abstractItem()->isGroupItem()) {
00159 TaskGroupItem *group = static_cast<TaskGroupItem*>(item);
00160 if (!group->collapsed()) {
00161 LayoutWidget *layout = dynamic_cast<LayoutWidget*>(group->layoutWidget());
00162 if (!layout) {
00163 kDebug() << "Error group has no layout";
00164 continue;
00165 }
00166 groupSize += layout->size();
00167 continue;
00168 }
00169 }
00170 groupSize++;
00171 }
00172
00173
00174 return groupSize;
00175 }
00176
00177
00178 int LayoutWidget::maximumRows()
00179 {
00180 int maxRows;
00181 if (m_itemPositions.isEmpty()) {
00182 return 1;
00183 }
00184
00185 if (m_forceRows) {
00186 return m_maxRows;
00187 }
00188
00189
00190
00191 QSizeF itemSize = m_itemPositions.first()->basicPreferredSize();
00192 if (m_applet->formFactor() == Plasma::Vertical) {
00193 maxRows = qMin(qMax(1, int(m_groupItem->geometry().width() / itemSize.width())), m_maxRows);
00194 } else {
00195 maxRows = qMin(qMax(1, int(m_groupItem->geometry().height() / itemSize.height())), m_maxRows);
00196 }
00197
00198 return maxRows;
00199 }
00200
00201
00202 int LayoutWidget::preferredColumns()
00203 {
00204 if (m_forceRows) {
00205 m_rowSize = 1;
00206 } else {
00207 if (m_itemPositions.isEmpty()) {
00208 return 1;
00209 }
00210
00211
00212 QSizeF itemSize = m_itemPositions.first()->basicPreferredSize();
00213
00214 if (m_applet->formFactor() == Plasma::Vertical) {
00215 m_rowSize = qMax(1, int(m_groupItem->geometry().height() / itemSize.height()));
00216 } else {
00217 m_rowSize = qMax(1, int(m_groupItem->geometry().width() / itemSize.width()));
00218 }
00219 }
00220
00221 return qMax(1, qMin(m_rowSize, size()));
00222 }
00223
00224 QPair<int, int> LayoutWidget::gridLayoutSize()
00225 {
00226 int groupSize = size();
00227
00228 int columns = preferredColumns();
00229 int maxRows = maximumRows();
00230
00231
00232 while (ceil(static_cast<float>(groupSize)/static_cast<float>(columns)) > maxRows) {
00233 columns++;
00234 }
00235
00236 int rows;
00237 if (m_forceRows) {
00238 rows = maxRows;
00239 } else {
00240 rows = ceil(static_cast<float>(groupSize) / static_cast<float>(columns));
00241 }
00242
00243 return QPair <int,int> (columns, rows);
00244 }
00245
00246 void LayoutWidget::createLayout()
00247 {
00248 m_layout = new QGraphicsGridLayout(m_groupItem);
00249 m_layout->setContentsMargins(0,0,0,0);
00250 m_layout->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));
00251 m_layout->setMaximumSize(INT_MAX,INT_MAX);
00252 }
00253
00254 void LayoutWidget::layoutItems()
00255 {
00256
00257
00258 QPair <int,int> grid = gridLayoutSize();
00259 int columns = grid.first;
00260 int rows = grid.second;
00261
00262
00263
00264 int rowHeight = qMax(1, int(m_groupItem->geometry().height() / rows));
00265
00266 int columnWidth = qMax(1, int(m_groupItem->geometry().size().width() / columns));
00267
00268
00269 QSizeF maximumCellSize;
00270 if (!m_itemPositions.isEmpty()) {
00271 maximumCellSize = m_itemPositions.first()->basicPreferredSize() * 1.8;
00272 }
00273
00274 createLayout();
00275
00276 if (m_applet->formFactor() == Plasma::Vertical) {
00277 m_layout->setHorizontalSpacing(0);
00278 m_layout->setVerticalSpacing(2);
00279 } else {
00280 m_layout->setHorizontalSpacing(2);
00281 m_layout->setVerticalSpacing(0);
00282 }
00283
00284
00285 int numberOfItems = 0;
00286 foreach (AbstractTaskItem *item, m_itemPositions) {
00287 int row;
00288 int col;
00289 if (!m_forceRows) {
00290 if (m_applet->formFactor() == Plasma::Vertical) {
00291 row = numberOfItems % columns;
00292 col = numberOfItems / columns;
00293 } else {
00294 row = numberOfItems / columns;
00295 col = numberOfItems % columns;
00296 }
00297
00298 } else {
00299 if (m_applet->formFactor() == Plasma::Vertical) {
00300 row = numberOfItems / rows;
00301 col = numberOfItems % rows;
00302 } else {
00303 row = numberOfItems % rows;
00304 col = numberOfItems / rows;
00305 }
00306 }
00307
00308
00309 m_layout->setColumnPreferredWidth(col, columnWidth);
00310 m_layout->setRowPreferredHeight(row, rowHeight);
00311
00312 if (maximumCellSize.isValid()) {
00313 if (m_applet->formFactor() == Plasma::Vertical) {
00314 m_layout->setRowMaximumHeight(row, maximumCellSize.height());
00315 } else {
00316 m_layout->setColumnMaximumWidth(col, maximumCellSize.width());
00317 }
00318 }
00319
00320 if (item->abstractItem() && item->abstractItem()->isGroupItem()) {
00321 TaskGroupItem *group = static_cast<TaskGroupItem*>(item);
00322 if (group->collapsed()) {
00323 group->unsplitGroup();
00324 m_layout->addItem(item, row, col, 1, 1);
00325 } else {
00326 LayoutWidget *layout = group->layoutWidget();
00327 if (!layout) {
00328 kDebug() << "group has no valid layout";
00329 continue;
00330 }
00331 int groupRowWidth = layout->numberOfColumns();
00332
00333 if ((columns-col) < groupRowWidth) {
00334 int splitIndex = columns - col;
00335 TaskGroupItem *splitChild = group->splitGroup(splitIndex);
00336 m_layout->addItem(item, row, col, 1, splitIndex);
00337
00338 if (splitChild) {
00339 m_layout->addItem(splitChild, row + 1, 0, 1, groupRowWidth - splitIndex);
00340 }
00341
00342 } else {
00343 group->unsplitGroup();
00344 m_layout->addItem(item, row, col, 1, groupRowWidth);
00345
00346 }
00347
00348 numberOfItems += groupRowWidth - 1;
00349 }
00350 } else {
00351 m_layout->addItem(item, row, col, 1, 1);
00352 }
00353
00354
00355 numberOfItems++;
00356 }
00357
00358 updatePreferredSize();
00359 m_groupItem->setLayout(m_layout);
00360 }
00361
00362
00363 void LayoutWidget::updatePreferredSize()
00364 {
00365
00366
00367 if (m_layout->count() > 0) {
00368 AbstractTaskItem *item = dynamic_cast<AbstractTaskItem *>(m_layout->itemAt(0));
00369 Q_ASSERT(item);
00370 m_layout->setPreferredSize(item->basicPreferredSize().width()*m_layout->columnCount(), item->basicPreferredSize().height()*m_layout->rowCount());
00371
00372 } else {
00373 kDebug() << "Empty layout!!!!!!!!!!!!!!!!!!";
00374 if (m_applet->formFactor() == Plasma::Vertical) {
00375 m_layout->setPreferredSize(10, 10);
00376 } else {
00377 m_layout->setPreferredSize(10, 10);
00378 }
00379 }
00380
00381 emit sizeHintChanged(Qt::PreferredSize);
00382 }
00383
00384 void LayoutWidget::setMaximumRows(int rows)
00385 {
00386 m_maxRows = rows;
00387 }
00388
00389 void LayoutWidget::setForceRows(bool forceRows)
00390 {
00391 m_forceRows = forceRows;
00392 }
00393
00394 int LayoutWidget::insertionIndexAt(const QPointF &pos)
00395 {
00396 int insertIndex = -1;
00397 int row = numberOfRows();
00398 int col = numberOfColumns();
00399
00400
00401 if (pos.toPoint() == QPoint(-1, -1)) {
00402 kDebug() << "Error";
00403 return -1;
00404 } else {
00405 QRectF siblingGeometry;
00406
00407
00408 for (int i = 0; i < numberOfRows(); i++) {
00409 if (m_applet->formFactor() == Plasma::Vertical) {
00410 siblingGeometry = m_layout->itemAt(0, i)->geometry();
00411 if (pos.x() <= siblingGeometry.right()) {
00412 row = i;
00413 break;
00414 }
00415 } else {
00416 siblingGeometry = m_layout->itemAt(i, 0)->geometry();
00417 if (pos.y() <= siblingGeometry.bottom()) {
00418 row = i;
00419 break;
00420 }
00421 }
00422 }
00423
00424 for (int i = 0; i < numberOfColumns(); i++) {
00425 if (m_applet->formFactor() == Plasma::Vertical) {
00426 siblingGeometry = m_layout->itemAt(i, 0)->geometry();
00427 qreal vertMiddle = (siblingGeometry.top() + siblingGeometry.bottom()) / 2.0;
00428 if (pos.y() < vertMiddle) {
00429 col = i;
00430 break;
00431 }
00432
00433 } else {
00434 siblingGeometry = m_layout->itemAt(0, i)->geometry();
00435 qreal horizMiddle = (siblingGeometry.left() + siblingGeometry.right()) / 2.0;
00436
00437 if (pos.x() < horizMiddle) {
00438 col = i;
00439 break;
00440 }
00441 }
00442 }
00443 }
00444
00445
00446
00447 if (!m_forceRows) {
00448 insertIndex = row * numberOfColumns() + col;
00449 } else {
00450 insertIndex = col * numberOfRows() + row;
00451 }
00452
00453 if (insertIndex > m_layout->count()) {
00454 insertIndex--;
00455
00456 }
00457
00458
00459 return insertIndex;
00460 }
00461
00462 int LayoutWidget::numberOfRows()
00463 {
00464 if (m_applet->formFactor() == Plasma::Vertical) {
00465 return m_layout->columnCount();
00466 } else {
00467 return m_layout->rowCount();
00468 }
00469 }
00470
00471 int LayoutWidget::numberOfColumns()
00472 {
00473 if (m_applet->formFactor() == Plasma::Vertical) {
00474 return m_layout->rowCount();
00475 } else {
00476 return m_layout->columnCount();
00477 }
00478 }
00479
00480
00481 #include "layoutwidget.moc"
00482