• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Applets

layoutwidget.cpp

Go to the documentation of this file.
00001 #include "layoutwidget.h"
00002 
00003 //Taskmanager
00004 #include <taskmanager/taskmanager.h>
00005 #include <taskmanager/abstractgroupableitem.h>
00006 #include <taskmanager/groupmanager.h>
00007 
00008 // Qt
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 //GroupItem Constructor
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     //kDebug();
00034     foreach(AbstractTaskItem *item, m_groupItem->memberList()) {
00035         addTaskItem(item);
00036     }
00037 }
00038 
00039 LayoutWidget::~LayoutWidget()
00040 {
00041     //kDebug();
00042 }
00043 
00044 
00045 void LayoutWidget::init()
00046 {
00047     createLayout();
00048     //calculatePreferredRowSize();
00049 }
00050 
00051 
00052 void LayoutWidget::constraintsChanged(Plasma::Constraints constraints)
00053 {
00054     Q_ASSERT(m_applet);
00055     //kDebug();
00056 
00057     if (constraints & Plasma::SizeConstraint) {
00058         layoutItems();
00059     }
00060 }
00061 
00062 void LayoutWidget::addTaskItem(AbstractTaskItem * item)
00063 {
00064     //kDebug();
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())); //update on expanding group
00076         }
00077     }
00078     if (m_groupItem->scene() && !item->scene()) {
00079         //kDebug() << "layout widget got scene"<<m_groupItem->scene()<< "add item to scene" <<item->scene();
00080         m_groupItem->scene()->addItem(item);
00081         //kDebug() << "itemScene" << item->scene();
00082     }
00083 
00084    if (!insert(m_groupItem->indexOf(item), item)) {
00085         kDebug() << "error on  insert";
00086         return;
00087     }
00088     item->show();
00089     //kDebug() << "end";
00090 }
00091 
00092 void LayoutWidget::removeTaskItem(AbstractTaskItem * item)
00093 {
00094     if (!remove(item)) {
00095         return;
00096     }
00097 
00098     //kDebug();
00099 
00100     if (m_groupItem->scene()) {
00101         //kDebug() << "got scene";
00102         m_groupItem->scene()->removeItem(item);
00103     } else {
00104         kDebug() << "No Scene available";
00105     }
00106     //kDebug() << "done";
00107 }
00108 
00109 bool LayoutWidget::insert(int index, AbstractTaskItem* item)
00110 {
00111     //kDebug() << item->text() << index;
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     //kDebug();
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()) { //this item is a startup task
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();// increase number of items since expanded groups occupy several spaces
00167                 continue;
00168             }
00169         }
00170         groupSize++;
00171     }
00172 
00173     //kDebug() << "group size" << groupSize;
00174     return groupSize;
00175 }
00176 
00177 //return maximum colums set by the user unless the setting is to high and the items would get unusable
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     // in this case rows are columns, columns are rows...
00190     //TODO basicPreferredSize isn't the optimal source here because  it changes because of margins probably
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     //kDebug() << "maximum rows: " << maxRows << m_maxRows << m_groupItem->geometry().height() << itemSize.height();
00198     return maxRows;
00199 }
00200 
00201 //returns a reasonable amount of columns
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         //TODO basicPreferredSize isn't the optimal source here because  it changes because of margins probably
00212         QSizeF itemSize = m_itemPositions.first()->basicPreferredSize();
00213         //kDebug() << itemSize.width() << m_groupItem->geometry().width();
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     //kDebug() << "preferred columns: " << qMax(1, qMin(m_rowSize, size()));
00221     return qMax(1, qMin(m_rowSize, size()));
00222 }
00223 // <columns,rows>
00224 QPair<int, int> LayoutWidget::gridLayoutSize()
00225 {
00226     int groupSize = size();
00227     //the basic settings
00228     int columns = preferredColumns();
00229     int maxRows = maximumRows();
00230 
00231     //check for adjustments on columns because there isnt room enough yet for all of the items
00232     while (ceil(static_cast<float>(groupSize)/static_cast<float>(columns)) > maxRows) {
00233         columns++;  // more rows needed than allowed so we add some columns instead
00234     }
00235     //kDebug() << "groupWidth" << columns << maxRows << m_maxRows;
00236     int rows;
00237     if (m_forceRows) {
00238         rows = maxRows;
00239     } else {
00240         rows = ceil(static_cast<float>(groupSize) / static_cast<float>(columns)); //actually needed rows
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     //kDebug();
00257 
00258     QPair <int,int> grid = gridLayoutSize();
00259     int columns = grid.first;
00260     int rows = grid.second;
00261 
00262     //kDebug() << "Laying out with" << columns << rows;
00263     //kDebug() << "geometry" << m_groupItem->geometry();
00264     int rowHeight = qMax(1, int(m_groupItem->geometry().height() / rows));
00265     //kDebug() << "rowHeight" << rowHeight;
00266     int columnWidth = qMax(1, int(m_groupItem->geometry().size().width() / columns));
00267     //kDebug() << "column width set to " << columnWidth;
00268 
00269     QSizeF maximumCellSize;
00270     if (!m_itemPositions.isEmpty()) {
00271         maximumCellSize = m_itemPositions.first()->basicPreferredSize() * 1.8;
00272     }
00273 
00274     createLayout(); //its a shame that we have to create a new layout every time but the QGraphicsGridLayout is just to buggy yet
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     //go through all items of this layoutwidget and populate the layout with items
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);//Somehow this line is absolutely crucial
00310         m_layout->setRowPreferredHeight(row, rowHeight);//Somehow this line is absolutely crucial
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) {//we need to split the group
00334                     int splitIndex = columns - col;//number of items in group that are on this row
00335                     TaskGroupItem *splitChild = group->splitGroup(splitIndex);
00336                     m_layout->addItem(item, row, col, 1, splitIndex); //Add the normal item
00337                     //kDebug() << "add normal item: split index = column span " << splitIndex;
00338                     if (splitChild) {
00339                        m_layout->addItem(splitChild, row + 1, 0, 1, groupRowWidth - splitIndex);//also add the second part of the group if there is one
00340                     }
00341                     //kDebug() << "add split item: column span " << groupRowWidth - splitIndex;
00342                 } else  {
00343                     group->unsplitGroup();
00344                     m_layout->addItem(item, row, col, 1, groupRowWidth); //Add the normal item
00345                     //kDebug() << "add unsplit expanded item over columns " << groupRowWidth;
00346                 }
00347 
00348                 numberOfItems += groupRowWidth - 1;
00349             }
00350         } else {
00351             m_layout->addItem(item, row, col, 1, 1);
00352         }
00353 
00354         //kDebug() << "addItem at: " << row  <<  col;
00355         numberOfItems++;
00356     }
00357 
00358     updatePreferredSize();
00359     m_groupItem->setLayout(m_layout);
00360 }
00361 
00362 
00363 void LayoutWidget::updatePreferredSize()
00364 {
00365     //kDebug() << "column count: " << m_layout->columnCount();
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     //Empty taskbar, arbitrary small value
00372     } else {
00373         kDebug() << "Empty layout!!!!!!!!!!!!!!!!!!";
00374         if (m_applet->formFactor() == Plasma::Vertical) {
00375             m_layout->setPreferredSize(/*m_layout->preferredSize().width()*/10, 10); //since we recreate the layout we don't have the previous values
00376         } else {
00377             m_layout->setPreferredSize(10, /*m_layout->preferredSize().height()*/10);
00378         }
00379     }
00380     //kDebug() << "preferred size: " << m_layout->preferredSize();
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     //if pos is (-1,-1) insert at the end of the panel
00401     if (pos.toPoint() == QPoint(-1, -1)) {
00402         kDebug() << "Error";
00403         return -1;
00404     } else {
00405         QRectF siblingGeometry;
00406 
00407         //get correct row
00408         for (int i = 0; i < numberOfRows(); i++) {
00409             if (m_applet->formFactor() == Plasma::Vertical) {
00410                 siblingGeometry = m_layout->itemAt(0, i)->geometry();//set geometry of single item
00411                 if (pos.x() <= siblingGeometry.right()) {
00412                     row = i;
00413                     break;
00414                 }
00415             } else {
00416                 siblingGeometry = m_layout->itemAt(i, 0)->geometry();//set geometry of single item
00417                 if (pos.y() <= siblingGeometry.bottom()) {
00418                     row = i;
00419                     break;
00420                 }
00421             }
00422         }
00423         //and column
00424         for (int i = 0; i < numberOfColumns(); i++) {
00425             if (m_applet->formFactor() == Plasma::Vertical) {
00426                 siblingGeometry = m_layout->itemAt(i, 0)->geometry();//set geometry of single item
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();//set geometry of single item
00435                 qreal horizMiddle = (siblingGeometry.left() + siblingGeometry.right()) / 2.0;
00436                 //kDebug() << "pos middle " << pos.x() << horizMiddle;
00437                 if (pos.x() < horizMiddle) {
00438                     col = i;
00439                     break;
00440                 }
00441             }
00442         }
00443     }
00444 
00445     //kDebug() << row << col;
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         //kDebug() << "correction";
00456     }
00457 
00458     //kDebug() << "insert Index" << insertIndex;
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 

Applets

Skip menu "Applets"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal