kurlrequester.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1999,2000,2001 Carsten Pfeiffer <pfeiffer@kde.org> 00003 00004 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 00020 #include <sys/stat.h> 00021 #include <unistd.h> 00022 00023 #include <qstring.h> 00024 #include <qtooltip.h> 00025 #include <qapplication.h> 00026 00027 #include <kaccel.h> 00028 #include <kcombobox.h> 00029 #include <kdebug.h> 00030 #include <kdialog.h> 00031 #include <kdirselectdialog.h> 00032 #include <kfiledialog.h> 00033 #include <kglobal.h> 00034 #include <kiconloader.h> 00035 #include <klineedit.h> 00036 #include <klocale.h> 00037 #include <kurlcompletion.h> 00038 #include <kurldrag.h> 00039 #include <kprotocolinfo.h> 00040 00041 #include "kurlrequester.h" 00042 00043 00044 class KURLDragPushButton : public KPushButton 00045 { 00046 public: 00047 KURLDragPushButton( QWidget *parent, const char *name=0 ) 00048 : KPushButton( parent, name ) { 00049 setDragEnabled( true ); 00050 } 00051 ~KURLDragPushButton() {} 00052 00053 void setURL( const KURL& url ) { 00054 m_urls.clear(); 00055 m_urls.append( url ); 00056 } 00057 00058 /* not needed so far 00059 void setURLs( const KURL::List& urls ) { 00060 m_urls = urls; 00061 } 00062 const KURL::List& urls() const { return m_urls; } 00063 */ 00064 00065 protected: 00066 virtual QDragObject *dragObject() { 00067 if ( m_urls.isEmpty() ) 00068 return 0L; 00069 00070 QDragObject *drag = new KURLDrag( m_urls, this, "url drag" ); 00071 return drag; 00072 } 00073 00074 private: 00075 KURL::List m_urls; 00076 00077 }; 00078 00079 00080 /* 00081 ************************************************************************* 00082 */ 00083 00084 class KURLRequester::KURLRequesterPrivate 00085 { 00086 public: 00087 KURLRequesterPrivate() { 00088 edit = 0L; 00089 combo = 0L; 00090 fileDialogMode = KFile::File | KFile::ExistingOnly | KFile::LocalOnly; 00091 } 00092 00093 void setText( const QString& text ) { 00094 if ( combo ) 00095 { 00096 if (combo->editable()) 00097 { 00098 combo->setEditText( text ); 00099 } 00100 else 00101 { 00102 combo->insertItem( text ); 00103 combo->setCurrentItem( combo->count()-1 ); 00104 } 00105 } 00106 else 00107 { 00108 edit->setText( text ); 00109 } 00110 } 00111 00112 void connectSignals( QObject *receiver ) { 00113 QObject *sender; 00114 if ( combo ) 00115 sender = combo; 00116 else 00117 sender = edit; 00118 00119 connect( sender, SIGNAL( textChanged( const QString& )), 00120 receiver, SIGNAL( textChanged( const QString& ))); 00121 connect( sender, SIGNAL( returnPressed() ), 00122 receiver, SIGNAL( returnPressed() )); 00123 connect( sender, SIGNAL( returnPressed( const QString& ) ), 00124 receiver, SIGNAL( returnPressed( const QString& ) )); 00125 } 00126 00127 void setCompletionObject( KCompletion *comp ) { 00128 if ( combo ) 00129 combo->setCompletionObject( comp ); 00130 else 00131 edit->setCompletionObject( comp ); 00132 } 00133 00137 QString url() { 00138 QString txt = combo ? combo->currentText() : edit->text(); 00139 KURLCompletion *comp; 00140 if ( combo ) 00141 comp = dynamic_cast<KURLCompletion*>(combo->completionObject()); 00142 else 00143 comp = dynamic_cast<KURLCompletion*>(edit->completionObject()); 00144 00145 if ( comp ) 00146 return comp->replacedPath( txt ); 00147 else 00148 return txt; 00149 } 00150 00151 KLineEdit *edit; 00152 KComboBox *combo; 00153 int fileDialogMode; 00154 QString fileDialogFilter; 00155 }; 00156 00157 00158 00159 KURLRequester::KURLRequester( QWidget *editWidget, QWidget *parent, 00160 const char *name ) 00161 : QHBox( parent, name ) 00162 { 00163 d = new KURLRequesterPrivate; 00164 00165 // must have this as parent 00166 editWidget->reparent( this, 0, QPoint(0,0) ); 00167 d->edit = dynamic_cast<KLineEdit*>( editWidget ); 00168 d->combo = dynamic_cast<KComboBox*>( editWidget ); 00169 00170 init(); 00171 } 00172 00173 00174 KURLRequester::KURLRequester( QWidget *parent, const char *name ) 00175 : QHBox( parent, name ) 00176 { 00177 d = new KURLRequesterPrivate; 00178 init(); 00179 } 00180 00181 00182 KURLRequester::KURLRequester( const QString& url, QWidget *parent, 00183 const char *name ) 00184 : QHBox( parent, name ) 00185 { 00186 d = new KURLRequesterPrivate; 00187 init(); 00188 setKURL( KURL::fromPathOrURL( url ) ); 00189 } 00190 00191 00192 KURLRequester::~KURLRequester() 00193 { 00194 delete myCompletion; 00195 delete myFileDialog; 00196 delete d; 00197 } 00198 00199 00200 void KURLRequester::init() 00201 { 00202 myFileDialog = 0L; 00203 myShowLocalProt = false; 00204 00205 if ( !d->combo && !d->edit ) 00206 d->edit = new KLineEdit( this, "line edit" ); 00207 00208 myButton = new KURLDragPushButton( this, "kfile button"); 00209 QIconSet iconSet = SmallIconSet(QString::fromLatin1("fileopen")); 00210 QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal ); 00211 myButton->setIconSet( iconSet ); 00212 myButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 ); 00213 QToolTip::add(myButton, i18n("Open file dialog")); 00214 00215 connect( myButton, SIGNAL( pressed() ), SLOT( slotUpdateURL() )); 00216 00217 setSpacing( KDialog::spacingHint() ); 00218 00219 QWidget *widget = d->combo ? (QWidget*) d->combo : (QWidget*) d->edit; 00220 widget->installEventFilter( this ); 00221 setFocusProxy( widget ); 00222 00223 d->connectSignals( this ); 00224 connect( myButton, SIGNAL( clicked() ), this, SLOT( slotOpenDialog() )); 00225 00226 myCompletion = new KURLCompletion(); 00227 d->setCompletionObject( myCompletion ); 00228 00229 KAccel *accel = new KAccel( this ); 00230 accel->insert( KStdAccel::Open, this, SLOT( slotOpenDialog() )); 00231 accel->readSettings(); 00232 } 00233 00234 00235 void KURLRequester::setURL( const QString& url ) 00236 { 00237 if ( myShowLocalProt ) 00238 { 00239 d->setText( url ); 00240 } 00241 else 00242 { 00243 // ### This code is broken (e.g. for paths with '#') 00244 if ( url.startsWith("file://") ) 00245 d->setText( url.mid( 7 ) ); 00246 else if ( url.startsWith("file:") ) 00247 d->setText( url.mid( 5 ) ); 00248 else 00249 d->setText( url ); 00250 } 00251 } 00252 00253 void KURLRequester::setKURL( const KURL& url ) 00254 { 00255 if ( myShowLocalProt ) 00256 d->setText( url.url() ); 00257 else 00258 d->setText( url.pathOrURL() ); 00259 } 00260 00261 void KURLRequester::setCaption( const QString& caption ) 00262 { 00263 QWidget::setCaption( caption ); 00264 if (myFileDialog) 00265 myFileDialog->setCaption( caption ); 00266 } 00267 00268 QString KURLRequester::url() const 00269 { 00270 return d->url(); 00271 } 00272 00273 void KURLRequester::slotOpenDialog() 00274 { 00275 KURL newurl; 00276 if ( (d->fileDialogMode & KFile::Directory) && !(d->fileDialogMode & KFile::File) || 00277 /* catch possible fileDialog()->setMode( KFile::Directory ) changes */ 00278 (myFileDialog && ( (myFileDialog->mode() & KFile::Directory) && 00279 (myFileDialog->mode() & (KFile::File | KFile::Files)) == 0 ) ) ) 00280 { 00281 newurl = KDirSelectDialog::selectDirectory(url(), d->fileDialogMode & KFile::LocalOnly); 00282 if ( !newurl.isValid() ) 00283 { 00284 return; 00285 } 00286 } 00287 else 00288 { 00289 emit openFileDialog( this ); 00290 00291 KFileDialog *dlg = fileDialog(); 00292 if ( !d->url().isEmpty() ) { 00293 KURL u( url() ); 00294 // If we won't be able to list it (e.g. http), then don't try :) 00295 if ( KProtocolInfo::supportsListing( u ) ) 00296 dlg->setSelection( u.url() ); 00297 } 00298 00299 if ( dlg->exec() != QDialog::Accepted ) 00300 { 00301 return; 00302 } 00303 00304 newurl = dlg->selectedURL(); 00305 } 00306 00307 setKURL( newurl ); 00308 emit urlSelected( d->url() ); 00309 } 00310 00311 void KURLRequester::setMode(uint mode) 00312 { 00313 Q_ASSERT( (mode & KFile::Files) == 0 ); 00314 d->fileDialogMode = mode; 00315 if ( (mode & KFile::Directory) && !(mode & KFile::File) ) 00316 myCompletion->setMode( KURLCompletion::DirCompletion ); 00317 00318 if (myFileDialog) 00319 myFileDialog->setMode( d->fileDialogMode ); 00320 } 00321 00322 unsigned int KURLRequester::mode() const 00323 { 00324 return d->fileDialogMode; 00325 } 00326 00327 void KURLRequester::setFilter(const QString &filter) 00328 { 00329 d->fileDialogFilter = filter; 00330 if (myFileDialog) 00331 myFileDialog->setFilter( d->fileDialogFilter ); 00332 } 00333 00334 QString KURLRequester::filter( ) const 00335 { 00336 return d->fileDialogFilter; 00337 } 00338 00339 00340 KFileDialog * KURLRequester::fileDialog() const 00341 { 00342 if ( !myFileDialog ) { 00343 QWidget *p = parentWidget(); 00344 myFileDialog = new KFileDialog( QString::null, d->fileDialogFilter, p, 00345 "file dialog", true ); 00346 00347 myFileDialog->setMode( d->fileDialogMode ); 00348 myFileDialog->setCaption( caption() ); 00349 } 00350 00351 return myFileDialog; 00352 } 00353 00354 00355 void KURLRequester::setShowLocalProtocol( bool b ) 00356 { 00357 if ( myShowLocalProt == b ) 00358 return; 00359 00360 myShowLocalProt = b; 00361 setKURL( url() ); 00362 } 00363 00364 void KURLRequester::clear() 00365 { 00366 d->setText( QString::null ); 00367 } 00368 00369 KLineEdit * KURLRequester::lineEdit() const 00370 { 00371 return d->edit; 00372 } 00373 00374 KComboBox * KURLRequester::comboBox() const 00375 { 00376 return d->combo; 00377 } 00378 00379 void KURLRequester::slotUpdateURL() 00380 { 00381 // bin compat, myButton is declared as QPushButton 00382 KURL u; 00383 u = KURL( KURL( QDir::currentDirPath() + '/' ), url() ); 00384 (static_cast<KURLDragPushButton *>( myButton ))->setURL( u ); 00385 } 00386 00387 bool KURLRequester::eventFilter( QObject *obj, QEvent *ev ) 00388 { 00389 if ( ( d->edit == obj ) || ( d->combo == obj ) ) 00390 { 00391 if (( ev->type() == QEvent::FocusIn ) || ( ev->type() == QEvent::FocusOut )) 00392 // Forward focusin/focusout events to the urlrequester; needed by file form element in khtml 00393 QApplication::sendEvent( this, ev ); 00394 } 00395 return QWidget::eventFilter( obj, ev ); 00396 } 00397 00398 KPushButton * KURLRequester::button() const 00399 { 00400 return myButton; 00401 } 00402 00403 KEditListBox::CustomEditor KURLRequester::customEditor() 00404 { 00405 setSizePolicy(QSizePolicy( QSizePolicy::Preferred, 00406 QSizePolicy::Fixed)); 00407 00408 KLineEdit *edit = d->edit; 00409 if ( !edit && d->combo ) 00410 edit = dynamic_cast<KLineEdit*>( d->combo->lineEdit() ); 00411 00412 #ifndef NDEBUG 00413 if ( !edit ) 00414 kdWarning() << "KURLRequester's lineedit is not a KLineEdit!??\n"; 00415 #endif 00416 00417 KEditListBox::CustomEditor editor( this, edit ); 00418 return editor; 00419 } 00420 00421 void KURLRequester::virtual_hook( int, void* ) 00422 { /*BASE::virtual_hook( id, data );*/ } 00423 00424 KURLComboRequester::KURLComboRequester( QWidget *parent, 00425 const char *name ) 00426 : KURLRequester( new KComboBox(false), parent, name) 00427 { 00428 } 00429 00430 #include "kurlrequester.moc"