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