#include "qlayout.h"
#include "private/qlayoutengine_p.h"
#include "qvector.h"
#include "qwidget.h"
#include <qlist.h>
#include <qalgorithms.h>
#include <qdebug.h>
Include dependency graph for qlayoutengine.cpp:

Go to the source code of this file.
Typedefs | |
| typedef qint64 | Fixed |
Functions | |
| static Fixed | toFixed (int i) |
| static int | fRound (Fixed i) |
| void | qGeomCalc (QVector< QLayoutStruct > &chain, int start, int count, int pos, int space, int spacer) |
| Q_GUI_EXPORT QSize | qSmartMinSize (const QWidgetItem *i) |
| Q_GUI_EXPORT QSize | qSmartMinSize (const QWidget *w) |
| Q_GUI_EXPORT QSize | qSmartMaxSize (const QWidgetItem *i, Qt::Alignment align) |
| Q_GUI_EXPORT QSize | qSmartMaxSize (const QWidget *w, Qt::Alignment align) |
Definition at line 36 of file qlayoutengine.cpp.
| static int fRound | ( | Fixed | i | ) | [inline, static] |
| void qGeomCalc | ( | QVector< QLayoutStruct > & | chain, | |
| int | start, | |||
| int | count, | |||
| int | pos, | |||
| int | space, | |||
| int | spacer | |||
| ) |
Definition at line 57 of file qlayoutengine.cpp.
References QVector< T >::empty(), fRound(), i, n, p, qDebug(), qMin(), qSort(), QVector< T >::size(), size, space_left(), toFixed(), and w.
Referenced by QBoxLayoutPrivate::calcHfw(), QGridLayoutPrivate::distribute(), distributeMultiBox(), QSplitterPrivate::doResize(), QDockAreaLayoutInfo::fitItems(), QDockWidgetLayout::fitLayout(), QGridLayoutPrivate::heightForWidth(), QTabBarPrivate::layoutTabs(), and QBoxLayout::setGeometry().
00059 { 00060 int cHint = 0; 00061 int cMin = 0; 00062 int cMax = 0; 00063 int sumStretch = 0; 00064 int spacerCount = 0; 00065 00066 bool wannaGrow = false; // anyone who really wants to grow? 00067 // bool canShrink = false; // anyone who could be persuaded to shrink? 00068 00069 bool allEmptyNonstretch = true; 00070 int i; 00071 for (i = start; i < start + count; i++) { 00072 chain[i].done = false; 00073 cHint += chain[i].smartSizeHint(); 00074 cMin += chain[i].minimumSize; 00075 cMax += chain[i].maximumSize; 00076 sumStretch += chain[i].stretch; 00077 if (!chain[i].empty) 00078 spacerCount++; 00079 wannaGrow = wannaGrow || chain[i].expansive || chain[i].stretch > 0; 00080 allEmptyNonstretch = allEmptyNonstretch && !wannaGrow && chain[i].empty; 00081 } 00082 00083 int extraspace = 0; 00084 if (spacerCount) 00085 spacerCount--; // only spacers between things 00086 00087 if (space < cMin + spacerCount * spacer) { 00088 /* 00089 Less space than minimumSize; take from the biggest first 00090 */ 00091 00092 int minSize = cMin + spacerCount * spacer; 00093 00094 //shrink the spacers proportionally 00095 spacer = minSize > 0 ? (spacer * space) / minSize : 0; 00096 00097 QList<int> list; 00098 00099 for (i = start; i < start+count; i++) { 00100 list << chain[i].minimumSize; 00101 } 00102 00103 qSort(list); 00104 00105 int space_left = space - spacerCount*spacer; 00106 00107 int sum = 0; 00108 int idx = 0; 00109 int space_used=0; 00110 int current = 0; 00111 while (idx < count && space_used < space_left) { 00112 current = list.at(idx); 00113 space_used = sum + current * (count - idx); 00114 sum += current; 00115 ++idx; 00116 } 00117 --idx; 00118 int deficit = space_used - space_left; 00119 00120 int items = count - idx; 00121 int maxval = current - deficit/items; 00122 00123 for (i = start; i < start+count; i++) { 00124 chain[i].size = qMin(chain[i].minimumSize, maxval); 00125 chain[i].done = true; 00126 } 00127 } else if (space < cHint + spacerCount*spacer) { 00128 /* 00129 Less space than smartSizeHint(), but more than minimumSize. 00130 Currently take space equally from each, as in Qt 2.x. 00131 Commented-out lines will give more space to stretchier 00132 items. 00133 */ 00134 int n = count; 00135 int space_left = space - spacerCount*spacer; 00136 int overdraft = cHint - space_left; 00137 00138 // first give to the fixed ones: 00139 for (i = start; i < start + count; i++) { 00140 if (!chain[i].done 00141 && chain[i].minimumSize >= chain[i].smartSizeHint()) { 00142 chain[i].size = chain[i].smartSizeHint(); 00143 chain[i].done = true; 00144 space_left -= chain[i].smartSizeHint(); 00145 // sumStretch -= chain[i].stretch; 00146 n--; 00147 } 00148 } 00149 bool finished = n == 0; 00150 while (!finished) { 00151 finished = true; 00152 Fixed fp_over = toFixed(overdraft); 00153 Fixed fp_w = 0; 00154 00155 for (i = start; i < start+count; i++) { 00156 if (chain[i].done) 00157 continue; 00158 // if (sumStretch <= 0) 00159 fp_w += fp_over / n; 00160 // else 00161 // fp_w += (fp_over * chain[i].stretch) / sumStretch; 00162 int w = fRound(fp_w); 00163 chain[i].size = chain[i].smartSizeHint() - w; 00164 fp_w -= toFixed(w); // give the difference to the next 00165 if (chain[i].size < chain[i].minimumSize) { 00166 chain[i].done = true; 00167 chain[i].size = chain[i].minimumSize; 00168 finished = false; 00169 overdraft -= (chain[i].smartSizeHint() 00170 - chain[i].minimumSize); 00171 // sumStretch -= chain[i].stretch; 00172 n--; 00173 break; 00174 } 00175 } 00176 } 00177 } else { // extra space 00178 int n = count; 00179 int space_left = space - spacerCount*spacer; 00180 // first give to the fixed ones, and handle non-expansiveness 00181 for (i = start; i < start + count; i++) { 00182 if (!chain[i].done 00183 && (chain[i].maximumSize <= chain[i].smartSizeHint() 00184 || (wannaGrow && !chain[i].expansive && chain[i].stretch == 0) 00185 || (!allEmptyNonstretch && chain[i].empty && 00186 !chain[i].expansive && chain[i].stretch == 0))) { 00187 chain[i].size = chain[i].smartSizeHint(); 00188 chain[i].done = true; 00189 space_left -= chain[i].size; 00190 sumStretch -= chain[i].stretch; 00191 n--; 00192 } 00193 } 00194 extraspace = space_left; 00195 00196 /* 00197 Do a trial distribution and calculate how much it is off. 00198 If there are more deficit pixels than surplus pixels, give 00199 the minimum size items what they need, and repeat. 00200 Otherwise give to the maximum size items, and repeat. 00201 00202 Paul Olav Tvete has a wonderful mathematical proof of the 00203 correctness of this principle, but unfortunately this 00204 comment is too small to contain it. 00205 */ 00206 int surplus, deficit; 00207 do { 00208 surplus = deficit = 0; 00209 Fixed fp_space = toFixed(space_left); 00210 Fixed fp_w = 0; 00211 for (i = start; i < start+count; i++) { 00212 if (chain[i].done) 00213 continue; 00214 extraspace = 0; 00215 if (sumStretch <= 0) 00216 fp_w += fp_space / n; 00217 else 00218 fp_w += (fp_space * chain[i].stretch) / sumStretch; 00219 int w = fRound(fp_w); 00220 chain[i].size = w; 00221 fp_w -= toFixed(w); // give the difference to the next 00222 if (w < chain[i].smartSizeHint()) { 00223 deficit += chain[i].smartSizeHint() - w; 00224 } else if (w > chain[i].maximumSize) { 00225 surplus += w - chain[i].maximumSize; 00226 } 00227 } 00228 if (deficit > 0 && surplus <= deficit) { 00229 // give to the ones that have too little 00230 for (i = start; i < start+count; i++) { 00231 if (!chain[i].done && 00232 chain[i].size < chain[i].smartSizeHint()) { 00233 chain[i].size = chain[i].smartSizeHint(); 00234 chain[i].done = true; 00235 space_left -= chain[i].smartSizeHint(); 00236 sumStretch -= chain[i].stretch; 00237 n--; 00238 } 00239 } 00240 } 00241 if (surplus > 0 && surplus >= deficit) { 00242 // take from the ones that have too much 00243 for (i = start; i < start+count; i++) { 00244 if (!chain[i].done && 00245 chain[i].size > chain[i].maximumSize) { 00246 chain[i].size = chain[i].maximumSize; 00247 chain[i].done = true; 00248 space_left -= chain[i].maximumSize; 00249 sumStretch -= chain[i].stretch; 00250 n--; 00251 } 00252 } 00253 } 00254 } while (n > 0 && surplus != deficit); 00255 if (n == 0) 00256 extraspace = space_left; 00257 } 00258 00259 /* 00260 As a last resort, we distribute the unwanted space equally 00261 among the spacers (counting the start and end of the chain). We 00262 could, but don't, attempt a sub-pixel allocation of the extra 00263 space. 00264 */ 00265 int extra = extraspace / (spacerCount + 2); 00266 int p = pos + extra; 00267 for (i = start; i < start+count; i++) { 00268 chain[i].pos = p; 00269 p = p + chain[i].size; 00270 if (!chain[i].empty) 00271 p += spacer+extra; 00272 } 00273 00274 00275 #ifdef QLAYOUT_EXTRA_DEBUG 00276 qDebug() << "qGeomCalc" << "start" << start << "count" << count << "pos" << pos << "space" << space << "spacer" << spacer; 00277 for (i = start; i < start + count; i++) { 00278 qDebug() << i << ":" << chain[i].minimumSize << chain[i].smartSizeHint() << chain[i].maximumSize 00279 << "stretch" << chain[i].stretch << "empty" << chain[i].empty << "expansive" << chain[i].expansive; 00280 qDebug() << "result pos" << chain[i].pos << "size" << chain[i].size; 00281 } 00282 #endif 00283 }
Here is the call graph for this function:

Definition at line 347 of file qlayoutengine.cpp.
References qSmartMaxSize(), and w.
00348 { 00349 QWidgetItem item(const_cast<QWidget *>(w)); 00350 return qSmartMaxSize(&item, align); 00351 }
Here is the call graph for this function:

| Q_GUI_EXPORT QSize qSmartMaxSize | ( | const QWidgetItem * | i, | |
| Qt::Alignment | align | |||
| ) |
Definition at line 324 of file qlayoutengine.cpp.
Referenced by QLayout::closestAcceptableSize(), QWidgetItem::maximumSize(), QDockAreaLayoutItem::maximumSize(), qSmartMaxSize(), QWidgetItem::setGeometry(), and QScrollAreaPrivate::updateScrollBars().
00325 { 00326 QWidget *w = ((QWidgetItem*)i)->widget(); 00327 if (align & Qt::AlignHorizontal_Mask && align & Qt::AlignVertical_Mask) 00328 return QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX); 00329 QSize s = w->maximumSize(); 00330 if (s.width() == QWIDGETSIZE_MAX && !(align & Qt::AlignHorizontal_Mask)) 00331 if (!(w->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag)) 00332 s.setWidth(w->sizeHint().width()); 00333 00334 if (s.height() == QWIDGETSIZE_MAX && !(align & Qt::AlignVertical_Mask)) 00335 if (!(w->sizePolicy().verticalPolicy() & QSizePolicy::GrowFlag)) 00336 s.setHeight(w->sizeHint().height()); 00337 00338 s = s.expandedTo(w->minimumSize()); 00339 00340 if (align & Qt::AlignHorizontal_Mask) 00341 s.setWidth(QLAYOUTSIZE_MAX); 00342 if (align & Qt::AlignVertical_Mask) 00343 s.setHeight(QLAYOUTSIZE_MAX); 00344 return s; 00345 }
Definition at line 318 of file qlayoutengine.cpp.
References qSmartMinSize(), and w.
00319 { 00320 QWidgetItem item(const_cast<QWidget *>(w)); 00321 return qSmartMinSize(&item); 00322 }
Here is the call graph for this function:

