00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "kurlcombobox.h"
00020
00021 #include <QtCore/QDir>
00022 #include <QtGui/QMouseEvent>
00023 #include <QtGui/QDrag>
00024
00025 #include <kdebug.h>
00026 #include <kglobal.h>
00027 #include <kicon.h>
00028 #include <klocale.h>
00029 #include <kmimetype.h>
00030 #include <kiconloader.h>
00031
00032 class KUrlComboBox::KUrlComboBoxPrivate
00033 {
00034 public:
00035 KUrlComboBoxPrivate(KUrlComboBox *parent)
00036 : m_parent(parent),
00037 dirIcon(QLatin1String("folder"))
00038 {}
00039
00040 ~KUrlComboBoxPrivate()
00041 {
00042 qDeleteAll( itemList );
00043 qDeleteAll( defaultList );
00044 }
00045
00046 typedef struct {
00047 QString text;
00048 KUrl url;
00049 QIcon icon;
00050 } KUrlComboItem;
00051
00052 void init( Mode mode );
00053 void insertUrlItem( const KUrlComboItem * );
00054 QIcon getIcon( const KUrl& url ) const;
00055 void updateItem( const KUrlComboItem *item, int index, const QIcon& icon );
00056
00057 void _k_slotActivated( int );
00058
00059 KUrlComboBox *m_parent;
00060 KIcon dirIcon;
00061 bool urlAdded;
00062 int myMaximum;
00063 Mode myMode;
00064
00065 QPoint m_dragPoint;
00066
00067 QList<const KUrlComboItem*> itemList;
00068 QList<const KUrlComboItem*> defaultList;
00069 QMap<int,const KUrlComboItem*> itemMapper;
00070
00071 QIcon opendirIcon;
00072 };
00073
00074
00075 KUrlComboBox::KUrlComboBox( Mode mode, QWidget *parent)
00076 : KComboBox( parent),d(new KUrlComboBoxPrivate(this))
00077 {
00078 d->init( mode );
00079 }
00080
00081
00082 KUrlComboBox::KUrlComboBox( Mode mode, bool rw, QWidget *parent)
00083 : KComboBox( rw, parent),d(new KUrlComboBoxPrivate(this))
00084 {
00085 d->init( mode );
00086 }
00087
00088
00089 KUrlComboBox::~KUrlComboBox()
00090 {
00091 delete d;
00092 }
00093
00094
00095 void KUrlComboBox::KUrlComboBoxPrivate::init( Mode mode )
00096 {
00097 myMode = mode;
00098 urlAdded = false;
00099 myMaximum = 10;
00100 m_parent->setInsertPolicy( NoInsert );
00101 m_parent->setTrapReturnKey( true );
00102 m_parent->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ));
00103 m_parent->setLayoutDirection( Qt::LeftToRight );
00104 if ( m_parent->completionObject() ) {
00105 m_parent->completionObject()->setOrder( KCompletion::Sorted );
00106 }
00107
00108 opendirIcon = KIcon(QLatin1String("folder-open"));
00109
00110 m_parent->connect( m_parent, SIGNAL( activated( int )), SLOT( _k_slotActivated( int )));
00111 }
00112
00113
00114 QStringList KUrlComboBox::urls() const
00115 {
00116 kDebug(250) << "::urls()";
00117
00118 QStringList list;
00119 QString url;
00120 for ( int i = d->defaultList.count(); i < count(); i++ ) {
00121 url = itemText( i );
00122 if ( !url.isEmpty() ) {
00123
00124
00125
00126 list.append( url );
00127 }
00128 }
00129
00130 return list;
00131 }
00132
00133
00134 void KUrlComboBox::addDefaultUrl( const KUrl& url, const QString& text )
00135 {
00136 addDefaultUrl( url, d->getIcon( url ), text );
00137 }
00138
00139
00140 void KUrlComboBox::addDefaultUrl( const KUrl& url, const QIcon& icon,
00141 const QString& text )
00142 {
00143 KUrlComboBoxPrivate::KUrlComboItem *item = new KUrlComboBoxPrivate::KUrlComboItem;
00144 item->url = url;
00145 item->icon = icon;
00146 if ( text.isEmpty() )
00147 item->text = url.pathOrUrl(d->myMode == Directories
00148 ? KUrl::AddTrailingSlash
00149 : KUrl::RemoveTrailingSlash);
00150 else
00151 item->text = text;
00152
00153 d->defaultList.append( item );
00154 }
00155
00156
00157 void KUrlComboBox::setDefaults()
00158 {
00159 clear();
00160 d->itemMapper.clear();
00161
00162 const KUrlComboBoxPrivate::KUrlComboItem *item;
00163 for ( int id = 0; id < d->defaultList.count(); id++ ) {
00164 item = d->defaultList.at( id );
00165 d->insertUrlItem( item );
00166 }
00167 }
00168
00169 void KUrlComboBox::setUrls( const QStringList &urls )
00170 {
00171 setUrls( urls, RemoveBottom );
00172 }
00173
00174 void KUrlComboBox::setUrls( const QStringList &_urls, OverLoadResolving remove )
00175 {
00176 setDefaults();
00177 qDeleteAll( d->itemList );
00178 d->itemList.clear();
00179 d->urlAdded = false;
00180
00181 if ( _urls.isEmpty() )
00182 return;
00183
00184 QStringList urls;
00185 QStringList::ConstIterator it = _urls.constBegin();
00186
00187
00188 while ( it != _urls.constEnd() ) {
00189 if ( !urls.contains( *it ) )
00190 urls += *it;
00191 ++it;
00192 }
00193
00194
00195
00196
00197 int Overload = urls.count() - d->myMaximum + d->defaultList.count();
00198 while ( Overload > 0) {
00199 if (remove == RemoveBottom) {
00200 if (!urls.isEmpty())
00201 urls.removeLast();
00202 }
00203 else {
00204 if (!urls.isEmpty())
00205 urls.removeFirst();
00206 }
00207 Overload--;
00208 }
00209
00210 it = urls.constBegin();
00211
00212 KUrlComboBoxPrivate::KUrlComboItem *item = 0L;
00213
00214 while ( it != urls.constEnd() ) {
00215 if ( (*it).isEmpty() ) {
00216 ++it;
00217 continue;
00218 }
00219 KUrl u = *it;
00220
00221
00222 if (u.isLocalFile() && !QFile::exists(u.path())) {
00223 ++it;
00224 continue;
00225 }
00226
00227 item = new KUrlComboBoxPrivate::KUrlComboItem;
00228 item->url = u;
00229 item->icon = d->getIcon( u );
00230 item->text = u.pathOrUrl(d->myMode == Directories
00231 ? KUrl::AddTrailingSlash
00232 : KUrl::RemoveTrailingSlash);
00233
00234 d->insertUrlItem( item );
00235 d->itemList.append( item );
00236 ++it;
00237 }
00238 }
00239
00240
00241 void KUrlComboBox::setUrl( const KUrl& url )
00242 {
00243 if ( url.isEmpty() )
00244 return;
00245
00246 bool blocked = blockSignals( true );
00247
00248
00249 QMap<int,const KUrlComboBoxPrivate::KUrlComboItem*>::ConstIterator mit = d->itemMapper.constBegin();
00250 QString urlToInsert = url.url(KUrl::RemoveTrailingSlash);
00251 while ( mit != d->itemMapper.constEnd() ) {
00252 Q_ASSERT( mit.value() );
00253
00254 if ( urlToInsert == mit.value()->url.url(KUrl::RemoveTrailingSlash) ) {
00255 setCurrentIndex( mit.key() );
00256
00257 if (d->myMode == Directories)
00258 d->updateItem( mit.value(), mit.key(), d->opendirIcon );
00259
00260 blockSignals( blocked );
00261 return;
00262 }
00263 ++mit;
00264 }
00265
00266
00267
00268
00269 if (d->urlAdded) {
00270 Q_ASSERT(!d->itemList.isEmpty());
00271 d->itemList.removeLast();
00272 d->urlAdded = false;
00273 }
00274
00275 setDefaults();
00276
00277 QListIterator<const KUrlComboBoxPrivate::KUrlComboItem*> it( d->itemList );
00278 while ( it.hasNext() )
00279 d->insertUrlItem( it.next() );
00280
00281 KUrlComboBoxPrivate::KUrlComboItem *item = new KUrlComboBoxPrivate::KUrlComboItem;
00282 item->url = url;
00283 item->icon = d->getIcon( url );
00284 item->text = url.pathOrUrl(d->myMode == Directories
00285 ? KUrl::AddTrailingSlash
00286 : KUrl::RemoveTrailingSlash);
00287 kDebug(250) << "setURL: text=" << item->text;
00288
00289 int id = count();
00290 QString text = item->text;
00291
00292 if (d->myMode == Directories)
00293 KComboBox::insertItem( id, d->opendirIcon, text);
00294 else
00295 KComboBox::insertItem( id,item->icon, text);
00296
00297 d->itemMapper.insert( id, item );
00298 d->itemList.append( item );
00299
00300 setCurrentIndex( id );
00301 Q_ASSERT(!d->itemList.isEmpty());
00302 d->urlAdded = true;
00303 blockSignals( blocked );
00304 }
00305
00306
00307 void KUrlComboBox::KUrlComboBoxPrivate::_k_slotActivated( int index )
00308 {
00309 const KUrlComboItem *item = itemMapper.value(index);
00310
00311 if ( item ) {
00312 m_parent->setUrl( item->url );
00313 emit m_parent->urlActivated( item->url );
00314 }
00315 }
00316
00317
00318 void KUrlComboBox::KUrlComboBoxPrivate::insertUrlItem( const KUrlComboBoxPrivate::KUrlComboItem *item )
00319 {
00320 Q_ASSERT( item );
00321
00322
00323 int id = m_parent->count();
00324 m_parent->KComboBox::insertItem(id, item->icon, item->text);
00325 itemMapper.insert( id, item );
00326 }
00327
00328
00329 void KUrlComboBox::setMaxItems( int max )
00330 {
00331 d->myMaximum = max;
00332
00333 if (count() > d->myMaximum) {
00334 int oldCurrent = currentIndex();
00335
00336 setDefaults();
00337
00338 QListIterator<const KUrlComboBoxPrivate::KUrlComboItem*> it( d->itemList );
00339 int Overload = d->itemList.count() - d->myMaximum + d->defaultList.count();
00340 for ( int i = 0; i <= Overload; i++ )
00341 it.next();
00342
00343 while ( it.hasNext() )
00344 d->insertUrlItem( it.next() );
00345
00346 if ( count() > 0 ) {
00347 if ( oldCurrent >= count() )
00348 oldCurrent = count() -1;
00349 setCurrentIndex( oldCurrent );
00350 }
00351 }
00352 }
00353
00354 int KUrlComboBox::maxItems() const
00355 {
00356 return d->myMaximum;
00357 }
00358
00359 void KUrlComboBox::removeUrl( const KUrl& url, bool checkDefaultURLs )
00360 {
00361 QMap<int,const KUrlComboBoxPrivate::KUrlComboItem*>::ConstIterator mit = d->itemMapper.constBegin();
00362 while ( mit != d->itemMapper.constEnd() ) {
00363 if ( url.url(KUrl::RemoveTrailingSlash) == mit.value()->url.url(KUrl::RemoveTrailingSlash) ) {
00364 if ( !d->itemList.removeAll( mit.value() ) && checkDefaultURLs )
00365 d->defaultList.removeAll( mit.value() );
00366 }
00367 ++mit;
00368 }
00369
00370 bool blocked = blockSignals( true );
00371 setDefaults();
00372 QListIterator<const KUrlComboBoxPrivate::KUrlComboItem*> it( d->itemList );
00373 while ( it.hasNext() ) {
00374 d->insertUrlItem( it.next() );
00375 }
00376 blockSignals( blocked );
00377 }
00378
00379 void KUrlComboBox::setCompletionObject(KCompletion* compObj, bool hsig)
00380 {
00381 if ( compObj ) {
00382
00383
00384
00385 compObj->setOrder( KCompletion::Sorted );
00386 }
00387 KComboBox::setCompletionObject( compObj, hsig );
00388 }
00389
00390 void KUrlComboBox::mousePressEvent(QMouseEvent *event)
00391 {
00392 QStyleOptionComboBox comboOpt;
00393 comboOpt.initFrom(this);
00394 const int x0 = QStyle::visualRect(layoutDirection(), rect(),
00395 style()->subControlRect(QStyle::CC_ComboBox, &comboOpt, QStyle::SC_ComboBoxEditField, this)).x();
00396 const int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &comboOpt, this);
00397
00398 if (event->x() < (x0 + KIconLoader::SizeSmall + frameWidth)) {
00399 d->m_dragPoint = event->pos();
00400 } else {
00401 d->m_dragPoint = QPoint();
00402 }
00403
00404 KComboBox::mousePressEvent(event);
00405 }
00406
00407 void KUrlComboBox::mouseMoveEvent(QMouseEvent *event)
00408 {
00409 const int index = currentIndex();
00410
00411 if (!itemIcon(index).isNull() && !d->m_dragPoint.isNull() && event->buttons() & Qt::LeftButton &&
00412 (event->pos() - d->m_dragPoint).manhattanLength() > KGlobalSettings::dndEventDelay()) {
00413 QDrag *drag = new QDrag(this);
00414 QMimeData *mime = new QMimeData();
00415 mime->setUrls(QList<QUrl>() << KUrl(itemText(index)));
00416 mime->setText(itemText(index));
00417 drag->setPixmap(itemIcon(index).pixmap(KIconLoader::SizeMedium));
00418 drag->setMimeData(mime);
00419 drag->exec();
00420 }
00421
00422 KComboBox::mouseMoveEvent(event);
00423 }
00424
00425 QIcon KUrlComboBox::KUrlComboBoxPrivate::getIcon( const KUrl& url ) const
00426 {
00427 if (myMode == Directories)
00428 return dirIcon;
00429 else
00430 return KIcon(KMimeType::iconNameForUrl(url, 0));
00431 }
00432
00433
00434
00435 void KUrlComboBox::KUrlComboBoxPrivate::updateItem( const KUrlComboBoxPrivate::KUrlComboItem *item,
00436 int index, const QIcon& icon)
00437 {
00438 m_parent->setItemIcon(index,icon);
00439
00440 if ( m_parent->isEditable() ) {
00441 m_parent->setItemText(index, item->url.pathOrUrl(myMode == Directories
00442 ? KUrl::AddTrailingSlash
00443 : KUrl::RemoveTrailingSlash));
00444 }
00445 else {
00446 m_parent->setItemText(index,item->text);
00447 }
00448 }
00449
00450
00451 #include "kurlcombobox.moc"