00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 #include <sys/stat.h>
00021 #include <unistd.h>
00022 
00023 #include <qstring.h>
00024 #include <qtooltip.h>
00025 
00026 #include <kaccel.h>
00027 #include <kcombobox.h>
00028 #include <kdebug.h>
00029 #include <kdialog.h>
00030 #include <kfiledialog.h>
00031 #include <kglobal.h>
00032 #include <kiconloader.h>
00033 #include <klineedit.h>
00034 #include <klocale.h>
00035 #include <kurlcompletion.h>
00036 #include <kurldrag.h>
00037 #include <kprotocolinfo.h>
00038 
00039 #include "kurlrequester.h"
00040 
00041 
00042 class KURLDragPushButton : public KPushButton
00043 {
00044 public:
00045     KURLDragPushButton( QWidget *parent, const char *name=0 )
00046     : KPushButton( parent, name ) {
00047         setDragEnabled( true );
00048     }
00049     ~KURLDragPushButton() {}
00050 
00051     void setURL( const KURL& url ) {
00052     m_urls.clear();
00053     m_urls.append( url );
00054     }
00055 
00056     
00057 
00058 
00059 
00060 
00061 
00062 
00063 protected:
00064     virtual QDragObject *dragObject() {
00065     if ( m_urls.isEmpty() )
00066         return 0L;
00067 
00068     QDragObject *drag = new KURLDrag( m_urls, this, "url drag" );
00069     return drag;
00070     }
00071 
00072 private:
00073     KURL::List m_urls;
00074 
00075 };
00076 
00077 
00078 
00079 
00080 
00081 
00082 class KURLRequester::KURLRequesterPrivate
00083 {
00084 public:
00085     KURLRequesterPrivate() {
00086     edit = 0L;
00087     combo = 0L;
00088         fileDialogMode = KFile::File | KFile::ExistingOnly | KFile::LocalOnly;
00089     }
00090 
00091     void setText( const QString& text ) {
00092     if ( combo )
00093     {
00094         if (combo->editable())
00095         {
00096                combo->setEditText( text );
00097             }
00098             else
00099             {
00100                combo->insertItem( text );
00101                combo->setCurrentItem( combo->count()-1 );
00102             }
00103         }
00104     else
00105     {
00106         edit->setText( text );
00107     }
00108     }
00109 
00110     void connectSignals( QObject *receiver ) {
00111     QObject *sender;
00112     if ( combo )
00113         sender = combo;
00114     else
00115         sender = edit;
00116 
00117     connect( sender, SIGNAL( textChanged( const QString& )),
00118          receiver, SIGNAL( textChanged( const QString& )));
00119     connect( sender, SIGNAL( returnPressed() ),
00120          receiver, SIGNAL( returnPressed() ));
00121     connect( sender, SIGNAL( returnPressed( const QString& ) ),
00122          receiver, SIGNAL( returnPressed( const QString& ) ));
00123     }
00124 
00125     void setCompletionObject( KCompletion *comp ) {
00126     if ( combo )
00127         combo->setCompletionObject( comp );
00128     else
00129         edit->setCompletionObject( comp );
00130     }
00131 
00135     QString url() {
00136         QString txt = combo ? combo->currentText() : edit->text();
00137         KURLCompletion *comp;
00138         if ( combo )
00139             comp = dynamic_cast<KURLCompletion*>(combo->completionObject());
00140         else
00141             comp = dynamic_cast<KURLCompletion*>(edit->completionObject());
00142 
00143         if ( comp )
00144             return comp->replacedPath( txt );
00145         else
00146             return txt;
00147     }
00148 
00149     KLineEdit *edit;
00150     KComboBox *combo;
00151     int fileDialogMode;
00152     QString fileDialogFilter;
00153 };
00154 
00155 
00156 
00157 KURLRequester::KURLRequester( QWidget *editWidget, QWidget *parent,
00158                   const char *name )
00159   : QHBox( parent, name )
00160 {
00161     d = new KURLRequesterPrivate;
00162 
00163     
00164     editWidget->reparent( this, 0, QPoint(0,0) );
00165     d->edit = dynamic_cast<KLineEdit*>( editWidget );
00166     d->combo = dynamic_cast<KComboBox*>( editWidget );
00167 
00168     init();
00169 }
00170 
00171 
00172 KURLRequester::KURLRequester( QWidget *parent, const char *name )
00173   : QHBox( parent, name )
00174 {
00175     d = new KURLRequesterPrivate;
00176     init();
00177 }
00178 
00179 
00180 KURLRequester::KURLRequester( const QString& url, QWidget *parent,
00181                   const char *name )
00182   : QHBox( parent, name )
00183 {
00184     d = new KURLRequesterPrivate;
00185     init();
00186     setURL( url );
00187 }
00188 
00189 
00190 KURLRequester::~KURLRequester()
00191 {
00192     delete myCompletion;
00193     delete myFileDialog;
00194     delete d;
00195 }
00196 
00197 
00198 void KURLRequester::init()
00199 {
00200     myFileDialog    = 0L;
00201     myShowLocalProt = false;
00202 
00203     if ( !d->combo && !d->edit )
00204     d->edit = new KLineEdit( this, "line edit" );
00205 
00206     myButton = new KURLDragPushButton( this, "kfile button");
00207     QIconSet iconSet = SmallIconSet(QString::fromLatin1("fileopen"));
00208     QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal );
00209     myButton->setIconSet( iconSet );
00210     myButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
00211     QToolTip::add(myButton, i18n("Open file dialog"));
00212 
00213     connect( myButton, SIGNAL( pressed() ), SLOT( slotUpdateURL() ));
00214 
00215     setSpacing( KDialog::spacingHint() );
00216 
00217     QWidget *widget = d->combo ? (QWidget*) d->combo : (QWidget*) d->edit;
00218     setFocusProxy( widget );
00219 
00220     d->connectSignals( this );
00221     connect( myButton, SIGNAL( clicked() ), this, SLOT( slotOpenDialog() ));
00222 
00223     myCompletion = new KURLCompletion();
00224     d->setCompletionObject( myCompletion );
00225 
00226     KAccel *accel = new KAccel( this );
00227     accel->insert( KStdAccel::Open, this, SLOT( slotOpenDialog() ));
00228     accel->readSettings();
00229 }
00230 
00231 
00232 void KURLRequester::setURL( const QString& url )
00233 {
00234     bool hasLocalPrefix = (url.startsWith("file:"));
00235 
00236     if ( !myShowLocalProt && hasLocalPrefix )
00237     d->setText( url.mid( 5, url.length()-5 ));
00238     else
00239     d->setText( url );
00240 }
00241 
00242 void KURLRequester::setCaption( const QString& caption )
00243 {
00244    QWidget::setCaption( caption );
00245    if (myFileDialog)
00246       myFileDialog->setCaption( caption );
00247 }
00248 
00249 QString KURLRequester::url() const
00250 {
00251     return d->url();
00252 }
00253 
00254 
00255 void KURLRequester::slotOpenDialog()
00256 {
00257     emit openFileDialog( this );
00258 
00259     KFileDialog *dlg = fileDialog();
00260     if ( !d->url().isEmpty() ) {
00261         KURL u( url() );
00262         
00263         if ( KProtocolInfo::supportsListing( u ) )
00264         dlg->setSelection( u.url() );
00265     }
00266 
00267     if ( dlg->exec() == QDialog::Accepted )
00268     {
00269     setURL( dlg->selectedURL().prettyURL() );
00270         emit urlSelected( d->url() );
00271     }
00272 }
00273 
00274 void KURLRequester::setMode(unsigned int mode)
00275 {
00276     Q_ASSERT( (mode & KFile::Files) == 0 );
00277     d->fileDialogMode = mode;
00278     if ( (mode & KFile::Directory) && !(mode & KFile::File) )
00279         myCompletion->setMode( KURLCompletion::DirCompletion );
00280 
00281     if (myFileDialog)
00282        myFileDialog->setMode( d->fileDialogMode );
00283 }
00284 
00285 void KURLRequester::setFilter(const QString &filter)
00286 {
00287     d->fileDialogFilter = filter;
00288     if (myFileDialog)
00289        myFileDialog->setFilter( d->fileDialogFilter );
00290 }
00291 
00292 KFileDialog * KURLRequester::fileDialog() const
00293 {
00294     if ( !myFileDialog ) {
00295     QWidget *p = parentWidget();
00296     myFileDialog = new KFileDialog( QString::null, QString::null, p,
00297                     "file dialog", true );
00298 
00299     myFileDialog->setMode( d->fileDialogMode );
00300         myFileDialog->setFilter( d->fileDialogFilter );
00301         myFileDialog->setCaption( caption() );
00302     }
00303 
00304     return myFileDialog;
00305 }
00306 
00307 
00308 void KURLRequester::setShowLocalProtocol( bool b )
00309 {
00310     if ( myShowLocalProt == b )
00311     return;
00312 
00313     myShowLocalProt = b;
00314     setURL( url() );
00315 }
00316 
00317 void KURLRequester::clear()
00318 {
00319     d->setText( QString::null );
00320 }
00321 
00322 KLineEdit * KURLRequester::lineEdit() const
00323 {
00324     return d->edit;
00325 }
00326 
00327 KComboBox * KURLRequester::comboBox() const
00328 {
00329     return d->combo;
00330 }
00331 
00332 void KURLRequester::slotUpdateURL()
00333 {
00334     
00335     KURL u( QDir::currentDirPath() + '/', url() );
00336     (static_cast<KURLDragPushButton *>( myButton))->setURL( u );
00337 }
00338 
00339 KPushButton * KURLRequester::button() const
00340 {
00341     return myButton;
00342 }
00343 
00344 KEditListBox::CustomEditor KURLRequester::customEditor()
00345 {
00346     setSizePolicy(QSizePolicy( QSizePolicy::Preferred,
00347                                QSizePolicy::Fixed));
00348 
00349     KLineEdit *edit = d->edit;
00350     if ( !edit && d->combo )
00351         edit = dynamic_cast<KLineEdit*>( d->combo->lineEdit() );
00352 
00353 #ifndef NDEBUG
00354     if ( !edit )
00355         kdWarning() << "KURLRequester's lineedit is not a KLineEdit!??\n";
00356 #endif
00357 
00358     KEditListBox::CustomEditor editor( this, edit );
00359     return editor;
00360 }
00361 
00362 void KURLRequester::virtual_hook( int, void* )
00363 {  }
00364 
00365 KURLComboRequester::KURLComboRequester( QWidget *parent,
00366                   const char *name )
00367   : KURLRequester( new KComboBox(false), parent, name)
00368 {
00369 }
00370 
00371 #include "kurlrequester.moc"