KIO
kmimetyperesolver.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kmimetyperesolver.h"
00022 #include <kdebug.h>
00023 #include "defaultviewadapter_p.h"
00024 #include <kdirmodel.h>
00025 #include <kfileitem.h>
00026 #include <kdirlister.h>
00027 #include <QAbstractItemView>
00028 #include <QAbstractProxyModel>
00029 #include <QScrollBar>
00030 #include <QTimer>
00031
00032 class KMimeTypeResolverPrivate
00033 {
00034 public:
00035 KMimeTypeResolverPrivate(KMimeTypeResolver *parent)
00036 : q(parent),
00037 m_delayForNonVisibleIcons(10),
00038 m_noVisibleIcon(false)
00039 {
00040 m_timer.setSingleShot(true);
00041 }
00042
00043
00044 void _k_slotRowsInserted(const QModelIndex&,int,int);
00045 void _k_slotViewportAdjusted();
00046 void _k_slotProcessMimeIcons();
00047
00048 void init();
00049 QModelIndex findVisibleIcon();
00050
00051 KMimeTypeResolver* q;
00052 KAbstractViewAdapter* m_adapter;
00053 QAbstractProxyModel* m_proxyModel;
00054 KDirModel* m_dirModel;
00055 int m_delayForNonVisibleIcons;
00056 QList<QPersistentModelIndex> m_pendingIndexes;
00057 QTimer m_timer;
00058
00059
00060 bool m_noVisibleIcon;
00061 };
00062
00063 void KMimeTypeResolverPrivate::init()
00064 {
00065 QObject::connect(m_dirModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
00066 q, SLOT(_k_slotRowsInserted(QModelIndex,int,int)));
00067 QObject::connect(&m_timer, SIGNAL(timeout()),
00068 q, SLOT(_k_slotProcessMimeIcons()));
00069 m_adapter->connect(KAbstractViewAdapter::ScrollBarValueChanged, q, SLOT(_k_slotViewportAdjusted()));
00070 }
00071
00072 QModelIndex KMimeTypeResolverPrivate::findVisibleIcon()
00073 {
00074 if (m_noVisibleIcon)
00075 return QModelIndex();
00076
00077 if (m_pendingIndexes.count() < 20) {
00078
00079 return QModelIndex(m_pendingIndexes.first());
00080 }
00081
00082 const QRect visibleArea = m_adapter->visibleArea();
00083 QList<QPersistentModelIndex>::const_iterator it = m_pendingIndexes.constBegin();
00084 const QList<QPersistentModelIndex>::const_iterator end = m_pendingIndexes.constEnd();
00085 bool layoutDone = true;
00086 for ( ; it != end ; ++it ) {
00087 const QModelIndex index = m_proxyModel ? m_proxyModel->mapFromSource(*it) : QModelIndex(*it);
00088 const QRect rect = m_adapter->visualRect(index);
00089 if (rect.isNull())
00090 layoutDone = false;
00091 else if (rect.intersects(visibleArea)) {
00092
00093 return QModelIndex(*it);
00094 }
00095 }
00096
00097 if (layoutDone) {
00098
00099 m_noVisibleIcon = true;
00100 return QModelIndex();
00101 } else {
00102
00103 return QModelIndex(m_pendingIndexes.first());
00104 }
00105 }
00106
00108
00109 KMimeTypeResolver::KMimeTypeResolver(QAbstractItemView* view, KDirModel* model)
00110 : QObject(view), d(new KMimeTypeResolverPrivate(this))
00111 {
00112 d->m_adapter = new KIO::DefaultViewAdapter(view, this);
00113 d->m_proxyModel = 0;
00114 d->m_dirModel = model;
00115 d->init();
00116 }
00117
00118 KMimeTypeResolver::KMimeTypeResolver(QAbstractItemView* view, QAbstractProxyModel* model)
00119 : QObject(view), d(new KMimeTypeResolverPrivate(this))
00120 {
00121 d->m_adapter = new KIO::DefaultViewAdapter(view, this);
00122 d->m_proxyModel = model;
00123 d->m_dirModel = static_cast<KDirModel*>(model->sourceModel());
00124 d->init();
00125 }
00126
00127 KMimeTypeResolver::KMimeTypeResolver(KAbstractViewAdapter* adapter)
00128 : QObject(adapter), d(new KMimeTypeResolverPrivate(this))
00129 {
00130 QAbstractItemModel *model = adapter->model();
00131 d->m_adapter = adapter;
00132 d->m_proxyModel = qobject_cast<QAbstractProxyModel*>(model);
00133 d->m_dirModel = d->m_proxyModel ? qobject_cast<KDirModel*>(d->m_proxyModel->sourceModel())
00134 : qobject_cast<KDirModel*>(model);
00135 Q_ASSERT(d->m_dirModel);
00136 d->init();
00137 }
00138
00139 KMimeTypeResolver::~KMimeTypeResolver()
00140 {
00141 delete d;
00142 }
00143
00144 void KMimeTypeResolverPrivate::_k_slotProcessMimeIcons()
00145 {
00146 if (m_pendingIndexes.isEmpty()) {
00147
00148 return;
00149 }
00150
00151 int nextDelay = 0;
00152 QModelIndex index = findVisibleIcon();
00153 if (index.isValid()) {
00154
00155 const int numFound = m_pendingIndexes.removeAll(index);
00156 Q_ASSERT(numFound == 1);
00157 } else {
00158
00159
00160 index = m_pendingIndexes.takeFirst();
00161 nextDelay = m_delayForNonVisibleIcons;
00162 }
00163 KFileItem item = m_dirModel->itemForIndex(index);
00164 if (!item.isNull()) {
00165 if (!item.isMimeTypeKnown()) {
00166 item.determineMimeType();
00167 m_dirModel->itemChanged(index);
00168 }
00169 }
00170 m_timer.start(nextDelay);
00171 }
00172
00173 void KMimeTypeResolverPrivate::_k_slotRowsInserted(const QModelIndex& parent, int first, int last)
00174 {
00175 KDirModel* model = m_dirModel;
00176 for (int row = first; row <= last; ++row) {
00177 QModelIndex idx = model->index(row, 0, parent);
00178 KFileItem item = model->itemForIndex(idx);
00179 if (!item.isMimeTypeKnown())
00180 m_pendingIndexes.append(idx);
00181
00182
00183
00184 }
00185 m_noVisibleIcon = false;
00186 m_timer.start(m_delayForNonVisibleIcons);
00187 }
00188
00189 void KMimeTypeResolverPrivate::_k_slotViewportAdjusted()
00190 {
00191 m_noVisibleIcon = false;
00192 m_timer.start(0);
00193 }
00194
00195 #include "kmimetyperesolver.moc"