kio Library API Documentation

kdiroperator.cpp

00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1999,2000 Stephan Kulow <coolo@kde.org> 00003 1999,2000,2001,2002,2003 Carsten Pfeiffer <pfeiffer@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 00021 #include <unistd.h> 00022 00023 #include <qdir.h> 00024 #include <qapplication.h> 00025 #include <qdialog.h> 00026 #include <qlabel.h> 00027 #include <qlayout.h> 00028 #include <qpushbutton.h> 00029 #include <qpopupmenu.h> 00030 #include <qregexp.h> 00031 #include <qtimer.h> 00032 #include <qvbox.h> 00033 00034 #include <kaction.h> 00035 #include <kapplication.h> 00036 #include <kdebug.h> 00037 #include <kdialog.h> 00038 #include <kdialogbase.h> 00039 #include <kdirlister.h> 00040 #include <kinputdialog.h> 00041 #include <klocale.h> 00042 #include <kmessagebox.h> 00043 #include <kpopupmenu.h> 00044 #include <kprogress.h> 00045 #include <kstdaction.h> 00046 #include <kio/job.h> 00047 #include <kio/jobclasses.h> 00048 #include <kio/netaccess.h> 00049 #include <kio/previewjob.h> 00050 #include <kio/renamedlg.h> 00051 #include <kpropertiesdialog.h> 00052 #include <kservicetypefactory.h> 00053 #include <kstdaccel.h> 00054 #include <kde_file.h> 00055 00056 #include "config-kfile.h" 00057 #include "kcombiview.h" 00058 #include "kdiroperator.h" 00059 #include "kfiledetailview.h" 00060 #include "kfileiconview.h" 00061 #include "kfilepreview.h" 00062 #include "kfileview.h" 00063 #include "kfileitem.h" 00064 #include "kfilemetapreview.h" 00065 00066 00067 template class QPtrStack<KURL>; 00068 template class QDict<KFileItem>; 00069 00070 00071 class KDirOperator::KDirOperatorPrivate 00072 { 00073 public: 00074 KDirOperatorPrivate() { 00075 onlyDoubleClickSelectsFiles = false; 00076 progressDelayTimer = 0L; 00077 dirHighlighting = false; 00078 config = 0L; 00079 dropOptions = 0; 00080 } 00081 00082 ~KDirOperatorPrivate() { 00083 delete progressDelayTimer; 00084 } 00085 00086 bool dirHighlighting; 00087 QString lastURL; // used for highlighting a directory on cdUp 00088 bool onlyDoubleClickSelectsFiles; 00089 QTimer *progressDelayTimer; 00090 KActionSeparator *viewActionSeparator; 00091 int dropOptions; 00092 00093 KConfig *config; 00094 QString configGroup; 00095 }; 00096 00097 KDirOperator::KDirOperator(const KURL& _url, 00098 QWidget *parent, const char* _name) 00099 : QWidget(parent, _name), 00100 dir(0), 00101 m_fileView(0), 00102 progress(0) 00103 { 00104 myPreview = 0L; 00105 myMode = KFile::File; 00106 m_viewKind = KFile::Simple; 00107 mySorting = static_cast<QDir::SortSpec>(QDir::Name | QDir::DirsFirst); 00108 d = new KDirOperatorPrivate; 00109 00110 if (_url.isEmpty()) { // no dir specified -> current dir 00111 QString strPath = QDir::currentDirPath(); 00112 strPath.append('/'); 00113 currUrl = KURL(); 00114 currUrl.setProtocol(QString::fromLatin1("file")); 00115 currUrl.setPath(strPath); 00116 } 00117 else { 00118 currUrl = _url; 00119 if ( currUrl.protocol().isEmpty() ) 00120 currUrl.setProtocol(QString::fromLatin1("file")); 00121 00122 currUrl.addPath("/"); // make sure we have a trailing slash! 00123 } 00124 00125 setDirLister( new KDirLister( true ) ); 00126 00127 connect(&myCompletion, SIGNAL(match(const QString&)), 00128 SLOT(slotCompletionMatch(const QString&))); 00129 00130 progress = new KProgress(this, "progress"); 00131 progress->adjustSize(); 00132 progress->move(2, height() - progress->height() -2); 00133 00134 d->progressDelayTimer = new QTimer( this, "progress delay timer" ); 00135 connect( d->progressDelayTimer, SIGNAL( timeout() ), 00136 SLOT( slotShowProgress() )); 00137 00138 myCompleteListDirty = false; 00139 00140 backStack.setAutoDelete( true ); 00141 forwardStack.setAutoDelete( true ); 00142 00143 // action stuff 00144 setupActions(); 00145 setupMenu(); 00146 00147 setFocusPolicy(QWidget::WheelFocus); 00148 } 00149 00150 KDirOperator::~KDirOperator() 00151 { 00152 resetCursor(); 00153 if ( m_fileView ) 00154 { 00155 if ( d->config ) 00156 m_fileView->writeConfig( d->config, d->configGroup ); 00157 00158 delete m_fileView; 00159 m_fileView = 0L; 00160 } 00161 00162 delete myPreview; 00163 delete dir; 00164 delete d; 00165 } 00166 00167 00168 void KDirOperator::setSorting( QDir::SortSpec spec ) 00169 { 00170 if ( m_fileView ) 00171 m_fileView->setSorting( spec ); 00172 mySorting = spec; 00173 updateSortActions(); 00174 } 00175 00176 void KDirOperator::resetCursor() 00177 { 00178 QApplication::restoreOverrideCursor(); 00179 progress->hide(); 00180 } 00181 00182 void KDirOperator::insertViewDependentActions() 00183 { 00184 // If we have a new view actionCollection(), insert its actions 00185 // into viewActionMenu. 00186 00187 if( !m_fileView ) 00188 return; 00189 00190 if ( (viewActionMenu->popupMenu()->count() == 0) || // Not yet initialized or... 00191 (viewActionCollection != m_fileView->actionCollection()) ) // ...changed since. 00192 { 00193 if (viewActionCollection) 00194 { 00195 disconnect( viewActionCollection, SIGNAL( inserted( KAction * )), 00196 this, SLOT( slotViewActionAdded( KAction * ))); 00197 disconnect( viewActionCollection, SIGNAL( removed( KAction * )), 00198 this, SLOT( slotViewActionRemoved( KAction * ))); 00199 } 00200 00201 viewActionMenu->popupMenu()->clear(); 00202 // viewActionMenu->insert( shortAction ); 00203 // viewActionMenu->insert( detailedAction ); 00204 // viewActionMenu->insert( actionSeparator ); 00205 viewActionMenu->insert( myActionCollection->action( "short view" ) ); 00206 viewActionMenu->insert( myActionCollection->action( "detailed view" ) ); 00207 viewActionMenu->insert( actionSeparator ); 00208 viewActionMenu->insert( showHiddenAction ); 00209 // viewActionMenu->insert( myActionCollection->action( "single" )); 00210 viewActionMenu->insert( separateDirsAction ); 00211 // Warning: adjust slotViewActionAdded() and slotViewActionRemoved() 00212 // when you add/remove actions here! 00213 00214 viewActionCollection = m_fileView->actionCollection(); 00215 if (!viewActionCollection) 00216 return; 00217 00218 if ( !viewActionCollection->isEmpty() ) 00219 { 00220 viewActionMenu->insert( d->viewActionSeparator ); 00221 00222 // first insert the normal actions, then the grouped ones 00223 QStringList groups = viewActionCollection->groups(); 00224 groups.prepend( QString::null ); // actions without group 00225 QStringList::ConstIterator git = groups.begin(); 00226 KActionPtrList list; 00227 KAction *sep = actionCollection()->action("separator"); 00228 for ( ; git != groups.end(); ++git ) 00229 { 00230 if ( git != groups.begin() ) 00231 viewActionMenu->insert( sep ); 00232 00233 list = viewActionCollection->actions( *git ); 00234 KActionPtrList::ConstIterator it = list.begin(); 00235 for ( ; it != list.end(); ++it ) 00236 viewActionMenu->insert( *it ); 00237 } 00238 } 00239 00240 connect( viewActionCollection, SIGNAL( inserted( KAction * )), 00241 SLOT( slotViewActionAdded( KAction * ))); 00242 connect( viewActionCollection, SIGNAL( removed( KAction * )), 00243 SLOT( slotViewActionRemoved( KAction * ))); 00244 } 00245 } 00246 00247 void KDirOperator::activatedMenu( const KFileItem *, const QPoint& pos ) 00248 { 00249 setupMenu(); 00250 updateSelectionDependentActions(); 00251 00252 actionMenu->popup( pos ); 00253 } 00254 00255 void KDirOperator::updateSelectionDependentActions() 00256 { 00257 bool hasSelection = m_fileView && m_fileView->selectedItems() && 00258 !m_fileView->selectedItems()->isEmpty(); 00259 myActionCollection->action( "trash" )->setEnabled( hasSelection ); 00260 myActionCollection->action( "delete" )->setEnabled( hasSelection ); 00261 myActionCollection->action( "properties" )->setEnabled( hasSelection ); 00262 } 00263 00264 void KDirOperator::setPreviewWidget(const QWidget *w) 00265 { 00266 if(w != 0L) 00267 m_viewKind = (m_viewKind | KFile::PreviewContents); 00268 else 00269 m_viewKind = (m_viewKind & ~KFile::PreviewContents); 00270 00271 delete myPreview; 00272 myPreview = w; 00273 00274 KToggleAction *preview = static_cast<KToggleAction*>(myActionCollection->action("preview")); 00275 preview->setEnabled( w != 0L ); 00276 preview->setChecked( w != 0L ); 00277 setView( static_cast<KFile::FileView>(m_viewKind) ); 00278 } 00279 00280 int KDirOperator::numDirs() const 00281 { 00282 return m_fileView ? m_fileView->numDirs() : 0; 00283 } 00284 00285 int KDirOperator::numFiles() const 00286 { 00287 return m_fileView ? m_fileView->numFiles() : 0; 00288 } 00289 00290 void KDirOperator::slotDetailedView() 00291 { 00292 KFile::FileView view = static_cast<KFile::FileView>( (m_viewKind & ~KFile::Simple) | KFile::Detail ); 00293 setView( view ); 00294 } 00295 00296 void KDirOperator::slotSimpleView() 00297 { 00298 KFile::FileView view = static_cast<KFile::FileView>( (m_viewKind & ~KFile::Detail) | KFile::Simple ); 00299 setView( view ); 00300 } 00301 00302 void KDirOperator::slotToggleHidden( bool show ) 00303 { 00304 dir->setShowingDotFiles( show ); 00305 updateDir(); 00306 if ( m_fileView ) 00307 m_fileView->listingCompleted(); 00308 } 00309 00310 void KDirOperator::slotSeparateDirs() 00311 { 00312 if (separateDirsAction->isChecked()) 00313 { 00314 KFile::FileView view = static_cast<KFile::FileView>( m_viewKind | KFile::SeparateDirs ); 00315 setView( view ); 00316 } 00317 else 00318 { 00319 KFile::FileView view = static_cast<KFile::FileView>( m_viewKind & ~KFile::SeparateDirs ); 00320 setView( view ); 00321 } 00322 } 00323 00324 void KDirOperator::slotDefaultPreview() 00325 { 00326 m_viewKind = m_viewKind | KFile::PreviewContents; 00327 if ( !myPreview ) { 00328 myPreview = new KFileMetaPreview( this ); 00329 (static_cast<KToggleAction*>( myActionCollection->action("preview") ))->setChecked(true); 00330 } 00331 00332 setView( static_cast<KFile::FileView>(m_viewKind) ); 00333 } 00334 00335 void KDirOperator::slotSortByName() 00336 { 00337 int sorting = (m_fileView->sorting()) & ~QDir::SortByMask; 00338 m_fileView->setSorting( static_cast<QDir::SortSpec>( sorting | QDir::Name )); 00339 mySorting = m_fileView->sorting(); 00340 caseInsensitiveAction->setEnabled( true ); 00341 } 00342 00343 void KDirOperator::slotSortBySize() 00344 { 00345 int sorting = (m_fileView->sorting()) & ~QDir::SortByMask; 00346 m_fileView->setSorting( static_cast<QDir::SortSpec>( sorting | QDir::Size )); 00347 mySorting = m_fileView->sorting(); 00348 caseInsensitiveAction->setEnabled( false ); 00349 } 00350 00351 void KDirOperator::slotSortByDate() 00352 { 00353 int sorting = (m_fileView->sorting()) & ~QDir::SortByMask; 00354 m_fileView->setSorting( static_cast<QDir::SortSpec>( sorting | QDir::Time )); 00355 mySorting = m_fileView->sorting(); 00356 caseInsensitiveAction->setEnabled( false ); 00357 } 00358 00359 void KDirOperator::slotSortReversed() 00360 { 00361 if ( m_fileView ) 00362 m_fileView->sortReversed(); 00363 } 00364 00365 void KDirOperator::slotToggleDirsFirst() 00366 { 00367 QDir::SortSpec sorting = m_fileView->sorting(); 00368 if ( !KFile::isSortDirsFirst( sorting ) ) 00369 m_fileView->setSorting( static_cast<QDir::SortSpec>( sorting | QDir::DirsFirst )); 00370 else 00371 m_fileView->setSorting( static_cast<QDir::SortSpec>( sorting & ~QDir::DirsFirst)); 00372 mySorting = m_fileView->sorting(); 00373 } 00374 00375 void KDirOperator::slotToggleIgnoreCase() 00376 { 00377 QDir::SortSpec sorting = m_fileView->sorting(); 00378 if ( !KFile::isSortCaseInsensitive( sorting ) ) 00379 m_fileView->setSorting( static_cast<QDir::SortSpec>( sorting | QDir::IgnoreCase )); 00380 else 00381 m_fileView->setSorting( static_cast<QDir::SortSpec>( sorting & ~QDir::IgnoreCase)); 00382 mySorting = m_fileView->sorting(); 00383 } 00384 00385 void KDirOperator::mkdir() 00386 { 00387 bool ok; 00388 QString where = url().pathOrURL(); 00389 QString name = i18n( "New Folder" ); 00390 if ( url().isLocalFile() && QFileInfo( url().path(+1) + name ).exists() ) 00391 name = KIO::RenameDlg::suggestName( url(), name ); 00392 00393 QString dir = KInputDialog::getText( i18n( "New Folder" ), 00394 i18n( "Create new folder in:\n%1" ).arg( where ), 00395 name, &ok, this); 00396 if (ok) 00397 mkdir( KIO::encodeFileName( dir ), true ); 00398 } 00399 00400 bool KDirOperator::mkdir( const QString& directory, bool enterDirectory ) 00401 { 00402 // Creates "directory", relative to the current directory (currUrl). 00403 // The given path may contain any number directories, existant or not. 00404 // They will all be created, if possible. 00405 00406 bool writeOk = false; 00407 bool exists = false; 00408 KURL url( currUrl ); 00409 00410 QStringList dirs = QStringList::split( QDir::separator(), directory ); 00411 QStringList::ConstIterator it = dirs.begin(); 00412 00413 for ( ; it != dirs.end(); ++it ) 00414 { 00415 url.addPath( *it ); 00416 exists = KIO::NetAccess::exists( url, false, 0 ); 00417 writeOk = !exists && KIO::NetAccess::mkdir( url, topLevelWidget() ); 00418 } 00419 00420 if ( exists ) // url was already existant 00421 { 00422 KMessageBox::sorry(viewWidget(), i18n("A file or folder named %1 already exists.").arg(url.pathOrURL())); 00423 enterDirectory = false; 00424 } 00425 else if ( !writeOk ) { 00426 KMessageBox::sorry(viewWidget(), i18n("You do not have permission to " 00427 "create that folder." )); 00428 } 00429 else if ( enterDirectory ) { 00430 setURL( url, true ); 00431 } 00432 00433 return writeOk; 00434 } 00435 00436 KIO::DeleteJob * KDirOperator::del( const KFileItemList& items, 00437 bool ask, bool showProgress ) 00438 { 00439 return del( items, this, ask, showProgress ); 00440 } 00441 00442 KIO::DeleteJob * KDirOperator::del( const KFileItemList& items, 00443 QWidget *parent, 00444 bool ask, bool showProgress ) 00445 { 00446 if ( items.isEmpty() ) { 00447 KMessageBox::information( parent, 00448 i18n("You did not select a file to delete."), 00449 i18n("Nothing to Delete") ); 00450 return 0L; 00451 } 00452 00453 KURL::List urls; 00454 QStringList files; 00455 KFileItemListIterator it( items ); 00456 00457 for ( ; it.current(); ++it ) { 00458 KURL url = (*it)->url(); 00459 urls.append( url ); 00460 if ( url.isLocalFile() ) 00461 files.append( url.path() ); 00462 else 00463 files.append( url.prettyURL() ); 00464 } 00465 00466 bool doIt = !ask; 00467 if ( ask ) { 00468 int ret; 00469 if ( items.count() == 1 ) { 00470 ret = KMessageBox::warningContinueCancel( parent, 00471 i18n( "<qt>Do you really want to delete\n <b>'%1'</b>?</qt>" ) 00472 .arg( files.first() ), 00473 i18n("Delete File"), 00474 KStdGuiItem::del(), "AskForDelete" ); 00475 } 00476 else 00477 ret = KMessageBox::warningContinueCancelList( parent, 00478 i18n("translators: not called for n == 1", "Do you really want to delete these %n items?", items.count() ), 00479 files, 00480 i18n("Delete Files"), 00481 KStdGuiItem::del(), "AskForDelete" ); 00482 doIt = (ret == KMessageBox::Continue); 00483 } 00484 00485 if ( doIt ) { 00486 KIO::DeleteJob *job = KIO::del( urls, false, showProgress ); 00487 job->setWindow (topLevelWidget()); 00488 job->setAutoErrorHandlingEnabled( true, parent ); 00489 return job; 00490 } 00491 00492 return 0L; 00493 } 00494 00495 void KDirOperator::deleteSelected() 00496 { 00497 if ( !m_fileView ) 00498 return; 00499 00500 const KFileItemList *list = m_fileView->selectedItems(); 00501 if ( list ) 00502 del( *list ); 00503 } 00504 00505 KIO::CopyJob * KDirOperator::trash( const KFileItemList& items, 00506 QWidget *parent, 00507 bool ask, bool showProgress ) 00508 { 00509 if ( items.isEmpty() ) { 00510 KMessageBox::information( parent, 00511 i18n("You did not select a file to trash."), 00512 i18n("Nothing to Trash") ); 00513 return 0L; 00514 } 00515 00516 KURL::List urls; 00517 QStringList files; 00518 KFileItemListIterator it( items ); 00519 00520 for ( ; it.current(); ++it ) { 00521 KURL url = (*it)->url(); 00522 urls.append( url ); 00523 if ( url.isLocalFile() ) 00524 files.append( url.path() ); 00525 else 00526 files.append( url.prettyURL() ); 00527 } 00528 00529 bool doIt = !ask; 00530 if ( ask ) { 00531 int ret; 00532 if ( items.count() == 1 ) { 00533 ret = KMessageBox::warningContinueCancel( parent, 00534 i18n( "<qt>Do you really want to trash\n <b>'%1'</b>?</qt>" ) 00535 .arg( files.first() ), 00536 i18n("Trash File"), 00537 KGuiItem("&Trash","edittrash"), "AskForTrash" ); 00538 } 00539 else 00540 ret = KMessageBox::warningContinueCancelList( parent, 00541 i18n("translators: not called for n == 1", "Do you really want to trash these %n items?", items.count() ), 00542 files, 00543 i18n("Trash Files"), 00544 KGuiItem("&Trash","edittrash"), "AskForTrash" ); 00545 doIt = (ret == KMessageBox::Continue); 00546 } 00547 00548 if ( doIt ) { 00549 KIO::CopyJob *job = KIO::trash( urls, showProgress ); 00550 job->setWindow (topLevelWidget()); 00551 job->setAutoErrorHandlingEnabled( true, parent ); 00552 return job; 00553 } 00554 00555 return 0L; 00556 } 00557 00558 void KDirOperator::trashSelected(KAction::ActivationReason reason, Qt::ButtonState state) 00559 { 00560 if ( !m_fileView ) 00561 return; 00562 00563 if ( reason == KAction::PopupMenuActivation && ( state & Qt::ShiftButton ) ) { 00564 deleteSelected(); 00565 return; 00566 } 00567 00568 const KFileItemList *list = m_fileView->selectedItems(); 00569 if ( list ) 00570 trash( *list, this ); 00571 } 00572 00573 void KDirOperator::close() 00574 { 00575 resetCursor(); 00576 pendingMimeTypes.clear(); 00577 myCompletion.clear(); 00578 myDirCompletion.clear(); 00579 myCompleteListDirty = true; 00580 dir->stop(); 00581 } 00582 00583 void KDirOperator::checkPath(const QString &, bool /*takeFiles*/) // SLOT 00584 { 00585 #if 0 00586 // copy the argument in a temporary string 00587 QString text = _txt; 00588 // it's unlikely to happen, that at the beginning are spaces, but 00589 // for the end, it happens quite often, I guess. 00590 text = text.stripWhiteSpace(); 00591 // if the argument is no URL (the check is quite fragil) and it's 00592 // no absolute path, we add the current directory to get a correct url 00593 if (text.find(':') < 0 && text[0] != '/') 00594 text.insert(0, currUrl); 00595 00596 // in case we have a selection defined and someone patched the file- 00597 // name, we check, if the end of the new name is changed. 00598 if (!selection.isNull()) { 00599 int position = text.findRev('/'); 00600 ASSERT(position >= 0); // we already inserted the current dir in case 00601 QString filename = text.mid(position + 1, text.length()); 00602 if (filename != selection) 00603 selection = QString::null; 00604 } 00605 00606 KURL u(text); // I have to take care of entered URLs 00607 bool filenameEntered = false; 00608 00609 if (u.isLocalFile()) { 00610 // the empty path is kind of a hack 00611 KFileItem i("", u.path()); 00612 if (i.isDir()) 00613 setURL(text, true); 00614 else { 00615 if (takeFiles) 00616 if (acceptOnlyExisting && !i.isFile()) 00617 warning("you entered an invalid URL"); 00618 else 00619 filenameEntered = true; 00620 } 00621 } else 00622 setURL(text, true); 00623 00624 if (filenameEntered) { 00625 filename_ = u.url(); 00626 emit fileSelected(filename_); 00627 00628 QApplication::restoreOverrideCursor(); 00629 00630 accept(); 00631 } 00632 #endif 00633 kdDebug(kfile_area) << "TODO KDirOperator::checkPath()" << endl; 00634 } 00635 00636 void KDirOperator::setURL(const KURL& _newurl, bool clearforward) 00637 { 00638 KURL newurl; 00639 00640 if ( !_newurl.isValid() ) 00641 newurl.setPath( QDir::homeDirPath() ); 00642 else 00643 newurl = _newurl; 00644 00645 QString pathstr = newurl.path(+1); 00646 newurl.setPath(pathstr); 00647 00648 // already set 00649 if ( newurl.equals( currUrl, true ) ) 00650 return; 00651 00652 if ( !isReadable( newurl ) ) { 00653 // maybe newurl is a file? check its parent directory 00654 newurl.cd(QString::fromLatin1("..")); 00655 if ( !isReadable( newurl ) ) { 00656 resetCursor(); 00657 KMessageBox::error(viewWidget(), 00658 i18n("The specified folder does not exist " 00659 "or was not readable.")); 00660 return; 00661 } 00662 } 00663 00664 if (clearforward) { 00665 // autodelete should remove this one 00666 backStack.push(new KURL(currUrl)); 00667 forwardStack.clear(); 00668 } 00669 00670 d->lastURL = currUrl.url(-1); 00671 currUrl = newurl; 00672 00673 pathChanged(); 00674 emit urlEntered(newurl); 00675 00676 // enable/disable actions 00677 forwardAction->setEnabled( !forwardStack.isEmpty() ); 00678 backAction->setEnabled( !backStack.isEmpty() ); 00679 upAction->setEnabled( !isRoot() ); 00680 00681 dir->openURL( newurl ); 00682 } 00683 00684 void KDirOperator::updateDir() 00685 { 00686 dir->emitChanges(); 00687 if ( m_fileView ) 00688 m_fileView->listingCompleted(); 00689 } 00690 00691 void KDirOperator::rereadDir() 00692 { 00693 pathChanged(); 00694 dir->openURL( currUrl, false, true ); 00695 } 00696 00697 // Protected 00698 void KDirOperator::pathChanged() 00699 { 00700 if (!m_fileView) 00701 return; 00702 00703 pendingMimeTypes.clear(); 00704 m_fileView->clear(); 00705 myCompletion.clear(); 00706 myDirCompletion.clear(); 00707 00708 // it may be, that we weren't ready at this time 00709 QApplication::restoreOverrideCursor(); 00710 00711 // when KIO::Job emits finished, the slot will restore the cursor 00712 QApplication::setOverrideCursor( waitCursor ); 00713 00714 if ( !isReadable( currUrl )) { 00715 KMessageBox::error(viewWidget(), 00716 i18n("The specified folder does not exist " 00717 "or was not readable.")); 00718 if (backStack.isEmpty()) 00719 home(); 00720 else 00721 back(); 00722 } 00723 } 00724 00725 void KDirOperator::slotRedirected( const KURL& newURL ) 00726 { 00727 currUrl = newURL; 00728 pendingMimeTypes.clear(); 00729 myCompletion.clear(); 00730 myDirCompletion.clear(); 00731 myCompleteListDirty = true; 00732 emit urlEntered( newURL ); 00733 } 00734 00735 // Code pinched from kfm then hacked 00736 void KDirOperator::back() 00737 { 00738 if ( backStack.isEmpty() ) 00739 return; 00740 00741 forwardStack.push( new KURL(currUrl) ); 00742 00743 KURL *s = backStack.pop(); 00744 00745 setURL(*s, false); 00746 delete s; 00747 } 00748 00749 // Code pinched from kfm then hacked 00750 void KDirOperator::forward() 00751 { 00752 if ( forwardStack.isEmpty() ) 00753 return; 00754 00755 backStack.push(new KURL(currUrl)); 00756 00757 KURL *s = forwardStack.pop(); 00758 setURL(*s, false); 00759 delete s; 00760 } 00761 00762 KURL KDirOperator::url() const 00763 { 00764 return currUrl; 00765 } 00766 00767 void KDirOperator::cdUp() 00768 { 00769 KURL tmp( currUrl ); 00770 tmp.cd(QString::fromLatin1("..")); 00771 setURL(tmp, true); 00772 } 00773 00774 void KDirOperator::home() 00775 { 00776 KURL u; 00777 u.setPath( QDir::homeDirPath() ); 00778 setURL(u, true); 00779 } 00780 00781 void KDirOperator::clearFilter() 00782 { 00783 dir->setNameFilter( QString::null ); 00784 dir->clearMimeFilter(); 00785 checkPreviewSupport(); 00786 } 00787 00788 void KDirOperator::setNameFilter(const QString& filter) 00789 { 00790 dir->setNameFilter(filter); 00791 checkPreviewSupport(); 00792 } 00793 00794 void KDirOperator::setMimeFilter( const QStringList& mimetypes ) 00795 { 00796 dir->setMimeFilter( mimetypes ); 00797 checkPreviewSupport(); 00798 } 00799 00800 bool KDirOperator::checkPreviewSupport() 00801 { 00802 KToggleAction *previewAction = static_cast<KToggleAction*>( myActionCollection->action( "preview" )); 00803 00804 bool hasPreviewSupport = false; 00805 KConfig *kc = KGlobal::config(); 00806 KConfigGroupSaver cs( kc, ConfigGroup ); 00807 if ( kc->readBoolEntry( "Show Default Preview", true ) ) 00808 hasPreviewSupport = checkPreviewInternal(); 00809 00810 previewAction->setEnabled( hasPreviewSupport ); 00811 return hasPreviewSupport; 00812 } 00813 00814 bool KDirOperator::checkPreviewInternal() const 00815 { 00816 QStringList supported = KIO::PreviewJob::supportedMimeTypes(); 00817 // no preview support for directories? 00818 if ( dirOnlyMode() && supported.findIndex( "inode/directory" ) == -1 ) 00819 return false; 00820 00821 QStringList mimeTypes = dir->mimeFilters(); 00822 QStringList nameFilter = QStringList::split( " ", dir->nameFilter() ); 00823 00824 if ( mimeTypes.isEmpty() && nameFilter.isEmpty() && !supported.isEmpty() ) 00825 return true; 00826 else { 00827 QRegExp r; 00828 r.setWildcard( true ); // the "mimetype" can be "image/*" 00829 00830 if ( !mimeTypes.isEmpty() ) { 00831 QStringList::Iterator it = supported.begin(); 00832 00833 for ( ; it != supported.end(); ++it ) { 00834 r.setPattern( *it ); 00835 00836 QStringList result = mimeTypes.grep( r ); 00837 if ( !result.isEmpty() ) { // matches! -> we want previews 00838 return true; 00839 } 00840 } 00841 } 00842 00843 if ( !nameFilter.isEmpty() ) { 00844 // find the mimetypes of all the filter-patterns and 00845 KServiceTypeFactory *fac = KServiceTypeFactory::self(); 00846 QStringList::Iterator it1 = nameFilter.begin(); 00847 for ( ; it1 != nameFilter.end(); ++it1 ) { 00848 if ( (*it1) == "*" ) { 00849 return true; 00850 } 00851 00852 KMimeType *mt = fac->findFromPattern( *it1 ); 00853 if ( !mt ) 00854 continue; 00855 QString mime = mt->name(); 00856 delete mt; 00857 00858 // the "mimetypes" we get from the PreviewJob can be "image/*" 00859 // so we need to check in wildcard mode 00860 QStringList::Iterator it2 = supported.begin(); 00861 for ( ; it2 != supported.end(); ++it2 ) { 00862 r.setPattern( *it2 ); 00863 if ( r.search( mime ) != -1 ) { 00864 return true; 00865 } 00866 } 00867 } 00868 } 00869 } 00870 00871 return false; 00872 } 00873 00874 KFileView* KDirOperator::createView( QWidget* parent, KFile::FileView view ) 00875 { 00876 KFileView* new_view = 0L; 00877 bool separateDirs = KFile::isSeparateDirs( view ); 00878 bool preview = ( KFile::isPreviewInfo(view) || KFile::isPreviewContents( view ) ); 00879 00880 if ( separateDirs || preview ) { 00881 KCombiView *combi = 0L; 00882 if (separateDirs) 00883 { 00884 combi = new KCombiView( parent, "combi view" ); 00885 combi->setOnlyDoubleClickSelectsFiles(d->onlyDoubleClickSelectsFiles); 00886 } 00887 00888 KFileView* v = 0L; 00889 if ( KFile::isSimpleView( view ) ) 00890 v = createView( combi, KFile::Simple ); 00891 else 00892 v = createView( combi, KFile::Detail ); 00893 00894 v->setOnlyDoubleClickSelectsFiles(d->onlyDoubleClickSelectsFiles); 00895 00896 if (combi) 00897 combi->setRight( v ); 00898 00899 if (preview) 00900 { 00901 KFilePreview* pView = new KFilePreview( combi ? combi : v, parent, "preview" ); 00902 pView->setOnlyDoubleClickSelectsFiles(d->onlyDoubleClickSelectsFiles); 00903 new_view = pView; 00904 } 00905 else 00906 new_view = combi; 00907 } 00908 else if ( KFile::isDetailView( view ) && !preview ) { 00909 new_view = new KFileDetailView( parent, "detail view"); 00910 new_view->setViewName( i18n("Detailed View") ); 00911 } 00912 else /* if ( KFile::isSimpleView( view ) && !preview ) */ { 00913 KFileIconView *iconView = new KFileIconView( parent, "simple view"); 00914 new_view = iconView; 00915 new_view->setViewName( i18n("Short View") ); 00916 } 00917 00918 new_view->widget()->setAcceptDrops(acceptDrops()); 00919 return new_view; 00920 } 00921 00922 void KDirOperator::setAcceptDrops(bool b) 00923 { 00924 if (m_fileView) 00925 m_fileView->widget()->setAcceptDrops(b); 00926 QWidget::setAcceptDrops(b); 00927 } 00928 00929 void KDirOperator::setDropOptions(int options) 00930 { 00931 d->dropOptions = options; 00932 if (m_fileView) 00933 m_fileView->setDropOptions(options); 00934 } 00935 00936 void KDirOperator::setView( KFile::FileView view ) 00937 { 00938 bool separateDirs = KFile::isSeparateDirs( view ); 00939 bool preview=( KFile::isPreviewInfo(view) || KFile::isPreviewContents( view ) ); 00940 00941 if (view == KFile::Default) { 00942 if ( KFile::isDetailView( (KFile::FileView) defaultView ) ) 00943 view = KFile::Detail; 00944 else 00945 view = KFile::Simple; 00946 00947 separateDirs = KFile::isSeparateDirs( static_cast<KFile::FileView>(defaultView) ); 00948 preview = ( KFile::isPreviewInfo( static_cast<KFile::FileView>(defaultView) ) || 00949 KFile::isPreviewContents( static_cast<KFile::FileView>(defaultView) ) ) 00950 && myActionCollection->action("preview")->isEnabled(); 00951 00952 if ( preview ) { // instantiates KFileMetaPreview and calls setView() 00953 m_viewKind = defaultView; 00954 slotDefaultPreview(); 00955 return; 00956 } 00957 else if ( !separateDirs ) 00958 separateDirsAction->setChecked(true); 00959 } 00960 00961 // if we don't have any files, we can't separate dirs from files :) 00962 if ( (mode() & KFile::File) == 0 && 00963 (mode() & KFile::Files) == 0 ) { 00964 separateDirs = false; 00965 separateDirsAction->setEnabled( false ); 00966 } 00967 00968 m_viewKind = static_cast<int>(view) | (separateDirs ? KFile::SeparateDirs : 0); 00969 view = static_cast<KFile::FileView>(m_viewKind); 00970 00971 KFileView *new_view = createView( this, view ); 00972 if ( preview ) { 00973 // we keep the preview-_widget_ around, but not the KFilePreview. 00974 // KFilePreview::setPreviewWidget handles the reparenting for us 00975 static_cast<KFilePreview*>(new_view)->setPreviewWidget(myPreview, url()); 00976 } 00977 00978 setView( new_view ); 00979 } 00980 00981 00982 void KDirOperator::connectView(KFileView *view) 00983 { 00984 // TODO: do a real timer and restart it after that 00985 pendingMimeTypes.clear(); 00986 bool listDir = true; 00987 00988 if ( dirOnlyMode() ) 00989 view->setViewMode(KFileView::Directories); 00990 else 00991 view->setViewMode(KFileView::All); 00992 00993 if ( myMode & KFile::Files ) 00994 view->setSelectionMode( KFile::Extended ); 00995 else 00996 view->setSelectionMode( KFile::Single ); 00997 00998 if (m_fileView) 00999 { 01000 if ( d->config ) // save and restore the views' configuration 01001 { 01002 m_fileView->writeConfig( d->config, d->configGroup ); 01003 view->readConfig( d->config, d->configGroup ); 01004 } 01005 01006 // transfer the state from old view to new view 01007 view->clear(); 01008 view->addItemList( *m_fileView->items() ); 01009 listDir = false; 01010 01011 if ( m_fileView->widget()->hasFocus() ) 01012 view->widget()->setFocus(); 01013 01014 KFileItem *oldCurrentItem = m_fileView->currentFileItem(); 01015 if ( oldCurrentItem ) { 01016 view->setCurrentItem( oldCurrentItem ); 01017 view->setSelected( oldCurrentItem, false ); 01018 view->ensureItemVisible( oldCurrentItem ); 01019 } 01020 01021 const KFileItemList *oldSelected = m_fileView->selectedItems(); 01022 if ( !oldSelected->isEmpty() ) { 01023 KFileItemListIterator it( *oldSelected ); 01024 for ( ; it.current(); ++it ) 01025 view->setSelected( it.current(), true ); 01026 } 01027 01028 m_fileView->widget()->hide(); 01029 delete m_fileView; 01030 } 01031 01032 else 01033 { 01034 if ( d->config ) 01035 view->readConfig( d->config, d->configGroup ); 01036 } 01037 01038 m_fileView = view; 01039 m_fileView->setDropOptions(d->dropOptions); 01040 viewActionCollection = 0L; 01041 KFileViewSignaler *sig = view->signaler(); 01042 01043 connect(sig, SIGNAL( activatedMenu(const KFileItem *, const QPoint& ) ), 01044 this, SLOT( activatedMenu(const KFileItem *, const QPoint& ))); 01045 connect(sig, SIGNAL( dirActivated(const KFileItem *) ), 01046 this, SLOT( selectDir(const KFileItem*) ) ); 01047 connect(sig, SIGNAL( fileSelected(const KFileItem *) ), 01048 this, SLOT( selectFile(const KFileItem*) ) ); 01049 connect(sig, SIGNAL( fileHighlighted(const KFileItem *) ), 01050 this, SLOT( highlightFile(const KFileItem*) )); 01051 connect(sig, SIGNAL( sortingChanged( QDir::SortSpec ) ), 01052 this, SLOT( slotViewSortingChanged( QDir::SortSpec ))); 01053 connect(sig, SIGNAL( dropped(const KFileItem *, QDropEvent*, const KURL::List&) ), 01054 this, SIGNAL( dropped(const KFileItem *, QDropEvent*, const KURL::List&)) ); 01055 01056 if ( reverseAction->isChecked() != m_fileView->isReversed() ) 01057 slotSortReversed(); 01058 01059 updateViewActions(); 01060 m_fileView->widget()->resize(size()); 01061 m_fileView->widget()->show(); 01062 01063 if ( listDir ) { 01064 QApplication::setOverrideCursor( waitCursor ); 01065 dir->openURL( currUrl ); 01066 } 01067 else 01068 view->listingCompleted(); 01069 } 01070 01071 KFile::Mode KDirOperator::mode() const 01072 { 01073 return myMode; 01074 } 01075 01076 void KDirOperator::setMode(KFile::Mode m) 01077 { 01078 if (myMode == m) 01079 return; 01080 01081 myMode = m; 01082 01083 dir->setDirOnlyMode( dirOnlyMode() ); 01084 01085 // reset the view with the different mode 01086 setView( static_cast<KFile::FileView>(m_viewKind) ); 01087 } 01088 01089 void KDirOperator::setView(KFileView *view) 01090 { 01091 if ( view == m_fileView ) { 01092 return; 01093 } 01094 01095 setFocusProxy(view->widget()); 01096 view->setSorting( mySorting ); 01097 view->setOnlyDoubleClickSelectsFiles( d->onlyDoubleClickSelectsFiles ); 01098 connectView(view); // also deletes the old view 01099 01100 emit viewChanged( view ); 01101 } 01102 01103 void KDirOperator::setDirLister( KDirLister *lister ) 01104 { 01105 if ( lister == dir ) // sanity check 01106 return; 01107 01108 delete dir; 01109 dir = lister; 01110 01111 dir->setAutoUpdate( true ); 01112 01113 QWidget* mainWidget = topLevelWidget(); 01114 dir->setMainWindow (mainWidget); 01115 kdDebug (kfile_area) << "mainWidget=" << mainWidget << endl; 01116 01117 connect( dir, SIGNAL( percent( int )), 01118 SLOT( slotProgress( int ) )); 01119 connect( dir, SIGNAL(started( const KURL& )), SLOT(slotStarted())); 01120 connect( dir, SIGNAL(newItems(const KFileItemList &)), 01121 SLOT(insertNewFiles(const KFileItemList &))); 01122 connect( dir, SIGNAL(completed()), SLOT(slotIOFinished())); 01123 connect( dir, SIGNAL(canceled()), SLOT(slotCanceled())); 01124 connect( dir, SIGNAL(deleteItem(KFileItem *)), 01125 SLOT(itemDeleted(KFileItem *))); 01126 connect( dir, SIGNAL(redirection( const KURL& )), 01127 SLOT( slotRedirected( const KURL& ))); 01128 connect( dir, SIGNAL( clear() ), SLOT( slotClearView() )); 01129 connect( dir, SIGNAL( refreshItems( const KFileItemList& ) ), 01130 SLOT( slotRefreshItems( const KFileItemList& ) ) ); 01131 } 01132 01133 void KDirOperator::insertNewFiles(const KFileItemList &newone) 01134 { 01135 if ( newone.isEmpty() || !m_fileView ) 01136 return; 01137 01138 myCompleteListDirty = true; 01139 m_fileView->addItemList( newone ); 01140 emit updateInformation(m_fileView->numDirs(), m_fileView->numFiles()); 01141 01142 KFileItem *item; 01143 KFileItemListIterator it( newone ); 01144 01145 while ( (item = it.current()) ) { 01146 // highlight the dir we come from, if possible 01147 if ( d->dirHighlighting && item->isDir() && 01148 item->url().url(-1) == d->lastURL ) { 01149 m_fileView->setCurrentItem( item ); 01150 m_fileView->ensureItemVisible( item ); 01151 } 01152 01153 ++it; 01154 } 01155 01156 QTimer::singleShot(200, this, SLOT(resetCursor())); 01157 } 01158 01159 void KDirOperator::selectDir(const KFileItem *item) 01160 { 01161 setURL(item->url(), true); 01162 } 01163 01164 void KDirOperator::itemDeleted(KFileItem *item) 01165 { 01166 pendingMimeTypes.removeRef( item ); 01167 if ( m_fileView ) 01168 { 01169 m_fileView->removeItem( static_cast<KFileItem *>( item )); 01170 emit updateInformation(m_fileView->numDirs(), m_fileView->numFiles()); 01171 } 01172 } 01173 01174 void KDirOperator::selectFile(const KFileItem *item) 01175 { 01176 QApplication::restoreOverrideCursor(); 01177 01178 emit fileSelected( item ); 01179 } 01180 01181 void KDirOperator::setCurrentItem( const QString& filename ) 01182 { 01183 if ( m_fileView ) { 01184 const KFileItem *item = 0L; 01185 01186 if ( !filename.isNull() ) 01187 item = static_cast<KFileItem *>(dir->findByName( filename )); 01188 01189 m_fileView->clearSelection(); 01190 if ( item ) { 01191 m_fileView->setCurrentItem( item ); 01192 m_fileView->setSelected( item, true ); 01193 m_fileView->ensureItemVisible( item ); 01194 } 01195 } 01196 } 01197 01198 QString KDirOperator::makeCompletion(const QString& string) 01199 { 01200 if ( string.isEmpty() ) { 01201 m_fileView->clearSelection(); 01202 return QString::null; 01203 } 01204 01205 prepareCompletionObjects(); 01206 return myCompletion.makeCompletion( string ); 01207 } 01208 01209 QString KDirOperator::makeDirCompletion(const QString& string) 01210 { 01211 if ( string.isEmpty() ) { 01212 m_fileView->clearSelection(); 01213 return QString::null; 01214 } 01215 01216 prepareCompletionObjects(); 01217 return myDirCompletion.makeCompletion( string ); 01218 } 01219 01220 void KDirOperator::prepareCompletionObjects() 01221 { 01222 if ( !m_fileView ) 01223 return; 01224 01225 if ( myCompleteListDirty ) { // create the list of all possible completions 01226 KFileItemListIterator it( *(m_fileView->items()) ); 01227 for( ; it.current(); ++it ) { 01228 KFileItem *item = it.current(); 01229 01230 myCompletion.addItem( item->name() ); 01231 if ( item->isDir() ) 01232 myDirCompletion.addItem( item->name() ); 01233 } 01234 myCompleteListDirty = false; 01235 } 01236 } 01237 01238 void KDirOperator::slotCompletionMatch(const QString& match) 01239 { 01240 setCurrentItem( match ); 01241 emit completion( match ); 01242 } 01243 01244 void KDirOperator::setupActions() 01245 { 01246 myActionCollection = new KActionCollection( this, "KDirOperator::myActionCollection" ); 01247 actionMenu = new KActionMenu( i18n("Menu"), myActionCollection, "popupMenu" ); 01248 upAction = KStdAction::up( this, SLOT( cdUp() ), myActionCollection, "up" ); 01249 upAction->setText( i18n("Parent Folder") ); 01250 backAction = KStdAction::back( this, SLOT( back() ), myActionCollection, "back" ); 01251 forwardAction = KStdAction::forward( this, SLOT(forward()), myActionCollection, "forward" ); 01252 homeAction = KStdAction::home( this, SLOT( home() ), myActionCollection, "home" ); 01253 homeAction->setText(i18n("Home Folder")); 01254 reloadAction = KStdAction::redisplay( this, SLOT(rereadDir()), myActionCollection, "reload" ); 01255 actionSeparator = new KActionSeparator( myActionCollection, "separator" ); 01256 d->viewActionSeparator = new KActionSeparator( myActionCollection, 01257 "viewActionSeparator" ); 01258 mkdirAction = new KAction( i18n("New Folder..."), 0, 01259 this, SLOT( mkdir() ), myActionCollection, "mkdir" ); 01260 KAction* trash = new KAction( i18n( "Move to Trash" ), "edittrash", Key_Delete, myActionCollection, "trash" ); 01261 connect( trash, SIGNAL( activated( KAction::ActivationReason, Qt::ButtonState ) ), 01262 this, SLOT( trashSelected( KAction::ActivationReason, Qt::ButtonState ) ) ); 01263 new KAction( i18n( "Delete" ), "editdelete", SHIFT+Key_Delete, this, 01264 SLOT( deleteSelected() ), myActionCollection, "delete" ); 01265 mkdirAction->setIcon( QString::fromLatin1("folder_new") ); 01266 reloadAction->setText( i18n("Reload") ); 01267 reloadAction->setShortcut( KStdAccel::shortcut( KStdAccel::Reload )); 01268 01269 01270 // the sort menu actions 01271 sortActionMenu = new KActionMenu( i18n("Sorting"), myActionCollection, "sorting menu"); 01272 byNameAction = new KRadioAction( i18n("By Name"), 0, 01273 this, SLOT( slotSortByName() ), 01274 myActionCollection, "by name" ); 01275 byDateAction = new KRadioAction( i18n("By Date"), 0, 01276 this, SLOT( slotSortByDate() ), 01277 myActionCollection, "by date" ); 01278 bySizeAction = new KRadioAction( i18n("By Size"), 0, 01279 this, SLOT( slotSortBySize() ), 01280 myActionCollection, "by size" ); 01281 reverseAction = new KToggleAction( i18n("Reverse"), 0, 01282 this, SLOT( slotSortReversed() ), 01283 myActionCollection, "reversed" ); 01284 01285 QString sortGroup = QString::fromLatin1("sort"); 01286 byNameAction->setExclusiveGroup( sortGroup ); 01287 byDateAction->setExclusiveGroup( sortGroup ); 01288 bySizeAction->setExclusiveGroup( sortGroup ); 01289 01290 01291 dirsFirstAction = new KToggleAction( i18n("Folders First"), 0, 01292 myActionCollection, "dirs first"); 01293 caseInsensitiveAction = new KToggleAction(i18n("Case Insensitive"), 0, 01294 myActionCollection, "case insensitive" ); 01295 01296 connect( dirsFirstAction, SIGNAL( toggled( bool ) ), 01297 SLOT( slotToggleDirsFirst() )); 01298 connect( caseInsensitiveAction, SIGNAL( toggled( bool ) ), 01299 SLOT( slotToggleIgnoreCase() )); 01300 01301 01302 01303 // the view menu actions 01304 viewActionMenu = new KActionMenu( i18n("&View"), myActionCollection, "view menu" ); 01305 connect( viewActionMenu->popupMenu(), SIGNAL( aboutToShow() ), 01306 SLOT( insertViewDependentActions() )); 01307 01308 shortAction = new KRadioAction( i18n("Short View"), "view_multicolumn", 01309 KShortcut(), myActionCollection, "short view" ); 01310 detailedAction = new KRadioAction( i18n("Detailed View"), "view_detailed", 01311 KShortcut(), myActionCollection, "detailed view" ); 01312 01313 showHiddenAction = new KToggleAction( i18n("Show Hidden Files"), KShortcut(), 01314 myActionCollection, "show hidden" ); 01315 // showHiddenAction->setCheckedState( i18n("Hide Hidden Files") ); 01316 separateDirsAction = new KToggleAction( i18n("Separate Folders"), KShortcut(), 01317 this, 01318 SLOT(slotSeparateDirs()), 01319 myActionCollection, "separate dirs" ); 01320 KToggleAction *previewAction = new KToggleAction(i18n("Show Preview"), 01321 "thumbnail", KShortcut(), 01322 myActionCollection, 01323 "preview" ); 01324 previewAction->setCheckedState(i18n("Hide Preview")); 01325 connect( previewAction, SIGNAL( toggled( bool )), 01326 SLOT( togglePreview( bool ))); 01327 01328 01329 QString viewGroup = QString::fromLatin1("view"); 01330 shortAction->setExclusiveGroup( viewGroup ); 01331 detailedAction->setExclusiveGroup( viewGroup ); 01332 01333 connect( shortAction, SIGNAL( activated() ), 01334 SLOT( slotSimpleView() )); 01335 connect( detailedAction, SIGNAL( activated() ), 01336 SLOT( slotDetailedView() )); 01337 connect( showHiddenAction, SIGNAL( toggled( bool ) ), 01338 SLOT( slotToggleHidden( bool ) )); 01339 01340 new KAction( i18n("Properties"), KShortcut(ALT+Key_Return), this, 01341 SLOT(slotProperties()), myActionCollection, "properties" ); 01342 } 01343 01344 void KDirOperator::setupMenu() 01345 { 01346 setupMenu(AllActions); 01347 } 01348 01349 void KDirOperator::setupMenu(int whichActions) 01350 { 01351 // first fill the submenus (sort and view) 01352 sortActionMenu->popupMenu()->clear(); 01353 sortActionMenu->insert( byNameAction ); 01354 sortActionMenu->insert( byDateAction ); 01355 sortActionMenu->insert( bySizeAction ); 01356 sortActionMenu->insert( actionSeparator ); 01357 sortActionMenu->insert( reverseAction ); 01358 sortActionMenu->insert( dirsFirstAction ); 01359 sortActionMenu->insert( caseInsensitiveAction ); 01360 01361 // now plug everything into the popupmenu 01362 actionMenu->popupMenu()->clear(); 01363 if (whichActions & NavActions) 01364 { 01365 actionMenu->insert( upAction ); 01366 actionMenu->insert( backAction ); 01367 actionMenu->insert( forwardAction ); 01368 actionMenu->insert( homeAction ); 01369 actionMenu->insert( actionSeparator ); 01370 } 01371 01372 if (whichActions & FileActions) 01373 { 01374 actionMenu->insert( mkdirAction ); 01375 if (currUrl.isLocalFile() && !(KApplication::keyboardMouseState() & Qt::ShiftButton)) 01376 actionMenu->insert( myActionCollection->action( "trash" ) ); 01377 KConfig *globalconfig = KGlobal::config(); 01378 KConfigGroupSaver cs( globalconfig, QString::fromLatin1("KDE") ); 01379 if (!currUrl.isLocalFile() || (KApplication::keyboardMouseState() & Qt::ShiftButton) || 01380 globalconfig->readBoolEntry("ShowDeleteCommand", false)) 01381 actionMenu->insert( myActionCollection->action( "delete" ) ); 01382 actionMenu->insert( actionSeparator ); 01383 } 01384 01385 if (whichActions & SortActions) 01386 { 01387 actionMenu->insert( sortActionMenu ); 01388 actionMenu->insert( actionSeparator ); 01389 } 01390 01391 if (whichActions & ViewActions) 01392 { 01393 actionMenu->insert( viewActionMenu ); 01394 actionMenu->insert( actionSeparator ); 01395 } 01396 01397 if (whichActions & FileActions) 01398 { 01399 actionMenu->insert( myActionCollection->action( "properties" ) ); 01400 } 01401 } 01402 01403 void KDirOperator::updateSortActions() 01404 { 01405 if ( KFile::isSortByName( mySorting ) ) 01406 byNameAction->setChecked( true ); 01407 else if ( KFile::isSortByDate( mySorting ) ) 01408 byDateAction->setChecked( true ); 01409 else if ( KFile::isSortBySize( mySorting ) ) 01410 bySizeAction->setChecked( true ); 01411 01412 dirsFirstAction->setChecked( KFile::isSortDirsFirst( mySorting ) ); 01413 caseInsensitiveAction->setChecked( KFile::isSortCaseInsensitive(mySorting) ); 01414 caseInsensitiveAction->setEnabled( KFile::isSortByName( mySorting ) ); 01415 01416 if ( m_fileView ) 01417 reverseAction->setChecked( m_fileView->isReversed() ); 01418 } 01419 01420 void KDirOperator::updateViewActions() 01421 { 01422 KFile::FileView fv = static_cast<KFile::FileView>( m_viewKind ); 01423 01424 separateDirsAction->setChecked( KFile::isSeparateDirs( fv ) && 01425 separateDirsAction->isEnabled() ); 01426 01427 shortAction->setChecked( KFile::isSimpleView( fv )); 01428 detailedAction->setChecked( KFile::isDetailView( fv )); 01429 } 01430 01431 void KDirOperator::readConfig( KConfig *kc, const QString& group ) 01432 { 01433 if ( !kc ) 01434 return; 01435 QString oldGroup = kc->group(); 01436 if ( !group.isEmpty() ) 01437 kc->setGroup( group ); 01438 01439 defaultView = 0; 01440 int sorting = 0; 01441 01442 QString viewStyle = kc->readEntry( QString::fromLatin1("View Style"), 01443 QString::fromLatin1("Simple") ); 01444 if ( viewStyle == QString::fromLatin1("Detail") ) 01445 defaultView |= KFile::Detail; 01446 else 01447 defaultView |= KFile::Simple; 01448 if ( kc->readBoolEntry( QString::fromLatin1("Separate Directories"), 01449 DefaultMixDirsAndFiles ) ) 01450 defaultView |= KFile::SeparateDirs; 01451 if ( kc->readBoolEntry(QString::fromLatin1("Show Preview"), false)) 01452 defaultView |= KFile::PreviewContents; 01453 01454 if ( kc->readBoolEntry( QString::fromLatin1("Sort case insensitively"), 01455 DefaultCaseInsensitive ) ) 01456 sorting |= QDir::IgnoreCase; 01457 if ( kc->readBoolEntry( QString::fromLatin1("Sort directories first"), 01458 DefaultDirsFirst ) ) 01459 sorting |= QDir::DirsFirst; 01460 01461 01462 QString name = QString::fromLatin1("Name"); 01463 QString sortBy = kc->readEntry( QString::fromLatin1("Sort by"), name ); 01464 if ( sortBy == name ) 01465 sorting |= QDir::Name; 01466 else if ( sortBy == QString::fromLatin1("Size") ) 01467 sorting |= QDir::Size; 01468 else if ( sortBy == QString::fromLatin1("Date") ) 01469 sorting |= QDir::Time; 01470 01471 mySorting = static_cast<QDir::SortSpec>( sorting ); 01472 setSorting( mySorting ); 01473 01474 01475 if ( kc->readBoolEntry( QString::fromLatin1("Show hidden files"), 01476 DefaultShowHidden ) ) { 01477 showHiddenAction->setChecked( true ); 01478 dir->setShowingDotFiles( true ); 01479 } 01480 if ( kc->readBoolEntry( QString::fromLatin1("Sort reversed"), 01481 DefaultSortReversed ) ) 01482 reverseAction->setChecked( true ); 01483 01484 kc->setGroup( oldGroup ); 01485 } 01486 01487 void KDirOperator::writeConfig( KConfig *kc, const QString& group ) 01488 { 01489 if ( !kc ) 01490 return; 01491 01492 const QString oldGroup = kc->group(); 01493 01494 if ( !group.isEmpty() ) 01495 kc->setGroup( group ); 01496 01497 QString sortBy = QString::fromLatin1("Name"); 01498 if ( KFile::isSortBySize( mySorting ) ) 01499 sortBy = QString::fromLatin1("Size"); 01500 else if ( KFile::isSortByDate( mySorting ) ) 01501 sortBy = QString::fromLatin1("Date"); 01502 kc->writeEntry( QString::fromLatin1("Sort by"), sortBy ); 01503 01504 kc->writeEntry( QString::fromLatin1("Sort reversed"), 01505 reverseAction->isChecked() ); 01506 kc->writeEntry( QString::fromLatin1("Sort case insensitively"), 01507 caseInsensitiveAction->isChecked() ); 01508 kc->writeEntry( QString::fromLatin1("Sort directories first"), 01509 dirsFirstAction->isChecked() ); 01510 01511 // don't save the separate dirs or preview when an application specific 01512 // preview is in use. 01513 bool appSpecificPreview = false; 01514 if ( myPreview ) { 01515 QWidget *preview = const_cast<QWidget*>( myPreview ); // grmbl 01516 KFileMetaPreview *tmp = dynamic_cast<KFileMetaPreview*>( preview ); 01517 appSpecificPreview = (tmp == 0L); 01518 } 01519 01520 if ( !appSpecificPreview ) { 01521 if ( separateDirsAction->isEnabled() ) 01522 kc->writeEntry( QString::fromLatin1("Separate Directories"), 01523 separateDirsAction->isChecked() ); 01524 01525 KToggleAction *previewAction = static_cast<KToggleAction*>(myActionCollection->action("preview")); 01526 if ( previewAction->isEnabled() ) { 01527 bool hasPreview = previewAction->isChecked(); 01528 kc->writeEntry( QString::fromLatin1("Show Preview"), hasPreview ); 01529 } 01530 } 01531 01532 kc->writeEntry( QString::fromLatin1("Show hidden files"), 01533 showHiddenAction->isChecked() ); 01534 01535 KFile::FileView fv = static_cast<KFile::FileView>( m_viewKind ); 01536 QString style; 01537 if ( KFile::isDetailView( fv ) ) 01538 style = QString::fromLatin1("Detail"); 01539 else if ( KFile::isSimpleView( fv ) ) 01540 style = QString::fromLatin1("Simple"); 01541 kc->writeEntry( QString::fromLatin1("View Style"), style ); 01542 01543 kc->setGroup( oldGroup ); 01544 } 01545 01546 01547 void KDirOperator::resizeEvent( QResizeEvent * ) 01548 { 01549 if (m_fileView) 01550 m_fileView->widget()->resize( size() ); 01551 01552 if ( progress->parent() == this ) // might be reparented into a statusbar 01553 progress->move(2, height() - progress->height() -2); 01554 } 01555 01556 void KDirOperator::setOnlyDoubleClickSelectsFiles( bool enable ) 01557 { 01558 d->onlyDoubleClickSelectsFiles = enable; 01559 if ( m_fileView ) 01560 m_fileView->setOnlyDoubleClickSelectsFiles( enable ); 01561 } 01562 01563 bool KDirOperator::onlyDoubleClickSelectsFiles() const 01564 { 01565 return d->onlyDoubleClickSelectsFiles; 01566 } 01567 01568 void KDirOperator::slotStarted() 01569 { 01570 progress->setProgress( 0 ); 01571 // delay showing the progressbar for one second 01572 d->progressDelayTimer->start( 1000, true ); 01573 } 01574 01575 void KDirOperator::slotShowProgress() 01576 { 01577 progress->raise(); 01578 progress->show(); 01579 QApplication::flushX(); 01580 } 01581 01582 void KDirOperator::slotProgress( int percent ) 01583 { 01584 progress->setProgress( percent ); 01585 // we have to redraw this as fast as possible 01586 if ( progress->isVisible() ) 01587 QApplication::flushX(); 01588 } 01589 01590 01591 void KDirOperator::slotIOFinished() 01592 { 01593 d->progressDelayTimer->stop(); 01594 slotProgress( 100 ); 01595 progress->hide(); 01596 emit finishedLoading(); 01597 resetCursor(); 01598 01599 if ( m_fileView ) 01600 m_fileView->listingCompleted(); 01601 } 01602 01603 void KDirOperator::slotCanceled() 01604 { 01605 emit finishedLoading(); 01606 resetCursor(); 01607 01608 if ( m_fileView ) 01609 m_fileView->listingCompleted(); 01610 } 01611 01612 KProgress * KDirOperator::progressBar() const 01613 { 01614 return progress; 01615 } 01616 01617 void KDirOperator::clearHistory() 01618 { 01619 backStack.clear(); 01620 backAction->setEnabled( false ); 01621 forwardStack.clear(); 01622 forwardAction->setEnabled( false ); 01623 } 01624 01625 void KDirOperator::slotViewActionAdded( KAction *action ) 01626 { 01627 if ( viewActionMenu->popupMenu()->count() == 5 ) // need to add a separator 01628 viewActionMenu->insert( d->viewActionSeparator ); 01629 01630 viewActionMenu->insert( action ); 01631 } 01632 01633 void KDirOperator::slotViewActionRemoved( KAction *action ) 01634 { 01635 viewActionMenu->remove( action ); 01636 01637 if ( viewActionMenu->popupMenu()->count() == 6 ) // remove the separator 01638 viewActionMenu->remove( d->viewActionSeparator ); 01639 } 01640 01641 void KDirOperator::slotViewSortingChanged( QDir::SortSpec sort ) 01642 { 01643 mySorting = sort; 01644 updateSortActions(); 01645 } 01646 01647 void KDirOperator::setEnableDirHighlighting( bool enable ) 01648 { 01649 d->dirHighlighting = enable; 01650 } 01651 01652 bool KDirOperator::dirHighlighting() const 01653 { 01654 return d->dirHighlighting; 01655 } 01656 01657 void KDirOperator::slotProperties() 01658 { 01659 if ( m_fileView ) { 01660 const KFileItemList *list = m_fileView->selectedItems(); 01661 if ( !list->isEmpty() ) 01662 (void) new KPropertiesDialog( *list, this, "props dlg", true); 01663 } 01664 } 01665 01666 void KDirOperator::slotClearView() 01667 { 01668 if ( m_fileView ) 01669 m_fileView->clearView(); 01670 } 01671 01672 // ### temporary code 01673 #include <dirent.h> 01674 bool KDirOperator::isReadable( const KURL& url ) 01675 { 01676 if ( !url.isLocalFile() ) 01677 return true; // what else can we say? 01678 01679 KDE_struct_stat buf; 01680 QString ts = url.path(+1); 01681 bool readable = ( KDE_stat( QFile::encodeName( ts ), &buf) == 0 ); 01682 if (readable) { // further checks 01683 DIR *test; 01684 test = opendir( QFile::encodeName( ts )); // we do it just to test here 01685 readable = (test != 0); 01686 if (test) 01687 closedir(test); 01688 } 01689 return readable; 01690 } 01691 01692 void KDirOperator::togglePreview( bool on ) 01693 { 01694 if ( on ) 01695 slotDefaultPreview(); 01696 else 01697 setView( (KFile::FileView) (m_viewKind & ~(KFile::PreviewContents|KFile::PreviewInfo)) ); 01698 } 01699 01700 void KDirOperator::slotRefreshItems( const KFileItemList& items ) 01701 { 01702 if ( !m_fileView ) 01703 return; 01704 01705 KFileItemListIterator it( items ); 01706 for ( ; it.current(); ++it ) 01707 m_fileView->updateView( it.current() ); 01708 } 01709 01710 void KDirOperator::setViewConfig( KConfig *config, const QString& group ) 01711 { 01712 d->config = config; 01713 d->configGroup = group; 01714 } 01715 01716 KConfig * KDirOperator::viewConfig() 01717 { 01718 return d->config; 01719 } 01720 01721 QString KDirOperator::viewConfigGroup() const 01722 { 01723 return d->configGroup; 01724 } 01725 01726 void KDirOperator::virtual_hook( int, void* ) 01727 { /*BASE::virtual_hook( id, data );*/ } 01728 01729 #include "kdiroperator.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 23:09:09 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003