⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qcompleter.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        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 dirModel = false;#ifndef QT_NO_DIRMODEL    dirModel = (qobject_cast<QDirModel *>(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)#ifndef Q_OS_WIN            && (!dirModel || str != QDir::separator())#endif            )            m.indices.append(i);    }    return m;}// Returns a match hint from the cache by chopping the search stringbool 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 ;        for (it1 = cache.begin(); it1 != cache.end(); ++it1) {            CacheItem& ci = it1.value();            int sz = ci.count()/2;            QMap<QString, QMatchData>::iterator it2 = ci.begin();            for (int i = 0; it2 != ci.end() && i < sz; i++, ++it2) {                cost -= it2.value().indices.cost();                ci.erase(it2);            }            if (ci.count() == 0)                cache.erase(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))            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),  sorting(QCompleter::UnsortedModel), wrap(true), eatFocusOut(true){}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())        completion = prefix;    else {        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    }    if (highlighted) {        emit q->highlighted(index);        emit q->highlighted(completion);    } else {        emit q->activated(index);        emit q->activated(completion);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -