00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "kfilewidget.h"
00028
00029 #include "kfileplacesview.h"
00030 #include "kfileplacesmodel.h"
00031 #include "kfilebookmarkhandler_p.h"
00032 #include "kurlcombobox.h"
00033 #include "kurlnavigator.h"
00034 #include <config-kfile.h>
00035
00036 #include <kactioncollection.h>
00037 #include <kdiroperator.h>
00038 #include <kdirselectdialog.h>
00039 #include <kfilefiltercombo.h>
00040 #include <kimagefilepreview.h>
00041 #include <kmenu.h>
00042 #include <kmimetype.h>
00043 #include <kpushbutton.h>
00044 #include <krecentdocument.h>
00045 #include <ktoolbar.h>
00046 #include <kurlcompletion.h>
00047 #include <kuser.h>
00048 #include <kprotocolmanager.h>
00049 #include <kio/job.h>
00050 #include <kio/jobuidelegate.h>
00051 #include <kio/netaccess.h>
00052 #include <kio/scheduler.h>
00053 #include <krecentdirs.h>
00054 #include <kdebug.h>
00055
00056 #include <QtGui/QCheckBox>
00057 #include <QtGui/QLayout>
00058 #include <QtGui/QLabel>
00059 #include <QtGui/QLineEdit>
00060 #include <QtGui/QSplitter>
00061 #include <QtCore/QFSFileEngine>
00062 #include <kshell.h>
00063 #include <kmessagebox.h>
00064 #include <kauthorized.h>
00065
00066 class KFileWidgetPrivate
00067 {
00068 public:
00069 KFileWidgetPrivate( KFileWidget* q )
00070 : boxLayout(0),
00071 labeledCustomWidget(0),
00072 bottomCustomWidget(0),
00073 speedBarWidth(-1),
00074 inAccept(false),
00075 dummyAdded(false),
00076 q(q)
00077 {
00078 }
00079 void updateLocationWhatsThis();
00080 void updateAutoSelectExtension();
00081 void initSpeedbar();
00082 void initGUI();
00083 void readConfig(const KConfigGroup &configGroup);
00084 void writeConfig(KConfigGroup &configGroup);
00085 void setNonExtSelection();
00086 void setLocationText(const KUrl&);
00087 void setLocationText(const KUrl::List&);
00088 void appendExtension(KUrl &url);
00089 void updateLocationEditExtension(const QString &);
00090 void updateFilter();
00091 void updateSplitterSize();
00092 KUrl::List& parseSelectedUrls();
00099 KUrl::List tokenize(const QString& line) const;
00103 void readRecentFiles( KConfig * );
00107 void saveRecentFiles( KConfig * );
00112 void multiSelectionChanged();
00113
00117 KUrl getCompleteUrl(const QString&) const;
00118
00123 void setDummyHistoryEntry(const QString& text, const QPixmap& icon = QPixmap(),
00124 bool usePreviousPixmapIfNull = true);
00125
00129 void removeDummyHistoryEntry();
00130
00131
00132 void _k_slotLocationChanged( const QString& );
00133 void _k_urlEntered( const KUrl& );
00134 void _k_enterUrl( const KUrl& );
00135 void _k_enterUrl( const QString& );
00136 void _k_locationAccepted( const QString& );
00137 void _k_locationActivated( const QString& );
00138 void _k_slotFilterChanged();
00139 void _k_fileHighlighted( const KFileItem& );
00140 void _k_fileSelected( const KFileItem& );
00141 void _k_slotStatResult( KJob* );
00142 void _k_slotLoadingFinished();
00143 void _k_fileCompletion( const QString& );
00144 void _k_toggleSpeedbar( bool );
00145 void _k_toggleBookmarks( bool );
00146 void _k_slotAutoSelectExtClicked();
00147 void _k_placesViewSplitterMoved();
00148
00149 void addToRecentDocuments();
00150
00151 QString locationEditCurrentText() const;
00152
00153
00154 KUrl url;
00155
00156
00157 QString filenames;
00158
00159
00160 QString selection;
00161
00162
00163
00164 QBoxLayout *boxLayout;
00165 QGridLayout *lafBox;
00166 QVBoxLayout *vbox;
00167
00168 QLabel *locationLabel;
00169
00170
00171 QLabel *filterLabel;
00172 KUrlNavigator *urlNavigator;
00173 KPushButton *okButton, *cancelButton;
00174 KFilePlacesView *placesView;
00175 QSplitter *placesViewSplitter;
00176 QWidget *labeledCustomWidget;
00177 QWidget *bottomCustomWidget;
00178
00179
00180 QCheckBox *autoSelectExtCheckBox;
00181 bool autoSelectExtChecked;
00182 QString extension;
00183
00184 QList<KIO::StatJob*> statJobs;
00185
00186 KUrl::List urlList;
00187
00188
00189
00190
00191 int speedBarWidth;
00192
00193
00194
00195 bool keepLocation;
00196
00197
00198
00199 bool hasView;
00200
00201 bool hasDefaultFilter;
00202 bool autoDirectoryFollowing;
00203 bool inAccept;
00204 bool dummyAdded;
00205
00206
00207 KFileWidget::OperationMode operationMode;
00208
00209
00210 QString fileClass;
00211
00212 KFileBookmarkHandler *bookmarkHandler;
00213
00214 KActionMenu* bookmarkButton;
00215 KConfigGroup *viewConfigGroup;
00216
00217 KToolBar *toolbar;
00218 KUrlComboBox *locationEdit;
00219 KDirOperator *ops;
00220 KFileFilterCombo *filterWidget;
00221 KFileWidget* q;
00222
00223 KFilePlacesModel *model;
00224 };
00225
00226 K_GLOBAL_STATIC(KUrl, lastDirectory)
00227
00228 static const char autocompletionWhatsThisText[] = I18N_NOOP("<qt>While typing in the text area, you may be presented "
00229 "with possible matches. "
00230 "This feature can be controlled by clicking with the right mouse button "
00231 "and selecting a preferred mode from the <b>Text Completion</b> menu.") "</qt>";
00232
00233
00234 static bool containsProtocolSection( const QString& string )
00235 {
00236 int len = string.length();
00237 static const char prot[] = ":/";
00238 for (int i=0; i < len;) {
00239 i = string.indexOf( QLatin1String(prot), i );
00240 if (i == -1)
00241 return false;
00242 int j=i-1;
00243 for (; j >= 0; j--) {
00244 const QChar& ch( string[j] );
00245 if (ch.toAscii() == 0 || !ch.isLetter())
00246 break;
00247 if (ch.isSpace() && (i-j-1) >= 2)
00248 return true;
00249 }
00250 if (j < 0 && i >= 2)
00251 return true;
00252 i += 3;
00253 }
00254 return false;
00255 }
00256
00257 KFileWidget::KFileWidget( const KUrl& startDir, QWidget *parent )
00258 : QWidget(parent), KAbstractFileWidget(), d(new KFileWidgetPrivate(this))
00259 {
00260
00261 d->keepLocation = false;
00262 d->operationMode = Opening;
00263 d->bookmarkHandler = 0;
00264 d->hasDefaultFilter = false;
00265 d->hasView = false;
00266 d->placesViewSplitter = 0;
00267
00268 d->okButton = new KPushButton(KStandardGuiItem::ok(), this);
00269 d->okButton->setDefault( true );
00270 d->cancelButton = new KPushButton(KStandardGuiItem::cancel(), this);
00271
00272 d->okButton->hide();
00273 d->cancelButton->hide();
00274
00275 d->autoSelectExtCheckBox = 0;
00276 d->autoSelectExtChecked = false;
00277 d->placesView = 0;
00278
00279 d->toolbar = new KToolBar(this, true);
00280 d->toolbar->setObjectName("KFileWidget::toolbar");
00281 d->toolbar->setMovable(false);
00282
00283 d->model = new KFilePlacesModel(this);
00284 d->urlNavigator = new KUrlNavigator(d->model, startDir, d->toolbar);
00285 d->urlNavigator->setPlacesSelectorVisible(false);
00286
00287 KUrl u;
00288 KUrlComboBox *pathCombo = d->urlNavigator->editor();
00289 #ifdef Q_WS_WIN
00290 foreach( const QFileInfo &drive,QFSFileEngine::drives() )
00291 {
00292 u.setPath( drive.filePath() );
00293 pathCombo->addDefaultUrl(u,
00294 KIO::pixmapForUrl( u, 0, KIconLoader::Small ),
00295 i18n("Drive: %1", u.toLocalFile()));
00296 }
00297 #else
00298 u.setPath(QDir::rootPath());
00299 pathCombo->addDefaultUrl(u,
00300 KIO::pixmapForUrl(u, 0, KIconLoader::Small),
00301 u.toLocalFile());
00302 #endif
00303
00304 u.setPath(QDir::homePath());
00305 pathCombo->addDefaultUrl(u, KIO::pixmapForUrl(u, 0, KIconLoader::Small),
00306 u.path(KUrl::AddTrailingSlash));
00307
00308 KUrl docPath;
00309 docPath.setPath( KGlobalSettings::documentPath() );
00310 if ( (u.path(KUrl::AddTrailingSlash) != docPath.path(KUrl::AddTrailingSlash)) &&
00311 QDir(docPath.path(KUrl::AddTrailingSlash)).exists() )
00312 {
00313 pathCombo->addDefaultUrl( docPath,
00314 KIO::pixmapForUrl( docPath, 0, KIconLoader::Small ),
00315 docPath.path(KUrl::AddTrailingSlash));
00316 }
00317
00318 u.setPath( KGlobalSettings::desktopPath() );
00319 pathCombo->addDefaultUrl(u,
00320 KIO::pixmapForUrl(u, 0, KIconLoader::Small),
00321 u.path(KUrl::AddTrailingSlash));
00322
00323 d->url = getStartUrl( startDir, d->fileClass );
00324 d->selection = d->url.url();
00325
00326
00327 if ( d->url.isLocalFile() )
00328 {
00329 if ( !QFile::exists( d->url.toLocalFile() ) )
00330 {
00331 d->url = d->url.upUrl();
00332 QDir dir( d->url.toLocalFile() );
00333 while ( !dir.exists() )
00334 {
00335 d->url = d->url.upUrl();
00336 dir.setPath( d->url.toLocalFile() );
00337 }
00338 }
00339 }
00340
00341 d->ops = new KDirOperator(d->url, this );
00342 d->ops->setObjectName( "KFileWidget::ops" );
00343 d->ops->setOnlyDoubleClickSelectsFiles( true );
00344 connect(d->ops, SIGNAL(urlEntered(const KUrl&)),
00345 SLOT(_k_urlEntered(const KUrl&)));
00346 connect(d->ops, SIGNAL(fileHighlighted(const KFileItem &)),
00347 SLOT(_k_fileHighlighted(const KFileItem &)));
00348 connect(d->ops, SIGNAL(fileSelected(const KFileItem &)),
00349 SLOT(_k_fileSelected(const KFileItem &)));
00350 connect(d->ops, SIGNAL(finishedLoading()),
00351 SLOT(_k_slotLoadingFinished()));
00352
00353 d->ops->setupMenu(KDirOperator::SortActions |
00354 KDirOperator::FileActions |
00355 KDirOperator::ViewActions);
00356 KActionCollection *coll = d->ops->actionCollection();
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 d->toolbar->addAction( coll->action( "up" ) );
00367 coll->action( "up" )->setWhatsThis(i18n("<qt>Click this button to enter the parent folder.<br /><br />"
00368 "For instance, if the current location is file:/home/%1 clicking this "
00369 "button will take you to file:/home.</qt>", KUser().loginName() ));
00370
00371 d->toolbar->addAction( coll->action( "back" ) );
00372 coll->action( "back" )->setWhatsThis(i18n("Click this button to move backwards one step in the browsing history."));
00373 d->toolbar->addAction( coll->action( "forward" ) );
00374 coll->action( "forward" )->setWhatsThis(i18n("Click this button to move forward one step in the browsing history."));
00375
00376 d->toolbar->addAction( coll->action( "reload" ) );
00377 coll->action( "reload" )->setWhatsThis(i18n("Click this button to reload the contents of the current location."));
00378 coll->action( "mkdir" )->setShortcut( QKeySequence(Qt::Key_F10) );
00379 d->toolbar->addAction( coll->action( "mkdir" ) );
00380 coll->action( "mkdir" )->setWhatsThis(i18n("Click this button to create a new folder."));
00381
00382 KToggleAction *showSidebarAction =
00383 new KToggleAction(i18n("Show Places Navigation Panel"), this);
00384 coll->addAction("toggleSpeedbar", showSidebarAction);
00385 showSidebarAction->setShortcut( QKeySequence(Qt::Key_F9) );
00386 connect( showSidebarAction, SIGNAL( toggled( bool ) ),
00387 SLOT( _k_toggleSpeedbar( bool )) );
00388
00389 KToggleAction *showBookmarksAction =
00390 new KToggleAction(i18n("Show Bookmarks"), this);
00391 coll->addAction("toggleBookmarks", showBookmarksAction);
00392 connect( showBookmarksAction, SIGNAL( toggled( bool ) ),
00393 SLOT( _k_toggleBookmarks( bool )) );
00394
00395 KActionMenu *menu = new KActionMenu( KIcon("configure"), i18n("Options"), this);
00396 coll->addAction("extra menu", menu);
00397 menu->setWhatsThis(i18n("<qt>This is the preferences menu for the file dialog. "
00398 "Various options can be accessed from this menu including: <ul>"
00399 "<li>how files are sorted in the list</li>"
00400 "<li>types of view, including icon and list</li>"
00401 "<li>showing of hidden files</li>"
00402 "<li>the Places navigation panel</li>"
00403 "<li>file previews</li>"
00404 "<li>separating folders from files</li></ul></qt>"));
00405 menu->addAction( coll->action( "sorting menu" ));
00406 menu->addSeparator();
00407 coll->action( "short view" )->setShortcut( QKeySequence(Qt::Key_F6) );
00408 menu->addAction( coll->action( "short view" ));
00409 coll->action( "detailed view" )->setShortcut( QKeySequence(Qt::Key_F7) );
00410 menu->addAction( coll->action( "detailed view" ));
00411 menu->addSeparator();
00412 coll->action( "show hidden" )->setShortcut( QKeySequence(Qt::Key_F8) );
00413 menu->addAction( coll->action( "show hidden" ));
00414 menu->addAction( showSidebarAction );
00415 menu->addAction( showBookmarksAction );
00416 coll->action( "preview" )->setShortcut( QKeySequence(Qt::Key_F11) );
00417 menu->addAction( coll->action( "preview" ));
00418
00419 menu->setDelayed( false );
00420 connect( menu->menu(), SIGNAL( aboutToShow() ),
00421 d->ops, SLOT( updateSelectionDependentActions() ));
00422 d->toolbar->addAction( menu );
00423
00424 d->toolbar->addWidget(d->urlNavigator);
00425
00426
00427
00428 d->toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly);
00429 d->toolbar->setMovable(false);
00430
00431 KUrlCompletion *pathCompletionObj = new KUrlCompletion( KUrlCompletion::DirCompletion );
00432 pathCombo->setCompletionObject( pathCompletionObj );
00433 pathCombo->setAutoDeleteCompletionObject( true );
00434
00435 connect( d->urlNavigator, SIGNAL( urlChanged( const KUrl& )),
00436 this, SLOT( _k_enterUrl( const KUrl& ) ));
00437
00438 QString whatsThisText;
00439
00440
00441 d->locationLabel = new QLabel(i18n("&Location:"), this);
00442 d->locationEdit = new KUrlComboBox(KUrlComboBox::Files, true, this);
00443
00444
00445
00446 d->locationEdit->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
00447 connect( d->locationEdit, SIGNAL( editTextChanged( const QString& ) ),
00448 SLOT( _k_slotLocationChanged( const QString& )) );
00449
00450 d->updateLocationWhatsThis();
00451 d->locationLabel->setBuddy(d->locationEdit);
00452
00453 KUrlCompletion *fileCompletionObj = new KUrlCompletion( KUrlCompletion::FileCompletion );
00454 QString dir = d->url.url(KUrl::AddTrailingSlash);
00455
00456 d->urlNavigator->setUrl( dir );
00457
00458 fileCompletionObj->setDir( dir );
00459 d->locationEdit->setCompletionObject( fileCompletionObj );
00460 d->locationEdit->setAutoDeleteCompletionObject( true );
00461 connect( fileCompletionObj, SIGNAL( match( const QString& ) ),
00462 SLOT( _k_fileCompletion( const QString& )) );
00463
00464 connect(d->locationEdit, SIGNAL( returnPressed( const QString& )),
00465 this, SLOT( _k_locationAccepted( const QString& ) ));
00466 connect(d->locationEdit, SIGNAL( activated( const QString& )),
00467 this, SLOT( _k_locationActivated( const QString& ) ));
00468
00469
00470 whatsThisText = i18n("<qt>This is the filter to apply to the file list. "
00471 "File names that do not match the filter will not be shown.<p>"
00472 "You may select from one of the preset filters in the "
00473 "drop down menu, or you may enter a custom filter "
00474 "directly into the text area.</p><p>"
00475 "Wildcards such as * and ? are allowed.</p></qt>");
00476 d->filterLabel = new QLabel(i18n("&Filter:"), this);
00477 d->filterLabel->setWhatsThis(whatsThisText);
00478 d->filterWidget = new KFileFilterCombo(this);
00479
00480
00481
00482 d->filterWidget->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
00483 d->filterWidget->setWhatsThis(whatsThisText);
00484 d->filterLabel->setBuddy(d->filterWidget);
00485 connect(d->filterWidget, SIGNAL(filterChanged()), SLOT(_k_slotFilterChanged()));
00486
00487
00488
00489 d->autoSelectExtCheckBox = new QCheckBox (this);
00490 d->autoSelectExtCheckBox->setStyleSheet(QString("QCheckBox { padding-top: %1px; }").arg(KDialog::spacingHint()));
00491 connect(d->autoSelectExtCheckBox, SIGNAL(clicked()), SLOT(_k_slotAutoSelectExtClicked()));
00492
00493 d->initGUI();
00494
00495 KSharedConfig::Ptr config = KGlobal::config();
00496 d->readRecentFiles(config.data());
00497
00498 d->viewConfigGroup=new KConfigGroup(config,ConfigGroup);
00499 d->ops->setViewConfig(*d->viewConfigGroup);
00500 d->readConfig(* d->viewConfigGroup);
00501 setSelection(d->selection);
00502 d->locationEdit->setFocus();
00503 }
00504
00505 KFileWidget::~KFileWidget()
00506 {
00507 KSharedConfig::Ptr config = KGlobal::config();
00508
00509 config->sync();
00510
00511 delete d->bookmarkHandler;
00512 delete d->ops;
00513 delete d->viewConfigGroup;
00514 delete d;
00515 }
00516
00517 void KFileWidget::setLocationLabel(const QString& text)
00518 {
00519 d->locationLabel->setText(text);
00520 }
00521
00522 void KFileWidget::setFilter(const QString& filter)
00523 {
00524 int pos = filter.indexOf('/');
00525
00526
00527
00528
00529 if (pos > 0 && filter[pos - 1] != '\\') {
00530 QStringList filters = filter.split(" ", QString::SkipEmptyParts);
00531 setMimeFilter( filters );
00532 return;
00533 }
00534
00535
00536
00537
00538 QString copy (filter);
00539 for (pos = 0; (pos = copy.indexOf("\\/", pos)) != -1; ++pos)
00540 copy.remove(pos, 1);
00541
00542 d->ops->clearFilter();
00543 d->filterWidget->setFilter(copy);
00544 d->ops->setNameFilter(d->filterWidget->currentFilter());
00545 d->hasDefaultFilter = false;
00546 d->filterWidget->setEditable( true );
00547
00548 d->updateAutoSelectExtension ();
00549 }
00550
00551 QString KFileWidget::currentFilter() const
00552 {
00553 return d->filterWidget->currentFilter();
00554 }
00555
00556 void KFileWidget::setMimeFilter( const QStringList& mimeTypes,
00557 const QString& defaultType )
00558 {
00559 d->filterWidget->setMimeFilter( mimeTypes, defaultType );
00560
00561 QStringList types = d->filterWidget->currentFilter().split(" ",QString::SkipEmptyParts);
00562 types.append( QLatin1String( "inode/directory" ));
00563 d->ops->clearFilter();
00564 d->ops->setMimeFilter( types );
00565 d->hasDefaultFilter = !defaultType.isEmpty();
00566 d->filterWidget->setEditable( !d->hasDefaultFilter ||
00567 d->operationMode != Saving );
00568
00569 d->updateAutoSelectExtension ();
00570 }
00571
00572 void KFileWidget::clearFilter()
00573 {
00574 d->filterWidget->setFilter( QString() );
00575 d->ops->clearFilter();
00576 d->hasDefaultFilter = false;
00577 d->filterWidget->setEditable( true );
00578
00579 d->updateAutoSelectExtension ();
00580 }
00581
00582 QString KFileWidget::currentMimeFilter() const
00583 {
00584 int i = d->filterWidget->currentIndex();
00585 if (d->filterWidget->showsAllTypes() && i == 0)
00586 return QString();
00587
00588 return d->filterWidget->filters()[i];
00589 }
00590
00591 KMimeType::Ptr KFileWidget::currentFilterMimeType()
00592 {
00593 return KMimeType::mimeType( currentMimeFilter() );
00594 }
00595
00596 void KFileWidget::setPreviewWidget(KPreviewWidgetBase *w) {
00597 d->ops->setPreviewWidget(w);
00598 d->ops->clearHistory();
00599 d->hasView = true;
00600 }
00601
00602 KUrl KFileWidgetPrivate::getCompleteUrl(const QString &_url) const
00603 {
00604 QString url = KShell::tildeExpand(_url);
00605 KUrl u;
00606
00607 if ( KUrl::isRelativeUrl(url) )
00608 {
00609 if (!url.isEmpty() && !QDir::isRelativePath(url) )
00610 u.setPath( url );
00611 else
00612 {
00613 u = ops->url();
00614 u.addPath( url );
00615 u.cleanPath();
00616 }
00617 }
00618 else
00619 u = url;
00620
00621 return u;
00622 }
00623
00624
00625 void KFileWidget::slotOk()
00626 {
00627 kDebug(kfile_area) << "slotOk\n";
00628
00629
00630
00631 const KFileItemList items = d->ops->selectedItems();
00632
00633 const QString locationEditCurrentText( d->locationEditCurrentText() );
00634
00635 if ( (mode() & KFile::Directory) != KFile::Directory ) {
00636 if ( locationEditCurrentText.isEmpty() ) {
00637
00638
00639 if (items.isEmpty())
00640 return;
00641
00642
00643
00644 bool multi = (mode() & KFile::Files) != 0;
00645 QString endQuote = QLatin1String("\" ");
00646 QString name;
00647 KUrl::List urlList;
00648 foreach (const KFileItem &fileItem, items) {
00649 name = fileItem.name();
00650 if ( multi ) {
00651 name.prepend( QLatin1Char( '"' ) );
00652 name.append( endQuote );
00653 }
00654
00655 urlList << fileItem.url();
00656 }
00657 d->setLocationText( urlList );
00658 return;
00659 }
00660 }
00661
00662 bool dirOnly = d->ops->dirOnlyMode();
00663
00664
00665 if ( !d->locationEdit->lineEdit()->isModified() &&
00666 !(items.isEmpty() && !dirOnly) ) {
00667
00668 d->urlList.clear();
00669 d->filenames.clear();
00670
00671 if ( dirOnly ) {
00672 d->url = d->ops->url();
00673 }
00674 else {
00675 if ( !(mode() & KFile::Files) ) {
00676 d->url = items.first().url();
00677 }
00678
00679 else {
00680 d->url = d->ops->url();
00681 KUrl::List urlList;
00682 foreach (const KFileItem &item, items) {
00683 urlList.append(item.url());
00684 }
00685 d->urlList = urlList;
00686 }
00687 }
00688
00689 KUrl url = KIO::NetAccess::mostLocalUrl(d->url,topLevelWidget());
00690 if ( ( (mode() & KFile::LocalOnly) == KFile::LocalOnly ) &&
00691 !url.isLocalFile() )
00692 {
00693
00694 KMessageBox::sorry( this,
00695 i18n("You can only select local files."),
00696 i18n("Remote Files Not Accepted") );
00697 return;
00698 }
00699
00700 d->url = url;
00701 emit accepted();
00702 return;
00703 }
00704
00705 KUrl selectedUrl;
00706
00707 if ( (mode() & KFile::Files) == KFile::Files ) {
00708 if ( locationEditCurrentText.contains( '/' ) ) {
00709
00710 KUrl u( d->ops->url(), KShell::tildeExpand( locationEditCurrentText ));
00711 if ( u.isValid() )
00712 selectedUrl = u;
00713 else
00714 selectedUrl = d->ops->url();
00715 }
00716 else
00717 selectedUrl = d->ops->url();
00718 }
00719
00720 else {
00721 selectedUrl = d->getCompleteUrl( locationEditCurrentText );
00722
00723
00724 d->appendExtension (selectedUrl);
00725 }
00726
00727 if ( !selectedUrl.isValid() ) {
00728 KMessageBox::sorry( this, i18n("%1\ndoes not appear to be a valid URL.\n", d->url.url()), i18n("Invalid URL") );
00729 return;
00730 }
00731
00732 KUrl url = KIO::NetAccess::mostLocalUrl(selectedUrl,topLevelWidget());
00733 if ( ( (mode() & KFile::LocalOnly) == KFile::LocalOnly ) &&
00734 !url.isLocalFile() )
00735 {
00736 KMessageBox::sorry( this,
00737 i18n("You can only select local files."),
00738 i18n("Remote Files Not Accepted") );
00739 return;
00740 }
00741
00742 d->url = url;
00743
00744
00745
00746 if ( (mode() & KFile::Directory) == KFile::Directory ) {
00747 kDebug(kfile_area) << "Directory";
00748 bool done = true;
00749 if ( d->url.isLocalFile() ) {
00750 if ( locationEditCurrentText.isEmpty() ) {
00751 QFileInfo info( d->url.toLocalFile() );
00752 if ( info.isDir() ) {
00753 d->filenames.clear();
00754 d->urlList.clear();
00755 d->urlList.append( d->url );
00756 emit accepted();
00757 }
00758 else if (!info.exists() && (mode() & KFile::File) != KFile::File) {
00759
00760 if ( d->ops->mkdir( d->url.url(), true ))
00761 return;
00762 else
00763 emit accepted();
00764 }
00765 else {
00766
00767 if ( (mode() & KFile::File) == KFile::File ||
00768 (mode() & KFile::Files) == KFile::Files )
00769 done = false;
00770 }
00771 }
00772 else
00773 {
00774 if ( mode() & KFile::ExistingOnly )
00775 {
00776 if ( d->ops->dirOnlyMode() )
00777 {
00778 KUrl fullURL(d->url, locationEditCurrentText);
00779 if ( QFile::exists( fullURL.toLocalFile() ) )
00780 {
00781 d->url = fullURL;
00782 d->filenames.clear();
00783 d->urlList.clear();
00784 emit accepted();
00785 return;
00786 }
00787 else
00788 return;
00789 }
00790 }
00791
00792 d->filenames = locationEditCurrentText;
00793 emit accepted();
00794 }
00795
00796 }
00797 else {
00798
00799 d->filenames.clear();
00800 d->urlList.clear();
00801 d->urlList.append( d->url );
00802
00803 if ( mode() & KFile::ExistingOnly )
00804 done = false;
00805 else
00806 emit accepted();
00807 }
00808
00809 if ( done )
00810 return;
00811 }
00812 else {
00813 KUrl::List urls = d->tokenize( locationEditCurrentText );
00814 if ( urls.count()==1 && urls.first().isLocalFile() ) {
00815 QFileInfo info( urls.first().toLocalFile() );
00816 if ( info.isDir() && this->selectedUrl().isValid() && !this->selectedUrl().equals( urls.first(), KUrl::CompareWithoutTrailingSlash ) ) {
00817 setSelection( info.absolutePath() );
00818 slotOk();
00819 return;
00820 }
00821 }
00822 }
00823
00824 if (!KAuthorized::authorizeUrlAction("open", KUrl(), d->url))
00825 {
00826 QString msg = KIO::buildErrorString(KIO::ERR_ACCESS_DENIED, d->url.prettyUrl());
00827 KMessageBox::error( this, msg);
00828 return;
00829 }
00830
00831 KIO::StatJob *job = 0L;
00832 d->statJobs.clear();
00833 d->filenames = KShell::tildeExpand( locationEditCurrentText );
00834
00835 if ( (mode() & KFile::Files) == KFile::Files &&
00836 !locationEditCurrentText.contains( '/' ) ) {
00837 kDebug(kfile_area) << "Files\n";
00838 KUrl::List list = d->parseSelectedUrls();
00839 for ( KUrl::List::ConstIterator it = list.begin();
00840 it != list.end(); ++it )
00841 {
00842 if (!KAuthorized::authorizeUrlAction("open", KUrl(), *it))
00843 {
00844 QString msg = KIO::buildErrorString(KIO::ERR_ACCESS_DENIED, (*it).prettyUrl());
00845 KMessageBox::error( this, msg);
00846 return;
00847 }
00848 }
00849 for ( KUrl::List::ConstIterator it = list.begin();
00850 it != list.end(); ++it )
00851 {
00852 KIO::JobFlags flags = !(*it).isLocalFile() ? KIO::DefaultFlags : KIO::HideProgressInfo;
00853 job = KIO::stat( *it, flags );
00854 job->ui()->setWindow (topLevelWidget());
00855 KIO::Scheduler::scheduleJob( job );
00856 d->statJobs.append( job );
00857 connect( job, SIGNAL( result(KJob *) ),
00858 SLOT( _k_slotStatResult( KJob *) ));
00859 }
00860 return;
00861 }
00862
00863 KIO::JobFlags flags = !d->url.isLocalFile() ? KIO::DefaultFlags : KIO::HideProgressInfo;
00864 job = KIO::stat(d->url,flags);
00865 job->ui()->setWindow (topLevelWidget());
00866 d->statJobs.append( job );
00867 connect(job, SIGNAL(result(KJob*)), SLOT(_k_slotStatResult(KJob*)));
00868 }
00869
00870
00871
00872
00873 void KFileWidgetPrivate::_k_slotStatResult(KJob* job)
00874 {
00875 kDebug(kfile_area) << "slotStatResult";
00876 KIO::StatJob *sJob = static_cast<KIO::StatJob *>( job );
00877
00878 if ( !statJobs.removeAll( sJob ) ) {
00879 return;
00880 }
00881
00882 int count = statJobs.count();
00883
00884
00885
00886 if (sJob->error() && count == 0 && !ops->dirOnlyMode())
00887 {
00888 emit q->accepted();
00889 return;
00890 }
00891
00892 KIO::UDSEntry t = sJob->statResult();
00893 if (t.isDir())
00894 {
00895 if ( ops->dirOnlyMode() )
00896 {
00897 filenames.clear();
00898 urlList.clear();
00899 emit q->accepted();
00900 }
00901 else
00902 {
00903 if ( count == 0 ) {
00904 locationEdit->clearEditText();
00905 locationEdit->lineEdit()->setModified( false );
00906 q->setUrl( sJob->url() );
00907 }
00908 }
00909 statJobs.clear();
00910 return;
00911 }
00912 else if ( ops->dirOnlyMode() )
00913 {
00914 return;
00915 }
00916
00917 kDebug(kfile_area) << "filename " << sJob->url().url();
00918
00919 if ( count == 0 )
00920 emit q->accepted();
00921 }
00922
00923 void KFileWidget::accept()
00924 {
00925 d->inAccept = true;
00926
00927 *lastDirectory = d->ops->url();
00928 if (!d->fileClass.isEmpty())
00929 KRecentDirs::add(d->fileClass, d->ops->url().url());
00930
00931
00932 d->locationEdit->setItemText( 0, QString() );
00933
00934 KUrl::List list = selectedUrls();
00935 QList<KUrl>::const_iterator it = list.begin();
00936 int atmost = d->locationEdit->maxItems();
00937 for ( ; it != list.end() && atmost > 0; ++it ) {
00938 const KUrl& url = *it;
00939
00940
00941
00942 QString file = url.isLocalFile() ? url.path(KUrl::RemoveTrailingSlash) : url.prettyUrl(KUrl::RemoveTrailingSlash);
00943
00944
00945 for ( int i = 1; i < d->locationEdit->count(); i++ ) {
00946 if ( d->locationEdit->itemText( i ) == file ) {
00947 d->locationEdit->removeItem( i-- );
00948 break;
00949 }
00950 }
00951
00952
00953
00954 d->locationEdit->insertItem( 1,file);
00955 atmost--;
00956 }
00957
00958 KSharedConfig::Ptr config = KGlobal::config();
00959 config->setForceGlobal( true );
00960 KConfigGroup grp(config,ConfigGroup);
00961 d->writeConfig(grp);
00962 config->setForceGlobal( false );
00963
00964 d->saveRecentFiles(config.data());
00965 config->sync();
00966
00967 d->addToRecentDocuments();
00968
00969 if ( (mode() & KFile::Files) != KFile::Files )
00970 emit fileSelected(d->url.url());
00971
00972 d->ops->close();
00973 }
00974
00975
00976 void KFileWidgetPrivate::_k_fileHighlighted(const KFileItem &i)
00977 {
00978 const bool modified = locationEdit->lineEdit()->isModified();
00979 locationEdit->lineEdit()->setModified( false );
00980
00981 if ( ( !i.isNull() && i.isDir() ) ||
00982 ( locationEdit->hasFocus() && !locationEdit->currentText().isEmpty() ) )
00983 return;
00984
00985 if ( (ops->mode() & KFile::Files) != KFile::Files ) {
00986 if ( i.isNull() ) {
00987 if ( !modified ) {
00988 setLocationText( KUrl() );
00989 }
00990 return;
00991 }
00992
00993 url = i.url();
00994
00995 if ( !locationEdit->hasFocus() ) {
00996 setLocationText( url );
00997 }
00998 emit q->fileHighlighted(url.url());
00999 }
01000
01001 else {
01002 multiSelectionChanged();
01003 emit q->selectionChanged();
01004 }
01005
01006 locationEdit->lineEdit()->selectAll();
01007 }
01008
01009 void KFileWidgetPrivate::_k_fileSelected(const KFileItem &i)
01010 {
01011 if (!i.isNull() && i.isDir())
01012 return;
01013
01014 if ( (ops->mode() & KFile::Files) != KFile::Files ) {
01015 if ( i.isNull() ) {
01016 setLocationText( KUrl() );
01017 return;
01018 }
01019
01020 setLocationText( i.url() );
01021 }
01022 else {
01023 multiSelectionChanged();
01024 emit q->selectionChanged();
01025 }
01026 q->slotOk();
01027 }
01028
01029
01030
01031
01032 void KFileWidgetPrivate::multiSelectionChanged()
01033 {
01034 if ( locationEdit->hasFocus() && !locationEdit->currentText().isEmpty() )
01035 return;
01036
01037 const KFileItemList list = ops->selectedItems();
01038
01039 if ( list.isEmpty() ) {
01040 setLocationText( KUrl() );
01041 return;
01042 }
01043
01044 static const QString &begin = KGlobal::staticQString(" \"");
01045 KUrl::List urlList;
01046 foreach (const KFileItem &fileItem, list) {
01047 urlList << fileItem.url();
01048 }
01049
01050 setLocationText( urlList );
01051 }
01052
01053 void KFileWidgetPrivate::setDummyHistoryEntry( const QString& text, const QPixmap& icon,
01054 bool usePreviousPixmapIfNull )
01055 {
01056
01057
01058
01059 QObject::disconnect( locationEdit, SIGNAL( editTextChanged( const QString& ) ),
01060 q, SLOT( _k_slotLocationChanged( const QString& ) ) );
01061
01062 bool dummyExists = dummyAdded;
01063
01064 int cursorPosition = locationEdit->lineEdit()->cursorPosition();
01065
01066 if ( dummyAdded ) {
01067 if ( !icon.isNull() ) {
01068 locationEdit->setItemIcon( 0, icon );
01069 locationEdit->setItemText( 0, text );
01070 } else {
01071 if ( !usePreviousPixmapIfNull ) {
01072 locationEdit->setItemIcon( 0, QPixmap() );
01073 }
01074 locationEdit->setItemText( 0, text );
01075 }
01076 } else {
01077 if ( !text.isEmpty() ) {
01078 if ( !icon.isNull() ) {
01079 locationEdit->insertItem( 0, icon, text );
01080 } else {
01081 if ( !usePreviousPixmapIfNull ) {
01082 locationEdit->insertItem( 0, QPixmap(), text );
01083 } else {
01084 locationEdit->insertItem( 0, text );
01085 }
01086 }
01087 dummyAdded = true;
01088 dummyExists = true;
01089 }
01090 }
01091
01092 if ( dummyExists && !text.isEmpty() ) {
01093 locationEdit->setCurrentIndex( 0 );
01094 }
01095
01096 locationEdit->lineEdit()->setCursorPosition( cursorPosition );
01097
01098 QObject::connect( locationEdit, SIGNAL( editTextChanged ( const QString& ) ),
01099 q, SLOT( _k_slotLocationChanged( const QString& )) );
01100 }
01101
01102 void KFileWidgetPrivate::removeDummyHistoryEntry()
01103 {
01104 if ( !dummyAdded || locationEdit->lineEdit()->isModified() ) {
01105 return;
01106 }
01107
01108
01109
01110
01111 QObject::disconnect( locationEdit, SIGNAL( editTextChanged( const QString& ) ),
01112 q, SLOT( _k_slotLocationChanged( const QString& ) ) );
01113
01114 locationEdit->removeItem( 0 );
01115 locationEdit->setCurrentIndex( -1 );
01116 dummyAdded = false;
01117
01118 QObject::connect( locationEdit, SIGNAL( editTextChanged ( const QString& ) ),
01119 q, SLOT( _k_slotLocationChanged( const QString& )) );
01120 }
01121
01122 void KFileWidgetPrivate::setLocationText( const KUrl& url )
01123 {
01124 if ( !url.isEmpty() ) {
01125 QPixmap mimeTypeIcon = KIconLoader::global()->loadMimeTypeIcon( KMimeType::iconNameForUrl( url ), KIconLoader::Small );
01126 setDummyHistoryEntry( url.fileName(), mimeTypeIcon );
01127 } else {
01128 removeDummyHistoryEntry();
01129 }
01130
01131
01132 if ( operationMode == KFileWidget::Saving && !locationEdit->isVisible())
01133 setNonExtSelection();
01134 }
01135
01136 void KFileWidgetPrivate::setLocationText( const KUrl::List& urlList )
01137 {
01138 if ( urlList.count() > 1 ) {
01139 QString urls;
01140 foreach (const KUrl &url, urlList) {
01141 urls += QString( "\"%1\"" ).arg( url.fileName() ) + ' ';
01142 }
01143 urls = urls.left( urls.size() - 1 );
01144
01145 setDummyHistoryEntry( urls, QPixmap(), false );
01146 } else if ( urlList.count() ) {
01147 const QPixmap mimeTypeIcon = KIconLoader::global()->loadMimeTypeIcon( KMimeType::iconNameForUrl( urlList[0] ), KIconLoader::Small );
01148 setDummyHistoryEntry( urlList[0].fileName(), mimeTypeIcon );
01149 } else {
01150 removeDummyHistoryEntry();
01151 }
01152
01153
01154 if ( operationMode == KFileWidget::Saving && !locationEdit->isVisible())
01155 setNonExtSelection();
01156 }
01157
01158 void KFileWidgetPrivate::updateLocationWhatsThis()
01159 {
01160 QString whatsThisText;
01161 if (operationMode == KFileWidget::Saving)
01162 {
01163 whatsThisText = "<qt>" + i18n("This is the name to save the file as.") +
01164 i18n (autocompletionWhatsThisText);
01165 }
01166 else if (ops->mode() & KFile::Files)
01167 {
01168 whatsThisText = "<qt>" + i18n("This is the list of files to open. More than "
01169 "one file can be specified by listing several "
01170 "files, separated by spaces.") +
01171 i18n (autocompletionWhatsThisText);
01172 }
01173 else
01174 {
01175 whatsThisText = "<qt>" + i18n("This is the name of the file to open.") +
01176 i18n (autocompletionWhatsThisText);
01177 }
01178
01179 locationLabel->setWhatsThis(whatsThisText);
01180 locationEdit->setWhatsThis(whatsThisText);
01181 }
01182
01183 void KFileWidgetPrivate::initSpeedbar()
01184 {
01185 placesView = new KFilePlacesView( q );
01186 placesView->setModel(model);
01187 placesView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
01188
01189 placesView->setObjectName( QLatin1String( "url bar" ) );
01190 QObject::connect( placesView, SIGNAL( urlChanged( const KUrl& )),
01191 q, SLOT( _k_enterUrl( const KUrl& )) );
01192
01193
01194
01195
01196
01197 placesView->setUrl( url );
01198
01199 placesViewSplitter->insertWidget( 0, placesView );
01200 }
01201
01202 void KFileWidgetPrivate::initGUI()
01203 {
01204 delete boxLayout;
01205
01206 boxLayout = new QVBoxLayout( q);
01207 boxLayout->setMargin(0);
01208 boxLayout->setSpacing(0);
01209 boxLayout->addWidget(toolbar, 0, Qt::AlignTop);
01210
01211 placesViewSplitter = new QSplitter(q);
01212 placesViewSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
01213 placesViewSplitter->setChildrenCollapsible(false);
01214 boxLayout->addWidget(placesViewSplitter);
01215
01216 QObject::connect(placesViewSplitter, SIGNAL(splitterMoved(int,int)), q, SLOT(_k_placesViewSplitterMoved()));
01217
01218 vbox = new QVBoxLayout();
01219 vbox->setMargin(0);
01220 QWidget *vboxWidget = new QWidget();
01221 vboxWidget->setLayout(vbox);
01222 placesViewSplitter->insertWidget(0, vboxWidget);
01223
01224 vbox->addWidget(ops, 4);
01225 vbox->addSpacing(KDialog::spacingHint());
01226
01227 lafBox = new QGridLayout();
01228
01229 lafBox->setSpacing(KDialog::spacingHint());
01230 lafBox->addWidget(locationLabel, 0, 0, Qt::AlignVCenter);
01231 lafBox->addWidget(locationEdit, 0, 1, Qt::AlignVCenter);
01232 lafBox->addWidget(okButton, 0, 2, Qt::AlignVCenter);
01233
01234 lafBox->addWidget(filterLabel, 1, 0, Qt::AlignVCenter);
01235 lafBox->addWidget(filterWidget, 1, 1, Qt::AlignVCenter);
01236 lafBox->addWidget(cancelButton, 1, 2, Qt::AlignVCenter);
01237
01238 lafBox->setColumnStretch(1, 4);
01239
01240 vbox->addLayout(lafBox);
01241
01242
01243 vbox->addWidget(autoSelectExtCheckBox);
01244
01245 q->setTabOrder(ops, autoSelectExtCheckBox);
01246 q->setTabOrder(autoSelectExtCheckBox, locationEdit);
01247 q->setTabOrder(locationEdit, filterWidget);
01248 q->setTabOrder(filterWidget, okButton);
01249 q->setTabOrder(okButton, cancelButton);
01250 q->setTabOrder(cancelButton, urlNavigator);
01251 q->setTabOrder(urlNavigator, ops);
01252 q->setTabOrder(cancelButton, urlNavigator);
01253 q->setTabOrder(urlNavigator, ops);
01254 }
01255
01256 void KFileWidgetPrivate::_k_slotFilterChanged()
01257 {
01258 QString filter = filterWidget->currentFilter();
01259 ops->clearFilter();
01260
01261 if ( filter.indexOf( '/' ) > -1 ) {
01262 QStringList types = filter.split(" ",QString::SkipEmptyParts);
01263 types.prepend( "inode/directory" );
01264 ops->setMimeFilter( types );
01265 }
01266 else
01267 ops->setNameFilter( filter );
01268
01269 ops->updateDir();
01270
01271 updateAutoSelectExtension();
01272
01273 emit q->filterChanged( filter );
01274 }
01275
01276
01277 void KFileWidget::setUrl(const KUrl& url, bool clearforward)
01278 {
01279 d->selection.clear();
01280 d->ops->setUrl( url, clearforward);
01281 }
01282
01283
01284 void KFileWidgetPrivate::_k_urlEntered(const KUrl& url)
01285 {
01286 QString filename = locationEditCurrentText();
01287 selection.clear();
01288
01289 KUrlComboBox* pathCombo = urlNavigator->editor();
01290 if ( pathCombo->count() != 0 ) {
01291 pathCombo->setUrl( url );
01292 }
01293
01294 bool blocked = locationEdit->blockSignals( true );
01295 if ( keepLocation ) {
01296 locationEdit->changeUrl( 0, KIcon( KMimeType::iconNameForUrl( filename ) ), filename );
01297 locationEdit->lineEdit()->setModified( true );
01298 }
01299
01300 locationEdit->blockSignals( blocked );
01301
01302 urlNavigator->setUrl( url );
01303
01304 QString dir = url.url(KUrl::AddTrailingSlash);
01305
01306 KUrlCompletion *completion = dynamic_cast<KUrlCompletion*>( locationEdit->completionObject() );
01307 if( completion )
01308 completion->setDir( dir );
01309
01310 if ( placesView )
01311 placesView->setUrl( url );
01312 }
01313
01314 void KFileWidgetPrivate::_k_locationAccepted( const QString& url )
01315 {
01316 ops->setCurrentItem( url );
01317 q->slotOk();
01318 }
01319
01320 void KFileWidgetPrivate::_k_locationActivated( const QString& url )
01321 {
01322
01323
01324 q->setUrl( url );
01325 }
01326
01327 void KFileWidgetPrivate::_k_enterUrl( const KUrl& url )
01328 {
01329 KUrl fixedUrl( url );
01330
01331
01332 fixedUrl.adjustPath( KUrl::AddTrailingSlash );
01333 q->setUrl( fixedUrl );
01334 }
01335
01336 void KFileWidgetPrivate::_k_enterUrl( const QString& url )
01337 {
01338 _k_enterUrl( KUrl( KUrlCompletion::replacedPath( url, true, true )) );
01339 }
01340
01341
01342 void KFileWidget::setSelection(const QString& url)
01343 {
01344 kDebug(kfile_area) << "setSelection " << url;
01345
01346 if (url.isEmpty()) {
01347 d->selection.clear();
01348 return;
01349 }
01350
01351 KUrl u = d->getCompleteUrl(url);
01352 if (!u.isValid()) {
01353 kWarning() << url << " is not a correct argument for setSelection!";
01354 return;
01355 }
01356
01357
01358 if (!KProtocolManager::supportsListing(u))
01359 return;
01360
01361
01362
01363
01364 KIO::UDSEntry entry;
01365 bool res = KIO::NetAccess::stat(u, entry, this);
01366 KFileItem i(entry, u);
01367
01368 kDebug(kfile_area) << "KFileItem " << u.path() << " " << i.isDir() << " " << u.isLocalFile() << " " << QFile::exists( u.path() );
01369 if ( res && i.isDir() && u.isLocalFile() && QFile::exists( u.path() ) ) {
01370
01371
01372
01373
01374 setUrl(u, true);
01375 }
01376 else if ( res ) {
01377 QString filename = u.url();
01378 int sep = filename.lastIndexOf('/');
01379 if (sep >= 0) {
01380 KUrl dir(u);
01381 dir.setQuery( QString() );
01382 dir.setFileName( QString() );
01383 setUrl(dir, true );
01384
01385
01386
01387 filename = u.fileName();
01388 kDebug(kfile_area) << "filename " << filename;
01389 d->selection = filename;
01390 d->setLocationText( u );
01391
01392
01393
01394
01395
01396
01397
01398
01399 d->locationEdit->lineEdit()->setModified( true );
01400 }
01401
01402 d->url = d->ops->url();
01403 d->url.addPath(filename);
01404 }
01405 else {
01406 d->setLocationText(url);
01407 d->locationEdit->lineEdit()->setModified( true );
01408 }
01409 }
01410
01411 void KFileWidgetPrivate::_k_slotLoadingFinished()
01412 {
01413 if ( !selection.isEmpty() )
01414 ops->setCurrentItem( selection );
01415 }
01416
01417 void KFileWidgetPrivate::_k_fileCompletion( const QString& match )
01418 {
01419 if ( match.isEmpty() && ops->view() ) {
01420 ops->view()->clearSelection();
01421 } else {
01422 ops->setCurrentItem( match );
01423 setDummyHistoryEntry( locationEdit->currentText(), KIconLoader::global()->loadMimeTypeIcon( KMimeType::iconNameForUrl( match ), KIconLoader::Small ), !locationEdit->currentText().isEmpty() );
01424 locationEdit->setCompletedText( match );
01425 }
01426 }
01427
01428 void KFileWidgetPrivate::_k_slotLocationChanged( const QString& text )
01429 {
01430 locationEdit->lineEdit()->setModified( true );
01431
01432 if ( text.isEmpty() && ops->view() )
01433 ops->view()->clearSelection();
01434
01435 if ( text.isEmpty() ) {
01436 removeDummyHistoryEntry();
01437 } else {
01438 setDummyHistoryEntry( text );
01439 }
01440
01441 ops->setCurrentItem( text );
01442
01443 updateFilter();
01444 }
01445
01446 KUrl KFileWidget::selectedUrl() const
01447 {
01448 if ( d->inAccept )
01449 return d->url;
01450 else
01451 return KUrl();
01452 }
01453
01454 KUrl::List KFileWidget::selectedUrls() const
01455 {
01456 KUrl::List list;
01457 if ( d->inAccept ) {
01458 if ( (d->ops->mode() & KFile::Files) == KFile::Files )
01459 list = d->parseSelectedUrls();
01460 else
01461 list.append( d->url );
01462 }
01463 return list;
01464 }
01465
01466
01467 KUrl::List& KFileWidgetPrivate::parseSelectedUrls()
01468 {
01469 if ( filenames.isEmpty() ) {
01470 return urlList;
01471 }
01472
01473 urlList.clear();
01474 if ( filenames.contains( '/' )) {
01475 KUrl u;
01476 if ( containsProtocolSection( filenames ) )
01477 u = filenames;
01478 else
01479 u.setPath( filenames );
01480
01481 if ( u.isValid() )
01482 urlList.append( u );
01483 else
01484 KMessageBox::error( q,
01485 i18n("The chosen filenames do not\n"
01486 "appear to be valid."),
01487 i18n("Invalid Filenames") );
01488 }
01489
01490 else
01491 urlList = tokenize( filenames );
01492
01493 filenames.clear();
01494
01495 return urlList;
01496 }
01497
01498
01499
01500 KUrl::List KFileWidgetPrivate::tokenize( const QString& line ) const
01501 {
01502 KUrl::List urls;
01503 KUrl u( ops->url() );
01504 QString name;
01505
01506 const int count = line.count( QLatin1Char( '"' ) );
01507 if ( count == 0 ) {
01508 u.setFileName( line );
01509 if ( u.isValid() )
01510 urls.append( u );
01511
01512 return urls;
01513 }
01514
01515 if ( (count % 2) == 1 ) {
01516 KMessageBox::sorry(q, i18n("The requested filenames\n"
01517 "%1\n"
01518 "do not appear to be valid;\n"
01519 "make sure every filename is enclosed in double quotes.", line),
01520 i18n("Filename Error"));
01521 return urls;
01522 }
01523
01524 int start = 0;
01525 int index1 = -1, index2 = -1;
01526 while ( true ) {
01527 index1 = line.indexOf( '"', start );
01528 index2 = line.indexOf( '"', index1 + 1 );
01529
01530 if ( index1 < 0 )
01531 break;
01532
01533
01534 name = line.mid( index1 + 1, index2 - index1 - 1 );
01535 u.setFileName( name );
01536 if ( u.isValid() )
01537 urls.append( u );
01538
01539 start = index2 + 1;
01540 }
01541 return urls;
01542 }
01543
01544
01545 QString KFileWidget::selectedFile() const
01546 {
01547 if ( d->inAccept ) {
01548 const KUrl url = KIO::NetAccess::mostLocalUrl(d->url,topLevelWidget());
01549 if (url.isLocalFile())
01550 return url.path();
01551 else {
01552 KMessageBox::sorry( const_cast<KFileWidget*>(this),
01553 i18n("You can only select local files."),
01554 i18n("Remote Files Not Accepted") );
01555 }
01556 }
01557 return QString();
01558 }
01559
01560 QStringList KFileWidget::selectedFiles() const
01561 {
01562 QStringList list;
01563
01564 if ( d->inAccept ) {
01565 if ( (d->ops->mode() & KFile::Files) == KFile::Files ) {
01566 KUrl::List urls = d->parseSelectedUrls();
01567 QList<KUrl>::const_iterator it = urls.begin();
01568 while ( it != urls.end() ) {
01569 KUrl url = KIO::NetAccess::mostLocalUrl(*it,topLevelWidget());
01570 if ( url.isLocalFile() )
01571 list.append( url.path() );
01572 ++it;
01573 }
01574 }
01575
01576 else {
01577 if ( d->url.isLocalFile() )
01578 list.append( d->url.path() );
01579 }
01580 }
01581
01582 return list;
01583 }
01584
01585 KUrl KFileWidget::baseUrl() const
01586 {
01587 return d->ops->url();
01588 }
01589
01590 void KFileWidget::resizeEvent(QResizeEvent* event)
01591 {
01592 d->updateSplitterSize();
01593
01594 QWidget::resizeEvent(event);
01595 }
01596
01597 void KFileWidget::showEvent(QShowEvent* event)
01598 {
01599 if ( !d->hasView ) {
01600 d->ops->setView(KFile::Default);
01601 d->ops->view()->setSizePolicy( QSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum ) );
01602 d->hasView = true;
01603 }
01604 d->ops->clearHistory();
01605
01606 QWidget::showEvent(event);
01607 }
01608
01609 void KFileWidget::setMode( KFile::Modes m )
01610 {
01611 d->ops->setMode(m);
01612 if ( d->ops->dirOnlyMode() ) {
01613 d->filterWidget->setDefaultFilter( i18n("*|All Folders") );
01614 }
01615 else {
01616 d->filterWidget->setDefaultFilter( i18n("*|All Files") );
01617 }
01618
01619 d->updateAutoSelectExtension();
01620 }
01621
01622 KFile::Modes KFileWidget::mode() const
01623 {
01624 return d->ops->mode();
01625 }
01626
01627
01628 void KFileWidgetPrivate::readConfig( const KConfigGroup &configGroup)
01629 {
01630 ops->readConfig(configGroup);
01631
01632 KUrlComboBox *combo = urlNavigator->editor();
01633 combo->setUrls( configGroup.readPathEntry( RecentURLs, QStringList() ), KUrlComboBox::RemoveTop );
01634 combo->setMaxItems( configGroup.readEntry( RecentURLsNumber,
01635 DefaultRecentURLsNumber ) );
01636 combo->setUrl( ops->url() );
01637 autoDirectoryFollowing = configGroup.readEntry( AutoDirectoryFollowing,
01638 DefaultDirectoryFollowing );
01639
01640 KGlobalSettings::Completion cm = (KGlobalSettings::Completion)
01641 configGroup.readEntry( PathComboCompletionMode,
01642 static_cast<int>( KGlobalSettings::completionMode() ) );
01643 if ( cm != KGlobalSettings::completionMode() )
01644 combo->setCompletionMode( cm );
01645
01646 cm = (KGlobalSettings::Completion)
01647 configGroup.readEntry( LocationComboCompletionMode,
01648 static_cast<int>( KGlobalSettings::completionMode() ) );
01649 if ( cm != KGlobalSettings::completionMode() )
01650 locationEdit->setCompletionMode( cm );
01651
01652
01653 _k_toggleSpeedbar( configGroup.readEntry( ShowSpeedbar, true ) );
01654
01655
01656 _k_toggleBookmarks( configGroup.readEntry(ShowBookmarks, false) );
01657
01658
01659 autoSelectExtChecked = configGroup.readEntry (AutoSelectExtChecked, DefaultAutoSelectExtChecked);
01660 updateAutoSelectExtension();
01661
01662
01663 urlNavigator->setUrlEditable( !configGroup.readEntry(BreadcrumbNavigation, true) );
01664
01665 int w1 = q->minimumSize().width();
01666 int w2 = toolbar->sizeHint().width();
01667 if (w1 < w2)
01668 q->setMinimumWidth(w2);
01669 }
01670
01671 void KFileWidgetPrivate::writeConfig(KConfigGroup &configGroup)
01672 {
01673 KUrlComboBox *pathCombo = urlNavigator->editor();
01674 configGroup.writePathEntry( RecentURLs, pathCombo->urls() );
01675
01676 configGroup.writeEntry( PathComboCompletionMode, static_cast<int>(pathCombo->completionMode()) );
01677 configGroup.writeEntry( LocationComboCompletionMode, static_cast<int>(locationEdit->completionMode()) );
01678
01679 const bool showSpeedbar = placesView && !placesView->isHidden();
01680 configGroup.writeEntry( ShowSpeedbar, showSpeedbar );
01681 if (showSpeedbar) {
01682 const QList<int> sizes = placesViewSplitter->sizes();
01683 Q_ASSERT( sizes.count() > 0 );
01684 configGroup.writeEntry( SpeedbarWidth, sizes[0] );
01685 }
01686
01687 configGroup.writeEntry( ShowBookmarks, bookmarkHandler != 0 );
01688 configGroup.writeEntry( AutoSelectExtChecked, autoSelectExtChecked );
01689 configGroup.writeEntry( BreadcrumbNavigation, !urlNavigator->isUrlEditable() );
01690
01691 ops->writeConfig(configGroup);
01692 }
01693
01694
01695 void KFileWidgetPrivate::readRecentFiles( KConfig *kc )
01696 {
01697 KConfigGroup cg( kc, ConfigGroup );
01698
01699 locationEdit->setMaxItems( cg.readEntry( RecentFilesNumber,
01700 DefaultRecentURLsNumber ) );
01701 locationEdit->setUrls( cg.readPathEntry( RecentFiles, QStringList() ),
01702 KUrlComboBox::RemoveBottom );
01703 locationEdit->setCurrentIndex( -1 );
01704 }
01705
01706 void KFileWidgetPrivate::saveRecentFiles( KConfig *kc )
01707 {
01708 KConfigGroup cg(kc, ConfigGroup );
01709 cg.writePathEntry( RecentFiles, locationEdit->urls() );
01710 }
01711
01712 KPushButton * KFileWidget::okButton() const
01713 {
01714 return d->okButton;
01715 }
01716
01717 KPushButton * KFileWidget::cancelButton() const
01718 {
01719 return d->cancelButton;
01720 }
01721
01722
01723 void KFileWidget::slotCancel()
01724 {
01725 d->ops->close();
01726
01727 KSharedConfig::Ptr config = KGlobal::config();
01728 config->setForceGlobal( true );
01729 KConfigGroup grp(config,ConfigGroup);
01730 d->writeConfig(grp);
01731 config->setForceGlobal( false );
01732 }
01733
01734 void KFileWidget::setKeepLocation( bool keep )
01735 {
01736 d->keepLocation = keep;
01737 }
01738
01739 bool KFileWidget::keepsLocation() const
01740 {
01741 return d->keepLocation;
01742 }
01743
01744 void KFileWidget::setOperationMode( OperationMode mode )
01745 {
01746 d->operationMode = mode;
01747 d->keepLocation = (mode == Saving);
01748 d->filterWidget->setEditable( !d->hasDefaultFilter || mode != Saving );
01749 if ( mode == Opening )
01750
01751 d->okButton->setGuiItem( KGuiItem( i18n( "&Open" ), "document-open") );
01752 else if ( mode == Saving ) {
01753 d->okButton->setGuiItem( KStandardGuiItem::save() );
01754 d->setNonExtSelection();
01755 }
01756 else
01757 d->okButton->setGuiItem( KStandardGuiItem::ok() );
01758 d->updateLocationWhatsThis();
01759 d->updateAutoSelectExtension();
01760 }
01761
01762 KFileWidget::OperationMode KFileWidget::operationMode() const
01763 {
01764 return d->operationMode;
01765 }
01766
01767 void KFileWidgetPrivate::_k_slotAutoSelectExtClicked()
01768 {
01769 kDebug (kfile_area) << "slotAutoSelectExtClicked(): "
01770 << autoSelectExtCheckBox->isChecked() << endl;
01771
01772
01773 autoSelectExtChecked = autoSelectExtCheckBox->isChecked();
01774
01775
01776 updateLocationEditExtension (extension );
01777 }
01778
01779 void KFileWidgetPrivate::_k_placesViewSplitterMoved()
01780 {
01781 const QList<int> sizes = placesViewSplitter->sizes();
01782 speedBarWidth = sizes[0];
01783 }
01784
01785 static QString getExtensionFromPatternList(const QStringList &patternList)
01786 {
01787 QString ret;
01788 kDebug (kfile_area) << "\tgetExtension " << patternList;
01789
01790 QStringList::ConstIterator patternListEnd = patternList.end();
01791 for (QStringList::ConstIterator it = patternList.begin();
01792 it != patternListEnd;
01793 ++it)
01794 {
01795 kDebug (kfile_area) << "\t\ttry: \'" << (*it) << "\'";
01796
01797
01798
01799
01800
01801
01802
01803
01804 if ((*it).startsWith ("*.") &&
01805 (*it).length() > 2 &&
01806 (*it).indexOf('*', 2) < 0 && (*it).indexOf ('?', 2) < 0)
01807 {
01808 ret = (*it).mid (1);
01809 break;
01810 }
01811 }
01812
01813 return ret;
01814 }
01815
01816 static QString stripUndisplayable (const QString &string)
01817 {
01818 QString ret = string;
01819
01820 ret.remove (':');
01821 ret.remove ('&');
01822
01823 return ret;
01824 }
01825
01826
01827
01828
01829
01830
01831
01832 void KFileWidgetPrivate::updateAutoSelectExtension()
01833 {
01834 if (!autoSelectExtCheckBox) return;
01835
01836
01837
01838
01839
01840
01841
01842
01843 kDebug (kfile_area) << "Figure out an extension: ";
01844 QString lastExtension = extension;
01845 extension.clear();
01846
01847
01848 if ((operationMode == KFileWidget::Saving) && (ops->mode() & KFile::File))
01849 {
01850
01851
01852
01853
01854 QString filter = filterWidget->currentFilter();
01855 if (!filter.isEmpty())
01856 {
01857
01858 if (filter.indexOf ('/') < 0)
01859 {
01860 extension = getExtensionFromPatternList (filter.split(" ",QString::SkipEmptyParts)).toLower();
01861 kDebug (kfile_area) << "\tsetFilter-style: pattern ext=\'"
01862 << extension << "\'" << endl;
01863 }
01864
01865 else
01866 {
01867 KMimeType::Ptr mime = KMimeType::mimeType (filter);
01868
01869 if (mime)
01870 {
01871
01872 QString nativeExtension = mime->property ("X-KDE-NativeExtension").toString();
01873 if (!nativeExtension.isEmpty() && nativeExtension.at (0) == '.')
01874 {
01875 extension = nativeExtension.toLower();
01876 kDebug (kfile_area) << "\tsetMimeFilter-style: native ext=\'"
01877 << extension << "\'" << endl;
01878 }
01879
01880
01881 if (extension.isEmpty())
01882 {
01883 extension = getExtensionFromPatternList (mime->patterns()).toLower();
01884 kDebug (kfile_area) << "\tsetMimeFilter-style: pattern ext=\'"
01885 << extension << "\'" << endl;
01886 }
01887 }
01888 }
01889 }
01890
01891
01892
01893
01894
01895
01896 QString whatsThisExtension;
01897 if (!extension.isEmpty())
01898 {
01899
01900 autoSelectExtCheckBox->setText (i18n ("Automatically select filename e&xtension (%1)", extension));
01901 whatsThisExtension = i18n ("the extension <b>%1</b>", extension);
01902
01903 autoSelectExtCheckBox->setEnabled (true);
01904 autoSelectExtCheckBox->setChecked (autoSelectExtChecked);
01905 }
01906 else
01907 {
01908
01909 autoSelectExtCheckBox->setText (i18n ("Automatically select filename e&xtension"));
01910 whatsThisExtension = i18n ("a suitable extension");
01911
01912 autoSelectExtCheckBox->setChecked (false);
01913 autoSelectExtCheckBox->setEnabled (false);
01914 }
01915
01916 const QString locationLabelText = stripUndisplayable (locationLabel->text());
01917 const QString filterLabelText = stripUndisplayable (filterLabel->text());
01918 autoSelectExtCheckBox->setWhatsThis( "<qt>" +
01919 i18n (
01920 "This option enables some convenient features for "
01921 "saving files with extensions:<br />"
01922 "<ol>"
01923 "<li>Any extension specified in the <b>%1</b> text "
01924 "area will be updated if you change the file type "
01925 "to save in.<br />"
01926 "<br /></li>"
01927 "<li>If no extension is specified in the <b>%2</b> "
01928 "text area when you click "
01929 "<b>Save</b>, %3 will be added to the end of the "
01930 "filename (if the filename does not already exist). "
01931 "This extension is based on the file type that you "
01932 "have chosen to save in.<br />"
01933 "<br />"
01934 "If you do not want KDE to supply an extension for the "
01935 "filename, you can either turn this option off or you "
01936 "can suppress it by adding a period (.) to the end of "
01937 "the filename (the period will be automatically "
01938 "removed)."
01939 "</li>"
01940 "</ol>"
01941 "If unsure, keep this option enabled as it makes your "
01942 "files more manageable."
01943 ,
01944 locationLabelText,
01945 locationLabelText,
01946 whatsThisExtension)
01947 + "</qt>"
01948 );
01949
01950 autoSelectExtCheckBox->show();
01951
01952
01953
01954 updateLocationEditExtension (lastExtension);
01955 }
01956
01957 else
01958 {
01959 autoSelectExtCheckBox->setChecked (false);
01960 autoSelectExtCheckBox->hide();
01961 }
01962 }
01963
01964
01965
01966
01967 void KFileWidgetPrivate::updateLocationEditExtension (const QString &lastExtension)
01968 {
01969 if (!autoSelectExtCheckBox->isChecked() || extension.isEmpty())
01970 return;
01971
01972 QString urlStr = locationEditCurrentText();
01973 if (urlStr.isEmpty())
01974 return;
01975
01976 KUrl url = getCompleteUrl(urlStr);
01977 kDebug (kfile_area) << "updateLocationEditExtension (" << url << ")";
01978
01979 const int fileNameOffset = urlStr.lastIndexOf ('/') + 1;
01980 QString fileName = urlStr.mid (fileNameOffset);
01981
01982 const int dot = fileName.lastIndexOf ('.');
01983 const int len = fileName.length();
01984 if (dot > 0 &&
01985
01986 dot != len - 1
01987 )
01988 {
01989
01990 KIO::UDSEntry t;
01991 if (KIO::NetAccess::stat (url, t, q->topLevelWidget()))
01992 {
01993 kDebug (kfile_area) << "\tfile exists";
01994
01995 if (t.isDir())
01996 {
01997 kDebug (kfile_area) << "\tisDir - won't alter extension";
01998 return;
01999 }
02000
02001
02002 }
02003
02004
02005
02006
02007
02008
02009
02010 if (lastExtension.length() && fileName.endsWith (lastExtension))
02011 fileName.truncate (len - lastExtension.length());
02012 else if (extension.length() && fileName.endsWith (extension))
02013 fileName.truncate (len - extension.length());
02014
02015 else
02016 fileName.truncate (dot);
02017
02018
02019 const QString newText = urlStr.left (fileNameOffset) + fileName + extension;
02020 if ( newText != locationEditCurrentText() )
02021 {
02022 locationEdit->setItemText(locationEdit->currentIndex(),urlStr.left (fileNameOffset) + fileName + extension);
02023 locationEdit->lineEdit()->setModified (true);
02024 }
02025 }
02026 }
02027
02028
02029
02030 void KFileWidgetPrivate::updateFilter()
02031 {
02032 if ((operationMode == KFileWidget::Saving) && (ops->mode() & KFile::File) ) {
02033 const QString urlStr = locationEditCurrentText();
02034 if (urlStr.isEmpty())
02035 return;
02036
02037 KMimeType::Ptr mime = KMimeType::findByPath(urlStr, 0, true);
02038 if (mime && mime->name() != KMimeType::defaultMimeType()) {
02039 if (filterWidget->currentFilter() != mime->name() &&
02040 filterWidget->filters().indexOf(mime->name()) != -1)
02041 filterWidget->setCurrentFilter(mime->name());
02042 }
02043 }
02044 }
02045
02046
02047
02048
02049
02050 void KFileWidgetPrivate::updateSplitterSize()
02051 {
02052 if (!placesViewSplitter) {
02053 return;
02054 }
02055
02056 QList<int> sizes = placesViewSplitter->sizes();
02057 if (sizes.count() == 2) {
02058
02059 KConfigGroup configGroup( KGlobal::config(), ConfigGroup );
02060 const int speedbarWidth = speedBarWidth == -1 ? configGroup.readEntry( SpeedbarWidth, placesView->sizeHintForColumn(0) )
02061 : speedBarWidth;
02062 const int availableWidth = q->width();
02063 sizes[0] = speedbarWidth + 1;
02064 sizes[1] = availableWidth - speedbarWidth - 1;
02065 placesViewSplitter->setSizes( sizes );
02066 }
02067 }
02068
02069
02070 void KFileWidgetPrivate::appendExtension (KUrl &url)
02071 {
02072 if (!autoSelectExtCheckBox->isChecked() || extension.isEmpty())
02073 return;
02074
02075 QString fileName = url.fileName();
02076 if (fileName.isEmpty())
02077 return;
02078
02079 kDebug (kfile_area) << "appendExtension(" << url << ")";
02080
02081 const int len = fileName.length();
02082 const int dot = fileName.lastIndexOf ('.');
02083
02084 const bool suppressExtension = (dot == len - 1);
02085 const bool unspecifiedExtension = (dot <= 0);
02086
02087
02088 if (!(suppressExtension || unspecifiedExtension))
02089 return;
02090
02091
02092 KIO::UDSEntry t;
02093 if (KIO::NetAccess::stat (url, t, q->topLevelWidget()))
02094 {
02095 kDebug (kfile_area) << "\tfile exists - won't append extension";
02096 return;
02097 }
02098
02099
02100 if (suppressExtension)
02101 {
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112 kDebug (kfile_area) << "\tstrip trailing dot";
02113 url.setFileName (fileName.left (len - 1));
02114 }
02115
02116 else if (unspecifiedExtension)
02117 {
02118 kDebug (kfile_area) << "\tappending extension \'" << extension << "\'...";
02119 url.setFileName (fileName + extension);
02120 kDebug (kfile_area) << "\tsaving as \'" << url << "\'";
02121 }
02122 }
02123
02124
02125
02126 void KFileWidgetPrivate::addToRecentDocuments()
02127 {
02128 int m = ops->mode();
02129 int atmost = KRecentDocument::maximumItems();
02130
02131
02132 if ( m & KFile::LocalOnly ) {
02133 const QStringList files = q->selectedFiles();
02134 QStringList::ConstIterator it = files.begin();
02135 for ( ; it != files.end() && atmost > 0; ++it ) {
02136 KRecentDocument::add( *it );
02137 atmost--;
02138 }
02139 }
02140
02141 else {
02142 KUrl::List urls = q->selectedUrls();
02143 KUrl::List::ConstIterator it = urls.begin();
02144 for ( ; it != urls.end() && atmost > 0; ++it ) {
02145 if ( (*it).isValid() ) {
02146 KRecentDocument::add( *it );
02147 atmost--;
02148 }
02149 }
02150 }
02151 }
02152
02153 KUrlComboBox* KFileWidget::locationEdit() const
02154 {
02155 return d->locationEdit;
02156 }
02157
02158 KFileFilterCombo* KFileWidget::filterWidget() const
02159 {
02160 return d->filterWidget;
02161 }
02162
02163 KActionCollection * KFileWidget::actionCollection() const
02164 {
02165 return d->ops->actionCollection();
02166 }
02167
02168 void KFileWidgetPrivate::_k_toggleSpeedbar( bool show )
02169 {
02170 if ( show )
02171 {
02172 if ( !placesView )
02173 initSpeedbar();
02174
02175 placesView->show();
02176
02177
02178 KUrl homeURL;
02179 homeURL.setPath( QDir::homePath() );
02180 KFilePlacesModel *model = static_cast<KFilePlacesModel*>(placesView->model());
02181 for ( int rowIndex = 0 ; rowIndex < placesView->model()->rowCount() ; rowIndex++ )
02182 {
02183 QModelIndex index = model->index(rowIndex, 0);
02184 KUrl url = model->url(index);
02185
02186 if ( homeURL.equals( url, KUrl::CompareWithoutTrailingSlash ) ) {
02187 toolbar->removeAction( ops->actionCollection()->action( "home" ) );
02188 break;
02189 }
02190 }
02191 }
02192 else
02193 {
02194 if (placesView)
02195 placesView->hide();
02196
02197 QAction* homeAction = ops->actionCollection()->action( "home" );
02198 QAction* reloadAction = ops->actionCollection()->action( "reload" );
02199 if ( !toolbar->actions().contains(homeAction) )
02200 toolbar->insertAction( reloadAction, homeAction );
02201 }
02202
02203 static_cast<KToggleAction *>(q->actionCollection()->action("toggleSpeedbar"))->setChecked( show );
02204 }
02205
02206 void KFileWidgetPrivate::_k_toggleBookmarks(bool show)
02207 {
02208 if (show)
02209 {
02210 if (bookmarkHandler)
02211 {
02212 return;
02213 }
02214
02215 bookmarkHandler = new KFileBookmarkHandler( q );
02216 q->connect( bookmarkHandler, SIGNAL( openUrl( const QString& )),
02217 SLOT( _k_enterUrl( const QString& )));
02218
02219 bookmarkButton = new KActionMenu(KIcon("bookmarks"),i18n("Bookmarks"), q);
02220 bookmarkButton->setDelayed(false);
02221 q->actionCollection()->addAction("bookmark", bookmarkButton);
02222 bookmarkButton->setMenu(bookmarkHandler->menu());
02223 bookmarkButton->setWhatsThis(i18n("<qt>This button allows you to bookmark specific locations. "
02224 "Click on this button to open the bookmark menu where you may add, "
02225 "edit or select a bookmark.<br /><br />"
02226 "These bookmarks are specific to the file dialog, but otherwise operate "
02227 "like bookmarks elsewhere in KDE.</qt>"));
02228 toolbar->addAction(bookmarkButton);
02229 }
02230 else if (bookmarkHandler)
02231 {
02232 delete bookmarkHandler;
02233 bookmarkHandler = 0;
02234 delete bookmarkButton;
02235 bookmarkButton = 0;
02236 }
02237
02238 static_cast<KToggleAction *>(q->actionCollection()->action("toggleBookmarks"))->setChecked( show );
02239 }
02240
02241
02242 KUrl KFileWidget::getStartUrl( const KUrl& startDir,
02243 QString& recentDirClass )
02244 {
02245 recentDirClass.clear();
02246 KUrl ret;
02247
02248 bool useDefaultStartDir = startDir.isEmpty();
02249 if ( !useDefaultStartDir )
02250 {
02251 if (startDir.protocol() == "kfiledialog")
02252 {
02253 if ( startDir.query() == "?global" )
02254 recentDirClass = QString( "::%1" ).arg( startDir.path().mid( 1 ) );
02255 else
02256 recentDirClass = QString( ":%1" ).arg( startDir.path().mid( 1 ) );
02257
02258 ret = KUrl( KRecentDirs::dir(recentDirClass) );
02259 }
02260 else
02261 {
02262 ret = startDir;
02263
02264 if ( !KProtocolManager::supportsListing( ret ) )
02265 useDefaultStartDir = true;
02266 }
02267 }
02268
02269 if ( useDefaultStartDir )
02270 {
02271 if (lastDirectory->isEmpty()) {
02272 lastDirectory->setPath(KGlobalSettings::documentPath());
02273 KUrl home;
02274 home.setPath( QDir::homePath() );
02275
02276
02277
02278
02279 if ( lastDirectory->path(KUrl::AddTrailingSlash) == home.path(KUrl::AddTrailingSlash) ||
02280 QDir::currentPath() != QDir::homePath() ||
02281 !QDir(lastDirectory->path(KUrl::AddTrailingSlash)).exists() )
02282 lastDirectory->setPath(QDir::currentPath());
02283 }
02284 ret = *lastDirectory;
02285 }
02286
02287 return ret;
02288 }
02289
02290 void KFileWidget::setStartDir( const KUrl& directory )
02291 {
02292 if ( directory.isValid() )
02293 *lastDirectory = directory;
02294 }
02295
02296 void KFileWidgetPrivate::setNonExtSelection()
02297 {
02298
02299 QString filename = locationEditCurrentText();
02300 QString extension = KMimeType::extractKnownExtension( filename );
02301
02302 if ( !extension.isEmpty() )
02303 locationEdit->lineEdit()->setSelection( 0, filename.length() - extension.length() - 1 );
02304 else
02305 {
02306 int lastDot = filename.lastIndexOf( '.' );
02307 if ( lastDot > 0 )
02308 locationEdit->lineEdit()->setSelection( 0, lastDot );
02309 }
02310 }
02311
02312 KToolBar * KFileWidget::toolBar() const
02313 {
02314 return d->toolbar;
02315 }
02316
02317 void KFileWidget::setCustomWidget(QWidget* widget)
02318 {
02319 delete d->bottomCustomWidget;
02320 d->bottomCustomWidget = widget;
02321
02322
02323
02324
02325 d->bottomCustomWidget->setParent( this );
02326
02327 d->vbox->addWidget( d->bottomCustomWidget );
02328
02329
02330
02331
02332
02333
02334
02335 setTabOrder(d->cancelButton, d->bottomCustomWidget);
02336 setTabOrder(d->bottomCustomWidget, d->urlNavigator);
02337 }
02338
02339 void KFileWidget::setCustomWidget(const QString& text, QWidget* widget)
02340 {
02341 delete d->labeledCustomWidget;
02342 d->labeledCustomWidget = widget;
02343
02344 QLabel* label = new QLabel(text, this);
02345 d->lafBox->addWidget(label, 2, 0, Qt::AlignVCenter);
02346 d->lafBox->addWidget(widget, 2, 1, Qt::AlignVCenter);
02347 }
02348
02349 void KFileWidget::virtual_hook( int id, void* data )
02350 {
02351 Q_UNUSED(id);
02352 Q_UNUSED(data);
02353 }
02354
02355 QString KFileWidgetPrivate::locationEditCurrentText() const
02356 {
02357 return QDir::fromNativeSeparators(locationEdit->currentText().trimmed());
02358 }
02359
02360 #include "kfilewidget.moc"