📄 qlistwidget.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qlistwidget.h"#ifndef QT_NO_LISTWIDGET#include <qitemdelegate.h>#include <private/qlistview_p.h>#include <private/qwidgetitemdata_p.h>#include <private/qlistwidget_p.h>// workaround for VC++ 6.0 linker bug (?)typedef bool(*LessThan)(const QPair<QListWidgetItem*,int>&,const QPair<QListWidgetItem*,int>&);class QListWidgetMimeData : public QMimeData{ Q_OBJECTpublic: QList<QListWidgetItem*> items;};#include "qlistwidget.moc"QListModel::QListModel(QListWidget *parent) : QAbstractListModel(parent){}QListModel::~QListModel(){ clear();}void QListModel::clear(){ for (int i = 0; i < items.count(); ++i) { if (items.at(i)) { items.at(i)->d->id = -1; items.at(i)->view = 0; delete items.at(i); } } items.clear(); reset();}QListWidgetItem *QListModel::at(int row) const{ return items.value(row);}void QListModel::remove(QListWidgetItem *item){ if (!item) return; int row = items.indexOf(item); // ### use index(item) - it's faster Q_ASSERT(row != -1); beginRemoveRows(QModelIndex(), row, row); items.at(row)->d->id = -1; items.at(row)->view = 0; items.removeAt(row); endRemoveRows();}void QListModel::insert(int row, QListWidgetItem *item){ if (!item) return; item->view = ::qobject_cast<QListWidget*>(QObject::parent()); if (item->view && item->view->isSortingEnabled()) { // sorted insertion QList<QListWidgetItem*>::iterator it; it = sortedInsertionIterator(items.begin(), items.end(), item->view->sortOrder(), item); row = qMax(it - items.begin(), 0); } else { if (row < 0) row = 0; else if (row > items.count()) row = items.count(); } beginInsertRows(QModelIndex(), row, row); items.insert(row, item); item->d->id = row; endInsertRows();}void QListModel::insert(int row, const QStringList &labels){ const int count = labels.count(); if (count <= 0) return; QListWidget *view = ::qobject_cast<QListWidget*>(QObject::parent()); if (view && view->isSortingEnabled()) { // sorted insertion for (int i = 0; i < count; ++i) { QListWidgetItem *item = new QListWidgetItem(labels.at(i)); insert(row, item); } } else { if (row < 0) row = 0; else if (row > items.count()) row = items.count(); beginInsertRows(QModelIndex(), row, row + count - 1); for (int i = 0; i < count; ++i) { QListWidgetItem *item = new QListWidgetItem(labels.at(i)); item->d->id = row; item->view = ::qobject_cast<QListWidget*>(QObject::parent()); items.insert(row++, item); } endInsertRows(); }}QListWidgetItem *QListModel::take(int row){ if (row < 0 || row >= items.count()) return 0; beginRemoveRows(QModelIndex(), row, row); items.at(row)->d->id = -1; items.at(row)->view = 0; QListWidgetItem *item = items.takeAt(row); endRemoveRows(); return item;}int QListModel::rowCount(const QModelIndex &parent) const{ return parent.isValid() ? 0 : items.count();}QModelIndex QListModel::index(QListWidgetItem *item) const{ if (!item || !item->view || static_cast<const QListModel *>(item->view->model()) != this || items.isEmpty()) return QModelIndex(); int row; const int id = item->d->id; if (id >= 0 && id < items.count() && items.at(id) == item) { row = id; } else { // we need to search for the item row = items.lastIndexOf(item); // lastIndexOf is an optimization in favor of indexOf if (row == -1) // not found return QModelIndex(); item->d->id = row; } return createIndex(row, 0, item);}QModelIndex QListModel::index(int row, int column, const QModelIndex &parent) const{ if (hasIndex(row, column, parent)) return createIndex(row, column, items.at(row)); return QModelIndex();}QVariant QListModel::data(const QModelIndex &index, int role) const{ if (!index.isValid() || index.row() >= items.count()) return QVariant(); return items.at(index.row())->data(role);}bool QListModel::setData(const QModelIndex &index, const QVariant &value, int role){ if (!index.isValid() || index.row() >= items.count()) return false; items.at(index.row())->setData(role, value); return true;}QMap<int, QVariant> QListModel::itemData(const QModelIndex &index) const{ QMap<int, QVariant> roles; if (!index.isValid() || index.row() >= items.count()) return roles; QListWidgetItem *itm = items.at(index.row()); for (int i = 0; i < itm->values.count(); ++i) { roles.insert(itm->values.at(i).role, itm->values.at(i).value); } return roles;}bool QListModel::insertRows(int row, int count, const QModelIndex &parent){ if (count < 1 || row < 0 || row > rowCount() || parent.isValid()) return false; beginInsertRows(QModelIndex(), row, row + count - 1); QListWidget *view = ::qobject_cast<QListWidget*>(QObject::parent()); QListWidgetItem *itm = 0; for (int r = row; r < row + count; ++r) { itm = new QListWidgetItem; itm->view = view; itm->d->id = r; items.insert(r, itm); } endInsertRows(); return true;}bool QListModel::removeRows(int row, int count, const QModelIndex &parent){ if (count < 1 || row < 0 || (row + count) > rowCount() || parent.isValid()) return false; beginRemoveRows(QModelIndex(), row, row + count - 1); QListWidgetItem *itm = 0; for (int r = row; r < row + count; ++r) { itm = items.takeAt(row); itm->view = 0; itm->d->id = -1; delete itm; } endRemoveRows(); return true;}Qt::ItemFlags QListModel::flags(const QModelIndex &index) const{ if (!index.isValid() || index.row() >= items.count() || index.model() != this) return Qt::ItemIsDropEnabled; // we allow drops outside the items return items.at(index.row())->flags();}void QListModel::sort(int column, Qt::SortOrder order){ if (column != 0) return; emit layoutAboutToBeChanged(); QModelIndexList fromIndexes; QVector < QPair<QListWidgetItem*,int> > sorting(items.count()); for (int i = 0; i < items.count(); ++i) { QListWidgetItem *item = items.at(i); sorting[i].first = item; sorting[i].second = i; fromIndexes.append(createIndex(i, 0, item)); } LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); qSort(sorting.begin(), sorting.end(), compare); QModelIndexList toIndexes; for (int r = 0; r < sorting.count(); ++r) { QListWidgetItem *item = sorting.at(r).first; items[r] = item; toIndexes.append(createIndex(sorting.at(r).second, 0, item)); } changePersistentIndexList(fromIndexes, toIndexes); emit layoutChanged();}/** * This function assumes that all items in the model except the items that are between * (inclusive) start and end are sorted. * With these assumptions, this function can ensure that the model is sorted in a * much more efficient way than doing a naive 'sort everything'. * (provided that the range is relatively small compared to the total number of items) */void QListModel::ensureSorted(int column, Qt::SortOrder order, int start, int end){ if (column != 0) return; int count = end - start + 1; QVector < QPair<QListWidgetItem*,int> > sorting(count); for (int i = 0; i < count; ++i) { sorting[i].first = items.at(start + i); sorting[i].second = start + i; } LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); qSort(sorting.begin(), sorting.end(), compare); QModelIndexList oldPersistentIndexes = persistentIndexList(); QModelIndexList newPersistentIndexes = oldPersistentIndexes; QList<QListWidgetItem*> tmp = items; QList<QListWidgetItem*>::iterator lit = tmp.begin(); bool changed = false; for (int i = 0; i < count; ++i) { int oldRow = sorting.at(i).second; QListWidgetItem *item = tmp.takeAt(oldRow); lit = sortedInsertionIterator(lit, tmp.end(), order, item); int newRow = qMax(lit - tmp.begin(), 0); lit = tmp.insert(lit, item); if (newRow != oldRow) { changed = true; for (int j = i + 1; j < count; ++j) { int otherRow = sorting.at(j).second; if (oldRow < otherRow && newRow >= otherRow) --sorting[j].second; else if (oldRow > otherRow && newRow <= otherRow) ++sorting[j].second; } for (int k = 0; k < newPersistentIndexes.count(); ++k) { QModelIndex pi = newPersistentIndexes.at(k); int oldPersistentRow = pi.row(); int newPersistentRow = oldPersistentRow; if (oldPersistentRow == oldRow) newPersistentRow = newRow; else if (oldRow < oldPersistentRow && newRow >= oldPersistentRow) newPersistentRow = oldPersistentRow - 1; else if (oldRow > oldPersistentRow && newRow <= oldPersistentRow) newPersistentRow = oldPersistentRow + 1; if (newPersistentRow != oldPersistentRow) newPersistentIndexes[k] = createIndex(newPersistentRow, pi.column(), pi.internalPointer()); } } } if (changed) { emit layoutAboutToBeChanged(); items = tmp; changePersistentIndexList(oldPersistentIndexes, newPersistentIndexes); emit layoutChanged(); }}bool QListModel::itemLessThan(const QPair<QListWidgetItem*,int> &left, const QPair<QListWidgetItem*,int> &right){ return (*left.first) < (*right.first);}bool QListModel::itemGreaterThan(const QPair<QListWidgetItem*,int> &left, const QPair<QListWidgetItem*,int> &right){ return !((*left.first) < (*right.first));}QList<QListWidgetItem*>::iterator QListModel::sortedInsertionIterator( const QList<QListWidgetItem*>::iterator &begin, const QList<QListWidgetItem*>::iterator &end, Qt::SortOrder order, QListWidgetItem *item){ if (order == Qt::AscendingOrder) return qLowerBound(begin, end, item, QListModelLessThan()); return qLowerBound(begin, end, item, QListModelGreaterThan());}void QListModel::itemChanged(QListWidgetItem *item){ QModelIndex idx = index(item); emit dataChanged(idx, idx);}QStringList QListModel::mimeTypes() const{ const QListWidget *view = ::qobject_cast<const QListWidget*>(QObject::parent()); return view->mimeTypes();}QMimeData *QListModel::internalMimeData() const{ return QAbstractItemModel::mimeData(cachedIndexes);}QMimeData *QListModel::mimeData(const QModelIndexList &indexes) const{ QList<QListWidgetItem*> itemlist; for (int i = 0; i < indexes.count(); ++i) itemlist << at(indexes.at(i).row()); const QListWidget *view = ::qobject_cast<const QListWidget*>(QObject::parent()); cachedIndexes = indexes; QMimeData *mimeData = view->mimeData(itemlist); cachedIndexes.clear(); return mimeData;}#ifndef QT_NO_DRAGANDDROPbool QListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &index){ Q_UNUSED(column); QListWidget *view = ::qobject_cast<QListWidget*>(QObject::parent()); if (index.isValid()) row = index.row(); else if (row == -1) row = items.count(); return view->dropMimeData(row, data, action);}Qt::DropActions QListModel::supportedDropActions() const{ const QListWidget *view = ::qobject_cast<const QListWidget*>(QObject::parent()); return view->supportedDropActions();}#endif // QT_NO_DRAGANDDROP/*! \class QListWidgetItem \brief The QListWidgetItem class provides an item for use with the QListWidget item view class. \ingroup model-view QListWidgetItem is used to represent items in a list provided by the QListWidget class. Each item can hold several pieces of information, and will display these appropriately. The item view convenience classes use a classic item-based interface rather than a pure model/view approach. For a more flexible list view widget, consider using the QListView class with a standard model. List items can be automatically inserted into a list when they are constructed by specifying the list widget: \quotefile snippets/qlistwidget-using/mainwindow.cpp \skipto new QListWidgetItem(tr("Hazel \printuntil new QListWidgetItem(tr("Hazel They can also be created without a parent widget, and later inserted into a list (see \l{QListWidget::insertItem()}).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -