summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorJeremy Katz <jeremy.katz@nokia.com>2009-09-25 14:44:15 (GMT)
committerJeremy Katz <jeremy.katz@nokia.com>2009-09-25 14:44:15 (GMT)
commit2c37fde6b5a503a14bb4655a785d51be77fe889b (patch)
treefe35633047ac706f4736fc119bcd2abbb6d79d22 /src/gui
parent2b1f40b7dcf7ef69fe1f832ff544fcb31cf5c3a1 (diff)
parentb4c52810efd42ba9cd8087180a5bf9d48c18de84 (diff)
downloadQt-2c37fde6b5a503a14bb4655a785d51be77fe889b.zip
Qt-2c37fde6b5a503a14bb4655a785d51be77fe889b.tar.gz
Qt-2c37fde6b5a503a14bb4655a785d51be77fe889b.tar.bz2
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/qt into 4.6
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicssceneindex.cpp7
-rw-r--r--src/gui/graphicsview/qgraphicssceneindex_p.h4
-rw-r--r--src/gui/graphicsview/qsimplex_p.cpp173
-rw-r--r--src/gui/image/qmovie.cpp4
-rw-r--r--src/gui/kernel/qapplication_s60.cpp19
-rw-r--r--src/gui/util/qdesktopservices_s60.cpp5
7 files changed, 178 insertions, 36 deletions
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
index 7041d58..49aabf5 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -542,7 +542,7 @@ static bool simplifySequentialChunk(Graph<AnchorVertex, AnchorData> *graph,
void QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation)
{
static bool noSimplification = !qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty();
- if (noSimplification)
+ if (noSimplification || items.isEmpty())
return;
if (graphSimplified[orientation])
diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp
index 3ea957f..f0404fd 100644
--- a/src/gui/graphicsview/qgraphicssceneindex.cpp
+++ b/src/gui/graphicsview/qgraphicssceneindex.cpp
@@ -265,12 +265,13 @@ bool QGraphicsSceneIndexPrivate::itemCollidesWithPath(const QGraphicsItem *item,
/*!
\internal
+ This function returns the items in ascending order.
*/
void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF exposeRect,
QGraphicsSceneIndexIntersector *intersector,
QList<QGraphicsItem *> *items,
const QTransform &viewTransform,
- Qt::ItemSelectionMode mode, Qt::SortOrder order,
+ Qt::ItemSelectionMode mode,
qreal parentOpacity) const
{
Q_ASSERT(item);
@@ -326,7 +327,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe
if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
continue;
recursive_items_helper(child, exposeRect, intersector, items, viewTransform,
- mode, order, opacity);
+ mode, opacity);
}
}
@@ -343,7 +344,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe
if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
continue;
recursive_items_helper(child, exposeRect, intersector, items, viewTransform,
- mode, order, opacity);
+ mode, opacity);
}
}
}
diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h
index 768c724..adebfde 100644
--- a/src/gui/graphicsview/qgraphicssceneindex_p.h
+++ b/src/gui/graphicsview/qgraphicssceneindex_p.h
@@ -138,7 +138,7 @@ public:
void recursive_items_helper(QGraphicsItem *item, QRectF exposeRect,
QGraphicsSceneIndexIntersector *intersector, QList<QGraphicsItem *> *items,
const QTransform &viewTransform,
- Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const;
+ Qt::ItemSelectionMode mode, qreal parentOpacity = 1.0) const;
inline void items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector *intersector,
QList<QGraphicsItem *> *items, const QTransform &viewTransform,
Qt::ItemSelectionMode mode, Qt::SortOrder order) const;
@@ -156,7 +156,7 @@ inline void QGraphicsSceneIndexPrivate::items_helper(const QRectF &rect, QGraphi
Q_Q(const QGraphicsSceneIndex);
const QList<QGraphicsItem *> tli = q->estimateTopLevelItems(rect, Qt::AscendingOrder);
for (int i = 0; i < tli.size(); ++i)
- recursive_items_helper(tli.at(i), rect, intersector, items, viewTransform, mode, order);
+ recursive_items_helper(tli.at(i), rect, intersector, items, viewTransform, mode);
if (order == Qt::DescendingOrder) {
const int n = items->size();
for (int i = 0; i < n / 2; ++i)
diff --git a/src/gui/graphicsview/qsimplex_p.cpp b/src/gui/graphicsview/qsimplex_p.cpp
index e3a991e..1ba24a3 100644
--- a/src/gui/graphicsview/qsimplex_p.cpp
+++ b/src/gui/graphicsview/qsimplex_p.cpp
@@ -48,6 +48,32 @@
QT_BEGIN_NAMESPACE
+/*!
+ \class QSimplex
+
+ The QSimplex class is a Linear Programming problem solver based on the two-phase
+ simplex method.
+
+ It takes a set of QSimplexConstraints as its restrictive constraints and an
+ additional QSimplexConstraint as its objective function. Then methods to maximize
+ and minimize the problem solution are provided.
+
+ The two-phase simplex method is based on the following steps:
+ First phase:
+ 1.a) Modify the original, complex, and possibly not feasible problem, into a new,
+ easy to solve problem.
+ 1.b) Set as the objective of the new problem, a feasible solution for the original
+ complex problem.
+ 1.c) Run simplex to optimize the modified problem and check whether a solution for
+ the original problem exists.
+
+ Second phase:
+ 2.a) Go back to the original problem with the feasibl (but not optimal) solution
+ found in the first phase.
+ 2.b) Set the original objective.
+ 3.c) Run simplex to optimize the original problem towards its optimal solution.
+*/
+
QSimplex::QSimplex() : objective(0), rows(0), columns(0), firstArtificial(0), matrix(0)
{
}
@@ -84,15 +110,31 @@ void QSimplex::clearDataStructures()
objective = 0;
}
+/*!
+ Sets the new constraints in the simplex solver and returns whether the problem
+ is feasible.
+
+ This method sets the new constraints, normalizes them, creates the simplex matrix
+ and runs the first simplex phase.
+*/
bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints)
{
+ ////////////////////////////
+ // Reset to initial state //
+ ////////////////////////////
clearDataStructures();
if (newConstraints.isEmpty())
return true; // we are ok with no constraints
constraints = newConstraints;
- // Set Variables direct mapping
+ ///////////////////////////////////////
+ // Prepare variables and constraints //
+ ///////////////////////////////////////
+
+ // Set Variables direct mapping.
+ // "variables" is a list that provides a stable, indexed list of all variables
+ // used in this problem.
QSet<QSimplexVariable *> variablesSet;
for (int i = 0; i < constraints.size(); ++i)
variablesSet += \
@@ -100,12 +142,25 @@ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints)
variables = variablesSet.toList();
// Set Variables reverse mapping
+ // We also need to be able to find the index for a given variable, to do that
+ // we store in each variable its index.
for (int i = 0; i < variables.size(); ++i) {
// The variable "0" goes at the column "1", etc...
variables[i]->index = i + 1;
}
// Normalize Constraints
+ // In this step, we prepare the constraints in two ways:
+ // Firstly, we modify all constraints of type "LessOrEqual" or "MoreOrEqual"
+ // by the adding slack or surplus variables and making them "Equal" constraints.
+ // Secondly, we need every single constraint to have a direct, easy feasible
+ // solution. Constraints that have slack variables are already easy to solve,
+ // to all the others we add artificial variables.
+ //
+ // At the end we modify the constraints as follows:
+ // - LessOrEqual: SLACK variable is added.
+ // - Equal: ARTIFICIAL variable is added.
+ // - More or Equal: ARTIFICIAL and SURPLUS variables are added.
int variableIndex = variables.size();
QList <QSimplexVariable *> artificialList;
@@ -138,12 +193,18 @@ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints)
}
}
+ // All original, slack and surplus have already had its index set
+ // at this point. We now set the index of the artificial variables
+ // as to ensure they are at the end of the variable list and therefore
+ // can be easily removed at the end of this method.
firstArtificial = variableIndex + 1;
for (int i = 0; i < artificialList.size(); ++i)
artificialList[i]->index = ++variableIndex;
artificialList.clear();
- // Matrix
+ /////////////////////////////
+ // Fill the Simplex matrix //
+ /////////////////////////////
// One for each variable plus the Basic and BFS columns (first and last)
columns = variableIndex + 2;
@@ -188,24 +249,61 @@ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints)
setValueAt(i, columns - 1, c->constant);
}
- // Set temporary objective: -1 * sum_of_artificial_vars
+ // Set objective for the first-phase Simplex.
+ // Z = -1 * sum_of_artificial_vars
for (int j = firstArtificial; j < columns - 1; ++j)
setValueAt(0, j, 1.0);
// Maximize our objective (artificial vars go to zero)
solveMaxHelper();
+ // If there is a solution where the sum of all artificial
+ // variables is zero, then all of them can be removed and yet
+ // we will have a feasible (but not optimal) solution for the
+ // original problem.
+ // Otherwise, we clean up our structures and report there is
+ // no feasible solution.
if (valueAt(0, columns - 1) != 0.0) {
qWarning() << "QSimplex: No feasible solution!";
clearDataStructures();
return false;
}
- // Remove artificial variables
+ // Remove artificial variables. We already have a feasible
+ // solution for the first problem, thus we don't need them
+ // anymore.
clearColumns(firstArtificial, columns - 2);
+
+ #ifdef QT_DEBUG
+ // Ensure that at the end of the simplex each row should either:
+ // - Have a positive value on the column associated to its variable, or
+ // - Have zero values in all columns.
+ //
+ // This avoids a regression where restrictions would be lost
+ // due to randomness in the pivotRowForColumn method.
+ for (int i = 1; i < rows; ++i) {
+ int variableIndex = valueAt(i, 0);
+ if (valueAt(i, variableIndex) > 0)
+ continue;
+
+ for (int j = 1; j < columns; ++j) {
+ Q_ASSERT(valueAt(i, j) == 0);
+ }
+ }
+ #endif
+
return true;
}
+/*!
+ \internal
+
+ Run simplex on the current matrix with the current objective.
+
+ This is the iterative method. The matrix lines are combined
+ as to modify the variable values towards the best solution possible.
+ The method returns when the matrix is in the optimal state.
+*/
void QSimplex::solveMaxHelper()
{
reducedRowEchelon();
@@ -235,23 +333,21 @@ void QSimplex::clearColumns(int first, int last)
void QSimplex::dumpMatrix()
{
- printf("---- Simplex Matrix ----\n");
+ qDebug("---- Simplex Matrix ----\n");
- printf(" ");
+ QString str(QLatin1String(" "));
for (int j = 0; j < columns; ++j)
- printf(" <% 2d >", j);
- printf("\n");
-
+ str += QString::fromAscii(" <%1 >").arg(j, 2);
+ qDebug("%s", qPrintable(str));
for (int i = 0; i < rows; ++i) {
- printf("Row %2d:", i);
+ str = QString::fromAscii("Row %1:").arg(i, 2);
qreal *row = matrix + i * columns;
- for (int j = 0; j < columns; ++j) {
- printf(" % 2.2f", row[j]);
- }
- printf("\n");
+ for (int j = 0; j < columns; ++j)
+ str += QString::fromAscii("%1").arg(row[j], 7, 'f', 2);
+ qDebug("%s", qPrintable(str));
}
- printf("------------------------\n\n");
+ qDebug("------------------------\n");
}
void QSimplex::combineRows(int toIndex, int fromIndex, qreal factor)
@@ -292,6 +388,23 @@ int QSimplex::findPivotColumn()
return minIndex;
}
+/*!
+ \internal
+
+ For a given pivot column, find the pivot row. That is, the row with the
+ minimum associated "quotient" where:
+
+ - quotient is the division of the value in the last column by the value
+ in the pivot column.
+ - rows with value less or equal to zero are ignored
+ - if two rows have the same quotient, lines are chosen based on the
+ highest variable index (value in the first column)
+
+ The last condition avoids a bug where artificial variables would be
+ left behind for the second-phase simplex, and with 'good'
+ constraints would be removed before it, what would lead to incorrect
+ results.
+*/
int QSimplex::pivotRowForColumn(int column)
{
qreal min = qreal(999999999999.0); // ###
@@ -306,6 +419,8 @@ int QSimplex::pivotRowForColumn(int column)
if (quotient < min) {
min = quotient;
minIndex = i;
+ } else if ((quotient == min) && (valueAt(i, 0) > valueAt(minIndex, 0))) {
+ minIndex = i;
}
}
@@ -320,6 +435,12 @@ void QSimplex::reducedRowEchelon()
}
}
+/*!
+ \internal
+
+ Does one iteration towards a better solution for the problem.
+ See 'solveMaxHelper'.
+*/
bool QSimplex::iterate()
{
// Find Pivot column
@@ -351,7 +472,7 @@ bool QSimplex::iterate()
setValueAt(pivotRow, 0, pivotColumn);
// dumpMatrix();
- // printf("------------ end of iteration --------------\n");
+ // qDebug("------------ end of iteration --------------\n");
return true;
}
@@ -361,7 +482,13 @@ bool QSimplex::iterate()
Both solveMin and solveMax are interfaces to this method.
The enum solverFactor admits 2 values: Minimum (-1) and Maximum (+1).
- */
+
+ This method sets the original objective and runs the second phase
+ Simplex to obtain the optimal solution for the problem. As the internal
+ simplex solver is only able to _maximize_ objectives, we handle the
+ minimization case by inverting the original objective and then
+ maximizing it.
+*/
qreal QSimplex::solver(solverFactor factor)
{
// Remove old objective
@@ -381,16 +508,28 @@ qreal QSimplex::solver(solverFactor factor)
return factor * valueAt(0, columns - 1);
}
+/*!
+ Minimize the original objective.
+*/
qreal QSimplex::solveMin()
{
return solver(Minimum);
}
+/*!
+ Maximize the original objective.
+*/
qreal QSimplex::solveMax()
{
return solver(Maximum);
}
+/*!
+ \internal
+
+ Reads results from the simplified matrix and saves them in the
+ "result" member of each QSimplexVariable.
+*/
void QSimplex::collectResults()
{
// All variables are zero unless overridden below.
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp
index 48aee1c..42b8dea 100644
--- a/src/gui/image/qmovie.cpp
+++ b/src/gui/image/qmovie.cpp
@@ -47,6 +47,10 @@
\ingroup painting
+ This class is used to show simple animations without sound. If you want
+ to display video and media content, use the \l{Phonon Module}{Phonon}
+ multimedia framework instead.
+
First, create a QMovie object by passing either the name of a file or a
pointer to a QIODevice containing an animated image format to QMovie's
constructor. You can call isValid() to check if the image data is valid,
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 27e8602..8daac42 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -480,7 +480,7 @@ void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent)
alienWidget = qwidget;
S60->mousePressTarget = alienWidget;
}
-
+
alienWidget = S60->mousePressTarget;
if (alienWidget != S60->lastPointerEventTarget)
@@ -600,7 +600,7 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod
if (keyCode >= Qt::Key_Left && keyCode <= Qt::Key_Down || keyCode == Qt::Key_Select) {
/*Explanation about virtualMouseAccel:
Tapping an arrow key allows precise pixel positioning
- Holding an arrow key down, acceleration is applied to allow cursor
+ Holding an arrow key down, acceleration is applied to allow cursor
to be quickly moved to another part of the screen by key repeats.
*/
if (S60->virtualMouseLastKey == keyCode) {
@@ -668,7 +668,7 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod
}
}
#endif
-
+
Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers);
QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode,
mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
@@ -993,13 +993,13 @@ void qt_init(QApplicationPrivate * /* priv */, int)
S60->hasTouchscreen = true;
S60->virtualMouseRequired = false;
}
-
+
if (touch) {
QApplicationPrivate::navigationMode = Qt::NavigationModeNone;
} else {
QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional;
}
-
+
#ifndef QT_NO_CURSOR
//Check if window server pointer cursors are supported or not
#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
@@ -1063,7 +1063,7 @@ void qt_cleanup()
// it dies.
delete QApplicationPrivate::inputContext;
QApplicationPrivate::inputContext = 0;
-
+
//Change mouse pointer back
S60->wsSession().SetPointerCursorMode(EPointerCursorNone);
@@ -1383,7 +1383,8 @@ int QApplication::s60ProcessEvent(TWsEvent *event)
} else if ((visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible)
&& !w->d_func()->maybeBackingStore()) {
w->d_func()->topData()->backingStore = new QWidgetBackingStore(w);
- w->update();
+ w->d_func()->invalidateBuffer(w->rect());
+ w->repaint();
}
return 1;
}
@@ -1599,7 +1600,7 @@ void QApplicationPrivate::setNavigationMode(Qt::NavigationMode mode)
const bool isCursorOn = (mode == Qt::NavigationModeCursorAuto
&& !S60->hasTouchscreen)
|| mode == Qt::NavigationModeCursorForceVisible;
-
+
if (!wasCursorOn && isCursorOn) {
//Show the cursor, when changing from another mode to cursor mode
qt_symbian_set_cursor_visible(true);
@@ -1629,7 +1630,7 @@ void QApplication::restoreOverrideCursor()
if (qApp->d_func()->cursor_list.isEmpty())
return;
qApp->d_func()->cursor_list.removeFirst();
-
+
if (!qApp->d_func()->cursor_list.isEmpty()) {
qt_symbian_setGlobalCursor(qApp->d_func()->cursor_list.first());
}
diff --git a/src/gui/util/qdesktopservices_s60.cpp b/src/gui/util/qdesktopservices_s60.cpp
index b78e51b..fd06cf3 100644
--- a/src/gui/util/qdesktopservices_s60.cpp
+++ b/src/gui/util/qdesktopservices_s60.cpp
@@ -70,7 +70,6 @@ QT_BEGIN_NAMESPACE
_LIT(KCacheSubDir, "Cache\\");
_LIT(KSysBin, "\\Sys\\Bin\\");
-_LIT(KTempDir, "\\System\\Temp\\");
_LIT(KBrowserPrefix, "4 " );
_LIT(KFontsDir, "z:\\resource\\Fonts\\");
const TUid KUidBrowser = { 0x10008D39 };
@@ -381,9 +380,7 @@ QString QDesktopServices::storageLocation(StandardLocation type)
#endif
break;
case TempLocation:
- path.Append(writableExeDrive().Name());
- path.Append(KTempDir);
- //return QDir::tempPath(); break;
+ return QDir::tempPath();
break;
case HomeLocation:
path.Append(writableDataRoot());