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
00104 opendirIcon = KIcon(QLatin1String("folder-open"));
00105
00106 m_parent->connect( m_parent, SIGNAL( activated( int )), SLOT( _k_slotActivated( int )));
00107 }
00108
00109
00110 QStringList KUrlComboBox::urls() const
00111 {
00112 kDebug(250) << "::urls()";
00113
00114 QStringList list;
00115 QString url;
00116 for ( int i = d->defaultList.count(); i < count(); i++ ) {
00117 url = itemText( i );
00118 if ( !url.isEmpty() ) {
00119
00120
00121
00122 list.append( url );
00123 }
00124 }
00125
00126 return list;
00127 }
00128
00129
00130 void KUrlComboBox::addDefaultUrl( const KUrl& url, const QString& text )
00131 {
00132 addDefaultUrl( url, d->getIcon( url ), text );
00133 }
00134
00135
00136 void KUrlComboBox::addDefaultUrl( const KUrl& url, const QIcon& icon,
00137 const QString& text )
00138 {
00139 KUrlComboBoxPrivate::KUrlComboItem *item = new KUrlComboBoxPrivate::KUrlComboItem;
00140 item->url = url;
00141 item->icon = icon;
00142 if ( text.isEmpty() ) {
00143 KUrl::AdjustPathOption mode = KUrl::LeaveTrailingSlash;
00144 if (d->myMode == Directories)
00145 mode = KUrl::AddTrailingSlash;
00146 else
00147 mode = KUrl::RemoveTrailingSlash;
00148 if ( url.isLocalFile() )
00149 item->text = url.path( mode );
00150 else
00151 item->text = url.prettyUrl( mode );
00152 }
00153 else
00154 item->text = text;
00155
00156 d->defaultList.append( item );
00157 }
00158
00159
00160 void KUrlComboBox::setDefaults()
00161 {
00162 clear();
00163 d->itemMapper.clear();
00164
00165 const KUrlComboBoxPrivate::KUrlComboItem *item;
00166 for ( int id = 0; id < d->defaultList.count(); id++ ) {
00167 item = d->defaultList.at( id );
00168 d->insertUrlItem( item );
00169 }
00170 }
00171
00172 void KUrlComboBox::setUrls( const QStringList &urls )
00173 {
00174 setUrls( urls, RemoveBottom );
00175 }
00176
00177 void KUrlComboBox::setUrls( const QStringList &_urls, OverLoadResolving remove )
00178 {
00179 setDefaults();
00180 qDeleteAll( d->itemList );
00181 d->itemList.clear();
00182 d->urlAdded = false;
00183
00184 if ( _urls.isEmpty() )
00185 return;
00186
00187 QStringList urls;
00188 QStringList::ConstIterator it = _urls.constBegin();
00189
00190
00191 while ( it != _urls.constEnd() ) {
00192 if ( !urls.contains( *it ) )
00193 urls += *it;
00194 ++it;
00195 }
00196
00197
00198
00199
00200 int Overload = urls.count() - d->myMaximum + d->defaultList.count();
00201 while ( Overload > 0) {
00202 if (remove == RemoveBottom) {
00203 if (!urls.isEmpty())
00204 urls.removeLast();
00205 }
00206 else {
00207 if (!urls.isEmpty())
00208 urls.removeFirst();
00209 }
00210 Overload--;
00211 }
00212
00213 it = urls.begin();
00214
00215 KUrlComboBoxPrivate::KUrlComboItem *item = 0L;
00216
00217 while ( it != urls.end() ) {
00218 if ( (*it).isEmpty() ) {
00219 ++it;
00220 continue;
00221 }
00222 KUrl u = *it;
00223
00224
00225 if (u.isLocalFile() && !QFile::exists(u.path())) {
00226 ++it;
00227 continue;
00228 }
00229
00230 item = new KUrlComboBoxPrivate::KUrlComboItem;
00231 item->url = u;
00232 item->icon = d->getIcon( u );
00233
00234 if ( u.isLocalFile() )
00235 {
00236 KUrl::AdjustPathOption mode = KUrl::LeaveTrailingSlash;
00237 if (d->myMode == Directories)
00238 mode = KUrl::AddTrailingSlash;
00239 else
00240 mode = KUrl::RemoveTrailingSlash;
00241 item->text = u.path( mode );
00242 }
00243 else
00244 item->text = u.prettyUrl();
00245
00246 d->insertUrlItem( item );
00247 d->itemList.append( item );
00248 ++it;
00249 }
00250 }
00251
00252
00253 void KUrlComboBox::setUrl( const KUrl& url )
00254 {
00255 if ( url.isEmpty() )
00256 return;
00257
00258 bool blocked = blockSignals( true );
00259
00260
00261 QMap<int,const KUrlComboBoxPrivate::KUrlComboItem*>::ConstIterator mit = d->itemMapper.begin();
00262 QString urlToInsert = url.url(KUrl::RemoveTrailingSlash);
00263 while ( mit != d->itemMapper.end() ) {
00264 Q_ASSERT( mit.value() );
00265
00266 if ( urlToInsert == mit.value()->url.url(KUrl::RemoveTrailingSlash) ) {
00267 setCurrentIndex( mit.key() );
00268
00269 if (d->myMode == Directories)
00270 d->updateItem( mit.value(), mit.key(), d->opendirIcon );
00271
00272 blockSignals( blocked );
00273 return;
00274 }
00275 ++mit;
00276 }
00277
00278
00279
00280
00281 if (d->urlAdded) {
00282 Q_ASSERT(!d->itemList.isEmpty());
00283 d->itemList.removeLast();
00284 d->urlAdded = false;
00285 }
00286
00287 setDefaults();
00288
00289 QListIterator<const KUrlComboBoxPrivate::KUrlComboItem*> it( d->itemList );
00290 while ( it.hasNext() )
00291 d->insertUrlItem( it.next() );
00292
00293 KUrl::AdjustPathOption mode = KUrl::LeaveTrailingSlash;
00294 if (d->myMode == Directories)
00295 mode = KUrl::AddTrailingSlash;
00296 else
00297 mode = KUrl::RemoveTrailingSlash;
00298 KUrlComboBoxPrivate::KUrlComboItem *item = new KUrlComboBoxPrivate::KUrlComboItem;
00299 item->url = url;
00300 item->icon = d->getIcon( url );
00301 if ( url.isLocalFile() )
00302 item->text = url.path( mode );
00303 else
00304 item->text = url.prettyUrl( mode );
00305 kDebug(250) << "setURL: text=" << item->text;
00306
00307 int id = count();
00308 QString text = item->text;
00309
00310 if (d->myMode == Directories)
00311 KComboBox::insertItem( id, d->opendirIcon, text);
00312 else
00313 KComboBox::insertItem( id,item->icon, text);
00314
00315 d->itemMapper.insert( id, item );
00316 d->itemList.append( item );
00317
00318 setCurrentIndex( id );
00319 Q_ASSERT(!d->itemList.isEmpty());
00320 d->urlAdded = true;
00321 blockSignals( blocked );
00322 }
00323
00324
00325 void KUrlComboBox::KUrlComboBoxPrivate::_k_slotActivated( int index )
00326 {
00327 const KUrlComboItem *item = itemMapper.value(index);
00328
00329 if ( item ) {
00330 m_parent->setUrl( item->url );
00331 emit m_parent->urlActivated( item->url );
00332 }
00333 }
00334
00335
00336 void KUrlComboBox::KUrlComboBoxPrivate::insertUrlItem( const KUrlComboBoxPrivate::KUrlComboItem *item )
00337 {
00338 Q_ASSERT( item );
00339
00340
00341 int id = m_parent->count();
00342 m_parent->KComboBox::insertItem(id, item->icon, item->text);
00343 itemMapper.insert( id, item );
00344 }
00345
00346
00347 void KUrlComboBox::setMaxItems( int max )
00348 {
00349 d->myMaximum = max;
00350
00351 if (count() > d->myMaximum) {
00352 int oldCurrent = currentIndex();
00353
00354 setDefaults();
00355
00356 QListIterator<const KUrlComboBoxPrivate::KUrlComboItem*> it( d->itemList );
00357 int Overload = d->itemList.count() - d->myMaximum + d->defaultList.count();
00358 for ( int i = 0; i <= Overload; i++ )
00359 it.next();
00360
00361 while ( it.hasNext() )
00362 d->insertUrlItem( it.next() );
00363
00364 if ( count() > 0 ) {
00365 if ( oldCurrent >= count() )
00366 oldCurrent = count() -1;
00367 setCurrentIndex( oldCurrent );
00368 }
00369 }
00370 }
00371
00372 int KUrlComboBox::maxItems() const
00373 {
00374 return d->myMaximum;
00375 }
00376
00377 void KUrlComboBox::removeUrl( const KUrl& url, bool checkDefaultURLs )
00378 {
00379 QMap<int,const KUrlComboBoxPrivate::KUrlComboItem*>::ConstIterator mit = d->itemMapper.begin();
00380 while ( mit != d->itemMapper.end() ) {
00381 if ( url.url(KUrl::RemoveTrailingSlash) == mit.value()->url.url(KUrl::RemoveTrailingSlash) ) {
00382 if ( !d->itemList.removeAll( mit.value() ) && checkDefaultURLs )
00383 d->defaultList.removeAll( mit.value() );
00384 }
00385 ++mit;
00386 }
00387
00388 bool blocked = blockSignals( true );
00389 setDefaults();
00390 QListIterator<const KUrlComboBoxPrivate::KUrlComboItem*> it( d->itemList );
00391 while ( it.hasNext() ) {
00392 d->insertUrlItem( it.next() );
00393 }
00394 blockSignals( blocked );
00395 }
00396
00397 void KUrlComboBox::mousePressEvent(QMouseEvent *event)
00398 {
00399 QStyleOptionComboBox comboOpt;
00400 comboOpt.initFrom(this);
00401 const int x0 = QStyle::visualRect(layoutDirection(), rect(),
00402 style()->subControlRect(QStyle::CC_ComboBox, &comboOpt, QStyle::SC_ComboBoxEditField, this)).x();
00403 const int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &comboOpt, this);
00404
00405 if (event->x() < (x0 + KIconLoader::SizeSmall + frameWidth)) {
00406 d->m_dragPoint = event->pos();
00407 } else {
00408 d->m_dragPoint = QPoint();
00409 }
00410
00411 KComboBox::mousePressEvent(event);
00412 }
00413
00414 void KUrlComboBox::mouseMoveEvent(QMouseEvent *event)
00415 {
00416 const int index = currentIndex();
00417
00418 if (!itemIcon(index).isNull() && !d->m_dragPoint.isNull() && event->buttons() & Qt::LeftButton &&
00419 (event->pos() - d->m_dragPoint).manhattanLength() > KGlobalSettings::dndEventDelay()) {
00420 QDrag *drag = new QDrag(this);
00421 QMimeData *mime = new QMimeData();
00422 mime->setUrls(QList<QUrl>() << KUrl(itemText(index)));
00423 drag->setPixmap(itemIcon(index).pixmap(KIconLoader::SizeMedium));
00424 drag->setMimeData(mime);
00425 drag->start();
00426 }
00427
00428 KComboBox::mouseMoveEvent(event);
00429 }
00430
00431 QIcon KUrlComboBox::KUrlComboBoxPrivate::getIcon( const KUrl& url ) const
00432 {
00433 if (myMode == Directories)
00434 return dirIcon;
00435 else
00436 return KIcon(KMimeType::iconNameForUrl(url, 0));
00437 }
00438
00439
00440
00441 void KUrlComboBox::KUrlComboBoxPrivate::updateItem( const KUrlComboBoxPrivate::KUrlComboItem *item,
00442 int index, const QIcon& icon)
00443 {
00444 m_parent->setItemIcon(index,icon);
00445
00446 if ( m_parent->isEditable() ) {
00447 KUrl::AdjustPathOption mode = KUrl::LeaveTrailingSlash;
00448 if (myMode == Directories)
00449 mode = KUrl::AddTrailingSlash;
00450 else
00451 mode = KUrl::RemoveTrailingSlash;
00452
00453 m_parent->setItemText( index, item->url.isLocalFile() ? item->url.path( mode ) :
00454 item->url.prettyUrl( mode ));
00455 }
00456 else {
00457 m_parent->setItemText(index,item->text);
00458 }
00459 }
00460
00461
00462 #include "kurlcombobox.moc"