diff options
Diffstat (limited to 'krusader/Panel/krdetailedview.cpp')
-rw-r--r-- | krusader/Panel/krdetailedview.cpp | 1587 |
1 files changed, 1587 insertions, 0 deletions
diff --git a/krusader/Panel/krdetailedview.cpp b/krusader/Panel/krdetailedview.cpp new file mode 100644 index 0000000..633c2d7 --- /dev/null +++ b/krusader/Panel/krdetailedview.cpp @@ -0,0 +1,1587 @@ +/*************************************************************************** + krdetailedview.cpp + ------------------- +copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai +e-mail : krusader@users.sourceforge.net +web site : http://krusader.sourceforge.net +--------------------------------------------------------------------------- +Description +*************************************************************************** + +A + +db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. +88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D +88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' +88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b +88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. +YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD + + S o u r c e F i l e + +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ +#include "krdetailedview.h" +#include "krdetailedviewitem.h" +#include "krcolorcache.h" +#include "krselectionmode.h" +#include "../krusader.h" +#include "../kicons.h" +#include "../defaults.h" +#include "../krusaderview.h" +#include "../krslots.h" +#include "../VFS/krpermhandler.h" +#include "../VFS/krarchandler.h" +#include "../GUI/kcmdline.h" +#include "../Dialogs/krspecialwidgets.h" +#include "../panelmanager.h" +#include <qlayout.h> +#include <qdir.h> +#include <qwhatsthis.h> +#include <qheader.h> +#include <qstyle.h> +#include <kprogress.h> +#include <kstatusbar.h> +#include <kinputdialog.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <qdict.h> + +////////////////////////////////////////////////////////////////////////// +// The following is KrDetailedView's settings in KConfig: +// Group name: KrDetailedView +// +// Ext Column +#define _ExtColumn true +// Mime Column +#define _MimeColumn false +// Size Column +#define _SizeColumn true +// DateTime Column +#define _DateTimeColumn true +// Perm Column +#define _PermColumn false +// KrPerm Column +#define _KrPermColumn true +// Owner Column +#define _OwnerColumn false +// Group Column +#define _GroupColumn false +// Do Quicksearch +#define _DoQuicksearch true +////////////////////////////////////////////////////////////////////////// + +#define CANCEL_TWO_CLICK_RENAME {singleClicked = false;renameTimer.stop();} +#define COLUMN(X) static_cast<KrDetailedViewProperties*>(_properties)->column[ KrDetailedViewProperties::X ] +#define PROPS static_cast<KrDetailedViewProperties*>(_properties) +#define VF getVfile() + +#define COLUMN_POPUP_IDS 91 + +QString KrDetailedView::ColumnName[ KrDetailedViewProperties::MAX_COLUMNS ]; + +KrDetailedView::KrDetailedView( QWidget *parent, bool &left, KConfig *cfg, const char *name ) : + KListView( parent, name ), KrView( cfg ), _currDragItem( 0L ), currentlyRenamedItem( 0 ), + pressedItem( 0 ) { + setWidget( this ); + _nameInKConfig=QString( "KrDetailedView" ) + QString( ( left ? "Left" : "Right" ) ) ; + krConfig->setGroup("Private"); + if (krConfig->readBoolEntry("Enable Input Method", true)) + setInputMethodEnabled(true); +} + +void KrDetailedView::setup() { + lastSwushPosition = 0; + if ( ColumnName[ 0 ].isEmpty() ) { + ColumnName[ 0 ] = i18n( "Name" ); + ColumnName[ 1 ] = i18n( "Ext" ); + ColumnName[ 2 ] = i18n( "Type" ); + ColumnName[ 3 ] = i18n( "Size" ); + ColumnName[ 4 ] = i18n( "Modified" ); + ColumnName[ 5 ] = i18n( "Perms" ); + ColumnName[ 6 ] = i18n( "rwx" ); + ColumnName[ 7 ] = i18n( "Owner" ); + ColumnName[ 8 ] = i18n( "Group" ); + } + + /////////////////////////////// listview //////////////////////////////////// + { // use the {} so that KConfigGroupSaver will work correctly! + KConfigGroupSaver grpSvr( _config, "Look&Feel" ); + setFont( _config->readFontEntry( "Filelist Font", _FilelistFont ) ); + // decide on single click/double click selection + if ( _config->readBoolEntry( "Single Click Selects", _SingleClickSelects ) && + KGlobalSettings::singleClick() ) { + connect( this, SIGNAL( executed( QListViewItem* ) ), this, SLOT( slotExecuted( QListViewItem* ) ) ); + } else { + connect( this, SIGNAL( clicked( QListViewItem* ) ), this, SLOT( slotClicked( QListViewItem* ) ) ); + connect( this, SIGNAL( doubleClicked( QListViewItem* ) ), this, SLOT( slotDoubleClicked( QListViewItem* ) ) ); + } + + // a change in the selection needs to update totals + connect( this, SIGNAL( onItem( QListViewItem* ) ), this, SLOT( slotItemDescription( QListViewItem* ) ) ); + connect( this, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint&, int ) ), + this, SLOT( handleContextMenu( QListViewItem*, const QPoint&, int ) ) ); + connect( this, SIGNAL( rightButtonPressed(QListViewItem*, const QPoint&, int)), + this, SLOT(slotRightButtonPressed(QListViewItem*, const QPoint&, int))); + connect( this, SIGNAL( currentChanged( QListViewItem* ) ), this, SLOT( setNameToMakeCurrent( QListViewItem* ) ) ); + connect( this, SIGNAL( currentChanged( QListViewItem* ) ), this, SLOT( transformCurrentChanged( QListViewItem* ) ) ); + connect( this, SIGNAL( mouseButtonClicked ( int, QListViewItem *, const QPoint &, int ) ), + this, SLOT( slotMouseClicked ( int, QListViewItem *, const QPoint &, int ) ) ); + connect( &KrColorCache::getColorCache(), SIGNAL( colorsRefreshed() ), this, SLOT( refreshColors() ) ); + connect( header(), SIGNAL(clicked(int)), this, SLOT(sortOrderChanged(int ))); + } + + // add whatever columns are needed to the listview + krConfig->setGroup( nameInKConfig() ); + + newColumn( KrDetailedViewProperties::Name ); // we always have a name + setColumnWidthMode( COLUMN(Name), QListView::Manual ); + if ( _config->readBoolEntry( "Ext Column", _ExtColumn ) ) { + newColumn( KrDetailedViewProperties::Extention ); + setColumnWidthMode( COLUMN(Extention), QListView::Manual ); + setColumnWidth( COLUMN(Extention), QFontMetrics( font() ).width( "tar.bz2" ) ); + } + if ( _config->readBoolEntry( "Mime Column", _MimeColumn ) ) { + newColumn( KrDetailedViewProperties::Mime ); + setColumnWidthMode( COLUMN(Mime), QListView::Manual ); + setColumnWidth( COLUMN(Mime), QFontMetrics( font() ).width( 'X' ) * 6 ); + } + if ( _config->readBoolEntry( "Size Column", _SizeColumn ) ) { + newColumn( KrDetailedViewProperties::Size ); + setColumnWidthMode( COLUMN(Size), QListView::Manual ); + setColumnWidth( COLUMN(Size), QFontMetrics( font() ).width( "9" ) * 10 ); + setColumnAlignment( COLUMN(Size), Qt::AlignRight ); // right-align numbers + } + if ( _config->readBoolEntry( "DateTime Column", _DateTimeColumn ) ) { + newColumn( KrDetailedViewProperties::DateTime ); + setColumnWidthMode( COLUMN(DateTime), QListView::Manual ); + //setColumnWidth( column( DateTime ), QFontMetrics( font() ).width( "99/99/99 99:99" ) ); + setColumnWidth( COLUMN(DateTime), QFontMetrics( font() ).width( KGlobal::locale() ->formatDateTime( + QDateTime ( QDate( 2099, 12, 29 ), QTime( 23, 59 ) ) ) ) + 3 ); + } + if ( _config->readBoolEntry( "Perm Column", _PermColumn ) ) { + newColumn( KrDetailedViewProperties::Permissions ); + setColumnWidthMode( COLUMN(Permissions), QListView::Manual ); + setColumnWidth( COLUMN(Permissions), QFontMetrics( font() ).width( "drwxrwxrwx" ) ); + } + if ( _config->readBoolEntry( "KrPerm Column", _KrPermColumn ) ) { + newColumn( KrDetailedViewProperties::KrPermissions ); + setColumnWidthMode( COLUMN(KrPermissions), QListView::Manual ); + setColumnWidth( COLUMN(KrPermissions), QFontMetrics( font() ).width( "RWX" ) ); + } + if ( _config->readBoolEntry( "Owner Column", _OwnerColumn ) ) { + newColumn( KrDetailedViewProperties::Owner ); + setColumnWidthMode( COLUMN(Owner), QListView::Manual ); + setColumnWidth( COLUMN(Owner), QFontMetrics( font() ).width( 'X' ) * 6 ); + } + if ( _config->readBoolEntry( "Group Column", _GroupColumn ) ) { + newColumn( KrDetailedViewProperties::Group ); + setColumnWidthMode( COLUMN(Group), QListView::Manual ); + setColumnWidth( COLUMN(Group), QFontMetrics( font() ).width( 'X' ) * 6 ); + } + + // determine basic settings for the listview + setAcceptDrops( true ); + setDragEnabled( true ); + setTooltipColumn( COLUMN(Name) ); + setDropVisualizer(false); + setDropHighlighter(true); + setSelectionModeExt( KListView::FileManager ); + setAllColumnsShowFocus( true ); + setShowSortIndicator( true ); + header() ->setStretchEnabled( true, COLUMN(Name) ); + + //---- don't enable these lines, as it causes an ugly bug with inplace renaming + //--> setItemsRenameable( true ); + //--> setRenameable( column( Name ), true ); + //------------------------------------------------------------------------------- + + header()->installEventFilter( this ); + renameLineEdit()->installEventFilter( this ); + + // allow in-place renaming + connect( renameLineEdit(), SIGNAL( done( QListViewItem *, int ) ), + this, SLOT( inplaceRenameFinished( QListViewItem*, int ) ) ); + connect( &renameTimer, SIGNAL( timeout() ), this, SLOT( renameCurrentItem() ) ); + connect( &contextMenuTimer, SIGNAL (timeout()), this, SLOT (showContextMenu())); + + connect( header(), SIGNAL(clicked(int)), this, SLOT(slotSortOrderChanged(int ))); + + setFocusPolicy( StrongFocus ); + restoreSettings(); + refreshColors(); + + CANCEL_TWO_CLICK_RENAME; +} + +KrDetailedView::~KrDetailedView() { + delete _properties; _properties = 0; + delete _operator; _operator = 0; +} + +void KrDetailedView::newColumn( KrDetailedViewProperties::ColumnType type ) { + // get the next available column + int max = KrDetailedViewProperties::Unused; + for (int i=0; i<KrDetailedViewProperties::MAX_COLUMNS; ++i) { + if (PROPS->column[i]>=max) + max = PROPS->column[i]+1; + } + if ( max >= KrDetailedViewProperties::MAX_COLUMNS ) + perror( "KrDetailedView::newColumn() - too many columns" ); + + PROPS->column[type] = max; + addColumn( ColumnName[type], -1 ); +} + +/** + * returns the number of column which holds values of type 'type'. + * if such values are not presented in the view, -1 is returned. + */ +int KrDetailedView::column( KrDetailedViewProperties::ColumnType type ) { + return PROPS->column[type]; +} + +// if vfile passes the filter, create an item, otherwise, drop it +KrViewItem *KrDetailedView::preAddItem( vfile *vf ) { + QString size = KRpermHandler::parseSize( vf->vfile_getSize() ); + QString name = vf->vfile_getName(); + bool isDir = vf->vfile_isDir(); + if ( !isDir || ( isDir && ( _properties->filter & KrViewProperties::ApplyToDirs ) ) ) { + switch ( _properties->filter ) { + case KrViewProperties::All : + break; + case KrViewProperties::Custom : + if ( !_properties->filterMask.match( vf ) ) return 0; + break; + case KrViewProperties::Dirs: + if ( !vf->vfile_isDir() ) return 0; + break; + case KrViewProperties::Files: + if ( vf->vfile_isDir() ) return 0; + break; + case KrViewProperties::ApplyToDirs : + break; // no-op, stop compiler complaints + } + } + // passed the filter ... + return new KrDetailedViewItem( this, lastItem(), vf ); +} + +bool KrDetailedView::preDelItem(KrViewItem *item) { + /* KDE HACK START - the renaming item is not disappeared after delete */ + /* solution: we send an ESC key event to terminate the rename */ + if( item ) { + QListViewItem * viewItem = dynamic_cast<QListViewItem*>( item ); + if( viewItem == currentlyRenamedItem ) { + currentlyRenamedItem = 0; + QKeyEvent escEvent( QEvent::KeyPress, Key_Escape, 27, 0 ); + QApplication::sendEvent( renameLineEdit(), &escEvent ); + } + } + /* KDE HACK END */ + return true; +} + +void KrDetailedView::addItems( vfs *v, bool addUpDir ) { + QListViewItem * item = firstChild(); + QListViewItem *currentItem = item; + QString size, name; + + // add the up-dir arrow if needed + if ( addUpDir ) { + new KrDetailedViewItem( this, ( QListViewItem* ) 0L, ( vfile* ) 0L ); + } + + // text for updating the status bar + QString statusText = QString("%1/ ").arg( v->vfs_getOrigin().fileName() ) + i18n("Directory"); + + int cnt = 0; + int cl = columnSorted(); + bool as = ascendingSort(); + setSorting( -1 ); // disable sorting + + for ( vfile * vf = v->vfs_getFirstFile(); vf != 0 ; vf = v->vfs_getNextFile() ) { + size = KRpermHandler::parseSize( vf->vfile_getSize() ); + name = vf->vfile_getName(); + bool isDir = vf->vfile_isDir(); + if ( !isDir || ( isDir && ( _properties->filter & KrViewProperties::ApplyToDirs ) ) ) { + switch ( _properties->filter ) { + case KrViewProperties::All : + break; + case KrViewProperties::Custom : + if ( !_properties->filterMask.match( vf ) ) + continue; + break; + case KrViewProperties::Dirs: + if ( !vf->vfile_isDir() ) + continue; + break; + case KrViewProperties::Files: + if ( vf->vfile_isDir() ) + continue; + break; + + case KrViewProperties::ApplyToDirs : + break; // no-op, stop compiler complaints + } + } + + KrDetailedViewItem *dvitem = new KrDetailedViewItem( this, item, vf ); + _dict.insert( vf->vfile_getName(), dvitem ); + if ( isDir ) + ++_numDirs; + else + _countSize += dvitem->VF->vfile_getSize(); + ++_count; + // if the item should be current - make it so + if ( dvitem->name() == nameToMakeCurrent() ) + { + currentItem = static_cast<QListViewItem*>(dvitem); + statusText = dvitem->description(); + } + + cnt++; + } + + + // re-enable sorting + setSorting( cl, as ); + sort(); + + if ( !currentItem ) + currentItem = firstChild(); + KListView::setCurrentItem( currentItem ); + ensureItemVisible( currentItem ); + + op()->emitItemDescription( statusText ); +} + +QString KrDetailedView::getCurrentItem() const { + QListViewItem * it = currentItem(); + if ( !it ) + return QString::null; + else + return dynamic_cast<KrViewItem*>( it ) ->name(); +} + +void KrDetailedView::setCurrentItem( const QString& name ) { + KrDetailedViewItem * it = dynamic_cast<KrDetailedViewItem*>(_dict[ name ]); + if ( it ) + KListView::setCurrentItem( it ); +} + +void KrDetailedView::clear() { + /* KDE HACK START - the renaming item is not disappeared after clear */ + /* solution: we send an ESC key event to terminate the rename */ + if( currentlyRenamedItem ) { + currentlyRenamedItem = 0; + QKeyEvent escEvent( QEvent::KeyPress, Key_Escape, 27, 0 ); + QApplication::sendEvent( renameLineEdit(), &escEvent ); + } + /* KDE HACK END */ + + op()->emitSelectionChanged(); /* to avoid rename crash at refresh */ + KListView::clear(); + KrView::clear(); +} + +void KrDetailedView::setSortMode( KrViewProperties::SortSpec mode ) { + KrView::setSortMode(mode); // the KrViewItems will check it by themselves + bool ascending = !( mode & KrViewProperties::Descending ); + int cl = -1; + if ( mode & KrViewProperties::Name ) + cl = COLUMN( Name ); + else + if ( mode & KrViewProperties::Ext ) + cl = COLUMN( Extention ); + else + if ( mode & KrViewProperties::Size ) + cl = COLUMN( Size ); + else + if ( mode & KrViewProperties::Type ) + cl = COLUMN( Mime ); + else + if ( mode & KrViewProperties::Modified ) + cl = COLUMN( DateTime ); + else + if ( mode & KrViewProperties::Permissions ) + cl = COLUMN( Permissions ); + else + if ( mode & KrViewProperties::KrPermissions ) + cl = COLUMN( KrPermissions ); + else + if ( mode & KrViewProperties::Owner ) + cl = COLUMN( Owner ); + else + if ( mode & KrViewProperties::Group ) + cl = COLUMN( Group ); + setSorting( cl, ascending ); + KListView::sort(); +} + +void KrDetailedView::slotClicked( QListViewItem *item ) { + if ( !item ) return ; + + if ( !modifierPressed ) { + if ( singleClicked && !renameTimer.isActive() ) { + KConfig * config = KGlobal::config(); + config->setGroup( "KDE" ); + int doubleClickInterval = config->readNumEntry( "DoubleClickInterval", 400 ); + + int msecsFromLastClick = clickTime.msecsTo( QTime::currentTime() ); + + if ( msecsFromLastClick > doubleClickInterval && msecsFromLastClick < 5 * doubleClickInterval ) { + singleClicked = false; + renameTimer.start( doubleClickInterval, true ); + return ; + } + } + + CANCEL_TWO_CLICK_RENAME; + singleClicked = true; + clickTime = QTime::currentTime(); + clickedItem = item; + } +} + +void KrDetailedView::slotDoubleClicked( QListViewItem *item ) { + CANCEL_TWO_CLICK_RENAME; + if ( !item ) + return ; + QString tmp = dynamic_cast<KrViewItem*>( item ) ->name(); + op()->emitExecuted(tmp); +} + +void KrDetailedView::prepareForActive() { + KrView::prepareForActive(); + setFocus(); + slotItemDescription( currentItem() ); +} + +void KrDetailedView::prepareForPassive() { + KrView::prepareForPassive(); + CANCEL_TWO_CLICK_RENAME; + if ( renameLineEdit() ->isVisible() ) + renameLineEdit() ->clearFocus(); + KConfigGroupSaver grpSvr( _config, "Look&Feel" ); + if ( _config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) ) { + if ( MAIN_VIEW ) { + if ( ACTIVE_PANEL ) { + if ( ACTIVE_PANEL->quickSearch ) { + if ( ACTIVE_PANEL->quickSearch->isShown() ) { + stopQuickSearch( 0 ); + } + } + } + } + } +} + +void KrDetailedView::slotItemDescription( QListViewItem * item ) { + KrViewItem * it = static_cast<KrDetailedViewItem*>( item ); + if ( !it ) + return ; + QString desc = it->description(); + op()->emitItemDescription(desc); +} + +void KrDetailedView::handleQuickSearchEvent( QKeyEvent * e ) { + switch ( e->key() ) { + case Key_Insert: + { + QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Space, 0, 0 ); + KListView::keyPressEvent( & ev ); + ev = QKeyEvent( QKeyEvent::KeyPress, Key_Down, 0, 0 ); + keyPressEvent( & ev ); + break; + } + case Key_Home: + { + QListView::setCurrentItem( firstChild() ); + QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Down, 0, 0 ); + keyPressEvent( & ev ); + break; + } + case Key_End: + { + QListView::setCurrentItem( firstChild() ); + QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Up, 0, 0 ); + keyPressEvent( & ev ); + break; + } + } +} + + +void KrDetailedView::slotCurrentChanged( QListViewItem * item ) { + CANCEL_TWO_CLICK_RENAME; + if ( !item ) + return ; + _nameToMakeCurrent = static_cast<KrDetailedViewItem*>( item ) ->name(); +} + +void KrDetailedView::contentsMousePressEvent( QMouseEvent * e ) { + bool callDefaultHandler = true, processEvent = true, selectionChanged = false; + pressedItem = 0; + + QListViewItem * oldCurrent = currentItem(); + QListViewItem *newCurrent = itemAt( contentsToViewport( e->pos() ) ); + if (e->button() == RightButton) + { + if (KrSelectionMode::getSelectionHandler()->rightButtonSelects() || + (((e->state() & ShiftButton) || (e->state() & ControlButton))) && KrSelectionMode::getSelectionHandler()->shiftCtrlRightButtonSelects()) + { + if (KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection() && !(e->state() & ShiftButton) + && !(e->state() & ControlButton) && !(e->state() & AltButton)) + { + if (newCurrent) + { + if (KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0) + { + swushSelects = !newCurrent->isSelected(); + lastSwushPosition = newCurrent; + } + newCurrent->setSelected(!newCurrent->isSelected()); + newCurrent->repaint(); + selectionChanged = true; + } + callDefaultHandler = false; + processEvent = false; + e->accept(); + } + + if( !KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection() && KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0) + { + if( (e->state() & ControlButton) && !(e->state() & AltButton) ) + { + if( newCurrent ) + { + newCurrent->setSelected(!newCurrent->isSelected()); + newCurrent->repaint(); + selectionChanged = true; + callDefaultHandler = false; + e->accept(); + } + } + else if( !(e->state() & ControlButton) && !(e->state() & AltButton) ) + { + clearSelection(); + if( newCurrent ) + { + newCurrent->setSelected( true ); + newCurrent->repaint(); + } + selectionChanged = true; + callDefaultHandler = false; + e->accept(); + } + } + } + else + { + callDefaultHandler = false; + processEvent = false; + e->accept(); + } + } + if (e->button() == LeftButton) + { + dragStartPos = e->pos(); + if (KrSelectionMode::getSelectionHandler()->leftButtonSelects() || + (((e->state() & ShiftButton) || (e->state() & ControlButton))) && + KrSelectionMode::getSelectionHandler()->shiftCtrlLeftButtonSelects()) + { + if (KrSelectionMode::getSelectionHandler()->leftButtonPreservesSelection() && !(e->state() & ShiftButton) + && !(e->state() & ControlButton) && !(e->state() & AltButton)) + { + if (newCurrent) + { + newCurrent->setSelected(!newCurrent->isSelected()); + newCurrent->repaint(); + selectionChanged = true; + } + callDefaultHandler = false; + processEvent = false; + e->accept(); + } + } + else + { + callDefaultHandler = false; + processEvent = false; + e->accept(); + } + } + + modifierPressed = false; + if ( (e->state() & ShiftButton) || (e->state() & ControlButton) || (e->state() & AltButton) ) { + CANCEL_TWO_CLICK_RENAME; + modifierPressed = true; + } + + // stop quick search in case a mouse click occured + KConfigGroupSaver grpSvr( _config, "Look&Feel" ); + if ( _config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) ) { + if ( MAIN_VIEW ) { + if ( ACTIVE_PANEL ) { + if ( ACTIVE_PANEL->quickSearch ) { + if ( ACTIVE_PANEL->quickSearch->isShown() ) { + stopQuickSearch( 0 ); + } + } + } + } + } + + if ( !_focused ) + op()->emitNeedFocus(); + if (processEvent && ( (e->state() & ShiftButton) || (e->state() & ControlButton) || (e->state() & AltButton) ) && !KrSelectionMode::getSelectionHandler()->useQTSelection()){ + if ( oldCurrent && newCurrent && oldCurrent != newCurrent && e->state() & ShiftButton ) { + int oldPos = oldCurrent->itemPos(); + int newPos = newCurrent->itemPos(); + QListViewItem *top = 0, *bottom = 0; + if ( oldPos > newPos ) { + top = newCurrent; + bottom = oldCurrent; + } else { + top = oldCurrent; + bottom = newCurrent; + } + QListViewItemIterator it( top ); + for ( ; it.current(); ++it ) { + if ( !it.current() ->isSelected() ) { + it.current() ->setSelected( true ); + selectionChanged = true; + } + if ( it.current() == bottom ) + break; + } + QListView::setCurrentItem( newCurrent ); + callDefaultHandler = false; + } + } + + if (selectionChanged) + updateView(); // don't call triggerUpdate directly! + + // QListViewItem * i = itemAt( contentsToViewport( e->pos() ) ); + if (callDefaultHandler) + { + dragStartPos = QPoint( -1, -1 ); + + QString name = QString::null; // will the file be deleted by the mouse event? + if( newCurrent ) // save the name of the file + name = static_cast<KrDetailedViewItem*>( newCurrent ) ->name(); + + KListView::contentsMousePressEvent( e ); + + if( name.isEmpty() || _dict.find( name ) == 0 ) // is the file still valid? + newCurrent = 0; // if not, don't do any crash... + } else { + // emitting the missing signals from QListView::contentsMousePressEvent(); + // the right click signal is not emitted as it is used for selection + + QPoint vp = contentsToViewport( e->pos() ); + + if( !newCurrent || ( newCurrent && newCurrent->isEnabled() ) ) { + emit pressed( pressedItem = newCurrent ); + emit pressed( newCurrent, viewport()->mapToGlobal( vp ), 0 ); + } + + emit mouseButtonPressed( e->button(), newCurrent, viewport()->mapToGlobal( vp ), 0 ); + } + + // if (i != 0) // comment in, if click sould NOT select + // setSelected(i, FALSE); + if (newCurrent) QListView::setCurrentItem(newCurrent); + + if ( ACTIVE_PANEL->quickSearch->isShown() ) { + ACTIVE_PANEL->quickSearch->hide(); + ACTIVE_PANEL->quickSearch->clear(); + krDirUp->setEnabled( true ); + } + if ( OTHER_PANEL->quickSearch->isShown() ) { + OTHER_PANEL->quickSearch->hide(); + OTHER_PANEL->quickSearch->clear(); + krDirUp->setEnabled( true ); + } +} + +void KrDetailedView::contentsMouseReleaseEvent( QMouseEvent * e ) { + if (e->button() == RightButton) + contextMenuTimer.stop(); + KListView::contentsMouseReleaseEvent( e ); + + if( pressedItem ) { + QPoint vp = contentsToViewport( e->pos() ); + QListViewItem *newCurrent = itemAt( vp ); + + if( pressedItem == newCurrent ) { + // emitting the missing signals from QListView::contentsMouseReleaseEvent(); + // the right click signal is not emitted as it is used for selection + + if( !newCurrent || ( newCurrent && newCurrent->isEnabled() ) ) { + emit clicked( newCurrent ); + emit clicked( newCurrent, viewport()->mapToGlobal( vp ), 0 ); + } + + emit mouseButtonClicked( e->button(), newCurrent, viewport()->mapToGlobal( vp ), 0 ); + } + + pressedItem = 0; + } +} + +void KrDetailedView::contentsMouseMoveEvent ( QMouseEvent * e ) { + if ( ( singleClicked || renameTimer.isActive() ) && itemAt( contentsToViewport( e->pos() ) ) != clickedItem ) + CANCEL_TWO_CLICK_RENAME; + if ( dragStartPos != QPoint( -1, -1 ) && + e->state() & LeftButton && ( dragStartPos - e->pos() ).manhattanLength() > QApplication::startDragDistance() ) + startDrag(); + if (KrSelectionMode::getSelectionHandler()->rightButtonPreservesSelection() + && KrSelectionMode::getSelectionHandler()->rightButtonSelects() + && KrSelectionMode::getSelectionHandler()->showContextMenu() >= 0 && e->state() == Qt::RightButton) + { + QListViewItem *newItem = itemAt( contentsToViewport( e->pos() ) ); + e->accept(); + if (newItem != lastSwushPosition && newItem) + { + // is the new item above or below the previous one? + QListViewItem * above = newItem; + QListViewItem * below = newItem; + for (;(above || below) && above != lastSwushPosition && below != lastSwushPosition;) + { + if (above) + above = above->itemAbove(); + if (below) + below = below->itemBelow(); + } + if (above && (above == lastSwushPosition)) + { + for (; above != newItem; above = above->itemBelow()) + above->setSelected(swushSelects); + newItem->setSelected(swushSelects); + lastSwushPosition = newItem; + updateView(); + } + else if (below && (below == lastSwushPosition)) + { + for (; below != newItem; below = below->itemAbove()) + below->setSelected(swushSelects); + newItem->setSelected(swushSelects); + lastSwushPosition = newItem; + updateView(); + } + contextMenuTimer.stop(); + } + // emitting the missing signals from QListView::contentsMouseMoveEvent(); + if( newItem ) + emit onItem( newItem ); + else + emit onViewport(); + } + else + KListView::contentsMouseMoveEvent( e ); +} + +void KrDetailedView::contentsWheelEvent( QWheelEvent * e ) { + if ( !_focused ) + op()->emitNeedFocus(); + KListView::contentsWheelEvent( e ); +} + +void KrDetailedView::handleContextMenu( QListViewItem * it, const QPoint & pos, int ) { + if ( !_focused ) + op()->emitNeedFocus(); + if ( !it ) + return ; + if ( static_cast<KrDetailedViewItem*>( it ) -> + name() == ".." ) + return ; + int i = KrSelectionMode::getSelectionHandler()->showContextMenu(); + contextMenuPoint = QPoint( pos.x(), pos.y() - header() ->height() ); + if (i < 0) + showContextMenu(); + else if (i > 0) + contextMenuTimer.start(i, true); +} + +void KrDetailedView::showContextMenu() +{ + if (lastSwushPosition) + lastSwushPosition->setSelected(true); + op()->emitContextMenu( contextMenuPoint ); +} + +KrViewItem *KrDetailedView::getKrViewItemAt( const QPoint & vp ) { + return dynamic_cast<KrViewItem*>( KListView::itemAt( vp ) ); +} + +bool KrDetailedView::acceptDrag( QDropEvent* ) const { + return true; +} + +QRect KrDetailedView::drawItemHighlighter(QPainter *painter, QListViewItem *item) +{ + QRect r; + if( _currDragItem && item ) { + r = itemRect(item); + + if (painter) + style().drawPrimitive(QStyle::PE_FocusRect, painter, r, colorGroup(), + QStyle::Style_FocusAtBorder, colorGroup().highlight()); + } + return r; +} + +void KrDetailedView::contentsDropEvent( QDropEvent * e ) { + e->setPoint( contentsToViewport( e->pos() ) ); + op()->emitGotDrop(e); + e->ignore(); + KListView::contentsDropEvent( e ); +} + +void KrDetailedView::contentsDragMoveEvent( QDragMoveEvent * e ) { + _currDragItem = getKrViewItemAt(contentsToViewport(e->pos())); + if( _currDragItem && !_currDragItem->VF->vfile_isDir() ) + _currDragItem = 0; + + KListView::contentsDragMoveEvent( e ); +} + +void KrDetailedView::imStartEvent(QIMEvent* e) +{ + if ( ACTIVE_PANEL->quickSearch->isShown() ) { + ACTIVE_PANEL->quickSearch->myIMStartEvent( e ); + return ; + }else { + KConfigGroupSaver grpSvr( _config, "Look&Feel" ); + if ( !_config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) ) + KListView::imStartEvent( e ); + else { + // first, show the quicksearch if its hidden + if ( ACTIVE_PANEL->quickSearch->isHidden() ) { + ACTIVE_PANEL->quickSearch->show(); + // hack: if the pressed key requires a scroll down, the selected + // item is "below" the quick search window, as the list view will + // realize its new size after the key processing. The following line + // will resize the list view immediately. + ACTIVE_PANEL->layout->activate(); + // second, we need to disable the dirup action - hack! + krDirUp->setEnabled( false ); + } + // now, send the key to the quicksearch + ACTIVE_PANEL->quickSearch->myIMStartEvent( e ); + } + } +} + +void KrDetailedView::imEndEvent(QIMEvent* e) +{ + if ( ACTIVE_PANEL->quickSearch->isShown() ) { + ACTIVE_PANEL->quickSearch->myIMEndEvent( e ); + return ; + } +} + +void KrDetailedView::imComposeEvent(QIMEvent* e) +{ + if ( ACTIVE_PANEL->quickSearch->isShown() ) { + ACTIVE_PANEL->quickSearch->myIMComposeEvent( e ); + return ; + } +} + +// TODO: for brief mode, move as much of this as possible to the viewOperator +void KrDetailedView::keyPressEvent( QKeyEvent * e ) { + if ( !e || !firstChild() ) + return ; // subclass bug + if ( ACTIVE_PANEL->quickSearch->isShown() ) { + ACTIVE_PANEL->quickSearch->myKeyPressEvent( e ); + return ; + } + switch ( e->key() ) { + case Key_Up : + if ( e->state() == ControlButton ) { // let the panel handle it - jump to the Location Bar + e->ignore(); + break; + } else if (!KrSelectionMode::getSelectionHandler()->useQTSelection()) { + QListViewItem * i = currentItem(); + if ( !i ) break; + if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected() ); + i = i->itemAbove(); + if ( i ) { + QListView::setCurrentItem( i ); + QListView::ensureItemVisible( i ); + } + } else KListView::keyPressEvent(e); + break; + case Key_Down : + if ( e->state() == ControlButton || e->state() == ( ControlButton | ShiftButton ) ) { // let the panel handle it - jump to command line + e->ignore(); + break; + } else if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){ + QListViewItem * i = currentItem(); + if ( !i ) break; + if ( e->state() == ShiftButton ) setSelected( i, !i->isSelected() ); + i = i->itemBelow(); + if ( i ) {QListView::setCurrentItem( i ); QListView::ensureItemVisible( i ); } + } else KListView::keyPressEvent(e); + break; + case Key_Next: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){ + QListViewItem * i = currentItem(), *j; + if ( !i ) break; + QRect r( itemRect( i ) ); + if ( !r.height() ) break; + for ( int page = visibleHeight() / r.height() - 1; page > 0 && ( j = i->itemBelow() ); --page ) + i = j; + if ( i ) {QListView::setCurrentItem( i ); QListView::ensureItemVisible( i ); } + } else KListView::keyPressEvent(e); + break; + case Key_Prior: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){ + QListViewItem * i = currentItem(), *j; + if ( !i ) break; + QRect r( itemRect( i ) ); + if ( !r.height() ) break; + for ( int page = visibleHeight() / r.height() - 1; page > 0 && ( j = i->itemAbove() ); --page ) + i = j; + if ( i ) {QListView::setCurrentItem( i ); QListView::ensureItemVisible( i ); } + } else KListView::keyPressEvent(e); + break; + case Key_Home: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){ + if ( e->state() & ShiftButton ) /* Shift+Home */ + { + clearSelection(); + KListView::keyPressEvent( e ); + op()->emitSelectionChanged(); + triggerUpdate(); + break; + } else { + QListViewItem * i = firstChild(); + if ( i ) {QListView::setCurrentItem( i ); QListView::ensureItemVisible( i ); } + } + } else KListView::keyPressEvent(e); + break; + case Key_End: if (!KrSelectionMode::getSelectionHandler()->useQTSelection()){ + if ( e->state() & ShiftButton ) /* Shift+End */ + { + clearSelection(); + KListView::keyPressEvent( e ); + op()->emitSelectionChanged(); + triggerUpdate(); + break; + } else { + QListViewItem *i = firstChild(), *j; + while ( ( j = i->nextSibling() ) ) + i = j; + while ( ( j = i->itemBelow() ) ) + i = j; + if ( i ) {QListView::setCurrentItem( i ); QListView::ensureItemVisible( i ); } + break; + } + } else KListView::keyPressEvent(e); + break; + case Key_Enter : + case Key_Return : { + if ( e->state() & ControlButton ) // let the panel handle it + e->ignore(); + else { + KrViewItem * i = getCurrentKrViewItem(); + QString tmp = i->name(); + op()->emitExecuted(tmp); + } + break; + } + case Key_QuoteLeft : // Terminal Emulator bugfix + if ( e->state() == ControlButton ) { // let the panel handle it + e->ignore(); + break; + } else { // a normal click - do a lynx-like moving thing + SLOTS->home(); // ask krusader to move up a directory + return ; // safety + } + break; + case Key_Right : + if ( e->state() == ControlButton || e->state() == ShiftButton ) { // let the panel handle it + e->ignore(); + break; + } else { // just a normal click - do a lynx-like moving thing + KrViewItem *i = getCurrentKrViewItem(); + if ( i->name() == ".." ) { // if clicking on the ".." entry + SLOTS->dirUp(); // ask krusader to move up a directory + return ; + } + if ( i->VF->vfile_isDir() ) { // we create a return-pressed event, + QString tmp = i->name(); + op()->emitExecuted(tmp); // thereby emulating a chdir + } else if( i->VF->vfile_getUrl().isLocalFile() ) { + bool encrypted; + KURL url = i->VF->vfile_getUrl(); + QString mime = ((vfile *)(i->VF))->vfile_getMime(); + QString type = KRarcHandler::getType( encrypted, url.path(), mime, false ); + + if( KRarcHandler::arcSupported( type ) ) { + KURL url = i->VF->vfile_getUrl(); + if( type == "-tar" || type == "-tgz" || type == "-tbz" ) + url.setProtocol( "tar" ); + else + url.setProtocol( "krarc" ); + ACTIVE_FUNC->openUrl( url ); + } + } + return ; // safety + } + case Key_Backspace : // Terminal Emulator bugfix + case Key_Left : + if ( e->state() == ControlButton || e->state() == ShiftButton ) { // let the panel handle it + e->ignore(); + break; + } else { // a normal click - do a lynx-like moving thing + SLOTS->dirUp(); // ask krusader to move up a directory + return ; // safety + } + //case Key_Up : + //KListView::keyPressEvent( e ); + //break; +/*#ifndef _newSelectionHandling + case Key_Down : + if ( e->state() == ControlButton ) { // let the panel handle it + e->ignore(); + break; + } else + KListView::keyPressEvent( e ); + break; +#endif*/ + case Key_Delete : // kill file + SLOTS->deleteFiles( e->state() == ShiftButton || e->state() == ControlButton ); + + break ; + case Key_Insert : { + if (KrSelectionMode::getSelectionHandler()->insertMovesDown()) + KListView::keyPressEvent( e ); + else + { + QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Space, 0, 0 ); + KListView::keyPressEvent( & ev ); + } + break ; + } + case Key_Space : { + KrDetailedViewItem * viewItem = static_cast<KrDetailedViewItem *> ( getCurrentKrViewItem() ); + if ( !viewItem || viewItem->name() == ".." ) { // wrong type, just mark(unmark it) + if (KrSelectionMode::getSelectionHandler()->spaceMovesDown()) + { + QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Insert, 0, 0 ); + KListView::keyPressEvent( & ev ); + } + else + KListView::keyPressEvent( e ); + break ; + } + if ( viewItem->VF->vfile_isDir() && viewItem->VF->vfile_getSize() <= 0 && + KrSelectionMode::getSelectionHandler()->spaceCalculatesDiskSpace()) { + // + // NOTE: this is buggy incase somewhere down in the folder we're calculating, + // there's a folder we can't enter (permissions). in that case, the returned + // size will not be correct. + // + KIO::filesize_t totalSize = 0; + unsigned long totalFiles = 0, totalDirs = 0; + QStringList items; + items.push_back( viewItem->name() ); + if ( ACTIVE_PANEL->func->calcSpace( items, totalSize, totalFiles, totalDirs ) ) { + // did we succeed to calcSpace? we'll fail if we don't have permissions + if ( totalSize == 0 ) { // just mark it, and bail out + goto mark; + } + viewItem->setSize( totalSize ); + viewItem->repaintItem(); + } + } +mark: if (KrSelectionMode::getSelectionHandler()->spaceMovesDown()) + { + QKeyEvent ev = QKeyEvent( QKeyEvent::KeyPress, Key_Insert, 0, 0 ); + KListView::keyPressEvent( & ev ); + } + else + KListView::keyPressEvent( e ); + } + break; + case Key_A : // mark all + if ( e->state() == ControlButton ) { + KListView::keyPressEvent( e ); + updateView(); + break; + } + default: + if ( e->key() == Key_Escape ) { + QListView::keyPressEvent( e ); return ; // otherwise the selection gets lost??!?? + } + // if the key is A..Z or 1..0 do quick search otherwise... + if ( e->text().length() > 0 && e->text() [ 0 ].isPrint() ) // better choice. Otherwise non-ascii characters like can not be the first character of a filename + /* if ( ( e->key() >= Key_A && e->key() <= Key_Z ) || + ( e->key() >= Key_0 && e->key() <= Key_9 ) || + ( e->key() == Key_Backspace ) || + ( e->key() == Key_Down ) || + ( e->key() == Key_Period ) ) */{ + // are we doing quicksearch? if not, send keys to panel + //if ( _config->readBoolEntry( "Do Quicksearch", _DoQuicksearch ) ) { + // are we using krusader's classic quicksearch, or wincmd style? + { + KConfigGroupSaver grpSvr( _config, "Look&Feel" ); + if ( !_config->readBoolEntry( "New Style Quicksearch", _NewStyleQuicksearch ) ) + KListView::keyPressEvent( e ); + else { + // first, show the quicksearch if its hidden + if ( ACTIVE_PANEL->quickSearch->isHidden() ) { + ACTIVE_PANEL->quickSearch->show(); + // hack: if the pressed key requires a scroll down, the selected + // item is "below" the quick search window, as the list view will + // realize its new size after the key processing. The following line + // will resize the list view immediately. + ACTIVE_PANEL->layout->activate(); + // second, we need to disable the dirup action - hack! + krDirUp->setEnabled( false ); + } + // now, send the key to the quicksearch + ACTIVE_PANEL->quickSearch->myKeyPressEvent( e ); + } + } + //} else + // e->ignore(); // send to panel + } else { + if ( ACTIVE_PANEL->quickSearch->isShown() ) { + ACTIVE_PANEL->quickSearch->hide(); + ACTIVE_PANEL->quickSearch->clear(); + krDirUp->setEnabled( true ); + } + KListView::keyPressEvent( e ); + } + } + // emit the new item description + slotItemDescription( currentItem() ); // actually send the QListViewItem +} + +// overridden to make sure EXTENTION won't be lost during rename +void KrDetailedView::rename( QListViewItem * item, int c ) { + // do we have an EXT column? if so, handle differently: + // copy the contents of the EXT column over to the name + if ( COLUMN( Extention ) != -1 ) { + item->setText( COLUMN( Name ), static_cast<KrDetailedViewItem*>( item ) ->name() ); + item->setText( COLUMN( Extention ), QString::null ); + repaintItem( item ); + } + + currentlyRenamedItem = item; + renameLineEdit()->setBackgroundMode(Qt::FixedColor); + renameLineEdit()->setPaletteBackgroundColor(Qt::white); + renameLineEdit()->setPaletteForegroundColor(Qt::black); + KListView::rename( item, c ); + renameLineEdit() ->selectAll(); +} + +void KrDetailedView::renameCurrentItem() { + int c; + QString newName, fileName; + + // handle inplace renaming, if possible + + KrDetailedViewItem *it = static_cast<KrDetailedViewItem*>(getCurrentKrViewItem()); + if ( it ) + fileName = it->name(); + else + return ; // quit if no current item available + // don't allow anyone to rename .. + if ( fileName == ".." ) + return ; + + // determine which column is inplace renameable + for ( c = 0; c < columns(); c++ ) + if ( isRenameable( c ) ) + break; // one MUST be renamable + if ( !isRenameable( c ) ) + c = -1; // failsafe + + if ( c >= 0 ) { + rename( static_cast<QListViewItem*>( it ), c ); + // if applicable, select only the name without extension + KConfigGroupSaver svr(krConfig,"Look&Feel"); + if (!krConfig->readBoolEntry("Rename Selects Extension", true)) { + if (it->hasExtension() && !it->VF->vfile_isDir() ) + renameLineEdit()->setSelection(0, it->name().findRev(it->extension())-1); + } + // signal will be emited when renaming is done, and finalization + // will occur in inplaceRenameFinished() + } else { + // do this in case inplace renaming is disabled + // this actually does the good old dialog box rename + KrView::renameCurrentItem(); + } +} + +void KrDetailedView::inplaceRenameFinished( QListViewItem * it, int ) { + if( currentlyRenamedItem == 0 ) + return; + + if ( !it ) { // major failure - call developers + krOut << "Major failure at inplaceRenameFinished(): item is null" << endl; + return; + } + + if( COLUMN( Extention ) != -1 && !currentlyRenamedItem ) + return; /* does the event filter restored the original state? */ + + // check if the item was indeed renamed + bool restoreView = false; + if ( it->text( COLUMN( Name ) ) != static_cast<KrDetailedViewItem*>( it ) ->name() ) { // was renamed + op()->emitRenameItem( static_cast<KrDetailedViewItem*>( it ) ->name(), it->text( COLUMN( Name ) ) ); + } else restoreView = true; + + // restore the view always! if the file was indeed renamed, we'll get a signal from the vfs about + // it, and update the view when needed +#if 0 + if ( COLUMN( Extention ) != -1 && restoreView ) { // nothing happened, restore the view (if needed) +#endif + + QString ext, name = static_cast<KrDetailedViewItem*>( it ) ->name(); + if ( !static_cast<KrDetailedViewItem*>( it ) ->VF->vfile_isDir() && COLUMN( Extention ) != -1 ) { + ext = static_cast<KrDetailedViewItem*>( it ) ->extension(); + name = static_cast<KrDetailedViewItem*>( it ) ->name( false ); + } + it->setText( COLUMN( Name ), name ); + it->setText( COLUMN( Extention ), ext ); + repaintItem( it ); +#if 0 + } +#endif + + setFocus(); + + currentlyRenamedItem = 0; +} + +// TODO: move the whole quicksearch mess out of here and into krview +void KrDetailedView::quickSearch( const QString & str, int direction ) { + KrViewItem * item = getCurrentKrViewItem(); + if (!item) + return; + KConfigGroupSaver grpSvr( _config, "Look&Feel" ); + bool caseSensitive = _config->readBoolEntry( "Case Sensitive Quicksearch", _CaseSensitiveQuicksearch ); + if ( !direction ) { + if ( caseSensitive ? item->name().startsWith( str ) : item->name().lower().startsWith( str.lower() ) ) + return ; + direction = 1; + } + KrViewItem * startItem = item; + while ( true ) { + item = ( direction > 0 ) ? getNext( item ) : getPrev( item ); + if ( !item ) + item = ( direction > 0 ) ? getFirst() : getLast(); + if ( item == startItem ) + return ; + if ( caseSensitive ? item->name().startsWith( str ) : item->name().lower().startsWith( str.lower() ) ) { + setCurrentItem( item->name() ); + makeItemVisible( item ); + return ; + } + } +} + +void KrDetailedView::stopQuickSearch( QKeyEvent * e ) { + if( ACTIVE_PANEL && ACTIVE_PANEL->quickSearch ) { + ACTIVE_PANEL->quickSearch->hide(); + ACTIVE_PANEL->quickSearch->clear(); + krDirUp->setEnabled( true ); + if ( e ) + keyPressEvent( e ); + } +} + +// internal: converts signal from qlistview to krview +void KrDetailedView::setNameToMakeCurrent( QListViewItem * it ) { + if (!it) return; + KrView::setNameToMakeCurrent( static_cast<KrDetailedViewItem*>( it ) ->name() ); +} + +void KrDetailedView::slotMouseClicked( int button, QListViewItem * item, const QPoint&, int ) { + pressedItem = 0; // if the signals are emitted, don't emit twice at contentsMouseReleaseEvent + if ( button == Qt::MidButton ) + emit middleButtonClicked( dynamic_cast<KrViewItem *>( item ) ); +} + +void KrDetailedView::refreshColors() { + krConfig->setGroup("Colors"); + bool kdeDefault = krConfig->readBoolEntry("KDE Default"); + bool alternateBackgroundEnabled = krConfig->readBoolEntry("Enable Alternate Background"); + if ( !kdeDefault ) { + // KDE default is not choosen: set the background color (as this paints the empty areas) and the alternate color + bool isActive = hasFocus(); + if ( MAIN_VIEW && ACTIVE_PANEL && ACTIVE_PANEL->view ) + isActive = ( static_cast<KrView *>( this ) == ACTIVE_PANEL->view ); + QColorGroup cg; + KrColorCache::getColorCache().getColors(cg, KrColorItemType(KrColorItemType::File, false, isActive, false, false)); + setPaletteBackgroundColor( cg.background() ); + + KrColorCache::getColorCache().getColors(cg, KrColorItemType(KrColorItemType::File, true, isActive, false, false)); + setAlternateBackground( cg.background() ); + } else { + // KDE default is choosen: set back the background color + setPaletteBackgroundColor( KGlobalSettings::baseColor() ); + // Set the alternate color to its default or to an invalid color, to turn alternate the background off. + setAlternateBackground( alternateBackgroundEnabled ? KGlobalSettings::alternateBackgroundColor() : QColor() ); + } +} + +bool KrDetailedView::event( QEvent *e ) { + modifierPressed = false; + + switch ( e->type() ) { + case QEvent::Timer: + case QEvent::MouseMove: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + break; + default: + CANCEL_TWO_CLICK_RENAME; + } + return KListView::event( e ); +} + +bool KrDetailedView::eventFilter( QObject * watched, QEvent * e ) +{ + if( watched == renameLineEdit() ) + { + if( currentlyRenamedItem && e->type() == QEvent::Hide ) + { + /* checking if the currentlyRenamedItem pointer is valid (vfs_refresh can delete this item) */ + for( QListViewItem *it = firstChild(); it; it = it->nextSibling() ) + if( it == currentlyRenamedItem ) + { + if ( it->text( COLUMN( Name ) ) == dynamic_cast<KrDetailedViewItem*>( it ) ->name() && COLUMN( Extention ) != -1 ) + inplaceRenameFinished( it, COLUMN( Name ) ); + break; + } + } + return FALSE; + } + else if( watched == header() ) + { + if( e->type() == QEvent::MouseButtonPress && ((QMouseEvent *)e )->button() == Qt::RightButton ) + { + selectColumns(); + return TRUE; + } + return FALSE; + } + return KListView::eventFilter( watched, e ); +} + +void KrDetailedView::makeItemVisible( const KrViewItem *item ) { +// qApp->processEvents(); // Please don't remove the comment. Causes crash if it is inserted! + ensureItemVisible( static_cast<const KrDetailedViewItem*>( item ) ); +} + +void KrDetailedView::initOperator() { + _operator = new KrViewOperator(this, this); + // klistview emits selection changed, so chain them to operator + connect(this, SIGNAL(selectionChanged()), _operator, SIGNAL(selectionChanged())); +} + +void KrDetailedView::initProperties() { + _properties = new KrDetailedViewProperties; + KConfigGroupSaver grpSvr( _config, "Look&Feel" ); + for (int i=0; i<KrDetailedViewProperties::MAX_COLUMNS;++i) + PROPS->column[i]=-1; + PROPS->displayIcons = _config->readBoolEntry( "With Icons", _WithIcons ); + bool dirsByNameAlways = _config->readBoolEntry("Always sort dirs by name", false); + PROPS->sortMode = static_cast<KrViewProperties::SortSpec>( KrViewProperties::Name | + KrViewProperties::Descending | KrViewProperties::DirsFirst | + (dirsByNameAlways ? KrViewProperties::AlwaysSortDirsByName : 0) ); + PROPS->numericPermissions = _config->readBoolEntry("Numeric permissions", _NumericPermissions); + if ( !_config->readBoolEntry( "Case Sensative Sort", _CaseSensativeSort ) ) + PROPS->sortMode = static_cast<KrViewProperties::SortSpec>( _properties->sortMode | + KrViewProperties::IgnoreCase ); + PROPS->humanReadableSize = krConfig->readBoolEntry("Human Readable Size", _HumanReadableSize); + PROPS->localeAwareCompareIsCaseSensitive = QString( "a" ).localeAwareCompare( "B" ) > 0; // see KDE bug #40131 + QStringList defaultAtomicExtensions; + defaultAtomicExtensions += ".tar.gz"; + defaultAtomicExtensions += ".tar.bz2"; + defaultAtomicExtensions += ".moc.cpp"; + QStringList atomicExtensions = krConfig->readListEntry("Atomic Extensions", defaultAtomicExtensions); + for (QStringList::iterator i = atomicExtensions.begin(); i != atomicExtensions.end(); ) + { + QString & ext = *i; + ext = ext.stripWhiteSpace(); + if (!ext.length()) + { + i = atomicExtensions.remove(i); + continue; + } + if (!ext.startsWith(".")) + ext.insert(0, '.'); + ++i; + } + PROPS->atomicExtensions = atomicExtensions; +} + +void KrDetailedView::selectColumns() +{ + KPopupMenu popup( this ); + popup.insertTitle( i18n("Columns")); + + bool refresh = false; + + bool hasExtention = COLUMN( Extention ) != -1; + bool hasMime = COLUMN( Mime ) != -1; + bool hasSize = COLUMN( Size ) != -1; + bool hasDate = COLUMN( DateTime ) != -1; + bool hasPerms = COLUMN( Permissions ) != -1; + bool hasKrPerms = COLUMN( KrPermissions ) != -1; + bool hasOwner = COLUMN( Owner ) != -1; + bool hasGroup = COLUMN( Group ) != -1; + + popup.insertItem( i18n( "Ext" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::Extention ); + popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::Extention, hasExtention ); + + popup.insertItem( i18n( "Type" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::Mime ); + popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::Mime, hasMime ); + + popup.insertItem( i18n( "Size" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::Size ); + popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::Size, hasSize ); + + popup.insertItem( i18n( "Modified" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::DateTime ); + popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::DateTime, hasDate ); + + popup.insertItem( i18n( "Perms" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::Permissions ); + popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::Permissions, hasPerms ); + + popup.insertItem( i18n( "rwx" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::KrPermissions ); + popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::KrPermissions, hasKrPerms ); + + popup.insertItem( i18n( "Owner" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::Owner ); + popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::Owner, hasOwner ); + + popup.insertItem( i18n( "Group" ), COLUMN_POPUP_IDS + KrDetailedViewProperties::Group ); + popup.setItemChecked( COLUMN_POPUP_IDS + KrDetailedViewProperties::Group, hasGroup ); + + int result=popup.exec(QCursor::pos()); + + krConfig->setGroup( nameInKConfig() ); + + switch( result - COLUMN_POPUP_IDS ) + { + case KrDetailedViewProperties::Extention: + krConfig->writeEntry( "Ext Column", !hasExtention ); + refresh = true; + break; + case KrDetailedViewProperties::Mime: + krConfig->writeEntry( "Mime Column", !hasMime ); + refresh = true; + break; + case KrDetailedViewProperties::Size: + krConfig->writeEntry( "Size Column", !hasSize ); + refresh = true; + break; + case KrDetailedViewProperties::DateTime: + krConfig->writeEntry( "DateTime Column", !hasDate ); + refresh = true; + break; + case KrDetailedViewProperties::Permissions: + krConfig->writeEntry( "Perm Column", !hasPerms ); + refresh = true; + break; + case KrDetailedViewProperties::KrPermissions: + krConfig->writeEntry( "KrPerm Column", !hasKrPerms ); + refresh = true; + break; + case KrDetailedViewProperties::Owner: + krConfig->writeEntry( "Owner Column", !hasOwner ); + refresh = true; + break; + case KrDetailedViewProperties::Group: + krConfig->writeEntry( "Group Column", !hasGroup ); + refresh = true; + break; + } + + if( refresh ) + { + PanelManager *p = ACTIVE_PANEL->view == this ? ACTIVE_MNG : OTHER_MNG; + QTimer::singleShot( 0, p, SLOT( slotRecreatePanels() ) ); + } +} + +void KrDetailedView::sortOrderChanged(int) { + ensureItemVisible(currentItem()); +} + +void KrDetailedView::updateView() { + triggerUpdate(); + op()->emitSelectionChanged(); +} + +void KrDetailedView::updateItem(KrViewItem* item) { + dynamic_cast<KrDetailedViewItem*>(item)->repaintItem(); +} + +void KrDetailedView::slotRightButtonPressed(QListViewItem*, const QPoint& point, int) { + op()->emitEmptyContextMenu(point); +} + +// hack: this needs to be done in a more cross-view way +void KrDetailedView::slotSortOrderChanged(int col) { + // map the column to a sort specification + KrViewProperties::SortSpec sp = KrViewProperties::Name; + int i; + for (i = 0; i < KrDetailedViewProperties::MAX_COLUMNS; ++i) { + if (PROPS->column[i] == col) break; + } + switch (i) { + case KrDetailedViewProperties::Name: + sp = KrViewProperties::Name; break; + case KrDetailedViewProperties::Extention: + sp = KrViewProperties::Ext; break; + case KrDetailedViewProperties::Mime: + sp = KrViewProperties::Type; break; + case KrDetailedViewProperties::Size: + sp = KrViewProperties::Size; break; + case KrDetailedViewProperties::DateTime: + sp = KrViewProperties::Modified; break; + case KrDetailedViewProperties::Permissions: + sp = KrViewProperties::Permissions; break; + case KrDetailedViewProperties::KrPermissions: + sp = KrViewProperties::KrPermissions; break; + case KrDetailedViewProperties::Owner: + sp = KrViewProperties::Owner; break; + case KrDetailedViewProperties::Group: + sp = KrViewProperties::Group; break; + default: qFatal("slotSortOrderChanged: unknown column"); + } + if (sortMode() & KrViewProperties::DirsFirst) + sp = static_cast<KrViewProperties::SortSpec>(sp | KrViewProperties::DirsFirst); + if (sortMode() & KrViewProperties::IgnoreCase) + sp = static_cast<KrViewProperties::SortSpec>(sp | KrViewProperties::IgnoreCase); + if (sortMode() & KrViewProperties::Descending) + sp = static_cast<KrViewProperties::SortSpec>(sp | KrViewProperties::Descending); + if (sortMode() & KrViewProperties::AlwaysSortDirsByName) + sp = static_cast<KrViewProperties::SortSpec>(sp | KrViewProperties::AlwaysSortDirsByName); + // fix the ascending/decending stuff + if (sortMode() == sp) { + if (sp & KrViewProperties::Descending) + sp = static_cast<KrViewProperties::SortSpec>(sp &~ KrViewProperties::Descending); + else sp = static_cast<KrViewProperties::SortSpec>(sp | KrViewProperties::Descending); + } + PROPS->sortMode = sp; + + if( !_focused ) + op()->emitNeedFocus(); +} + +#include "krdetailedview.moc" |