tdefileview.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1998 Stephan Kulow <coolo@kde.org> 00003 1998 Daniel Grana <grana@ie.iwi.unibe.ch> 00004 2001 Carsten Pfeiffer <pfeiffer@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include <assert.h> 00023 #include <stdlib.h> 00024 00025 #include <tdeaction.h> 00026 #include <tdeapplication.h> 00027 #include <kdebug.h> 00028 #include <tdeglobal.h> 00029 #include <tdelocale.h> 00030 #include <kstandarddirs.h> 00031 00032 #include "config-tdefile.h" 00033 #include "tdefileview.h" 00034 00035 #ifdef Unsorted // the "I hate X.h" modus 00036 #undef Unsorted 00037 #endif 00038 00039 TQDir::SortSpec KFileView::defaultSortSpec = static_cast<TQDir::SortSpec>(TQDir::Name | TQDir::IgnoreCase | TQDir::DirsFirst); 00040 00041 class KFileView::KFileViewPrivate 00042 { 00043 public: 00044 KFileViewPrivate() 00045 { 00046 actions = 0; 00047 dropOptions = 0; 00048 } 00049 00050 ~KFileViewPrivate() 00051 { 00052 if( actions ) { 00053 actions->clear(); // so that the removed() signal is emitted! 00054 delete actions; 00055 } 00056 } 00057 00058 TQGuardedPtr<TDEActionCollection> actions; 00059 int dropOptions; 00060 }; 00061 00062 00063 KFileView::KFileView() 00064 { 00065 d = new KFileViewPrivate(); 00066 m_sorting = KFileView::defaultSortSpec; 00067 00068 sig = new KFileViewSignaler(); 00069 sig->setName("view-signaller"); 00070 00071 m_selectedList = 0L; 00072 filesNumber = 0; 00073 dirsNumber = 0; 00074 00075 view_mode = All; 00076 selection_mode = KFile::Single; 00077 m_viewName = i18n("Unknown View"); 00078 00079 myOnlyDoubleClickSelectsFiles = false; 00080 m_itemList.setAutoDelete( false ); // just references 00081 } 00082 00083 KFileView::~KFileView() 00084 { 00085 delete d; 00086 delete sig; 00087 delete m_selectedList; 00088 } 00089 00090 void KFileView::setParentView(KFileView *parent) 00091 { 00092 if ( parent ) { // pass all signals right to our parent 00093 TQObject::connect(sig, TQT_SIGNAL( activatedMenu(const KFileItem *, 00094 const TQPoint& ) ), 00095 parent->sig, TQT_SIGNAL( activatedMenu(const KFileItem *, 00096 const TQPoint& ))); 00097 TQObject::connect(sig, TQT_SIGNAL( dirActivated(const KFileItem *)), 00098 parent->sig, TQT_SIGNAL( dirActivated(const KFileItem*))); 00099 TQObject::connect(sig, TQT_SIGNAL( fileSelected(const KFileItem *)), 00100 parent->sig, TQT_SIGNAL( fileSelected(const KFileItem*))); 00101 TQObject::connect(sig, TQT_SIGNAL( fileHighlighted(const KFileItem *) ), 00102 parent->sig,TQT_SIGNAL(fileHighlighted(const KFileItem*))); 00103 TQObject::connect(sig, TQT_SIGNAL( sortingChanged( TQDir::SortSpec ) ), 00104 parent->sig, TQT_SIGNAL(sortingChanged( TQDir::SortSpec))); 00105 TQObject::connect(sig, TQT_SIGNAL( dropped(const KFileItem *, TQDropEvent*, const KURL::List&) ), 00106 parent->sig, TQT_SIGNAL(dropped(const KFileItem *, TQDropEvent*, const KURL::List&))); 00107 } 00108 } 00109 00110 bool KFileView::updateNumbers(const KFileItem *i) 00111 { 00112 if (!( viewMode() & Files ) && i->isFile()) 00113 return false; 00114 00115 if (!( viewMode() & Directories ) && i->isDir()) 00116 return false; 00117 00118 if (i->isDir()) 00119 dirsNumber++; 00120 else 00121 filesNumber++; 00122 00123 return true; 00124 } 00125 00126 void qt_qstring_stats(); 00127 00128 // filter out files if we're in directory mode and count files/directories 00129 // and insert into the view 00130 void KFileView::addItemList(const KFileItemList& list) 00131 { 00132 KFileItem *tmp; 00133 00134 for (KFileItemListIterator it(list); (tmp = it.current()); ++it) 00135 { 00136 if (!updateNumbers(tmp)) 00137 continue; 00138 00139 insertItem( tmp ); 00140 } 00141 00142 #ifdef Q2HELPER 00143 qt_qstring_stats(); 00144 #endif 00145 } 00146 00147 void KFileView::insertItem( KFileItem * ) 00148 { 00149 } 00150 00151 void KFileView::setSorting(TQDir::SortSpec new_sort) 00152 { 00153 m_sorting = new_sort; 00154 } 00155 00156 void KFileView::clear() 00157 { 00158 m_itemList.clear(); 00159 filesNumber = 0; 00160 dirsNumber = 0; 00161 clearView(); 00162 } 00163 00164 void KFileView::sortReversed() 00165 { 00166 int spec = sorting(); 00167 00168 setSorting( static_cast<TQDir::SortSpec>( spec ^ TQDir::Reversed ) ); 00169 } 00170 00171 #if 0 00172 int KFileView::compareItems(const KFileItem *fi1, const KFileItem *fi2) const 00173 { 00174 static const TQString &dirup = TDEGlobal::staticQString(".."); 00175 bool bigger = true; 00176 bool keepFirst = false; 00177 bool dirsFirst = ((m_sorting & TQDir::DirsFirst) == TQDir::DirsFirst); 00178 00179 if (fi1 == fi2) 00180 return 0; 00181 00182 // .. is always bigger, independent of the sort criteria 00183 if ( fi1->name() == dirup ) { 00184 bigger = false; 00185 keepFirst = dirsFirst; 00186 } 00187 else if ( fi2->name() == dirup ) { 00188 bigger = true; 00189 keepFirst = dirsFirst; 00190 } 00191 00192 else { 00193 if ( fi1->isDir() != fi2->isDir() && dirsFirst ) { 00194 bigger = fi2->isDir(); 00195 keepFirst = true; 00196 } 00197 else { 00198 00199 TQDir::SortSpec sort = static_cast<TQDir::SortSpec>(m_sorting & TQDir::SortByMask); 00200 00201 //if (fi1->isDir() || fi2->isDir()) 00202 // sort = static_cast<TQDir::SortSpec>(KFileView::defaultSortSpec & TQDir::SortByMask); 00203 00204 switch (sort) { 00205 case TQDir::Name: 00206 default: 00207 sort_by_name: 00208 if ( (m_sorting & TQDir::IgnoreCase) == TQDir::IgnoreCase ) 00209 bigger = (fi1->name( true ) > fi2->name( true )); 00210 else 00211 bigger = (fi1->name() > fi2->name()); 00212 break; 00213 case TQDir::Time: 00214 { 00215 time_t t1 = fi1->time( TDEIO::UDS_MODIFICATION_TIME ); 00216 time_t t2 = fi2->time( TDEIO::UDS_MODIFICATION_TIME ); 00217 if ( t1 != t2 ) { 00218 bigger = (t1 > t2); 00219 break; 00220 } 00221 00222 // Sort by name if both items have the same timestamp. 00223 // Don't honor the reverse flag tho. 00224 else { 00225 keepFirst = true; 00226 goto sort_by_name; 00227 } 00228 } 00229 case TQDir::Size: 00230 { 00231 TDEIO::filesize_t s1 = fi1->size(); 00232 TDEIO::filesize_t s2 = fi2->size(); 00233 if ( s1 != s2 ) { 00234 bigger = (s1 > s2); 00235 break; 00236 } 00237 00238 // Sort by name if both items have the same size. 00239 // Don't honor the reverse flag tho. 00240 else { 00241 keepFirst = true; 00242 goto sort_by_name; 00243 } 00244 } 00245 case TQDir::Unsorted: 00246 bigger = true; // nothing 00247 break; 00248 } 00249 } 00250 } 00251 00252 if (reversed && !keepFirst ) // don't reverse dirs to the end! 00253 bigger = !bigger; 00254 00255 return (bigger ? 1 : -1); 00256 } 00257 #endif 00258 00259 void KFileView::updateView(bool f) 00260 { 00261 widget()->repaint(f); 00262 } 00263 00264 void KFileView::updateView(const KFileItem *) 00265 { 00266 } 00267 00268 void KFileView::setCurrentItem(const TQString &filename ) 00269 { 00270 if (!filename.isNull()) { 00271 KFileItem *item; 00272 for ( (item = firstFileItem()); item; item = nextItem( item ) ) { 00273 if (item->name() == filename) { 00274 setCurrentItem( item ); 00275 return; 00276 } 00277 } 00278 } 00279 00280 kdDebug(tdefile_area) << "setCurrentItem: no match found: " << filename << endl; 00281 } 00282 00283 const KFileItemList * KFileView::items() const 00284 { 00285 KFileItem *item = 0L; 00286 00287 // only ever use m_itemList in this method! 00288 m_itemList.clear(); 00289 for ( (item = firstFileItem()); item; item = nextItem( item ) ) 00290 m_itemList.append( item ); 00291 00292 return &m_itemList; 00293 } 00294 00295 00296 const KFileItemList * KFileView::selectedItems() const 00297 { 00298 if ( !m_selectedList ) 00299 m_selectedList = new KFileItemList; 00300 00301 m_selectedList->clear(); 00302 00303 KFileItem *item; 00304 for ( (item = firstFileItem()); item; item = nextItem( item ) ) { 00305 if ( isSelected( item ) ) 00306 m_selectedList->append( item ); 00307 } 00308 00309 return m_selectedList; 00310 } 00311 00312 void KFileView::selectAll() 00313 { 00314 if (selection_mode == KFile::NoSelection || selection_mode== KFile::Single) 00315 return; 00316 00317 KFileItem *item = 0L; 00318 for ( (item = firstFileItem()); item; item = nextItem( item ) ) 00319 setSelected( item, true ); 00320 } 00321 00322 00323 void KFileView::invertSelection() 00324 { 00325 KFileItem *item = 0L; 00326 for ( (item = firstFileItem()); item; item = nextItem( item ) ) 00327 setSelected( item, !isSelected( item ) ); 00328 } 00329 00330 00331 void KFileView::setSelectionMode( KFile::SelectionMode sm ) 00332 { 00333 selection_mode = sm; 00334 } 00335 00336 KFile::SelectionMode KFileView::selectionMode() const 00337 { 00338 return selection_mode; 00339 } 00340 00341 void KFileView::setViewMode( ViewMode vm ) 00342 { 00343 view_mode = vm; 00344 } 00345 00346 void KFileView::removeItem( const KFileItem *item ) 00347 { 00348 if ( !item ) 00349 return; 00350 00351 if ( item->isDir() ) 00352 dirsNumber--; 00353 else 00354 filesNumber--; 00355 00356 if ( m_selectedList ) 00357 m_selectedList->removeRef( item ); 00358 } 00359 00360 void KFileView::listingCompleted() 00361 { 00362 // empty default impl. 00363 } 00364 00365 TDEActionCollection * KFileView::actionCollection() const 00366 { 00367 if ( !d->actions ) 00368 d->actions = new TDEActionCollection( widget(), "KFileView::d->actions" ); 00369 return d->actions; 00370 } 00371 00372 void KFileView::readConfig( TDEConfig *, const TQString& ) 00373 { 00374 } 00375 00376 void KFileView::writeConfig( TDEConfig *, const TQString& ) 00377 { 00378 } 00379 00380 TQString KFileView::sortingKey( const TQString& value, bool isDir, int sortSpec ) 00381 { 00382 bool reverse = sortSpec & TQDir::Reversed; 00383 bool dirsFirst = sortSpec & TQDir::DirsFirst; 00384 char start = (isDir && dirsFirst) ? (reverse ? '2' : '0') : '1'; 00385 TQString result = (sortSpec & TQDir::IgnoreCase) ? value.lower() : value; 00386 return result.prepend( start ); 00387 } 00388 00389 TQString KFileView::sortingKey( TDEIO::filesize_t value, bool isDir, int sortSpec) 00390 { 00391 bool reverse = sortSpec & TQDir::Reversed; 00392 bool dirsFirst = sortSpec & TQDir::DirsFirst; 00393 char start = (isDir && dirsFirst) ? (reverse ? '2' : '0') : '1'; 00394 return TDEIO::number( value ).rightJustify( 24, '0' ).prepend( start ); 00395 } 00396 00397 void KFileView::setDropOptions(int options) 00398 { 00399 virtual_hook(VIRTUAL_SET_DROP_OPTIONS, &options); // Virtual call 00400 } 00401 00402 void KFileView::setDropOptions_impl(int options) 00403 { 00404 d->dropOptions = options; 00405 } 00406 00407 int KFileView::dropOptions() 00408 { 00409 return d->dropOptions; 00410 } 00411 00412 int KFileView::autoOpenDelay() 00413 { 00414 return (TQApplication::startDragTime() * 3) / 2; 00415 } 00416 00417 void KFileView::virtual_hook( int id, void* data) 00418 { 00419 switch(id) { 00420 case VIRTUAL_SET_DROP_OPTIONS: 00421 setDropOptions_impl(*(int *)data); 00422 break; 00423 default: 00424 /*BASE::virtual_hook( id, data );*/ 00425 break; 00426 } 00427 } 00428 00429 #include "tdefileview.moc"