summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJanne Anttila <janne.anttila@digia.com>2009-09-25 11:37:51 (GMT)
committerJanne Anttila <janne.anttila@digia.com>2009-09-25 11:37:51 (GMT)
commitf33e399b34eda645d2b87b053e887d0b21e8e32a (patch)
tree1f6f87ef5892a7ff36fbc419a9796159e018cd0f /src
parent02f161410dce9e2bac89f11d293f811bb224257c (diff)
parent8a993264ca8bd6273f1d5bb4288d64592d07760f (diff)
downloadQt-f33e399b34eda645d2b87b053e887d0b21e8e32a.zip
Qt-f33e399b34eda645d2b87b053e887d0b21e8e32a.tar.gz
Qt-f33e399b34eda645d2b87b053e887d0b21e8e32a.tar.bz2
Merge branch '4.6' of git@scm.dev.troll.no:qt/qt into 4.6
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qglobal.cpp34
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp133
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib_p.h2
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp8
-rw-r--r--src/corelib/statemachine/qabstracttransition.cpp6
-rw-r--r--src/corelib/statemachine/qabstracttransition_p.h4
-rw-r--r--src/corelib/statemachine/qstate.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.cpp2
-rw-r--r--src/gui/graphicsview/qsimplex_p.cpp173
-rw-r--r--src/gui/kernel/qapplication_s60.cpp19
10 files changed, 300 insertions, 85 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 4974acf..97362af 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1769,25 +1769,6 @@ static QSysInfo::S60Version cachedS60Version = QSysInfo::S60Version(-1);
QSysInfo::S60Version QSysInfo::s60Version()
{
-# ifdef Q_CC_NOKIAX86
- // For emulator builds. Emulators don't support the trick we use to figure
- // out which SDK we are running under, so simply hardcode it there.
-# if defined(__SERIES60_31__)
- return SV_S60_3_1;
-
-# elif defined(__S60_32__)
- return SV_S60_3_2;
-
-# elif defined(__S60_50__)
- return SV_S60_5_0;
-
-# else
- return SV_S60_Unknown;
-
-# endif
-
-# else
- // For hardware builds.
if (cachedS60Version != -1)
return cachedS60Version;
@@ -1818,6 +1799,19 @@ QSysInfo::S60Version QSysInfo::s60Version()
delete contents;
}
+# ifdef Q_CC_NOKIAX86
+ // Some emulator environments may not contain the version specific .sis files, so
+ // simply hardcode the version on those environments.
+# if defined(__SERIES60_31__)
+ return cachedS60Version = SV_S60_3_1;
+# elif defined(__S60_32__)
+ return cachedS60Version = SV_S60_3_2;
+# elif defined(__S60_50__)
+ return cachedS60Version = SV_S60_5_0;
+# else
+ return cachedS60Version = SV_S60_Unknown;
+# endif
+# else
return cachedS60Version = SV_S60_Unknown;
# endif
}
@@ -2718,7 +2712,7 @@ int qrand()
\since 4.6
\brief The QT_TRID_NOOP macro marks an id for dynamic translation.
-
+
The only purpose of this macro is to provide an anchor for attaching
meta data like to qtTrId().
diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp
index 6e457f4..665b73e 100644
--- a/src/corelib/kernel/qeventdispatcher_glib.cpp
+++ b/src/corelib/kernel/qeventdispatcher_glib.cpp
@@ -127,16 +127,11 @@ struct GTimerSource
GSource source;
QTimerInfoList timerList;
QEventLoop::ProcessEventsFlags processEventsFlags;
+ bool runWithIdlePriority;
};
-static gboolean timerSourcePrepare(GSource *source, gint *timeout)
+static gboolean timerSourcePrepareHelper(GTimerSource *src, gint *timeout)
{
- gint dummy;
- if (!timeout)
- timeout = &dummy;
-
- GTimerSource *src = reinterpret_cast<GTimerSource *>(source);
-
timeval tv = { 0l, 0l };
if (!(src->processEventsFlags & QEventLoop::X11ExcludeTimers) && src->timerList.timerWait(tv))
*timeout = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
@@ -146,10 +141,8 @@ static gboolean timerSourcePrepare(GSource *source, gint *timeout)
return (*timeout == 0);
}
-static gboolean timerSourceCheck(GSource *source)
+static gboolean timerSourceCheckHelper(GTimerSource *src)
{
- GTimerSource *src = reinterpret_cast<GTimerSource *>(source);
-
if (src->timerList.isEmpty()
|| (src->processEventsFlags & QEventLoop::X11ExcludeTimers))
return false;
@@ -160,9 +153,35 @@ static gboolean timerSourceCheck(GSource *source)
return true;
}
+static gboolean timerSourcePrepare(GSource *source, gint *timeout)
+{
+ gint dummy;
+ if (!timeout)
+ timeout = &dummy;
+
+ GTimerSource *src = reinterpret_cast<GTimerSource *>(source);
+ if (src->runWithIdlePriority) {
+ if (timeout)
+ *timeout = -1;
+ return false;
+ }
+
+ return timerSourcePrepareHelper(src, timeout);
+}
+
+static gboolean timerSourceCheck(GSource *source)
+{
+ GTimerSource *src = reinterpret_cast<GTimerSource *>(source);
+ if (src->runWithIdlePriority)
+ return false;
+ return timerSourceCheckHelper(src);
+}
+
static gboolean timerSourceDispatch(GSource *source, GSourceFunc, gpointer)
{
- (void) reinterpret_cast<GTimerSource *>(source)->timerList.activateTimers();
+ GTimerSource *timerSource = reinterpret_cast<GTimerSource *>(source);
+ timerSource->runWithIdlePriority = true;
+ (void) timerSource->timerList.activateTimers();
return true; // ??? don't remove, right again?
}
@@ -175,6 +194,53 @@ static GSourceFuncs timerSourceFuncs = {
NULL
};
+struct GIdleTimerSource
+{
+ GSource source;
+ GTimerSource *timerSource;
+};
+
+static gboolean idleTimerSourcePrepare(GSource *source, gint *timeout)
+{
+ GIdleTimerSource *idleTimerSource = reinterpret_cast<GIdleTimerSource *>(source);
+ GTimerSource *timerSource = idleTimerSource->timerSource;
+ if (!timerSource->runWithIdlePriority) {
+ // Yield to the normal priority timer source
+ if (timeout)
+ *timeout = -1;
+ return false;
+ }
+
+ return timerSourcePrepareHelper(timerSource, timeout);
+}
+
+static gboolean idleTimerSourceCheck(GSource *source)
+{
+ GIdleTimerSource *idleTimerSource = reinterpret_cast<GIdleTimerSource *>(source);
+ GTimerSource *timerSource = idleTimerSource->timerSource;
+ if (!timerSource->runWithIdlePriority) {
+ // Yield to the normal priority timer source
+ return false;
+ }
+ return timerSourceCheckHelper(timerSource);
+}
+
+static gboolean idleTimerSourceDispatch(GSource *source, GSourceFunc, gpointer)
+{
+ GTimerSource *timerSource = reinterpret_cast<GIdleTimerSource *>(source)->timerSource;
+ (void) timerSourceDispatch(&timerSource->source, 0, 0);
+ return true;
+}
+
+static GSourceFuncs idleTimerSourceFuncs = {
+ idleTimerSourcePrepare,
+ idleTimerSourceCheck,
+ idleTimerSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
struct GPostEventSource
{
GSource source;
@@ -235,14 +301,15 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
g_main_context_ref(mainContext);
} else {
QCoreApplication *app = QCoreApplication::instance();
- if (app && QThread::currentThread() == app->thread()) {
- mainContext = g_main_context_default();
- g_main_context_ref(mainContext);
- } else {
- mainContext = g_main_context_new();
- }
+ if (app && QThread::currentThread() == app->thread()) {
+ mainContext = g_main_context_default();
+ g_main_context_ref(mainContext);
+ } else {
+ mainContext = g_main_context_new();
+ }
}
+ // setup post event source
postEventSource = reinterpret_cast<GPostEventSource *>(g_source_new(&postEventSourceFuncs,
sizeof(GPostEventSource)));
postEventSource->serialNumber = 1;
@@ -257,14 +324,21 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
g_source_set_can_recurse(&socketNotifierSource->source, true);
g_source_attach(&socketNotifierSource->source, mainContext);
- // setup timerSource
+ // setup normal and idle timer sources
timerSource = reinterpret_cast<GTimerSource *>(g_source_new(&timerSourceFuncs,
sizeof(GTimerSource)));
(void) new (&timerSource->timerList) QTimerInfoList();
timerSource->processEventsFlags = QEventLoop::AllEvents;
+ timerSource->runWithIdlePriority = false;
g_source_set_can_recurse(&timerSource->source, true);
- g_source_set_priority(&timerSource->source, G_PRIORITY_DEFAULT_IDLE);
g_source_attach(&timerSource->source, mainContext);
+
+ idleTimerSource = reinterpret_cast<GIdleTimerSource *>(g_source_new(&idleTimerSourceFuncs,
+ sizeof(GIdleTimerSource)));
+ idleTimerSource->timerSource = timerSource;
+ g_source_set_can_recurse(&idleTimerSource->source, true);
+ g_source_set_priority(&idleTimerSource->source, G_PRIORITY_DEFAULT_IDLE);
+ g_source_attach(&idleTimerSource->source, mainContext);
}
QEventDispatcherGlib::QEventDispatcherGlib(QObject *parent)
@@ -272,12 +346,9 @@ QEventDispatcherGlib::QEventDispatcherGlib(QObject *parent)
{
}
-QEventDispatcherGlib::QEventDispatcherGlib(GMainContext *mainContext,
- QObject *parent)
- : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate(mainContext)),
- parent)
-{
-}
+QEventDispatcherGlib::QEventDispatcherGlib(GMainContext *mainContext, QObject *parent)
+ : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate(mainContext)), parent)
+{ }
QEventDispatcherGlib::~QEventDispatcherGlib()
{
@@ -289,6 +360,9 @@ QEventDispatcherGlib::~QEventDispatcherGlib()
g_source_destroy(&d->timerSource->source);
g_source_unref(&d->timerSource->source);
d->timerSource = 0;
+ g_source_destroy(&d->idleTimerSource->source);
+ g_source_unref(&d->idleTimerSource->source);
+ d->idleTimerSource = 0;
// destroy socket notifier source
for (int i = 0; i < d->socketNotifierSource->pollfds.count(); ++i) {
@@ -324,11 +398,16 @@ bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
// tell postEventSourcePrepare() and timerSource about any new flags
QEventLoop::ProcessEventsFlags savedFlags = d->timerSource->processEventsFlags;
d->timerSource->processEventsFlags = flags;
-
+
+ if (!(flags & QEventLoop::EventLoopExec)) {
+ // force timers to be sent at normal priority
+ d->timerSource->runWithIdlePriority = false;
+ }
+
bool result = g_main_context_iteration(d->mainContext, canWait);
while (!result && canWait)
result = g_main_context_iteration(d->mainContext, canWait);
-
+
d->timerSource->processEventsFlags = savedFlags;
if (canWait)
diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h
index 8dbc44d..6a4e726 100644
--- a/src/corelib/kernel/qeventdispatcher_glib_p.h
+++ b/src/corelib/kernel/qeventdispatcher_glib_p.h
@@ -98,6 +98,7 @@ protected:
struct GPostEventSource;
struct GSocketNotifierSource;
struct GTimerSource;
+struct GIdleTimerSource;
class Q_CORE_EXPORT QEventDispatcherGlibPrivate : public QAbstractEventDispatcherPrivate
{
@@ -108,6 +109,7 @@ public:
GPostEventSource *postEventSource;
GSocketNotifierSource *socketNotifierSource;
GTimerSource *timerSource;
+ GIdleTimerSource *idleTimerSource;
};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index a912971..5a0afb8 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -446,10 +446,10 @@ bool QTimerInfoList::timerWait(timeval &tm)
// Find first waiting timer not already active
QTimerInfo *t = 0;
for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {
- if (!(*it)->inTimerEvent) {
- t = *it;
- break;
- }
+ if (!(*it)->inTimerEvent) {
+ t = *it;
+ break;
+ }
}
if (!t)
diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp
index a81fe0f..8b858c7 100644
--- a/src/corelib/statemachine/qabstracttransition.cpp
+++ b/src/corelib/statemachine/qabstracttransition.cpp
@@ -187,7 +187,7 @@ QAbstractState *QAbstractTransition::targetState() const
Q_D(const QAbstractTransition);
if (d->targetStates.isEmpty())
return 0;
- return d->targetStates.first();
+ return d->targetStates.first().data();
}
/*!
@@ -211,7 +211,7 @@ QList<QAbstractState*> QAbstractTransition::targetStates() const
Q_D(const QAbstractTransition);
QList<QAbstractState*> result;
for (int i = 0; i < d->targetStates.size(); ++i) {
- QAbstractState *target = d->targetStates.at(i);
+ QAbstractState *target = d->targetStates.at(i).data();
if (target)
result.append(target);
}
@@ -225,7 +225,7 @@ void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets)
{
Q_D(QAbstractTransition);
- for (int i=0; i<targets.size(); ++i) {
+ for (int i = 0; i < targets.size(); ++i) {
QAbstractState *target = targets.at(i);
if (!target) {
qWarning("QAbstractTransition::setTargetStates: target state(s) cannot be null");
diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h
index 7465243..5b4df1b 100644
--- a/src/corelib/statemachine/qabstracttransition_p.h
+++ b/src/corelib/statemachine/qabstracttransition_p.h
@@ -56,7 +56,7 @@
#include <private/qobject_p.h>
#include <QtCore/qlist.h>
-#include <QtCore/qpointer.h>
+#include <QtCore/qsharedpointer.h>
QT_BEGIN_NAMESPACE
@@ -80,7 +80,7 @@ public:
QStateMachine *machine() const;
void emitTriggered();
- QList<QPointer<QAbstractState> > targetStates;
+ QList<QWeakPointer<QAbstractState> > targetStates;
#ifndef QT_NO_ANIMATION
QList<QAbstractAnimation*> animations;
diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp
index 70026b8..a6e4a57 100644
--- a/src/corelib/statemachine/qstate.cpp
+++ b/src/corelib/statemachine/qstate.cpp
@@ -291,9 +291,9 @@ QAbstractTransition *QState::addTransition(QAbstractTransition *transition)
}
transition->setParent(this);
- const QList<QPointer<QAbstractState> > &targets = QAbstractTransitionPrivate::get(transition)->targetStates;
+ const QList<QWeakPointer<QAbstractState> > &targets = QAbstractTransitionPrivate::get(transition)->targetStates;
for (int i = 0; i < targets.size(); ++i) {
- QAbstractState *t = targets.at(i);
+ QAbstractState *t = targets.at(i).data();
if (!t) {
qWarning("QState::addTransition: cannot add transition to null state");
return 0;
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/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/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());
}