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