diff options
Diffstat (limited to 'src/gui/util')
33 files changed, 1341 insertions, 11808 deletions
diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp deleted file mode 100644 index 07bfac729d..0000000000 --- a/src/gui/util/qcompleter.cpp +++ /dev/null @@ -1,1833 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QCompleter - \brief The QCompleter class provides completions based on an item model. - \since 4.2 - - You can use QCompleter to provide auto completions in any Qt - widget, such as QLineEdit and QComboBox. - When the user starts typing a word, QCompleter suggests possible ways of - completing the word, based on a word list. The word list is - provided as a QAbstractItemModel. (For simple applications, where - the word list is static, you can pass a QStringList to - QCompleter's constructor.) - - \tableofcontents - - \section1 Basic Usage - - A QCompleter is used typically with a QLineEdit or QComboBox. - For example, here's how to provide auto completions from a simple - word list in a QLineEdit: - - \snippet doc/src/snippets/code/src_gui_util_qcompleter.cpp 0 - - A QFileSystemModel can be used to provide auto completion of file names. - For example: - - \snippet doc/src/snippets/code/src_gui_util_qcompleter.cpp 1 - - To set the model on which QCompleter should operate, call - setModel(). By default, QCompleter will attempt to match the \l - {completionPrefix}{completion prefix} (i.e., the word that the - user has started typing) against the Qt::EditRole data stored in - column 0 in the model case sensitively. This can be changed - using setCompletionRole(), setCompletionColumn(), and - setCaseSensitivity(). - - If the model is sorted on the column and role that are used for completion, - you can call setModelSorting() with either - QCompleter::CaseSensitivelySortedModel or - QCompleter::CaseInsensitivelySortedModel as the argument. On large models, - this can lead to significant performance improvements, because QCompleter - can then use binary search instead of linear search. - - The model can be a \l{QAbstractListModel}{list model}, - a \l{QAbstractTableModel}{table model}, or a - \l{QAbstractItemModel}{tree model}. Completion on tree models - is slightly more involved and is covered in the \l{Handling - Tree Models} section below. - - The completionMode() determines the mode used to provide completions to - the user. - - \section1 Iterating Through Completions - - To retrieve a single candidate string, call setCompletionPrefix() - with the text that needs to be completed and call - currentCompletion(). You can iterate through the list of - completions as below: - - \snippet doc/src/snippets/code/src_gui_util_qcompleter.cpp 2 - - completionCount() returns the total number of completions for the - current prefix. completionCount() should be avoided when possible, - since it requires a scan of the entire model. - - \section1 The Completion Model - - completionModel() return a list model that contains all possible - completions for the current completion prefix, in the order in which - they appear in the model. This model can be used to display the current - completions in a custom view. Calling setCompletionPrefix() automatically - refreshes the completion model. - - \section1 Handling Tree Models - - QCompleter can look for completions in tree models, assuming - that any item (or sub-item or sub-sub-item) can be unambiguously - represented as a string by specifying the path to the item. The - completion is then performed one level at a time. - - Let's take the example of a user typing in a file system path. - The model is a (hierarchical) QFileSystemModel. The completion - occurs for every element in the path. For example, if the current - text is \c C:\Wind, QCompleter might suggest \c Windows to - complete the current path element. Similarly, if the current text - is \c C:\Windows\Sy, QCompleter might suggest \c System. - - For this kind of completion to work, QCompleter needs to be able to - split the path into a list of strings that are matched at each level. - For \c C:\Windows\Sy, it needs to be split as "C:", "Windows" and "Sy". - The default implementation of splitPath(), splits the completionPrefix - using QDir::separator() if the model is a QFileSystemModel. - - To provide completions, QCompleter needs to know the path from an index. - This is provided by pathFromIndex(). The default implementation of - pathFromIndex(), returns the data for the \l{Qt::EditRole}{edit role} - for list models and the absolute file path if the mode is a QFileSystemModel. - - \sa QAbstractItemModel, QLineEdit, QComboBox, {Completer Example} -*/ - -#include "qcompleter_p.h" - -#ifndef QT_NO_COMPLETER - -#include "QtGui/qscrollbar.h" -#include "QtGui/qstringlistmodel.h" -#include "QtGui/qdirmodel.h" -#include "QtGui/qfilesystemmodel.h" -#include "QtGui/qheaderview.h" -#include "QtGui/qlistview.h" -#include "QtGui/qapplication.h" -#include "QtGui/qevent.h" -#include "QtGui/qheaderview.h" -#include "QtGui/qdesktopwidget.h" -#include "QtGui/qlineedit.h" - -QT_BEGIN_NAMESPACE - -QCompletionModel::QCompletionModel(QCompleterPrivate *c, QObject *parent) - : QAbstractProxyModel(*new QCompletionModelPrivate, parent), - c(c), showAll(false) -{ - createEngine(); -} - -int QCompletionModel::columnCount(const QModelIndex &) const -{ - Q_D(const QCompletionModel); - return d->model->columnCount(); -} - -void QCompletionModel::setSourceModel(QAbstractItemModel *source) -{ - bool hadModel = (sourceModel() != 0); - - if (hadModel) - QObject::disconnect(sourceModel(), 0, this, 0); - - QAbstractProxyModel::setSourceModel(source); - - if (source) { - // TODO: Optimize updates in the source model - connect(source, SIGNAL(modelReset()), this, SLOT(invalidate())); - connect(source, SIGNAL(destroyed()), this, SLOT(modelDestroyed())); - connect(source, SIGNAL(layoutChanged()), this, SLOT(invalidate())); - connect(source, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowsInserted())); - connect(source, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(invalidate())); - connect(source, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(invalidate())); - connect(source, SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(invalidate())); - connect(source, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(invalidate())); - } - - invalidate(); -} - -void QCompletionModel::createEngine() -{ - bool sortedEngine = false; - switch (c->sorting) { - case QCompleter::UnsortedModel: - sortedEngine = false; - break; - case QCompleter::CaseSensitivelySortedModel: - sortedEngine = c->cs == Qt::CaseSensitive; - break; - case QCompleter::CaseInsensitivelySortedModel: - sortedEngine = c->cs == Qt::CaseInsensitive; - break; - } - - if (sortedEngine) - engine.reset(new QSortedModelEngine(c)); - else - engine.reset(new QUnsortedModelEngine(c)); -} - -QModelIndex QCompletionModel::mapToSource(const QModelIndex& index) const -{ - Q_D(const QCompletionModel); - if (!index.isValid()) - return engine->curParent; - - int row; - QModelIndex parent = engine->curParent; - if (!showAll) { - if (!engine->matchCount()) - return QModelIndex(); - Q_ASSERT(index.row() < engine->matchCount()); - QIndexMapper& rootIndices = engine->historyMatch.indices; - if (index.row() < rootIndices.count()) { - row = rootIndices[index.row()]; - parent = QModelIndex(); - } else { - row = engine->curMatch.indices[index.row() - rootIndices.count()]; - } - } else { - row = index.row(); - } - - return d->model->index(row, index.column(), parent); -} - -QModelIndex QCompletionModel::mapFromSource(const QModelIndex& idx) const -{ - if (!idx.isValid()) - return QModelIndex(); - - int row = -1; - if (!showAll) { - if (!engine->matchCount()) - return QModelIndex(); - - QIndexMapper& rootIndices = engine->historyMatch.indices; - if (idx.parent().isValid()) { - if (idx.parent() != engine->curParent) - return QModelIndex(); - } else { - row = rootIndices.indexOf(idx.row()); - if (row == -1 && engine->curParent.isValid()) - return QModelIndex(); // source parent and our parent don't match - } - - if (row == -1) { - QIndexMapper& indices = engine->curMatch.indices; - engine->filterOnDemand(idx.row() - indices.last()); - row = indices.indexOf(idx.row()) + rootIndices.count(); - } - - if (row == -1) - return QModelIndex(); - } else { - if (idx.parent() != engine->curParent) - return QModelIndex(); - row = idx.row(); - } - - return createIndex(row, idx.column()); -} - -bool QCompletionModel::setCurrentRow(int row) -{ - if (row < 0 || !engine->matchCount()) - return false; - - if (row >= engine->matchCount()) - engine->filterOnDemand(row + 1 - engine->matchCount()); - - if (row >= engine->matchCount()) // invalid row - return false; - - engine->curRow = row; - return true; -} - -QModelIndex QCompletionModel::currentIndex(bool sourceIndex) const -{ - if (!engine->matchCount()) - return QModelIndex(); - - int row = engine->curRow; - if (showAll) - row = engine->curMatch.indices[engine->curRow]; - - QModelIndex idx = createIndex(row, c->column); - if (!sourceIndex) - return idx; - return mapToSource(idx); -} - -QModelIndex QCompletionModel::index(int row, int column, const QModelIndex& parent) const -{ - Q_D(const QCompletionModel); - if (row < 0 || column < 0 || column >= columnCount(parent) || parent.isValid()) - return QModelIndex(); - - if (!showAll) { - if (!engine->matchCount()) - return QModelIndex(); - if (row >= engine->historyMatch.indices.count()) { - int want = row + 1 - engine->matchCount(); - if (want > 0) - engine->filterOnDemand(want); - if (row >= engine->matchCount()) - return QModelIndex(); - } - } else { - if (row >= d->model->rowCount(engine->curParent)) - return QModelIndex(); - } - - return createIndex(row, column); -} - -int QCompletionModel::completionCount() const -{ - if (!engine->matchCount()) - return 0; - - engine->filterOnDemand(INT_MAX); - return engine->matchCount(); -} - -int QCompletionModel::rowCount(const QModelIndex &parent) const -{ - Q_D(const QCompletionModel); - if (parent.isValid()) - return 0; - - if (showAll) { - // Show all items below current parent, even if we have no valid matches - if (engine->curParts.count() != 1 && !engine->matchCount() - && !engine->curParent.isValid()) - return 0; - return d->model->rowCount(engine->curParent); - } - - return completionCount(); -} - -void QCompletionModel::setFiltered(bool filtered) -{ - if (showAll == !filtered) - return; - showAll = !filtered; - resetModel(); -} - -bool QCompletionModel::hasChildren(const QModelIndex &parent) const -{ - Q_D(const QCompletionModel); - if (parent.isValid()) - return false; - - if (showAll) - return d->model->hasChildren(mapToSource(parent)); - - if (!engine->matchCount()) - return false; - - return true; -} - -QVariant QCompletionModel::data(const QModelIndex& index, int role) const -{ - Q_D(const QCompletionModel); - return d->model->data(mapToSource(index), role); -} - -void QCompletionModel::modelDestroyed() -{ - QAbstractProxyModel::setSourceModel(0); // switch to static empty model - invalidate(); -} - -void QCompletionModel::rowsInserted() -{ - invalidate(); - emit rowsAdded(); -} - -void QCompletionModel::invalidate() -{ - engine->cache.clear(); - filter(engine->curParts); -} - -void QCompletionModel::filter(const QStringList& parts) -{ - Q_D(QCompletionModel); - engine->filter(parts); - resetModel(); - - if (d->model->canFetchMore(engine->curParent)) - d->model->fetchMore(engine->curParent); -} - -void QCompletionModel::resetModel() -{ - if (rowCount() == 0) { - reset(); - return; - } - - emit layoutAboutToBeChanged(); - QModelIndexList piList = persistentIndexList(); - QModelIndexList empty; - for (int i = 0; i < piList.size(); i++) - empty.append(QModelIndex()); - changePersistentIndexList(piList, empty); - emit layoutChanged(); -} - -////////////////////////////////////////////////////////////////////////////// -void QCompletionEngine::filter(const QStringList& parts) -{ - const QAbstractItemModel *model = c->proxy->sourceModel(); - curParts = parts; - if (curParts.isEmpty()) - curParts.append(QString()); - - curRow = -1; - curParent = QModelIndex(); - curMatch = QMatchData(); - historyMatch = filterHistory(); - - if (!model) - return; - - QModelIndex parent; - for (int i = 0; i < curParts.count() - 1; i++) { - QString part = curParts[i]; - int emi = filter(part, parent, -1).exactMatchIndex; - if (emi == -1) - return; - parent = model->index(emi, c->column, parent); - } - - // Note that we set the curParent to a valid parent, even if we have no matches - // When filtering is disabled, we show all the items under this parent - curParent = parent; - if (curParts.last().isEmpty()) - curMatch = QMatchData(QIndexMapper(0, model->rowCount(curParent) - 1), -1, false); - else - curMatch = filter(curParts.last(), curParent, 1); // build at least one - curRow = curMatch.isValid() ? 0 : -1; -} - -QMatchData QCompletionEngine::filterHistory() -{ - QAbstractItemModel *source = c->proxy->sourceModel(); - if (curParts.count() <= 1 || c->proxy->showAll || !source) - return QMatchData(); - bool isDirModel = false; - bool isFsModel = false; -#ifndef QT_NO_DIRMODEL - isDirModel = (qobject_cast<QDirModel *>(source) != 0); -#endif -#ifndef QT_NO_FILESYSTEMMODEL - isFsModel = (qobject_cast<QFileSystemModel *>(source) != 0); -#endif - QVector<int> v; - QIndexMapper im(v); - QMatchData m(im, -1, true); - - for (int i = 0; i < source->rowCount(); i++) { - QString str = source->index(i, c->column).data().toString(); - if (str.startsWith(c->prefix, c->cs) -#if (!defined(Q_OS_WIN) || defined(Q_OS_WINCE)) && !defined(Q_OS_SYMBIAN) - && ((!isFsModel && !isDirModel) || QDir::toNativeSeparators(str) != QDir::separator()) -#endif - ) - m.indices.append(i); - } - return m; -} - -// Returns a match hint from the cache by chopping the search string -bool QCompletionEngine::matchHint(QString part, const QModelIndex& parent, QMatchData *hint) -{ - if (c->cs == Qt::CaseInsensitive) - part = part.toLower(); - - const CacheItem& map = cache[parent]; - - QString key = part; - while (!key.isEmpty()) { - key.chop(1); - if (map.contains(key)) { - *hint = map[key]; - return true; - } - } - - return false; -} - -bool QCompletionEngine::lookupCache(QString part, const QModelIndex& parent, QMatchData *m) -{ - if (c->cs == Qt::CaseInsensitive) - part = part.toLower(); - const CacheItem& map = cache[parent]; - if (!map.contains(part)) - return false; - *m = map[part]; - return true; -} - -// When the cache size exceeds 1MB, it clears out about 1/2 of the cache. -void QCompletionEngine::saveInCache(QString part, const QModelIndex& parent, const QMatchData& m) -{ - QMatchData old = cache[parent].take(part); - cost = cost + m.indices.cost() - old.indices.cost(); - if (cost * sizeof(int) > 1024 * 1024) { - QMap<QModelIndex, CacheItem>::iterator it1 = cache.begin(); - while (it1 != cache.end()) { - CacheItem& ci = it1.value(); - int sz = ci.count()/2; - QMap<QString, QMatchData>::iterator it2 = ci.begin(); - int i = 0; - while (it2 != ci.end() && i < sz) { - cost -= it2.value().indices.cost(); - it2 = ci.erase(it2); - i++; - } - if (ci.count() == 0) { - it1 = cache.erase(it1); - } else { - ++it1; - } - } - } - - if (c->cs == Qt::CaseInsensitive) - part = part.toLower(); - cache[parent][part] = m; -} - -/////////////////////////////////////////////////////////////////////////////////// -QIndexMapper QSortedModelEngine::indexHint(QString part, const QModelIndex& parent, Qt::SortOrder order) -{ - const QAbstractItemModel *model = c->proxy->sourceModel(); - - if (c->cs == Qt::CaseInsensitive) - part = part.toLower(); - - const CacheItem& map = cache[parent]; - - // Try to find a lower and upper bound for the search from previous results - int to = model->rowCount(parent) - 1; - int from = 0; - const CacheItem::const_iterator it = map.lowerBound(part); - - // look backward for first valid hint - for(CacheItem::const_iterator it1 = it; it1-- != map.constBegin();) { - const QMatchData& value = it1.value(); - if (value.isValid()) { - if (order == Qt::AscendingOrder) { - from = value.indices.last() + 1; - } else { - to = value.indices.first() - 1; - } - break; - } - } - - // look forward for first valid hint - for(CacheItem::const_iterator it2 = it; it2 != map.constEnd(); ++it2) { - const QMatchData& value = it2.value(); - if (value.isValid() && !it2.key().startsWith(part)) { - if (order == Qt::AscendingOrder) { - to = value.indices.first() - 1; - } else { - from = value.indices.first() + 1; - } - break; - } - } - - return QIndexMapper(from, to); -} - -Qt::SortOrder QSortedModelEngine::sortOrder(const QModelIndex &parent) const -{ - const QAbstractItemModel *model = c->proxy->sourceModel(); - - int rowCount = model->rowCount(parent); - if (rowCount < 2) - return Qt::AscendingOrder; - QString first = model->data(model->index(0, c->column, parent), c->role).toString(); - QString last = model->data(model->index(rowCount - 1, c->column, parent), c->role).toString(); - return QString::compare(first, last, c->cs) <= 0 ? Qt::AscendingOrder : Qt::DescendingOrder; -} - -QMatchData QSortedModelEngine::filter(const QString& part, const QModelIndex& parent, int) -{ - const QAbstractItemModel *model = c->proxy->sourceModel(); - - QMatchData hint; - if (lookupCache(part, parent, &hint)) - return hint; - - QIndexMapper indices; - Qt::SortOrder order = sortOrder(parent); - - if (matchHint(part, parent, &hint)) { - if (!hint.isValid()) - return QMatchData(); - indices = hint.indices; - } else { - indices = indexHint(part, parent, order); - } - - // binary search the model within 'indices' for 'part' under 'parent' - int high = indices.to() + 1; - int low = indices.from() - 1; - int probe; - QModelIndex probeIndex; - QString probeData; - - while (high - low > 1) - { - probe = (high + low) / 2; - probeIndex = model->index(probe, c->column, parent); - probeData = model->data(probeIndex, c->role).toString(); - const int cmp = QString::compare(probeData, part, c->cs); - if ((order == Qt::AscendingOrder && cmp >= 0) - || (order == Qt::DescendingOrder && cmp < 0)) { - high = probe; - } else { - low = probe; - } - } - - if ((order == Qt::AscendingOrder && low == indices.to()) - || (order == Qt::DescendingOrder && high == indices.from())) { // not found - saveInCache(part, parent, QMatchData()); - return QMatchData(); - } - - probeIndex = model->index(order == Qt::AscendingOrder ? low+1 : high-1, c->column, parent); - probeData = model->data(probeIndex, c->role).toString(); - if (!probeData.startsWith(part, c->cs)) { - saveInCache(part, parent, QMatchData()); - return QMatchData(); - } - - const bool exactMatch = QString::compare(probeData, part, c->cs) == 0; - int emi = exactMatch ? (order == Qt::AscendingOrder ? low+1 : high-1) : -1; - - int from = 0; - int to = 0; - if (order == Qt::AscendingOrder) { - from = low + 1; - high = indices.to() + 1; - low = from; - } else { - to = high - 1; - low = indices.from() - 1; - high = to; - } - - while (high - low > 1) - { - probe = (high + low) / 2; - probeIndex = model->index(probe, c->column, parent); - probeData = model->data(probeIndex, c->role).toString(); - const bool startsWith = probeData.startsWith(part, c->cs); - if ((order == Qt::AscendingOrder && startsWith) - || (order == Qt::DescendingOrder && !startsWith)) { - low = probe; - } else { - high = probe; - } - } - - QMatchData m(order == Qt::AscendingOrder ? QIndexMapper(from, high - 1) : QIndexMapper(low+1, to), emi, false); - saveInCache(part, parent, m); - return m; -} - -//////////////////////////////////////////////////////////////////////////////////////// -int QUnsortedModelEngine::buildIndices(const QString& str, const QModelIndex& parent, int n, - const QIndexMapper& indices, QMatchData* m) -{ - Q_ASSERT(m->partial); - Q_ASSERT(n != -1 || m->exactMatchIndex == -1); - const QAbstractItemModel *model = c->proxy->sourceModel(); - int i, count = 0; - - for (i = 0; i < indices.count() && count != n; ++i) { - QModelIndex idx = model->index(indices[i], c->column, parent); - QString data = model->data(idx, c->role).toString(); - if (!data.startsWith(str, c->cs) || !(model->flags(idx) & Qt::ItemIsSelectable)) - continue; - m->indices.append(indices[i]); - ++count; - if (m->exactMatchIndex == -1 && QString::compare(data, str, c->cs) == 0) { - m->exactMatchIndex = indices[i]; - if (n == -1) - return indices[i]; - } - } - return indices[i-1]; -} - -void QUnsortedModelEngine::filterOnDemand(int n) -{ - Q_ASSERT(matchCount()); - if (!curMatch.partial) - return; - Q_ASSERT(n >= -1); - const QAbstractItemModel *model = c->proxy->sourceModel(); - int lastRow = model->rowCount(curParent) - 1; - QIndexMapper im(curMatch.indices.last() + 1, lastRow); - int lastIndex = buildIndices(curParts.last(), curParent, n, im, &curMatch); - curMatch.partial = (lastRow != lastIndex); - saveInCache(curParts.last(), curParent, curMatch); -} - -QMatchData QUnsortedModelEngine::filter(const QString& part, const QModelIndex& parent, int n) -{ - QMatchData hint; - - QVector<int> v; - QIndexMapper im(v); - QMatchData m(im, -1, true); - - const QAbstractItemModel *model = c->proxy->sourceModel(); - bool foundInCache = lookupCache(part, parent, &m); - - if (!foundInCache) { - if (matchHint(part, parent, &hint) && !hint.isValid()) - return QMatchData(); - } - - if (!foundInCache && !hint.isValid()) { - const int lastRow = model->rowCount(parent) - 1; - QIndexMapper all(0, lastRow); - int lastIndex = buildIndices(part, parent, n, all, &m); - m.partial = (lastIndex != lastRow); - } else { - if (!foundInCache) { // build from hint as much as we can - buildIndices(part, parent, INT_MAX, hint.indices, &m); - m.partial = hint.partial; - } - if (m.partial && ((n == -1 && m.exactMatchIndex == -1) || (m.indices.count() < n))) { - // need more and have more - const int lastRow = model->rowCount(parent) - 1; - QIndexMapper rest(hint.indices.last() + 1, lastRow); - int want = n == -1 ? -1 : n - m.indices.count(); - int lastIndex = buildIndices(part, parent, want, rest, &m); - m.partial = (lastRow != lastIndex); - } - } - - saveInCache(part, parent, m); - return m; -} - -/////////////////////////////////////////////////////////////////////////////// -QCompleterPrivate::QCompleterPrivate() -: widget(0), proxy(0), popup(0), cs(Qt::CaseSensitive), role(Qt::EditRole), column(0), - maxVisibleItems(7), sorting(QCompleter::UnsortedModel), wrap(true), eatFocusOut(true), - hiddenBecauseNoMatch(false) -{ -} - -void QCompleterPrivate::init(QAbstractItemModel *m) -{ - Q_Q(QCompleter); - proxy = new QCompletionModel(this, q); - QObject::connect(proxy, SIGNAL(rowsAdded()), q, SLOT(_q_autoResizePopup())); - q->setModel(m); -#ifdef QT_NO_LISTVIEW - q->setCompletionMode(QCompleter::InlineCompletion); -#else - q->setCompletionMode(QCompleter::PopupCompletion); -#endif // QT_NO_LISTVIEW -} - -void QCompleterPrivate::setCurrentIndex(QModelIndex index, bool select) -{ - Q_Q(QCompleter); - if (!q->popup()) - return; - if (!select) { - popup->selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate); - } else { - if (!index.isValid()) - popup->selectionModel()->clear(); - else - popup->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select - | QItemSelectionModel::Rows); - } - index = popup->selectionModel()->currentIndex(); - if (!index.isValid()) - popup->scrollToTop(); - else - popup->scrollTo(index, QAbstractItemView::PositionAtTop); -} - -void QCompleterPrivate::_q_completionSelected(const QItemSelection& selection) -{ - QModelIndex index; - if (!selection.indexes().isEmpty()) - index = selection.indexes().first(); - - _q_complete(index, true); -} - -void QCompleterPrivate::_q_complete(QModelIndex index, bool highlighted) -{ - Q_Q(QCompleter); - QString completion; - - if (!index.isValid() || (!proxy->showAll && (index.row() >= proxy->engine->matchCount()))) { - completion = prefix; - } else { - if (!(index.flags() & Qt::ItemIsEnabled)) - return; - QModelIndex si = proxy->mapToSource(index); - si = si.sibling(si.row(), column); // for clicked() - completion = q->pathFromIndex(si); -#ifndef QT_NO_DIRMODEL - // add a trailing separator in inline - if (mode == QCompleter::InlineCompletion) { - if (qobject_cast<QDirModel *>(proxy->sourceModel()) && QFileInfo(completion).isDir()) - completion += QDir::separator(); - } -#endif -#ifndef QT_NO_FILESYSTEMMODEL - // add a trailing separator in inline - if (mode == QCompleter::InlineCompletion) { - if (qobject_cast<QFileSystemModel *>(proxy->sourceModel()) && QFileInfo(completion).isDir()) - completion += QDir::separator(); - } -#endif - } - - if (highlighted) { - emit q->highlighted(index); - emit q->highlighted(completion); - } else { - emit q->activated(index); - emit q->activated(completion); - } -} - -void QCompleterPrivate::_q_autoResizePopup() -{ - if (!popup || !popup->isVisible()) - return; - showPopup(popupRect); -} - -void QCompleterPrivate::showPopup(const QRect& rect) -{ - const QRect screen = QApplication::desktop()->availableGeometry(widget); - Qt::LayoutDirection dir = widget->layoutDirection(); - QPoint pos; - int rh, w; - int h = (popup->sizeHintForRow(0) * qMin(maxVisibleItems, popup->model()->rowCount()) + 3) + 3; - QScrollBar *hsb = popup->horizontalScrollBar(); - if (hsb && hsb->isVisible()) - h += popup->horizontalScrollBar()->sizeHint().height(); - - if (rect.isValid()) { - rh = rect.height(); - w = rect.width(); - pos = widget->mapToGlobal(dir == Qt::RightToLeft ? rect.bottomRight() : rect.bottomLeft()); - } else { - rh = widget->height(); - pos = widget->mapToGlobal(QPoint(0, widget->height() - 2)); - w = widget->width(); - } - - if (w > screen.width()) - w = screen.width(); - if ((pos.x() + w) > (screen.x() + screen.width())) - pos.setX(screen.x() + screen.width() - w); - if (pos.x() < screen.x()) - pos.setX(screen.x()); - - int top = pos.y() - rh - screen.top() + 2; - int bottom = screen.bottom() - pos.y(); - h = qMax(h, popup->minimumHeight()); - if (h > bottom) { - h = qMin(qMax(top, bottom), h); - - if (top > bottom) - pos.setY(pos.y() - h - rh + 2); - } - - popup->setGeometry(pos.x(), pos.y(), w, h); - - if (!popup->isVisible()) - popup->show(); -} - -void QCompleterPrivate::_q_fileSystemModelDirectoryLoaded(const QString &path) -{ - Q_Q(QCompleter); - // Slot called when QFileSystemModel has finished loading. - // If we hide the popup because there was no match because the model was not loaded yet, - // we re-start the completion when we get the results - if (hiddenBecauseNoMatch - && prefix.startsWith(path) && prefix != (path + QLatin1Char('/')) - && widget) { - q->complete(); - } -} - -/*! - Constructs a completer object with the given \a parent. -*/ -QCompleter::QCompleter(QObject *parent) -: QObject(*new QCompleterPrivate(), parent) -{ - Q_D(QCompleter); - d->init(); -} - -/*! - Constructs a completer object with the given \a parent that provides completions - from the specified \a model. -*/ -QCompleter::QCompleter(QAbstractItemModel *model, QObject *parent) - : QObject(*new QCompleterPrivate(), parent) -{ - Q_D(QCompleter); - d->init(model); -} - -#ifndef QT_NO_STRINGLISTMODEL -/*! - Constructs a QCompleter object with the given \a parent that uses the specified - \a list as a source of possible completions. -*/ -QCompleter::QCompleter(const QStringList& list, QObject *parent) -: QObject(*new QCompleterPrivate(), parent) -{ - Q_D(QCompleter); - d->init(new QStringListModel(list, this)); -} -#endif // QT_NO_STRINGLISTMODEL - -/*! - Destroys the completer object. -*/ -QCompleter::~QCompleter() -{ -} - -/*! - Sets the widget for which completion are provided for to \a widget. This - function is automatically called when a QCompleter is set on a QLineEdit - using QLineEdit::setCompleter() or on a QComboBox using - QComboBox::setCompleter(). The widget needs to be set explicitly when - providing completions for custom widgets. - - \sa widget(), setModel(), setPopup() - */ -void QCompleter::setWidget(QWidget *widget) -{ - Q_D(QCompleter); - if (d->widget) - d->widget->removeEventFilter(this); - d->widget = widget; - if (d->widget) - d->widget->installEventFilter(this); - if (d->popup) { - d->popup->hide(); - d->popup->setFocusProxy(d->widget); - } -} - -/*! - Returns the widget for which the completer object is providing completions. - - \sa setWidget() - */ -QWidget *QCompleter::widget() const -{ - Q_D(const QCompleter); - return d->widget; -} - -/*! - Sets the model which provides completions to \a model. The \a model can - be list model or a tree model. If a model has been already previously set - and it has the QCompleter as its parent, it is deleted. - - For convenience, if \a model is a QFileSystemModel, QCompleter switches its - caseSensitivity to Qt::CaseInsensitive on Windows and Qt::CaseSensitive - on other platforms. - - \sa completionModel(), modelSorting, {Handling Tree Models} -*/ -void QCompleter::setModel(QAbstractItemModel *model) -{ - Q_D(QCompleter); - QAbstractItemModel *oldModel = d->proxy->sourceModel(); - d->proxy->setSourceModel(model); - if (d->popup) - setPopup(d->popup); // set the model and make new connections - if (oldModel && oldModel->QObject::parent() == this) - delete oldModel; -#ifndef QT_NO_DIRMODEL - if (qobject_cast<QDirModel *>(model)) { -#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN) - setCaseSensitivity(Qt::CaseInsensitive); -#else - setCaseSensitivity(Qt::CaseSensitive); -#endif - } -#endif // QT_NO_DIRMODEL -#ifndef QT_NO_FILESYSTEMMODEL - QFileSystemModel *fsModel = qobject_cast<QFileSystemModel *>(model); - if (fsModel) { -#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN) - setCaseSensitivity(Qt::CaseInsensitive); -#else - setCaseSensitivity(Qt::CaseSensitive); -#endif - setCompletionRole(QFileSystemModel::FileNameRole); - connect(fsModel, SIGNAL(directoryLoaded(QString)), this, SLOT(_q_fileSystemModelDirectoryLoaded(QString))); - } -#endif // QT_NO_FILESYSTEMMODEL -} - -/*! - Returns the model that provides completion strings. - - \sa completionModel() -*/ -QAbstractItemModel *QCompleter::model() const -{ - Q_D(const QCompleter); - return d->proxy->sourceModel(); -} - -/*! - \enum QCompleter::CompletionMode - - This enum specifies how completions are provided to the user. - - \value PopupCompletion Current completions are displayed in a popup window. - \value InlineCompletion Completions appear inline (as selected text). - \value UnfilteredPopupCompletion All possible completions are displayed in a popup window with the most likely suggestion indicated as current. - - \sa setCompletionMode() -*/ - -/*! - \property QCompleter::completionMode - \brief how the completions are provided to the user - - The default value is QCompleter::PopupCompletion. -*/ -void QCompleter::setCompletionMode(QCompleter::CompletionMode mode) -{ - Q_D(QCompleter); - d->mode = mode; - d->proxy->setFiltered(mode != QCompleter::UnfilteredPopupCompletion); - - if (mode == QCompleter::InlineCompletion) { - if (d->widget) - d->widget->removeEventFilter(this); - if (d->popup) { - d->popup->deleteLater(); - d->popup = 0; - } - } else { - if (d->widget) - d->widget->installEventFilter(this); - } -} - -QCompleter::CompletionMode QCompleter::completionMode() const -{ - Q_D(const QCompleter); - return d->mode; -} - -/*! - Sets the popup used to display completions to \a popup. QCompleter takes - ownership of the view. - - A QListView is automatically created when the completionMode() is set to - QCompleter::PopupCompletion or QCompleter::UnfilteredPopupCompletion. The - default popup displays the completionColumn(). - - Ensure that this function is called before the view settings are modified. - This is required since view's properties may require that a model has been - set on the view (for example, hiding columns in the view requires a model - to be set on the view). - - \sa popup() -*/ -void QCompleter::setPopup(QAbstractItemView *popup) -{ - Q_D(QCompleter); - Q_ASSERT(popup != 0); - if (d->popup) { - QObject::disconnect(d->popup->selectionModel(), 0, this, 0); - QObject::disconnect(d->popup, 0, this, 0); - } - if (d->popup != popup) - delete d->popup; - if (popup->model() != d->proxy) - popup->setModel(d->proxy); -#if defined(Q_OS_MAC) && !defined(QT_MAC_USE_COCOA) - popup->show(); -#else - popup->hide(); -#endif - - Qt::FocusPolicy origPolicy = Qt::NoFocus; - if (d->widget) - origPolicy = d->widget->focusPolicy(); - popup->setParent(0, Qt::Popup); - popup->setFocusPolicy(Qt::NoFocus); - if (d->widget) - d->widget->setFocusPolicy(origPolicy); - - popup->setFocusProxy(d->widget); - popup->installEventFilter(this); - popup->setItemDelegate(new QCompleterItemDelegate(popup)); -#ifndef QT_NO_LISTVIEW - if (QListView *listView = qobject_cast<QListView *>(popup)) { - listView->setModelColumn(d->column); - } -#endif - - QObject::connect(popup, SIGNAL(clicked(QModelIndex)), - this, SLOT(_q_complete(QModelIndex))); - QObject::connect(this, SIGNAL(activated(QModelIndex)), - popup, SLOT(hide())); - - QObject::connect(popup->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - this, SLOT(_q_completionSelected(QItemSelection))); - d->popup = popup; -} - -/*! - Returns the popup used to display completions. - - \sa setPopup() -*/ -QAbstractItemView *QCompleter::popup() const -{ - Q_D(const QCompleter); -#ifndef QT_NO_LISTVIEW - if (!d->popup && completionMode() != QCompleter::InlineCompletion) { - QListView *listView = new QListView; - listView->setEditTriggers(QAbstractItemView::NoEditTriggers); - listView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - listView->setSelectionBehavior(QAbstractItemView::SelectRows); - listView->setSelectionMode(QAbstractItemView::SingleSelection); - listView->setModelColumn(d->column); - QCompleter *that = const_cast<QCompleter*>(this); - that->setPopup(listView); - } -#endif // QT_NO_LISTVIEW - return d->popup; -} - -/*! - \reimp -*/ -bool QCompleter::event(QEvent *ev) -{ - return QObject::event(ev); -} - -/*! - \reimp -*/ -bool QCompleter::eventFilter(QObject *o, QEvent *e) -{ - Q_D(QCompleter); - - if (d->eatFocusOut && o == d->widget && e->type() == QEvent::FocusOut) { - d->hiddenBecauseNoMatch = false; - if (d->popup && d->popup->isVisible()) - return true; - } - - if (o != d->popup) - return QObject::eventFilter(o, e); - - switch (e->type()) { - case QEvent::KeyPress: { - QKeyEvent *ke = static_cast<QKeyEvent *>(e); - - QModelIndex curIndex = d->popup->currentIndex(); - QModelIndexList selList = d->popup->selectionModel()->selectedIndexes(); - - const int key = ke->key(); - // In UnFilteredPopup mode, select the current item - if ((key == Qt::Key_Up || key == Qt::Key_Down) && selList.isEmpty() && curIndex.isValid() - && d->mode == QCompleter::UnfilteredPopupCompletion) { - d->setCurrentIndex(curIndex); - return true; - } - - // Handle popup navigation keys. These are hardcoded because up/down might make the - // widget do something else (lineedit cursor moves to home/end on mac, for instance) - switch (key) { - case Qt::Key_End: - case Qt::Key_Home: - if (ke->modifiers() & Qt::ControlModifier) - return false; - break; - - case Qt::Key_Up: - if (!curIndex.isValid()) { - int rowCount = d->proxy->rowCount(); - QModelIndex lastIndex = d->proxy->index(rowCount - 1, d->column); - d->setCurrentIndex(lastIndex); - return true; - } else if (curIndex.row() == 0) { - if (d->wrap) - d->setCurrentIndex(QModelIndex()); - return true; - } - return false; - - case Qt::Key_Down: - if (!curIndex.isValid()) { - QModelIndex firstIndex = d->proxy->index(0, d->column); - d->setCurrentIndex(firstIndex); - return true; - } else if (curIndex.row() == d->proxy->rowCount() - 1) { - if (d->wrap) - d->setCurrentIndex(QModelIndex()); - return true; - } - return false; - - case Qt::Key_PageUp: - case Qt::Key_PageDown: - return false; - } - - // Send the event to the widget. If the widget accepted the event, do nothing - // If the widget did not accept the event, provide a default implementation - d->eatFocusOut = false; - (static_cast<QObject *>(d->widget))->event(ke); - d->eatFocusOut = true; - if (!d->widget || e->isAccepted() || !d->popup->isVisible()) { - // widget lost focus, hide the popup - if (d->widget && (!d->widget->hasFocus() -#ifdef QT_KEYPAD_NAVIGATION - || (QApplication::keypadNavigationEnabled() && !d->widget->hasEditFocus()) -#endif - )) - d->popup->hide(); - if (e->isAccepted()) - return true; - } - - // default implementation for keys not handled by the widget when popup is open - switch (key) { -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Select: - if (!QApplication::keypadNavigationEnabled()) - break; -#endif - case Qt::Key_Return: - case Qt::Key_Enter: - case Qt::Key_Tab: - d->popup->hide(); - if (curIndex.isValid()) - d->_q_complete(curIndex); - break; - - case Qt::Key_F4: - if (ke->modifiers() & Qt::AltModifier) - d->popup->hide(); - break; - - case Qt::Key_Backtab: - case Qt::Key_Escape: - d->popup->hide(); - break; - - default: - break; - } - - return true; - } - -#ifdef QT_KEYPAD_NAVIGATION - case QEvent::KeyRelease: { - QKeyEvent *ke = static_cast<QKeyEvent *>(e); - if (QApplication::keypadNavigationEnabled() && ke->key() == Qt::Key_Back) { - // Send the event to the 'widget'. This is what we did for KeyPress, so we need - // to do the same for KeyRelease, in case the widget's KeyPress event set - // up something (such as a timer) that is relying on also receiving the - // key release. I see this as a bug in Qt, and should really set it up for all - // the affected keys. However, it is difficult to tell how this will affect - // existing code, and I can't test for every combination! - d->eatFocusOut = false; - static_cast<QObject *>(d->widget)->event(ke); - d->eatFocusOut = true; - } - break; - } -#endif - - case QEvent::MouseButtonPress: { -#ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { - // if we've clicked in the widget (or its descendant), let it handle the click - QWidget *source = qobject_cast<QWidget *>(o); - if (source) { - QPoint pos = source->mapToGlobal((static_cast<QMouseEvent *>(e))->pos()); - QWidget *target = QApplication::widgetAt(pos); - if (target && (d->widget->isAncestorOf(target) || - target == d->widget)) { - d->eatFocusOut = false; - static_cast<QObject *>(target)->event(e); - d->eatFocusOut = true; - return true; - } - } - } -#endif - if (!d->popup->underMouse()) { - d->popup->hide(); - return true; - } - } - return false; - - case QEvent::InputMethod: - case QEvent::ShortcutOverride: - QApplication::sendEvent(d->widget, e); - break; - - default: - return false; - } - return false; -} - -/*! - For QCompleter::PopupCompletion and QCompletion::UnfilteredPopupCompletion - modes, calling this function displays the popup displaying the current - completions. By default, if \a rect is not specified, the popup is displayed - on the bottom of the widget(). If \a rect is specified the popup is - displayed on the left edge of the rectangle. - - For QCompleter::InlineCompletion mode, the highlighted() signal is fired - with the current completion. -*/ -void QCompleter::complete(const QRect& rect) -{ - Q_D(QCompleter); - QModelIndex idx = d->proxy->currentIndex(false); - d->hiddenBecauseNoMatch = false; - if (d->mode == QCompleter::InlineCompletion) { - if (idx.isValid()) - d->_q_complete(idx, true); - return; - } - - Q_ASSERT(d->widget != 0); - if ((d->mode == QCompleter::PopupCompletion && !idx.isValid()) - || (d->mode == QCompleter::UnfilteredPopupCompletion && d->proxy->rowCount() == 0)) { - if (d->popup) - d->popup->hide(); // no suggestion, hide - d->hiddenBecauseNoMatch = true; - return; - } - - popup(); - if (d->mode == QCompleter::UnfilteredPopupCompletion) - d->setCurrentIndex(idx, false); - - d->showPopup(rect); - d->popupRect = rect; -} - -/*! - Sets the current row to the \a row specified. Returns true if successful; - otherwise returns false. - - This function may be used along with currentCompletion() to iterate - through all the possible completions. - - \sa currentCompletion(), completionCount() -*/ -bool QCompleter::setCurrentRow(int row) -{ - Q_D(QCompleter); - return d->proxy->setCurrentRow(row); -} - -/*! - Returns the current row. - - \sa setCurrentRow() -*/ -int QCompleter::currentRow() const -{ - Q_D(const QCompleter); - return d->proxy->currentRow(); -} - -/*! - Returns the number of completions for the current prefix. For an unsorted - model with a large number of items this can be expensive. Use setCurrentRow() - and currentCompletion() to iterate through all the completions. -*/ -int QCompleter::completionCount() const -{ - Q_D(const QCompleter); - return d->proxy->completionCount(); -} - -/*! - \enum QCompleter::ModelSorting - - This enum specifies how the items in the model are sorted. - - \value UnsortedModel The model is unsorted. - \value CaseSensitivelySortedModel The model is sorted case sensitively. - \value CaseInsensitivelySortedModel The model is sorted case insensitively. - - \sa setModelSorting() -*/ - -/*! - \property QCompleter::modelSorting - \brief the way the model is sorted - - By default, no assumptions are made about the order of the items - in the model that provides the completions. - - If the model's data for the completionColumn() and completionRole() is sorted in - ascending order, you can set this property to \l CaseSensitivelySortedModel - or \l CaseInsensitivelySortedModel. On large models, this can lead to - significant performance improvements because the completer object can - then use a binary search algorithm instead of linear search algorithm. - - The sort order (i.e ascending or descending order) of the model is determined - dynamically by inspecting the contents of the model. - - \bold{Note:} The performance improvements described above cannot take place - when the completer's \l caseSensitivity is different to the case sensitivity - used by the model's when sorting. - - \sa setCaseSensitivity(), QCompleter::ModelSorting -*/ -void QCompleter::setModelSorting(QCompleter::ModelSorting sorting) -{ - Q_D(QCompleter); - if (d->sorting == sorting) - return; - d->sorting = sorting; - d->proxy->createEngine(); - d->proxy->invalidate(); -} - -QCompleter::ModelSorting QCompleter::modelSorting() const -{ - Q_D(const QCompleter); - return d->sorting; -} - -/*! - \property QCompleter::completionColumn - \brief the column in the model in which completions are searched for. - - If the popup() is a QListView, it is automatically setup to display - this column. - - By default, the match column is 0. - - \sa completionRole, caseSensitivity -*/ -void QCompleter::setCompletionColumn(int column) -{ - Q_D(QCompleter); - if (d->column == column) - return; -#ifndef QT_NO_LISTVIEW - if (QListView *listView = qobject_cast<QListView *>(d->popup)) - listView->setModelColumn(column); -#endif - d->column = column; - d->proxy->invalidate(); -} - -int QCompleter::completionColumn() const -{ - Q_D(const QCompleter); - return d->column; -} - -/*! - \property QCompleter::completionRole - \brief the item role to be used to query the contents of items for matching. - - The default role is Qt::EditRole. - - \sa completionColumn, caseSensitivity -*/ -void QCompleter::setCompletionRole(int role) -{ - Q_D(QCompleter); - if (d->role == role) - return; - d->role = role; - d->proxy->invalidate(); -} - -int QCompleter::completionRole() const -{ - Q_D(const QCompleter); - return d->role; -} - -/*! - \property QCompleter::wrapAround - \brief the completions wrap around when navigating through items - \since 4.3 - - The default is true. -*/ -void QCompleter::setWrapAround(bool wrap) -{ - Q_D(QCompleter); - if (d->wrap == wrap) - return; - d->wrap = wrap; -} - -bool QCompleter::wrapAround() const -{ - Q_D(const QCompleter); - return d->wrap; -} - -/*! - \property QCompleter::maxVisibleItems - \brief the maximum allowed size on screen of the completer, measured in items - \since 4.6 - - By default, this property has a value of 7. -*/ -int QCompleter::maxVisibleItems() const -{ - Q_D(const QCompleter); - return d->maxVisibleItems; -} - -void QCompleter::setMaxVisibleItems(int maxItems) -{ - Q_D(QCompleter); - if (maxItems < 0) { - qWarning("QCompleter::setMaxVisibleItems: " - "Invalid max visible items (%d) must be >= 0", maxItems); - return; - } - d->maxVisibleItems = maxItems; -} - -/*! - \property QCompleter::caseSensitivity - \brief the case sensitivity of the matching - - The default is Qt::CaseSensitive. - - \sa completionColumn, completionRole, modelSorting -*/ -void QCompleter::setCaseSensitivity(Qt::CaseSensitivity cs) -{ - Q_D(QCompleter); - if (d->cs == cs) - return; - d->cs = cs; - d->proxy->createEngine(); - d->proxy->invalidate(); -} - -Qt::CaseSensitivity QCompleter::caseSensitivity() const -{ - Q_D(const QCompleter); - return d->cs; -} - -/*! - \property QCompleter::completionPrefix - \brief the completion prefix used to provide completions. - - The completionModel() is updated to reflect the list of possible - matches for \a prefix. -*/ -void QCompleter::setCompletionPrefix(const QString &prefix) -{ - Q_D(QCompleter); - d->prefix = prefix; - d->proxy->filter(splitPath(prefix)); -} - -QString QCompleter::completionPrefix() const -{ - Q_D(const QCompleter); - return d->prefix; -} - -/*! - Returns the model index of the current completion in the completionModel(). - - \sa setCurrentRow(), currentCompletion(), model() -*/ -QModelIndex QCompleter::currentIndex() const -{ - Q_D(const QCompleter); - return d->proxy->currentIndex(false); -} - -/*! - Returns the current completion string. This includes the \l completionPrefix. - When used alongside setCurrentRow(), it can be used to iterate through - all the matches. - - \sa setCurrentRow(), currentIndex() -*/ -QString QCompleter::currentCompletion() const -{ - Q_D(const QCompleter); - return pathFromIndex(d->proxy->currentIndex(true)); -} - -/*! - Returns the completion model. The completion model is a read-only list model - that contains all the possible matches for the current completion prefix. - The completion model is auto-updated to reflect the current completions. - - \note The return value of this function is defined to be an QAbstractItemModel - purely for generality. This actual kind of model returned is an instance of an - QAbstractProxyModel subclass. - - \sa completionPrefix, model() -*/ -QAbstractItemModel *QCompleter::completionModel() const -{ - Q_D(const QCompleter); - return d->proxy; -} - -/*! - Returns the path for the given \a index. The completer object uses this to - obtain the completion text from the underlying model. - - The default implementation returns the \l{Qt::EditRole}{edit role} of the - item for list models. It returns the absolute file path if the model is a - QFileSystemModel. - - \sa splitPath() -*/ - -QString QCompleter::pathFromIndex(const QModelIndex& index) const -{ - Q_D(const QCompleter); - if (!index.isValid()) - return QString(); - - QAbstractItemModel *sourceModel = d->proxy->sourceModel(); - if (!sourceModel) - return QString(); - bool isDirModel = false; - bool isFsModel = false; -#ifndef QT_NO_DIRMODEL - isDirModel = qobject_cast<QDirModel *>(d->proxy->sourceModel()) != 0; -#endif -#ifndef QT_NO_FILESYSTEMMODEL - isFsModel = qobject_cast<QFileSystemModel *>(d->proxy->sourceModel()) != 0; -#endif - if (!isDirModel && !isFsModel) - return sourceModel->data(index, d->role).toString(); - - QModelIndex idx = index; - QStringList list; - do { - QString t; - if (isDirModel) - t = sourceModel->data(idx, Qt::EditRole).toString(); -#ifndef QT_NO_FILESYSTEMMODEL - else - t = sourceModel->data(idx, QFileSystemModel::FileNameRole).toString(); -#endif - list.prepend(t); - QModelIndex parent = idx.parent(); - idx = parent.sibling(parent.row(), index.column()); - } while (idx.isValid()); - -#if (!defined(Q_OS_WIN) || defined(Q_OS_WINCE)) && !defined(Q_OS_SYMBIAN) - if (list.count() == 1) // only the separator or some other text - return list[0]; - list[0].clear() ; // the join below will provide the separator -#endif - - return list.join(QDir::separator()); -} - -/*! - Splits the given \a path into strings that are used to match at each level - in the model(). - - The default implementation of splitPath() splits a file system path based on - QDir::separator() when the sourceModel() is a QFileSystemModel. - - When used with list models, the first item in the returned list is used for - matching. - - \sa pathFromIndex(), {Handling Tree Models} -*/ -QStringList QCompleter::splitPath(const QString& path) const -{ - bool isDirModel = false; - bool isFsModel = false; -#ifndef QT_NO_DIRMODEL - Q_D(const QCompleter); - isDirModel = qobject_cast<QDirModel *>(d->proxy->sourceModel()) != 0; -#endif -#ifndef QT_NO_FILESYSTEMMODEL -#ifdef QT_NO_DIRMODEL - Q_D(const QCompleter); -#endif - isFsModel = qobject_cast<QFileSystemModel *>(d->proxy->sourceModel()) != 0; -#endif - - if ((!isDirModel && !isFsModel) || path.isEmpty()) - return QStringList(completionPrefix()); - - QString pathCopy = QDir::toNativeSeparators(path); - QString sep = QDir::separator(); -#if defined(Q_OS_SYMBIAN) - if (pathCopy == QLatin1String("\\")) - return QStringList(pathCopy); -#elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - if (pathCopy == QLatin1String("\\") || pathCopy == QLatin1String("\\\\")) - return QStringList(pathCopy); - QString doubleSlash(QLatin1String("\\\\")); - if (pathCopy.startsWith(doubleSlash)) - pathCopy = pathCopy.mid(2); - else - doubleSlash.clear(); -#endif - - QRegExp re(QLatin1Char('[') + QRegExp::escape(sep) + QLatin1Char(']')); - QStringList parts = pathCopy.split(re); - -#if defined(Q_OS_SYMBIAN) - // Do nothing -#elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - if (!doubleSlash.isEmpty()) - parts[0].prepend(doubleSlash); -#else - if (pathCopy[0] == sep[0]) // readd the "/" at the beginning as the split removed it - parts[0] = QDir::fromNativeSeparators(QString(sep[0])); -#endif - - return parts; -} - -/*! - \fn void QCompleter::activated(const QModelIndex& index) - - This signal is sent when an item in the popup() is activated by the user. - (by clicking or pressing return). The item's \a index in the completionModel() - is given. - -*/ - -/*! - \fn void QCompleter::activated(const QString &text) - - This signal is sent when an item in the popup() is activated by the user (by - clicking or pressing return). The item's \a text is given. - -*/ - -/*! - \fn void QCompleter::highlighted(const QModelIndex& index) - - This signal is sent when an item in the popup() is highlighted by - the user. It is also sent if complete() is called with the completionMode() - set to QCompleter::InlineCompletion. The item's \a index in the completionModel() - is given. -*/ - -/*! - \fn void QCompleter::highlighted(const QString &text) - - This signal is sent when an item in the popup() is highlighted by - the user. It is also sent if complete() is called with the completionMode() - set to QCompleter::InlineCompletion. The item's \a text is given. -*/ - -QT_END_NAMESPACE - -#include "moc_qcompleter.cpp" - -#endif // QT_NO_COMPLETER diff --git a/src/gui/util/qcompleter.h b/src/gui/util/qcompleter.h deleted file mode 100644 index 61797ee645..0000000000 --- a/src/gui/util/qcompleter.h +++ /dev/null @@ -1,171 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QCOMPLETER_H -#define QCOMPLETER_H - -#include <QtCore/qobject.h> -#include <QtCore/qpoint.h> -#include <QtCore/qstring.h> -#include <QtCore/qabstractitemmodel.h> -#include <QtCore/qrect.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#ifndef QT_NO_COMPLETER - -class QCompleterPrivate; -class QAbstractItemView; -class QAbstractProxyModel; -class QWidget; - -class Q_GUI_EXPORT QCompleter : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString completionPrefix READ completionPrefix WRITE setCompletionPrefix) - Q_PROPERTY(ModelSorting modelSorting READ modelSorting WRITE setModelSorting) - Q_PROPERTY(CompletionMode completionMode READ completionMode WRITE setCompletionMode) - Q_PROPERTY(int completionColumn READ completionColumn WRITE setCompletionColumn) - Q_PROPERTY(int completionRole READ completionRole WRITE setCompletionRole) - Q_PROPERTY(int maxVisibleItems READ maxVisibleItems WRITE setMaxVisibleItems) - Q_PROPERTY(Qt::CaseSensitivity caseSensitivity READ caseSensitivity WRITE setCaseSensitivity) - Q_PROPERTY(bool wrapAround READ wrapAround WRITE setWrapAround) - -public: - enum CompletionMode { - PopupCompletion, - UnfilteredPopupCompletion, - InlineCompletion - }; - - enum ModelSorting { - UnsortedModel = 0, - CaseSensitivelySortedModel, - CaseInsensitivelySortedModel - }; - - QCompleter(QObject *parent = 0); - QCompleter(QAbstractItemModel *model, QObject *parent = 0); -#ifndef QT_NO_STRINGLISTMODEL - QCompleter(const QStringList& completions, QObject *parent = 0); -#endif - ~QCompleter(); - - void setWidget(QWidget *widget); - QWidget *widget() const; - - void setModel(QAbstractItemModel *c); - QAbstractItemModel *model() const; - - void setCompletionMode(CompletionMode mode); - CompletionMode completionMode() const; - - QAbstractItemView *popup() const; - void setPopup(QAbstractItemView *popup); - - void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity); - Qt::CaseSensitivity caseSensitivity() const; - - void setModelSorting(ModelSorting sorting); - ModelSorting modelSorting() const; - - void setCompletionColumn(int column); - int completionColumn() const; - - void setCompletionRole(int role); - int completionRole() const; - - bool wrapAround() const; - - int maxVisibleItems() const; - void setMaxVisibleItems(int maxItems); - - int completionCount() const; - bool setCurrentRow(int row); - int currentRow() const; - - QModelIndex currentIndex() const; - QString currentCompletion() const; - - QAbstractItemModel *completionModel() const; - - QString completionPrefix() const; - -public Q_SLOTS: - void setCompletionPrefix(const QString &prefix); - void complete(const QRect& rect = QRect()); - void setWrapAround(bool wrap); - -public: - virtual QString pathFromIndex(const QModelIndex &index) const; - virtual QStringList splitPath(const QString &path) const; - -protected: - bool eventFilter(QObject *o, QEvent *e); - bool event(QEvent *); - -Q_SIGNALS: - void activated(const QString &text); - void activated(const QModelIndex &index); - void highlighted(const QString &text); - void highlighted(const QModelIndex &index); - -private: - Q_DISABLE_COPY(QCompleter) - Q_DECLARE_PRIVATE(QCompleter) - - Q_PRIVATE_SLOT(d_func(), void _q_complete(QModelIndex)) - Q_PRIVATE_SLOT(d_func(), void _q_completionSelected(const QItemSelection&)) - Q_PRIVATE_SLOT(d_func(), void _q_autoResizePopup()) - Q_PRIVATE_SLOT(d_func(), void _q_fileSystemModelDirectoryLoaded(const QString&)) -}; - -#endif // QT_NO_COMPLETER - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QCOMPLETER_H diff --git a/src/gui/util/qcompleter_p.h b/src/gui/util/qcompleter_p.h deleted file mode 100644 index e06440cb07..0000000000 --- a/src/gui/util/qcompleter_p.h +++ /dev/null @@ -1,264 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QCOMPLETER_P_H -#define QCOMPLETER_P_H - - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "private/qobject_p.h" - -#ifndef QT_NO_COMPLETER - -#include "QtGui/qtreeview.h" -#include "QtGui/qabstractproxymodel.h" -#include "qcompleter.h" -#include "QtGui/qitemdelegate.h" -#include "QtGui/qpainter.h" -#include "private/qabstractproxymodel_p.h" - -QT_BEGIN_NAMESPACE - -class QCompletionModel; - -class QCompleterPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QCompleter) - -public: - QCompleterPrivate(); - ~QCompleterPrivate() { delete popup; } - void init(QAbstractItemModel *model = 0); - - QPointer<QWidget> widget; - QCompletionModel *proxy; - QAbstractItemView *popup; - QCompleter::CompletionMode mode; - - QString prefix; - Qt::CaseSensitivity cs; - int role; - int column; - int maxVisibleItems; - QCompleter::ModelSorting sorting; - bool wrap; - - bool eatFocusOut; - QRect popupRect; - bool hiddenBecauseNoMatch; - - void showPopup(const QRect&); - void _q_complete(QModelIndex, bool = false); - void _q_completionSelected(const QItemSelection&); - void _q_autoResizePopup(); - void _q_fileSystemModelDirectoryLoaded(const QString &path); - void setCurrentIndex(QModelIndex, bool = true); -}; - -class QIndexMapper -{ -public: - QIndexMapper() : v(false), f(0), t(-1) { } - QIndexMapper(int f, int t) : v(false), f(f), t(t) { } - QIndexMapper(QVector<int> vec) : v(true), vector(vec), f(-1), t(-1) { } - - inline int count() const { return v ? vector.count() : t - f + 1; } - inline int operator[] (int index) const { return v ? vector[index] : f + index; } - inline int indexOf(int x) const { return v ? vector.indexOf(x) : ((t < f) ? -1 : x - f); } - inline bool isValid() const { return !isEmpty(); } - inline bool isEmpty() const { return v ? vector.isEmpty() : (t < f); } - inline void append(int x) { Q_ASSERT(v); vector.append(x); } - inline int first() const { return v ? vector.first() : f; } - inline int last() const { return v ? vector.last() : t; } - inline int from() const { Q_ASSERT(!v); return f; } - inline int to() const { Q_ASSERT(!v); return t; } - inline int cost() const { return vector.count()+2; } - -private: - bool v; - QVector<int> vector; - int f, t; -}; - -struct QMatchData { - QMatchData() : exactMatchIndex(-1) { } - QMatchData(const QIndexMapper& indices, int em, bool p) : - indices(indices), exactMatchIndex(em), partial(p) { } - QIndexMapper indices; - inline bool isValid() const { return indices.isValid(); } - int exactMatchIndex; - bool partial; -}; - -class QCompletionEngine -{ -public: - typedef QMap<QString, QMatchData> CacheItem; - typedef QMap<QModelIndex, CacheItem> Cache; - - QCompletionEngine(QCompleterPrivate *c) : c(c), curRow(-1), cost(0) { } - virtual ~QCompletionEngine() { } - - void filter(const QStringList &parts); - - QMatchData filterHistory(); - bool matchHint(QString, const QModelIndex&, QMatchData*); - - void saveInCache(QString, const QModelIndex&, const QMatchData&); - bool lookupCache(QString part, const QModelIndex& parent, QMatchData *m); - - virtual void filterOnDemand(int) { } - virtual QMatchData filter(const QString&, const QModelIndex&, int) = 0; - - int matchCount() const { return curMatch.indices.count() + historyMatch.indices.count(); } - - QMatchData curMatch, historyMatch; - QCompleterPrivate *c; - QStringList curParts; - QModelIndex curParent; - int curRow; - - Cache cache; - int cost; -}; - -class QSortedModelEngine : public QCompletionEngine -{ -public: - QSortedModelEngine(QCompleterPrivate *c) : QCompletionEngine(c) { } - QMatchData filter(const QString&, const QModelIndex&, int); - QIndexMapper indexHint(QString, const QModelIndex&, Qt::SortOrder); - Qt::SortOrder sortOrder(const QModelIndex&) const; -}; - -class QUnsortedModelEngine : public QCompletionEngine -{ -public: - QUnsortedModelEngine(QCompleterPrivate *c) : QCompletionEngine(c) { } - - void filterOnDemand(int); - QMatchData filter(const QString&, const QModelIndex&, int); -private: - int buildIndices(const QString& str, const QModelIndex& parent, int n, - const QIndexMapper& iv, QMatchData* m); -}; - -class QCompleterItemDelegate : public QItemDelegate -{ -public: - QCompleterItemDelegate(QAbstractItemView *view) - : QItemDelegate(view), view(view) { } - void paint(QPainter *p, const QStyleOptionViewItem& opt, const QModelIndex& idx) const { - QStyleOptionViewItem optCopy = opt; - optCopy.showDecorationSelected = true; - if (view->currentIndex() == idx) - optCopy.state |= QStyle::State_HasFocus; - QItemDelegate::paint(p, optCopy, idx); - } - -private: - QAbstractItemView *view; -}; - -class QCompletionModelPrivate; - -class QCompletionModel : public QAbstractProxyModel -{ - Q_OBJECT - -public: - QCompletionModel(QCompleterPrivate *c, QObject *parent); - - void createEngine(); - void setFiltered(bool); - void filter(const QStringList& parts); - int completionCount() const; - int currentRow() const { return engine->curRow; } - bool setCurrentRow(int row); - QModelIndex currentIndex(bool) const; - void resetModel(); - - QModelIndex index(int row, int column, const QModelIndex & = QModelIndex()) const; - int rowCount(const QModelIndex &index = QModelIndex()) const; - int columnCount(const QModelIndex &index = QModelIndex()) const; - bool hasChildren(const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex & = QModelIndex()) const { return QModelIndex(); } - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; - - void setSourceModel(QAbstractItemModel *sourceModel); - QModelIndex mapToSource(const QModelIndex& proxyIndex) const; - QModelIndex mapFromSource(const QModelIndex& sourceIndex) const; - - QCompleterPrivate *c; - QScopedPointer<QCompletionEngine> engine; - bool showAll; - - Q_DECLARE_PRIVATE(QCompletionModel) - -signals: - void rowsAdded(); - -public Q_SLOTS: - void invalidate(); - void rowsInserted(); - void modelDestroyed(); -}; - -class QCompletionModelPrivate : public QAbstractProxyModelPrivate -{ - Q_DECLARE_PUBLIC(QCompletionModel) -}; - -QT_END_NAMESPACE - -#endif // QT_NO_COMPLETER - -#endif // QCOMPLETER_P_H diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp index e79819e69f..669f7ea893 100644 --- a/src/gui/util/qdesktopservices.cpp +++ b/src/gui/util/qdesktopservices.cpp @@ -46,7 +46,7 @@ #include <qdebug.h> #if defined(Q_WS_QWS) || defined(Q_WS_QPA) -#include "qdesktopservices_qws.cpp" +#include "qdesktopservices_qpa.cpp" #elif defined(Q_WS_X11) #include "qdesktopservices_x11.cpp" #elif defined(Q_WS_WIN) diff --git a/src/gui/util/qdesktopservices_qws.cpp b/src/gui/util/qdesktopservices_qpa.cpp index e3847e5bfd..374b06b4f0 100644 --- a/src/gui/util/qdesktopservices_qws.cpp +++ b/src/gui/util/qdesktopservices_qpa.cpp @@ -41,6 +41,7 @@ #include <qcoreapplication.h> #include <qdir.h> +#include <qurl.h> QT_BEGIN_NAMESPACE diff --git a/src/gui/util/qflickgesture.cpp b/src/gui/util/qflickgesture.cpp deleted file mode 100644 index 07eca6c53b..0000000000 --- a/src/gui/util/qflickgesture.cpp +++ /dev/null @@ -1,715 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qgesture.h" -#include "qapplication.h" -#include "qevent.h" -#include "qwidget.h" -#include "qgraphicsitem.h" -#include "qgraphicsscene.h" -#include "qgraphicssceneevent.h" -#include "qgraphicsview.h" -#include "qscroller.h" -#include "private/qevent_p.h" -#include "private/qflickgesture_p.h" -#include "qdebug.h" - -#ifndef QT_NO_GESTURES - -QT_BEGIN_NAMESPACE - -//#define QFLICKGESTURE_DEBUG - -#ifdef QFLICKGESTURE_DEBUG -# define qFGDebug qDebug -#else -# define qFGDebug while (false) qDebug -#endif - -extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); - -static QMouseEvent *copyMouseEvent(QEvent *e) -{ - switch (e->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: { - QMouseEvent *me = static_cast<QMouseEvent *>(e); - return new QMouseEvent(me->type(), QPoint(0, 0), me->globalPos(), me->button(), me->buttons(), me->modifiers()); - } -#ifndef QT_NO_GRAPHICSVIEW - case QEvent::GraphicsSceneMousePress: - case QEvent::GraphicsSceneMouseRelease: - case QEvent::GraphicsSceneMouseMove: { - QGraphicsSceneMouseEvent *me = static_cast<QGraphicsSceneMouseEvent *>(e); -#if 1 - QEvent::Type met = me->type() == QEvent::GraphicsSceneMousePress ? QEvent::MouseButtonPress : - (me->type() == QEvent::GraphicsSceneMouseRelease ? QEvent::MouseButtonRelease : QEvent::MouseMove); - return new QMouseEvent(met, QPoint(0, 0), me->screenPos(), me->button(), me->buttons(), me->modifiers()); -#else - QGraphicsSceneMouseEvent *copy = new QGraphicsSceneMouseEvent(me->type()); - copy->setPos(me->pos()); - copy->setScenePos(me->scenePos()); - copy->setScreenPos(me->screenPos()); - for (int i = 0x1; i <= 0x10; i <<= 1) { - Qt::MouseButton button = Qt::MouseButton(i); - copy->setButtonDownPos(button, me->buttonDownPos(button)); - copy->setButtonDownScenePos(button, me->buttonDownScenePos(button)); - copy->setButtonDownScreenPos(button, me->buttonDownScreenPos(button)); - } - copy->setLastPos(me->lastPos()); - copy->setLastScenePos(me->lastScenePos()); - copy->setLastScreenPos(me->lastScreenPos()); - copy->setButtons(me->buttons()); - copy->setButton(me->button()); - copy->setModifiers(me->modifiers()); - return copy; -#endif - } -#endif // QT_NO_GRAPHICSVIEW - default: - return 0; - } -} - -class PressDelayHandler : public QObject -{ -private: - PressDelayHandler(QObject *parent = 0) - : QObject(parent) - , pressDelayTimer(0) - , sendingEvent(false) - , mouseButton(Qt::NoButton) - , mouseTarget(0) - { } - - static PressDelayHandler *inst; - -public: - enum { - UngrabMouseBefore = 1, - RegrabMouseAfterwards = 2 - }; - - static PressDelayHandler *instance() - { - static PressDelayHandler *inst = 0; - if (!inst) - inst = new PressDelayHandler(QCoreApplication::instance()); - return inst; - } - - bool shouldEventBeIgnored(QEvent *) const - { - return sendingEvent; - } - - bool isDelaying() const - { - return !pressDelayEvent.isNull(); - } - - void pressed(QEvent *e, int delay) - { - if (!pressDelayEvent) { - pressDelayEvent.reset(copyMouseEvent(e)); - pressDelayTimer = startTimer(delay); - mouseTarget = QApplication::widgetAt(pressDelayEvent->globalPos()); - mouseButton = pressDelayEvent->button(); - qFGDebug() << "QFG: consuming/delaying mouse press"; - } else { - qFGDebug() << "QFG: NOT consuming/delaying mouse press"; - } - e->setAccepted(true); - } - - bool released(QEvent *e, bool scrollerWasActive, bool scrollerIsActive) - { - // consume this event if the scroller was or is active - bool result = scrollerWasActive || scrollerIsActive; - - // stop the timer - if (pressDelayTimer) { - killTimer(pressDelayTimer); - pressDelayTimer = 0; - } - // we still haven't even sent the press, so do it now - if (pressDelayEvent && mouseTarget && !scrollerIsActive) { - QScopedPointer<QMouseEvent> releaseEvent(copyMouseEvent(e)); - - qFGDebug() << "QFG: re-sending mouse press (due to release) for " << mouseTarget; - sendMouseEvent(pressDelayEvent.data(), UngrabMouseBefore); - - qFGDebug() << "QFG: faking mouse release (due to release) for " << mouseTarget; - sendMouseEvent(releaseEvent.data()); - - result = true; // consume this event - } else if (mouseTarget && scrollerIsActive) { - // we grabbed the mouse expicitly when the scroller became active, so undo that now - sendMouseEvent(0, UngrabMouseBefore); - } - pressDelayEvent.reset(0); - mouseTarget = 0; - return result; - } - - void scrollerWasIntercepted() - { - qFGDebug() << "QFG: deleting delayed mouse press, since scroller was only intercepted"; - if (pressDelayEvent) { - // we still haven't even sent the press, so just throw it away now - if (pressDelayTimer) { - killTimer(pressDelayTimer); - pressDelayTimer = 0; - } - pressDelayEvent.reset(0); - } - mouseTarget = 0; - } - - void scrollerBecameActive() - { - if (pressDelayEvent) { - // we still haven't even sent the press, so just throw it away now - qFGDebug() << "QFG: deleting delayed mouse press, since scroller is active now"; - if (pressDelayTimer) { - killTimer(pressDelayTimer); - pressDelayTimer = 0; - } - pressDelayEvent.reset(0); - mouseTarget = 0; - } else if (mouseTarget) { - // we did send a press, so we need to fake a release now - - // release all pressed mouse buttons - /* Qt::MouseButtons mouseButtons = QApplication::mouseButtons(); - for (int i = 0; i < 32; ++i) { - if (mouseButtons & (1 << i)) { - Qt::MouseButton b = static_cast<Qt::MouseButton>(1 << i); - mouseButtons &= ~b; - QPoint farFarAway(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX); - - qFGDebug() << "QFG: sending a fake mouse release at far-far-away to " << mouseTarget; - QMouseEvent re(QEvent::MouseButtonRelease, QPoint(), farFarAway, - b, mouseButtons, QApplication::keyboardModifiers()); - sendMouseEvent(&re); - } - }*/ - - QPoint farFarAway(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX); - - qFGDebug() << "QFG: sending a fake mouse release at far-far-away to " << mouseTarget; - QMouseEvent re(QEvent::MouseButtonRelease, QPoint(), farFarAway, - mouseButton, QApplication::mouseButtons() & ~mouseButton, - QApplication::keyboardModifiers()); - sendMouseEvent(&re, RegrabMouseAfterwards); - // don't clear the mouseTarget just yet, since we need to explicitly ungrab the mouse on release! - } - } - -protected: - void timerEvent(QTimerEvent *e) - { - if (e->timerId() == pressDelayTimer) { - if (pressDelayEvent && mouseTarget) { - qFGDebug() << "QFG: timer event: re-sending mouse press to " << mouseTarget; - sendMouseEvent(pressDelayEvent.data(), UngrabMouseBefore); - } - pressDelayEvent.reset(0); - - if (pressDelayTimer) { - killTimer(pressDelayTimer); - pressDelayTimer = 0; - } - } - } - - void sendMouseEvent(QMouseEvent *me, int flags = 0) - { - if (mouseTarget) { - sendingEvent = true; - -#ifndef QT_NO_GRAPHICSVIEW - QGraphicsItem *grabber = 0; - if (mouseTarget->parentWidget()) { - if (QGraphicsView *gv = qobject_cast<QGraphicsView *>(mouseTarget->parentWidget())) { - if (gv->scene()) - grabber = gv->scene()->mouseGrabberItem(); - } - } - - if (grabber && (flags & UngrabMouseBefore)) { - // GraphicsView Mouse Handling Workaround #1: - // we need to ungrab the mouse before re-sending the press, - // since the scene had already set the mouse grabber to the - // original (and consumed) event's receiver - qFGDebug() << "QFG: ungrabbing" << grabber; - grabber->ungrabMouse(); - } -#endif // QT_NO_GRAPHICSVIEW - - if (me) { - QMouseEvent copy(me->type(), mouseTarget->mapFromGlobal(me->globalPos()), me->globalPos(), me->button(), me->buttons(), me->modifiers()); - qt_sendSpontaneousEvent(mouseTarget, ©); - } - -#ifndef QT_NO_GRAPHICSVIEW - if (grabber && (flags & RegrabMouseAfterwards)) { - // GraphicsView Mouse Handling Workaround #2: - // we need to re-grab the mouse after sending a faked mouse - // release, since we still need the mouse moves for the gesture - // (the scene will clear the item's mouse grabber status on - // release). - qFGDebug() << "QFG: re-grabbing" << grabber; - grabber->grabMouse(); - } -#endif - sendingEvent = false; - } - } - - -private: - int pressDelayTimer; - QScopedPointer<QMouseEvent> pressDelayEvent; - bool sendingEvent; - Qt::MouseButton mouseButton; - QPointer<QWidget> mouseTarget; -}; - - -/*! - \internal - \class QFlickGesture - \since 4.8 - \brief The QFlickGesture class describes a flicking gesture made by the user. - \ingroup gestures - The QFlickGesture is more complex than the QPanGesture that uses QScroller and QScrollerProperties - to decide if it is triggered. - This gesture is reacting on touch event as compared to the QMouseFlickGesture. - - \sa {Gestures Programming}, QScroller, QScrollerProperties, QMouseFlickGesture -*/ - -/*! - \internal -*/ -QFlickGesture::QFlickGesture(QObject *receiver, Qt::MouseButton button, QObject *parent) - : QGesture(*new QFlickGesturePrivate, parent) -{ - d_func()->q_ptr = this; - d_func()->receiver = receiver; - d_func()->receiverScroller = (receiver && QScroller::hasScroller(receiver)) ? QScroller::scroller(receiver) : 0; - d_func()->button = button; -} - -QFlickGesture::~QFlickGesture() -{ } - -QFlickGesturePrivate::QFlickGesturePrivate() - : receiverScroller(0), button(Qt::NoButton), macIgnoreWheel(false) -{ } - - -// -// QFlickGestureRecognizer -// - - -QFlickGestureRecognizer::QFlickGestureRecognizer(Qt::MouseButton button) -{ - this->button = button; -} - -/*! \reimp - */ -QGesture *QFlickGestureRecognizer::create(QObject *target) -{ -#ifndef QT_NO_GRAPHICSVIEW - QGraphicsObject *go = qobject_cast<QGraphicsObject*>(target); - if (go && button == Qt::NoButton) { - go->setAcceptTouchEvents(true); - } -#endif - return new QFlickGesture(target, button); -} - -/*! \internal - The recognize function detects a touch event suitable to start the attached QScroller. - The QFlickGesture will be triggered as soon as the scroller is no longer in the state - QScroller::Inactive or QScroller::Pressed. It will be finished or canceled - at the next QEvent::TouchEnd. - Note that the QScroller might continue scrolling (kinetically) at this point. - */ -QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state, - QObject *watched, - QEvent *event) -{ - Q_UNUSED(watched); - - static QElapsedTimer monotonicTimer; - if (!monotonicTimer.isValid()) - monotonicTimer.start(); - - QFlickGesture *q = static_cast<QFlickGesture *>(state); - QFlickGesturePrivate *d = q->d_func(); - - QScroller *scroller = d->receiverScroller; - if (!scroller) - return Ignore; // nothing to do without a scroller? - - QWidget *receiverWidget = qobject_cast<QWidget *>(d->receiver); -#ifndef QT_NO_GRAPHICSVIEW - QGraphicsObject *receiverGraphicsObject = qobject_cast<QGraphicsObject *>(d->receiver); -#endif - - // this is only set for events that we inject into the event loop via sendEvent() - if (PressDelayHandler::instance()->shouldEventBeIgnored(event)) { - //qFGDebug() << state << "QFG: ignored event: " << event->type(); - return Ignore; - } - - const QMouseEvent *me = 0; -#ifndef QT_NO_GRAPHICSVIEW - const QGraphicsSceneMouseEvent *gsme = 0; -#endif - const QTouchEvent *te = 0; - QPoint globalPos; - - // qFGDebug() << "FlickGesture "<<state<<"watched:"<<watched<<"receiver"<<d->receiver<<"event"<<event->type()<<"button"<<button; - - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - if (!receiverWidget) - return Ignore; - if (button != Qt::NoButton) { - me = static_cast<const QMouseEvent *>(event); - globalPos = me->globalPos(); - } - break; -#ifndef QT_NO_GRAPHICSVIEW - case QEvent::GraphicsSceneMousePress: - case QEvent::GraphicsSceneMouseRelease: - case QEvent::GraphicsSceneMouseMove: - if (!receiverGraphicsObject) - return Ignore; - if (button != Qt::NoButton) { - gsme = static_cast<const QGraphicsSceneMouseEvent *>(event); - globalPos = gsme->screenPos(); - } - break; -#endif - case QEvent::TouchBegin: - case QEvent::TouchEnd: - case QEvent::TouchUpdate: - if (button == Qt::NoButton) { - te = static_cast<const QTouchEvent *>(event); - if (!te->touchPoints().isEmpty()) - globalPos = te->touchPoints().at(0).screenPos().toPoint(); - } - break; - -#if defined(Q_WS_MAC) - // the only way to distinguish between real mouse wheels and wheel - // events generated by the native 2 finger swipe gesture is to listen - // for these events (according to Apple's Cocoa Event-Handling Guide) - - case QEvent::NativeGesture: { - QNativeGestureEvent *nge = static_cast<QNativeGestureEvent *>(event); - if (nge->gestureType == QNativeGestureEvent::GestureBegin) - d->macIgnoreWheel = true; - else if (nge->gestureType == QNativeGestureEvent::GestureEnd) - d->macIgnoreWheel = false; - break; - } -#endif - - // consume all wheel events if the scroller is active - case QEvent::Wheel: - if (d->macIgnoreWheel || (scroller->state() != QScroller::Inactive)) - return Ignore | ConsumeEventHint; - break; - - // consume all dbl click events if the scroller is active - case QEvent::MouseButtonDblClick: - if (scroller->state() != QScroller::Inactive) - return Ignore | ConsumeEventHint; - break; - - default: - break; - } - - if (!me -#ifndef QT_NO_GRAPHICSVIEW - && !gsme -#endif - && !te) // Neither mouse nor touch - return Ignore; - - // get the current pointer position in local coordinates. - QPointF point; - QScroller::Input inputType = (QScroller::Input) 0; - - switch (event->type()) { - case QEvent::MouseButtonPress: - if (me && me->button() == button && me->buttons() == button) { - point = me->globalPos(); - inputType = QScroller::InputPress; - } else if (me) { - scroller->stop(); - return CancelGesture; - } - break; - case QEvent::MouseButtonRelease: - if (me && me->button() == button) { - point = me->globalPos(); - inputType = QScroller::InputRelease; - } - break; - case QEvent::MouseMove: -#ifdef Q_OS_SYMBIAN - // Qt on Symbian tracks the button state internally, while Qt on Win/Mac/Unix - // relies on the windowing system to report the current buttons state. - if (me && (me->buttons() == button || !me->buttons())) { -#else - if (me && me->buttons() == button) { -#endif - point = me->globalPos(); - inputType = QScroller::InputMove; - } - break; - -#ifndef QT_NO_GRAPHICSVIEW - case QEvent::GraphicsSceneMousePress: - if (gsme && gsme->button() == button && gsme->buttons() == button) { - point = gsme->scenePos(); - inputType = QScroller::InputPress; - } else if (gsme) { - scroller->stop(); - return CancelGesture; - } - break; - case QEvent::GraphicsSceneMouseRelease: - if (gsme && gsme->button() == button) { - point = gsme->scenePos(); - inputType = QScroller::InputRelease; - } - break; - case QEvent::GraphicsSceneMouseMove: -#ifdef Q_OS_SYMBIAN - // Qt on Symbian tracks the button state internally, while Qt on Win/Mac/Unix - // relies on the windowing system to report the current buttons state. - if (gsme && (gsme->buttons() == button || !me->buttons())) { -#else - if (gsme && gsme->buttons() == button) { -#endif - point = gsme->scenePos(); - inputType = QScroller::InputMove; - } - break; -#endif - - case QEvent::TouchBegin: - inputType = QScroller::InputPress; - // fall through - case QEvent::TouchEnd: - if (!inputType) - inputType = QScroller::InputRelease; - // fallthrough - case QEvent::TouchUpdate: - if (!inputType) - inputType = QScroller::InputMove; - - if (te->deviceType() == QTouchEvent::TouchPad) { - if (te->touchPoints().count() != 2) // 2 fingers on pad - return Ignore; - - point = te->touchPoints().at(0).startScenePos() + - ((te->touchPoints().at(0).scenePos() - te->touchPoints().at(0).startScenePos()) + - (te->touchPoints().at(1).scenePos() - te->touchPoints().at(1).startScenePos())) / 2; - } else { // TouchScreen - if (te->touchPoints().count() != 1) // 1 finger on screen - return Ignore; - - point = te->touchPoints().at(0).scenePos(); - } - break; - - default: - break; - } - - // Check for an active scroller at globalPos - if (inputType == QScroller::InputPress) { - foreach (QScroller *as, QScroller::activeScrollers()) { - if (as != scroller) { - QRegion scrollerRegion; - - if (QWidget *w = qobject_cast<QWidget *>(as->target())) { - scrollerRegion = QRect(w->mapToGlobal(QPoint(0, 0)), w->size()); -#ifndef QT_NO_GRAPHICSVIEW - } else if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(as->target())) { - if (go->scene() && !go->scene()->views().isEmpty()) { - foreach (QGraphicsView *gv, go->scene()->views()) - scrollerRegion |= gv->mapFromScene(go->mapToScene(go->boundingRect())) - .translated(gv->mapToGlobal(QPoint(0, 0))); - } -#endif - } - // active scrollers always have priority - if (scrollerRegion.contains(globalPos)) - return Ignore; - } - } - } - - bool scrollerWasDragging = (scroller->state() == QScroller::Dragging); - bool scrollerWasScrolling = (scroller->state() == QScroller::Scrolling); - - if (inputType) { - if (QWidget *w = qobject_cast<QWidget *>(d->receiver)) - point = w->mapFromGlobal(point.toPoint()); -#ifndef QT_NO_GRAPHICSVIEW - else if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(d->receiver)) - point = go->mapFromScene(point); -#endif - - // inform the scroller about the new event - scroller->handleInput(inputType, point, monotonicTimer.elapsed()); - } - - // depending on the scroller state return the gesture state - Result result(0); - bool scrollerIsActive = (scroller->state() == QScroller::Dragging || - scroller->state() == QScroller::Scrolling); - - // Consume all mouse events while dragging or scrolling to avoid nasty - // side effects with Qt's standard widgets. - if ((me -#ifndef QT_NO_GRAPHICSVIEW - || gsme -#endif - ) && scrollerIsActive) - result |= ConsumeEventHint; - - // The only problem with this approach is that we consume the - // MouseRelease when we start the scrolling with a flick gesture, so we - // have to fake a MouseRelease "somewhere" to not mess with the internal - // states of Qt's widgets (a QPushButton would stay in 'pressed' state - // forever, if it doesn't receive a MouseRelease). - if (me -#ifndef QT_NO_GRAPHICSVIEW - || gsme -#endif - ) { - if (!scrollerWasDragging && !scrollerWasScrolling && scrollerIsActive) - PressDelayHandler::instance()->scrollerBecameActive(); - else if (scrollerWasScrolling && (scroller->state() == QScroller::Dragging || scroller->state() == QScroller::Inactive)) - PressDelayHandler::instance()->scrollerWasIntercepted(); - } - - if (!inputType) { - result |= Ignore; - } else { - switch (event->type()) { - case QEvent::MouseButtonPress: -#ifndef QT_NO_GRAPHICSVIEW - case QEvent::GraphicsSceneMousePress: -#endif - if (scroller->state() == QScroller::Pressed) { - int pressDelay = int(1000 * scroller->scrollerProperties().scrollMetric(QScrollerProperties::MousePressEventDelay).toReal()); - if (pressDelay > 0) { - result |= ConsumeEventHint; - - PressDelayHandler::instance()->pressed(event, pressDelay); - event->accept(); - } - } - // fall through - case QEvent::TouchBegin: - q->setHotSpot(globalPos); - result |= scrollerIsActive ? TriggerGesture : MayBeGesture; - break; - - case QEvent::MouseMove: -#ifndef QT_NO_GRAPHICSVIEW - case QEvent::GraphicsSceneMouseMove: -#endif - if (PressDelayHandler::instance()->isDelaying()) - result |= ConsumeEventHint; - // fall through - case QEvent::TouchUpdate: - result |= scrollerIsActive ? TriggerGesture : Ignore; - break; - -#ifndef QT_NO_GRAPHICSVIEW - case QEvent::GraphicsSceneMouseRelease: -#endif - case QEvent::MouseButtonRelease: - if (PressDelayHandler::instance()->released(event, scrollerWasDragging || scrollerWasScrolling, scrollerIsActive)) - result |= ConsumeEventHint; - // fall through - case QEvent::TouchEnd: - result |= scrollerIsActive ? FinishGesture : CancelGesture; - break; - - default: - result |= Ignore; - break; - } - } - return result; -} - - -/*! \reimp - */ -void QFlickGestureRecognizer::reset(QGesture *state) -{ - QGestureRecognizer::reset(state); -} - -QT_END_NAMESPACE - -#endif // QT_NO_GESTURES diff --git a/src/gui/util/qflickgesture_p.h b/src/gui/util/qflickgesture_p.h deleted file mode 100644 index e095cf5eab..0000000000 --- a/src/gui/util/qflickgesture_p.h +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFLICKGESTURE_P_H -#define QFLICKGESTURE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qevent.h" -#include "qgesturerecognizer.h" -#include "private/qgesture_p.h" -#include "qscroller.h" -#include "qscopedpointer.h" - -#ifndef QT_NO_GESTURES - -QT_BEGIN_NAMESPACE - -class QFlickGesturePrivate; -class QGraphicsItem; - -class Q_GUI_EXPORT QFlickGesture : public QGesture -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QFlickGesture) - -public: - QFlickGesture(QObject *receiver, Qt::MouseButton button, QObject *parent = 0); - ~QFlickGesture(); - - friend class QFlickGestureRecognizer; -}; - -class PressDelayHandler; - -class QFlickGesturePrivate : public QGesturePrivate -{ - Q_DECLARE_PUBLIC(QFlickGesture) -public: - QFlickGesturePrivate(); - - QPointer<QObject> receiver; - QScroller *receiverScroller; - Qt::MouseButton button; // NoButton == Touch - bool macIgnoreWheel; - static PressDelayHandler *pressDelayHandler; -}; - -class QFlickGestureRecognizer : public QGestureRecognizer -{ -public: - QFlickGestureRecognizer(Qt::MouseButton button); - - QGesture *create(QObject *target); - QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); - void reset(QGesture *state); - -private: - Qt::MouseButton button; // NoButton == Touch -}; - -QT_END_NAMESPACE - -#endif // QT_NO_GESTURES - -#endif // QFLICKGESTURE_P_H diff --git a/src/gui/util/qhexstring_p.h b/src/gui/util/qhexstring_p.h new file mode 100644 index 0000000000..3c8d562756 --- /dev/null +++ b/src/gui/util/qhexstring_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qglobal.h> +#include <QtCore/qpoint.h> +#include <QtCore/qstring.h> +#include <QtGui/qpolygon.h> +#include <QtCore/qstringbuilder.h> + +#ifndef QHEXSTRING_P_H +#define QHEXSTRING_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +// internal helper. Converts an integer value to an unique string token +template <typename T> + struct HexString +{ + inline HexString(const T t) + : val(t) + {} + + inline void write(QChar *&dest) const + { + const ushort hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + const char *c = reinterpret_cast<const char *>(&val); + for (uint i = 0; i < sizeof(T); ++i) { + *dest++ = hexChars[*c & 0xf]; + *dest++ = hexChars[(*c & 0xf0) >> 4]; + ++c; + } + } + const T val; +}; + +// specialization to enable fast concatenating of our string tokens to a string +template <typename T> + struct QConcatenable<HexString<T> > +{ + typedef HexString<T> type; + enum { ExactSize = true }; + static int size(const HexString<T> &) { return sizeof(T) * 2; } + static inline void appendTo(const HexString<T> &str, QChar *&out) { str.write(out); } + typedef QString ConvertTo; +}; + +QT_END_NAMESPACE + +#endif // QHEXSTRING_P_H diff --git a/src/gui/util/qscroller.cpp b/src/gui/util/qscroller.cpp deleted file mode 100644 index 7ad726228d..0000000000 --- a/src/gui/util/qscroller.cpp +++ /dev/null @@ -1,2056 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qevent.h" -#include "qwidget.h" -#include "qscroller.h" -#include "private/qflickgesture_p.h" -#include "private/qscroller_p.h" -#include "qscrollerproperties.h" -#include "private/qscrollerproperties_p.h" -#include "qnumeric.h" -#include "math.h" - -#include <QTime> -#include <QElapsedTimer> -#include <QMap> -#include <QApplication> -#include <QAbstractScrollArea> -#include <QGraphicsObject> -#include <QGraphicsScene> -#include <QGraphicsView> -#include <QDesktopWidget> -#include <QtCore/qmath.h> -#include <QtGui/qevent.h> -#include <qnumeric.h> - -#include <QtDebug> - -#if defined(Q_WS_X11) -# include "private/qt_x11_p.h" -#endif - - -QT_BEGIN_NAMESPACE - -bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); - -//#define QSCROLLER_DEBUG - -#ifdef QSCROLLER_DEBUG -# define qScrollerDebug qDebug -#else -# define qScrollerDebug while (false) qDebug -#endif - -QDebug &operator<<(QDebug &dbg, const QScrollerPrivate::ScrollSegment &s) -{ - dbg << "\n Time: start:" << s.startTime << " duration:" << s.deltaTime << " stop progress:" << s.stopProgress; - dbg << "\n Pos: start:" << s.startPos << " delta:" << s.deltaPos << " stop:" << s.stopPos; - dbg << "\n Curve: type:" << s.curve.type() << "\n"; - return dbg; -} - - -// a few helper operators to make the code below a lot more readable: -// otherwise a lot of ifs would have to be multi-line to check both the x -// and y coordinate separately. - -// returns true only if the abs. value of BOTH x and y are <= f -inline bool operator<=(const QPointF &p, qreal f) -{ - return (qAbs(p.x()) <= f) && (qAbs(p.y()) <= f); -} - -// returns true only if the abs. value of BOTH x and y are < f -inline bool operator<(const QPointF &p, qreal f) -{ - return (qAbs(p.x()) < f) && (qAbs(p.y()) < f); -} - -// returns true if the abs. value of EITHER x or y are >= f -inline bool operator>=(const QPointF &p, qreal f) -{ - return (qAbs(p.x()) >= f) || (qAbs(p.y()) >= f); -} - -// returns true if the abs. value of EITHER x or y are > f -inline bool operator>(const QPointF &p, qreal f) -{ - return (qAbs(p.x()) > f) || (qAbs(p.y()) > f); -} - -// returns a new point with both coordinates having the abs. value of the original one -inline QPointF qAbs(const QPointF &p) -{ - return QPointF(qAbs(p.x()), qAbs(p.y())); -} - -// returns a new point with all components of p1 multiplied by the corresponding components of p2 -inline QPointF operator*(const QPointF &p1, const QPointF &p2) -{ - return QPointF(p1.x() * p2.x(), p1.y() * p2.y()); -} - -// returns a new point with all components of p1 divided by the corresponding components of p2 -inline QPointF operator/(const QPointF &p1, const QPointF &p2) -{ - return QPointF(p1.x() / p2.x(), p1.y() / p2.y()); -} - -inline QPointF clampToRect(const QPointF &p, const QRectF &rect) -{ - qreal x = qBound(rect.left(), p.x(), rect.right()); - qreal y = qBound(rect.top(), p.y(), rect.bottom()); - return QPointF(x, y); -} - -// returns -1, 0 or +1 according to r being <0, ==0 or >0 -inline int qSign(qreal r) -{ - return (r < 0) ? -1 : ((r > 0) ? 1 : 0); -} - -// this version is not mathematically exact, but it just works for every -// easing curve type (even custom ones) - -static qreal differentialForProgress(const QEasingCurve &curve, qreal pos) -{ - const qreal dx = 0.01; - qreal left = (pos < qreal(0.5)) ? pos : pos - qreal(dx); - qreal right = (pos >= qreal(0.5)) ? pos : pos + qreal(dx); - qreal d = (curve.valueForProgress(right) - curve.valueForProgress(left)) / qreal(dx); - - //qScrollerDebug() << "differentialForProgress(type: " << curve.type() << ", pos: " << pos << ") = " << d; - - return d; -} - -// this version is not mathematically exact, but it just works for every -// easing curve type (even custom ones) - -static qreal progressForValue(const QEasingCurve &curve, qreal value) -{ - if (curve.type() >= QEasingCurve::InElastic && - curve.type() < QEasingCurve::Custom) { - qWarning("progressForValue(): QEasingCurves of type %d do not have an inverse, since they are not injective.", curve.type()); - return value; - } - if (value < qreal(0) || value > qreal(1)) - return value; - - qreal progress = value, left(0), right(1); - for (int iterations = 6; iterations; --iterations) { - qreal v = curve.valueForProgress(progress); - if (v < value) - left = progress; - else if (v > value) - right = progress; - else - break; - progress = (left + right) / qreal(2); - } - return progress; -} - - -#ifndef QT_NO_ANIMATION -class QScrollTimer : public QAbstractAnimation -{ -public: - QScrollTimer(QScrollerPrivate *_d) - : d(_d), ignoreUpdate(false), skip(0) - { } - - int duration() const - { - return -1; - } - - void start() - { - // QAbstractAnimation::start() will immediately call - // updateCurrentTime(), but our state is not set correctly yet - ignoreUpdate = true; - QAbstractAnimation::start(); - ignoreUpdate = false; - skip = 0; - } - -protected: - void updateCurrentTime(int /*currentTime*/) - { - if (!ignoreUpdate) { - if (++skip >= d->frameRateSkip()) { - skip = 0; - d->timerTick(); - } - } - } - -private: - QScrollerPrivate *d; - bool ignoreUpdate; - int skip; -}; -#endif // QT_NO_ANIMATION - -/*! - \class QScroller - \brief The QScroller class enables kinetic scrolling for any scrolling widget or graphics item. - \since 4.8 - - With kinetic scrolling, the user can push the widget in a given - direction and it will continue to scroll in this direction until it is - stopped either by the user or by friction. Aspects of inertia, friction - and other physical concepts can be changed in order to fine-tune an - intuitive user experience. - - The QScroller object is the object that stores the current position and - scrolling speed and takes care of updates. - QScroller can be triggered by a flick gesture - - \code - QWidget *w = ...; - QScroller::grabGesture(w, QScroller::LeftMouseButtonGesture); - \endcode - - or directly like this: - - \code - QWidget *w = ...; - QScroller *scroller = QScroller::scroller(w); - scroller->scrollTo(QPointF(100, 100)); - \endcode - - The scrolled QObjects receive a QScrollPrepareEvent whenever the scroller needs to - update its geometry information and a QScrollEvent whenever the content of the object should - actually be scrolled. - - The scroller uses the global QAbstractAnimation timer to generate its QScrollEvents. This - can be changed with QScrollerProperties::FrameRate on a per-QScroller basis. - - Several examples in the \c scroller examples directory show how QScroller, - QScrollEvent and the scroller gesture can be used. - - Even though this kinetic scroller has a large number of settings available via - QScrollerProperties, we recommend that you leave them all at their default, platform optimized - values. Before changing them you can experiment with the \c plot example in - the \c scroller examples directory. - - \sa QScrollEvent, QScrollPrepareEvent, QScrollerProperties -*/ - -typedef QMap<QObject *, QScroller *> ScrollerHash; -typedef QSet<QScroller *> ScrollerSet; - -Q_GLOBAL_STATIC(ScrollerHash, qt_allScrollers) -Q_GLOBAL_STATIC(ScrollerSet, qt_activeScrollers) - -/*! - Returns \c true if a QScroller object was already created for \a target; \c false otherwise. - - \sa scroller() -*/ -bool QScroller::hasScroller(QObject *target) -{ - return (qt_allScrollers()->value(target)); -} - -/*! - Returns the scroller for the given \a target. - As long as the object exists this function will always return the same QScroller instance. - If no QScroller exists for the \a target, one will implicitly be created. - At no point more than one QScroller will be active on an object. - - \sa hasScroller(), target() -*/ -QScroller *QScroller::scroller(QObject *target) -{ - if (!target) { - qWarning("QScroller::scroller() was called with a null target."); - return 0; - } - - if (qt_allScrollers()->contains(target)) - return qt_allScrollers()->value(target); - - QScroller *s = new QScroller(target); - qt_allScrollers()->insert(target, s); - return s; -} - -/*! - \overload - This is the const version of scroller(). -*/ -const QScroller *QScroller::scroller(const QObject *target) -{ - return scroller(const_cast<QObject*>(target)); -} - -/*! - Returns an application wide list of currently active QScroller objects. - Active QScroller objects are in a state() that is not QScroller::Inactive. - This function is useful when writing your own gesture recognizer. -*/ -QList<QScroller *> QScroller::activeScrollers() -{ - return qt_activeScrollers()->toList(); -} - -/*! - Returns the target object of this scroller. - \sa hasScroller(), scroller() - */ -QObject *QScroller::target() const -{ - Q_D(const QScroller); - return d->target; -} - -/*! - \fn QScroller::scrollerPropertiesChanged(const QScrollerProperties &newProperties); - - QScroller emits this signal whenever its scroller properties change. - \a newProperties are the new scroller properties. - - \sa scrollerProperties -*/ - - -/*! \property QScroller::scrollerProperties - \brief The scroller properties of this scroller. - The properties are used by the QScroller to determine its scrolling behavior. -*/ -QScrollerProperties QScroller::scrollerProperties() const -{ - Q_D(const QScroller); - return d->properties; -} - -void QScroller::setScrollerProperties(const QScrollerProperties &sp) -{ - Q_D(QScroller); - if (d->properties != sp) { - d->properties = sp; - emit scrollerPropertiesChanged(sp); - - // we need to force the recalculation here, since the overshootPolicy may have changed and - // existing segments may include an overshoot animation. - d->recalcScrollingSegments(true); - } -} - -#ifndef QT_NO_GESTURES - -/*! - Registers a custom scroll gesture recognizer, grabs it for the \a - target and returns the resulting gesture type. If \a scrollGestureType is - set to TouchGesture the gesture triggers on touch events. If it is set to - one of LeftMouseButtonGesture, RightMouseButtonGesture or - MiddleMouseButtonGesture it triggers on mouse events of the - corresponding button. - - Only one scroll gesture can be active on a single object at the same - time. If you call this function twice on the same object, it will - ungrab the existing gesture before grabbing the new one. - - \note To avoid unwanted side-effects, mouse events are consumed while - the gesture is triggered. Since the initial mouse press event is - not consumed, the gesture sends a fake mouse release event - at the global position \c{(INT_MIN, INT_MIN)}. This ensures that - internal states of the widget that received the original mouse press - are consistent. - - \sa ungrabGesture(), grabbedGesture() -*/ -Qt::GestureType QScroller::grabGesture(QObject *target, ScrollerGestureType scrollGestureType) -{ - // ensure that a scroller for target is created - QScroller *s = scroller(target); - if (!s) - return Qt::GestureType(0); - - QScrollerPrivate *sp = s->d_ptr; - if (sp->recognizer) - ungrabGesture(target); // ungrab the old gesture - - Qt::MouseButton button; - switch (scrollGestureType) { - case LeftMouseButtonGesture : button = Qt::LeftButton; break; - case RightMouseButtonGesture : button = Qt::RightButton; break; - case MiddleMouseButtonGesture: button = Qt::MiddleButton; break; - default : - case TouchGesture : button = Qt::NoButton; break; // NoButton == Touch - } - - sp->recognizer = new QFlickGestureRecognizer(button); - sp->recognizerType = QGestureRecognizer::registerRecognizer(sp->recognizer); - - if (target->isWidgetType()) { - QWidget *widget = static_cast<QWidget *>(target); - widget->grabGesture(sp->recognizerType); - if (scrollGestureType == TouchGesture) - widget->setAttribute(Qt::WA_AcceptTouchEvents); -#ifndef QT_NO_GRAPHICSVIEW - } else if (QGraphicsObject *go = qobject_cast<QGraphicsObject*>(target)) { - if (scrollGestureType == TouchGesture) - go->setAcceptTouchEvents(true); - go->grabGesture(sp->recognizerType); -#endif // QT_NO_GRAPHICSVIEW - } - return sp->recognizerType; -} - -/*! - Returns the gesture type currently grabbed for the \a target or 0 if no - gesture is grabbed. - - \sa grabGesture(), ungrabGesture() -*/ -Qt::GestureType QScroller::grabbedGesture(QObject *target) -{ - QScroller *s = scroller(target); - if (s && s->d_ptr) - return s->d_ptr->recognizerType; - else - return Qt::GestureType(0); -} - -/*! - Ungrabs the gesture for the \a target. - Does nothing if no gesture is grabbed. - - \sa grabGesture(), grabbedGesture() -*/ -void QScroller::ungrabGesture(QObject *target) -{ - QScroller *s = scroller(target); - if (!s) - return; - - QScrollerPrivate *sp = s->d_ptr; - if (!sp->recognizer) - return; // nothing to do - - if (target->isWidgetType()) { - QWidget *widget = static_cast<QWidget *>(target); - widget->ungrabGesture(sp->recognizerType); -#ifndef QT_NO_GRAPHICSVIEW - } else if (QGraphicsObject *go = qobject_cast<QGraphicsObject*>(target)) { - go->ungrabGesture(sp->recognizerType); -#endif - } - - QGestureRecognizer::unregisterRecognizer(sp->recognizerType); - // do not delete the recognizer. The QGestureManager is doing this. - sp->recognizer = 0; -} - -#endif // QT_NO_GESTURES - -/*! - \internal -*/ -QScroller::QScroller(QObject *target) - : d_ptr(new QScrollerPrivate(this, target)) -{ - Q_ASSERT(target); // you can't create a scroller without a target in any normal way - Q_D(QScroller); - d->init(); -} - -/*! - \internal -*/ -QScroller::~QScroller() -{ - Q_D(QScroller); -#ifndef QT_NO_GESTURES - QGestureRecognizer::unregisterRecognizer(d->recognizerType); - // do not delete the recognizer. The QGestureManager is doing this. - d->recognizer = 0; -#endif - qt_allScrollers()->remove(d->target); - qt_activeScrollers()->remove(this); - - delete d_ptr; -} - - -/*! - \fn QScroller::stateChanged(QScroller::State newState); - - QScroller emits this signal whenever the state changes. \a newState is the new State. - - \sa state -*/ - -/*! - \property QScroller::state - \brief the state of the scroller - - \sa QScroller::State -*/ -QScroller::State QScroller::state() const -{ - Q_D(const QScroller); - return d->state; -} - -/*! - Stops the scroller and resets its state back to Inactive. -*/ -void QScroller::stop() -{ - Q_D(QScroller); - if (d->state != Inactive) { - QPointF here = clampToRect(d->contentPosition, d->contentPosRange); - qreal snapX = d->nextSnapPos(here.x(), 0, Qt::Horizontal); - qreal snapY = d->nextSnapPos(here.y(), 0, Qt::Vertical); - QPointF snap = here; - if (!qIsNaN(snapX)) - snap.setX(snapX); - if (!qIsNaN(snapY)) - snap.setY(snapY); - d->contentPosition = snap; - d->overshootPosition = QPointF(0, 0); - - d->setState(Inactive); - } -} - -/*! - Returns the pixel per meter metric for the scrolled widget. - - The value is reported for both the x and y axis separately by using a QPointF. - - \note Please note that this value should be physically correct. The actual DPI settings - that Qt returns for the display may be reported wrongly on purpose by the underlying - windowing system, for example on Mac OS X or Maemo 5. -*/ -QPointF QScroller::pixelPerMeter() const -{ - Q_D(const QScroller); - QPointF ppm = d->pixelPerMeter; - -#ifndef QT_NO_GRAPHICSVIEW - if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(d->target)) { - QTransform viewtr; - //TODO: the first view isn't really correct - maybe use an additional field in the prepare event? - if (go->scene() && !go->scene()->views().isEmpty()) - viewtr = go->scene()->views().first()->viewportTransform(); - QTransform tr = go->deviceTransform(viewtr); - if (tr.isScaling()) { - QPointF p0 = tr.map(QPointF(0, 0)); - QPointF px = tr.map(QPointF(1, 0)); - QPointF py = tr.map(QPointF(0, 1)); - ppm.rx() /= QLineF(p0, px).length(); - ppm.ry() /= QLineF(p0, py).length(); - } - } -#endif // QT_NO_GRAPHICSVIEW - return ppm; -} - -/*! - Returns the current scrolling velocity in meter per second when the state is Scrolling or Dragging. - Returns a zero velocity otherwise. - - The velocity is reported for both the x and y axis separately by using a QPointF. - - \sa pixelPerMeter() -*/ -QPointF QScroller::velocity() const -{ - Q_D(const QScroller); - const QScrollerPropertiesPrivate *sp = d->properties.d.data(); - - switch (state()) { - case Dragging: - return d->releaseVelocity; - case Scrolling: { - QPointF vel; - qint64 now = d->monotonicTimer.elapsed(); - - if (!d->xSegments.isEmpty()) { - const QScrollerPrivate::ScrollSegment &s = d->xSegments.head(); - qreal progress = qreal(now - s.startTime) / qreal(s.deltaTime); - qreal v = qSign(s.deltaPos) * qreal(s.deltaTime) / qreal(1000) * sp->decelerationFactor * qreal(0.5) * differentialForProgress(s.curve, progress); - vel.setX(v); - } - - if (!d->ySegments.isEmpty()) { - const QScrollerPrivate::ScrollSegment &s = d->ySegments.head(); - qreal progress = qreal(now - s.startTime) / qreal(s.deltaTime); - qreal v = qSign(s.deltaPos) * qreal(s.deltaTime) / qreal(1000) * sp->decelerationFactor * qreal(0.5) * differentialForProgress(s.curve, progress); - vel.setY(v); - } - return vel; - } - default: - return QPointF(0, 0); - } -} - -/*! - Returns the estimated final position for the current scroll movement. - Returns the current position if the scroller state is not Scrolling. - The result is undefined when the scroller state is Inactive. - - The target position is in pixel. - - \sa pixelPerMeter(), scrollTo() -*/ -QPointF QScroller::finalPosition() const -{ - Q_D(const QScroller); - return QPointF(d->scrollingSegmentsEndPos(Qt::Horizontal), - d->scrollingSegmentsEndPos(Qt::Vertical)); -} - -/*! - Starts scrolling the widget so that point \a pos is at the top-left position in - the viewport. - - The behaviour when scrolling outside the valid scroll area is undefined. - In this case the scroller might or might not overshoot. - - The scrolling speed will be calculated so that the given position will - be reached after a platform-defined time span. - - \a pos is given in viewport coordinates. - - \sa ensureVisible() -*/ -void QScroller::scrollTo(const QPointF &pos) -{ - // we could make this adjustable via QScrollerProperties - scrollTo(pos, 300); -} - -/*! \overload - - This version will reach its destination position in \a scrollTime milliseconds. -*/ -void QScroller::scrollTo(const QPointF &pos, int scrollTime) -{ - Q_D(QScroller); - - if (d->state == Pressed || d->state == Dragging ) - return; - - // no need to resend a prepare event if we are already scrolling - if (d->state == Inactive && !d->prepareScrolling(QPointF())) - return; - - QPointF newpos = clampToRect(pos, d->contentPosRange); - qreal snapX = d->nextSnapPos(newpos.x(), 0, Qt::Horizontal); - qreal snapY = d->nextSnapPos(newpos.y(), 0, Qt::Vertical); - if (!qIsNaN(snapX)) - newpos.setX(snapX); - if (!qIsNaN(snapY)) - newpos.setY(snapY); - - qScrollerDebug() << "QScroller::scrollTo(req:" << pos << " [pix] / snap:" << newpos << ", " << scrollTime << " [ms])"; - - if (newpos == d->contentPosition + d->overshootPosition) - return; - - QPointF vel = velocity(); - - if (scrollTime < 0) - scrollTime = 0; - qreal time = qreal(scrollTime) / 1000; - - d->createScrollToSegments(vel.x(), time, newpos.x(), Qt::Horizontal, QScrollerPrivate::ScrollTypeScrollTo); - d->createScrollToSegments(vel.y(), time, newpos.y(), Qt::Vertical, QScrollerPrivate::ScrollTypeScrollTo); - - if (!scrollTime) - d->setContentPositionHelperScrolling(); - d->setState(scrollTime ? Scrolling : Inactive); -} - -/*! - Starts scrolling so that the rectangle \a rect is visible inside the - viewport with additional margins specified in pixels by \a xmargin and \a ymargin around - the rect. - - In cases where it is not possible to fit the rect plus margins inside the viewport the contents - are scrolled so that as much as possible is visible from \a rect. - - The scrolling speed is calculated so that the given position is reached after a platform-defined - time span. - - This function performs the actual scrolling by calling scrollTo(). - - \sa scrollTo() -*/ -void QScroller::ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin) -{ - // we could make this adjustable via QScrollerProperties - ensureVisible(rect, xmargin, ymargin, 1000); -} - -/*! \overload - - This version will reach its destination position in \a scrollTime milliseconds. -*/ -void QScroller::ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin, int scrollTime) -{ - Q_D(QScroller); - - if (d->state == Pressed || d->state == Dragging ) - return; - - if (d->state == Inactive && !d->prepareScrolling(QPointF())) - return; - - // -- calculate the current pos (or the position after the current scroll) - QPointF startPos = d->contentPosition + d->overshootPosition; - startPos = QPointF(d->scrollingSegmentsEndPos(Qt::Horizontal), - d->scrollingSegmentsEndPos(Qt::Vertical)); - - QRectF marginRect(rect.x() - xmargin, rect.y() - ymargin, - rect.width() + 2 * xmargin, rect.height() + 2 * ymargin); - - QSizeF visible = d->viewportSize; - QRectF visibleRect(startPos, visible); - - qScrollerDebug() << "QScroller::ensureVisible(" << rect << " [pix], " << xmargin << " [pix], " << ymargin << " [pix], " << scrollTime << "[ms])"; - qScrollerDebug() << " --> content position:" << d->contentPosition; - - if (visibleRect.contains(marginRect)) - return; - - QPointF newPos = startPos; - - if (visibleRect.width() < rect.width()) { - // at least try to move the rect into view - if (rect.left() > visibleRect.left()) - newPos.setX(rect.left()); - else if (rect.right() < visibleRect.right()) - newPos.setX(rect.right() - visible.width()); - - } else if (visibleRect.width() < marginRect.width()) { - newPos.setX(rect.center().x() - visibleRect.width() / 2); - } else if (marginRect.left() > visibleRect.left()) { - newPos.setX(marginRect.left()); - } else if (marginRect.right() < visibleRect.right()) { - newPos.setX(marginRect.right() - visible.width()); - } - - if (visibleRect.height() < rect.height()) { - // at least try to move the rect into view - if (rect.top() > visibleRect.top()) - newPos.setX(rect.top()); - else if (rect.bottom() < visibleRect.bottom()) - newPos.setX(rect.bottom() - visible.height()); - - } else if (visibleRect.height() < marginRect.height()) { - newPos.setY(rect.center().y() - visibleRect.height() / 2); - } else if (marginRect.top() > visibleRect.top()) { - newPos.setY(marginRect.top()); - } else if (marginRect.bottom() < visibleRect.bottom()) { - newPos.setY(marginRect.bottom() - visible.height()); - } - - // clamp to maximum content position - newPos = clampToRect(newPos, d->contentPosRange); - if (newPos == startPos) - return; - - scrollTo(newPos, scrollTime); -} - -/*! This function resends the QScrollPrepareEvent. - Calling resendPrepareEvent triggers a QScrollPrepareEvent from the scroller. - This allows the receiver to re-set content position and content size while - scrolling. - Calling this function while in the Inactive state is useless as the prepare event - is sent again before scrolling starts. - */ -void QScroller::resendPrepareEvent() -{ - Q_D(QScroller); - d->prepareScrolling(d->pressPosition); -} - -/*! Set the snap positions for the horizontal axis to a list of \a positions. - This overwrites all previously set snap positions and also a previously - set snapping interval. - Snapping can be deactivated by setting an empty list of positions. - */ -void QScroller::setSnapPositionsX(const QList<qreal> &positions) -{ - Q_D(QScroller); - d->snapPositionsX = positions; - d->snapIntervalX = 0.0; - - d->recalcScrollingSegments(); -} - -/*! Set the snap positions for the horizontal axis to regular spaced intervals. - The first snap position is at \a first. The next at \a first + \a interval. - This can be used to implement a list header. - This overwrites all previously set snap positions and also a previously - set snapping interval. - Snapping can be deactivated by setting an interval of 0.0 - */ -void QScroller::setSnapPositionsX(qreal first, qreal interval) -{ - Q_D(QScroller); - d->snapFirstX = first; - d->snapIntervalX = interval; - d->snapPositionsX.clear(); - - d->recalcScrollingSegments(); -} - -/*! Set the snap positions for the vertical axis to a list of \a positions. - This overwrites all previously set snap positions and also a previously - set snapping interval. - Snapping can be deactivated by setting an empty list of positions. - */ -void QScroller::setSnapPositionsY(const QList<qreal> &positions) -{ - Q_D(QScroller); - d->snapPositionsY = positions; - d->snapIntervalY = 0.0; - - d->recalcScrollingSegments(); -} - -/*! Set the snap positions for the vertical axis to regular spaced intervals. - The first snap position is at \a first. The next at \a first + \a interval. - This overwrites all previously set snap positions and also a previously - set snapping interval. - Snapping can be deactivated by setting an interval of 0.0 - */ -void QScroller::setSnapPositionsY(qreal first, qreal interval) -{ - Q_D(QScroller); - d->snapFirstY = first; - d->snapIntervalY = interval; - d->snapPositionsY.clear(); - - d->recalcScrollingSegments(); -} - - - -// -------------- private ------------ - -QScrollerPrivate::QScrollerPrivate(QScroller *q, QObject *_target) - : target(_target) -#ifndef QT_NO_GESTURES - , recognizer(0) - , recognizerType(Qt::CustomGesture) -#endif - , state(QScroller::Inactive) - , firstScroll(true) - , pressTimestamp(0) - , lastTimestamp(0) - , snapFirstX(-1.0) - , snapIntervalX(0.0) - , snapFirstY(-1.0) - , snapIntervalY(0.0) -#ifndef QT_NO_ANIMATION - , scrollTimer(new QScrollTimer(this)) -#endif - , q_ptr(q) -{ - connect(target, SIGNAL(destroyed(QObject*)), this, SLOT(targetDestroyed())); -} - -void QScrollerPrivate::init() -{ - setDpiFromWidget(0); - monotonicTimer.start(); -} - -void QScrollerPrivate::sendEvent(QObject *o, QEvent *e) -{ - qt_sendSpontaneousEvent(o, e); -} - -const char *QScrollerPrivate::stateName(QScroller::State state) -{ - switch (state) { - case QScroller::Inactive: return "inactive"; - case QScroller::Pressed: return "pressed"; - case QScroller::Dragging: return "dragging"; - case QScroller::Scrolling: return "scrolling"; - default: return "(invalid)"; - } -} - -const char *QScrollerPrivate::inputName(QScroller::Input input) -{ - switch (input) { - case QScroller::InputPress: return "press"; - case QScroller::InputMove: return "move"; - case QScroller::InputRelease: return "release"; - default: return "(invalid)"; - } -} - -void QScrollerPrivate::targetDestroyed() -{ -#ifndef QT_NO_ANIMATION - scrollTimer->stop(); -#endif - delete q_ptr; -} - -void QScrollerPrivate::timerTick() -{ - struct timerevent { - QScroller::State state; - typedef void (QScrollerPrivate::*timerhandler_t)(); - timerhandler_t handler; - }; - - timerevent timerevents[] = { - { QScroller::Dragging, &QScrollerPrivate::timerEventWhileDragging }, - { QScroller::Scrolling, &QScrollerPrivate::timerEventWhileScrolling }, - }; - - for (int i = 0; i < int(sizeof(timerevents) / sizeof(*timerevents)); ++i) { - timerevent *te = timerevents + i; - - if (state == te->state) { - (this->*te->handler)(); - return; - } - } - -#ifndef QT_NO_ANIMATION - scrollTimer->stop(); -#endif -} - -/*! - This function is used by gesture recognizers to inform the scroller about a new input event. - The scroller changes its internal state() according to the input event and its attached - scroller properties. The scroller doesn't distinguish between the kind of input device the - event came from. Therefore the event needs to be split into the \a input type, a \a position and a - milli-second \a timestamp. The \a position needs to be in the target's coordinate system. - - The return value is \c true if the event should be consumed by the calling filter or \c false - if the event should be forwarded to the control. - - \note Using grabGesture() should be sufficient for most use cases. -*/ -bool QScroller::handleInput(Input input, const QPointF &position, qint64 timestamp) -{ - Q_D(QScroller); - - qScrollerDebug() << "QScroller::handleInput(" << input << ", " << d->stateName(d->state) << ", " << position << ", " << timestamp << ")"; - struct statechange { - State state; - Input input; - typedef bool (QScrollerPrivate::*inputhandler_t)(const QPointF &position, qint64 timestamp); - inputhandler_t handler; - }; - - statechange statechanges[] = { - { QScroller::Inactive, InputPress, &QScrollerPrivate::pressWhileInactive }, - { QScroller::Pressed, InputMove, &QScrollerPrivate::moveWhilePressed }, - { QScroller::Pressed, InputRelease, &QScrollerPrivate::releaseWhilePressed }, - { QScroller::Dragging, InputMove, &QScrollerPrivate::moveWhileDragging }, - { QScroller::Dragging, InputRelease, &QScrollerPrivate::releaseWhileDragging }, - { QScroller::Scrolling, InputPress, &QScrollerPrivate::pressWhileScrolling } - }; - - for (int i = 0; i < int(sizeof(statechanges) / sizeof(*statechanges)); ++i) { - statechange *sc = statechanges + i; - - if (d->state == sc->state && input == sc->input) - return (d->*sc->handler)(position - d->overshootPosition, timestamp); - } - return false; -} - -#if !defined(Q_WS_MAC) -// the Mac version is implemented in qscroller_mac.mm - -QPointF QScrollerPrivate::realDpi(int screen) -{ -# ifdef Q_WS_MAEMO_5 - Q_UNUSED(screen); - - // The DPI value is hardcoded to 96 on Maemo5: - // https://projects.maemo.org/bugzilla/show_bug.cgi?id=152525 - // This value (260) is only correct for the N900 though, but - // there's no way to get the real DPI at run time. - return QPointF(260, 260); - -# elif defined(Q_WS_X11) && !defined(QT_NO_XRANDR) - if (X11 && X11->use_xrandr && X11->ptrXRRSizes && X11->ptrXRRRootToScreen) { - int nsizes = 0; - // QDesktopWidget is based on Xinerama screens, which do not always - // correspond to RandR screens: NVidia's TwinView e.g. will show up - // as 2 screens in QDesktopWidget, but libXRandR will only see 1 screen. - // (although with the combined size of the Xinerama screens). - // Additionally, libXrandr will simply crash when calling XRRSizes - // for (the non-existent) screen 1 in this scenario. - Window root = RootWindow(X11->display, screen == -1 ? X11->defaultScreen : screen); - int randrscreen = (root != XNone) ? X11->ptrXRRRootToScreen(X11->display, root) : -1; - - XRRScreenSize *sizes = X11->ptrXRRSizes(X11->display, randrscreen == -1 ? 0 : randrscreen, &nsizes); - if (nsizes > 0 && sizes && sizes->width && sizes->height && sizes->mwidth && sizes->mheight) { - qScrollerDebug() << "XRandR DPI:" << QPointF(qreal(25.4) * qreal(sizes->width) / qreal(sizes->mwidth), - qreal(25.4) * qreal(sizes->height) / qreal(sizes->mheight)); - return QPointF(qreal(25.4) * qreal(sizes->width) / qreal(sizes->mwidth), - qreal(25.4) * qreal(sizes->height) / qreal(sizes->mheight)); - } - } -# endif - - QWidget *w = QApplication::desktop()->screen(screen); - return QPointF(w->physicalDpiX(), w->physicalDpiY()); -} - -#endif // !Q_WS_MAC - - -/*! \internal - Returns the resolution of the used screen. -*/ -QPointF QScrollerPrivate::dpi() const -{ - return pixelPerMeter * qreal(0.0254); -} - -/*! \internal - Sets the resolution used for scrolling. - This resolution is only used by the kinetic scroller. If you change this - then the scroller will behave quite different as a lot of the values are - given in physical distances (millimeter). -*/ -void QScrollerPrivate::setDpi(const QPointF &dpi) -{ - pixelPerMeter = dpi / qreal(0.0254); -} - -/*! \internal - Sets the dpi used for scrolling to the value of the widget. -*/ -void QScrollerPrivate::setDpiFromWidget(QWidget *widget) -{ - QDesktopWidget *dw = QApplication::desktop(); - setDpi(realDpi(widget ? dw->screenNumber(widget) : dw->primaryScreen())); -} - -/*! \internal - Updates the velocity during dragging. - Sets releaseVelocity. -*/ -void QScrollerPrivate::updateVelocity(const QPointF &deltaPixelRaw, qint64 deltaTime) -{ - if (deltaTime <= 0) - return; - - Q_Q(QScroller); - QPointF ppm = q->pixelPerMeter(); - const QScrollerPropertiesPrivate *sp = properties.d.data(); - QPointF deltaPixel = deltaPixelRaw; - - qScrollerDebug() << "QScroller::updateVelocity(" << deltaPixelRaw << " [delta pix], " << deltaTime << " [delta ms])"; - - // faster than 2.5mm/ms seems bogus (that would be a screen height in ~20 ms) - if (((deltaPixelRaw / qreal(deltaTime)).manhattanLength() / ((ppm.x() + ppm.y()) / 2) * 1000) > qreal(2.5)) - deltaPixel = deltaPixelRaw * qreal(2.5) * ppm / 1000 / (deltaPixelRaw / qreal(deltaTime)).manhattanLength(); - - QPointF newv = -deltaPixel / qreal(deltaTime) * qreal(1000) / ppm; - // around 95% of all updates are in the [1..50] ms range, so make sure - // to scale the smoothing factor over that range: this way a 50ms update - // will have full impact, while 5ms update will only have a 10% impact. - qreal smoothing = sp->dragVelocitySmoothingFactor * qMin(qreal(deltaTime), qreal(50)) / qreal(50); - - // only smooth if we already have a release velocity and only if the - // user hasn't stopped to move his finger for more than 100ms - if ((releaseVelocity != QPointF(0, 0)) && (deltaTime < 100)) { - qScrollerDebug() << "SMOOTHED from " << newv << " to " << newv * smoothing + releaseVelocity * (qreal(1) - smoothing); - // smooth x or y only if the new velocity is either 0 or at least in - // the same direction of the release velocity - if (!newv.x() || (qSign(releaseVelocity.x()) == qSign(newv.x()))) - newv.setX(newv.x() * smoothing + releaseVelocity.x() * (qreal(1) - smoothing)); - if (!newv.y() || (qSign(releaseVelocity.y()) == qSign(newv.y()))) - newv.setY(newv.y() * smoothing + releaseVelocity.y() * (qreal(1) - smoothing)); - } else - qScrollerDebug() << "NO SMOOTHING to " << newv; - - releaseVelocity.setX(qBound(-sp->maximumVelocity, newv.x(), sp->maximumVelocity)); - releaseVelocity.setY(qBound(-sp->maximumVelocity, newv.y(), sp->maximumVelocity)); - - qScrollerDebug() << " --> new velocity:" << releaseVelocity; -} - -void QScrollerPrivate::pushSegment(ScrollType type, qreal deltaTime, qreal stopProgress, qreal startPos, qreal deltaPos, qreal stopPos, QEasingCurve::Type curve, Qt::Orientation orientation) -{ - if (startPos == stopPos || deltaPos == 0) - return; - - ScrollSegment s; - if (orientation == Qt::Horizontal && !xSegments.isEmpty()) - s.startTime = xSegments.last().startTime + xSegments.last().deltaTime * xSegments.last().stopProgress; - else if (orientation == Qt::Vertical && !ySegments.isEmpty()) - s.startTime = ySegments.last().startTime + ySegments.last().deltaTime * ySegments.last().stopProgress; - else - s.startTime = monotonicTimer.elapsed(); - - s.startPos = startPos; - s.deltaPos = deltaPos; - s.stopPos = stopPos; - s.deltaTime = deltaTime * 1000; - s.stopProgress = stopProgress; - s.curve.setType(curve); - s.type = type; - - if (orientation == Qt::Horizontal) - xSegments.enqueue(s); - else - ySegments.enqueue(s); - - qScrollerDebug() << "+++ Added a new ScrollSegment: " << s; -} - - -/*! \internal - Clears the old segments and recalculates them if the current segments are not longer valid -*/ -void QScrollerPrivate::recalcScrollingSegments(bool forceRecalc) -{ - Q_Q(QScroller); - QPointF ppm = q->pixelPerMeter(); - - releaseVelocity = q->velocity(); - - if (forceRecalc || !scrollingSegmentsValid(Qt::Horizontal)) - createScrollingSegments(releaseVelocity.x(), contentPosition.x() + overshootPosition.x(), ppm.x(), Qt::Horizontal); - - if (forceRecalc || !scrollingSegmentsValid(Qt::Vertical)) - createScrollingSegments(releaseVelocity.y(), contentPosition.y() + overshootPosition.y(), ppm.y(), Qt::Vertical); -} - -/*! \internal - Returns the end position after the current scroll has finished. -*/ -qreal QScrollerPrivate::scrollingSegmentsEndPos(Qt::Orientation orientation) const -{ - if (orientation == Qt::Horizontal) { - if (xSegments.isEmpty()) - return contentPosition.x() + overshootPosition.x(); - else - return xSegments.last().stopPos; - } else { - if (ySegments.isEmpty()) - return contentPosition.y() + overshootPosition.y(); - else - return ySegments.last().stopPos; - } -} - -/*! \internal - Checks if the scroller segment end in a valid position. -*/ -bool QScrollerPrivate::scrollingSegmentsValid(Qt::Orientation orientation) -{ - QQueue<ScrollSegment> *segments; - qreal minPos; - qreal maxPos; - - if (orientation == Qt::Horizontal) { - segments = &xSegments; - minPos = contentPosRange.left(); - maxPos = contentPosRange.right(); - } else { - segments = &ySegments; - minPos = contentPosRange.top(); - maxPos = contentPosRange.bottom(); - } - - if (segments->isEmpty()) - return true; - - const ScrollSegment &last = segments->last(); - qreal stopPos = last.stopPos; - - if (last.type == ScrollTypeScrollTo) - return true; // scrollTo is always valid - - if (last.type == ScrollTypeOvershoot && - (stopPos != minPos && stopPos != maxPos)) - return false; - - if (stopPos < minPos || stopPos > maxPos) - return false; - - if (stopPos == minPos || stopPos == maxPos) // the begin and the end of the list are always ok - return true; - - qreal nextSnap = nextSnapPos(stopPos, 0, orientation); - if (!qIsNaN(nextSnap) && stopPos != nextSnap) - return false; - - return true; -} - -/*! \internal - Creates the sections needed to scroll to the specific \a endPos to the segments queue. -*/ -void QScrollerPrivate::createScrollToSegments(qreal v, qreal deltaTime, qreal endPos, Qt::Orientation orientation, ScrollType type) -{ - Q_UNUSED(v); - - if (orientation == Qt::Horizontal) - xSegments.clear(); - else - ySegments.clear(); - - qScrollerDebug() << "+++ createScrollToSegments: t:" << deltaTime << "ep:" << endPos << "o:" << int(orientation); - - const QScrollerPropertiesPrivate *sp = properties.d.data(); - - qreal startPos = (orientation == Qt::Horizontal) ? contentPosition.x() + overshootPosition.x() - : contentPosition.y() + overshootPosition.y(); - qreal deltaPos = (endPos - startPos) / 2; - - pushSegment(type, deltaTime * qreal(0.3), qreal(1.0), startPos, deltaPos, startPos + deltaPos, QEasingCurve::InQuad, orientation); - pushSegment(type, deltaTime * qreal(0.7), qreal(1.0), startPos + deltaPos, deltaPos, endPos, sp->scrollingCurve.type(), orientation); -} - -/*! \internal -*/ -void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal ppm, Qt::Orientation orientation) -{ - const QScrollerPropertiesPrivate *sp = properties.d.data(); - - QScrollerProperties::OvershootPolicy policy; - qreal minPos; - qreal maxPos; - qreal viewSize; - - if (orientation == Qt::Horizontal) { - xSegments.clear(); - policy = sp->hOvershootPolicy; - minPos = contentPosRange.left(); - maxPos = contentPosRange.right(); - viewSize = viewportSize.width(); - } else { - ySegments.clear(); - policy = sp->vOvershootPolicy; - minPos = contentPosRange.top(); - maxPos = contentPosRange.bottom(); - viewSize = viewportSize.height(); - } - - bool alwaysOvershoot = (policy == QScrollerProperties::OvershootAlwaysOn); - bool noOvershoot = (policy == QScrollerProperties::OvershootAlwaysOff) || !sp->overshootScrollDistanceFactor; - bool canOvershoot = !noOvershoot && (alwaysOvershoot || maxPos); - - qScrollerDebug() << "+++ createScrollingSegments: s:" << startPos << "maxPos:" << maxPos << "o:" << int(orientation); - - qScrollerDebug() << "v = " << v << ", decelerationFactor = " << sp->decelerationFactor << ", curveType = " << sp->scrollingCurve.type(); - - // This is only correct for QEasingCurve::OutQuad (linear velocity, - // constant deceleration), but the results look and feel ok for OutExpo - // and OutSine as well - - // v(t) = deltaTime * a * 0.5 * differentialForProgress(t / deltaTime) - // v(0) = vrelease - // v(deltaTime) = 0 - // deltaTime = (2 * vrelease) / (a * differntial(0)) - - // pos(t) = integrate(v(t)dt) - // pos(t) = vrelease * t - 0.5 * a * t * t - // pos(t) = deltaTime * a * 0.5 * progress(t / deltaTime) * deltaTime - // deltaPos = pos(deltaTime) - - qreal deltaTime = (qreal(2) * qAbs(v)) / (sp->decelerationFactor * differentialForProgress(sp->scrollingCurve, 0)); - qreal deltaPos = qSign(v) * deltaTime * deltaTime * qreal(0.5) * sp->decelerationFactor * ppm; - qreal endPos = startPos + deltaPos; - - qScrollerDebug() << " Real Delta:" << deltaPos; - - // -- determine snap points - qreal nextSnap = nextSnapPos(endPos, 0, orientation); - qreal lowerSnapPos = nextSnapPos(startPos, -1, orientation); - qreal higherSnapPos = nextSnapPos(startPos, 1, orientation); - - qScrollerDebug() << " Real Delta:" << lowerSnapPos <<"-"<<nextSnap <<"-"<<higherSnapPos; - - // - check if we can reach another snap point - if (nextSnap > higherSnapPos || qIsNaN(higherSnapPos)) - higherSnapPos = nextSnap; - if (nextSnap < lowerSnapPos || qIsNaN(lowerSnapPos)) - lowerSnapPos = nextSnap; - - // -- check if are in overshoot and end in overshoot - if ((startPos < minPos && endPos < minPos) || - (startPos > maxPos && endPos > maxPos)) { - qreal stopPos = endPos < minPos ? minPos : maxPos; - qreal oDeltaTime = sp->overshootScrollTime; - - pushSegment(ScrollTypeOvershoot, oDeltaTime * qreal(0.7), qreal(1.0), startPos, stopPos - startPos, stopPos, sp->scrollingCurve.type(), orientation); - return; - } - - if (qAbs(v) < sp->minimumVelocity) { - - qScrollerDebug() << "### below minimum Vel" << orientation; - - // - no snap points or already at one - if (qIsNaN(nextSnap) || nextSnap == startPos) - return; // nothing to do, no scrolling needed. - - // - decide which point to use - - qreal snapDistance = higherSnapPos - lowerSnapPos; - - qreal pressDistance = (orientation == Qt::Horizontal) ? - lastPosition.x() - pressPosition.x() : - lastPosition.y() - pressPosition.y(); - - // if not dragged far enough, pick the next snap point. - if (sp->snapPositionRatio == 0.0 || qAbs(pressDistance / sp->snapPositionRatio) > snapDistance) - endPos = nextSnap; - else if (pressDistance < 0.0) - endPos = lowerSnapPos; - else - endPos = higherSnapPos; - - deltaPos = endPos - startPos; - qreal midPos = startPos + deltaPos * qreal(0.3); - pushSegment(ScrollTypeFlick, sp->snapTime * qreal(0.3), qreal(1.0), startPos, midPos - startPos, midPos, QEasingCurve::InQuad, orientation); - pushSegment(ScrollTypeFlick, sp->snapTime * qreal(0.7), qreal(1.0), midPos, endPos - midPos, endPos, sp->scrollingCurve.type(), orientation); - return; - } - - // - go to the next snappoint if there is one - if (v > 0 && !qIsNaN(higherSnapPos)) { - // change the time in relation to the changed end position - if (endPos - startPos) - deltaTime *= qAbs((higherSnapPos - startPos) / (endPos - startPos)); - if (deltaTime > sp->snapTime) - deltaTime = sp->snapTime; - endPos = higherSnapPos; - - } else if (v < 0 && !qIsNaN(lowerSnapPos)) { - // change the time in relation to the changed end position - if (endPos - startPos) - deltaTime *= qAbs((lowerSnapPos - startPos) / (endPos - startPos)); - if (deltaTime > sp->snapTime) - deltaTime = sp->snapTime; - endPos = lowerSnapPos; - - // -- check if we are overshooting - } else if (endPos < minPos || endPos > maxPos) { - qreal stopPos = endPos < minPos ? minPos : maxPos; - - qScrollerDebug() << "Overshoot: delta:" << (stopPos - startPos); - - qreal stopProgress = progressForValue(sp->scrollingCurve, qAbs((stopPos - startPos) / deltaPos)); - - if (!canOvershoot) { - qScrollerDebug() << "Overshoot stopp:" << stopProgress; - - pushSegment(ScrollTypeFlick, deltaTime, stopProgress, startPos, endPos, stopPos, sp->scrollingCurve.type(), orientation); - } else { - qreal oDeltaTime = sp->overshootScrollTime; - qreal oStopProgress = qMin(stopProgress + oDeltaTime * qreal(0.3) / deltaTime, qreal(1)); - qreal oDistance = startPos + deltaPos * sp->scrollingCurve.valueForProgress(oStopProgress) - stopPos; - qreal oMaxDistance = qSign(oDistance) * (viewSize * sp->overshootScrollDistanceFactor); - - qScrollerDebug() << "1 oDistance:" << oDistance << "Max:" << oMaxDistance << "stopP/oStopP" << stopProgress << oStopProgress; - - if (qAbs(oDistance) > qAbs(oMaxDistance)) { - oStopProgress = progressForValue(sp->scrollingCurve, qAbs((stopPos + oMaxDistance - startPos) / deltaPos)); - oDistance = oMaxDistance; - qScrollerDebug() << "2 oDistance:" << oDistance << "Max:" << oMaxDistance << "stopP/oStopP" << stopProgress << oStopProgress; - } - - pushSegment(ScrollTypeFlick, deltaTime, oStopProgress, startPos, deltaPos, stopPos + oDistance, sp->scrollingCurve.type(), orientation); - pushSegment(ScrollTypeOvershoot, oDeltaTime * qreal(0.7), qreal(1.0), stopPos + oDistance, -oDistance, stopPos, sp->scrollingCurve.type(), orientation); - } - return; - } - - pushSegment(ScrollTypeFlick, deltaTime, qreal(1.0), startPos, deltaPos, endPos, sp->scrollingCurve.type(), orientation); -} - - -/*! \internal - Prepares scrolling by sending a QScrollPrepareEvent to the receiver widget. - Returns true if the scrolling was accepted and a target was returned. -*/ -bool QScrollerPrivate::prepareScrolling(const QPointF &position) -{ - QScrollPrepareEvent spe(position); - spe.ignore(); - sendEvent(target, &spe); - - qScrollerDebug() << "QScrollPrepareEvent returned from" << target << "with" << spe.isAccepted() << "mcp:" << spe.contentPosRange() << "cp:" << spe.contentPos(); - if (spe.isAccepted()) { - QPointF oldContentPos = contentPosition + overshootPosition; - QPointF contentDelta = spe.contentPos() - oldContentPos; - - viewportSize = spe.viewportSize(); - contentPosRange = spe.contentPosRange(); - if (contentPosRange.width() < 0) - contentPosRange.setWidth(0); - if (contentPosRange.height() < 0) - contentPosRange.setHeight(0); - contentPosition = clampToRect(spe.contentPos(), contentPosRange); - overshootPosition = spe.contentPos() - contentPosition; - - // - check if the content position was moved - if (contentDelta != QPointF(0, 0)) { - // need to correct all segments - for (int i = 0; i < xSegments.count(); i++) - xSegments[i].startPos -= contentDelta.x(); - - for (int i = 0; i < ySegments.count(); i++) - ySegments[i].startPos -= contentDelta.y(); - } - - if (QWidget *w = qobject_cast<QWidget *>(target)) - setDpiFromWidget(w); -#ifndef QT_NO_GRAPHICSVIEW - if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(target)) { - //TODO: the first view isn't really correct - maybe use an additional field in the prepare event? - if (go->scene() && !go->scene()->views().isEmpty()) - setDpiFromWidget(go->scene()->views().first()); - } -#endif - - if (state == QScroller::Scrolling) { - recalcScrollingSegments(); - } - return true; - } - - return false; -} - -void QScrollerPrivate::handleDrag(const QPointF &position, qint64 timestamp) -{ - const QScrollerPropertiesPrivate *sp = properties.d.data(); - - QPointF deltaPixel = position - lastPosition; - qint64 deltaTime = timestamp - lastTimestamp; - - if (sp->axisLockThreshold) { - int dx = qAbs(deltaPixel.x()); - int dy = qAbs(deltaPixel.y()); - if (dx || dy) { - bool vertical = (dy > dx); - qreal alpha = qreal(vertical ? dx : dy) / qreal(vertical ? dy : dx); - //qScrollerDebug() << "QScroller::handleDrag() -- axis lock:" << alpha << " / " << axisLockThreshold << "- isvertical:" << vertical << "- dx:" << dx << "- dy:" << dy; - if (alpha <= sp->axisLockThreshold) { - if (vertical) - deltaPixel.setX(0); - else - deltaPixel.setY(0); - } - } - } - - // calculate velocity (if the user would release the mouse NOW) - updateVelocity(deltaPixel, deltaTime); - - // restrict velocity, if content is not scrollable - QRectF max = contentPosRange; - bool canScrollX = (max.width() > 0) || (sp->hOvershootPolicy == QScrollerProperties::OvershootAlwaysOn); - bool canScrollY = (max.height() > 0) || (sp->vOvershootPolicy == QScrollerProperties::OvershootAlwaysOn); - - if (!canScrollX) { - deltaPixel.setX(0); - releaseVelocity.setX(0); - } - if (!canScrollY) { - deltaPixel.setY(0); - releaseVelocity.setY(0); - } - -// if (firstDrag) { -// // Do not delay the first drag -// setContentPositionHelper(q->contentPosition() - overshootDistance - deltaPixel); -// dragDistance = QPointF(0, 0); -// } else { - dragDistance += deltaPixel; -// } -//qScrollerDebug() << "######################" << deltaPixel << position.y() << lastPosition.y(); - if (canScrollX) - lastPosition.setX(position.x()); - if (canScrollY) - lastPosition.setY(position.y()); - lastTimestamp = timestamp; -} - -bool QScrollerPrivate::pressWhileInactive(const QPointF &position, qint64 timestamp) -{ - if (prepareScrolling(position)) { - const QScrollerPropertiesPrivate *sp = properties.d.data(); - - if (!contentPosRange.isNull() || - (sp->hOvershootPolicy == QScrollerProperties::OvershootAlwaysOn) || - (sp->vOvershootPolicy == QScrollerProperties::OvershootAlwaysOn)) { - - lastPosition = pressPosition = position; - lastTimestamp = pressTimestamp = timestamp; - setState(QScroller::Pressed); - } - } - return false; -} - -bool QScrollerPrivate::releaseWhilePressed(const QPointF &, qint64) -{ - if (overshootPosition != QPointF(0.0, 0.0)) { - setState(QScroller::Scrolling); - return true; - } else { - setState(QScroller::Inactive); - return false; - } -} - -bool QScrollerPrivate::moveWhilePressed(const QPointF &position, qint64 timestamp) -{ - Q_Q(QScroller); - const QScrollerPropertiesPrivate *sp = properties.d.data(); - QPointF ppm = q->pixelPerMeter(); - - QPointF deltaPixel = position - pressPosition; - - bool moveAborted = false; - bool moveStarted = (((deltaPixel / ppm).manhattanLength()) > sp->dragStartDistance); - - // check the direction of the mouse drag and abort if it's too much in the wrong direction. - if (moveStarted) { - QRectF max = contentPosRange; - bool canScrollX = (max.width() > 0); - bool canScrollY = (max.height() > 0); - - if (sp->hOvershootPolicy == QScrollerProperties::OvershootAlwaysOn) - canScrollX = true; - if (sp->vOvershootPolicy == QScrollerProperties::OvershootAlwaysOn) - canScrollY = true; - - if (qAbs(deltaPixel.x() / ppm.x()) < qAbs(deltaPixel.y() / ppm.y())) { - if (!canScrollY) - moveAborted = true; - } else { - if (!canScrollX) - moveAborted = true; - } - } - - if (moveAborted) { - setState(QScroller::Inactive); - moveStarted = false; - - } else if (moveStarted) { - setState(QScroller::Dragging); - - // subtract the dragStartDistance - deltaPixel = deltaPixel - deltaPixel * (sp->dragStartDistance / deltaPixel.manhattanLength()); - - if (deltaPixel != QPointF(0, 0)) { - // handleDrag updates lastPosition, lastTimestamp and velocity - handleDrag(pressPosition + deltaPixel, timestamp); - } - } - return moveStarted; -} - -bool QScrollerPrivate::moveWhileDragging(const QPointF &position, qint64 timestamp) -{ - // handleDrag updates lastPosition, lastTimestamp and velocity - handleDrag(position, timestamp); - return true; -} - -void QScrollerPrivate::timerEventWhileDragging() -{ - if (dragDistance != QPointF(0, 0)) { - qScrollerDebug() << "QScroller::timerEventWhileDragging() -- dragDistance:" << dragDistance; - - setContentPositionHelperDragging(-dragDistance); - dragDistance = QPointF(0, 0); - } -} - -bool QScrollerPrivate::releaseWhileDragging(const QPointF &position, qint64 timestamp) -{ - Q_Q(QScroller); - const QScrollerPropertiesPrivate *sp = properties.d.data(); - - // handleDrag updates lastPosition, lastTimestamp and velocity - handleDrag(position, timestamp); - - // check if we moved at all - this can happen if you stop a running - // scroller with a press and release shortly afterwards - QPointF deltaPixel = position - pressPosition; - if (((deltaPixel / q->pixelPerMeter()).manhattanLength()) > sp->dragStartDistance) { - - // handle accelerating flicks - if ((oldVelocity != QPointF(0, 0)) && sp->acceleratingFlickMaximumTime && - ((timestamp - pressTimestamp) < qint64(sp->acceleratingFlickMaximumTime * 1000))) { - - // - determine if the direction was changed - int signX = 0, signY = 0; - if (releaseVelocity.x()) - signX = (releaseVelocity.x() > 0) == (oldVelocity.x() > 0) ? 1 : -1; - if (releaseVelocity.y()) - signY = (releaseVelocity.y() > 0) == (oldVelocity.y() > 0) ? 1 : -1; - - if (signX > 0) - releaseVelocity.setX(qBound(-sp->maximumVelocity, - oldVelocity.x() * sp->acceleratingFlickSpeedupFactor, - sp->maximumVelocity)); - if (signY > 0) - releaseVelocity.setY(qBound(-sp->maximumVelocity, - oldVelocity.y() * sp->acceleratingFlickSpeedupFactor, - sp->maximumVelocity)); - } - } - - QPointF ppm = q->pixelPerMeter(); - createScrollingSegments(releaseVelocity.x(), contentPosition.x() + overshootPosition.x(), ppm.x(), Qt::Horizontal); - createScrollingSegments(releaseVelocity.y(), contentPosition.y() + overshootPosition.y(), ppm.y(), Qt::Vertical); - - qScrollerDebug() << "QScroller::releaseWhileDragging() -- velocity:" << releaseVelocity << "-- minimum velocity:" << sp->minimumVelocity << "overshoot" << overshootPosition; - - if (xSegments.isEmpty() && ySegments.isEmpty()) - setState(QScroller::Inactive); - else - setState(QScroller::Scrolling); - - return true; -} - -void QScrollerPrivate::timerEventWhileScrolling() -{ - qScrollerDebug() << "QScroller::timerEventWhileScrolling()"; - - setContentPositionHelperScrolling(); - if (xSegments.isEmpty() && ySegments.isEmpty()) - setState(QScroller::Inactive); -} - -bool QScrollerPrivate::pressWhileScrolling(const QPointF &position, qint64 timestamp) -{ - Q_Q(QScroller); - - if ((q->velocity() <= properties.d->maximumClickThroughVelocity) && - (overshootPosition == QPointF(0.0, 0.0))) { - setState(QScroller::Inactive); - return false; - } else { - lastPosition = pressPosition = position; - lastTimestamp = pressTimestamp = timestamp; - setState(QScroller::Pressed); - setState(QScroller::Dragging); - return true; - } -} - -/*! \internal - This function handles all state changes of the scroller. -*/ -void QScrollerPrivate::setState(QScroller::State newstate) -{ - Q_Q(QScroller); - bool sendLastScroll = false; - - if (state == newstate) - return; - - qScrollerDebug() << q << "QScroller::setState(" << stateName(newstate) << ")"; - - switch (newstate) { - case QScroller::Inactive: -#ifndef QT_NO_ANIMATION - scrollTimer->stop(); -#endif - - // send the last scroll event (but only after the current state change was finished) - if (!firstScroll) - sendLastScroll = true; - - releaseVelocity = QPointF(0, 0); - break; - - case QScroller::Pressed: -#ifndef QT_NO_ANIMATION - scrollTimer->stop(); -#endif - - oldVelocity = releaseVelocity; - releaseVelocity = QPointF(0, 0); - break; - - case QScroller::Dragging: - dragDistance = QPointF(0, 0); -#ifndef QT_NO_ANIMATION - if (state == QScroller::Pressed) - scrollTimer->start(); -#endif - break; - - case QScroller::Scrolling: -#ifndef QT_NO_ANIMATION - scrollTimer->start(); -#endif - break; - } - - qSwap(state, newstate); - - if (sendLastScroll) { - QScrollEvent se(contentPosition, overshootPosition, QScrollEvent::ScrollFinished); - sendEvent(target, &se); - firstScroll = true; - } - if (state == QScroller::Dragging || state == QScroller::Scrolling) - qt_activeScrollers()->insert(q); - else - qt_activeScrollers()->remove(q); - emit q->stateChanged(state); -} - - -/*! \internal - Helps when setting the content position. - It will try to move the content by the requested delta but stop in case - when we are coming back from an overshoot or a scrollTo. - It will also indicate a new overshooting condition by the overshootX and oversthootY flags. - - In this cases it will reset the velocity variables and other flags. - - Also keeps track of the current over-shooting value in overshootPosition. - - \a deltaPos is the amount of pixels the current content position should be moved -*/ -void QScrollerPrivate::setContentPositionHelperDragging(const QPointF &deltaPos) -{ - const QScrollerPropertiesPrivate *sp = properties.d.data(); - - if (sp->overshootDragResistanceFactor) - overshootPosition /= sp->overshootDragResistanceFactor; - - QPointF oldPos = contentPosition + overshootPosition; - QPointF newPos = oldPos + deltaPos; - - qScrollerDebug() << "QScroller::setContentPositionHelperDragging(" << deltaPos << " [pix])"; - qScrollerDebug() << " --> overshoot:" << overshootPosition << "- old pos:" << oldPos << "- new pos:" << newPos; - - QPointF oldClampedPos = clampToRect(oldPos, contentPosRange); - QPointF newClampedPos = clampToRect(newPos, contentPosRange); - - // --- handle overshooting and stop if the coordinate is going back inside the normal area - bool alwaysOvershootX = (sp->hOvershootPolicy == QScrollerProperties::OvershootAlwaysOn); - bool alwaysOvershootY = (sp->vOvershootPolicy == QScrollerProperties::OvershootAlwaysOn); - bool noOvershootX = (sp->hOvershootPolicy == QScrollerProperties::OvershootAlwaysOff) || - ((state == QScroller::Dragging) && !sp->overshootDragResistanceFactor) || - !sp->overshootDragDistanceFactor; - bool noOvershootY = (sp->vOvershootPolicy == QScrollerProperties::OvershootAlwaysOff) || - ((state == QScroller::Dragging) && !sp->overshootDragResistanceFactor) || - !sp->overshootDragDistanceFactor; - bool canOvershootX = !noOvershootX && (alwaysOvershootX || contentPosRange.width()); - bool canOvershootY = !noOvershootY && (alwaysOvershootY || contentPosRange.height()); - - qreal oldOvershootX = (canOvershootX) ? oldPos.x() - oldClampedPos.x() : 0; - qreal oldOvershootY = (canOvershootY) ? oldPos.y() - oldClampedPos.y() : 0; - - qreal newOvershootX = (canOvershootX) ? newPos.x() - newClampedPos.x() : 0; - qreal newOvershootY = (canOvershootY) ? newPos.y() - newClampedPos.y() : 0; - - qreal maxOvershootX = viewportSize.width() * sp->overshootDragDistanceFactor; - qreal maxOvershootY = viewportSize.height() * sp->overshootDragDistanceFactor; - - qScrollerDebug() << " --> noOs:" << noOvershootX << "drf:" << sp->overshootDragResistanceFactor << "mdf:" << sp->overshootScrollDistanceFactor << "ossP:"<<sp->hOvershootPolicy; - qScrollerDebug() << " --> canOS:" << canOvershootX << "newOS:" << newOvershootX << "maxOS:" << maxOvershootX; - - if (sp->overshootDragResistanceFactor) { - oldOvershootX *= sp->overshootDragResistanceFactor; - oldOvershootY *= sp->overshootDragResistanceFactor; - newOvershootX *= sp->overshootDragResistanceFactor; - newOvershootY *= sp->overshootDragResistanceFactor; - } - - // -- stop at the maximum overshoot distance - - newOvershootX = qBound(-maxOvershootX, newOvershootX, maxOvershootX); - newOvershootY = qBound(-maxOvershootY, newOvershootY, maxOvershootY); - - overshootPosition.setX(newOvershootX); - overshootPosition.setY(newOvershootY); - contentPosition = newClampedPos; - - QScrollEvent se(contentPosition, overshootPosition, firstScroll ? QScrollEvent::ScrollStarted : QScrollEvent::ScrollUpdated); - sendEvent(target, &se); - firstScroll = false; - - qScrollerDebug() << " --> new position:" << newClampedPos << "- new overshoot:" << overshootPosition << - "- overshoot x/y?:" << overshootPosition; -} - - -qreal QScrollerPrivate::nextSegmentPosition(QQueue<ScrollSegment> &segments, qint64 now, qreal oldPos) -{ - qreal pos = oldPos; - - // check the X segments for new positions - while (!segments.isEmpty()) { - const ScrollSegment s = segments.head(); - - if ((s.startTime + s.deltaTime * s.stopProgress) <= now) { - segments.dequeue(); - pos = s.stopPos; - } else if (s.startTime <= now) { - qreal progress = qreal(now - s.startTime) / qreal(s.deltaTime); - pos = s.startPos + s.deltaPos * s.curve.valueForProgress(progress); - if (s.deltaPos > 0 ? pos > s.stopPos : pos < s.stopPos) { - segments.dequeue(); - pos = s.stopPos; - } else { - break; - } - } else { - break; - } - } - return pos; -} - -void QScrollerPrivate::setContentPositionHelperScrolling() -{ - qint64 now = monotonicTimer.elapsed(); - QPointF newPos = contentPosition + overshootPosition; - - newPos.setX(nextSegmentPosition(xSegments, now, newPos.x())); - newPos.setY(nextSegmentPosition(ySegments, now, newPos.y())); - - // -- set the position and handle overshoot - qScrollerDebug() << "QScroller::setContentPositionHelperScrolling()"; - qScrollerDebug() << " --> overshoot:" << overshootPosition << "- new pos:" << newPos; - - QPointF newClampedPos = clampToRect(newPos, contentPosRange); - - overshootPosition = newPos - newClampedPos; - contentPosition = newClampedPos; - - QScrollEvent se(contentPosition, overshootPosition, firstScroll ? QScrollEvent::ScrollStarted : QScrollEvent::ScrollUpdated); - sendEvent(target, &se); - firstScroll = false; - - qScrollerDebug() << " --> new position:" << newClampedPos << "- new overshoot:" << overshootPosition; -} - -/*! \internal - Returns the next snap point in direction. - If \a direction >0 it will return the next snap point that is larger than the current position. - If \a direction <0 it will return the next snap point that is smaller than the current position. - If \a direction ==0 it will return the nearest snap point (or the current position if we are already - on a snap point. - Returns the nearest snap position or NaN if no such point could be found. - */ -qreal QScrollerPrivate::nextSnapPos(qreal p, int dir, Qt::Orientation orientation) -{ - qreal bestSnapPos = Q_QNAN; - qreal bestSnapPosDist = Q_INFINITY; - - qreal minPos; - qreal maxPos; - - if (orientation == Qt::Horizontal) { - minPos = contentPosRange.left(); - maxPos = contentPosRange.right(); - } else { - minPos = contentPosRange.top(); - maxPos = contentPosRange.bottom(); - } - - if (orientation == Qt::Horizontal) { - // the snap points in the list - foreach (qreal snapPos, snapPositionsX) { - qreal snapPosDist = snapPos - p; - if ((dir > 0 && snapPosDist < 0) || - (dir < 0 && snapPosDist > 0)) - continue; // wrong direction - if (snapPos < minPos || snapPos > maxPos ) - continue; // invalid - - if (qIsNaN(bestSnapPos) || - qAbs(snapPosDist) < bestSnapPosDist ) { - bestSnapPos = snapPos; - bestSnapPosDist = qAbs(snapPosDist); - } - } - - // the snap point interval - if (snapIntervalX > 0.0) { - qreal first = minPos + snapFirstX; - qreal snapPos; - if (dir > 0) - snapPos = qCeil((p - first) / snapIntervalX) * snapIntervalX + first; - else if (dir < 0) - snapPos = qFloor((p - first) / snapIntervalX) * snapIntervalX + first; - else if (p <= first) - snapPos = first; - else - { - qreal last = qFloor((maxPos - first) / snapIntervalX) * snapIntervalX + first; - if (p >= last) - snapPos = last; - else - snapPos = qRound((p - first) / snapIntervalX) * snapIntervalX + first; - } - - if (snapPos >= first && snapPos <= maxPos ) { - qreal snapPosDist = snapPos - p; - - if (qIsNaN(bestSnapPos) || - qAbs(snapPosDist) < bestSnapPosDist ) { - bestSnapPos = snapPos; - bestSnapPosDist = qAbs(snapPosDist); - } - } - } - - } else { // (orientation == Qt::Vertical) - // the snap points in the list - foreach (qreal snapPos, snapPositionsY) { - qreal snapPosDist = snapPos - p; - if ((dir > 0 && snapPosDist < 0) || - (dir < 0 && snapPosDist > 0)) - continue; // wrong direction - if (snapPos < minPos || snapPos > maxPos ) - continue; // invalid - - if (qIsNaN(bestSnapPos) || - qAbs(snapPosDist) < bestSnapPosDist) { - bestSnapPos = snapPos; - bestSnapPosDist = qAbs(snapPosDist); - } - } - - // the snap point interval - if (snapIntervalY > 0.0) { - qreal first = minPos + snapFirstY; - qreal snapPos; - if (dir > 0) - snapPos = qCeil((p - first) / snapIntervalY) * snapIntervalY + first; - else if (dir < 0) - snapPos = qFloor((p - first) / snapIntervalY) * snapIntervalY + first; - else if (p <= first) - snapPos = first; - else - { - qreal last = qFloor((maxPos - first) / snapIntervalY) * snapIntervalY + first; - if (p >= last) - snapPos = last; - else - snapPos = qRound((p - first) / snapIntervalY) * snapIntervalY + first; - } - - if (snapPos >= first && snapPos <= maxPos ) { - qreal snapPosDist = snapPos - p; - - if (qIsNaN(bestSnapPos) || - qAbs(snapPosDist) < bestSnapPosDist) { - bestSnapPos = snapPos; - bestSnapPosDist = qAbs(snapPosDist); - } - } - } - } - - return bestSnapPos; -} - -/*! - \enum QScroller::State - - This enum contains the different QScroller states. - - \value Inactive The scroller is not scrolling and nothing is pressed. - \value Pressed A touch event was received or the mouse button was pressed but the scroll area is currently not dragged. - \value Dragging The scroll area is currently following the touch point or mouse. - \value Scrolling The scroll area is moving on it's own. -*/ - -/*! - \enum QScroller::ScrollerGestureType - - This enum contains the different gesture types that are supported by the QScroller gesture recognizer. - - \value TouchGesture The gesture recognizer will only trigger on touch - events. Specifically it will react on single touch points when using a - touch screen and dual touch points when using a touchpad. - \value LeftMouseButtonGesture The gesture recognizer will only trigger on left mouse button events. - \value MiddleMouseButtonGesture The gesture recognizer will only trigger on middle mouse button events. - \value RightMouseButtonGesture The gesture recognizer will only trigger on right mouse button events. -*/ - -/*! - \enum QScroller::Input - - This enum contains an input device agnostic view of input events that are relevant for QScroller. - - \value InputPress The user pressed the input device (e.g. QEvent::MouseButtonPress, - QEvent::GraphicsSceneMousePress, QEvent::TouchBegin) - - \value InputMove The user moved the input device (e.g. QEvent::MouseMove, - QEvent::GraphicsSceneMouseMove, QEvent::TouchUpdate) - - \value InputRelease The user released the input device (e.g. QEvent::MouseButtonRelease, - QEvent::GraphicsSceneMouseRelease, QEvent::TouchEnd) - -*/ - -QT_END_NAMESPACE diff --git a/src/gui/util/qscroller.h b/src/gui/util/qscroller.h deleted file mode 100644 index 16a7f2e421..0000000000 --- a/src/gui/util/qscroller.h +++ /dev/null @@ -1,155 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCROLLER_H -#define QSCROLLER_H - -#include <QtCore/QObject> -#include <QtCore/QPointF> -#include <QtGui/QScrollerProperties> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QWidget; -class QScrollerPrivate; -class QScrollerProperties; -#ifndef QT_NO_GESTURES -class QFlickGestureRecognizer; -class QMouseFlickGestureRecognizer; -#endif - -class Q_GUI_EXPORT QScroller : public QObject -{ - Q_OBJECT - Q_PROPERTY(State state READ state NOTIFY stateChanged) - Q_PROPERTY(QScrollerProperties scrollerProperties READ scrollerProperties WRITE setScrollerProperties NOTIFY scrollerPropertiesChanged) - Q_ENUMS(State) - -public: - enum State - { - Inactive, - Pressed, - Dragging, - Scrolling - }; - - enum ScrollerGestureType - { - TouchGesture, - LeftMouseButtonGesture, - RightMouseButtonGesture, - MiddleMouseButtonGesture - }; - - enum Input - { - InputPress = 1, - InputMove, - InputRelease - }; - - static bool hasScroller(QObject *target); - - static QScroller *scroller(QObject *target); - static const QScroller *scroller(const QObject *target); - -#ifndef QT_NO_GESTURES - static Qt::GestureType grabGesture(QObject *target, ScrollerGestureType gestureType = TouchGesture); - static Qt::GestureType grabbedGesture(QObject *target); - static void ungrabGesture(QObject *target); -#endif - - static QList<QScroller *> activeScrollers(); - - QObject *target() const; - - State state() const; - - bool handleInput(Input input, const QPointF &position, qint64 timestamp = 0); - - void stop(); - QPointF velocity() const; - QPointF finalPosition() const; - QPointF pixelPerMeter() const; - - QScrollerProperties scrollerProperties() const; - - void setSnapPositionsX( const QList<qreal> &positions ); - void setSnapPositionsX( qreal first, qreal interval ); - void setSnapPositionsY( const QList<qreal> &positions ); - void setSnapPositionsY( qreal first, qreal interval ); - -public Q_SLOTS: - void setScrollerProperties(const QScrollerProperties &prop); - void scrollTo(const QPointF &pos); - void scrollTo(const QPointF &pos, int scrollTime); - void ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin); - void ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin, int scrollTime); - void resendPrepareEvent(); - -Q_SIGNALS: - void stateChanged(QScroller::State newstate); - void scrollerPropertiesChanged(const QScrollerProperties &); - -private: - QScrollerPrivate *d_ptr; - - QScroller(QObject *target); - virtual ~QScroller(); - - Q_DISABLE_COPY(QScroller) - Q_DECLARE_PRIVATE(QScroller) - -#ifndef QT_NO_GESTURES - friend class QFlickGestureRecognizer; -#endif -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QSCROLLER_H diff --git a/src/gui/util/qscroller_mac.mm b/src/gui/util/qscroller_mac.mm deleted file mode 100644 index 81d18aaf6b..0000000000 --- a/src/gui/util/qscroller_mac.mm +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/qglobal.h> - -#ifdef Q_WS_MAC - -#import <Cocoa/Cocoa.h> - -#include "qscroller_p.h" - -QT_BEGIN_NAMESPACE - -QPointF QScrollerPrivate::realDpi(int screen) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSArray *nsscreens = [NSScreen screens]; - - if (screen < 0 || screen >= int([nsscreens count])) - screen = 0; - - NSScreen *nsscreen = [nsscreens objectAtIndex:screen]; - CGDirectDisplayID display = [[[nsscreen deviceDescription] objectForKey:@"NSScreenNumber"] intValue]; - - CGSize mmsize = CGDisplayScreenSize(display); - if (mmsize.width > 0 && mmsize.height > 0) { - return QPointF(CGDisplayPixelsWide(display) / mmsize.width, - CGDisplayPixelsHigh(display) / mmsize.height) * qreal(25.4); - } else { - return QPointF(); - } - [pool release]; -} - -QT_END_NAMESPACE - -#endif diff --git a/src/gui/util/qscroller_p.h b/src/gui/util/qscroller_p.h deleted file mode 100644 index b4f4db5e34..0000000000 --- a/src/gui/util/qscroller_p.h +++ /dev/null @@ -1,209 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCROLLER_P_H -#define QSCROLLER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QObject> -#include <QPointer> -#include <QQueue> -#include <QSet> -#include <QEasingCurve> -#include <QElapsedTimer> -#include <QSizeF> -#include <QPointF> -#include <QRectF> -#include <qscroller.h> -#include <qscrollerproperties.h> -#include <private/qscrollerproperties_p.h> -#include <QAbstractAnimation> - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_GESTURES -class QFlickGestureRecognizer; -#endif - -#ifndef QT_NO_ANIMATION -class QScrollTimer; -#endif -class QScrollerPrivate : public QObject -{ - Q_OBJECT - Q_DECLARE_PUBLIC(QScroller) - -public: - QScrollerPrivate(QScroller *q, QObject *target); - void init(); - - void sendEvent(QObject *o, QEvent *e); - - void setState(QScroller::State s); - - enum ScrollType { - ScrollTypeFlick = 0, - ScrollTypeScrollTo, - ScrollTypeOvershoot - }; - - struct ScrollSegment { - qint64 startTime; - qint64 deltaTime; - qreal startPos; - qreal deltaPos; - QEasingCurve curve; - qreal stopProgress; // whatever is.. - qreal stopPos; // ..reached first - ScrollType type; - }; - - bool pressWhileInactive(const QPointF &position, qint64 timestamp); - bool moveWhilePressed(const QPointF &position, qint64 timestamp); - bool releaseWhilePressed(const QPointF &position, qint64 timestamp); - bool moveWhileDragging(const QPointF &position, qint64 timestamp); - bool releaseWhileDragging(const QPointF &position, qint64 timestamp); - bool pressWhileScrolling(const QPointF &position, qint64 timestamp); - - void timerTick(); - void timerEventWhileDragging(); - void timerEventWhileScrolling(); - - bool prepareScrolling(const QPointF &position); - void handleDrag(const QPointF &position, qint64 timestamp); - - QPointF realDpi(int screen); - QPointF dpi() const; - void setDpi(const QPointF &dpi); - void setDpiFromWidget(QWidget *widget); - - void updateVelocity(const QPointF &deltaPixelRaw, qint64 deltaTime); - void pushSegment(ScrollType type, qreal deltaTime, qreal stopProgress, qreal startPos, qreal deltaPos, qreal stopPos, QEasingCurve::Type curve, Qt::Orientation orientation); - void recalcScrollingSegments(bool forceRecalc = false); - qreal scrollingSegmentsEndPos(Qt::Orientation orientation) const; - bool scrollingSegmentsValid(Qt::Orientation orientation); - void createScrollToSegments(qreal v, qreal deltaTime, qreal endPos, Qt::Orientation orientation, ScrollType type); - void createScrollingSegments(qreal v, qreal startPos, qreal ppm, Qt::Orientation orientation); - - void setContentPositionHelperDragging(const QPointF &deltaPos); - void setContentPositionHelperScrolling(); - - qreal nextSnapPos(qreal p, int dir, Qt::Orientation orientation); - static qreal nextSegmentPosition(QQueue<ScrollSegment> &segments, qint64 now, qreal oldPos); - - inline int frameRateSkip() const { return properties.d.data()->frameRate; } - - static const char *stateName(QScroller::State state); - static const char *inputName(QScroller::Input input); - -public slots: - void targetDestroyed(); - -public: - // non static - QObject *target; - QScrollerProperties properties; -#ifndef QT_NO_GESTURES - QFlickGestureRecognizer *recognizer; - Qt::GestureType recognizerType; -#endif - - // scroller state: - - // QPointer<QObject> scrollTarget; - QSizeF viewportSize; - QRectF contentPosRange; - QPointF contentPosition; - QPointF overshootPosition; // the number of pixels we are overshooting (before overshootDragResistanceFactor) - - // state - - bool enabled; - QScroller::State state; - bool firstScroll; // true if we haven't already send a scroll event - - QPointF oldVelocity; // the release velocity of the last drag - - QPointF pressPosition; - QPointF lastPosition; - qint64 pressTimestamp; - qint64 lastTimestamp; - - QPointF dragDistance; // the distance we should move during the next drag timer event - - QQueue<ScrollSegment> xSegments; - QQueue<ScrollSegment> ySegments; - - // snap positions - QList<qreal> snapPositionsX; - qreal snapFirstX; - qreal snapIntervalX; - QList<qreal> snapPositionsY; - qreal snapFirstY; - qreal snapIntervalY; - - QPointF pixelPerMeter; - - QElapsedTimer monotonicTimer; - - QPointF releaseVelocity; // the starting velocity of the scrolling state -#ifndef QT_NO_ANIMATION - QScrollTimer *scrollTimer; -#endif - - QScroller *q_ptr; -}; - - -QT_END_NAMESPACE - -#endif // QSCROLLER_P_H - diff --git a/src/gui/util/qscrollerproperties.cpp b/src/gui/util/qscrollerproperties.cpp deleted file mode 100644 index 5e2459a37e..0000000000 --- a/src/gui/util/qscrollerproperties.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QPointer> -#include <QObject> -#include <QtCore/qmath.h> -#ifdef Q_WS_WIN -# include <QLibrary> -#endif - -#include "qscrollerproperties.h" -#include "private/qscrollerproperties_p.h" - -QT_BEGIN_NAMESPACE - -static QScrollerPropertiesPrivate *userDefaults = 0; -static QScrollerPropertiesPrivate *systemDefaults = 0; - -QScrollerPropertiesPrivate *QScrollerPropertiesPrivate::defaults() -{ - if (!systemDefaults) { - QScrollerPropertiesPrivate spp; - spp.mousePressEventDelay = qreal(0.25); - spp.dragStartDistance = qreal(5.0 / 1000); - spp.dragVelocitySmoothingFactor = qreal(0.8); - spp.axisLockThreshold = qreal(0); - spp.scrollingCurve.setType(QEasingCurve::OutQuad); - spp.decelerationFactor = qreal(0.125); - spp.minimumVelocity = qreal(50.0 / 1000); - spp.maximumVelocity = qreal(500.0 / 1000); - spp.maximumClickThroughVelocity = qreal(66.5 / 1000); - spp.acceleratingFlickMaximumTime = qreal(1.25); - spp.acceleratingFlickSpeedupFactor = qreal(3.0); - spp.snapPositionRatio = qreal(0.5); - spp.snapTime = qreal(0.3); - spp.overshootDragResistanceFactor = qreal(0.5); - spp.overshootDragDistanceFactor = qreal(1); - spp.overshootScrollDistanceFactor = qreal(0.5); - spp.overshootScrollTime = qreal(0.7); -# ifdef Q_WS_WIN - if (QLibrary::resolve(QLatin1String("UxTheme"), "BeginPanningFeedback")) - spp.overshootScrollTime = qreal(0.35); -# endif - spp.hOvershootPolicy = QScrollerProperties::OvershootWhenScrollable; - spp.vOvershootPolicy = QScrollerProperties::OvershootWhenScrollable; - spp.frameRate = QScrollerProperties::Standard; - - systemDefaults = new QScrollerPropertiesPrivate(spp); - } - return new QScrollerPropertiesPrivate(userDefaults ? *userDefaults : *systemDefaults); -} - -/*! - \class QScrollerProperties - \brief The QScrollerProperties class stores the settings for a QScroller. - \since 4.8 - - The QScrollerProperties class stores the parameters used by QScroller. - - The default settings are platform dependent so that Qt emulates the - platform behaviour for kinetic scrolling. - - As a convention the QScrollerProperties are in physical units (meter, - seconds) and are converted by QScroller using the current DPI. - - \sa QScroller -*/ - -/*! - Constructs new scroller properties. -*/ -QScrollerProperties::QScrollerProperties() - : d(QScrollerPropertiesPrivate::defaults()) -{ -} - -/*! - Constructs a copy of \a sp. -*/ -QScrollerProperties::QScrollerProperties(const QScrollerProperties &sp) - : d(new QScrollerPropertiesPrivate(*sp.d)) -{ -} - -/*! - Assigns \a sp to these scroller properties and returns a reference to these scroller properties. -*/ -QScrollerProperties &QScrollerProperties::operator=(const QScrollerProperties &sp) -{ - *d.data() = *sp.d.data(); - return *this; -} - -/*! - Destroys the scroller properties. -*/ -QScrollerProperties::~QScrollerProperties() -{ -} - -/*! - Returns true if these scroller properties are equal to \a sp; otherwise returns false. -*/ -bool QScrollerProperties::operator==(const QScrollerProperties &sp) const -{ - return *d.data() == *sp.d.data(); -} - -/*! - Returns true if these scroller properties are different from \a sp; otherwise returns false. -*/ -bool QScrollerProperties::operator!=(const QScrollerProperties &sp) const -{ - return !(*d.data() == *sp.d.data()); -} - -bool QScrollerPropertiesPrivate::operator==(const QScrollerPropertiesPrivate &p) const -{ - bool same = true; - same &= (mousePressEventDelay == p.mousePressEventDelay); - same &= (dragStartDistance == p.dragStartDistance); - same &= (dragVelocitySmoothingFactor == p.dragVelocitySmoothingFactor); - same &= (axisLockThreshold == p.axisLockThreshold); - same &= (scrollingCurve == p.scrollingCurve); - same &= (decelerationFactor == p.decelerationFactor); - same &= (minimumVelocity == p.minimumVelocity); - same &= (maximumVelocity == p.maximumVelocity); - same &= (maximumClickThroughVelocity == p.maximumClickThroughVelocity); - same &= (acceleratingFlickMaximumTime == p.acceleratingFlickMaximumTime); - same &= (acceleratingFlickSpeedupFactor == p.acceleratingFlickSpeedupFactor); - same &= (snapPositionRatio == p.snapPositionRatio); - same &= (snapTime == p.snapTime); - same &= (overshootDragResistanceFactor == p.overshootDragResistanceFactor); - same &= (overshootDragDistanceFactor == p.overshootDragDistanceFactor); - same &= (overshootScrollDistanceFactor == p.overshootScrollDistanceFactor); - same &= (overshootScrollTime == p.overshootScrollTime); - same &= (hOvershootPolicy == p.hOvershootPolicy); - same &= (vOvershootPolicy == p.vOvershootPolicy); - same &= (frameRate == p.frameRate); - return same; -} - -/*! - Sets the scroller properties for all new QScrollerProperties objects to \a sp. - - Use this function to override the platform default properties returned by the default - constructor. If you only want to change the scroller properties of a single scroller, use - QScroller::setScrollerProperties() - - \note Calling this function will not change the content of already existing - QScrollerProperties objects. - - \sa unsetDefaultScrollerProperties() -*/ -void QScrollerProperties::setDefaultScrollerProperties(const QScrollerProperties &sp) -{ - if (!userDefaults) - userDefaults = new QScrollerPropertiesPrivate(*sp.d); - else - *userDefaults = *sp.d; -} - -/*! - Sets the scroller properties returned by the default constructor back to the platform default - properties. - - \sa setDefaultScrollerProperties() -*/ -void QScrollerProperties::unsetDefaultScrollerProperties() -{ - delete userDefaults; - userDefaults = 0; -} - -/*! - Query the \a metric value of the scroller properties. - - \sa setScrollMetric(), ScrollMetric -*/ -QVariant QScrollerProperties::scrollMetric(ScrollMetric metric) const -{ - switch (metric) { - case MousePressEventDelay: return d->mousePressEventDelay; - case DragStartDistance: return d->dragStartDistance; - case DragVelocitySmoothingFactor: return d->dragVelocitySmoothingFactor; - case AxisLockThreshold: return d->axisLockThreshold; - case ScrollingCurve: return d->scrollingCurve; - case DecelerationFactor: return d->decelerationFactor; - case MinimumVelocity: return d->minimumVelocity; - case MaximumVelocity: return d->maximumVelocity; - case MaximumClickThroughVelocity: return d->maximumClickThroughVelocity; - case AcceleratingFlickMaximumTime: return d->acceleratingFlickMaximumTime; - case AcceleratingFlickSpeedupFactor:return d->acceleratingFlickSpeedupFactor; - case SnapPositionRatio: return d->snapPositionRatio; - case SnapTime: return d->snapTime; - case OvershootDragResistanceFactor: return d->overshootDragResistanceFactor; - case OvershootDragDistanceFactor: return d->overshootDragDistanceFactor; - case OvershootScrollDistanceFactor: return d->overshootScrollDistanceFactor; - case OvershootScrollTime: return d->overshootScrollTime; - case HorizontalOvershootPolicy: return QVariant::fromValue(d->hOvershootPolicy); - case VerticalOvershootPolicy: return QVariant::fromValue(d->vOvershootPolicy); - case FrameRate: return QVariant::fromValue(d->frameRate); - case ScrollMetricCount: break; - } - return QVariant(); -} - -/*! - Set a specific value of the \a metric ScrollerMetric to \a value. - - \sa scrollMetric(), ScrollMetric -*/ -void QScrollerProperties::setScrollMetric(ScrollMetric metric, const QVariant &value) -{ - switch (metric) { - case MousePressEventDelay: d->mousePressEventDelay = value.toReal(); break; - case DragStartDistance: d->dragStartDistance = value.toReal(); break; - case DragVelocitySmoothingFactor: d->dragVelocitySmoothingFactor = qBound(qreal(0), value.toReal(), qreal(1)); break; - case AxisLockThreshold: d->axisLockThreshold = qBound(qreal(0), value.toReal(), qreal(1)); break; - case ScrollingCurve: d->scrollingCurve = value.toEasingCurve(); break; - case DecelerationFactor: d->decelerationFactor = value.toReal(); break; - case MinimumVelocity: d->minimumVelocity = value.toReal(); break; - case MaximumVelocity: d->maximumVelocity = value.toReal(); break; - case MaximumClickThroughVelocity: d->maximumClickThroughVelocity = value.toReal(); break; - case AcceleratingFlickMaximumTime: d->acceleratingFlickMaximumTime = value.toReal(); break; - case AcceleratingFlickSpeedupFactor:d->acceleratingFlickSpeedupFactor = value.toReal(); break; - case SnapPositionRatio: d->snapPositionRatio = qBound(qreal(0), value.toReal(), qreal(1)); break; - case SnapTime: d->snapTime = value.toReal(); break; - case OvershootDragResistanceFactor: d->overshootDragResistanceFactor = value.toReal(); break; - case OvershootDragDistanceFactor: d->overshootDragDistanceFactor = qBound(qreal(0), value.toReal(), qreal(1)); break; - case OvershootScrollDistanceFactor: d->overshootScrollDistanceFactor = qBound(qreal(0), value.toReal(), qreal(1)); break; - case OvershootScrollTime: d->overshootScrollTime = value.toReal(); break; - case HorizontalOvershootPolicy: d->hOvershootPolicy = value.value<QScrollerProperties::OvershootPolicy>(); break; - case VerticalOvershootPolicy: d->vOvershootPolicy = value.value<QScrollerProperties::OvershootPolicy>(); break; - case FrameRate: d->frameRate = value.value<QScrollerProperties::FrameRates>(); break; - case ScrollMetricCount: break; - } -} - -/*! - \enum QScrollerProperties::FrameRates - - This enum describes the available frame rates used while dragging or scrolling. - - \value Fps60 60 frames per second - \value Fps30 30 frames per second - \value Fps20 20 frames per second - \value Standard the default value is 60 frames per second (which corresponds to QAbstractAnimation). -*/ - -/*! - \enum QScrollerProperties::OvershootPolicy - - This enum describes the various modes of overshooting. - - \value OvershootWhenScrollable Overshooting is possible when the content is scrollable. This is the - default. - - \value OvershootAlwaysOff Overshooting is never enabled, even when the content is scrollable. - - \value OvershootAlwaysOn Overshooting is always enabled, even when the content is not - scrollable. -*/ - -/*! - \enum QScrollerProperties::ScrollMetric - - This enum contains the different scroll metric types. When not indicated otherwise the - setScrollMetric function expects a QVariant of type qreal. - - See the QScroller documentation for further details of the concepts behind the different - values. - - \value MousePressEventDelay This is the time a mouse press event is delayed when starting - a flick gesture in \c{[s]}. If the gesture is triggered within that time, no mouse press or - release is sent to the scrolled object. If it triggers after that delay the delayed - mouse press plus a faked release event at global postion \c{QPoint(-QWIDGETSIZE_MAX, - -QWIDGETSIZE_MAX)} is sent. If the gesture is canceled, then both the delayed mouse - press plus the real release event are delivered. - - \value DragStartDistance This is the minimum distance the touch or mouse point needs to be - moved before the flick gesture is triggered in \c m. - - \value DragVelocitySmoothingFactor A value that describes to which extent new drag velocities are - included in the final scrolling velocity. This value should be in the range between \c 0 and - \c 1. The lower the value, the more smoothing is applied to the dragging velocity. - - \value AxisLockThreshold Restricts the movement to one axis if the movement is inside an angle - around the axis. The threshold must be in the range \c 0 to \c 1. - - \value ScrollingCurve The QEasingCurve used when decelerating the scrolling velocity after an - user initiated flick. Please note that this is the easing curve for the positions, \bold{not} - the velocity: the default is QEasingCurve::OutQuad, which results in a linear decrease in - velocity (1st derivative) and a constant deceleration (2nd derivative). - - \value DecelerationFactor This factor influences how long it takes the scroller to decelerate - to 0 velocity. The actual value depends on the chosen ScrollingCurve. For most - types the value should be in the range from \c 0.1 to \c 2.0 - - \value MinimumVelocity The minimum velocity that is needed after ending the touch or releasing - the mouse to start scrolling in \c{m/s}. - - \value MaximumVelocity This is the maximum velocity that can be reached in \c{m/s}. - - \value MaximumClickThroughVelocity This is the maximum allowed scroll speed for a click-through - in \c{m/s}. This means that a click on a currently (slowly) scrolling object will not only stop - the scrolling but the click event will also be delivered to the UI control. This is - useful when using exponential-type scrolling curves. - - \value AcceleratingFlickMaximumTime This is the maximum time in \c seconds that a flick gesture - can take to be recognized as an accelerating flick. If set to zero no such gesture is - detected. An "accelerating flick" is a flick gesture executed on an already scrolling object. - In such cases the scrolling speed is multiplied by AcceleratingFlickSpeedupFactor in order to - accelerate it. - - \value AcceleratingFlickSpeedupFactor The current speed is multiplied by this number if an - accelerating flick is detected. Should be \c{>= 1}. - - \value SnapPositionRatio This is the distance that the user must drag the area beween two snap - points in order to snap it to the next position. \c{0.33} means that the scroll must only - reach one third of the distance between two snap points to snap to the next one. The ratio must - be between \c 0 and \c 1. - - \value SnapTime This is the time factor for the scrolling curve. A lower value means that the - scrolling will take longer. The scrolling distance is independet of this value. - - \value OvershootDragResistanceFactor This value is the factor between the mouse dragging and - the actual scroll area movement (during overshoot). The factor must be between \c 0 and \c 1. - - \value OvershootDragDistanceFactor This is the maximum distance for overshoot movements while - dragging. The actual overshoot distance is calculated by multiplying this value with the - viewport size of the scrolled object. The factor must be between \c 0 and \c 1. - - \value OvershootScrollDistanceFactor This is the maximum distance for overshoot movements while - scrolling. The actual overshoot distance is calculated by multiplying this value with the - viewport size of the scrolled object. The factor must be between \c 0 and \c 1. - - \value OvershootScrollTime This is the time in \c seconds that is used to play the - complete overshoot animation. - - \value HorizontalOvershootPolicy This is the horizontal overshooting policy (see OvershootPolicy). - - \value VerticalOvershootPolicy This is the horizontal overshooting policy (see OvershootPolicy). - - \value FrameRate This is the frame rate which should be used while dragging or scrolling. - QScroller uses a QAbstractAnimation timer internally to sync all scrolling operations to other - animations that might be active at the same time. If the standard value of 60 frames per - second is too fast, it can be lowered with this setting, - while still being in-sync with QAbstractAnimation. Please note that only the values of the - FrameRates enum are allowed here. - - \value ScrollMetricCount This is always the last entry. -*/ - -QT_END_NAMESPACE diff --git a/src/gui/util/qscrollerproperties.h b/src/gui/util/qscrollerproperties.h deleted file mode 100644 index 46d1c2f44a..0000000000 --- a/src/gui/util/qscrollerproperties.h +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCROLLERPROPERTIES_H -#define QSCROLLERPROPERTIES_H - -#include <QtCore/QScopedPointer> -#include <QtCore/QMetaType> -#include <QtCore/QVariant> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QScroller; -class QScrollerPrivate; -class QScrollerPropertiesPrivate; - -class Q_GUI_EXPORT QScrollerProperties -{ -public: - QScrollerProperties(); - QScrollerProperties(const QScrollerProperties &sp); - QScrollerProperties &operator=(const QScrollerProperties &sp); - virtual ~QScrollerProperties(); - - bool operator==(const QScrollerProperties &sp) const; - bool operator!=(const QScrollerProperties &sp) const; - - static void setDefaultScrollerProperties(const QScrollerProperties &sp); - static void unsetDefaultScrollerProperties(); - - enum OvershootPolicy - { - OvershootWhenScrollable, - OvershootAlwaysOff, - OvershootAlwaysOn - }; - - enum FrameRates { - Standard, - Fps60, - Fps30, - Fps20 - }; - - enum ScrollMetric - { - MousePressEventDelay, // qreal [s] - DragStartDistance, // qreal [m] - DragVelocitySmoothingFactor, // qreal [0..1/s] (complex calculation involving time) v = v_new* DASF + v_old * (1-DASF) - AxisLockThreshold, // qreal [0..1] atan(|min(dx,dy)|/|max(dx,dy)|) - - ScrollingCurve, // QEasingCurve - DecelerationFactor, // slope of the curve - - MinimumVelocity, // qreal [m/s] - MaximumVelocity, // qreal [m/s] - MaximumClickThroughVelocity, // qreal [m/s] - - AcceleratingFlickMaximumTime, // qreal [s] - AcceleratingFlickSpeedupFactor, // qreal [1..] - - SnapPositionRatio, // qreal [0..1] - SnapTime, // qreal [s] - - OvershootDragResistanceFactor, // qreal [0..1] - OvershootDragDistanceFactor, // qreal [0..1] - OvershootScrollDistanceFactor, // qreal [0..1] - OvershootScrollTime, // qreal [s] - - HorizontalOvershootPolicy, // enum OvershootPolicy - VerticalOvershootPolicy, // enum OvershootPolicy - FrameRate, // enum FrameRates - - ScrollMetricCount - }; - - QVariant scrollMetric(ScrollMetric metric) const; - void setScrollMetric(ScrollMetric metric, const QVariant &value); - -protected: - QScopedPointer<QScrollerPropertiesPrivate> d; - -private: - QScrollerProperties(QScrollerPropertiesPrivate &dd); - - friend class QScrollerPropertiesPrivate; - friend class QScroller; - friend class QScrollerPrivate; -}; - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QScrollerProperties::OvershootPolicy) -Q_DECLARE_METATYPE(QScrollerProperties::FrameRates) - -QT_END_HEADER - -#endif // QSCROLLERPROPERTIES_H diff --git a/src/gui/util/qscrollerproperties_p.h b/src/gui/util/qscrollerproperties_p.h deleted file mode 100644 index 2e57a3f7dd..0000000000 --- a/src/gui/util/qscrollerproperties_p.h +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCROLLERPROPERTIES_P_H -#define QSCROLLERPROPERTIES_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QPointF> -#include <QEasingCurve> -#include <qscrollerproperties.h> - -QT_BEGIN_NAMESPACE - -class QScrollerPropertiesPrivate -{ -public: - static QScrollerPropertiesPrivate *defaults(); - - bool operator==(const QScrollerPropertiesPrivate &) const; - - qreal mousePressEventDelay; - qreal dragStartDistance; - qreal dragVelocitySmoothingFactor; - qreal axisLockThreshold; - QEasingCurve scrollingCurve; - qreal decelerationFactor; - qreal minimumVelocity; - qreal maximumVelocity; - qreal maximumClickThroughVelocity; - qreal acceleratingFlickMaximumTime; - qreal acceleratingFlickSpeedupFactor; - qreal snapPositionRatio; - qreal snapTime; - qreal overshootDragResistanceFactor; - qreal overshootDragDistanceFactor; - qreal overshootScrollDistanceFactor; - qreal overshootScrollTime; - QScrollerProperties::OvershootPolicy hOvershootPolicy; - QScrollerProperties::OvershootPolicy vOvershootPolicy; - QScrollerProperties::FrameRates frameRate; -}; - -QT_END_NAMESPACE - -#endif // QSCROLLERPROPERTIES_P_H - diff --git a/src/gui/util/qsystemtrayicon.cpp b/src/gui/util/qsystemtrayicon.cpp deleted file mode 100644 index 28d493248f..0000000000 --- a/src/gui/util/qsystemtrayicon.cpp +++ /dev/null @@ -1,674 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsystemtrayicon.h" -#include "qsystemtrayicon_p.h" - -#ifndef QT_NO_SYSTEMTRAYICON - -#include "qmenu.h" -#include "qevent.h" -#include "qpoint.h" -#include "qlabel.h" -#include "qpushbutton.h" -#include "qpainterpath.h" -#include "qpainter.h" -#include "qstyle.h" -#include "qgridlayout.h" -#include "qapplication.h" -#include "qdesktopwidget.h" -#include "qbitmap.h" -#include "private/qlabel_p.h" -#include "qapplication.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QSystemTrayIcon - \brief The QSystemTrayIcon class provides an icon for an application in the system tray. - \since 4.2 - \ingroup desktop - - Modern operating systems usually provide a special area on the desktop, - called the \e{system tray} or \e{notification area}, where long-running - applications can display icons and short messages. - - \image system-tray.png The system tray on Windows XP. - - The QSystemTrayIcon class can be used on the following platforms: - - \list - \o All supported versions of Windows. - \o All window managers for X11 that implement the \l{freedesktop.org} system - tray specification, including recent versions of KDE and GNOME. - \o All supported versions of Mac OS X. Note that the Growl - notification system must be installed for - QSystemTrayIcon::showMessage() to display messages. - \endlist - - To check whether a system tray is present on the user's desktop, - call the QSystemTrayIcon::isSystemTrayAvailable() static function. - - To add a system tray entry, create a QSystemTrayIcon object, call setContextMenu() - to provide a context menu for the icon, and call show() to make it visible in the - system tray. Status notification messages ("balloon messages") can be displayed at - any time using showMessage(). - - If the system tray is unavailable when a system tray icon is constructed, but - becomes available later, QSystemTrayIcon will automatically add an entry for the - application in the system tray if the icon is \l visible. - - The activated() signal is emitted when the user activates the icon. - - Only on X11, when a tooltip is requested, the QSystemTrayIcon receives a QHelpEvent - of type QEvent::ToolTip. Additionally, the QSystemTrayIcon receives wheel events of - type QEvent::Wheel. These are not supported on any other platform. - - \sa QDesktopServices, QDesktopWidget, {Desktop Integration}, {System Tray Icon Example} -*/ - -/*! - \enum QSystemTrayIcon::MessageIcon - - This enum describes the icon that is shown when a balloon message is displayed. - - \value NoIcon No icon is shown. - \value Information An information icon is shown. - \value Warning A standard warning icon is shown. - \value Critical A critical warning icon is shown. - - \sa QMessageBox -*/ - -/*! - Constructs a QSystemTrayIcon object with the given \a parent. - - The icon is initially invisible. - - \sa visible -*/ -QSystemTrayIcon::QSystemTrayIcon(QObject *parent) -: QObject(*new QSystemTrayIconPrivate(), parent) -{ -} - -/*! - Constructs a QSystemTrayIcon object with the given \a icon and \a parent. - - The icon is initially invisible. - - \sa visible -*/ -QSystemTrayIcon::QSystemTrayIcon(const QIcon &icon, QObject *parent) -: QObject(*new QSystemTrayIconPrivate(), parent) -{ - setIcon(icon); -} - -/*! - Removes the icon from the system tray and frees all allocated resources. -*/ -QSystemTrayIcon::~QSystemTrayIcon() -{ - Q_D(QSystemTrayIcon); - d->remove_sys(); -} - -#ifndef QT_NO_MENU - -/*! - Sets the specified \a menu to be the context menu for the system tray icon. - - The menu will pop up when the user requests the context menu for the system - tray icon by clicking the mouse button. - - On Mac OS X, this is currenly converted to a NSMenu, so the - aboutToHide() signal is not emitted. - - \note The system tray icon does not take ownership of the menu. You must - ensure that it is deleted at the appropriate time by, for example, creating - the menu with a suitable parent object. -*/ -void QSystemTrayIcon::setContextMenu(QMenu *menu) -{ - Q_D(QSystemTrayIcon); - d->menu = menu; - d->updateMenu_sys(); -} - -/*! - Returns the current context menu for the system tray entry. -*/ -QMenu* QSystemTrayIcon::contextMenu() const -{ - Q_D(const QSystemTrayIcon); - return d->menu; -} - -#endif // QT_NO_MENU - -/*! - \property QSystemTrayIcon::icon - \brief the system tray icon - - On Windows, the system tray icon size is 16x16; on X11, the preferred size is - 22x22. The icon will be scaled to the appropriate size as necessary. -*/ -void QSystemTrayIcon::setIcon(const QIcon &icon) -{ - Q_D(QSystemTrayIcon); - d->icon = icon; - d->updateIcon_sys(); -} - -QIcon QSystemTrayIcon::icon() const -{ - Q_D(const QSystemTrayIcon); - return d->icon; -} - -/*! - \property QSystemTrayIcon::toolTip - \brief the tooltip for the system tray entry - - On some systems, the tooltip's length is limited. The tooltip will be truncated - if necessary. -*/ -void QSystemTrayIcon::setToolTip(const QString &tooltip) -{ - Q_D(QSystemTrayIcon); - d->toolTip = tooltip; - d->updateToolTip_sys(); -} - -QString QSystemTrayIcon::toolTip() const -{ - Q_D(const QSystemTrayIcon); - return d->toolTip; -} - -/*! - \fn void QSystemTrayIcon::show() - - Shows the icon in the system tray. - - \sa hide(), visible -*/ - -/*! - \fn void QSystemTrayIcon::hide() - - Hides the system tray entry. - - \sa show(), visible -*/ - -/*! - \since 4.3 - Returns the geometry of the system tray icon in screen coordinates. - - \sa visible -*/ -QRect QSystemTrayIcon::geometry() const -{ - Q_D(const QSystemTrayIcon); - if (!d->visible) - return QRect(); - return d->geometry_sys(); -} - -/*! - \property QSystemTrayIcon::visible - \brief whether the system tray entry is visible - - Setting this property to true or calling show() makes the system tray icon - visible; setting this property to false or calling hide() hides it. -*/ -void QSystemTrayIcon::setVisible(bool visible) -{ - Q_D(QSystemTrayIcon); - if (visible == d->visible) - return; - if (d->icon.isNull() && visible) - qWarning("QSystemTrayIcon::setVisible: No Icon set"); - d->visible = visible; - if (d->visible) - d->install_sys(); - else - d->remove_sys(); -} - -bool QSystemTrayIcon::isVisible() const -{ - Q_D(const QSystemTrayIcon); - return d->visible; -} - -/*! - \reimp -*/ -bool QSystemTrayIcon::event(QEvent *e) -{ -#if defined(Q_WS_X11) - if (e->type() == QEvent::ToolTip) { - Q_D(QSystemTrayIcon); - return d->sys->deliverToolTipEvent(e); - } -#endif - return QObject::event(e); -} - -/*! - \enum QSystemTrayIcon::ActivationReason - - This enum describes the reason the system tray was activated. - - \value Unknown Unknown reason - \value Context The context menu for the system tray entry was requested - \value DoubleClick The system tray entry was double clicked - \value Trigger The system tray entry was clicked - \value MiddleClick The system tray entry was clicked with the middle mouse button - - \sa activated() -*/ - -/*! - \fn void QSystemTrayIcon::activated(QSystemTrayIcon::ActivationReason reason) - - This signal is emitted when the user activates the system tray icon. \a reason - specifies the reason for activation. QSystemTrayIcon::ActivationReason enumerates - the various reasons. - - \sa QSystemTrayIcon::ActivationReason -*/ - -/*! - \fn void QSystemTrayIcon::messageClicked() - - This signal is emitted when the message displayed using showMessage() - was clicked by the user. - - Currently this signal is not sent on Mac OS X. - - \note We follow Microsoft Windows XP/Vista behavior, so the - signal is also emitted when the user clicks on a tray icon with - a balloon message displayed. - - \sa activated() -*/ - - -/*! - Returns true if the system tray is available; otherwise returns false. - - If the system tray is currently unavailable but becomes available later, - QSystemTrayIcon will automatically add an entry in the system tray if it - is \l visible. -*/ - -bool QSystemTrayIcon::isSystemTrayAvailable() -{ - return QSystemTrayIconPrivate::isSystemTrayAvailable_sys(); -} - -/*! - Returns true if the system tray supports balloon messages; otherwise returns false. - - \sa showMessage() -*/ -bool QSystemTrayIcon::supportsMessages() -{ - return QSystemTrayIconPrivate::supportsMessages_sys(); -} - -/*! - \fn void QSystemTrayIcon::showMessage(const QString &title, const QString &message, MessageIcon icon, int millisecondsTimeoutHint) - \since 4.3 - - Shows a balloon message for the entry with the given \a title, \a message and - \a icon for the time specified in \a millisecondsTimeoutHint. \a title and \a message - must be plain text strings. - - Message can be clicked by the user; the messageClicked() signal will emitted when - this occurs. - - Note that display of messages are dependent on the system configuration and user - preferences, and that messages may not appear at all. Hence, it should not be - relied upon as the sole means for providing critical information. - - On Windows, the \a millisecondsTimeoutHint is usually ignored by the system - when the application has focus. - - On Mac OS X, the Growl notification system must be installed for this function to - display messages. - - \sa show() supportsMessages() - */ -void QSystemTrayIcon::showMessage(const QString& title, const QString& msg, - QSystemTrayIcon::MessageIcon icon, int msecs) -{ - Q_D(QSystemTrayIcon); - if (d->visible) - d->showMessage_sys(title, msg, icon, msecs); -} - -////////////////////////////////////////////////////////////////////// -static QBalloonTip *theSolitaryBalloonTip = 0; - -void QBalloonTip::showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title, - const QString& message, QSystemTrayIcon *trayIcon, - const QPoint& pos, int timeout, bool showArrow) -{ - hideBalloon(); - if (message.isEmpty() && title.isEmpty()) - return; - - theSolitaryBalloonTip = new QBalloonTip(icon, title, message, trayIcon); - if (timeout < 0) - timeout = 10000; //10 s default - theSolitaryBalloonTip->balloon(pos, timeout, showArrow); -} - -void QBalloonTip::hideBalloon() -{ - if (!theSolitaryBalloonTip) - return; - theSolitaryBalloonTip->hide(); - delete theSolitaryBalloonTip; - theSolitaryBalloonTip = 0; -} - -bool QBalloonTip::isBalloonVisible() -{ - return theSolitaryBalloonTip; -} - -QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title, - const QString& message, QSystemTrayIcon *ti) - : QWidget(0, Qt::ToolTip), trayIcon(ti), timerId(-1) -{ - setAttribute(Qt::WA_DeleteOnClose); - QObject::connect(ti, SIGNAL(destroyed()), this, SLOT(close())); - - QLabel *titleLabel = new QLabel; - titleLabel->installEventFilter(this); - titleLabel->setText(title); - QFont f = titleLabel->font(); - f.setBold(true); -#ifdef Q_WS_WINCE - f.setPointSize(f.pointSize() - 2); -#endif - titleLabel->setFont(f); - titleLabel->setTextFormat(Qt::PlainText); // to maintain compat with windows - -#ifdef Q_WS_WINCE - const int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize); - const int closeButtonSize = style()->pixelMetric(QStyle::PM_SmallIconSize) - 2; -#else - const int iconSize = 18; - const int closeButtonSize = 15; -#endif - - QPushButton *closeButton = new QPushButton; - closeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton)); - closeButton->setIconSize(QSize(closeButtonSize, closeButtonSize)); - closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - closeButton->setFixedSize(closeButtonSize, closeButtonSize); - QObject::connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); - - QLabel *msgLabel = new QLabel; -#ifdef Q_WS_WINCE - f.setBold(false); - msgLabel->setFont(f); -#endif - msgLabel->installEventFilter(this); - msgLabel->setText(message); - msgLabel->setTextFormat(Qt::PlainText); - msgLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft); - - // smart size for the message label -#ifdef Q_WS_WINCE - int limit = QApplication::desktop()->availableGeometry(msgLabel).size().width() / 2; -#else - int limit = QApplication::desktop()->availableGeometry(msgLabel).size().width() / 3; -#endif - if (msgLabel->sizeHint().width() > limit) { - msgLabel->setWordWrap(true); - if (msgLabel->sizeHint().width() > limit) { - msgLabel->d_func()->ensureTextControl(); - if (QTextControl *control = msgLabel->d_func()->control) { - QTextOption opt = control->document()->defaultTextOption(); - opt.setWrapMode(QTextOption::WrapAnywhere); - control->document()->setDefaultTextOption(opt); - } - } -#ifdef Q_WS_WINCE - // Make sure that the text isn't wrapped "somewhere" in the balloon widget - // in the case that we have a long title label. - setMaximumWidth(limit); -#else - // Here we allow the text being much smaller than the balloon widget - // to emulate the weird standard windows behavior. - msgLabel->setFixedSize(limit, msgLabel->heightForWidth(limit)); -#endif - } - - QIcon si; - switch (icon) { - case QSystemTrayIcon::Warning: - si = style()->standardIcon(QStyle::SP_MessageBoxWarning); - break; - case QSystemTrayIcon::Critical: - si = style()->standardIcon(QStyle::SP_MessageBoxCritical); - break; - case QSystemTrayIcon::Information: - si = style()->standardIcon(QStyle::SP_MessageBoxInformation); - break; - case QSystemTrayIcon::NoIcon: - default: - break; - } - - QGridLayout *layout = new QGridLayout; - if (!si.isNull()) { - QLabel *iconLabel = new QLabel; - iconLabel->setPixmap(si.pixmap(iconSize, iconSize)); - iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - iconLabel->setMargin(2); - layout->addWidget(iconLabel, 0, 0); - layout->addWidget(titleLabel, 0, 1); - } else { - layout->addWidget(titleLabel, 0, 0, 1, 2); - } - - layout->addWidget(closeButton, 0, 2); - layout->addWidget(msgLabel, 1, 0, 1, 3); - layout->setSizeConstraint(QLayout::SetFixedSize); - layout->setMargin(3); - setLayout(layout); - - QPalette pal = palette(); - pal.setColor(QPalette::Window, QColor(0xff, 0xff, 0xe1)); - pal.setColor(QPalette::WindowText, Qt::black); - setPalette(pal); -} - -QBalloonTip::~QBalloonTip() -{ - theSolitaryBalloonTip = 0; -} - -void QBalloonTip::paintEvent(QPaintEvent *) -{ - QPainter painter(this); - painter.drawPixmap(rect(), pixmap); -} - -void QBalloonTip::resizeEvent(QResizeEvent *ev) -{ - QWidget::resizeEvent(ev); -} - -void QBalloonTip::balloon(const QPoint& pos, int msecs, bool showArrow) -{ - QRect scr = QApplication::desktop()->screenGeometry(pos); - QSize sh = sizeHint(); - const int border = 1; - const int ah = 18, ao = 18, aw = 18, rc = 7; - bool arrowAtTop = (pos.y() + sh.height() + ah < scr.height()); - bool arrowAtLeft = (pos.x() + sh.width() - ao < scr.width()); - setContentsMargins(border + 3, border + (arrowAtTop ? ah : 0) + 2, border + 3, border + (arrowAtTop ? 0 : ah) + 2); - updateGeometry(); - sh = sizeHint(); - - int ml, mr, mt, mb; - QSize sz = sizeHint(); - if (!arrowAtTop) { - ml = mt = 0; - mr = sz.width() - 1; - mb = sz.height() - ah - 1; - } else { - ml = 0; - mt = ah; - mr = sz.width() - 1; - mb = sz.height() - 1; - } - - QPainterPath path; -#if defined(QT_NO_XSHAPE) && defined(Q_WS_X11) - // XShape is required for setting the mask, so we just - // draw an ugly square when its not available - path.moveTo(0, 0); - path.lineTo(sz.width() - 1, 0); - path.lineTo(sz.width() - 1, sz.height() - 1); - path.lineTo(0, sz.height() - 1); - path.lineTo(0, 0); - move(qMax(pos.x() - sz.width(), scr.left()), pos.y()); -#else - path.moveTo(ml + rc, mt); - if (arrowAtTop && arrowAtLeft) { - if (showArrow) { - path.lineTo(ml + ao, mt); - path.lineTo(ml + ao, mt - ah); - path.lineTo(ml + ao + aw, mt); - } - move(qMax(pos.x() - ao, scr.left() + 2), pos.y()); - } else if (arrowAtTop && !arrowAtLeft) { - if (showArrow) { - path.lineTo(mr - ao - aw, mt); - path.lineTo(mr - ao, mt - ah); - path.lineTo(mr - ao, mt); - } - move(qMin(pos.x() - sh.width() + ao, scr.right() - sh.width() - 2), pos.y()); - } - path.lineTo(mr - rc, mt); - path.arcTo(QRect(mr - rc*2, mt, rc*2, rc*2), 90, -90); - path.lineTo(mr, mb - rc); - path.arcTo(QRect(mr - rc*2, mb - rc*2, rc*2, rc*2), 0, -90); - if (!arrowAtTop && !arrowAtLeft) { - if (showArrow) { - path.lineTo(mr - ao, mb); - path.lineTo(mr - ao, mb + ah); - path.lineTo(mr - ao - aw, mb); - } - move(qMin(pos.x() - sh.width() + ao, scr.right() - sh.width() - 2), - pos.y() - sh.height()); - } else if (!arrowAtTop && arrowAtLeft) { - if (showArrow) { - path.lineTo(ao + aw, mb); - path.lineTo(ao, mb + ah); - path.lineTo(ao, mb); - } - move(qMax(pos.x() - ao, scr.x() + 2), pos.y() - sh.height()); - } - path.lineTo(ml + rc, mb); - path.arcTo(QRect(ml, mb - rc*2, rc*2, rc*2), -90, -90); - path.lineTo(ml, mt + rc); - path.arcTo(QRect(ml, mt, rc*2, rc*2), 180, -90); - - // Set the mask - QBitmap bitmap = QBitmap(sizeHint()); - bitmap.fill(Qt::color0); - QPainter painter1(&bitmap); - painter1.setPen(QPen(Qt::color1, border)); - painter1.setBrush(QBrush(Qt::color1)); - painter1.drawPath(path); - setMask(bitmap); -#endif - - // Draw the border - pixmap = QPixmap(sz); - QPainter painter2(&pixmap); - painter2.setPen(QPen(palette().color(QPalette::Window).darker(160), border)); - painter2.setBrush(palette().color(QPalette::Window)); - painter2.drawPath(path); - - if (msecs > 0) - timerId = startTimer(msecs); - show(); -} - -void QBalloonTip::mousePressEvent(QMouseEvent *e) -{ - close(); - if(e->button() == Qt::LeftButton) - emit trayIcon->messageClicked(); -} - -void QBalloonTip::timerEvent(QTimerEvent *e) -{ - if (e->timerId() == timerId) { - killTimer(timerId); - if (!underMouse()) - close(); - return; - } - QWidget::timerEvent(e); -} - -void qtsystray_sendActivated(QSystemTrayIcon *i, int r) -{ - emit i->activated((QSystemTrayIcon::ActivationReason)r); -} - -QT_END_NAMESPACE - -#endif // QT_NO_SYSTEMTRAYICON diff --git a/src/gui/util/qsystemtrayicon.h b/src/gui/util/qsystemtrayicon.h deleted file mode 100644 index 879a0d293f..0000000000 --- a/src/gui/util/qsystemtrayicon.h +++ /dev/null @@ -1,132 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSYSTEMTRAYICON_H -#define QSYSTEMTRAYICON_H - -#include <QtCore/qobject.h> - -#ifndef QT_NO_SYSTEMTRAYICON - -#include <QtGui/qicon.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QSystemTrayIconPrivate; - -class QMenu; -class QEvent; -class QWheelEvent; -class QMouseEvent; -class QPoint; - -class Q_GUI_EXPORT QSystemTrayIcon : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip) - Q_PROPERTY(QIcon icon READ icon WRITE setIcon) - Q_PROPERTY(bool visible READ isVisible WRITE setVisible DESIGNABLE false) - -public: - QSystemTrayIcon(QObject *parent = 0); - QSystemTrayIcon(const QIcon &icon, QObject *parent = 0); - ~QSystemTrayIcon(); - - enum ActivationReason { - Unknown, - Context, - DoubleClick, - Trigger, - MiddleClick - }; - -#ifndef QT_NO_MENU - void setContextMenu(QMenu *menu); - QMenu *contextMenu() const; -#endif - - QIcon icon() const; - void setIcon(const QIcon &icon); - - QString toolTip() const; - void setToolTip(const QString &tip); - - static bool isSystemTrayAvailable(); - static bool supportsMessages(); - - enum MessageIcon { NoIcon, Information, Warning, Critical }; - void showMessage(const QString &title, const QString &msg, - MessageIcon icon = Information, int msecs = 10000); - - QRect geometry() const; - bool isVisible() const; - -public Q_SLOTS: - void setVisible(bool visible); - inline void show() { setVisible(true); } - inline void hide() { setVisible(false); } - -Q_SIGNALS: - void activated(QSystemTrayIcon::ActivationReason reason); - void messageClicked(); - -protected: - bool event(QEvent *event); - -private: - Q_DISABLE_COPY(QSystemTrayIcon) - Q_DECLARE_PRIVATE(QSystemTrayIcon) - - friend class QSystemTrayIconSys; - friend class QBalloonTip; - friend void qtsystray_sendActivated(QSystemTrayIcon *, int); -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QT_NO_SYSTEMTRAYICON -#endif // QSYSTEMTRAYICON_H diff --git a/src/gui/util/qsystemtrayicon_mac.mm b/src/gui/util/qsystemtrayicon_mac.mm deleted file mode 100644 index 4186ac3e55..0000000000 --- a/src/gui/util/qsystemtrayicon_mac.mm +++ /dev/null @@ -1,578 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Copyright (c) 2007-2008, Apple, Inc. -** -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are met: -** -** * Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** -** * Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** -** * Neither the name of Apple, Inc. nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -****************************************************************************/ - -#define QT_MAC_SYSTEMTRAY_USE_GROWL - -#include <private/qt_cocoa_helpers_mac_p.h> -#include <private/qsystemtrayicon_p.h> -#include <qtemporaryfile.h> -#include <qimagewriter.h> -#include <qapplication.h> -#include <qdebug.h> -#include <qstyle.h> - -#include <private/qt_mac_p.h> -#import <AppKit/AppKit.h> - -QT_BEGIN_NAMESPACE -extern bool qt_mac_execute_apple_script(const QString &script, AEDesc *ret); //qapplication_mac.cpp -extern void qtsystray_sendActivated(QSystemTrayIcon *i, int r); //qsystemtrayicon.cpp -extern NSString *keySequenceToKeyEqivalent(const QKeySequence &accel); // qmenu_mac.mm -extern NSUInteger keySequenceModifierMask(const QKeySequence &accel); // qmenu_mac.mm -extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); -QT_END_NAMESPACE - -QT_USE_NAMESPACE - -@class QT_MANGLE_NAMESPACE(QNSMenu); -@class QT_MANGLE_NAMESPACE(QNSImageView); - -@interface QT_MANGLE_NAMESPACE(QNSStatusItem) : NSObject { - NSStatusItem *item; - QSystemTrayIcon *icon; - QSystemTrayIconPrivate *iconPrivate; - QT_MANGLE_NAMESPACE(QNSImageView) *imageCell; -} --(id)initWithIcon:(QSystemTrayIcon*)icon iconPrivate:(QSystemTrayIconPrivate *)iprivate; --(void)dealloc; --(QSystemTrayIcon*)icon; --(NSStatusItem*)item; --(QRectF)geometry; -- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton; -- (void)doubleClickSelector:(id)sender; -@end - -@interface QT_MANGLE_NAMESPACE(QNSImageView) : NSImageView { - BOOL down; - QT_MANGLE_NAMESPACE(QNSStatusItem) *parent; -} --(id)initWithParent:(QT_MANGLE_NAMESPACE(QNSStatusItem)*)myParent; --(QSystemTrayIcon*)icon; --(void)menuTrackingDone:(NSNotification*)notification; --(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton; -@end - - -#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 - -@protocol NSMenuDelegate <NSObject> --(void)menuNeedsUpdate:(NSMenu*)menu; -@end -#endif - - -@interface QT_MANGLE_NAMESPACE(QNSMenu) : NSMenu <NSMenuDelegate> { - QMenu *qmenu; -} --(QMenu*)menu; --(id)initWithQMenu:(QMenu*)qmenu; --(void)selectedAction:(id)item; -@end - -QT_BEGIN_NAMESPACE -class QSystemTrayIconSys -{ -public: - QSystemTrayIconSys(QSystemTrayIcon *icon, QSystemTrayIconPrivate *d) { - QMacCocoaAutoReleasePool pool; - item = [[QT_MANGLE_NAMESPACE(QNSStatusItem) alloc] initWithIcon:icon iconPrivate:d]; - } - ~QSystemTrayIconSys() { - QMacCocoaAutoReleasePool pool; - [[[item item] view] setHidden: YES]; - [item release]; - } - QT_MANGLE_NAMESPACE(QNSStatusItem) *item; -}; - -void QSystemTrayIconPrivate::install_sys() -{ - Q_Q(QSystemTrayIcon); - if (!sys) { - sys = new QSystemTrayIconSys(q, this); - updateIcon_sys(); - updateMenu_sys(); - updateToolTip_sys(); - } -} - -QRect QSystemTrayIconPrivate::geometry_sys() const -{ - if(sys) { - const QRectF geom = [sys->item geometry]; - if(!geom.isNull()) - return geom.toRect(); - } - return QRect(); -} - -void QSystemTrayIconPrivate::remove_sys() -{ - delete sys; - sys = 0; -} - -void QSystemTrayIconPrivate::updateIcon_sys() -{ - if(sys && !icon.isNull()) { - QMacCocoaAutoReleasePool pool; -#ifndef QT_MAC_USE_COCOA - const short scale = GetMBarHeight()-4; -#else - CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; - const short scale = hgt - 4; -#endif - NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(icon.pixmap(QSize(scale, scale)))); - [(NSImageView*)[[sys->item item] view] setImage: nsimage]; - [nsimage release]; - } -} - -void QSystemTrayIconPrivate::updateMenu_sys() -{ - if(sys) { - QMacCocoaAutoReleasePool pool; - if(menu && !menu->isEmpty()) { - [[sys->item item] setHighlightMode:YES]; - } else { - [[sys->item item] setHighlightMode:NO]; - } - } -} - -void QSystemTrayIconPrivate::updateToolTip_sys() -{ - if(sys) { - QMacCocoaAutoReleasePool pool; - QCFString string(toolTip); - [[[sys->item item] view] setToolTip:(NSString*)static_cast<CFStringRef>(string)]; - } -} - -bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys() -{ - return true; -} - -bool QSystemTrayIconPrivate::supportsMessages_sys() -{ - return true; -} - -void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon icon, int) -{ - - if(sys) { -#ifdef QT_MAC_SYSTEMTRAY_USE_GROWL - // Make sure that we have Growl installed on the machine we are running on. - QCFType<CFURLRef> cfurl; - OSStatus status = LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, - CFSTR("growlTicket"), kLSRolesAll, 0, &cfurl); - if (status == kLSApplicationNotFoundErr) - return; - QCFType<CFBundleRef> bundle = CFBundleCreate(0, cfurl); - - if (CFStringCompare(CFBundleGetIdentifier(bundle), CFSTR("com.Growl.GrowlHelperApp"), - kCFCompareCaseInsensitive | kCFCompareBackwards) != kCFCompareEqualTo) - return; - QPixmap notificationIconPixmap; - if(icon == QSystemTrayIcon::Information) - notificationIconPixmap = QApplication::style()->standardPixmap(QStyle::SP_MessageBoxInformation); - else if(icon == QSystemTrayIcon::Warning) - notificationIconPixmap = QApplication::style()->standardPixmap(QStyle::SP_MessageBoxWarning); - else if(icon == QSystemTrayIcon::Critical) - notificationIconPixmap = QApplication::style()->standardPixmap(QStyle::SP_MessageBoxCritical); - QTemporaryFile notificationIconFile; - QString notificationType(QLatin1String("Notification")), notificationIcon, notificationApp(QApplication::applicationName()); - if(notificationApp.isEmpty()) - notificationApp = QLatin1String("Application"); - if(!notificationIconPixmap.isNull() && notificationIconFile.open()) { - QImageWriter writer(¬ificationIconFile, "PNG"); - if(writer.write(notificationIconPixmap.toImage())) - notificationIcon = QLatin1String("image from location \"file://") + notificationIconFile.fileName() + QLatin1String("\""); - } - const QString script(QLatin1String( - "tell application \"GrowlHelperApp\"\n" - "-- Make a list of all the notification types (all)\n" - "set the allNotificationsList to {\"") + notificationType + QLatin1String("\"}\n" - - "-- Make a list of the notifications (enabled)\n" - "set the enabledNotificationsList to {\"") + notificationType + QLatin1String("\"}\n" - - "-- Register our script with growl.\n" - "register as application \"") + notificationApp + QLatin1String("\" all notifications allNotificationsList default notifications enabledNotificationsList\n" - - "-- Send a Notification...\n") + - QLatin1String("notify with name \"") + notificationType + - QLatin1String("\" title \"") + title + - QLatin1String("\" description \"") + message + - QLatin1String("\" application name \"") + notificationApp + - QLatin1String("\" ") + notificationIcon + - QLatin1String("\nend tell")); - qt_mac_execute_apple_script(script, 0); -#elif 0 - Q_Q(QSystemTrayIcon); - NSView *v = [[sys->item item] view]; - NSWindow *w = [v window]; - w = [[sys->item item] window]; - qDebug() << w << v; - QPoint p(qRound([w frame].origin.x), qRound([w frame].origin.y)); - qDebug() << p; - QBalloonTip::showBalloon(icon, message, title, q, QPoint(0, 0), msecs); -#else - Q_UNUSED(icon); - Q_UNUSED(title); - Q_UNUSED(message); -#endif - } -} -QT_END_NAMESPACE - -@implementation NSStatusItem (Qt) -@end - -@implementation QT_MANGLE_NAMESPACE(QNSImageView) --(id)initWithParent:(QT_MANGLE_NAMESPACE(QNSStatusItem)*)myParent { - self = [super init]; - parent = myParent; - down = NO; - return self; -} - --(QSystemTrayIcon*)icon { - return [parent icon]; -} - --(void)menuTrackingDone:(NSNotification*)notification -{ - Q_UNUSED(notification); - down = NO; - - if( ![self icon]->icon().isNull() ) { -#ifndef QT_MAC_USE_COCOA - const short scale = GetMBarHeight()-4; -#else - CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; - const short scale = hgt - 4; -#endif - NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage([self icon]->icon().pixmap(QSize(scale, scale)))); - [self setImage: nsimage]; - [nsimage release]; - } - - if([self icon]->contextMenu()) - [self icon]->contextMenu()->hide(); - - [self setNeedsDisplay:YES]; -} - --(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton -{ - down = YES; - int clickCount = [mouseEvent clickCount]; - [self setNeedsDisplay:YES]; - -#ifndef QT_MAC_USE_COCOA - const short scale = GetMBarHeight()-4; -#else - CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; - const short scale = hgt - 4; -#endif - - if (![self icon]->icon().isNull() ) { - NSImage *nsaltimage = static_cast<NSImage *>(qt_mac_create_nsimage([self icon]->icon().pixmap(QSize(scale, scale), QIcon::Selected))); - [self setImage: nsaltimage]; - [nsaltimage release]; - } - - if ((clickCount == 2)) { - [self menuTrackingDone:nil]; - [parent doubleClickSelector:self]; - } else { - [parent triggerSelector:self button:mouseButton]; - } -} - --(void)mouseDown:(NSEvent *)mouseEvent -{ - [self mousePressed:mouseEvent button:Qt::LeftButton]; -} - --(void)mouseUp:(NSEvent *)mouseEvent -{ - Q_UNUSED(mouseEvent); - [self menuTrackingDone:nil]; -} - -- (void)rightMouseDown:(NSEvent *)mouseEvent -{ - [self mousePressed:mouseEvent button:Qt::RightButton]; -} - --(void)rightMouseUp:(NSEvent *)mouseEvent -{ - Q_UNUSED(mouseEvent); - [self menuTrackingDone:nil]; -} - -- (void)otherMouseDown:(NSEvent *)mouseEvent -{ - [self mousePressed:mouseEvent button:cocoaButton2QtButton([mouseEvent buttonNumber])]; -} - --(void)otherMouseUp:(NSEvent *)mouseEvent -{ - Q_UNUSED(mouseEvent); - [self menuTrackingDone:nil]; -} - --(void)drawRect:(NSRect)rect { - [[parent item] drawStatusBarBackgroundInRect:rect withHighlight:down]; - [super drawRect:rect]; -} -@end - -@implementation QT_MANGLE_NAMESPACE(QNSStatusItem) - --(id)initWithIcon:(QSystemTrayIcon*)i iconPrivate:(QSystemTrayIconPrivate *)iPrivate -{ - self = [super init]; - if(self) { - icon = i; - iconPrivate = iPrivate; - item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain]; - imageCell = [[QT_MANGLE_NAMESPACE(QNSImageView) alloc] initWithParent:self]; - [item setView: imageCell]; - } - return self; -} --(void)dealloc { - [[NSStatusBar systemStatusBar] removeStatusItem:item]; - [imageCell release]; - [item release]; - [super dealloc]; - -} - --(QSystemTrayIcon*)icon { - return icon; -} - --(NSStatusItem*)item { - return item; -} --(QRectF)geometry { - if(NSWindow *window = [[item view] window]) { - NSRect screenRect = [[window screen] frame]; - NSRect windowRect = [window frame]; - return QRectF(windowRect.origin.x, screenRect.size.height-windowRect.origin.y-windowRect.size.height, windowRect.size.width, windowRect.size.height); - } - return QRectF(); -} - -- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton { - Q_UNUSED(sender); - if (!icon) - return; - - if (mouseButton == Qt::MidButton) - qtsystray_sendActivated(icon, QSystemTrayIcon::MiddleClick); - else - qtsystray_sendActivated(icon, QSystemTrayIcon::Trigger); - - if (icon->contextMenu()) { -#ifndef QT_MAC_USE_COCOA - [[[self item] view] removeAllToolTips]; - iconPrivate->updateToolTip_sys(); -#endif - NSMenu *m = [[QT_MANGLE_NAMESPACE(QNSMenu) alloc] initWithQMenu:icon->contextMenu()]; - [m setAutoenablesItems: NO]; - [[NSNotificationCenter defaultCenter] addObserver:imageCell - selector:@selector(menuTrackingDone:) - name:NSMenuDidEndTrackingNotification - object:m]; - [item popUpStatusItemMenu: m]; - [m release]; - } -} - -- (void)doubleClickSelector:(id)sender { - Q_UNUSED(sender); - if(!icon) - return; - qtsystray_sendActivated(icon, QSystemTrayIcon::DoubleClick); -} - -@end - -class QSystemTrayIconQMenu : public QMenu -{ -public: - void doAboutToShow() { emit aboutToShow(); } -private: - QSystemTrayIconQMenu(); -}; - -@implementation QT_MANGLE_NAMESPACE(QNSMenu) --(id)initWithQMenu:(QMenu*)qm { - self = [super init]; - if(self) { - self->qmenu = qm; - [self setDelegate:self]; - } - return self; -} --(QMenu*)menu { - return qmenu; -} --(void)menuNeedsUpdate:(NSMenu*)nsmenu { - QT_MANGLE_NAMESPACE(QNSMenu) *menu = static_cast<QT_MANGLE_NAMESPACE(QNSMenu) *>(nsmenu); - emit static_cast<QSystemTrayIconQMenu*>(menu->qmenu)->doAboutToShow(); - for(int i = [menu numberOfItems]-1; i >= 0; --i) - [menu removeItemAtIndex:i]; - QList<QAction*> actions = menu->qmenu->actions();; - for(int i = 0; i < actions.size(); ++i) { - const QAction *action = actions[i]; - if(!action->isVisible()) - continue; - - NSMenuItem *item = 0; - bool needRelease = false; - if(action->isSeparator()) { - item = [NSMenuItem separatorItem]; - } else { - item = [[NSMenuItem alloc] init]; - needRelease = true; - QString text = action->text(); - QKeySequence accel = action->shortcut(); - { - int st = text.lastIndexOf(QLatin1Char('\t')); - if(st != -1) { - accel = QKeySequence(text.right(text.length()-(st+1))); - text.remove(st, text.length()-st); - } - } - if(accel.count() > 1) - text += QLatin1String(" (****)"); //just to denote a multi stroke shortcut - - [item setTitle:(NSString*)QCFString::toCFStringRef(qt_mac_removeMnemonics(text))]; - [item setEnabled:menu->qmenu->isEnabled() && action->isEnabled()]; - [item setState:action->isChecked() ? NSOnState : NSOffState]; - [item setToolTip:(NSString*)QCFString::toCFStringRef(action->toolTip())]; - const QIcon icon = action->icon(); - if(!icon.isNull()) { -#ifndef QT_MAC_USE_COCOA - const short scale = GetMBarHeight(); -#else - const short scale = [[NSApp mainMenu] menuBarHeight]; -#endif - NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(icon.pixmap(QSize(scale, scale)))); - [item setImage: nsimage]; - [nsimage release]; - } - if(action->menu()) { - QT_MANGLE_NAMESPACE(QNSMenu) *sub = [[QT_MANGLE_NAMESPACE(QNSMenu) alloc] initWithQMenu:action->menu()]; - [item setSubmenu:sub]; - } else { - [item setAction:@selector(selectedAction:)]; - [item setTarget:self]; - } - if(!accel.isEmpty()) { - [item setKeyEquivalent:keySequenceToKeyEqivalent(accel)]; - [item setKeyEquivalentModifierMask:keySequenceModifierMask(accel)]; - } - } - if(item) - [menu addItem:item]; - if (needRelease) - [item release]; - } -} --(void)selectedAction:(id)a { - const int activated = [self indexOfItem:a]; - QAction *action = 0; - QList<QAction*> actions = qmenu->actions(); - for(int i = 0, cnt = 0; i < actions.size(); ++i) { - if(actions.at(i)->isVisible() && (cnt++) == activated) { - action = actions.at(i); - break; - } - } - if(action) { - action->activate(QAction::Trigger); - } -} -@end - diff --git a/src/gui/util/qsystemtrayicon_p.h b/src/gui/util/qsystemtrayicon_p.h deleted file mode 100644 index 14495eee59..0000000000 --- a/src/gui/util/qsystemtrayicon_p.h +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSYSTEMTRAYICON_P_H -#define QSYSTEMTRAYICON_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of a number of Qt sources files. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include "qsystemtrayicon.h" -#include "private/qobject_p.h" - -#ifndef QT_NO_SYSTEMTRAYICON - -#include "QtGui/qmenu.h" -#include "QtGui/qpixmap.h" -#include "QtCore/qstring.h" -#include "QtCore/qpointer.h" - -QT_BEGIN_NAMESPACE - -class QSystemTrayIconSys; -class QToolButton; -class QLabel; - -class QSystemTrayIconPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QSystemTrayIcon) - -public: - QSystemTrayIconPrivate() : sys(0), visible(false) { } - - void install_sys(); - void remove_sys(); - void updateIcon_sys(); - void updateToolTip_sys(); - void updateMenu_sys(); - QRect geometry_sys() const; - void showMessage_sys(const QString &msg, const QString &title, QSystemTrayIcon::MessageIcon icon, int secs); - - static bool isSystemTrayAvailable_sys(); - static bool supportsMessages_sys(); - - QPointer<QMenu> menu; - QIcon icon; - QString toolTip; - QSystemTrayIconSys *sys; - bool visible; -}; - -class QBalloonTip : public QWidget -{ - Q_OBJECT -public: - static void showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title, - const QString& msg, QSystemTrayIcon *trayIcon, - const QPoint& pos, int timeout, bool showArrow = true); - static void hideBalloon(); - static bool isBalloonVisible(); - -private: - QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title, - const QString& msg, QSystemTrayIcon *trayIcon); - ~QBalloonTip(); - void balloon(const QPoint&, int, bool); - -protected: - void paintEvent(QPaintEvent *); - void resizeEvent(QResizeEvent *); - void mousePressEvent(QMouseEvent *e); - void timerEvent(QTimerEvent *e); - -private: - QSystemTrayIcon *trayIcon; - QPixmap pixmap; - int timerId; -}; - -#if defined(Q_WS_X11) -QT_BEGIN_INCLUDE_NAMESPACE -#include <QtCore/qcoreapplication.h> -#include <X11/Xlib.h> -#include <X11/Xatom.h> -#include <X11/Xutil.h> -QT_END_INCLUDE_NAMESPACE - -class QSystemTrayIconSys : public QWidget -{ - friend class QSystemTrayIconPrivate; - -public: - QSystemTrayIconSys(QSystemTrayIcon *q); - ~QSystemTrayIconSys(); - enum { - SYSTEM_TRAY_REQUEST_DOCK = 0, - SYSTEM_TRAY_BEGIN_MESSAGE = 1, - SYSTEM_TRAY_CANCEL_MESSAGE =2 - }; - - void addToTray(); - void updateIcon(); - XVisualInfo* getSysTrayVisualInfo(); - - // QObject::event is public but QWidget's ::event() re-implementation - // is protected ;( - inline bool deliverToolTipEvent(QEvent *e) - { return QWidget::event(e); } - - static Window sysTrayWindow; - static QList<QSystemTrayIconSys *> trayIcons; - static QCoreApplication::EventFilter oldEventFilter; - static bool sysTrayTracker(void *message, long *result); - static Window locateSystemTray(); - static Atom sysTraySelection; - static XVisualInfo sysTrayVisual; - -protected: - void paintEvent(QPaintEvent *pe); - void resizeEvent(QResizeEvent *re); - bool x11Event(XEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseDoubleClickEvent(QMouseEvent *event); -#ifndef QT_NO_WHEELEVENT - void wheelEvent(QWheelEvent *event); -#endif - bool event(QEvent *e); - -private: - QPixmap background; - QSystemTrayIcon *q; - Colormap colormap; -}; -#endif // Q_WS_X11 - -QT_END_NAMESPACE - -#endif // QT_NO_SYSTEMTRAYICON - -#endif // QSYSTEMTRAYICON_P_H - diff --git a/src/gui/util/qsystemtrayicon_qws.cpp b/src/gui/util/qsystemtrayicon_qws.cpp deleted file mode 100644 index 9a4f12d02d..0000000000 --- a/src/gui/util/qsystemtrayicon_qws.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsystemtrayicon_p.h" - -#ifndef QT_NO_SYSTEMTRAYICON - -QT_BEGIN_NAMESPACE - -void QSystemTrayIconPrivate::install_sys() -{ -} - -void QSystemTrayIconPrivate::remove_sys() -{ -} - -QRect QSystemTrayIconPrivate::geometry_sys() const -{ - return QRect(); -} - -void QSystemTrayIconPrivate::updateIcon_sys() -{ -} - -void QSystemTrayIconPrivate::updateMenu_sys() -{ -} - -void QSystemTrayIconPrivate::updateToolTip_sys() -{ -} - -bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys() -{ - return false; -} - -bool QSystemTrayIconPrivate::supportsMessages_sys() -{ - return false; -} - -void QSystemTrayIconPrivate::showMessage_sys(const QString &message, - const QString &title, - QSystemTrayIcon::MessageIcon icon, - int msecs) -{ - Q_UNUSED(message); - Q_UNUSED(title); - Q_UNUSED(icon); - Q_UNUSED(msecs); -} - -QT_END_NAMESPACE - -#endif // QT_NO_SYSTEMTRAYICON diff --git a/src/gui/util/qsystemtrayicon_win.cpp b/src/gui/util/qsystemtrayicon_win.cpp deleted file mode 100644 index 7a572849b0..0000000000 --- a/src/gui/util/qsystemtrayicon_win.cpp +++ /dev/null @@ -1,524 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsystemtrayicon_p.h" -#ifndef QT_NO_SYSTEMTRAYICON - -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 -#endif - -#ifndef _WIN32_IE -#define _WIN32_IE 0x600 -#endif - -#include <qt_windows.h> -#include <windowsx.h> -#include <commctrl.h> - -#include <private/qsystemlibrary_p.h> -#include <QApplication> -#include <QSettings> - -QT_BEGIN_NAMESPACE - -static const UINT q_uNOTIFYICONID = 0; - -static uint MYWM_TASKBARCREATED = 0; -#define MYWM_NOTIFYICON (WM_APP+101) - -struct Q_NOTIFYICONIDENTIFIER { - DWORD cbSize; - HWND hWnd; - UINT uID; - GUID guidItem; -}; - -#ifndef NOTIFYICON_VERSION_4 -#define NOTIFYICON_VERSION_4 4 -#endif - -#ifndef NIN_SELECT -#define NIN_SELECT (WM_USER + 0) -#endif - -#ifndef NIN_KEYSELECT -#define NIN_KEYSELECT (WM_USER + 1) -#endif - -#ifndef NIN_BALLOONTIMEOUT -#define NIN_BALLOONTIMEOUT (WM_USER + 4) -#endif - -#ifndef NIN_BALLOONUSERCLICK -#define NIN_BALLOONUSERCLICK (WM_USER + 5) -#endif - -#ifndef NIF_SHOWTIP -#define NIF_SHOWTIP 0x00000080 -#endif - -#define Q_MSGFLT_ALLOW 1 - -typedef HRESULT (WINAPI *PtrShell_NotifyIconGetRect)(const Q_NOTIFYICONIDENTIFIER* identifier, RECT* iconLocation); -typedef BOOL (WINAPI *PtrChangeWindowMessageFilter)(UINT message, DWORD dwFlag); -typedef BOOL (WINAPI *PtrChangeWindowMessageFilterEx)(HWND hWnd, UINT message, DWORD action, void* pChangeFilterStruct); - -class QSystemTrayIconSys : QWidget -{ -public: - QSystemTrayIconSys(QSystemTrayIcon *object); - ~QSystemTrayIconSys(); - bool winEvent( MSG *m, long *result ); - bool trayMessage(DWORD msg); - void setIconContents(NOTIFYICONDATA &data); - bool showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs); - QRect findIconGeometry(const int a_iButtonID); - void createIcon(); - HICON hIcon; - QPoint globalPos; - QSystemTrayIcon *q; -private: - uint notifyIconSize; - int maxTipLength; - int version; - bool ignoreNextMouseRelease; -}; - -static bool allowsMessages() -{ -#ifndef QT_NO_SETTINGS - QSettings settings(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft" - "\\Windows\\CurrentVersion\\Explorer\\Advanced"), QSettings::NativeFormat); - return settings.value(QLatin1String("EnableBalloonTips"), true).toBool(); -#else - return false; -#endif -} - -QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *object) - : hIcon(0), q(object), ignoreNextMouseRelease(false) - -{ - if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) { - notifyIconSize = sizeof(NOTIFYICONDATA); - version = NOTIFYICON_VERSION_4; - } else { - notifyIconSize = NOTIFYICONDATA_V2_SIZE; - version = NOTIFYICON_VERSION; - } - - maxTipLength = 128; - - // For restoring the tray icon after explorer crashes - if (!MYWM_TASKBARCREATED) { - MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated"); - } - - // Allow the WM_TASKBARCREATED message through the UIPI filter on Windows Vista and higher - static PtrChangeWindowMessageFilterEx pChangeWindowMessageFilterEx = - (PtrChangeWindowMessageFilterEx)QSystemLibrary::resolve(QLatin1String("user32"), "ChangeWindowMessageFilterEx"); - - if (pChangeWindowMessageFilterEx) { - // Call the safer ChangeWindowMessageFilterEx API if available - pChangeWindowMessageFilterEx(winId(), MYWM_TASKBARCREATED, Q_MSGFLT_ALLOW, 0); - } else { - static PtrChangeWindowMessageFilter pChangeWindowMessageFilter = - (PtrChangeWindowMessageFilter)QSystemLibrary::resolve(QLatin1String("user32"), "ChangeWindowMessageFilter"); - - if (pChangeWindowMessageFilter) { - // Call the deprecated ChangeWindowMessageFilter API otherwise - pChangeWindowMessageFilter(MYWM_TASKBARCREATED, Q_MSGFLT_ALLOW); - } - } -} - -QSystemTrayIconSys::~QSystemTrayIconSys() -{ - if (hIcon) - DestroyIcon(hIcon); -} - -void QSystemTrayIconSys::setIconContents(NOTIFYICONDATA &tnd) -{ - tnd.uFlags |= NIF_MESSAGE | NIF_ICON | NIF_TIP; - tnd.uCallbackMessage = MYWM_NOTIFYICON; - tnd.hIcon = hIcon; - QString tip = q->toolTip(); - - if (!tip.isNull()) { - tip = tip.left(maxTipLength - 1) + QChar(); - memcpy(tnd.szTip, tip.utf16(), qMin(tip.length() + 1, maxTipLength) * sizeof(wchar_t)); - } -} - -static int iconFlag( QSystemTrayIcon::MessageIcon icon ) -{ - switch (icon) { - case QSystemTrayIcon::Information: - return NIIF_INFO; - case QSystemTrayIcon::Warning: - return NIIF_WARNING; - case QSystemTrayIcon::Critical: - return NIIF_ERROR; - case QSystemTrayIcon::NoIcon: - return NIIF_NONE; - default: - Q_ASSERT_X(false, "QSystemTrayIconSys::showMessage", "Invalid QSystemTrayIcon::MessageIcon value"); - return NIIF_NONE; - } -} - -bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs) -{ - NOTIFYICONDATA tnd; - memset(&tnd, 0, notifyIconSize); - - memcpy(tnd.szInfo, message.utf16(), qMin(message.length() + 1, 256) * sizeof(wchar_t)); - memcpy(tnd.szInfoTitle, title.utf16(), qMin(title.length() + 1, 64) * sizeof(wchar_t)); - - tnd.uID = q_uNOTIFYICONID; - tnd.dwInfoFlags = iconFlag(type); - tnd.cbSize = notifyIconSize; - tnd.hWnd = winId(); - tnd.uTimeout = uSecs; - tnd.uFlags = NIF_INFO | NIF_SHOWTIP; - - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - - return Shell_NotifyIcon(NIM_MODIFY, &tnd); -} - -bool QSystemTrayIconSys::trayMessage(DWORD msg) -{ - NOTIFYICONDATA tnd; - memset(&tnd, 0, notifyIconSize); - - tnd.uID = q_uNOTIFYICONID; - tnd.cbSize = notifyIconSize; - tnd.hWnd = winId(); - tnd.uFlags = NIF_SHOWTIP; - tnd.uVersion = version; - - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - - if (msg == NIM_ADD || msg == NIM_MODIFY) { - setIconContents(tnd); - } - - bool success = Shell_NotifyIcon(msg, &tnd); - - if (msg == NIM_ADD) - return success && Shell_NotifyIcon(NIM_SETVERSION, &tnd); - else - return success; -} - -void QSystemTrayIconSys::createIcon() -{ - hIcon = 0; - QIcon icon = q->icon(); - if (icon.isNull()) - return; - - const int iconSizeX = GetSystemMetrics(SM_CXSMICON); - const int iconSizeY = GetSystemMetrics(SM_CYSMICON); - QSize size = icon.actualSize(QSize(iconSizeX, iconSizeY)); - QPixmap pm = icon.pixmap(size); - if (pm.isNull()) - return; - - hIcon = pm.toWinHICON(); -} - -bool QSystemTrayIconSys::winEvent( MSG *m, long *result ) -{ - switch(m->message) { - case MYWM_NOTIFYICON: - { - int message = 0; - QPoint gpos; - - if (version == NOTIFYICON_VERSION_4) { - Q_ASSERT(q_uNOTIFYICONID == HIWORD(m->lParam)); - message = LOWORD(m->lParam); - gpos = QPoint(GET_X_LPARAM(m->wParam), GET_Y_LPARAM(m->wParam)); - } else { - Q_ASSERT(q_uNOTIFYICONID == m->wParam); - message = m->lParam; - gpos = QCursor::pos(); - } - - switch (message) { - case NIN_SELECT: - case NIN_KEYSELECT: - if (ignoreNextMouseRelease) - ignoreNextMouseRelease = false; - else - emit q->activated(QSystemTrayIcon::Trigger); - break; - - case WM_LBUTTONDBLCLK: - ignoreNextMouseRelease = true; // Since DBLCLICK Generates a second mouse - // release we must ignore it - emit q->activated(QSystemTrayIcon::DoubleClick); - break; - - case WM_CONTEXTMENU: - if (q->contextMenu()) { - q->contextMenu()->popup(gpos); - q->contextMenu()->activateWindow(); - } - emit q->activated(QSystemTrayIcon::Context); - break; - - case NIN_BALLOONUSERCLICK: - emit q->messageClicked(); - break; - - case WM_MBUTTONUP: - emit q->activated(QSystemTrayIcon::MiddleClick); - break; - - default: - break; - } - break; - } - default: - if (m->message == MYWM_TASKBARCREATED) - trayMessage(NIM_ADD); - else - return QWidget::winEvent(m, result); - break; - } - return 0; -} - -void QSystemTrayIconPrivate::install_sys() -{ - Q_Q(QSystemTrayIcon); - if (!sys) { - sys = new QSystemTrayIconSys(q); - sys->createIcon(); - sys->trayMessage(NIM_ADD); - } -} - -/* -* This function tries to determine the icon geometry from the tray -* -* If it fails an invalid rect is returned. -*/ -QRect QSystemTrayIconSys::findIconGeometry(const int iconId) -{ - static PtrShell_NotifyIconGetRect Shell_NotifyIconGetRect = - (PtrShell_NotifyIconGetRect)QSystemLibrary::resolve(QLatin1String("shell32"), "Shell_NotifyIconGetRect"); - - if (Shell_NotifyIconGetRect) { - Q_NOTIFYICONIDENTIFIER nid; - memset(&nid, 0, sizeof(nid)); - nid.cbSize = sizeof(nid); - nid.hWnd = winId(); - nid.uID = iconId; - - RECT rect; - HRESULT hr = Shell_NotifyIconGetRect(&nid, &rect); - if (SUCCEEDED(hr)) { - return QRect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); - } - } - - QRect ret; - - TBBUTTON buttonData; - DWORD processID = 0; - HWND trayHandle = FindWindow(L"Shell_TrayWnd", NULL); - - //find the toolbar used in the notification area - if (trayHandle) { - trayHandle = FindWindowEx(trayHandle, NULL, L"TrayNotifyWnd", NULL); - if (trayHandle) { - HWND hwnd = FindWindowEx(trayHandle, NULL, L"SysPager", NULL); - if (hwnd) { - hwnd = FindWindowEx(hwnd, NULL, L"ToolbarWindow32", NULL); - if (hwnd) - trayHandle = hwnd; - } - } - } - - if (!trayHandle) - return ret; - - GetWindowThreadProcessId(trayHandle, &processID); - if (processID <= 0) - return ret; - - HANDLE trayProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ, 0, processID); - if (!trayProcess) - return ret; - - int buttonCount = SendMessage(trayHandle, TB_BUTTONCOUNT, 0, 0); - LPVOID data = VirtualAllocEx(trayProcess, NULL, sizeof(TBBUTTON), MEM_COMMIT, PAGE_READWRITE); - - if ( buttonCount < 1 || !data ) { - CloseHandle(trayProcess); - return ret; - } - - //search for our icon among all toolbar buttons - for (int toolbarButton = 0; toolbarButton < buttonCount; ++toolbarButton ) { - SIZE_T numBytes = 0; - DWORD appData[2] = { 0, 0 }; - SendMessage(trayHandle, TB_GETBUTTON, toolbarButton , (LPARAM)data); - - if (!ReadProcessMemory(trayProcess, data, &buttonData, sizeof(TBBUTTON), &numBytes)) - continue; - - if (!ReadProcessMemory(trayProcess, (LPVOID) buttonData.dwData, appData, sizeof(appData), &numBytes)) - continue; - - int currentIconId = appData[1]; - HWND currentIconHandle = (HWND) appData[0]; - bool isHidden = buttonData.fsState & TBSTATE_HIDDEN; - - if (currentIconHandle == winId() && - currentIconId == iconId && !isHidden) { - SendMessage(trayHandle, TB_GETITEMRECT, toolbarButton , (LPARAM)data); - RECT iconRect = {0, 0}; - if(ReadProcessMemory(trayProcess, data, &iconRect, sizeof(RECT), &numBytes)) { - MapWindowPoints(trayHandle, NULL, (LPPOINT)&iconRect, 2); - QRect geometry(iconRect.left + 1, iconRect.top + 1, - iconRect.right - iconRect.left - 2, - iconRect.bottom - iconRect.top - 2); - if (geometry.isValid()) - ret = geometry; - break; - } - } - } - VirtualFreeEx(trayProcess, data, 0, MEM_RELEASE); - CloseHandle(trayProcess); - return ret; -} - -void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, int timeOut) -{ - if (!sys || !allowsMessages()) - return; - - uint uSecs = 0; - if ( timeOut < 0) - uSecs = 10000; //10 sec default - else uSecs = (int)timeOut; - - //message is limited to 255 chars + NULL - QString messageString; - if (message.isEmpty() && !title.isEmpty()) - messageString = QLatin1Char(' '); //ensures that the message shows when only title is set - else - messageString = message.left(255) + QChar(); - - //title is limited to 63 chars + NULL - QString titleString = title.left(63) + QChar(); - - sys->showMessage(titleString, messageString, type, uSecs); -} - -QRect QSystemTrayIconPrivate::geometry_sys() const -{ - if (!sys) - return QRect(); - - return sys->findIconGeometry(q_uNOTIFYICONID); -} - -void QSystemTrayIconPrivate::remove_sys() -{ - if (!sys) - return; - - sys->trayMessage(NIM_DELETE); - delete sys; - sys = 0; -} - -void QSystemTrayIconPrivate::updateIcon_sys() -{ - if (!sys) - return; - - HICON hIconToDestroy = sys->hIcon; - - sys->createIcon(); - sys->trayMessage(NIM_MODIFY); - - if (hIconToDestroy) - DestroyIcon(hIconToDestroy); -} - -void QSystemTrayIconPrivate::updateMenu_sys() -{ - -} - -void QSystemTrayIconPrivate::updateToolTip_sys() -{ - if (!sys) - return; - - sys->trayMessage(NIM_MODIFY); -} - -bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys() -{ - return true; -} - -bool QSystemTrayIconPrivate::supportsMessages_sys() -{ - return allowsMessages(); -} - -QT_END_NAMESPACE - -#endif diff --git a/src/gui/util/qsystemtrayicon_wince.cpp b/src/gui/util/qsystemtrayicon_wince.cpp deleted file mode 100644 index 7a403a3ee5..0000000000 --- a/src/gui/util/qsystemtrayicon_wince.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsystemtrayicon_p.h" -#ifndef QT_NO_SYSTEMTRAYICON -#define _WIN32_IE 0x0600 //required for NOTIFYICONDATA_V2_SIZE - -#include <qt_windows.h> -#include <shlwapi.h> -#include <QApplication> - -QT_BEGIN_NAMESPACE - -static const UINT q_uNOTIFYICONID = 13; // IDs from 0 to 12 are reserved on WinCE. -#define MYWM_NOTIFYICON (WM_APP+101) - -struct Q_NOTIFYICONIDENTIFIER { - DWORD cbSize; - HWND hWnd; - UINT uID; - GUID guidItem; -}; - -class QSystemTrayIconSys : QWidget -{ -public: - QSystemTrayIconSys(QSystemTrayIcon *object); - ~QSystemTrayIconSys(); - bool winEvent( MSG *m, long *result ); - bool trayMessage(DWORD msg); - void setIconContents(NOTIFYICONDATA &data); - void createIcon(); - QRect findTrayGeometry(); - HICON hIcon; - QPoint globalPos; - QSystemTrayIcon *q; -private: - uint notifyIconSize; - int maxTipLength; - bool ignoreNextMouseRelease; -}; - -QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *object) - : hIcon(0), q(object), ignoreNextMouseRelease(false) - -{ - notifyIconSize = FIELD_OFFSET(NOTIFYICONDATA, szTip[64]); // NOTIFYICONDATAW_V1_SIZE; - maxTipLength = 64; -} - -QSystemTrayIconSys::~QSystemTrayIconSys() -{ - if (hIcon) - DestroyIcon(hIcon); -} - -QRect QSystemTrayIconSys::findTrayGeometry() -{ - // Use lower right corner as fallback - QPoint brCorner = qApp->desktop()->screenGeometry().bottomRight(); - QRect ret(brCorner.x() - 10, brCorner.y() - 10, 10, 10); - return ret; -} - -void QSystemTrayIconSys::setIconContents(NOTIFYICONDATA &tnd) -{ - tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; - tnd.uCallbackMessage = MYWM_NOTIFYICON; - tnd.hIcon = hIcon; - QString tip = q->toolTip(); - - if (!tip.isNull()) { - tip = tip.left(maxTipLength - 1) + QChar(); - memcpy(tnd.szTip, tip.utf16(), qMin(tip.length() + 1, maxTipLength) * sizeof(wchar_t)); - } -} - -bool QSystemTrayIconSys::trayMessage(DWORD msg) -{ - NOTIFYICONDATA tnd; - memset(&tnd, 0, notifyIconSize); - tnd.uID = q_uNOTIFYICONID; - tnd.cbSize = notifyIconSize; - tnd.hWnd = winId(); - - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - - if (msg != NIM_DELETE) { - setIconContents(tnd); - } - - return Shell_NotifyIcon(msg, &tnd); -} - -void QSystemTrayIconSys::createIcon() -{ - hIcon = 0; - QIcon icon = q->icon(); - if (icon.isNull()) - return; - - //const QSize preferredSize(GetSystemMetrics(SM_CXSMICON) * 2, GetSystemMetrics(SM_CYSMICON) * 2); - const QSize preferredSize(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); - QPixmap pm = icon.pixmap(preferredSize); - if (pm.isNull()) - return; - - hIcon = pm.toWinHICON(); -} - -bool QSystemTrayIconSys::winEvent( MSG *m, long *result ) -{ - switch(m->message) { - case WM_CREATE: - SetWindowLong(winId(), GWL_USERDATA, (LONG)((CREATESTRUCTW*)m->lParam)->lpCreateParams); - break; - - case MYWM_NOTIFYICON: - { - QPoint gpos = QCursor::pos(); - - switch (m->lParam) { - case WM_LBUTTONUP: - if (ignoreNextMouseRelease) - ignoreNextMouseRelease = false; - else - emit q->activated(QSystemTrayIcon::Trigger); - break; - - case WM_LBUTTONDBLCLK: - ignoreNextMouseRelease = true; // Since DBLCLICK Generates a second mouse - // release we must ignore it - emit q->activated(QSystemTrayIcon::DoubleClick); - break; - - case WM_RBUTTONUP: - if (q->contextMenu()) { - q->contextMenu()->popup(gpos); - - // We must ensure that the popup menu doesn't show up behind the task bar. - QRect desktopRect = qApp->desktop()->availableGeometry(); - int maxY = desktopRect.y() + desktopRect.height() - q->contextMenu()->height(); - if (gpos.y() > maxY) { - gpos.ry() = maxY; - q->contextMenu()->move(gpos); - } - } - emit q->activated(QSystemTrayIcon::Context); - break; - - case WM_MBUTTONUP: - emit q->activated(QSystemTrayIcon::MiddleClick); - break; - - default: - break; - } - break; - } - default: - return QWidget::winEvent(m, result); - } - return 0; -} - -void QSystemTrayIconPrivate::install_sys() -{ - Q_Q(QSystemTrayIcon); - if (!sys) { - sys = new QSystemTrayIconSys(q); - sys->createIcon(); - sys->trayMessage(NIM_ADD); - } -} - -void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, int timeOut) -{ - if (!sys) - return; - - uint uSecs = 0; - if ( timeOut < 0) - uSecs = 10000; //10 sec default - else uSecs = (int)timeOut; - - //message is limited to 255 chars + NULL - QString messageString; - if (message.isEmpty() && !title.isEmpty()) - messageString = QLatin1Char(' '); //ensures that the message shows when only title is set - else - messageString = message.left(255) + QChar(); - - //title is limited to 63 chars + NULL - QString titleString = title.left(63) + QChar(); - - //show QBalloonTip - QRect trayRect = sys->findTrayGeometry(); - QBalloonTip::showBalloon(type, title, message, sys->q, QPoint(trayRect.left(), - trayRect.center().y()), uSecs, false); -} - -QRect QSystemTrayIconPrivate::geometry_sys() const -{ - return QRect(); -} - -void QSystemTrayIconPrivate::remove_sys() -{ - if (!sys) - return; - - sys->trayMessage(NIM_DELETE); - delete sys; - sys = 0; -} - -void QSystemTrayIconPrivate::updateIcon_sys() -{ - if (!sys) - return; - - HICON hIconToDestroy = sys->hIcon; - - sys->createIcon(); - sys->trayMessage(NIM_MODIFY); - - if (hIconToDestroy) - DestroyIcon(hIconToDestroy); -} - -void QSystemTrayIconPrivate::updateMenu_sys() -{ - -} - -void QSystemTrayIconPrivate::updateToolTip_sys() -{ - // Calling sys->trayMessage(NIM_MODIFY) on an existing icon is broken on Windows CE. - // So we need to call updateIcon_sys() which creates a new icon handle. - updateIcon_sys(); -} - -bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys() -{ - return true; -} - -bool QSystemTrayIconPrivate::supportsMessages_sys() -{ - return true; -} - -QT_END_NAMESPACE - -#endif diff --git a/src/gui/util/qsystemtrayicon_x11.cpp b/src/gui/util/qsystemtrayicon_x11.cpp deleted file mode 100644 index 86c27499b4..0000000000 --- a/src/gui/util/qsystemtrayicon_x11.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "private/qt_x11_p.h" -#include "qlabel.h" -#include "qx11info_x11.h" -#include "qpainter.h" -#include "qpixmap.h" -#include "qbitmap.h" -#include "qevent.h" -#include "qapplication.h" -#include "qlist.h" -#include "qmenu.h" -#include "qtimer.h" -#include "qsystemtrayicon_p.h" -#include "qpaintengine.h" - -#ifndef QT_NO_SYSTEMTRAYICON -QT_BEGIN_NAMESPACE - -Window QSystemTrayIconSys::sysTrayWindow = XNone; -QList<QSystemTrayIconSys *> QSystemTrayIconSys::trayIcons; -QCoreApplication::EventFilter QSystemTrayIconSys::oldEventFilter = 0; -Atom QSystemTrayIconSys::sysTraySelection = XNone; -XVisualInfo QSystemTrayIconSys::sysTrayVisual = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -// Locate the system tray -Window QSystemTrayIconSys::locateSystemTray() -{ - Display *display = QX11Info::display(); - if (sysTraySelection == XNone) { - int screen = QX11Info::appScreen(); - QString net_sys_tray = QString::fromLatin1("_NET_SYSTEM_TRAY_S%1").arg(screen); - sysTraySelection = XInternAtom(display, net_sys_tray.toLatin1(), False); - } - - return XGetSelectionOwner(QX11Info::display(), sysTraySelection); -} - -XVisualInfo* QSystemTrayIconSys::getSysTrayVisualInfo() -{ - Display *display = QX11Info::display(); - - if (!sysTrayVisual.visual) { - Window win = locateSystemTray(); - if (win != XNone) { - Atom actual_type; - int actual_format; - ulong nitems, bytes_remaining; - uchar *data = 0; - int result = XGetWindowProperty(display, win, ATOM(_NET_SYSTEM_TRAY_VISUAL), 0, 1, - False, XA_VISUALID, &actual_type, - &actual_format, &nitems, &bytes_remaining, &data); - VisualID vid = 0; - if (result == Success && data && actual_type == XA_VISUALID && actual_format == 32 && - nitems == 1 && bytes_remaining == 0) - vid = *(VisualID*)data; - if (data) - XFree(data); - if (vid == 0) - return 0; - - uint mask = VisualIDMask; - XVisualInfo *vi, rvi; - int count; - rvi.visualid = vid; - vi = XGetVisualInfo(display, mask, &rvi, &count); - if (vi) { - sysTrayVisual = vi[0]; - XFree((char*)vi); - } - if (sysTrayVisual.depth != 32) - memset(&sysTrayVisual, 0, sizeof(sysTrayVisual)); - } - } - - return sysTrayVisual.visual ? &sysTrayVisual : 0; -} - -bool QSystemTrayIconSys::sysTrayTracker(void *message, long *result) -{ - bool retval = false; - if (QSystemTrayIconSys::oldEventFilter) - retval = QSystemTrayIconSys::oldEventFilter(message, result); - - if (trayIcons.isEmpty()) - return retval; - - Display *display = QX11Info::display(); - XEvent *ev = (XEvent *)message; - if (ev->type == DestroyNotify && ev->xany.window == sysTrayWindow) { - sysTrayWindow = locateSystemTray(); - memset(&sysTrayVisual, 0, sizeof(sysTrayVisual)); - for (int i = 0; i < trayIcons.count(); i++) { - if (sysTrayWindow == XNone) { - QBalloonTip::hideBalloon(); - trayIcons[i]->hide(); // still no luck - trayIcons[i]->destroy(); - trayIcons[i]->create(); - } else - trayIcons[i]->addToTray(); // add it to the new tray - } - retval = true; - } else if (ev->type == ClientMessage && sysTrayWindow == XNone) { - static Atom manager_atom = XInternAtom(display, "MANAGER", False); - XClientMessageEvent *cm = (XClientMessageEvent *)message; - if ((cm->message_type == manager_atom) && ((Atom)cm->data.l[1] == sysTraySelection)) { - sysTrayWindow = cm->data.l[2]; - memset(&sysTrayVisual, 0, sizeof(sysTrayVisual)); - XSelectInput(display, sysTrayWindow, StructureNotifyMask); - for (int i = 0; i < trayIcons.count(); i++) { - trayIcons[i]->addToTray(); - } - retval = true; - } - } else if (ev->type == PropertyNotify && ev->xproperty.atom == ATOM(_NET_SYSTEM_TRAY_VISUAL) && - ev->xproperty.window == sysTrayWindow) { - memset(&sysTrayVisual, 0, sizeof(sysTrayVisual)); - for (int i = 0; i < trayIcons.count(); i++) { - trayIcons[i]->addToTray(); - } - } - - return retval; -} - -QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *q) - : QWidget(0, Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint), - q(q), colormap(0) -{ - setAttribute(Qt::WA_AlwaysShowToolTips); - setAttribute(Qt::WA_QuitOnClose, false); - setAttribute(Qt::WA_NoSystemBackground, true); - setAttribute(Qt::WA_PaintOnScreen); - - static bool eventFilterAdded = false; - Display *display = QX11Info::display(); - if (!eventFilterAdded) { - oldEventFilter = qApp->setEventFilter(sysTrayTracker); - eventFilterAdded = true; - Window root = QX11Info::appRootWindow(); - XWindowAttributes attr; - XGetWindowAttributes(display, root, &attr); - if ((attr.your_event_mask & StructureNotifyMask) != StructureNotifyMask) { - (void) QApplication::desktop(); // lame trick to ensure our event mask is not overridden - XSelectInput(display, root, attr.your_event_mask | StructureNotifyMask); // for MANAGER selection - } - } - if (trayIcons.isEmpty()) { - sysTrayWindow = locateSystemTray(); - if (sysTrayWindow != XNone) - XSelectInput(display, sysTrayWindow, StructureNotifyMask); // track tray events - } - trayIcons.append(this); - setMouseTracking(true); -#ifndef QT_NO_TOOLTIP - setToolTip(q->toolTip()); -#endif - if (sysTrayWindow != XNone) - addToTray(); -} - -QSystemTrayIconSys::~QSystemTrayIconSys() -{ - trayIcons.removeAt(trayIcons.indexOf(this)); - Display *display = QX11Info::display(); - if (trayIcons.isEmpty()) { - if (sysTrayWindow == XNone) - return; - if (display) - XSelectInput(display, sysTrayWindow, 0); // stop tracking the tray - sysTrayWindow = XNone; - } - if (colormap) - XFreeColormap(display, colormap); -} - -void QSystemTrayIconSys::addToTray() -{ - Q_ASSERT(sysTrayWindow != XNone); - Display *display = QX11Info::display(); - - XVisualInfo *vi = getSysTrayVisualInfo(); - if (vi && vi->visual) { - Window root = RootWindow(display, vi->screen); - Window p = root; - if (QWidget *pw = parentWidget()) - p = pw->effectiveWinId(); - colormap = XCreateColormap(display, root, vi->visual, AllocNone); - XSetWindowAttributes wsa; - wsa.background_pixmap = 0; - wsa.colormap = colormap; - wsa.background_pixel = 0; - wsa.border_pixel = 0; - Window wid = XCreateWindow(display, p, -1, -1, 1, 1, - 0, vi->depth, InputOutput, vi->visual, - CWBackPixmap|CWBackPixel|CWBorderPixel|CWColormap, &wsa); - create(wid); - } else { - XSetWindowBackgroundPixmap(display, winId(), ParentRelative); - } - - // GNOME, NET WM Specification - static Atom netwm_tray_atom = XInternAtom(display, "_NET_SYSTEM_TRAY_OPCODE", False); - long l[5] = { CurrentTime, SYSTEM_TRAY_REQUEST_DOCK, winId(), 0, 0 }; - XEvent ev; - memset(&ev, 0, sizeof(ev)); - ev.xclient.type = ClientMessage; - ev.xclient.window = sysTrayWindow; - ev.xclient.message_type = netwm_tray_atom; - ev.xclient.format = 32; - memcpy((char *)&ev.xclient.data, (const char *) l, sizeof(l)); - XSendEvent(display, sysTrayWindow, False, 0, &ev); - setMinimumSize(22, 22); // required at least on GNOME -} - -void QSystemTrayIconSys::updateIcon() -{ - update(); -} - -void QSystemTrayIconSys::resizeEvent(QResizeEvent *re) -{ - QWidget::resizeEvent(re); - updateIcon(); -} - -void QSystemTrayIconSys::paintEvent(QPaintEvent*) -{ - QPainter p(this); - if (!getSysTrayVisualInfo()) { - const QRegion oldSystemClip = p.paintEngine()->systemClip(); - const QRect clearedRect = oldSystemClip.boundingRect(); - XClearArea(QX11Info::display(), winId(), clearedRect.x(), clearedRect.y(), - clearedRect.width(), clearedRect.height(), False); - QPaintEngine *pe = p.paintEngine(); - pe->setSystemClip(clearedRect); - q->icon().paint(&p, rect()); - pe->setSystemClip(oldSystemClip); - } else { - p.setCompositionMode(QPainter::CompositionMode_Source); - p.fillRect(rect(), Qt::transparent); - p.setCompositionMode(QPainter::CompositionMode_SourceOver); - q->icon().paint(&p, rect()); - } -} - -void QSystemTrayIconSys::mousePressEvent(QMouseEvent *ev) -{ - QPoint globalPos = ev->globalPos(); - if (ev->button() == Qt::RightButton && q->contextMenu()) - q->contextMenu()->popup(globalPos); - - if (QBalloonTip::isBalloonVisible()) { - emit q->messageClicked(); - QBalloonTip::hideBalloon(); - } - - if (ev->button() == Qt::LeftButton) - emit q->activated(QSystemTrayIcon::Trigger); - else if (ev->button() == Qt::RightButton) - emit q->activated(QSystemTrayIcon::Context); - else if (ev->button() == Qt::MidButton) - emit q->activated(QSystemTrayIcon::MiddleClick); -} - -void QSystemTrayIconSys::mouseDoubleClickEvent(QMouseEvent *ev) -{ - if (ev->button() == Qt::LeftButton) - emit q->activated(QSystemTrayIcon::DoubleClick); -} - -#ifndef QT_NO_WHEELEVENT -void QSystemTrayIconSys::wheelEvent(QWheelEvent *e) -{ - QApplication::sendEvent(q, e); -} -#endif - -bool QSystemTrayIconSys::event(QEvent *e) -{ - if (e->type() == QEvent::ToolTip) { - return QApplication::sendEvent(q, e); - } - return QWidget::event(e); -} - -bool QSystemTrayIconSys::x11Event(XEvent *event) -{ - if (event->type == ReparentNotify) - show(); - return QWidget::x11Event(event); -} - -//////////////////////////////////////////////////////////////////////////// -void QSystemTrayIconPrivate::install_sys() -{ - Q_Q(QSystemTrayIcon); - if (!sys) - sys = new QSystemTrayIconSys(q); -} - -QRect QSystemTrayIconPrivate::geometry_sys() const -{ - if (!sys) - return QRect(); - return QRect(sys->mapToGlobal(QPoint(0, 0)), sys->size()); -} - -void QSystemTrayIconPrivate::remove_sys() -{ - if (!sys) - return; - QBalloonTip::hideBalloon(); - sys->hide(); // this should do the trick, but... - delete sys; // wm may resize system tray only for DestroyEvents - sys = 0; -} - -void QSystemTrayIconPrivate::updateIcon_sys() -{ - if (!sys) - return; - sys->updateIcon(); -} - -void QSystemTrayIconPrivate::updateMenu_sys() -{ - -} - -void QSystemTrayIconPrivate::updateToolTip_sys() -{ - if (!sys) - return; -#ifndef QT_NO_TOOLTIP - sys->setToolTip(toolTip); -#endif -} - -bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys() -{ - return QSystemTrayIconSys::locateSystemTray() != XNone; -} - -bool QSystemTrayIconPrivate::supportsMessages_sys() -{ - return true; -} - -void QSystemTrayIconPrivate::showMessage_sys(const QString &message, const QString &title, - QSystemTrayIcon::MessageIcon icon, int msecs) -{ - if (!sys) - return; - QPoint g = sys->mapToGlobal(QPoint(0, 0)); - QBalloonTip::showBalloon(icon, message, title, sys->q, - QPoint(g.x() + sys->width()/2, g.y() + sys->height()/2), - msecs); -} - -QT_END_NAMESPACE -#endif //QT_NO_SYSTEMTRAYICON diff --git a/src/gui/util/qundogroup.cpp b/src/gui/util/qundogroup.cpp deleted file mode 100644 index 4f83e3a815..0000000000 --- a/src/gui/util/qundogroup.cpp +++ /dev/null @@ -1,505 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qundogroup.h" -#include "qundostack.h" -#include "qundostack_p.h" - -#ifndef QT_NO_UNDOGROUP - -QT_BEGIN_NAMESPACE - -class QUndoGroupPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QUndoGroup) -public: - QUndoGroupPrivate() : active(0) {} - - QUndoStack *active; - QList<QUndoStack*> stack_list; -}; - -/*! - \class QUndoGroup - \brief The QUndoGroup class is a group of QUndoStack objects. - \since 4.2 - - For an overview of the Qt's undo framework, see the - \link qundo.html overview\endlink. - - An application often has multiple undo stacks, one for each opened document. At the - same time, an application usually has one undo action and one redo action, which - triggers undo or redo in the active document. - - QUndoGroup is a group of QUndoStack objects, one of which may be active. It has - an undo() and redo() slot, which calls QUndoStack::undo() and QUndoStack::redo() - for the active stack. It also has the functions createUndoAction() and createRedoAction(). - The actions returned by these functions behave in the same way as those returned by - QUndoStack::createUndoAction() and QUndoStack::createRedoAction() of the active - stack. - - Stacks are added to a group with addStack() and removed with removeStack(). A stack - is implicitly added to a group when it is created with the group as its parent - QObject. - - It is the programmer's responsibility to specify which stack is active by - calling QUndoStack::setActive(), usually when the associated document window receives focus. - The active stack may also be set with setActiveStack(), and is returned by activeStack(). - - When a stack is added to a group using addStack(), the group does not take ownership - of the stack. This means the stack has to be deleted separately from the group. When - a stack is deleted, it is automatically removed from a group. A stack may belong to - only one group. Adding it to another group will cause it to be removed from the previous - group. - - A QUndoGroup is also useful in conjunction with QUndoView. If a QUndoView is - set to watch a group using QUndoView::setGroup(), it will update itself to display - the active stack. -*/ - -/*! - Creates an empty QUndoGroup object with parent \a parent. - - \sa addStack() -*/ - -QUndoGroup::QUndoGroup(QObject *parent) - : QObject(*new QUndoGroupPrivate(), parent) -{ -} - -/*! - Destroys the QUndoGroup. -*/ -QUndoGroup::~QUndoGroup() -{ - // Ensure all QUndoStacks no longer refer to this group. - Q_D(QUndoGroup); - QList<QUndoStack *>::iterator it = d->stack_list.begin(); - QList<QUndoStack *>::iterator end = d->stack_list.end(); - while (it != end) { - (*it)->d_func()->group = 0; - ++it; - } -} - -/*! - Adds \a stack to this group. The group does not take ownership of the stack. Another - way of adding a stack to a group is by specifying the group as the stack's parent - QObject in QUndoStack::QUndoStack(). In this case, the stack is deleted when the - group is deleted, in the usual manner of QObjects. - - \sa removeStack() stacks() QUndoStack::QUndoStack() -*/ - -void QUndoGroup::addStack(QUndoStack *stack) -{ - Q_D(QUndoGroup); - - if (d->stack_list.contains(stack)) - return; - d->stack_list.append(stack); - - if (QUndoGroup *other = stack->d_func()->group) - other->removeStack(stack); - stack->d_func()->group = this; -} - -/*! - Removes \a stack from this group. If the stack was the active stack in the group, - the active stack becomes 0. - - \sa addStack() stacks() QUndoStack::~QUndoStack() -*/ - -void QUndoGroup::removeStack(QUndoStack *stack) -{ - Q_D(QUndoGroup); - - if (d->stack_list.removeAll(stack) == 0) - return; - if (stack == d->active) - setActiveStack(0); - stack->d_func()->group = 0; -} - -/*! - Returns a list of stacks in this group. - - \sa addStack() removeStack() -*/ - -QList<QUndoStack*> QUndoGroup::stacks() const -{ - Q_D(const QUndoGroup); - return d->stack_list; -} - -/*! - Sets the active stack of this group to \a stack. - - If the stack is not a member of this group, this function does nothing. - - Synonymous with calling QUndoStack::setActive() on \a stack. - - The actions returned by createUndoAction() and createRedoAction() will now behave - in the same way as those returned by \a stack's QUndoStack::createUndoAction() - and QUndoStack::createRedoAction(). - - \sa QUndoStack::setActive() activeStack() -*/ - -void QUndoGroup::setActiveStack(QUndoStack *stack) -{ - Q_D(QUndoGroup); - if (d->active == stack) - return; - - if (d->active != 0) { - disconnect(d->active, SIGNAL(canUndoChanged(bool)), - this, SIGNAL(canUndoChanged(bool))); - disconnect(d->active, SIGNAL(undoTextChanged(QString)), - this, SIGNAL(undoTextChanged(QString))); - disconnect(d->active, SIGNAL(canRedoChanged(bool)), - this, SIGNAL(canRedoChanged(bool))); - disconnect(d->active, SIGNAL(redoTextChanged(QString)), - this, SIGNAL(redoTextChanged(QString))); - disconnect(d->active, SIGNAL(indexChanged(int)), - this, SIGNAL(indexChanged(int))); - disconnect(d->active, SIGNAL(cleanChanged(bool)), - this, SIGNAL(cleanChanged(bool))); - } - - d->active = stack; - - if (d->active == 0) { - emit canUndoChanged(false); - emit undoTextChanged(QString()); - emit canRedoChanged(false); - emit redoTextChanged(QString()); - emit cleanChanged(true); - emit indexChanged(0); - } else { - connect(d->active, SIGNAL(canUndoChanged(bool)), - this, SIGNAL(canUndoChanged(bool))); - connect(d->active, SIGNAL(undoTextChanged(QString)), - this, SIGNAL(undoTextChanged(QString))); - connect(d->active, SIGNAL(canRedoChanged(bool)), - this, SIGNAL(canRedoChanged(bool))); - connect(d->active, SIGNAL(redoTextChanged(QString)), - this, SIGNAL(redoTextChanged(QString))); - connect(d->active, SIGNAL(indexChanged(int)), - this, SIGNAL(indexChanged(int))); - connect(d->active, SIGNAL(cleanChanged(bool)), - this, SIGNAL(cleanChanged(bool))); - emit canUndoChanged(d->active->canUndo()); - emit undoTextChanged(d->active->undoText()); - emit canRedoChanged(d->active->canRedo()); - emit redoTextChanged(d->active->redoText()); - emit cleanChanged(d->active->isClean()); - emit indexChanged(d->active->index()); - } - - emit activeStackChanged(d->active); -} - -/*! - Returns the active stack of this group. - - If none of the stacks are active, or if the group is empty, this function - returns 0. - - \sa setActiveStack() QUndoStack::setActive() -*/ - -QUndoStack *QUndoGroup::activeStack() const -{ - Q_D(const QUndoGroup); - return d->active; -} - -/*! - Calls QUndoStack::undo() on the active stack. - - If none of the stacks are active, or if the group is empty, this function - does nothing. - - \sa redo() canUndo() setActiveStack() -*/ - -void QUndoGroup::undo() -{ - Q_D(QUndoGroup); - if (d->active != 0) - d->active->undo(); -} - -/*! - Calls QUndoStack::redo() on the active stack. - - If none of the stacks are active, or if the group is empty, this function - does nothing. - - \sa undo() canRedo() setActiveStack() -*/ - - -void QUndoGroup::redo() -{ - Q_D(QUndoGroup); - if (d->active != 0) - d->active->redo(); -} - -/*! - Returns the value of the active stack's QUndoStack::canUndo(). - - If none of the stacks are active, or if the group is empty, this function - returns false. - - \sa canRedo() setActiveStack() -*/ - -bool QUndoGroup::canUndo() const -{ - Q_D(const QUndoGroup); - return d->active != 0 && d->active->canUndo(); -} - -/*! - Returns the value of the active stack's QUndoStack::canRedo(). - - If none of the stacks are active, or if the group is empty, this function - returns false. - - \sa canUndo() setActiveStack() -*/ - -bool QUndoGroup::canRedo() const -{ - Q_D(const QUndoGroup); - return d->active != 0 && d->active->canRedo(); -} - -/*! - Returns the value of the active stack's QUndoStack::undoText(). - - If none of the stacks are active, or if the group is empty, this function - returns an empty string. - - \sa redoText() setActiveStack() -*/ - -QString QUndoGroup::undoText() const -{ - Q_D(const QUndoGroup); - return d->active == 0 ? QString() : d->active->undoText(); -} - -/*! - Returns the value of the active stack's QUndoStack::redoText(). - - If none of the stacks are active, or if the group is empty, this function - returns an empty string. - - \sa undoText() setActiveStack() -*/ - -QString QUndoGroup::redoText() const -{ - Q_D(const QUndoGroup); - return d->active == 0 ? QString() : d->active->redoText(); -} - -/*! - Returns the value of the active stack's QUndoStack::isClean(). - - If none of the stacks are active, or if the group is empty, this function - returns true. - - \sa setActiveStack() -*/ - -bool QUndoGroup::isClean() const -{ - Q_D(const QUndoGroup); - return d->active == 0 || d->active->isClean(); -} - -#ifndef QT_NO_ACTION - -/*! - Creates an undo QAction object with parent \a parent. - - Triggering this action will cause a call to QUndoStack::undo() on the active stack. - The text of this action will always be the text of the command which will be undone - in the next call to undo(), prefixed by \a prefix. If there is no command available - for undo, if the group is empty or if none of the stacks are active, this action will - be disabled. - - If \a prefix is empty, the default template "Undo %1" is used instead of prefix. - Before Qt 4.8, the prefix "Undo" was used by default. - - \sa createRedoAction() canUndo() QUndoCommand::text() -*/ - -QAction *QUndoGroup::createUndoAction(QObject *parent, const QString &prefix) const -{ - QUndoAction *result = new QUndoAction(prefix, parent); - if (prefix.isEmpty()) - result->setTextFormat(tr("Undo %1"), tr("Undo", "Default text for undo action")); - - result->setEnabled(canUndo()); - result->setPrefixedText(undoText()); - connect(this, SIGNAL(canUndoChanged(bool)), - result, SLOT(setEnabled(bool))); - connect(this, SIGNAL(undoTextChanged(QString)), - result, SLOT(setPrefixedText(QString))); - connect(result, SIGNAL(triggered()), this, SLOT(undo())); - return result; -} - -/*! - Creates an redo QAction object with parent \a parent. - - Triggering this action will cause a call to QUndoStack::redo() on the active stack. - The text of this action will always be the text of the command which will be redone - in the next call to redo(), prefixed by \a prefix. If there is no command available - for redo, if the group is empty or if none of the stacks are active, this action will - be disabled. - - If \a prefix is empty, the default template "Redo %1" is used instead of prefix. - Before Qt 4.8, the prefix "Redo" was used by default. - - \sa createUndoAction() canRedo() QUndoCommand::text() -*/ - -QAction *QUndoGroup::createRedoAction(QObject *parent, const QString &prefix) const -{ - QUndoAction *result = new QUndoAction(prefix, parent); - if (prefix.isEmpty()) - result->setTextFormat(tr("Redo %1"), tr("Redo", "Default text for redo action")); - - result->setEnabled(canRedo()); - result->setPrefixedText(redoText()); - connect(this, SIGNAL(canRedoChanged(bool)), - result, SLOT(setEnabled(bool))); - connect(this, SIGNAL(redoTextChanged(QString)), - result, SLOT(setPrefixedText(QString))); - connect(result, SIGNAL(triggered()), this, SLOT(redo())); - return result; -} - -#endif // QT_NO_ACTION - -/*! \fn void QUndoGroup::activeStackChanged(QUndoStack *stack) - - This signal is emitted whenever the active stack of the group changes. This can happen - when setActiveStack() or QUndoStack::setActive() is called, or when the active stack - is removed form the group. \a stack is the new active stack. If no stack is active, - \a stack is 0. - - \sa setActiveStack() QUndoStack::setActive() -*/ - -/*! \fn void QUndoGroup::indexChanged(int idx) - - This signal is emitted whenever the active stack emits QUndoStack::indexChanged() - or the active stack changes. - - \a idx is the new current index, or 0 if the active stack is 0. - - \sa QUndoStack::indexChanged() setActiveStack() -*/ - -/*! \fn void QUndoGroup::cleanChanged(bool clean) - - This signal is emitted whenever the active stack emits QUndoStack::cleanChanged() - or the active stack changes. - - \a clean is the new state, or true if the active stack is 0. - - \sa QUndoStack::cleanChanged() setActiveStack() -*/ - -/*! \fn void QUndoGroup::canUndoChanged(bool canUndo) - - This signal is emitted whenever the active stack emits QUndoStack::canUndoChanged() - or the active stack changes. - - \a canUndo is the new state, or false if the active stack is 0. - - \sa QUndoStack::canUndoChanged() setActiveStack() -*/ - -/*! \fn void QUndoGroup::canRedoChanged(bool canRedo) - - This signal is emitted whenever the active stack emits QUndoStack::canRedoChanged() - or the active stack changes. - - \a canRedo is the new state, or false if the active stack is 0. - - \sa QUndoStack::canRedoChanged() setActiveStack() -*/ - -/*! \fn void QUndoGroup::undoTextChanged(const QString &undoText) - - This signal is emitted whenever the active stack emits QUndoStack::undoTextChanged() - or the active stack changes. - - \a undoText is the new state, or an empty string if the active stack is 0. - - \sa QUndoStack::undoTextChanged() setActiveStack() -*/ - -/*! \fn void QUndoGroup::redoTextChanged(const QString &redoText) - - This signal is emitted whenever the active stack emits QUndoStack::redoTextChanged() - or the active stack changes. - - \a redoText is the new state, or an empty string if the active stack is 0. - - \sa QUndoStack::redoTextChanged() setActiveStack() -*/ - -QT_END_NAMESPACE - -#endif // QT_NO_UNDOGROUP diff --git a/src/gui/util/qundogroup.h b/src/gui/util/qundogroup.h deleted file mode 100644 index 99026fc077..0000000000 --- a/src/gui/util/qundogroup.h +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QUNDOGROUP_H -#define QUNDOGROUP_H - -#include <QtCore/qobject.h> -#include <QtCore/qstring.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QUndoGroupPrivate; -class QUndoStack; -class QAction; - -QT_MODULE(Gui) - -#ifndef QT_NO_UNDOGROUP - -class Q_GUI_EXPORT QUndoGroup : public QObject -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QUndoGroup) - -public: - explicit QUndoGroup(QObject *parent = 0); - ~QUndoGroup(); - - void addStack(QUndoStack *stack); - void removeStack(QUndoStack *stack); - QList<QUndoStack*> stacks() const; - QUndoStack *activeStack() const; - -#ifndef QT_NO_ACTION - QAction *createUndoAction(QObject *parent, - const QString &prefix = QString()) const; - QAction *createRedoAction(QObject *parent, - const QString &prefix = QString()) const; -#endif // QT_NO_ACTION - bool canUndo() const; - bool canRedo() const; - QString undoText() const; - QString redoText() const; - bool isClean() const; - -public Q_SLOTS: - void undo(); - void redo(); - void setActiveStack(QUndoStack *stack); - -Q_SIGNALS: - void activeStackChanged(QUndoStack *stack); - void indexChanged(int idx); - void cleanChanged(bool clean); - void canUndoChanged(bool canUndo); - void canRedoChanged(bool canRedo); - void undoTextChanged(const QString &undoText); - void redoTextChanged(const QString &redoText); - -private: - Q_DISABLE_COPY(QUndoGroup) -}; - -#endif // QT_NO_UNDOGROUP - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QUNDOGROUP_H diff --git a/src/gui/util/qundostack.cpp b/src/gui/util/qundostack.cpp deleted file mode 100644 index 59e73e6ad2..0000000000 --- a/src/gui/util/qundostack.cpp +++ /dev/null @@ -1,1175 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/qdebug.h> -#include "qundostack.h" -#include "qundogroup.h" -#include "qundostack_p.h" - -#ifndef QT_NO_UNDOCOMMAND - -QT_BEGIN_NAMESPACE - -/*! - \class QUndoCommand - \brief The QUndoCommand class is the base class of all commands stored on a QUndoStack. - \since 4.2 - - For an overview of Qt's Undo Framework, see the - \l{Overview of Qt's Undo Framework}{overview document}. - - A QUndoCommand represents a single editing action on a document; for example, - inserting or deleting a block of text in a text editor. QUndoCommand can apply - a change to the document with redo() and undo the change with undo(). The - implementations for these functions must be provided in a derived class. - - \snippet doc/src/snippets/code/src_gui_util_qundostack.cpp 0 - - A QUndoCommand has an associated text(). This is a short string - describing what the command does. It is used to update the text - properties of the stack's undo and redo actions; see - QUndoStack::createUndoAction() and QUndoStack::createRedoAction(). - - QUndoCommand objects are owned by the stack they were pushed on. - QUndoStack deletes a command if it has been undone and a new command is pushed. For example: - -\snippet doc/src/snippets/code/src_gui_util_qundostack.cpp 1 - - In effect, when a command is pushed, it becomes the top-most command - on the stack. - - To support command compression, QUndoCommand has an id() and the virtual function - mergeWith(). These functions are used by QUndoStack::push(). - - To support command macros, a QUndoCommand object can have any number of child - commands. Undoing or redoing the parent command will cause the child - commands to be undone or redone. A command can be assigned - to a parent explicitly in the constructor. In this case, the command - will be owned by the parent. - - The parent in this case is usually an empty command, in that it doesn't - provide its own implementation of undo() and redo(). Instead, it uses - the base implementations of these functions, which simply call undo() or - redo() on all its children. The parent should, however, have a meaningful - text(). - - \snippet doc/src/snippets/code/src_gui_util_qundostack.cpp 2 - - Another way to create macros is to use the convenience functions - QUndoStack::beginMacro() and QUndoStack::endMacro(). - - \sa QUndoStack -*/ - -/*! - Constructs a QUndoCommand object with the given \a parent and \a text. - - If \a parent is not 0, this command is appended to parent's child list. - The parent command then owns this command and will delete it in its - destructor. - - \sa ~QUndoCommand() -*/ - -QUndoCommand::QUndoCommand(const QString &text, QUndoCommand *parent) -{ - d = new QUndoCommandPrivate; - if (parent != 0) - parent->d->child_list.append(this); - setText(text); -} - -/*! - Constructs a QUndoCommand object with parent \a parent. - - If \a parent is not 0, this command is appended to parent's child list. - The parent command then owns this command and will delete it in its - destructor. - - \sa ~QUndoCommand() -*/ - -QUndoCommand::QUndoCommand(QUndoCommand *parent) -{ - d = new QUndoCommandPrivate; - if (parent != 0) - parent->d->child_list.append(this); -} - -/*! - Destroys the QUndoCommand object and all child commands. - - \sa QUndoCommand() -*/ - -QUndoCommand::~QUndoCommand() -{ - qDeleteAll(d->child_list); - delete d; -} - -/*! - Returns the ID of this command. - - A command ID is used in command compression. It must be an integer unique to - this command's class, or -1 if the command doesn't support compression. - - If the command supports compression this function must be overridden in the - derived class to return the correct ID. The base implementation returns -1. - - QUndoStack::push() will only try to merge two commands if they have the - same ID, and the ID is not -1. - - \sa mergeWith(), QUndoStack::push() -*/ - -int QUndoCommand::id() const -{ - return -1; -} - -/*! - Attempts to merge this command with \a command. Returns true on - success; otherwise returns false. - - If this function returns true, calling this command's redo() must have the same - effect as redoing both this command and \a command. - Similarly, calling this command's undo() must have the same effect as undoing - \a command and this command. - - QUndoStack will only try to merge two commands if they have the same id, and - the id is not -1. - - The default implementation returns false. - - \snippet doc/src/snippets/code/src_gui_util_qundostack.cpp 3 - - \sa id() QUndoStack::push() -*/ - -bool QUndoCommand::mergeWith(const QUndoCommand *command) -{ - Q_UNUSED(command); - return false; -} - -/*! - Applies a change to the document. This function must be implemented in - the derived class. Calling QUndoStack::push(), - QUndoStack::undo() or QUndoStack::redo() from this function leads to - undefined beahavior. - - The default implementation calls redo() on all child commands. - - \sa undo() -*/ - -void QUndoCommand::redo() -{ - for (int i = 0; i < d->child_list.size(); ++i) - d->child_list.at(i)->redo(); -} - -/*! - Reverts a change to the document. After undo() is called, the state of - the document should be the same as before redo() was called. This function must - be implemented in the derived class. Calling QUndoStack::push(), - QUndoStack::undo() or QUndoStack::redo() from this function leads to - undefined beahavior. - - The default implementation calls undo() on all child commands in reverse order. - - \sa redo() -*/ - -void QUndoCommand::undo() -{ - for (int i = d->child_list.size() - 1; i >= 0; --i) - d->child_list.at(i)->undo(); -} - -/*! - Returns a short text string describing what this command does; for example, - "insert text". - - The text is used for names of items in QUndoView. - - \sa actionText(), setText(), QUndoStack::createUndoAction(), QUndoStack::createRedoAction() -*/ - -QString QUndoCommand::text() const -{ - return d->text; -} - -/*! - \since 4.8 - - Returns a short text string describing what this command does; for example, - "insert text". - - The text is used when the text properties of the stack's undo and redo - actions are updated. - - \sa text(), setText(), QUndoStack::createUndoAction(), QUndoStack::createRedoAction() -*/ - -QString QUndoCommand::actionText() const -{ - return d->actionText; -} - -/*! - Sets the command's text to be the \a text specified. - - The specified text should be a short user-readable string describing what this - command does. - - If you need to have two different strings for text() and actionText(), separate - them with "\n" and pass into this function. Even if you do not use this feature - for English strings during development, you can still let translators use two - different strings in order to match specific languages' needs. - The described feature and the function actionText() are available since Qt 4.8. - - \sa text() actionText() QUndoStack::createUndoAction() QUndoStack::createRedoAction() -*/ - -void QUndoCommand::setText(const QString &text) -{ - int cdpos = text.indexOf(QLatin1Char('\n')); - if (cdpos > 0) { - d->text = text.left(cdpos); - d->actionText = text.mid(cdpos + 1); - } else { - d->text = text; - d->actionText = text; - } -} - -/*! - \since 4.4 - - Returns the number of child commands in this command. - - \sa child() -*/ - -int QUndoCommand::childCount() const -{ - return d->child_list.count(); -} - -/*! - \since 4.4 - - Returns the child command at \a index. - - \sa childCount(), QUndoStack::command() -*/ - -const QUndoCommand *QUndoCommand::child(int index) const -{ - if (index < 0 || index >= d->child_list.count()) - return 0; - return d->child_list.at(index); -} - -#endif // QT_NO_UNDOCOMMAND - -#ifndef QT_NO_UNDOSTACK - -/*! - \class QUndoStack - \brief The QUndoStack class is a stack of QUndoCommand objects. - \since 4.2 - - For an overview of Qt's Undo Framework, see the - \l{Overview of Qt's Undo Framework}{overview document}. - - An undo stack maintains a stack of commands that have been applied to a - document. - - New commands are pushed on the stack using push(). Commands can be - undone and redone using undo() and redo(), or by triggering the - actions returned by createUndoAction() and createRedoAction(). - - QUndoStack keeps track of the \a current command. This is the command - which will be executed by the next call to redo(). The index of this - command is returned by index(). The state of the edited object can be - rolled forward or back using setIndex(). If the top-most command on the - stack has already been redone, index() is equal to count(). - - QUndoStack provides support for undo and redo actions, command - compression, command macros, and supports the concept of a - \e{clean state}. - - \section1 Undo and Redo Actions - - QUndoStack provides convenient undo and redo QAction objects, which - can be inserted into a menu or a toolbar. When commands are undone or - redone, QUndoStack updates the text properties of these actions - to reflect what change they will trigger. The actions are also disabled - when no command is available for undo or redo. These actions - are returned by QUndoStack::createUndoAction() and QUndoStack::createRedoAction(). - - \section1 Command Compression and Macros - - Command compression is useful when several commands can be compressed - into a single command that can be undone and redone in a single operation. - For example, when a user types a character in a text editor, a new command - is created. This command inserts the character into the document at the - cursor position. However, it is more convenient for the user to be able - to undo or redo typing of whole words, sentences, or paragraphs. - Command compression allows these single-character commands to be merged - into a single command which inserts or deletes sections of text. - For more information, see QUndoCommand::mergeWith() and push(). - - A command macro is a sequence of commands, all of which are undone and - redone in one go. Command macros are created by giving a command a list - of child commands. - Undoing or redoing the parent command will cause the child commands to - be undone or redone. Command macros may be created explicitly - by specifying a parent in the QUndoCommand constructor, or by using the - convenience functions beginMacro() and endMacro(). - - Although command compression and macros appear to have the same effect to the - user, they often have different uses in an application. Commands that - perform small changes to a document may be usefully compressed if there is - no need to individually record them, and if only larger changes are relevant - to the user. - However, for commands that need to be recorded individually, or those that - cannot be compressed, it is useful to use macros to provide a more convenient - user experience while maintaining a record of each command. - - \section1 Clean State - - QUndoStack supports the concept of a clean state. When the - document is saved to disk, the stack can be marked as clean using - setClean(). Whenever the stack returns to this state through undoing and - redoing commands, it emits the signal cleanChanged(). This signal - is also emitted when the stack leaves the clean state. This signal is - usually used to enable and disable the save actions in the application, - and to update the document's title to reflect that it contains unsaved - changes. - - \sa QUndoCommand, QUndoView -*/ - -#ifndef QT_NO_ACTION - -QUndoAction::QUndoAction(const QString &prefix, QObject *parent) - : QAction(parent) -{ - m_prefix = prefix; -} - -void QUndoAction::setPrefixedText(const QString &text) -{ - if (m_defaultText.isEmpty()) { - QString s = m_prefix; - if (!m_prefix.isEmpty() && !text.isEmpty()) - s.append(QLatin1Char(' ')); - s.append(text); - setText(s); - } else { - if (text.isEmpty()) - setText(m_defaultText); - else - setText(m_prefix.arg(text)); - } -} - -void QUndoAction::setTextFormat(const QString &textFormat, const QString &defaultText) -{ - m_prefix = textFormat; - m_defaultText = defaultText; -} - -#endif // QT_NO_ACTION - -/*! \internal - Sets the current index to \a idx, emitting appropriate signals. If \a clean is true, - makes \a idx the clean index as well. -*/ - -void QUndoStackPrivate::setIndex(int idx, bool clean) -{ - Q_Q(QUndoStack); - - bool was_clean = index == clean_index; - - if (idx != index) { - index = idx; - emit q->indexChanged(index); - emit q->canUndoChanged(q->canUndo()); - emit q->undoTextChanged(q->undoText()); - emit q->canRedoChanged(q->canRedo()); - emit q->redoTextChanged(q->redoText()); - } - - if (clean) - clean_index = index; - - bool is_clean = index == clean_index; - if (is_clean != was_clean) - emit q->cleanChanged(is_clean); -} - -/*! \internal - If the number of commands on the stack exceedes the undo limit, deletes commands from - the bottom of the stack. - - Returns true if commands were deleted. -*/ - -bool QUndoStackPrivate::checkUndoLimit() -{ - if (undo_limit <= 0 || !macro_stack.isEmpty() || undo_limit >= command_list.count()) - return false; - - int del_count = command_list.count() - undo_limit; - - for (int i = 0; i < del_count; ++i) - delete command_list.takeFirst(); - - index -= del_count; - if (clean_index != -1) { - if (clean_index < del_count) - clean_index = -1; // we've deleted the clean command - else - clean_index -= del_count; - } - - return true; -} - -/*! - Constructs an empty undo stack with the parent \a parent. The - stack will initially be in the clean state. If \a parent is a - QUndoGroup object, the stack is automatically added to the group. - - \sa push() -*/ - -QUndoStack::QUndoStack(QObject *parent) - : QObject(*(new QUndoStackPrivate), parent) -{ -#ifndef QT_NO_UNDOGROUP - if (QUndoGroup *group = qobject_cast<QUndoGroup*>(parent)) - group->addStack(this); -#endif -} - -/*! - Destroys the undo stack, deleting any commands that are on it. If the - stack is in a QUndoGroup, the stack is automatically removed from the group. - - \sa QUndoStack() -*/ - -QUndoStack::~QUndoStack() -{ -#ifndef QT_NO_UNDOGROUP - Q_D(QUndoStack); - if (d->group != 0) - d->group->removeStack(this); -#endif - clear(); -} - -/*! - Clears the command stack by deleting all commands on it, and returns the stack - to the clean state. - - Commands are not undone or redone; the state of the edited object remains - unchanged. - - This function is usually used when the contents of the document are - abandoned. - - \sa QUndoStack() -*/ - -void QUndoStack::clear() -{ - Q_D(QUndoStack); - - if (d->command_list.isEmpty()) - return; - - bool was_clean = isClean(); - - d->macro_stack.clear(); - qDeleteAll(d->command_list); - d->command_list.clear(); - - d->index = 0; - d->clean_index = 0; - - emit indexChanged(0); - emit canUndoChanged(false); - emit undoTextChanged(QString()); - emit canRedoChanged(false); - emit redoTextChanged(QString()); - - if (!was_clean) - emit cleanChanged(true); -} - -/*! - Pushes \a cmd on the stack or merges it with the most recently executed command. - In either case, executes \a cmd by calling its redo() function. - - If \a cmd's id is not -1, and if the id is the same as that of the - most recently executed command, QUndoStack will attempt to merge the two - commands by calling QUndoCommand::mergeWith() on the most recently executed - command. If QUndoCommand::mergeWith() returns true, \a cmd is deleted. - - In all other cases \a cmd is simply pushed on the stack. - - If commands were undone before \a cmd was pushed, the current command and - all commands above it are deleted. Hence \a cmd always ends up being the - top-most on the stack. - - Once a command is pushed, the stack takes ownership of it. There - are no getters to return the command, since modifying it after it has - been executed will almost always lead to corruption of the document's - state. - - \sa QUndoCommand::id() QUndoCommand::mergeWith() -*/ - -void QUndoStack::push(QUndoCommand *cmd) -{ - Q_D(QUndoStack); - cmd->redo(); - - bool macro = !d->macro_stack.isEmpty(); - - QUndoCommand *cur = 0; - if (macro) { - QUndoCommand *macro_cmd = d->macro_stack.last(); - if (!macro_cmd->d->child_list.isEmpty()) - cur = macro_cmd->d->child_list.last(); - } else { - if (d->index > 0) - cur = d->command_list.at(d->index - 1); - while (d->index < d->command_list.size()) - delete d->command_list.takeLast(); - if (d->clean_index > d->index) - d->clean_index = -1; // we've deleted the clean state - } - - bool try_merge = cur != 0 - && cur->id() != -1 - && cur->id() == cmd->id() - && (macro || d->index != d->clean_index); - - if (try_merge && cur->mergeWith(cmd)) { - delete cmd; - if (!macro) { - emit indexChanged(d->index); - emit canUndoChanged(canUndo()); - emit undoTextChanged(undoText()); - emit canRedoChanged(canRedo()); - emit redoTextChanged(redoText()); - } - } else { - if (macro) { - d->macro_stack.last()->d->child_list.append(cmd); - } else { - d->command_list.append(cmd); - d->checkUndoLimit(); - d->setIndex(d->index + 1, false); - } - } -} - -/*! - Marks the stack as clean and emits cleanChanged() if the stack was - not already clean. - - Whenever the stack returns to this state through the use of undo/redo - commands, it emits the signal cleanChanged(). This signal is also - emitted when the stack leaves the clean state. - - \sa isClean(), cleanIndex() -*/ - -void QUndoStack::setClean() -{ - Q_D(QUndoStack); - if (!d->macro_stack.isEmpty()) { - qWarning("QUndoStack::setClean(): cannot set clean in the middle of a macro"); - return; - } - - d->setIndex(d->index, true); -} - -/*! - If the stack is in the clean state, returns true; otherwise returns false. - - \sa setClean() cleanIndex() -*/ - -bool QUndoStack::isClean() const -{ - Q_D(const QUndoStack); - if (!d->macro_stack.isEmpty()) - return false; - return d->clean_index == d->index; -} - -/*! - Returns the clean index. This is the index at which setClean() was called. - - A stack may not have a clean index. This happens if a document is saved, - some commands are undone, then a new command is pushed. Since - push() deletes all the undone commands before pushing the new command, the stack - can't return to the clean state again. In this case, this function returns -1. - - \sa isClean() setClean() -*/ - -int QUndoStack::cleanIndex() const -{ - Q_D(const QUndoStack); - return d->clean_index; -} - -/*! - Undoes the command below the current command by calling QUndoCommand::undo(). - Decrements the current command index. - - If the stack is empty, or if the bottom command on the stack has already been - undone, this function does nothing. - - \sa redo() index() -*/ - -void QUndoStack::undo() -{ - Q_D(QUndoStack); - if (d->index == 0) - return; - - if (!d->macro_stack.isEmpty()) { - qWarning("QUndoStack::undo(): cannot undo in the middle of a macro"); - return; - } - - int idx = d->index - 1; - d->command_list.at(idx)->undo(); - d->setIndex(idx, false); -} - -/*! - Redoes the current command by calling QUndoCommand::redo(). Increments the current - command index. - - If the stack is empty, or if the top command on the stack has already been - redone, this function does nothing. - - \sa undo() index() -*/ - -void QUndoStack::redo() -{ - Q_D(QUndoStack); - if (d->index == d->command_list.size()) - return; - - if (!d->macro_stack.isEmpty()) { - qWarning("QUndoStack::redo(): cannot redo in the middle of a macro"); - return; - } - - d->command_list.at(d->index)->redo(); - d->setIndex(d->index + 1, false); -} - -/*! - Returns the number of commands on the stack. Macro commands are counted as - one command. - - \sa index() setIndex() command() -*/ - -int QUndoStack::count() const -{ - Q_D(const QUndoStack); - return d->command_list.size(); -} - -/*! - Returns the index of the current command. This is the command that will be - executed on the next call to redo(). It is not always the top-most command - on the stack, since a number of commands may have been undone. - - \sa undo() redo() count() -*/ - -int QUndoStack::index() const -{ - Q_D(const QUndoStack); - return d->index; -} - -/*! - Repeatedly calls undo() or redo() until the current command index reaches - \a idx. This function can be used to roll the state of the document forwards - of backwards. indexChanged() is emitted only once. - - \sa index() count() undo() redo() -*/ - -void QUndoStack::setIndex(int idx) -{ - Q_D(QUndoStack); - if (!d->macro_stack.isEmpty()) { - qWarning("QUndoStack::setIndex(): cannot set index in the middle of a macro"); - return; - } - - if (idx < 0) - idx = 0; - else if (idx > d->command_list.size()) - idx = d->command_list.size(); - - int i = d->index; - while (i < idx) - d->command_list.at(i++)->redo(); - while (i > idx) - d->command_list.at(--i)->undo(); - - d->setIndex(idx, false); -} - -/*! - Returns true if there is a command available for undo; otherwise returns false. - - This function returns false if the stack is empty, or if the bottom command - on the stack has already been undone. - - Synonymous with index() == 0. - - \sa index() canRedo() -*/ - -bool QUndoStack::canUndo() const -{ - Q_D(const QUndoStack); - if (!d->macro_stack.isEmpty()) - return false; - return d->index > 0; -} - -/*! - Returns true if there is a command available for redo; otherwise returns false. - - This function returns false if the stack is empty or if the top command - on the stack has already been redone. - - Synonymous with index() == count(). - - \sa index() canUndo() -*/ - -bool QUndoStack::canRedo() const -{ - Q_D(const QUndoStack); - if (!d->macro_stack.isEmpty()) - return false; - return d->index < d->command_list.size(); -} - -/*! - Returns the text of the command which will be undone in the next call to undo(). - - \sa QUndoCommand::actionText() redoText() -*/ - -QString QUndoStack::undoText() const -{ - Q_D(const QUndoStack); - if (!d->macro_stack.isEmpty()) - return QString(); - if (d->index > 0) - return d->command_list.at(d->index - 1)->actionText(); - return QString(); -} - -/*! - Returns the text of the command which will be redone in the next call to redo(). - - \sa QUndoCommand::actionText() undoText() -*/ - -QString QUndoStack::redoText() const -{ - Q_D(const QUndoStack); - if (!d->macro_stack.isEmpty()) - return QString(); - if (d->index < d->command_list.size()) - return d->command_list.at(d->index)->actionText(); - return QString(); -} - -#ifndef QT_NO_ACTION - -/*! - Creates an undo QAction object with the given \a parent. - - Triggering this action will cause a call to undo(). The text of this action - is the text of the command which will be undone in the next call to undo(), - prefixed by the specified \a prefix. If there is no command available for undo, - this action will be disabled. - - If \a prefix is empty, the default template "Undo %1" is used instead of prefix. - Before Qt 4.8, the prefix "Undo" was used by default. - - \sa createRedoAction(), canUndo(), QUndoCommand::text() -*/ - -QAction *QUndoStack::createUndoAction(QObject *parent, const QString &prefix) const -{ - QUndoAction *result = new QUndoAction(prefix, parent); - if (prefix.isEmpty()) - result->setTextFormat(tr("Undo %1"), tr("Undo", "Default text for undo action")); - - result->setEnabled(canUndo()); - result->setPrefixedText(undoText()); - connect(this, SIGNAL(canUndoChanged(bool)), - result, SLOT(setEnabled(bool))); - connect(this, SIGNAL(undoTextChanged(QString)), - result, SLOT(setPrefixedText(QString))); - connect(result, SIGNAL(triggered()), this, SLOT(undo())); - return result; -} - -/*! - Creates an redo QAction object with the given \a parent. - - Triggering this action will cause a call to redo(). The text of this action - is the text of the command which will be redone in the next call to redo(), - prefixed by the specified \a prefix. If there is no command available for redo, - this action will be disabled. - - If \a prefix is empty, the default template "Redo %1" is used instead of prefix. - Before Qt 4.8, the prefix "Redo" was used by default. - - \sa createUndoAction(), canRedo(), QUndoCommand::text() -*/ - -QAction *QUndoStack::createRedoAction(QObject *parent, const QString &prefix) const -{ - QUndoAction *result = new QUndoAction(prefix, parent); - if (prefix.isEmpty()) - result->setTextFormat(tr("Redo %1"), tr("Redo", "Default text for redo action")); - - result->setEnabled(canRedo()); - result->setPrefixedText(redoText()); - connect(this, SIGNAL(canRedoChanged(bool)), - result, SLOT(setEnabled(bool))); - connect(this, SIGNAL(redoTextChanged(QString)), - result, SLOT(setPrefixedText(QString))); - connect(result, SIGNAL(triggered()), this, SLOT(redo())); - return result; -} - -#endif // QT_NO_ACTION - -/*! - Begins composition of a macro command with the given \a text description. - - An empty command described by the specified \a text is pushed on the stack. - Any subsequent commands pushed on the stack will be appended to the empty - command's children until endMacro() is called. - - Calls to beginMacro() and endMacro() may be nested, but every call to - beginMacro() must have a matching call to endMacro(). - - While a macro is composed, the stack is disabled. This means that: - \list - \i indexChanged() and cleanChanged() are not emitted, - \i canUndo() and canRedo() return false, - \i calling undo() or redo() has no effect, - \i the undo/redo actions are disabled. - \endlist - - The stack becomes enabled and appropriate signals are emitted when endMacro() - is called for the outermost macro. - - \snippet doc/src/snippets/code/src_gui_util_qundostack.cpp 4 - - This code is equivalent to: - - \snippet doc/src/snippets/code/src_gui_util_qundostack.cpp 5 - - \sa endMacro() -*/ - -void QUndoStack::beginMacro(const QString &text) -{ - Q_D(QUndoStack); - QUndoCommand *cmd = new QUndoCommand(); - cmd->setText(text); - - if (d->macro_stack.isEmpty()) { - while (d->index < d->command_list.size()) - delete d->command_list.takeLast(); - if (d->clean_index > d->index) - d->clean_index = -1; // we've deleted the clean state - d->command_list.append(cmd); - } else { - d->macro_stack.last()->d->child_list.append(cmd); - } - d->macro_stack.append(cmd); - - if (d->macro_stack.count() == 1) { - emit canUndoChanged(false); - emit undoTextChanged(QString()); - emit canRedoChanged(false); - emit redoTextChanged(QString()); - } -} - -/*! - Ends composition of a macro command. - - If this is the outermost macro in a set nested macros, this function emits - indexChanged() once for the entire macro command. - - \sa beginMacro() -*/ - -void QUndoStack::endMacro() -{ - Q_D(QUndoStack); - if (d->macro_stack.isEmpty()) { - qWarning("QUndoStack::endMacro(): no matching beginMacro()"); - return; - } - - d->macro_stack.removeLast(); - - if (d->macro_stack.isEmpty()) { - d->checkUndoLimit(); - d->setIndex(d->index + 1, false); - } -} - -/*! - \since 4.4 - - Returns a const pointer to the command at \a index. - - This function returns a const pointer, because modifying a command, - once it has been pushed onto the stack and executed, almost always - causes corruption of the state of the document, if the command is - later undone or redone. - - \sa QUndoCommand::child() -*/ -const QUndoCommand *QUndoStack::command(int index) const -{ - Q_D(const QUndoStack); - - if (index < 0 || index >= d->command_list.count()) - return 0; - return d->command_list.at(index); -} - -/*! - Returns the text of the command at index \a idx. - - \sa beginMacro() -*/ - -QString QUndoStack::text(int idx) const -{ - Q_D(const QUndoStack); - - if (idx < 0 || idx >= d->command_list.size()) - return QString(); - return d->command_list.at(idx)->text(); -} - -/*! - \property QUndoStack::undoLimit - \brief the maximum number of commands on this stack. - \since 4.3 - - When the number of commands on a stack exceedes the stack's undoLimit, commands are - deleted from the bottom of the stack. Macro commands (commands with child commands) - are treated as one command. The default value is 0, which means that there is no - limit. - - This property may only be set when the undo stack is empty, since setting it on a - non-empty stack might delete the command at the current index. Calling setUndoLimit() - on a non-empty stack prints a warning and does nothing. -*/ - -void QUndoStack::setUndoLimit(int limit) -{ - Q_D(QUndoStack); - - if (!d->command_list.isEmpty()) { - qWarning("QUndoStack::setUndoLimit(): an undo limit can only be set when the stack is empty"); - return; - } - - if (limit == d->undo_limit) - return; - d->undo_limit = limit; - d->checkUndoLimit(); -} - -int QUndoStack::undoLimit() const -{ - Q_D(const QUndoStack); - - return d->undo_limit; -} - -/*! - \property QUndoStack::active - \brief the active status of this stack. - - An application often has multiple undo stacks, one for each opened document. The active - stack is the one associated with the currently active document. If the stack belongs - to a QUndoGroup, calls to QUndoGroup::undo() or QUndoGroup::redo() will be forwarded - to this stack when it is active. If the QUndoGroup is watched by a QUndoView, the view - will display the contents of this stack when it is active. If the stack does not belong to - a QUndoGroup, making it active has no effect. - - It is the programmer's responsibility to specify which stack is active by - calling setActive(), usually when the associated document window receives focus. - - \sa QUndoGroup -*/ - -void QUndoStack::setActive(bool active) -{ -#ifdef QT_NO_UNDOGROUP - Q_UNUSED(active); -#else - Q_D(QUndoStack); - - if (d->group != 0) { - if (active) - d->group->setActiveStack(this); - else if (d->group->activeStack() == this) - d->group->setActiveStack(0); - } -#endif -} - -bool QUndoStack::isActive() const -{ -#ifdef QT_NO_UNDOGROUP - return true; -#else - Q_D(const QUndoStack); - return d->group == 0 || d->group->activeStack() == this; -#endif -} - -/*! - \fn void QUndoStack::indexChanged(int idx) - - This signal is emitted whenever a command modifies the state of the document. - This happens when a command is undone or redone. When a macro - command is undone or redone, or setIndex() is called, this signal - is emitted only once. - - \a idx specifies the index of the current command, ie. the command which will be - executed on the next call to redo(). - - \sa index() setIndex() -*/ - -/*! - \fn void QUndoStack::cleanChanged(bool clean) - - This signal is emitted whenever the stack enters or leaves the clean state. - If \a clean is true, the stack is in a clean state; otherwise this signal - indicates that it has left the clean state. - - \sa isClean() setClean() -*/ - -/*! - \fn void QUndoStack::undoTextChanged(const QString &undoText) - - This signal is emitted whenever the value of undoText() changes. It is - used to update the text property of the undo action returned by createUndoAction(). - \a undoText specifies the new text. -*/ - -/*! - \fn void QUndoStack::canUndoChanged(bool canUndo) - - This signal is emitted whenever the value of canUndo() changes. It is - used to enable or disable the undo action returned by createUndoAction(). - \a canUndo specifies the new value. -*/ - -/*! - \fn void QUndoStack::redoTextChanged(const QString &redoText) - - This signal is emitted whenever the value of redoText() changes. It is - used to update the text property of the redo action returned by createRedoAction(). - \a redoText specifies the new text. -*/ - -/*! - \fn void QUndoStack::canRedoChanged(bool canRedo) - - This signal is emitted whenever the value of canRedo() changes. It is - used to enable or disable the redo action returned by createRedoAction(). - \a canRedo specifies the new value. -*/ - -QT_END_NAMESPACE - -#endif // QT_NO_UNDOSTACK diff --git a/src/gui/util/qundostack.h b/src/gui/util/qundostack.h deleted file mode 100644 index 2cbbc0ad4a..0000000000 --- a/src/gui/util/qundostack.h +++ /dev/null @@ -1,159 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QUNDOSTACK_H -#define QUNDOSTACK_H - -#include <QtCore/qobject.h> -#include <QtCore/qstring.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QAction; -class QUndoCommandPrivate; -class QUndoStackPrivate; - -#ifndef QT_NO_UNDOCOMMAND - -class Q_GUI_EXPORT QUndoCommand -{ - QUndoCommandPrivate *d; - -public: - explicit QUndoCommand(QUndoCommand *parent = 0); - explicit QUndoCommand(const QString &text, QUndoCommand *parent = 0); - virtual ~QUndoCommand(); - - virtual void undo(); - virtual void redo(); - - QString text() const; - QString actionText() const; - void setText(const QString &text); - - virtual int id() const; - virtual bool mergeWith(const QUndoCommand *other); - - int childCount() const; - const QUndoCommand *child(int index) const; - -private: - Q_DISABLE_COPY(QUndoCommand) - friend class QUndoStack; -}; - -#endif // QT_NO_UNDOCOMMAND - -#ifndef QT_NO_UNDOSTACK - -class Q_GUI_EXPORT QUndoStack : public QObject -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QUndoStack) - Q_PROPERTY(bool active READ isActive WRITE setActive) - Q_PROPERTY(int undoLimit READ undoLimit WRITE setUndoLimit) - -public: - explicit QUndoStack(QObject *parent = 0); - ~QUndoStack(); - void clear(); - - void push(QUndoCommand *cmd); - - bool canUndo() const; - bool canRedo() const; - QString undoText() const; - QString redoText() const; - - int count() const; - int index() const; - QString text(int idx) const; - -#ifndef QT_NO_ACTION - QAction *createUndoAction(QObject *parent, - const QString &prefix = QString()) const; - QAction *createRedoAction(QObject *parent, - const QString &prefix = QString()) const; -#endif // QT_NO_ACTION - - bool isActive() const; - bool isClean() const; - int cleanIndex() const; - - void beginMacro(const QString &text); - void endMacro(); - - void setUndoLimit(int limit); - int undoLimit() const; - - const QUndoCommand *command(int index) const; - -public Q_SLOTS: - void setClean(); - void setIndex(int idx); - void undo(); - void redo(); - void setActive(bool active = true); - -Q_SIGNALS: - void indexChanged(int idx); - void cleanChanged(bool clean); - void canUndoChanged(bool canUndo); - void canRedoChanged(bool canRedo); - void undoTextChanged(const QString &undoText); - void redoTextChanged(const QString &redoText); - -private: - Q_DISABLE_COPY(QUndoStack) - friend class QUndoGroup; -}; - -#endif // QT_NO_UNDOSTACK - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QUNDOSTACK_H diff --git a/src/gui/util/qundostack_p.h b/src/gui/util/qundostack_p.h deleted file mode 100644 index 7162e19842..0000000000 --- a/src/gui/util/qundostack_p.h +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QUNDOSTACK_P_H -#define QUNDOSTACK_P_H - -#include <private/qobject_p.h> -#include <QtCore/qlist.h> -#include <QtCore/qstring.h> -#include <QtGui/qaction.h> - -#include "qundostack.h" - -QT_BEGIN_NAMESPACE -class QUndoCommand; -class QUndoGroup; - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -class QUndoCommandPrivate -{ -public: - QUndoCommandPrivate() : id(-1) {} - QList<QUndoCommand*> child_list; - QString text; - QString actionText; - int id; -}; - -#ifndef QT_NO_UNDOSTACK - -class QUndoStackPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QUndoStack) -public: - QUndoStackPrivate() : index(0), clean_index(0), group(0), undo_limit(0) {} - - QList<QUndoCommand*> command_list; - QList<QUndoCommand*> macro_stack; - int index; - int clean_index; - QUndoGroup *group; - int undo_limit; - - void setIndex(int idx, bool clean); - bool checkUndoLimit(); -}; - -#ifndef QT_NO_ACTION -class QUndoAction : public QAction -{ - Q_OBJECT -public: - QUndoAction(const QString &prefix, QObject *parent = 0); - void setTextFormat(const QString &textFormat, const QString &defaultText); -public Q_SLOTS: - void setPrefixedText(const QString &text); -private: - QString m_prefix; - QString m_defaultText; -}; -#endif // QT_NO_ACTION - - -QT_END_NAMESPACE -#endif // QT_NO_UNDOSTACK -#endif // QUNDOSTACK_P_H diff --git a/src/gui/util/qundoview.cpp b/src/gui/util/qundoview.cpp deleted file mode 100644 index d0f411105b..0000000000 --- a/src/gui/util/qundoview.cpp +++ /dev/null @@ -1,476 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qundostack.h" -#include "qundoview.h" - -#ifndef QT_NO_UNDOVIEW - -#include "qundogroup.h" -#include <QtCore/qabstractitemmodel.h> -#include <QtCore/qpointer.h> -#include <QtGui/qicon.h> -#include <private/qlistview_p.h> - -QT_BEGIN_NAMESPACE - -class QUndoModel : public QAbstractItemModel -{ - Q_OBJECT -public: - QUndoModel(QObject *parent = 0); - - QUndoStack *stack() const; - - virtual QModelIndex index(int row, int column, - const QModelIndex &parent = QModelIndex()) const; - virtual QModelIndex parent(const QModelIndex &child) const; - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; - virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - - QModelIndex selectedIndex() const; - QItemSelectionModel *selectionModel() const; - - QString emptyLabel() const; - void setEmptyLabel(const QString &label); - - void setCleanIcon(const QIcon &icon); - QIcon cleanIcon() const; - -public slots: - void setStack(QUndoStack *stack); - -private slots: - void stackChanged(); - void stackDestroyed(QObject *obj); - void setStackCurrentIndex(const QModelIndex &index); - -private: - QUndoStack *m_stack; - QItemSelectionModel *m_sel_model; - QString m_emty_label; - QIcon m_clean_icon; -}; - -QUndoModel::QUndoModel(QObject *parent) - : QAbstractItemModel(parent) -{ - m_stack = 0; - m_sel_model = new QItemSelectionModel(this, this); - connect(m_sel_model, SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(setStackCurrentIndex(QModelIndex))); - m_emty_label = tr("<empty>"); -} - -QItemSelectionModel *QUndoModel::selectionModel() const -{ - return m_sel_model; -} - -QUndoStack *QUndoModel::stack() const -{ - return m_stack; -} - -void QUndoModel::setStack(QUndoStack *stack) -{ - if (m_stack == stack) - return; - - if (m_stack != 0) { - disconnect(m_stack, SIGNAL(cleanChanged(bool)), this, SLOT(stackChanged())); - disconnect(m_stack, SIGNAL(indexChanged(int)), this, SLOT(stackChanged())); - disconnect(m_stack, SIGNAL(destroyed(QObject*)), this, SLOT(stackDestroyed(QObject*))); - } - m_stack = stack; - if (m_stack != 0) { - connect(m_stack, SIGNAL(cleanChanged(bool)), this, SLOT(stackChanged())); - connect(m_stack, SIGNAL(indexChanged(int)), this, SLOT(stackChanged())); - connect(m_stack, SIGNAL(destroyed(QObject*)), this, SLOT(stackDestroyed(QObject*))); - } - - stackChanged(); -} - -void QUndoModel::stackDestroyed(QObject *obj) -{ - if (obj != m_stack) - return; - m_stack = 0; - - stackChanged(); -} - -void QUndoModel::stackChanged() -{ - reset(); - m_sel_model->setCurrentIndex(selectedIndex(), QItemSelectionModel::ClearAndSelect); -} - -void QUndoModel::setStackCurrentIndex(const QModelIndex &index) -{ - if (m_stack == 0) - return; - - if (index == selectedIndex()) - return; - - if (index.column() != 0) - return; - - m_stack->setIndex(index.row()); -} - -QModelIndex QUndoModel::selectedIndex() const -{ - return m_stack == 0 ? QModelIndex() : createIndex(m_stack->index(), 0); -} - -QModelIndex QUndoModel::index(int row, int column, const QModelIndex &parent) const -{ - if (m_stack == 0) - return QModelIndex(); - - if (parent.isValid()) - return QModelIndex(); - - if (column != 0) - return QModelIndex(); - - if (row < 0 || row > m_stack->count()) - return QModelIndex(); - - return createIndex(row, column); -} - -QModelIndex QUndoModel::parent(const QModelIndex&) const -{ - return QModelIndex(); -} - -int QUndoModel::rowCount(const QModelIndex &parent) const -{ - if (m_stack == 0) - return 0; - - if (parent.isValid()) - return 0; - - return m_stack->count() + 1; -} - -int QUndoModel::columnCount(const QModelIndex&) const -{ - return 1; -} - -QVariant QUndoModel::data(const QModelIndex &index, int role) const -{ - if (m_stack == 0) - return QVariant(); - - if (index.column() != 0) - return QVariant(); - - if (index.row() < 0 || index.row() > m_stack->count()) - return QVariant(); - - if (role == Qt::DisplayRole) { - if (index.row() == 0) - return m_emty_label; - return m_stack->text(index.row() - 1); - } else if (role == Qt::DecorationRole) { - if (index.row() == m_stack->cleanIndex() && !m_clean_icon.isNull()) - return m_clean_icon; - return QVariant(); - } - - return QVariant(); -} - -QString QUndoModel::emptyLabel() const -{ - return m_emty_label; -} - -void QUndoModel::setEmptyLabel(const QString &label) -{ - m_emty_label = label; - stackChanged(); -} - -void QUndoModel::setCleanIcon(const QIcon &icon) -{ - m_clean_icon = icon; - stackChanged(); -} - -QIcon QUndoModel::cleanIcon() const -{ - return m_clean_icon; -} - -/*! - \class QUndoView - \brief The QUndoView class displays the contents of a QUndoStack. - \since 4.2 - - \ingroup advanced - - QUndoView is a QListView which displays the list of commands pushed on an undo stack. - The most recently executed command is always selected. Selecting a different command - results in a call to QUndoStack::setIndex(), rolling the state of the document - backwards or forward to the new command. - - The stack can be set explicitly with setStack(). Alternatively, a QUndoGroup object can - be set with setGroup(). The view will then update itself automatically whenever the - active stack of the group changes. - - \image qundoview.png -*/ - -class QUndoViewPrivate : public QListViewPrivate -{ - Q_DECLARE_PUBLIC(QUndoView) -public: - QUndoViewPrivate() : -#ifndef QT_NO_UNDOGROUP - group(0), -#endif - model(0) {} - -#ifndef QT_NO_UNDOGROUP - QPointer<QUndoGroup> group; -#endif - QUndoModel *model; - - void init(); -}; - -void QUndoViewPrivate::init() -{ - Q_Q(QUndoView); - - model = new QUndoModel(q); - q->setModel(model); - q->setSelectionModel(model->selectionModel()); -} - -/*! - Constructs a new view with parent \a parent. -*/ - -QUndoView::QUndoView(QWidget *parent) - : QListView(*new QUndoViewPrivate(), parent) -{ - Q_D(QUndoView); - d->init(); -} - -/*! - Constructs a new view with parent \a parent and sets the observed stack to \a stack. -*/ - -QUndoView::QUndoView(QUndoStack *stack, QWidget *parent) - : QListView(*new QUndoViewPrivate(), parent) -{ - Q_D(QUndoView); - d->init(); - setStack(stack); -} - -#ifndef QT_NO_UNDOGROUP - -/*! - Constructs a new view with parent \a parent and sets the observed group to \a group. - - The view will update itself autmiatically whenever the active stack of the group changes. -*/ - -QUndoView::QUndoView(QUndoGroup *group, QWidget *parent) - : QListView(*new QUndoViewPrivate(), parent) -{ - Q_D(QUndoView); - d->init(); - setGroup(group); -} - -#endif // QT_NO_UNDOGROUP - -/*! - Destroys this view. -*/ - -QUndoView::~QUndoView() -{ -} - -/*! - Returns the stack currently displayed by this view. If the view is looking at a - QUndoGroup, this the group's active stack. - - \sa setStack() setGroup() -*/ - -QUndoStack *QUndoView::stack() const -{ - Q_D(const QUndoView); - return d->model->stack(); -} - -/*! - Sets the stack displayed by this view to \a stack. If \a stack is 0, the view - will be empty. - - If the view was previously looking at a QUndoGroup, the group is set to 0. - - \sa stack() setGroup() -*/ - -void QUndoView::setStack(QUndoStack *stack) -{ - Q_D(QUndoView); -#ifndef QT_NO_UNDOGROUP - setGroup(0); -#endif - d->model->setStack(stack); -} - -#ifndef QT_NO_UNDOGROUP - -/*! - Sets the group displayed by this view to \a group. If \a group is 0, the view will - be empty. - - The view will update itself autmiatically whenever the active stack of the group changes. - - \sa group() setStack() -*/ - -void QUndoView::setGroup(QUndoGroup *group) -{ - Q_D(QUndoView); - - if (d->group == group) - return; - - if (d->group != 0) { - disconnect(d->group, SIGNAL(activeStackChanged(QUndoStack*)), - d->model, SLOT(setStack(QUndoStack*))); - } - - d->group = group; - - if (d->group != 0) { - connect(d->group, SIGNAL(activeStackChanged(QUndoStack*)), - d->model, SLOT(setStack(QUndoStack*))); - d->model->setStack(d->group->activeStack()); - } else { - d->model->setStack(0); - } -} - -/*! - Returns the group displayed by this view. - - If the view is not looking at group, this function returns 0. - - \sa setGroup() setStack() -*/ - -QUndoGroup *QUndoView::group() const -{ - Q_D(const QUndoView); - return d->group; -} - -#endif // QT_NO_UNDOGROUP - -/*! - \property QUndoView::emptyLabel - \brief the label used for the empty state. - - The empty label is the topmost element in the list of commands, which represents - the state of the document before any commands were pushed on the stack. The default - is the string "<empty>". -*/ - -void QUndoView::setEmptyLabel(const QString &label) -{ - Q_D(QUndoView); - d->model->setEmptyLabel(label); -} - -QString QUndoView::emptyLabel() const -{ - Q_D(const QUndoView); - return d->model->emptyLabel(); -} - -/*! - \property QUndoView::cleanIcon - \brief the icon used to represent the clean state. - - A stack may have a clean state set with QUndoStack::setClean(). This is usually - the state of the document at the point it was saved. QUndoView can display an - icon in the list of commands to show the clean state. If this property is - a null icon, no icon is shown. The default value is the null icon. -*/ - -void QUndoView::setCleanIcon(const QIcon &icon) -{ - Q_D(const QUndoView); - d->model->setCleanIcon(icon); - -} - -QIcon QUndoView::cleanIcon() const -{ - Q_D(const QUndoView); - return d->model->cleanIcon(); -} - -QT_END_NAMESPACE - -#include "qundoview.moc" - -#endif // QT_NO_UNDOVIEW diff --git a/src/gui/util/qundoview.h b/src/gui/util/qundoview.h deleted file mode 100644 index 5c3801ddea..0000000000 --- a/src/gui/util/qundoview.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QUNDOVIEW_H -#define QUNDOVIEW_H - -#include <QtGui/qlistview.h> -#include <QtCore/qstring.h> - -#ifndef QT_NO_UNDOVIEW - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QUndoViewPrivate; -class QUndoStack; -class QUndoGroup; -class QIcon; - -QT_MODULE(Gui) - -class Q_GUI_EXPORT QUndoView : public QListView -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QUndoView) - Q_PROPERTY(QString emptyLabel READ emptyLabel WRITE setEmptyLabel) - Q_PROPERTY(QIcon cleanIcon READ cleanIcon WRITE setCleanIcon) - -public: - explicit QUndoView(QWidget *parent = 0); - explicit QUndoView(QUndoStack *stack, QWidget *parent = 0); -#ifndef QT_NO_UNDOGROUP - explicit QUndoView(QUndoGroup *group, QWidget *parent = 0); -#endif - ~QUndoView(); - - QUndoStack *stack() const; -#ifndef QT_NO_UNDOGROUP - QUndoGroup *group() const; -#endif - - void setEmptyLabel(const QString &label); - QString emptyLabel() const; - - void setCleanIcon(const QIcon &icon); - QIcon cleanIcon() const; - -public Q_SLOTS: - void setStack(QUndoStack *stack); -#ifndef QT_NO_UNDOGROUP - void setGroup(QUndoGroup *group); -#endif - -private: - Q_DISABLE_COPY(QUndoView) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QT_NO_UNDOVIEW -#endif // QUNDOVIEW_H diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp new file mode 100644 index 0000000000..43251a8829 --- /dev/null +++ b/src/gui/util/qvalidator.cpp @@ -0,0 +1,1012 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qdebug.h> + +#include "qvalidator.h" +#ifndef QT_NO_VALIDATOR +#include "private/qobject_p.h" +#include "private/qlocale_p.h" + +#include <limits.h> +#include <math.h> + +QT_BEGIN_NAMESPACE + +/*! + \class QValidator + \brief The QValidator class provides validation of input text. + + The class itself is abstract. Two subclasses, \l QIntValidator and + \l QDoubleValidator, provide basic numeric-range checking, and \l + QRegExpValidator provides general checking using a custom regular + expression. + + If the built-in validators aren't sufficient, you can subclass + QValidator. The class has two virtual functions: validate() and + fixup(). + + \l validate() must be implemented by every subclass. It returns + \l Invalid, \l Intermediate or \l Acceptable depending on whether + its argument is valid (for the subclass's definition of valid). + + These three states require some explanation. An \l Invalid string + is \e clearly invalid. \l Intermediate is less obvious: the + concept of validity is difficult to apply when the string is + incomplete (still being edited). QValidator defines \l Intermediate + as the property of a string that is neither clearly invalid nor + acceptable as a final result. \l Acceptable means that the string + is acceptable as a final result. One might say that any string + that is a plausible intermediate state during entry of an \l + Acceptable string is \l Intermediate. + + Here are some examples: + + \list + + \i For a line edit that accepts integers from 10 to 1000 inclusive, + 42 and 123 are \l Acceptable, the empty string and 5 are \l + Intermediate, and "asdf" and 1114 is \l Invalid. + + \i For an editable combobox that accepts URLs, any well-formed URL + is \l Acceptable, "http://example.com/," is \l Intermediate + (it might be a cut and paste action that accidentally took in a + comma at the end), the empty string is \l Intermediate (the user + might select and delete all of the text in preparation for entering + a new URL) and "http:///./" is \l Invalid. + + \i For a spin box that accepts lengths, "11cm" and "1in" are \l + Acceptable, "11" and the empty string are \l Intermediate, and + "http://example.com" and "hour" are \l Invalid. + + \endlist + + \l fixup() is provided for validators that can repair some user + errors. The default implementation does nothing. QLineEdit, for + example, will call fixup() if the user presses Enter (or Return) + and the content is not currently valid. This allows the fixup() + function the opportunity of performing some magic to make an \l + Invalid string \l Acceptable. + + A validator has a locale, set with setLocale(). It is typically used + to parse localized data. For example, QIntValidator and QDoubleValidator + use it to parse localized representations of integers and doubles. + + QValidator is typically used with QLineEdit, QSpinBox and + QComboBox. + + \sa QIntValidator, QDoubleValidator, QRegExpValidator, {Line Edits Example} +*/ + + +/*! + \enum QValidator::State + + This enum type defines the states in which a validated string can + exist. + + \value Invalid The string is \e clearly invalid. + \value Intermediate The string is a plausible intermediate value. + \value Acceptable The string is acceptable as a final result; + i.e. it is valid. + + \omitvalue Valid +*/ + + +/*! + \fn void QIntValidator::topChanged(int top) + + This signal is emitted after the top property changed. + + \sa QIntValidator::top(), QIntValidator::setTop(), QIntValidator::bottom(), QIntValidator::setBottom() + \internal +*/ + +/*! + \fn void QIntValidator::bottomChanged(int bottom) + + This signal is emitted after the bottom property changed. + + \sa QIntValidator::top(), QIntValidator::setTop(), QIntValidator::bottom(), QIntValidator::setBottom() + \internal +*/ + +/*! + \fn void QDoubleValidator::topChanged(int top) + + This signal is emitted after the top property changed. + + \sa QDoubleValidator::top(), QDoubleValidator::setTop(), QDoubleValidator::bottom(), QDoubleValidator::setBottom() + \internal +*/ + +/*! + \fn void QDoubleValidator::bottomChanged(int bottom) + + This signal is emitted after the bottom property changed. + + \sa QDoubleValidator::top(), QDoubleValidator::setTop(), QDoubleValidator::bottom(), QDoubleValidator::setBottom() + \internal +*/ + +/*! + \fn void QDoubleValidator::decimalsChanged(int decimals) + + This signal is emitted after the decimals property changed. + + \internal +*/ + +/*! + \fn void QDoubleValidator::notationChanged(QDoubleValidator::Notation notation) + + This signal is emitted after the notation property changed. + + QDoubleValidator::Notation is not a registered metatype, so for queued connections, + you will have to register it with Q_DECLARE_METATYPE() and qRegisterMetaType(). + + \internal +*/ + +/*! + \fn void QRegExpValidator::regExpChanged(const QRegExp ®Exp) + + This signal is emitted after the regExp property changed. + \internal +*/ + +class QValidatorPrivate : public QObjectPrivate{ + Q_DECLARE_PUBLIC(QValidator) +public: + QValidatorPrivate() : QObjectPrivate() + { + } + + QLocale locale; +}; + + +/*! + Sets up the validator. The \a parent parameter is + passed on to the QObject constructor. +*/ + +QValidator::QValidator(QObject * parent) + : QObject(*new QValidatorPrivate, parent) +{ +} + +#ifdef QT3_SUPPORT +/*! + \obsolete + Sets up the validator. The \a parent and \a name parameters are + passed on to the QObject constructor. +*/ + +QValidator::QValidator(QObject * parent, const char *name) + : QObject(*new QValidatorPrivate, parent) +{ + setObjectName(QString::fromAscii(name)); +} +#endif + +/*! + Destroys the validator, freeing any storage and other resources + used. +*/ + +QValidator::~QValidator() +{ +} + +/*! + Returns the locale for the validator. The locale is by default initialized to the same as QLocale(). + + \sa setLocale() + \sa QLocale::QLocale() +*/ +QLocale QValidator::locale() const +{ + Q_D(const QValidator); + return d->locale; +} + +/*! + Sets the \a locale that will be used for the validator. Unless + setLocale has been called, the validator will use the default + locale set with QLocale::setDefault(). If a default locale has not + been set, it is the operating system's locale. + + \sa locale() QLocale::setDefault() +*/ +void QValidator::setLocale(const QLocale &locale) +{ + Q_D(QValidator); + d->locale = locale; +} + +/*! + \fn QValidator::State QValidator::validate(QString &input, int &pos) const + + This virtual function returns \l Invalid if \a input is invalid + according to this validator's rules, \l Intermediate if it + is likely that a little more editing will make the input + acceptable (e.g. the user types "4" into a widget which accepts + integers between 10 and 99), and \l Acceptable if the input is + valid. + + The function can change both \a input and \a pos (the cursor position) + if required. +*/ + + +/*! + \fn void QValidator::fixup(QString & input) const + + This function attempts to change \a input to be valid according to + this validator's rules. It need not result in a valid string: + callers of this function must re-test afterwards; the default does + nothing. + + Reimplementations of this function can change \a input even if + they do not produce a valid string. For example, an ISBN validator + might want to delete every character except digits and "-", even + if the result is still not a valid ISBN; a surname validator might + want to remove whitespace from the start and end of the string, + even if the resulting string is not in the list of accepted + surnames. +*/ + +void QValidator::fixup(QString &) const +{ +} + + +/*! + \class QIntValidator + \brief The QIntValidator class provides a validator that ensures + a string contains a valid integer within a specified range. + + Example of use: + + \snippet doc/src/snippets/code/src_gui_widgets_qvalidator.cpp 0 + + Below we present some examples of validators. In practice they would + normally be associated with a widget as in the example above. + + \snippet doc/src/snippets/code/src_gui_widgets_qvalidator.cpp 1 + + Notice that the value \c 999 returns Intermediate. Values + consisting of a number of digits equal to or less than the max + value are considered intermediate. This is intended because the + digit that prevents a number to be in range is not necessarily the + last digit typed. This also means that an intermediate number can + have leading zeros. + + The minimum and maximum values are set in one call with setRange(), + or individually with setBottom() and setTop(). + + QIntValidator uses its locale() to interpret the number. For example, + in Arabic locales, QIntValidator will accept Arabic digits. In addition, + QIntValidator is always guaranteed to accept a number formatted according + to the "C" locale. + + \sa QDoubleValidator, QRegExpValidator, {Line Edits Example} +*/ + +/*! + Constructs a validator with a \a parent object that + accepts all integers. +*/ + +QIntValidator::QIntValidator(QObject * parent) + : QValidator(parent) +{ + b = INT_MIN; + t = INT_MAX; +} + + +/*! + Constructs a validator with a \a parent, that accepts integers + from \a minimum to \a maximum inclusive. +*/ + +QIntValidator::QIntValidator(int minimum, int maximum, + QObject * parent) + : QValidator(parent) +{ + b = minimum; + t = maximum; +} + + +#ifdef QT3_SUPPORT +/*! + \obsolete + + Constructs a validator with a \a parent object and a \a name that + accepts all integers. +*/ + +QIntValidator::QIntValidator(QObject * parent, const char *name) + : QValidator(parent) +{ + setObjectName(QString::fromAscii(name)); + b = INT_MIN; + t = INT_MAX; +} + + +/*! + \obsolete + + Constructs a validator called \a name with a \a parent, that + accepts integers from \a minimum to \a maximum inclusive. +*/ + +QIntValidator::QIntValidator(int minimum, int maximum, + QObject * parent, const char* name) + : QValidator(parent) +{ + setObjectName(QString::fromAscii(name)); + b = minimum; + t = maximum; +} +#endif + +/*! + Destroys the validator. +*/ + +QIntValidator::~QIntValidator() +{ + // nothing +} + + +/*! + \fn QValidator::State QIntValidator::validate(QString &input, int &pos) const + + Returns \l Acceptable if the \a input is an integer within the + valid range, \l Intermediate if the \a input is a prefix of an integer in the + valid range, and \l Invalid otherwise. + + If the valid range consists of just positive integers (e.g., 32 to 100) + and \a input is a negative integer, then Invalid is returned. (On the other + hand, if the range consists of negative integers (e.g., -100 to -32) and + \a input is a positive integer, then Intermediate is returned, because + the user might be just about to type the minus (especially for right-to-left + languages). + + \snippet doc/src/snippets/code/src_gui_widgets_qvalidator.cpp 2 + + By default, the \a pos parameter is not used by this validator. +*/ + +static int numDigits(qlonglong n) +{ + if (n == 0) + return 1; + return (int)log10(double(n)) + 1; +} + +static qlonglong pow10(int exp) +{ + qlonglong result = 1; + for (int i = 0; i < exp; ++i) + result *= 10; + return result; +} + +QValidator::State QIntValidator::validate(QString & input, int&) const +{ + QByteArray buff; + if (!locale().d()->validateChars(input, QLocalePrivate::IntegerMode, &buff)) { + QLocale cl(QLocale::C); + if (!cl.d()->validateChars(input, QLocalePrivate::IntegerMode, &buff)) + return Invalid; + } + + if (buff.isEmpty()) + return Intermediate; + + if (b >= 0 && buff.startsWith('-')) + return Invalid; + + if (t < 0 && buff.startsWith('+')) + return Invalid; + + if (buff.size() == 1 && (buff.at(0) == '+' || buff.at(0) == '-')) + return Intermediate; + + bool ok, overflow; + qlonglong entered = QLocalePrivate::bytearrayToLongLong(buff.constData(), 10, &ok, &overflow); + if (overflow || !ok) + return Invalid; + if (entered >= b && entered <= t) { + locale().toInt(input, &ok); + return ok ? Acceptable : Intermediate; + } + + if (entered >= 0) { + // the -entered < b condition is necessary to allow people to type + // the minus last (e.g. for right-to-left languages) + return (entered > t && -entered < b) ? Invalid : Intermediate; + } else { + return (entered < b) ? Invalid : Intermediate; + } +} + +/*! \reimp */ +void QIntValidator::fixup(QString &input) const +{ + QByteArray buff; + if (!locale().d()->validateChars(input, QLocalePrivate::IntegerMode, &buff)) { + QLocale cl(QLocale::C); + if (!cl.d()->validateChars(input, QLocalePrivate::IntegerMode, &buff)) + return; + } + bool ok, overflow; + qlonglong entered = QLocalePrivate::bytearrayToLongLong(buff.constData(), 10, &ok, &overflow); + if (ok && !overflow) + input = locale().toString(entered); +} + +/*! + Sets the range of the validator to only accept integers between \a + bottom and \a top inclusive. +*/ + +void QIntValidator::setRange(int bottom, int top) +{ + if (b != bottom) { + b = bottom; + emit bottomChanged(b); + } + + if (t != top) { + t = top; + emit topChanged(t); + } +} + + +/*! + \property QIntValidator::bottom + \brief the validator's lowest acceptable value + + By default, this property's value is derived from the lowest signed + integer available (typically -2147483647). + + \sa setRange() +*/ +void QIntValidator::setBottom(int bottom) +{ + setRange(bottom, top()); +} + +/*! + \property QIntValidator::top + \brief the validator's highest acceptable value + + By default, this property's value is derived from the highest signed + integer available (typically 2147483647). + + \sa setRange() +*/ +void QIntValidator::setTop(int top) +{ + setRange(bottom(), top); +} + + +#ifndef QT_NO_REGEXP + +/*! + \internal +*/ +QValidator::QValidator(QObjectPrivate &d, QObject *parent) + : QObject(d, parent) +{ +} + +/*! + \internal +*/ +QValidator::QValidator(QValidatorPrivate &d, QObject *parent) + : QObject(d, parent) +{ +} + +class QDoubleValidatorPrivate : public QValidatorPrivate +{ + Q_DECLARE_PUBLIC(QDoubleValidator) +public: + QDoubleValidatorPrivate() + : QValidatorPrivate() + , notation(QDoubleValidator::ScientificNotation) + { + } + + QDoubleValidator::Notation notation; + + QValidator::State validateWithLocale(QString & input, QLocalePrivate::NumberMode numMode, const QLocale &locale) const; +}; + + +/*! + \class QDoubleValidator + + \brief The QDoubleValidator class provides range checking of + floating-point numbers. + + QDoubleValidator provides an upper bound, a lower bound, and a + limit on the number of digits after the decimal point. It does not + provide a fixup() function. + + You can set the acceptable range in one call with setRange(), or + with setBottom() and setTop(). Set the number of decimal places + with setDecimals(). The validate() function returns the validation + state. + + QDoubleValidator uses its locale() to interpret the number. For example, + in the German locale, "1,234" will be accepted as the fractional number + 1.234. In Arabic locales, QDoubleValidator will accept Arabic digits. + + In addition, QDoubleValidator is always guaranteed to accept a number + formatted according to the "C" locale. QDoubleValidator will not accept + numbers with thousand-separators. + + \sa QIntValidator, QRegExpValidator, {Line Edits Example} +*/ + + /*! + \enum QDoubleValidator::Notation + \since 4.3 + This enum defines the allowed notations for entering a double. + + \value StandardNotation The string is written as a standard number + (i.e. 0.015). + \value ScientificNotation The string is written in scientific + form. It may have an exponent part(i.e. 1.5E-2). +*/ + +/*! + Constructs a validator object with a \a parent object + that accepts any double. +*/ + +QDoubleValidator::QDoubleValidator(QObject * parent) + : QValidator(*new QDoubleValidatorPrivate , parent) +{ + b = -HUGE_VAL; + t = HUGE_VAL; + dec = 1000; +} + + +/*! + Constructs a validator object with a \a parent object. This + validator will accept doubles from \a bottom to \a top inclusive, + with up to \a decimals digits after the decimal point. +*/ + +QDoubleValidator::QDoubleValidator(double bottom, double top, int decimals, + QObject * parent) + : QValidator(*new QDoubleValidatorPrivate , parent) +{ + b = bottom; + t = top; + dec = decimals; +} + +#ifdef QT3_SUPPORT +/*! + \obsolete + + Constructs a validator object with a \a parent object and a \a name + that accepts any double. +*/ + +QDoubleValidator::QDoubleValidator(QObject * parent, const char *name) + : QValidator(*new QDoubleValidatorPrivate , parent) +{ + setObjectName(QString::fromAscii(name)); + b = -HUGE_VAL; + t = HUGE_VAL; + dec = 1000; +} + + +/*! + \obsolete + + Constructs a validator object with a \a parent object, called \a + name. This validator will accept doubles from \a bottom to \a top + inclusive, with up to \a decimals digits after the decimal point. +*/ + +QDoubleValidator::QDoubleValidator(double bottom, double top, int decimals, + QObject * parent, const char* name) + : QValidator(*new QDoubleValidatorPrivate, parent) +{ + setObjectName(QString::fromAscii(name)); + b = bottom; + t = top; + dec = decimals; +} +#endif + +/*! + Destroys the validator. +*/ + +QDoubleValidator::~QDoubleValidator() +{ +} + + +/*! + \fn QValidator::State QDoubleValidator::validate(QString &input, int &pos) const + + Returns \l Acceptable if the string \a input contains a double + that is within the valid range and is in the correct format. + + Returns \l Intermediate if \a input contains a double that is + outside the range or is in the wrong format; e.g. with too many + digits after the decimal point or is empty. + + Returns \l Invalid if the \a input is not a double. + + Note: If the valid range consists of just positive doubles (e.g. 0.0 to 100.0) + and \a input is a negative double then \l Invalid is returned. If notation() + is set to StandardNotation, and the input contains more digits before the + decimal point than a double in the valid range may have, \l Invalid is returned. + If notation() is ScientificNotation, and the input is not in the valid range, + \l Intermediate is returned. The value may yet become valid by changing the exponent. + + By default, the \a pos parameter is not used by this validator. +*/ + +#ifndef LLONG_MAX +# define LLONG_MAX Q_INT64_C(0x7fffffffffffffff) +#endif + +QValidator::State QDoubleValidator::validate(QString & input, int &) const +{ + Q_D(const QDoubleValidator); + + QLocalePrivate::NumberMode numMode = QLocalePrivate::DoubleStandardMode; + switch (d->notation) { + case StandardNotation: + numMode = QLocalePrivate::DoubleStandardMode; + break; + case ScientificNotation: + numMode = QLocalePrivate::DoubleScientificMode; + break; + } + + State currentLocaleValidation = d->validateWithLocale(input, numMode, locale()); + if (currentLocaleValidation == Acceptable || locale().language() == QLocale::C) + return currentLocaleValidation; + State cLocaleValidation = d->validateWithLocale(input, numMode, QLocale(QLocale::C)); + return qMax(currentLocaleValidation, cLocaleValidation); +} + +QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QLocalePrivate::NumberMode numMode, const QLocale &locale) const +{ + Q_Q(const QDoubleValidator); + QByteArray buff; + if (!locale.d()->validateChars(input, numMode, &buff, q->dec)) + return QValidator::Invalid; + + if (buff.isEmpty()) + return QValidator::Intermediate; + + if (q->b >= 0 && buff.startsWith('-')) + return QValidator::Invalid; + + if (q->t < 0 && buff.startsWith('+')) + return QValidator::Invalid; + + bool ok, overflow; + double i = QLocalePrivate::bytearrayToDouble(buff.constData(), &ok, &overflow); + if (overflow) + return QValidator::Invalid; + if (!ok) + return QValidator::Intermediate; + + if (i >= q->b && i <= q->t) + return QValidator::Acceptable; + + if (notation == QDoubleValidator::StandardNotation) { + double max = qMax(qAbs(q->b), qAbs(q->t)); + if (max < LLONG_MAX) { + qlonglong n = pow10(numDigits(qlonglong(max))) - 1; + if (qAbs(i) > n) + return QValidator::Invalid; + } + } + + return QValidator::Intermediate; +} + + +/*! + Sets the validator to accept doubles from \a minimum to \a maximum + inclusive, with at most \a decimals digits after the decimal + point. +*/ + +void QDoubleValidator::setRange(double minimum, double maximum, int decimals) +{ + if (b != minimum) { + b = minimum; + emit bottomChanged(b); + } + + if (t != maximum) { + t = maximum; + emit topChanged(t); + } + + if (dec != decimals) { + dec = decimals; + emit decimalsChanged(dec); + } +} + +/*! + \property QDoubleValidator::bottom + \brief the validator's minimum acceptable value + + By default, this property contains a value of -infinity. + + \sa setRange() +*/ + +void QDoubleValidator::setBottom(double bottom) +{ + setRange(bottom, top(), decimals()); +} + + +/*! + \property QDoubleValidator::top + \brief the validator's maximum acceptable value + + By default, this property contains a value of infinity. + + \sa setRange() +*/ + +void QDoubleValidator::setTop(double top) +{ + setRange(bottom(), top, decimals()); +} + +/*! + \property QDoubleValidator::decimals + \brief the validator's maximum number of digits after the decimal point + + By default, this property contains a value of 1000. + + \sa setRange() +*/ + +void QDoubleValidator::setDecimals(int decimals) +{ + setRange(bottom(), top(), decimals); +} + +/*! + \property QDoubleValidator::notation + \since 4.3 + \brief the notation of how a string can describe a number + + By default, this property is set to ScientificNotation. + + \sa Notation +*/ + +void QDoubleValidator::setNotation(Notation newNotation) +{ + Q_D(QDoubleValidator); + if (d->notation != newNotation) { + d->notation = newNotation; + emit notationChanged(d->notation); + } +} + +QDoubleValidator::Notation QDoubleValidator::notation() const +{ + Q_D(const QDoubleValidator); + return d->notation; +} + +/*! + \class QRegExpValidator + \brief The QRegExpValidator class is used to check a string + against a regular expression. + + QRegExpValidator uses a regular expression (regexp) to + determine whether an input string is \l Acceptable, \l + Intermediate, or \l Invalid. The regexp can either be supplied + when the QRegExpValidator is constructed, or at a later time. + + When QRegExpValidator determines whether a string is \l Acceptable + or not, the regexp is treated as if it begins with the start of string + assertion (\bold{^}) and ends with the end of string assertion + (\bold{$}); the match is against the entire input string, or from + the given position if a start position greater than zero is given. + + If a string is a prefix of an \l Acceptable string, it is considered + \l Intermediate. For example, "" and "A" are \l Intermediate for the + regexp \bold{[A-Z][0-9]} (whereas "_" would be \l Invalid). + + For a brief introduction to Qt's regexp engine, see \l QRegExp. + + Example of use: + \snippet doc/src/snippets/code/src_gui_widgets_qvalidator.cpp 3 + + Below we present some examples of validators. In practice they would + normally be associated with a widget as in the example above. + + \snippet doc/src/snippets/code/src_gui_widgets_qvalidator.cpp 4 + + \sa QRegExp, QIntValidator, QDoubleValidator, {Settings Editor Example} +*/ + +/*! + Constructs a validator with a \a parent object that accepts + any string (including an empty one) as valid. +*/ + +QRegExpValidator::QRegExpValidator(QObject *parent) + : QValidator(parent), r(QString::fromLatin1(".*")) +{ +} + +/*! + Constructs a validator with a \a parent object that + accepts all strings that match the regular expression \a rx. + + The match is made against the entire string; e.g. if the regexp is + \bold{[A-Fa-f0-9]+} it will be treated as \bold{^[A-Fa-f0-9]+$}. +*/ + +QRegExpValidator::QRegExpValidator(const QRegExp& rx, QObject *parent) + : QValidator(parent), r(rx) +{ +} + +#ifdef QT3_SUPPORT +/*! + \obsolete + + Constructs a validator with a \a parent object and \a name that accepts + any string (including an empty one) as valid. +*/ + +QRegExpValidator::QRegExpValidator(QObject *parent, const char *name) + : QValidator(parent), r(QString::fromLatin1(".*")) +{ + setObjectName(QString::fromAscii(name)); +} + +/*! + \obsolete + + Constructs a validator with a \a parent object and a \a name that + accepts all strings that match the regular expression \a rx. + + The match is made against the entire string; e.g. if the regexp is + \bold{[A-Fa-f0-9]+} it will be treated as \bold{^[A-Fa-f0-9]+$}. +*/ + +QRegExpValidator::QRegExpValidator(const QRegExp& rx, QObject *parent, + const char *name) + : QValidator(parent), r(rx) +{ + setObjectName(QString::fromAscii(name)); +} +#endif + +/*! + Destroys the validator. +*/ + +QRegExpValidator::~QRegExpValidator() +{ +} + +/*! + Returns \l Acceptable if \a input is matched by the regular + expression for this validator, \l Intermediate if it has matched + partially (i.e. could be a valid match if additional valid + characters are added), and \l Invalid if \a input is not matched. + + The \a pos parameter is set to the length of the \a input parameter. + + For example, if the regular expression is \bold{\\w\\d\\d} + (word-character, digit, digit) then "A57" is \l Acceptable, + "E5" is \l Intermediate, and "+9" is \l Invalid. + + \sa QRegExp::exactMatch() +*/ + +QValidator::State QRegExpValidator::validate(QString &input, int& pos) const +{ + if (r.exactMatch(input)) { + return Acceptable; + } else { + if (const_cast<QRegExp &>(r).matchedLength() == input.size()) { + return Intermediate; + } else { + pos = input.size(); + return Invalid; + } + } +} + +/*! + \property QRegExpValidator::regExp + \brief the regular expression used for validation + + By default, this property contains a regular expression with the pattern \c{.*} + that matches any string. +*/ + +void QRegExpValidator::setRegExp(const QRegExp& rx) +{ + if (r != rx) { + r = rx; + emit regExpChanged(r); + } +} + +#endif + +QT_END_NAMESPACE + +#endif // QT_NO_VALIDATOR diff --git a/src/gui/util/qvalidator.h b/src/gui/util/qvalidator.h new file mode 100644 index 0000000000..cb0436cc3e --- /dev/null +++ b/src/gui/util/qvalidator.h @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVALIDATOR_H +#define QVALIDATOR_H + +#include <QtCore/qobject.h> +#include <QtCore/qstring.h> +#include <QtCore/qregexp.h> +#include <QtCore/qlocale.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#ifndef QT_NO_VALIDATOR + +class QValidatorPrivate; + +class Q_GUI_EXPORT QValidator : public QObject +{ + Q_OBJECT +public: + explicit QValidator(QObject * parent = 0); + ~QValidator(); + + enum State { + Invalid, + Intermediate, + Acceptable + +#if defined(QT3_SUPPORT) && !defined(Q_MOC_RUN) + , Valid = Intermediate +#endif + }; + + void setLocale(const QLocale &locale); + QLocale locale() const; + + virtual State validate(QString &, int &) const = 0; + virtual void fixup(QString &) const; + +#ifdef QT3_SUPPORT +public: + QT3_SUPPORT_CONSTRUCTOR QValidator(QObject * parent, const char *name); +#endif +protected: + QValidator(QObjectPrivate &d, QObject *parent); + QValidator(QValidatorPrivate &d, QObject *parent); + +private: + Q_DISABLE_COPY(QValidator) + Q_DECLARE_PRIVATE(QValidator) +}; + +class Q_GUI_EXPORT QIntValidator : public QValidator +{ + Q_OBJECT + Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY bottomChanged) + Q_PROPERTY(int top READ top WRITE setTop NOTIFY topChanged) + +public: + explicit QIntValidator(QObject * parent = 0); + QIntValidator(int bottom, int top, QObject *parent = 0); + ~QIntValidator(); + + QValidator::State validate(QString &, int &) const; + void fixup(QString &input) const; + + void setBottom(int); + void setTop(int); + virtual void setRange(int bottom, int top); + + int bottom() const { return b; } + int top() const { return t; } +Q_SIGNALS: + void bottomChanged(int bottom); + void topChanged(int top); +#ifdef QT3_SUPPORT +public: + QT3_SUPPORT_CONSTRUCTOR QIntValidator(QObject * parent, const char *name); + QT3_SUPPORT_CONSTRUCTOR QIntValidator(int bottom, int top, QObject * parent, const char *name); +#endif + +private: + Q_DISABLE_COPY(QIntValidator) + + int b; + int t; +}; + +#ifndef QT_NO_REGEXP + +class QDoubleValidatorPrivate; + +class Q_GUI_EXPORT QDoubleValidator : public QValidator +{ + Q_OBJECT + Q_PROPERTY(double bottom READ bottom WRITE setBottom NOTIFY bottomChanged) + Q_PROPERTY(double top READ top WRITE setTop NOTIFY topChanged) + Q_PROPERTY(int decimals READ decimals WRITE setDecimals NOTIFY decimalsChanged) + Q_ENUMS(Notation) + Q_PROPERTY(Notation notation READ notation WRITE setNotation NOTIFY notationChanged) + +public: + explicit QDoubleValidator(QObject * parent = 0); + QDoubleValidator(double bottom, double top, int decimals, QObject *parent = 0); + ~QDoubleValidator(); + + enum Notation { + StandardNotation, + ScientificNotation + }; + QValidator::State validate(QString &, int &) const; + + virtual void setRange(double bottom, double top, int decimals = 0); + void setBottom(double); + void setTop(double); + void setDecimals(int); + void setNotation(Notation); + + double bottom() const { return b; } + double top() const { return t; } + int decimals() const { return dec; } + Notation notation() const; + +Q_SIGNALS: + void bottomChanged(double bottom); + void topChanged(double top); + void decimalsChanged(int decimals); + void notationChanged(QDoubleValidator::Notation notation); + +#ifdef QT3_SUPPORT +public: + QT3_SUPPORT_CONSTRUCTOR QDoubleValidator(QObject * parent, const char *name); + QT3_SUPPORT_CONSTRUCTOR QDoubleValidator(double bottom, double top, int decimals, + QObject * parent, const char *name); +#endif +private: + Q_DECLARE_PRIVATE(QDoubleValidator) + Q_DISABLE_COPY(QDoubleValidator) + + double b; + double t; + int dec; +}; + + +class Q_GUI_EXPORT QRegExpValidator : public QValidator +{ + Q_OBJECT + Q_PROPERTY(QRegExp regExp READ regExp WRITE setRegExp NOTIFY regExpChanged) + +public: + explicit QRegExpValidator(QObject *parent = 0); + QRegExpValidator(const QRegExp& rx, QObject *parent = 0); + ~QRegExpValidator(); + + virtual QValidator::State validate(QString& input, int& pos) const; + + void setRegExp(const QRegExp& rx); + const QRegExp& regExp() const { return r; } // ### make inline for 5.0 + +Q_SIGNALS: + void regExpChanged(const QRegExp& regExp); +#ifdef QT3_SUPPORT +public: + QT3_SUPPORT_CONSTRUCTOR QRegExpValidator(QObject *parent, const char *name); + QT3_SUPPORT_CONSTRUCTOR QRegExpValidator(const QRegExp& rx, QObject *parent, const char *name); +#endif + +private: + Q_DISABLE_COPY(QRegExpValidator) + + QRegExp r; +}; + +#endif // QT_NO_REGEXP + +#endif // QT_NO_VALIDATOR + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QVALIDATOR_H diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri index 2814a2d30a..dfb221667e 100644 --- a/src/gui/util/util.pri +++ b/src/gui/util/util.pri @@ -1,71 +1,10 @@ # Qt util module HEADERS += \ - util/qsystemtrayicon.h \ - util/qcompleter.h \ - util/qcompleter_p.h \ util/qdesktopservices.h \ - util/qsystemtrayicon_p.h \ - util/qscroller.h \ - util/qscroller_p.h \ - util/qscrollerproperties.h \ - util/qscrollerproperties_p.h \ - util/qflickgesture_p.h \ - util/qundogroup.h \ - util/qundostack.h \ - util/qundostack_p.h \ - util/qundoview.h + util/qhexstring_p.h \ + util/qvalidator.h SOURCES += \ - util/qsystemtrayicon.cpp \ - util/qcompleter.cpp \ util/qdesktopservices.cpp \ - util/qscroller.cpp \ - util/qscrollerproperties.cpp \ - util/qflickgesture.cpp \ - util/qundogroup.cpp \ - util/qundostack.cpp \ - util/qundoview.cpp - - -wince* { - SOURCES += \ - util/qsystemtrayicon_wince.cpp -} else:win32 { - SOURCES += \ - util/qsystemtrayicon_win.cpp -} - -unix:x11 { - SOURCES += \ - util/qsystemtrayicon_x11.cpp -} - -embedded|qpa { - SOURCES += \ - util/qsystemtrayicon_qws.cpp -} - -!embedded:!qpa:!x11:mac { - OBJECTIVE_SOURCES += util/qsystemtrayicon_mac.mm -} - -symbian { - LIBS += -letext -lplatformenv - contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) { - LIBS += -lsendas2 -lapmime - contains(QT_CONFIG, s60) { - contains(CONFIG, is_using_gnupoc) { - LIBS += -lcommonui - } else { - LIBS += -lCommonUI - } - } - } else { - DEFINES += USE_SCHEMEHANDLER - } -} - -macx { - OBJECTIVE_SOURCES += util/qscroller_mac.mm -} + util/qvalidator.cpp |