| Q_GUI_EXPORT QSize qSmartMinSize | ( | const QWidgetItem * | i | ) |
Definition at line 285 of file qlayoutengine.cpp.
Referenced by QSplitterPrivate::addContribution(), QWorkspace::addWindow(), QWorkspace::cascade(), QLayout::closestAcceptableSize(), QSplitterPrivate::doMove(), QSplitterPrivate::doResize(), QStatusBar::event(), QSplitterPrivate::findWidgetJustBeforeOrJustAfter(), QWidgetItem::minimumSize(), QStackedLayout::minimumSize(), QDockAreaLayoutItem::minimumSize(), QSplitter::minimumSizeHint(), QWidgetResizeHandler::mouseMoveEvent(), qSmartMinSize(), QSplitterPrivate::recalc(), QStatusBar::reformat(), QSplitterPrivate::setGeo(), QSplitter::setSizes(), Q3WidgetStack::sizeHint(), and QScrollAreaPrivate::updateScrollBars().
00286 { 00287 QWidget *w = ((QWidgetItem *)i)->widget(); 00288 00289 QSize s(0, 0); 00290 QSize msh(w->minimumSizeHint()); 00291 QSize sh(w->sizeHint()); 00292 00293 if (w->sizePolicy().horizontalPolicy() != QSizePolicy::Ignored) { 00294 if (w->sizePolicy().horizontalPolicy() & QSizePolicy::ShrinkFlag) 00295 s.setWidth(msh.width()); 00296 else 00297 s.setWidth(qMax(sh.width(), msh.width())); 00298 } 00299 00300 if (w->sizePolicy().verticalPolicy() != QSizePolicy::Ignored) { 00301 if (w->sizePolicy().verticalPolicy() & QSizePolicy::ShrinkFlag) { 00302 s.setHeight(msh.height()); 00303 } else { 00304 s.setHeight(qMax(sh.height(), msh.height())); 00305 } 00306 } 00307 00308 s = s.boundedTo(w->maximumSize()); 00309 QSize min = w->minimumSize(); 00310 if (min.width() > 0) 00311 s.setWidth(min.width()); 00312 if (min.height() > 0) 00313 s.setHeight(min.height()); 00314 00315 return s.expandedTo(QSize(0,0)); 00316 }
| static Fixed toFixed | ( | int | i | ) | [inline, static] |
1.5.1