KIO
kurlcombobox.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License version 2, as published by the Free Software Foundation. 00007 00008 This library is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 Library General Public License for more details. 00012 00013 You should have received a copy of the GNU Library General Public License 00014 along with this library; see the file COPYING.LIB. If not, write to 00015 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00016 Boston, MA 02110-1301, USA. 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 <kglobalsettings.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; // can be used as parameter to KUR::path( int ) or url( int ) 00064 // to specify if we want a trailing slash or not 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; // default 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 //static const QString &fileProt = KGlobal::staticQString("file:"); 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 //if ( url.at(0) == '/' ) 00124 // list.append( url.prepend( fileProt ) ); 00125 //else 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 // kill duplicates 00188 while ( it != _urls.constEnd() ) { 00189 if ( !urls.contains( *it ) ) 00190 urls += *it; 00191 ++it; 00192 } 00193 00194 // limit to myMaximum items 00195 /* Note: overload is an (old) C++ keyword, some compilers (KCC) choke 00196 on that, so call it Overload (capital 'O'). (matz) */ 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 // Don't restore if file doesn't exist anymore 00222 if (u.isLocalFile() && !QFile::exists(u.toLocalFile())) { 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 // check for duplicates 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 // not in the combo yet -> create a new item and insert it 00267 00268 // first remove the old item 00269 if (d->urlAdded) { 00270 Q_ASSERT(!d->itemList.isEmpty()); 00271 d->itemList.removeLast(); 00272 d->urlAdded = false; 00273 } 00274 00275 setDefaults(); 00276 00277 int offset = qMax (0, d->itemList.count() - d->myMaximum + d->defaultList.count()); 00278 for ( int i = offset; i < d->itemList.count(); i++ ) 00279 d->insertUrlItem( d->itemList[i] ); 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 = /*isEditable() ? item->url.prettyUrl( (KUrl::AdjustPathOption)myMode ) : */ 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 // kDebug(250) << "insertURLItem " << item->text; 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 int offset = qMax (0, d->itemList.count() - d->myMaximum + d->defaultList.count()); 00339 for ( int i = offset; i < d->itemList.count(); i++ ) 00340 d->insertUrlItem( d->itemList[i] ); 00341 00342 if ( count() > 0 ) { // restore the previous currentItem 00343 if ( oldCurrent >= count() ) 00344 oldCurrent = count() -1; 00345 setCurrentIndex( oldCurrent ); 00346 } 00347 } 00348 } 00349 00350 int KUrlComboBox::maxItems() const 00351 { 00352 return d->myMaximum; 00353 } 00354 00355 void KUrlComboBox::removeUrl( const KUrl& url, bool checkDefaultURLs ) 00356 { 00357 QMap<int,const KUrlComboBoxPrivate::KUrlComboItem*>::ConstIterator mit = d->itemMapper.constBegin(); 00358 while ( mit != d->itemMapper.constEnd() ) { 00359 if ( url.url(KUrl::RemoveTrailingSlash) == mit.value()->url.url(KUrl::RemoveTrailingSlash) ) { 00360 if ( !d->itemList.removeAll( mit.value() ) && checkDefaultURLs ) 00361 d->defaultList.removeAll( mit.value() ); 00362 } 00363 ++mit; 00364 } 00365 00366 bool blocked = blockSignals( true ); 00367 setDefaults(); 00368 QListIterator<const KUrlComboBoxPrivate::KUrlComboItem*> it( d->itemList ); 00369 while ( it.hasNext() ) { 00370 d->insertUrlItem( it.next() ); 00371 } 00372 blockSignals( blocked ); 00373 } 00374 00375 void KUrlComboBox::setCompletionObject(KCompletion* compObj, bool hsig) 00376 { 00377 if ( compObj ) { 00378 // on a url combo box we want completion matches to be sorted. This way, if we are given 00379 // a suggestion, we match the "best" one. For instance, if we have "foo" and "foobar", 00380 // and we write "foo", the match is "foo" and never "foobar". (ereslibre) 00381 compObj->setOrder( KCompletion::Sorted ); 00382 } 00383 KComboBox::setCompletionObject( compObj, hsig ); 00384 } 00385 00386 void KUrlComboBox::mousePressEvent(QMouseEvent *event) 00387 { 00388 QStyleOptionComboBox comboOpt; 00389 comboOpt.initFrom(this); 00390 const int x0 = QStyle::visualRect(layoutDirection(), rect(), 00391 style()->subControlRect(QStyle::CC_ComboBox, &comboOpt, QStyle::SC_ComboBoxEditField, this)).x(); 00392 const int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &comboOpt, this); 00393 00394 if (event->x() < (x0 + KIconLoader::SizeSmall + frameWidth)) { 00395 d->m_dragPoint = event->pos(); 00396 } else { 00397 d->m_dragPoint = QPoint(); 00398 } 00399 00400 KComboBox::mousePressEvent(event); 00401 } 00402 00403 void KUrlComboBox::mouseMoveEvent(QMouseEvent *event) 00404 { 00405 const int index = currentIndex(); 00406 00407 if (!itemIcon(index).isNull() && !d->m_dragPoint.isNull() && event->buttons() & Qt::LeftButton && 00408 (event->pos() - d->m_dragPoint).manhattanLength() > KGlobalSettings::dndEventDelay()) { 00409 QDrag *drag = new QDrag(this); 00410 QMimeData *mime = new QMimeData(); 00411 mime->setUrls(QList<QUrl>() << KUrl(itemText(index))); 00412 mime->setText(itemText(index)); 00413 drag->setPixmap(itemIcon(index).pixmap(KIconLoader::SizeMedium)); 00414 drag->setMimeData(mime); 00415 drag->exec(); 00416 } 00417 00418 KComboBox::mouseMoveEvent(event); 00419 } 00420 00421 QIcon KUrlComboBox::KUrlComboBoxPrivate::getIcon( const KUrl& url ) const 00422 { 00423 if (myMode == Directories) 00424 return dirIcon; 00425 else 00426 return KIcon(KMimeType::iconNameForUrl(url, 0)); 00427 } 00428 00429 00430 // updates "item" with icon "icon" and sets the URL instead of text 00431 void KUrlComboBox::KUrlComboBoxPrivate::updateItem( const KUrlComboBoxPrivate::KUrlComboItem *item, 00432 int index, const QIcon& icon) 00433 { 00434 m_parent->setItemIcon(index,icon); 00435 00436 if ( m_parent->isEditable() ) { 00437 m_parent->setItemText(index, item->url.pathOrUrl(myMode == Directories 00438 ? KUrl::AddTrailingSlash 00439 : KUrl::RemoveTrailingSlash)); 00440 } 00441 else { 00442 m_parent->setItemText(index,item->text); 00443 } 00444 } 00445 00446 00447 #include "kurlcombobox.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:55:23 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:55:23 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.